This commit is contained in:
parent
c0939063aa
commit
58521527fd
|
|
@ -28,23 +28,43 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import type { AnalysisRequest } from "@/lib/types";
|
import type { AnalysisRequest } from "@/lib/types";
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
ticker: z.string().min(1, "股票代碼為必填").max(10),
|
ticker: z.string().min(1, "股票代碼為必填").max(10),
|
||||||
analysis_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "日期格式必須為 YYYY-MM-DD"),
|
analysis_date: z
|
||||||
|
.string()
|
||||||
|
.regex(/^\d{4}-\d{2}-\d{2}$/, "日期格式必須為 YYYY-MM-DD"),
|
||||||
analysts: z.array(z.string()).min(1, "請至少選擇一位分析師"),
|
analysts: z.array(z.string()).min(1, "請至少選擇一位分析師"),
|
||||||
research_depth: z.number().int().min(1).max(5),
|
research_depth: z.number().int().min(1).max(5),
|
||||||
shallow_thinking_agent: z.string().min(1, "請選擇快速思維模型"),
|
shallow_thinking_agent: z.string().min(1, "請選擇快速思維模型"),
|
||||||
deep_thinking_agent: z.string().min(1, "請選擇深層思維模型"),
|
deep_thinking_agent: z.string().min(1, "請選擇深層思維模型"),
|
||||||
|
|
||||||
// API Configuration
|
// API Configuration
|
||||||
quick_think_base_url: z.string().url("請輸入有效的 URL").optional().or(z.literal("")),
|
quick_think_base_url: z
|
||||||
deep_think_base_url: z.string().url("請輸入有效的 URL").optional().or(z.literal("")),
|
.string()
|
||||||
|
.url("請輸入有效的 URL")
|
||||||
|
.optional()
|
||||||
|
.or(z.literal("")),
|
||||||
|
deep_think_base_url: z
|
||||||
|
.string()
|
||||||
|
.url("請輸入有效的 URL")
|
||||||
|
.optional()
|
||||||
|
.or(z.literal("")),
|
||||||
quick_think_api_key: z.string().optional().or(z.literal("")),
|
quick_think_api_key: z.string().optional().or(z.literal("")),
|
||||||
deep_think_api_key: z.string().optional().or(z.literal("")),
|
deep_think_api_key: z.string().optional().or(z.literal("")),
|
||||||
embedding_base_url: z.string().url("請輸入有效的 URL").optional().or(z.literal("")),
|
embedding_base_url: z
|
||||||
|
.string()
|
||||||
|
.url("請輸入有效的 URL")
|
||||||
|
.optional()
|
||||||
|
.or(z.literal("")),
|
||||||
embedding_api_key: z.string().optional().or(z.literal("")),
|
embedding_api_key: z.string().optional().or(z.literal("")),
|
||||||
alpha_vantage_api_key: z.string().min(1, "請輸入 Alpha Vantage API Key"),
|
alpha_vantage_api_key: z.string().min(1, "請輸入 Alpha Vantage API Key"),
|
||||||
});
|
});
|
||||||
|
|
@ -87,7 +107,10 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
if (currentAnalysts.length === ANALYSTS.length) {
|
if (currentAnalysts.length === ANALYSTS.length) {
|
||||||
form.setValue("analysts", []);
|
form.setValue("analysts", []);
|
||||||
} else {
|
} else {
|
||||||
form.setValue("analysts", ANALYSTS.map(a => a.value));
|
form.setValue(
|
||||||
|
"analysts",
|
||||||
|
ANALYSTS.map((a) => a.value)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -102,19 +125,26 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<Card className="shadow-lg">
|
<Card className="shadow-lg">
|
||||||
<CardContent className="pt-6">
|
<CardContent className="pt-6">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-6">
|
<form
|
||||||
|
onSubmit={form.handleSubmit(handleSubmit)}
|
||||||
|
className="space-y-6"
|
||||||
|
>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{/* 分析師選擇區塊 - 全寬 */}
|
{/* 分析師選擇區塊 - 全寬 */}
|
||||||
<div className="md:col-span-2 border-b pb-6">
|
<div className="md:col-span-2 border-b pb-6">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<FormLabel className="text-base font-semibold">分析師團隊</FormLabel>
|
<FormLabel className="text-base font-semibold">
|
||||||
|
分析師團隊
|
||||||
|
</FormLabel>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={toggleSelectAll}
|
onClick={toggleSelectAll}
|
||||||
>
|
>
|
||||||
{form.watch("analysts").length === ANALYSTS.length ? "取消全選" : "全選"}
|
{form.watch("analysts").length === ANALYSTS.length
|
||||||
|
? "取消全選"
|
||||||
|
: "全選"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<FormField
|
<FormField
|
||||||
|
|
@ -136,13 +166,19 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
>
|
>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={field.value?.includes(analyst.value)}
|
checked={field.value?.includes(
|
||||||
|
analyst.value
|
||||||
|
)}
|
||||||
onCheckedChange={(checked) => {
|
onCheckedChange={(checked) => {
|
||||||
return checked
|
return checked
|
||||||
? field.onChange([...field.value, analyst.value])
|
? field.onChange([
|
||||||
|
...field.value,
|
||||||
|
analyst.value,
|
||||||
|
])
|
||||||
: field.onChange(
|
: field.onChange(
|
||||||
field.value?.filter(
|
field.value?.filter(
|
||||||
(value: string) => value !== analyst.value
|
(value: string) =>
|
||||||
|
value !== analyst.value
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
@ -191,9 +227,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="date" {...field} />
|
<Input type="date" {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>選擇分析日期</FormDescription>
|
||||||
選擇分析日期
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
@ -209,7 +243,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>研究深度</FormLabel>
|
<FormLabel>研究深度</FormLabel>
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(value) => field.onChange(parseInt(value))}
|
onValueChange={(value) =>
|
||||||
|
field.onChange(parseInt(value))
|
||||||
|
}
|
||||||
defaultValue={field.value.toString()}
|
defaultValue={field.value.toString()}
|
||||||
>
|
>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
|
@ -218,14 +254,18 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent className="max-h-80">
|
<SelectContent className="max-h-80">
|
||||||
<SelectItem value="1" className="py-3 cursor-pointer">淺層 - 快速研究</SelectItem>
|
<SelectItem value="1" className="py-3 cursor-pointer">
|
||||||
<SelectItem value="3" className="py-3 cursor-pointer">中等 - 適度討論</SelectItem>
|
淺層 - 快速研究
|
||||||
<SelectItem value="5" className="py-3 cursor-pointer">深層 - 深入研究</SelectItem>
|
</SelectItem>
|
||||||
|
<SelectItem value="3" className="py-3 cursor-pointer">
|
||||||
|
中等 - 適度討論
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="5" className="py-3 cursor-pointer">
|
||||||
|
深層 - 深入研究
|
||||||
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormDescription>
|
<FormDescription>選擇分析深度</FormDescription>
|
||||||
選擇分析深度
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
@ -248,42 +288,75 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{/* OpenAI */}
|
{/* OpenAI */}
|
||||||
<SelectItem value="gpt-5.1-2025-11-13">OpenAI: GPT-5.1</SelectItem>
|
<SelectItem value="gpt-5.1-2025-11-13">
|
||||||
<SelectItem value="gpt-5-mini-2025-08-07">OpenAI: GPT-5 Mini</SelectItem>
|
OpenAI: GPT-5.1
|
||||||
<SelectItem value="gpt-5-nano-2025-08-07">OpenAI: GPT-5 Nano</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="gpt-4.1-mini">OpenAI: GPT-4.1 Mini</SelectItem>
|
<SelectItem value="gpt-5-mini-2025-08-07">
|
||||||
<SelectItem value="gpt-4.1-nano">OpenAI: GPT-4.1 Nano</SelectItem>
|
OpenAI: GPT-5 Mini
|
||||||
<SelectItem value="o4-mini-2025-04-16">OpenAI: o4-mini</SelectItem>
|
</SelectItem>
|
||||||
|
<SelectItem value="gpt-5-nano-2025-08-07">
|
||||||
|
OpenAI: GPT-5 Nano
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="gpt-4.1-mini">
|
||||||
|
OpenAI: GPT-4.1 Mini
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="gpt-4.1-nano">
|
||||||
|
OpenAI: GPT-4.1 Nano
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="o4-mini-2025-04-16">
|
||||||
|
OpenAI: o4-mini
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* Anthropic */}
|
{/* Anthropic */}
|
||||||
<SelectItem value="claude-haiku-4-5-20251001">Anthropic: Claude Haiku 4.5</SelectItem>
|
<SelectItem value="claude-haiku-4-5-20251001">
|
||||||
<SelectItem value="claude-sonnet-4-5-20250929">Anthropic: Claude Sonnet 4.5</SelectItem>
|
Anthropic: Claude Haiku 4.5
|
||||||
<SelectItem value="claude-sonnet-4-0">Anthropic: Claude Sonnet 4</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="claude-3-5-haiku-20241022">Anthropic: Claude 3.5 Haiku</SelectItem>
|
<SelectItem value="claude-sonnet-4-5-20250929">
|
||||||
<SelectItem value="claude-3-haiku-20240307">Anthropic: Claude 3 Haiku</SelectItem>
|
Anthropic: Claude Sonnet 4.5
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="claude-sonnet-4-0">
|
||||||
|
Anthropic: Claude Sonnet 4
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="claude-3-5-haiku-20241022">
|
||||||
|
Anthropic: Claude 3.5 Haiku
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="claude-3-haiku-20240307">
|
||||||
|
Anthropic: Claude 3 Haiku
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* Grok */}
|
{/* Grok */}
|
||||||
<SelectItem value="grok-4-1-fast-reasoning">Grok: 4.1 Fast Reasoning</SelectItem>
|
<SelectItem value="grok-4-1-fast-reasoning">
|
||||||
<SelectItem value="grok-4-1-fast-non-reasoning">Grok: 4.1 Fast Non Reasoning</SelectItem>
|
Grok: 4.1 Fast Reasoning
|
||||||
<SelectItem value="grok-4-fast-reasoning">Grok: 4 Fast Reasoning</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="grok-4-fast-non-reasoning">Grok: 4 Fast Non Reasoning</SelectItem>
|
<SelectItem value="grok-4-1-fast-non-reasoning">
|
||||||
|
Grok: 4.1 Fast Non Reasoning
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="grok-4-fast-reasoning">
|
||||||
|
Grok: 4 Fast Reasoning
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="grok-4-fast-non-reasoning">
|
||||||
|
Grok: 4 Fast Non Reasoning
|
||||||
|
</SelectItem>
|
||||||
<SelectItem value="grok-4-0709">Grok: 4</SelectItem>
|
<SelectItem value="grok-4-0709">Grok: 4</SelectItem>
|
||||||
<SelectItem value="grok-3">Grok: 3</SelectItem>
|
<SelectItem value="grok-3">Grok: 3</SelectItem>
|
||||||
<SelectItem value="grok-3-mini">Grok: 3 Mini</SelectItem>
|
<SelectItem value="grok-3-mini">
|
||||||
|
Grok: 3 Mini
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* DeepSeek */}
|
{/* DeepSeek */}
|
||||||
<SelectItem value="deepseek-reasoner">DeepSeek: Reasoner</SelectItem>
|
<SelectItem value="deepseek-reasoner">
|
||||||
<SelectItem value="deepseek-chat">DeepSeek: Chat</SelectItem>
|
DeepSeek: Reasoner
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="deepseek-chat">
|
||||||
|
DeepSeek: Chat
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* Qwen */}
|
{/* Qwen */}
|
||||||
<SelectItem value="qwen3-max">Qwen: 3 Max</SelectItem>
|
<SelectItem value="qwen3-max">Qwen: 3 Max</SelectItem>
|
||||||
<SelectItem value="qwen-plus">Qwen: Plus</SelectItem>
|
<SelectItem value="qwen-plus">Qwen: Plus</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormDescription>
|
<FormDescription>快速回應模型</FormDescription>
|
||||||
快速回應模型
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
@ -306,42 +379,75 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{/* OpenAI */}
|
{/* OpenAI */}
|
||||||
<SelectItem value="gpt-5.1-2025-11-13">OpenAI: GPT-5.1</SelectItem>
|
<SelectItem value="gpt-5.1-2025-11-13">
|
||||||
<SelectItem value="gpt-5-mini-2025-08-07">OpenAI: GPT-5 Mini</SelectItem>
|
OpenAI: GPT-5.1
|
||||||
<SelectItem value="gpt-5-nano-2025-08-07">OpenAI: GPT-5 Nano</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="gpt-4.1-mini">OpenAI: GPT-4.1 Mini</SelectItem>
|
<SelectItem value="gpt-5-mini-2025-08-07">
|
||||||
<SelectItem value="gpt-4.1-nano">OpenAI: GPT-4.1 Nano</SelectItem>
|
OpenAI: GPT-5 Mini
|
||||||
<SelectItem value="o4-mini-2025-04-16">OpenAI: o4-mini</SelectItem>
|
</SelectItem>
|
||||||
|
<SelectItem value="gpt-5-nano-2025-08-07">
|
||||||
|
OpenAI: GPT-5 Nano
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="gpt-4.1-mini">
|
||||||
|
OpenAI: GPT-4.1 Mini
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="gpt-4.1-nano">
|
||||||
|
OpenAI: GPT-4.1 Nano
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="o4-mini-2025-04-16">
|
||||||
|
OpenAI: o4-mini
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* Anthropic */}
|
{/* Anthropic */}
|
||||||
<SelectItem value="claude-haiku-4-5-20251001">Anthropic: Claude Haiku 4.5</SelectItem>
|
<SelectItem value="claude-haiku-4-5-20251001">
|
||||||
<SelectItem value="claude-sonnet-4-5-20250929">Anthropic: Claude Sonnet 4.5</SelectItem>
|
Anthropic: Claude Haiku 4.5
|
||||||
<SelectItem value="claude-sonnet-4-0">Anthropic: Claude Sonnet 4</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="claude-3-5-haiku-20241022">Anthropic: Claude 3.5 Haiku</SelectItem>
|
<SelectItem value="claude-sonnet-4-5-20250929">
|
||||||
<SelectItem value="claude-3-haiku-20240307">Anthropic: Claude 3 Haiku</SelectItem>
|
Anthropic: Claude Sonnet 4.5
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="claude-sonnet-4-0">
|
||||||
|
Anthropic: Claude Sonnet 4
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="claude-3-5-haiku-20241022">
|
||||||
|
Anthropic: Claude 3.5 Haiku
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="claude-3-haiku-20240307">
|
||||||
|
Anthropic: Claude 3 Haiku
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* Grok */}
|
{/* Grok */}
|
||||||
<SelectItem value="grok-4-1-fast-reasoning">Grok: 4.1 Fast Reasoning</SelectItem>
|
<SelectItem value="grok-4-1-fast-reasoning">
|
||||||
<SelectItem value="grok-4-1-fast-non-reasoning">Grok: 4.1 Fast Non Reasoning</SelectItem>
|
Grok: 4.1 Fast Reasoning
|
||||||
<SelectItem value="grok-4-fast-reasoning">Grok: 4 Fast Reasoning</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="grok-4-fast-non-reasoning">Grok: 4 Fast Non Reasoning</SelectItem>
|
<SelectItem value="grok-4-1-fast-non-reasoning">
|
||||||
|
Grok: 4.1 Fast Non Reasoning
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="grok-4-fast-reasoning">
|
||||||
|
Grok: 4 Fast Reasoning
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="grok-4-fast-non-reasoning">
|
||||||
|
Grok: 4 Fast Non Reasoning
|
||||||
|
</SelectItem>
|
||||||
<SelectItem value="grok-4-0709">Grok: 4</SelectItem>
|
<SelectItem value="grok-4-0709">Grok: 4</SelectItem>
|
||||||
<SelectItem value="grok-3">Grok: 3</SelectItem>
|
<SelectItem value="grok-3">Grok: 3</SelectItem>
|
||||||
<SelectItem value="grok-3-mini">Grok: 3 Mini</SelectItem>
|
<SelectItem value="grok-3-mini">
|
||||||
|
Grok: 3 Mini
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* DeepSeek */}
|
{/* DeepSeek */}
|
||||||
<SelectItem value="deepseek-reasoner">DeepSeek: Reasoner</SelectItem>
|
<SelectItem value="deepseek-reasoner">
|
||||||
<SelectItem value="deepseek-chat">DeepSeek: Chat</SelectItem>
|
DeepSeek: Reasoner
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="deepseek-chat">
|
||||||
|
DeepSeek: Chat
|
||||||
|
</SelectItem>
|
||||||
|
|
||||||
{/* Qwen */}
|
{/* Qwen */}
|
||||||
<SelectItem value="qwen3-max">Qwen: 3 Max</SelectItem>
|
<SelectItem value="qwen3-max">Qwen: 3 Max</SelectItem>
|
||||||
<SelectItem value="qwen-plus">Qwen: Plus</SelectItem>
|
<SelectItem value="qwen-plus">Qwen: Plus</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormDescription>
|
<FormDescription>複雜推理模型</FormDescription>
|
||||||
複雜推理模型
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
@ -349,10 +455,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* API Configuration Section */}
|
{/* API Configuration Section */}
|
||||||
<div className="space-y-4 border-t pt-6 mt-6">
|
<div className="space-y-4 border-t pt-6 mt-6">
|
||||||
<h3 className="text-lg font-semibold">API 配置</h3>
|
<h3 className="text-lg font-semibold">API 配置</h3>
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
|
@ -372,10 +477,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
[
|
[
|
||||||
"https://api.openai.com/v1",
|
"https://api.openai.com/v1",
|
||||||
"https://api.anthropic.com/",
|
"https://api.anthropic.com/",
|
||||||
"https://generativelanguage.googleapis.com/v1",
|
|
||||||
"https://api.x.ai/v1",
|
"https://api.x.ai/v1",
|
||||||
"https://api.deepseek.com",
|
"https://api.deepseek.com",
|
||||||
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
||||||
].includes(field.value || "")
|
].includes(field.value || "")
|
||||||
? field.value
|
? field.value
|
||||||
: "custom"
|
: "custom"
|
||||||
|
|
@ -387,12 +491,21 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="https://api.openai.com/v1">OpenAI (預設)</SelectItem>
|
<SelectItem value="https://api.openai.com/v1">
|
||||||
<SelectItem value="https://api.anthropic.com/">Anthropic</SelectItem>
|
OpenAI (預設)
|
||||||
<SelectItem value="https://generativelanguage.googleapis.com/v1">Google Gemini</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="https://api.x.ai/v1">Grok (xAI)</SelectItem>
|
<SelectItem value="https://api.anthropic.com/">
|
||||||
<SelectItem value="https://api.deepseek.com">DeepSeek</SelectItem>
|
Anthropic
|
||||||
<SelectItem value="https://dashscope-intl.aliyuncs.com/compatible-mode/v1">Qwen (Alibaba)</SelectItem>
|
</SelectItem>
|
||||||
|
<SelectItem value="https://api.x.ai/v1">
|
||||||
|
Grok (xAI)
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="https://api.deepseek.com">
|
||||||
|
DeepSeek
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="https://dashscope-intl.aliyuncs.com/compatible-mode/v1">
|
||||||
|
Qwen (Alibaba)
|
||||||
|
</SelectItem>
|
||||||
<SelectItem value="custom">自訂端點</SelectItem>
|
<SelectItem value="custom">自訂端點</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
@ -403,8 +516,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
"https://generativelanguage.googleapis.com/v1",
|
"https://generativelanguage.googleapis.com/v1",
|
||||||
"https://api.x.ai/v1",
|
"https://api.x.ai/v1",
|
||||||
"https://api.deepseek.com",
|
"https://api.deepseek.com",
|
||||||
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
||||||
].includes(field.value || "") || field.value === "") && (
|
].includes(field.value || "") ||
|
||||||
|
field.value === "") && (
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -459,10 +573,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
[
|
[
|
||||||
"https://api.openai.com/v1",
|
"https://api.openai.com/v1",
|
||||||
"https://api.anthropic.com/",
|
"https://api.anthropic.com/",
|
||||||
"https://generativelanguage.googleapis.com/v1",
|
|
||||||
"https://api.x.ai/v1",
|
"https://api.x.ai/v1",
|
||||||
"https://api.deepseek.com",
|
"https://api.deepseek.com",
|
||||||
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
||||||
].includes(field.value || "")
|
].includes(field.value || "")
|
||||||
? field.value
|
? field.value
|
||||||
: "custom"
|
: "custom"
|
||||||
|
|
@ -474,12 +587,21 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="https://api.openai.com/v1">OpenAI (預設)</SelectItem>
|
<SelectItem value="https://api.openai.com/v1">
|
||||||
<SelectItem value="https://api.anthropic.com/">Anthropic</SelectItem>
|
OpenAI (預設)
|
||||||
<SelectItem value="https://generativelanguage.googleapis.com/v1">Google Gemini</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="https://api.x.ai/v1">Grok (xAI)</SelectItem>
|
<SelectItem value="https://api.anthropic.com/">
|
||||||
<SelectItem value="https://api.deepseek.com">DeepSeek</SelectItem>
|
Anthropic
|
||||||
<SelectItem value="https://dashscope-intl.aliyuncs.com/compatible-mode/v1">Qwen (Alibaba)</SelectItem>
|
</SelectItem>
|
||||||
|
<SelectItem value="https://api.x.ai/v1">
|
||||||
|
Grok (xAI)
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="https://api.deepseek.com">
|
||||||
|
DeepSeek
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="https://dashscope-intl.aliyuncs.com/compatible-mode/v1">
|
||||||
|
Qwen (Alibaba)
|
||||||
|
</SelectItem>
|
||||||
<SelectItem value="custom">自訂端點</SelectItem>
|
<SelectItem value="custom">自訂端點</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
@ -490,8 +612,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
"https://generativelanguage.googleapis.com/v1",
|
"https://generativelanguage.googleapis.com/v1",
|
||||||
"https://api.x.ai/v1",
|
"https://api.x.ai/v1",
|
||||||
"https://api.deepseek.com",
|
"https://api.deepseek.com",
|
||||||
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
|
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
||||||
].includes(field.value || "") || field.value === "") && (
|
].includes(field.value || "") ||
|
||||||
|
field.value === "") && (
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -543,7 +666,8 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
field.value === "https://api.openai.com/v1" || !field.value
|
field.value === "https://api.openai.com/v1" ||
|
||||||
|
!field.value
|
||||||
? "https://api.openai.com/v1"
|
? "https://api.openai.com/v1"
|
||||||
: "custom"
|
: "custom"
|
||||||
}
|
}
|
||||||
|
|
@ -554,7 +678,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="https://api.openai.com/v1">OpenAI (預設)</SelectItem>
|
<SelectItem value="https://api.openai.com/v1">
|
||||||
|
OpenAI (預設)
|
||||||
|
</SelectItem>
|
||||||
<SelectItem value="custom">自訂端點</SelectItem>
|
<SelectItem value="custom">自訂端點</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
@ -603,7 +729,11 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Alpha Vantage API Key *</FormLabel>
|
<FormLabel>Alpha Vantage API Key *</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input type="password" placeholder="輸入 Alpha Vantage API Key(必填)" {...field} />
|
<Input
|
||||||
|
type="password"
|
||||||
|
placeholder="輸入 Alpha Vantage API Key(必填)"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
用於獲取市場基本面數據(必填)
|
用於獲取市場基本面數據(必填)
|
||||||
|
|
@ -614,7 +744,12 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button type="submit" className="w-full" disabled={loading} size="lg">
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="w-full"
|
||||||
|
disabled={loading}
|
||||||
|
size="lg"
|
||||||
|
>
|
||||||
{loading ? "執行分析中..." : "執行分析"}
|
{loading ? "執行分析中..." : "執行分析"}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue