[feat]:[FL-204][优化防雷计算任务创建表单]
1. 用弹窗代替抽屉:将 Drawer 改为 Modal 2. 调整表单布局:采用纵向排布 3. 优化字段顺序:任务名、任务类型、线路在前,依赖表单采用双列展示 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -5,8 +5,8 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Drawer,
|
||||
Form,
|
||||
Modal,
|
||||
Space,
|
||||
Typography,
|
||||
message,
|
||||
@@ -49,7 +49,7 @@ export default function AdminFlAnalysisPage() {
|
||||
const { user, initializing, fetchWithAuth, hasPermission } = useAuth();
|
||||
const queryClient = useQueryClient();
|
||||
const [selectedJobId, setSelectedJobId] = useState<string | null>(null);
|
||||
const [createDrawerOpen, setCreateDrawerOpen] = useState(false);
|
||||
const [createModalOpen, setCreateModalOpen] = useState(false);
|
||||
const [detailRow, setDetailRow] = useState<FlAnalysisTowerResultSummary | null>(null);
|
||||
const [mitigationModalOpen, setMitigationModalOpen] = useState(false);
|
||||
const [scenarioModalOpen, setScenarioModalOpen] = useState(false);
|
||||
@@ -318,7 +318,7 @@ export default function AdminFlAnalysisPage() {
|
||||
onSuccess: async (job) => {
|
||||
await invalidateFlAnalysisQueries();
|
||||
setSelectedJobId(job.id);
|
||||
setCreateDrawerOpen(false);
|
||||
setCreateModalOpen(false);
|
||||
messageApi.success(`${formatJobType(job.job_type, mitigationMode(job))}任务已创建并启动`);
|
||||
createJobForm.setFieldsValue({ job_name: "" });
|
||||
},
|
||||
@@ -570,7 +570,7 @@ export default function AdminFlAnalysisPage() {
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setCreateDrawerOpen(true);
|
||||
setCreateModalOpen(true);
|
||||
}}
|
||||
>
|
||||
新建任务
|
||||
@@ -649,17 +649,21 @@ export default function AdminFlAnalysisPage() {
|
||||
) : null}
|
||||
</Space>
|
||||
|
||||
<Drawer
|
||||
<Modal
|
||||
title="新建防雷任务"
|
||||
open={createDrawerOpen}
|
||||
width={900}
|
||||
onClose={() => {
|
||||
open={createModalOpen}
|
||||
width={800}
|
||||
onCancel={() => {
|
||||
if (createJobMutation.isPending) {
|
||||
return;
|
||||
}
|
||||
setCreateDrawerOpen(false);
|
||||
setCreateModalOpen(false);
|
||||
}}
|
||||
destroyOnHidden={false}
|
||||
onOk={() => createJobForm.submit()}
|
||||
okText="创建并启动任务"
|
||||
cancelText="取消"
|
||||
confirmLoading={createJobMutation.isPending}
|
||||
destroyOnClose={false}
|
||||
>
|
||||
<CreateJobForm
|
||||
form={createJobForm}
|
||||
@@ -675,12 +679,11 @@ export default function AdminFlAnalysisPage() {
|
||||
selectedAtpModel={selectedAtpModel}
|
||||
engineQueryData={engineQuery.data}
|
||||
workflowExecutionMessage={workflowExecutionMessage}
|
||||
submitting={createJobMutation.isPending}
|
||||
onSubmit={(values) => {
|
||||
createJobMutation.mutate(values);
|
||||
}}
|
||||
/>
|
||||
</Drawer>
|
||||
</Modal>
|
||||
|
||||
<DetailModal
|
||||
open={detailModalOpen}
|
||||
|
||||
@@ -42,7 +42,6 @@ type CreateJobFormProps = {
|
||||
selectedAtpModel: AtpModelSummary | null;
|
||||
engineQueryData: AtpEngineStatusResponse | undefined;
|
||||
workflowExecutionMessage: string;
|
||||
submitting: boolean;
|
||||
onSubmit: (values: CreateJobFormValues) => void;
|
||||
};
|
||||
|
||||
@@ -60,7 +59,6 @@ export function CreateJobForm({
|
||||
selectedAtpModel,
|
||||
engineQueryData,
|
||||
workflowExecutionMessage,
|
||||
submitting,
|
||||
onSubmit,
|
||||
}: CreateJobFormProps) {
|
||||
const selectedLinePreparation = readLinePreparation(selectedLine);
|
||||
@@ -73,60 +71,50 @@ export function CreateJobForm({
|
||||
initialValues={CREATE_JOB_DEFAULTS}
|
||||
onFinish={onSubmit}
|
||||
>
|
||||
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-5">
|
||||
<Form.Item name="job_name" label="任务名">
|
||||
<Input
|
||||
placeholder={selectedLine
|
||||
? `${selectedLine.name || selectedLine.code}-${formatJobType(selectedJobType)}`
|
||||
: `${formatJobType(selectedJobType)}任务`}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="job_type" label="任务类型" rules={[{ required: true, message: "请选择任务类型" }]}>
|
||||
<Select
|
||||
options={[
|
||||
{ value: "normal", label: "普通计算" },
|
||||
{ value: "tongtiao", label: "同跳计算" },
|
||||
{ value: "risk", label: "风险评估" },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="line_id"
|
||||
label="线路"
|
||||
rules={[{ required: true, message: "请选择线路" }]}
|
||||
>
|
||||
<Select
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
placeholder="选择线路"
|
||||
loading={linesLoading}
|
||||
options={lines.map((item) => ({
|
||||
value: item.id,
|
||||
label: `${item.name || item.code} / ${item.code}`,
|
||||
}))}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{selectedJobType === "normal" || selectedJobType === "tongtiao" ? (
|
||||
<Form.Item
|
||||
name="line_id"
|
||||
label="线路"
|
||||
rules={[{ required: true, message: "请选择线路" }]}
|
||||
name="external_adapter"
|
||||
label="执行适配器"
|
||||
rules={[{ required: true, message: "请选择执行适配器" }]}
|
||||
>
|
||||
<Select
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
placeholder="选择线路"
|
||||
loading={linesLoading}
|
||||
options={lines.map((item) => ({
|
||||
value: item.id,
|
||||
label: `${item.name || item.code} / ${item.code}`,
|
||||
}))}
|
||||
/>
|
||||
<Select options={adapterOptions.map((item) => ({ ...item }))} />
|
||||
</Form.Item>
|
||||
<Form.Item name="job_type" label="任务类型" rules={[{ required: true, message: "请选择任务类型" }]}>
|
||||
<Select
|
||||
options={[
|
||||
{ value: "normal", label: "普通计算" },
|
||||
{ value: "tongtiao", label: "同跳计算" },
|
||||
{ value: "risk", label: "风险评估" },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
{selectedJobType === "normal" || selectedJobType === "tongtiao" ? (
|
||||
<Form.Item
|
||||
name="external_adapter"
|
||||
label="执行适配器"
|
||||
rules={[{ required: true, message: "请选择执行适配器" }]}
|
||||
>
|
||||
<Select options={adapterOptions.map((item) => ({ ...item }))} />
|
||||
</Form.Item>
|
||||
) : null}
|
||||
<Form.Item name="job_name" label="任务名">
|
||||
<Input
|
||||
placeholder={selectedLine
|
||||
? `${selectedLine.name || selectedLine.code}-${formatJobType(selectedJobType)}`
|
||||
: `${formatJobType(selectedJobType)}任务`}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label=" ">
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
loading={submitting}
|
||||
disabled={!selectedLine || !selectedLinePreparation.all_ready}
|
||||
className="w-full"
|
||||
>
|
||||
创建并启动{formatJobType(selectedJobType)}任务
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{selectedLine ? (
|
||||
<Alert
|
||||
@@ -173,7 +161,7 @@ export function CreateJobForm({
|
||||
/>
|
||||
) : null}
|
||||
{externalAdapterActive ? (
|
||||
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
||||
<>
|
||||
<Form.Item
|
||||
name="atp_model_id"
|
||||
label="ATP模型"
|
||||
@@ -195,11 +183,10 @@ export function CreateJobForm({
|
||||
showIcon
|
||||
message={`执行模式:${engineQueryData ? formatExternalAdapter(engineQueryData.mode === "wine" ? "wine" : "atp") : "-"}`}
|
||||
description={selectedAtpModel ? `当前模型:${selectedAtpModel.name} / ${selectedAtpModel.code}。执行时默认使用该模型的当前模板。` : "从 ATP 模型管理中选择可用模板。"}
|
||||
className="md:col-span-1 xl:col-span-2"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
<div className="grid gap-3 md:grid-cols-4">
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
<Form.Item name="current_waveform" label="雷电流波形">
|
||||
<Select
|
||||
options={[
|
||||
|
||||
Reference in New Issue
Block a user