This commit is contained in:
parent
8b2dbe9437
commit
c9f6e6a8d1
|
|
@ -121,6 +121,41 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Safari mobile touch fixes */
|
||||||
|
@layer base {
|
||||||
|
/* Fix for Safari iOS touch events on buttons and interactive elements */
|
||||||
|
button,
|
||||||
|
[role="button"],
|
||||||
|
input[type="submit"],
|
||||||
|
input[type="button"],
|
||||||
|
.cursor-pointer {
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
touch-action: manipulation;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure form elements are properly interactive on iOS */
|
||||||
|
select,
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fix for Radix UI popover/select on iOS Safari */
|
||||||
|
[data-radix-popper-content-wrapper] {
|
||||||
|
touch-action: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure buttons inside forms work on iOS */
|
||||||
|
form button[type="submit"] {
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Custom animations */
|
/* Custom animations */
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from {
|
from {
|
||||||
|
|
@ -186,7 +221,8 @@
|
||||||
|
|
||||||
/* Heartbeat animation for buttons */
|
/* Heartbeat animation for buttons */
|
||||||
@keyframes heartbeat {
|
@keyframes heartbeat {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
10% {
|
10% {
|
||||||
|
|
@ -283,19 +319,19 @@
|
||||||
|
|
||||||
/* Gradient Backgrounds - Blue/Pink in light, Blue/Purple in dark */
|
/* Gradient Backgrounds - Blue/Pink in light, Blue/Purple in dark */
|
||||||
.gradient-bg-primary {
|
.gradient-bg-primary {
|
||||||
background: linear-gradient(135deg, #3B82F6 0%, #EC4899 100%);
|
background: linear-gradient(135deg, #3b82f6 0%, #ec4899 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .gradient-bg-primary {
|
.dark .gradient-bg-primary {
|
||||||
background: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%);
|
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.gradient-bg-secondary {
|
.gradient-bg-secondary {
|
||||||
background: linear-gradient(135deg, #60A5FA 0%, #F472B6 100%);
|
background: linear-gradient(135deg, #60a5fa 0%, #f472b6 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .gradient-bg-secondary {
|
.dark .gradient-bg-secondary {
|
||||||
background: linear-gradient(135deg, #60A5FA 0%, #A78BFA 100%);
|
background: linear-gradient(135deg, #60a5fa 0%, #a78bfa 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.gradient-bg-accent {
|
.gradient-bg-accent {
|
||||||
|
|
@ -436,28 +472,28 @@
|
||||||
|
|
||||||
/* Gradient Text - Blue/Pink in light, Blue/Purple in dark */
|
/* Gradient Text - Blue/Pink in light, Blue/Purple in dark */
|
||||||
.gradient-text-primary {
|
.gradient-text-primary {
|
||||||
background: linear-gradient(135deg, #3B82F6 0%, #EC4899 100%);
|
background: linear-gradient(135deg, #3b82f6 0%, #ec4899 100%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .gradient-text-primary {
|
.dark .gradient-text-primary {
|
||||||
background: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%);
|
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gradient-text-secondary {
|
.gradient-text-secondary {
|
||||||
background: linear-gradient(135deg, #60A5FA 0%, #F472B6 100%);
|
background: linear-gradient(135deg, #60a5fa 0%, #f472b6 100%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .gradient-text-secondary {
|
.dark .gradient-text-secondary {
|
||||||
background: linear-gradient(135deg, #60A5FA 0%, #A78BFA 100%);
|
background: linear-gradient(135deg, #60a5fa 0%, #a78bfa 100%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
|
|
@ -635,5 +671,3 @@
|
||||||
box-shadow: 0 4px 20px 0 rgba(147, 51, 234, 0.2),
|
box-shadow: 0 4px 20px 0 rgba(147, 51, 234, 0.2),
|
||||||
inset 0 1px 0 0 rgba(255, 255, 255, 0.1);
|
inset 0 1px 0 0 rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,10 @@ const formSchema = z.object({
|
||||||
research_depth: z.number().int().min(1).max(5),
|
research_depth: z.number().int().min(1).max(5),
|
||||||
quick_think_llm: z.string().min(1, "請選擇快速思維模型"),
|
quick_think_llm: z.string().min(1, "請選擇快速思維模型"),
|
||||||
deep_think_llm: z.string().min(1, "請選擇深層思維模型"),
|
deep_think_llm: z.string().min(1, "請選擇深層思維模型"),
|
||||||
|
|
||||||
// Market type selection: us=美股, twse=上市, tpex=上櫃/興櫃
|
// Market type selection: us=美股, twse=上市, tpex=上櫃/興櫃
|
||||||
market_type: z.enum(["us", "twse", "tpex"]),
|
market_type: z.enum(["us", "twse", "tpex"]),
|
||||||
|
|
||||||
// Custom model names (when "custom" is selected)
|
// Custom model names (when "custom" is selected)
|
||||||
custom_quick_think_model: z.string().optional(),
|
custom_quick_think_model: z.string().optional(),
|
||||||
custom_deep_think_model: z.string().optional(),
|
custom_deep_think_model: z.string().optional(),
|
||||||
|
|
@ -79,8 +79,8 @@ const formSchema = z.object({
|
||||||
.optional()
|
.optional()
|
||||||
.or(z.literal("")),
|
.or(z.literal("")),
|
||||||
embedding_api_key: z.string().min(1, "請輸入嵌入模型 API Key"),
|
embedding_api_key: z.string().min(1, "請輸入嵌入模型 API Key"),
|
||||||
alpha_vantage_api_key: z.string().optional().or(z.literal("")), // 選填
|
alpha_vantage_api_key: z.string().optional().or(z.literal("")), // 選填
|
||||||
finmind_api_key: z.string().optional().or(z.literal("")), // 選填
|
finmind_api_key: z.string().optional().or(z.literal("")), // 選填
|
||||||
});
|
});
|
||||||
|
|
||||||
interface AnalysisFormProps {
|
interface AnalysisFormProps {
|
||||||
|
|
@ -125,7 +125,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
const marketType = form.watch("market_type");
|
const marketType = form.watch("market_type");
|
||||||
const isQuickThinkCustom = quickThinkLlm === "custom";
|
const isQuickThinkCustom = quickThinkLlm === "custom";
|
||||||
const isDeepThinkCustom = deepThinkLlm === "custom";
|
const isDeepThinkCustom = deepThinkLlm === "custom";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Use async version to get decrypted API keys
|
// Use async version to get decrypted API keys
|
||||||
const loadSettings = async () => {
|
const loadSettings = async () => {
|
||||||
|
|
@ -133,27 +133,57 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
|
|
||||||
// For custom models, always use custom base URL and API key
|
// For custom models, always use custom base URL and API key
|
||||||
if (isQuickThinkCustom) {
|
if (isQuickThinkCustom) {
|
||||||
form.setValue("quick_think_base_url", savedSettings.custom_base_url || "");
|
form.setValue(
|
||||||
form.setValue("quick_think_api_key", savedSettings.custom_api_key || "");
|
"quick_think_base_url",
|
||||||
|
savedSettings.custom_base_url || ""
|
||||||
|
);
|
||||||
|
form.setValue(
|
||||||
|
"quick_think_api_key",
|
||||||
|
savedSettings.custom_api_key || ""
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
form.setValue("quick_think_base_url", getBaseUrlForModel(quickThinkLlm, savedSettings.custom_base_url));
|
form.setValue(
|
||||||
form.setValue("quick_think_api_key", getApiKeyForModel(quickThinkLlm, savedSettings));
|
"quick_think_base_url",
|
||||||
}
|
getBaseUrlForModel(quickThinkLlm, savedSettings.custom_base_url)
|
||||||
|
);
|
||||||
if (isDeepThinkCustom) {
|
form.setValue(
|
||||||
form.setValue("deep_think_base_url", savedSettings.custom_base_url || "");
|
"quick_think_api_key",
|
||||||
form.setValue("deep_think_api_key", savedSettings.custom_api_key || "");
|
getApiKeyForModel(quickThinkLlm, savedSettings)
|
||||||
} else {
|
);
|
||||||
form.setValue("deep_think_base_url", getBaseUrlForModel(deepThinkLlm, savedSettings.custom_base_url));
|
|
||||||
form.setValue("deep_think_api_key", getApiKeyForModel(deepThinkLlm, savedSettings));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form.setValue("embedding_base_url", savedSettings.custom_base_url || "https://api.openai.com/v1");
|
if (isDeepThinkCustom) {
|
||||||
form.setValue("embedding_api_key", savedSettings.custom_api_key || savedSettings.openai_api_key);
|
form.setValue(
|
||||||
form.setValue("alpha_vantage_api_key", savedSettings.alpha_vantage_api_key || "");
|
"deep_think_base_url",
|
||||||
|
savedSettings.custom_base_url || ""
|
||||||
|
);
|
||||||
|
form.setValue("deep_think_api_key", savedSettings.custom_api_key || "");
|
||||||
|
} else {
|
||||||
|
form.setValue(
|
||||||
|
"deep_think_base_url",
|
||||||
|
getBaseUrlForModel(deepThinkLlm, savedSettings.custom_base_url)
|
||||||
|
);
|
||||||
|
form.setValue(
|
||||||
|
"deep_think_api_key",
|
||||||
|
getApiKeyForModel(deepThinkLlm, savedSettings)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
form.setValue(
|
||||||
|
"embedding_base_url",
|
||||||
|
savedSettings.custom_base_url || "https://api.openai.com/v1"
|
||||||
|
);
|
||||||
|
form.setValue(
|
||||||
|
"embedding_api_key",
|
||||||
|
savedSettings.custom_api_key || savedSettings.openai_api_key
|
||||||
|
);
|
||||||
|
form.setValue(
|
||||||
|
"alpha_vantage_api_key",
|
||||||
|
savedSettings.alpha_vantage_api_key || ""
|
||||||
|
);
|
||||||
form.setValue("finmind_api_key", savedSettings.finmind_api_key || "");
|
form.setValue("finmind_api_key", savedSettings.finmind_api_key || "");
|
||||||
};
|
};
|
||||||
|
|
||||||
loadSettings();
|
loadSettings();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [quickThinkLlm, deepThinkLlm, isQuickThinkCustom, isDeepThinkCustom]);
|
}, [quickThinkLlm, deepThinkLlm, isQuickThinkCustom, isDeepThinkCustom]);
|
||||||
|
|
@ -163,9 +193,13 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
const currentTicker = form.getValues("ticker");
|
const currentTicker = form.getValues("ticker");
|
||||||
// 只在用戶未修改預設值時才自動切換
|
// 只在用戶未修改預設值時才自動切換
|
||||||
const isTwStock = marketType === "twse" || marketType === "tpex";
|
const isTwStock = marketType === "twse" || marketType === "tpex";
|
||||||
const isDefaultUsTicker = currentTicker === "NVDA" || currentTicker === "AAPL";
|
const isDefaultUsTicker =
|
||||||
const isDefaultTwTicker = currentTicker === "2330" || currentTicker === "2317" || currentTicker === "6488";
|
currentTicker === "NVDA" || currentTicker === "AAPL";
|
||||||
|
const isDefaultTwTicker =
|
||||||
|
currentTicker === "2330" ||
|
||||||
|
currentTicker === "2317" ||
|
||||||
|
currentTicker === "6488";
|
||||||
|
|
||||||
if (isTwStock && isDefaultUsTicker) {
|
if (isTwStock && isDefaultUsTicker) {
|
||||||
form.setValue("ticker", marketType === "twse" ? "2330" : "6488");
|
form.setValue("ticker", marketType === "twse" ? "2330" : "6488");
|
||||||
} else if (marketType === "us" && isDefaultTwTicker) {
|
} else if (marketType === "us" && isDefaultTwTicker) {
|
||||||
|
|
@ -189,31 +223,36 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
|
|
||||||
function handleSubmit(values: z.infer<typeof formSchema>) {
|
function handleSubmit(values: z.infer<typeof formSchema>) {
|
||||||
// Use custom model names if "custom" is selected
|
// Use custom model names if "custom" is selected
|
||||||
const finalQuickThinkLlm = values.quick_think_llm === "custom"
|
const finalQuickThinkLlm =
|
||||||
? values.custom_quick_think_model || ""
|
values.quick_think_llm === "custom"
|
||||||
: values.quick_think_llm;
|
? values.custom_quick_think_model || ""
|
||||||
|
: values.quick_think_llm;
|
||||||
const finalDeepThinkLlm = values.deep_think_llm === "custom"
|
|
||||||
? values.custom_deep_think_model || ""
|
const finalDeepThinkLlm =
|
||||||
: values.deep_think_llm;
|
values.deep_think_llm === "custom"
|
||||||
|
? values.custom_deep_think_model || ""
|
||||||
|
: values.deep_think_llm;
|
||||||
|
|
||||||
// Validate custom model names
|
// Validate custom model names
|
||||||
if (values.quick_think_llm === "custom" && !values.custom_quick_think_model) {
|
if (
|
||||||
|
values.quick_think_llm === "custom" &&
|
||||||
|
!values.custom_quick_think_model
|
||||||
|
) {
|
||||||
form.setError("custom_quick_think_model", {
|
form.setError("custom_quick_think_model", {
|
||||||
type: "manual",
|
type: "manual",
|
||||||
message: "請輸入快速思維模型的完整名稱"
|
message: "請輸入快速思維模型的完整名稱",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.deep_think_llm === "custom" && !values.custom_deep_think_model) {
|
if (values.deep_think_llm === "custom" && !values.custom_deep_think_model) {
|
||||||
form.setError("custom_deep_think_model", {
|
form.setError("custom_deep_think_model", {
|
||||||
type: "manual",
|
type: "manual",
|
||||||
message: "請輸入深層思維模型的完整名稱"
|
message: "請輸入深層思維模型的完整名稱",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const request: AnalysisRequest = {
|
const request: AnalysisRequest = {
|
||||||
...values,
|
...values,
|
||||||
quick_think_llm: finalQuickThinkLlm,
|
quick_think_llm: finalQuickThinkLlm,
|
||||||
|
|
@ -255,17 +294,18 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||||
{ANALYSTS.map((analyst) => {
|
{ANALYSTS.map((analyst) => {
|
||||||
const isSelected = field.value?.includes(analyst.value);
|
const isSelected = field.value?.includes(
|
||||||
|
analyst.value
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<FormItem
|
<FormItem key={analyst.value} className="space-y-0">
|
||||||
key={analyst.value}
|
|
||||||
className="space-y-0"
|
|
||||||
>
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const newValue = isSelected
|
const newValue = isSelected
|
||||||
? field.value?.filter((v: string) => v !== analyst.value)
|
? field.value?.filter(
|
||||||
|
(v: string) => v !== analyst.value
|
||||||
|
)
|
||||||
: [...(field.value ?? []), analyst.value];
|
: [...(field.value ?? []), analyst.value];
|
||||||
field.onChange(newValue);
|
field.onChange(newValue);
|
||||||
}}
|
}}
|
||||||
|
|
@ -284,9 +324,13 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
: "border-muted-foreground"
|
: "border-muted-foreground"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{isSelected && <CheckIcon className="h-3.5 w-3.5" />}
|
{isSelected && (
|
||||||
|
<CheckIcon className="h-3.5 w-3.5" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="font-medium select-none">{analyst.label}</span>
|
<span className="font-medium select-none">
|
||||||
|
{analyst.label}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
@ -318,20 +362,27 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="us" className="py-3 cursor-pointer">
|
<SelectItem
|
||||||
|
value="us"
|
||||||
|
className="py-3 cursor-pointer"
|
||||||
|
>
|
||||||
🇺🇸 美股
|
🇺🇸 美股
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="twse" className="py-3 cursor-pointer">
|
<SelectItem
|
||||||
|
value="twse"
|
||||||
|
className="py-3 cursor-pointer"
|
||||||
|
>
|
||||||
🇹🇼 台股上市
|
🇹🇼 台股上市
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="tpex" className="py-3 cursor-pointer">
|
<SelectItem
|
||||||
|
value="tpex"
|
||||||
|
className="py-3 cursor-pointer"
|
||||||
|
>
|
||||||
🇹🇼 台股上櫃/興櫃
|
🇹🇼 台股上櫃/興櫃
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormDescription>
|
<FormDescription>選擇分析的股票市場</FormDescription>
|
||||||
選擇分析的股票市場
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|
@ -345,21 +396,23 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>股票代碼</FormLabel>
|
<FormLabel>股票代碼</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={
|
placeholder={
|
||||||
marketType === "us" ? "NVDA" :
|
marketType === "us"
|
||||||
marketType === "twse" ? "2330" : "6488"
|
? "NVDA"
|
||||||
}
|
: marketType === "twse"
|
||||||
{...field}
|
? "2330"
|
||||||
|
: "6488"
|
||||||
|
}
|
||||||
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
{marketType === "us"
|
{marketType === "us"
|
||||||
? "輸入美股代碼(例如:NVDA、AAPL)"
|
? "輸入美股代碼(例如:NVDA、AAPL)"
|
||||||
: marketType === "twse"
|
: marketType === "twse"
|
||||||
? "輸入上市股票代碼(例如:2330、2317)"
|
? "輸入上市股票代碼(例如:2330、2317)"
|
||||||
: "輸入上櫃/興櫃股票代碼(例如:6488、5765)"
|
: "輸入上櫃/興櫃股票代碼(例如:6488、5765)"}
|
||||||
}
|
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
@ -376,7 +429,9 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<DatePicker
|
<DatePicker
|
||||||
date={field.value ? new Date(field.value) : undefined}
|
date={field.value ? new Date(field.value) : undefined}
|
||||||
onDateChange={(date) => {
|
onDateChange={(date) => {
|
||||||
field.onChange(date ? format(date, "yyyy-MM-dd") : "")
|
field.onChange(
|
||||||
|
date ? format(date, "yyyy-MM-dd") : ""
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
placeholder="選擇分析日期"
|
placeholder="選擇分析日期"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
|
@ -535,7 +590,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<SelectItem value="qwen-flash">
|
<SelectItem value="qwen-flash">
|
||||||
Qwen: Flash
|
Qwen: Flash
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
|
||||||
{/* Custom Model */}
|
{/* Custom Model */}
|
||||||
<SelectItem value="custom">
|
<SelectItem value="custom">
|
||||||
Other(自訂模型)
|
Other(自訂模型)
|
||||||
|
|
@ -547,7 +602,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Custom Quick Think Model Input */}
|
{/* Custom Quick Think Model Input */}
|
||||||
{isQuickThinkCustom && (
|
{isQuickThinkCustom && (
|
||||||
<FormField
|
<FormField
|
||||||
|
|
@ -557,10 +612,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormItem className="md:col-span-3 animate-scale-up">
|
<FormItem className="md:col-span-3 animate-scale-up">
|
||||||
<FormLabel>自訂快速思維模型名稱</FormLabel>
|
<FormLabel>自訂快速思維模型名稱</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input placeholder="例如:deepseek-chat" {...field} />
|
||||||
placeholder="例如:deepseek-chat"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
請輸入完整的模型名稱(此模型將使用自訂端點)
|
請輸入完整的模型名稱(此模型將使用自訂端點)
|
||||||
|
|
@ -680,7 +732,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<SelectItem value="qwen-flash">
|
<SelectItem value="qwen-flash">
|
||||||
Qwen: Flash
|
Qwen: Flash
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
|
||||||
{/* Custom Model */}
|
{/* Custom Model */}
|
||||||
<SelectItem value="custom">
|
<SelectItem value="custom">
|
||||||
Other(自訂模型)
|
Other(自訂模型)
|
||||||
|
|
@ -692,7 +744,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Custom Deep Think Model Input */}
|
{/* Custom Deep Think Model Input */}
|
||||||
{isDeepThinkCustom && (
|
{isDeepThinkCustom && (
|
||||||
<FormField
|
<FormField
|
||||||
|
|
@ -702,10 +754,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
<FormItem className="md:col-span-3 animate-scale-up">
|
<FormItem className="md:col-span-3 animate-scale-up">
|
||||||
<FormLabel>自訂深層思維模型名稱</FormLabel>
|
<FormLabel>自訂深層思維模型名稱</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input placeholder="例如:deepseek-chat" {...field} />
|
||||||
placeholder="例如:deepseek-chat"
|
|
||||||
{...field}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
請輸入完整的模型名稱(此模型將使用自訂端點)
|
請輸入完整的模型名稱(此模型將使用自訂端點)
|
||||||
|
|
@ -723,6 +772,14 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
|
||||||
className="w-full bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 hover:from-blue-600 hover:to-pink-600 dark:hover:from-blue-700 dark:hover:to-purple-700 shadow-lg hover:shadow-xl transition-all animate-heartbeat"
|
className="w-full bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 hover:from-blue-600 hover:to-pink-600 dark:hover:from-blue-700 dark:hover:to-purple-700 shadow-lg hover:shadow-xl transition-all animate-heartbeat"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
size="lg"
|
size="lg"
|
||||||
|
style={{
|
||||||
|
touchAction: "manipulation",
|
||||||
|
WebkitTapHighlightColor: "transparent",
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
// Ensure touch events work on Safari mobile
|
||||||
|
e.currentTarget.blur();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{loading ? "執行分析中..." : "執行分析"}
|
{loading ? "執行分析中..." : "執行分析"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue