sy-form-components 0.2.6 → 0.2.7

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.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AddressField: () => AddressField,
34
+ ApprovalActionBar: () => ApprovalActionBar,
34
35
  ApprovalActions: () => ApprovalActions,
35
36
  ApprovalTimeline: () => ApprovalTimeline,
36
37
  AssociationFormField: () => AssociationFormField,
@@ -41,6 +42,7 @@ __export(index_exports, {
41
42
  CheckboxField: () => CheckboxField,
42
43
  ComponentRegistryContext: () => ComponentRegistryContext,
43
44
  ComponentRegistryProvider: () => ComponentRegistryProvider,
45
+ DataManagementList: () => DataManagementList,
44
46
  DateField: () => DateField,
45
47
  DepartmentSelectField: () => DepartmentSelectField,
46
48
  DigitalSignatureField: () => DigitalSignatureField,
@@ -72,34 +74,58 @@ __export(index_exports, {
72
74
  ProcessDetailTemplate: () => ProcessDetailTemplate,
73
75
  ProcessPreview: () => ProcessPreview,
74
76
  RadioField: () => RadioField,
77
+ RecordChangePanel: () => RecordChangePanel,
78
+ RuntimePageShell: () => RuntimePageShell,
75
79
  SelectField: () => SelectField,
76
80
  SerialNumberField: () => SerialNumberField,
81
+ StickyActionBar: () => StickyActionBar,
77
82
  SubFormField: () => SubFormField,
83
+ SummaryPanel: () => SummaryPanel,
78
84
  TASK_STATUS_META: () => TASK_STATUS_META,
79
85
  TextAreaField: () => TextAreaField,
80
86
  TextField: () => TextField,
81
87
  TextareaField: () => TextAreaField,
82
88
  UserSelectField: () => UserSelectField,
89
+ advancedSearchDataManagement: () => advancedSearchDataManagement,
90
+ batchApproveDataManagementRows: () => batchApproveDataManagementRows,
91
+ buildFilterPayload: () => buildFilterPayload,
83
92
  checkUserApproval: () => checkUserApproval,
84
93
  createFormRuntimeApi: () => createFormRuntimeApi,
85
94
  defaultComponentRegistry: () => defaultComponentRegistry,
86
95
  defineFormSchema: () => defineFormSchema,
96
+ deleteDataManagementRows: () => deleteDataManagementRows,
87
97
  deleteFormData: () => deleteFormData,
88
98
  evaluateEffects: () => evaluateEffects,
99
+ exportDataManagementRows: () => exportDataManagementRows,
89
100
  extractFormValues: () => extractFormValues,
90
101
  getChangeRecords: () => getChangeRecords,
102
+ getDataManagementConfig: () => getDataManagementConfig,
103
+ getDataManagementSchema: () => getDataManagementSchema,
104
+ getDataManagementTransferRecords: () => getDataManagementTransferRecords,
91
105
  getFormData: () => getFormData,
92
106
  getProcessBasic: () => getProcessBasic,
93
107
  getProcessDefinition: () => getProcessDefinition,
94
108
  getProcessProgress: () => getProcessProgress,
95
109
  getReturnableNodes: () => getReturnableNodes,
110
+ getSystemFieldsForFormType: () => getSystemFieldsForFormType,
96
111
  getViewPermission: () => getViewPermission,
97
112
  handleApproval: () => handleApproval,
113
+ hasViewOperation: () => hasViewOperation,
114
+ hasViewPermission: () => hasViewPermission,
115
+ importDataManagementRows: () => importDataManagementRows,
116
+ importPreviewDataManagementRows: () => importPreviewDataManagementRows,
117
+ normalizeColumnConfig: () => normalizeColumnConfig,
118
+ normalizeDataManagementFields: () => normalizeDataManagementFields,
119
+ normalizeDataManagementList: () => normalizeDataManagementList,
120
+ normalizeFieldBehaviors: () => normalizeFieldBehaviors,
121
+ normalizeOperation: () => normalizeOperation,
98
122
  previewProcess: () => previewProcess,
99
123
  resubmitTask: () => resubmitTask,
100
124
  returnTask: () => returnTask,
125
+ saveDataManagementConfig: () => saveDataManagementConfig,
101
126
  saveTask: () => saveTask,
102
127
  transferTask: () => transferTask,
128
+ triggerCallbackTask: () => triggerCallbackTask,
103
129
  useApprovalActions: () => useApprovalActions,
104
130
  useChangeRecords: () => useChangeRecords,
105
131
  useComponent: () => useComponent,
@@ -6008,8 +6034,8 @@ var parseResponse = async (response) => {
6008
6034
  const contentType = response.headers.get("content-type") || "";
6009
6035
  const payload = contentType.includes("application/json") ? await response.json() : await response.text();
6010
6036
  if (!response.ok) {
6011
- const message = typeof payload === "object" && payload ? payload.message || payload.error || response.statusText : response.statusText;
6012
- throw new Error(message || "\u8BF7\u6C42\u5931\u8D25");
6037
+ const message2 = typeof payload === "object" && payload ? payload.message || payload.error || response.statusText : response.statusText;
6038
+ throw new Error(message2 || "\u8BF7\u6C42\u5931\u8D25");
6013
6039
  }
6014
6040
  if (typeof payload === "object" && payload) {
6015
6041
  return payload;
@@ -6690,6 +6716,26 @@ var normalizeApprovalPermission = (value) => {
6690
6716
  currentTasks
6691
6717
  };
6692
6718
  };
6719
+ var normalizeReturnableNodes = (value) => {
6720
+ const raw = value?.candidates || value?.nodes || value?.data || value;
6721
+ if (!Array.isArray(raw)) return [];
6722
+ return raw.map((node) => ({
6723
+ ...node,
6724
+ nodeId: node?.nodeId || node?.id || "",
6725
+ nodeName: node?.nodeName || node?.name || node?.title || node?.id || ""
6726
+ }));
6727
+ };
6728
+ var normalizeProcessDefinition = (value) => {
6729
+ const raw = value?.definitionJson || value?.viewJson || value || {};
6730
+ const nodes = Array.isArray(raw.nodes) ? raw.nodes : [];
6731
+ const startNode = nodes.find((node) => node?.type === "start" || node?.nodeType === "start");
6732
+ return {
6733
+ ...raw,
6734
+ processId: raw.processId || raw.id || value?.id || "",
6735
+ flowConfig: raw.flowConfig || value?.flowConfig || {},
6736
+ startNodeId: raw.startNodeId || startNode?.id || value?.startNodeId
6737
+ };
6738
+ };
6693
6739
  async function getProcessBasic(request, formInstId) {
6694
6740
  const response = await request({
6695
6741
  url: `/workflow/instance/${formInstId}/basic`,
@@ -6769,7 +6815,7 @@ async function getReturnableNodes(request, taskId) {
6769
6815
  url: `/workflow/task/${taskId}/returnable-nodes`,
6770
6816
  method: "get"
6771
6817
  });
6772
- return response.data || response.result || [];
6818
+ return normalizeReturnableNodes(response.data || response.result);
6773
6819
  }
6774
6820
  async function previewProcess(request, params) {
6775
6821
  const response = await request({
@@ -6785,6 +6831,14 @@ async function getProcessDefinition(request, formUuid) {
6785
6831
  method: "get",
6786
6832
  params: { formUuid }
6787
6833
  });
6834
+ return normalizeProcessDefinition(response.data || response.result);
6835
+ }
6836
+ async function triggerCallbackTask(request, params) {
6837
+ const response = await request({
6838
+ url: `/workflow/task/${params.taskId}/callback`,
6839
+ method: "post",
6840
+ data: params.payload || {}
6841
+ });
6788
6842
  return response.data || response.result;
6789
6843
  }
6790
6844
  async function getFormData(request, params) {
@@ -6820,6 +6874,256 @@ async function getViewPermission(request, params) {
6820
6874
  return response.data || response.result;
6821
6875
  }
6822
6876
 
6877
+ // src/core/dataManagementApi.ts
6878
+ var unwrap = (response) => {
6879
+ if (response instanceof Blob) return response;
6880
+ if (response?.data?.result !== void 0) return response.data.result;
6881
+ if (response?.result !== void 0) return response.result;
6882
+ if (response?.data !== void 0) return response.data;
6883
+ return response;
6884
+ };
6885
+ var pickData = (value) => value?.data ?? value?.result ?? value;
6886
+ var normalizeComponentName = (field) => field?.componentName || field?.component_name || field?.component_type || field?.componentType || field?.type || "TextField";
6887
+ var normalizeField = (key, field, system = false) => ({
6888
+ ...field,
6889
+ id: field?.id || field?.fieldId || key,
6890
+ fieldId: field?.fieldId || field?.id || key,
6891
+ componentName: normalizeComponentName(field),
6892
+ label: field?.label || field?.title || field?.name || key,
6893
+ width: field?.width,
6894
+ system
6895
+ });
6896
+ var PROCESS_INSTANCE_STATUS_OPTIONS = [
6897
+ { label: "\u5F85\u5904\u7406", value: "pending" },
6898
+ { label: "\u5BA1\u6279\u4E2D", value: "running" },
6899
+ { label: "\u7B49\u5F85\u4E2D", value: "waiting" },
6900
+ { label: "\u6D41\u7A0B\u5F02\u5E38", value: "exception" },
6901
+ { label: "\u5DF2\u5B8C\u6210", value: "completed" },
6902
+ { label: "\u5DF2\u62D2\u7EDD", value: "terminated" },
6903
+ { label: "\u5DF2\u64A4\u9500", value: "withdrawn" }
6904
+ ];
6905
+ var APPROVAL_RESULT_OPTIONS = [
6906
+ { label: "\u5BA1\u6279\u4E2D", value: "processing" },
6907
+ { label: "\u540C\u610F", value: "approved" },
6908
+ { label: "\u62D2\u7EDD", value: "rejected" },
6909
+ { label: "\u64A4\u9500", value: "withdrawn" },
6910
+ { label: "\u5F02\u5E38", value: "exception" }
6911
+ ];
6912
+ var PROCESS_SYSTEM_FIELDS = [
6913
+ normalizeField(
6914
+ "currentApprovalNodeName",
6915
+ {
6916
+ label: "\u5F53\u524D\u5BA1\u6279\u8282\u70B9",
6917
+ componentName: "TextField",
6918
+ width: 140,
6919
+ processOnly: true,
6920
+ displayable: true
6921
+ },
6922
+ true
6923
+ ),
6924
+ normalizeField(
6925
+ "processInstanceStatus",
6926
+ {
6927
+ label: "\u5B9E\u4F8B\u72B6\u6001",
6928
+ componentName: "SelectField",
6929
+ width: 110,
6930
+ options: PROCESS_INSTANCE_STATUS_OPTIONS,
6931
+ processOnly: true,
6932
+ displayable: true
6933
+ },
6934
+ true
6935
+ ),
6936
+ normalizeField(
6937
+ "approvalResult",
6938
+ {
6939
+ label: "\u5BA1\u6279\u7ED3\u679C",
6940
+ componentName: "SelectField",
6941
+ width: 110,
6942
+ options: APPROVAL_RESULT_OPTIONS,
6943
+ processOnly: true,
6944
+ displayable: true
6945
+ },
6946
+ true
6947
+ )
6948
+ ];
6949
+ var BASE_SYSTEM_FIELDS = [
6950
+ normalizeField("createTime", { label: "\u521B\u5EFA\u65F6\u95F4", componentName: "DateField", width: 170 }, true),
6951
+ normalizeField(
6952
+ "modifiedTime",
6953
+ { label: "\u66F4\u65B0\u65F6\u95F4", componentName: "DateField", width: 170 },
6954
+ true
6955
+ ),
6956
+ normalizeField(
6957
+ "originatorName",
6958
+ { label: "\u521B\u5EFA\u4EBA", componentName: "TextField", width: 130 },
6959
+ true
6960
+ )
6961
+ ];
6962
+ var getSystemFieldsForFormType = (formType) => formType === "process" ? [...BASE_SYSTEM_FIELDS, ...PROCESS_SYSTEM_FIELDS] : BASE_SYSTEM_FIELDS;
6963
+ var normalizeDataManagementFields = (payload) => {
6964
+ const data = pickData(payload);
6965
+ const formType = data?.formType || data?.schema?.formType || data?.type;
6966
+ const rawFields = data?.formFields || data?.schema?.formFields || data?.fields || data?.schema?.fields || data?.formSchema?.fields || [];
6967
+ const fields = Array.isArray(rawFields) ? rawFields.map((field) => normalizeField(field?.fieldId || field?.id, field)) : Object.entries(rawFields).map(([key, field]) => normalizeField(key, field));
6968
+ return {
6969
+ fields: fields.filter((field) => field.componentName !== "PageSection"),
6970
+ formType
6971
+ };
6972
+ };
6973
+ var normalizeDataManagementList = (payload) => {
6974
+ const data = unwrap(payload);
6975
+ const body = data?.result || data;
6976
+ const records = body?.data || body?.records || body?.list || body?.items || [];
6977
+ const total = body?.totalCount ?? body?.total ?? body?.count ?? records.length;
6978
+ return {
6979
+ records: Array.isArray(records) ? records : [],
6980
+ total: Number(total) || 0
6981
+ };
6982
+ };
6983
+ var buildFilterPayload = (group) => {
6984
+ if (!group) return void 0;
6985
+ const trimGroup = (current) => ({
6986
+ ...current,
6987
+ rules: (current.rules || []).filter(
6988
+ (rule) => rule.key && rule.operator && rule.value !== void 0 && rule.value !== ""
6989
+ ),
6990
+ conditions: (current.conditions || []).map(trimGroup).filter((item) => item.rules.length > 0 || item.conditions.length > 0)
6991
+ });
6992
+ const payload = trimGroup(group);
6993
+ if (payload.rules.length === 0 && payload.conditions.length === 0) return void 0;
6994
+ return JSON.stringify(payload);
6995
+ };
6996
+ var normalizeColumnConfig = (cfg, fields) => {
6997
+ const allowed = new Set(fields.map((field) => field.fieldId));
6998
+ const configured = Array.isArray(cfg?.showFields) ? cfg.showFields.filter((fieldId) => allowed.has(fieldId)) : [];
6999
+ const defaultShow = fields.filter((field) => !field.system || field.displayable).slice(0, 8).map((field) => field.fieldId);
7000
+ return {
7001
+ showFields: configured.length > 0 ? configured : defaultShow,
7002
+ widths: cfg?.widths || {},
7003
+ lockFieldIds: cfg?.lockFieldIds || [],
7004
+ sort: Array.isArray(cfg?.sort) ? cfg.sort : [],
7005
+ density: cfg?.density || "middle",
7006
+ detailOpenMode: cfg?.detailOpenMode === "newPage" ? "newPage" : "drawer",
7007
+ pageSize: cfg?.pageSize || 10
7008
+ };
7009
+ };
7010
+ async function getDataManagementSchema(request, params) {
7011
+ const response = await request({
7012
+ url: "/form/getFormSchemaAndPackages",
7013
+ method: "get",
7014
+ params
7015
+ });
7016
+ return normalizeDataManagementFields(response);
7017
+ }
7018
+ async function getDataManagementConfig(request, options) {
7019
+ const targetFormUuid = options.menuFormUuid || options.formUuid;
7020
+ const personal = options.scope === "personal";
7021
+ const response = await request({
7022
+ url: `/${options.appType}/v1/form/dataManagement/config/${personal ? "personal/" : ""}get.json`,
7023
+ method: "get",
7024
+ params: { formUuid: targetFormUuid }
7025
+ });
7026
+ return unwrap(response);
7027
+ }
7028
+ async function saveDataManagementConfig(request, options) {
7029
+ const targetFormUuid = options.menuFormUuid || options.formUuid;
7030
+ const personal = options.scope === "personal";
7031
+ const response = await request({
7032
+ url: `/${options.appType}/v1/form/dataManagement/config/${personal ? "personal/" : ""}save.json`,
7033
+ method: "post",
7034
+ data: { formUuid: targetFormUuid, config: options.config }
7035
+ });
7036
+ return unwrap(response);
7037
+ }
7038
+ async function advancedSearchDataManagement(request, query) {
7039
+ const response = await request({
7040
+ url: `/${query.appType}/v1/form/advancedSearch.json`,
7041
+ method: "get",
7042
+ params: {
7043
+ appType: query.appType,
7044
+ formUuid: query.formUuid,
7045
+ filters: query.rawFilters ?? buildFilterPayload(query.filters),
7046
+ conditionType: query.conditionType,
7047
+ searchKeyWord: query.searchKeyWord,
7048
+ currentPage: query.currentPage || 1,
7049
+ pageSize: query.pageSize || 10,
7050
+ order: JSON.stringify(query.order || []),
7051
+ instanceStatus: query.instanceStatus
7052
+ }
7053
+ });
7054
+ return normalizeDataManagementList(response);
7055
+ }
7056
+ async function deleteDataManagementRows(request, params) {
7057
+ const response = await request({
7058
+ url: `/${params.appType}/v1/form/deleteFormData.json`,
7059
+ method: "post",
7060
+ data: {
7061
+ appType: params.appType,
7062
+ formUuid: params.formUuid,
7063
+ formInstIds: params.formInstanceIds,
7064
+ formInstanceIds: params.formInstanceIds
7065
+ }
7066
+ });
7067
+ return unwrap(response);
7068
+ }
7069
+ async function batchApproveDataManagementRows(request, params) {
7070
+ const response = await request({
7071
+ url: "/workflow/approve/batch",
7072
+ method: "post",
7073
+ data: {
7074
+ instanceIds: params.formInstanceIds,
7075
+ action: params.action,
7076
+ comments: params.comments
7077
+ }
7078
+ });
7079
+ return unwrap(response);
7080
+ }
7081
+ async function exportDataManagementRows(request, params) {
7082
+ return request({
7083
+ url: `/${params.appType}/v1/form/advancedExport.xlsx`,
7084
+ method: "get",
7085
+ responseType: "blob",
7086
+ params: {
7087
+ appType: params.appType,
7088
+ formUuid: params.formUuid,
7089
+ filters: params.rawFilters ?? buildFilterPayload(params.filters),
7090
+ conditionType: params.conditionType,
7091
+ searchKeyWord: params.searchKeyWord,
7092
+ currentPage: params.currentPage,
7093
+ pageSize: params.pageSize,
7094
+ order: JSON.stringify(params.order || []),
7095
+ instanceStatus: params.instanceStatus,
7096
+ exportAll: params.exportAll || "n",
7097
+ embedImages: params.embedImages || "n",
7098
+ exportFields: (params.exportFields || []).join(",")
7099
+ }
7100
+ });
7101
+ }
7102
+ async function importPreviewDataManagementRows(request, params) {
7103
+ const response = await request({
7104
+ url: `/${params.appType}/v1/form/importPreview.xlsx`,
7105
+ method: "post",
7106
+ data: { formUuid: params.formUuid, fileBase64: params.fileBase64 }
7107
+ });
7108
+ return unwrap(response);
7109
+ }
7110
+ async function importDataManagementRows(request, params) {
7111
+ const response = await request({
7112
+ url: `/${params.appType}/v1/form/import.xlsx`,
7113
+ method: "post",
7114
+ data: { formUuid: params.formUuid, fileBase64: params.fileBase64 }
7115
+ });
7116
+ return unwrap(response);
7117
+ }
7118
+ async function getDataManagementTransferRecords(request, params) {
7119
+ const response = await request({
7120
+ url: `/${params.appType}/v1/form/${params.type}Records.json`,
7121
+ method: "get",
7122
+ params
7123
+ });
7124
+ return normalizeDataManagementList(response);
7125
+ }
7126
+
6823
7127
  // src/layout/FormSection/index.tsx
6824
7128
  var import_react41 = require("react");
6825
7129
  var import_jsx_runtime72 = require("react/jsx-runtime");
@@ -7226,37 +7530,91 @@ function useFormSubmit(config) {
7226
7530
 
7227
7531
  // src/hooks/useFieldPermission.ts
7228
7532
  var import_react48 = require("react");
7533
+
7534
+ // src/utils/permissions.ts
7535
+ var OPERATION_ALIASES = {
7536
+ VIEW: "view",
7537
+ EDIT: "edit",
7538
+ DELETE: "delete",
7539
+ VIEW_CHANGE_RECORDS: "change_records",
7540
+ CHANGE_RECORDS: "change_records",
7541
+ VIEW_PROCESS: "workflow",
7542
+ WORKFLOW: "workflow"
7543
+ };
7544
+ function normalizeOperation(operation) {
7545
+ const raw = String(operation || "").trim();
7546
+ if (!raw) return "";
7547
+ const upper = raw.toUpperCase();
7548
+ return OPERATION_ALIASES[upper] || raw.toLowerCase();
7549
+ }
7550
+ function hasViewOperation(operations, expected) {
7551
+ const normalized = new Set((operations || []).map(normalizeOperation));
7552
+ return normalized.has(normalizeOperation(expected));
7553
+ }
7554
+ function normalizeFieldBehaviors(permissions, mode) {
7555
+ const behaviors = {};
7556
+ Object.entries(permissions?.fieldPermissions || {}).forEach(([fieldId, value]) => {
7557
+ if (value === "FORM_FILED_HIDDEN") {
7558
+ behaviors[fieldId] = "HIDDEN";
7559
+ } else if (value === "FORM_FILED_EDIT") {
7560
+ behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7561
+ } else {
7562
+ behaviors[fieldId] = "READONLY";
7563
+ }
7564
+ });
7565
+ return behaviors;
7566
+ }
7567
+ function hasViewPermission(permissions) {
7568
+ const operations = permissions?.operations || [];
7569
+ return operations.length === 0 ? false : hasViewOperation(operations, "view");
7570
+ }
7571
+
7572
+ // src/hooks/useFieldPermission.ts
7573
+ var normalizeBehavior = (value) => {
7574
+ if (value === "EDITABLE") return "NORMAL";
7575
+ if (value === "READ_ONLY") return "READONLY";
7576
+ if (value === "DISABLED") return "DISABLED";
7577
+ if (value === "HIDDEN") return "HIDDEN";
7578
+ if (value === "NORMAL" || value === "READONLY") return value;
7579
+ return "READONLY";
7580
+ };
7581
+ var normalizeFlowConfig = (config) => {
7582
+ if (!config) return null;
7583
+ if (Array.isArray(config)) {
7584
+ const result = {};
7585
+ config.forEach((item) => {
7586
+ const fieldId = item?.fieldId || item?.field_id || item?.id;
7587
+ if (!fieldId) return;
7588
+ result[fieldId] = normalizeBehavior(item?.fieldBehavior || item?.behavior || item?.value);
7589
+ });
7590
+ return Object.keys(result).length > 0 ? result : null;
7591
+ }
7592
+ if (typeof config === "object") {
7593
+ const result = {};
7594
+ Object.entries(config).forEach(([fieldId, value]) => {
7595
+ result[fieldId] = normalizeBehavior(
7596
+ typeof value === "string" ? value : value?.fieldBehavior || value?.behavior
7597
+ );
7598
+ });
7599
+ return result;
7600
+ }
7601
+ return null;
7602
+ };
7229
7603
  function useFieldPermission(options) {
7230
7604
  const { viewPermissions, processDefinition, currentTask, isApprover, mode } = options;
7231
7605
  const computeBehaviors = (0, import_react48.useCallback)(() => {
7232
7606
  const behaviors = {};
7233
7607
  if (!currentTask && viewPermissions) {
7234
- const { fieldPermissions } = viewPermissions;
7235
- for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
7236
- if (perm === "FORM_FILED_HIDDEN") {
7237
- behaviors[fieldId] = "HIDDEN";
7238
- } else if (perm === "FORM_FILED_VIEW") {
7239
- behaviors[fieldId] = "READONLY";
7240
- } else if (perm === "FORM_FILED_EDIT") {
7241
- behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7242
- }
7243
- }
7244
- return behaviors;
7608
+ return normalizeFieldBehaviors(viewPermissions, mode);
7245
7609
  }
7246
7610
  if (currentTask && !isApprover && viewPermissions) {
7247
- const { fieldPermissions } = viewPermissions;
7248
- for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
7249
- if (perm === "FORM_FILED_HIDDEN") {
7250
- behaviors[fieldId] = "HIDDEN";
7251
- } else {
7252
- behaviors[fieldId] = "READONLY";
7253
- }
7254
- }
7255
- return behaviors;
7611
+ return normalizeFieldBehaviors(viewPermissions, "readonly");
7256
7612
  }
7257
7613
  if (currentTask && isApprover && currentTask.nodeType === "originator_return") {
7258
7614
  if (processDefinition?.flowConfig && processDefinition.startNodeId) {
7259
- const startConfig = processDefinition.flowConfig[processDefinition.startNodeId];
7615
+ const startConfig = normalizeFlowConfig(
7616
+ processDefinition.flowConfig[processDefinition.startNodeId]
7617
+ );
7260
7618
  if (startConfig) {
7261
7619
  for (const [fieldId, behavior] of Object.entries(startConfig)) {
7262
7620
  behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
@@ -7276,7 +7634,7 @@ function useFieldPermission(options) {
7276
7634
  return behaviors;
7277
7635
  }
7278
7636
  if (currentTask && isApprover && processDefinition?.flowConfig) {
7279
- const nodeConfig = processDefinition.flowConfig[currentTask.nodeId];
7637
+ const nodeConfig = normalizeFlowConfig(processDefinition.flowConfig[currentTask.nodeId]);
7280
7638
  if (nodeConfig) {
7281
7639
  for (const [fieldId, behavior] of Object.entries(nodeConfig)) {
7282
7640
  behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
@@ -7285,16 +7643,7 @@ function useFieldPermission(options) {
7285
7643
  }
7286
7644
  }
7287
7645
  if (viewPermissions) {
7288
- const { fieldPermissions } = viewPermissions;
7289
- for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
7290
- if (perm === "FORM_FILED_HIDDEN") {
7291
- behaviors[fieldId] = "HIDDEN";
7292
- } else if (perm === "FORM_FILED_VIEW") {
7293
- behaviors[fieldId] = "READONLY";
7294
- } else if (perm === "FORM_FILED_EDIT") {
7295
- behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7296
- }
7297
- }
7646
+ return normalizeFieldBehaviors(viewPermissions, mode);
7298
7647
  }
7299
7648
  return behaviors;
7300
7649
  }, [viewPermissions, processDefinition, currentTask, isApprover, mode]);
@@ -7373,20 +7722,6 @@ var extractFormValues = (formInstance, fieldIds) => {
7373
7722
  };
7374
7723
 
7375
7724
  // src/hooks/useFormDetail.ts
7376
- function buildFieldBehaviors(permissions, mode) {
7377
- const behaviors = {};
7378
- if (!permissions) return behaviors;
7379
- for (const [fieldId, perm] of Object.entries(permissions.fieldPermissions)) {
7380
- if (perm === "FORM_FILED_HIDDEN") {
7381
- behaviors[fieldId] = "HIDDEN";
7382
- } else if (perm === "FORM_FILED_VIEW") {
7383
- behaviors[fieldId] = "READONLY";
7384
- } else if (perm === "FORM_FILED_EDIT") {
7385
- behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7386
- }
7387
- }
7388
- return behaviors;
7389
- }
7390
7725
  function useFormDetail(options) {
7391
7726
  const { formUuid, appType, formInstanceId, fieldIds, onPermissionDenied } = options;
7392
7727
  const { api } = useFormContext();
@@ -7412,7 +7747,7 @@ function useFormDetail(options) {
7412
7747
  getFormData(request, { formInstanceId, appType, formUuid })
7413
7748
  ]);
7414
7749
  if (!mountedRef.current) return;
7415
- if (!permResult || !permResult.operations || permResult.operations.length === 0) {
7750
+ if (!permResult || !hasViewOperation(permResult.operations, "view")) {
7416
7751
  onPermissionDenied?.();
7417
7752
  }
7418
7753
  setPermissions(permResult);
@@ -7434,10 +7769,10 @@ function useFormDetail(options) {
7434
7769
  (0, import_react49.useEffect)(() => {
7435
7770
  loadData();
7436
7771
  }, [loadData]);
7437
- const fieldBehaviors = buildFieldBehaviors(permissions, mode);
7438
- const canEdit = permissions?.operations?.includes("EDIT") ?? false;
7439
- const canDelete = permissions?.operations?.includes("DELETE") ?? false;
7440
- const canViewChangeRecords = permissions?.operations?.includes("VIEW_CHANGE_RECORDS") ?? false;
7772
+ const fieldBehaviors = normalizeFieldBehaviors(permissions, mode);
7773
+ const canEdit = hasViewOperation(permissions?.operations, "edit");
7774
+ const canDelete = hasViewOperation(permissions?.operations, "delete");
7775
+ const canViewChangeRecords = hasViewOperation(permissions?.operations, "change_records");
7441
7776
  const switchToEdit = (0, import_react49.useCallback)(() => {
7442
7777
  setMode("edit");
7443
7778
  loadData();
@@ -7841,6 +8176,30 @@ function useApprovalActions(options) {
7841
8176
  },
7842
8177
  [request, currentTaskId, formUuid, appType, getFormValues, onActionComplete, resetLoading]
7843
8178
  );
8179
+ const callbackTask = (0, import_react51.useCallback)(
8180
+ async (payload) => {
8181
+ if (!currentTaskId) {
8182
+ console.error("[useApprovalActions] callbackTask failed: no currentTaskId");
8183
+ return false;
8184
+ }
8185
+ setIsLoading(true);
8186
+ setCurrentAction("callback");
8187
+ try {
8188
+ await triggerCallbackTask(request, {
8189
+ taskId: currentTaskId,
8190
+ payload
8191
+ });
8192
+ resetLoading();
8193
+ onActionComplete?.("callback");
8194
+ return true;
8195
+ } catch (error) {
8196
+ console.error("[useApprovalActions] callbackTask failed:", error);
8197
+ resetLoading();
8198
+ return false;
8199
+ }
8200
+ },
8201
+ [request, currentTaskId, onActionComplete, resetLoading]
8202
+ );
7844
8203
  const loadReturnableNodes = (0, import_react51.useCallback)(async () => {
7845
8204
  if (!currentTaskId) return;
7846
8205
  try {
@@ -7860,6 +8219,7 @@ function useApprovalActions(options) {
7860
8219
  withdraw,
7861
8220
  save,
7862
8221
  resubmit,
8222
+ callbackTask,
7863
8223
  isLoading,
7864
8224
  currentAction,
7865
8225
  returnableNodes,
@@ -8227,178 +8587,813 @@ var FormSummaryCard = ({
8227
8587
  ] });
8228
8588
  };
8229
8589
 
8230
- // src/modules/ChangeRecords.tsx
8590
+ // src/modules/RecordChangePanel.tsx
8231
8591
  var import_react55 = require("react");
8232
8592
  var import_antd23 = require("antd");
8233
8593
  var import_icons3 = require("@ant-design/icons");
8234
8594
  var import_jsx_runtime78 = require("react/jsx-runtime");
8235
- var ChangeRecords = ({
8595
+ var sourceLabels = {
8596
+ frontend: "\u524D\u7AEF",
8597
+ integration: "\u96C6\u6210",
8598
+ automation: "\u81EA\u52A8\u5316",
8599
+ import: "\u5BFC\u5165"
8600
+ };
8601
+ var typeLabels = {
8602
+ create: "\u65B0\u589E",
8603
+ update: "\u4FEE\u6539",
8604
+ delete: "\u5220\u9664"
8605
+ };
8606
+ function formatValue(value) {
8607
+ if (value === null || value === void 0 || value === "")
8608
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-ant-text-tertiary", children: "\u7A7A" });
8609
+ if (Array.isArray(value)) {
8610
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "inline-flex flex-wrap gap-1", children: value.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tag, { className: "m-0", children: String(
8611
+ typeof item === "object" ? item.label || item.value || JSON.stringify(item) : item
8612
+ ) }, `${index}-${String(item)}`)) });
8613
+ }
8614
+ if (typeof value === "object") {
8615
+ const label = value.label ?? value.value;
8616
+ return label ? String(label) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("code", { className: "text-xs", children: JSON.stringify(value) });
8617
+ }
8618
+ return String(value);
8619
+ }
8620
+ function getInitial(name) {
8621
+ return String(name || "?").trim().slice(0, 1).toUpperCase() || "?";
8622
+ }
8623
+ var RecordChangePanel = ({
8236
8624
  records = [],
8237
8625
  loading = false,
8626
+ total,
8627
+ page = 1,
8628
+ pageSize = 20,
8238
8629
  defaultExpanded = false,
8239
8630
  hasMore = false,
8240
8631
  onLoadMore,
8632
+ onRefresh,
8241
8633
  onExpand,
8242
- className = "",
8243
- renderItem
8634
+ onPageChange,
8635
+ className = ""
8244
8636
  }) => {
8245
8637
  const [expanded, setExpanded] = (0, import_react55.useState)(defaultExpanded);
8638
+ const count = total ?? records.length;
8246
8639
  const handleToggle = () => {
8247
8640
  const next = !expanded;
8248
8641
  setExpanded(next);
8249
- if (next && onExpand) {
8250
- onExpand();
8251
- }
8642
+ if (next) onExpand?.();
8252
8643
  };
8253
- const defaultRenderItem = (record) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "pl-4 py-3 border-l-2 border-gray-200 ml-1", children: [
8254
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex items-center gap-2 text-xs text-gray-400", children: [
8255
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: record.operatedAt }),
8256
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-gray-600 font-medium", children: record.operatorName }),
8257
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: "\u4FEE\u6539\u4E86" }),
8258
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-gray-800 font-medium", children: record.fieldLabel })
8259
- ] }),
8260
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "mt-1.5 text-sm text-gray-600 flex items-center gap-2", children: [
8261
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "bg-red-50 text-red-600 px-1.5 py-0.5 rounded text-xs line-through", children: formatValue(record.oldValue) }),
8262
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-gray-400", children: "\u2192" }),
8263
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "bg-green-50 text-green-600 px-1.5 py-0.5 rounded text-xs", children: formatValue(record.newValue) })
8264
- ] })
8265
- ] });
8266
- return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 ${className}`, children: [
8267
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8268
- "button",
8644
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8645
+ "section",
8646
+ {
8647
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
8648
+ children: [
8649
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex items-center justify-between gap-3 border-b border-ant-border-secondary px-5 py-4", children: [
8650
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8651
+ "button",
8652
+ {
8653
+ type: "button",
8654
+ className: "flex min-w-0 items-center gap-2 bg-transparent p-0 text-left",
8655
+ onClick: handleToggle,
8656
+ children: [
8657
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.HistoryOutlined, { className: "text-ant-primary" }),
8658
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "font-semibold text-ant-text", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8659
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-xs text-ant-text-tertiary", children: [
8660
+ count,
8661
+ " \u6761"
8662
+ ] }),
8663
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.UpOutlined, { className: "text-xs" }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.DownOutlined, { className: "text-xs" })
8664
+ ]
8665
+ }
8666
+ ),
8667
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8668
+ import_antd23.Button,
8669
+ {
8670
+ type: "text",
8671
+ size: "small",
8672
+ icon: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.ReloadOutlined, {}),
8673
+ onClick: onRefresh,
8674
+ disabled: loading,
8675
+ children: "\u5237\u65B0"
8676
+ }
8677
+ )
8678
+ ] }),
8679
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "p-5", children: [
8680
+ loading && records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Skeleton, { active: true, paragraph: { rows: 3 } }) : records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Empty, { description: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "space-y-4", children: records.map((record) => {
8681
+ const changes = record.changes && record.changes.length > 0 ? record.changes : [
8682
+ {
8683
+ fieldKey: record.fieldId,
8684
+ fieldLabel: record.fieldLabel,
8685
+ beforeValue: record.oldValue,
8686
+ afterValue: record.newValue
8687
+ }
8688
+ ];
8689
+ const operator = record.operatorName || (record.changeSource ? "\u7CFB\u7EDF" : "\u672A\u77E5");
8690
+ const operatedAt = record.operatedAt || record.createdAt || "-";
8691
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8692
+ "article",
8693
+ {
8694
+ className: "rounded-md border border-ant-border-secondary p-4",
8695
+ children: [
8696
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
8697
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex min-w-0 items-center gap-3", children: [
8698
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-blue-50 text-sm font-semibold text-blue-700", children: getInitial(operator) }),
8699
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "min-w-0", children: [
8700
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "block text-sm font-medium text-ant-text", children: [
8701
+ operator,
8702
+ record.operatorDepartmentName && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "ml-2 font-normal text-ant-text-tertiary", children: record.operatorDepartmentName })
8703
+ ] }),
8704
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "block text-xs text-ant-text-tertiary", children: [
8705
+ "\u53D8\u66F4 ",
8706
+ record.changedCount || changes.length,
8707
+ " \u9879 \xB7 ",
8708
+ operatedAt
8709
+ ] })
8710
+ ] })
8711
+ ] }),
8712
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "flex flex-wrap justify-end gap-2", children: [
8713
+ record.changeType && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tag, { children: typeLabels[record.changeType] || record.changeType }),
8714
+ record.changeSource && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tag, { color: "blue", children: sourceLabels[record.changeSource] || record.changeSource }),
8715
+ record.operationId && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tooltip, { title: `\u64CD\u4F5CID\uFF1A${record.operationId}`, children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tag, { children: record.operationId.slice(0, 8) }) })
8716
+ ] })
8717
+ ] }),
8718
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mt-4 space-y-3", children: changes.map((change) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8719
+ "div",
8720
+ {
8721
+ className: "grid gap-2 md:grid-cols-[160px_1fr]",
8722
+ children: [
8723
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "text-sm font-medium text-ant-text-secondary", children: change.fieldLabel || change.fieldKey || "-" }),
8724
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "grid min-w-0 grid-cols-[1fr_auto_1fr] items-start gap-2 text-sm", children: [
8725
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "min-w-0 rounded bg-red-50 px-2 py-1 text-red-700", children: formatValue(change.beforeValue) }),
8726
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.ArrowRightOutlined, { className: "mt-1 text-xs text-ant-text-tertiary" }),
8727
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "min-w-0 rounded bg-emerald-50 px-2 py-1 text-emerald-700", children: formatValue(change.afterValue) })
8728
+ ] })
8729
+ ]
8730
+ },
8731
+ change.fieldKey || change.fieldLabel
8732
+ )) })
8733
+ ]
8734
+ },
8735
+ record.id || record.operationId
8736
+ );
8737
+ }) }),
8738
+ onPageChange && count > pageSize ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8739
+ import_antd23.Pagination,
8740
+ {
8741
+ size: "small",
8742
+ current: page,
8743
+ pageSize,
8744
+ total: count,
8745
+ onChange: onPageChange,
8746
+ showSizeChanger: true
8747
+ }
8748
+ ) }) : hasMore ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Button, { block: true, className: "mt-4", onClick: onLoadMore, loading, children: "\u52A0\u8F7D\u66F4\u591A" }) : null
8749
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "px-5 py-4 text-sm text-ant-text-tertiary", children: "\u70B9\u51FB\u5C55\u5F00\u67E5\u770B\u53D8\u66F4\u8BB0\u5F55" })
8750
+ ]
8751
+ }
8752
+ );
8753
+ };
8754
+
8755
+ // src/modules/ChangeRecords.tsx
8756
+ var import_jsx_runtime79 = require("react/jsx-runtime");
8757
+ var ChangeRecords = ({
8758
+ records = [],
8759
+ loading = false,
8760
+ defaultExpanded = false,
8761
+ hasMore = false,
8762
+ onLoadMore,
8763
+ onExpand,
8764
+ className = "",
8765
+ renderItem
8766
+ }) => {
8767
+ if (renderItem) {
8768
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8769
+ "section",
8269
8770
  {
8270
- type: "button",
8271
- className: "w-full flex items-center justify-between p-6 text-left hover:bg-gray-50/50 transition-colors rounded-xl",
8272
- onClick: handleToggle,
8771
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
8273
8772
  children: [
8274
- /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex items-center gap-2", children: [
8275
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("h3", { className: "text-lg font-semibold text-gray-900", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8276
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-xs text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded-full", children: records.length })
8277
- ] }),
8278
- /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-gray-400 text-xs", children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.UpOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.DownOutlined, {}) })
8773
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "border-b border-ant-border-secondary px-5 py-4 font-semibold", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8774
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "p-5", children: [
8775
+ records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "m-0 text-center text-sm text-ant-text-tertiary", children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "space-y-2", children: records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { children: renderItem(record) }, record.id)) }),
8776
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8777
+ "button",
8778
+ {
8779
+ type: "button",
8780
+ className: "mt-4 w-full rounded-md border border-ant-border-secondary py-2 text-sm text-ant-primary",
8781
+ onClick: onLoadMore,
8782
+ disabled: loading,
8783
+ children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
8784
+ }
8785
+ )
8786
+ ] })
8279
8787
  ]
8280
8788
  }
8281
- ),
8282
- expanded && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "px-6 pb-6", children: [
8283
- loading && records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Skeleton, { active: true, paragraph: { rows: 3 } }) : records.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "text-sm text-gray-400 text-center py-4", children: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "space-y-1", children: records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { children: renderItem ? renderItem(record) : defaultRenderItem(record) }, record.id)) }),
8284
- hasMore && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8285
- "button",
8286
- {
8287
- type: "button",
8288
- 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",
8289
- onClick: onLoadMore,
8290
- disabled: loading,
8291
- children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
8292
- }
8293
- )
8294
- ] })
8295
- ] });
8789
+ );
8790
+ }
8791
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8792
+ RecordChangePanel,
8793
+ {
8794
+ records,
8795
+ loading,
8796
+ defaultExpanded,
8797
+ hasMore,
8798
+ onLoadMore,
8799
+ onRefresh: onExpand,
8800
+ onExpand,
8801
+ className
8802
+ }
8803
+ );
8296
8804
  };
8297
- function formatValue(value) {
8298
- if (value === null || value === void 0) return "\u7A7A";
8299
- if (typeof value === "object") return JSON.stringify(value);
8300
- return String(value);
8301
- }
8302
8805
 
8303
8806
  // src/modules/ApprovalTimeline.tsx
8304
- var import_jsx_runtime79 = require("react/jsx-runtime");
8807
+ var import_react56 = require("react");
8808
+ var import_icons4 = require("@ant-design/icons");
8809
+ var import_jsx_runtime80 = require("react/jsx-runtime");
8810
+ var systemNodeTypes = /* @__PURE__ */ new Set([
8811
+ "condition",
8812
+ "condition_branch",
8813
+ "js_code",
8814
+ "data_retrieve_single",
8815
+ "data_retrieve_batch",
8816
+ "data_create",
8817
+ "data_update",
8818
+ "connector_call",
8819
+ "loop_container",
8820
+ "work_notification",
8821
+ "dingtalk_card",
8822
+ "system"
8823
+ ]);
8824
+ var systemLabels = {
8825
+ condition: "\u6761\u4EF6\u5224\u65AD",
8826
+ condition_branch: "\u6761\u4EF6\u5206\u652F",
8827
+ js_code: "JS \u4EE3\u7801",
8828
+ data_retrieve_single: "\u6570\u636E\u8BFB\u53D6",
8829
+ data_retrieve_batch: "\u6279\u91CF\u8BFB\u53D6",
8830
+ data_create: "\u6570\u636E\u521B\u5EFA",
8831
+ data_update: "\u6570\u636E\u66F4\u65B0",
8832
+ connector_call: "\u8FDE\u63A5\u5668\u8C03\u7528",
8833
+ loop_container: "\u5FAA\u73AF\u8282\u70B9",
8834
+ work_notification: "\u5DE5\u4F5C\u901A\u77E5",
8835
+ dingtalk_card: "\u9489\u9489\u5361\u7247",
8836
+ system: "\u7CFB\u7EDF\u52A8\u4F5C"
8837
+ };
8305
8838
  var toneClasses2 = {
8306
- brand: "bg-blue-50 text-blue-600",
8307
- success: "bg-green-50 text-green-600",
8308
- danger: "bg-red-50 text-red-600",
8309
- neutral: "bg-gray-100 text-gray-500",
8310
- warning: "bg-amber-50 text-amber-600"
8839
+ brand: "bg-blue-600 text-white border-blue-600",
8840
+ success: "bg-emerald-50 text-emerald-700 border-emerald-200",
8841
+ danger: "bg-red-50 text-red-700 border-red-200",
8842
+ neutral: "bg-gray-50 text-gray-600 border-gray-200",
8843
+ warning: "bg-amber-50 text-amber-700 border-amber-200",
8844
+ return: "bg-amber-50 text-amber-700 border-amber-200",
8845
+ future: "bg-gray-50 text-gray-400 border-gray-200"
8311
8846
  };
8312
- function getNodePhase(task) {
8313
- if (task.status === "approved" || task.status === "rejected" || task.status === "returned" || task.status === "copied") {
8847
+ function groupTasks(tasks) {
8848
+ const groups = /* @__PURE__ */ new Map();
8849
+ tasks.forEach((task, index) => {
8850
+ const key = task.nodeVisitId || `${task.nodeId || "node"}-${task.id || task.taskId || index}`;
8851
+ const group = groups.get(key) || [];
8852
+ group.push(task);
8853
+ groups.set(key, group);
8854
+ });
8855
+ return Array.from(groups.values()).map((group) => {
8856
+ const hasOrSignResult = group.some(
8857
+ (task) => task.nodeType === "approval" && task.multiApproveMode === "or" && !task.isSimulated && ["approved", "rejected", "returned"].includes(task.status)
8858
+ );
8859
+ if (!hasOrSignResult) return group;
8860
+ const outcome = group.filter(
8861
+ (task) => !task.isSimulated && ["approved", "rejected", "returned"].includes(task.status)
8862
+ );
8863
+ return outcome.length > 0 ? outcome : group;
8864
+ });
8865
+ }
8866
+ function isCompactNode(task) {
8867
+ return task.nodeType === "start" || task.nodeType === "copy" || task.nodeType === "end" || systemNodeTypes.has(task.nodeType);
8868
+ }
8869
+ function getNodeTitle(task) {
8870
+ if (task.nodeType === "start") return task.title || task.nodeName || "\u6D41\u7A0B\u63D0\u4EA4";
8871
+ if (task.nodeType === "originator_return") return task.title || task.nodeName || "\u53D1\u8D77\u4EBA\u4FEE\u6539";
8872
+ if (task.nodeType === "copy") return task.title || task.nodeName || "\u6284\u9001\u901A\u77E5";
8873
+ if (task.nodeType === "callback_wait") return task.title || task.nodeName || "\u7B49\u5F85\u7B2C\u4E09\u65B9\u56DE\u8C03";
8874
+ if (task.nodeType === "end") return task.title || task.nodeName || "\u6D41\u7A0B\u5B8C\u6210";
8875
+ if (systemNodeTypes.has(task.nodeType))
8876
+ return task.title || task.nodeName || systemLabels[task.nodeType] || "\u7CFB\u7EDF\u52A8\u4F5C";
8877
+ return task.title || task.nodeName || "\u5BA1\u6279";
8878
+ }
8879
+ function getVisualState(task, isFutureGroup) {
8880
+ if (isFutureGroup || task.isSimulated || task.status === "simulated") return "future";
8881
+ if (task.status === "rejected") return "rejected";
8882
+ if (task.status === "returned") return "returned";
8883
+ if (task.status === "pending" || task.status === "waiting" || task.canApprove)
8884
+ return task.canApprove ? "current" : "waiting";
8885
+ if (task.status === "approved" || task.status === "copied" || task.nodeType === "start" || task.nodeType === "end") {
8314
8886
  return "completed";
8315
8887
  }
8316
- if (task.status === "pending" || task.status === "waiting") {
8317
- return "active";
8888
+ return "neutral";
8889
+ }
8890
+ function getStatusMeta(task, state, compact) {
8891
+ if (state === "future") return { label: "\u672A\u5F00\u59CB", tone: "neutral" };
8892
+ if (state === "current")
8893
+ return { label: task.nodeType === "callback_wait" ? "\u7B49\u5F85\u56DE\u8C03" : "\u5BA1\u6279\u4E2D", tone: "brand" };
8894
+ if (state === "waiting") return { label: "\u7B49\u5F85\u5904\u7406\u4E2D", tone: "neutral" };
8895
+ if (state === "rejected") return TASK_STATUS_META.rejected;
8896
+ if (state === "returned") return TASK_STATUS_META.returned;
8897
+ if (task.nodeType === "copy" || task.status === "copied") return TASK_STATUS_META.copied;
8898
+ if (compact) return { label: "\u5DF2\u5B8C\u6210", tone: "neutral" };
8899
+ return TASK_STATUS_META[task.status] || TASK_STATUS_META.approved;
8900
+ }
8901
+ function getIcon(task, state) {
8902
+ if (state === "current")
8903
+ return task.nodeType === "callback_wait" ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ClockCircleOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.LoadingOutlined, {});
8904
+ if (state === "future" || state === "waiting")
8905
+ return task.nodeType === "approval" ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.UserOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ClockCircleOutlined, {});
8906
+ if (state === "rejected") return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CloseCircleFilled, {});
8907
+ if (state === "returned") return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.RollbackOutlined, {});
8908
+ switch (task.nodeType) {
8909
+ case "start":
8910
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.FileTextOutlined, {});
8911
+ case "approval":
8912
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CheckCircleFilled, {});
8913
+ case "originator_return":
8914
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.EditOutlined, {});
8915
+ case "copy":
8916
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CopyOutlined, {});
8917
+ case "callback_wait":
8918
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ClockCircleOutlined, {});
8919
+ case "js_code":
8920
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CodeOutlined, {});
8921
+ case "connector_call":
8922
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ApiOutlined, {});
8923
+ case "work_notification":
8924
+ case "dingtalk_card":
8925
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.NotificationOutlined, {});
8926
+ case "data_retrieve_single":
8927
+ case "data_retrieve_batch":
8928
+ case "data_create":
8929
+ case "data_update":
8930
+ case "loop_container":
8931
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ReloadOutlined, {});
8932
+ default:
8933
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CheckCircleFilled, {});
8318
8934
  }
8319
- return "pending";
8935
+ }
8936
+ function getDotClass(state) {
8937
+ const map = {
8938
+ completed: "border-emerald-500 text-emerald-600 bg-white",
8939
+ current: "border-blue-600 bg-blue-600 text-white",
8940
+ waiting: "border-gray-200 text-gray-300 bg-white",
8941
+ future: "border-dashed border-gray-300 text-gray-300 bg-white",
8942
+ rejected: "border-red-500 text-red-600 bg-white",
8943
+ returned: "border-amber-500 text-amber-600 bg-white",
8944
+ neutral: "border-gray-200 text-gray-400 bg-white"
8945
+ };
8946
+ return map[state];
8320
8947
  }
8321
8948
  var ApprovalTimeline = ({
8322
8949
  tasks,
8323
8950
  className = "",
8324
8951
  renderNode,
8325
8952
  showRemarks = true,
8326
- compactMode = false
8953
+ compactMode = false,
8954
+ showApproverInfo = true
8327
8955
  }) => {
8328
- const taskList = Array.isArray(tasks) ? tasks : [];
8956
+ const taskList = (0, import_react56.useMemo)(() => Array.isArray(tasks) ? tasks : [], [tasks]);
8957
+ const groups = (0, import_react56.useMemo)(() => groupTasks(taskList), [taskList]);
8329
8958
  if (taskList.length === 0) {
8330
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 p-6 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("p", { className: "text-sm text-gray-400 text-center", children: "\u6682\u65E0\u5BA1\u6279\u8BB0\u5F55" }) });
8959
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8960
+ "div",
8961
+ {
8962
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container p-6 ${className}`,
8963
+ children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("p", { className: "m-0 text-center text-sm text-ant-text-tertiary", children: "\u6682\u65E0\u5BA1\u6279\u8BB0\u5F55" })
8964
+ }
8965
+ );
8331
8966
  }
8332
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: `${className}`, children: taskList.map((task, index) => {
8333
- const taskKey = task.taskId || task.id || `${task.nodeId}-${index}`;
8334
- if (renderNode) {
8335
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { children: renderNode(task, index) }, taskKey);
8336
- }
8337
- const phase = getNodePhase(task);
8338
- const isLast = index === taskList.length - 1;
8339
- const statusMeta = TASK_STATUS_META[task.status];
8340
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex gap-4", children: [
8341
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex flex-col items-center", children: [
8342
- phase === "completed" && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "w-3 h-3 rounded-full bg-green-500 flex-shrink-0" }),
8343
- phase === "active" && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "w-3 h-3 rounded-full bg-blue-500 ring-4 ring-blue-100 flex-shrink-0" }),
8344
- phase === "pending" && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "w-3 h-3 rounded-full bg-gray-300 flex-shrink-0" }),
8345
- !isLast && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8346
- "div",
8347
- {
8348
- 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"}`
8349
- }
8350
- )
8351
- ] }),
8352
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: `flex-1 pb-6 ${isLast ? "pb-0" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8967
+ if (renderNode) {
8968
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className, children: taskList.map((task, index) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { children: renderNode(task, index) }, task.taskId || task.id || index)) });
8969
+ }
8970
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: `approval-timeline ${className}`, children: groups.map((group, index) => {
8971
+ const node = group[0];
8972
+ const isLast = index === groups.length - 1;
8973
+ const isFutureGroup = group.some((task) => task.isSimulated || task.status === "simulated");
8974
+ const compact = compactMode || isCompactNode(node);
8975
+ const state = getVisualState(node, isFutureGroup);
8976
+ const statusMeta = getStatusMeta(node, state, compact);
8977
+ const title = getNodeTitle(node);
8978
+ const time = node.actionAt || node.createdAt;
8979
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
8980
+ "div",
8981
+ {
8982
+ className: `relative flex gap-4 pb-5 ${isLast ? "pb-0" : ""}`,
8983
+ children: [
8984
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8985
+ "div",
8986
+ {
8987
+ className: `absolute bottom-0 left-[21px] top-11 w-px ${state === "future" ? "border-l border-dashed border-gray-300" : "bg-ant-border-secondary"}`
8988
+ }
8989
+ ),
8990
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8991
+ "div",
8992
+ {
8993
+ className: `relative z-10 flex h-11 w-11 shrink-0 items-center justify-center rounded-full border-2 shadow-[0_0_0_4px_var(--ant-color-bg-layout,#f5f5f5)] ${getDotClass(state)}`,
8994
+ children: getIcon(node, state)
8995
+ }
8996
+ ),
8997
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
8998
+ "div",
8999
+ {
9000
+ className: `rounded-lg border p-4 ${state === "current" ? "border-blue-300 bg-blue-50/60" : state === "future" ? "border-dashed border-gray-200 bg-gray-50/70" : "border-ant-border-secondary bg-ant-bg-container"}`,
9001
+ children: [
9002
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
9003
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
9004
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "font-medium text-ant-text", children: title }),
9005
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9006
+ "span",
9007
+ {
9008
+ className: `inline-flex min-h-6 items-center rounded-md border px-2 text-xs font-medium ${state === "future" ? toneClasses2.future : toneClasses2[statusMeta.tone]}`,
9009
+ children: statusMeta.label
9010
+ }
9011
+ ),
9012
+ node.nodeType === "originator_return" && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "rounded-md bg-amber-50 px-2 py-1 text-xs text-amber-700", children: "\u53D1\u8D77\u4EBA\u64CD\u4F5C" })
9013
+ ] }),
9014
+ !isFutureGroup && time && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "text-xs text-ant-text-tertiary", children: time })
9015
+ ] }),
9016
+ showApproverInfo && !compact && group.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3", children: [
9017
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "w-full text-xs font-medium text-ant-text-tertiary", children: state === "current" || state === "waiting" ? "\u5F53\u524D\u5BA1\u6279\u4EBA" : "\u5904\u7406\u4EBA" }),
9018
+ group.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9019
+ "span",
9020
+ {
9021
+ className: "inline-flex min-w-0 items-center gap-2",
9022
+ children: [
9023
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-blue-50 text-xs font-semibold text-blue-700", children: assignee.assigneeName?.slice(0, 1) || "?" }),
9024
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "min-w-0", children: [
9025
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "block text-sm font-medium text-ant-text", children: assignee.assigneeName || "\u7CFB\u7EDF" }),
9026
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "block text-xs text-ant-text-tertiary", children: assignee.departmentName || assignee.actionAt || assignee.createdAt || "" })
9027
+ ] })
9028
+ ]
9029
+ },
9030
+ assignee.taskId || assignee.id
9031
+ ))
9032
+ ] }),
9033
+ showApproverInfo && compact && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "mt-2 text-sm text-ant-text-secondary", children: group.map((item) => item.assigneeName).filter(Boolean).join("\u3001") || (node.nodeType === "start" ? "\u63D0\u4EA4\u7533\u8BF7" : systemNodeTypes.has(node.nodeType) ? node.comments || "\u7CFB\u7EDF\u81EA\u52A8\u5904\u7406" : "") }),
9034
+ showRemarks && node.comments && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9035
+ "div",
9036
+ {
9037
+ className: `mt-3 border-l-2 pl-3 text-sm leading-6 ${state === "rejected" ? "border-red-300 text-red-700" : state === "returned" ? "border-amber-300 text-amber-700" : "border-ant-border-secondary text-ant-text-secondary"}`,
9038
+ children: node.comments
9039
+ }
9040
+ )
9041
+ ]
9042
+ }
9043
+ ) })
9044
+ ]
9045
+ },
9046
+ node.nodeVisitId || `${node.nodeId}-${node.taskId}-${index}`
9047
+ );
9048
+ }) });
9049
+ };
9050
+
9051
+ // src/modules/ApprovalActionBar.tsx
9052
+ var import_react58 = require("react");
9053
+ var import_antd25 = require("antd");
9054
+ var import_icons6 = require("@ant-design/icons");
9055
+
9056
+ // src/modules/StickyActionBar.tsx
9057
+ var import_react57 = require("react");
9058
+ var import_antd24 = require("antd");
9059
+ var import_icons5 = require("@ant-design/icons");
9060
+ var import_jsx_runtime81 = require("react/jsx-runtime");
9061
+ var getActionPriority = (action) => {
9062
+ const maybePriority = action.priority;
9063
+ if (typeof maybePriority === "number") return maybePriority;
9064
+ if (action.type === "primary") return 10;
9065
+ if (action.type === "danger") return 90;
9066
+ return 50;
9067
+ };
9068
+ var getPlacement = (action) => action.placement;
9069
+ var StickyActionBar = ({
9070
+ actions,
9071
+ className = "",
9072
+ maxMobileButtons = 2,
9073
+ layoutMode = "default",
9074
+ inDrawer = false,
9075
+ maxWidth = 1120
9076
+ }) => {
9077
+ const [isMobile, setIsMobile] = (0, import_react57.useState)(false);
9078
+ (0, import_react57.useEffect)(() => {
9079
+ const update = () => setIsMobile(typeof window !== "undefined" && window.innerWidth <= 768);
9080
+ update();
9081
+ window.addEventListener("resize", update);
9082
+ return () => window.removeEventListener("resize", update);
9083
+ }, []);
9084
+ const visibleActions = (0, import_react57.useMemo)(
9085
+ () => actions.filter((action) => action.visible !== false).sort((left, right) => getActionPriority(left) - getActionPriority(right)),
9086
+ [actions]
9087
+ );
9088
+ if (visibleActions.length === 0) return null;
9089
+ const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
9090
+ const primaryMobile = visibleActions.slice(0, maxMobileButtons);
9091
+ const moreMobile = visibleActions.slice(maxMobileButtons);
9092
+ const leftActions = visibleActions.filter((action) => getPlacement(action) === "left");
9093
+ const rightActions = visibleActions.filter((action) => getPlacement(action) !== "left");
9094
+ const renderButton = (action, mobile = false) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9095
+ import_antd24.Button,
9096
+ {
9097
+ type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
9098
+ danger: action.type === "danger",
9099
+ loading: action.loading,
9100
+ disabled: action.disabled,
9101
+ icon: action.icon,
9102
+ onClick: () => {
9103
+ if (action.confirm) {
9104
+ import_antd24.Modal.confirm({
9105
+ title: action.confirm.title,
9106
+ content: action.confirm.content,
9107
+ okText: action.confirm.okText || "\u786E\u8BA4",
9108
+ cancelText: action.confirm.cancelText || "\u53D6\u6D88",
9109
+ onOk: action.onClick
9110
+ });
9111
+ return;
9112
+ }
9113
+ action.onClick();
9114
+ },
9115
+ className: `${mobile ? "min-w-0 flex-1" : "min-w-[88px]"} rounded-md`,
9116
+ children: action.label
9117
+ },
9118
+ action.key
9119
+ );
9120
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9121
+ "div",
9122
+ {
9123
+ className: `fixed bottom-0 left-0 right-0 z-50 border-t border-ant-border-secondary bg-ant-bg-container/95 px-4 py-3 shadow-[0_-8px_24px_rgba(15,23,42,0.06)] backdrop-blur supports-[padding:max(0px)]:pb-[max(0.75rem,env(safe-area-inset-bottom))] ${inDrawer ? "absolute" : ""} ${className}`,
9124
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
8353
9125
  "div",
8354
9126
  {
8355
- 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"}`,
8356
- children: [
8357
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "flex items-center justify-between", children: [
8358
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "text-sm font-medium text-gray-900", children: task.nodeName }),
8359
- statusMeta && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8360
- "span",
9127
+ className: `mx-auto flex w-full items-center gap-3 ${layoutMode === "approval" && !isMobile ? "justify-between" : "justify-end"}`,
9128
+ style: { maxWidth: maxWidthStyle },
9129
+ children: isMobile ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
9130
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-1 gap-2", children: primaryMobile.map((action) => renderButton(action, true)) }),
9131
+ moreMobile.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9132
+ import_antd24.Dropdown,
9133
+ {
9134
+ trigger: ["click"],
9135
+ placement: "topRight",
9136
+ menu: {
9137
+ items: moreMobile.map((action) => ({
9138
+ key: action.key,
9139
+ label: action.label,
9140
+ danger: action.type === "danger",
9141
+ disabled: action.disabled,
9142
+ icon: action.icon,
9143
+ onClick: () => {
9144
+ if (action.confirm) {
9145
+ import_antd24.Modal.confirm({
9146
+ title: action.confirm.title,
9147
+ content: action.confirm.content,
9148
+ okText: action.confirm.okText || "\u786E\u8BA4",
9149
+ cancelText: action.confirm.cancelText || "\u53D6\u6D88",
9150
+ onOk: action.onClick
9151
+ });
9152
+ return;
9153
+ }
9154
+ action.onClick();
9155
+ }
9156
+ }))
9157
+ },
9158
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_antd24.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(import_icons5.MoreOutlined, {}), className: "rounded-md", children: "\u66F4\u591A" })
9159
+ }
9160
+ )
9161
+ ] }) : layoutMode === "approval" && leftActions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
9162
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-wrap items-center gap-3", children: leftActions.map((action) => renderButton(action)) }),
9163
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: rightActions.map((action) => renderButton(action)) })
9164
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: visibleActions.map((action) => renderButton(action)) })
9165
+ }
9166
+ )
9167
+ }
9168
+ );
9169
+ };
9170
+
9171
+ // src/modules/ApprovalActionBar.tsx
9172
+ var import_jsx_runtime82 = require("react/jsx-runtime");
9173
+ var actionPriority = {
9174
+ agree: 10,
9175
+ approved: 10,
9176
+ return: 20,
9177
+ transfer: 30,
9178
+ resubmit: 40,
9179
+ save: 80,
9180
+ withdraw: 90,
9181
+ rejected: 100,
9182
+ reject: 100
9183
+ };
9184
+ function getActionLabel(action) {
9185
+ return action.name?.zh_CN || action.text?.zh_CN || action.action;
9186
+ }
9187
+ function normalizeAction(action) {
9188
+ if (action === "approved") return "agree";
9189
+ if (action === "reject") return "rejected";
9190
+ if (action === "agree" || action === "rejected" || action === "withdraw" || action === "transfer" || action === "return" || action === "resubmit") {
9191
+ return action;
9192
+ }
9193
+ if (action === "save" || action === "callback") return action;
9194
+ return "agree";
9195
+ }
9196
+ function getModalTitle(action) {
9197
+ switch (action) {
9198
+ case "agree":
9199
+ return "\u5BA1\u6279\u610F\u89C1";
9200
+ case "rejected":
9201
+ return "\u62D2\u7EDD\u7406\u7531";
9202
+ case "withdraw":
9203
+ return "\u64A4\u9500\u6D41\u7A0B";
9204
+ case "transfer":
9205
+ return "\u8F6C\u4EA4\u4EFB\u52A1";
9206
+ case "return":
9207
+ return "\u9000\u56DE\u4EFB\u52A1";
9208
+ case "resubmit":
9209
+ return "\u91CD\u65B0\u63D0\u4EA4";
9210
+ default:
9211
+ return "\u786E\u8BA4\u64CD\u4F5C";
9212
+ }
9213
+ }
9214
+ var ApprovalActionBar = ({
9215
+ actions,
9216
+ onApprove,
9217
+ onReject,
9218
+ onTransfer,
9219
+ onReturn,
9220
+ onWithdraw,
9221
+ onSave,
9222
+ onResubmit,
9223
+ onCallback,
9224
+ returnableNodes = [],
9225
+ onLoadReturnableNodes,
9226
+ renderTransferSelector,
9227
+ renderReturnNodeLabel,
9228
+ renderActionModalExtra,
9229
+ maxMobileButtons = 2,
9230
+ className = "",
9231
+ inDrawer = false
9232
+ }) => {
9233
+ const [form] = import_antd25.Form.useForm();
9234
+ const [modalAction, setModalAction] = (0, import_react58.useState)(null);
9235
+ const [activeAction, setActiveAction] = (0, import_react58.useState)(null);
9236
+ const [loading, setLoading] = (0, import_react58.useState)(false);
9237
+ const visibleActions = (0, import_react58.useMemo)(
9238
+ () => actions.filter((action) => !action.hidden).sort((a, b) => (actionPriority[a.action] ?? 50) - (actionPriority[b.action] ?? 50)),
9239
+ [actions]
9240
+ );
9241
+ const openModal = async (action, target) => {
9242
+ setActiveAction(action);
9243
+ const defaultComments = action.remark?.content?.zh_CN;
9244
+ form.setFieldsValue({
9245
+ comments: defaultComments || "",
9246
+ reason: "",
9247
+ userId: void 0,
9248
+ nodeId: void 0
9249
+ });
9250
+ if (target === "return") await onLoadReturnableNodes?.();
9251
+ setModalAction(target);
9252
+ };
9253
+ const executeDirect = async (action) => {
9254
+ const normalized = normalizeAction(action.action);
9255
+ if (normalized === "save") {
9256
+ await onSave?.();
9257
+ return;
9258
+ }
9259
+ if (normalized === "callback") {
9260
+ await onCallback?.();
9261
+ return;
9262
+ }
9263
+ if (normalized === "agree") {
9264
+ await onApprove?.();
9265
+ }
9266
+ };
9267
+ const handleActionClick = async (action) => {
9268
+ const normalized = normalizeAction(action.action);
9269
+ if (normalized === "save" || normalized === "callback") {
9270
+ await executeDirect(action);
9271
+ return;
9272
+ }
9273
+ await openModal(action, normalized);
9274
+ };
9275
+ const handleOk = async () => {
9276
+ if (!modalAction) return;
9277
+ const values = await form.validateFields();
9278
+ setLoading(true);
9279
+ try {
9280
+ if (modalAction === "agree") await onApprove?.(values.comments || void 0);
9281
+ if (modalAction === "rejected") await onReject?.(values.comments || void 0);
9282
+ if (modalAction === "withdraw")
9283
+ await onWithdraw?.(values.reason || values.comments || void 0);
9284
+ if (modalAction === "transfer") await onTransfer?.(values.userId, values.reason || void 0);
9285
+ if (modalAction === "return") await onReturn?.(values.nodeId, values.reason || void 0);
9286
+ if (modalAction === "resubmit") await onResubmit?.(values.comments || void 0);
9287
+ setModalAction(null);
9288
+ setActiveAction(null);
9289
+ form.resetFields();
9290
+ } finally {
9291
+ setLoading(false);
9292
+ }
9293
+ };
9294
+ const actionConfigs = visibleActions.map((action) => {
9295
+ const normalized = normalizeAction(action.action);
9296
+ const danger = normalized === "rejected" || normalized === "withdraw";
9297
+ return {
9298
+ key: action.action,
9299
+ label: getActionLabel(action),
9300
+ type: normalized === "agree" ? "primary" : danger ? "danger" : "default",
9301
+ icon: normalized === "agree" ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons6.CheckOutlined, {}) : normalized === "rejected" ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons6.CloseOutlined, {}) : normalized === "transfer" ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons6.SwapOutlined, {}) : normalized === "return" || normalized === "withdraw" ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons6.RollbackOutlined, {}) : normalized === "save" ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons6.SaveOutlined, {}) : void 0,
9302
+ onClick: () => handleActionClick(action),
9303
+ placement: danger || normalized === "save" ? "right" : "left",
9304
+ priority: actionPriority[action.action] ?? 50
9305
+ };
9306
+ });
9307
+ const requiredComment = activeAction?.remark?.required || modalAction === "rejected" || modalAction === "withdraw";
9308
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
9309
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9310
+ StickyActionBar,
9311
+ {
9312
+ actions: actionConfigs,
9313
+ layoutMode: "approval",
9314
+ maxMobileButtons,
9315
+ className,
9316
+ inDrawer
9317
+ }
9318
+ ),
9319
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9320
+ import_antd25.Modal,
9321
+ {
9322
+ title: getModalTitle(modalAction),
9323
+ open: modalAction !== null,
9324
+ okText: "\u786E\u8BA4",
9325
+ cancelText: "\u53D6\u6D88",
9326
+ confirmLoading: loading,
9327
+ onOk: handleOk,
9328
+ onCancel: () => {
9329
+ setModalAction(null);
9330
+ setActiveAction(null);
9331
+ form.resetFields();
9332
+ },
9333
+ destroyOnClose: true,
9334
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_antd25.Form, { form, layout: "vertical", children: [
9335
+ modalAction === "transfer" && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9336
+ import_antd25.Form.Item,
9337
+ {
9338
+ name: "userId",
9339
+ label: "\u8F6C\u4EA4\u7ED9",
9340
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u8F6C\u4EA4\u7528\u6237" }],
9341
+ children: renderTransferSelector ? renderTransferSelector({
9342
+ value: form.getFieldValue("userId"),
9343
+ onChange: (userId) => form.setFieldsValue({ userId })
9344
+ }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd25.Input, { placeholder: "\u8BF7\u8F93\u5165\u7528\u6237 ID" })
9345
+ }
9346
+ ),
9347
+ modalAction === "return" && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9348
+ import_antd25.Form.Item,
9349
+ {
9350
+ name: "nodeId",
9351
+ label: "\u9000\u56DE\u5230\u8282\u70B9",
9352
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9" }],
9353
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9354
+ import_antd25.Select,
8361
9355
  {
8362
- className: `px-2 py-0.5 rounded-full text-xs font-medium ${toneClasses2[statusMeta.tone] || toneClasses2.neutral}`,
8363
- children: statusMeta.label
9356
+ placeholder: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9",
9357
+ options: returnableNodes.map((node) => ({
9358
+ value: node.nodeId || node.id || "",
9359
+ label: renderReturnNodeLabel ? renderReturnNodeLabel(node) : node.nodeName || node.name || node.nodeId || node.id
9360
+ }))
8364
9361
  }
8365
9362
  )
8366
- ] }),
8367
- task.assigneeName && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "mt-2 flex items-center gap-1.5 text-sm text-gray-600", children: [
8368
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "text-gray-400", children: "\u{1F464}" }),
8369
- /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { children: [
8370
- phase === "active" ? "\u5F53\u524D\u5BA1\u6279\u4EBA: " : "",
8371
- task.assigneeName
8372
- ] }),
8373
- task.departmentName && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(import_jsx_runtime79.Fragment, { children: [
8374
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "text-gray-300", children: "\xB7" }),
8375
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "text-gray-400", children: task.departmentName })
8376
- ] })
8377
- ] }),
8378
- !compactMode && showRemarks && task.comments && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "mt-2 bg-gray-50 rounded-md p-3 text-sm text-gray-600 italic", children: [
8379
- "\u{1F4AC} \u201C",
8380
- task.comments,
8381
- "\u201D"
8382
- ] }),
8383
- !compactMode && phase === "active" && !task.comments && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "mt-2 text-xs text-gray-400", children: "\u23F3 \u7B49\u5F85\u5904\u7406\u4E2D..." }),
8384
- !compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "mt-2 text-xs text-gray-400", children: [
8385
- "\u{1F550} ",
8386
- task.actionAt || task.createdAt
8387
- ] }),
8388
- compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "mt-1 text-xs text-gray-400", children: task.actionAt || task.createdAt })
8389
- ]
8390
- }
8391
- ) })
8392
- ] }, taskKey);
8393
- }) });
9363
+ }
9364
+ ),
9365
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9366
+ import_antd25.Form.Item,
9367
+ {
9368
+ name: modalAction === "withdraw" || modalAction === "transfer" || modalAction === "return" ? "reason" : "comments",
9369
+ label: modalAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : modalAction === "transfer" ? "\u8F6C\u4EA4\u539F\u56E0" : modalAction === "return" ? "\u9000\u56DE\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1",
9370
+ rules: [{ required: requiredComment, message: "\u8BF7\u586B\u5199\u8BF4\u660E" }],
9371
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd25.Input.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u8BF4\u660E" })
9372
+ }
9373
+ ),
9374
+ activeAction && renderActionModalExtra?.(activeAction)
9375
+ ] })
9376
+ }
9377
+ )
9378
+ ] });
8394
9379
  };
8395
9380
 
8396
9381
  // src/modules/ApprovalActions.tsx
8397
- var import_react56 = require("react");
8398
- var import_antd24 = require("antd");
8399
- var import_icons4 = require("@ant-design/icons");
8400
- var import_jsx_runtime80 = require("react/jsx-runtime");
8401
- var { TextArea: TextArea3 } = import_antd24.Input;
9382
+ var import_react59 = require("react");
9383
+ var import_antd26 = require("antd");
9384
+ var import_icons7 = require("@ant-design/icons");
9385
+ var import_jsx_runtime83 = require("react/jsx-runtime");
9386
+ var priority = {
9387
+ agree: 10,
9388
+ approved: 10,
9389
+ transfer: 20,
9390
+ return: 30,
9391
+ save: 40,
9392
+ withdraw: 90,
9393
+ rejected: 100,
9394
+ reject: 100
9395
+ };
9396
+ var getLabel = (action) => action.name?.zh_CN || action.text?.zh_CN || action.action;
8402
9397
  var ApprovalActions = ({
8403
9398
  actions,
8404
9399
  onApprove,
@@ -8411,167 +9406,148 @@ var ApprovalActions = ({
8411
9406
  maxVisible = 3,
8412
9407
  className = ""
8413
9408
  }) => {
8414
- const [drawerAction, setDrawerAction] = (0, import_react56.useState)(null);
8415
- const [comments, setComments] = (0, import_react56.useState)("");
8416
- const [loading, setLoading] = (0, import_react56.useState)(false);
8417
- const [saveLoading, setSaveLoading] = (0, import_react56.useState)(false);
8418
- const handleOpenDrawer = (action) => {
8419
- setComments("");
8420
- setDrawerAction(action);
8421
- };
8422
- const handleConfirm = async () => {
8423
- setLoading(true);
8424
- try {
8425
- if (drawerAction === "approve" && onApprove) {
8426
- await onApprove(comments || void 0);
8427
- } else if (drawerAction === "reject" && onReject) {
8428
- await onReject(comments || void 0);
8429
- } else if (drawerAction === "withdraw" && onWithdraw) {
8430
- await onWithdraw(comments || void 0);
8431
- }
8432
- setDrawerAction(null);
8433
- } finally {
8434
- setLoading(false);
8435
- }
9409
+ const [form] = import_antd26.Form.useForm();
9410
+ const [modalAction, setModalAction] = (0, import_react59.useState)(null);
9411
+ const [activeAction, setActiveAction] = (0, import_react59.useState)(null);
9412
+ const [loading, setLoading] = (0, import_react59.useState)(false);
9413
+ const [saveLoading, setSaveLoading] = (0, import_react59.useState)(false);
9414
+ const renderableActions = (0, import_react59.useMemo)(
9415
+ () => actions.filter((action) => !action.hidden).sort((a, b) => (priority[a.action] ?? 50) - (priority[b.action] ?? 50)),
9416
+ [actions]
9417
+ );
9418
+ const openModal = (target, action) => {
9419
+ setActiveAction(action);
9420
+ form.setFieldsValue({ comments: action.remark?.content?.zh_CN || "" });
9421
+ setModalAction(target);
8436
9422
  };
8437
9423
  const handleSave = async () => {
8438
- if (!onSave) return;
8439
9424
  setSaveLoading(true);
8440
9425
  try {
8441
- await onSave();
9426
+ await onSave?.();
8442
9427
  } finally {
8443
9428
  setSaveLoading(false);
8444
9429
  }
8445
9430
  };
8446
- const actionMap = {};
8447
- actions.forEach((action) => {
8448
- switch (action.action) {
8449
- case "agree":
8450
- actionMap["agree"] = {
8451
- label: action.name.zh_CN || "\u540C\u610F",
8452
- handler: () => handleOpenDrawer("approve"),
8453
- type: "primary",
8454
- color: "green"
8455
- };
8456
- break;
8457
- case "rejected":
8458
- actionMap["rejected"] = {
8459
- label: action.name.zh_CN || "\u62D2\u7EDD",
8460
- handler: () => handleOpenDrawer("reject"),
8461
- type: "default"
8462
- };
8463
- break;
8464
- case "transfer":
8465
- actionMap["transfer"] = {
8466
- label: action.name.zh_CN || "\u8F6C\u4EA4",
8467
- handler: () => onTransfer?.(),
8468
- type: "default"
8469
- };
8470
- break;
8471
- case "return":
8472
- actionMap["return"] = {
8473
- label: action.name.zh_CN || "\u9000\u56DE",
8474
- handler: () => onReturn?.(),
8475
- type: "default"
8476
- };
8477
- break;
8478
- case "withdraw":
8479
- actionMap["withdraw"] = {
8480
- label: action.name.zh_CN || "\u64A4\u9500",
8481
- handler: () => handleOpenDrawer("withdraw"),
8482
- type: "default"
8483
- };
8484
- break;
8485
- case "save":
8486
- actionMap["save"] = {
8487
- label: action.name.zh_CN || "\u6682\u5B58",
8488
- handler: handleSave,
8489
- type: "default"
8490
- };
8491
- break;
9431
+ const handleAction = (action) => {
9432
+ if (action.action === "transfer") {
9433
+ onTransfer?.();
9434
+ return;
8492
9435
  }
8493
- });
8494
- const allButtons = Object.entries(actionMap);
8495
- const visibleButtons = allButtons.slice(0, maxVisible);
8496
- const moreButtons = allButtons.slice(maxVisible);
8497
- const drawerTitle = drawerAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : drawerAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : drawerAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1";
8498
- return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_jsx_runtime80.Fragment, { children: [
8499
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9436
+ if (action.action === "return") {
9437
+ onReturn?.();
9438
+ return;
9439
+ }
9440
+ if (action.action === "save") {
9441
+ void handleSave();
9442
+ return;
9443
+ }
9444
+ if (action.action === "withdraw") {
9445
+ openModal("withdraw", action);
9446
+ return;
9447
+ }
9448
+ if (action.action === "rejected" || action.action === "reject") {
9449
+ openModal("reject", action);
9450
+ return;
9451
+ }
9452
+ openModal("approve", action);
9453
+ };
9454
+ const handleConfirm = async () => {
9455
+ const values = await form.validateFields();
9456
+ setLoading(true);
9457
+ try {
9458
+ if (modalAction === "approve") await onApprove?.(values.comments || void 0);
9459
+ if (modalAction === "reject") await onReject?.(values.comments || void 0);
9460
+ if (modalAction === "withdraw") await onWithdraw?.(values.comments || void 0);
9461
+ setModalAction(null);
9462
+ setActiveAction(null);
9463
+ form.resetFields();
9464
+ } finally {
9465
+ setLoading(false);
9466
+ }
9467
+ };
9468
+ const visibleButtons = renderableActions.slice(0, maxVisible);
9469
+ const moreButtons = renderableActions.slice(maxVisible);
9470
+ const title = modalAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : modalAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : "\u64A4\u9500\u539F\u56E0";
9471
+ const button = (action) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9472
+ import_antd26.Button,
9473
+ {
9474
+ type: action.action === "agree" || action.action === "approved" ? "primary" : "default",
9475
+ danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9476
+ onClick: () => handleAction(action),
9477
+ loading: action.action === "save" && saveLoading,
9478
+ children: getLabel(action)
9479
+ },
9480
+ action.action
9481
+ );
9482
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
9483
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
8500
9484
  "div",
8501
9485
  {
8502
9486
  className: `${layout === "horizontal" ? "flex items-center gap-3" : "flex flex-col gap-2"} ${className}`,
8503
9487
  children: [
8504
- visibleButtons.map(([key, btn]) => /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8505
- import_antd24.Button,
8506
- {
8507
- type: btn.type === "primary" ? "primary" : "default",
8508
- className: btn.color === "green" ? "!bg-green-600 !border-green-600 hover:!bg-green-700" : "",
8509
- onClick: btn.handler,
8510
- loading: key === "save" && saveLoading,
8511
- children: btn.label
8512
- },
8513
- key
8514
- )),
8515
- moreButtons.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8516
- import_antd24.Dropdown,
9488
+ visibleButtons.map(button),
9489
+ moreButtons.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9490
+ import_antd26.Dropdown,
8517
9491
  {
9492
+ trigger: ["click"],
8518
9493
  menu: {
8519
- items: moreButtons.map(([key, btn]) => ({
8520
- key,
8521
- label: btn.label,
8522
- onClick: btn.handler
9494
+ items: moreButtons.map((action) => ({
9495
+ key: action.action,
9496
+ label: getLabel(action),
9497
+ danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9498
+ onClick: () => handleAction(action)
8523
9499
  }))
8524
9500
  },
8525
- trigger: ["click"],
8526
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_antd24.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.MoreOutlined, {}), children: "\u66F4\u591A" })
9501
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd26.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_icons7.MoreOutlined, {}), children: "\u66F4\u591A" })
8527
9502
  }
8528
9503
  )
8529
9504
  ]
8530
9505
  }
8531
9506
  ),
8532
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8533
- import_antd24.Drawer,
9507
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9508
+ import_antd26.Modal,
8534
9509
  {
8535
- title: drawerTitle,
8536
- open: drawerAction !== null,
8537
- onClose: () => setDrawerAction(null),
8538
- width: 400,
8539
- footer: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex justify-end gap-3", children: [
8540
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_antd24.Button, { onClick: () => setDrawerAction(null), children: "\u53D6\u6D88" }),
8541
- /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(import_antd24.Button, { type: "primary", onClick: handleConfirm, loading, children: [
8542
- loading && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.LoadingOutlined, {}),
8543
- "\u786E\u8BA4"
8544
- ] })
8545
- ] }),
8546
- children: /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { children: [
8547
- /* @__PURE__ */ (0, import_jsx_runtime80.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" }),
8548
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8549
- TextArea3,
8550
- {
8551
- rows: 4,
8552
- value: comments,
8553
- onChange: (e) => setComments(e.target.value),
8554
- 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...",
8555
- maxLength: 500,
8556
- showCount: true
8557
- }
8558
- )
8559
- ] }) })
9510
+ title,
9511
+ open: modalAction !== null,
9512
+ okText: "\u786E\u8BA4",
9513
+ cancelText: "\u53D6\u6D88",
9514
+ confirmLoading: loading,
9515
+ onOk: handleConfirm,
9516
+ onCancel: () => {
9517
+ setModalAction(null);
9518
+ setActiveAction(null);
9519
+ form.resetFields();
9520
+ },
9521
+ destroyOnClose: true,
9522
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd26.Form, { form, layout: "vertical", children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9523
+ import_antd26.Form.Item,
9524
+ {
9525
+ name: "comments",
9526
+ label: modalAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : "\u8BF7\u8F93\u5165\u7406\u7531",
9527
+ rules: [
9528
+ {
9529
+ required: Boolean(activeAction?.remark?.required) || modalAction !== "approve",
9530
+ message: "\u8BF7\u586B\u5199\u8BF4\u660E"
9531
+ }
9532
+ ],
9533
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd26.Input.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u8BF4\u660E" })
9534
+ }
9535
+ ) })
8560
9536
  }
8561
9537
  )
8562
9538
  ] });
8563
9539
  };
8564
9540
 
8565
9541
  // src/modules/FormActionBar.tsx
8566
- var import_react57 = require("react");
8567
- var import_antd25 = require("antd");
8568
- var import_jsx_runtime81 = require("react/jsx-runtime");
9542
+ var import_react60 = require("react");
9543
+ var import_antd27 = require("antd");
9544
+ var import_jsx_runtime84 = require("react/jsx-runtime");
8569
9545
  var FormActionBar = ({
8570
9546
  actions,
8571
9547
  position = "bottom-fixed",
8572
9548
  className = ""
8573
9549
  }) => {
8574
- const [loadingKeys, setLoadingKeys] = (0, import_react57.useState)(/* @__PURE__ */ new Set());
9550
+ const [loadingKeys, setLoadingKeys] = (0, import_react60.useState)(/* @__PURE__ */ new Set());
8575
9551
  const visibleActions = actions.filter((a) => a.visible !== false);
8576
9552
  const sortedActions = [...visibleActions].sort((a, b) => {
8577
9553
  if (a.type === "danger" && b.type !== "danger") return -1;
@@ -8582,7 +9558,7 @@ var FormActionBar = ({
8582
9558
  });
8583
9559
  const handleClick = async (action) => {
8584
9560
  if (action.confirm) {
8585
- import_antd25.Modal.confirm({
9561
+ import_antd27.Modal.confirm({
8586
9562
  title: action.confirm.title,
8587
9563
  content: action.confirm.content,
8588
9564
  okText: "\u786E\u8BA4",
@@ -8608,14 +9584,14 @@ var FormActionBar = ({
8608
9584
  }
8609
9585
  };
8610
9586
  const isFixed = position === "bottom-fixed";
8611
- const bar = /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9587
+ const bar = /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
8612
9588
  "div",
8613
9589
  {
8614
9590
  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}`,
8615
- children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex items-center justify-end gap-3 flex-wrap md:flex-nowrap", children: sortedActions.map((action) => {
9591
+ children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "flex items-center justify-end gap-3 flex-wrap md:flex-nowrap", children: sortedActions.map((action) => {
8616
9592
  const isLoading = action.loading || loadingKeys.has(action.key);
8617
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
8618
- import_antd25.Button,
9593
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
9594
+ import_antd27.Button,
8619
9595
  {
8620
9596
  type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
8621
9597
  danger: action.type === "danger",
@@ -8632,18 +9608,137 @@ var FormActionBar = ({
8632
9608
  }
8633
9609
  );
8634
9610
  if (isFixed) {
8635
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
9611
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(import_jsx_runtime84.Fragment, { children: [
8636
9612
  bar,
8637
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "h-16" })
9613
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "h-16" })
8638
9614
  ] });
8639
9615
  }
8640
9616
  return bar;
8641
9617
  };
8642
9618
 
9619
+ // src/modules/RuntimePageShell.tsx
9620
+ var import_antd28 = require("antd");
9621
+ var import_jsx_runtime85 = require("react/jsx-runtime");
9622
+ var RuntimePageShell = ({
9623
+ children,
9624
+ actions,
9625
+ loading = false,
9626
+ loadingTip = "\u6B63\u5728\u52A0\u8F7D\u9875\u9762...",
9627
+ accessDenied = false,
9628
+ error,
9629
+ empty,
9630
+ className = "",
9631
+ contentClassName = "",
9632
+ maxWidth = 1120,
9633
+ inDrawer = false
9634
+ }) => {
9635
+ const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
9636
+ const renderState = () => {
9637
+ if (loading) {
9638
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "min-h-[360px] flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd28.Spin, { tip: loadingTip }) });
9639
+ }
9640
+ if (accessDenied) {
9641
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd28.Empty, { description: "\u65E0\u6743\u9650\u67E5\u770B\u8BE6\u60C5" });
9642
+ }
9643
+ if (error) {
9644
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd28.Alert, { type: "error", showIcon: true, message: "\u9875\u9762\u52A0\u8F7D\u5931\u8D25", description: error });
9645
+ }
9646
+ if (empty) {
9647
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_jsx_runtime85.Fragment, { children: empty });
9648
+ }
9649
+ return children;
9650
+ };
9651
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: `sy-runtime-page min-h-screen bg-ant-bg-layout text-ant-text ${className}`, children: [
9652
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9653
+ "div",
9654
+ {
9655
+ className: `sy-runtime-page__content mx-auto w-full px-4 py-6 pb-24 md:px-6 ${inDrawer ? "py-4 md:px-4" : ""} ${contentClassName}`,
9656
+ style: { maxWidth: maxWidthStyle },
9657
+ children: renderState()
9658
+ }
9659
+ ),
9660
+ actions
9661
+ ] });
9662
+ };
9663
+
9664
+ // src/modules/SummaryPanel.tsx
9665
+ var import_antd29 = require("antd");
9666
+ var import_icons8 = require("@ant-design/icons");
9667
+ var import_jsx_runtime86 = require("react/jsx-runtime");
9668
+ var toneClasses3 = {
9669
+ brand: "bg-blue-50 text-blue-700 border-blue-200",
9670
+ success: "bg-emerald-50 text-emerald-700 border-emerald-200",
9671
+ danger: "bg-red-50 text-red-700 border-red-200",
9672
+ neutral: "bg-gray-50 text-gray-600 border-gray-200",
9673
+ warning: "bg-amber-50 text-amber-700 border-amber-200"
9674
+ };
9675
+ var SummaryPanel = ({
9676
+ title = "\u8BE6\u60C5",
9677
+ eyebrow,
9678
+ status,
9679
+ creator,
9680
+ createdAt,
9681
+ metaItems,
9682
+ className = "",
9683
+ children
9684
+ }) => {
9685
+ const defaultItems = [
9686
+ {
9687
+ key: "creator",
9688
+ label: "\u521B\u5EFA\u4EBA",
9689
+ value: creator?.name || "\u672A\u77E5\u7528\u6237",
9690
+ icon: creator?.avatar ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_antd29.Avatar, { size: 24, src: creator.avatar }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_antd29.Avatar, { size: 24, children: creator?.name?.slice(0, 1) || "\u8868" })
9691
+ },
9692
+ {
9693
+ key: "department",
9694
+ label: "\u6240\u5C5E\u90E8\u95E8",
9695
+ value: creator?.department || "-",
9696
+ icon: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_icons8.ApartmentOutlined, {})
9697
+ },
9698
+ {
9699
+ key: "createdAt",
9700
+ label: "\u521B\u5EFA\u65F6\u95F4",
9701
+ value: createdAt || "-",
9702
+ icon: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_icons8.CalendarOutlined, {})
9703
+ }
9704
+ ];
9705
+ const items = metaItems || defaultItems;
9706
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9707
+ "section",
9708
+ {
9709
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
9710
+ children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "p-5 md:p-6", children: [
9711
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
9712
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "min-w-0 text-sm text-ant-text-tertiary", children: eyebrow || /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
9713
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_icons8.FileTextOutlined, {}),
9714
+ "\u6570\u636E\u5B9E\u4F8B"
9715
+ ] }) }),
9716
+ status && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9717
+ "span",
9718
+ {
9719
+ className: `inline-flex min-h-6 items-center rounded-md border px-2.5 text-xs font-medium ${toneClasses3[status.tone] || toneClasses3.neutral}`,
9720
+ children: status.label
9721
+ }
9722
+ )
9723
+ ] }),
9724
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("h1", { className: "m-0 break-words text-2xl font-semibold leading-9 text-ant-text md:text-[28px]", children: title }),
9725
+ items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "mt-5 grid grid-cols-1 gap-4 md:grid-cols-3", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "flex min-w-0 items-center gap-3", children: [
9726
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-gray-100 text-ant-text-secondary", children: item.icon }),
9727
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "min-w-0", children: [
9728
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "block text-xs leading-5 text-ant-text-tertiary", children: item.label }),
9729
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "block break-words text-sm font-medium leading-6 text-ant-text", children: item.value || "-" })
9730
+ ] })
9731
+ ] }, item.key)) }),
9732
+ children && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "mt-5", children })
9733
+ ] })
9734
+ }
9735
+ );
9736
+ };
9737
+
8643
9738
  // src/modules/DraftManager.tsx
8644
- var import_antd26 = require("antd");
8645
- var import_icons5 = require("@ant-design/icons");
8646
- var import_jsx_runtime82 = require("react/jsx-runtime");
9739
+ var import_antd30 = require("antd");
9740
+ var import_icons9 = require("@ant-design/icons");
9741
+ var import_jsx_runtime87 = require("react/jsx-runtime");
8647
9742
  function formatRelativeTime(timestamp) {
8648
9743
  const now = Date.now();
8649
9744
  const diff = now - timestamp;
@@ -8664,25 +9759,25 @@ var DraftManager = ({
8664
9759
  }) => {
8665
9760
  if (!hasDraft) return null;
8666
9761
  const timeLabel = draftTimestamp ? formatRelativeTime(draftTimestamp) : null;
8667
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9762
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
8668
9763
  "div",
8669
9764
  {
8670
9765
  className: `bg-blue-50 border border-blue-200 rounded-lg p-4 animate-[slideDown_0.3s_ease-out] ${className}`,
8671
- children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
8672
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
8673
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_icons5.EditOutlined, { className: "text-blue-500" }),
8674
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { children: [
9766
+ children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
9767
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
9768
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_icons9.EditOutlined, { className: "text-blue-500" }),
9769
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { children: [
8675
9770
  "\u68C0\u6D4B\u5230\u672A\u63D0\u4EA4\u7684\u8349\u7A3F",
8676
- timeLabel && /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("span", { className: "text-blue-500 ml-1", children: [
9771
+ timeLabel && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "text-blue-500 ml-1", children: [
8677
9772
  "\uFF08\u4FDD\u5B58\u4E8E ",
8678
9773
  timeLabel,
8679
9774
  "\uFF09"
8680
9775
  ] })
8681
9776
  ] })
8682
9777
  ] }),
8683
- /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "flex items-center gap-2", children: [
8684
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd26.Button, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
8685
- /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd26.Button, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
9778
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center gap-2", children: [
9779
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_antd30.Button, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
9780
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_antd30.Button, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
8686
9781
  ] })
8687
9782
  ] })
8688
9783
  }
@@ -8690,9 +9785,9 @@ var DraftManager = ({
8690
9785
  };
8691
9786
 
8692
9787
  // src/modules/ProcessPreview.tsx
8693
- var import_antd27 = require("antd");
8694
- var import_icons6 = require("@ant-design/icons");
8695
- var import_jsx_runtime83 = require("react/jsx-runtime");
9788
+ var import_antd31 = require("antd");
9789
+ var import_icons10 = require("@ant-design/icons");
9790
+ var import_jsx_runtime88 = require("react/jsx-runtime");
8696
9791
  var ProcessPreview = ({
8697
9792
  open,
8698
9793
  onClose,
@@ -8700,49 +9795,1117 @@ var ProcessPreview = ({
8700
9795
  routes,
8701
9796
  loading = false
8702
9797
  }) => {
8703
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
8704
- import_antd27.Modal,
9798
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
9799
+ import_antd31.Modal,
8705
9800
  {
8706
9801
  title: "\u6D41\u7A0B\u9884\u89C8",
8707
9802
  open,
8708
9803
  onCancel: onClose,
8709
9804
  width: 520,
8710
- footer: /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex justify-end gap-3", children: [
8711
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd27.Button, { onClick: onClose, children: "\u53D6\u6D88" }),
8712
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd27.Button, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
9805
+ footer: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex justify-end gap-3", children: [
9806
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_antd31.Button, { onClick: onClose, children: "\u53D6\u6D88" }),
9807
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_antd31.Button, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
8713
9808
  ] }),
8714
- children: loading && routes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd27.Skeleton, { active: true, paragraph: { rows: 4 } }) : routes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("p", { className: "text-sm text-gray-400 text-center py-8", children: "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) : /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "py-2", children: routes.map((route, index) => {
9809
+ children: loading && routes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_antd31.Skeleton, { active: true, paragraph: { rows: 4 } }) : routes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("p", { className: "text-sm text-gray-400 text-center py-8", children: "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) : /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "py-2", children: routes.map((route, index) => {
8715
9810
  const isLast = index === routes.length - 1;
8716
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex gap-3", children: [
8717
- /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "flex flex-col items-center", children: [
8718
- /* @__PURE__ */ (0, import_jsx_runtime83.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_runtime83.jsx)(import_icons6.CheckCircleOutlined, { className: "text-blue-500 text-xs" }) }),
8719
- !isLast && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
9811
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex gap-3", children: [
9812
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex flex-col items-center", children: [
9813
+ /* @__PURE__ */ (0, import_jsx_runtime88.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_runtime88.jsx)(import_icons10.CheckCircleOutlined, { className: "text-blue-500 text-xs" }) }),
9814
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
9815
+ ] }),
9816
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
9817
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
9818
+ route.assignees && route.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "mt-1 flex items-center gap-1.5 flex-wrap", children: [
9819
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_icons10.UserOutlined, { className: "text-gray-400 text-xs" }),
9820
+ route.assignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
9821
+ "span",
9822
+ {
9823
+ className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
9824
+ children: assignee.name
9825
+ },
9826
+ assignee.id
9827
+ ))
9828
+ ] })
9829
+ ] })
9830
+ ] }, route.nodeId);
9831
+ }) })
9832
+ }
9833
+ );
9834
+ };
9835
+
9836
+ // src/modules/DataManagementList.tsx
9837
+ var import_react61 = require("react");
9838
+ var import_antd32 = require("antd");
9839
+ var import_icons11 = require("@ant-design/icons");
9840
+ var import_jsx_runtime89 = require("react/jsx-runtime");
9841
+ var createGroup = () => ({
9842
+ id: `group_${Date.now()}_${Math.random().toString(36).slice(2)}`,
9843
+ logic: "AND",
9844
+ rules: [],
9845
+ conditions: []
9846
+ });
9847
+ var createRule = (field) => ({
9848
+ id: `rule_${Date.now()}_${Math.random().toString(36).slice(2)}`,
9849
+ key: field?.fieldId || "",
9850
+ operator: "contains",
9851
+ value: "",
9852
+ componentName: field?.componentName
9853
+ });
9854
+ var getRecordId = (record) => record?.formInstanceId || record?.formInstId || record?.form_instance_id || record?.instanceId || record?.id || record?.processInstanceId;
9855
+ var getSelectedRecordId = (record, fallback) => record?.formInstId || record?.formInstanceId || record?.form_instance_id || record?.id || fallback;
9856
+ var hydrateFilterGroup = (group) => {
9857
+ if (!group) return createGroup();
9858
+ return {
9859
+ id: group.id || createGroup().id,
9860
+ logic: group.logic === "OR" ? "OR" : "AND",
9861
+ rules: Array.isArray(group.rules) ? group.rules.map((rule) => ({
9862
+ ...rule,
9863
+ id: rule.id || `rule_${Date.now()}_${Math.random().toString(36).slice(2)}`
9864
+ })) : [],
9865
+ conditions: Array.isArray(group.conditions) ? group.conditions.map(hydrateFilterGroup) : []
9866
+ };
9867
+ };
9868
+ var formatPrimitive = (value) => {
9869
+ if (value === void 0 || value === null || value === "")
9870
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "text-ant-color-text-quaternary", children: "--" });
9871
+ return String(value);
9872
+ };
9873
+ var pickOptionLabel = (field, value) => {
9874
+ const options = field.options || field.optionList || field.option_list || field.componentProps?.options || [];
9875
+ const scalar = typeof value === "object" ? value?.value ?? value?.id ?? value?.label ?? value?.name : value;
9876
+ const match = Array.isArray(options) ? options.find((option) => String(option.value ?? option.id) === String(scalar)) : void 0;
9877
+ return match?.label || match?.name || value?.label || value?.name || scalar;
9878
+ };
9879
+ var renderStatusTag = (value, fieldId) => {
9880
+ const raw = String(value || "");
9881
+ const statusMap = {
9882
+ pending: { label: "\u5F85\u5904\u7406", color: "processing" },
9883
+ running: { label: "\u5BA1\u6279\u4E2D", color: "processing" },
9884
+ waiting: { label: "\u7B49\u5F85\u4E2D", color: "default" },
9885
+ exception: { label: "\u6D41\u7A0B\u5F02\u5E38", color: "error" },
9886
+ completed: { label: "\u5DF2\u5B8C\u6210", color: "success" },
9887
+ terminated: { label: "\u5DF2\u62D2\u7EDD", color: "error" },
9888
+ withdrawn: { label: "\u5DF2\u64A4\u9500", color: "default" },
9889
+ processing: { label: "\u5BA1\u6279\u4E2D", color: "processing" },
9890
+ approved: { label: "\u540C\u610F", color: "success" },
9891
+ rejected: { label: "\u62D2\u7EDD", color: "error" }
9892
+ };
9893
+ if (fieldId !== "processInstanceStatus" && fieldId !== "approvalResult") return null;
9894
+ const meta = statusMap[raw];
9895
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Tag, { color: meta?.color, children: meta?.label || raw || "--" });
9896
+ };
9897
+ var renderCellValue = (value, field) => {
9898
+ const status = renderStatusTag(value, field.fieldId);
9899
+ if (status) return status;
9900
+ if (Array.isArray(value)) {
9901
+ if (value.length === 0) return formatPrimitive("");
9902
+ if (field.componentName === "ImageField") {
9903
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "flex max-w-[180px] gap-1 overflow-hidden", children: value.slice(0, 3).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
9904
+ "img",
9905
+ {
9906
+ alt: item?.name || field.label,
9907
+ src: item?.url || item?.previewUrl,
9908
+ className: "h-8 w-8 rounded object-cover"
9909
+ },
9910
+ item?.uid || item?.id || item?.url || index
9911
+ )) });
9912
+ }
9913
+ if (field.componentName === "AttachmentField") {
9914
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { size: 4, wrap: true, children: [
9915
+ value.slice(0, 3).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Tag, { children: item?.name || item?.originalName || `\u9644\u4EF6${index + 1}` }, item?.uid || item?.id || index)),
9916
+ value.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Tag, { children: [
9917
+ "+",
9918
+ value.length - 3
9919
+ ] })
9920
+ ] });
9921
+ }
9922
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { size: 4, wrap: true, children: [
9923
+ value.slice(0, 4).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Tag, { children: pickOptionLabel(field, item) }, `${field.fieldId}_${index}`)),
9924
+ value.length > 4 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Tag, { children: [
9925
+ "+",
9926
+ value.length - 4
9927
+ ] })
9928
+ ] });
9929
+ }
9930
+ if (value && typeof value === "object") {
9931
+ if (field.componentName === "UserSelectField" || field.componentName === "DepartmentSelectField") {
9932
+ return value.name || value.label || value.username || formatPrimitive(value.id);
9933
+ }
9934
+ if (value.start || value.end) {
9935
+ return [value.start, value.end].filter(Boolean).join(" \u81F3 ");
9936
+ }
9937
+ if (value.label || value.name || value.value) {
9938
+ return pickOptionLabel(field, value);
9939
+ }
9940
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Tooltip, { title: JSON.stringify(value), children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "text-ant-color-text-secondary", children: "\u5BF9\u8C61\u6570\u636E" }) });
9941
+ }
9942
+ if (["SelectField", "RadioField", "CheckboxField", "MultiSelectField"].includes(field.componentName)) {
9943
+ return pickOptionLabel(field, value);
9944
+ }
9945
+ return formatPrimitive(value);
9946
+ };
9947
+ var fileToBase64 = (file) => new Promise((resolve, reject) => {
9948
+ const reader = new FileReader();
9949
+ reader.onload = () => {
9950
+ const result = String(reader.result || "");
9951
+ resolve(result.includes(",") ? result.split(",")[1] : result);
9952
+ };
9953
+ reader.onerror = reject;
9954
+ reader.readAsDataURL(file);
9955
+ });
9956
+ function FilterGroupEditor({
9957
+ group,
9958
+ fields,
9959
+ onChange,
9960
+ level = 0
9961
+ }) {
9962
+ const fieldOptions = fields.map((field) => ({ label: field.label, value: field.fieldId }));
9963
+ const updateRule = (ruleId, patch) => {
9964
+ onChange({
9965
+ ...group,
9966
+ rules: group.rules.map((rule) => rule.id === ruleId ? { ...rule, ...patch } : rule)
9967
+ });
9968
+ };
9969
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
9970
+ "div",
9971
+ {
9972
+ className: `${level > 0 ? "ml-4 border-l border-ant-border-secondary pl-4" : ""} space-y-3`,
9973
+ children: [
9974
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "flex items-center justify-between", children: [
9975
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
9976
+ import_antd32.Segmented,
9977
+ {
9978
+ size: "small",
9979
+ value: group.logic,
9980
+ options: [
9981
+ { label: "\u6EE1\u8DB3\u5168\u90E8", value: "AND" },
9982
+ { label: "\u6EE1\u8DB3\u4EFB\u4E00", value: "OR" }
9983
+ ],
9984
+ onChange: (value) => onChange({ ...group, logic: value })
9985
+ }
9986
+ ),
9987
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { children: [
9988
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
9989
+ import_antd32.Button,
9990
+ {
9991
+ size: "small",
9992
+ onClick: () => onChange({ ...group, rules: [...group.rules, createRule(fields[0])] }),
9993
+ children: "\u6DFB\u52A0\u6761\u4EF6"
9994
+ }
9995
+ ),
9996
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
9997
+ import_antd32.Button,
9998
+ {
9999
+ size: "small",
10000
+ onClick: () => onChange({ ...group, conditions: [...group.conditions, createGroup()] }),
10001
+ children: "\u6DFB\u52A0\u5206\u7EC4"
10002
+ }
10003
+ )
10004
+ ] })
10005
+ ] }),
10006
+ group.rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
10007
+ "div",
10008
+ {
10009
+ className: "grid grid-cols-[minmax(120px,1fr)_120px_minmax(160px,1fr)_auto] gap-2",
10010
+ children: [
10011
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10012
+ import_antd32.Select,
10013
+ {
10014
+ showSearch: true,
10015
+ placeholder: "\u5B57\u6BB5",
10016
+ value: rule.key,
10017
+ options: fieldOptions,
10018
+ optionFilterProp: "label",
10019
+ onChange: (fieldId) => {
10020
+ const field = fields.find((item) => item.fieldId === fieldId);
10021
+ updateRule(rule.id, { key: fieldId, componentName: field?.componentName });
10022
+ }
10023
+ }
10024
+ ),
10025
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10026
+ import_antd32.Select,
10027
+ {
10028
+ value: rule.operator,
10029
+ options: [
10030
+ { label: "\u5305\u542B", value: "contains" },
10031
+ { label: "\u7B49\u4E8E", value: "eq" },
10032
+ { label: "\u4E0D\u7B49\u4E8E", value: "ne" },
10033
+ { label: "\u5927\u4E8E", value: "gt" },
10034
+ { label: "\u5C0F\u4E8E", value: "lt" }
10035
+ ],
10036
+ onChange: (operator) => updateRule(rule.id, { operator })
10037
+ }
10038
+ ),
10039
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10040
+ import_antd32.Input,
10041
+ {
10042
+ value: rule.value,
10043
+ placeholder: "\u8F93\u5165\u7B5B\u9009\u503C",
10044
+ onChange: (event) => updateRule(rule.id, { value: event.target.value })
10045
+ }
10046
+ ),
10047
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10048
+ import_antd32.Button,
10049
+ {
10050
+ danger: true,
10051
+ type: "text",
10052
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DeleteOutlined, {}),
10053
+ onClick: () => onChange({ ...group, rules: group.rules.filter((item) => item.id !== rule.id) })
10054
+ }
10055
+ )
10056
+ ]
10057
+ },
10058
+ rule.id
10059
+ )),
10060
+ group.conditions.map((child) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10061
+ FilterGroupEditor,
10062
+ {
10063
+ group: child,
10064
+ fields,
10065
+ level: level + 1,
10066
+ onChange: (next) => onChange({
10067
+ ...group,
10068
+ conditions: group.conditions.map((item) => item.id === child.id ? next : item)
10069
+ })
10070
+ },
10071
+ child.id
10072
+ )),
10073
+ group.rules.length === 0 && group.conditions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Empty, { image: import_antd32.Empty.PRESENTED_IMAGE_SIMPLE, description: "\u6682\u65E0\u7B5B\u9009\u6761\u4EF6" })
10074
+ ]
10075
+ }
10076
+ );
10077
+ }
10078
+ var DataManagementList = ({
10079
+ appType,
10080
+ formUuid,
10081
+ menuFormUuid,
10082
+ readonly = false,
10083
+ fullHeight = true,
10084
+ configScope = "global",
10085
+ title,
10086
+ detailRenderer,
10087
+ submitRenderer,
10088
+ requestOverride,
10089
+ rowActions = []
10090
+ }) => {
10091
+ const api = (0, import_react61.useMemo)(() => {
10092
+ if (typeof requestOverride === "function") {
10093
+ return createFormRuntimeApi({ request: requestOverride });
10094
+ }
10095
+ return createFormRuntimeApi(requestOverride);
10096
+ }, [requestOverride]);
10097
+ const [fields, setFields] = (0, import_react61.useState)([]);
10098
+ const [config, setConfig] = (0, import_react61.useState)({});
10099
+ const [showFields, setShowFields] = (0, import_react61.useState)([]);
10100
+ const [lockFieldIds, setLockFieldIds] = (0, import_react61.useState)([]);
10101
+ const [widths, setWidths] = (0, import_react61.useState)({});
10102
+ const [sort, setSort] = (0, import_react61.useState)([]);
10103
+ const [density, setDensity] = (0, import_react61.useState)("middle");
10104
+ const [detailOpenMode, setDetailOpenMode] = (0, import_react61.useState)("drawer");
10105
+ const [searchKeyWord, setSearchKeyWord] = (0, import_react61.useState)("");
10106
+ const [filterGroup, setFilterGroup] = (0, import_react61.useState)(createGroup);
10107
+ const [dataSource, setDataSource] = (0, import_react61.useState)([]);
10108
+ const [total, setTotal] = (0, import_react61.useState)(0);
10109
+ const [current, setCurrent] = (0, import_react61.useState)(1);
10110
+ const [pageSize, setPageSize] = (0, import_react61.useState)(10);
10111
+ const [loading, setLoading] = (0, import_react61.useState)(false);
10112
+ const [schemaLoading, setSchemaLoading] = (0, import_react61.useState)(true);
10113
+ const [selectedRowKeys, setSelectedRowKeys] = (0, import_react61.useState)([]);
10114
+ const [filterOpen, setFilterOpen] = (0, import_react61.useState)(false);
10115
+ const [columnOpen, setColumnOpen] = (0, import_react61.useState)(false);
10116
+ const [exportOpen, setExportOpen] = (0, import_react61.useState)(false);
10117
+ const [exportScope, setExportScope] = (0, import_react61.useState)("all");
10118
+ const [exportFields, setExportFields] = (0, import_react61.useState)([]);
10119
+ const [exporting, setExporting] = (0, import_react61.useState)(false);
10120
+ const [importOpen, setImportOpen] = (0, import_react61.useState)(false);
10121
+ const [importPreview, setImportPreview] = (0, import_react61.useState)([]);
10122
+ const [importBase64, setImportBase64] = (0, import_react61.useState)("");
10123
+ const [recordsOpen, setRecordsOpen] = (0, import_react61.useState)(false);
10124
+ const [recordTab, setRecordTab] = (0, import_react61.useState)("export");
10125
+ const [transferRecords, setTransferRecords] = (0, import_react61.useState)([]);
10126
+ const [batchApprovalOpen, setBatchApprovalOpen] = (0, import_react61.useState)(false);
10127
+ const [batchApprovalAction, setBatchApprovalAction] = (0, import_react61.useState)(
10128
+ "approved"
10129
+ );
10130
+ const [batchApprovalComments, setBatchApprovalComments] = (0, import_react61.useState)("");
10131
+ const [batchApproving, setBatchApproving] = (0, import_react61.useState)(false);
10132
+ const [activeRecord, setActiveRecord] = (0, import_react61.useState)(null);
10133
+ const [detailOpen, setDetailOpen] = (0, import_react61.useState)(false);
10134
+ const [submitOpen, setSubmitOpen] = (0, import_react61.useState)(false);
10135
+ const fetchStateRef = (0, import_react61.useRef)({});
10136
+ const request = api.request;
10137
+ const visibleFields = (0, import_react61.useMemo)(
10138
+ () => showFields.map((fieldId) => fields.find((field) => field.fieldId === fieldId)).filter(Boolean),
10139
+ [fields, showFields]
10140
+ );
10141
+ (0, import_react61.useEffect)(() => {
10142
+ fetchStateRef.current = {
10143
+ current,
10144
+ pageSize,
10145
+ searchKeyWord,
10146
+ filterGroup,
10147
+ sort
10148
+ };
10149
+ }, [current, filterGroup, pageSize, searchKeyWord, sort]);
10150
+ const loadData = (0, import_react61.useCallback)(
10151
+ async (overrides = {}) => {
10152
+ if (!appType || !formUuid) return;
10153
+ const fetchState = { ...fetchStateRef.current, ...overrides };
10154
+ const nextCurrent = fetchState.current || 1;
10155
+ const nextPageSize = fetchState.pageSize || 10;
10156
+ fetchStateRef.current = {
10157
+ ...fetchState,
10158
+ current: nextCurrent,
10159
+ pageSize: nextPageSize
10160
+ };
10161
+ setLoading(true);
10162
+ try {
10163
+ const result = await advancedSearchDataManagement(request, {
10164
+ appType,
10165
+ formUuid,
10166
+ currentPage: nextCurrent,
10167
+ pageSize: nextPageSize,
10168
+ searchKeyWord: fetchState.searchKeyWord,
10169
+ filters: fetchState.filterGroup,
10170
+ order: fetchState.sort
10171
+ });
10172
+ setDataSource(result.records);
10173
+ setTotal(result.total);
10174
+ setCurrent(nextCurrent);
10175
+ setPageSize(nextPageSize);
10176
+ } catch (error) {
10177
+ console.error("[DataManagementList] loadData failed:", error);
10178
+ import_antd32.message.error("\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
10179
+ } finally {
10180
+ setLoading(false);
10181
+ }
10182
+ },
10183
+ [appType, formUuid, request]
10184
+ );
10185
+ (0, import_react61.useEffect)(() => {
10186
+ let mounted = true;
10187
+ const loadSchemaAndConfig = async () => {
10188
+ if (!appType || !formUuid) return;
10189
+ setSchemaLoading(true);
10190
+ setDataSource([]);
10191
+ setTotal(0);
10192
+ setSelectedRowKeys([]);
10193
+ try {
10194
+ const schemaResult = await getDataManagementSchema(request, { appType, formUuid });
10195
+ if (!mounted) return;
10196
+ const allFields = [
10197
+ ...schemaResult.fields,
10198
+ ...getSystemFieldsForFormType(schemaResult.formType)
10199
+ ];
10200
+ const saved = await getDataManagementConfig(request, {
10201
+ appType,
10202
+ formUuid,
10203
+ menuFormUuid,
10204
+ scope: configScope
10205
+ }).catch(() => void 0);
10206
+ if (!mounted) return;
10207
+ const resolved = normalizeColumnConfig(saved, allFields);
10208
+ const nextSearchKeyWord = saved?.filter?.searchKeyWord || "";
10209
+ const nextFilterGroup = hydrateFilterGroup(saved?.filter?.group);
10210
+ setFields(allFields);
10211
+ setConfig(saved || {});
10212
+ setShowFields(resolved.showFields);
10213
+ setWidths(resolved.widths);
10214
+ setLockFieldIds(resolved.lockFieldIds);
10215
+ setSort(resolved.sort);
10216
+ setDensity(resolved.density);
10217
+ setDetailOpenMode(resolved.detailOpenMode);
10218
+ setPageSize(resolved.pageSize);
10219
+ setSearchKeyWord(nextSearchKeyWord);
10220
+ setFilterGroup(nextFilterGroup);
10221
+ await loadData({
10222
+ current: 1,
10223
+ pageSize: resolved.pageSize,
10224
+ searchKeyWord: nextSearchKeyWord,
10225
+ filterGroup: nextFilterGroup,
10226
+ sort: resolved.sort
10227
+ });
10228
+ } catch (error) {
10229
+ console.error("[DataManagementList] load schema failed:", error);
10230
+ import_antd32.message.error("\u52A0\u8F7D\u8868\u5355\u914D\u7F6E\u5931\u8D25");
10231
+ } finally {
10232
+ if (mounted) setSchemaLoading(false);
10233
+ }
10234
+ };
10235
+ loadSchemaAndConfig();
10236
+ return () => {
10237
+ mounted = false;
10238
+ };
10239
+ }, [appType, configScope, formUuid, loadData, menuFormUuid, request]);
10240
+ const persistConfig = (0, import_react61.useCallback)(
10241
+ async (patch) => {
10242
+ const nextConfig = { ...config, ...patch };
10243
+ setConfig(nextConfig);
10244
+ await saveDataManagementConfig(request, {
10245
+ appType,
10246
+ formUuid,
10247
+ menuFormUuid,
10248
+ scope: configScope,
10249
+ config: nextConfig
10250
+ }).catch((error) => {
10251
+ console.error("[DataManagementList] save config failed:", error);
10252
+ import_antd32.message.warning("\u914D\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u672C\u6B21\u4EC5\u5728\u5F53\u524D\u9875\u9762\u751F\u6548");
10253
+ });
10254
+ },
10255
+ [appType, config, configScope, formUuid, menuFormUuid, request]
10256
+ );
10257
+ const handleColumnCommit = async () => {
10258
+ setColumnOpen(false);
10259
+ await persistConfig({
10260
+ showFields,
10261
+ lockFieldIds,
10262
+ widths,
10263
+ density,
10264
+ detailOpenMode,
10265
+ pageSize
10266
+ });
10267
+ };
10268
+ const handleDetail = (0, import_react61.useCallback)(
10269
+ (record) => {
10270
+ const formInstanceId = getRecordId(record);
10271
+ if (detailOpenMode === "newPage" && typeof window !== "undefined") {
10272
+ window.open(`/${appType}/forms/${formUuid}/detail/${formInstanceId}`, "_blank");
10273
+ return;
10274
+ }
10275
+ setActiveRecord(record);
10276
+ setDetailOpen(true);
10277
+ },
10278
+ [appType, detailOpenMode, formUuid]
10279
+ );
10280
+ const handleDelete = (0, import_react61.useCallback)(
10281
+ async (ids) => {
10282
+ if (ids.length === 0) return;
10283
+ await deleteDataManagementRows(request, { appType, formUuid, formInstanceIds: ids });
10284
+ setSelectedRowKeys([]);
10285
+ await loadData({ current, pageSize });
10286
+ },
10287
+ [appType, current, formUuid, loadData, pageSize, request]
10288
+ );
10289
+ const getSelectedRecordIds = (0, import_react61.useCallback)(
10290
+ () => selectedRowKeys.map((key) => {
10291
+ const record = dataSource.find((item) => String(getRecordId(item)) === String(key));
10292
+ return String(getSelectedRecordId(record, key));
10293
+ }),
10294
+ [dataSource, selectedRowKeys]
10295
+ );
10296
+ const handleBatchApprove = () => {
10297
+ if (selectedRowKeys.length === 0) return;
10298
+ setBatchApprovalOpen(true);
10299
+ };
10300
+ const handleBatchApprovalConfirm = async () => {
10301
+ const ids = getSelectedRecordIds();
10302
+ if (ids.length === 0) return;
10303
+ setBatchApproving(true);
10304
+ try {
10305
+ await batchApproveDataManagementRows(request, {
10306
+ appType,
10307
+ formUuid,
10308
+ formInstanceIds: ids,
10309
+ action: batchApprovalAction,
10310
+ comments: batchApprovalComments || void 0
10311
+ });
10312
+ import_antd32.message.success(`\u6279\u91CF${batchApprovalAction === "approved" ? "\u901A\u8FC7" : "\u62D2\u7EDD"}\u5DF2\u63D0\u4EA4`);
10313
+ setSelectedRowKeys([]);
10314
+ setBatchApprovalOpen(false);
10315
+ setBatchApprovalAction("approved");
10316
+ setBatchApprovalComments("");
10317
+ await loadData({ current, pageSize });
10318
+ } catch (error) {
10319
+ console.error("[DataManagementList] batch approval failed:", error);
10320
+ import_antd32.message.error("\u6279\u91CF\u5BA1\u6279\u5931\u8D25");
10321
+ } finally {
10322
+ setBatchApproving(false);
10323
+ }
10324
+ };
10325
+ const handleExport = async (scope) => {
10326
+ const selectedIds = scope === "selected" ? getSelectedRecordIds() : [];
10327
+ if (scope === "selected" && selectedIds.length === 0) {
10328
+ import_antd32.message.warning("\u8BF7\u5148\u9009\u62E9\u8981\u5BFC\u51FA\u7684\u8BB0\u5F55");
10329
+ return;
10330
+ }
10331
+ const selectedFilters = selectedIds.map((id) => ({
10332
+ key: "form_instance_id",
10333
+ operator: "EQ",
10334
+ value: id
10335
+ }));
10336
+ setExporting(true);
10337
+ try {
10338
+ await exportDataManagementRows(request, {
10339
+ appType,
10340
+ formUuid,
10341
+ currentPage: scope === "selected" ? 1 : current,
10342
+ pageSize: scope === "selected" ? selectedIds.length : pageSize,
10343
+ searchKeyWord: scope === "selected" ? void 0 : searchKeyWord,
10344
+ filters: scope === "selected" ? void 0 : filterGroup,
10345
+ rawFilters: scope === "selected" ? JSON.stringify(selectedFilters) : void 0,
10346
+ conditionType: scope === "selected" ? "OR" : void 0,
10347
+ order: sort,
10348
+ exportAll: scope === "all" ? "y" : "n",
10349
+ exportFields
10350
+ });
10351
+ import_antd32.message.success("\u5BFC\u51FA\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF0C\u53EF\u5728\u5BFC\u5165\u5BFC\u51FA\u8BB0\u5F55\u4E2D\u67E5\u770B");
10352
+ setExportOpen(false);
10353
+ } catch (error) {
10354
+ console.error("[DataManagementList] export failed:", error);
10355
+ import_antd32.message.error("\u5BFC\u51FA\u5931\u8D25");
10356
+ } finally {
10357
+ setExporting(false);
10358
+ }
10359
+ };
10360
+ const loadTransferRecords = async (type) => {
10361
+ setRecordTab(type);
10362
+ setRecordsOpen(true);
10363
+ const result = await getDataManagementTransferRecords(request, {
10364
+ appType,
10365
+ formUuid,
10366
+ type,
10367
+ currentPage: 1,
10368
+ pageSize: 10
10369
+ });
10370
+ setTransferRecords(result.records);
10371
+ };
10372
+ const handleImportPreview = async (file) => {
10373
+ const base64 = await fileToBase64(file);
10374
+ setImportBase64(base64);
10375
+ const result = await importPreviewDataManagementRows(request, {
10376
+ appType,
10377
+ formUuid,
10378
+ fileBase64: base64
10379
+ });
10380
+ const records = result?.data || result?.records || result?.list || result || [];
10381
+ setImportPreview(Array.isArray(records) ? records : []);
10382
+ return false;
10383
+ };
10384
+ const handleImportConfirm = async () => {
10385
+ if (!importBase64) return;
10386
+ await importDataManagementRows(request, { appType, formUuid, fileBase64: importBase64 });
10387
+ import_antd32.message.success("\u5BFC\u5165\u4EFB\u52A1\u5DF2\u521B\u5EFA");
10388
+ setImportOpen(false);
10389
+ setImportPreview([]);
10390
+ setImportBase64("");
10391
+ await loadData({ current: 1, pageSize });
10392
+ };
10393
+ const columns = (0, import_react61.useMemo)(() => {
10394
+ const baseColumns = visibleFields.map((field) => ({
10395
+ title: field.label,
10396
+ dataIndex: field.fieldId,
10397
+ key: field.fieldId,
10398
+ width: widths[field.fieldId] || field.width || 160,
10399
+ fixed: lockFieldIds.includes(field.fieldId) ? "left" : void 0,
10400
+ ellipsis: true,
10401
+ sorter: true,
10402
+ render: (value) => renderCellValue(value, field)
10403
+ })) || [];
10404
+ return [
10405
+ ...baseColumns,
10406
+ {
10407
+ title: "\u64CD\u4F5C",
10408
+ key: "__actions",
10409
+ width: 148,
10410
+ fixed: "right",
10411
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { size: 4, children: [
10412
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { type: "link", size: "small", onClick: () => handleDetail(record), children: "\u8BE6\u60C5" }),
10413
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10414
+ import_antd32.Dropdown,
10415
+ {
10416
+ trigger: ["click"],
10417
+ menu: {
10418
+ items: [
10419
+ ...rowActions.map((action) => ({
10420
+ key: action.key,
10421
+ label: action.label,
10422
+ danger: action.danger,
10423
+ onClick: () => action.onClick(record)
10424
+ })),
10425
+ {
10426
+ key: "workflow",
10427
+ label: "\u6D41\u7A0B\u65E5\u5FD7",
10428
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.HistoryOutlined, {}),
10429
+ onClick: () => import_antd32.message.info("\u8BF7\u901A\u8FC7 detailRenderer \u63A5\u5165\u6D41\u7A0B\u65E5\u5FD7\u6216\u6D41\u7A0B\u56FE\u5165\u53E3")
10430
+ },
10431
+ ...!readonly ? [
10432
+ {
10433
+ key: "delete",
10434
+ label: "\u5220\u9664",
10435
+ danger: true,
10436
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DeleteOutlined, {}),
10437
+ onClick: () => import_antd32.Modal.confirm({
10438
+ title: "\u786E\u8BA4\u5220\u9664",
10439
+ content: "\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F",
10440
+ onOk: () => handleDelete([String(getRecordId(record))])
10441
+ })
10442
+ }
10443
+ ] : []
10444
+ ]
10445
+ },
10446
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { type: "text", size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.MoreOutlined, {}) })
10447
+ }
10448
+ )
10449
+ ] })
10450
+ }
10451
+ ];
10452
+ }, [handleDelete, handleDetail, lockFieldIds, readonly, rowActions, visibleFields, widths]);
10453
+ const tableSize = density === "compact" ? "small" : density === "loose" ? "large" : "middle";
10454
+ const importPreviewColumns = (0, import_react61.useMemo)(() => {
10455
+ const keys = Array.from(
10456
+ new Set(importPreview.flatMap((record) => Object.keys(record || {})))
10457
+ ).slice(0, 16);
10458
+ return keys.map((key) => {
10459
+ const field = fields.find((item) => item.fieldId === key || item.id === key);
10460
+ return {
10461
+ title: field?.label || key,
10462
+ dataIndex: key,
10463
+ key,
10464
+ width: 150,
10465
+ ellipsis: true,
10466
+ render: (value) => field ? renderCellValue(value, field) : formatPrimitive(value)
10467
+ };
10468
+ });
10469
+ }, [fields, importPreview]);
10470
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: `${fullHeight ? "h-full min-h-screen" : ""} bg-ant-bg-layout`, children: [
10471
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "mx-auto flex h-full max-w-[1440px] flex-col px-4 py-4 md:px-6", children: [
10472
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
10473
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10474
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("h1", { className: "text-xl font-semibold text-ant-color-text", children: title || "\u6570\u636E\u7BA1\u7406" }),
10475
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("p", { className: "mt-1 text-sm text-ant-color-text-secondary", children: [
10476
+ "\u5171 ",
10477
+ total,
10478
+ " \u6761\u6570\u636E\uFF0C\u5DF2\u9009\u62E9 ",
10479
+ selectedRowKeys.length,
10480
+ " \u6761"
10481
+ ] })
10482
+ ] }),
10483
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { wrap: true, children: [
10484
+ !readonly && submitRenderer && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.PlusOutlined, {}), type: "primary", onClick: () => setSubmitOpen(true), children: "\u65B0\u589E" }),
10485
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10486
+ import_antd32.Input.Search,
10487
+ {
10488
+ allowClear: true,
10489
+ className: "w-[260px]",
10490
+ placeholder: "\u641C\u7D22\u5173\u952E\u5B57",
10491
+ value: searchKeyWord,
10492
+ onChange: (event) => setSearchKeyWord(event.target.value),
10493
+ onSearch: (value) => {
10494
+ const nextSearchKeyWord = String(value || "");
10495
+ setSearchKeyWord(nextSearchKeyWord);
10496
+ persistConfig({ filter: { searchKeyWord: nextSearchKeyWord, group: filterGroup } });
10497
+ loadData({
10498
+ current: 1,
10499
+ pageSize,
10500
+ searchKeyWord: nextSearchKeyWord,
10501
+ filterGroup
10502
+ });
10503
+ }
10504
+ }
10505
+ ),
10506
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.FilterOutlined, {}), onClick: () => setFilterOpen(true), children: "\u7B5B\u9009" }),
10507
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.SettingOutlined, {}), onClick: () => setColumnOpen(true), children: "\u5217\u8BBE\u7F6E" }),
10508
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10509
+ import_antd32.Dropdown,
10510
+ {
10511
+ menu: {
10512
+ items: [
10513
+ {
10514
+ key: "selected",
10515
+ label: "\u5BFC\u51FA\u9009\u4E2D",
10516
+ disabled: selectedRowKeys.length === 0,
10517
+ onClick: () => {
10518
+ setExportScope("selected");
10519
+ setExportFields(showFields);
10520
+ setExportOpen(true);
10521
+ }
10522
+ },
10523
+ {
10524
+ key: "all",
10525
+ label: "\u5BFC\u51FA\u5168\u90E8",
10526
+ onClick: () => {
10527
+ setExportScope("all");
10528
+ setExportFields(showFields);
10529
+ setExportOpen(true);
10530
+ }
10531
+ },
10532
+ {
10533
+ key: "records",
10534
+ label: "\u5BFC\u51FA\u8BB0\u5F55",
10535
+ onClick: () => loadTransferRecords("export")
10536
+ }
10537
+ ]
10538
+ },
10539
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DownloadOutlined, {}), children: "\u5BFC\u51FA" })
10540
+ }
10541
+ ),
10542
+ !readonly && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10543
+ import_antd32.Dropdown,
10544
+ {
10545
+ menu: {
10546
+ items: [
10547
+ { key: "import", label: "\u5BFC\u5165\u6570\u636E", onClick: () => setImportOpen(true) },
10548
+ {
10549
+ key: "records",
10550
+ label: "\u5BFC\u5165\u8BB0\u5F55",
10551
+ onClick: () => loadTransferRecords("import")
10552
+ }
10553
+ ]
10554
+ },
10555
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.ImportOutlined, {}), children: "\u5BFC\u5165" })
10556
+ }
10557
+ ),
10558
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.ReloadOutlined, {}), onClick: () => loadData({ current, pageSize }) })
10559
+ ] })
10560
+ ] }),
10561
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "relative flex-1 overflow-hidden rounded-lg border border-ant-border-secondary bg-ant-bg-container", children: [
10562
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10563
+ import_antd32.Table,
10564
+ {
10565
+ rowKey: (record) => String(getRecordId(record)),
10566
+ loading: loading || schemaLoading,
10567
+ columns,
10568
+ dataSource,
10569
+ size: tableSize,
10570
+ scroll: {
10571
+ x: Math.max(900, visibleFields.length * 160),
10572
+ y: fullHeight ? "calc(100vh - 260px)" : void 0
10573
+ },
10574
+ rowSelection: {
10575
+ selectedRowKeys,
10576
+ onChange: setSelectedRowKeys
10577
+ },
10578
+ pagination: {
10579
+ current,
10580
+ pageSize,
10581
+ total,
10582
+ showSizeChanger: true,
10583
+ showTotal: (count) => `\u5171 ${count} \u6761`
10584
+ },
10585
+ onChange: (pagination, _filters, sorter) => {
10586
+ const sorters = Array.isArray(sorter) ? sorter : [sorter];
10587
+ const nextSort = sorters.filter((item) => item?.field && item?.order).map((item) => ({
10588
+ id: String(item.field),
10589
+ isAsc: item.order === "ascend" ? "y" : "n"
10590
+ }));
10591
+ setSort(nextSort);
10592
+ persistConfig({ sort: nextSort });
10593
+ loadData({
10594
+ current: pagination.current || 1,
10595
+ pageSize: pagination.pageSize || pageSize,
10596
+ sort: nextSort
10597
+ });
10598
+ }
10599
+ }
10600
+ ),
10601
+ selectedRowKeys.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "absolute bottom-4 left-1/2 z-10 flex -translate-x-1/2 items-center gap-3 rounded-lg border border-ant-border-secondary bg-ant-bg-elevated px-4 py-3 shadow-lg", children: [
10602
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "text-sm text-ant-color-text-secondary", children: [
10603
+ "\u5DF2\u9009 ",
10604
+ selectedRowKeys.length,
10605
+ " \u6761"
10606
+ ] }),
10607
+ !readonly && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.SwapOutlined, {}), onClick: handleBatchApprove, children: "\u6279\u91CF\u5BA1\u6279" }),
10608
+ !readonly && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10609
+ import_antd32.Button,
10610
+ {
10611
+ danger: true,
10612
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DeleteOutlined, {}),
10613
+ onClick: () => import_antd32.Modal.confirm({
10614
+ title: "\u786E\u8BA4\u6279\u91CF\u5220\u9664",
10615
+ content: `\u5C06\u5220\u9664 ${selectedRowKeys.length} \u6761\u6570\u636E\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F`,
10616
+ onOk: () => handleDelete(selectedRowKeys.map(String))
10617
+ }),
10618
+ children: "\u6279\u91CF\u5220\u9664"
10619
+ }
10620
+ ),
10621
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { type: "link", onClick: () => setSelectedRowKeys([]), children: "\u53D6\u6D88\u9009\u62E9" })
10622
+ ] })
10623
+ ] })
10624
+ ] }),
10625
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10626
+ import_antd32.Modal,
10627
+ {
10628
+ title: "\u9AD8\u7EA7\u7B5B\u9009",
10629
+ open: filterOpen,
10630
+ width: 760,
10631
+ onCancel: () => setFilterOpen(false),
10632
+ onOk: () => {
10633
+ setFilterOpen(false);
10634
+ persistConfig({ filter: { searchKeyWord, group: filterGroup } });
10635
+ loadData({ current: 1, pageSize, searchKeyWord, filterGroup });
10636
+ },
10637
+ okText: "\u5E94\u7528\u7B5B\u9009",
10638
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(FilterGroupEditor, { group: filterGroup, fields, onChange: setFilterGroup })
10639
+ }
10640
+ ),
10641
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10642
+ import_antd32.Modal,
10643
+ {
10644
+ title: "\u5217\u8BBE\u7F6E",
10645
+ open: columnOpen,
10646
+ width: 720,
10647
+ onCancel: () => setColumnOpen(false),
10648
+ onOk: handleColumnCommit,
10649
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "space-y-5", children: [
10650
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10651
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u663E\u793A\u5217" }),
10652
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10653
+ import_antd32.Checkbox.Group,
10654
+ {
10655
+ className: "grid grid-cols-2 gap-2 md:grid-cols-3",
10656
+ value: showFields,
10657
+ options: fields.map((field) => ({ label: field.label, value: field.fieldId })),
10658
+ onChange: (values) => setShowFields(values.map(String))
10659
+ }
10660
+ )
8720
10661
  ] }),
8721
- /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
8722
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
8723
- route.assignees && route.assignees.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "mt-1 flex items-center gap-1.5 flex-wrap", children: [
8724
- /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_icons6.UserOutlined, { className: "text-gray-400 text-xs" }),
8725
- route.assignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
8726
- "span",
10662
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10663
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u51BB\u7ED3\u5217" }),
10664
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10665
+ import_antd32.Select,
10666
+ {
10667
+ mode: "multiple",
10668
+ className: "w-full",
10669
+ value: lockFieldIds,
10670
+ options: showFields.map((fieldId) => {
10671
+ const field = fields.find((item) => item.fieldId === fieldId);
10672
+ return { label: field?.label || fieldId, value: fieldId };
10673
+ }),
10674
+ onChange: setLockFieldIds
10675
+ }
10676
+ )
10677
+ ] }),
10678
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "grid gap-4 md:grid-cols-3", children: [
10679
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10680
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u8868\u683C\u5BC6\u5EA6" }),
10681
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10682
+ import_antd32.Segmented,
8727
10683
  {
8728
- className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
8729
- children: assignee.name
8730
- },
8731
- assignee.id
8732
- ))
10684
+ block: true,
10685
+ value: density,
10686
+ options: [
10687
+ { label: "\u7D27\u51D1", value: "compact" },
10688
+ { label: "\u6807\u51C6", value: "middle" },
10689
+ { label: "\u5BBD\u677E", value: "loose" }
10690
+ ],
10691
+ onChange: (value) => setDensity(value)
10692
+ }
10693
+ )
10694
+ ] }),
10695
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10696
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u8BE6\u60C5\u6253\u5F00\u65B9\u5F0F" }),
10697
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10698
+ import_antd32.Segmented,
10699
+ {
10700
+ block: true,
10701
+ value: detailOpenMode,
10702
+ options: [
10703
+ { label: "\u62BD\u5C49", value: "drawer" },
10704
+ { label: "\u65B0\u9875", value: "newPage" }
10705
+ ],
10706
+ onChange: (value) => setDetailOpenMode(value)
10707
+ }
10708
+ )
10709
+ ] }),
10710
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10711
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u9875\u5927\u5C0F" }),
10712
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10713
+ import_antd32.Select,
10714
+ {
10715
+ className: "w-full",
10716
+ value: pageSize,
10717
+ options: [10, 20, 50, 100].map((value) => ({ label: `${value} \u6761`, value })),
10718
+ onChange: setPageSize
10719
+ }
10720
+ )
8733
10721
  ] })
8734
10722
  ] })
8735
- ] }, route.nodeId);
8736
- }) })
8737
- }
8738
- );
10723
+ ] })
10724
+ }
10725
+ ),
10726
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10727
+ import_antd32.Modal,
10728
+ {
10729
+ title: exportScope === "selected" ? "\u5BFC\u51FA\u9009\u4E2D\u6570\u636E" : "\u5BFC\u51FA\u5168\u90E8\u6570\u636E",
10730
+ open: exportOpen,
10731
+ onCancel: () => setExportOpen(false),
10732
+ footer: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { children: [
10733
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { onClick: () => setExportOpen(false), children: "\u53D6\u6D88" }),
10734
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10735
+ import_antd32.Button,
10736
+ {
10737
+ type: "primary",
10738
+ loading: exporting,
10739
+ disabled: exportScope === "selected" && selectedRowKeys.length === 0,
10740
+ onClick: () => handleExport(exportScope),
10741
+ children: exportScope === "selected" ? `\u5BFC\u51FA\u9009\u4E2D (${selectedRowKeys.length})` : "\u5BFC\u51FA\u5168\u90E8"
10742
+ }
10743
+ )
10744
+ ] }),
10745
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10746
+ import_antd32.Checkbox.Group,
10747
+ {
10748
+ className: "grid grid-cols-2 gap-2",
10749
+ value: exportFields,
10750
+ options: fields.map((field) => ({ label: field.label, value: field.fieldId })),
10751
+ onChange: (values) => setExportFields(values.map(String))
10752
+ }
10753
+ )
10754
+ }
10755
+ ),
10756
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10757
+ import_antd32.Modal,
10758
+ {
10759
+ title: "\u6279\u91CF\u5BA1\u6279",
10760
+ open: batchApprovalOpen,
10761
+ onCancel: () => setBatchApprovalOpen(false),
10762
+ onOk: handleBatchApprovalConfirm,
10763
+ okText: batchApprovalAction === "approved" ? "\u786E\u8BA4\u901A\u8FC7" : "\u786E\u8BA4\u62D2\u7EDD",
10764
+ confirmLoading: batchApproving,
10765
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "space-y-4", children: [
10766
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "text-sm text-ant-color-text-secondary", children: [
10767
+ "\u5DF2\u9009\u62E9 ",
10768
+ selectedRowKeys.length,
10769
+ " \u6761\u8BB0\u5F55"
10770
+ ] }),
10771
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10772
+ import_antd32.Segmented,
10773
+ {
10774
+ block: true,
10775
+ value: batchApprovalAction,
10776
+ options: [
10777
+ { label: "\u540C\u610F", value: "approved" },
10778
+ { label: "\u62D2\u7EDD", value: "rejected" }
10779
+ ],
10780
+ onChange: (value) => setBatchApprovalAction(value)
10781
+ }
10782
+ ),
10783
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10784
+ import_antd32.Input.TextArea,
10785
+ {
10786
+ value: batchApprovalComments,
10787
+ rows: 4,
10788
+ maxLength: 500,
10789
+ showCount: true,
10790
+ placeholder: "\u586B\u5199\u5BA1\u6279\u610F\u89C1",
10791
+ onChange: (event) => setBatchApprovalComments(event.target.value)
10792
+ }
10793
+ )
10794
+ ] })
10795
+ }
10796
+ ),
10797
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
10798
+ import_antd32.Modal,
10799
+ {
10800
+ title: "\u5BFC\u5165\u6570\u636E",
10801
+ open: importOpen,
10802
+ width: 720,
10803
+ onCancel: () => setImportOpen(false),
10804
+ onOk: handleImportConfirm,
10805
+ okButtonProps: { disabled: !importBase64 },
10806
+ okText: "\u786E\u8BA4\u5BFC\u5165",
10807
+ children: [
10808
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10809
+ import_antd32.Upload.Dragger,
10810
+ {
10811
+ accept: ".xlsx,.xls",
10812
+ maxCount: 1,
10813
+ beforeUpload: handleImportPreview,
10814
+ onRemove: () => {
10815
+ setImportBase64("");
10816
+ setImportPreview([]);
10817
+ },
10818
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("p", { className: "text-ant-color-text-secondary", children: "\u62D6\u62FD Excel \u6587\u4EF6\u5230\u6B64\u5904\uFF0C\u6216\u70B9\u51FB\u9009\u62E9\u6587\u4EF6" })
10819
+ }
10820
+ ),
10821
+ importPreview.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "mt-4", children: [
10822
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u5BFC\u5165\u9884\u89C8" }),
10823
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10824
+ import_antd32.Table,
10825
+ {
10826
+ size: "small",
10827
+ dataSource: importPreview,
10828
+ columns: importPreviewColumns,
10829
+ scroll: { x: Math.max(600, (importPreviewColumns?.length || 0) * 150) },
10830
+ pagination: false,
10831
+ rowKey: (_, index) => String(index)
10832
+ }
10833
+ )
10834
+ ] })
10835
+ ]
10836
+ }
10837
+ ),
10838
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
10839
+ import_antd32.Drawer,
10840
+ {
10841
+ title: recordTab === "import" ? "\u5BFC\u5165\u8BB0\u5F55" : "\u5BFC\u51FA\u8BB0\u5F55",
10842
+ open: recordsOpen,
10843
+ width: 720,
10844
+ onClose: () => setRecordsOpen(false),
10845
+ children: [
10846
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10847
+ import_antd32.Segmented,
10848
+ {
10849
+ value: recordTab,
10850
+ options: [
10851
+ { label: "\u5BFC\u5165\u8BB0\u5F55", value: "import" },
10852
+ { label: "\u5BFC\u51FA\u8BB0\u5F55", value: "export" }
10853
+ ],
10854
+ onChange: (value) => loadTransferRecords(value)
10855
+ }
10856
+ ),
10857
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10858
+ import_antd32.Table,
10859
+ {
10860
+ className: "mt-4",
10861
+ size: "small",
10862
+ dataSource: transferRecords,
10863
+ rowKey: (record) => record.id || record.recordId
10864
+ }
10865
+ )
10866
+ ]
10867
+ }
10868
+ ),
10869
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10870
+ import_antd32.Drawer,
10871
+ {
10872
+ title: "\u8BE6\u60C5",
10873
+ open: detailOpen,
10874
+ width: 720,
10875
+ onClose: () => setDetailOpen(false),
10876
+ destroyOnClose: true,
10877
+ children: activeRecord && detailRenderer ? detailRenderer({
10878
+ record: activeRecord,
10879
+ formInstanceId: String(getRecordId(activeRecord)),
10880
+ onClose: () => setDetailOpen(false)
10881
+ }) : /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Empty, { description: "\u8BF7\u901A\u8FC7 detailRenderer \u63A5\u5165\u8BE6\u60C5\u6A21\u677F" })
10882
+ }
10883
+ ),
10884
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10885
+ import_antd32.Drawer,
10886
+ {
10887
+ title: "\u65B0\u589E\u6570\u636E",
10888
+ open: submitOpen,
10889
+ width: 720,
10890
+ onClose: () => setSubmitOpen(false),
10891
+ destroyOnClose: true,
10892
+ children: submitRenderer ? submitRenderer({
10893
+ onClose: () => setSubmitOpen(false),
10894
+ onSubmitted: () => {
10895
+ setSubmitOpen(false);
10896
+ loadData({ current: 1, pageSize });
10897
+ }
10898
+ }) : /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Empty, { description: "\u8BF7\u901A\u8FC7 submitRenderer \u63A5\u5165\u63D0\u4EA4\u6A21\u677F" })
10899
+ }
10900
+ )
10901
+ ] });
8739
10902
  };
8740
10903
 
8741
10904
  // src/templates/FormSubmitTemplate.tsx
8742
- var import_react58 = require("react");
8743
- var import_antd28 = require("antd");
8744
- var import_icons7 = require("@ant-design/icons");
8745
- var import_jsx_runtime84 = require("react/jsx-runtime");
10905
+ var import_react62 = require("react");
10906
+ var import_antd33 = require("antd");
10907
+ var import_icons12 = require("@ant-design/icons");
10908
+ var import_jsx_runtime90 = require("react/jsx-runtime");
8746
10909
  var pickFormInstanceId = (value) => {
8747
10910
  if (!value) return void 0;
8748
10911
  if (typeof value === "string") return value;
@@ -8759,22 +10922,22 @@ var SubmitSuccessCard = ({
8759
10922
  renderSuccess
8760
10923
  }) => {
8761
10924
  if (renderSuccess) {
8762
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_jsx_runtime84.Fragment, { children: renderSuccess(info) });
10925
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_jsx_runtime90.Fragment, { children: renderSuccess(info) });
8763
10926
  }
8764
- return /* @__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.jsxs)("div", { className: "flex flex-col items-center py-16 animate-[fadeIn_0.3s_ease-out,scaleIn_0.3s_ease-out]", children: [
8765
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_icons7.CheckCircleFilled, { className: "text-2xl text-green-500" }) }),
8766
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
8767
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("p", { className: "text-sm text-gray-500 mb-6", children: info.message || "\u5DF2\u6210\u529F\u521B\u5EFA\u4E00\u6761\u65B0\u8BB0\u5F55" }),
8768
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex gap-3", children: [
8769
- (mode === "stay" || mode === "redirect") && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_antd28.Button, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
8770
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_antd28.Button, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
10927
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "flex flex-col items-center py-16 animate-[fadeIn_0.3s_ease-out,scaleIn_0.3s_ease-out]", children: [
10928
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_icons12.CheckCircleFilled, { className: "text-2xl text-green-500" }) }),
10929
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
10930
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("p", { className: "text-sm text-gray-500 mb-6", children: info.message || "\u5DF2\u6210\u529F\u521B\u5EFA\u4E00\u6761\u65B0\u8BB0\u5F55" }),
10931
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "flex gap-3", children: [
10932
+ (mode === "stay" || mode === "redirect") && /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_antd33.Button, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
10933
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_antd33.Button, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
8771
10934
  ] }),
8772
- isRedirecting && /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "mt-6 w-48", children: [
8773
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
10935
+ isRedirecting && /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "mt-6 w-48", children: [
10936
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
8774
10937
  countdown,
8775
10938
  "\u79D2\u540E\u81EA\u52A8\u8DF3\u8F6C"
8776
10939
  ] }),
8777
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "h-1 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
10940
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "h-1 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8778
10941
  "div",
8779
10942
  {
8780
10943
  className: "h-full bg-blue-500 transition-all duration-1000",
@@ -8790,18 +10953,28 @@ var InnerFormContent = ({
8790
10953
  formType,
8791
10954
  submitSuccessMode,
8792
10955
  enableDraft,
10956
+ enableProcessPreview,
10957
+ enableSubmissionDepartmentSelect,
10958
+ departmentOptions,
8793
10959
  header,
8794
10960
  footer,
8795
10961
  beforeForm,
8796
10962
  afterForm,
10963
+ renderDepartmentSelector,
8797
10964
  renderForm,
8798
10965
  renderSuccess,
8799
- onSubmitSuccess
10966
+ onSubmitSuccess,
10967
+ inDrawer = false
8800
10968
  }) => {
8801
- const { validateAll, getFormData: getFormData2, resetForm, api } = useFormContext();
8802
- const [submitted, setSubmitted] = (0, import_react58.useState)(false);
8803
- const [successInfo, setSuccessInfo] = (0, import_react58.useState)(null);
8804
- const [submitting, setSubmitting] = (0, import_react58.useState)(false);
10969
+ const { validateAll, getFormData: getFormData2, setFieldValue, resetForm, api } = useFormContext();
10970
+ const [submitted, setSubmitted] = (0, import_react62.useState)(false);
10971
+ const [successInfo, setSuccessInfo] = (0, import_react62.useState)(null);
10972
+ const [submitting, setSubmitting] = (0, import_react62.useState)(false);
10973
+ const [departmentId, setDepartmentId] = (0, import_react62.useState)();
10974
+ const [previewOpen, setPreviewOpen] = (0, import_react62.useState)(false);
10975
+ const [previewLoading, setPreviewLoading] = (0, import_react62.useState)(false);
10976
+ const [previewRoutes, setPreviewRoutes] = (0, import_react62.useState)([]);
10977
+ const [pendingFormData, setPendingFormData] = (0, import_react62.useState)(null);
8805
10978
  const { hasDraft, draftTimestamp, saveDraft, restoreDraft, clearDraft } = useDraftStorage({
8806
10979
  appType: config.appType,
8807
10980
  formUuid: config.formUuid
@@ -8813,79 +10986,123 @@ var InnerFormContent = ({
8813
10986
  mode: submitSuccessMode === "continue" ? "stay" : submitSuccessMode,
8814
10987
  basePath: config.navigation?.basePath
8815
10988
  });
8816
- const handleSubmit = (0, import_react58.useCallback)(async () => {
10989
+ const performSubmit = (0, import_react62.useCallback)(
10990
+ async (formData) => {
10991
+ setSubmitting(true);
10992
+ try {
10993
+ const submitResponse = config.mode === "edit" && config.formInstanceId ? await api.updateFormData({
10994
+ appType: config.appType,
10995
+ formUuid: config.formUuid,
10996
+ formInstId: config.formInstanceId,
10997
+ formInstanceId: config.formInstanceId,
10998
+ updateFormDataJson: JSON.stringify(formData)
10999
+ }) : await api.submitFormData({
11000
+ appType: config.appType,
11001
+ formUuid: config.formUuid,
11002
+ data: formData,
11003
+ submissionDepartmentId: departmentId
11004
+ });
11005
+ const formInstId = pickFormInstanceId(submitResponse) || config.formInstanceId || `inst_${Date.now()}`;
11006
+ if (config.submit?.afterSubmit) {
11007
+ await config.submit.afterSubmit({
11008
+ formInstanceId: formInstId,
11009
+ data: formData,
11010
+ response: submitResponse
11011
+ });
11012
+ }
11013
+ if (enableDraft) {
11014
+ clearDraft();
11015
+ }
11016
+ onSubmitSuccess?.(formInstId);
11017
+ if (submitSuccessMode === "continue") {
11018
+ resetForm();
11019
+ } else {
11020
+ setSuccessInfo({ formInstanceId: formInstId });
11021
+ setSubmitted(true);
11022
+ handlePostSubmit(formInstId);
11023
+ }
11024
+ } catch (error) {
11025
+ console.error("[FormSubmitTemplate] Submit failed:", error);
11026
+ } finally {
11027
+ setSubmitting(false);
11028
+ }
11029
+ },
11030
+ [
11031
+ api,
11032
+ clearDraft,
11033
+ config,
11034
+ departmentId,
11035
+ enableDraft,
11036
+ handlePostSubmit,
11037
+ onSubmitSuccess,
11038
+ resetForm,
11039
+ submitSuccessMode
11040
+ ]
11041
+ );
11042
+ const prepareSubmit = (0, import_react62.useCallback)(async () => {
8817
11043
  const valid = await validateAll();
8818
11044
  if (!valid) return;
8819
- setSubmitting(true);
8820
- try {
8821
- const formData = getFormData2();
8822
- if (config.submit?.beforeSubmit) {
8823
- const shouldContinue = await config.submit.beforeSubmit(formData);
8824
- if (shouldContinue === false) {
8825
- setSubmitting(false);
8826
- return;
8827
- }
11045
+ const formData = getFormData2();
11046
+ if (config.submit?.beforeSubmit) {
11047
+ const shouldContinue = await config.submit.beforeSubmit(formData);
11048
+ if (shouldContinue === false) {
11049
+ return;
8828
11050
  }
8829
- const submitResponse = config.mode === "edit" && config.formInstanceId ? await api.updateFormData({
8830
- appType: config.appType,
8831
- formUuid: config.formUuid,
8832
- formInstId: config.formInstanceId,
8833
- formInstanceId: config.formInstanceId,
8834
- updateFormDataJson: JSON.stringify(formData)
8835
- }) : await api.submitFormData({
8836
- appType: config.appType,
8837
- formUuid: config.formUuid,
8838
- data: formData
8839
- });
8840
- const formInstId = pickFormInstanceId(submitResponse) || config.formInstanceId || `inst_${Date.now()}`;
8841
- if (config.submit?.afterSubmit) {
8842
- await config.submit.afterSubmit({
8843
- formInstanceId: formInstId,
11051
+ }
11052
+ if (formType === "process" && enableProcessPreview) {
11053
+ setPendingFormData(formData);
11054
+ setPreviewOpen(true);
11055
+ setPreviewLoading(true);
11056
+ try {
11057
+ const routes = await previewProcess(api.request, {
11058
+ appType: config.appType,
11059
+ formUuid: config.formUuid,
8844
11060
  data: formData,
8845
- response: submitResponse
11061
+ submissionDepartmentId: departmentId
8846
11062
  });
11063
+ setPreviewRoutes(routes);
11064
+ } catch (error) {
11065
+ console.error("[FormSubmitTemplate] Preview failed:", error);
11066
+ setPreviewRoutes([]);
11067
+ } finally {
11068
+ setPreviewLoading(false);
8847
11069
  }
8848
- if (enableDraft) {
8849
- clearDraft();
8850
- }
8851
- onSubmitSuccess?.(formInstId);
8852
- if (submitSuccessMode === "continue") {
8853
- resetForm();
8854
- } else {
8855
- setSuccessInfo({ formInstanceId: formInstId });
8856
- setSubmitted(true);
8857
- handlePostSubmit(formInstId);
8858
- }
8859
- } catch (error) {
8860
- console.error("[FormSubmitTemplate] Submit failed:", error);
8861
- } finally {
8862
- setSubmitting(false);
11070
+ return;
8863
11071
  }
11072
+ await performSubmit(formData);
8864
11073
  }, [
8865
11074
  validateAll,
8866
11075
  getFormData2,
8867
11076
  config,
8868
11077
  api,
8869
- enableDraft,
8870
- clearDraft,
8871
- onSubmitSuccess,
8872
- submitSuccessMode,
8873
- resetForm,
8874
- handlePostSubmit
11078
+ formType,
11079
+ enableProcessPreview,
11080
+ departmentId,
11081
+ performSubmit
8875
11082
  ]);
8876
- const handleSaveDraft = (0, import_react58.useCallback)(() => {
11083
+ const handlePreviewConfirm = (0, import_react62.useCallback)(async () => {
11084
+ const data = pendingFormData ?? getFormData2();
11085
+ setPreviewOpen(false);
11086
+ setPendingFormData(null);
11087
+ await performSubmit(data);
11088
+ }, [getFormData2, pendingFormData, performSubmit]);
11089
+ const handleSaveDraft = (0, import_react62.useCallback)(() => {
8877
11090
  const data = getFormData2();
8878
11091
  saveDraft(data);
8879
11092
  }, [getFormData2, saveDraft]);
8880
- const handleRestoreDraft = (0, import_react58.useCallback)(() => {
8881
- restoreDraft();
8882
- }, [restoreDraft]);
8883
- const handleContinue = (0, import_react58.useCallback)(() => {
11093
+ const handleRestoreDraft = (0, import_react62.useCallback)(() => {
11094
+ const data = restoreDraft();
11095
+ if (!data) return;
11096
+ Object.entries(data).forEach(([fieldId, value]) => {
11097
+ setFieldValue(fieldId, value);
11098
+ });
11099
+ }, [restoreDraft, setFieldValue]);
11100
+ const handleContinue = (0, import_react62.useCallback)(() => {
8884
11101
  setSubmitted(false);
8885
11102
  setSuccessInfo(null);
8886
11103
  resetForm();
8887
11104
  }, [resetForm]);
8888
- const handleViewDetail = (0, import_react58.useCallback)(() => {
11105
+ const handleViewDetail = (0, import_react62.useCallback)(() => {
8889
11106
  if (!successInfo) return;
8890
11107
  if (formType === "process") {
8891
11108
  navigateToProcessDetail(successInfo.formInstanceId);
@@ -8913,15 +11130,38 @@ var InnerFormContent = ({
8913
11130
  label: "\u63D0\u4EA4",
8914
11131
  type: "primary",
8915
11132
  loading: submitting,
8916
- onClick: handleSubmit
11133
+ onClick: prepareSubmit
8917
11134
  });
8918
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "min-h-screen bg-gray-50/50", children: [
8919
- /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: [
8920
- header || /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "mb-6", children: [
8921
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("h1", { className: "text-2xl font-bold text-gray-900", children: schema.formMeta.title }),
8922
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("p", { className: "text-sm text-gray-500 mt-1", children: "\u8BF7\u586B\u5199\u4EE5\u4E0B\u4FE1\u606F" })
8923
- ] }),
8924
- enableDraft && hasDraft && !submitted && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11135
+ const departmentSelector = formType === "process" && enableSubmissionDepartmentSelect ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "mb-5 rounded-lg border border-ant-border-secondary bg-ant-bg-elevated px-4 py-3", children: [
11136
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u63D0\u4EA4\u90E8\u95E8" }),
11137
+ renderDepartmentSelector ? renderDepartmentSelector({
11138
+ value: departmentId,
11139
+ onChange: setDepartmentId,
11140
+ options: departmentOptions
11141
+ }) : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11142
+ import_antd33.Select,
11143
+ {
11144
+ allowClear: true,
11145
+ className: "w-full",
11146
+ placeholder: "\u8BF7\u9009\u62E9\u672C\u6B21\u63D0\u4EA4\u6D41\u7A0B\u6240\u5C5E\u90E8\u95E8",
11147
+ value: departmentId,
11148
+ options: departmentOptions,
11149
+ onChange: setDepartmentId
11150
+ }
11151
+ )
11152
+ ] }) : null;
11153
+ const actionsNode = !submitted ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(StickyActionBar, { actions, inDrawer }) : null;
11154
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(RuntimePageShell, { actions: actionsNode, inDrawer, children: [
11155
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "space-y-6", children: [
11156
+ header || /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11157
+ SummaryPanel,
11158
+ {
11159
+ title: schema.formMeta.title,
11160
+ eyebrow: formType === "process" ? "\u6D41\u7A0B\u53D1\u8D77" : "\u6570\u636E\u63D0\u4EA4",
11161
+ status: formType === "process" ? { label: "\u5F85\u63D0\u4EA4", tone: "brand" } : void 0
11162
+ }
11163
+ ),
11164
+ enableDraft && hasDraft && !submitted && /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8925
11165
  DraftManager,
8926
11166
  {
8927
11167
  hasDraft,
@@ -8930,11 +11170,12 @@ var InnerFormContent = ({
8930
11170
  onDiscard: clearDraft
8931
11171
  }
8932
11172
  ) }),
8933
- !submitted ? /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6 animate-[fadeIn_0.2s_ease-out]", children: [
11173
+ !submitted ? /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: [
11174
+ departmentSelector,
8934
11175
  beforeForm,
8935
- renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormRenderer, { columns: 2 }),
11176
+ renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(FormRenderer, { columns: 2 }),
8936
11177
  afterForm
8937
- ] }) : successInfo && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11178
+ ] }) : successInfo && /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8938
11179
  SubmitSuccessCard,
8939
11180
  {
8940
11181
  info: successInfo,
@@ -8948,7 +11189,16 @@ var InnerFormContent = ({
8948
11189
  ),
8949
11190
  footer
8950
11191
  ] }),
8951
- !submitted && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormActionBar, { actions, position: "bottom-fixed" })
11192
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11193
+ ProcessPreview,
11194
+ {
11195
+ open: previewOpen,
11196
+ routes: previewRoutes,
11197
+ loading: previewLoading,
11198
+ onClose: () => setPreviewOpen(false),
11199
+ onConfirm: handlePreviewConfirm
11200
+ }
11201
+ )
8952
11202
  ] });
8953
11203
  };
8954
11204
  var FormSubmitTemplate = ({
@@ -8957,15 +11207,20 @@ var FormSubmitTemplate = ({
8957
11207
  formType = "form",
8958
11208
  submitSuccessMode = "redirect",
8959
11209
  enableDraft = false,
11210
+ enableProcessPreview = false,
11211
+ enableSubmissionDepartmentSelect = false,
11212
+ departmentOptions = [],
8960
11213
  header,
8961
11214
  footer,
8962
11215
  beforeForm,
8963
11216
  afterForm,
11217
+ renderDepartmentSelector,
8964
11218
  renderForm,
8965
11219
  renderSuccess,
8966
- onSubmitSuccess
11220
+ onSubmitSuccess,
11221
+ inDrawer = false
8967
11222
  }) => {
8968
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormProvider, { schema, config, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11223
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(FormProvider, { schema, config, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8969
11224
  InnerFormContent,
8970
11225
  {
8971
11226
  schema,
@@ -8973,83 +11228,95 @@ var FormSubmitTemplate = ({
8973
11228
  formType,
8974
11229
  submitSuccessMode,
8975
11230
  enableDraft,
11231
+ enableProcessPreview,
11232
+ enableSubmissionDepartmentSelect,
11233
+ departmentOptions,
8976
11234
  header,
8977
11235
  footer,
8978
11236
  beforeForm,
8979
11237
  afterForm,
11238
+ renderDepartmentSelector,
8980
11239
  renderForm,
8981
11240
  renderSuccess,
8982
- onSubmitSuccess
11241
+ onSubmitSuccess,
11242
+ inDrawer
8983
11243
  }
8984
11244
  ) });
8985
11245
  };
8986
11246
 
8987
11247
  // src/templates/FormDetailTemplate.tsx
8988
- var import_react59 = require("react");
11248
+ var import_react63 = require("react");
8989
11249
 
8990
11250
  // src/templates/PageSkeleton.tsx
8991
- var import_antd29 = require("antd");
8992
- var import_jsx_runtime85 = require("react/jsx-runtime");
8993
- var CardSkeleton = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
8994
- var SummaryCardSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(CardSkeleton, { children: [
8995
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-start justify-between", children: [
8996
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex-1", children: [
8997
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
8998
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "mt-2", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }) })
11251
+ var import_antd34 = require("antd");
11252
+ var import_jsx_runtime91 = require("react/jsx-runtime");
11253
+ var CardSkeleton = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
11254
+ var SummaryCardSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(CardSkeleton, { children: [
11255
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex items-start justify-between", children: [
11256
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex-1", children: [
11257
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
11258
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "mt-2", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }) })
8999
11259
  ] }),
9000
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
11260
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
9001
11261
  ] }),
9002
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex items-center gap-3 mt-4", children: [
9003
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Avatar, { active: true, size: "small" }),
9004
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "small", style: { width: 120 } })
11262
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex items-center gap-3 mt-4", children: [
11263
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Avatar, { active: true, size: "small" }),
11264
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 120 } })
9005
11265
  ] })
9006
11266
  ] });
9007
- var FormGridSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(CardSkeleton, { children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "space-y-2", children: [
9008
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }),
9009
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, block: true, style: { width: "100%" } })
11267
+ var FormGridSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(CardSkeleton, { children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-2", children: [
11268
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }),
11269
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, block: true, style: { width: "100%" } })
9010
11270
  ] }, i)) }) });
9011
- var ActionBarSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime85.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_runtime85.jsxs)("div", { className: "flex items-center justify-end gap-3", children: [
9012
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Button, { active: true, style: { width: 80 } }),
9013
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Button, { active: true, style: { width: 80 } })
11271
+ var ActionBarSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime91.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_runtime91.jsxs)("div", { className: "flex items-center justify-end gap-3", children: [
11272
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Button, { active: true, style: { width: 80 } }),
11273
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Button, { active: true, style: { width: 80 } })
9014
11274
  ] }) });
9015
- var TimelineSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)(CardSkeleton, { children: [
9016
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
9017
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex gap-4", children: [
9018
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "flex flex-col items-center", children: [
9019
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
9020
- i < 2 && /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
11275
+ var TimelineSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(CardSkeleton, { children: [
11276
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
11277
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex gap-4", children: [
11278
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex flex-col items-center", children: [
11279
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
11280
+ i < 2 && /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
9021
11281
  ] }),
9022
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)("div", { className: "flex-1 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton, { active: true, paragraph: { rows: 1 }, title: { width: "60%" } }) })
11282
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "flex-1 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton, { active: true, paragraph: { rows: 1 }, title: { width: "60%" } }) })
9023
11283
  ] }, i)) })
9024
11284
  ] });
9025
11285
  var PageSkeleton = ({ type }) => {
9026
11286
  if (type === "submit") {
9027
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "space-y-6", children: [
9028
- /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "space-y-2", children: [
9029
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
9030
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Input, { active: true, size: "small", style: { width: 300 } })
11287
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-6", children: [
11288
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-2", children: [
11289
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
11290
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 300 } })
9031
11291
  ] }),
9032
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormGridSkeleton, {}),
9033
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ActionBarSkeleton, {})
11292
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FormGridSkeleton, {}),
11293
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ActionBarSkeleton, {})
9034
11294
  ] });
9035
11295
  }
9036
11296
  if (type === "detail") {
9037
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "space-y-6", children: [
9038
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SummaryCardSkeleton, {}),
9039
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormGridSkeleton, {}),
9040
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ActionBarSkeleton, {})
11297
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-6", children: [
11298
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(SummaryCardSkeleton, {}),
11299
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FormGridSkeleton, {}),
11300
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ActionBarSkeleton, {})
9041
11301
  ] });
9042
11302
  }
9043
- return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: "space-y-6", children: [
9044
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(SummaryCardSkeleton, {}),
9045
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormGridSkeleton, {}),
9046
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(TimelineSkeleton, {}),
9047
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ActionBarSkeleton, {})
11303
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-6", children: [
11304
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(SummaryCardSkeleton, {}),
11305
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FormGridSkeleton, {}),
11306
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(TimelineSkeleton, {}),
11307
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ActionBarSkeleton, {})
9048
11308
  ] });
9049
11309
  };
9050
11310
 
9051
11311
  // src/templates/FormDetailTemplate.tsx
9052
- var import_jsx_runtime86 = require("react/jsx-runtime");
11312
+ var import_jsx_runtime92 = require("react/jsx-runtime");
11313
+ function FormDataBridge({
11314
+ formDataRef
11315
+ }) {
11316
+ const { getFormData: getFormData2 } = useFormContext();
11317
+ formDataRef.current = getFormData2;
11318
+ return null;
11319
+ }
9053
11320
  var InnerDetailContent = ({
9054
11321
  schema,
9055
11322
  formUuid,
@@ -9063,9 +11330,12 @@ var InnerDetailContent = ({
9063
11330
  renderSummary,
9064
11331
  renderActions,
9065
11332
  onDelete,
9066
- onSave
11333
+ onSave,
11334
+ inDrawer = false
9067
11335
  }) => {
9068
- const fieldIds = (0, import_react59.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11336
+ const formDataRef = (0, import_react63.useRef)(void 0);
11337
+ const [accessDenied, setAccessDenied] = (0, import_react63.useState)(false);
11338
+ const fieldIds = (0, import_react63.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
9069
11339
  const {
9070
11340
  loading,
9071
11341
  mode,
@@ -9079,7 +11349,13 @@ var InnerDetailContent = ({
9079
11349
  canEdit,
9080
11350
  canDelete,
9081
11351
  canViewChangeRecords
9082
- } = useFormDetail({ formUuid, appType, formInstanceId, fieldIds });
11352
+ } = useFormDetail({
11353
+ formUuid,
11354
+ appType,
11355
+ formInstanceId,
11356
+ fieldIds,
11357
+ onPermissionDenied: () => setAccessDenied(true)
11358
+ });
9083
11359
  const {
9084
11360
  records,
9085
11361
  loading: recordsLoading,
@@ -9092,20 +11368,21 @@ var InnerDetailContent = ({
9092
11368
  formInstanceId,
9093
11369
  autoLoad: enableChangeRecords && canViewChangeRecords
9094
11370
  });
9095
- const handleSave = (0, import_react59.useCallback)(async () => {
9096
- if (!formData) return;
9097
- const success = await saveChanges(formData);
11371
+ const handleSave = (0, import_react63.useCallback)(async () => {
11372
+ const values = formDataRef.current?.() ?? formData;
11373
+ if (!values) return;
11374
+ const success = await saveChanges(values);
9098
11375
  if (success) {
9099
- onSave?.(formData);
11376
+ onSave?.(values);
9100
11377
  }
9101
11378
  }, [formData, saveChanges, onSave]);
9102
- const handleDelete = (0, import_react59.useCallback)(async () => {
11379
+ const handleDelete = (0, import_react63.useCallback)(async () => {
9103
11380
  const success = await deleteInstance();
9104
11381
  if (success) {
9105
11382
  onDelete?.();
9106
11383
  }
9107
11384
  }, [deleteInstance, onDelete]);
9108
- const handleCancel = (0, import_react59.useCallback)(() => {
11385
+ const handleCancel = (0, import_react63.useCallback)(() => {
9109
11386
  switchToReadonly();
9110
11387
  }, [switchToReadonly]);
9111
11388
  const readonlyActions = [];
@@ -9142,41 +11419,44 @@ var InnerDetailContent = ({
9142
11419
  }
9143
11420
  };
9144
11421
  if (loading) {
9145
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(PageSkeleton, { type: "detail" }) }) });
11422
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "min-h-screen bg-ant-bg-layout", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(PageSkeleton, { type: "detail" }) }) });
9146
11423
  }
9147
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "min-h-screen bg-gray-50/50", children: [
9148
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
9149
- header,
9150
- renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9151
- FormSummaryCard,
9152
- {
9153
- title: schema.formMeta.title,
9154
- formInstanceId,
9155
- creator: instanceInfo?.creator ? {
9156
- name: instanceInfo.creator.name,
9157
- avatar: instanceInfo.creator.avatar,
9158
- department: instanceInfo.creator.department
9159
- } : void 0,
9160
- createdAt: instanceInfo?.createdAt,
9161
- status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
9162
- }
9163
- ),
9164
- mode === "edit" && /* @__PURE__ */ (0, import_jsx_runtime86.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" }),
9165
- /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FormRenderer, { columns: 2 }) }) }),
9166
- enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9167
- ChangeRecords,
9168
- {
9169
- records,
9170
- loading: recordsLoading,
9171
- hasMore,
9172
- onLoadMore: loadMore,
9173
- onExpand: refreshRecords
9174
- }
9175
- ),
9176
- footer
11424
+ const actionsNode = currentActions.length > 0 ? renderActions ? renderActions(currentActions) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(StickyActionBar, { actions: currentActions, inDrawer }) : null;
11425
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(RuntimePageShell, { actions: actionsNode, accessDenied, inDrawer, children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "space-y-6", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)("div", { children: [
11426
+ header,
11427
+ renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
11428
+ SummaryPanel,
11429
+ {
11430
+ title: instanceInfo?.title || formData?.instanceTitle || schema.formMeta.title,
11431
+ eyebrow: `\u6570\u636E\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
11432
+ creator: instanceInfo?.creator ? {
11433
+ name: instanceInfo.creator.name,
11434
+ avatar: instanceInfo.creator.avatar,
11435
+ department: instanceInfo.creator.department
11436
+ } : void 0,
11437
+ createdAt: instanceInfo?.createdAt,
11438
+ status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
11439
+ }
11440
+ ),
11441
+ mode === "edit" && /* @__PURE__ */ (0, import_jsx_runtime92.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" }),
11442
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "mt-6 rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
11443
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FormDataBridge, { formDataRef }),
11444
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FormRenderer, { columns: 2 })
9177
11445
  ] }) }),
9178
- currentActions.length > 0 && (renderActions ? /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_jsx_runtime86.Fragment, { children: renderActions(currentActions) }) : /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FormActionBar, { position: "bottom-fixed", actions: currentActions }))
9179
- ] });
11446
+ enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
11447
+ RecordChangePanel,
11448
+ {
11449
+ records,
11450
+ loading: recordsLoading,
11451
+ total: records.length,
11452
+ hasMore,
11453
+ onLoadMore: loadMore,
11454
+ onRefresh: refreshRecords,
11455
+ onExpand: refreshRecords
11456
+ }
11457
+ ) }),
11458
+ footer
11459
+ ] }) }) });
9180
11460
  };
9181
11461
  var FormDetailTemplate = (props) => {
9182
11462
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -9186,13 +11466,13 @@ var FormDetailTemplate = (props) => {
9186
11466
  appType,
9187
11467
  formInstanceId
9188
11468
  };
9189
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(InnerDetailContent, { ...props }) });
11469
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(InnerDetailContent, { ...props }) });
9190
11470
  };
9191
11471
 
9192
11472
  // src/templates/ProcessDetailTemplate.tsx
9193
- var import_react60 = require("react");
9194
- var import_jsx_runtime87 = require("react/jsx-runtime");
9195
- function FormDataBridge({
11473
+ var import_react64 = require("react");
11474
+ var import_jsx_runtime93 = require("react/jsx-runtime");
11475
+ function FormDataBridge2({
9196
11476
  formDataRef
9197
11477
  }) {
9198
11478
  const { getFormData: getFormData2 } = useFormContext();
@@ -9207,12 +11487,16 @@ var InnerProcessContent = ({
9207
11487
  header,
9208
11488
  renderTimeline,
9209
11489
  renderActions,
11490
+ renderTransferSelector,
11491
+ renderReturnNodeLabel,
11492
+ renderActionModalExtra,
9210
11493
  beforeForm,
9211
11494
  afterForm,
9212
- onActionComplete
11495
+ onActionComplete,
11496
+ inDrawer = false
9213
11497
  }) => {
9214
- const formDataRef = (0, import_react60.useRef)(void 0);
9215
- const fieldIds = (0, import_react60.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11498
+ const formDataRef = (0, import_react64.useRef)(void 0);
11499
+ const fieldIds = (0, import_react64.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
9216
11500
  const {
9217
11501
  loading,
9218
11502
  processInfo,
@@ -9220,6 +11504,7 @@ var InnerProcessContent = ({
9220
11504
  currentTask,
9221
11505
  progressList,
9222
11506
  formData,
11507
+ instanceInfo,
9223
11508
  isApprover,
9224
11509
  activeActions,
9225
11510
  fieldBehaviors,
@@ -9230,7 +11515,18 @@ var InnerProcessContent = ({
9230
11515
  switchToReadonly,
9231
11516
  refreshProgress
9232
11517
  } = useProcessDetail({ formUuid, appType, formInstanceId, fieldIds });
9233
- const { approve, reject, withdraw, save, resubmit } = useApprovalActions({
11518
+ const {
11519
+ approve,
11520
+ reject,
11521
+ transfer,
11522
+ returnTo,
11523
+ withdraw,
11524
+ save,
11525
+ resubmit,
11526
+ callbackTask,
11527
+ returnableNodes,
11528
+ loadReturnableNodes
11529
+ } = useApprovalActions({
9234
11530
  formInstanceId,
9235
11531
  formUuid,
9236
11532
  appType,
@@ -9239,72 +11535,102 @@ var InnerProcessContent = ({
9239
11535
  onActionComplete?.(action);
9240
11536
  await refreshProgress();
9241
11537
  },
9242
- getFormValues: () => formDataRef.current?.() ?? {}
11538
+ getFormValues: () => formDataRef.current?.() ?? formData ?? {}
9243
11539
  });
9244
- const handleApprove = (0, import_react60.useCallback)(
11540
+ const handleApprove = (0, import_react64.useCallback)(
9245
11541
  async (comments) => {
9246
11542
  await approve(comments);
9247
11543
  },
9248
11544
  [approve]
9249
11545
  );
9250
- const handleReject = (0, import_react60.useCallback)(
11546
+ const handleReject = (0, import_react64.useCallback)(
9251
11547
  async (comments) => {
9252
11548
  await reject(comments);
9253
11549
  },
9254
11550
  [reject]
9255
11551
  );
9256
- const handleWithdraw = (0, import_react60.useCallback)(
11552
+ const handleTransfer = (0, import_react64.useCallback)(
11553
+ async (userId, reason) => {
11554
+ await transfer(userId, reason);
11555
+ },
11556
+ [transfer]
11557
+ );
11558
+ const handleReturn = (0, import_react64.useCallback)(
11559
+ async (nodeId, reason) => {
11560
+ await returnTo(nodeId, reason);
11561
+ },
11562
+ [returnTo]
11563
+ );
11564
+ const handleWithdraw = (0, import_react64.useCallback)(
9257
11565
  async (reason) => {
9258
11566
  await withdraw(reason);
9259
11567
  },
9260
11568
  [withdraw]
9261
11569
  );
9262
- const handleSave = (0, import_react60.useCallback)(async () => {
11570
+ const handleSave = (0, import_react64.useCallback)(async () => {
9263
11571
  await save();
9264
11572
  }, [save]);
9265
- const handleResubmit = (0, import_react60.useCallback)(async () => {
9266
- await resubmit();
9267
- }, [resubmit]);
9268
- const buildActions = () => {
9269
- const actions = [];
9270
- if (isApprover && activeActions.length > 0) {
9271
- return [];
9272
- }
11573
+ const handleResubmit = (0, import_react64.useCallback)(
11574
+ async (comments) => {
11575
+ await resubmit(comments);
11576
+ },
11577
+ [resubmit]
11578
+ );
11579
+ const handleCallback = (0, import_react64.useCallback)(async () => {
11580
+ await callbackTask();
11581
+ }, [callbackTask]);
11582
+ const bottomActions = (0, import_react64.useMemo)(() => {
11583
+ if (isApprover && activeActions.length > 0) return [];
9273
11584
  if (isOriginatorReturn) {
9274
11585
  if (mode === "readonly") {
9275
- actions.push({
9276
- key: "edit",
9277
- label: "\u7F16\u8F91",
9278
- type: "primary",
9279
- onClick: switchToEdit
9280
- });
9281
- } else {
9282
- actions.push({
11586
+ return [
11587
+ {
11588
+ key: "edit",
11589
+ label: "\u7F16\u8F91",
11590
+ type: "primary",
11591
+ onClick: switchToEdit
11592
+ }
11593
+ ];
11594
+ }
11595
+ return [
11596
+ {
9283
11597
  key: "cancel",
9284
11598
  label: "\u53D6\u6D88",
9285
11599
  type: "default",
9286
- onClick: switchToReadonly
9287
- });
9288
- actions.push({
11600
+ onClick: switchToReadonly,
11601
+ placement: "left"
11602
+ },
11603
+ {
9289
11604
  key: "resubmit",
9290
11605
  label: "\u91CD\u65B0\u63D0\u4EA4",
9291
11606
  type: "primary",
9292
- onClick: handleResubmit
9293
- });
9294
- }
9295
- return actions;
11607
+ onClick: () => handleResubmit()
11608
+ }
11609
+ ];
9296
11610
  }
9297
11611
  if (canWithdraw) {
9298
- actions.push({
9299
- key: "withdraw",
9300
- label: "\u64A4\u9500",
9301
- type: "default",
9302
- onClick: () => handleWithdraw(),
9303
- confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u786E\u8BA4\u8981\u64A4\u9500\u6B64\u6D41\u7A0B\u5417\uFF1F" }
9304
- });
11612
+ return [
11613
+ {
11614
+ key: "withdraw",
11615
+ label: "\u64A4\u9500",
11616
+ type: "danger",
11617
+ onClick: () => handleWithdraw(),
11618
+ confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u64A4\u9500\u540E\u6D41\u7A0B\u5C06\u7EC8\u6B62\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F" }
11619
+ }
11620
+ ];
9305
11621
  }
9306
- return actions;
9307
- };
11622
+ return [];
11623
+ }, [
11624
+ activeActions.length,
11625
+ canWithdraw,
11626
+ handleResubmit,
11627
+ handleWithdraw,
11628
+ isApprover,
11629
+ isOriginatorReturn,
11630
+ mode,
11631
+ switchToEdit,
11632
+ switchToReadonly
11633
+ ]);
9308
11634
  const formConfig = {
9309
11635
  mode: mode === "edit" ? "edit" : "readonly",
9310
11636
  formUuid,
@@ -9316,50 +11642,68 @@ var InnerProcessContent = ({
9316
11642
  }
9317
11643
  };
9318
11644
  if (loading) {
9319
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(PageSkeleton, { type: "process" }) }) });
11645
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "min-h-screen bg-ant-bg-layout", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "mx-auto max-w-4xl px-6 py-8 pb-24", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(PageSkeleton, { type: "process" }) }) });
9320
11646
  }
9321
- const bottomActions = buildActions();
9322
11647
  const showApprovalActions = isApprover && activeActions.length > 0;
9323
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "min-h-screen bg-gray-50/50", children: [
9324
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
9325
- header,
9326
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
9327
- FormSummaryCard,
9328
- {
9329
- title: schema.formMeta.title,
9330
- formInstanceId,
9331
- creator: processInfo?.originatorName ? {
9332
- name: processInfo.originatorName,
9333
- department: processInfo.originatorDepartment
9334
- } : void 0,
9335
- createdAt: processInfo?.createdAt,
9336
- status: processStatus ? PROCESS_STATUS_META[processStatus] : void 0
9337
- }
9338
- ),
9339
- beforeForm,
9340
- mode === "edit" && /* @__PURE__ */ (0, import_jsx_runtime87.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" }),
9341
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
9342
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(FormDataBridge, { formDataRef }),
9343
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(FormRenderer, { columns: 2 })
9344
- ] }) }),
9345
- afterForm,
9346
- /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
9347
- /* @__PURE__ */ (0, import_jsx_runtime87.jsx)("h3", { className: "text-lg font-semibold text-gray-900 mb-4", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
9348
- renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(ApprovalTimeline, { tasks: progressList, showRemarks: true })
9349
- ] })
9350
- ] }) }),
9351
- showApprovalActions && (renderActions ? /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_jsx_runtime87.Fragment, { children: renderActions(activeActions) }) : /* @__PURE__ */ (0, import_jsx_runtime87.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_runtime87.jsx)("div", { className: "max-w-4xl mx-auto flex items-center justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
9352
- ApprovalActions,
11648
+ const actionsNode = showApprovalActions ? renderActions ? renderActions(activeActions) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
11649
+ ApprovalActionBar,
11650
+ {
11651
+ actions: activeActions,
11652
+ onApprove: handleApprove,
11653
+ onReject: handleReject,
11654
+ onTransfer: handleTransfer,
11655
+ onReturn: handleReturn,
11656
+ onWithdraw: handleWithdraw,
11657
+ onSave: handleSave,
11658
+ onResubmit: handleResubmit,
11659
+ onCallback: handleCallback,
11660
+ returnableNodes,
11661
+ onLoadReturnableNodes: loadReturnableNodes,
11662
+ renderTransferSelector,
11663
+ renderReturnNodeLabel,
11664
+ renderActionModalExtra,
11665
+ inDrawer
11666
+ }
11667
+ ) : bottomActions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(StickyActionBar, { actions: bottomActions, inDrawer }) : null;
11668
+ const statusMeta = processStatus ? PROCESS_STATUS_META[processStatus] : void 0;
11669
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(RuntimePageShell, { actions: actionsNode, inDrawer, children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "space-y-6", children: [
11670
+ header,
11671
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
11672
+ SummaryPanel,
9353
11673
  {
9354
- actions: activeActions,
9355
- onApprove: handleApprove,
9356
- onReject: handleReject,
9357
- onWithdraw: handleWithdraw,
9358
- onSave: handleSave
9359
- }
9360
- ) }) })),
9361
- !showApprovalActions && bottomActions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(FormActionBar, { position: "bottom-fixed", actions: bottomActions })
9362
- ] });
11674
+ title: processInfo?.title || instanceInfo?.title || schema.formMeta.title,
11675
+ eyebrow: `\u6D41\u7A0B\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
11676
+ creator: processInfo?.originatorName ? {
11677
+ name: processInfo.originatorName,
11678
+ department: processInfo.originatorDepartment
11679
+ } : void 0,
11680
+ createdAt: processInfo?.createdAt,
11681
+ status: statusMeta,
11682
+ metaItems: [
11683
+ { key: "currentTask", label: "\u5F53\u524D\u8282\u70B9", value: currentTask?.nodeName || "\u65E0" },
11684
+ {
11685
+ key: "processStatus",
11686
+ label: "\u5B9E\u4F8B\u72B6\u6001",
11687
+ value: statusMeta?.label || processStatus || "-"
11688
+ }
11689
+ ]
11690
+ }
11691
+ ),
11692
+ beforeForm,
11693
+ mode === "edit" && /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "rounded-lg border border-blue-200 bg-blue-50 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" }),
11694
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
11695
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FormDataBridge2, { formDataRef }),
11696
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FormRenderer, { columns: 2 })
11697
+ ] }) }),
11698
+ afterForm,
11699
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: [
11700
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("div", { className: "mb-4 flex items-center justify-between gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { children: [
11701
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "text-base font-semibold text-ant-color-text", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
11702
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("p", { className: "mt-1 text-xs text-ant-color-text-tertiary", children: "\u8282\u70B9\u3001\u5BA1\u6279\u4EBA\u3001\u5904\u7406\u610F\u89C1\u548C\u7B49\u5F85\u72B6\u6001" })
11703
+ ] }) }),
11704
+ renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(ApprovalTimeline, { tasks: progressList, showRemarks: true, showApproverInfo: true })
11705
+ ] })
11706
+ ] }) });
9363
11707
  };
9364
11708
  var ProcessDetailTemplate = (props) => {
9365
11709
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -9369,11 +11713,12 @@ var ProcessDetailTemplate = (props) => {
9369
11713
  appType,
9370
11714
  formInstanceId
9371
11715
  };
9372
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(InnerProcessContent, { ...props }) });
11716
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(InnerProcessContent, { ...props }) });
9373
11717
  };
9374
11718
  // Annotate the CommonJS export names for ESM import in node:
9375
11719
  0 && (module.exports = {
9376
11720
  AddressField,
11721
+ ApprovalActionBar,
9377
11722
  ApprovalActions,
9378
11723
  ApprovalTimeline,
9379
11724
  AssociationFormField,
@@ -9384,6 +11729,7 @@ var ProcessDetailTemplate = (props) => {
9384
11729
  CheckboxField,
9385
11730
  ComponentRegistryContext,
9386
11731
  ComponentRegistryProvider,
11732
+ DataManagementList,
9387
11733
  DateField,
9388
11734
  DepartmentSelectField,
9389
11735
  DigitalSignatureField,
@@ -9415,34 +11761,58 @@ var ProcessDetailTemplate = (props) => {
9415
11761
  ProcessDetailTemplate,
9416
11762
  ProcessPreview,
9417
11763
  RadioField,
11764
+ RecordChangePanel,
11765
+ RuntimePageShell,
9418
11766
  SelectField,
9419
11767
  SerialNumberField,
11768
+ StickyActionBar,
9420
11769
  SubFormField,
11770
+ SummaryPanel,
9421
11771
  TASK_STATUS_META,
9422
11772
  TextAreaField,
9423
11773
  TextField,
9424
11774
  TextareaField,
9425
11775
  UserSelectField,
11776
+ advancedSearchDataManagement,
11777
+ batchApproveDataManagementRows,
11778
+ buildFilterPayload,
9426
11779
  checkUserApproval,
9427
11780
  createFormRuntimeApi,
9428
11781
  defaultComponentRegistry,
9429
11782
  defineFormSchema,
11783
+ deleteDataManagementRows,
9430
11784
  deleteFormData,
9431
11785
  evaluateEffects,
11786
+ exportDataManagementRows,
9432
11787
  extractFormValues,
9433
11788
  getChangeRecords,
11789
+ getDataManagementConfig,
11790
+ getDataManagementSchema,
11791
+ getDataManagementTransferRecords,
9434
11792
  getFormData,
9435
11793
  getProcessBasic,
9436
11794
  getProcessDefinition,
9437
11795
  getProcessProgress,
9438
11796
  getReturnableNodes,
11797
+ getSystemFieldsForFormType,
9439
11798
  getViewPermission,
9440
11799
  handleApproval,
11800
+ hasViewOperation,
11801
+ hasViewPermission,
11802
+ importDataManagementRows,
11803
+ importPreviewDataManagementRows,
11804
+ normalizeColumnConfig,
11805
+ normalizeDataManagementFields,
11806
+ normalizeDataManagementList,
11807
+ normalizeFieldBehaviors,
11808
+ normalizeOperation,
9441
11809
  previewProcess,
9442
11810
  resubmitTask,
9443
11811
  returnTask,
11812
+ saveDataManagementConfig,
9444
11813
  saveTask,
9445
11814
  transferTask,
11815
+ triggerCallbackTask,
9446
11816
  useApprovalActions,
9447
11817
  useChangeRecords,
9448
11818
  useComponent,