openxiangda 2.0.0-alpha.99 → 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/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/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/RecordDetailFrame.js +1 -1
- package/dist/browser/components/resource/RecordDetailFrame.js.map +1 -1
- package/dist/browser/components/resource/SurfaceFields.d.ts +3 -2
- package/dist/browser/components/resource/SurfaceFields.d.ts.map +1 -1
- package/dist/browser/components/resource/SurfaceFields.js +14 -7
- 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.map +1 -1
- package/dist/browser/components/todo/ApplicationTodoCenterPage.js +1 -2
- package/dist/browser/components/todo/ApplicationTodoCenterPage.js.map +1 -1
- package/dist/browser/components/workflow/StandardWorkflowPages.d.ts.map +1 -1
- package/dist/browser/components/workflow/StandardWorkflowPages.js +54 -52
- package/dist/browser/components/workflow/StandardWorkflowPages.js.map +1 -1
- package/dist/browser/platform-client.d.ts +3 -2
- package/dist/browser/platform-client.d.ts.map +1 -1
- package/dist/browser/platform-client.js +69 -18
- package/dist/browser/platform-client.js.map +1 -1
- package/dist/browser/record-detail.css +3 -2
- 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/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 -285
- 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,17 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { ArrowLeftOutlined, ClockCircleOutlined,
|
|
2
|
+
import { ArrowLeftOutlined, ClockCircleOutlined, EllipsisOutlined, ReloadOutlined, CloseOutlined, ExpandOutlined, CompressOutlined, ExportOutlined, } from '@ant-design/icons';
|
|
3
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
14
|
import { SurfaceFieldValue, } from '../resource/SurfaceFields';
|
|
14
|
-
import { buildWorkflowNamedOperationInput, parseWorkflowNamedOperationResult, workflowLaunchContractJsonEqual, } from '../../workflow-launch';
|
|
15
|
+
import { workflowContextScalarValue, processStatusReadRetryDelay, buildWorkflowNamedOperationInput, parseWorkflowNamedOperationResult, workflowLaunchContractJsonEqual, } from '../../workflow-launch';
|
|
15
16
|
import { normalizeFormValues, normalizeRecordForForm, } from '../platform-fields/field-form-codec';
|
|
16
17
|
import { RecordDetailFrame, RecordDetailSections, detailTime } from '../resource/RecordDetailFrame';
|
|
17
18
|
import { RecordChangeHistory } from '../resource/RecordChangeHistory';
|
|
@@ -75,6 +76,9 @@ function workflowStatus(status) {
|
|
|
75
76
|
};
|
|
76
77
|
return states[status] || { label: status || '未知', color: 'default' };
|
|
77
78
|
}
|
|
79
|
+
function workflowHasEnded(instance) {
|
|
80
|
+
return ['completed', 'approved', 'rejected', 'withdrawn', 'terminated', 'cancelled', 'expired'].includes(instance.status);
|
|
81
|
+
}
|
|
78
82
|
function StatusTag({ status }) {
|
|
79
83
|
const state = workflowStatus(status);
|
|
80
84
|
return _jsx(Tag, { color: state.color, children: state.label });
|
|
@@ -302,28 +306,15 @@ export function WorkflowTimelineSection({ timeline, }) {
|
|
|
302
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));
|
|
303
307
|
}) })) : (_jsx(Empty, { description: "\u6682\u65E0\u6D41\u7A0B\u8F68\u8FF9", image: Empty.PRESENTED_IMAGE_SIMPLE })) }));
|
|
304
308
|
}
|
|
305
|
-
function
|
|
306
|
-
const [
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
.then((page) => {
|
|
315
|
-
if (current !== sequence.current)
|
|
316
|
-
return;
|
|
317
|
-
setOptions(page.items.map((item) => ({ label: item.label, value: item.id })));
|
|
318
|
-
})
|
|
319
|
-
.catch(() => { if (current === sequence.current)
|
|
320
|
-
setOptions([]); })
|
|
321
|
-
.finally(() => {
|
|
322
|
-
if (current === sequence.current)
|
|
323
|
-
setLoading(false);
|
|
324
|
-
});
|
|
325
|
-
};
|
|
326
|
-
return (_jsx(Select, { id: id, mode: multiple ? 'multiple' : undefined, maxCount: maxCount, filterOption: false, loading: loading, onChange: onChange, onSearch: search, options: options, placeholder: placeholder || '搜索并选择人员', 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
|
+
} });
|
|
327
318
|
}
|
|
328
319
|
function schemaProperties(operation) {
|
|
329
320
|
const schema = operation.inputSchema;
|
|
@@ -335,7 +326,7 @@ function schemaProperties(operation) {
|
|
|
335
326
|
required: schema.required?.includes(key) === true,
|
|
336
327
|
}));
|
|
337
328
|
}
|
|
338
|
-
function OperationFields({ operation, }) {
|
|
329
|
+
function OperationFields({ operation, variant, }) {
|
|
339
330
|
return (_jsx(_Fragment, { children: schemaProperties(operation).map(({ key, property, required, ui }) => {
|
|
340
331
|
const rules = [
|
|
341
332
|
...(required ? [{ required: true, message: `请填写${property.title || key}` }] : []),
|
|
@@ -349,7 +340,7 @@ function OperationFields({ operation, }) {
|
|
|
349
340
|
];
|
|
350
341
|
let control = _jsx(Input, { placeholder: ui.placeholder });
|
|
351
342
|
if (ui.component === 'user_select')
|
|
352
|
-
control = _jsx(
|
|
343
|
+
control = _jsx(WorkflowMemberPicker, { variant: variant, multiple: property.type === 'array' || ui.mode === 'multiple', placeholder: ui.placeholder || `请选择${property.title || '成员'}` });
|
|
353
344
|
else if (property.enum) {
|
|
354
345
|
control = (_jsx(Select, { options: property.enum.map((value, index) => ({
|
|
355
346
|
label: property.enumNames?.[index] || value,
|
|
@@ -373,9 +364,9 @@ function OperationDialog({ operation, submitting, variant, onCancel, onSubmit, }
|
|
|
373
364
|
if (!operation)
|
|
374
365
|
return null;
|
|
375
366
|
const ui = operation.uiSchema;
|
|
376
|
-
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 })] }));
|
|
377
368
|
if (variant === 'mobile') {
|
|
378
|
-
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 }));
|
|
379
370
|
}
|
|
380
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 }));
|
|
381
372
|
}
|
|
@@ -734,11 +725,13 @@ function StandardWorkflowDetailRenderer({ surface, timeline, warning, operations
|
|
|
734
725
|
const activeNode = timeline?.display?.entries.find(entry => entry.status === 'active');
|
|
735
726
|
const people = activeNode?.people.map(person => person.displayName).filter(Boolean).join('、');
|
|
736
727
|
const statusTone = workflowStatus(instance.status).color;
|
|
737
|
-
const bannerTone = statusTone === '
|
|
728
|
+
const bannerTone = statusTone === 'error' ? 'error' : 'active';
|
|
729
|
+
const edit = workflowHasEnded(instance) ? onEdit : undefined;
|
|
730
|
+
const hasActions = standardWorkflowOperations(surface).length > 0;
|
|
738
731
|
const loadAudit = useCallback(() => loadWorkflowDataAudit(instance.id), [instance.id]);
|
|
739
732
|
const back = onClose || (() => navigate(variant === 'mobile' ? '/m/work-center' : '/work-center'));
|
|
740
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,
|
|
741
|
-
summary.submittedAt ? `${detailTime(summary.submittedAt)} 创建` : ''].filter(Boolean).join(' · '), updatedAt: business.record.updated_at || instance.completedAt || instance.startedAt, onClose: back, onEdit:
|
|
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: [
|
|
742
735
|
{ key: 'application', label: '申请内容', children: _jsx(WorkflowBusinessDetailSections, { surface: surface, variant: variant }) },
|
|
743
736
|
{ key: 'history', label: '审批历史', children: _jsx(WorkflowTimelineSection, { timeline: timeline }) },
|
|
744
737
|
{ key: 'changes', label: '变更记录', children: tab === 'changes' && business.surface && business.resourceCode && business.recordId
|
|
@@ -852,7 +845,7 @@ function WorkflowDetailPage({ kind, variant, resourceCode, recordId, onDismiss,
|
|
|
852
845
|
? _jsx(WorkflowTaskOperationsPanel, { onCommandCompleted: onCommandCompleted, surface: surface, taskId: task.id, variant: variant }, task.id)
|
|
853
846
|
: _jsx(WorkflowInstanceOperationsPanel, { instanceId: instance.id, onCommandCompleted: onCommandCompleted, surface: surface, variant: variant });
|
|
854
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)
|
|
855
|
-
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: identity.isAppSuperAdmin && (business?.status === 'ready' || business?.status === 'stale') ? () => setEditing(true) : undefined });
|
|
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 });
|
|
856
849
|
}
|
|
857
850
|
export function WorkflowRecordDetailPage({ variant = 'desktop', ...props }) { return _jsx(WorkflowDetailPage, { ...props, variant: variant, kind: "record" }); }
|
|
858
851
|
export function WorkflowTaskPage({ variant = 'desktop', }) {
|
|
@@ -902,7 +895,7 @@ export function WorkflowWorkCenterPage({ variant = 'desktop' }) {
|
|
|
902
895
|
current: pageNumber, pageSize, total: page?.total || 0, showSizeChanger: true,
|
|
903
896
|
onChange: (number, size) => { setPageNumber(number); setPageSize(size); },
|
|
904
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" })] })] })] });
|
|
905
|
-
return
|
|
898
|
+
return content;
|
|
906
899
|
}
|
|
907
900
|
function RequirementFields({ requirements, }) {
|
|
908
901
|
return (_jsx(_Fragment, { children: requirements.map((requirement) => (_jsx(Form.Item, { label: requirement.title, name: requirement.id, rules: requirement.required
|
|
@@ -1024,20 +1017,7 @@ async function workflowContextPrefillValue(field, rawValue, resources) {
|
|
|
1024
1017
|
...(Object.keys(snapshot).length ? { snapshot } : {}),
|
|
1025
1018
|
};
|
|
1026
1019
|
}
|
|
1027
|
-
|
|
1028
|
-
const parsed = Number(value);
|
|
1029
|
-
if (!Number.isFinite(parsed)) {
|
|
1030
|
-
throw new Error('OPENXIANGDA_WORKFLOW_LAUNCH_CONTEXT_VALUE_INVALID');
|
|
1031
|
-
}
|
|
1032
|
-
return parsed;
|
|
1033
|
-
}
|
|
1034
|
-
if (field.type === 'boolean') {
|
|
1035
|
-
if (!['true', 'false'].includes(value)) {
|
|
1036
|
-
throw new Error('OPENXIANGDA_WORKFLOW_LAUNCH_CONTEXT_VALUE_INVALID');
|
|
1037
|
-
}
|
|
1038
|
-
return value === 'true';
|
|
1039
|
-
}
|
|
1040
|
-
return value;
|
|
1020
|
+
return workflowContextScalarValue(field, value);
|
|
1041
1021
|
}
|
|
1042
1022
|
export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWorkflowCode, variant = 'desktop', onDismiss, onCompleted, } = {}) {
|
|
1043
1023
|
const { workflowCode: routeWorkflowCode = '' } = useParams();
|
|
@@ -1263,16 +1243,29 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1263
1243
|
}
|
|
1264
1244
|
let active = true;
|
|
1265
1245
|
let timer;
|
|
1246
|
+
const startedAt = Date.now();
|
|
1247
|
+
let failures = 0;
|
|
1248
|
+
let controller;
|
|
1266
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)));
|
|
1267
1258
|
try {
|
|
1268
|
-
const next = await loadProcessCommandSurface(commandId);
|
|
1259
|
+
const next = await loadProcessCommandSurface(commandId, controller.signal);
|
|
1269
1260
|
if (!active)
|
|
1270
1261
|
return;
|
|
1271
|
-
if (next.command.
|
|
1262
|
+
if (next.command.id !== commandId ||
|
|
1263
|
+
next.command.environmentKey !== identity.environment.key ||
|
|
1272
1264
|
next.command.workflowCode !== workflowCode ||
|
|
1273
1265
|
next.command.subject.resourceCode !== definition?.subject.resourceCode) {
|
|
1274
1266
|
throw new Error('OPENXIANGDA_PROCESS_COMMAND_SCOPE_MISMATCH');
|
|
1275
1267
|
}
|
|
1268
|
+
failures = 0;
|
|
1276
1269
|
setProcessSurface(next);
|
|
1277
1270
|
setProcessError(null);
|
|
1278
1271
|
if (next.command.status === 'started' && next.command.workflowInstanceId) {
|
|
@@ -1295,13 +1288,21 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1295
1288
|
}
|
|
1296
1289
|
}
|
|
1297
1290
|
catch (error) {
|
|
1298
|
-
if (active)
|
|
1299
|
-
|
|
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);
|
|
1300
1300
|
}
|
|
1301
1301
|
};
|
|
1302
1302
|
void refresh();
|
|
1303
1303
|
return () => {
|
|
1304
1304
|
active = false;
|
|
1305
|
+
controller?.abort();
|
|
1305
1306
|
if (timer)
|
|
1306
1307
|
clearTimeout(timer);
|
|
1307
1308
|
};
|
|
@@ -1545,6 +1546,7 @@ export function WorkflowSubmissionPage({ instancePath, workflowCode: declaredWor
|
|
|
1545
1546
|
const uploadOperationCode = namedIntent?.operationCode || definition.processOperationCode;
|
|
1546
1547
|
const fieldRenderers = uploadOperationCode
|
|
1547
1548
|
? {
|
|
1549
|
+
...(namedIntent ? { referenceLaunch: { workflowCode: definition.code, operationCode: namedIntent.operationCode } } : {}),
|
|
1548
1550
|
upload: async (field, file) => await uploadOperationManagedFile({
|
|
1549
1551
|
operationCode: uploadOperationCode,
|
|
1550
1552
|
resourceCode: subjectDefinition.code,
|