|
|
@@ -307,6 +307,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
const [workJobBasicForm] = Form.useForm(); // 基本信息表单
|
|
|
const [workJobPublishForm] = Form.useForm(); // 发布作业表单
|
|
|
const [workflowJson, setWorkflowJson] = useState<any>(null); // 流程设计JSON
|
|
|
+ const [workflowWorkId, setWorkflowWorkId] = useState<number | null>(null); // 作业票ID(新增后返回)
|
|
|
|
|
|
// ReactFlow相关状态(用于流程管理tab)
|
|
|
const [workflowNodes, setWorkflowNodes, onWorkflowNodesChange] = useNodesState([]);
|
|
|
@@ -592,7 +593,6 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
// 流程设计搜索参数
|
|
|
const [processDesignQuery, setProcessDesignQuery] = useState({
|
|
|
name: '',
|
|
|
- status: undefined as string | undefined,
|
|
|
});
|
|
|
const [processDesignPagination, setProcessDesignPagination] = useState({
|
|
|
pageNo: 1,
|
|
|
@@ -609,70 +609,6 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
pageSize: 10,
|
|
|
});
|
|
|
|
|
|
- // 作业管理模拟数据
|
|
|
- const workJobMockData: WorkJobVO[] = [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- code: 'WORK-2024-001',
|
|
|
- name: '2024年1月设备检修作业',
|
|
|
- initiator: '张三',
|
|
|
- initiateTime: new Date('2024-01-15 10:30:00').getTime(),
|
|
|
- content: '对1号生产线进行定期检修,包括设备清洁、润滑、检查等',
|
|
|
- currentNode: '审核/确认',
|
|
|
- status: '进行中',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- code: 'WORK-2024-002',
|
|
|
- name: '安全隔离作业',
|
|
|
- initiator: '李四',
|
|
|
- initiateTime: new Date('2024-01-14 14:20:00').getTime(),
|
|
|
- content: '对2号设备进行安全隔离,执行上锁挂牌操作',
|
|
|
- currentNode: '隔离/方案',
|
|
|
- status: '进行中',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- code: 'WORK-2024-003',
|
|
|
- name: '设备维护作业',
|
|
|
- initiator: '王五',
|
|
|
- initiateTime: new Date('2024-01-13 09:15:00').getTime(),
|
|
|
- content: '对3号设备进行日常维护保养',
|
|
|
- currentNode: '完成/结束',
|
|
|
- status: '已完成',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 4,
|
|
|
- code: 'WORK-2024-004',
|
|
|
- name: '紧急维修作业',
|
|
|
- initiator: '赵六',
|
|
|
- initiateTime: new Date('2024-01-12 16:45:00').getTime(),
|
|
|
- content: '对故障设备进行紧急维修',
|
|
|
- currentNode: '提交/开始',
|
|
|
- status: '待开始',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 5,
|
|
|
- code: 'WORK-2024-005',
|
|
|
- name: '年度大修作业',
|
|
|
- initiator: '钱七',
|
|
|
- initiateTime: new Date('2024-01-11 11:20:00').getTime(),
|
|
|
- content: '对主要生产设备进行年度大修,包括全面检查、更换易损件等',
|
|
|
- currentNode: '-',
|
|
|
- status: '已完成',
|
|
|
- },
|
|
|
- {
|
|
|
- id: 6,
|
|
|
- code: 'WORK-2024-006',
|
|
|
- name: '设备调试作业',
|
|
|
- initiator: '孙八',
|
|
|
- initiateTime: new Date('2024-01-10 08:30:00').getTime(),
|
|
|
- content: '对新安装设备进行调试和测试',
|
|
|
- currentNode: '-',
|
|
|
- status: '已取消',
|
|
|
- },
|
|
|
- ];
|
|
|
-
|
|
|
// 作业管理数据(旧数据,保留用于兼容)
|
|
|
const workData: TableRow[] = [
|
|
|
{
|
|
|
@@ -863,7 +799,6 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
const resetProcessDesignQuery = () => {
|
|
|
setProcessDesignQuery({
|
|
|
name: '',
|
|
|
- status: undefined,
|
|
|
});
|
|
|
setProcessDesignPagination({ pageNo: 1, pageSize: 10 });
|
|
|
// 立即调用接口刷新数据
|
|
|
@@ -877,7 +812,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
// 重置分页到第一页
|
|
|
setProcessDesignPagination({ pageNo: 1, pageSize: 10 });
|
|
|
// 重置查询条件
|
|
|
- setProcessDesignQuery({ name: '', status: undefined });
|
|
|
+ setProcessDesignQuery({ name: '' });
|
|
|
// 加载数据
|
|
|
getProcessDesignList();
|
|
|
} else if (subMenu === '作业管理') {
|
|
|
@@ -909,7 +844,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
const getWorkJobList = async () => {
|
|
|
setWorkJobLoading(true);
|
|
|
try {
|
|
|
- const response = await workJobApi.getWorkJobPage({
|
|
|
+ const response = await workJobApi.getWorkflowWorkPage({
|
|
|
pageNo: workJobPagination.pageNo,
|
|
|
pageSize: workJobPagination.pageSize,
|
|
|
name: workJobQuery.name || undefined,
|
|
|
@@ -918,28 +853,10 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
setWorkJobList(response.list || []);
|
|
|
setWorkJobTotal(response.total || 0);
|
|
|
} catch (error: any) {
|
|
|
- console.error('获取作业列表失败,使用模拟数据:', error);
|
|
|
- // API 调用失败时使用模拟数据
|
|
|
- let filteredData = workJobMockData;
|
|
|
-
|
|
|
- // 如果有搜索条件,进行过滤
|
|
|
- if (workJobQuery.name) {
|
|
|
- filteredData = filteredData.filter(item =>
|
|
|
- item.name?.toLowerCase().includes(workJobQuery.name.toLowerCase())
|
|
|
- );
|
|
|
- }
|
|
|
- if (workJobQuery.status) {
|
|
|
- filteredData = filteredData.filter(item => item.status === workJobQuery.status);
|
|
|
- }
|
|
|
-
|
|
|
- // 分页处理
|
|
|
- const startIndex = (workJobPagination.pageNo - 1) * workJobPagination.pageSize;
|
|
|
- const endIndex = startIndex + workJobPagination.pageSize;
|
|
|
- const pageData = filteredData.slice(startIndex, endIndex);
|
|
|
-
|
|
|
- setWorkJobList(pageData);
|
|
|
- setWorkJobTotal(filteredData.length);
|
|
|
- // 不显示错误提示,静默使用模拟数据
|
|
|
+ console.error('获取作业列表失败:', error);
|
|
|
+ message.error(error?.message || '获取作业列表失败');
|
|
|
+ setWorkJobList([]);
|
|
|
+ setWorkJobTotal(0);
|
|
|
} finally {
|
|
|
setWorkJobLoading(false);
|
|
|
}
|
|
|
@@ -1359,7 +1276,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
cancelText: '取消',
|
|
|
onOk: async () => {
|
|
|
try {
|
|
|
- await workJobApi.deleteWorkJobList([id]);
|
|
|
+ await workJobApi.deleteWorkflowWorkList([id]);
|
|
|
message.success('删除成功');
|
|
|
// 删除成功后刷新列表
|
|
|
if (workJobList.length === 1 && workJobPagination.pageNo > 1) {
|
|
|
@@ -1376,19 +1293,238 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
};
|
|
|
|
|
|
// 作业管理编辑处理
|
|
|
- const handleWorkJobEdit = (item: WorkJobVO) => {
|
|
|
- setEditingItem(item as TableRow);
|
|
|
- form.setFieldsValue({
|
|
|
- name: item.name || '',
|
|
|
- content: item.content || '',
|
|
|
- });
|
|
|
- setShowAddModal(true);
|
|
|
+ const handleWorkJobEdit = async (item: WorkJobVO) => {
|
|
|
+ try {
|
|
|
+ // 调用详情接口获取完整数据
|
|
|
+ const response = await workJobApi.selectWorkflowWorkById(item.id!);
|
|
|
+ // axios拦截器可能已经处理了数据格式,直接使用response
|
|
|
+ const detail = response as any;
|
|
|
+
|
|
|
+ // 设置作业ID,这样点击"下一步"时会调用更新接口
|
|
|
+ setWorkflowWorkId(detail.id);
|
|
|
+
|
|
|
+ // 重置表单和步骤
|
|
|
+ setWorkJobStep(0);
|
|
|
+ workJobBasicForm.resetFields();
|
|
|
+ workJobPublishForm.resetFields();
|
|
|
+
|
|
|
+ // 加载字典数据和流程模板列表
|
|
|
+ await Promise.all([
|
|
|
+ getWorkTypeDictList(),
|
|
|
+ getUrgencyLevelDictList(),
|
|
|
+ getWorkflowTemplateList(),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 回显基本信息表单数据
|
|
|
+ workJobBasicForm.setFieldsValue({
|
|
|
+ workflowTemplate: detail.designId || undefined,
|
|
|
+ jobCategory: detail.type || undefined,
|
|
|
+ jobName: detail.name || '',
|
|
|
+ jobContent: detail.description || '',
|
|
|
+ urgency: detail.urgencyLevel || undefined,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果有流程设计内容,加载流程设计JSON
|
|
|
+ // 优先使用 designContent(如果存在),否则使用 designId 调用接口
|
|
|
+ if (detail.designContent) {
|
|
|
+ try {
|
|
|
+ // 如果详情中直接包含流程设计内容,直接解析并设置
|
|
|
+ const jsonData = typeof detail.designContent === 'string'
|
|
|
+ ? JSON.parse(detail.designContent)
|
|
|
+ : detail.designContent;
|
|
|
+ setWorkflowJson(jsonData);
|
|
|
+
|
|
|
+ // 调用 loadWorkflowJson 的逻辑来渲染节点和连线
|
|
|
+ // 这里直接使用已有的 loadWorkflowJson 函数,但需要先设置 workflowJson
|
|
|
+ // 然后手动触发渲染逻辑
|
|
|
+ if (jsonData && jsonData.nodes && Array.isArray(jsonData.nodes) && jsonData.edges && Array.isArray(jsonData.edges)) {
|
|
|
+ // 使用 loadWorkflowJson 中的渲染逻辑
|
|
|
+ const importedNodes: Node[] = jsonData.nodes.map((node: any) => {
|
|
|
+ const nodeData = node.data || {};
|
|
|
+ const nodeId = node.id || node.uuid;
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: nodeId,
|
|
|
+ type: node.type || 'createJob',
|
|
|
+ position: node.position || { x: 0, y: 0 },
|
|
|
+ data: {
|
|
|
+ ...nodeData,
|
|
|
+ label: nodeData.label || node.label || nodeConfigs.find(c => c.type === (node.type || nodeData.type))?.label || '节点',
|
|
|
+ type: node.type || nodeData.type || 'createJob',
|
|
|
+ },
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ const importedEdges: Edge[] = jsonData.edges.map((edge: any) => {
|
|
|
+ let sourceHandle = edge.sourceHandle;
|
|
|
+ let targetHandle = edge.targetHandle;
|
|
|
+
|
|
|
+ if (!sourceHandle && edge.id) {
|
|
|
+ const sourceMatch = edge.id.match(/right-source|left-source|top-source|bottom-source/);
|
|
|
+ if (sourceMatch) {
|
|
|
+ sourceHandle = sourceMatch[0].replace('-source', '');
|
|
|
+ } else {
|
|
|
+ sourceHandle = 'right-source';
|
|
|
+ }
|
|
|
+ } else if (!sourceHandle) {
|
|
|
+ sourceHandle = 'right-source';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!targetHandle && edge.id) {
|
|
|
+ const targetMatch = edge.id.match(/right-target|left-target|top-target|bottom-target/);
|
|
|
+ if (targetMatch) {
|
|
|
+ targetHandle = targetMatch[0].replace('-target', '');
|
|
|
+ } else {
|
|
|
+ targetHandle = 'left-target';
|
|
|
+ }
|
|
|
+ } else if (!targetHandle) {
|
|
|
+ targetHandle = 'left-target';
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: edge.id || `${edge.source}-${edge.target}`,
|
|
|
+ source: edge.source,
|
|
|
+ target: edge.target,
|
|
|
+ sourceHandle: sourceHandle,
|
|
|
+ targetHandle: targetHandle,
|
|
|
+ type: 'straight',
|
|
|
+ style: { strokeWidth: 2, stroke: '#94a3b8' },
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ setWorkflowNodes(importedNodes);
|
|
|
+ setWorkflowEdges(importedEdges);
|
|
|
+
|
|
|
+ // 清空之前的缓存和完成状态
|
|
|
+ setWorkflowNodeConfigCache(new Map());
|
|
|
+ setCompletedNodeIds(new Set());
|
|
|
+
|
|
|
+ // 自动选中第一个节点
|
|
|
+ if (importedNodes.length > 0) {
|
|
|
+ setTimeout(() => {
|
|
|
+ const firstNode = importedNodes[0];
|
|
|
+ setSelectedWorkflowNode(firstNode);
|
|
|
+ const source = firstNode.data || {};
|
|
|
+ const config = nodeConfigs.find(c => c.type === source.type);
|
|
|
+ setWorkflowNodeConfig({
|
|
|
+ nodeName: source.label || config?.label || '',
|
|
|
+ nodeIcon: source.icon || '',
|
|
|
+ responsible: source.responsible || '',
|
|
|
+ remark: source.remark || '',
|
|
|
+ submitForm: source.submitForm || '',
|
|
|
+ isolationMethod: source.isolationMethod || '',
|
|
|
+ isolationPoints: source.isolationPoints || [],
|
|
|
+ isolationNode: source.isolationNode || [],
|
|
|
+ selectedIsolationNodeId: source.selectedIsolationNodeId || '',
|
|
|
+ lockPerson: source.lockPerson || '',
|
|
|
+ coLockPersons: source.coLockPersons || [],
|
|
|
+ notificationMethods: source.notificationMethods || {
|
|
|
+ sms: false,
|
|
|
+ message: false,
|
|
|
+ email: false,
|
|
|
+ app: false,
|
|
|
+ },
|
|
|
+ notificationContent: source.notificationContent || '',
|
|
|
+ });
|
|
|
+ setWorkflowNodes(prev => prev.map(n => ({
|
|
|
+ ...n,
|
|
|
+ selected: n.id === firstNode.id,
|
|
|
+ })));
|
|
|
+ }, 100);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('解析流程设计内容失败:', error);
|
|
|
+ // 如果解析失败,尝试使用 designId 调用接口
|
|
|
+ if (detail.designId) {
|
|
|
+ try {
|
|
|
+ await loadWorkflowJson(detail.designId);
|
|
|
+ } catch (loadError: any) {
|
|
|
+ console.error('加载流程设计失败:', loadError);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (detail.designId) {
|
|
|
+ try {
|
|
|
+ await loadWorkflowJson(detail.designId);
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('加载流程设计失败:', error);
|
|
|
+ // 不阻止弹框打开,只是不加载流程设计
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打开多步骤弹框
|
|
|
+ setShowAddModal(true);
|
|
|
+ setEditingItem(null); // 确保不是编辑模式(使用新增的多步骤弹框)
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('获取作业详情失败:', error);
|
|
|
+ message.error(error?.message || '获取作业详情失败');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
// 作业管理查看处理
|
|
|
- const handleWorkJobView = (item: WorkJobVO) => {
|
|
|
- // TODO: 实现查看详情功能
|
|
|
- message.info('查看功能待实现');
|
|
|
+ const handleWorkJobView = async (item: WorkJobVO) => {
|
|
|
+ try {
|
|
|
+ // 调用详情接口获取完整数据
|
|
|
+ const response = await workJobApi.selectWorkflowWorkById(item.id!);
|
|
|
+ // axios拦截器可能已经处理了数据格式,直接使用response
|
|
|
+ const detail = response as any;
|
|
|
+ Modal.info({
|
|
|
+ title: '作业详情',
|
|
|
+ width: 600,
|
|
|
+ content: (
|
|
|
+ <div className="space-y-3 mt-4">
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">作业名称:</span>
|
|
|
+ <span className="font-medium">{detail.name || '-'}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">作业编号:</span>
|
|
|
+ <span className="font-medium">{detail.orderNo || detail.code || '-'}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">发起人:</span>
|
|
|
+ <span className="font-medium">{detail.initiatorName || detail.initiator || '-'}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">发起时间:</span>
|
|
|
+ <span className="font-medium">
|
|
|
+ {(detail.initiationTime || detail.initiateTime)
|
|
|
+ ? new Date(detail.initiationTime || detail.initiateTime).toLocaleString('zh-CN')
|
|
|
+ : '-'}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">作业内容:</span>
|
|
|
+ <div className="mt-1">{detail.description || detail.content || '-'}</div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">当前节点:</span>
|
|
|
+ <span className="font-medium">{detail.currentNodeId || detail.currentNode || '-'}</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span className="text-gray-600">作业状态:</span>
|
|
|
+ <span className="font-medium">
|
|
|
+ {(() => {
|
|
|
+ const statusMap: Record<string, string> = {
|
|
|
+ 'pending': '待执行',
|
|
|
+ 'running': '执行中',
|
|
|
+ 'completed': '执行完成',
|
|
|
+ 'rejected': '已退回',
|
|
|
+ 'skipped': '已跳过',
|
|
|
+ };
|
|
|
+ const statusStr = String(detail.status || '').toLowerCase();
|
|
|
+ return statusMap[statusStr] || detail.status || '-';
|
|
|
+ })()}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ });
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('获取作业详情失败:', error);
|
|
|
+ message.error(error?.message || '获取作业详情失败');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
// 根据当前子菜单获取数据和列配置
|
|
|
@@ -1424,9 +1560,6 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
item.name.toLowerCase().includes(processDesignQuery.name.toLowerCase())
|
|
|
);
|
|
|
}
|
|
|
- if (processDesignQuery.status) {
|
|
|
- filtered = filtered.filter(item => item.status === processDesignQuery.status);
|
|
|
- }
|
|
|
return {
|
|
|
data: filtered,
|
|
|
columns: [
|
|
|
@@ -2012,6 +2145,12 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
|
|
|
// 作业管理表格列配置
|
|
|
const workJobColumns: ColumnsType<WorkJobVO> = [
|
|
|
+ {
|
|
|
+ title: '作业编号',
|
|
|
+ dataIndex: 'orderNo',
|
|
|
+ width: '12%',
|
|
|
+ render: (orderNo: string, record: WorkJobVO) => orderNo || record.code || '-',
|
|
|
+ },
|
|
|
{
|
|
|
title: '作业名称',
|
|
|
dataIndex: 'name',
|
|
|
@@ -2019,22 +2158,24 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
},
|
|
|
{
|
|
|
title: '发起人',
|
|
|
- dataIndex: 'initiator',
|
|
|
+ dataIndex: 'initiatorName',
|
|
|
width: '10%',
|
|
|
+ render: (initiatorName: string, record: WorkJobVO) => initiatorName || record.initiator || '-',
|
|
|
},
|
|
|
{
|
|
|
title: '发起时间',
|
|
|
- dataIndex: 'initiateTime',
|
|
|
+ dataIndex: 'initiationTime',
|
|
|
width: '16%',
|
|
|
- render: (time: string | Date | number) => {
|
|
|
- if (!time) return '-';
|
|
|
+ render: (time: string | Date | number, record: WorkJobVO) => {
|
|
|
+ const actualTime = time || record.initiateTime;
|
|
|
+ if (!actualTime) return '-';
|
|
|
let date: Date;
|
|
|
- if (typeof time === 'number') {
|
|
|
- date = new Date(time);
|
|
|
- } else if (typeof time === 'string') {
|
|
|
- date = new Date(time);
|
|
|
+ if (typeof actualTime === 'number') {
|
|
|
+ date = new Date(actualTime);
|
|
|
+ } else if (typeof actualTime === 'string') {
|
|
|
+ date = new Date(actualTime);
|
|
|
} else {
|
|
|
- date = time;
|
|
|
+ date = actualTime;
|
|
|
}
|
|
|
return date.toLocaleString('zh-CN', {
|
|
|
year: 'numeric',
|
|
|
@@ -2048,33 +2189,37 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
},
|
|
|
{
|
|
|
title: '作业内容',
|
|
|
- dataIndex: 'content',
|
|
|
+ dataIndex: 'description',
|
|
|
width: '26%',
|
|
|
ellipsis: true,
|
|
|
- render: (content: string) => content || '-',
|
|
|
+ render: (description: string, record: WorkJobVO) => description || record.content || '-',
|
|
|
},
|
|
|
{
|
|
|
title: '当前节点',
|
|
|
- dataIndex: 'currentNode',
|
|
|
+ dataIndex: 'currentNodeId',
|
|
|
width: '12%',
|
|
|
- render: (node: string) => node || '-',
|
|
|
+ render: (currentNodeId: string, record: WorkJobVO) => currentNodeId || record.currentNode || '-',
|
|
|
},
|
|
|
{
|
|
|
title: '作业状态',
|
|
|
dataIndex: 'status',
|
|
|
width: '10%',
|
|
|
render: (status: string | number) => {
|
|
|
- const statusMap: Record<string | number, { text: string; className: string }> = {
|
|
|
+ // 状态转义映射
|
|
|
+ const statusMap: Record<string, { text: string; className: string }> = {
|
|
|
+ 'pending': { text: '待执行', className: 'bg-orange-100 text-orange-700' },
|
|
|
+ 'running': { text: '执行中', className: 'bg-blue-100 text-blue-700' },
|
|
|
+ 'completed': { text: '执行完成', className: 'bg-green-100 text-green-700' },
|
|
|
+ 'rejected': { text: '已退回', className: 'bg-red-100 text-red-700' },
|
|
|
+ 'skipped': { text: '已跳过', className: 'bg-gray-100 text-gray-700' },
|
|
|
+ // 兼容旧的状态值
|
|
|
'进行中': { text: '进行中', className: 'bg-blue-100 text-blue-700' },
|
|
|
'已完成': { text: '已完成', className: 'bg-green-100 text-green-700' },
|
|
|
'待开始': { text: '待开始', className: 'bg-orange-100 text-orange-700' },
|
|
|
'已取消': { text: '已取消', className: 'bg-gray-100 text-gray-700' },
|
|
|
- 1: { text: '进行中', className: 'bg-blue-100 text-blue-700' },
|
|
|
- 2: { text: '已完成', className: 'bg-green-100 text-green-700' },
|
|
|
- 3: { text: '待开始', className: 'bg-orange-100 text-orange-700' },
|
|
|
- 4: { text: '已取消', className: 'bg-gray-100 text-gray-700' },
|
|
|
};
|
|
|
- const statusInfo = statusMap[status] || { text: String(status), className: 'bg-gray-100 text-gray-700' };
|
|
|
+ const statusStr = String(status).toLowerCase();
|
|
|
+ const statusInfo = statusMap[statusStr] || { text: String(status), className: 'bg-gray-100 text-gray-700' };
|
|
|
return (
|
|
|
<span className={`inline-flex px-3 py-1 rounded-lg text-xs ${statusInfo.className}`}>
|
|
|
{statusInfo.text}
|
|
|
@@ -2355,17 +2500,6 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
/>
|
|
|
</div>
|
|
|
<div className="flex items-center gap-2 lg:gap-3 flex-shrink-0">
|
|
|
- <label className="text-sm font-medium text-gray-700 whitespace-nowrap">状态:</label>
|
|
|
- <Select
|
|
|
- value={processDesignQuery.status}
|
|
|
- onChange={(value) => setProcessDesignQuery({ ...processDesignQuery, status: value })}
|
|
|
- placeholder="请选择状态"
|
|
|
- className="min-w-[150px] max-w-[200px]"
|
|
|
- allowClear
|
|
|
- >
|
|
|
- <Select.Option value="启用">启用</Select.Option>
|
|
|
- <Select.Option value="停用">停用</Select.Option>
|
|
|
- </Select>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
@@ -2621,7 +2755,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
<div className="flex flex-wrap items-center justify-between gap-3 lg:gap-4">
|
|
|
<div className="flex flex-wrap items-center gap-3 lg:gap-4">
|
|
|
<div className="flex items-center gap-2">
|
|
|
- <label className="text-sm font-medium text-gray-700 whitespace-nowrap">搜索作业名称:</label>
|
|
|
+ <label className="text-sm font-medium text-gray-700 whitespace-nowrap">作业名称:</label>
|
|
|
<Input
|
|
|
value={workJobQuery.name}
|
|
|
onChange={(e) => setWorkJobQuery({ ...workJobQuery, name: e.target.value })}
|
|
|
@@ -2631,20 +2765,23 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
className="min-w-[200px] max-w-[300px]"
|
|
|
/>
|
|
|
</div>
|
|
|
- <Select
|
|
|
- value={workJobQuery.status ?? ''}
|
|
|
- onChange={(value) => setWorkJobQuery({ ...workJobQuery, status: value || undefined })}
|
|
|
- placeholder="全部状态"
|
|
|
- allowClear
|
|
|
- className="w-32"
|
|
|
- options={[
|
|
|
- { label: '全部状态', value: '' },
|
|
|
- { label: '进行中', value: '进行中' },
|
|
|
- { label: '已完成', value: '已完成' },
|
|
|
- { label: '待开始', value: '待开始' },
|
|
|
- { label: '已取消', value: '已取消' },
|
|
|
- ]}
|
|
|
- />
|
|
|
+ <div className="flex items-center gap-2">
|
|
|
+ <label className="text-sm font-medium text-gray-700 whitespace-nowrap">作业状态:</label>
|
|
|
+ <Select
|
|
|
+ value={workJobQuery.status ?? ''}
|
|
|
+ onChange={(value) => setWorkJobQuery({ ...workJobQuery, status: value || undefined })}
|
|
|
+ placeholder="请选择作业状态"
|
|
|
+ allowClear
|
|
|
+ className="w-32"
|
|
|
+ options={[
|
|
|
+ { label: '待执行', value: 'pending' },
|
|
|
+ { label: '执行中', value: 'running' },
|
|
|
+ { label: '执行完成', value: 'completed' },
|
|
|
+ { label: '已退回', value: 'rejected' },
|
|
|
+ { label: '已跳过', value: 'skipped' },
|
|
|
+ ]}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<Space>
|
|
|
<Button
|
|
|
@@ -2722,7 +2859,7 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
</div>
|
|
|
)}
|
|
|
|
|
|
- {/* 发起作业多步骤弹窗 */}
|
|
|
+ {/* 发起作业多步骤弹窗(新增和编辑共用) */}
|
|
|
{subMenu === '作业管理' && showAddModal && !editingItem ? (
|
|
|
<Modal
|
|
|
title={null}
|
|
|
@@ -2733,6 +2870,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
workJobBasicForm.resetFields();
|
|
|
workJobPublishForm.resetFields();
|
|
|
setWorkflowJson(null);
|
|
|
+ setWorkflowWorkId(null); // 清空作业ID
|
|
|
+ // 清空流程管理相关状态
|
|
|
+ setWorkflowNodes([]);
|
|
|
+ setWorkflowEdges([]);
|
|
|
+ setSelectedWorkflowNode(null);
|
|
|
+ setWorkflowNodeConfigCache(new Map());
|
|
|
+ setCompletedNodeIds(new Set());
|
|
|
}}
|
|
|
footer={null}
|
|
|
width={1400}
|
|
|
@@ -3445,6 +3589,15 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
setShowAddModal(false);
|
|
|
setWorkJobStep(0);
|
|
|
workJobBasicForm.resetFields();
|
|
|
+ workJobPublishForm.resetFields();
|
|
|
+ setWorkflowJson(null);
|
|
|
+ setWorkflowWorkId(null); // 清空作业ID
|
|
|
+ // 清空流程管理相关状态
|
|
|
+ setWorkflowNodes([]);
|
|
|
+ setWorkflowEdges([]);
|
|
|
+ setSelectedWorkflowNode(null);
|
|
|
+ setWorkflowNodeConfigCache(new Map());
|
|
|
+ setCompletedNodeIds(new Set());
|
|
|
}}>
|
|
|
取消
|
|
|
</Button>
|
|
|
@@ -3455,17 +3608,43 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
// 验证必填项
|
|
|
const values = await workJobBasicForm.validateFields();
|
|
|
|
|
|
- // 调用接口创建流程作业
|
|
|
- await workJobApi.insertWorkflowWork({
|
|
|
- name: values.jobName, // 作业名称
|
|
|
- type: values.jobCategory, // 作业分类
|
|
|
- designId: values.workflowTemplate, // 流程设计ID
|
|
|
- description: values.jobContent, // 作业内容
|
|
|
- urgencyLevel: values.urgency, // 紧急程度
|
|
|
- });
|
|
|
+ // 判断是新增还是更新
|
|
|
+ if (workflowWorkId) {
|
|
|
+ // 已有ID,调用更新接口
|
|
|
+ await workJobApi.updateWorkflowWork({
|
|
|
+ id: workflowWorkId, // 作业票ID
|
|
|
+ name: values.jobName, // 作业名称
|
|
|
+ type: values.jobCategory, // 作业分类
|
|
|
+ designId: values.workflowTemplate, // 流程设计ID
|
|
|
+ description: values.jobContent, // 作业内容
|
|
|
+ urgencyLevel: values.urgency, // 紧急程度
|
|
|
+ });
|
|
|
+ message.success('基本信息更新成功');
|
|
|
+ } else {
|
|
|
+ // 没有ID,调用新增接口
|
|
|
+ const response = await workJobApi.insertWorkflowWork({
|
|
|
+ name: values.jobName, // 作业名称
|
|
|
+ type: values.jobCategory, // 作业分类
|
|
|
+ designId: values.workflowTemplate, // 流程设计ID
|
|
|
+ description: values.jobContent, // 作业内容
|
|
|
+ urgencyLevel: values.urgency, // 紧急程度
|
|
|
+ });
|
|
|
+
|
|
|
+ // 保存返回的作业ID
|
|
|
+ // 响应格式: { code: 0, data: 13, msg: "" }
|
|
|
+ // axios拦截器可能已经处理了数据格式,直接使用response
|
|
|
+ const responseData = response as any;
|
|
|
+ // 尝试多种方式获取ID
|
|
|
+ const workId = responseData?.data || responseData?.id || (typeof responseData === 'number' ? responseData : null);
|
|
|
+ if (workId) {
|
|
|
+ setWorkflowWorkId(Number(workId));
|
|
|
+ console.log('保存作业ID:', workId);
|
|
|
+ }
|
|
|
+
|
|
|
+ message.success('基本信息保存成功');
|
|
|
+ }
|
|
|
|
|
|
// 成功后进入下一步
|
|
|
- message.success('基本信息保存成功');
|
|
|
setWorkJobStep(1);
|
|
|
} catch (error: any) {
|
|
|
if (error.errorFields) {
|
|
|
@@ -3629,6 +3808,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
workJobBasicForm.resetFields();
|
|
|
workJobPublishForm.resetFields();
|
|
|
setWorkflowJson(null);
|
|
|
+ setWorkflowWorkId(null); // 清空作业ID
|
|
|
+ // 清空流程管理相关状态
|
|
|
+ setWorkflowNodes([]);
|
|
|
+ setWorkflowEdges([]);
|
|
|
+ setSelectedWorkflowNode(null);
|
|
|
+ setWorkflowNodeConfigCache(new Map());
|
|
|
+ setCompletedNodeIds(new Set());
|
|
|
getWorkJobList();
|
|
|
} catch (error: any) {
|
|
|
if (error.errorFields) {
|
|
|
@@ -3661,10 +3847,13 @@ export default function IsolationWork({ subMenu }: IsolationWorkProps) {
|
|
|
onOk={async () => {
|
|
|
try {
|
|
|
const values = await form.validateFields();
|
|
|
- await workJobApi.updateWorkJob({
|
|
|
+ await workJobApi.updateWorkflowWork({
|
|
|
id: editingItem.id!,
|
|
|
name: values.name,
|
|
|
- content: values.content || '',
|
|
|
+ type: values.type || editingItem.type || '',
|
|
|
+ designId: values.designId || editingItem.designId || editingItem.workflowDesignId || 0,
|
|
|
+ description: values.content || '',
|
|
|
+ urgencyLevel: values.urgencyLevel || editingItem.urgencyLevel || '',
|
|
|
});
|
|
|
message.success('更新作业成功');
|
|
|
setShowAddModal(false);
|