openxiangda 2.0.0-alpha.98 → 2.0.0
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.
- package/LICENSE +21 -0
- package/README.md +23 -20
- package/bin/distribution/commands.js +55 -0
- package/bin/distribution/launcher.js +49 -0
- package/bin/distribution/migrate.js +60 -0
- package/bin/distribution/releases.js +52 -0
- package/bin/distribution/skills.js +80 -0
- package/bin/distribution/update.js +68 -0
- package/bin/distribution/workspace.js +85 -0
- package/bin/run.js +9 -11
- package/dist/browser/AuthoritativeSelector.d.ts +3 -2
- package/dist/browser/AuthoritativeSelector.d.ts.map +1 -1
- package/dist/browser/AuthoritativeSelector.js +39 -24
- package/dist/browser/AuthoritativeSelector.js.map +1 -1
- package/dist/browser/Shell.d.ts.map +1 -1
- package/dist/browser/Shell.js +24 -18
- package/dist/browser/Shell.js.map +1 -1
- package/dist/browser/admin-information-architecture.d.ts +4 -2
- package/dist/browser/admin-information-architecture.d.ts.map +1 -1
- package/dist/browser/admin-information-architecture.js +2 -2
- package/dist/browser/admin-information-architecture.js.map +1 -1
- package/dist/browser/application.d.ts.map +1 -1
- package/dist/browser/application.js +3 -3
- package/dist/browser/application.js.map +1 -1
- package/dist/browser/components/platform-fields/AttachmentFileList.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/AttachmentFileList.js +5 -1
- package/dist/browser/components/platform-fields/AttachmentFileList.js.map +1 -1
- package/dist/browser/components/platform-fields/MobileFieldControls.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/MobileFieldControls.js +2 -2
- package/dist/browser/components/platform-fields/MobileFieldControls.js.map +1 -1
- package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts +4 -2
- package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/ResourceReferenceField.js +2 -2
- package/dist/browser/components/platform-fields/ResourceReferenceField.js.map +1 -1
- package/dist/browser/components/platform-fields/SubtableField.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/SubtableField.js +60 -80
- package/dist/browser/components/platform-fields/SubtableField.js.map +1 -1
- package/dist/browser/components/platform-fields/rich-text-value.d.ts.map +1 -1
- package/dist/browser/components/platform-fields/rich-text-value.js +11 -1
- package/dist/browser/components/platform-fields/rich-text-value.js.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceCrud.d.ts.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceCrud.js +33 -114
- package/dist/browser/components/resource/GeneratedResourceCrud.js.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceForm.d.ts +3 -1
- package/dist/browser/components/resource/GeneratedResourceForm.d.ts.map +1 -1
- package/dist/browser/components/resource/GeneratedResourceForm.js +11 -4
- package/dist/browser/components/resource/GeneratedResourceForm.js.map +1 -1
- package/dist/browser/components/resource/RecordChangeHistory.d.ts +12 -0
- package/dist/browser/components/resource/RecordChangeHistory.d.ts.map +1 -0
- package/dist/browser/components/resource/RecordChangeHistory.js +61 -0
- package/dist/browser/components/resource/RecordChangeHistory.js.map +1 -0
- package/dist/browser/components/resource/RecordDetailFrame.d.ts +30 -0
- package/dist/browser/components/resource/RecordDetailFrame.d.ts.map +1 -0
- package/dist/browser/components/resource/RecordDetailFrame.js +25 -0
- package/dist/browser/components/resource/RecordDetailFrame.js.map +1 -0
- package/dist/browser/components/resource/ResourceFormFrame.d.ts +2 -1
- package/dist/browser/components/resource/ResourceFormFrame.d.ts.map +1 -1
- package/dist/browser/components/resource/ResourceFormFrame.js +4 -4
- package/dist/browser/components/resource/ResourceFormFrame.js.map +1 -1
- package/dist/browser/components/resource/StandardResourcePages.d.ts +2 -4
- package/dist/browser/components/resource/StandardResourcePages.d.ts.map +1 -1
- package/dist/browser/components/resource/StandardResourcePages.js +8 -26
- package/dist/browser/components/resource/StandardResourcePages.js.map +1 -1
- package/dist/browser/components/resource/SurfaceFields.d.ts +5 -3
- package/dist/browser/components/resource/SurfaceFields.d.ts.map +1 -1
- package/dist/browser/components/resource/SurfaceFields.js +37 -12
- package/dist/browser/components/resource/SurfaceFields.js.map +1 -1
- package/dist/browser/components/resource/resource-import.d.ts +16 -1
- package/dist/browser/components/resource/resource-import.d.ts.map +1 -1
- package/dist/browser/components/resource/resource-import.js +58 -34
- package/dist/browser/components/resource/resource-import.js.map +1 -1
- package/dist/browser/components/resource/useResourceFormDrafts.d.ts.map +1 -1
- package/dist/browser/components/todo/ApplicationTodoCenterPage.d.ts +5 -2
- package/dist/browser/components/todo/ApplicationTodoCenterPage.d.ts.map +1 -1
- package/dist/browser/components/todo/ApplicationTodoCenterPage.js +19 -14
- package/dist/browser/components/todo/ApplicationTodoCenterPage.js.map +1 -1
- package/dist/browser/components/workflow/StandardWorkflowPages.d.ts +21 -5
- package/dist/browser/components/workflow/StandardWorkflowPages.d.ts.map +1 -1
- package/dist/browser/components/workflow/StandardWorkflowPages.js +175 -192
- package/dist/browser/components/workflow/StandardWorkflowPages.js.map +1 -1
- package/dist/browser/components/workflow/WorkflowRecordEditor.d.ts +2 -1
- package/dist/browser/components/workflow/WorkflowRecordEditor.d.ts.map +1 -1
- package/dist/browser/components/workflow/WorkflowRecordEditor.js +7 -4
- package/dist/browser/components/workflow/WorkflowRecordEditor.js.map +1 -1
- package/dist/browser/platform-client.d.ts +10 -4
- package/dist/browser/platform-client.d.ts.map +1 -1
- package/dist/browser/platform-client.js +78 -17
- package/dist/browser/platform-client.js.map +1 -1
- package/dist/browser/record-detail.css +115 -0
- package/dist/browser/runtime.d.ts.map +1 -1
- package/dist/browser/runtime.js +26 -2
- package/dist/browser/runtime.js.map +1 -1
- package/dist/browser/styles.css +1 -0
- package/dist/browser/workflow-launch.d.ts +4 -1
- package/dist/browser/workflow-launch.d.ts.map +1 -1
- package/dist/browser/workflow-launch.js +32 -0
- package/dist/browser/workflow-launch.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js.map +1 -1
- package/documentation/AGENTS.md +26 -0
- package/documentation/administration.md +27 -0
- package/documentation/application-foundation.md +162 -0
- package/documentation/appspec.md +152 -0
- package/documentation/backend.md +132 -0
- package/documentation/concepts.md +61 -0
- package/documentation/data-authz.md +62 -0
- package/documentation/delivery.md +110 -0
- package/documentation/development.md +32 -0
- package/documentation/field-components.md +236 -0
- package/documentation/frontend.md +269 -0
- package/documentation/getting-started.md +66 -0
- package/documentation/interaction-patterns.md +56 -0
- package/documentation/manifest.json +120 -0
- package/documentation/product-design.md +142 -0
- package/documentation/public-access.md +167 -0
- package/documentation/reference/cli.md +27 -0
- package/documentation/reference/mcp.md +649 -0
- package/documentation/testing.md +63 -0
- package/documentation/upgrading.md +39 -0
- package/documentation/workflow-events.md +181 -0
- package/launcher-skill/openxiangda/SKILL.md +24 -0
- package/package.json +72 -9
- package/releases/2.0.0.json +50 -0
- package/skills/manifest.json +2 -2
- package/skills/openxiangda-v2/SKILL.md +64 -51
- package/skills/openxiangda-v2/agents/openai.yaml +2 -2
- package/skills/openxiangda-v2/references/administration.md +27 -0
- package/skills/openxiangda-v2/references/application-foundation.md +162 -0
- package/skills/openxiangda-v2/references/appspec.md +132 -47
- package/skills/openxiangda-v2/references/backend.md +101 -248
- package/skills/openxiangda-v2/references/cli.md +27 -0
- package/skills/openxiangda-v2/references/concepts.md +61 -0
- package/skills/openxiangda-v2/references/data-authz.md +36 -388
- package/skills/openxiangda-v2/references/delivery.md +110 -49
- package/skills/openxiangda-v2/references/development.md +32 -0
- package/skills/openxiangda-v2/references/field-components.md +236 -0
- package/skills/openxiangda-v2/references/frontend.md +254 -280
- package/skills/openxiangda-v2/references/getting-started.md +66 -0
- package/skills/openxiangda-v2/references/interaction-patterns.md +56 -0
- package/skills/openxiangda-v2/references/mcp.md +649 -0
- package/skills/openxiangda-v2/references/product-design.md +142 -0
- package/skills/openxiangda-v2/references/public-access.md +92 -84
- package/skills/openxiangda-v2/references/testing.md +45 -56
- package/skills/openxiangda-v2/references/upgrading.md +39 -0
- package/skills/openxiangda-v2/references/workflow-events.md +143 -266
- package/skills/openxiangda-v2/references/architecture.md +0 -9
- package/skills/openxiangda-v2/references/commands.md +0 -21
- package/skills/openxiangda-v2/references/discovery.md +0 -15
- package/skills/openxiangda-v2/references/workspace.md +0 -62
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { ArrowLeftOutlined, EllipsisOutlined, ReloadOutlined, CloseOutlined, ExpandOutlined, CompressOutlined, ExportOutlined, } from '@ant-design/icons';
|
|
3
|
-
import { Alert, App, Button, Card,
|
|
2
|
+
import { ArrowLeftOutlined, ClockCircleOutlined, EllipsisOutlined, ReloadOutlined, CloseOutlined, ExpandOutlined, CompressOutlined, ExportOutlined, } from '@ant-design/icons';
|
|
3
|
+
import { Alert, App, Button, Card, Drawer, Empty, Form, Input, Modal, Result, Segmented, Select, Space, Spin, Table, Tabs, Tag, Tooltip, Typography, } from 'antd';
|
|
4
4
|
import { normalizeWorkflowBusinessDetail, } from 'openxiangda-contracts/browser';
|
|
5
5
|
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
6
6
|
import { Link, Navigate, useHref, useNavigate, useParams, useSearchParams, } from 'react-router-dom';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { PlatformDirectoryPicker } from '../platform-fields/PlatformDirectoryPicker';
|
|
8
|
+
import { directoryStoredValues } from '../platform-fields/directory-value';
|
|
9
|
+
import { executeWorkflowOperation, executeWorkflowLaunchNamedOperation, loadWorkflowInstanceDetail, loadWorkflowRecordDetail, loadWorkflowDataAudit, loadWorkflowInstanceSurface, loadWorkflowLaunchSurface, loadWorkflowTaskSurface, loadWorkflowTaskDetail, loadWorkflowWorkCenter, answerBusinessProcessCommand, commitStandardProcess, createNativeResourceClient, loadProcessCommandSurface, retryBusinessProcessCommand, uploadOperationManagedFile, } from '../../platform-client';
|
|
9
10
|
import { useWorkflowDefinition, } from '../../workflow-definitions';
|
|
10
11
|
import { useResourceDefinitions } from '../../resource-definitions';
|
|
11
12
|
import { selectedSurfaceFields } from '../resource/resource-field-selection';
|
|
12
13
|
import { useRuntime } from '../../runtime';
|
|
13
|
-
import {
|
|
14
|
-
import { buildWorkflowNamedOperationInput, parseWorkflowNamedOperationResult, workflowLaunchContractJsonEqual, } from '../../workflow-launch';
|
|
14
|
+
import { SurfaceFieldValue, } from '../resource/SurfaceFields';
|
|
15
|
+
import { workflowContextScalarValue, processStatusReadRetryDelay, buildWorkflowNamedOperationInput, parseWorkflowNamedOperationResult, workflowLaunchContractJsonEqual, } from '../../workflow-launch';
|
|
15
16
|
import { normalizeFormValues, normalizeRecordForForm, } from '../platform-fields/field-form-codec';
|
|
17
|
+
import { RecordDetailFrame, RecordDetailSections, detailTime } from '../resource/RecordDetailFrame';
|
|
18
|
+
import { RecordChangeHistory } from '../resource/RecordChangeHistory';
|
|
19
|
+
import { ResourceFormContent } from '../resource/ResourceFormFrame';
|
|
20
|
+
import { WorkflowRecordEditor } from './WorkflowRecordEditor';
|
|
16
21
|
import { PlatformAvatar } from '../PlatformAvatar';
|
|
17
22
|
/**
|
|
18
23
|
* An advanced task command has completed the current task and may have
|
|
@@ -71,6 +76,9 @@ function workflowStatus(status) {
|
|
|
71
76
|
};
|
|
72
77
|
return states[status] || { label: status || '未知', color: 'default' };
|
|
73
78
|
}
|
|
79
|
+
function workflowHasEnded(instance) {
|
|
80
|
+
return ['completed', 'approved', 'rejected', 'withdrawn', 'terminated', 'cancelled', 'expired'].includes(instance.status);
|
|
81
|
+
}
|
|
74
82
|
function StatusTag({ status }) {
|
|
75
83
|
const state = workflowStatus(status);
|
|
76
84
|
return _jsx(Tag, { color: state.color, children: state.label });
|
|
@@ -176,7 +184,7 @@ function WorkflowSubtableValue({ detail, field, instanceId, variant, }) {
|
|
|
176
184
|
: [];
|
|
177
185
|
});
|
|
178
186
|
if (variant === 'mobile') {
|
|
179
|
-
return (_jsx("div", { className: "oxa-workflow-subtable-mobile", children: subtable.rows.map((row, index) => (_jsxs("div", { children: [_jsxs("strong", { children: ["\u660E\u7EC6 ", index + 1] }), fields.map((child) => (_jsxs("div", { children: [_jsx(Typography.Text, { type: "secondary", children: child.label }), _jsx(SurfaceFieldValue, { field: child, presentation: "workflow-detail", resourceCode: subtable.resourceCode, value: row[child.key], workflowFileBinding: {
|
|
187
|
+
return (_jsx("div", { className: "oxa-workflow-subtable-mobile", children: subtable.rows.map((row, index) => (_jsxs("div", { children: [_jsxs("strong", { children: ["\u660E\u7EC6 ", index + 1] }), fields.map((child) => (_jsxs("div", { children: [_jsx(Typography.Text, { type: "secondary", children: child.label }), _jsx(SurfaceFieldValue, { field: child, mobile: true, presentation: "workflow-detail", resourceCode: subtable.resourceCode, value: row[child.key], workflowFileBinding: {
|
|
180
188
|
instanceId,
|
|
181
189
|
resourceCode: subtable.resourceCode,
|
|
182
190
|
recordId: String(row.id),
|
|
@@ -214,22 +222,9 @@ export function WorkflowBusinessDetailSections({ surface, variant, }) {
|
|
|
214
222
|
if (detail.status === 'unavailable' || !detail.surface) {
|
|
215
223
|
return _jsx(Result, { status: "warning", title: "\u4E1A\u52A1\u8BE6\u60C5\u6682\u65F6\u4E0D\u53EF\u7528" });
|
|
216
224
|
}
|
|
217
|
-
return
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
span: field.type === 'subtable' || ['file', 'image', 'text.rich', 'signature'].includes(field.type) ? 2 : 1,
|
|
221
|
-
children: field.type === 'subtable' ? (_jsx(WorkflowSubtableValue, { detail: detail, field: field, instanceId: instance.id, variant: variant })) : (_jsx(SurfaceFieldValue, { field: field, presentation: "workflow-detail", resourceCode: detail.resourceCode || undefined, value: detail.record[field.key], workflowFileBinding: {
|
|
222
|
-
instanceId: instance.id,
|
|
223
|
-
resourceCode: String(detail.resourceCode),
|
|
224
|
-
recordId: String(detail.recordId),
|
|
225
|
-
fieldCode: field.key,
|
|
226
|
-
} })),
|
|
227
|
-
})) })) : (_jsx("div", { className: "oxa-workflow-mobile-fields", children: group.fields.map((field) => (_jsxs("div", { className: field.type === 'subtable' ? 'is-wide' : undefined, children: [_jsx(Typography.Text, { type: "secondary", children: field.label }), field.type === 'subtable' ? (_jsx(WorkflowSubtableValue, { detail: detail, field: field, instanceId: instance.id, variant: variant })) : (_jsx(SurfaceFieldValue, { field: field, presentation: "workflow-detail", resourceCode: detail.resourceCode || undefined, value: detail.record[field.key], workflowFileBinding: {
|
|
228
|
-
instanceId: instance.id,
|
|
229
|
-
resourceCode: String(detail.resourceCode),
|
|
230
|
-
recordId: String(detail.recordId),
|
|
231
|
-
fieldCode: field.key,
|
|
232
|
-
} }))] }, field.key))) })) }, group.section))) }));
|
|
225
|
+
return _jsx(RecordDetailSections, { groups: groups, renderValue: field => field.type === 'subtable'
|
|
226
|
+
? _jsx(WorkflowSubtableValue, { detail: detail, field: field, instanceId: instance.id, variant: variant })
|
|
227
|
+
: _jsx(SurfaceFieldValue, { field: field, presentation: "workflow-detail", mobile: variant === 'mobile', resourceCode: detail.resourceCode || undefined, value: detail.record[field.key], workflowFileBinding: { instanceId: instance.id, resourceCode: String(detail.resourceCode), recordId: String(detail.recordId), fieldCode: field.key } }) });
|
|
233
228
|
}
|
|
234
229
|
function timelineTone(status) {
|
|
235
230
|
return `is-${status}`;
|
|
@@ -311,25 +306,15 @@ export function WorkflowTimelineSection({ timeline, }) {
|
|
|
311
306
|
return (_jsxs("div", { className: timelineTone(item.status), children: [_jsx("span", { className: "oxa-workflow-timeline-dot", children: _jsx(WorkflowStatusIcon, { status: item.status }) }), _jsxs("div", { children: [_jsxs("div", { className: "oxa-workflow-timeline-title", children: [_jsx("strong", { children: item.title }), _jsx(StatusTag, { status: item.status })] }), visiblePeople.length > 0 && (_jsx("div", { className: "oxa-workflow-timeline-assignees", children: visiblePeople.map((person, index) => (_jsxs("div", { children: [_jsx(PlatformAvatar, { avatarUrl: person.avatarUrl, size: 20 }), _jsxs("span", { children: [_jsx(Typography.Text, { children: person.displayName }), person.departmentDisplayName && (_jsx("small", { children: person.departmentDisplayName }))] })] }, `${person.userId || person.displayName}:${index}`))) })), operations.length > 0 && (_jsx("div", { className: "oxa-workflow-timeline-operations", children: operations.map((operation) => (_jsxs("div", { children: [_jsx(PlatformAvatar, { avatarUrl: operation.actor.avatarUrl, size: 20 }), _jsxs("span", { className: "oxa-workflow-operation-content", children: [_jsxs("span", { children: [_jsx(Typography.Text, { children: operation.actor.displayName }), _jsx("strong", { children: operation.operationLabel })] }), operation.reason && (_jsxs("span", { className: "oxa-workflow-operation-opinion", children: [_jsx(Typography.Text, { type: "secondary", children: "\u610F\u89C1" }), _jsx(Typography.Text, { children: operation.reason })] }))] })] }, operation.id))) })), item.terminalReason && !operations.some(operation => operation.reason) && (_jsxs(Typography.Text, { type: "secondary", children: ["\u539F\u56E0\uFF1A", item.terminalReason] })), item.primaryDisplayTime && (_jsx("time", { className: "oxa-workflow-primary-time", children: formatTime(item.primaryDisplayTime) }))] })] }, item.key));
|
|
312
307
|
}) })) : (_jsx(Empty, { description: "\u6682\u65E0\u6D41\u7A0B\u8F68\u8FF9", image: Empty.PRESENTED_IMAGE_SIMPLE })) }));
|
|
313
308
|
}
|
|
314
|
-
function
|
|
315
|
-
const [
|
|
316
|
-
const
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if (current !== sequence.current)
|
|
324
|
-
return;
|
|
325
|
-
setOptions(page.items.map((item) => ({ label: item.label, value: item.id })));
|
|
326
|
-
})
|
|
327
|
-
.finally(() => {
|
|
328
|
-
if (current === sequence.current)
|
|
329
|
-
setLoading(false);
|
|
330
|
-
});
|
|
331
|
-
};
|
|
332
|
-
return (_jsx(Select, { filterOption: false, loading: loading, onChange: onChange, onSearch: search, options: options, placeholder: "\u641C\u7D22\u5E76\u9009\u62E9\u4EBA\u5458", showSearch: true, value: value }));
|
|
309
|
+
function WorkflowMemberPicker({ id, placeholder, value, onChange, multiple = false, variant }) {
|
|
310
|
+
const [snapshots, setSnapshots] = useState([]);
|
|
311
|
+
const ids = Array.isArray(value) ? value : value ? [value] : [];
|
|
312
|
+
const selected = ids.map(id => snapshots.find(item => item.value === id) || { value: id, label: '已选成员' });
|
|
313
|
+
return _jsx(PlatformDirectoryPicker, { id: id, kind: "user", mobile: variant === 'mobile', multiple: multiple, placeholder: placeholder || '请选择成员', value: multiple ? selected : selected[0], onChange: next => {
|
|
314
|
+
const items = directoryStoredValues(next);
|
|
315
|
+
setSnapshots(items);
|
|
316
|
+
onChange?.(multiple ? items.map(item => item.value) : items[0]?.value);
|
|
317
|
+
} });
|
|
333
318
|
}
|
|
334
319
|
function schemaProperties(operation) {
|
|
335
320
|
const schema = operation.inputSchema;
|
|
@@ -341,14 +326,21 @@ function schemaProperties(operation) {
|
|
|
341
326
|
required: schema.required?.includes(key) === true,
|
|
342
327
|
}));
|
|
343
328
|
}
|
|
344
|
-
function OperationFields({ operation, }) {
|
|
329
|
+
function OperationFields({ operation, variant, }) {
|
|
345
330
|
return (_jsx(_Fragment, { children: schemaProperties(operation).map(({ key, property, required, ui }) => {
|
|
346
|
-
const rules =
|
|
347
|
-
? [{ required: true, message: `请填写${property.title || key}` }]
|
|
348
|
-
:
|
|
331
|
+
const rules = [
|
|
332
|
+
...(required ? [{ required: true, message: `请填写${property.title || key}` }] : []),
|
|
333
|
+
...(property.type === 'array' ? [{ validator: async (_rule, value) => {
|
|
334
|
+
if (value == null && !required)
|
|
335
|
+
return;
|
|
336
|
+
if (!Array.isArray(value) || value.length < (property.minItems ?? 0) || value.length > (property.maxItems ?? 200)) {
|
|
337
|
+
throw new Error(`请选择 ${property.minItems ?? 0} 至 ${property.maxItems ?? 200} 位人员`);
|
|
338
|
+
}
|
|
339
|
+
} }] : []),
|
|
340
|
+
];
|
|
349
341
|
let control = _jsx(Input, { placeholder: ui.placeholder });
|
|
350
342
|
if (ui.component === 'user_select')
|
|
351
|
-
control = _jsx(
|
|
343
|
+
control = _jsx(WorkflowMemberPicker, { variant: variant, multiple: property.type === 'array' || ui.mode === 'multiple', placeholder: ui.placeholder || `请选择${property.title || '成员'}` });
|
|
352
344
|
else if (property.enum) {
|
|
353
345
|
control = (_jsx(Select, { options: property.enum.map((value, index) => ({
|
|
354
346
|
label: property.enumNames?.[index] || value,
|
|
@@ -372,9 +364,9 @@ function OperationDialog({ operation, submitting, variant, onCancel, onSubmit, }
|
|
|
372
364
|
if (!operation)
|
|
373
365
|
return null;
|
|
374
366
|
const ui = operation.uiSchema;
|
|
375
|
-
const formNode = (_jsxs(Form, { form: form, layout: "vertical", onFinish: onSubmit, children: [ui.confirmation?.description && (_jsx(Alert, { className: "oxa-workflow-operation-alert", description: ui.confirmation.description, showIcon: true, type: operation.emphasis === 'danger' ? 'warning' : 'info' })), _jsx(OperationFields, { operation: operation })] }));
|
|
367
|
+
const formNode = (_jsxs(Form, { form: form, layout: "vertical", onFinish: onSubmit, children: [ui.confirmation?.description && (_jsx(Alert, { className: "oxa-workflow-operation-alert", description: ui.confirmation.description, showIcon: true, type: operation.emphasis === 'danger' ? 'warning' : 'info' })), _jsx(OperationFields, { operation: operation, variant: variant })] }));
|
|
376
368
|
if (variant === 'mobile') {
|
|
377
|
-
return (_jsx(Drawer, { extra: _jsx(Button, { loading: submitting, onClick: () => form.submit(), type: "primary", children: ui.confirmText || `确认${operation.label}` }), onClose: onCancel, open: true, placement: "bottom", size: "
|
|
369
|
+
return (_jsx(Drawer, { extra: _jsx(Button, { loading: submitting, onClick: () => form.submit(), type: "primary", children: ui.confirmText || `确认${operation.label}` }), rootClassName: "oxa-workflow-operation-drawer", styles: { body: { overflowY: 'auto', minHeight: 0 } }, keyboard: !submitting, mask: { closable: !submitting }, closable: !submitting, onClose: submitting ? undefined : onCancel, open: true, placement: "bottom", size: "min(640px, 92dvh)", title: operation.label, children: formNode }));
|
|
378
370
|
}
|
|
379
371
|
return (_jsx(Modal, { cancelText: "\u53D6\u6D88", confirmLoading: submitting, okText: ui.confirmText || `确认${operation.label}`, onCancel: onCancel, onOk: () => form.submit(), open: true, title: operation.label, children: formNode }));
|
|
380
372
|
}
|
|
@@ -722,20 +714,40 @@ export function WorkflowSummarySection({ surface }) {
|
|
|
722
714
|
};
|
|
723
715
|
return (_jsxs("div", { className: "oxa-workflow-summary-metadata", children: [_jsxs("span", { children: [_jsx(Typography.Text, { type: "secondary", children: "\u7533\u8BF7\u4EBA" }), _jsxs("span", { className: "oxa-workflow-applicant", children: [_jsx(PlatformAvatar, { avatarUrl: initiator.avatarUrl, size: 32 }), _jsxs("span", { children: [_jsx("strong", { children: initiator.displayName }), initiator.departmentDisplayName && (_jsx("small", { children: initiator.departmentDisplayName }))] })] })] }), _jsxs("span", { children: [_jsx(Typography.Text, { type: "secondary", children: "\u63D0\u4EA4\u65F6\u95F4" }), formatTime(summary.submittedAt)] }), summary.businessNumber && (_jsxs("span", { children: [_jsx(Typography.Text, { type: "secondary", children: "\u4E1A\u52A1\u7F16\u53F7" }), summary.businessNumber] }))] }));
|
|
724
716
|
}
|
|
725
|
-
|
|
717
|
+
function StandardWorkflowDetailRenderer({ surface, timeline, warning, operations, variant, onClose, onEdit, drawer, drawerState, newPageHref, editing, busy, }) {
|
|
718
|
+
const navigate = useNavigate();
|
|
719
|
+
const [tab, setTab] = useState('application');
|
|
726
720
|
const instance = surfaceInstance(surface);
|
|
727
|
-
const
|
|
721
|
+
const business = surfaceBusinessDetail(surface);
|
|
728
722
|
const summary = surface.presentation.summary;
|
|
729
|
-
|
|
723
|
+
const titleField = workflowDetailGroups(business).flatMap(group => group.fields).find(field => field.type === 'text.short');
|
|
724
|
+
const title = titleField && business.record[titleField.key] ? String(business.record[titleField.key]) : summary.title;
|
|
725
|
+
const activeNode = timeline?.display?.entries.find(entry => entry.status === 'active');
|
|
726
|
+
const people = activeNode?.people.map(person => person.displayName).filter(Boolean).join('、');
|
|
727
|
+
const statusTone = workflowStatus(instance.status).color;
|
|
728
|
+
const bannerTone = statusTone === 'error' ? 'error' : 'active';
|
|
729
|
+
const edit = workflowHasEnded(instance) ? onEdit : undefined;
|
|
730
|
+
const hasActions = standardWorkflowOperations(surface).length > 0;
|
|
731
|
+
const loadAudit = useCallback(() => loadWorkflowDataAudit(instance.id), [instance.id]);
|
|
732
|
+
const back = onClose || (() => navigate(variant === 'mobile' ? '/m/work-center' : '/work-center'));
|
|
733
|
+
return _jsxs(RecordDetailFrame, { variant: variant, title: "\u7533\u8BF7\u8BE6\u60C5", heading: title, status: _jsx(StatusTag, { status: instance.status }), metadata: [summary.initiator?.displayName || summary.initiatorDisplayName, summary.initiator?.departmentDisplayName || summary.departmentDisplayName,
|
|
734
|
+
summary.submittedAt ? `${detailTime(summary.submittedAt)} 创建` : ''].filter(Boolean).join(' · '), updatedAt: business.record.updated_at || instance.completedAt || instance.startedAt, onClose: back, onEdit: edit, editing: editing, busy: busy, drawer: drawer, drawerState: drawerState, newPageHref: newPageHref, footer: hasActions || edit ? _jsxs(_Fragment, { children: [operations, edit && _jsx(Button, { onClick: edit, children: "\u7F16\u8F91" })] }) : null, children: [warning && _jsx(Alert, { description: warning, showIcon: true, type: "warning" }), !workflowHasEnded(instance) && activeNode && _jsxs("div", { className: `oxa-workflow-current-node is-${bannerTone}`, role: "status", children: [_jsxs("span", { children: [_jsx(ClockCircleOutlined, {}), "\u5F53\u524D\u8282\u70B9\uFF1A", activeNode.title] }), people && _jsxs("span", { children: ["\u7B49\u5F85", people, "\u5904\u7406"] })] }), _jsx(Tabs, { activeKey: tab, onChange: setTab, items: [
|
|
735
|
+
{ key: 'application', label: '申请内容', children: _jsx(WorkflowBusinessDetailSections, { surface: surface, variant: variant }) },
|
|
736
|
+
{ key: 'history', label: '审批历史', children: _jsx(WorkflowTimelineSection, { timeline: timeline }) },
|
|
737
|
+
{ key: 'changes', label: '变更记录', children: tab === 'changes' && business.surface && business.resourceCode && business.recordId
|
|
738
|
+
? _jsx(RecordChangeHistory, { resourceCode: business.resourceCode, recordId: business.recordId, surface: business.surface, readable: () => true, loadPage: loadAudit })
|
|
739
|
+
: _jsx(Empty, { description: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) },
|
|
740
|
+
] })] });
|
|
730
741
|
}
|
|
731
|
-
export function
|
|
732
|
-
|
|
733
|
-
const task = surfaceTask(surface);
|
|
734
|
-
const summary = surface.presentation.summary;
|
|
735
|
-
return (_jsxs("div", { className: "oxa-workflow-detail-mobile-native", children: [_jsxs("main", { children: [_jsxs(Card, { className: "oxa-workflow-summary-card-mobile", children: [_jsxs("div", { className: "oxa-workflow-summary-title-mobile", children: [_jsx(Typography.Title, { level: 3, children: summary.title }), _jsx(StatusTag, { status: task?.status || instance.status })] }), _jsx(WorkflowSummarySection, { surface: surface })] }), warning && _jsx(Alert, { description: warning, showIcon: true, type: "warning" }), _jsx(WorkflowBusinessDetailSections, { surface: surface, variant: "mobile" }), _jsx(WorkflowTimelineSection, { timeline: timeline })] }), operations] }));
|
|
742
|
+
export function DesktopWorkflowDetailRenderer(props) {
|
|
743
|
+
return _jsx(StandardWorkflowDetailRenderer, { ...props, variant: "desktop" });
|
|
736
744
|
}
|
|
737
|
-
export function
|
|
738
|
-
|
|
745
|
+
export function MobileWorkflowDetailRenderer(props) {
|
|
746
|
+
return _jsx(StandardWorkflowDetailRenderer, { ...props, variant: "mobile" });
|
|
747
|
+
}
|
|
748
|
+
export function useWorkflowDetail({ kind, id, resourceCode }) {
|
|
749
|
+
const { identity } = useRuntime();
|
|
750
|
+
const detailKey = `${identity.identityScope}:${identity.environment.id}:${kind}:${resourceCode || ''}:${id}`;
|
|
739
751
|
const [state, setState] = useState({ detailKey, detail: null, error: '' });
|
|
740
752
|
const [loading, setLoading] = useState(true);
|
|
741
753
|
const requestSequence = useRef(0);
|
|
@@ -748,7 +760,7 @@ export function useWorkflowDetail({ kind, id, }) {
|
|
|
748
760
|
? { ...current, error: '' }
|
|
749
761
|
: { detailKey, detail: null, error: '' });
|
|
750
762
|
try {
|
|
751
|
-
const detail = kind === 'task'
|
|
763
|
+
const detail = kind === 'record' ? await loadWorkflowRecordDetail(resourceCode, id) : kind === 'task'
|
|
752
764
|
? await loadWorkflowTaskDetail(id)
|
|
753
765
|
: await loadWorkflowInstanceDetail(id);
|
|
754
766
|
if (!isCurrent())
|
|
@@ -777,7 +789,7 @@ export function useWorkflowDetail({ kind, id, }) {
|
|
|
777
789
|
if (isCurrent())
|
|
778
790
|
setLoading(false);
|
|
779
791
|
}
|
|
780
|
-
}, [detailKey, id, kind]);
|
|
792
|
+
}, [detailKey, id, kind, resourceCode]);
|
|
781
793
|
useEffect(() => {
|
|
782
794
|
activeRef.current = true;
|
|
783
795
|
void refresh();
|
|
@@ -800,128 +812,90 @@ export function useWorkflowDetail({ kind, id, }) {
|
|
|
800
812
|
refresh,
|
|
801
813
|
};
|
|
802
814
|
}
|
|
803
|
-
function WorkflowDetailPage({ kind, variant, }) {
|
|
815
|
+
function WorkflowDetailPage({ kind, variant, resourceCode, recordId, onDismiss, drawerState }) {
|
|
804
816
|
const params = useParams();
|
|
805
|
-
const id = String(kind === 'task' ? params.taskId || '' : params.instanceId || '');
|
|
817
|
+
const id = recordId || String(kind === 'task' ? params.taskId || '' : kind === 'record' ? params.id || '' : params.instanceId || '');
|
|
806
818
|
const navigate = useNavigate();
|
|
807
|
-
const {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
if (kind === 'task' && result.advanced === true) {
|
|
826
|
-
const instanceId = String(result.instanceId || '').trim();
|
|
827
|
-
if (!instanceId)
|
|
828
|
-
return;
|
|
829
|
-
const nextDetail = await loadWorkflowInstanceDetail(instanceId);
|
|
830
|
-
navigate(variant === 'mobile'
|
|
831
|
-
? nextDetail.surface.detailNavigation.mobilePath
|
|
832
|
-
: nextDetail.surface.detailNavigation.desktopPath, { replace: true });
|
|
819
|
+
const { identity } = useRuntime();
|
|
820
|
+
const [editing, setEditing] = useState(false);
|
|
821
|
+
const [editBusy, setEditBusy] = useState(false);
|
|
822
|
+
const { detail, surface, timeline, loading, error, refresh } = useWorkflowDetail({ kind, id, resourceCode });
|
|
823
|
+
const instance = surface ? surfaceInstance(surface) : null;
|
|
824
|
+
const task = surface ? surfaceTask(surface) : null;
|
|
825
|
+
const business = surface ? surfaceBusinessDetail(surface) : null;
|
|
826
|
+
const detailPath = surface ? (variant === 'mobile' ? surface.detailNavigation.mobilePath : surface.detailNavigation.desktopPath) : '';
|
|
827
|
+
const newPageHref = useHref(detailPath || '.');
|
|
828
|
+
const close = onDismiss || (() => navigate(detail ? variant === 'mobile' ? detail.navigationContext.mobileReturnPath : detail.navigationContext.desktopReturnPath : variant === 'mobile' ? '/m/work-center' : '/work-center'));
|
|
829
|
+
if (!surface || !detail || !instance)
|
|
830
|
+
return _jsx(RecordDetailFrame, { variant: variant, title: "\u7533\u8BF7\u8BE6\u60C5", drawer: Boolean(onDismiss), drawerState: drawerState, onClose: close, children: loading ? _jsx(Spin, {}) : _jsx(Result, { status: "error", title: "\u6D41\u7A0B\u8BE6\u60C5\u52A0\u8F7D\u5931\u8D25", subTitle: error || '流程不存在', extra: _jsx(Button, { onClick: () => void refresh(), children: "\u91CD\u8BD5" }) }) });
|
|
831
|
+
if (surface.detailNavigation.custom)
|
|
832
|
+
return _jsx(Navigate, { replace: true, to: detailPath });
|
|
833
|
+
const onCommandCompleted = async (result) => {
|
|
834
|
+
if (kind === 'task' && result.advanced === true) {
|
|
835
|
+
const nextId = String(result.instanceId || '').trim();
|
|
836
|
+
if (!nextId)
|
|
833
837
|
return;
|
|
834
|
-
|
|
838
|
+
const next = await loadWorkflowInstanceDetail(nextId);
|
|
839
|
+
navigate(variant === 'mobile' ? next.surface.detailNavigation.mobilePath : next.surface.detailNavigation.desktopPath, { replace: true });
|
|
840
|
+
}
|
|
841
|
+
else
|
|
835
842
|
await refresh();
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
operations,
|
|
843
|
-
};
|
|
844
|
-
content = variant === 'desktop' ? (_jsx(DesktopWorkflowDetailRenderer, { ...rendererProps })) : (_jsx(MobileWorkflowDetailRenderer, { ...rendererProps }));
|
|
845
|
-
}
|
|
846
|
-
return variant === 'desktop' ? (_jsx("div", { className: "oxa-workflow-desktop-page", children: content })) : (_jsx("div", { className: "oxa-workflow-mobile-page oxa-workflow-mobile-detail-page", children: content }));
|
|
843
|
+
};
|
|
844
|
+
const operations = task
|
|
845
|
+
? _jsx(WorkflowTaskOperationsPanel, { onCommandCompleted: onCommandCompleted, surface: surface, taskId: task.id, variant: variant }, task.id)
|
|
846
|
+
: _jsx(WorkflowInstanceOperationsPanel, { instanceId: instance.id, onCommandCompleted: onCommandCompleted, surface: surface, variant: variant });
|
|
847
|
+
return _jsx(StandardWorkflowDetailRenderer, { surface: surface, timeline: timeline, warning: error, operations: operations, variant: variant, drawer: Boolean(onDismiss), drawerState: drawerState, newPageHref: newPageHref, onClose: editing ? () => { if (!editBusy)
|
|
848
|
+
setEditing(false); } : close, busy: editBusy, editing: editing && business?.resourceCode && business.recordId ? _jsx(WorkflowRecordEditor, { resourceCode: business.resourceCode, recordId: business.recordId, variant: variant, presentation: "embedded", onBusyChange: setEditBusy, onDismiss: () => setEditing(false), onSaved: () => { setEditing(false); void refresh(); } }) : undefined, onEdit: workflowHasEnded(instance) && identity.isAppSuperAdmin && (business?.status === 'ready' || business?.status === 'stale') ? () => setEditing(true) : undefined });
|
|
847
849
|
}
|
|
850
|
+
export function WorkflowRecordDetailPage({ variant = 'desktop', ...props }) { return _jsx(WorkflowDetailPage, { ...props, variant: variant, kind: "record" }); }
|
|
848
851
|
export function WorkflowTaskPage({ variant = 'desktop', }) {
|
|
849
852
|
return _jsx(WorkflowDetailPage, { kind: "task", variant: variant });
|
|
850
853
|
}
|
|
851
854
|
export function WorkflowInstancePage({ variant = 'desktop', }) {
|
|
852
855
|
return _jsx(WorkflowDetailPage, { kind: "instance", variant: variant });
|
|
853
856
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
{ label: '我已处理', value: 'completed' },
|
|
860
|
-
], value: status }), loading && !page ? (_jsx("div", { className: "oxa-page-loading", children: _jsx(Spin, {}) })) : null, _jsx("div", { className: "oxa-workflow-mobile-tasks", children: (page?.items || []).map((task) => (_jsxs(Card, { hoverable: true, onClick: () => navigate(task.detailNavigation.mobilePath), children: [_jsxs("div", { className: "oxa-workflow-mobile-task-heading", children: [_jsx("strong", { children: task.title }), _jsx(StatusTag, { status: task.status })] }), _jsx(Typography.Text, { children: task.businessKey }), _jsxs(Typography.Text, { type: "secondary", children: [task.workflowCode, " \u00B7 ", formatTime(task.updatedAt)] })] }, task.id))) }), !loading && !page?.items.length && _jsx(Empty, { description: "\u6682\u65E0\u6D41\u7A0B\u4EFB\u52A1" }), _jsxs("div", { className: "oxa-mobile-pagination", children: [_jsx(Button, { disabled: current <= 1, onClick: () => onPage(current - 1), children: "\u4E0A\u4E00\u9875" }), _jsxs(Typography.Text, { children: ["\u7B2C ", current, " \u9875"] }), _jsx(Button, { disabled: current * (page?.limit || 20) >= (page?.total || 0), onClick: () => onPage(current + 1), children: "\u4E0B\u4E00\u9875" })] })] }));
|
|
861
|
-
}
|
|
862
|
-
export function WorkflowWorkCenterPage({ variant = 'desktop', }) {
|
|
857
|
+
const WORK_VIEWS = [
|
|
858
|
+
{ value: 'created', label: '我创建的' }, { value: 'pending', label: '待我审批' },
|
|
859
|
+
{ value: 'handled', label: '我已处理' }, { value: 'cc', label: '抄送我的' },
|
|
860
|
+
];
|
|
861
|
+
export function WorkflowWorkCenterPage({ variant = 'desktop' }) {
|
|
863
862
|
const navigate = useNavigate();
|
|
864
|
-
const [
|
|
863
|
+
const [view, setView] = useState('pending');
|
|
865
864
|
const [pageNumber, setPageNumber] = useState(1);
|
|
866
865
|
const [pageSize, setPageSize] = useState(20);
|
|
867
866
|
const [page, setPage] = useState(null);
|
|
868
867
|
const [loading, setLoading] = useState(true);
|
|
869
868
|
const [error, setError] = useState('');
|
|
870
|
-
const
|
|
869
|
+
const [attempt, setAttempt] = useState(0);
|
|
870
|
+
useEffect(() => {
|
|
871
|
+
let active = true;
|
|
871
872
|
setLoading(true);
|
|
872
873
|
setError('');
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
setLoading(false);
|
|
885
|
-
}
|
|
886
|
-
}, [pageNumber, pageSize, status]);
|
|
887
|
-
useEffect(() => {
|
|
888
|
-
void load();
|
|
889
|
-
}, [load]);
|
|
890
|
-
const changeStatus = (value) => {
|
|
891
|
-
setStatus(value);
|
|
892
|
-
setPageNumber(1);
|
|
893
|
-
};
|
|
894
|
-
if (variant === 'mobile') {
|
|
895
|
-
return (_jsxs(_Fragment, { children: [error && _jsx(Alert, { description: error, showIcon: true, type: "error" }), _jsx(WorkCenterMobile, { loading: loading, onPage: setPageNumber, onStatus: changeStatus, page: page, status: status })] }));
|
|
896
|
-
}
|
|
874
|
+
setPage(null);
|
|
875
|
+
void loadWorkflowWorkCenter({ view, limit: pageSize, offset: (pageNumber - 1) * pageSize })
|
|
876
|
+
.then(result => { if (active)
|
|
877
|
+
setPage(result); })
|
|
878
|
+
.catch(reason => { if (active)
|
|
879
|
+
setError(errorMessage(reason, '待办加载失败')); })
|
|
880
|
+
.finally(() => { if (active)
|
|
881
|
+
setLoading(false); });
|
|
882
|
+
return () => { active = false; };
|
|
883
|
+
}, [attempt, pageNumber, pageSize, view]);
|
|
884
|
+
const open = (item) => navigate(variant === 'mobile' ? item.detailNavigation.mobilePath : item.detailNavigation.desktopPath);
|
|
897
885
|
const columns = [
|
|
898
|
-
{
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
},
|
|
903
|
-
{ title: '业务标识', dataIndex: 'businessKey' },
|
|
904
|
-
{ title: '流程', dataIndex: 'workflowCode' },
|
|
905
|
-
{
|
|
906
|
-
title: '状态',
|
|
907
|
-
dataIndex: 'status',
|
|
908
|
-
render: (value) => _jsx(StatusTag, { status: String(value) }),
|
|
909
|
-
},
|
|
910
|
-
{ title: '更新时间', dataIndex: 'updatedAt', render: formatTime },
|
|
886
|
+
{ title: '申请事项', key: 'title', render: (_, item) => _jsx(Button, { type: "link", className: "oxa-work-item-link", onClick: () => open(item), children: item.title }) },
|
|
887
|
+
{ title: '流程', dataIndex: 'workflowTitle', render: value => value || '—' },
|
|
888
|
+
{ title: '当前节点', dataIndex: 'taskTitle', render: value => value || '—' },
|
|
889
|
+
{ title: '状态', dataIndex: 'instanceStatus', render: (value, item) => _jsx(StatusTag, { status: String(value || item.status) }) },
|
|
890
|
+
{ title: view === 'created' ? '创建时间' : view === 'cc' ? '抄送时间' : '更新时间', dataIndex: 'occurredAt', render: formatTime },
|
|
911
891
|
];
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
showSizeChanger: true,
|
|
920
|
-
onChange: (next, size) => {
|
|
921
|
-
setPageNumber(next);
|
|
922
|
-
setPageSize(size);
|
|
923
|
-
},
|
|
924
|
-
}, rowKey: "id" })] }) }));
|
|
892
|
+
const content = _jsxs("main", { className: `oxa-application-work-center oxa-application-work-center-${variant}`, children: [_jsxs("header", { children: [_jsx("h1", { children: "\u5F85\u529E\u4E2D\u5FC3" }), _jsx(Button, { icon: _jsx(ReloadOutlined, {}), loading: loading, onClick: () => setAttempt(value => value + 1), children: "\u5237\u65B0" })] }), _jsx(Tabs, { activeKey: view, onChange: value => { setView(value); setPageNumber(1); }, items: WORK_VIEWS.map(item => ({
|
|
893
|
+
key: item.value, label: _jsxs("span", { children: [item.label, page?.counts && _jsx("small", { className: "oxa-work-count", children: page.counts[item.value] })] }),
|
|
894
|
+
})) }), error && _jsx(Alert, { title: "\u5F85\u529E\u52A0\u8F7D\u5931\u8D25", description: error, type: "error", showIcon: true, action: _jsx(Button, { onClick: () => setAttempt(value => value + 1), children: "\u91CD\u8BD5" }) }), variant === 'desktop' ? _jsx(Table, { rowKey: "id", columns: columns, dataSource: page?.items || [], loading: loading, pagination: {
|
|
895
|
+
current: pageNumber, pageSize, total: page?.total || 0, showSizeChanger: true,
|
|
896
|
+
onChange: (number, size) => { setPageNumber(number); setPageSize(size); },
|
|
897
|
+
} }) : _jsxs(_Fragment, { children: [loading && _jsx(Spin, {}), _jsx("div", { className: "oxa-work-center-mobile-list", children: page?.items.map(item => _jsxs("button", { type: "button", className: "oxa-work-center-item", onClick: () => open(item), children: [_jsxs("div", { children: [_jsx("strong", { children: item.title }), _jsx(StatusTag, { status: item.instanceStatus || item.status })] }), _jsx("p", { children: [item.workflowTitle, item.taskTitle].filter(Boolean).join(' · ') }), _jsx("time", { children: formatTime(item.occurredAt) })] }, item.id)) }), !loading && !page?.items.length && !error && _jsx(Empty, { description: "\u6682\u65E0\u76F8\u5173\u7533\u8BF7" }), Boolean(page && page.total > pageSize) && _jsxs("div", { className: "oxa-mobile-pagination", children: [_jsx(Button, { disabled: pageNumber <= 1, onClick: () => setPageNumber(value => value - 1), children: "\u4E0A\u4E00\u9875" }), _jsxs("span", { children: ["\u7B2C ", pageNumber, " \u9875"] }), _jsx(Button, { disabled: pageNumber * pageSize >= (page?.total || 0), onClick: () => setPageNumber(value => value + 1), children: "\u4E0B\u4E00\u9875" })] })] })] });
|
|
898
|
+
return content;
|
|
925
899
|
}
|
|
926
900
|
function RequirementFields({ requirements, }) {
|
|
927
901
|
return (_jsx(_Fragment, { children: requirements.map((requirement) => (_jsx(Form.Item, { label: requirement.title, name: requirement.id, rules: requirement.required
|
|
@@ -1043,20 +1017,7 @@ async function workflowContextPrefillValue(field, rawValue, resources) {
|
|
|
1043
1017
|
...(Object.keys(snapshot).length ? { snapshot } : {}),
|
|
1044
1018
|
};
|
|
1045
1019
|
}
|
|
1046
|
-
|
|
1047
|
-
const parsed = Number(value);
|
|
1048
|
-
if (!Number.isFinite(parsed)) {
|
|
1049
|
-
throw new Error('OPENXIANGDA_WORKFLOW_LAUNCH_CONTEXT_VALUE_INVALID');
|
|
1050
|
-
}
|
|
1051
|
-
return parsed;
|
|
1052
|
-
}
|
|
1053
|
-
if (field.type === 'boolean') {
|
|
1054
|
-
if (!['true', 'false'].includes(value)) {
|
|
1055
|
-
throw new Error('OPENXIANGDA_WORKFLOW_LAUNCH_CONTEXT_VALUE_INVALID');
|
|
1056
|
-
}
|
|
1057
|
-
return value === 'true';
|
|
1058
|
-
}
|
|
1059
|
-
return value;
|
|
1020
|
+
return workflowContextScalarValue(field, value);
|
|
1060
1021
|
}
|
|
1061
1022
|
export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWorkflowCode, variant = 'desktop', onDismiss, onCompleted, } = {}) {
|
|
1062
1023
|
const { workflowCode: routeWorkflowCode = '' } = useParams();
|
|
@@ -1282,16 +1243,29 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1282
1243
|
}
|
|
1283
1244
|
let active = true;
|
|
1284
1245
|
let timer;
|
|
1246
|
+
const startedAt = Date.now();
|
|
1247
|
+
let failures = 0;
|
|
1248
|
+
let controller;
|
|
1285
1249
|
const refresh = async () => {
|
|
1250
|
+
if (!active)
|
|
1251
|
+
return;
|
|
1252
|
+
if (Date.now() - startedAt >= 60_000) {
|
|
1253
|
+
setProcessError('申请已提交,处理尚未结束;可稍后刷新状态,无需重复提交');
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
controller = new AbortController();
|
|
1257
|
+
const timeout = setTimeout(() => controller?.abort(new DOMException('状态读取超时', 'TimeoutError')), Math.min(10_000, 60_000 - (Date.now() - startedAt)));
|
|
1286
1258
|
try {
|
|
1287
|
-
const next = await loadProcessCommandSurface(commandId);
|
|
1259
|
+
const next = await loadProcessCommandSurface(commandId, controller.signal);
|
|
1288
1260
|
if (!active)
|
|
1289
1261
|
return;
|
|
1290
|
-
if (next.command.
|
|
1262
|
+
if (next.command.id !== commandId ||
|
|
1263
|
+
next.command.environmentKey !== identity.environment.key ||
|
|
1291
1264
|
next.command.workflowCode !== workflowCode ||
|
|
1292
1265
|
next.command.subject.resourceCode !== definition?.subject.resourceCode) {
|
|
1293
1266
|
throw new Error('OPENXIANGDA_PROCESS_COMMAND_SCOPE_MISMATCH');
|
|
1294
1267
|
}
|
|
1268
|
+
failures = 0;
|
|
1295
1269
|
setProcessSurface(next);
|
|
1296
1270
|
setProcessError(null);
|
|
1297
1271
|
if (next.command.status === 'started' && next.command.workflowInstanceId) {
|
|
@@ -1314,13 +1288,21 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1314
1288
|
}
|
|
1315
1289
|
}
|
|
1316
1290
|
catch (error) {
|
|
1317
|
-
if (active)
|
|
1318
|
-
|
|
1291
|
+
if (!active)
|
|
1292
|
+
return;
|
|
1293
|
+
const delay = processStatusReadRetryDelay(error, ++failures, Date.now() - startedAt);
|
|
1294
|
+
setProcessError(delay === null ? '申请已提交,暂时无法读取处理状态;请稍后刷新,无需重复提交' : '申请已提交,正在重新读取处理状态,请勿重复提交');
|
|
1295
|
+
if (delay !== null)
|
|
1296
|
+
timer = setTimeout(() => void refresh(), delay);
|
|
1297
|
+
}
|
|
1298
|
+
finally {
|
|
1299
|
+
clearTimeout(timeout);
|
|
1319
1300
|
}
|
|
1320
1301
|
};
|
|
1321
1302
|
void refresh();
|
|
1322
1303
|
return () => {
|
|
1323
1304
|
active = false;
|
|
1305
|
+
controller?.abort();
|
|
1324
1306
|
if (timer)
|
|
1325
1307
|
clearTimeout(timer);
|
|
1326
1308
|
};
|
|
@@ -1357,7 +1339,7 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1357
1339
|
const drawerBusy = loading || Boolean(commandId && (!processSurface || ['accepted', 'resolving', 'ready', 'starting', 'retry_wait'].includes(processSurface.command.status)) && !processError);
|
|
1358
1340
|
const dismissDrawer = () => { if (!submitInFlight.current && !drawerBusy)
|
|
1359
1341
|
onDismiss?.(); };
|
|
1360
|
-
const frame = (content) => onDismiss ? _jsx(Drawer, { open: true, title: definition?.title || '新增流程申请', closable: false, rootClassName: "oxa-resource-drawer oxa-workflow-launch-drawer", size: fullScreen || variant === 'mobile' ? '100vw' : 'min(
|
|
1342
|
+
const frame = (content) => onDismiss ? _jsx(Drawer, { open: true, title: definition?.title || '新增流程申请', closable: false, rootClassName: "oxa-resource-drawer oxa-workflow-launch-drawer", size: fullScreen || variant === 'mobile' ? '100vw' : 'min(850px, calc(100vw - 48px))', styles: { body: { padding: 0, overflow: 'auto' } }, keyboard: !drawerBusy, mask: { closable: !drawerBusy }, onClose: dismissDrawer, extra: _jsxs(Space, { size: 4, children: [_jsx(Button, { type: "text", "aria-label": fullScreen ? '退出全屏' : '全屏', icon: fullScreen ? _jsx(CompressOutlined, {}) : _jsx(ExpandOutlined, {}), onClick: () => setFullScreen(value => !value) }), launchPagePath.current && _jsx(Tooltip, { title: commandId ? '新开页面继续查看当前申请' : '新开页面(未提交内容不会带入)', children: _jsx(Button, { type: "text", "aria-label": "\u65B0\u5F00\u9875\u9762", icon: _jsx(ExportOutlined, {}), href: newPageHref, target: "_blank", rel: "noopener noreferrer", disabled: loading }) }), _jsx(Button, { type: "text", "aria-label": "\u5173\u95ED", disabled: drawerBusy, icon: _jsx(CloseOutlined, {}), onClick: dismissDrawer })] }), children: content }) : variant === 'desktop' ? (_jsx("div", { className: "oxa-workflow-desktop-page oxa-workflow-submission-standalone-page", children: content })) : content;
|
|
1361
1343
|
if (!definition)
|
|
1362
1344
|
return frame(_jsx(Result, { status: "404", title: "\u672A\u58F0\u660E\u8BE5\u5DE5\u4F5C\u6D41" }));
|
|
1363
1345
|
if (definition.launch.mode !== 'standalone' &&
|
|
@@ -1564,6 +1546,7 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1564
1546
|
const uploadOperationCode = namedIntent?.operationCode || definition.processOperationCode;
|
|
1565
1547
|
const fieldRenderers = uploadOperationCode
|
|
1566
1548
|
? {
|
|
1549
|
+
...(namedIntent ? { referenceLaunch: { workflowCode: definition.code, operationCode: namedIntent.operationCode } } : {}),
|
|
1567
1550
|
upload: async (field, file) => await uploadOperationManagedFile({
|
|
1568
1551
|
operationCode: uploadOperationCode,
|
|
1569
1552
|
resourceCode: subjectDefinition.code,
|
|
@@ -1622,16 +1605,16 @@ function ProcessCommandPanel({ form, surface, error, loading, onAnswer, onRetry,
|
|
|
1622
1605
|
}
|
|
1623
1606
|
return (_jsxs("div", { className: "oxa-workflow-submission-followup", children: [command.status === 'awaiting_input' ? (_jsx(Card, { title: "\u8FD8\u9700\u8981\u8865\u5145\u4E00\u4E9B\u4FE1\u606F", children: _jsxs(Form, { form: form, layout: "vertical", onFinish: values => void onAnswer(values), children: [_jsx(RequirementFields, { requirements: surface.requirements }), _jsx(Button, { htmlType: "submit", loading: loading, type: "primary", children: "\u63D0\u4EA4\u8865\u5145\u4FE1\u606F" })] }) })) : null, ['cancelled', 'dead_letter'].includes(command.status) ? (_jsx(Result, { extra: surface.resume.retry ? (_jsx(Button, { loading: loading, onClick: () => void onRetry(), type: "primary", children: "\u91CD\u65B0\u5C1D\u8BD5" })) : null, status: "error", subTitle: "\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF1B\u5982\u95EE\u9898\u6301\u7EED\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002", title: "\u7533\u8BF7\u6682\u672A\u53D1\u8D77\u6210\u529F" })) : null] }));
|
|
1624
1607
|
}
|
|
1625
|
-
function
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
}
|
|
1635
|
-
return (_jsx(Spin, { description: "\u6B63\u5728\u63D0\u4EA4\u7533\u8BF7\uFF0C\u8BF7\u7A0D\u5019\u2026", spinning: props.processing, children: _jsxs("div", { className: "oxa-mobile-page oxa-workflow-submission-mobile", children: [!props.embedded && _jsx(Typography.Title, { level: 3, children: props.title }), props.launchControls, _jsxs(Form, { className: "oxa-mobile-form", form: props.subjectForm, layout: "vertical", onFinish: values => void props.onSubmit(values), children: [props.fields.map(field => (_jsx(MobileSurfaceFieldControl, { disabled: props.loading || props.submitted, field: field, operation: props.mutationMode === 'update' ? 'update' : 'create', recordId: props.recordId, renderers: props.fieldRenderers, resourceCode: props.subjectDefinition.code }, field.key))), _jsx(Button, { block: true, disabled: props.submitted, htmlType: "submit", loading: props.loading || props.processing, type: "primary", children: "\u63D0\u4EA4\u5BA1\u6279" })] }), _jsx(ProcessCommandPanel, { error: props.processError, form: props.requirementForm, loading: props.loading, onAnswer: props.onAnswer, onRetry: props.onRetry, onRefresh: props.onRefresh, surface: props.processSurface })] }) }));
|
|
1608
|
+
function StandardProcessSubmissionRenderer(props) {
|
|
1609
|
+
const groups = [...props.fields.reduce((groups, field) => {
|
|
1610
|
+
const section = field.section || 'default';
|
|
1611
|
+
groups.set(section, [...(groups.get(section) || []), field]);
|
|
1612
|
+
return groups;
|
|
1613
|
+
}, new Map())].map(([section, fields]) => ({ section, fields }));
|
|
1614
|
+
if (props.completion)
|
|
1615
|
+
return _jsx(Result, { status: "success", title: "\u63D0\u4EA4\u6210\u529F", extra: _jsx(Button, { onClick: props.onBack, children: "\u8FD4\u56DE" }) });
|
|
1616
|
+
return _jsxs("div", { className: props.variant === 'mobile' ? 'oxa-mobile-page oxa-mobile-entry oxa-workflow-submission-mobile' : 'oxa-workflow-entry', children: [!props.embedded && _jsxs("header", { className: props.variant === 'mobile' ? 'oxa-mobile-header' : 'oxa-workflow-entry-header', children: [_jsx(Button, { type: "text", "aria-label": "\u8FD4\u56DE", icon: _jsx(ArrowLeftOutlined, {}), disabled: props.processing, onClick: props.onBack }), _jsx("h3", { children: props.title }), _jsx("span", {})] }), _jsx(ResourceFormContent, { variant: props.variant, mode: props.mutationMode === 'update' ? 'edit' : 'create', resourceCode: props.subjectDefinition.code, recordId: props.recordId, groups: groups, form: props.subjectForm, busy: props.loading || props.submitted, pending: props.loading || props.processing, submitDisabled: props.submitted, submitLabel: "\u63D0\u4EA4\u5BA1\u6279", canWriteField: () => true, renderers: props.fieldRenderers, feedback: _jsxs(_Fragment, { children: [props.launchControls, props.processing && _jsx(Alert, { type: "info", showIcon: true, title: "\u6B63\u5728\u63D0\u4EA4\u7533\u8BF7\uFF0C\u8BF7\u7A0D\u5019\u2026" })] }), onSubmit: values => void props.onSubmit(values) }), _jsx(ProcessCommandPanel, { error: props.processError, form: props.requirementForm, loading: props.loading, onAnswer: props.onAnswer, onRetry: props.onRetry, onRefresh: props.onRefresh, surface: props.processSurface })] });
|
|
1636
1617
|
}
|
|
1618
|
+
function DesktopProcessSubmissionRenderer(props) { return _jsx(StandardProcessSubmissionRenderer, { ...props, variant: "desktop" }); }
|
|
1619
|
+
function MobileProcessSubmissionRenderer(props) { return _jsx(StandardProcessSubmissionRenderer, { ...props, variant: "mobile" }); }
|
|
1637
1620
|
//# sourceMappingURL=StandardWorkflowPages.js.map
|