sy-form-components 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4036,7 +4036,7 @@ function FormProvider({
4036
4036
  });
4037
4037
  }, []);
4038
4038
  const getFieldValue = useCallback((fieldId) => formData[fieldId], [formData]);
4039
- const getFormData = useCallback(() => ({ ...formData }), [formData]);
4039
+ const getFormData2 = useCallback(() => ({ ...formData }), [formData]);
4040
4040
  const validateFieldById = useCallback(
4041
4041
  async (fieldId) => {
4042
4042
  const field = schema.fields.find((f) => f.fieldId === fieldId);
@@ -4113,7 +4113,7 @@ function FormProvider({
4113
4113
  },
4114
4114
  setFieldValue,
4115
4115
  getFieldValue,
4116
- getFormData,
4116
+ getFormData: getFormData2,
4117
4117
  validateField: validateFieldById,
4118
4118
  validateAll,
4119
4119
  resetForm,
@@ -4133,7 +4133,7 @@ function FormProvider({
4133
4133
  config.submit,
4134
4134
  setFieldValue,
4135
4135
  getFieldValue,
4136
- getFormData,
4136
+ getFormData2,
4137
4137
  validateFieldById,
4138
4138
  validateAll,
4139
4139
  resetForm,
@@ -4204,14 +4204,14 @@ function FormActions({
4204
4204
  showReset = true,
4205
4205
  onSubmit
4206
4206
  }) {
4207
- const { mode, validateAll, getFormData, resetForm, api, config } = useFormContext();
4207
+ const { mode, validateAll, getFormData: getFormData2, resetForm, api, config } = useFormContext();
4208
4208
  const [isSubmitting, setIsSubmitting] = useState13(false);
4209
4209
  const [submitError, setSubmitError] = useState13(null);
4210
4210
  const handleSubmit = useCallback2(async () => {
4211
4211
  setSubmitError(null);
4212
4212
  const valid = await validateAll();
4213
4213
  if (!valid) return;
4214
- const values = getFormData();
4214
+ const values = getFormData2();
4215
4215
  setIsSubmitting(true);
4216
4216
  try {
4217
4217
  const beforeResult = await config.submit?.beforeSubmit?.(values);
@@ -4242,7 +4242,7 @@ function FormActions({
4242
4242
  } finally {
4243
4243
  setIsSubmitting(false);
4244
4244
  }
4245
- }, [api, config, getFormData, mode, onSubmit, validateAll]);
4245
+ }, [api, config, getFormData2, mode, onSubmit, validateAll]);
4246
4246
  const handleReset = useCallback2(() => {
4247
4247
  resetForm();
4248
4248
  }, [resetForm]);
@@ -4302,6 +4302,160 @@ function FormContainer({
4302
4302
  ] });
4303
4303
  }
4304
4304
 
4305
+ // src/core/constants.ts
4306
+ var PROCESS_STATUS_META = {
4307
+ running: { label: "\u5BA1\u6279\u4E2D", tone: "brand" },
4308
+ waiting: { label: "\u7B49\u5F85\u4E2D", tone: "neutral" },
4309
+ exception: { label: "\u6D41\u7A0B\u5F02\u5E38", tone: "danger" },
4310
+ completed: { label: "\u5DF2\u5B8C\u6210", tone: "success" },
4311
+ terminated: { label: "\u5DF2\u62D2\u7EDD", tone: "danger" },
4312
+ withdrawn: { label: "\u5DF2\u64A4\u9500", tone: "neutral" },
4313
+ pending: { label: "\u5F85\u5904\u7406", tone: "brand" },
4314
+ cancelled: { label: "\u5DF2\u53D6\u6D88", tone: "neutral" }
4315
+ };
4316
+ var TASK_STATUS_META = {
4317
+ pending: { label: "\u5F85\u5904\u7406", tone: "brand" },
4318
+ approved: { label: "\u5DF2\u540C\u610F", tone: "success" },
4319
+ rejected: { label: "\u5DF2\u62D2\u7EDD", tone: "danger" },
4320
+ returned: { label: "\u5DF2\u9000\u56DE", tone: "warning" },
4321
+ suspended: { label: "\u5DF2\u6302\u8D77", tone: "neutral" },
4322
+ cancelled: { label: "\u5DF2\u53D6\u6D88", tone: "neutral" },
4323
+ copied: { label: "\u5DF2\u6284\u9001", tone: "neutral" },
4324
+ waiting: { label: "\u7B49\u5F85\u4E2D", tone: "neutral" },
4325
+ simulated: { label: "\u672A\u5F00\u59CB", tone: "neutral" }
4326
+ };
4327
+
4328
+ // src/core/processApi.ts
4329
+ async function getProcessBasic(request, formInstId) {
4330
+ const response = await request({
4331
+ url: `/workflow/instance/${formInstId}/basic`,
4332
+ method: "get"
4333
+ });
4334
+ return response.data || response.result;
4335
+ }
4336
+ async function getProcessProgress(request, formInstId) {
4337
+ const response = await request({
4338
+ url: `/workflow/instance/${formInstId}`,
4339
+ method: "get"
4340
+ });
4341
+ return response.data || response.result || [];
4342
+ }
4343
+ async function checkUserApproval(request, formInstId) {
4344
+ const response = await request({
4345
+ url: `/workflow/instance/${formInstId}/permission`,
4346
+ method: "get"
4347
+ });
4348
+ return response.data || response.result;
4349
+ }
4350
+ async function handleApproval(request, params) {
4351
+ const response = await request({
4352
+ url: "/workflow/approve",
4353
+ method: "post",
4354
+ data: params
4355
+ });
4356
+ return response.data || response.result;
4357
+ }
4358
+ async function withdrawProcess(request, params) {
4359
+ const response = await request({
4360
+ url: `/workflow/instance/${params.instanceId}/withdraw`,
4361
+ method: "put",
4362
+ data: { reason: params.reason }
4363
+ });
4364
+ return response.data || response.result;
4365
+ }
4366
+ async function transferTask(request, params) {
4367
+ const response = await request({
4368
+ url: `/workflow/task/${params.taskId}/transfer`,
4369
+ method: "put",
4370
+ data: { newAssignee: params.newAssignee, reason: params.reason }
4371
+ });
4372
+ return response.data || response.result;
4373
+ }
4374
+ async function returnTask(request, params) {
4375
+ const response = await request({
4376
+ url: `/workflow/task/${params.taskId}/return`,
4377
+ method: "put",
4378
+ data: { targetNodeId: params.targetNodeId, reason: params.reason }
4379
+ });
4380
+ return response.data || response.result;
4381
+ }
4382
+ async function resubmitTask(request, params) {
4383
+ const response = await request({
4384
+ url: `/workflow/task/${params.taskId}/resubmit`,
4385
+ method: "post",
4386
+ data: {
4387
+ formUuid: params.formUuid,
4388
+ appType: params.appType,
4389
+ updateFormDataJson: params.updateFormDataJson,
4390
+ comments: params.comments
4391
+ }
4392
+ });
4393
+ return response.data || response.result;
4394
+ }
4395
+ async function saveTask(request, params) {
4396
+ const response = await request({
4397
+ url: "/workflow/task/save",
4398
+ method: "post",
4399
+ data: params
4400
+ });
4401
+ return response.data || response.result;
4402
+ }
4403
+ async function getReturnableNodes(request, taskId) {
4404
+ const response = await request({
4405
+ url: `/workflow/task/${taskId}/returnable-nodes`,
4406
+ method: "get"
4407
+ });
4408
+ return response.data || response.result || [];
4409
+ }
4410
+ async function previewProcess(request, params) {
4411
+ const response = await request({
4412
+ url: "/workflow/preview",
4413
+ method: "post",
4414
+ data: params
4415
+ });
4416
+ return response.data || response.result || [];
4417
+ }
4418
+ async function getProcessDefinition(request, formUuid) {
4419
+ const response = await request({
4420
+ url: "/workflow/definition/form",
4421
+ method: "get",
4422
+ params: { formUuid }
4423
+ });
4424
+ return response.data || response.result;
4425
+ }
4426
+ async function getFormData(request, params) {
4427
+ const response = await request({
4428
+ url: "/form/queryFormDataByFormInstanceId",
4429
+ method: "get",
4430
+ params
4431
+ });
4432
+ return response.data || response.result;
4433
+ }
4434
+ async function deleteFormData(request, params) {
4435
+ const response = await request({
4436
+ url: `/${params.appType}/v1/form/deleteFormData.json`,
4437
+ method: "post",
4438
+ data: params
4439
+ });
4440
+ return response.data || response.result;
4441
+ }
4442
+ async function getChangeRecords(request, params) {
4443
+ const response = await request({
4444
+ url: "/form/getFormDataChangeRecords",
4445
+ method: "get",
4446
+ params
4447
+ });
4448
+ return response.data || response.result;
4449
+ }
4450
+ async function getViewPermission(request, params) {
4451
+ const response = await request({
4452
+ url: "/permission/form-group/view-permissions",
4453
+ method: "get",
4454
+ params
4455
+ });
4456
+ return response.data || response.result;
4457
+ }
4458
+
4305
4459
  // src/layout/FormSection/index.tsx
4306
4460
  import { useState as useState14 } from "react";
4307
4461
  import { jsx as jsx70, jsxs as jsxs17 } from "react/jsx-runtime";
@@ -4502,7 +4656,7 @@ function FormSummary({
4502
4656
  const { schema, formData } = useFormContext();
4503
4657
  const displayFields = fields ? schema.fields.filter((f) => fields.includes(f.fieldId)) : schema.fields;
4504
4658
  const colClass = columnClasses2[columns];
4505
- const formatValue = (value) => {
4659
+ const formatValue2 = (value) => {
4506
4660
  if (value === null || value === void 0 || value === "") return "--";
4507
4661
  if (Array.isArray(value)) {
4508
4662
  if (value.length === 0) return "--";
@@ -4518,7 +4672,7 @@ function FormSummary({
4518
4672
  "data-testid": `summary-field-${field.fieldId}`,
4519
4673
  children: [
4520
4674
  /* @__PURE__ */ jsx74("span", { className: labelClassName ?? "text-sm text-gray-500 mb-1", children: field.label }),
4521
- /* @__PURE__ */ jsx74("span", { className: valueClassName ?? "text-sm text-gray-900", children: formatValue(formData[field.fieldId]) })
4675
+ /* @__PURE__ */ jsx74("span", { className: valueClassName ?? "text-sm text-gray-900", children: formatValue2(formData[field.fieldId]) })
4522
4676
  ]
4523
4677
  },
4524
4678
  field.fieldId
@@ -4575,7 +4729,7 @@ function useFormEngine(schema, config) {
4575
4729
  });
4576
4730
  }, []);
4577
4731
  const getFieldValue = useCallback3((fieldId) => formData[fieldId], [formData]);
4578
- const getFormData = useCallback3(() => ({ ...formData }), [formData]);
4732
+ const getFormData2 = useCallback3(() => ({ ...formData }), [formData]);
4579
4733
  const validateAll = useCallback3(async () => {
4580
4734
  const fieldRules = {};
4581
4735
  for (const field of schema.fields) {
@@ -4602,7 +4756,7 @@ function useFormEngine(schema, config) {
4602
4756
  formData,
4603
4757
  setFieldValue,
4604
4758
  getFieldValue,
4605
- getFormData,
4759
+ getFormData: getFormData2,
4606
4760
  validateAll,
4607
4761
  resetForm,
4608
4762
  mode: config.mode,
@@ -4631,7 +4785,7 @@ function useFormData(initialValues = {}) {
4631
4785
  },
4632
4786
  [formData]
4633
4787
  );
4634
- const getFormData = useCallback4(() => {
4788
+ const getFormData2 = useCallback4(() => {
4635
4789
  return { ...formData };
4636
4790
  }, [formData]);
4637
4791
  const resetForm = useCallback4(() => {
@@ -4642,7 +4796,7 @@ function useFormData(initialValues = {}) {
4642
4796
  formData,
4643
4797
  setFieldValue,
4644
4798
  getFieldValue,
4645
- getFormData,
4799
+ getFormData: getFormData2,
4646
4800
  resetForm,
4647
4801
  dirtyFields
4648
4802
  };
@@ -4706,60 +4860,2085 @@ function useFormSubmit(config) {
4706
4860
  return { submit, isSubmitting, submitError };
4707
4861
  }
4708
4862
 
4863
+ // src/hooks/useFieldPermission.ts
4864
+ import { useMemo as useMemo7, useCallback as useCallback6 } from "react";
4865
+ function useFieldPermission(options) {
4866
+ const { viewPermissions, processDefinition, currentTask, isApprover, mode } = options;
4867
+ const computeBehaviors = useCallback6(() => {
4868
+ const behaviors = {};
4869
+ if (!currentTask && viewPermissions) {
4870
+ const { fieldPermissions } = viewPermissions;
4871
+ for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
4872
+ if (perm === "FORM_FILED_HIDDEN") {
4873
+ behaviors[fieldId] = "HIDDEN";
4874
+ } else if (perm === "FORM_FILED_VIEW") {
4875
+ behaviors[fieldId] = "READONLY";
4876
+ } else if (perm === "FORM_FILED_EDIT") {
4877
+ behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
4878
+ }
4879
+ }
4880
+ return behaviors;
4881
+ }
4882
+ if (currentTask && !isApprover && viewPermissions) {
4883
+ const { fieldPermissions } = viewPermissions;
4884
+ for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
4885
+ if (perm === "FORM_FILED_HIDDEN") {
4886
+ behaviors[fieldId] = "HIDDEN";
4887
+ } else {
4888
+ behaviors[fieldId] = "READONLY";
4889
+ }
4890
+ }
4891
+ return behaviors;
4892
+ }
4893
+ if (currentTask && isApprover && currentTask.nodeType === "originator_return") {
4894
+ if (processDefinition?.flowConfig && processDefinition.startNodeId) {
4895
+ const startConfig = processDefinition.flowConfig[processDefinition.startNodeId];
4896
+ if (startConfig) {
4897
+ for (const [fieldId, behavior] of Object.entries(startConfig)) {
4898
+ behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
4899
+ }
4900
+ return behaviors;
4901
+ }
4902
+ }
4903
+ if (viewPermissions) {
4904
+ for (const fieldId of Object.keys(viewPermissions.fieldPermissions)) {
4905
+ if (viewPermissions.fieldPermissions[fieldId] === "FORM_FILED_HIDDEN") {
4906
+ behaviors[fieldId] = "HIDDEN";
4907
+ } else {
4908
+ behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
4909
+ }
4910
+ }
4911
+ }
4912
+ return behaviors;
4913
+ }
4914
+ if (currentTask && isApprover && processDefinition?.flowConfig) {
4915
+ const nodeConfig = processDefinition.flowConfig[currentTask.nodeId];
4916
+ if (nodeConfig) {
4917
+ for (const [fieldId, behavior] of Object.entries(nodeConfig)) {
4918
+ behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
4919
+ }
4920
+ return behaviors;
4921
+ }
4922
+ }
4923
+ if (viewPermissions) {
4924
+ const { fieldPermissions } = viewPermissions;
4925
+ for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
4926
+ if (perm === "FORM_FILED_HIDDEN") {
4927
+ behaviors[fieldId] = "HIDDEN";
4928
+ } else if (perm === "FORM_FILED_VIEW") {
4929
+ behaviors[fieldId] = "READONLY";
4930
+ } else if (perm === "FORM_FILED_EDIT") {
4931
+ behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
4932
+ }
4933
+ }
4934
+ }
4935
+ return behaviors;
4936
+ }, [viewPermissions, processDefinition, currentTask, isApprover, mode]);
4937
+ const fieldBehaviors = useMemo7(() => computeBehaviors(), [computeBehaviors]);
4938
+ return { fieldBehaviors, computeBehaviors };
4939
+ }
4940
+
4941
+ // src/hooks/useFormDetail.ts
4942
+ import { useState as useState20, useEffect as useEffect27, useCallback as useCallback7, useRef as useRef7 } from "react";
4943
+ function buildFieldBehaviors(permissions, mode) {
4944
+ const behaviors = {};
4945
+ if (!permissions) return behaviors;
4946
+ for (const [fieldId, perm] of Object.entries(permissions.fieldPermissions)) {
4947
+ if (perm === "FORM_FILED_HIDDEN") {
4948
+ behaviors[fieldId] = "HIDDEN";
4949
+ } else if (perm === "FORM_FILED_VIEW") {
4950
+ behaviors[fieldId] = "READONLY";
4951
+ } else if (perm === "FORM_FILED_EDIT") {
4952
+ behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
4953
+ }
4954
+ }
4955
+ return behaviors;
4956
+ }
4957
+ function useFormDetail(options) {
4958
+ const { formUuid, appType, formInstanceId, onPermissionDenied } = options;
4959
+ const { api } = useFormContext();
4960
+ const request = api.request;
4961
+ const [loading, setLoading] = useState20(true);
4962
+ const [mode, setMode] = useState20("readonly");
4963
+ const [formData, setFormData] = useState20(null);
4964
+ const [instanceInfo, setInstanceInfo] = useState20(null);
4965
+ const [permissions, setPermissions] = useState20(null);
4966
+ const mountedRef = useRef7(true);
4967
+ useEffect27(() => {
4968
+ mountedRef.current = true;
4969
+ return () => {
4970
+ mountedRef.current = false;
4971
+ };
4972
+ }, []);
4973
+ const loadData = useCallback7(async () => {
4974
+ if (!mountedRef.current) return;
4975
+ setLoading(true);
4976
+ try {
4977
+ const [permResult, formResult] = await Promise.all([
4978
+ getViewPermission(request, { formUuid, appType, formInstanceId }),
4979
+ getFormData(request, { formInstanceId, appType, formUuid })
4980
+ ]);
4981
+ if (!mountedRef.current) return;
4982
+ if (!permResult || !permResult.operations || permResult.operations.length === 0) {
4983
+ onPermissionDenied?.();
4984
+ }
4985
+ setPermissions(permResult);
4986
+ setInstanceInfo(formResult);
4987
+ setFormData(formResult?.data ?? null);
4988
+ } catch (error) {
4989
+ console.error("[useFormDetail] Failed to load data:", error);
4990
+ if (mountedRef.current) {
4991
+ setPermissions(null);
4992
+ setInstanceInfo(null);
4993
+ setFormData(null);
4994
+ }
4995
+ } finally {
4996
+ if (mountedRef.current) {
4997
+ setLoading(false);
4998
+ }
4999
+ }
5000
+ }, [request, formUuid, appType, formInstanceId, onPermissionDenied]);
5001
+ useEffect27(() => {
5002
+ loadData();
5003
+ }, [loadData]);
5004
+ const fieldBehaviors = buildFieldBehaviors(permissions, mode);
5005
+ const canEdit = permissions?.operations?.includes("EDIT") ?? false;
5006
+ const canDelete = permissions?.operations?.includes("DELETE") ?? false;
5007
+ const canViewChangeRecords = permissions?.operations?.includes("VIEW_CHANGE_RECORDS") ?? false;
5008
+ const switchToEdit = useCallback7(() => {
5009
+ setMode("edit");
5010
+ loadData();
5011
+ }, [loadData]);
5012
+ const switchToReadonly = useCallback7(() => {
5013
+ setMode("readonly");
5014
+ }, []);
5015
+ const saveChanges = useCallback7(
5016
+ async (values) => {
5017
+ try {
5018
+ await api.updateFormData({
5019
+ formInstanceId,
5020
+ formUuid,
5021
+ appType,
5022
+ updateFormDataJson: JSON.stringify(values)
5023
+ });
5024
+ if (mountedRef.current) {
5025
+ setFormData(values);
5026
+ setMode("readonly");
5027
+ }
5028
+ return true;
5029
+ } catch (error) {
5030
+ console.error("[useFormDetail] Failed to save changes:", error);
5031
+ return false;
5032
+ }
5033
+ },
5034
+ [api, formInstanceId, formUuid, appType]
5035
+ );
5036
+ const deleteInstance = useCallback7(async () => {
5037
+ try {
5038
+ await deleteFormData(request, { formInstanceId, appType, formUuid });
5039
+ return true;
5040
+ } catch (error) {
5041
+ console.error("[useFormDetail] Failed to delete instance:", error);
5042
+ return false;
5043
+ }
5044
+ }, [request, formInstanceId, appType, formUuid]);
5045
+ return {
5046
+ loading,
5047
+ mode,
5048
+ formData,
5049
+ instanceInfo,
5050
+ permissions,
5051
+ fieldBehaviors,
5052
+ switchToEdit,
5053
+ switchToReadonly,
5054
+ saveChanges,
5055
+ deleteInstance,
5056
+ canEdit,
5057
+ canDelete,
5058
+ canViewChangeRecords
5059
+ };
5060
+ }
5061
+
5062
+ // src/hooks/useProcessDetail.ts
5063
+ import { useState as useState21, useEffect as useEffect28, useCallback as useCallback8, useRef as useRef8 } from "react";
5064
+ function useProcessDetail(options) {
5065
+ const { formUuid, appType, formInstanceId } = options;
5066
+ const { api } = useFormContext();
5067
+ const request = api.request;
5068
+ const [loading, setLoading] = useState21(true);
5069
+ const [mode, setMode] = useState21("readonly");
5070
+ const [processInfo, setProcessInfo] = useState21(null);
5071
+ const [progressList, setProgressList] = useState21([]);
5072
+ const [formData, setFormData] = useState21(null);
5073
+ const [instanceInfo, setInstanceInfo] = useState21(null);
5074
+ const [isApprover, setIsApprover] = useState21(false);
5075
+ const [canWithdraw, setCanWithdraw] = useState21(false);
5076
+ const [permissions, setPermissions] = useState21(null);
5077
+ const [processDefinition, setProcessDefinition] = useState21(null);
5078
+ const mountedRef = useRef8(true);
5079
+ useEffect28(() => {
5080
+ mountedRef.current = true;
5081
+ return () => {
5082
+ mountedRef.current = false;
5083
+ };
5084
+ }, []);
5085
+ const currentTask = processInfo?.currentTask ?? null;
5086
+ const processStatus = processInfo?.processStatus ?? null;
5087
+ const isOriginatorReturn = currentTask?.nodeType === "originator_return";
5088
+ const isProcessCompleted = processStatus === "completed" || processStatus === "terminated";
5089
+ const { fieldBehaviors } = useFieldPermission({
5090
+ viewPermissions: permissions ?? void 0,
5091
+ processDefinition: processDefinition ?? void 0,
5092
+ currentTask: currentTask ?? void 0,
5093
+ isApprover,
5094
+ mode
5095
+ });
5096
+ const activeActions = isApprover && currentTask?.actions ? currentTask.actions : [];
5097
+ const loadData = useCallback8(async () => {
5098
+ if (!mountedRef.current) return;
5099
+ setLoading(true);
5100
+ try {
5101
+ const [basicResult, approvalResult, permResult, formResult] = await Promise.all([
5102
+ getProcessBasic(request, formInstanceId),
5103
+ checkUserApproval(request, formInstanceId),
5104
+ getViewPermission(request, { formUuid, appType, formInstanceId }),
5105
+ getFormData(request, { formInstanceId, appType, formUuid })
5106
+ ]);
5107
+ if (!mountedRef.current) return;
5108
+ setProcessInfo(basicResult);
5109
+ setIsApprover(approvalResult?.isApprover ?? false);
5110
+ setCanWithdraw(approvalResult?.canUndo ?? false);
5111
+ setPermissions(permResult);
5112
+ setInstanceInfo(formResult);
5113
+ setFormData(formResult?.data ?? null);
5114
+ if (permResult?.operations?.includes("VIEW_PROCESS") || permResult?.operations?.length > 0) {
5115
+ try {
5116
+ const progress = await getProcessProgress(request, formInstanceId);
5117
+ if (mountedRef.current) {
5118
+ setProgressList(progress);
5119
+ }
5120
+ } catch (error) {
5121
+ console.error("[useProcessDetail] Failed to load progress:", error);
5122
+ }
5123
+ }
5124
+ const task = basicResult?.currentTask;
5125
+ if (approvalResult?.isApprover && task && (task.nodeType === "originator_return" || task.nodeType === "approval")) {
5126
+ try {
5127
+ const definition = await getProcessDefinition(request, formUuid);
5128
+ if (mountedRef.current) {
5129
+ setProcessDefinition(definition);
5130
+ }
5131
+ } catch (error) {
5132
+ console.error("[useProcessDetail] Failed to load process definition:", error);
5133
+ }
5134
+ }
5135
+ } catch (error) {
5136
+ console.error("[useProcessDetail] Failed to load data:", error);
5137
+ if (mountedRef.current) {
5138
+ setProcessInfo(null);
5139
+ setFormData(null);
5140
+ setInstanceInfo(null);
5141
+ }
5142
+ } finally {
5143
+ if (mountedRef.current) {
5144
+ setLoading(false);
5145
+ }
5146
+ }
5147
+ }, [request, formUuid, appType, formInstanceId]);
5148
+ useEffect28(() => {
5149
+ loadData();
5150
+ }, [loadData]);
5151
+ const switchToEdit = useCallback8(() => {
5152
+ setMode("edit");
5153
+ }, []);
5154
+ const switchToReadonly = useCallback8(() => {
5155
+ setMode("readonly");
5156
+ }, []);
5157
+ const refreshProgress = useCallback8(async () => {
5158
+ try {
5159
+ const [progress, basicResult] = await Promise.all([
5160
+ getProcessProgress(request, formInstanceId),
5161
+ getProcessBasic(request, formInstanceId)
5162
+ ]);
5163
+ if (mountedRef.current) {
5164
+ setProgressList(progress);
5165
+ setProcessInfo(basicResult);
5166
+ }
5167
+ } catch (error) {
5168
+ console.error("[useProcessDetail] Failed to refresh progress:", error);
5169
+ }
5170
+ }, [request, formInstanceId]);
5171
+ return {
5172
+ loading,
5173
+ processInfo,
5174
+ processStatus,
5175
+ currentTask,
5176
+ progressList,
5177
+ formData,
5178
+ instanceInfo,
5179
+ isApprover,
5180
+ activeActions,
5181
+ fieldBehaviors,
5182
+ mode,
5183
+ isOriginatorReturn,
5184
+ isProcessCompleted,
5185
+ canWithdraw,
5186
+ switchToEdit,
5187
+ switchToReadonly,
5188
+ refreshProgress
5189
+ };
5190
+ }
5191
+
5192
+ // src/hooks/useApprovalActions.ts
5193
+ import { useState as useState22, useCallback as useCallback9, useRef as useRef9, useEffect as useEffect29 } from "react";
5194
+ function useApprovalActions(options) {
5195
+ const { formInstanceId, formUuid, appType, currentTaskId, onActionComplete, getFormValues } = options;
5196
+ const { api } = useFormContext();
5197
+ const request = api.request;
5198
+ const [isLoading, setIsLoading] = useState22(false);
5199
+ const [currentAction, setCurrentAction] = useState22(null);
5200
+ const [returnableNodes, setReturnableNodes] = useState22([]);
5201
+ const mountedRef = useRef9(true);
5202
+ useEffect29(() => {
5203
+ mountedRef.current = true;
5204
+ return () => {
5205
+ mountedRef.current = false;
5206
+ };
5207
+ }, []);
5208
+ const resetLoading = useCallback9(() => {
5209
+ if (mountedRef.current) {
5210
+ setIsLoading(false);
5211
+ setCurrentAction(null);
5212
+ }
5213
+ }, []);
5214
+ const approve = useCallback9(
5215
+ async (comments) => {
5216
+ setIsLoading(true);
5217
+ setCurrentAction("approve");
5218
+ try {
5219
+ const formValues = getFormValues?.();
5220
+ await handleApproval(request, {
5221
+ instanceId: formInstanceId,
5222
+ action: "approved",
5223
+ comments,
5224
+ appType,
5225
+ formUuid,
5226
+ updateFormDataJson: formValues ? JSON.stringify(formValues) : void 0
5227
+ });
5228
+ resetLoading();
5229
+ onActionComplete?.("approve");
5230
+ return true;
5231
+ } catch (error) {
5232
+ console.error("[useApprovalActions] approve failed:", error);
5233
+ resetLoading();
5234
+ return false;
5235
+ }
5236
+ },
5237
+ [request, formInstanceId, appType, formUuid, getFormValues, onActionComplete, resetLoading]
5238
+ );
5239
+ const reject = useCallback9(
5240
+ async (comments) => {
5241
+ setIsLoading(true);
5242
+ setCurrentAction("reject");
5243
+ try {
5244
+ const formValues = getFormValues?.();
5245
+ await handleApproval(request, {
5246
+ instanceId: formInstanceId,
5247
+ action: "rejected",
5248
+ comments,
5249
+ appType,
5250
+ formUuid,
5251
+ updateFormDataJson: formValues ? JSON.stringify(formValues) : void 0
5252
+ });
5253
+ resetLoading();
5254
+ onActionComplete?.("reject");
5255
+ return true;
5256
+ } catch (error) {
5257
+ console.error("[useApprovalActions] reject failed:", error);
5258
+ resetLoading();
5259
+ return false;
5260
+ }
5261
+ },
5262
+ [request, formInstanceId, appType, formUuid, getFormValues, onActionComplete, resetLoading]
5263
+ );
5264
+ const transfer = useCallback9(
5265
+ async (userId, reason) => {
5266
+ if (!currentTaskId) {
5267
+ console.error("[useApprovalActions] transfer failed: no currentTaskId");
5268
+ return false;
5269
+ }
5270
+ setIsLoading(true);
5271
+ setCurrentAction("transfer");
5272
+ try {
5273
+ await transferTask(request, {
5274
+ taskId: currentTaskId,
5275
+ newAssignee: userId,
5276
+ reason
5277
+ });
5278
+ resetLoading();
5279
+ onActionComplete?.("transfer");
5280
+ return true;
5281
+ } catch (error) {
5282
+ console.error("[useApprovalActions] transfer failed:", error);
5283
+ resetLoading();
5284
+ return false;
5285
+ }
5286
+ },
5287
+ [request, currentTaskId, onActionComplete, resetLoading]
5288
+ );
5289
+ const returnTo = useCallback9(
5290
+ async (nodeId, reason) => {
5291
+ if (!currentTaskId) {
5292
+ console.error("[useApprovalActions] returnTo failed: no currentTaskId");
5293
+ return false;
5294
+ }
5295
+ setIsLoading(true);
5296
+ setCurrentAction("return");
5297
+ try {
5298
+ await returnTask(request, {
5299
+ taskId: currentTaskId,
5300
+ targetNodeId: nodeId,
5301
+ reason
5302
+ });
5303
+ resetLoading();
5304
+ onActionComplete?.("return");
5305
+ return true;
5306
+ } catch (error) {
5307
+ console.error("[useApprovalActions] returnTo failed:", error);
5308
+ resetLoading();
5309
+ return false;
5310
+ }
5311
+ },
5312
+ [request, currentTaskId, onActionComplete, resetLoading]
5313
+ );
5314
+ const withdraw = useCallback9(
5315
+ async (reason) => {
5316
+ setIsLoading(true);
5317
+ setCurrentAction("withdraw");
5318
+ try {
5319
+ await withdrawProcess(request, {
5320
+ instanceId: formInstanceId,
5321
+ reason
5322
+ });
5323
+ resetLoading();
5324
+ onActionComplete?.("withdraw");
5325
+ return true;
5326
+ } catch (error) {
5327
+ console.error("[useApprovalActions] withdraw failed:", error);
5328
+ resetLoading();
5329
+ return false;
5330
+ }
5331
+ },
5332
+ [request, formInstanceId, onActionComplete, resetLoading]
5333
+ );
5334
+ const save = useCallback9(async () => {
5335
+ setIsLoading(true);
5336
+ setCurrentAction("save");
5337
+ try {
5338
+ const formValues = getFormValues?.() ?? {};
5339
+ await saveTask(request, {
5340
+ instanceId: formInstanceId,
5341
+ formUuid,
5342
+ appType,
5343
+ updateFormDataJson: JSON.stringify(formValues)
5344
+ });
5345
+ resetLoading();
5346
+ onActionComplete?.("save");
5347
+ return true;
5348
+ } catch (error) {
5349
+ console.error("[useApprovalActions] save failed:", error);
5350
+ resetLoading();
5351
+ return false;
5352
+ }
5353
+ }, [request, formInstanceId, formUuid, appType, getFormValues, onActionComplete, resetLoading]);
5354
+ const resubmit = useCallback9(
5355
+ async (comments) => {
5356
+ if (!currentTaskId) {
5357
+ console.error("[useApprovalActions] resubmit failed: no currentTaskId");
5358
+ return false;
5359
+ }
5360
+ setIsLoading(true);
5361
+ setCurrentAction("resubmit");
5362
+ try {
5363
+ const formValues = getFormValues?.() ?? {};
5364
+ await resubmitTask(request, {
5365
+ taskId: currentTaskId,
5366
+ formUuid,
5367
+ appType,
5368
+ updateFormDataJson: JSON.stringify(formValues),
5369
+ comments
5370
+ });
5371
+ resetLoading();
5372
+ onActionComplete?.("resubmit");
5373
+ return true;
5374
+ } catch (error) {
5375
+ console.error("[useApprovalActions] resubmit failed:", error);
5376
+ resetLoading();
5377
+ return false;
5378
+ }
5379
+ },
5380
+ [request, currentTaskId, formUuid, appType, getFormValues, onActionComplete, resetLoading]
5381
+ );
5382
+ const loadReturnableNodes = useCallback9(async () => {
5383
+ if (!currentTaskId) return;
5384
+ try {
5385
+ const nodes = await getReturnableNodes(request, currentTaskId);
5386
+ if (mountedRef.current) {
5387
+ setReturnableNodes(nodes);
5388
+ }
5389
+ } catch (error) {
5390
+ console.error("[useApprovalActions] loadReturnableNodes failed:", error);
5391
+ }
5392
+ }, [request, currentTaskId]);
5393
+ return {
5394
+ approve,
5395
+ reject,
5396
+ transfer,
5397
+ returnTo,
5398
+ withdraw,
5399
+ save,
5400
+ resubmit,
5401
+ isLoading,
5402
+ currentAction,
5403
+ returnableNodes,
5404
+ loadReturnableNodes
5405
+ };
5406
+ }
5407
+
5408
+ // src/hooks/useChangeRecords.ts
5409
+ import { useState as useState23, useEffect as useEffect30, useCallback as useCallback10, useRef as useRef10 } from "react";
5410
+ function useChangeRecords(options) {
5411
+ const { formUuid, appType, formInstanceId, pageSize = 20, autoLoad = true } = options;
5412
+ const { api } = useFormContext();
5413
+ const request = api.request;
5414
+ const [records, setRecords] = useState23([]);
5415
+ const [loading, setLoading] = useState23(false);
5416
+ const [total, setTotal] = useState23(0);
5417
+ const [page, setPage] = useState23(1);
5418
+ const mountedRef = useRef10(true);
5419
+ useEffect30(() => {
5420
+ mountedRef.current = true;
5421
+ return () => {
5422
+ mountedRef.current = false;
5423
+ };
5424
+ }, []);
5425
+ const fetchRecords = useCallback10(
5426
+ async (pageNum, append) => {
5427
+ if (!mountedRef.current) return;
5428
+ setLoading(true);
5429
+ try {
5430
+ const result = await getChangeRecords(request, {
5431
+ formUuid,
5432
+ appType,
5433
+ formInstanceId,
5434
+ page: pageNum,
5435
+ pageSize
5436
+ });
5437
+ if (!mountedRef.current) return;
5438
+ if (append) {
5439
+ setRecords((prev) => [...prev, ...result.records]);
5440
+ } else {
5441
+ setRecords(result.records);
5442
+ }
5443
+ setTotal(result.total);
5444
+ setPage(pageNum);
5445
+ } catch (error) {
5446
+ console.error("[useChangeRecords] Failed to load change records:", error);
5447
+ } finally {
5448
+ if (mountedRef.current) {
5449
+ setLoading(false);
5450
+ }
5451
+ }
5452
+ },
5453
+ [request, formUuid, appType, formInstanceId, pageSize]
5454
+ );
5455
+ useEffect30(() => {
5456
+ if (autoLoad) {
5457
+ fetchRecords(1, false);
5458
+ }
5459
+ }, [autoLoad, fetchRecords]);
5460
+ const hasMore = records.length < total;
5461
+ const loadMore = useCallback10(async () => {
5462
+ if (!hasMore || loading) return;
5463
+ await fetchRecords(page + 1, true);
5464
+ }, [hasMore, loading, page, fetchRecords]);
5465
+ const refresh = useCallback10(async () => {
5466
+ setRecords([]);
5467
+ setPage(1);
5468
+ setTotal(0);
5469
+ await fetchRecords(1, false);
5470
+ }, [fetchRecords]);
5471
+ return {
5472
+ records,
5473
+ loading,
5474
+ total,
5475
+ page,
5476
+ loadMore,
5477
+ refresh,
5478
+ hasMore
5479
+ };
5480
+ }
5481
+
5482
+ // src/hooks/useFormNavigation.ts
5483
+ import { useState as useState24, useCallback as useCallback11, useRef as useRef11, useEffect as useEffect31 } from "react";
5484
+ function useFormNavigation(options) {
5485
+ const {
5486
+ appType,
5487
+ formUuid,
5488
+ formType = "form",
5489
+ mode = "redirect",
5490
+ redirectDelay = 3e3,
5491
+ onStay
5492
+ } = options;
5493
+ const [isRedirecting, setIsRedirecting] = useState24(false);
5494
+ const [countdown, setCountdown] = useState24(0);
5495
+ const timerRef = useRef11(null);
5496
+ const redirectTargetRef = useRef11(null);
5497
+ const mountedRef = useRef11(true);
5498
+ useEffect31(() => {
5499
+ mountedRef.current = true;
5500
+ return () => {
5501
+ mountedRef.current = false;
5502
+ if (timerRef.current) {
5503
+ clearInterval(timerRef.current);
5504
+ timerRef.current = null;
5505
+ }
5506
+ };
5507
+ }, []);
5508
+ const navigateToDetail = useCallback11(
5509
+ (formInstId) => {
5510
+ window.location.href = `/${appType}/formDetail/${formUuid}?formInstId=${formInstId}`;
5511
+ },
5512
+ [appType, formUuid]
5513
+ );
5514
+ const navigateToProcessDetail = useCallback11(
5515
+ (formInstId) => {
5516
+ window.location.href = `/${appType}/processDetail/${formUuid}?formInstId=${formInstId}`;
5517
+ },
5518
+ [appType, formUuid]
5519
+ );
5520
+ const startRedirectCountdown = useCallback11(
5521
+ (targetUrl) => {
5522
+ const totalSeconds = Math.ceil(redirectDelay / 1e3);
5523
+ setIsRedirecting(true);
5524
+ setCountdown(totalSeconds);
5525
+ redirectTargetRef.current = targetUrl;
5526
+ timerRef.current = setInterval(() => {
5527
+ if (!mountedRef.current) {
5528
+ if (timerRef.current) {
5529
+ clearInterval(timerRef.current);
5530
+ timerRef.current = null;
5531
+ }
5532
+ return;
5533
+ }
5534
+ setCountdown((prev) => {
5535
+ const next = prev - 1;
5536
+ if (next <= 0) {
5537
+ if (timerRef.current) {
5538
+ clearInterval(timerRef.current);
5539
+ timerRef.current = null;
5540
+ }
5541
+ setIsRedirecting(false);
5542
+ if (redirectTargetRef.current) {
5543
+ window.location.href = redirectTargetRef.current;
5544
+ }
5545
+ return 0;
5546
+ }
5547
+ return next;
5548
+ });
5549
+ }, 1e3);
5550
+ },
5551
+ [redirectDelay]
5552
+ );
5553
+ const cancelRedirect = useCallback11(() => {
5554
+ if (timerRef.current) {
5555
+ clearInterval(timerRef.current);
5556
+ timerRef.current = null;
5557
+ }
5558
+ setIsRedirecting(false);
5559
+ setCountdown(0);
5560
+ redirectTargetRef.current = null;
5561
+ }, []);
5562
+ const handlePostSubmit = useCallback11(
5563
+ (formInstId) => {
5564
+ if (mode === "stay") {
5565
+ onStay?.(formInstId);
5566
+ return;
5567
+ }
5568
+ if (mode === "callback") {
5569
+ onStay?.(formInstId);
5570
+ return;
5571
+ }
5572
+ const targetUrl = formType === "process" ? `/${appType}/processDetail/${formUuid}?formInstId=${formInstId}` : `/${appType}/formDetail/${formUuid}?formInstId=${formInstId}`;
5573
+ startRedirectCountdown(targetUrl);
5574
+ },
5575
+ [mode, formType, appType, formUuid, onStay, startRedirectCountdown]
5576
+ );
5577
+ return {
5578
+ navigateToDetail,
5579
+ navigateToProcessDetail,
5580
+ handlePostSubmit,
5581
+ isRedirecting,
5582
+ countdown,
5583
+ cancelRedirect
5584
+ };
5585
+ }
5586
+
5587
+ // src/hooks/useDraftStorage.ts
5588
+ import { useState as useState25, useCallback as useCallback12, useEffect as useEffect32 } from "react";
5589
+ function getDraftKey(appType, formUuid) {
5590
+ return `${appType}__${formUuid}__draft`;
5591
+ }
5592
+ function readDraft(key) {
5593
+ try {
5594
+ const raw = localStorage.getItem(key);
5595
+ if (!raw) return null;
5596
+ const parsed = JSON.parse(raw);
5597
+ if (parsed && typeof parsed.data === "object" && typeof parsed.ts === "number") {
5598
+ return parsed;
5599
+ }
5600
+ return null;
5601
+ } catch {
5602
+ return null;
5603
+ }
5604
+ }
5605
+ function useDraftStorage(options) {
5606
+ const { appType, formUuid, autoRestore = false } = options;
5607
+ const key = getDraftKey(appType, formUuid);
5608
+ const [hasDraft, setHasDraft] = useState25(false);
5609
+ const [draftData, setDraftData] = useState25(null);
5610
+ const [draftTimestamp, setDraftTimestamp] = useState25(null);
5611
+ useEffect32(() => {
5612
+ const stored = readDraft(key);
5613
+ if (stored) {
5614
+ setHasDraft(true);
5615
+ setDraftTimestamp(stored.ts);
5616
+ if (autoRestore) {
5617
+ setDraftData(stored.data);
5618
+ }
5619
+ } else {
5620
+ setHasDraft(false);
5621
+ setDraftData(null);
5622
+ setDraftTimestamp(null);
5623
+ }
5624
+ }, [key, autoRestore]);
5625
+ const saveDraft = useCallback12(
5626
+ (data) => {
5627
+ const payload = { data, ts: Date.now() };
5628
+ try {
5629
+ localStorage.setItem(key, JSON.stringify(payload));
5630
+ setHasDraft(true);
5631
+ setDraftData(data);
5632
+ setDraftTimestamp(payload.ts);
5633
+ } catch (error) {
5634
+ console.error("[useDraftStorage] Failed to save draft:", error);
5635
+ }
5636
+ },
5637
+ [key]
5638
+ );
5639
+ const restoreDraft = useCallback12(() => {
5640
+ const stored = readDraft(key);
5641
+ if (stored) {
5642
+ setDraftData(stored.data);
5643
+ return stored.data;
5644
+ }
5645
+ return null;
5646
+ }, [key]);
5647
+ const clearDraft = useCallback12(() => {
5648
+ try {
5649
+ localStorage.removeItem(key);
5650
+ } catch (error) {
5651
+ console.error("[useDraftStorage] Failed to clear draft:", error);
5652
+ }
5653
+ setHasDraft(false);
5654
+ setDraftData(null);
5655
+ setDraftTimestamp(null);
5656
+ }, [key]);
5657
+ return {
5658
+ hasDraft,
5659
+ draftData,
5660
+ draftTimestamp,
5661
+ saveDraft,
5662
+ restoreDraft,
5663
+ clearDraft
5664
+ };
5665
+ }
5666
+
4709
5667
  // src/utils/defineFormSchema.ts
4710
5668
  function defineFormSchema(schema) {
4711
5669
  return schema;
4712
5670
  }
5671
+
5672
+ // src/modules/FormSummaryCard.tsx
5673
+ import { Fragment, jsx as jsx75, jsxs as jsxs21 } from "react/jsx-runtime";
5674
+ var toneClasses = {
5675
+ brand: "bg-blue-50 text-blue-600",
5676
+ success: "bg-green-50 text-green-600",
5677
+ danger: "bg-red-50 text-red-600",
5678
+ neutral: "bg-gray-100 text-gray-500",
5679
+ warning: "bg-amber-50 text-amber-600"
5680
+ };
5681
+ var FormSummaryCard = ({
5682
+ title,
5683
+ formInstanceId,
5684
+ creator,
5685
+ createdAt,
5686
+ status,
5687
+ className = "",
5688
+ children
5689
+ }) => {
5690
+ const shortId = formInstanceId ? formInstanceId.slice(0, 8) : null;
5691
+ const renderAvatar = () => {
5692
+ if (!creator) return null;
5693
+ if (creator.avatar) {
5694
+ return /* @__PURE__ */ jsx75(
5695
+ "img",
5696
+ {
5697
+ src: creator.avatar,
5698
+ alt: creator.name,
5699
+ className: "w-7 h-7 rounded-full object-cover"
5700
+ }
5701
+ );
5702
+ }
5703
+ const initial = creator.name.charAt(0);
5704
+ return /* @__PURE__ */ jsx75("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 });
5705
+ };
5706
+ return /* @__PURE__ */ jsxs21("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 p-6 ${className}`, children: [
5707
+ /* @__PURE__ */ jsxs21("div", { className: "flex items-start justify-between", children: [
5708
+ /* @__PURE__ */ jsxs21("div", { className: "min-w-0 flex-1", children: [
5709
+ title && /* @__PURE__ */ jsx75("h2", { className: "text-xl font-semibold text-gray-900 truncate", children: title }),
5710
+ shortId && /* @__PURE__ */ jsxs21("span", { className: "text-xs text-gray-400 mt-0.5 inline-block", children: [
5711
+ "#",
5712
+ shortId
5713
+ ] })
5714
+ ] }),
5715
+ status && /* @__PURE__ */ jsx75(
5716
+ "span",
5717
+ {
5718
+ className: `px-2.5 py-0.5 rounded-full text-xs font-medium whitespace-nowrap ${toneClasses[status.tone] || toneClasses.neutral}`,
5719
+ children: status.label
5720
+ }
5721
+ )
5722
+ ] }),
5723
+ creator && /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2 mt-4 text-sm text-gray-600", children: [
5724
+ renderAvatar(),
5725
+ /* @__PURE__ */ jsx75("span", { className: "font-medium", children: creator.name }),
5726
+ creator.department && /* @__PURE__ */ jsxs21(Fragment, { children: [
5727
+ /* @__PURE__ */ jsx75("span", { className: "text-gray-300", children: "\xB7" }),
5728
+ /* @__PURE__ */ jsx75("span", { children: creator.department })
5729
+ ] }),
5730
+ createdAt && /* @__PURE__ */ jsxs21(Fragment, { children: [
5731
+ /* @__PURE__ */ jsx75("span", { className: "text-gray-300", children: "\xB7" }),
5732
+ /* @__PURE__ */ jsx75("span", { className: "text-gray-400", children: createdAt })
5733
+ ] })
5734
+ ] }),
5735
+ children && /* @__PURE__ */ jsx75("div", { className: "mt-4", children })
5736
+ ] });
5737
+ };
5738
+
5739
+ // src/modules/ChangeRecords.tsx
5740
+ import { useState as useState26 } from "react";
5741
+ import { Skeleton } from "antd";
5742
+ import { DownOutlined, UpOutlined } from "@ant-design/icons";
5743
+ import { jsx as jsx76, jsxs as jsxs22 } from "react/jsx-runtime";
5744
+ var ChangeRecords = ({
5745
+ records = [],
5746
+ loading = false,
5747
+ defaultExpanded = false,
5748
+ hasMore = false,
5749
+ onLoadMore,
5750
+ onExpand,
5751
+ className = "",
5752
+ renderItem
5753
+ }) => {
5754
+ const [expanded, setExpanded] = useState26(defaultExpanded);
5755
+ const handleToggle = () => {
5756
+ const next = !expanded;
5757
+ setExpanded(next);
5758
+ if (next && onExpand) {
5759
+ onExpand();
5760
+ }
5761
+ };
5762
+ const defaultRenderItem = (record) => /* @__PURE__ */ jsxs22("div", { className: "pl-4 py-3 border-l-2 border-gray-200 ml-1", children: [
5763
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2 text-xs text-gray-400", children: [
5764
+ /* @__PURE__ */ jsx76("span", { children: record.operatedAt }),
5765
+ /* @__PURE__ */ jsx76("span", { className: "text-gray-600 font-medium", children: record.operatorName }),
5766
+ /* @__PURE__ */ jsx76("span", { children: "\u4FEE\u6539\u4E86" }),
5767
+ /* @__PURE__ */ jsx76("span", { className: "text-gray-800 font-medium", children: record.fieldLabel })
5768
+ ] }),
5769
+ /* @__PURE__ */ jsxs22("div", { className: "mt-1.5 text-sm text-gray-600 flex items-center gap-2", children: [
5770
+ /* @__PURE__ */ jsx76("span", { className: "bg-red-50 text-red-600 px-1.5 py-0.5 rounded text-xs line-through", children: formatValue(record.oldValue) }),
5771
+ /* @__PURE__ */ jsx76("span", { className: "text-gray-400", children: "\u2192" }),
5772
+ /* @__PURE__ */ jsx76("span", { className: "bg-green-50 text-green-600 px-1.5 py-0.5 rounded text-xs", children: formatValue(record.newValue) })
5773
+ ] })
5774
+ ] });
5775
+ return /* @__PURE__ */ jsxs22("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 ${className}`, children: [
5776
+ /* @__PURE__ */ jsxs22(
5777
+ "button",
5778
+ {
5779
+ type: "button",
5780
+ className: "w-full flex items-center justify-between p-6 text-left hover:bg-gray-50/50 transition-colors rounded-xl",
5781
+ onClick: handleToggle,
5782
+ children: [
5783
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
5784
+ /* @__PURE__ */ jsx76("h3", { className: "text-lg font-semibold text-gray-900", children: "\u53D8\u66F4\u8BB0\u5F55" }),
5785
+ /* @__PURE__ */ jsx76("span", { className: "text-xs text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded-full", children: records.length })
5786
+ ] }),
5787
+ /* @__PURE__ */ jsx76("span", { className: "text-gray-400 text-xs", children: expanded ? /* @__PURE__ */ jsx76(UpOutlined, {}) : /* @__PURE__ */ jsx76(DownOutlined, {}) })
5788
+ ]
5789
+ }
5790
+ ),
5791
+ expanded && /* @__PURE__ */ jsxs22("div", { className: "px-6 pb-6", children: [
5792
+ loading && records.length === 0 ? /* @__PURE__ */ jsx76(Skeleton, { active: true, paragraph: { rows: 3 } }) : records.length === 0 ? /* @__PURE__ */ jsx76("p", { className: "text-sm text-gray-400 text-center py-4", children: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ jsx76("div", { className: "space-y-1", children: records.map((record) => /* @__PURE__ */ jsx76("div", { children: renderItem ? renderItem(record) : defaultRenderItem(record) }, record.id)) }),
5793
+ hasMore && /* @__PURE__ */ jsx76(
5794
+ "button",
5795
+ {
5796
+ type: "button",
5797
+ 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",
5798
+ onClick: onLoadMore,
5799
+ disabled: loading,
5800
+ children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
5801
+ }
5802
+ )
5803
+ ] })
5804
+ ] });
5805
+ };
5806
+ function formatValue(value) {
5807
+ if (value === null || value === void 0) return "\u7A7A";
5808
+ if (typeof value === "object") return JSON.stringify(value);
5809
+ return String(value);
5810
+ }
5811
+
5812
+ // src/modules/ApprovalTimeline.tsx
5813
+ import { Fragment as Fragment2, jsx as jsx77, jsxs as jsxs23 } from "react/jsx-runtime";
5814
+ var toneClasses2 = {
5815
+ brand: "bg-blue-50 text-blue-600",
5816
+ success: "bg-green-50 text-green-600",
5817
+ danger: "bg-red-50 text-red-600",
5818
+ neutral: "bg-gray-100 text-gray-500",
5819
+ warning: "bg-amber-50 text-amber-600"
5820
+ };
5821
+ function getNodePhase(task) {
5822
+ if (task.status === "approved" || task.status === "rejected" || task.status === "returned" || task.status === "copied") {
5823
+ return "completed";
5824
+ }
5825
+ if (task.status === "pending" || task.status === "waiting") {
5826
+ return "active";
5827
+ }
5828
+ return "pending";
5829
+ }
5830
+ var ApprovalTimeline = ({
5831
+ tasks,
5832
+ className = "",
5833
+ renderNode,
5834
+ showRemarks = true,
5835
+ compactMode = false
5836
+ }) => {
5837
+ if (!tasks || tasks.length === 0) {
5838
+ return /* @__PURE__ */ jsx77("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 p-6 ${className}`, children: /* @__PURE__ */ jsx77("p", { className: "text-sm text-gray-400 text-center", children: "\u6682\u65E0\u5BA1\u6279\u8BB0\u5F55" }) });
5839
+ }
5840
+ return /* @__PURE__ */ jsx77("div", { className: `${className}`, children: tasks.map((task, index) => {
5841
+ if (renderNode) {
5842
+ return /* @__PURE__ */ jsx77("div", { children: renderNode(task, index) }, task.taskId);
5843
+ }
5844
+ const phase = getNodePhase(task);
5845
+ const isLast = index === tasks.length - 1;
5846
+ const statusMeta = TASK_STATUS_META[task.status];
5847
+ return /* @__PURE__ */ jsxs23("div", { className: "flex gap-4", children: [
5848
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col items-center", children: [
5849
+ phase === "completed" && /* @__PURE__ */ jsx77("div", { className: "w-3 h-3 rounded-full bg-green-500 flex-shrink-0" }),
5850
+ phase === "active" && /* @__PURE__ */ jsx77("div", { className: "w-3 h-3 rounded-full bg-blue-500 ring-4 ring-blue-100 flex-shrink-0" }),
5851
+ phase === "pending" && /* @__PURE__ */ jsx77("div", { className: "w-3 h-3 rounded-full bg-gray-300 flex-shrink-0" }),
5852
+ !isLast && /* @__PURE__ */ jsx77(
5853
+ "div",
5854
+ {
5855
+ 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"}`
5856
+ }
5857
+ )
5858
+ ] }),
5859
+ /* @__PURE__ */ jsx77("div", { className: `flex-1 pb-6 ${isLast ? "pb-0" : ""}`, children: /* @__PURE__ */ jsxs23(
5860
+ "div",
5861
+ {
5862
+ 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"}`,
5863
+ children: [
5864
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
5865
+ /* @__PURE__ */ jsx77("span", { className: "text-sm font-medium text-gray-900", children: task.nodeName }),
5866
+ statusMeta && /* @__PURE__ */ jsx77(
5867
+ "span",
5868
+ {
5869
+ className: `px-2 py-0.5 rounded-full text-xs font-medium ${toneClasses2[statusMeta.tone] || toneClasses2.neutral}`,
5870
+ children: statusMeta.label
5871
+ }
5872
+ )
5873
+ ] }),
5874
+ task.assigneeName && /* @__PURE__ */ jsxs23("div", { className: "mt-2 flex items-center gap-1.5 text-sm text-gray-600", children: [
5875
+ /* @__PURE__ */ jsx77("span", { className: "text-gray-400", children: "\u{1F464}" }),
5876
+ /* @__PURE__ */ jsxs23("span", { children: [
5877
+ phase === "active" ? "\u5F53\u524D\u5BA1\u6279\u4EBA: " : "",
5878
+ task.assigneeName
5879
+ ] }),
5880
+ task.departmentName && /* @__PURE__ */ jsxs23(Fragment2, { children: [
5881
+ /* @__PURE__ */ jsx77("span", { className: "text-gray-300", children: "\xB7" }),
5882
+ /* @__PURE__ */ jsx77("span", { className: "text-gray-400", children: task.departmentName })
5883
+ ] })
5884
+ ] }),
5885
+ !compactMode && showRemarks && task.comments && /* @__PURE__ */ jsxs23("div", { className: "mt-2 bg-gray-50 rounded-md p-3 text-sm text-gray-600 italic", children: [
5886
+ "\u{1F4AC} \u201C",
5887
+ task.comments,
5888
+ "\u201D"
5889
+ ] }),
5890
+ !compactMode && phase === "active" && !task.comments && /* @__PURE__ */ jsx77("div", { className: "mt-2 text-xs text-gray-400", children: "\u23F3 \u7B49\u5F85\u5904\u7406\u4E2D..." }),
5891
+ !compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ jsxs23("div", { className: "mt-2 text-xs text-gray-400", children: [
5892
+ "\u{1F550} ",
5893
+ task.actionAt || task.createdAt
5894
+ ] }),
5895
+ compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ jsx77("div", { className: "mt-1 text-xs text-gray-400", children: task.actionAt || task.createdAt })
5896
+ ]
5897
+ }
5898
+ ) })
5899
+ ] }, task.taskId);
5900
+ }) });
5901
+ };
5902
+
5903
+ // src/modules/ApprovalActions.tsx
5904
+ import { useState as useState27 } from "react";
5905
+ import { Button as Button5, Drawer, Input as Input8, Dropdown } from "antd";
5906
+ import { MoreOutlined, LoadingOutlined } from "@ant-design/icons";
5907
+ import { Fragment as Fragment3, jsx as jsx78, jsxs as jsxs24 } from "react/jsx-runtime";
5908
+ var { TextArea: TextArea4 } = Input8;
5909
+ var ApprovalActions = ({
5910
+ actions,
5911
+ onApprove,
5912
+ onReject,
5913
+ onTransfer,
5914
+ onReturn,
5915
+ onWithdraw,
5916
+ onSave,
5917
+ layout = "horizontal",
5918
+ maxVisible = 3,
5919
+ className = ""
5920
+ }) => {
5921
+ const [drawerAction, setDrawerAction] = useState27(null);
5922
+ const [comments, setComments] = useState27("");
5923
+ const [loading, setLoading] = useState27(false);
5924
+ const [saveLoading, setSaveLoading] = useState27(false);
5925
+ const handleOpenDrawer = (action) => {
5926
+ setComments("");
5927
+ setDrawerAction(action);
5928
+ };
5929
+ const handleConfirm = async () => {
5930
+ setLoading(true);
5931
+ try {
5932
+ if (drawerAction === "approve" && onApprove) {
5933
+ await onApprove(comments || void 0);
5934
+ } else if (drawerAction === "reject" && onReject) {
5935
+ await onReject(comments || void 0);
5936
+ } else if (drawerAction === "withdraw" && onWithdraw) {
5937
+ await onWithdraw(comments || void 0);
5938
+ }
5939
+ setDrawerAction(null);
5940
+ } finally {
5941
+ setLoading(false);
5942
+ }
5943
+ };
5944
+ const handleSave = async () => {
5945
+ if (!onSave) return;
5946
+ setSaveLoading(true);
5947
+ try {
5948
+ await onSave();
5949
+ } finally {
5950
+ setSaveLoading(false);
5951
+ }
5952
+ };
5953
+ const actionMap = {};
5954
+ actions.forEach((action) => {
5955
+ switch (action.action) {
5956
+ case "agree":
5957
+ actionMap["agree"] = {
5958
+ label: action.name.zh_CN || "\u540C\u610F",
5959
+ handler: () => handleOpenDrawer("approve"),
5960
+ type: "primary",
5961
+ color: "green"
5962
+ };
5963
+ break;
5964
+ case "rejected":
5965
+ actionMap["rejected"] = {
5966
+ label: action.name.zh_CN || "\u62D2\u7EDD",
5967
+ handler: () => handleOpenDrawer("reject"),
5968
+ type: "default"
5969
+ };
5970
+ break;
5971
+ case "transfer":
5972
+ actionMap["transfer"] = {
5973
+ label: action.name.zh_CN || "\u8F6C\u4EA4",
5974
+ handler: () => onTransfer?.(),
5975
+ type: "default"
5976
+ };
5977
+ break;
5978
+ case "return":
5979
+ actionMap["return"] = {
5980
+ label: action.name.zh_CN || "\u9000\u56DE",
5981
+ handler: () => onReturn?.(),
5982
+ type: "default"
5983
+ };
5984
+ break;
5985
+ case "withdraw":
5986
+ actionMap["withdraw"] = {
5987
+ label: action.name.zh_CN || "\u64A4\u9500",
5988
+ handler: () => handleOpenDrawer("withdraw"),
5989
+ type: "default"
5990
+ };
5991
+ break;
5992
+ case "save":
5993
+ actionMap["save"] = {
5994
+ label: action.name.zh_CN || "\u6682\u5B58",
5995
+ handler: handleSave,
5996
+ type: "default"
5997
+ };
5998
+ break;
5999
+ }
6000
+ });
6001
+ const allButtons = Object.entries(actionMap);
6002
+ const visibleButtons = allButtons.slice(0, maxVisible);
6003
+ const moreButtons = allButtons.slice(maxVisible);
6004
+ const drawerTitle = drawerAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : drawerAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : drawerAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1";
6005
+ return /* @__PURE__ */ jsxs24(Fragment3, { children: [
6006
+ /* @__PURE__ */ jsxs24(
6007
+ "div",
6008
+ {
6009
+ className: `${layout === "horizontal" ? "flex items-center gap-3" : "flex flex-col gap-2"} ${className}`,
6010
+ children: [
6011
+ visibleButtons.map(([key, btn]) => /* @__PURE__ */ jsx78(
6012
+ Button5,
6013
+ {
6014
+ type: btn.type === "primary" ? "primary" : "default",
6015
+ className: btn.color === "green" ? "!bg-green-600 !border-green-600 hover:!bg-green-700" : "",
6016
+ onClick: btn.handler,
6017
+ loading: key === "save" && saveLoading,
6018
+ children: btn.label
6019
+ },
6020
+ key
6021
+ )),
6022
+ moreButtons.length > 0 && /* @__PURE__ */ jsx78(
6023
+ Dropdown,
6024
+ {
6025
+ menu: {
6026
+ items: moreButtons.map(([key, btn]) => ({
6027
+ key,
6028
+ label: btn.label,
6029
+ onClick: btn.handler
6030
+ }))
6031
+ },
6032
+ trigger: ["click"],
6033
+ children: /* @__PURE__ */ jsx78(Button5, { icon: /* @__PURE__ */ jsx78(MoreOutlined, {}), children: "\u66F4\u591A" })
6034
+ }
6035
+ )
6036
+ ]
6037
+ }
6038
+ ),
6039
+ /* @__PURE__ */ jsx78(
6040
+ Drawer,
6041
+ {
6042
+ title: drawerTitle,
6043
+ open: drawerAction !== null,
6044
+ onClose: () => setDrawerAction(null),
6045
+ width: 400,
6046
+ footer: /* @__PURE__ */ jsxs24("div", { className: "flex justify-end gap-3", children: [
6047
+ /* @__PURE__ */ jsx78(Button5, { onClick: () => setDrawerAction(null), children: "\u53D6\u6D88" }),
6048
+ /* @__PURE__ */ jsxs24(Button5, { type: "primary", onClick: handleConfirm, loading, children: [
6049
+ loading && /* @__PURE__ */ jsx78(LoadingOutlined, {}),
6050
+ "\u786E\u8BA4"
6051
+ ] })
6052
+ ] }),
6053
+ children: /* @__PURE__ */ jsx78("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs24("div", { children: [
6054
+ /* @__PURE__ */ jsx78("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" }),
6055
+ /* @__PURE__ */ jsx78(
6056
+ TextArea4,
6057
+ {
6058
+ rows: 4,
6059
+ value: comments,
6060
+ onChange: (e) => setComments(e.target.value),
6061
+ 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...",
6062
+ maxLength: 500,
6063
+ showCount: true
6064
+ }
6065
+ )
6066
+ ] }) })
6067
+ }
6068
+ )
6069
+ ] });
6070
+ };
6071
+
6072
+ // src/modules/FormActionBar.tsx
6073
+ import { useState as useState28 } from "react";
6074
+ import { Button as Button6, Modal as Modal2 } from "antd";
6075
+ import { Fragment as Fragment4, jsx as jsx79, jsxs as jsxs25 } from "react/jsx-runtime";
6076
+ var FormActionBar = ({
6077
+ actions,
6078
+ position = "bottom-fixed",
6079
+ className = ""
6080
+ }) => {
6081
+ const [loadingKeys, setLoadingKeys] = useState28(/* @__PURE__ */ new Set());
6082
+ const visibleActions = actions.filter((a) => a.visible !== false);
6083
+ const sortedActions = [...visibleActions].sort((a, b) => {
6084
+ if (a.type === "danger" && b.type !== "danger") return -1;
6085
+ if (a.type !== "danger" && b.type === "danger") return 1;
6086
+ if (a.type === "primary" && b.type !== "primary") return 1;
6087
+ if (a.type !== "primary" && b.type === "primary") return -1;
6088
+ return 0;
6089
+ });
6090
+ const handleClick = async (action) => {
6091
+ if (action.confirm) {
6092
+ Modal2.confirm({
6093
+ title: action.confirm.title,
6094
+ content: action.confirm.content,
6095
+ okText: "\u786E\u8BA4",
6096
+ cancelText: "\u53D6\u6D88",
6097
+ onOk: async () => {
6098
+ await executeAction(action);
6099
+ }
6100
+ });
6101
+ } else {
6102
+ await executeAction(action);
6103
+ }
6104
+ };
6105
+ const executeAction = async (action) => {
6106
+ setLoadingKeys((prev) => new Set(prev).add(action.key));
6107
+ try {
6108
+ await action.onClick();
6109
+ } finally {
6110
+ setLoadingKeys((prev) => {
6111
+ const next = new Set(prev);
6112
+ next.delete(action.key);
6113
+ return next;
6114
+ });
6115
+ }
6116
+ };
6117
+ const isFixed = position === "bottom-fixed";
6118
+ const bar = /* @__PURE__ */ jsx79(
6119
+ "div",
6120
+ {
6121
+ 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}`,
6122
+ children: /* @__PURE__ */ jsx79("div", { className: "flex items-center justify-end gap-3 flex-wrap md:flex-nowrap", children: sortedActions.map((action) => {
6123
+ const isLoading = action.loading || loadingKeys.has(action.key);
6124
+ return /* @__PURE__ */ jsx79(
6125
+ Button6,
6126
+ {
6127
+ type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
6128
+ danger: action.type === "danger",
6129
+ loading: isLoading,
6130
+ disabled: action.disabled,
6131
+ icon: action.icon,
6132
+ onClick: () => handleClick(action),
6133
+ className: "md:w-auto w-full",
6134
+ children: action.label
6135
+ },
6136
+ action.key
6137
+ );
6138
+ }) })
6139
+ }
6140
+ );
6141
+ if (isFixed) {
6142
+ return /* @__PURE__ */ jsxs25(Fragment4, { children: [
6143
+ bar,
6144
+ /* @__PURE__ */ jsx79("div", { className: "h-16" })
6145
+ ] });
6146
+ }
6147
+ return bar;
6148
+ };
6149
+
6150
+ // src/modules/DraftManager.tsx
6151
+ import { Button as Button7 } from "antd";
6152
+ import { EditOutlined } from "@ant-design/icons";
6153
+ import { jsx as jsx80, jsxs as jsxs26 } from "react/jsx-runtime";
6154
+ function formatRelativeTime(timestamp) {
6155
+ const now = Date.now();
6156
+ const diff = now - timestamp;
6157
+ const minutes = Math.floor(diff / 6e4);
6158
+ const hours = Math.floor(diff / 36e5);
6159
+ const days = Math.floor(diff / 864e5);
6160
+ if (minutes < 1) return "\u521A\u521A";
6161
+ if (minutes < 60) return `${minutes}\u5206\u949F\u524D`;
6162
+ if (hours < 24) return `${hours}\u5C0F\u65F6\u524D`;
6163
+ return `${days}\u5929\u524D`;
6164
+ }
6165
+ var DraftManager = ({
6166
+ hasDraft,
6167
+ draftTimestamp,
6168
+ onRestore,
6169
+ onDiscard,
6170
+ className = ""
6171
+ }) => {
6172
+ if (!hasDraft) return null;
6173
+ const timeLabel = draftTimestamp ? formatRelativeTime(draftTimestamp) : null;
6174
+ return /* @__PURE__ */ jsx80(
6175
+ "div",
6176
+ {
6177
+ className: `bg-blue-50 border border-blue-200 rounded-lg p-4 animate-[slideDown_0.3s_ease-out] ${className}`,
6178
+ children: /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
6179
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
6180
+ /* @__PURE__ */ jsx80(EditOutlined, { className: "text-blue-500" }),
6181
+ /* @__PURE__ */ jsxs26("span", { children: [
6182
+ "\u68C0\u6D4B\u5230\u672A\u63D0\u4EA4\u7684\u8349\u7A3F",
6183
+ timeLabel && /* @__PURE__ */ jsxs26("span", { className: "text-blue-500 ml-1", children: [
6184
+ "\uFF08\u4FDD\u5B58\u4E8E ",
6185
+ timeLabel,
6186
+ "\uFF09"
6187
+ ] })
6188
+ ] })
6189
+ ] }),
6190
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2", children: [
6191
+ /* @__PURE__ */ jsx80(Button7, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
6192
+ /* @__PURE__ */ jsx80(Button7, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
6193
+ ] })
6194
+ ] })
6195
+ }
6196
+ );
6197
+ };
6198
+
6199
+ // src/modules/ProcessPreview.tsx
6200
+ import { Modal as Modal3, Skeleton as Skeleton2, Button as Button8 } from "antd";
6201
+ import { CheckCircleOutlined, UserOutlined } from "@ant-design/icons";
6202
+ import { jsx as jsx81, jsxs as jsxs27 } from "react/jsx-runtime";
6203
+ var ProcessPreview = ({
6204
+ open,
6205
+ onClose,
6206
+ onConfirm,
6207
+ routes,
6208
+ loading = false
6209
+ }) => {
6210
+ return /* @__PURE__ */ jsx81(
6211
+ Modal3,
6212
+ {
6213
+ title: "\u6D41\u7A0B\u9884\u89C8",
6214
+ open,
6215
+ onCancel: onClose,
6216
+ width: 520,
6217
+ footer: /* @__PURE__ */ jsxs27("div", { className: "flex justify-end gap-3", children: [
6218
+ /* @__PURE__ */ jsx81(Button8, { onClick: onClose, children: "\u53D6\u6D88" }),
6219
+ /* @__PURE__ */ jsx81(Button8, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
6220
+ ] }),
6221
+ children: loading && routes.length === 0 ? /* @__PURE__ */ jsx81(Skeleton2, { active: true, paragraph: { rows: 4 } }) : routes.length === 0 ? /* @__PURE__ */ jsx81("p", { className: "text-sm text-gray-400 text-center py-8", children: "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) : /* @__PURE__ */ jsx81("div", { className: "py-2", children: routes.map((route, index) => {
6222
+ const isLast = index === routes.length - 1;
6223
+ return /* @__PURE__ */ jsxs27("div", { className: "flex gap-3", children: [
6224
+ /* @__PURE__ */ jsxs27("div", { className: "flex flex-col items-center", children: [
6225
+ /* @__PURE__ */ jsx81("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__ */ jsx81(CheckCircleOutlined, { className: "text-blue-500 text-xs" }) }),
6226
+ !isLast && /* @__PURE__ */ jsx81("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
6227
+ ] }),
6228
+ /* @__PURE__ */ jsxs27("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
6229
+ /* @__PURE__ */ jsx81("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
6230
+ route.assignees && route.assignees.length > 0 && /* @__PURE__ */ jsxs27("div", { className: "mt-1 flex items-center gap-1.5 flex-wrap", children: [
6231
+ /* @__PURE__ */ jsx81(UserOutlined, { className: "text-gray-400 text-xs" }),
6232
+ route.assignees.map((assignee) => /* @__PURE__ */ jsx81(
6233
+ "span",
6234
+ {
6235
+ className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
6236
+ children: assignee.name
6237
+ },
6238
+ assignee.id
6239
+ ))
6240
+ ] })
6241
+ ] })
6242
+ ] }, route.nodeId);
6243
+ }) })
6244
+ }
6245
+ );
6246
+ };
6247
+
6248
+ // src/templates/FormSubmitTemplate.tsx
6249
+ import { useState as useState29, useCallback as useCallback13 } from "react";
6250
+ import { Button as Button9 } from "antd";
6251
+ import { CheckCircleFilled } from "@ant-design/icons";
6252
+ import { Fragment as Fragment5, jsx as jsx82, jsxs as jsxs28 } from "react/jsx-runtime";
6253
+ var SubmitSuccessCard = ({
6254
+ info,
6255
+ mode,
6256
+ isRedirecting,
6257
+ countdown,
6258
+ onContinue,
6259
+ onViewDetail,
6260
+ renderSuccess
6261
+ }) => {
6262
+ if (renderSuccess) {
6263
+ return /* @__PURE__ */ jsx82(Fragment5, { children: renderSuccess(info) });
6264
+ }
6265
+ return /* @__PURE__ */ jsx82("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center py-16 animate-[fadeIn_0.3s_ease-out,scaleIn_0.3s_ease-out]", children: [
6266
+ /* @__PURE__ */ jsx82("div", { className: "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx82(CheckCircleFilled, { className: "text-2xl text-green-500" }) }),
6267
+ /* @__PURE__ */ jsx82("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
6268
+ /* @__PURE__ */ jsx82("p", { className: "text-sm text-gray-500 mb-6", children: info.message || "\u5DF2\u6210\u529F\u521B\u5EFA\u4E00\u6761\u65B0\u8BB0\u5F55" }),
6269
+ /* @__PURE__ */ jsxs28("div", { className: "flex gap-3", children: [
6270
+ (mode === "stay" || mode === "redirect") && /* @__PURE__ */ jsx82(Button9, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
6271
+ /* @__PURE__ */ jsx82(Button9, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
6272
+ ] }),
6273
+ isRedirecting && /* @__PURE__ */ jsxs28("div", { className: "mt-6 w-48", children: [
6274
+ /* @__PURE__ */ jsxs28("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
6275
+ countdown,
6276
+ "\u79D2\u540E\u81EA\u52A8\u8DF3\u8F6C"
6277
+ ] }),
6278
+ /* @__PURE__ */ jsx82("div", { className: "h-1 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx82(
6279
+ "div",
6280
+ {
6281
+ className: "h-full bg-blue-500 transition-all duration-1000",
6282
+ style: { width: `${countdown / 3 * 100}%` }
6283
+ }
6284
+ ) })
6285
+ ] })
6286
+ ] }) });
6287
+ };
6288
+ var InnerFormContent = ({
6289
+ schema,
6290
+ config,
6291
+ formType,
6292
+ submitSuccessMode,
6293
+ enableDraft,
6294
+ header,
6295
+ footer,
6296
+ beforeForm,
6297
+ afterForm,
6298
+ renderForm,
6299
+ renderSuccess,
6300
+ onSubmitSuccess
6301
+ }) => {
6302
+ const { validateAll, getFormData: getFormData2, resetForm } = useFormContext();
6303
+ const [submitted, setSubmitted] = useState29(false);
6304
+ const [successInfo, setSuccessInfo] = useState29(null);
6305
+ const [submitting, setSubmitting] = useState29(false);
6306
+ const { hasDraft, draftTimestamp, saveDraft, restoreDraft, clearDraft } = useDraftStorage({
6307
+ appType: config.appType,
6308
+ formUuid: config.formUuid
6309
+ });
6310
+ const { navigateToDetail, navigateToProcessDetail, isRedirecting, countdown, handlePostSubmit } = useFormNavigation({
6311
+ appType: config.appType,
6312
+ formUuid: config.formUuid,
6313
+ formType,
6314
+ mode: submitSuccessMode === "continue" ? "stay" : submitSuccessMode
6315
+ });
6316
+ const handleSubmit = useCallback13(async () => {
6317
+ const valid = await validateAll();
6318
+ if (!valid) return;
6319
+ setSubmitting(true);
6320
+ try {
6321
+ const formData = getFormData2();
6322
+ if (config.submit?.beforeSubmit) {
6323
+ const shouldContinue = await config.submit.beforeSubmit(formData);
6324
+ if (shouldContinue === false) {
6325
+ setSubmitting(false);
6326
+ return;
6327
+ }
6328
+ }
6329
+ const formInstId = `inst_${Date.now()}`;
6330
+ if (config.submit?.afterSubmit) {
6331
+ await config.submit.afterSubmit({ formInstanceId: formInstId, data: formData });
6332
+ }
6333
+ if (enableDraft) {
6334
+ clearDraft();
6335
+ }
6336
+ onSubmitSuccess?.(formInstId);
6337
+ if (submitSuccessMode === "continue") {
6338
+ resetForm();
6339
+ } else {
6340
+ setSuccessInfo({ formInstanceId: formInstId });
6341
+ setSubmitted(true);
6342
+ handlePostSubmit(formInstId);
6343
+ }
6344
+ } catch (error) {
6345
+ console.error("[FormSubmitTemplate] Submit failed:", error);
6346
+ } finally {
6347
+ setSubmitting(false);
6348
+ }
6349
+ }, [
6350
+ validateAll,
6351
+ getFormData2,
6352
+ config,
6353
+ enableDraft,
6354
+ clearDraft,
6355
+ onSubmitSuccess,
6356
+ submitSuccessMode,
6357
+ resetForm,
6358
+ handlePostSubmit
6359
+ ]);
6360
+ const handleSaveDraft = useCallback13(() => {
6361
+ const data = getFormData2();
6362
+ saveDraft(data);
6363
+ }, [getFormData2, saveDraft]);
6364
+ const handleRestoreDraft = useCallback13(() => {
6365
+ restoreDraft();
6366
+ }, [restoreDraft]);
6367
+ const handleContinue = useCallback13(() => {
6368
+ setSubmitted(false);
6369
+ setSuccessInfo(null);
6370
+ resetForm();
6371
+ }, [resetForm]);
6372
+ const handleViewDetail = useCallback13(() => {
6373
+ if (!successInfo) return;
6374
+ if (formType === "process") {
6375
+ navigateToProcessDetail(successInfo.formInstanceId);
6376
+ } else {
6377
+ navigateToDetail(successInfo.formInstanceId);
6378
+ }
6379
+ }, [successInfo, formType, navigateToDetail, navigateToProcessDetail]);
6380
+ const actions = [];
6381
+ if (enableDraft) {
6382
+ actions.push({
6383
+ key: "draft",
6384
+ label: "\u6682\u5B58",
6385
+ type: "default",
6386
+ onClick: handleSaveDraft
6387
+ });
6388
+ }
6389
+ actions.push({
6390
+ key: "reset",
6391
+ label: "\u91CD\u7F6E",
6392
+ type: "default",
6393
+ onClick: () => resetForm()
6394
+ });
6395
+ actions.push({
6396
+ key: "submit",
6397
+ label: "\u63D0\u4EA4",
6398
+ type: "primary",
6399
+ loading: submitting,
6400
+ onClick: handleSubmit
6401
+ });
6402
+ return /* @__PURE__ */ jsxs28("div", { className: "min-h-screen bg-gray-50/50", children: [
6403
+ /* @__PURE__ */ jsxs28("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: [
6404
+ header || /* @__PURE__ */ jsxs28("div", { className: "mb-6", children: [
6405
+ /* @__PURE__ */ jsx82("h1", { className: "text-2xl font-bold text-gray-900", children: schema.formMeta.title }),
6406
+ /* @__PURE__ */ jsx82("p", { className: "text-sm text-gray-500 mt-1", children: "\u8BF7\u586B\u5199\u4EE5\u4E0B\u4FE1\u606F" })
6407
+ ] }),
6408
+ enableDraft && hasDraft && !submitted && /* @__PURE__ */ jsx82("div", { className: "mb-6", children: /* @__PURE__ */ jsx82(
6409
+ DraftManager,
6410
+ {
6411
+ hasDraft,
6412
+ draftTimestamp,
6413
+ onRestore: handleRestoreDraft,
6414
+ onDiscard: clearDraft
6415
+ }
6416
+ ) }),
6417
+ !submitted ? /* @__PURE__ */ jsxs28("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6 animate-[fadeIn_0.2s_ease-out]", children: [
6418
+ beforeForm,
6419
+ renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ jsx82(FormRenderer, { columns: 2 }),
6420
+ afterForm
6421
+ ] }) : successInfo && /* @__PURE__ */ jsx82(
6422
+ SubmitSuccessCard,
6423
+ {
6424
+ info: successInfo,
6425
+ mode: submitSuccessMode,
6426
+ isRedirecting,
6427
+ countdown,
6428
+ onContinue: handleContinue,
6429
+ onViewDetail: handleViewDetail,
6430
+ renderSuccess
6431
+ }
6432
+ ),
6433
+ footer
6434
+ ] }),
6435
+ !submitted && /* @__PURE__ */ jsx82(FormActionBar, { actions, position: "bottom-fixed" })
6436
+ ] });
6437
+ };
6438
+ var FormSubmitTemplate = ({
6439
+ schema,
6440
+ config,
6441
+ formType = "form",
6442
+ submitSuccessMode = "redirect",
6443
+ enableDraft = false,
6444
+ header,
6445
+ footer,
6446
+ beforeForm,
6447
+ afterForm,
6448
+ renderForm,
6449
+ renderSuccess,
6450
+ onSubmitSuccess
6451
+ }) => {
6452
+ return /* @__PURE__ */ jsx82(FormProvider, { schema, config, children: /* @__PURE__ */ jsx82(
6453
+ InnerFormContent,
6454
+ {
6455
+ schema,
6456
+ config,
6457
+ formType,
6458
+ submitSuccessMode,
6459
+ enableDraft,
6460
+ header,
6461
+ footer,
6462
+ beforeForm,
6463
+ afterForm,
6464
+ renderForm,
6465
+ renderSuccess,
6466
+ onSubmitSuccess
6467
+ }
6468
+ ) });
6469
+ };
6470
+
6471
+ // src/templates/FormDetailTemplate.tsx
6472
+ import { useCallback as useCallback14 } from "react";
6473
+
6474
+ // src/templates/PageSkeleton.tsx
6475
+ import { Skeleton as Skeleton3 } from "antd";
6476
+ import { jsx as jsx83, jsxs as jsxs29 } from "react/jsx-runtime";
6477
+ var CardSkeleton = ({ children }) => /* @__PURE__ */ jsx83("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
6478
+ var SummaryCardSkeleton = () => /* @__PURE__ */ jsxs29(CardSkeleton, { children: [
6479
+ /* @__PURE__ */ jsxs29("div", { className: "flex items-start justify-between", children: [
6480
+ /* @__PURE__ */ jsxs29("div", { className: "flex-1", children: [
6481
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "large", style: { width: 200 } }),
6482
+ /* @__PURE__ */ jsx83("div", { className: "mt-2", children: /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "small", style: { width: 80 } }) })
6483
+ ] }),
6484
+ /* @__PURE__ */ jsx83(Skeleton3.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
6485
+ ] }),
6486
+ /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-3 mt-4", children: [
6487
+ /* @__PURE__ */ jsx83(Skeleton3.Avatar, { active: true, size: "small" }),
6488
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "small", style: { width: 120 } })
6489
+ ] })
6490
+ ] });
6491
+ var FormGridSkeleton = () => /* @__PURE__ */ jsx83(CardSkeleton, { children: /* @__PURE__ */ jsx83("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs29("div", { className: "space-y-2", children: [
6492
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "small", style: { width: 80 } }),
6493
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, block: true, style: { width: "100%" } })
6494
+ ] }, i)) }) });
6495
+ var ActionBarSkeleton = () => /* @__PURE__ */ jsx83("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__ */ jsxs29("div", { className: "flex items-center justify-end gap-3", children: [
6496
+ /* @__PURE__ */ jsx83(Skeleton3.Button, { active: true, style: { width: 80 } }),
6497
+ /* @__PURE__ */ jsx83(Skeleton3.Button, { active: true, style: { width: 80 } })
6498
+ ] }) });
6499
+ var TimelineSkeleton = () => /* @__PURE__ */ jsxs29(CardSkeleton, { children: [
6500
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
6501
+ /* @__PURE__ */ jsx83("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs29("div", { className: "flex gap-4", children: [
6502
+ /* @__PURE__ */ jsxs29("div", { className: "flex flex-col items-center", children: [
6503
+ /* @__PURE__ */ jsx83("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
6504
+ i < 2 && /* @__PURE__ */ jsx83("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
6505
+ ] }),
6506
+ /* @__PURE__ */ jsx83("div", { className: "flex-1 pb-4", children: /* @__PURE__ */ jsx83(Skeleton3, { active: true, paragraph: { rows: 1 }, title: { width: "60%" } }) })
6507
+ ] }, i)) })
6508
+ ] });
6509
+ var PageSkeleton = ({ type }) => {
6510
+ if (type === "submit") {
6511
+ return /* @__PURE__ */ jsxs29("div", { className: "space-y-6", children: [
6512
+ /* @__PURE__ */ jsxs29("div", { className: "space-y-2", children: [
6513
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "large", style: { width: 200 } }),
6514
+ /* @__PURE__ */ jsx83(Skeleton3.Input, { active: true, size: "small", style: { width: 300 } })
6515
+ ] }),
6516
+ /* @__PURE__ */ jsx83(FormGridSkeleton, {}),
6517
+ /* @__PURE__ */ jsx83(ActionBarSkeleton, {})
6518
+ ] });
6519
+ }
6520
+ if (type === "detail") {
6521
+ return /* @__PURE__ */ jsxs29("div", { className: "space-y-6", children: [
6522
+ /* @__PURE__ */ jsx83(SummaryCardSkeleton, {}),
6523
+ /* @__PURE__ */ jsx83(FormGridSkeleton, {}),
6524
+ /* @__PURE__ */ jsx83(ActionBarSkeleton, {})
6525
+ ] });
6526
+ }
6527
+ return /* @__PURE__ */ jsxs29("div", { className: "space-y-6", children: [
6528
+ /* @__PURE__ */ jsx83(SummaryCardSkeleton, {}),
6529
+ /* @__PURE__ */ jsx83(FormGridSkeleton, {}),
6530
+ /* @__PURE__ */ jsx83(TimelineSkeleton, {}),
6531
+ /* @__PURE__ */ jsx83(ActionBarSkeleton, {})
6532
+ ] });
6533
+ };
6534
+
6535
+ // src/templates/FormDetailTemplate.tsx
6536
+ import { Fragment as Fragment6, jsx as jsx84, jsxs as jsxs30 } from "react/jsx-runtime";
6537
+ var InnerDetailContent = ({
6538
+ schema,
6539
+ formUuid,
6540
+ appType,
6541
+ formInstanceId,
6542
+ enableEdit = true,
6543
+ enableDelete = false,
6544
+ enableChangeRecords = false,
6545
+ header,
6546
+ footer,
6547
+ renderSummary,
6548
+ renderActions,
6549
+ onDelete,
6550
+ onSave
6551
+ }) => {
6552
+ const {
6553
+ loading,
6554
+ mode,
6555
+ formData,
6556
+ instanceInfo,
6557
+ fieldBehaviors,
6558
+ switchToEdit,
6559
+ switchToReadonly,
6560
+ saveChanges,
6561
+ deleteInstance,
6562
+ canEdit,
6563
+ canDelete,
6564
+ canViewChangeRecords
6565
+ } = useFormDetail({ formUuid, appType, formInstanceId });
6566
+ const {
6567
+ records,
6568
+ loading: recordsLoading,
6569
+ hasMore,
6570
+ loadMore,
6571
+ refresh: refreshRecords
6572
+ } = useChangeRecords({
6573
+ formUuid,
6574
+ appType,
6575
+ formInstanceId,
6576
+ autoLoad: enableChangeRecords && canViewChangeRecords
6577
+ });
6578
+ const handleSave = useCallback14(async () => {
6579
+ if (!formData) return;
6580
+ const success = await saveChanges(formData);
6581
+ if (success) {
6582
+ onSave?.(formData);
6583
+ }
6584
+ }, [formData, saveChanges, onSave]);
6585
+ const handleDelete = useCallback14(async () => {
6586
+ const success = await deleteInstance();
6587
+ if (success) {
6588
+ onDelete?.();
6589
+ }
6590
+ }, [deleteInstance, onDelete]);
6591
+ const handleCancel = useCallback14(() => {
6592
+ switchToReadonly();
6593
+ }, [switchToReadonly]);
6594
+ const readonlyActions = [];
6595
+ if (enableEdit && canEdit) {
6596
+ readonlyActions.push({
6597
+ key: "edit",
6598
+ label: "\u7F16\u8F91",
6599
+ type: "primary",
6600
+ onClick: switchToEdit
6601
+ });
6602
+ }
6603
+ if (enableDelete && canDelete) {
6604
+ readonlyActions.push({
6605
+ key: "delete",
6606
+ label: "\u5220\u9664",
6607
+ type: "danger",
6608
+ onClick: handleDelete,
6609
+ confirm: { title: "\u786E\u8BA4\u5220\u9664", content: "\u5220\u9664\u540E\u5C06\u65E0\u6CD5\u6062\u590D\uFF0C\u786E\u8BA4\u8981\u5220\u9664\u5417\uFF1F" }
6610
+ });
6611
+ }
6612
+ const editActions = [
6613
+ { key: "cancel", label: "\u53D6\u6D88", type: "default", onClick: handleCancel },
6614
+ { key: "save", label: "\u4FDD\u5B58", type: "primary", onClick: handleSave }
6615
+ ];
6616
+ const currentActions = mode === "readonly" ? readonlyActions : editActions;
6617
+ const formConfig = {
6618
+ mode: mode === "edit" ? "edit" : "readonly",
6619
+ formUuid,
6620
+ appType,
6621
+ formInstanceId,
6622
+ permissions: {
6623
+ fieldPermissions: fieldBehaviors,
6624
+ operations: []
6625
+ }
6626
+ };
6627
+ if (loading) {
6628
+ return /* @__PURE__ */ jsx84("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ jsx84("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ jsx84(PageSkeleton, { type: "detail" }) }) });
6629
+ }
6630
+ return /* @__PURE__ */ jsxs30("div", { className: "min-h-screen bg-gray-50/50", children: [
6631
+ /* @__PURE__ */ jsx84("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ jsxs30("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
6632
+ header,
6633
+ renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ jsx84(
6634
+ FormSummaryCard,
6635
+ {
6636
+ title: schema.formMeta.title,
6637
+ formInstanceId,
6638
+ creator: instanceInfo?.creator ? {
6639
+ name: instanceInfo.creator.name,
6640
+ avatar: instanceInfo.creator.avatar,
6641
+ department: instanceInfo.creator.department
6642
+ } : void 0,
6643
+ createdAt: instanceInfo?.createdAt,
6644
+ status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
6645
+ }
6646
+ ),
6647
+ mode === "edit" && /* @__PURE__ */ jsx84("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" }),
6648
+ /* @__PURE__ */ jsx84("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsx84(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: /* @__PURE__ */ jsx84(FormRenderer, { columns: 2 }) }) }),
6649
+ enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ jsx84(
6650
+ ChangeRecords,
6651
+ {
6652
+ records,
6653
+ loading: recordsLoading,
6654
+ hasMore,
6655
+ onLoadMore: loadMore,
6656
+ onExpand: refreshRecords
6657
+ }
6658
+ ),
6659
+ footer
6660
+ ] }) }),
6661
+ currentActions.length > 0 && (renderActions ? /* @__PURE__ */ jsx84(Fragment6, { children: renderActions(currentActions) }) : /* @__PURE__ */ jsx84(FormActionBar, { position: "bottom-fixed", actions: currentActions }))
6662
+ ] });
6663
+ };
6664
+ var FormDetailTemplate = (props) => {
6665
+ const { schema, formUuid, appType, formInstanceId } = props;
6666
+ const wrapperConfig = {
6667
+ mode: "readonly",
6668
+ formUuid,
6669
+ appType,
6670
+ formInstanceId
6671
+ };
6672
+ return /* @__PURE__ */ jsx84(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ jsx84(InnerDetailContent, { ...props }) });
6673
+ };
6674
+
6675
+ // src/templates/ProcessDetailTemplate.tsx
6676
+ import { useCallback as useCallback15, useRef as useRef12 } from "react";
6677
+ import { Fragment as Fragment7, jsx as jsx85, jsxs as jsxs31 } from "react/jsx-runtime";
6678
+ function FormDataBridge({
6679
+ formDataRef
6680
+ }) {
6681
+ const { getFormData: getFormData2 } = useFormContext();
6682
+ formDataRef.current = getFormData2;
6683
+ return null;
6684
+ }
6685
+ var InnerProcessContent = ({
6686
+ schema,
6687
+ formUuid,
6688
+ appType,
6689
+ formInstanceId,
6690
+ header,
6691
+ renderTimeline,
6692
+ renderActions,
6693
+ beforeForm,
6694
+ afterForm,
6695
+ onActionComplete
6696
+ }) => {
6697
+ const formDataRef = useRef12(void 0);
6698
+ const {
6699
+ loading,
6700
+ processInfo,
6701
+ processStatus,
6702
+ currentTask,
6703
+ progressList,
6704
+ formData,
6705
+ isApprover,
6706
+ activeActions,
6707
+ fieldBehaviors,
6708
+ mode,
6709
+ isOriginatorReturn,
6710
+ canWithdraw,
6711
+ switchToEdit,
6712
+ switchToReadonly,
6713
+ refreshProgress
6714
+ } = useProcessDetail({ formUuid, appType, formInstanceId });
6715
+ const { approve, reject, withdraw, save, resubmit } = useApprovalActions({
6716
+ formInstanceId,
6717
+ formUuid,
6718
+ appType,
6719
+ currentTaskId: currentTask?.taskId,
6720
+ onActionComplete: async (action) => {
6721
+ onActionComplete?.(action);
6722
+ await refreshProgress();
6723
+ },
6724
+ getFormValues: () => formDataRef.current?.() ?? {}
6725
+ });
6726
+ const handleApprove = useCallback15(
6727
+ async (comments) => {
6728
+ await approve(comments);
6729
+ },
6730
+ [approve]
6731
+ );
6732
+ const handleReject = useCallback15(
6733
+ async (comments) => {
6734
+ await reject(comments);
6735
+ },
6736
+ [reject]
6737
+ );
6738
+ const handleWithdraw = useCallback15(
6739
+ async (reason) => {
6740
+ await withdraw(reason);
6741
+ },
6742
+ [withdraw]
6743
+ );
6744
+ const handleSave = useCallback15(async () => {
6745
+ await save();
6746
+ }, [save]);
6747
+ const handleResubmit = useCallback15(async () => {
6748
+ await resubmit();
6749
+ }, [resubmit]);
6750
+ const buildActions = () => {
6751
+ const actions = [];
6752
+ if (isApprover && activeActions.length > 0) {
6753
+ return [];
6754
+ }
6755
+ if (isOriginatorReturn) {
6756
+ if (mode === "readonly") {
6757
+ actions.push({
6758
+ key: "edit",
6759
+ label: "\u7F16\u8F91",
6760
+ type: "primary",
6761
+ onClick: switchToEdit
6762
+ });
6763
+ } else {
6764
+ actions.push({
6765
+ key: "cancel",
6766
+ label: "\u53D6\u6D88",
6767
+ type: "default",
6768
+ onClick: switchToReadonly
6769
+ });
6770
+ actions.push({
6771
+ key: "resubmit",
6772
+ label: "\u91CD\u65B0\u63D0\u4EA4",
6773
+ type: "primary",
6774
+ onClick: handleResubmit
6775
+ });
6776
+ }
6777
+ return actions;
6778
+ }
6779
+ if (canWithdraw) {
6780
+ actions.push({
6781
+ key: "withdraw",
6782
+ label: "\u64A4\u9500",
6783
+ type: "default",
6784
+ onClick: () => handleWithdraw(),
6785
+ confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u786E\u8BA4\u8981\u64A4\u9500\u6B64\u6D41\u7A0B\u5417\uFF1F" }
6786
+ });
6787
+ }
6788
+ return actions;
6789
+ };
6790
+ const formConfig = {
6791
+ mode: mode === "edit" ? "edit" : "readonly",
6792
+ formUuid,
6793
+ appType,
6794
+ formInstanceId,
6795
+ permissions: {
6796
+ fieldPermissions: fieldBehaviors,
6797
+ operations: []
6798
+ }
6799
+ };
6800
+ if (loading) {
6801
+ return /* @__PURE__ */ jsx85("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ jsx85("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ jsx85(PageSkeleton, { type: "process" }) }) });
6802
+ }
6803
+ const bottomActions = buildActions();
6804
+ const showApprovalActions = isApprover && activeActions.length > 0;
6805
+ return /* @__PURE__ */ jsxs31("div", { className: "min-h-screen bg-gray-50/50", children: [
6806
+ /* @__PURE__ */ jsx85("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ jsxs31("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
6807
+ header,
6808
+ /* @__PURE__ */ jsx85(
6809
+ FormSummaryCard,
6810
+ {
6811
+ title: schema.formMeta.title,
6812
+ formInstanceId,
6813
+ creator: processInfo?.originatorName ? {
6814
+ name: processInfo.originatorName,
6815
+ department: processInfo.originatorDepartment
6816
+ } : void 0,
6817
+ createdAt: processInfo?.createdAt,
6818
+ status: processStatus ? PROCESS_STATUS_META[processStatus] : void 0
6819
+ }
6820
+ ),
6821
+ beforeForm,
6822
+ mode === "edit" && /* @__PURE__ */ jsx85("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" }),
6823
+ /* @__PURE__ */ jsx85("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsxs31(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
6824
+ /* @__PURE__ */ jsx85(FormDataBridge, { formDataRef }),
6825
+ /* @__PURE__ */ jsx85(FormRenderer, { columns: 2 })
6826
+ ] }) }),
6827
+ afterForm,
6828
+ /* @__PURE__ */ jsxs31("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
6829
+ /* @__PURE__ */ jsx85("h3", { className: "text-lg font-semibold text-gray-900 mb-4", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
6830
+ renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ jsx85(ApprovalTimeline, { tasks: progressList, showRemarks: true })
6831
+ ] })
6832
+ ] }) }),
6833
+ showApprovalActions && (renderActions ? /* @__PURE__ */ jsx85(Fragment7, { children: renderActions(activeActions) }) : /* @__PURE__ */ jsx85("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__ */ jsx85("div", { className: "max-w-4xl mx-auto flex items-center justify-end", children: /* @__PURE__ */ jsx85(
6834
+ ApprovalActions,
6835
+ {
6836
+ actions: activeActions,
6837
+ onApprove: handleApprove,
6838
+ onReject: handleReject,
6839
+ onWithdraw: handleWithdraw,
6840
+ onSave: handleSave
6841
+ }
6842
+ ) }) })),
6843
+ !showApprovalActions && bottomActions.length > 0 && /* @__PURE__ */ jsx85(FormActionBar, { position: "bottom-fixed", actions: bottomActions })
6844
+ ] });
6845
+ };
6846
+ var ProcessDetailTemplate = (props) => {
6847
+ const { schema, formUuid, appType, formInstanceId } = props;
6848
+ const wrapperConfig = {
6849
+ mode: "readonly",
6850
+ formUuid,
6851
+ appType,
6852
+ formInstanceId
6853
+ };
6854
+ return /* @__PURE__ */ jsx85(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ jsx85(InnerProcessContent, { ...props }) });
6855
+ };
4713
6856
  export {
4714
6857
  AddressField,
6858
+ ApprovalActions,
6859
+ ApprovalTimeline,
4715
6860
  AssociationFormField,
4716
6861
  AttachmentField,
4717
6862
  CascadeDateField,
4718
6863
  CascadeSelectField,
6864
+ ChangeRecords,
4719
6865
  CheckboxField,
4720
6866
  ComponentRegistryContext,
4721
6867
  ComponentRegistryProvider,
4722
6868
  DateField,
4723
6869
  DepartmentSelectField,
4724
6870
  DigitalSignatureField,
6871
+ DraftManager,
4725
6872
  EditorField,
4726
6873
  UserSelectField as EmployeeSelectField,
4727
6874
  FieldWrapper,
6875
+ FormActionBar,
4728
6876
  FormActions,
4729
6877
  FormContainer,
4730
6878
  FormContext,
6879
+ FormDetailTemplate,
4731
6880
  FormGrid,
4732
6881
  FormProvider,
4733
6882
  FormRenderer,
4734
6883
  FormSection,
4735
6884
  FormSteps,
6885
+ FormSubmitTemplate,
4736
6886
  FormSummary,
6887
+ FormSummaryCard,
4737
6888
  FormTabs,
4738
6889
  ImageField,
4739
6890
  JSONField,
4740
6891
  LocationField,
4741
6892
  MultiSelectField,
4742
6893
  NumberField,
6894
+ PROCESS_STATUS_META,
6895
+ PageSkeleton,
6896
+ ProcessDetailTemplate,
6897
+ ProcessPreview,
4743
6898
  RadioField,
4744
6899
  SelectField,
4745
6900
  SerialNumberField,
4746
6901
  SubFormField,
6902
+ TASK_STATUS_META,
4747
6903
  TextAreaField,
4748
6904
  TextField,
4749
6905
  TextAreaField as TextareaField,
4750
6906
  UserSelectField,
6907
+ checkUserApproval,
4751
6908
  createFormRuntimeApi,
4752
6909
  defaultComponentRegistry,
4753
6910
  defineFormSchema,
6911
+ deleteFormData,
4754
6912
  evaluateEffects,
6913
+ getChangeRecords,
6914
+ getFormData,
6915
+ getProcessBasic,
6916
+ getProcessDefinition,
6917
+ getProcessProgress,
6918
+ getReturnableNodes,
6919
+ getViewPermission,
6920
+ handleApproval,
6921
+ previewProcess,
6922
+ resubmitTask,
6923
+ returnTask,
6924
+ saveTask,
6925
+ transferTask,
6926
+ useApprovalActions,
6927
+ useChangeRecords,
4755
6928
  useComponent,
4756
6929
  useDeviceDetect,
6930
+ useDraftStorage,
4757
6931
  useFieldBehavior,
6932
+ useFieldPermission,
4758
6933
  useFormContext,
4759
6934
  useFormData,
6935
+ useFormDetail,
4760
6936
  useFormEngine,
6937
+ useFormNavigation,
4761
6938
  useFormSubmit,
6939
+ useProcessDetail,
4762
6940
  validateAllFields,
4763
- validateField
6941
+ validateField,
6942
+ withdrawProcess
4764
6943
  };
4765
6944
  //# sourceMappingURL=index.mjs.map