166 lines
4.4 KiB
TypeScript
166 lines
4.4 KiB
TypeScript
"use client"
|
|
|
|
import { projectConfig } from "@/components/label/api/project"
|
|
import { ProjectDetail } from "@/components/label/api/project/typing"
|
|
import {
|
|
Button,
|
|
Checkbox,
|
|
Group,
|
|
NumberInput,
|
|
Paper,
|
|
SimpleGrid,
|
|
Stack,
|
|
Text,
|
|
} from "@mantine/core"
|
|
import { useForm } from "@mantine/form"
|
|
import { notifications } from "@mantine/notifications"
|
|
import { useEffect } from "react"
|
|
|
|
type GradeKey = "A" | "B" | "C"
|
|
|
|
export default function SamplingPlanContainer(props: {
|
|
projectId: number
|
|
info: ProjectDetail.DataProps | undefined
|
|
onUpdated: () => void
|
|
}) {
|
|
const { projectId, info, onUpdated } = props
|
|
|
|
const form = useForm({
|
|
initialValues: {
|
|
check_task: false,
|
|
check_frame: false,
|
|
A_task: 0,
|
|
A_frame: 0,
|
|
B_task: 0,
|
|
B_frame: 0,
|
|
C_task: 0,
|
|
C_frame: 0,
|
|
},
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (!info) return
|
|
const grade = info.user_grade ?? ({} as any)
|
|
const toPercent = (v?: number) => Number(((v ?? 0) * 100).toFixed(2))
|
|
form.setValues({
|
|
check_task: !!info.check_task,
|
|
check_frame: !!info.check_frame,
|
|
A_task: toPercent(grade.A?.task),
|
|
A_frame: toPercent(grade.A?.frame),
|
|
B_task: toPercent(grade.B?.task),
|
|
B_frame: toPercent(grade.B?.frame),
|
|
C_task: toPercent(grade.C?.task),
|
|
C_frame: toPercent(grade.C?.frame),
|
|
})
|
|
form.resetDirty()
|
|
}, [info, form])
|
|
|
|
const save = async () => {
|
|
try {
|
|
const toRatio = (v: number) => Number((v / 100).toFixed(4))
|
|
await projectConfig({
|
|
project_id: projectId,
|
|
check_task: form.values.check_task,
|
|
check_frame: form.values.check_frame,
|
|
user_grade: {
|
|
A: {
|
|
task: toRatio(form.values.A_task),
|
|
frame: toRatio(form.values.A_frame),
|
|
},
|
|
B: {
|
|
task: toRatio(form.values.B_task),
|
|
frame: toRatio(form.values.B_frame),
|
|
},
|
|
C: {
|
|
task: toRatio(form.values.C_task),
|
|
frame: toRatio(form.values.C_frame),
|
|
},
|
|
},
|
|
})
|
|
notifications.show({
|
|
color: "green",
|
|
title: "操作成功",
|
|
message: "已保存抽检配置",
|
|
})
|
|
onUpdated()
|
|
} catch (e) {
|
|
notifications.show({
|
|
color: "red",
|
|
title: "操作失败",
|
|
message: e instanceof Error ? e.message : "请求失败",
|
|
})
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Paper
|
|
withBorder
|
|
p="sm"
|
|
radius="md"
|
|
style={{ borderColor: "rgba(0,0,0,0.06)" }}>
|
|
<Stack gap="sm">
|
|
<Group justify="space-between" wrap="wrap">
|
|
<Text fw={700}>抽检方案</Text>
|
|
<Button size="xs" onClick={save}>
|
|
保存
|
|
</Button>
|
|
</Group>
|
|
|
|
<Group gap="md" wrap="wrap">
|
|
<Checkbox
|
|
label="抽检任务"
|
|
checked={form.values.check_task}
|
|
onChange={(e) =>
|
|
form.setFieldValue("check_task", e.currentTarget.checked)
|
|
}
|
|
/>
|
|
<Checkbox
|
|
label="抽检帧"
|
|
checked={form.values.check_frame}
|
|
onChange={(e) =>
|
|
form.setFieldValue("check_frame", e.currentTarget.checked)
|
|
}
|
|
/>
|
|
</Group>
|
|
|
|
<SimpleGrid cols={{ base: 1, sm: 3 }} spacing="sm">
|
|
{(["A", "B", "C"] as GradeKey[]).map((g) => (
|
|
<Paper
|
|
key={g}
|
|
withBorder
|
|
p="sm"
|
|
radius="md"
|
|
style={{ borderColor: "rgba(0,0,0,0.06)" }}>
|
|
<Stack gap="xs">
|
|
<Text fw={600}>等级 {g}</Text>
|
|
<NumberInput
|
|
label="任务抽检比例(%)"
|
|
min={0}
|
|
max={100}
|
|
decimalScale={2}
|
|
value={form.values[`${g}_task` as const]}
|
|
onChange={(v) =>
|
|
form.setFieldValue(`${g}_task` as any, Number(v ?? 0))
|
|
}
|
|
hideControls
|
|
/>
|
|
<NumberInput
|
|
label="帧抽检比例(%)"
|
|
min={0}
|
|
max={100}
|
|
decimalScale={2}
|
|
value={form.values[`${g}_frame` as const]}
|
|
onChange={(v) =>
|
|
form.setFieldValue(`${g}_frame` as any, Number(v ?? 0))
|
|
}
|
|
hideControls
|
|
/>
|
|
</Stack>
|
|
</Paper>
|
|
))}
|
|
</SimpleGrid>
|
|
</Stack>
|
|
</Paper>
|
|
)
|
|
}
|