PMFlow/frontend/src/pages/project-board/components/ProjectSettingsDialog.tsx

155 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Dispatch, SetStateAction } from "react";
import type { AIRoutingConfig } from "@/api/sstc";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
interface ProjectSettingsDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
routingDraft: AIRoutingConfig | null;
setRoutingDraft: Dispatch<SetStateAction<AIRoutingConfig | null>>;
routingConfigLoading: boolean;
isSaving: boolean;
onCancel: () => void;
onSave: (payload: {
cold_start_enabled: boolean;
signal_auto_enter_threshold: number;
project_auto_create_threshold: number;
project_uncertain_threshold: number;
}) => void;
}
export default function ProjectSettingsDialog({
open,
onOpenChange,
routingDraft,
setRoutingDraft,
routingConfigLoading,
isSaving,
onCancel,
onSave,
}: ProjectSettingsDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="w-[min(640px,calc(100vw-1rem))] max-w-[calc(100vw-1rem)] sm:max-w-[640px]">
<DialogHeader>
<DialogTitle>项目设置</DialogTitle>
<DialogDescription>
管理冷启动与自动路由阈值。示例:`0.80` 表示模型置信度达到 80% 即自动入库。
</DialogDescription>
</DialogHeader>
{!routingDraft ? (
<p className="text-sm text-muted-foreground">{routingConfigLoading ? "正在加载项目设置…" : "暂未加载到路由配置"}</p>
) : (
<div className="space-y-4">
<div className="rounded-md border bg-muted/20 p-3">
<div className="flex flex-wrap items-start justify-between gap-3">
<div className="space-y-1">
<p className="text-sm font-semibold">冷启动开关</p>
<p className="text-xs text-muted-foreground">{routingDraft.tips.cold_start_enabled}</p>
</div>
<Button
size="sm"
variant={routingDraft.cold_start_enabled ? "default" : "outline"}
disabled={isSaving}
onClick={() =>
setRoutingDraft((prev) => (prev ? { ...prev, cold_start_enabled: !prev.cold_start_enabled } : prev))
}
>
冷启动:{routingDraft.cold_start_enabled ? "开启" : "关闭"}
</Button>
</div>
</div>
<div className="grid gap-3 md:grid-cols-3">
<label className="space-y-1 text-xs">
<span className="font-medium">自动入库阈值(confidence)</span>
<Input
type="number"
step="0.01"
min="0"
max="1"
value={routingDraft.signal_auto_enter_threshold}
disabled={isSaving}
onChange={(e) => {
const val = Number(e.target.value);
setRoutingDraft((prev) =>
prev && Number.isFinite(val) ? { ...prev, signal_auto_enter_threshold: val } : prev
);
}}
/>
<p className="text-muted-foreground">{routingDraft.tips.signal_auto_enter_threshold}</p>
</label>
<label className="space-y-1 text-xs">
<span className="font-medium">自动建项阈值(project_score)</span>
<Input
type="number"
step="0.01"
min="0"
max="1"
value={routingDraft.project_auto_create_threshold}
disabled={isSaving}
onChange={(e) => {
const val = Number(e.target.value);
setRoutingDraft((prev) =>
prev && Number.isFinite(val) ? { ...prev, project_auto_create_threshold: val } : prev
);
}}
/>
<p className="text-muted-foreground">{routingDraft.tips.project_auto_create_threshold}</p>
</label>
<label className="space-y-1 text-xs">
<span className="font-medium">项目待确认阈值(project_uncertain)</span>
<Input
type="number"
step="0.01"
min="0"
max="1"
value={routingDraft.project_uncertain_threshold}
disabled={isSaving}
onChange={(e) => {
const val = Number(e.target.value);
setRoutingDraft((prev) =>
prev && Number.isFinite(val) ? { ...prev, project_uncertain_threshold: val } : prev
);
}}
/>
<p className="text-muted-foreground">{routingDraft.tips.project_uncertain_threshold}</p>
</label>
</div>
</div>
)}
<DialogFooter>
<Button variant="outline" onClick={onCancel}>
取消
</Button>
<Button
disabled={!routingDraft || isSaving}
onClick={() => {
if (!routingDraft) return;
onSave({
cold_start_enabled: routingDraft.cold_start_enabled,
signal_auto_enter_threshold: Number(routingDraft.signal_auto_enter_threshold.toFixed(2)),
project_auto_create_threshold: Number(routingDraft.project_auto_create_threshold.toFixed(2)),
project_uncertain_threshold: Number(routingDraft.project_uncertain_threshold.toFixed(2)),
});
}}
>
{isSaving ? "保存中…" : "保存设置"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}