openxiangda 2.63.1 → 2.65.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/browser/components/workflow/WorkflowBusinessStepEditor.d.ts +11 -0
  2. package/dist/browser/components/workflow/WorkflowBusinessStepEditor.d.ts.map +1 -0
  3. package/dist/browser/components/workflow/WorkflowBusinessStepEditor.js +55 -0
  4. package/dist/browser/components/workflow/WorkflowBusinessStepEditor.js.map +1 -0
  5. package/dist/browser/components/workflow/WorkflowConditionConfigurationEditor.d.ts.map +1 -1
  6. package/dist/browser/components/workflow/WorkflowConditionConfigurationEditor.js +2 -1
  7. package/dist/browser/components/workflow/WorkflowConditionConfigurationEditor.js.map +1 -1
  8. package/dist/browser/components/workflow/WorkflowConditionExamples.d.ts +11 -0
  9. package/dist/browser/components/workflow/WorkflowConditionExamples.d.ts.map +1 -0
  10. package/dist/browser/components/workflow/WorkflowConditionExamples.js +52 -0
  11. package/dist/browser/components/workflow/WorkflowConditionExamples.js.map +1 -0
  12. package/dist/browser/components/workflow/WorkflowDesigner.d.ts.map +1 -1
  13. package/dist/browser/components/workflow/WorkflowDesigner.js +122 -46
  14. package/dist/browser/components/workflow/WorkflowDesigner.js.map +1 -1
  15. package/dist/browser/components/workflow/WorkflowDesignerAssistant.d.ts +2 -1
  16. package/dist/browser/components/workflow/WorkflowDesignerAssistant.d.ts.map +1 -1
  17. package/dist/browser/components/workflow/WorkflowDesignerAssistant.js +3 -3
  18. package/dist/browser/components/workflow/WorkflowDesignerAssistant.js.map +1 -1
  19. package/dist/browser/components/workflow/WorkflowDraftHandlingEditor.d.ts +9 -3
  20. package/dist/browser/components/workflow/WorkflowDraftHandlingEditor.d.ts.map +1 -1
  21. package/dist/browser/components/workflow/WorkflowDraftHandlingEditor.js +7 -5
  22. package/dist/browser/components/workflow/WorkflowDraftHandlingEditor.js.map +1 -1
  23. package/dist/browser/components/workflow/WorkflowPeopleSourceEditor.d.ts +9 -0
  24. package/dist/browser/components/workflow/WorkflowPeopleSourceEditor.d.ts.map +1 -0
  25. package/dist/browser/components/workflow/WorkflowPeopleSourceEditor.js +13 -0
  26. package/dist/browser/components/workflow/WorkflowPeopleSourceEditor.js.map +1 -0
  27. package/dist/browser/components/workflow/WorkflowReminderEditor.d.ts +3 -1
  28. package/dist/browser/components/workflow/WorkflowReminderEditor.d.ts.map +1 -1
  29. package/dist/browser/components/workflow/WorkflowReminderEditor.js +21 -5
  30. package/dist/browser/components/workflow/WorkflowReminderEditor.js.map +1 -1
  31. package/dist/browser/components/workflow/WorkflowReturnPolicyEditor.d.ts.map +1 -1
  32. package/dist/browser/components/workflow/WorkflowReturnPolicyEditor.js +3 -2
  33. package/dist/browser/components/workflow/WorkflowReturnPolicyEditor.js.map +1 -1
  34. package/dist/browser/components/workflow/workflow-flow-layout.d.ts +10 -9
  35. package/dist/browser/components/workflow/workflow-flow-layout.d.ts.map +1 -1
  36. package/dist/browser/components/workflow/workflow-flow-layout.js +13 -38
  37. package/dist/browser/components/workflow/workflow-flow-layout.js.map +1 -1
  38. package/dist/browser/components/workflow/workflow-parallel-layout.d.ts +37 -0
  39. package/dist/browser/components/workflow/workflow-parallel-layout.d.ts.map +1 -0
  40. package/dist/browser/components/workflow/workflow-parallel-layout.js +176 -0
  41. package/dist/browser/components/workflow/workflow-parallel-layout.js.map +1 -0
  42. package/dist/browser/styles.css +32 -1
  43. package/dist/config.d.ts +1 -0
  44. package/dist/config.d.ts.map +1 -1
  45. package/documentation/getting-started.md +7 -7
  46. package/documentation/manifest.json +2 -2
  47. package/package.json +18 -37
  48. package/releases/2.64.0.json +30 -0
  49. package/releases/2.65.0.json +30 -0
  50. package/releases/2.65.1.json +27 -0
  51. package/skills/manifest.json +1 -1
  52. package/skills/openxiangda-v2/SKILL.md +4 -4
  53. package/skills/openxiangda-v2/references/getting-started.md +7 -7
  54. package/releases/2.63.0.json +0 -45
  55. package/releases/2.63.1.json +0 -46
@@ -1,4 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { workflowAuthoringCatalog, workflowCanvasBindingKey, createWorkflowHumanNode, pruneWorkflowCanvasBindings, validateWorkflowBusinessSteps } from 'openxiangda-contracts/browser';
3
+ import { WorkflowBusinessStepEditor } from './WorkflowBusinessStepEditor';
2
4
  import { WorkflowParallelConfigurationEditor } from './WorkflowParallelConfigurationEditor.js';
3
5
  import { WorkflowReminderEditor } from './WorkflowReminderEditor.js';
4
6
  import { WorkflowNotificationEditor } from './WorkflowNotificationEditor.js';
@@ -27,13 +29,16 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
27
29
  const { message } = App.useApp();
28
30
  const [draft, setDraft] = useState();
29
31
  const [definition, setDefinition] = useState();
32
+ const [stepInputInvalid, setStepInputInvalid] = useState(false);
33
+ const [reminderDirty, setReminderDirty] = useState(false);
34
+ const [binding, setBinding] = useState();
30
35
  const [nativeHeadRevision, setNativeHeadRevision] = useState();
31
36
  const [configurations, setConfigurations] = useState();
32
37
  const [selected, setSelected] = useState('');
33
38
  const [selectedEdge, setSelectedEdge] = useState();
34
39
  const [publishedView, setPublishedView] = useState(false);
35
40
  const [outline, setOutline] = useState(true);
36
- const [detailInspector, setDetailInspector] = useState(false);
41
+ const [detailInspector, setDetailInspector] = useState(true);
37
42
  const [inspector, setInspector] = useState(true);
38
43
  const [narrow, setNarrow] = useState(() => typeof matchMedia !== 'undefined' && matchMedia('(max-width: 899px)').matches);
39
44
  const inspectorElement = useRef(null);
@@ -53,6 +58,7 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
53
58
  const [insert, setInsert] = useState();
54
59
  const [template, setTemplate] = useState('condition');
55
60
  const [nodeTitle, setNodeTitle] = useState('');
61
+ const [assistantContext, setAssistantContext] = useState('');
56
62
  const [assistantOpen, setAssistantOpen] = useState(false);
57
63
  const [assistantState, setAssistantState] = useState({ busy: false, unknown: false });
58
64
  const [versionsOpen, setVersionsOpen] = useState(false);
@@ -81,6 +87,7 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
81
87
  return;
82
88
  setDraft(value);
83
89
  setDefinition(value.definition);
90
+ setBinding(value.binding);
84
91
  setConfigurations(configuration);
85
92
  setNativeHeadRevision(context.headRevision);
86
93
  setSelected(value.definition.startAt);
@@ -96,7 +103,7 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
96
103
  setConfigurations(configuration);
97
104
  setNativeHeadRevision(context.headRevision);
98
105
  };
99
- const dirty = !!draft && !!definition && !same(draft.definition, definition);
106
+ const dirty = !!draft && !!definition && (!same(draft.definition, definition) || !same(draft.binding, binding) || stepInputInvalid || reminderDirty);
100
107
  useEffect(() => { const unknown = !!frozenSave.current || !!frozenPublish.current || !!frozenAux.current || assistantState.unknown || liveState.unknown; onDirtyChange?.(dirty || liveState.dirty || unknown); onStateChange?.({ dirty: dirty || liveState.dirty, busy: busy || assistantState.busy || liveState.busy, unknown }); }, [dirty, busy, assistantState, liveState, onDirtyChange, onStateChange]);
101
108
  useEffect(() => { const guard = (event) => { if (dirty || frozenSave.current || frozenPublish.current || frozenAux.current || assistantState.unknown) {
102
109
  event.preventDefault();
@@ -119,22 +126,29 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
119
126
  const outlineNodes = useMemo(() => displayGraph ? workflowDesignerOutlineRows(displayGraph) : [], [displayGraph]);
120
127
  useEffect(() => { if (shown && selected !== workflowDesignerStartId && !shown.nodes[selected])
121
128
  setSelected(shown.startAt); }, [shown, selected]);
129
+ const catalog = useMemo(() => draft?.capabilities || (draft ? workflowAuthoringCatalog(draft.publishedDefinition, draft.publishedBinding) : undefined), [draft]);
122
130
  const variables = useMemo(() => definition ? workflowDesignerVariables(definition) : [], [definition]);
123
- const errors = useMemo(() => definition ? validateWorkflowDesignerDocument(definition) : [], [definition]);
131
+ const errors = useMemo(() => definition ? [...validateWorkflowDesignerDocument(definition), ...validateWorkflowBusinessSteps(definition), ...Object.values(definition.nodes).flatMap(node => {
132
+ if (!('binding' in node))
133
+ return [];
134
+ const entry = binding?.bindings[node.binding];
135
+ return !entry || entry.provider === 'fixed_users' && !entry.users?.length || entry.provider === 'app_role' && !entry.roleCode && !entry.roleCodes?.length ? [`WORKFLOW_DESIGNER_PEOPLE_REQUIRED:${node.id}`] : [];
136
+ })] : [], [definition, binding]);
124
137
  const node = shown?.nodes[selected];
125
138
  const liveNode = configurations?.nodes.find(item => item.nodeId === selected);
126
139
  const disabled = busy || assistantState.busy || assistantState.unknown || publishedView || !!frozenSave.current || !!frozenPublish.current || !!frozenAux.current;
127
- const mutate = (next) => {
128
- if (!definition || disabled)
140
+ const mutate = (next, nextBinding = binding) => {
141
+ if (!definition || !binding || !nextBinding || disabled)
129
142
  return;
130
143
  setHistory(current => {
131
- const bounded = [...current, definition].slice(-25);
144
+ const bounded = [...current, { definition, binding }].slice(-25);
132
145
  while (bounded.length > 1 && bounded.reduce((bytes, item) => bytes + JSON.stringify(item).length, 0) > 4 * 1024 * 1024)
133
146
  bounded.shift();
134
147
  return bounded;
135
148
  });
136
149
  setFuture([]);
137
150
  setDefinition(next);
151
+ setBinding(pruneWorkflowCanvasBindings(next, nextBinding, draft.publishedBinding));
138
152
  setError(undefined);
139
153
  };
140
154
  const patch = (patch) => { if (definition && node)
@@ -142,13 +156,22 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
142
156
  const save = async (quiet = false) => {
143
157
  if (!draft || !definition)
144
158
  return undefined;
159
+ if (reminderDirty && !frozenSave.current) {
160
+ message.warning('请先确定或取消办理提醒的修改。');
161
+ return undefined;
162
+ }
163
+ if (stepInputInvalid && !frozenSave.current) {
164
+ setError('业务步骤固定值不是有效 JSON,请修正后再保存。');
165
+ return undefined;
166
+ }
145
167
  setBusy(true);
146
168
  try {
147
- frozenSave.current ||= { expectedRevision: draft.revision, expectedHeadRevision: draft.baseHeadRevision, operationId: createBrowserUuid(), definition, binding: draft.binding };
169
+ frozenSave.current ||= { expectedRevision: draft.revision, expectedHeadRevision: draft.baseHeadRevision, operationId: createBrowserUuid(), definition, binding: binding };
148
170
  const saved = await saveWorkflowDesignerDraft(workflowCode, frozenSave.current);
149
171
  frozenSave.current = undefined;
150
172
  setDraft(saved);
151
173
  setDefinition(saved.definition);
174
+ setBinding(saved.binding);
152
175
  setError(undefined);
153
176
  if (!quiet)
154
177
  message.success('流程草稿已保存');
@@ -167,12 +190,39 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
167
190
  const autosave = useRef(save);
168
191
  autosave.current = save;
169
192
  useEffect(() => {
170
- if (!dirty || !definition || busy || publishedView || errors.length || frozenSave.current || frozenPublish.current || frozenAux.current || attemptedAutosave.current === definition)
193
+ if (!dirty || !definition || stepInputInvalid || reminderDirty || busy || publishedView || frozenSave.current || frozenPublish.current || frozenAux.current || attemptedAutosave.current === JSON.stringify({ definition, binding }))
171
194
  return;
172
- const timer = setTimeout(() => { attemptedAutosave.current = definition; void autosave.current(true); }, 900);
195
+ let timer;
196
+ const persist = () => {
197
+ if (inspectorElement.current?.querySelector('[role="combobox"][aria-expanded="true"]')) {
198
+ timer = setTimeout(persist, 300);
199
+ return;
200
+ }
201
+ attemptedAutosave.current = JSON.stringify({ definition, binding });
202
+ void autosave.current(true);
203
+ };
204
+ timer = setTimeout(persist, 900);
173
205
  return () => clearTimeout(timer);
174
- }, [dirty, definition, busy, publishedView, errors.length]);
206
+ }, [dirty, definition, binding, busy, publishedView, stepInputInvalid, reminderDirty]);
207
+ const inspectorReady = () => {
208
+ if (stepInputInvalid) {
209
+ message.warning('业务步骤固定值不是有效 JSON,请先修正,或切换此输入来源以放弃该值。');
210
+ return false;
211
+ }
212
+ if (reminderDirty) {
213
+ message.warning('请先确定或取消办理提醒的修改。');
214
+ return false;
215
+ }
216
+ return true;
217
+ };
218
+ const closeInspector = () => { if (!inspectorReady())
219
+ return; const close = () => setInspector(false); if (leaveHandling.current)
220
+ leaveHandling.current(close);
221
+ else
222
+ close(); };
175
223
  const selectNode = (value, edgeId) => {
224
+ if (value !== selected && !inspectorReady())
225
+ return;
176
226
  const next = () => { setSelected(value); setSelectedEdge(edgeId); if (value !== selected)
177
227
  setStructureKeys([]); setInspector(value !== workflowDesignerStartId); };
178
228
  if (value !== selected && leaveHandling.current)
@@ -197,11 +247,7 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
197
247
  return;
198
248
  if (event.key === 'Escape' && ![...element.querySelectorAll('[aria-expanded="true"]')].some(item => item.getClientRects().length)) {
199
249
  event.preventDefault();
200
- const close = () => setInspector(false);
201
- if (leaveHandling.current)
202
- leaveHandling.current(close);
203
- else
204
- close();
250
+ closeInspector();
205
251
  }
206
252
  if (event.key === 'Tab') {
207
253
  const focusable = [...element.querySelectorAll('button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex="0"]')].filter(item => item.getClientRects().length);
@@ -215,8 +261,10 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
215
261
  element?.querySelector('button')?.focus();
216
262
  document.addEventListener('keydown', keydown);
217
263
  return () => { document.removeEventListener('keydown', keydown); previous?.focus({ preventScroll: true }); };
218
- }, [narrow, inspector]);
264
+ }, [narrow, inspector, stepInputInvalid, reminderDirty]);
219
265
  const switchVersion = (value) => {
266
+ if (!inspectorReady())
267
+ return;
220
268
  const next = () => { setPublishedView(value === 'published'); };
221
269
  if (leaveHandling.current)
222
270
  leaveHandling.current(next);
@@ -224,6 +272,8 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
224
272
  next();
225
273
  };
226
274
  const goBack = () => {
275
+ if (!inspectorReady())
276
+ return;
227
277
  const next = () => { if (dirty) {
228
278
  void save(true).then(saved => { if (saved) {
229
279
  if (onBack)
@@ -304,7 +354,7 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
304
354
  }
305
355
  };
306
356
  const openAssistant = async () => {
307
- if (disabled)
357
+ if (disabled || !inspectorReady())
308
358
  return;
309
359
  if (dirty || frozenSave.current) {
310
360
  const saved = await save();
@@ -353,6 +403,7 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
353
403
  const restored = await restoreWorkflowDesignerVersion(workflowCode, input);
354
404
  setDraft(restored);
355
405
  setDefinition(restored.definition);
406
+ setBinding(restored.binding);
356
407
  setHistory([]);
357
408
  setFuture([]);
358
409
  setVersionsOpen(false);
@@ -408,6 +459,8 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
408
459
  return;
409
460
  }
410
461
  let next;
462
+ let nextBinding = binding;
463
+ let insertionDefinition = definition;
411
464
  if (chosenTemplate === 'condition')
412
465
  next = { id: nodeId, kind: 'condition', title: chosenTitle.trim(), branches: [{ label: '条件 1', when: defaultWorkflowCondition(variables), target: edge.to }], otherwise: edge.to };
413
466
  else if (chosenTemplate === 'platform_notify')
@@ -415,21 +468,46 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
415
468
  handler: { code: WORKFLOW_PLATFORM_NOTIFY_HANDLER, version: 1, mode: 'reconciled-effect' },
416
469
  inputSchema: structuredClone(WORKFLOW_PLATFORM_NOTIFY_INPUT_SCHEMA), outputSchema: structuredClone(WORKFLOW_PLATFORM_NOTIFY_OUTPUT_SCHEMA),
417
470
  inputs: { text: { source: 'literal', value: '请关注此申请的最新进展。' } }, notification: { template: 'workflow_message', recipients: { provider: 'initiator' } } };
471
+ else if (['approval', 'handle', 'cc'].includes(chosenTemplate)) {
472
+ let reject = Object.values(definition.nodes).find(node => node.kind === 'end' && node.outcome === 'rejected')?.id;
473
+ if (chosenTemplate === 'approval' && !reject) {
474
+ reject = id();
475
+ insertionDefinition = { ...definition, nodes: { ...definition.nodes, [reject]: { id: reject, kind: 'end', title: '申请已拒绝', outcome: 'rejected' } } };
476
+ }
477
+ next = createWorkflowHumanNode(nodeId, chosenTemplate, chosenTitle.trim(), edge.to, undefined, catalog?.taskPages, reject);
478
+ nextBinding = { ...binding, bindings: { ...binding.bindings, [workflowCanvasBindingKey(nodeId)]: { provider: 'fixed_users', users: [] } } };
479
+ }
480
+ else if (chosenTemplate === 'action') {
481
+ const step = catalog?.steps[0];
482
+ if (!step) {
483
+ message.info('应用还没有发布可选业务步骤,请通过 AI 助手准备新能力。');
484
+ setAssistantContext('当前应用没有可选业务步骤。请提出需要由应用开发新增并发布的步骤能力方案,不要假设未发布代码已经可以执行。');
485
+ setAssistantOpen(true);
486
+ setInspector(true);
487
+ return;
488
+ }
489
+ next = { ...structuredClone(step), id: nodeId, kind: 'action', next: edge.to, inputs: {} };
490
+ }
418
491
  else {
419
492
  const source = draft?.publishedDefinition.nodes[chosenTemplate];
420
493
  if (!source || !['approval', 'handle', 'cc', 'action'].includes(source.kind))
421
494
  return;
422
- next = { ...structuredClone(source), id: nodeId, title: chosenTitle.trim() };
423
- if (next.kind === 'approval')
424
- next.onApprove = edge.to;
425
- else if ('next' in next)
426
- next.next = edge.to;
495
+ if (source.kind === 'approval' || source.kind === 'handle' || source.kind === 'cc') {
496
+ next = createWorkflowHumanNode(nodeId, source.kind, chosenTitle.trim(), edge.to, 'taskPageCode' in source ? source.taskPageCode : undefined, catalog.taskPages, source.kind === 'approval' ? source.onReject : undefined);
497
+ if (next.kind === 'approval' || next.kind === 'handle')
498
+ next.mode = source.kind === 'approval' || source.kind === 'handle' ? source.mode : 'single';
499
+ nextBinding = { ...binding, bindings: { ...binding.bindings, [workflowCanvasBindingKey(nodeId)]: structuredClone(draft.publishedBinding.bindings[source.binding]) } };
500
+ }
501
+ else if (source.kind === 'action')
502
+ next = { ...structuredClone(source), id: nodeId, title: chosenTitle.trim(), next: edge.to };
503
+ else
504
+ return;
427
505
  }
428
506
  try {
429
- mutate(edge.from === workflowDesignerStartId ? { ...definition, startAt: next.id, nodes: { ...definition.nodes, [next.id]: next } } : editWorkflowDesignerDefinition(definition, { type: 'insert', from: edge.from, target: edge.to, node: next, edge: edge.kind === 'branch' ? (edge.priority || 1) - 1 : edge.kind === 'default' ? 'default' : edge.kind }));
507
+ mutate(edge.from === workflowDesignerStartId ? { ...insertionDefinition, startAt: next.id, nodes: { ...insertionDefinition.nodes, [next.id]: next } } : editWorkflowDesignerDefinition(insertionDefinition, { type: 'insert', from: edge.from, target: edge.to, node: next, edge: edge.kind === 'branch' ? (edge.priority || 1) - 1 : edge.kind === 'default' ? 'default' : edge.kind }), nextBinding);
430
508
  setSelected(nodeId);
431
509
  setInspector(true);
432
- setStructureKeys(next.kind === 'condition' ? [] : ['advanced']);
510
+ setStructureKeys([]);
433
511
  setInsert(undefined);
434
512
  }
435
513
  catch (error) {
@@ -448,15 +526,14 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
448
526
  return [item.nodeId, `${mode}${mode ? ' · ' : ''}${source}`];
449
527
  }));
450
528
  const human = node?.kind === 'approval' || node?.kind === 'handle';
451
- const panel = _jsxs("div", { className: "oxa-workflow-designer-inspector", children: [_jsxs("header", { children: [_jsx("span", { className: `oxa-designer-inspector-icon kind-${node?.kind || 'start'}`, children: _jsx(NodeIcon, {}) }), _jsx("h2", { children: node?.title || '流程发起' }), _jsx(Tag, { children: isWorkflowPlatformNotify(node) ? '通知节点' : kinds[node?.kind || ''] || '发起' }), _jsx(Button, { type: "text", icon: _jsx(CloseOutlined, {}), "aria-label": "\u5173\u95ED\u8282\u70B9\u8BBE\u7F6E", onClick: () => { const close = () => setInspector(false); if (leaveHandling.current)
452
- leaveHandling.current(close);
453
- else
454
- close(); } })] }), node ? _jsxs(_Fragment, { children: [_jsx("div", { hidden: human && structureKeys.includes('return'), children: liveNode && configurations && ['approval', 'handle', 'cc'].includes(node.kind) ? _jsx(WorkflowNodeConfigurationEditor, { workflowCode: workflowCode, node: liveNode, principals: configurations.principals, expectedHeadRevision: nativeHeadRevision, presentation: "inline", readOnly: publishedView, compact: !detailInspector && !narrow, onExpand: () => { setDetailInspector(true); setOutline(false); }, onClose: () => setInspector(false), onStateChange: handlingStateChanged, onLeaveGuardChange: handlingGuardChanged, returnSummary: human && (node.returnPolicy?.targets || node.returnTargets || []).length ? _jsxs("div", { children: [_jsx(Tag, { color: "gold", children: "\u968F\u8349\u7A3F\u53D1\u5E03" }), _jsx("div", { children: (node.returnPolicy?.targets || (node.returnTargets || []).map(nodeId => ({ nodeId, defaultRoute: 'replay' }))).map(target => _jsxs("p", { children: [definition.nodes[target.nodeId]?.title || '退回目标', " \u00B7 ", target.defaultRoute === 'resume' ? '重新提交后直接回到本节点' : '重新提交后重新按流程流转'] }, target.nodeId)) }), _jsx(Button, { type: "link", size: "small", onClick: () => setStructureKeys(['return']), children: "\u7F16\u8F91\u9000\u56DE\u8BBE\u7F6E" })] }) : undefined, onSaved: () => { void refreshHandling().catch(failure => setError(`办理设置已保存,重新读取失败:${String(failure.message)}`)); } }, `${liveNode.nodeId}:${liveNode.configuration.revision}`) : human && _jsx(WorkflowDraftHandlingEditor, { node: node, baseline: Object.values(draft.publishedDefinition.nodes).find(source => source.kind === node.kind && 'taskPageCode' in source && source.taskPageCode === node.taskPageCode && 'binding' in source && source.binding === node.binding) || node, bindingOptions: Object.keys(draft.publishedBinding.bindings).map(value => ({ value, label: `${Object.values(draft.publishedDefinition.nodes).find(source => 'binding' in source && source.binding === value)?.title || '已发布节点'}的人员规则` })), disabled: disabled, onChange: value => patch({ ...value, ...(typeof value.binding === 'string' && draft.publishedBinding.bindings[value.binding]?.provider === 'supervisor_chain' && draft.publishedBinding.bindings[value.binding]?.continuous !== false ? { mode: 'sequence' } : {}) }) }) }), node.kind === 'parallel' && _jsx(WorkflowParallelConfigurationEditor, { node: node, selectedBranch: node.branches[(graph.edges.find(edge => edge.id === selectedEdge && edge.from === node.id)?.priority || 0) - 1]?.id, variables: variables, disabled: disabled, onChange: value => patch({ branches: value.branches }), onRemove: branchId => mutate(editWorkflowDesignerDefinition(definition, { type: 'remove_parallel_branch', nodeId: node.id, branchId })) }, node.id), node.kind === 'join' && _jsx(Alert, { type: "info", showIcon: true, title: "\u672C\u6B21\u8FDB\u5165\u7684\u5168\u90E8\u5206\u652F\u5B8C\u6210\u540E\u7EE7\u7EED", description: "\u6C47\u5408\u70B9\u4E0E\u5E76\u884C\u5206\u652F\u6210\u5BF9\u7EF4\u62A4\u3002\u82E5\u8981\u5220\u9664\u6574\u4E2A\u5E76\u884C\u533A\u57DF\uFF0C\u8BF7\u5728\u5E76\u884C\u8282\u70B9\u8BBE\u7F6E\u4E2D\u64CD\u4F5C\u3002" }), node.kind === 'condition' && _jsx(WorkflowConditionConfigurationEditor, { node: node, variables: variables, targets: targets, selectedBranch: graph.edges.find(edge => edge.id === selectedEdge && edge.from === node.id && edge.kind === 'branch')?.priority ? graph.edges.find(edge => edge.id === selectedEdge).priority - 1 : undefined, disabled: disabled, onChange: value => patch({ branches: value.branches, otherwise: value.otherwise }) }, node.id), human && structureKeys.includes('return') && _jsxs(_Fragment, { children: [_jsx(Button, { type: "link", className: "oxa-designer-return-back", icon: _jsx(ArrowLeftOutlined, {}), onClick: () => setStructureKeys([]), children: "\u8FD4\u56DE\u8282\u70B9\u914D\u7F6E" }), _jsx(WorkflowReturnPolicyEditor, { definition: definition, node: node, disabled: disabled, onChange: returnPolicy => patch({ returnPolicy, returnTargets: returnPolicy.targets.map(target => target.nodeId) }) })] }), _jsxs("section", { className: "oxa-designer-draft-band", hidden: human && structureKeys.includes('return'), children: [_jsx("h3", { children: "\u6D41\u7A0B\u7ED3\u6784 \u00B7 \u968F\u8349\u7A3F\u53D1\u5E03" }), _jsx(Collapse, { ghost: true, activeKey: structureKeys, onChange: keys => setStructureKeys(Array.isArray(keys) ? keys : [keys]), items: [
529
+ const panel = _jsxs("div", { className: "oxa-workflow-designer-inspector", children: [_jsxs("header", { children: [_jsx("span", { className: `oxa-designer-inspector-icon kind-${node?.kind || 'start'}`, children: _jsx(NodeIcon, {}) }), _jsx("h2", { children: node?.title || '流程发起' }), _jsx(Tag, { children: isWorkflowPlatformNotify(node) ? '通知节点' : kinds[node?.kind || ''] || '发起' }), _jsx(Button, { type: "text", icon: _jsx(CloseOutlined, {}), "aria-label": "\u5173\u95ED\u8282\u70B9\u8BBE\u7F6E", onClick: closeInspector })] }), node ? _jsxs(_Fragment, { children: [_jsx("div", { hidden: human && structureKeys.includes('return'), children: liveNode && configurations && ['approval', 'handle', 'cc'].includes(node.kind) ? _jsx(WorkflowNodeConfigurationEditor, { workflowCode: workflowCode, node: liveNode, principals: configurations.principals, expectedHeadRevision: nativeHeadRevision, presentation: "inline", readOnly: publishedView, compact: !detailInspector && !narrow, onExpand: () => { setDetailInspector(true); setOutline(false); }, onClose: closeInspector, onStateChange: handlingStateChanged, onLeaveGuardChange: handlingGuardChanged, returnSummary: human && (node.returnPolicy?.targets || node.returnTargets || []).length ? _jsxs("div", { children: [_jsx(Tag, { color: "gold", children: "\u968F\u8349\u7A3F\u53D1\u5E03" }), _jsx("div", { children: (node.returnPolicy?.targets || (node.returnTargets || []).map(nodeId => ({ nodeId, defaultRoute: 'replay' }))).map(target => _jsxs("p", { children: [definition.nodes[target.nodeId]?.title || '退回目标', " \u00B7 ", target.defaultRoute === 'resume' ? '重新提交后直接回到本节点' : '重新提交后重新按流程流转'] }, target.nodeId)) }), _jsx(Button, { type: "link", size: "small", onClick: () => setStructureKeys(['return']), children: "\u7F16\u8F91\u9000\u56DE\u8BBE\u7F6E" })] }) : undefined, onSaved: () => { void refreshHandling().catch(failure => setError(`办理设置已保存,重新读取失败:${String(failure.message)}`)); } }, `${liveNode.nodeId}:${liveNode.configuration.revision}`) : draft.publishedDefinition.nodes[node.id] && ['approval', 'handle', 'cc'].includes(node.kind) ? _jsx(Alert, { type: "warning", showIcon: true, title: "\u5DF2\u53D1\u5E03\u8282\u70B9\u7684\u529E\u7406\u8BBE\u7F6E\u672A\u80FD\u8F7D\u5165", description: "\u6B64\u8282\u70B9\u4E0D\u662F\u65B0\u589E\u8349\u7A3F\u8282\u70B9\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\u914D\u7F6E\u540E\u4FEE\u6539\u3002", action: _jsx(Button, { onClick: () => void refreshHandling().catch(failure => setError(String(failure.message))), children: "\u91CD\u65B0\u8BFB\u53D6\u529E\u7406\u8BBE\u7F6E" }) }) : ['approval', 'handle', 'cc'].includes(node.kind) && _jsx(WorkflowDraftHandlingEditor, { node: node, baseline: node, bindingOptions: Object.keys(draft.publishedBinding.bindings).map(value => ({ value, label: value })), binding: binding?.bindings['binding' in node ? node.binding : ''], sources: catalog.peopleSources, principals: configurations?.principals || { users: [], roles: [] }, disabled: disabled, onBindingChange: entry => { if (!('binding' in node) || !binding)
530
+ return; mutate({ ...definition, nodes: { ...definition.nodes, [node.id]: { ...node, ...(entry.provider === 'supervisor_chain' && entry.continuous !== false ? { mode: 'sequence' } : {}) } } }, { ...binding, bindings: { ...binding.bindings, [node.binding]: entry } }); }, onChange: patch }) }), node.kind === 'action' && !isWorkflowPlatformNotify(node) && catalog && _jsx(WorkflowBusinessStepEditor, { node: node, catalog: catalog, variables: variables, disabled: disabled, onValidityChange: setStepInputInvalid, onChange: patch, onAssistant: () => { setAssistantContext(`当前步骤:${node.title}(${node.handler.code} v${node.handler.version})。需要新增业务能力时,请提出源代码与发布契约的改造方案,不要假设新能力已经发布。`); setAssistantOpen(true); setInspector(true); } }, `${node.id}:${node.handler.code}`), node.kind === 'parallel' && _jsx(WorkflowParallelConfigurationEditor, { node: node, selectedBranch: node.branches[(graph.edges.find(edge => edge.id === selectedEdge && edge.from === node.id)?.priority || 0) - 1]?.id, variables: variables, disabled: disabled, onChange: value => patch({ branches: value.branches }), onRemove: branchId => mutate(editWorkflowDesignerDefinition(definition, { type: 'remove_parallel_branch', nodeId: node.id, branchId })) }, node.id), node.kind === 'join' && _jsx(Alert, { type: "info", showIcon: true, title: "\u672C\u6B21\u8FDB\u5165\u7684\u5168\u90E8\u5206\u652F\u5B8C\u6210\u540E\u7EE7\u7EED", description: "\u6C47\u5408\u70B9\u4E0E\u5E76\u884C\u5206\u652F\u6210\u5BF9\u7EF4\u62A4\u3002\u82E5\u8981\u5220\u9664\u6574\u4E2A\u5E76\u884C\u533A\u57DF\uFF0C\u8BF7\u5728\u5E76\u884C\u8282\u70B9\u8BBE\u7F6E\u4E2D\u64CD\u4F5C\u3002" }), node.kind === 'condition' && _jsx(WorkflowConditionConfigurationEditor, { node: node, variables: variables, targets: targets, selectedBranch: graph.edges.find(edge => edge.id === selectedEdge && edge.from === node.id && edge.kind === 'branch')?.priority ? graph.edges.find(edge => edge.id === selectedEdge).priority - 1 : undefined, disabled: disabled, onChange: value => patch({ branches: value.branches, otherwise: value.otherwise }) }, node.id), human && structureKeys.includes('return') && _jsxs(_Fragment, { children: [_jsx(Button, { type: "link", className: "oxa-designer-return-back", icon: _jsx(ArrowLeftOutlined, {}), onClick: () => setStructureKeys([]), children: "\u8FD4\u56DE\u8282\u70B9\u914D\u7F6E" }), _jsx(WorkflowReturnPolicyEditor, { definition: definition, node: node, disabled: disabled, onChange: returnPolicy => patch({ returnPolicy, returnTargets: returnPolicy.targets.map(target => target.nodeId) }) })] }), _jsxs("section", { className: "oxa-designer-draft-band", hidden: human && structureKeys.includes('return'), children: [_jsx("h3", { children: "\u6D41\u7A0B\u7ED3\u6784 \u00B7 \u968F\u8349\u7A3F\u53D1\u5E03" }), _jsx(Collapse, { ghost: true, activeKey: structureKeys, onChange: keys => setStructureKeys(Array.isArray(keys) ? keys : [keys]), items: [
455
531
  { key: 'name', label: '节点名称', extra: _jsx("span", { children: node.title || '未命名节点' }), children: _jsxs("label", { children: ["\u8282\u70B9\u540D\u79F0", _jsx(Input, { disabled: disabled, value: node.title || '', onChange: event => patch({ title: event.target.value }) })] }) },
456
532
  ...(human ? [{ key: 'return', label: '退回设置', extra: _jsx("span", { children: (node.returnPolicy?.targets || node.returnTargets || []).length ? `可退回 ${(node.returnPolicy?.targets || node.returnTargets || []).length} 个节点` : '未配置退回目标' }), children: null }] : []),
457
- ...(['approval', 'handle', 'correction'].includes(node.kind) ? [{ key: 'reminder', label: '办理提醒', extra: _jsx("span", { children: 'reminders' in node && node.reminders ? `${node.reminders.afterSeconds >= 3600 ? `${node.reminders.afterSeconds / 3600} 小时` : `${node.reminders.afterSeconds / 60} 分钟`}后提醒` : '未设置提醒' }), children: _jsx(_Fragment, { children: ['approval', 'handle', 'correction'].includes(node.kind) && _jsx(WorkflowReminderEditor, { rule: 'reminders' in node ? node.reminders : undefined, disabled: disabled, onChange: reminders => patch({ reminders }) }) }) }] : []),
458
- ...('taskPageCode' in node ? [{ key: 'page', label: '本节点表单', extra: _jsx("span", { children: definition.taskPages?.[node.taskPageCode || '']?.title || '应用自定义页面' }), children: _jsx("p", { children: "\u9875\u9762\u5185\u5BB9\u548C\u5B57\u6BB5\u89C4\u5219\u7531\u5E94\u7528\u7EF4\u62A4\u3002\u529E\u7406\u4EBA\u5458\u53EA\u80FD\u6309\u672C\u8282\u70B9\u5DF2\u5F00\u653E\u7684\u5B57\u6BB5\u586B\u5199\u3002" }) }] : []),
459
- { key: 'advanced', label: human ? '人员规则与流转路径' : '节点配置', children: _jsxs(_Fragment, { children: [_jsxs("label", { children: ["\u8282\u70B9\u540D\u79F0", _jsx(Input, { disabled: disabled, value: node.title || '', onChange: event => patch({ title: event.target.value }) })] }), (node.kind === 'approval' || node.kind === 'handle') && _jsxs(_Fragment, { children: [_jsxs("label", { children: ["\u4EBA\u5458\u89C4\u5219", _jsx(Select, { disabled: disabled, value: node.binding, options: Object.keys(draft.publishedBinding.bindings).map(value => ({ value, label: draft.publishedBinding.bindings[value]?.provider === 'supervisor_chain' ? formatWorkflowSupervisorChain(draft.publishedBinding.bindings[value]) : `${Object.values(draft.publishedDefinition.nodes).find(node => 'binding' in node && node.binding === value)?.title || '已发布节点'}的人员规则` })), onChange: binding => patch({ binding, ...(draft.publishedBinding.bindings[binding]?.provider === 'supervisor_chain' && draft.publishedBinding.bindings[binding]?.continuous !== false ? { mode: 'sequence' } : {}) }) })] }), _jsxs("label", { children: [node.kind === "handle" ? "办理完成后" : "通过后", _jsx(Select, { disabled: disabled, value: node.kind === "handle" ? node.next : node.onApprove, options: targets, onChange: target => patch(node.kind === "handle" ? { next: target } : { onApprove: target }) })] }), node.kind === "approval" && _jsxs("label", { children: ["\u62D2\u7EDD\u540E", _jsx(Select, { disabled: disabled, value: node.onReject, options: targets, onChange: onReject => patch({ onReject }) })] })] }), node.kind === 'action' && isWorkflowPlatformNotify(node) && _jsx(WorkflowNotificationEditor, { node: node, variables: variables, roles: configurations?.principals.roles || [], users: configurations?.principals.users || [], disabled: disabled, onChange: patch }), 'next' in node && _jsxs("label", { children: ["\u5B8C\u6210\u540E", _jsx(Select, { disabled: disabled, value: node.next, options: targets, onChange: next => patch({ next }) })] }), 'taskPageCode' in node && _jsxs("p", { children: ["\u672C\u8282\u70B9\u9875\u9762\uFF1A", definition.taskPages?.[node.taskPageCode || '']?.title || '按应用页面规则填写' || '标准审批页面'] }), !['end', 'correction', 'join'].includes(node.kind) && _jsx(Popconfirm, { title: node.kind === 'parallel' ? '删除并行区域及其中的所有节点?' : '删除节点并连接后续路径?', onConfirm: () => { try {
533
+ ...(['approval', 'handle', 'correction'].includes(node.kind) ? [{ key: 'reminder', label: '办理提醒', extra: _jsx("span", { children: 'reminders' in node && node.reminders ? `${node.reminders.afterSeconds >= 3600 ? `${node.reminders.afterSeconds / 3600} 小时` : `${node.reminders.afterSeconds / 60} 分钟`}后提醒` : '未设置提醒' }), children: _jsx(_Fragment, { children: ['approval', 'handle', 'correction'].includes(node.kind) && _jsx(WorkflowReminderEditor, { rule: 'reminders' in node ? node.reminders : undefined, disabled: disabled, onDirtyChange: setReminderDirty, onChange: reminders => patch({ reminders }) }, node.id) }) }] : []),
534
+ ...((human || 'taskPageCode' in node) ? [{ key: 'page', label: '本节点表单', extra: _jsx("span", { children: definition.taskPages?.[node.taskPageCode || '']?.title || '应用自定义页面' }), children: _jsxs(_Fragment, { children: [human && !liveNode ? _jsx(Select, { "aria-label": "\u672C\u8282\u70B9\u8868\u5355", allowClear: true, disabled: disabled, value: node.taskPageCode, placeholder: "\u6807\u51C6\u53EA\u8BFB\u8BE6\u60C5\uFF08\u4E0D\u4FDD\u5B58\u8868\u5355\uFF09", options: Object.entries(catalog.taskPages).map(([value, page]) => ({ value, label: page.title })), onChange: pageCode => { const standard = createWorkflowHumanNode(node.id, node.kind, node.title, node.kind === 'approval' ? node.onApprove : node.next, pageCode, catalog.taskPages, node.kind === 'approval' ? node.onReject : undefined); patch({ taskPageCode: pageCode, fieldPolicy: 'fieldPolicy' in standard ? standard.fieldPolicy : undefined, administration: 'administration' in standard ? standard.administration : undefined, allowedOperations: 'allowedOperations' in standard ? standard.allowedOperations : undefined, requiredOperations: 'requiredOperations' in standard ? standard.requiredOperations : undefined, operationPolicy: 'operationPolicy' in standard ? standard.operationPolicy : undefined }); } }) : null, _jsx("p", { children: "\u9875\u9762\u5185\u5BB9\u4E0E\u53EF\u7F16\u8F91\u5B57\u6BB5\u4E0A\u9650\u6765\u81EA\u5E94\u7528\u53D1\u5E03\u7684\u9875\u9762\uFF1B\u6CA1\u6709\u4EFB\u52A1\u8868\u5355\u65F6\u4F7F\u7528\u6807\u51C6\u53EA\u8BFB\u8BE6\u60C5\uFF0C\u4E0D\u63D0\u4F9B\u8868\u5355\u4FDD\u5B58\u3002" })] }) }] : []),
535
+ { key: 'advanced', label: human ? '人员规则与流转路径' : '节点配置', children: _jsxs(_Fragment, { children: [_jsxs("label", { children: ["\u8282\u70B9\u540D\u79F0", _jsx(Input, { disabled: disabled, value: node.title || '', onChange: event => patch({ title: event.target.value }) })] }), (node.kind === 'approval' || node.kind === 'handle') && _jsxs(_Fragment, { children: [_jsxs("label", { children: [node.kind === "handle" ? "办理完成后" : "通过后", _jsx(Select, { disabled: disabled, value: node.kind === "handle" ? node.next : node.onApprove, options: targets, onChange: target => patch(node.kind === "handle" ? { next: target } : { onApprove: target }) })] }), node.kind === "approval" && _jsxs("label", { children: ["\u62D2\u7EDD\u540E", _jsx(Select, { disabled: disabled, value: node.onReject, options: targets, onChange: onReject => patch({ onReject }) })] })] }), node.kind === 'action' && isWorkflowPlatformNotify(node) && _jsx(WorkflowNotificationEditor, { node: node, variables: variables, roles: configurations?.principals.roles || [], users: configurations?.principals.users || [], disabled: disabled, onChange: patch }), 'next' in node && _jsxs("label", { children: ["\u5B8C\u6210\u540E", _jsx(Select, { disabled: disabled, value: node.next, options: targets, onChange: next => patch({ next }) })] }), 'taskPageCode' in node && _jsxs("p", { children: ["\u672C\u8282\u70B9\u9875\u9762\uFF1A", definition.taskPages?.[node.taskPageCode || '']?.title || '按应用页面规则填写' || '标准审批页面'] }), !['end', 'correction', 'join'].includes(node.kind) && _jsx(Popconfirm, { title: node.kind === 'parallel' ? '删除并行区域及其中的所有节点?' : '删除节点并连接后续路径?', onConfirm: () => { if (!inspectorReady())
536
+ return; try {
460
537
  const next = editWorkflowDesignerDefinition(definition, { type: 'remove', nodeId: node.id, ...(node.kind === 'condition' ? { reconnectTo: node.otherwise } : {}) });
461
538
  mutate(next);
462
539
  setSelected(next.startAt);
@@ -471,40 +548,39 @@ export function WorkflowDesigner({ workflowCode, onPublished, onDirtyChange, onS
471
548
  const messages = { WORKFLOW_DESIGNER_CYCLE: '后续路径形成循环', WORKFLOW_DESIGNER_TARGET_MISSING: '后续节点不存在', WORKFLOW_DESIGNER_UNREACHABLE: '尚未连接到流程', WORKFLOW_DESIGNER_CONDITION_TYPE: '条件变量与比较值类型不一致', WORKFLOW_DESIGNER_VARIABLE_UNKNOWN: '条件变量来源无法确认', WORKFLOW_DESIGNER_CONDITION_BOOLEAN: '条件需要产生满足或不满足的判断', WORKFLOW_DESIGNER_BRANCH_LIMIT: '条件分支数量超出限制' };
472
549
  return `${title}:${messages[code || ''] || '配置需要调整'}`;
473
550
  };
474
- return _jsxs("section", { className: "oxa-workflow-designer", "aria-label": "\u6D41\u7A0B\u8BBE\u8BA1\u5668", children: [_jsxs("header", { className: "oxa-designer-toolbar", children: [_jsxs("div", { className: "oxa-designer-toolbar-identity", children: [_jsx(Tooltip, { title: "\u8FD4\u56DE\u6D41\u7A0B\u56FE", children: _jsx(Button, { icon: _jsx(ArrowLeftOutlined, {}), "aria-label": "\u8FD4\u56DE\u6D41\u7A0B\u56FE", disabled: busy || assistantState.unknown || liveState.busy || liveState.unknown, onClick: goBack }) }), _jsx("span", { className: "oxa-designer-toolbar-label", children: "\u6D41\u7A0B\u8BBE\u8BA1" }), _jsx("strong", { children: definition.title }), _jsx(Tag, { color: "blue", children: draft.environmentKey === 'production' ? '正式环境' : '测试环境' }), _jsx(Segmented, { "aria-label": "\u6D41\u7A0B\u8BBE\u8BA1\u67E5\u770B\u7248\u672C", value: publishedView ? 'published' : 'draft', onChange: switchVersion, options: [{ value: 'published', label: `已发布 v${draft.definitionVersion}` }, { value: 'draft', label: '草稿' }] }), _jsx("span", { className: "oxa-designer-save-state", children: busy && frozenSave.current ? '正在保存…' : dirty ? errors.length ? '修改待检查' : '草稿未保存' : `${draft.updatedAt ? '草稿已自动保存' : '草稿与已发布版本一致'}${draft.updatedAt ? ` ${new Date(draft.updatedAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}` : ''}` }), (frozenSave.current || dirty && error) && _jsx(Button, { type: "link", disabled: busy, onClick: () => void save(), children: frozenSave.current ? '重试原保存请求' : '重试保存' })] }), _jsxs(Space, { size: 8, className: "oxa-designer-toolbar-actions", children: [_jsx(Tooltip, { title: "\u64A4\u9500", children: _jsx(Button, { icon: _jsx(UndoOutlined, {}), "aria-label": "\u64A4\u9500", disabled: disabled || !history.length, onClick: () => { const previous = history.at(-1); if (previous) {
475
- setFuture(current => [...current, definition]);
551
+ return _jsxs("section", { className: "oxa-workflow-designer", "aria-label": "\u6D41\u7A0B\u8BBE\u8BA1\u5668", children: [_jsxs("header", { className: "oxa-designer-toolbar", children: [_jsxs("div", { className: "oxa-designer-toolbar-identity", children: [_jsx(Tooltip, { title: "\u8FD4\u56DE\u6D41\u7A0B\u56FE", children: _jsx(Button, { icon: _jsx(ArrowLeftOutlined, {}), "aria-label": "\u8FD4\u56DE\u6D41\u7A0B\u56FE", disabled: busy || assistantState.unknown || liveState.busy || liveState.unknown, onClick: goBack }) }), _jsx("span", { className: "oxa-designer-toolbar-label", children: "\u6D41\u7A0B\u8BBE\u8BA1" }), _jsx("strong", { children: definition.title }), _jsx(Tag, { color: "blue", children: draft.environmentKey === 'production' ? '正式环境' : '测试环境' }), _jsx(Segmented, { "aria-label": "\u6D41\u7A0B\u8BBE\u8BA1\u67E5\u770B\u7248\u672C", value: publishedView ? 'published' : 'draft', onChange: switchVersion, options: [{ value: 'published', label: `已发布 v${draft.definitionVersion}` }, { value: 'draft', label: '草稿' }] }), _jsx("span", { className: "oxa-designer-save-state", children: busy && frozenSave.current ? '正在保存…' : dirty ? errors.length ? '修改待检查' : '草稿未保存' : `${draft.updatedAt ? '草稿已自动保存' : '草稿与已发布版本一致'}${draft.updatedAt ? ` ${new Date(draft.updatedAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}` : ''}` }), (frozenSave.current || dirty && error) && _jsx(Button, { type: "link", disabled: busy, onClick: () => void save(), children: frozenSave.current ? '重试原保存请求' : '重试保存' })] }), _jsxs(Space, { size: 8, className: "oxa-designer-toolbar-actions", children: [_jsx(Tooltip, { title: "\u64A4\u9500", children: _jsx(Button, { icon: _jsx(UndoOutlined, {}), "aria-label": "\u64A4\u9500", disabled: disabled || stepInputInvalid || reminderDirty || !history.length, onClick: () => { const previous = history.at(-1); if (previous) {
552
+ setFuture(current => [...current, { definition, binding: binding }]);
476
553
  setHistory(current => current.slice(0, -1));
477
- setDefinition(previous);
478
- } }, children: "\u64A4\u9500" }) }), _jsx(Tooltip, { title: "\u91CD\u505A", children: _jsx(Button, { icon: _jsx(RedoOutlined, {}), "aria-label": "\u91CD\u505A", disabled: disabled || !future.length, onClick: () => { const next = future.at(-1); if (next) {
479
- setHistory(current => [...current, definition]);
554
+ setDefinition(previous.definition);
555
+ setBinding(previous.binding);
556
+ } }, children: "\u64A4\u9500" }) }), _jsx(Tooltip, { title: "\u91CD\u505A", children: _jsx(Button, { icon: _jsx(RedoOutlined, {}), "aria-label": "\u91CD\u505A", disabled: disabled || stepInputInvalid || reminderDirty || !future.length, onClick: () => { const next = future.at(-1); if (next) {
557
+ setHistory(current => [...current, { definition, binding: binding }]);
480
558
  setFuture(current => current.slice(0, -1));
481
- setDefinition(next);
559
+ setDefinition(next.definition);
560
+ setBinding(next.binding);
482
561
  } }, children: "\u91CD\u505A" }) }), _jsx(Button, { icon: _jsx(SafetyOutlined, {}), onClick: () => setChecksOpen(true), children: "\u7ED3\u6784\u68C0\u67E5" }), _jsx(Button, { icon: _jsx(HistoryOutlined, {}), onClick: () => void showVersions(), children: "\u7248\u672C\u8BB0\u5F55" }), _jsx(Button, { icon: _jsx(RobotOutlined, {}), disabled: disabled || liveState.busy || liveState.unknown, onClick: () => { const open = () => void openAssistant(); if (leaveHandling.current)
483
562
  leaveHandling.current(open);
484
563
  else
485
- open(); }, children: "AI \u52A9\u624B" }), _jsx(Button, { type: "primary", disabled: disabled || errors.length > 0 || liveState.dirty || liveState.busy || liveState.unknown, onClick: () => void openPublication(), children: "\u53D1\u5E03\u5E76\u542F\u7528" })] })] }), error && _jsx(Alert, { type: "error", title: error, action: frozenSave.current ? _jsx(Button, { onClick: () => void save(), children: "\u91CD\u8BD5\u4FDD\u5B58" }) : frozenAux.current ? _jsx(Button, { onClick: () => void retryAux(), children: "\u91CD\u8BD5\u539F\u64CD\u4F5C" }) : undefined }), receipt && _jsxs(_Fragment, { children: [_jsx(Alert, { type: receipt.counts.failed || receipt.counts.excepted ? 'warning' : 'success', title: `已发布 v${receipt.definitionVersion} · ${receipt.status === 'running' ? '正在更新进行中的申请' : '更新处理结束'}`, description: Object.entries(receipt.counts).map(([key, count]) => `${outcomeLabels[key] || key} ${count}`).join(' · '), action: _jsxs(Space, { children: [receipt.status === 'running' && _jsx(Button, { disabled: busy, onClick: () => void control('pause'), children: "\u6682\u505C\u66F4\u65B0" }), receipt.status === 'paused' && _jsx(Button, { disabled: busy, onClick: () => void control('resume'), children: "\u7EE7\u7EED\u66F4\u65B0" }), !!receipt.counts.failed && _jsx(Button, { disabled: busy, onClick: () => void control('retry_failed'), children: "\u91CD\u8BD5\u5931\u8D25\u7684\u7533\u8BF7" })] }) }), receipt.items?.length ? _jsxs("details", { children: [_jsx("summary", { children: "\u67E5\u770B\u7533\u8BF7\u66F4\u65B0\u8BB0\u5F55" }), _jsx(Table, { size: "small", rowKey: "instanceId", dataSource: receipt.items, pagination: { pageSize: 5 }, columns: [{ title: '申请', dataIndex: 'business_key' }, { title: '结果', render: (_, item) => outcomeLabels[item.outcome] || item.outcome }, { title: '原因', dataIndex: 'reason' }] }), receipt.items.some(item => item.outcome === 'held') && _jsxs("div", { style: { padding: 12 }, children: [_jsxs("label", { children: ["\u89E3\u9664\u539F\u7248\u672C\u4FDD\u7559", _jsx(Select, { mode: "multiple", style: { width: '100%' }, value: releaseIds, disabled: busy || !!frozenAux.current, options: receipt.items.filter(item => item.outcome === 'held').map(item => ({ value: item.instanceId, label: item.business_key })), onChange: setReleaseIds })] }), _jsx(Input, { "aria-label": "\u89E3\u9664\u4FDD\u7559\u8BF4\u660E", maxLength: 1000, value: releaseReason, disabled: busy || !!frozenAux.current, onChange: event => setReleaseReason(event.target.value), placeholder: "\u8BF4\u660E\u4E3A\u4EC0\u4E48\u5C06\u8FD9\u4E9B\u7533\u8BF7\u66F4\u65B0\u5230\u5F53\u524D\u7248\u672C" }), _jsx(Button, { disabled: busy || !!frozenAux.current || !releaseIds.length || !releaseReason.trim(), onClick: () => void releaseHolds(), children: "\u89E3\u9664\u4FDD\u7559\u5E76\u66F4\u65B0" })] })] }) : null] }), _jsxs("div", { className: `oxa-designer-workspace ${outline ? '' : 'without-outline'} ${inspector ? '' : 'without-inspector'} ${detailInspector ? 'detail-inspector' : ''}`, children: [_jsxs("aside", { className: "oxa-designer-outline", "aria-label": "\u6D41\u7A0B\u5927\u7EB2", children: [_jsxs("div", { className: "oxa-designer-outline-heading", children: [outline && _jsx("strong", { children: "\u6D41\u7A0B\u5927\u7EB2" }), _jsx(Button, { type: "text", icon: outline ? _jsx(MenuFoldOutlined, {}) : _jsx(MenuUnfoldOutlined, {}), "aria-label": outline ? '收起流程大纲' : '展开流程大纲', onClick: () => { const toggle = () => { if (!outline)
564
+ open(); }, children: "AI \u52A9\u624B" }), _jsx(Button, { type: "primary", disabled: disabled || stepInputInvalid || reminderDirty || errors.length > 0 || liveState.dirty || liveState.busy || liveState.unknown, onClick: () => void openPublication(), children: "\u53D1\u5E03\u5E76\u542F\u7528" })] })] }), error && _jsx(Alert, { type: "error", title: error, action: frozenSave.current ? _jsx(Button, { onClick: () => void save(), children: "\u91CD\u8BD5\u4FDD\u5B58" }) : frozenAux.current ? _jsx(Button, { onClick: () => void retryAux(), children: "\u91CD\u8BD5\u539F\u64CD\u4F5C" }) : undefined }), receipt && _jsxs(_Fragment, { children: [_jsx(Alert, { type: receipt.counts.failed || receipt.counts.excepted ? 'warning' : 'success', title: `已发布 v${receipt.definitionVersion} · ${receipt.status === 'running' ? '正在更新进行中的申请' : '更新处理结束'}`, description: Object.entries(receipt.counts).map(([key, count]) => `${outcomeLabels[key] || key} ${count}`).join(' · '), action: _jsxs(Space, { children: [receipt.status === 'running' && _jsx(Button, { disabled: busy, onClick: () => void control('pause'), children: "\u6682\u505C\u66F4\u65B0" }), receipt.status === 'paused' && _jsx(Button, { disabled: busy, onClick: () => void control('resume'), children: "\u7EE7\u7EED\u66F4\u65B0" }), !!receipt.counts.failed && _jsx(Button, { disabled: busy, onClick: () => void control('retry_failed'), children: "\u91CD\u8BD5\u5931\u8D25\u7684\u7533\u8BF7" })] }) }), receipt.items?.length ? _jsxs("details", { children: [_jsx("summary", { children: "\u67E5\u770B\u7533\u8BF7\u66F4\u65B0\u8BB0\u5F55" }), _jsx(Table, { size: "small", rowKey: "instanceId", dataSource: receipt.items, pagination: { pageSize: 5 }, columns: [{ title: '申请', dataIndex: 'business_key' }, { title: '结果', render: (_, item) => outcomeLabels[item.outcome] || item.outcome }, { title: '原因', dataIndex: 'reason' }] }), receipt.items.some(item => item.outcome === 'held') && _jsxs("div", { style: { padding: 12 }, children: [_jsxs("label", { children: ["\u89E3\u9664\u539F\u7248\u672C\u4FDD\u7559", _jsx(Select, { mode: "multiple", style: { width: '100%' }, value: releaseIds, disabled: busy || !!frozenAux.current, options: receipt.items.filter(item => item.outcome === 'held').map(item => ({ value: item.instanceId, label: item.business_key })), onChange: setReleaseIds })] }), _jsx(Input, { "aria-label": "\u89E3\u9664\u4FDD\u7559\u8BF4\u660E", maxLength: 1000, value: releaseReason, disabled: busy || !!frozenAux.current, onChange: event => setReleaseReason(event.target.value), placeholder: "\u8BF4\u660E\u4E3A\u4EC0\u4E48\u5C06\u8FD9\u4E9B\u7533\u8BF7\u66F4\u65B0\u5230\u5F53\u524D\u7248\u672C" }), _jsx(Button, { disabled: busy || !!frozenAux.current || !releaseIds.length || !releaseReason.trim(), onClick: () => void releaseHolds(), children: "\u89E3\u9664\u4FDD\u7559\u5E76\u66F4\u65B0" })] })] }) : null] }), _jsxs("div", { className: `oxa-designer-workspace ${outline ? '' : 'without-outline'} ${inspector ? '' : 'without-inspector'} ${detailInspector ? 'detail-inspector' : ''}`, children: [_jsxs("aside", { className: "oxa-designer-outline", "aria-label": "\u6D41\u7A0B\u5927\u7EB2", children: [_jsxs("div", { className: "oxa-designer-outline-heading", children: [outline && _jsx("strong", { children: "\u6D41\u7A0B\u5927\u7EB2" }), _jsx(Button, { type: "text", icon: outline ? _jsx(MenuFoldOutlined, {}) : _jsx(MenuUnfoldOutlined, {}), "aria-label": outline ? '收起流程大纲' : '展开流程大纲', onClick: () => { const toggle = () => { if (!outline)
486
565
  setDetailInspector(false); setOutline(value => !value); }; if (!outline && leaveHandling.current)
487
566
  leaveHandling.current(toggle);
488
567
  else
489
568
  toggle(); } })] }), outline && _jsx(Input.Search, { size: "small", "aria-label": "\u641C\u7D22\u6D41\u7A0B\u8282\u70B9", placeholder: "\u641C\u7D22\u8282\u70B9", value: outlineKeyword, allowClear: true, onChange: event => setOutlineKeyword(event.target.value) }), _jsx("nav", { children: outlineNodes.filter(item => !outlineKeyword || item.title.includes(outlineKeyword)).map(item => {
490
569
  const Icon = item.presentation === 'notification' ? BellOutlined : typeIcons[item.kind] || CodeOutlined;
491
570
  return _jsx(Tooltip, { title: !outline ? item.title : undefined, placement: "right", children: _jsxs("button", { type: "button", className: `kind-${item.kind}`, "aria-label": item.title, "aria-pressed": item.edgeId ? selectedEdge === item.edgeId : selected === item.nodeId, style: outline && item.depth ? { paddingLeft: 14 + item.depth * 16 } : undefined, onClick: () => item.edgeId ? selectEdge(item.edgeId) : selectNode(item.nodeId), children: [_jsx(Icon, {}), outline && _jsx("span", { children: item.title })] }) }, item.id);
492
- }) }), outline && _jsxs("footer", { children: [_jsx("strong", { children: "\u68C0\u67E5\u7ED3\u679C" }), _jsxs("button", { type: "button", onClick: () => setChecksOpen(true), children: [_jsx(CheckCircleOutlined, {}), " ", errors.length ? `发现 ${errors.length} 项问题` : '未发现问题'] })] })] }), _jsxs("main", { children: [_jsxs("div", { className: "oxa-designer-banner", children: [publishedView ? `正在查看已发布 v${draft.definitionVersion}` : '正在编辑草稿', " \u00B7 \u53D1\u5E03\u5E76\u542F\u7528\u65F6\u53EF\u66F4\u65B0\u8FDB\u884C\u4E2D\u7684\u7533\u8BF7"] }), _jsx(WorkflowDiagram, { graph: displayGraph, summaries: summaries, selectedNodeId: selected, selectedEdgeId: selectedEdge, onSelectEdge: selectEdge, onSelectNode: selectNode, presentation: "designer", insertionOptions: [...Object.values(draft.publishedDefinition.nodes).filter(source => ['approval', 'handle', 'cc', 'action'].includes(source.kind) && !isWorkflowPlatformNotify(source)).map(source => ({ value: source.id, label: source.title || kinds[source.kind] || '已发布节点', kind: source.kind })), ...(variables.length ? [{ value: 'condition', label: '条件分支', kind: 'condition' }] : []), { value: 'parallel', label: '并行分支', kind: 'parallel' }, { value: 'platform_notify', label: '发送通知', kind: 'notification' }], onInsertEdge: disabled ? undefined : (value, chosenTemplate) => { const open = () => { if (chosenTemplate) {
493
- const title = chosenTemplate === 'parallel' ? '并行分支' : chosenTemplate === 'condition' ? '条件分支' : chosenTemplate === 'platform_notify' ? '发送通知' : draft.publishedDefinition.nodes[chosenTemplate]?.title || '新增节点';
571
+ }) }), outline && _jsxs("footer", { children: [_jsx("strong", { children: "\u68C0\u67E5\u7ED3\u679C" }), _jsxs("button", { type: "button", onClick: () => setChecksOpen(true), children: [_jsx(CheckCircleOutlined, {}), " ", errors.length ? `发现 ${errors.length} 项问题` : '未发现问题'] })] })] }), _jsxs("main", { children: [_jsxs("div", { className: "oxa-designer-banner", children: [publishedView ? `正在查看已发布 v${draft.definitionVersion}` : '正在编辑草稿', " \u00B7 \u53D1\u5E03\u5E76\u542F\u7528\u65F6\u53EF\u66F4\u65B0\u8FDB\u884C\u4E2D\u7684\u7533\u8BF7"] }), _jsx(WorkflowDiagram, { graph: displayGraph, summaries: summaries, selectedNodeId: selected, selectedEdgeId: selectedEdge, onSelectEdge: selectEdge, onSelectNode: selectNode, presentation: "designer", insertionOptions: [{ value: 'approval', label: '审批', kind: 'approval' }, { value: 'handle', label: '办理', kind: 'handle' }, { value: 'cc', label: '抄送', kind: 'cc' }, ...(variables.length ? [{ value: 'condition', label: '条件分支', kind: 'condition' }] : []), { value: 'parallel', label: '并行分支', kind: 'parallel' }, { value: 'action', label: '业务步骤', kind: 'action' }, { value: 'platform_notify', label: '发送通知', kind: 'notification' }], onInsertEdge: disabled || stepInputInvalid || reminderDirty ? undefined : (value, chosenTemplate) => { const open = () => { if (chosenTemplate) {
572
+ const title = chosenTemplate === 'parallel' ? '并行分支' : chosenTemplate === 'condition' ? '条件分支' : chosenTemplate === 'platform_notify' ? '发送通知' : kinds[chosenTemplate] || draft.publishedDefinition.nodes[chosenTemplate]?.title || '新增节点';
494
573
  insertNode(chosenTemplate, title, value);
495
574
  }
496
575
  else {
497
576
  setInsert(value);
498
577
  setNodeTitle('');
499
- setTemplate(variables.length ? 'condition' : Object.values(draft.publishedDefinition.nodes).find(node => node.kind === 'approval' || node.kind === 'handle')?.id || '');
578
+ setTemplate('approval');
500
579
  } }; if (leaveHandling.current)
501
580
  leaveHandling.current(open);
502
581
  else
503
- open(); } }), !inspector && _jsx(Button, { className: "oxa-designer-show-inspector", onClick: () => setInspector(true), children: "\u8282\u70B9\u8BBE\u7F6E" }), _jsxs(Button, { className: "oxa-designer-mobile-inspector", onClick: () => setInspector(true), children: ["\u7F16\u8F91 ", node?.title || '节点'] })] }), inspector && narrow && _jsx("button", { type: "button", className: "oxa-designer-inspector-backdrop", "aria-label": "\u5173\u95ED\u8282\u70B9\u8BBE\u7F6E", onClick: () => { const close = () => setInspector(false); if (leaveHandling.current)
504
- leaveHandling.current(close);
505
- else
506
- close(); } }), _jsxs("aside", { style: { display: inspector ? undefined : 'none' }, ref: inspectorElement, className: "oxa-designer-desktop-inspector", role: narrow ? 'dialog' : undefined, "aria-modal": narrow ? true : undefined, "aria-label": assistantOpen ? 'AI 助手' : '节点设置', children: [_jsx("div", { hidden: assistantOpen, children: panel }), _jsx(WorkflowDesignerAssistant, { presentation: "panel", workflowCode: workflowCode, draft: draft, open: assistantOpen, canApply: !dirty && !busy && !liveState.dirty && !liveState.busy && !liveState.unknown && !frozenSave.current && !frozenPublish.current && !frozenAux.current, onClose: () => setAssistantOpen(false), onApplied: value => { setPublishedView(false); setDraft(value); setDefinition(value.definition); setHistory(current => { const snapshots = [...current, definition].slice(-25); while (snapshots.length > 1 && snapshots.reduce((bytes, item) => bytes + JSON.stringify(item).length, 0) > 4 * 1024 * 1024)
507
- snapshots.shift(); return snapshots; }); setFuture([]); setError(undefined); }, onStateChange: setAssistantState })] })] }), _jsx(Drawer, { open: checksOpen, title: "\u6D41\u7A0B\u7ED3\u6784\u68C0\u67E5", width: 440, onClose: () => setChecksOpen(false), children: _jsx(Alert, { showIcon: true, type: errors.length ? 'warning' : 'success', title: errors.length ? `发现 ${errors.length} 项待修正的问题` : '未发现结构问题', description: errors.length ? errors.map(diagnostic).join(';') : '节点与流转路径已通过结构校验。发布时还会检查当前应用的人员规则、页面和业务步骤。' }) }), _jsxs(Modal, { open: !!insert, title: "\u65B0\u589E\u8282\u70B9", onCancel: () => setInsert(undefined), onOk: () => insertNode(), okText: "\u6DFB\u52A0", okButtonProps: { disabled: !nodeTitle.trim() || !template }, children: [_jsx("p", { children: "\u5728\u9009\u4E2D\u8DEF\u5F84\u4E2D\u63D2\u5165\u8282\u70B9\uFF0C\u6CBF\u7528\u5DF2\u53D1\u5E03\u7684\u4EBA\u5458\u89C4\u5219\u3001\u4E1A\u52A1\u6B65\u9AA4\u548C\u9875\u9762\u3002" }), _jsxs("label", { children: ["\u8282\u70B9\u7C7B\u578B", _jsx(Select, { style: { width: '100%' }, value: template, onChange: setTemplate, options: [{ value: 'parallel', label: '并行分支' }, { value: 'platform_notify', label: '发送通知' }, ...(variables.length ? [{ value: 'condition', label: '条件分支' }] : []), ...Object.values(draft.publishedDefinition.nodes).filter(node => ['approval', 'handle', 'cc', 'action'].includes(node.kind)).map(node => ({ value: node.id, label: `${kinds[node.kind]} · ${node.title}` }))] })] }), _jsxs("label", { children: ["\u8282\u70B9\u540D\u79F0", _jsx(Input, { value: nodeTitle, onChange: event => setNodeTitle(event.target.value) })] })] }), _jsx(Drawer, { open: versionsOpen, title: "\u6D41\u7A0B\u7248\u672C\u8BB0\u5F55", width: 620, onClose: () => setVersionsOpen(false), children: _jsx(Table, { loading: busy, rowKey: "publicationId", dataSource: versions, pagination: { pageSize: 10 }, columns: [{ title: '版本', render: (_, item) => `v${item.definitionVersion}` }, { title: '说明', dataIndex: 'reason' }, { title: '发布时间', dataIndex: 'createdAt', render: value => new Date(value).toLocaleString() }, { title: '操作', render: (_, item) => _jsx(Popconfirm, { title: "\u5C06\u8BE5\u7248\u672C\u6062\u590D\u5230\u5171\u4EAB\u8349\u7A3F\uFF1F", description: "\u5F53\u524D\u8349\u7A3F\u5C06\u88AB\u66FF\u6362\uFF1B\u53D1\u5E03\u540E\u624D\u4F1A\u751F\u6548\u3002", onConfirm: () => void restore(item.definitionVersion), children: _jsx(Button, { disabled: busy || dirty || liveState.dirty || liveState.busy || liveState.unknown || !!frozenSave.current || !!frozenPublish.current || !!frozenAux.current, children: "\u6062\u590D\u5230\u8349\u7A3F" }) }) }] }) }), _jsxs(Modal, { open: publication, title: "\u53D1\u5E03\u5E76\u542F\u7528", width: 648, className: "oxa-designer-publish-modal", cancelText: "\u7EE7\u7EED\u7F16\u8F91", onCancel: () => { if (!frozenPublish.current)
582
+ open(); } }), !inspector && _jsx(Button, { className: "oxa-designer-show-inspector", onClick: () => setInspector(true), children: "\u8282\u70B9\u8BBE\u7F6E" }), _jsxs(Button, { className: "oxa-designer-mobile-inspector", onClick: () => setInspector(true), children: ["\u7F16\u8F91 ", node?.title || '节点'] })] }), inspector && narrow && _jsx("button", { type: "button", className: "oxa-designer-inspector-backdrop", "aria-label": "\u5173\u95ED\u8282\u70B9\u8BBE\u7F6E", onClick: closeInspector }), _jsxs("aside", { style: { display: inspector ? undefined : 'none' }, ref: inspectorElement, className: "oxa-designer-desktop-inspector", role: narrow ? 'dialog' : undefined, "aria-modal": narrow ? true : undefined, "aria-label": assistantOpen ? 'AI 助手' : '节点设置', children: [_jsx("div", { hidden: assistantOpen, children: panel }), _jsx(WorkflowDesignerAssistant, { presentation: "panel", workflowCode: workflowCode, draft: draft, context: assistantContext, open: assistantOpen, canApply: !dirty && !busy && !liveState.dirty && !liveState.busy && !liveState.unknown && !frozenSave.current && !frozenPublish.current && !frozenAux.current, onClose: () => setAssistantOpen(false), onApplied: value => { setPublishedView(false); setDraft(value); setDefinition(value.definition); setBinding(value.binding); setHistory(current => { const snapshots = [...current, { definition, binding: binding }].slice(-25); while (snapshots.length > 1 && snapshots.reduce((bytes, item) => bytes + JSON.stringify(item).length, 0) > 4 * 1024 * 1024)
583
+ snapshots.shift(); return snapshots; }); setFuture([]); setError(undefined); }, onStateChange: setAssistantState })] })] }), _jsx(Drawer, { open: checksOpen, title: "\u6D41\u7A0B\u7ED3\u6784\u68C0\u67E5", width: 440, onClose: () => setChecksOpen(false), children: _jsx(Alert, { showIcon: true, type: errors.length ? 'warning' : 'success', title: errors.length ? `发现 ${errors.length} 项待修正的问题` : '未发现结构问题', description: errors.length ? errors.map(diagnostic).join(';') : '节点与流转路径已通过结构校验。发布时还会检查当前应用的人员规则、页面和业务步骤。' }) }), _jsxs(Modal, { open: !!insert, title: "\u65B0\u589E\u8282\u70B9", onCancel: () => setInsert(undefined), onOk: () => insertNode(), okText: "\u6DFB\u52A0", okButtonProps: { disabled: !nodeTitle.trim() || !template }, children: [_jsx("p", { children: "\u65B0\u589E\u7A7A\u767D\u8282\u70B9\u540E\u81EA\u884C\u914D\u7F6E\u4EBA\u5458\u3001\u6309\u94AE\u548C\u63D0\u9192\u3002\u4E1A\u52A1\u6B65\u9AA4\u4F7F\u7528\u5E94\u7528\u5DF2\u53D1\u5E03\u7684\u80FD\u529B\u3002" }), _jsxs("label", { children: ["\u8282\u70B9\u7C7B\u578B", _jsx(Select, { style: { width: '100%' }, value: template, onChange: setTemplate, options: [{ value: 'approval', label: '审批(空白)' }, { value: 'handle', label: '办理(空白)' }, { value: 'cc', label: '抄送(空白)' }, { value: 'action', label: '已发布业务步骤' }, { value: 'parallel', label: '并行分支' }, { value: 'platform_notify', label: '发送通知' }, ...(variables.length ? [{ value: 'condition', label: '条件分支' }] : []), ...Object.values(draft.publishedDefinition.nodes).filter(node => ['approval', 'handle', 'cc', 'action'].includes(node.kind)).map(node => ({ value: node.id, label: `复制已有配置 · ${node.title}` }))] })] }), _jsxs("label", { children: ["\u8282\u70B9\u540D\u79F0", _jsx(Input, { value: nodeTitle, onChange: event => setNodeTitle(event.target.value) })] })] }), _jsx(Drawer, { open: versionsOpen, title: "\u6D41\u7A0B\u7248\u672C\u8BB0\u5F55", width: 620, onClose: () => setVersionsOpen(false), children: _jsx(Table, { loading: busy, rowKey: "publicationId", dataSource: versions, pagination: { pageSize: 10 }, columns: [{ title: '版本', render: (_, item) => `v${item.definitionVersion}` }, { title: '说明', dataIndex: 'reason' }, { title: '发布时间', dataIndex: 'createdAt', render: value => new Date(value).toLocaleString() }, { title: '操作', render: (_, item) => _jsx(Popconfirm, { title: "\u5C06\u8BE5\u7248\u672C\u6062\u590D\u5230\u5171\u4EAB\u8349\u7A3F\uFF1F", description: "\u5F53\u524D\u8349\u7A3F\u5C06\u88AB\u66FF\u6362\uFF1B\u53D1\u5E03\u540E\u624D\u4F1A\u751F\u6548\u3002", onConfirm: () => void restore(item.definitionVersion), children: _jsx(Button, { disabled: busy || dirty || liveState.dirty || liveState.busy || liveState.unknown || !!frozenSave.current || !!frozenPublish.current || !!frozenAux.current, children: "\u6062\u590D\u5230\u8349\u7A3F" }) }) }] }) }), _jsxs(Modal, { open: publication, title: "\u53D1\u5E03\u5E76\u542F\u7528", width: 648, className: "oxa-designer-publish-modal", cancelText: "\u7EE7\u7EED\u7F16\u8F91", onCancel: () => { if (!frozenPublish.current)
508
584
  setPublication(false); }, onOk: () => void publish(), confirmLoading: busy, okText: frozenPublish.current ? '重试原发布请求' : '发布并启用', okButtonProps: { disabled: !reason.trim() || scope === 'running_and_new' && (holdIds.length > 0 || holdNodeIds.length > 0) && !holdReason.trim() || !preview || preview.truncated || scope === 'running_and_new' && !!preview.counts.excepted && !acknowledge }, children: [_jsxs("p", { children: ["\u5C06\u5F53\u524D\u8349\u7A3F\u53D1\u5E03\u5230", draft.environmentKey === 'production' ? '正式环境' : '测试环境', "\u3002\u68C0\u67E5\u901A\u8FC7\u540E\u7ACB\u5373\u751F\u6548\u3002"] }), _jsxs(Spin, { spinning: busy, children: [_jsxs("div", { className: "oxa-designer-publish-checks", children: [_jsx(CheckCircleOutlined, {}), _jsx("span", { children: preview ? '流程与应用能力检查已完成' : '正在检查流程与应用能力' })] }), _jsxs("fieldset", { disabled: busy || !!frozenPublish.current, children: [_jsx("h3", { children: "\u751F\u6548\u8303\u56F4" }), _jsxs(Radio.Group, { value: scope, disabled: busy || !!frozenPublish.current, onChange: event => setScope(event.target.value), className: "oxa-designer-publish-scope", children: [_jsxs(Radio, { value: "running_and_new", children: [_jsxs("strong", { children: ["\u8FDB\u884C\u4E2D\u7684\u7533\u8BF7\u548C\u65B0\u53D1\u8D77\u7684\u7533\u8BF7\u90FD\u4F7F\u7528\u65B0\u7248\u672C", _jsx(Tag, { color: "blue", children: "\u9ED8\u8BA4" })] }), _jsx("small", { children: "\u5DF2\u8FDB\u5165\u7684\u4EFB\u52A1\u4FDD\u7559\u539F\u6709\u4EBA\u9009\u3001\u6309\u94AE\u548C\u9875\u9762\uFF0C\u540E\u7EED\u6D41\u8F6C\u4F7F\u7528\u65B0\u7248\u672C\u3002" })] }), _jsxs(Radio, { value: "new_only", children: [_jsx("strong", { children: "\u4EC5\u65B0\u53D1\u8D77\u7684\u7533\u8BF7\u4F7F\u7528\u65B0\u7248\u672C" }), _jsx("small", { children: "\u8FDB\u884C\u4E2D\u7684\u7533\u8BF7\u7EE7\u7EED\u6309\u539F\u7248\u672C\u529E\u7406\u3002" })] })] }), scope === 'running_and_new' && _jsxs("details", { className: "oxa-designer-publish-holds", children: [_jsxs("summary", { children: ["\u6307\u5B9A\u4FDD\u7559\u5728\u539F\u7248\u672C\u7684\u7533\u8BF7", (holdIds.length > 0 || holdNodeIds.length > 0) && _jsx(Tag, { children: "\u5DF2\u6307\u5B9A" })] }), _jsxs("label", { children: ["\u4FDD\u7559\u539F\u7248\u672C\u7684\u7533\u8BF7", _jsx(Select, { mode: "multiple", showSearch: true, filterOption: false, onSearch: keyword => void searchHolds(keyword), disabled: busy || !!frozenPublish.current, value: holdIds, onChange: value => { setHoldIds(value); setPreview(undefined); }, options: holdCandidates.map(item => ({ value: item.instanceId, label: `${item.businessKey} · ${item.nodeTitle}` })) })] }), _jsxs("label", { children: ["\u4FDD\u7559\u5F53\u524D\u505C\u5728\u8FD9\u4E9B\u8282\u70B9\u7684\u7533\u8BF7", _jsx(Select, { mode: "multiple", disabled: busy || !!frozenPublish.current, value: holdNodeIds, options: Object.values(definition.nodes).filter(node => ['approval', 'handle', 'correction', 'action'].includes(node.kind)).map(node => ({ value: node.id, label: node.title || '流程节点' })), onChange: value => { setHoldNodeIds(value); setPreview(undefined); } })] }), (holdIds.length > 0 || holdNodeIds.length > 0) && _jsxs("label", { children: ["\u4FDD\u7559\u539F\u56E0", _jsx(Input, { disabled: busy || !!frozenPublish.current, value: holdReason, maxLength: 1000, onChange: event => setHoldReason(event.target.value) })] }), _jsx(Button, { disabled: busy || !!frozenPublish.current, onClick: () => void check(), children: "\u91CD\u65B0\u68C0\u67E5\u5F71\u54CD" })] }), preview && scope === 'running_and_new' && _jsxs(_Fragment, { children: [_jsx("h3", { children: "\u8FDB\u884C\u4E2D\u7684\u7533\u8BF7" }), _jsx("dl", { className: "oxa-designer-publish-counts", children: Object.entries(preview.counts).map(([key, count]) => _jsxs("div", { className: `outcome-${key}`, children: [_jsx("dt", { children: outcomeLabels[key] || key }), _jsx("dd", { children: count })] }, key)) }), preview.items.some(item => item.outcome !== 'eligible') && _jsxs("details", { className: "oxa-designer-publish-exceptions", children: [_jsx("summary", { children: "\u67E5\u770B\u9700\u5355\u72EC\u5904\u7406\u7684\u7533\u8BF7" }), _jsx(Table, { size: "small", rowKey: "instanceId", dataSource: preview.items.filter(item => item.outcome !== 'eligible'), pagination: { pageSize: 5 }, columns: [{ title: '申请', dataIndex: 'businessKey' }, { title: '处理', render: (_, item) => outcomeLabels[item.outcome] }, { title: '原因', dataIndex: 'reason' }] })] }), !!preview.counts.excepted && _jsx(Checkbox, { disabled: !!frozenPublish.current || busy, checked: acknowledge, onChange: event => setAcknowledge(event.target.checked), children: "\u6211\u5DF2\u4E86\u89E3\u4E0D\u80FD\u66F4\u65B0\u7684\u7533\u8BF7\u5C06\u4FDD\u7559\u539F\u7248\u672C\uFF0C\u5E76\u5728\u66F4\u65B0\u8BB0\u5F55\u4E2D\u5355\u72EC\u5217\u51FA\u3002" })] }), scope === 'new_only' && _jsx("p", { children: "\u65B0\u53D1\u8D77\u7684\u7533\u8BF7\u4F7F\u7528\u6B64\u7248\u672C\uFF0C\u8FDB\u884C\u4E2D\u7684\u7533\u8BF7\u4FDD\u6301\u5F53\u524D\u7248\u672C\u3002" }), _jsxs("label", { className: "oxa-designer-publish-reason", children: ["\u7248\u672C\u8BF4\u660E", _jsx(Input, { "aria-label": "\u6D41\u7A0B\u7248\u672C\u8BF4\u660E", disabled: busy || !!frozenPublish.current, value: reason, maxLength: 1000, onChange: event => setReason(event.target.value), placeholder: "\u8BF4\u660E\u672C\u6B21\u6D41\u7A0B\u7684\u8C03\u6574" })] })] })] })] })] });
509
585
  }
510
586
  //# sourceMappingURL=WorkflowDesigner.js.map