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