sy-form-components 0.2.0 → 0.2.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.
- package/README.md +5 -5
- package/dist/index.d.mts +537 -1
- package/dist/index.d.ts +537 -1
- package/dist/index.js +2229 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2192 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,55 +31,91 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AddressField: () => AddressField,
|
|
34
|
+
ApprovalActions: () => ApprovalActions,
|
|
35
|
+
ApprovalTimeline: () => ApprovalTimeline,
|
|
34
36
|
AssociationFormField: () => AssociationFormField,
|
|
35
37
|
AttachmentField: () => AttachmentField,
|
|
36
38
|
CascadeDateField: () => CascadeDateField,
|
|
37
39
|
CascadeSelectField: () => CascadeSelectField,
|
|
40
|
+
ChangeRecords: () => ChangeRecords,
|
|
38
41
|
CheckboxField: () => CheckboxField,
|
|
39
42
|
ComponentRegistryContext: () => ComponentRegistryContext,
|
|
40
43
|
ComponentRegistryProvider: () => ComponentRegistryProvider,
|
|
41
44
|
DateField: () => DateField,
|
|
42
45
|
DepartmentSelectField: () => DepartmentSelectField,
|
|
43
46
|
DigitalSignatureField: () => DigitalSignatureField,
|
|
47
|
+
DraftManager: () => DraftManager,
|
|
44
48
|
EditorField: () => EditorField,
|
|
45
49
|
EmployeeSelectField: () => UserSelectField,
|
|
46
50
|
FieldWrapper: () => FieldWrapper,
|
|
51
|
+
FormActionBar: () => FormActionBar,
|
|
47
52
|
FormActions: () => FormActions,
|
|
48
53
|
FormContainer: () => FormContainer,
|
|
49
54
|
FormContext: () => FormContext,
|
|
55
|
+
FormDetailTemplate: () => FormDetailTemplate,
|
|
50
56
|
FormGrid: () => FormGrid,
|
|
51
57
|
FormProvider: () => FormProvider,
|
|
52
58
|
FormRenderer: () => FormRenderer,
|
|
53
59
|
FormSection: () => FormSection,
|
|
54
60
|
FormSteps: () => FormSteps,
|
|
61
|
+
FormSubmitTemplate: () => FormSubmitTemplate,
|
|
55
62
|
FormSummary: () => FormSummary,
|
|
63
|
+
FormSummaryCard: () => FormSummaryCard,
|
|
56
64
|
FormTabs: () => FormTabs,
|
|
57
65
|
ImageField: () => ImageField,
|
|
58
66
|
JSONField: () => JSONField,
|
|
59
67
|
LocationField: () => LocationField,
|
|
60
68
|
MultiSelectField: () => MultiSelectField,
|
|
61
69
|
NumberField: () => NumberField,
|
|
70
|
+
PROCESS_STATUS_META: () => PROCESS_STATUS_META,
|
|
71
|
+
PageSkeleton: () => PageSkeleton,
|
|
72
|
+
ProcessDetailTemplate: () => ProcessDetailTemplate,
|
|
73
|
+
ProcessPreview: () => ProcessPreview,
|
|
62
74
|
RadioField: () => RadioField,
|
|
63
75
|
SelectField: () => SelectField,
|
|
64
76
|
SerialNumberField: () => SerialNumberField,
|
|
65
77
|
SubFormField: () => SubFormField,
|
|
78
|
+
TASK_STATUS_META: () => TASK_STATUS_META,
|
|
66
79
|
TextAreaField: () => TextAreaField,
|
|
67
80
|
TextField: () => TextField,
|
|
68
81
|
TextareaField: () => TextAreaField,
|
|
69
82
|
UserSelectField: () => UserSelectField,
|
|
83
|
+
checkUserApproval: () => checkUserApproval,
|
|
70
84
|
createFormRuntimeApi: () => createFormRuntimeApi,
|
|
71
85
|
defaultComponentRegistry: () => defaultComponentRegistry,
|
|
72
86
|
defineFormSchema: () => defineFormSchema,
|
|
87
|
+
deleteFormData: () => deleteFormData,
|
|
73
88
|
evaluateEffects: () => evaluateEffects,
|
|
89
|
+
getChangeRecords: () => getChangeRecords,
|
|
90
|
+
getFormData: () => getFormData,
|
|
91
|
+
getProcessBasic: () => getProcessBasic,
|
|
92
|
+
getProcessDefinition: () => getProcessDefinition,
|
|
93
|
+
getProcessProgress: () => getProcessProgress,
|
|
94
|
+
getReturnableNodes: () => getReturnableNodes,
|
|
95
|
+
getViewPermission: () => getViewPermission,
|
|
96
|
+
handleApproval: () => handleApproval,
|
|
97
|
+
previewProcess: () => previewProcess,
|
|
98
|
+
resubmitTask: () => resubmitTask,
|
|
99
|
+
returnTask: () => returnTask,
|
|
100
|
+
saveTask: () => saveTask,
|
|
101
|
+
transferTask: () => transferTask,
|
|
102
|
+
useApprovalActions: () => useApprovalActions,
|
|
103
|
+
useChangeRecords: () => useChangeRecords,
|
|
74
104
|
useComponent: () => useComponent,
|
|
75
105
|
useDeviceDetect: () => useDeviceDetect,
|
|
106
|
+
useDraftStorage: () => useDraftStorage,
|
|
76
107
|
useFieldBehavior: () => useFieldBehavior,
|
|
108
|
+
useFieldPermission: () => useFieldPermission,
|
|
77
109
|
useFormContext: () => useFormContext,
|
|
78
110
|
useFormData: () => useFormData,
|
|
111
|
+
useFormDetail: () => useFormDetail,
|
|
79
112
|
useFormEngine: () => useFormEngine,
|
|
113
|
+
useFormNavigation: () => useFormNavigation,
|
|
80
114
|
useFormSubmit: () => useFormSubmit,
|
|
115
|
+
useProcessDetail: () => useProcessDetail,
|
|
81
116
|
validateAllFields: () => validateAllFields,
|
|
82
|
-
validateField: () => validateField
|
|
117
|
+
validateField: () => validateField,
|
|
118
|
+
withdrawProcess: () => withdrawProcess
|
|
83
119
|
});
|
|
84
120
|
module.exports = __toCommonJS(index_exports);
|
|
85
121
|
|
|
@@ -4121,7 +4157,7 @@ function FormProvider({
|
|
|
4121
4157
|
});
|
|
4122
4158
|
}, []);
|
|
4123
4159
|
const getFieldValue = (0, import_react34.useCallback)((fieldId) => formData[fieldId], [formData]);
|
|
4124
|
-
const
|
|
4160
|
+
const getFormData2 = (0, import_react34.useCallback)(() => ({ ...formData }), [formData]);
|
|
4125
4161
|
const validateFieldById = (0, import_react34.useCallback)(
|
|
4126
4162
|
async (fieldId) => {
|
|
4127
4163
|
const field = schema.fields.find((f) => f.fieldId === fieldId);
|
|
@@ -4198,7 +4234,7 @@ function FormProvider({
|
|
|
4198
4234
|
},
|
|
4199
4235
|
setFieldValue,
|
|
4200
4236
|
getFieldValue,
|
|
4201
|
-
getFormData,
|
|
4237
|
+
getFormData: getFormData2,
|
|
4202
4238
|
validateField: validateFieldById,
|
|
4203
4239
|
validateAll,
|
|
4204
4240
|
resetForm,
|
|
@@ -4218,7 +4254,7 @@ function FormProvider({
|
|
|
4218
4254
|
config.submit,
|
|
4219
4255
|
setFieldValue,
|
|
4220
4256
|
getFieldValue,
|
|
4221
|
-
|
|
4257
|
+
getFormData2,
|
|
4222
4258
|
validateFieldById,
|
|
4223
4259
|
validateAll,
|
|
4224
4260
|
resetForm,
|
|
@@ -4289,14 +4325,14 @@ function FormActions({
|
|
|
4289
4325
|
showReset = true,
|
|
4290
4326
|
onSubmit
|
|
4291
4327
|
}) {
|
|
4292
|
-
const { mode, validateAll, getFormData, resetForm, api, config } = useFormContext();
|
|
4328
|
+
const { mode, validateAll, getFormData: getFormData2, resetForm, api, config } = useFormContext();
|
|
4293
4329
|
const [isSubmitting, setIsSubmitting] = (0, import_react36.useState)(false);
|
|
4294
4330
|
const [submitError, setSubmitError] = (0, import_react36.useState)(null);
|
|
4295
4331
|
const handleSubmit = (0, import_react36.useCallback)(async () => {
|
|
4296
4332
|
setSubmitError(null);
|
|
4297
4333
|
const valid = await validateAll();
|
|
4298
4334
|
if (!valid) return;
|
|
4299
|
-
const values =
|
|
4335
|
+
const values = getFormData2();
|
|
4300
4336
|
setIsSubmitting(true);
|
|
4301
4337
|
try {
|
|
4302
4338
|
const beforeResult = await config.submit?.beforeSubmit?.(values);
|
|
@@ -4327,7 +4363,7 @@ function FormActions({
|
|
|
4327
4363
|
} finally {
|
|
4328
4364
|
setIsSubmitting(false);
|
|
4329
4365
|
}
|
|
4330
|
-
}, [api, config,
|
|
4366
|
+
}, [api, config, getFormData2, mode, onSubmit, validateAll]);
|
|
4331
4367
|
const handleReset = (0, import_react36.useCallback)(() => {
|
|
4332
4368
|
resetForm();
|
|
4333
4369
|
}, [resetForm]);
|
|
@@ -4387,6 +4423,160 @@ function FormContainer({
|
|
|
4387
4423
|
] });
|
|
4388
4424
|
}
|
|
4389
4425
|
|
|
4426
|
+
// src/core/constants.ts
|
|
4427
|
+
var PROCESS_STATUS_META = {
|
|
4428
|
+
running: { label: "\u5BA1\u6279\u4E2D", tone: "brand" },
|
|
4429
|
+
waiting: { label: "\u7B49\u5F85\u4E2D", tone: "neutral" },
|
|
4430
|
+
exception: { label: "\u6D41\u7A0B\u5F02\u5E38", tone: "danger" },
|
|
4431
|
+
completed: { label: "\u5DF2\u5B8C\u6210", tone: "success" },
|
|
4432
|
+
terminated: { label: "\u5DF2\u62D2\u7EDD", tone: "danger" },
|
|
4433
|
+
withdrawn: { label: "\u5DF2\u64A4\u9500", tone: "neutral" },
|
|
4434
|
+
pending: { label: "\u5F85\u5904\u7406", tone: "brand" },
|
|
4435
|
+
cancelled: { label: "\u5DF2\u53D6\u6D88", tone: "neutral" }
|
|
4436
|
+
};
|
|
4437
|
+
var TASK_STATUS_META = {
|
|
4438
|
+
pending: { label: "\u5F85\u5904\u7406", tone: "brand" },
|
|
4439
|
+
approved: { label: "\u5DF2\u540C\u610F", tone: "success" },
|
|
4440
|
+
rejected: { label: "\u5DF2\u62D2\u7EDD", tone: "danger" },
|
|
4441
|
+
returned: { label: "\u5DF2\u9000\u56DE", tone: "warning" },
|
|
4442
|
+
suspended: { label: "\u5DF2\u6302\u8D77", tone: "neutral" },
|
|
4443
|
+
cancelled: { label: "\u5DF2\u53D6\u6D88", tone: "neutral" },
|
|
4444
|
+
copied: { label: "\u5DF2\u6284\u9001", tone: "neutral" },
|
|
4445
|
+
waiting: { label: "\u7B49\u5F85\u4E2D", tone: "neutral" },
|
|
4446
|
+
simulated: { label: "\u672A\u5F00\u59CB", tone: "neutral" }
|
|
4447
|
+
};
|
|
4448
|
+
|
|
4449
|
+
// src/core/processApi.ts
|
|
4450
|
+
async function getProcessBasic(request, formInstId) {
|
|
4451
|
+
const response = await request({
|
|
4452
|
+
url: `/workflow/instance/${formInstId}/basic`,
|
|
4453
|
+
method: "get"
|
|
4454
|
+
});
|
|
4455
|
+
return response.data || response.result;
|
|
4456
|
+
}
|
|
4457
|
+
async function getProcessProgress(request, formInstId) {
|
|
4458
|
+
const response = await request({
|
|
4459
|
+
url: `/workflow/instance/${formInstId}`,
|
|
4460
|
+
method: "get"
|
|
4461
|
+
});
|
|
4462
|
+
return response.data || response.result || [];
|
|
4463
|
+
}
|
|
4464
|
+
async function checkUserApproval(request, formInstId) {
|
|
4465
|
+
const response = await request({
|
|
4466
|
+
url: `/workflow/instance/${formInstId}/permission`,
|
|
4467
|
+
method: "get"
|
|
4468
|
+
});
|
|
4469
|
+
return response.data || response.result;
|
|
4470
|
+
}
|
|
4471
|
+
async function handleApproval(request, params) {
|
|
4472
|
+
const response = await request({
|
|
4473
|
+
url: "/workflow/approve",
|
|
4474
|
+
method: "post",
|
|
4475
|
+
data: params
|
|
4476
|
+
});
|
|
4477
|
+
return response.data || response.result;
|
|
4478
|
+
}
|
|
4479
|
+
async function withdrawProcess(request, params) {
|
|
4480
|
+
const response = await request({
|
|
4481
|
+
url: `/workflow/instance/${params.instanceId}/withdraw`,
|
|
4482
|
+
method: "put",
|
|
4483
|
+
data: { reason: params.reason }
|
|
4484
|
+
});
|
|
4485
|
+
return response.data || response.result;
|
|
4486
|
+
}
|
|
4487
|
+
async function transferTask(request, params) {
|
|
4488
|
+
const response = await request({
|
|
4489
|
+
url: `/workflow/task/${params.taskId}/transfer`,
|
|
4490
|
+
method: "put",
|
|
4491
|
+
data: { newAssignee: params.newAssignee, reason: params.reason }
|
|
4492
|
+
});
|
|
4493
|
+
return response.data || response.result;
|
|
4494
|
+
}
|
|
4495
|
+
async function returnTask(request, params) {
|
|
4496
|
+
const response = await request({
|
|
4497
|
+
url: `/workflow/task/${params.taskId}/return`,
|
|
4498
|
+
method: "put",
|
|
4499
|
+
data: { targetNodeId: params.targetNodeId, reason: params.reason }
|
|
4500
|
+
});
|
|
4501
|
+
return response.data || response.result;
|
|
4502
|
+
}
|
|
4503
|
+
async function resubmitTask(request, params) {
|
|
4504
|
+
const response = await request({
|
|
4505
|
+
url: `/workflow/task/${params.taskId}/resubmit`,
|
|
4506
|
+
method: "post",
|
|
4507
|
+
data: {
|
|
4508
|
+
formUuid: params.formUuid,
|
|
4509
|
+
appType: params.appType,
|
|
4510
|
+
updateFormDataJson: params.updateFormDataJson,
|
|
4511
|
+
comments: params.comments
|
|
4512
|
+
}
|
|
4513
|
+
});
|
|
4514
|
+
return response.data || response.result;
|
|
4515
|
+
}
|
|
4516
|
+
async function saveTask(request, params) {
|
|
4517
|
+
const response = await request({
|
|
4518
|
+
url: "/workflow/task/save",
|
|
4519
|
+
method: "post",
|
|
4520
|
+
data: params
|
|
4521
|
+
});
|
|
4522
|
+
return response.data || response.result;
|
|
4523
|
+
}
|
|
4524
|
+
async function getReturnableNodes(request, taskId) {
|
|
4525
|
+
const response = await request({
|
|
4526
|
+
url: `/workflow/task/${taskId}/returnable-nodes`,
|
|
4527
|
+
method: "get"
|
|
4528
|
+
});
|
|
4529
|
+
return response.data || response.result || [];
|
|
4530
|
+
}
|
|
4531
|
+
async function previewProcess(request, params) {
|
|
4532
|
+
const response = await request({
|
|
4533
|
+
url: "/workflow/preview",
|
|
4534
|
+
method: "post",
|
|
4535
|
+
data: params
|
|
4536
|
+
});
|
|
4537
|
+
return response.data || response.result || [];
|
|
4538
|
+
}
|
|
4539
|
+
async function getProcessDefinition(request, formUuid) {
|
|
4540
|
+
const response = await request({
|
|
4541
|
+
url: "/workflow/definition/form",
|
|
4542
|
+
method: "get",
|
|
4543
|
+
params: { formUuid }
|
|
4544
|
+
});
|
|
4545
|
+
return response.data || response.result;
|
|
4546
|
+
}
|
|
4547
|
+
async function getFormData(request, params) {
|
|
4548
|
+
const response = await request({
|
|
4549
|
+
url: "/form/queryFormDataByFormInstanceId",
|
|
4550
|
+
method: "get",
|
|
4551
|
+
params
|
|
4552
|
+
});
|
|
4553
|
+
return response.data || response.result;
|
|
4554
|
+
}
|
|
4555
|
+
async function deleteFormData(request, params) {
|
|
4556
|
+
const response = await request({
|
|
4557
|
+
url: `/${params.appType}/v1/form/deleteFormData.json`,
|
|
4558
|
+
method: "post",
|
|
4559
|
+
data: params
|
|
4560
|
+
});
|
|
4561
|
+
return response.data || response.result;
|
|
4562
|
+
}
|
|
4563
|
+
async function getChangeRecords(request, params) {
|
|
4564
|
+
const response = await request({
|
|
4565
|
+
url: "/form/getFormDataChangeRecords",
|
|
4566
|
+
method: "get",
|
|
4567
|
+
params
|
|
4568
|
+
});
|
|
4569
|
+
return response.data || response.result;
|
|
4570
|
+
}
|
|
4571
|
+
async function getViewPermission(request, params) {
|
|
4572
|
+
const response = await request({
|
|
4573
|
+
url: "/permission/form-group/view-permissions",
|
|
4574
|
+
method: "get",
|
|
4575
|
+
params
|
|
4576
|
+
});
|
|
4577
|
+
return response.data || response.result;
|
|
4578
|
+
}
|
|
4579
|
+
|
|
4390
4580
|
// src/layout/FormSection/index.tsx
|
|
4391
4581
|
var import_react37 = require("react");
|
|
4392
4582
|
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
@@ -4587,7 +4777,7 @@ function FormSummary({
|
|
|
4587
4777
|
const { schema, formData } = useFormContext();
|
|
4588
4778
|
const displayFields = fields ? schema.fields.filter((f) => fields.includes(f.fieldId)) : schema.fields;
|
|
4589
4779
|
const colClass = columnClasses2[columns];
|
|
4590
|
-
const
|
|
4780
|
+
const formatValue2 = (value) => {
|
|
4591
4781
|
if (value === null || value === void 0 || value === "") return "--";
|
|
4592
4782
|
if (Array.isArray(value)) {
|
|
4593
4783
|
if (value.length === 0) return "--";
|
|
@@ -4603,7 +4793,7 @@ function FormSummary({
|
|
|
4603
4793
|
"data-testid": `summary-field-${field.fieldId}`,
|
|
4604
4794
|
children: [
|
|
4605
4795
|
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: labelClassName ?? "text-sm text-gray-500 mb-1", children: field.label }),
|
|
4606
|
-
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: valueClassName ?? "text-sm text-gray-900", children:
|
|
4796
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { className: valueClassName ?? "text-sm text-gray-900", children: formatValue2(formData[field.fieldId]) })
|
|
4607
4797
|
]
|
|
4608
4798
|
},
|
|
4609
4799
|
field.fieldId
|
|
@@ -4660,7 +4850,7 @@ function useFormEngine(schema, config) {
|
|
|
4660
4850
|
});
|
|
4661
4851
|
}, []);
|
|
4662
4852
|
const getFieldValue = (0, import_react40.useCallback)((fieldId) => formData[fieldId], [formData]);
|
|
4663
|
-
const
|
|
4853
|
+
const getFormData2 = (0, import_react40.useCallback)(() => ({ ...formData }), [formData]);
|
|
4664
4854
|
const validateAll = (0, import_react40.useCallback)(async () => {
|
|
4665
4855
|
const fieldRules = {};
|
|
4666
4856
|
for (const field of schema.fields) {
|
|
@@ -4687,7 +4877,7 @@ function useFormEngine(schema, config) {
|
|
|
4687
4877
|
formData,
|
|
4688
4878
|
setFieldValue,
|
|
4689
4879
|
getFieldValue,
|
|
4690
|
-
getFormData,
|
|
4880
|
+
getFormData: getFormData2,
|
|
4691
4881
|
validateAll,
|
|
4692
4882
|
resetForm,
|
|
4693
4883
|
mode: config.mode,
|
|
@@ -4716,7 +4906,7 @@ function useFormData(initialValues = {}) {
|
|
|
4716
4906
|
},
|
|
4717
4907
|
[formData]
|
|
4718
4908
|
);
|
|
4719
|
-
const
|
|
4909
|
+
const getFormData2 = (0, import_react41.useCallback)(() => {
|
|
4720
4910
|
return { ...formData };
|
|
4721
4911
|
}, [formData]);
|
|
4722
4912
|
const resetForm = (0, import_react41.useCallback)(() => {
|
|
@@ -4727,7 +4917,7 @@ function useFormData(initialValues = {}) {
|
|
|
4727
4917
|
formData,
|
|
4728
4918
|
setFieldValue,
|
|
4729
4919
|
getFieldValue,
|
|
4730
|
-
getFormData,
|
|
4920
|
+
getFormData: getFormData2,
|
|
4731
4921
|
resetForm,
|
|
4732
4922
|
dirtyFields
|
|
4733
4923
|
};
|
|
@@ -4791,61 +4981,2086 @@ function useFormSubmit(config) {
|
|
|
4791
4981
|
return { submit, isSubmitting, submitError };
|
|
4792
4982
|
}
|
|
4793
4983
|
|
|
4984
|
+
// src/hooks/useFieldPermission.ts
|
|
4985
|
+
var import_react44 = require("react");
|
|
4986
|
+
function useFieldPermission(options) {
|
|
4987
|
+
const { viewPermissions, processDefinition, currentTask, isApprover, mode } = options;
|
|
4988
|
+
const computeBehaviors = (0, import_react44.useCallback)(() => {
|
|
4989
|
+
const behaviors = {};
|
|
4990
|
+
if (!currentTask && viewPermissions) {
|
|
4991
|
+
const { fieldPermissions } = viewPermissions;
|
|
4992
|
+
for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
|
|
4993
|
+
if (perm === "FORM_FILED_HIDDEN") {
|
|
4994
|
+
behaviors[fieldId] = "HIDDEN";
|
|
4995
|
+
} else if (perm === "FORM_FILED_VIEW") {
|
|
4996
|
+
behaviors[fieldId] = "READONLY";
|
|
4997
|
+
} else if (perm === "FORM_FILED_EDIT") {
|
|
4998
|
+
behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
return behaviors;
|
|
5002
|
+
}
|
|
5003
|
+
if (currentTask && !isApprover && viewPermissions) {
|
|
5004
|
+
const { fieldPermissions } = viewPermissions;
|
|
5005
|
+
for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
|
|
5006
|
+
if (perm === "FORM_FILED_HIDDEN") {
|
|
5007
|
+
behaviors[fieldId] = "HIDDEN";
|
|
5008
|
+
} else {
|
|
5009
|
+
behaviors[fieldId] = "READONLY";
|
|
5010
|
+
}
|
|
5011
|
+
}
|
|
5012
|
+
return behaviors;
|
|
5013
|
+
}
|
|
5014
|
+
if (currentTask && isApprover && currentTask.nodeType === "originator_return") {
|
|
5015
|
+
if (processDefinition?.flowConfig && processDefinition.startNodeId) {
|
|
5016
|
+
const startConfig = processDefinition.flowConfig[processDefinition.startNodeId];
|
|
5017
|
+
if (startConfig) {
|
|
5018
|
+
for (const [fieldId, behavior] of Object.entries(startConfig)) {
|
|
5019
|
+
behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
|
|
5020
|
+
}
|
|
5021
|
+
return behaviors;
|
|
5022
|
+
}
|
|
5023
|
+
}
|
|
5024
|
+
if (viewPermissions) {
|
|
5025
|
+
for (const fieldId of Object.keys(viewPermissions.fieldPermissions)) {
|
|
5026
|
+
if (viewPermissions.fieldPermissions[fieldId] === "FORM_FILED_HIDDEN") {
|
|
5027
|
+
behaviors[fieldId] = "HIDDEN";
|
|
5028
|
+
} else {
|
|
5029
|
+
behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
|
|
5030
|
+
}
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5033
|
+
return behaviors;
|
|
5034
|
+
}
|
|
5035
|
+
if (currentTask && isApprover && processDefinition?.flowConfig) {
|
|
5036
|
+
const nodeConfig = processDefinition.flowConfig[currentTask.nodeId];
|
|
5037
|
+
if (nodeConfig) {
|
|
5038
|
+
for (const [fieldId, behavior] of Object.entries(nodeConfig)) {
|
|
5039
|
+
behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
|
|
5040
|
+
}
|
|
5041
|
+
return behaviors;
|
|
5042
|
+
}
|
|
5043
|
+
}
|
|
5044
|
+
if (viewPermissions) {
|
|
5045
|
+
const { fieldPermissions } = viewPermissions;
|
|
5046
|
+
for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
|
|
5047
|
+
if (perm === "FORM_FILED_HIDDEN") {
|
|
5048
|
+
behaviors[fieldId] = "HIDDEN";
|
|
5049
|
+
} else if (perm === "FORM_FILED_VIEW") {
|
|
5050
|
+
behaviors[fieldId] = "READONLY";
|
|
5051
|
+
} else if (perm === "FORM_FILED_EDIT") {
|
|
5052
|
+
behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
return behaviors;
|
|
5057
|
+
}, [viewPermissions, processDefinition, currentTask, isApprover, mode]);
|
|
5058
|
+
const fieldBehaviors = (0, import_react44.useMemo)(() => computeBehaviors(), [computeBehaviors]);
|
|
5059
|
+
return { fieldBehaviors, computeBehaviors };
|
|
5060
|
+
}
|
|
5061
|
+
|
|
5062
|
+
// src/hooks/useFormDetail.ts
|
|
5063
|
+
var import_react45 = require("react");
|
|
5064
|
+
function buildFieldBehaviors(permissions, mode) {
|
|
5065
|
+
const behaviors = {};
|
|
5066
|
+
if (!permissions) return behaviors;
|
|
5067
|
+
for (const [fieldId, perm] of Object.entries(permissions.fieldPermissions)) {
|
|
5068
|
+
if (perm === "FORM_FILED_HIDDEN") {
|
|
5069
|
+
behaviors[fieldId] = "HIDDEN";
|
|
5070
|
+
} else if (perm === "FORM_FILED_VIEW") {
|
|
5071
|
+
behaviors[fieldId] = "READONLY";
|
|
5072
|
+
} else if (perm === "FORM_FILED_EDIT") {
|
|
5073
|
+
behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
return behaviors;
|
|
5077
|
+
}
|
|
5078
|
+
function useFormDetail(options) {
|
|
5079
|
+
const { formUuid, appType, formInstanceId, onPermissionDenied } = options;
|
|
5080
|
+
const { api } = useFormContext();
|
|
5081
|
+
const request = api.request;
|
|
5082
|
+
const [loading, setLoading] = (0, import_react45.useState)(true);
|
|
5083
|
+
const [mode, setMode] = (0, import_react45.useState)("readonly");
|
|
5084
|
+
const [formData, setFormData] = (0, import_react45.useState)(null);
|
|
5085
|
+
const [instanceInfo, setInstanceInfo] = (0, import_react45.useState)(null);
|
|
5086
|
+
const [permissions, setPermissions] = (0, import_react45.useState)(null);
|
|
5087
|
+
const mountedRef = (0, import_react45.useRef)(true);
|
|
5088
|
+
(0, import_react45.useEffect)(() => {
|
|
5089
|
+
mountedRef.current = true;
|
|
5090
|
+
return () => {
|
|
5091
|
+
mountedRef.current = false;
|
|
5092
|
+
};
|
|
5093
|
+
}, []);
|
|
5094
|
+
const loadData = (0, import_react45.useCallback)(async () => {
|
|
5095
|
+
if (!mountedRef.current) return;
|
|
5096
|
+
setLoading(true);
|
|
5097
|
+
try {
|
|
5098
|
+
const [permResult, formResult] = await Promise.all([
|
|
5099
|
+
getViewPermission(request, { formUuid, appType, formInstanceId }),
|
|
5100
|
+
getFormData(request, { formInstanceId, appType, formUuid })
|
|
5101
|
+
]);
|
|
5102
|
+
if (!mountedRef.current) return;
|
|
5103
|
+
if (!permResult || !permResult.operations || permResult.operations.length === 0) {
|
|
5104
|
+
onPermissionDenied?.();
|
|
5105
|
+
}
|
|
5106
|
+
setPermissions(permResult);
|
|
5107
|
+
setInstanceInfo(formResult);
|
|
5108
|
+
setFormData(formResult?.data ?? null);
|
|
5109
|
+
} catch (error) {
|
|
5110
|
+
console.error("[useFormDetail] Failed to load data:", error);
|
|
5111
|
+
if (mountedRef.current) {
|
|
5112
|
+
setPermissions(null);
|
|
5113
|
+
setInstanceInfo(null);
|
|
5114
|
+
setFormData(null);
|
|
5115
|
+
}
|
|
5116
|
+
} finally {
|
|
5117
|
+
if (mountedRef.current) {
|
|
5118
|
+
setLoading(false);
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
}, [request, formUuid, appType, formInstanceId, onPermissionDenied]);
|
|
5122
|
+
(0, import_react45.useEffect)(() => {
|
|
5123
|
+
loadData();
|
|
5124
|
+
}, [loadData]);
|
|
5125
|
+
const fieldBehaviors = buildFieldBehaviors(permissions, mode);
|
|
5126
|
+
const canEdit = permissions?.operations?.includes("EDIT") ?? false;
|
|
5127
|
+
const canDelete = permissions?.operations?.includes("DELETE") ?? false;
|
|
5128
|
+
const canViewChangeRecords = permissions?.operations?.includes("VIEW_CHANGE_RECORDS") ?? false;
|
|
5129
|
+
const switchToEdit = (0, import_react45.useCallback)(() => {
|
|
5130
|
+
setMode("edit");
|
|
5131
|
+
loadData();
|
|
5132
|
+
}, [loadData]);
|
|
5133
|
+
const switchToReadonly = (0, import_react45.useCallback)(() => {
|
|
5134
|
+
setMode("readonly");
|
|
5135
|
+
}, []);
|
|
5136
|
+
const saveChanges = (0, import_react45.useCallback)(
|
|
5137
|
+
async (values) => {
|
|
5138
|
+
try {
|
|
5139
|
+
await api.updateFormData({
|
|
5140
|
+
formInstanceId,
|
|
5141
|
+
formUuid,
|
|
5142
|
+
appType,
|
|
5143
|
+
updateFormDataJson: JSON.stringify(values)
|
|
5144
|
+
});
|
|
5145
|
+
if (mountedRef.current) {
|
|
5146
|
+
setFormData(values);
|
|
5147
|
+
setMode("readonly");
|
|
5148
|
+
}
|
|
5149
|
+
return true;
|
|
5150
|
+
} catch (error) {
|
|
5151
|
+
console.error("[useFormDetail] Failed to save changes:", error);
|
|
5152
|
+
return false;
|
|
5153
|
+
}
|
|
5154
|
+
},
|
|
5155
|
+
[api, formInstanceId, formUuid, appType]
|
|
5156
|
+
);
|
|
5157
|
+
const deleteInstance = (0, import_react45.useCallback)(async () => {
|
|
5158
|
+
try {
|
|
5159
|
+
await deleteFormData(request, { formInstanceId, appType, formUuid });
|
|
5160
|
+
return true;
|
|
5161
|
+
} catch (error) {
|
|
5162
|
+
console.error("[useFormDetail] Failed to delete instance:", error);
|
|
5163
|
+
return false;
|
|
5164
|
+
}
|
|
5165
|
+
}, [request, formInstanceId, appType, formUuid]);
|
|
5166
|
+
return {
|
|
5167
|
+
loading,
|
|
5168
|
+
mode,
|
|
5169
|
+
formData,
|
|
5170
|
+
instanceInfo,
|
|
5171
|
+
permissions,
|
|
5172
|
+
fieldBehaviors,
|
|
5173
|
+
switchToEdit,
|
|
5174
|
+
switchToReadonly,
|
|
5175
|
+
saveChanges,
|
|
5176
|
+
deleteInstance,
|
|
5177
|
+
canEdit,
|
|
5178
|
+
canDelete,
|
|
5179
|
+
canViewChangeRecords
|
|
5180
|
+
};
|
|
5181
|
+
}
|
|
5182
|
+
|
|
5183
|
+
// src/hooks/useProcessDetail.ts
|
|
5184
|
+
var import_react46 = require("react");
|
|
5185
|
+
function useProcessDetail(options) {
|
|
5186
|
+
const { formUuid, appType, formInstanceId } = options;
|
|
5187
|
+
const { api } = useFormContext();
|
|
5188
|
+
const request = api.request;
|
|
5189
|
+
const [loading, setLoading] = (0, import_react46.useState)(true);
|
|
5190
|
+
const [mode, setMode] = (0, import_react46.useState)("readonly");
|
|
5191
|
+
const [processInfo, setProcessInfo] = (0, import_react46.useState)(null);
|
|
5192
|
+
const [progressList, setProgressList] = (0, import_react46.useState)([]);
|
|
5193
|
+
const [formData, setFormData] = (0, import_react46.useState)(null);
|
|
5194
|
+
const [instanceInfo, setInstanceInfo] = (0, import_react46.useState)(null);
|
|
5195
|
+
const [isApprover, setIsApprover] = (0, import_react46.useState)(false);
|
|
5196
|
+
const [canWithdraw, setCanWithdraw] = (0, import_react46.useState)(false);
|
|
5197
|
+
const [permissions, setPermissions] = (0, import_react46.useState)(null);
|
|
5198
|
+
const [processDefinition, setProcessDefinition] = (0, import_react46.useState)(null);
|
|
5199
|
+
const mountedRef = (0, import_react46.useRef)(true);
|
|
5200
|
+
(0, import_react46.useEffect)(() => {
|
|
5201
|
+
mountedRef.current = true;
|
|
5202
|
+
return () => {
|
|
5203
|
+
mountedRef.current = false;
|
|
5204
|
+
};
|
|
5205
|
+
}, []);
|
|
5206
|
+
const currentTask = processInfo?.currentTask ?? null;
|
|
5207
|
+
const processStatus = processInfo?.processStatus ?? null;
|
|
5208
|
+
const isOriginatorReturn = currentTask?.nodeType === "originator_return";
|
|
5209
|
+
const isProcessCompleted = processStatus === "completed" || processStatus === "terminated";
|
|
5210
|
+
const { fieldBehaviors } = useFieldPermission({
|
|
5211
|
+
viewPermissions: permissions ?? void 0,
|
|
5212
|
+
processDefinition: processDefinition ?? void 0,
|
|
5213
|
+
currentTask: currentTask ?? void 0,
|
|
5214
|
+
isApprover,
|
|
5215
|
+
mode
|
|
5216
|
+
});
|
|
5217
|
+
const activeActions = isApprover && currentTask?.actions ? currentTask.actions : [];
|
|
5218
|
+
const loadData = (0, import_react46.useCallback)(async () => {
|
|
5219
|
+
if (!mountedRef.current) return;
|
|
5220
|
+
setLoading(true);
|
|
5221
|
+
try {
|
|
5222
|
+
const [basicResult, approvalResult, permResult, formResult] = await Promise.all([
|
|
5223
|
+
getProcessBasic(request, formInstanceId),
|
|
5224
|
+
checkUserApproval(request, formInstanceId),
|
|
5225
|
+
getViewPermission(request, { formUuid, appType, formInstanceId }),
|
|
5226
|
+
getFormData(request, { formInstanceId, appType, formUuid })
|
|
5227
|
+
]);
|
|
5228
|
+
if (!mountedRef.current) return;
|
|
5229
|
+
setProcessInfo(basicResult);
|
|
5230
|
+
setIsApprover(approvalResult?.isApprover ?? false);
|
|
5231
|
+
setCanWithdraw(approvalResult?.canUndo ?? false);
|
|
5232
|
+
setPermissions(permResult);
|
|
5233
|
+
setInstanceInfo(formResult);
|
|
5234
|
+
setFormData(formResult?.data ?? null);
|
|
5235
|
+
if (permResult?.operations?.includes("VIEW_PROCESS") || permResult?.operations?.length > 0) {
|
|
5236
|
+
try {
|
|
5237
|
+
const progress = await getProcessProgress(request, formInstanceId);
|
|
5238
|
+
if (mountedRef.current) {
|
|
5239
|
+
setProgressList(progress);
|
|
5240
|
+
}
|
|
5241
|
+
} catch (error) {
|
|
5242
|
+
console.error("[useProcessDetail] Failed to load progress:", error);
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
const task = basicResult?.currentTask;
|
|
5246
|
+
if (approvalResult?.isApprover && task && (task.nodeType === "originator_return" || task.nodeType === "approval")) {
|
|
5247
|
+
try {
|
|
5248
|
+
const definition = await getProcessDefinition(request, formUuid);
|
|
5249
|
+
if (mountedRef.current) {
|
|
5250
|
+
setProcessDefinition(definition);
|
|
5251
|
+
}
|
|
5252
|
+
} catch (error) {
|
|
5253
|
+
console.error("[useProcessDetail] Failed to load process definition:", error);
|
|
5254
|
+
}
|
|
5255
|
+
}
|
|
5256
|
+
} catch (error) {
|
|
5257
|
+
console.error("[useProcessDetail] Failed to load data:", error);
|
|
5258
|
+
if (mountedRef.current) {
|
|
5259
|
+
setProcessInfo(null);
|
|
5260
|
+
setFormData(null);
|
|
5261
|
+
setInstanceInfo(null);
|
|
5262
|
+
}
|
|
5263
|
+
} finally {
|
|
5264
|
+
if (mountedRef.current) {
|
|
5265
|
+
setLoading(false);
|
|
5266
|
+
}
|
|
5267
|
+
}
|
|
5268
|
+
}, [request, formUuid, appType, formInstanceId]);
|
|
5269
|
+
(0, import_react46.useEffect)(() => {
|
|
5270
|
+
loadData();
|
|
5271
|
+
}, [loadData]);
|
|
5272
|
+
const switchToEdit = (0, import_react46.useCallback)(() => {
|
|
5273
|
+
setMode("edit");
|
|
5274
|
+
}, []);
|
|
5275
|
+
const switchToReadonly = (0, import_react46.useCallback)(() => {
|
|
5276
|
+
setMode("readonly");
|
|
5277
|
+
}, []);
|
|
5278
|
+
const refreshProgress = (0, import_react46.useCallback)(async () => {
|
|
5279
|
+
try {
|
|
5280
|
+
const [progress, basicResult] = await Promise.all([
|
|
5281
|
+
getProcessProgress(request, formInstanceId),
|
|
5282
|
+
getProcessBasic(request, formInstanceId)
|
|
5283
|
+
]);
|
|
5284
|
+
if (mountedRef.current) {
|
|
5285
|
+
setProgressList(progress);
|
|
5286
|
+
setProcessInfo(basicResult);
|
|
5287
|
+
}
|
|
5288
|
+
} catch (error) {
|
|
5289
|
+
console.error("[useProcessDetail] Failed to refresh progress:", error);
|
|
5290
|
+
}
|
|
5291
|
+
}, [request, formInstanceId]);
|
|
5292
|
+
return {
|
|
5293
|
+
loading,
|
|
5294
|
+
processInfo,
|
|
5295
|
+
processStatus,
|
|
5296
|
+
currentTask,
|
|
5297
|
+
progressList,
|
|
5298
|
+
formData,
|
|
5299
|
+
instanceInfo,
|
|
5300
|
+
isApprover,
|
|
5301
|
+
activeActions,
|
|
5302
|
+
fieldBehaviors,
|
|
5303
|
+
mode,
|
|
5304
|
+
isOriginatorReturn,
|
|
5305
|
+
isProcessCompleted,
|
|
5306
|
+
canWithdraw,
|
|
5307
|
+
switchToEdit,
|
|
5308
|
+
switchToReadonly,
|
|
5309
|
+
refreshProgress
|
|
5310
|
+
};
|
|
5311
|
+
}
|
|
5312
|
+
|
|
5313
|
+
// src/hooks/useApprovalActions.ts
|
|
5314
|
+
var import_react47 = require("react");
|
|
5315
|
+
function useApprovalActions(options) {
|
|
5316
|
+
const { formInstanceId, formUuid, appType, currentTaskId, onActionComplete, getFormValues } = options;
|
|
5317
|
+
const { api } = useFormContext();
|
|
5318
|
+
const request = api.request;
|
|
5319
|
+
const [isLoading, setIsLoading] = (0, import_react47.useState)(false);
|
|
5320
|
+
const [currentAction, setCurrentAction] = (0, import_react47.useState)(null);
|
|
5321
|
+
const [returnableNodes, setReturnableNodes] = (0, import_react47.useState)([]);
|
|
5322
|
+
const mountedRef = (0, import_react47.useRef)(true);
|
|
5323
|
+
(0, import_react47.useEffect)(() => {
|
|
5324
|
+
mountedRef.current = true;
|
|
5325
|
+
return () => {
|
|
5326
|
+
mountedRef.current = false;
|
|
5327
|
+
};
|
|
5328
|
+
}, []);
|
|
5329
|
+
const resetLoading = (0, import_react47.useCallback)(() => {
|
|
5330
|
+
if (mountedRef.current) {
|
|
5331
|
+
setIsLoading(false);
|
|
5332
|
+
setCurrentAction(null);
|
|
5333
|
+
}
|
|
5334
|
+
}, []);
|
|
5335
|
+
const approve = (0, import_react47.useCallback)(
|
|
5336
|
+
async (comments) => {
|
|
5337
|
+
setIsLoading(true);
|
|
5338
|
+
setCurrentAction("approve");
|
|
5339
|
+
try {
|
|
5340
|
+
const formValues = getFormValues?.();
|
|
5341
|
+
await handleApproval(request, {
|
|
5342
|
+
instanceId: formInstanceId,
|
|
5343
|
+
action: "approved",
|
|
5344
|
+
comments,
|
|
5345
|
+
appType,
|
|
5346
|
+
formUuid,
|
|
5347
|
+
updateFormDataJson: formValues ? JSON.stringify(formValues) : void 0
|
|
5348
|
+
});
|
|
5349
|
+
resetLoading();
|
|
5350
|
+
onActionComplete?.("approve");
|
|
5351
|
+
return true;
|
|
5352
|
+
} catch (error) {
|
|
5353
|
+
console.error("[useApprovalActions] approve failed:", error);
|
|
5354
|
+
resetLoading();
|
|
5355
|
+
return false;
|
|
5356
|
+
}
|
|
5357
|
+
},
|
|
5358
|
+
[request, formInstanceId, appType, formUuid, getFormValues, onActionComplete, resetLoading]
|
|
5359
|
+
);
|
|
5360
|
+
const reject = (0, import_react47.useCallback)(
|
|
5361
|
+
async (comments) => {
|
|
5362
|
+
setIsLoading(true);
|
|
5363
|
+
setCurrentAction("reject");
|
|
5364
|
+
try {
|
|
5365
|
+
const formValues = getFormValues?.();
|
|
5366
|
+
await handleApproval(request, {
|
|
5367
|
+
instanceId: formInstanceId,
|
|
5368
|
+
action: "rejected",
|
|
5369
|
+
comments,
|
|
5370
|
+
appType,
|
|
5371
|
+
formUuid,
|
|
5372
|
+
updateFormDataJson: formValues ? JSON.stringify(formValues) : void 0
|
|
5373
|
+
});
|
|
5374
|
+
resetLoading();
|
|
5375
|
+
onActionComplete?.("reject");
|
|
5376
|
+
return true;
|
|
5377
|
+
} catch (error) {
|
|
5378
|
+
console.error("[useApprovalActions] reject failed:", error);
|
|
5379
|
+
resetLoading();
|
|
5380
|
+
return false;
|
|
5381
|
+
}
|
|
5382
|
+
},
|
|
5383
|
+
[request, formInstanceId, appType, formUuid, getFormValues, onActionComplete, resetLoading]
|
|
5384
|
+
);
|
|
5385
|
+
const transfer = (0, import_react47.useCallback)(
|
|
5386
|
+
async (userId, reason) => {
|
|
5387
|
+
if (!currentTaskId) {
|
|
5388
|
+
console.error("[useApprovalActions] transfer failed: no currentTaskId");
|
|
5389
|
+
return false;
|
|
5390
|
+
}
|
|
5391
|
+
setIsLoading(true);
|
|
5392
|
+
setCurrentAction("transfer");
|
|
5393
|
+
try {
|
|
5394
|
+
await transferTask(request, {
|
|
5395
|
+
taskId: currentTaskId,
|
|
5396
|
+
newAssignee: userId,
|
|
5397
|
+
reason
|
|
5398
|
+
});
|
|
5399
|
+
resetLoading();
|
|
5400
|
+
onActionComplete?.("transfer");
|
|
5401
|
+
return true;
|
|
5402
|
+
} catch (error) {
|
|
5403
|
+
console.error("[useApprovalActions] transfer failed:", error);
|
|
5404
|
+
resetLoading();
|
|
5405
|
+
return false;
|
|
5406
|
+
}
|
|
5407
|
+
},
|
|
5408
|
+
[request, currentTaskId, onActionComplete, resetLoading]
|
|
5409
|
+
);
|
|
5410
|
+
const returnTo = (0, import_react47.useCallback)(
|
|
5411
|
+
async (nodeId, reason) => {
|
|
5412
|
+
if (!currentTaskId) {
|
|
5413
|
+
console.error("[useApprovalActions] returnTo failed: no currentTaskId");
|
|
5414
|
+
return false;
|
|
5415
|
+
}
|
|
5416
|
+
setIsLoading(true);
|
|
5417
|
+
setCurrentAction("return");
|
|
5418
|
+
try {
|
|
5419
|
+
await returnTask(request, {
|
|
5420
|
+
taskId: currentTaskId,
|
|
5421
|
+
targetNodeId: nodeId,
|
|
5422
|
+
reason
|
|
5423
|
+
});
|
|
5424
|
+
resetLoading();
|
|
5425
|
+
onActionComplete?.("return");
|
|
5426
|
+
return true;
|
|
5427
|
+
} catch (error) {
|
|
5428
|
+
console.error("[useApprovalActions] returnTo failed:", error);
|
|
5429
|
+
resetLoading();
|
|
5430
|
+
return false;
|
|
5431
|
+
}
|
|
5432
|
+
},
|
|
5433
|
+
[request, currentTaskId, onActionComplete, resetLoading]
|
|
5434
|
+
);
|
|
5435
|
+
const withdraw = (0, import_react47.useCallback)(
|
|
5436
|
+
async (reason) => {
|
|
5437
|
+
setIsLoading(true);
|
|
5438
|
+
setCurrentAction("withdraw");
|
|
5439
|
+
try {
|
|
5440
|
+
await withdrawProcess(request, {
|
|
5441
|
+
instanceId: formInstanceId,
|
|
5442
|
+
reason
|
|
5443
|
+
});
|
|
5444
|
+
resetLoading();
|
|
5445
|
+
onActionComplete?.("withdraw");
|
|
5446
|
+
return true;
|
|
5447
|
+
} catch (error) {
|
|
5448
|
+
console.error("[useApprovalActions] withdraw failed:", error);
|
|
5449
|
+
resetLoading();
|
|
5450
|
+
return false;
|
|
5451
|
+
}
|
|
5452
|
+
},
|
|
5453
|
+
[request, formInstanceId, onActionComplete, resetLoading]
|
|
5454
|
+
);
|
|
5455
|
+
const save = (0, import_react47.useCallback)(async () => {
|
|
5456
|
+
setIsLoading(true);
|
|
5457
|
+
setCurrentAction("save");
|
|
5458
|
+
try {
|
|
5459
|
+
const formValues = getFormValues?.() ?? {};
|
|
5460
|
+
await saveTask(request, {
|
|
5461
|
+
instanceId: formInstanceId,
|
|
5462
|
+
formUuid,
|
|
5463
|
+
appType,
|
|
5464
|
+
updateFormDataJson: JSON.stringify(formValues)
|
|
5465
|
+
});
|
|
5466
|
+
resetLoading();
|
|
5467
|
+
onActionComplete?.("save");
|
|
5468
|
+
return true;
|
|
5469
|
+
} catch (error) {
|
|
5470
|
+
console.error("[useApprovalActions] save failed:", error);
|
|
5471
|
+
resetLoading();
|
|
5472
|
+
return false;
|
|
5473
|
+
}
|
|
5474
|
+
}, [request, formInstanceId, formUuid, appType, getFormValues, onActionComplete, resetLoading]);
|
|
5475
|
+
const resubmit = (0, import_react47.useCallback)(
|
|
5476
|
+
async (comments) => {
|
|
5477
|
+
if (!currentTaskId) {
|
|
5478
|
+
console.error("[useApprovalActions] resubmit failed: no currentTaskId");
|
|
5479
|
+
return false;
|
|
5480
|
+
}
|
|
5481
|
+
setIsLoading(true);
|
|
5482
|
+
setCurrentAction("resubmit");
|
|
5483
|
+
try {
|
|
5484
|
+
const formValues = getFormValues?.() ?? {};
|
|
5485
|
+
await resubmitTask(request, {
|
|
5486
|
+
taskId: currentTaskId,
|
|
5487
|
+
formUuid,
|
|
5488
|
+
appType,
|
|
5489
|
+
updateFormDataJson: JSON.stringify(formValues),
|
|
5490
|
+
comments
|
|
5491
|
+
});
|
|
5492
|
+
resetLoading();
|
|
5493
|
+
onActionComplete?.("resubmit");
|
|
5494
|
+
return true;
|
|
5495
|
+
} catch (error) {
|
|
5496
|
+
console.error("[useApprovalActions] resubmit failed:", error);
|
|
5497
|
+
resetLoading();
|
|
5498
|
+
return false;
|
|
5499
|
+
}
|
|
5500
|
+
},
|
|
5501
|
+
[request, currentTaskId, formUuid, appType, getFormValues, onActionComplete, resetLoading]
|
|
5502
|
+
);
|
|
5503
|
+
const loadReturnableNodes = (0, import_react47.useCallback)(async () => {
|
|
5504
|
+
if (!currentTaskId) return;
|
|
5505
|
+
try {
|
|
5506
|
+
const nodes = await getReturnableNodes(request, currentTaskId);
|
|
5507
|
+
if (mountedRef.current) {
|
|
5508
|
+
setReturnableNodes(nodes);
|
|
5509
|
+
}
|
|
5510
|
+
} catch (error) {
|
|
5511
|
+
console.error("[useApprovalActions] loadReturnableNodes failed:", error);
|
|
5512
|
+
}
|
|
5513
|
+
}, [request, currentTaskId]);
|
|
5514
|
+
return {
|
|
5515
|
+
approve,
|
|
5516
|
+
reject,
|
|
5517
|
+
transfer,
|
|
5518
|
+
returnTo,
|
|
5519
|
+
withdraw,
|
|
5520
|
+
save,
|
|
5521
|
+
resubmit,
|
|
5522
|
+
isLoading,
|
|
5523
|
+
currentAction,
|
|
5524
|
+
returnableNodes,
|
|
5525
|
+
loadReturnableNodes
|
|
5526
|
+
};
|
|
5527
|
+
}
|
|
5528
|
+
|
|
5529
|
+
// src/hooks/useChangeRecords.ts
|
|
5530
|
+
var import_react48 = require("react");
|
|
5531
|
+
function useChangeRecords(options) {
|
|
5532
|
+
const { formUuid, appType, formInstanceId, pageSize = 20, autoLoad = true } = options;
|
|
5533
|
+
const { api } = useFormContext();
|
|
5534
|
+
const request = api.request;
|
|
5535
|
+
const [records, setRecords] = (0, import_react48.useState)([]);
|
|
5536
|
+
const [loading, setLoading] = (0, import_react48.useState)(false);
|
|
5537
|
+
const [total, setTotal] = (0, import_react48.useState)(0);
|
|
5538
|
+
const [page, setPage] = (0, import_react48.useState)(1);
|
|
5539
|
+
const mountedRef = (0, import_react48.useRef)(true);
|
|
5540
|
+
(0, import_react48.useEffect)(() => {
|
|
5541
|
+
mountedRef.current = true;
|
|
5542
|
+
return () => {
|
|
5543
|
+
mountedRef.current = false;
|
|
5544
|
+
};
|
|
5545
|
+
}, []);
|
|
5546
|
+
const fetchRecords = (0, import_react48.useCallback)(
|
|
5547
|
+
async (pageNum, append) => {
|
|
5548
|
+
if (!mountedRef.current) return;
|
|
5549
|
+
setLoading(true);
|
|
5550
|
+
try {
|
|
5551
|
+
const result = await getChangeRecords(request, {
|
|
5552
|
+
formUuid,
|
|
5553
|
+
appType,
|
|
5554
|
+
formInstanceId,
|
|
5555
|
+
page: pageNum,
|
|
5556
|
+
pageSize
|
|
5557
|
+
});
|
|
5558
|
+
if (!mountedRef.current) return;
|
|
5559
|
+
if (append) {
|
|
5560
|
+
setRecords((prev) => [...prev, ...result.records]);
|
|
5561
|
+
} else {
|
|
5562
|
+
setRecords(result.records);
|
|
5563
|
+
}
|
|
5564
|
+
setTotal(result.total);
|
|
5565
|
+
setPage(pageNum);
|
|
5566
|
+
} catch (error) {
|
|
5567
|
+
console.error("[useChangeRecords] Failed to load change records:", error);
|
|
5568
|
+
} finally {
|
|
5569
|
+
if (mountedRef.current) {
|
|
5570
|
+
setLoading(false);
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
},
|
|
5574
|
+
[request, formUuid, appType, formInstanceId, pageSize]
|
|
5575
|
+
);
|
|
5576
|
+
(0, import_react48.useEffect)(() => {
|
|
5577
|
+
if (autoLoad) {
|
|
5578
|
+
fetchRecords(1, false);
|
|
5579
|
+
}
|
|
5580
|
+
}, [autoLoad, fetchRecords]);
|
|
5581
|
+
const hasMore = records.length < total;
|
|
5582
|
+
const loadMore = (0, import_react48.useCallback)(async () => {
|
|
5583
|
+
if (!hasMore || loading) return;
|
|
5584
|
+
await fetchRecords(page + 1, true);
|
|
5585
|
+
}, [hasMore, loading, page, fetchRecords]);
|
|
5586
|
+
const refresh = (0, import_react48.useCallback)(async () => {
|
|
5587
|
+
setRecords([]);
|
|
5588
|
+
setPage(1);
|
|
5589
|
+
setTotal(0);
|
|
5590
|
+
await fetchRecords(1, false);
|
|
5591
|
+
}, [fetchRecords]);
|
|
5592
|
+
return {
|
|
5593
|
+
records,
|
|
5594
|
+
loading,
|
|
5595
|
+
total,
|
|
5596
|
+
page,
|
|
5597
|
+
loadMore,
|
|
5598
|
+
refresh,
|
|
5599
|
+
hasMore
|
|
5600
|
+
};
|
|
5601
|
+
}
|
|
5602
|
+
|
|
5603
|
+
// src/hooks/useFormNavigation.ts
|
|
5604
|
+
var import_react49 = require("react");
|
|
5605
|
+
function useFormNavigation(options) {
|
|
5606
|
+
const {
|
|
5607
|
+
appType,
|
|
5608
|
+
formUuid,
|
|
5609
|
+
formType = "form",
|
|
5610
|
+
mode = "redirect",
|
|
5611
|
+
redirectDelay = 3e3,
|
|
5612
|
+
onStay
|
|
5613
|
+
} = options;
|
|
5614
|
+
const [isRedirecting, setIsRedirecting] = (0, import_react49.useState)(false);
|
|
5615
|
+
const [countdown, setCountdown] = (0, import_react49.useState)(0);
|
|
5616
|
+
const timerRef = (0, import_react49.useRef)(null);
|
|
5617
|
+
const redirectTargetRef = (0, import_react49.useRef)(null);
|
|
5618
|
+
const mountedRef = (0, import_react49.useRef)(true);
|
|
5619
|
+
(0, import_react49.useEffect)(() => {
|
|
5620
|
+
mountedRef.current = true;
|
|
5621
|
+
return () => {
|
|
5622
|
+
mountedRef.current = false;
|
|
5623
|
+
if (timerRef.current) {
|
|
5624
|
+
clearInterval(timerRef.current);
|
|
5625
|
+
timerRef.current = null;
|
|
5626
|
+
}
|
|
5627
|
+
};
|
|
5628
|
+
}, []);
|
|
5629
|
+
const navigateToDetail = (0, import_react49.useCallback)(
|
|
5630
|
+
(formInstId) => {
|
|
5631
|
+
window.location.href = `/${appType}/formDetail/${formUuid}?formInstId=${formInstId}`;
|
|
5632
|
+
},
|
|
5633
|
+
[appType, formUuid]
|
|
5634
|
+
);
|
|
5635
|
+
const navigateToProcessDetail = (0, import_react49.useCallback)(
|
|
5636
|
+
(formInstId) => {
|
|
5637
|
+
window.location.href = `/${appType}/processDetail/${formUuid}?formInstId=${formInstId}`;
|
|
5638
|
+
},
|
|
5639
|
+
[appType, formUuid]
|
|
5640
|
+
);
|
|
5641
|
+
const startRedirectCountdown = (0, import_react49.useCallback)(
|
|
5642
|
+
(targetUrl) => {
|
|
5643
|
+
const totalSeconds = Math.ceil(redirectDelay / 1e3);
|
|
5644
|
+
setIsRedirecting(true);
|
|
5645
|
+
setCountdown(totalSeconds);
|
|
5646
|
+
redirectTargetRef.current = targetUrl;
|
|
5647
|
+
timerRef.current = setInterval(() => {
|
|
5648
|
+
if (!mountedRef.current) {
|
|
5649
|
+
if (timerRef.current) {
|
|
5650
|
+
clearInterval(timerRef.current);
|
|
5651
|
+
timerRef.current = null;
|
|
5652
|
+
}
|
|
5653
|
+
return;
|
|
5654
|
+
}
|
|
5655
|
+
setCountdown((prev) => {
|
|
5656
|
+
const next = prev - 1;
|
|
5657
|
+
if (next <= 0) {
|
|
5658
|
+
if (timerRef.current) {
|
|
5659
|
+
clearInterval(timerRef.current);
|
|
5660
|
+
timerRef.current = null;
|
|
5661
|
+
}
|
|
5662
|
+
setIsRedirecting(false);
|
|
5663
|
+
if (redirectTargetRef.current) {
|
|
5664
|
+
window.location.href = redirectTargetRef.current;
|
|
5665
|
+
}
|
|
5666
|
+
return 0;
|
|
5667
|
+
}
|
|
5668
|
+
return next;
|
|
5669
|
+
});
|
|
5670
|
+
}, 1e3);
|
|
5671
|
+
},
|
|
5672
|
+
[redirectDelay]
|
|
5673
|
+
);
|
|
5674
|
+
const cancelRedirect = (0, import_react49.useCallback)(() => {
|
|
5675
|
+
if (timerRef.current) {
|
|
5676
|
+
clearInterval(timerRef.current);
|
|
5677
|
+
timerRef.current = null;
|
|
5678
|
+
}
|
|
5679
|
+
setIsRedirecting(false);
|
|
5680
|
+
setCountdown(0);
|
|
5681
|
+
redirectTargetRef.current = null;
|
|
5682
|
+
}, []);
|
|
5683
|
+
const handlePostSubmit = (0, import_react49.useCallback)(
|
|
5684
|
+
(formInstId) => {
|
|
5685
|
+
if (mode === "stay") {
|
|
5686
|
+
onStay?.(formInstId);
|
|
5687
|
+
return;
|
|
5688
|
+
}
|
|
5689
|
+
if (mode === "callback") {
|
|
5690
|
+
onStay?.(formInstId);
|
|
5691
|
+
return;
|
|
5692
|
+
}
|
|
5693
|
+
const targetUrl = formType === "process" ? `/${appType}/processDetail/${formUuid}?formInstId=${formInstId}` : `/${appType}/formDetail/${formUuid}?formInstId=${formInstId}`;
|
|
5694
|
+
startRedirectCountdown(targetUrl);
|
|
5695
|
+
},
|
|
5696
|
+
[mode, formType, appType, formUuid, onStay, startRedirectCountdown]
|
|
5697
|
+
);
|
|
5698
|
+
return {
|
|
5699
|
+
navigateToDetail,
|
|
5700
|
+
navigateToProcessDetail,
|
|
5701
|
+
handlePostSubmit,
|
|
5702
|
+
isRedirecting,
|
|
5703
|
+
countdown,
|
|
5704
|
+
cancelRedirect
|
|
5705
|
+
};
|
|
5706
|
+
}
|
|
5707
|
+
|
|
5708
|
+
// src/hooks/useDraftStorage.ts
|
|
5709
|
+
var import_react50 = require("react");
|
|
5710
|
+
function getDraftKey(appType, formUuid) {
|
|
5711
|
+
return `${appType}__${formUuid}__draft`;
|
|
5712
|
+
}
|
|
5713
|
+
function readDraft(key) {
|
|
5714
|
+
try {
|
|
5715
|
+
const raw = localStorage.getItem(key);
|
|
5716
|
+
if (!raw) return null;
|
|
5717
|
+
const parsed = JSON.parse(raw);
|
|
5718
|
+
if (parsed && typeof parsed.data === "object" && typeof parsed.ts === "number") {
|
|
5719
|
+
return parsed;
|
|
5720
|
+
}
|
|
5721
|
+
return null;
|
|
5722
|
+
} catch {
|
|
5723
|
+
return null;
|
|
5724
|
+
}
|
|
5725
|
+
}
|
|
5726
|
+
function useDraftStorage(options) {
|
|
5727
|
+
const { appType, formUuid, autoRestore = false } = options;
|
|
5728
|
+
const key = getDraftKey(appType, formUuid);
|
|
5729
|
+
const [hasDraft, setHasDraft] = (0, import_react50.useState)(false);
|
|
5730
|
+
const [draftData, setDraftData] = (0, import_react50.useState)(null);
|
|
5731
|
+
const [draftTimestamp, setDraftTimestamp] = (0, import_react50.useState)(null);
|
|
5732
|
+
(0, import_react50.useEffect)(() => {
|
|
5733
|
+
const stored = readDraft(key);
|
|
5734
|
+
if (stored) {
|
|
5735
|
+
setHasDraft(true);
|
|
5736
|
+
setDraftTimestamp(stored.ts);
|
|
5737
|
+
if (autoRestore) {
|
|
5738
|
+
setDraftData(stored.data);
|
|
5739
|
+
}
|
|
5740
|
+
} else {
|
|
5741
|
+
setHasDraft(false);
|
|
5742
|
+
setDraftData(null);
|
|
5743
|
+
setDraftTimestamp(null);
|
|
5744
|
+
}
|
|
5745
|
+
}, [key, autoRestore]);
|
|
5746
|
+
const saveDraft = (0, import_react50.useCallback)(
|
|
5747
|
+
(data) => {
|
|
5748
|
+
const payload = { data, ts: Date.now() };
|
|
5749
|
+
try {
|
|
5750
|
+
localStorage.setItem(key, JSON.stringify(payload));
|
|
5751
|
+
setHasDraft(true);
|
|
5752
|
+
setDraftData(data);
|
|
5753
|
+
setDraftTimestamp(payload.ts);
|
|
5754
|
+
} catch (error) {
|
|
5755
|
+
console.error("[useDraftStorage] Failed to save draft:", error);
|
|
5756
|
+
}
|
|
5757
|
+
},
|
|
5758
|
+
[key]
|
|
5759
|
+
);
|
|
5760
|
+
const restoreDraft = (0, import_react50.useCallback)(() => {
|
|
5761
|
+
const stored = readDraft(key);
|
|
5762
|
+
if (stored) {
|
|
5763
|
+
setDraftData(stored.data);
|
|
5764
|
+
return stored.data;
|
|
5765
|
+
}
|
|
5766
|
+
return null;
|
|
5767
|
+
}, [key]);
|
|
5768
|
+
const clearDraft = (0, import_react50.useCallback)(() => {
|
|
5769
|
+
try {
|
|
5770
|
+
localStorage.removeItem(key);
|
|
5771
|
+
} catch (error) {
|
|
5772
|
+
console.error("[useDraftStorage] Failed to clear draft:", error);
|
|
5773
|
+
}
|
|
5774
|
+
setHasDraft(false);
|
|
5775
|
+
setDraftData(null);
|
|
5776
|
+
setDraftTimestamp(null);
|
|
5777
|
+
}, [key]);
|
|
5778
|
+
return {
|
|
5779
|
+
hasDraft,
|
|
5780
|
+
draftData,
|
|
5781
|
+
draftTimestamp,
|
|
5782
|
+
saveDraft,
|
|
5783
|
+
restoreDraft,
|
|
5784
|
+
clearDraft
|
|
5785
|
+
};
|
|
5786
|
+
}
|
|
5787
|
+
|
|
4794
5788
|
// src/utils/defineFormSchema.ts
|
|
4795
5789
|
function defineFormSchema(schema) {
|
|
4796
5790
|
return schema;
|
|
4797
5791
|
}
|
|
5792
|
+
|
|
5793
|
+
// src/modules/FormSummaryCard.tsx
|
|
5794
|
+
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
5795
|
+
var toneClasses = {
|
|
5796
|
+
brand: "bg-blue-50 text-blue-600",
|
|
5797
|
+
success: "bg-green-50 text-green-600",
|
|
5798
|
+
danger: "bg-red-50 text-red-600",
|
|
5799
|
+
neutral: "bg-gray-100 text-gray-500",
|
|
5800
|
+
warning: "bg-amber-50 text-amber-600"
|
|
5801
|
+
};
|
|
5802
|
+
var FormSummaryCard = ({
|
|
5803
|
+
title,
|
|
5804
|
+
formInstanceId,
|
|
5805
|
+
creator,
|
|
5806
|
+
createdAt,
|
|
5807
|
+
status,
|
|
5808
|
+
className = "",
|
|
5809
|
+
children
|
|
5810
|
+
}) => {
|
|
5811
|
+
const shortId = formInstanceId ? formInstanceId.slice(0, 8) : null;
|
|
5812
|
+
const renderAvatar = () => {
|
|
5813
|
+
if (!creator) return null;
|
|
5814
|
+
if (creator.avatar) {
|
|
5815
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
5816
|
+
"img",
|
|
5817
|
+
{
|
|
5818
|
+
src: creator.avatar,
|
|
5819
|
+
alt: creator.name,
|
|
5820
|
+
className: "w-7 h-7 rounded-full object-cover"
|
|
5821
|
+
}
|
|
5822
|
+
);
|
|
5823
|
+
}
|
|
5824
|
+
const initial = creator.name.charAt(0);
|
|
5825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "w-7 h-7 rounded-full bg-blue-100 text-blue-600 flex items-center justify-center text-xs font-medium", children: initial });
|
|
5826
|
+
};
|
|
5827
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 p-6 ${className}`, children: [
|
|
5828
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "flex items-start justify-between", children: [
|
|
5829
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
5830
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("h2", { className: "text-xl font-semibold text-gray-900 truncate", children: title }),
|
|
5831
|
+
shortId && /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("span", { className: "text-xs text-gray-400 mt-0.5 inline-block", children: [
|
|
5832
|
+
"#",
|
|
5833
|
+
shortId
|
|
5834
|
+
] })
|
|
5835
|
+
] }),
|
|
5836
|
+
status && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(
|
|
5837
|
+
"span",
|
|
5838
|
+
{
|
|
5839
|
+
className: `px-2.5 py-0.5 rounded-full text-xs font-medium whitespace-nowrap ${toneClasses[status.tone] || toneClasses.neutral}`,
|
|
5840
|
+
children: status.label
|
|
5841
|
+
}
|
|
5842
|
+
)
|
|
5843
|
+
] }),
|
|
5844
|
+
creator && /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "flex items-center gap-2 mt-4 text-sm text-gray-600", children: [
|
|
5845
|
+
renderAvatar(),
|
|
5846
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "font-medium", children: creator.name }),
|
|
5847
|
+
creator.department && /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(import_jsx_runtime75.Fragment, { children: [
|
|
5848
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "text-gray-300", children: "\xB7" }),
|
|
5849
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { children: creator.department })
|
|
5850
|
+
] }),
|
|
5851
|
+
createdAt && /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)(import_jsx_runtime75.Fragment, { children: [
|
|
5852
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "text-gray-300", children: "\xB7" }),
|
|
5853
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "text-gray-400", children: createdAt })
|
|
5854
|
+
] })
|
|
5855
|
+
] }),
|
|
5856
|
+
children && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "mt-4", children })
|
|
5857
|
+
] });
|
|
5858
|
+
};
|
|
5859
|
+
|
|
5860
|
+
// src/modules/ChangeRecords.tsx
|
|
5861
|
+
var import_react51 = require("react");
|
|
5862
|
+
var import_antd22 = require("antd");
|
|
5863
|
+
var import_icons = require("@ant-design/icons");
|
|
5864
|
+
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
5865
|
+
var ChangeRecords = ({
|
|
5866
|
+
records = [],
|
|
5867
|
+
loading = false,
|
|
5868
|
+
defaultExpanded = false,
|
|
5869
|
+
hasMore = false,
|
|
5870
|
+
onLoadMore,
|
|
5871
|
+
onExpand,
|
|
5872
|
+
className = "",
|
|
5873
|
+
renderItem
|
|
5874
|
+
}) => {
|
|
5875
|
+
const [expanded, setExpanded] = (0, import_react51.useState)(defaultExpanded);
|
|
5876
|
+
const handleToggle = () => {
|
|
5877
|
+
const next = !expanded;
|
|
5878
|
+
setExpanded(next);
|
|
5879
|
+
if (next && onExpand) {
|
|
5880
|
+
onExpand();
|
|
5881
|
+
}
|
|
5882
|
+
};
|
|
5883
|
+
const defaultRenderItem = (record) => /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "pl-4 py-3 border-l-2 border-gray-200 ml-1", children: [
|
|
5884
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "flex items-center gap-2 text-xs text-gray-400", children: [
|
|
5885
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: record.operatedAt }),
|
|
5886
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "text-gray-600 font-medium", children: record.operatorName }),
|
|
5887
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { children: "\u4FEE\u6539\u4E86" }),
|
|
5888
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "text-gray-800 font-medium", children: record.fieldLabel })
|
|
5889
|
+
] }),
|
|
5890
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "mt-1.5 text-sm text-gray-600 flex items-center gap-2", children: [
|
|
5891
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "bg-red-50 text-red-600 px-1.5 py-0.5 rounded text-xs line-through", children: formatValue(record.oldValue) }),
|
|
5892
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "text-gray-400", children: "\u2192" }),
|
|
5893
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "bg-green-50 text-green-600 px-1.5 py-0.5 rounded text-xs", children: formatValue(record.newValue) })
|
|
5894
|
+
] })
|
|
5895
|
+
] });
|
|
5896
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 ${className}`, children: [
|
|
5897
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
5898
|
+
"button",
|
|
5899
|
+
{
|
|
5900
|
+
type: "button",
|
|
5901
|
+
className: "w-full flex items-center justify-between p-6 text-left hover:bg-gray-50/50 transition-colors rounded-xl",
|
|
5902
|
+
onClick: handleToggle,
|
|
5903
|
+
children: [
|
|
5904
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5905
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("h3", { className: "text-lg font-semibold text-gray-900", children: "\u53D8\u66F4\u8BB0\u5F55" }),
|
|
5906
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "text-xs text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded-full", children: records.length })
|
|
5907
|
+
] }),
|
|
5908
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "text-gray-400 text-xs", children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(import_icons.UpOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(import_icons.DownOutlined, {}) })
|
|
5909
|
+
]
|
|
5910
|
+
}
|
|
5911
|
+
),
|
|
5912
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "px-6 pb-6", children: [
|
|
5913
|
+
loading && records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(import_antd22.Skeleton, { active: true, paragraph: { rows: 3 } }) : records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "text-sm text-gray-400 text-center py-4", children: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { className: "space-y-1", children: records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { children: renderItem ? renderItem(record) : defaultRenderItem(record) }, record.id)) }),
|
|
5914
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
5915
|
+
"button",
|
|
5916
|
+
{
|
|
5917
|
+
type: "button",
|
|
5918
|
+
className: "mt-4 w-full text-center text-sm text-blue-600 hover:text-blue-700 py-2 rounded-lg hover:bg-blue-50/50 transition-colors",
|
|
5919
|
+
onClick: onLoadMore,
|
|
5920
|
+
disabled: loading,
|
|
5921
|
+
children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
|
|
5922
|
+
}
|
|
5923
|
+
)
|
|
5924
|
+
] })
|
|
5925
|
+
] });
|
|
5926
|
+
};
|
|
5927
|
+
function formatValue(value) {
|
|
5928
|
+
if (value === null || value === void 0) return "\u7A7A";
|
|
5929
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
5930
|
+
return String(value);
|
|
5931
|
+
}
|
|
5932
|
+
|
|
5933
|
+
// src/modules/ApprovalTimeline.tsx
|
|
5934
|
+
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
5935
|
+
var toneClasses2 = {
|
|
5936
|
+
brand: "bg-blue-50 text-blue-600",
|
|
5937
|
+
success: "bg-green-50 text-green-600",
|
|
5938
|
+
danger: "bg-red-50 text-red-600",
|
|
5939
|
+
neutral: "bg-gray-100 text-gray-500",
|
|
5940
|
+
warning: "bg-amber-50 text-amber-600"
|
|
5941
|
+
};
|
|
5942
|
+
function getNodePhase(task) {
|
|
5943
|
+
if (task.status === "approved" || task.status === "rejected" || task.status === "returned" || task.status === "copied") {
|
|
5944
|
+
return "completed";
|
|
5945
|
+
}
|
|
5946
|
+
if (task.status === "pending" || task.status === "waiting") {
|
|
5947
|
+
return "active";
|
|
5948
|
+
}
|
|
5949
|
+
return "pending";
|
|
5950
|
+
}
|
|
5951
|
+
var ApprovalTimeline = ({
|
|
5952
|
+
tasks,
|
|
5953
|
+
className = "",
|
|
5954
|
+
renderNode,
|
|
5955
|
+
showRemarks = true,
|
|
5956
|
+
compactMode = false
|
|
5957
|
+
}) => {
|
|
5958
|
+
if (!tasks || tasks.length === 0) {
|
|
5959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 p-6 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "text-sm text-gray-400 text-center", children: "\u6682\u65E0\u5BA1\u6279\u8BB0\u5F55" }) });
|
|
5960
|
+
}
|
|
5961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: `${className}`, children: tasks.map((task, index) => {
|
|
5962
|
+
if (renderNode) {
|
|
5963
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { children: renderNode(task, index) }, task.taskId);
|
|
5964
|
+
}
|
|
5965
|
+
const phase = getNodePhase(task);
|
|
5966
|
+
const isLast = index === tasks.length - 1;
|
|
5967
|
+
const statusMeta = TASK_STATUS_META[task.status];
|
|
5968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "flex gap-4", children: [
|
|
5969
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
5970
|
+
phase === "completed" && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "w-3 h-3 rounded-full bg-green-500 flex-shrink-0" }),
|
|
5971
|
+
phase === "active" && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "w-3 h-3 rounded-full bg-blue-500 ring-4 ring-blue-100 flex-shrink-0" }),
|
|
5972
|
+
phase === "pending" && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "w-3 h-3 rounded-full bg-gray-300 flex-shrink-0" }),
|
|
5973
|
+
!isLast && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
5974
|
+
"div",
|
|
5975
|
+
{
|
|
5976
|
+
className: `w-0.5 flex-1 mt-1 ${phase === "completed" ? "bg-green-300" : phase === "active" ? "bg-blue-400" : "border-l-2 border-dashed border-gray-200"}`
|
|
5977
|
+
}
|
|
5978
|
+
)
|
|
5979
|
+
] }),
|
|
5980
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: `flex-1 pb-6 ${isLast ? "pb-0" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
|
|
5981
|
+
"div",
|
|
5982
|
+
{
|
|
5983
|
+
className: `rounded-lg p-4 ${phase === "completed" ? "bg-white border border-gray-100" : phase === "active" ? "bg-white border-l-4 border-l-blue-500 border border-gray-100 shadow-sm" : "bg-gray-50 border border-gray-100 opacity-60"}`,
|
|
5984
|
+
children: [
|
|
5985
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
5986
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "text-sm font-medium text-gray-900", children: task.nodeName }),
|
|
5987
|
+
statusMeta && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
5988
|
+
"span",
|
|
5989
|
+
{
|
|
5990
|
+
className: `px-2 py-0.5 rounded-full text-xs font-medium ${toneClasses2[statusMeta.tone] || toneClasses2.neutral}`,
|
|
5991
|
+
children: statusMeta.label
|
|
5992
|
+
}
|
|
5993
|
+
)
|
|
5994
|
+
] }),
|
|
5995
|
+
task.assigneeName && /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "mt-2 flex items-center gap-1.5 text-sm text-gray-600", children: [
|
|
5996
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "text-gray-400", children: "\u{1F464}" }),
|
|
5997
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { children: [
|
|
5998
|
+
phase === "active" ? "\u5F53\u524D\u5BA1\u6279\u4EBA: " : "",
|
|
5999
|
+
task.assigneeName
|
|
6000
|
+
] }),
|
|
6001
|
+
task.departmentName && /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(import_jsx_runtime77.Fragment, { children: [
|
|
6002
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "text-gray-300", children: "\xB7" }),
|
|
6003
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "text-gray-400", children: task.departmentName })
|
|
6004
|
+
] })
|
|
6005
|
+
] }),
|
|
6006
|
+
!compactMode && showRemarks && task.comments && /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "mt-2 bg-gray-50 rounded-md p-3 text-sm text-gray-600 italic", children: [
|
|
6007
|
+
"\u{1F4AC} \u201C",
|
|
6008
|
+
task.comments,
|
|
6009
|
+
"\u201D"
|
|
6010
|
+
] }),
|
|
6011
|
+
!compactMode && phase === "active" && !task.comments && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "mt-2 text-xs text-gray-400", children: "\u23F3 \u7B49\u5F85\u5904\u7406\u4E2D..." }),
|
|
6012
|
+
!compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "mt-2 text-xs text-gray-400", children: [
|
|
6013
|
+
"\u{1F550} ",
|
|
6014
|
+
task.actionAt || task.createdAt
|
|
6015
|
+
] }),
|
|
6016
|
+
compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "mt-1 text-xs text-gray-400", children: task.actionAt || task.createdAt })
|
|
6017
|
+
]
|
|
6018
|
+
}
|
|
6019
|
+
) })
|
|
6020
|
+
] }, task.taskId);
|
|
6021
|
+
}) });
|
|
6022
|
+
};
|
|
6023
|
+
|
|
6024
|
+
// src/modules/ApprovalActions.tsx
|
|
6025
|
+
var import_react52 = require("react");
|
|
6026
|
+
var import_antd23 = require("antd");
|
|
6027
|
+
var import_icons2 = require("@ant-design/icons");
|
|
6028
|
+
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
6029
|
+
var { TextArea: TextArea4 } = import_antd23.Input;
|
|
6030
|
+
var ApprovalActions = ({
|
|
6031
|
+
actions,
|
|
6032
|
+
onApprove,
|
|
6033
|
+
onReject,
|
|
6034
|
+
onTransfer,
|
|
6035
|
+
onReturn,
|
|
6036
|
+
onWithdraw,
|
|
6037
|
+
onSave,
|
|
6038
|
+
layout = "horizontal",
|
|
6039
|
+
maxVisible = 3,
|
|
6040
|
+
className = ""
|
|
6041
|
+
}) => {
|
|
6042
|
+
const [drawerAction, setDrawerAction] = (0, import_react52.useState)(null);
|
|
6043
|
+
const [comments, setComments] = (0, import_react52.useState)("");
|
|
6044
|
+
const [loading, setLoading] = (0, import_react52.useState)(false);
|
|
6045
|
+
const [saveLoading, setSaveLoading] = (0, import_react52.useState)(false);
|
|
6046
|
+
const handleOpenDrawer = (action) => {
|
|
6047
|
+
setComments("");
|
|
6048
|
+
setDrawerAction(action);
|
|
6049
|
+
};
|
|
6050
|
+
const handleConfirm = async () => {
|
|
6051
|
+
setLoading(true);
|
|
6052
|
+
try {
|
|
6053
|
+
if (drawerAction === "approve" && onApprove) {
|
|
6054
|
+
await onApprove(comments || void 0);
|
|
6055
|
+
} else if (drawerAction === "reject" && onReject) {
|
|
6056
|
+
await onReject(comments || void 0);
|
|
6057
|
+
} else if (drawerAction === "withdraw" && onWithdraw) {
|
|
6058
|
+
await onWithdraw(comments || void 0);
|
|
6059
|
+
}
|
|
6060
|
+
setDrawerAction(null);
|
|
6061
|
+
} finally {
|
|
6062
|
+
setLoading(false);
|
|
6063
|
+
}
|
|
6064
|
+
};
|
|
6065
|
+
const handleSave = async () => {
|
|
6066
|
+
if (!onSave) return;
|
|
6067
|
+
setSaveLoading(true);
|
|
6068
|
+
try {
|
|
6069
|
+
await onSave();
|
|
6070
|
+
} finally {
|
|
6071
|
+
setSaveLoading(false);
|
|
6072
|
+
}
|
|
6073
|
+
};
|
|
6074
|
+
const actionMap = {};
|
|
6075
|
+
actions.forEach((action) => {
|
|
6076
|
+
switch (action.action) {
|
|
6077
|
+
case "agree":
|
|
6078
|
+
actionMap["agree"] = {
|
|
6079
|
+
label: action.name.zh_CN || "\u540C\u610F",
|
|
6080
|
+
handler: () => handleOpenDrawer("approve"),
|
|
6081
|
+
type: "primary",
|
|
6082
|
+
color: "green"
|
|
6083
|
+
};
|
|
6084
|
+
break;
|
|
6085
|
+
case "rejected":
|
|
6086
|
+
actionMap["rejected"] = {
|
|
6087
|
+
label: action.name.zh_CN || "\u62D2\u7EDD",
|
|
6088
|
+
handler: () => handleOpenDrawer("reject"),
|
|
6089
|
+
type: "default"
|
|
6090
|
+
};
|
|
6091
|
+
break;
|
|
6092
|
+
case "transfer":
|
|
6093
|
+
actionMap["transfer"] = {
|
|
6094
|
+
label: action.name.zh_CN || "\u8F6C\u4EA4",
|
|
6095
|
+
handler: () => onTransfer?.(),
|
|
6096
|
+
type: "default"
|
|
6097
|
+
};
|
|
6098
|
+
break;
|
|
6099
|
+
case "return":
|
|
6100
|
+
actionMap["return"] = {
|
|
6101
|
+
label: action.name.zh_CN || "\u9000\u56DE",
|
|
6102
|
+
handler: () => onReturn?.(),
|
|
6103
|
+
type: "default"
|
|
6104
|
+
};
|
|
6105
|
+
break;
|
|
6106
|
+
case "withdraw":
|
|
6107
|
+
actionMap["withdraw"] = {
|
|
6108
|
+
label: action.name.zh_CN || "\u64A4\u9500",
|
|
6109
|
+
handler: () => handleOpenDrawer("withdraw"),
|
|
6110
|
+
type: "default"
|
|
6111
|
+
};
|
|
6112
|
+
break;
|
|
6113
|
+
case "save":
|
|
6114
|
+
actionMap["save"] = {
|
|
6115
|
+
label: action.name.zh_CN || "\u6682\u5B58",
|
|
6116
|
+
handler: handleSave,
|
|
6117
|
+
type: "default"
|
|
6118
|
+
};
|
|
6119
|
+
break;
|
|
6120
|
+
}
|
|
6121
|
+
});
|
|
6122
|
+
const allButtons = Object.entries(actionMap);
|
|
6123
|
+
const visibleButtons = allButtons.slice(0, maxVisible);
|
|
6124
|
+
const moreButtons = allButtons.slice(maxVisible);
|
|
6125
|
+
const drawerTitle = drawerAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : drawerAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : drawerAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1";
|
|
6126
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(import_jsx_runtime78.Fragment, { children: [
|
|
6127
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
6128
|
+
"div",
|
|
6129
|
+
{
|
|
6130
|
+
className: `${layout === "horizontal" ? "flex items-center gap-3" : "flex flex-col gap-2"} ${className}`,
|
|
6131
|
+
children: [
|
|
6132
|
+
visibleButtons.map(([key, btn]) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
6133
|
+
import_antd23.Button,
|
|
6134
|
+
{
|
|
6135
|
+
type: btn.type === "primary" ? "primary" : "default",
|
|
6136
|
+
className: btn.color === "green" ? "!bg-green-600 !border-green-600 hover:!bg-green-700" : "",
|
|
6137
|
+
onClick: btn.handler,
|
|
6138
|
+
loading: key === "save" && saveLoading,
|
|
6139
|
+
children: btn.label
|
|
6140
|
+
},
|
|
6141
|
+
key
|
|
6142
|
+
)),
|
|
6143
|
+
moreButtons.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
6144
|
+
import_antd23.Dropdown,
|
|
6145
|
+
{
|
|
6146
|
+
menu: {
|
|
6147
|
+
items: moreButtons.map(([key, btn]) => ({
|
|
6148
|
+
key,
|
|
6149
|
+
label: btn.label,
|
|
6150
|
+
onClick: btn.handler
|
|
6151
|
+
}))
|
|
6152
|
+
},
|
|
6153
|
+
trigger: ["click"],
|
|
6154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons2.MoreOutlined, {}), children: "\u66F4\u591A" })
|
|
6155
|
+
}
|
|
6156
|
+
)
|
|
6157
|
+
]
|
|
6158
|
+
}
|
|
6159
|
+
),
|
|
6160
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
6161
|
+
import_antd23.Drawer,
|
|
6162
|
+
{
|
|
6163
|
+
title: drawerTitle,
|
|
6164
|
+
open: drawerAction !== null,
|
|
6165
|
+
onClose: () => setDrawerAction(null),
|
|
6166
|
+
width: 400,
|
|
6167
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex justify-end gap-3", children: [
|
|
6168
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Button, { onClick: () => setDrawerAction(null), children: "\u53D6\u6D88" }),
|
|
6169
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(import_antd23.Button, { type: "primary", onClick: handleConfirm, loading, children: [
|
|
6170
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons2.LoadingOutlined, {}),
|
|
6171
|
+
"\u786E\u8BA4"
|
|
6172
|
+
] })
|
|
6173
|
+
] }),
|
|
6174
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
|
|
6175
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: drawerAction === "approve" ? "\u5BA1\u6279\u610F\u89C1\uFF08\u53EF\u9009\uFF09" : "\u8BF7\u8F93\u5165\u7406\u7531" }),
|
|
6176
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
6177
|
+
TextArea4,
|
|
6178
|
+
{
|
|
6179
|
+
rows: 4,
|
|
6180
|
+
value: comments,
|
|
6181
|
+
onChange: (e) => setComments(e.target.value),
|
|
6182
|
+
placeholder: drawerAction === "approve" ? "\u8BF7\u8F93\u5165\u5BA1\u6279\u610F\u89C1..." : drawerAction === "reject" ? "\u8BF7\u8F93\u5165\u62D2\u7EDD\u7406\u7531..." : "\u8BF7\u8F93\u5165\u64A4\u9500\u539F\u56E0...",
|
|
6183
|
+
maxLength: 500,
|
|
6184
|
+
showCount: true
|
|
6185
|
+
}
|
|
6186
|
+
)
|
|
6187
|
+
] }) })
|
|
6188
|
+
}
|
|
6189
|
+
)
|
|
6190
|
+
] });
|
|
6191
|
+
};
|
|
6192
|
+
|
|
6193
|
+
// src/modules/FormActionBar.tsx
|
|
6194
|
+
var import_react53 = require("react");
|
|
6195
|
+
var import_antd24 = require("antd");
|
|
6196
|
+
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
6197
|
+
var FormActionBar = ({
|
|
6198
|
+
actions,
|
|
6199
|
+
position = "bottom-fixed",
|
|
6200
|
+
className = ""
|
|
6201
|
+
}) => {
|
|
6202
|
+
const [loadingKeys, setLoadingKeys] = (0, import_react53.useState)(/* @__PURE__ */ new Set());
|
|
6203
|
+
const visibleActions = actions.filter((a) => a.visible !== false);
|
|
6204
|
+
const sortedActions = [...visibleActions].sort((a, b) => {
|
|
6205
|
+
if (a.type === "danger" && b.type !== "danger") return -1;
|
|
6206
|
+
if (a.type !== "danger" && b.type === "danger") return 1;
|
|
6207
|
+
if (a.type === "primary" && b.type !== "primary") return 1;
|
|
6208
|
+
if (a.type !== "primary" && b.type === "primary") return -1;
|
|
6209
|
+
return 0;
|
|
6210
|
+
});
|
|
6211
|
+
const handleClick = async (action) => {
|
|
6212
|
+
if (action.confirm) {
|
|
6213
|
+
import_antd24.Modal.confirm({
|
|
6214
|
+
title: action.confirm.title,
|
|
6215
|
+
content: action.confirm.content,
|
|
6216
|
+
okText: "\u786E\u8BA4",
|
|
6217
|
+
cancelText: "\u53D6\u6D88",
|
|
6218
|
+
onOk: async () => {
|
|
6219
|
+
await executeAction(action);
|
|
6220
|
+
}
|
|
6221
|
+
});
|
|
6222
|
+
} else {
|
|
6223
|
+
await executeAction(action);
|
|
6224
|
+
}
|
|
6225
|
+
};
|
|
6226
|
+
const executeAction = async (action) => {
|
|
6227
|
+
setLoadingKeys((prev) => new Set(prev).add(action.key));
|
|
6228
|
+
try {
|
|
6229
|
+
await action.onClick();
|
|
6230
|
+
} finally {
|
|
6231
|
+
setLoadingKeys((prev) => {
|
|
6232
|
+
const next = new Set(prev);
|
|
6233
|
+
next.delete(action.key);
|
|
6234
|
+
return next;
|
|
6235
|
+
});
|
|
6236
|
+
}
|
|
6237
|
+
};
|
|
6238
|
+
const isFixed = position === "bottom-fixed";
|
|
6239
|
+
const bar = /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
6240
|
+
"div",
|
|
6241
|
+
{
|
|
6242
|
+
className: `${isFixed ? "fixed bottom-0 left-0 right-0 z-50 backdrop-blur-lg bg-white/80 border-t border-gray-200 shadow-[0_-1px_3px_rgba(0,0,0,0.05)] px-6 py-3" : ""} ${className}`,
|
|
6243
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "flex items-center justify-end gap-3 flex-wrap md:flex-nowrap", children: sortedActions.map((action) => {
|
|
6244
|
+
const isLoading = action.loading || loadingKeys.has(action.key);
|
|
6245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
6246
|
+
import_antd24.Button,
|
|
6247
|
+
{
|
|
6248
|
+
type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
|
|
6249
|
+
danger: action.type === "danger",
|
|
6250
|
+
loading: isLoading,
|
|
6251
|
+
disabled: action.disabled,
|
|
6252
|
+
icon: action.icon,
|
|
6253
|
+
onClick: () => handleClick(action),
|
|
6254
|
+
className: "md:w-auto w-full",
|
|
6255
|
+
children: action.label
|
|
6256
|
+
},
|
|
6257
|
+
action.key
|
|
6258
|
+
);
|
|
6259
|
+
}) })
|
|
6260
|
+
}
|
|
6261
|
+
);
|
|
6262
|
+
if (isFixed) {
|
|
6263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(import_jsx_runtime79.Fragment, { children: [
|
|
6264
|
+
bar,
|
|
6265
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "h-16" })
|
|
6266
|
+
] });
|
|
6267
|
+
}
|
|
6268
|
+
return bar;
|
|
6269
|
+
};
|
|
6270
|
+
|
|
6271
|
+
// src/modules/DraftManager.tsx
|
|
6272
|
+
var import_antd25 = require("antd");
|
|
6273
|
+
var import_icons3 = require("@ant-design/icons");
|
|
6274
|
+
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
6275
|
+
function formatRelativeTime(timestamp) {
|
|
6276
|
+
const now = Date.now();
|
|
6277
|
+
const diff = now - timestamp;
|
|
6278
|
+
const minutes = Math.floor(diff / 6e4);
|
|
6279
|
+
const hours = Math.floor(diff / 36e5);
|
|
6280
|
+
const days = Math.floor(diff / 864e5);
|
|
6281
|
+
if (minutes < 1) return "\u521A\u521A";
|
|
6282
|
+
if (minutes < 60) return `${minutes}\u5206\u949F\u524D`;
|
|
6283
|
+
if (hours < 24) return `${hours}\u5C0F\u65F6\u524D`;
|
|
6284
|
+
return `${days}\u5929\u524D`;
|
|
6285
|
+
}
|
|
6286
|
+
var DraftManager = ({
|
|
6287
|
+
hasDraft,
|
|
6288
|
+
draftTimestamp,
|
|
6289
|
+
onRestore,
|
|
6290
|
+
onDiscard,
|
|
6291
|
+
className = ""
|
|
6292
|
+
}) => {
|
|
6293
|
+
if (!hasDraft) return null;
|
|
6294
|
+
const timeLabel = draftTimestamp ? formatRelativeTime(draftTimestamp) : null;
|
|
6295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
6296
|
+
"div",
|
|
6297
|
+
{
|
|
6298
|
+
className: `bg-blue-50 border border-blue-200 rounded-lg p-4 animate-[slideDown_0.3s_ease-out] ${className}`,
|
|
6299
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
|
|
6300
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
|
|
6301
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons3.EditOutlined, { className: "text-blue-500" }),
|
|
6302
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { children: [
|
|
6303
|
+
"\u68C0\u6D4B\u5230\u672A\u63D0\u4EA4\u7684\u8349\u7A3F",
|
|
6304
|
+
timeLabel && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "text-blue-500 ml-1", children: [
|
|
6305
|
+
"\uFF08\u4FDD\u5B58\u4E8E ",
|
|
6306
|
+
timeLabel,
|
|
6307
|
+
"\uFF09"
|
|
6308
|
+
] })
|
|
6309
|
+
] })
|
|
6310
|
+
] }),
|
|
6311
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
6312
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_antd25.Button, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
|
|
6313
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_antd25.Button, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
|
|
6314
|
+
] })
|
|
6315
|
+
] })
|
|
6316
|
+
}
|
|
6317
|
+
);
|
|
6318
|
+
};
|
|
6319
|
+
|
|
6320
|
+
// src/modules/ProcessPreview.tsx
|
|
6321
|
+
var import_antd26 = require("antd");
|
|
6322
|
+
var import_icons4 = require("@ant-design/icons");
|
|
6323
|
+
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
6324
|
+
var ProcessPreview = ({
|
|
6325
|
+
open,
|
|
6326
|
+
onClose,
|
|
6327
|
+
onConfirm,
|
|
6328
|
+
routes,
|
|
6329
|
+
loading = false
|
|
6330
|
+
}) => {
|
|
6331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
6332
|
+
import_antd26.Modal,
|
|
6333
|
+
{
|
|
6334
|
+
title: "\u6D41\u7A0B\u9884\u89C8",
|
|
6335
|
+
open,
|
|
6336
|
+
onCancel: onClose,
|
|
6337
|
+
width: 520,
|
|
6338
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex justify-end gap-3", children: [
|
|
6339
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_antd26.Button, { onClick: onClose, children: "\u53D6\u6D88" }),
|
|
6340
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_antd26.Button, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
|
|
6341
|
+
] }),
|
|
6342
|
+
children: loading && routes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_antd26.Skeleton, { active: true, paragraph: { rows: 4 } }) : routes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("p", { className: "text-sm text-gray-400 text-center py-8", children: "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) : /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "py-2", children: routes.map((route, index) => {
|
|
6343
|
+
const isLast = index === routes.length - 1;
|
|
6344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex gap-3", children: [
|
|
6345
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
6346
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "w-6 h-6 rounded-full bg-blue-50 border-2 border-blue-400 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_icons4.CheckCircleOutlined, { className: "text-blue-500 text-xs" }) }),
|
|
6347
|
+
!isLast && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
|
|
6348
|
+
] }),
|
|
6349
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
|
|
6350
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
|
|
6351
|
+
route.assignees && route.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "mt-1 flex items-center gap-1.5 flex-wrap", children: [
|
|
6352
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_icons4.UserOutlined, { className: "text-gray-400 text-xs" }),
|
|
6353
|
+
route.assignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
|
|
6354
|
+
"span",
|
|
6355
|
+
{
|
|
6356
|
+
className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
|
|
6357
|
+
children: assignee.name
|
|
6358
|
+
},
|
|
6359
|
+
assignee.id
|
|
6360
|
+
))
|
|
6361
|
+
] })
|
|
6362
|
+
] })
|
|
6363
|
+
] }, route.nodeId);
|
|
6364
|
+
}) })
|
|
6365
|
+
}
|
|
6366
|
+
);
|
|
6367
|
+
};
|
|
6368
|
+
|
|
6369
|
+
// src/templates/FormSubmitTemplate.tsx
|
|
6370
|
+
var import_react54 = require("react");
|
|
6371
|
+
var import_antd27 = require("antd");
|
|
6372
|
+
var import_icons5 = require("@ant-design/icons");
|
|
6373
|
+
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
6374
|
+
var SubmitSuccessCard = ({
|
|
6375
|
+
info,
|
|
6376
|
+
mode,
|
|
6377
|
+
isRedirecting,
|
|
6378
|
+
countdown,
|
|
6379
|
+
onContinue,
|
|
6380
|
+
onViewDetail,
|
|
6381
|
+
renderSuccess
|
|
6382
|
+
}) => {
|
|
6383
|
+
if (renderSuccess) {
|
|
6384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_jsx_runtime82.Fragment, { children: renderSuccess(info) });
|
|
6385
|
+
}
|
|
6386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex flex-col items-center py-16 animate-[fadeIn_0.3s_ease-out,scaleIn_0.3s_ease-out]", children: [
|
|
6387
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons5.CheckCircleFilled, { className: "text-2xl text-green-500" }) }),
|
|
6388
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
|
|
6389
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "text-sm text-gray-500 mb-6", children: info.message || "\u5DF2\u6210\u529F\u521B\u5EFA\u4E00\u6761\u65B0\u8BB0\u5F55" }),
|
|
6390
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex gap-3", children: [
|
|
6391
|
+
(mode === "stay" || mode === "redirect") && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd27.Button, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
|
|
6392
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd27.Button, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
|
|
6393
|
+
] }),
|
|
6394
|
+
isRedirecting && /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "mt-6 w-48", children: [
|
|
6395
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
|
|
6396
|
+
countdown,
|
|
6397
|
+
"\u79D2\u540E\u81EA\u52A8\u8DF3\u8F6C"
|
|
6398
|
+
] }),
|
|
6399
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "h-1 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
6400
|
+
"div",
|
|
6401
|
+
{
|
|
6402
|
+
className: "h-full bg-blue-500 transition-all duration-1000",
|
|
6403
|
+
style: { width: `${countdown / 3 * 100}%` }
|
|
6404
|
+
}
|
|
6405
|
+
) })
|
|
6406
|
+
] })
|
|
6407
|
+
] }) });
|
|
6408
|
+
};
|
|
6409
|
+
var InnerFormContent = ({
|
|
6410
|
+
schema,
|
|
6411
|
+
config,
|
|
6412
|
+
formType,
|
|
6413
|
+
submitSuccessMode,
|
|
6414
|
+
enableDraft,
|
|
6415
|
+
header,
|
|
6416
|
+
footer,
|
|
6417
|
+
beforeForm,
|
|
6418
|
+
afterForm,
|
|
6419
|
+
renderForm,
|
|
6420
|
+
renderSuccess,
|
|
6421
|
+
onSubmitSuccess
|
|
6422
|
+
}) => {
|
|
6423
|
+
const { validateAll, getFormData: getFormData2, resetForm } = useFormContext();
|
|
6424
|
+
const [submitted, setSubmitted] = (0, import_react54.useState)(false);
|
|
6425
|
+
const [successInfo, setSuccessInfo] = (0, import_react54.useState)(null);
|
|
6426
|
+
const [submitting, setSubmitting] = (0, import_react54.useState)(false);
|
|
6427
|
+
const { hasDraft, draftTimestamp, saveDraft, restoreDraft, clearDraft } = useDraftStorage({
|
|
6428
|
+
appType: config.appType,
|
|
6429
|
+
formUuid: config.formUuid
|
|
6430
|
+
});
|
|
6431
|
+
const { navigateToDetail, navigateToProcessDetail, isRedirecting, countdown, handlePostSubmit } = useFormNavigation({
|
|
6432
|
+
appType: config.appType,
|
|
6433
|
+
formUuid: config.formUuid,
|
|
6434
|
+
formType,
|
|
6435
|
+
mode: submitSuccessMode === "continue" ? "stay" : submitSuccessMode
|
|
6436
|
+
});
|
|
6437
|
+
const handleSubmit = (0, import_react54.useCallback)(async () => {
|
|
6438
|
+
const valid = await validateAll();
|
|
6439
|
+
if (!valid) return;
|
|
6440
|
+
setSubmitting(true);
|
|
6441
|
+
try {
|
|
6442
|
+
const formData = getFormData2();
|
|
6443
|
+
if (config.submit?.beforeSubmit) {
|
|
6444
|
+
const shouldContinue = await config.submit.beforeSubmit(formData);
|
|
6445
|
+
if (shouldContinue === false) {
|
|
6446
|
+
setSubmitting(false);
|
|
6447
|
+
return;
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
const formInstId = `inst_${Date.now()}`;
|
|
6451
|
+
if (config.submit?.afterSubmit) {
|
|
6452
|
+
await config.submit.afterSubmit({ formInstanceId: formInstId, data: formData });
|
|
6453
|
+
}
|
|
6454
|
+
if (enableDraft) {
|
|
6455
|
+
clearDraft();
|
|
6456
|
+
}
|
|
6457
|
+
onSubmitSuccess?.(formInstId);
|
|
6458
|
+
if (submitSuccessMode === "continue") {
|
|
6459
|
+
resetForm();
|
|
6460
|
+
} else {
|
|
6461
|
+
setSuccessInfo({ formInstanceId: formInstId });
|
|
6462
|
+
setSubmitted(true);
|
|
6463
|
+
handlePostSubmit(formInstId);
|
|
6464
|
+
}
|
|
6465
|
+
} catch (error) {
|
|
6466
|
+
console.error("[FormSubmitTemplate] Submit failed:", error);
|
|
6467
|
+
} finally {
|
|
6468
|
+
setSubmitting(false);
|
|
6469
|
+
}
|
|
6470
|
+
}, [
|
|
6471
|
+
validateAll,
|
|
6472
|
+
getFormData2,
|
|
6473
|
+
config,
|
|
6474
|
+
enableDraft,
|
|
6475
|
+
clearDraft,
|
|
6476
|
+
onSubmitSuccess,
|
|
6477
|
+
submitSuccessMode,
|
|
6478
|
+
resetForm,
|
|
6479
|
+
handlePostSubmit
|
|
6480
|
+
]);
|
|
6481
|
+
const handleSaveDraft = (0, import_react54.useCallback)(() => {
|
|
6482
|
+
const data = getFormData2();
|
|
6483
|
+
saveDraft(data);
|
|
6484
|
+
}, [getFormData2, saveDraft]);
|
|
6485
|
+
const handleRestoreDraft = (0, import_react54.useCallback)(() => {
|
|
6486
|
+
restoreDraft();
|
|
6487
|
+
}, [restoreDraft]);
|
|
6488
|
+
const handleContinue = (0, import_react54.useCallback)(() => {
|
|
6489
|
+
setSubmitted(false);
|
|
6490
|
+
setSuccessInfo(null);
|
|
6491
|
+
resetForm();
|
|
6492
|
+
}, [resetForm]);
|
|
6493
|
+
const handleViewDetail = (0, import_react54.useCallback)(() => {
|
|
6494
|
+
if (!successInfo) return;
|
|
6495
|
+
if (formType === "process") {
|
|
6496
|
+
navigateToProcessDetail(successInfo.formInstanceId);
|
|
6497
|
+
} else {
|
|
6498
|
+
navigateToDetail(successInfo.formInstanceId);
|
|
6499
|
+
}
|
|
6500
|
+
}, [successInfo, formType, navigateToDetail, navigateToProcessDetail]);
|
|
6501
|
+
const actions = [];
|
|
6502
|
+
if (enableDraft) {
|
|
6503
|
+
actions.push({
|
|
6504
|
+
key: "draft",
|
|
6505
|
+
label: "\u6682\u5B58",
|
|
6506
|
+
type: "default",
|
|
6507
|
+
onClick: handleSaveDraft
|
|
6508
|
+
});
|
|
6509
|
+
}
|
|
6510
|
+
actions.push({
|
|
6511
|
+
key: "reset",
|
|
6512
|
+
label: "\u91CD\u7F6E",
|
|
6513
|
+
type: "default",
|
|
6514
|
+
onClick: () => resetForm()
|
|
6515
|
+
});
|
|
6516
|
+
actions.push({
|
|
6517
|
+
key: "submit",
|
|
6518
|
+
label: "\u63D0\u4EA4",
|
|
6519
|
+
type: "primary",
|
|
6520
|
+
loading: submitting,
|
|
6521
|
+
onClick: handleSubmit
|
|
6522
|
+
});
|
|
6523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "min-h-screen bg-gray-50/50", children: [
|
|
6524
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: [
|
|
6525
|
+
header || /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "mb-6", children: [
|
|
6526
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h1", { className: "text-2xl font-bold text-gray-900", children: schema.formMeta.title }),
|
|
6527
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { className: "text-sm text-gray-500 mt-1", children: "\u8BF7\u586B\u5199\u4EE5\u4E0B\u4FE1\u606F" })
|
|
6528
|
+
] }),
|
|
6529
|
+
enableDraft && hasDraft && !submitted && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("div", { className: "mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
6530
|
+
DraftManager,
|
|
6531
|
+
{
|
|
6532
|
+
hasDraft,
|
|
6533
|
+
draftTimestamp,
|
|
6534
|
+
onRestore: handleRestoreDraft,
|
|
6535
|
+
onDiscard: clearDraft
|
|
6536
|
+
}
|
|
6537
|
+
) }),
|
|
6538
|
+
!submitted ? /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6 animate-[fadeIn_0.2s_ease-out]", children: [
|
|
6539
|
+
beforeForm,
|
|
6540
|
+
renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(FormRenderer, { columns: 2 }),
|
|
6541
|
+
afterForm
|
|
6542
|
+
] }) : successInfo && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
6543
|
+
SubmitSuccessCard,
|
|
6544
|
+
{
|
|
6545
|
+
info: successInfo,
|
|
6546
|
+
mode: submitSuccessMode,
|
|
6547
|
+
isRedirecting,
|
|
6548
|
+
countdown,
|
|
6549
|
+
onContinue: handleContinue,
|
|
6550
|
+
onViewDetail: handleViewDetail,
|
|
6551
|
+
renderSuccess
|
|
6552
|
+
}
|
|
6553
|
+
),
|
|
6554
|
+
footer
|
|
6555
|
+
] }),
|
|
6556
|
+
!submitted && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(FormActionBar, { actions, position: "bottom-fixed" })
|
|
6557
|
+
] });
|
|
6558
|
+
};
|
|
6559
|
+
var FormSubmitTemplate = ({
|
|
6560
|
+
schema,
|
|
6561
|
+
config,
|
|
6562
|
+
formType = "form",
|
|
6563
|
+
submitSuccessMode = "redirect",
|
|
6564
|
+
enableDraft = false,
|
|
6565
|
+
header,
|
|
6566
|
+
footer,
|
|
6567
|
+
beforeForm,
|
|
6568
|
+
afterForm,
|
|
6569
|
+
renderForm,
|
|
6570
|
+
renderSuccess,
|
|
6571
|
+
onSubmitSuccess
|
|
6572
|
+
}) => {
|
|
6573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(FormProvider, { schema, config, children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
|
|
6574
|
+
InnerFormContent,
|
|
6575
|
+
{
|
|
6576
|
+
schema,
|
|
6577
|
+
config,
|
|
6578
|
+
formType,
|
|
6579
|
+
submitSuccessMode,
|
|
6580
|
+
enableDraft,
|
|
6581
|
+
header,
|
|
6582
|
+
footer,
|
|
6583
|
+
beforeForm,
|
|
6584
|
+
afterForm,
|
|
6585
|
+
renderForm,
|
|
6586
|
+
renderSuccess,
|
|
6587
|
+
onSubmitSuccess
|
|
6588
|
+
}
|
|
6589
|
+
) });
|
|
6590
|
+
};
|
|
6591
|
+
|
|
6592
|
+
// src/templates/FormDetailTemplate.tsx
|
|
6593
|
+
var import_react55 = require("react");
|
|
6594
|
+
|
|
6595
|
+
// src/templates/PageSkeleton.tsx
|
|
6596
|
+
var import_antd28 = require("antd");
|
|
6597
|
+
var import_jsx_runtime83 = require("react/jsx-runtime");
|
|
6598
|
+
var CardSkeleton = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
|
|
6599
|
+
var SummaryCardSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(CardSkeleton, { children: [
|
|
6600
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-start justify-between", children: [
|
|
6601
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex-1", children: [
|
|
6602
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
|
|
6603
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "mt-2", children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }) })
|
|
6604
|
+
] }),
|
|
6605
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
|
|
6606
|
+
] }),
|
|
6607
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-center gap-3 mt-4", children: [
|
|
6608
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Avatar, { active: true, size: "small" }),
|
|
6609
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "small", style: { width: 120 } })
|
|
6610
|
+
] })
|
|
6611
|
+
] });
|
|
6612
|
+
var FormGridSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(CardSkeleton, { children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "space-y-2", children: [
|
|
6613
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }),
|
|
6614
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, block: true, style: { width: "100%" } })
|
|
6615
|
+
] }, i)) }) });
|
|
6616
|
+
var ActionBarSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "fixed bottom-0 left-0 right-0 backdrop-blur-lg bg-white/80 border-t border-gray-200 px-6 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex items-center justify-end gap-3", children: [
|
|
6617
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Button, { active: true, style: { width: 80 } }),
|
|
6618
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Button, { active: true, style: { width: 80 } })
|
|
6619
|
+
] }) });
|
|
6620
|
+
var TimelineSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(CardSkeleton, { children: [
|
|
6621
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
|
|
6622
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex gap-4", children: [
|
|
6623
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex flex-col items-center", children: [
|
|
6624
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
|
|
6625
|
+
i < 2 && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
|
|
6626
|
+
] }),
|
|
6627
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "flex-1 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton, { active: true, paragraph: { rows: 1 }, title: { width: "60%" } }) })
|
|
6628
|
+
] }, i)) })
|
|
6629
|
+
] });
|
|
6630
|
+
var PageSkeleton = ({ type }) => {
|
|
6631
|
+
if (type === "submit") {
|
|
6632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "space-y-6", children: [
|
|
6633
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "space-y-2", children: [
|
|
6634
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
|
|
6635
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd28.Skeleton.Input, { active: true, size: "small", style: { width: 300 } })
|
|
6636
|
+
] }),
|
|
6637
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(FormGridSkeleton, {}),
|
|
6638
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(ActionBarSkeleton, {})
|
|
6639
|
+
] });
|
|
6640
|
+
}
|
|
6641
|
+
if (type === "detail") {
|
|
6642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "space-y-6", children: [
|
|
6643
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(SummaryCardSkeleton, {}),
|
|
6644
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(FormGridSkeleton, {}),
|
|
6645
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(ActionBarSkeleton, {})
|
|
6646
|
+
] });
|
|
6647
|
+
}
|
|
6648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "space-y-6", children: [
|
|
6649
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(SummaryCardSkeleton, {}),
|
|
6650
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(FormGridSkeleton, {}),
|
|
6651
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(TimelineSkeleton, {}),
|
|
6652
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(ActionBarSkeleton, {})
|
|
6653
|
+
] });
|
|
6654
|
+
};
|
|
6655
|
+
|
|
6656
|
+
// src/templates/FormDetailTemplate.tsx
|
|
6657
|
+
var import_jsx_runtime84 = require("react/jsx-runtime");
|
|
6658
|
+
var InnerDetailContent = ({
|
|
6659
|
+
schema,
|
|
6660
|
+
formUuid,
|
|
6661
|
+
appType,
|
|
6662
|
+
formInstanceId,
|
|
6663
|
+
enableEdit = true,
|
|
6664
|
+
enableDelete = false,
|
|
6665
|
+
enableChangeRecords = false,
|
|
6666
|
+
header,
|
|
6667
|
+
footer,
|
|
6668
|
+
renderSummary,
|
|
6669
|
+
renderActions,
|
|
6670
|
+
onDelete,
|
|
6671
|
+
onSave
|
|
6672
|
+
}) => {
|
|
6673
|
+
const {
|
|
6674
|
+
loading,
|
|
6675
|
+
mode,
|
|
6676
|
+
formData,
|
|
6677
|
+
instanceInfo,
|
|
6678
|
+
fieldBehaviors,
|
|
6679
|
+
switchToEdit,
|
|
6680
|
+
switchToReadonly,
|
|
6681
|
+
saveChanges,
|
|
6682
|
+
deleteInstance,
|
|
6683
|
+
canEdit,
|
|
6684
|
+
canDelete,
|
|
6685
|
+
canViewChangeRecords
|
|
6686
|
+
} = useFormDetail({ formUuid, appType, formInstanceId });
|
|
6687
|
+
const {
|
|
6688
|
+
records,
|
|
6689
|
+
loading: recordsLoading,
|
|
6690
|
+
hasMore,
|
|
6691
|
+
loadMore,
|
|
6692
|
+
refresh: refreshRecords
|
|
6693
|
+
} = useChangeRecords({
|
|
6694
|
+
formUuid,
|
|
6695
|
+
appType,
|
|
6696
|
+
formInstanceId,
|
|
6697
|
+
autoLoad: enableChangeRecords && canViewChangeRecords
|
|
6698
|
+
});
|
|
6699
|
+
const handleSave = (0, import_react55.useCallback)(async () => {
|
|
6700
|
+
if (!formData) return;
|
|
6701
|
+
const success = await saveChanges(formData);
|
|
6702
|
+
if (success) {
|
|
6703
|
+
onSave?.(formData);
|
|
6704
|
+
}
|
|
6705
|
+
}, [formData, saveChanges, onSave]);
|
|
6706
|
+
const handleDelete = (0, import_react55.useCallback)(async () => {
|
|
6707
|
+
const success = await deleteInstance();
|
|
6708
|
+
if (success) {
|
|
6709
|
+
onDelete?.();
|
|
6710
|
+
}
|
|
6711
|
+
}, [deleteInstance, onDelete]);
|
|
6712
|
+
const handleCancel = (0, import_react55.useCallback)(() => {
|
|
6713
|
+
switchToReadonly();
|
|
6714
|
+
}, [switchToReadonly]);
|
|
6715
|
+
const readonlyActions = [];
|
|
6716
|
+
if (enableEdit && canEdit) {
|
|
6717
|
+
readonlyActions.push({
|
|
6718
|
+
key: "edit",
|
|
6719
|
+
label: "\u7F16\u8F91",
|
|
6720
|
+
type: "primary",
|
|
6721
|
+
onClick: switchToEdit
|
|
6722
|
+
});
|
|
6723
|
+
}
|
|
6724
|
+
if (enableDelete && canDelete) {
|
|
6725
|
+
readonlyActions.push({
|
|
6726
|
+
key: "delete",
|
|
6727
|
+
label: "\u5220\u9664",
|
|
6728
|
+
type: "danger",
|
|
6729
|
+
onClick: handleDelete,
|
|
6730
|
+
confirm: { title: "\u786E\u8BA4\u5220\u9664", content: "\u5220\u9664\u540E\u5C06\u65E0\u6CD5\u6062\u590D\uFF0C\u786E\u8BA4\u8981\u5220\u9664\u5417\uFF1F" }
|
|
6731
|
+
});
|
|
6732
|
+
}
|
|
6733
|
+
const editActions = [
|
|
6734
|
+
{ key: "cancel", label: "\u53D6\u6D88", type: "default", onClick: handleCancel },
|
|
6735
|
+
{ key: "save", label: "\u4FDD\u5B58", type: "primary", onClick: handleSave }
|
|
6736
|
+
];
|
|
6737
|
+
const currentActions = mode === "readonly" ? readonlyActions : editActions;
|
|
6738
|
+
const formConfig = {
|
|
6739
|
+
mode: mode === "edit" ? "edit" : "readonly",
|
|
6740
|
+
formUuid,
|
|
6741
|
+
appType,
|
|
6742
|
+
formInstanceId,
|
|
6743
|
+
permissions: {
|
|
6744
|
+
fieldPermissions: fieldBehaviors,
|
|
6745
|
+
operations: []
|
|
6746
|
+
}
|
|
6747
|
+
};
|
|
6748
|
+
if (loading) {
|
|
6749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(PageSkeleton, { type: "detail" }) }) });
|
|
6750
|
+
}
|
|
6751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "min-h-screen bg-gray-50/50", children: [
|
|
6752
|
+
/* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
|
|
6753
|
+
header,
|
|
6754
|
+
renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
|
|
6755
|
+
FormSummaryCard,
|
|
6756
|
+
{
|
|
6757
|
+
title: schema.formMeta.title,
|
|
6758
|
+
formInstanceId,
|
|
6759
|
+
creator: instanceInfo?.creator ? {
|
|
6760
|
+
name: instanceInfo.creator.name,
|
|
6761
|
+
avatar: instanceInfo.creator.avatar,
|
|
6762
|
+
department: instanceInfo.creator.department
|
|
6763
|
+
} : void 0,
|
|
6764
|
+
createdAt: instanceInfo?.createdAt,
|
|
6765
|
+
status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
|
|
6766
|
+
}
|
|
6767
|
+
),
|
|
6768
|
+
mode === "edit" && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "bg-blue-50 border border-blue-200 rounded-lg px-4 py-3 text-sm text-blue-700 transition-all duration-150", children: "\u6B63\u5728\u7F16\u8F91\uFF0C\u4FEE\u6539\u540E\u8BF7\u4FDD\u5B58" }),
|
|
6769
|
+
/* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormRenderer, { columns: 2 }) }) }),
|
|
6770
|
+
enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
|
|
6771
|
+
ChangeRecords,
|
|
6772
|
+
{
|
|
6773
|
+
records,
|
|
6774
|
+
loading: recordsLoading,
|
|
6775
|
+
hasMore,
|
|
6776
|
+
onLoadMore: loadMore,
|
|
6777
|
+
onExpand: refreshRecords
|
|
6778
|
+
}
|
|
6779
|
+
),
|
|
6780
|
+
footer
|
|
6781
|
+
] }) }),
|
|
6782
|
+
currentActions.length > 0 && (renderActions ? /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_jsx_runtime84.Fragment, { children: renderActions(currentActions) }) : /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormActionBar, { position: "bottom-fixed", actions: currentActions }))
|
|
6783
|
+
] });
|
|
6784
|
+
};
|
|
6785
|
+
var FormDetailTemplate = (props) => {
|
|
6786
|
+
const { schema, formUuid, appType, formInstanceId } = props;
|
|
6787
|
+
const wrapperConfig = {
|
|
6788
|
+
mode: "readonly",
|
|
6789
|
+
formUuid,
|
|
6790
|
+
appType,
|
|
6791
|
+
formInstanceId
|
|
6792
|
+
};
|
|
6793
|
+
return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(InnerDetailContent, { ...props }) });
|
|
6794
|
+
};
|
|
6795
|
+
|
|
6796
|
+
// src/templates/ProcessDetailTemplate.tsx
|
|
6797
|
+
var import_react56 = require("react");
|
|
6798
|
+
var import_jsx_runtime85 = require("react/jsx-runtime");
|
|
6799
|
+
function FormDataBridge({
|
|
6800
|
+
formDataRef
|
|
6801
|
+
}) {
|
|
6802
|
+
const { getFormData: getFormData2 } = useFormContext();
|
|
6803
|
+
formDataRef.current = getFormData2;
|
|
6804
|
+
return null;
|
|
6805
|
+
}
|
|
6806
|
+
var InnerProcessContent = ({
|
|
6807
|
+
schema,
|
|
6808
|
+
formUuid,
|
|
6809
|
+
appType,
|
|
6810
|
+
formInstanceId,
|
|
6811
|
+
header,
|
|
6812
|
+
renderTimeline,
|
|
6813
|
+
renderActions,
|
|
6814
|
+
beforeForm,
|
|
6815
|
+
afterForm,
|
|
6816
|
+
onActionComplete
|
|
6817
|
+
}) => {
|
|
6818
|
+
const formDataRef = (0, import_react56.useRef)(void 0);
|
|
6819
|
+
const {
|
|
6820
|
+
loading,
|
|
6821
|
+
processInfo,
|
|
6822
|
+
processStatus,
|
|
6823
|
+
currentTask,
|
|
6824
|
+
progressList,
|
|
6825
|
+
formData,
|
|
6826
|
+
isApprover,
|
|
6827
|
+
activeActions,
|
|
6828
|
+
fieldBehaviors,
|
|
6829
|
+
mode,
|
|
6830
|
+
isOriginatorReturn,
|
|
6831
|
+
canWithdraw,
|
|
6832
|
+
switchToEdit,
|
|
6833
|
+
switchToReadonly,
|
|
6834
|
+
refreshProgress
|
|
6835
|
+
} = useProcessDetail({ formUuid, appType, formInstanceId });
|
|
6836
|
+
const { approve, reject, withdraw, save, resubmit } = useApprovalActions({
|
|
6837
|
+
formInstanceId,
|
|
6838
|
+
formUuid,
|
|
6839
|
+
appType,
|
|
6840
|
+
currentTaskId: currentTask?.taskId,
|
|
6841
|
+
onActionComplete: async (action) => {
|
|
6842
|
+
onActionComplete?.(action);
|
|
6843
|
+
await refreshProgress();
|
|
6844
|
+
},
|
|
6845
|
+
getFormValues: () => formDataRef.current?.() ?? {}
|
|
6846
|
+
});
|
|
6847
|
+
const handleApprove = (0, import_react56.useCallback)(
|
|
6848
|
+
async (comments) => {
|
|
6849
|
+
await approve(comments);
|
|
6850
|
+
},
|
|
6851
|
+
[approve]
|
|
6852
|
+
);
|
|
6853
|
+
const handleReject = (0, import_react56.useCallback)(
|
|
6854
|
+
async (comments) => {
|
|
6855
|
+
await reject(comments);
|
|
6856
|
+
},
|
|
6857
|
+
[reject]
|
|
6858
|
+
);
|
|
6859
|
+
const handleWithdraw = (0, import_react56.useCallback)(
|
|
6860
|
+
async (reason) => {
|
|
6861
|
+
await withdraw(reason);
|
|
6862
|
+
},
|
|
6863
|
+
[withdraw]
|
|
6864
|
+
);
|
|
6865
|
+
const handleSave = (0, import_react56.useCallback)(async () => {
|
|
6866
|
+
await save();
|
|
6867
|
+
}, [save]);
|
|
6868
|
+
const handleResubmit = (0, import_react56.useCallback)(async () => {
|
|
6869
|
+
await resubmit();
|
|
6870
|
+
}, [resubmit]);
|
|
6871
|
+
const buildActions = () => {
|
|
6872
|
+
const actions = [];
|
|
6873
|
+
if (isApprover && activeActions.length > 0) {
|
|
6874
|
+
return [];
|
|
6875
|
+
}
|
|
6876
|
+
if (isOriginatorReturn) {
|
|
6877
|
+
if (mode === "readonly") {
|
|
6878
|
+
actions.push({
|
|
6879
|
+
key: "edit",
|
|
6880
|
+
label: "\u7F16\u8F91",
|
|
6881
|
+
type: "primary",
|
|
6882
|
+
onClick: switchToEdit
|
|
6883
|
+
});
|
|
6884
|
+
} else {
|
|
6885
|
+
actions.push({
|
|
6886
|
+
key: "cancel",
|
|
6887
|
+
label: "\u53D6\u6D88",
|
|
6888
|
+
type: "default",
|
|
6889
|
+
onClick: switchToReadonly
|
|
6890
|
+
});
|
|
6891
|
+
actions.push({
|
|
6892
|
+
key: "resubmit",
|
|
6893
|
+
label: "\u91CD\u65B0\u63D0\u4EA4",
|
|
6894
|
+
type: "primary",
|
|
6895
|
+
onClick: handleResubmit
|
|
6896
|
+
});
|
|
6897
|
+
}
|
|
6898
|
+
return actions;
|
|
6899
|
+
}
|
|
6900
|
+
if (canWithdraw) {
|
|
6901
|
+
actions.push({
|
|
6902
|
+
key: "withdraw",
|
|
6903
|
+
label: "\u64A4\u9500",
|
|
6904
|
+
type: "default",
|
|
6905
|
+
onClick: () => handleWithdraw(),
|
|
6906
|
+
confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u786E\u8BA4\u8981\u64A4\u9500\u6B64\u6D41\u7A0B\u5417\uFF1F" }
|
|
6907
|
+
});
|
|
6908
|
+
}
|
|
6909
|
+
return actions;
|
|
6910
|
+
};
|
|
6911
|
+
const formConfig = {
|
|
6912
|
+
mode: mode === "edit" ? "edit" : "readonly",
|
|
6913
|
+
formUuid,
|
|
6914
|
+
appType,
|
|
6915
|
+
formInstanceId,
|
|
6916
|
+
permissions: {
|
|
6917
|
+
fieldPermissions: fieldBehaviors,
|
|
6918
|
+
operations: []
|
|
6919
|
+
}
|
|
6920
|
+
};
|
|
6921
|
+
if (loading) {
|
|
6922
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(PageSkeleton, { type: "process" }) }) });
|
|
6923
|
+
}
|
|
6924
|
+
const bottomActions = buildActions();
|
|
6925
|
+
const showApprovalActions = isApprover && activeActions.length > 0;
|
|
6926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "min-h-screen bg-gray-50/50", children: [
|
|
6927
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
|
|
6928
|
+
header,
|
|
6929
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
6930
|
+
FormSummaryCard,
|
|
6931
|
+
{
|
|
6932
|
+
title: schema.formMeta.title,
|
|
6933
|
+
formInstanceId,
|
|
6934
|
+
creator: processInfo?.originatorName ? {
|
|
6935
|
+
name: processInfo.originatorName,
|
|
6936
|
+
department: processInfo.originatorDepartment
|
|
6937
|
+
} : void 0,
|
|
6938
|
+
createdAt: processInfo?.createdAt,
|
|
6939
|
+
status: processStatus ? PROCESS_STATUS_META[processStatus] : void 0
|
|
6940
|
+
}
|
|
6941
|
+
),
|
|
6942
|
+
beforeForm,
|
|
6943
|
+
mode === "edit" && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "bg-blue-50 border border-blue-200 rounded-lg px-4 py-3 text-sm text-blue-700 transition-all duration-150", children: "\u6B63\u5728\u7F16\u8F91\u8868\u5355\uFF0C\u4FEE\u6539\u540E\u8BF7\u91CD\u65B0\u63D0\u4EA4" }),
|
|
6944
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
|
|
6945
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormDataBridge, { formDataRef }),
|
|
6946
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormRenderer, { columns: 2 })
|
|
6947
|
+
] }) }),
|
|
6948
|
+
afterForm,
|
|
6949
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
|
|
6950
|
+
/* @__PURE__ */ (0, import_jsx_runtime85.jsx)("h3", { className: "text-lg font-semibold text-gray-900 mb-4", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
|
|
6951
|
+
renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ApprovalTimeline, { tasks: progressList, showRemarks: true })
|
|
6952
|
+
] })
|
|
6953
|
+
] }) }),
|
|
6954
|
+
showApprovalActions && (renderActions ? /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_jsx_runtime85.Fragment, { children: renderActions(activeActions) }) : /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "fixed bottom-0 left-0 right-0 z-50 backdrop-blur-lg bg-white/80 border-t border-gray-200 shadow-[0_-1px_3px_rgba(0,0,0,0.05)] px-6 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "max-w-4xl mx-auto flex items-center justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
|
|
6955
|
+
ApprovalActions,
|
|
6956
|
+
{
|
|
6957
|
+
actions: activeActions,
|
|
6958
|
+
onApprove: handleApprove,
|
|
6959
|
+
onReject: handleReject,
|
|
6960
|
+
onWithdraw: handleWithdraw,
|
|
6961
|
+
onSave: handleSave
|
|
6962
|
+
}
|
|
6963
|
+
) }) })),
|
|
6964
|
+
!showApprovalActions && bottomActions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormActionBar, { position: "bottom-fixed", actions: bottomActions })
|
|
6965
|
+
] });
|
|
6966
|
+
};
|
|
6967
|
+
var ProcessDetailTemplate = (props) => {
|
|
6968
|
+
const { schema, formUuid, appType, formInstanceId } = props;
|
|
6969
|
+
const wrapperConfig = {
|
|
6970
|
+
mode: "readonly",
|
|
6971
|
+
formUuid,
|
|
6972
|
+
appType,
|
|
6973
|
+
formInstanceId
|
|
6974
|
+
};
|
|
6975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(InnerProcessContent, { ...props }) });
|
|
6976
|
+
};
|
|
4798
6977
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4799
6978
|
0 && (module.exports = {
|
|
4800
6979
|
AddressField,
|
|
6980
|
+
ApprovalActions,
|
|
6981
|
+
ApprovalTimeline,
|
|
4801
6982
|
AssociationFormField,
|
|
4802
6983
|
AttachmentField,
|
|
4803
6984
|
CascadeDateField,
|
|
4804
6985
|
CascadeSelectField,
|
|
6986
|
+
ChangeRecords,
|
|
4805
6987
|
CheckboxField,
|
|
4806
6988
|
ComponentRegistryContext,
|
|
4807
6989
|
ComponentRegistryProvider,
|
|
4808
6990
|
DateField,
|
|
4809
6991
|
DepartmentSelectField,
|
|
4810
6992
|
DigitalSignatureField,
|
|
6993
|
+
DraftManager,
|
|
4811
6994
|
EditorField,
|
|
4812
6995
|
EmployeeSelectField,
|
|
4813
6996
|
FieldWrapper,
|
|
6997
|
+
FormActionBar,
|
|
4814
6998
|
FormActions,
|
|
4815
6999
|
FormContainer,
|
|
4816
7000
|
FormContext,
|
|
7001
|
+
FormDetailTemplate,
|
|
4817
7002
|
FormGrid,
|
|
4818
7003
|
FormProvider,
|
|
4819
7004
|
FormRenderer,
|
|
4820
7005
|
FormSection,
|
|
4821
7006
|
FormSteps,
|
|
7007
|
+
FormSubmitTemplate,
|
|
4822
7008
|
FormSummary,
|
|
7009
|
+
FormSummaryCard,
|
|
4823
7010
|
FormTabs,
|
|
4824
7011
|
ImageField,
|
|
4825
7012
|
JSONField,
|
|
4826
7013
|
LocationField,
|
|
4827
7014
|
MultiSelectField,
|
|
4828
7015
|
NumberField,
|
|
7016
|
+
PROCESS_STATUS_META,
|
|
7017
|
+
PageSkeleton,
|
|
7018
|
+
ProcessDetailTemplate,
|
|
7019
|
+
ProcessPreview,
|
|
4829
7020
|
RadioField,
|
|
4830
7021
|
SelectField,
|
|
4831
7022
|
SerialNumberField,
|
|
4832
7023
|
SubFormField,
|
|
7024
|
+
TASK_STATUS_META,
|
|
4833
7025
|
TextAreaField,
|
|
4834
7026
|
TextField,
|
|
4835
7027
|
TextareaField,
|
|
4836
7028
|
UserSelectField,
|
|
7029
|
+
checkUserApproval,
|
|
4837
7030
|
createFormRuntimeApi,
|
|
4838
7031
|
defaultComponentRegistry,
|
|
4839
7032
|
defineFormSchema,
|
|
7033
|
+
deleteFormData,
|
|
4840
7034
|
evaluateEffects,
|
|
7035
|
+
getChangeRecords,
|
|
7036
|
+
getFormData,
|
|
7037
|
+
getProcessBasic,
|
|
7038
|
+
getProcessDefinition,
|
|
7039
|
+
getProcessProgress,
|
|
7040
|
+
getReturnableNodes,
|
|
7041
|
+
getViewPermission,
|
|
7042
|
+
handleApproval,
|
|
7043
|
+
previewProcess,
|
|
7044
|
+
resubmitTask,
|
|
7045
|
+
returnTask,
|
|
7046
|
+
saveTask,
|
|
7047
|
+
transferTask,
|
|
7048
|
+
useApprovalActions,
|
|
7049
|
+
useChangeRecords,
|
|
4841
7050
|
useComponent,
|
|
4842
7051
|
useDeviceDetect,
|
|
7052
|
+
useDraftStorage,
|
|
4843
7053
|
useFieldBehavior,
|
|
7054
|
+
useFieldPermission,
|
|
4844
7055
|
useFormContext,
|
|
4845
7056
|
useFormData,
|
|
7057
|
+
useFormDetail,
|
|
4846
7058
|
useFormEngine,
|
|
7059
|
+
useFormNavigation,
|
|
4847
7060
|
useFormSubmit,
|
|
7061
|
+
useProcessDetail,
|
|
4848
7062
|
validateAllFields,
|
|
4849
|
-
validateField
|
|
7063
|
+
validateField,
|
|
7064
|
+
withdrawProcess
|
|
4850
7065
|
});
|
|
4851
7066
|
//# sourceMappingURL=index.js.map
|