sy-form-components 0.2.6 → 0.2.8

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,
@@ -7869,6 +8229,16 @@ function useApprovalActions(options) {
7869
8229
 
7870
8230
  // src/hooks/useChangeRecords.ts
7871
8231
  var import_react52 = require("react");
8232
+ var normalizeChangeRecordList = (value) => {
8233
+ const body = value?.data ?? value?.result ?? value ?? {};
8234
+ const records = body.records ?? body.data ?? body.list ?? body.items ?? [];
8235
+ return {
8236
+ records: Array.isArray(records) ? records : [],
8237
+ total: Number(body.total ?? body.totalCount ?? body.count ?? records.length) || 0,
8238
+ page: Number(body.page ?? body.currentPage ?? 1) || 1,
8239
+ pageSize: Number(body.pageSize ?? body.limit ?? 20) || 20
8240
+ };
8241
+ };
7872
8242
  function useChangeRecords(options) {
7873
8243
  const { formUuid, appType, formInstanceId, pageSize = 20, autoLoad = true } = options;
7874
8244
  const { api } = useFormContext();
@@ -7897,13 +8267,14 @@ function useChangeRecords(options) {
7897
8267
  pageSize
7898
8268
  });
7899
8269
  if (!mountedRef.current) return;
8270
+ const normalized = normalizeChangeRecordList(result);
7900
8271
  if (append) {
7901
- setRecords((prev) => [...prev, ...result.records]);
8272
+ setRecords((prev) => [...prev, ...normalized.records]);
7902
8273
  } else {
7903
- setRecords(result.records);
8274
+ setRecords(normalized.records);
7904
8275
  }
7905
- setTotal(result.total);
7906
- setPage(pageNum);
8276
+ setTotal(normalized.total);
8277
+ setPage(normalized.page || pageNum);
7907
8278
  } catch (error) {
7908
8279
  console.error("[useChangeRecords] Failed to load change records:", error);
7909
8280
  } finally {
@@ -7919,7 +8290,8 @@ function useChangeRecords(options) {
7919
8290
  fetchRecords(1, false);
7920
8291
  }
7921
8292
  }, [autoLoad, fetchRecords]);
7922
- const hasMore = records.length < total;
8293
+ const safeRecords = Array.isArray(records) ? records : [];
8294
+ const hasMore = safeRecords.length < total;
7923
8295
  const loadMore = (0, import_react52.useCallback)(async () => {
7924
8296
  if (!hasMore || loading) return;
7925
8297
  await fetchRecords(page + 1, true);
@@ -7931,7 +8303,7 @@ function useChangeRecords(options) {
7931
8303
  await fetchRecords(1, false);
7932
8304
  }, [fetchRecords]);
7933
8305
  return {
7934
- records,
8306
+ records: safeRecords,
7935
8307
  loading,
7936
8308
  total,
7937
8309
  page,
@@ -8227,178 +8599,814 @@ var FormSummaryCard = ({
8227
8599
  ] });
8228
8600
  };
8229
8601
 
8230
- // src/modules/ChangeRecords.tsx
8602
+ // src/modules/RecordChangePanel.tsx
8231
8603
  var import_react55 = require("react");
8232
8604
  var import_antd23 = require("antd");
8233
8605
  var import_icons3 = require("@ant-design/icons");
8234
8606
  var import_jsx_runtime78 = require("react/jsx-runtime");
8235
- var ChangeRecords = ({
8607
+ var sourceLabels = {
8608
+ frontend: "\u524D\u7AEF",
8609
+ integration: "\u96C6\u6210",
8610
+ automation: "\u81EA\u52A8\u5316",
8611
+ import: "\u5BFC\u5165"
8612
+ };
8613
+ var typeLabels = {
8614
+ create: "\u65B0\u589E",
8615
+ update: "\u4FEE\u6539",
8616
+ delete: "\u5220\u9664"
8617
+ };
8618
+ function formatValue(value) {
8619
+ if (value === null || value === void 0 || value === "")
8620
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-ant-text-tertiary", children: "\u7A7A" });
8621
+ if (Array.isArray(value)) {
8622
+ 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(
8623
+ typeof item === "object" ? item.label || item.value || JSON.stringify(item) : item
8624
+ ) }, `${index}-${String(item)}`)) });
8625
+ }
8626
+ if (typeof value === "object") {
8627
+ const label = value.label ?? value.value;
8628
+ return label ? String(label) : /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("code", { className: "text-xs", children: JSON.stringify(value) });
8629
+ }
8630
+ return String(value);
8631
+ }
8632
+ function getInitial(name) {
8633
+ return String(name || "?").trim().slice(0, 1).toUpperCase() || "?";
8634
+ }
8635
+ var RecordChangePanel = ({
8236
8636
  records = [],
8237
8637
  loading = false,
8638
+ total,
8639
+ page = 1,
8640
+ pageSize = 20,
8238
8641
  defaultExpanded = false,
8239
8642
  hasMore = false,
8240
8643
  onLoadMore,
8644
+ onRefresh,
8241
8645
  onExpand,
8242
- className = "",
8243
- renderItem
8646
+ onPageChange,
8647
+ className = ""
8244
8648
  }) => {
8245
8649
  const [expanded, setExpanded] = (0, import_react55.useState)(defaultExpanded);
8650
+ const count = total ?? records.length;
8246
8651
  const handleToggle = () => {
8247
8652
  const next = !expanded;
8248
8653
  setExpanded(next);
8249
- if (next && onExpand) {
8250
- onExpand();
8251
- }
8654
+ if (next) onExpand?.();
8252
8655
  };
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",
8656
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8657
+ "section",
8658
+ {
8659
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
8660
+ children: [
8661
+ /* @__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: [
8662
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8663
+ "button",
8664
+ {
8665
+ type: "button",
8666
+ className: "flex min-w-0 items-center gap-2 bg-transparent p-0 text-left",
8667
+ onClick: handleToggle,
8668
+ children: [
8669
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.HistoryOutlined, { className: "text-ant-primary" }),
8670
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "font-semibold text-ant-text", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8671
+ /* @__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: [
8672
+ count,
8673
+ " \u6761"
8674
+ ] }),
8675
+ 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" })
8676
+ ]
8677
+ }
8678
+ ),
8679
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8680
+ import_antd23.Button,
8681
+ {
8682
+ type: "text",
8683
+ size: "small",
8684
+ icon: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.ReloadOutlined, {}),
8685
+ onClick: onRefresh,
8686
+ disabled: loading,
8687
+ children: "\u5237\u65B0"
8688
+ }
8689
+ )
8690
+ ] }),
8691
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "p-5", children: [
8692
+ 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) => {
8693
+ const changes = record.changes && record.changes.length > 0 ? record.changes : [
8694
+ {
8695
+ fieldKey: record.fieldId,
8696
+ fieldLabel: record.fieldLabel,
8697
+ beforeValue: record.oldValue,
8698
+ afterValue: record.newValue
8699
+ }
8700
+ ];
8701
+ const operator = record.operatorName || (record.changeSource ? "\u7CFB\u7EDF" : "\u672A\u77E5");
8702
+ const operatedAt = record.operatedAt || record.createdAt || "-";
8703
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8704
+ "article",
8705
+ {
8706
+ className: "rounded-md border border-ant-border-secondary p-4",
8707
+ children: [
8708
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
8709
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex min-w-0 items-center gap-3", children: [
8710
+ /* @__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) }),
8711
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "min-w-0", children: [
8712
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "block text-sm font-medium text-ant-text", children: [
8713
+ operator,
8714
+ record.operatorDepartmentName && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "ml-2 font-normal text-ant-text-tertiary", children: record.operatorDepartmentName })
8715
+ ] }),
8716
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "block text-xs text-ant-text-tertiary", children: [
8717
+ "\u53D8\u66F4 ",
8718
+ record.changedCount || changes.length,
8719
+ " \u9879 \xB7 ",
8720
+ operatedAt
8721
+ ] })
8722
+ ] })
8723
+ ] }),
8724
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "flex flex-wrap justify-end gap-2", children: [
8725
+ record.changeType && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tag, { children: typeLabels[record.changeType] || record.changeType }),
8726
+ record.changeSource && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Tag, { color: "blue", children: sourceLabels[record.changeSource] || record.changeSource }),
8727
+ 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) }) })
8728
+ ] })
8729
+ ] }),
8730
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mt-4 space-y-3", children: changes.map((change) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
8731
+ "div",
8732
+ {
8733
+ className: "grid gap-2 md:grid-cols-[160px_1fr]",
8734
+ children: [
8735
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "text-sm font-medium text-ant-text-secondary", children: change.fieldLabel || change.fieldKey || "-" }),
8736
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "grid min-w-0 grid-cols-[1fr_auto_1fr] items-start gap-2 text-sm", children: [
8737
+ /* @__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) }),
8738
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_icons3.ArrowRightOutlined, { className: "mt-1 text-xs text-ant-text-tertiary" }),
8739
+ /* @__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) })
8740
+ ] })
8741
+ ]
8742
+ },
8743
+ change.fieldKey || change.fieldLabel
8744
+ )) })
8745
+ ]
8746
+ },
8747
+ record.id || record.operationId
8748
+ );
8749
+ }) }),
8750
+ onPageChange && count > pageSize ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
8751
+ import_antd23.Pagination,
8752
+ {
8753
+ size: "small",
8754
+ current: page,
8755
+ pageSize,
8756
+ total: count,
8757
+ onChange: onPageChange,
8758
+ showSizeChanger: true
8759
+ }
8760
+ ) }) : hasMore ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_antd23.Button, { block: true, className: "mt-4", onClick: onLoadMore, loading, children: "\u52A0\u8F7D\u66F4\u591A" }) : null
8761
+ ] }) : /* @__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" })
8762
+ ]
8763
+ }
8764
+ );
8765
+ };
8766
+
8767
+ // src/modules/ChangeRecords.tsx
8768
+ var import_jsx_runtime79 = require("react/jsx-runtime");
8769
+ var ChangeRecords = ({
8770
+ records = [],
8771
+ loading = false,
8772
+ defaultExpanded = false,
8773
+ hasMore = false,
8774
+ onLoadMore,
8775
+ onExpand,
8776
+ className = "",
8777
+ renderItem
8778
+ }) => {
8779
+ if (renderItem) {
8780
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
8781
+ "section",
8269
8782
  {
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,
8783
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
8273
8784
  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, {}) })
8785
+ /* @__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" }),
8786
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "p-5", children: [
8787
+ 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)) }),
8788
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8789
+ "button",
8790
+ {
8791
+ type: "button",
8792
+ className: "mt-4 w-full rounded-md border border-ant-border-secondary py-2 text-sm text-ant-primary",
8793
+ onClick: onLoadMore,
8794
+ disabled: loading,
8795
+ children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
8796
+ }
8797
+ )
8798
+ ] })
8279
8799
  ]
8280
8800
  }
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
- ] });
8801
+ );
8802
+ }
8803
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
8804
+ RecordChangePanel,
8805
+ {
8806
+ records,
8807
+ loading,
8808
+ defaultExpanded,
8809
+ hasMore,
8810
+ onLoadMore,
8811
+ onRefresh: onExpand,
8812
+ onExpand,
8813
+ className
8814
+ }
8815
+ );
8296
8816
  };
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
8817
 
8303
8818
  // src/modules/ApprovalTimeline.tsx
8304
- var import_jsx_runtime79 = require("react/jsx-runtime");
8819
+ var import_react56 = require("react");
8820
+ var import_icons4 = require("@ant-design/icons");
8821
+ var import_jsx_runtime80 = require("react/jsx-runtime");
8822
+ var systemNodeTypes = /* @__PURE__ */ new Set([
8823
+ "condition",
8824
+ "condition_branch",
8825
+ "js_code",
8826
+ "data_retrieve_single",
8827
+ "data_retrieve_batch",
8828
+ "data_create",
8829
+ "data_update",
8830
+ "connector_call",
8831
+ "loop_container",
8832
+ "work_notification",
8833
+ "dingtalk_card",
8834
+ "system"
8835
+ ]);
8836
+ var systemLabels = {
8837
+ condition: "\u6761\u4EF6\u5224\u65AD",
8838
+ condition_branch: "\u6761\u4EF6\u5206\u652F",
8839
+ js_code: "JS \u4EE3\u7801",
8840
+ data_retrieve_single: "\u6570\u636E\u8BFB\u53D6",
8841
+ data_retrieve_batch: "\u6279\u91CF\u8BFB\u53D6",
8842
+ data_create: "\u6570\u636E\u521B\u5EFA",
8843
+ data_update: "\u6570\u636E\u66F4\u65B0",
8844
+ connector_call: "\u8FDE\u63A5\u5668\u8C03\u7528",
8845
+ loop_container: "\u5FAA\u73AF\u8282\u70B9",
8846
+ work_notification: "\u5DE5\u4F5C\u901A\u77E5",
8847
+ dingtalk_card: "\u9489\u9489\u5361\u7247",
8848
+ system: "\u7CFB\u7EDF\u52A8\u4F5C"
8849
+ };
8305
8850
  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"
8851
+ brand: "bg-blue-600 text-white border-blue-600",
8852
+ success: "bg-emerald-50 text-emerald-700 border-emerald-200",
8853
+ danger: "bg-red-50 text-red-700 border-red-200",
8854
+ neutral: "bg-gray-50 text-gray-600 border-gray-200",
8855
+ warning: "bg-amber-50 text-amber-700 border-amber-200",
8856
+ return: "bg-amber-50 text-amber-700 border-amber-200",
8857
+ future: "bg-gray-50 text-gray-400 border-gray-200"
8311
8858
  };
8312
- function getNodePhase(task) {
8313
- if (task.status === "approved" || task.status === "rejected" || task.status === "returned" || task.status === "copied") {
8859
+ function groupTasks(tasks) {
8860
+ const groups = /* @__PURE__ */ new Map();
8861
+ tasks.forEach((task, index) => {
8862
+ const key = task.nodeVisitId || `${task.nodeId || "node"}-${task.id || task.taskId || index}`;
8863
+ const group = groups.get(key) || [];
8864
+ group.push(task);
8865
+ groups.set(key, group);
8866
+ });
8867
+ return Array.from(groups.values()).map((group) => {
8868
+ const hasOrSignResult = group.some(
8869
+ (task) => task.nodeType === "approval" && task.multiApproveMode === "or" && !task.isSimulated && ["approved", "rejected", "returned"].includes(task.status)
8870
+ );
8871
+ if (!hasOrSignResult) return group;
8872
+ const outcome = group.filter(
8873
+ (task) => !task.isSimulated && ["approved", "rejected", "returned"].includes(task.status)
8874
+ );
8875
+ return outcome.length > 0 ? outcome : group;
8876
+ });
8877
+ }
8878
+ function isCompactNode(task) {
8879
+ return task.nodeType === "start" || task.nodeType === "copy" || task.nodeType === "end" || systemNodeTypes.has(task.nodeType);
8880
+ }
8881
+ function getNodeTitle(task) {
8882
+ if (task.nodeType === "start") return task.title || task.nodeName || "\u6D41\u7A0B\u63D0\u4EA4";
8883
+ if (task.nodeType === "originator_return") return task.title || task.nodeName || "\u53D1\u8D77\u4EBA\u4FEE\u6539";
8884
+ if (task.nodeType === "copy") return task.title || task.nodeName || "\u6284\u9001\u901A\u77E5";
8885
+ if (task.nodeType === "callback_wait") return task.title || task.nodeName || "\u7B49\u5F85\u7B2C\u4E09\u65B9\u56DE\u8C03";
8886
+ if (task.nodeType === "end") return task.title || task.nodeName || "\u6D41\u7A0B\u5B8C\u6210";
8887
+ if (systemNodeTypes.has(task.nodeType))
8888
+ return task.title || task.nodeName || systemLabels[task.nodeType] || "\u7CFB\u7EDF\u52A8\u4F5C";
8889
+ return task.title || task.nodeName || "\u5BA1\u6279";
8890
+ }
8891
+ function getVisualState(task, isFutureGroup) {
8892
+ if (isFutureGroup || task.isSimulated || task.status === "simulated") return "future";
8893
+ if (task.status === "rejected") return "rejected";
8894
+ if (task.status === "returned") return "returned";
8895
+ if (task.status === "pending" || task.status === "waiting" || task.canApprove)
8896
+ return task.canApprove ? "current" : "waiting";
8897
+ if (task.status === "approved" || task.status === "copied" || task.nodeType === "start" || task.nodeType === "end") {
8314
8898
  return "completed";
8315
8899
  }
8316
- if (task.status === "pending" || task.status === "waiting") {
8317
- return "active";
8900
+ return "neutral";
8901
+ }
8902
+ function getStatusMeta(task, state, compact) {
8903
+ if (state === "future") return { label: "\u672A\u5F00\u59CB", tone: "neutral" };
8904
+ if (state === "current")
8905
+ return { label: task.nodeType === "callback_wait" ? "\u7B49\u5F85\u56DE\u8C03" : "\u5BA1\u6279\u4E2D", tone: "brand" };
8906
+ if (state === "waiting") return { label: "\u7B49\u5F85\u5904\u7406\u4E2D", tone: "neutral" };
8907
+ if (state === "rejected") return TASK_STATUS_META.rejected;
8908
+ if (state === "returned") return TASK_STATUS_META.returned;
8909
+ if (task.nodeType === "copy" || task.status === "copied") return TASK_STATUS_META.copied;
8910
+ if (compact) return { label: "\u5DF2\u5B8C\u6210", tone: "neutral" };
8911
+ return TASK_STATUS_META[task.status] || TASK_STATUS_META.approved;
8912
+ }
8913
+ function getIcon(task, state) {
8914
+ if (state === "current")
8915
+ return task.nodeType === "callback_wait" ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ClockCircleOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.LoadingOutlined, {});
8916
+ if (state === "future" || state === "waiting")
8917
+ return task.nodeType === "approval" ? /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.UserOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ClockCircleOutlined, {});
8918
+ if (state === "rejected") return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CloseCircleFilled, {});
8919
+ if (state === "returned") return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.RollbackOutlined, {});
8920
+ switch (task.nodeType) {
8921
+ case "start":
8922
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.FileTextOutlined, {});
8923
+ case "approval":
8924
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CheckCircleFilled, {});
8925
+ case "originator_return":
8926
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.EditOutlined, {});
8927
+ case "copy":
8928
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CopyOutlined, {});
8929
+ case "callback_wait":
8930
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ClockCircleOutlined, {});
8931
+ case "js_code":
8932
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CodeOutlined, {});
8933
+ case "connector_call":
8934
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ApiOutlined, {});
8935
+ case "work_notification":
8936
+ case "dingtalk_card":
8937
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.NotificationOutlined, {});
8938
+ case "data_retrieve_single":
8939
+ case "data_retrieve_batch":
8940
+ case "data_create":
8941
+ case "data_update":
8942
+ case "loop_container":
8943
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.ReloadOutlined, {});
8944
+ default:
8945
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(import_icons4.CheckCircleFilled, {});
8318
8946
  }
8319
- return "pending";
8947
+ }
8948
+ function getDotClass(state) {
8949
+ const map = {
8950
+ completed: "border-emerald-500 text-emerald-600 bg-white",
8951
+ current: "border-blue-600 bg-blue-600 text-white",
8952
+ waiting: "border-gray-200 text-gray-300 bg-white",
8953
+ future: "border-dashed border-gray-300 text-gray-300 bg-white",
8954
+ rejected: "border-red-500 text-red-600 bg-white",
8955
+ returned: "border-amber-500 text-amber-600 bg-white",
8956
+ neutral: "border-gray-200 text-gray-400 bg-white"
8957
+ };
8958
+ return map[state];
8320
8959
  }
8321
8960
  var ApprovalTimeline = ({
8322
8961
  tasks,
8323
8962
  className = "",
8324
8963
  renderNode,
8325
8964
  showRemarks = true,
8326
- compactMode = false
8965
+ compactMode = false,
8966
+ showApproverInfo = true
8327
8967
  }) => {
8328
- const taskList = Array.isArray(tasks) ? tasks : [];
8968
+ const taskList = (0, import_react56.useMemo)(() => Array.isArray(tasks) ? tasks : [], [tasks]);
8969
+ const groups = (0, import_react56.useMemo)(() => groupTasks(taskList), [taskList]);
8329
8970
  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" }) });
8971
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8972
+ "div",
8973
+ {
8974
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container p-6 ${className}`,
8975
+ 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" })
8976
+ }
8977
+ );
8331
8978
  }
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)(
8979
+ if (renderNode) {
8980
+ 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)) });
8981
+ }
8982
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: `approval-timeline ${className}`, children: groups.map((group, index) => {
8983
+ const node = group[0];
8984
+ const isLast = index === groups.length - 1;
8985
+ const isFutureGroup = group.some((task) => task.isSimulated || task.status === "simulated");
8986
+ const compact = compactMode || isCompactNode(node);
8987
+ const state = getVisualState(node, isFutureGroup);
8988
+ const statusMeta = getStatusMeta(node, state, compact);
8989
+ const title = getNodeTitle(node);
8990
+ const time = node.actionAt || node.createdAt;
8991
+ return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
8992
+ "div",
8993
+ {
8994
+ className: `relative flex gap-4 pb-5 ${isLast ? "pb-0" : ""}`,
8995
+ children: [
8996
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8997
+ "div",
8998
+ {
8999
+ className: `absolute bottom-0 left-[21px] top-11 w-px ${state === "future" ? "border-l border-dashed border-gray-300" : "bg-ant-border-secondary"}`
9000
+ }
9001
+ ),
9002
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9003
+ "div",
9004
+ {
9005
+ 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)}`,
9006
+ children: getIcon(node, state)
9007
+ }
9008
+ ),
9009
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9010
+ "div",
9011
+ {
9012
+ 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"}`,
9013
+ children: [
9014
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
9015
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
9016
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "font-medium text-ant-text", children: title }),
9017
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9018
+ "span",
9019
+ {
9020
+ className: `inline-flex min-h-6 items-center rounded-md border px-2 text-xs font-medium ${state === "future" ? toneClasses2.future : toneClasses2[statusMeta.tone]}`,
9021
+ children: statusMeta.label
9022
+ }
9023
+ ),
9024
+ 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" })
9025
+ ] }),
9026
+ !isFutureGroup && time && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "text-xs text-ant-text-tertiary", children: time })
9027
+ ] }),
9028
+ showApproverInfo && !compact && group.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3", children: [
9029
+ /* @__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" }),
9030
+ group.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)(
9031
+ "span",
9032
+ {
9033
+ className: "inline-flex min-w-0 items-center gap-2",
9034
+ children: [
9035
+ /* @__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) || "?" }),
9036
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "min-w-0", children: [
9037
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "block text-sm font-medium text-ant-text", children: assignee.assigneeName || "\u7CFB\u7EDF" }),
9038
+ /* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "block text-xs text-ant-text-tertiary", children: assignee.departmentName || assignee.actionAt || assignee.createdAt || "" })
9039
+ ] })
9040
+ ]
9041
+ },
9042
+ assignee.taskId || assignee.id
9043
+ ))
9044
+ ] }),
9045
+ 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" : "") }),
9046
+ showRemarks && node.comments && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
9047
+ "div",
9048
+ {
9049
+ 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"}`,
9050
+ children: node.comments
9051
+ }
9052
+ )
9053
+ ]
9054
+ }
9055
+ ) })
9056
+ ]
9057
+ },
9058
+ node.nodeVisitId || `${node.nodeId}-${node.taskId}-${index}`
9059
+ );
9060
+ }) });
9061
+ };
9062
+
9063
+ // src/modules/ApprovalActionBar.tsx
9064
+ var import_react58 = require("react");
9065
+ var import_antd25 = require("antd");
9066
+ var import_icons6 = require("@ant-design/icons");
9067
+
9068
+ // src/modules/StickyActionBar.tsx
9069
+ var import_react57 = require("react");
9070
+ var import_antd24 = require("antd");
9071
+ var import_icons5 = require("@ant-design/icons");
9072
+
9073
+ // src/utils/confirmAction.ts
9074
+ var confirmAction = (title, content) => {
9075
+ const message2 = [title, content].filter(Boolean).join("\n") || "\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F";
9076
+ if (typeof window === "undefined" || typeof window.confirm !== "function") {
9077
+ return true;
9078
+ }
9079
+ try {
9080
+ return window.confirm(message2);
9081
+ } catch {
9082
+ return true;
9083
+ }
9084
+ };
9085
+
9086
+ // src/modules/StickyActionBar.tsx
9087
+ var import_jsx_runtime81 = require("react/jsx-runtime");
9088
+ var getActionPriority = (action) => {
9089
+ const maybePriority = action.priority;
9090
+ if (typeof maybePriority === "number") return maybePriority;
9091
+ if (action.type === "primary") return 10;
9092
+ if (action.type === "danger") return 90;
9093
+ return 50;
9094
+ };
9095
+ var getPlacement = (action) => action.placement;
9096
+ var StickyActionBar = ({
9097
+ actions,
9098
+ className = "",
9099
+ maxMobileButtons = 2,
9100
+ layoutMode = "default",
9101
+ maxWidth = 1120,
9102
+ position = "sticky"
9103
+ }) => {
9104
+ const [isMobile, setIsMobile] = (0, import_react57.useState)(false);
9105
+ (0, import_react57.useEffect)(() => {
9106
+ const update = () => setIsMobile(typeof window !== "undefined" && window.innerWidth <= 768);
9107
+ update();
9108
+ window.addEventListener("resize", update);
9109
+ return () => window.removeEventListener("resize", update);
9110
+ }, []);
9111
+ const visibleActions = (0, import_react57.useMemo)(
9112
+ () => actions.filter((action) => action.visible !== false).sort((left, right) => getActionPriority(left) - getActionPriority(right)),
9113
+ [actions]
9114
+ );
9115
+ if (visibleActions.length === 0) return null;
9116
+ const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
9117
+ const primaryMobile = visibleActions.slice(0, maxMobileButtons);
9118
+ const moreMobile = visibleActions.slice(maxMobileButtons);
9119
+ const leftActions = visibleActions.filter((action) => getPlacement(action) === "left");
9120
+ const rightActions = visibleActions.filter((action) => getPlacement(action) !== "left");
9121
+ const positionClass = position === "fixed" ? "fixed bottom-0 left-0 right-0" : position === "inline" ? "relative" : "sticky bottom-0";
9122
+ const runAction = (action) => {
9123
+ if (action.confirm) {
9124
+ const confirmed = confirmAction(action.confirm.title, action.confirm.content);
9125
+ if (!confirmed) return;
9126
+ }
9127
+ action.onClick();
9128
+ };
9129
+ const renderButton = (action, mobile = false) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9130
+ import_antd24.Button,
9131
+ {
9132
+ type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
9133
+ danger: action.type === "danger",
9134
+ loading: action.loading,
9135
+ disabled: action.disabled,
9136
+ icon: action.icon,
9137
+ onClick: () => runAction(action),
9138
+ className: `${mobile ? "min-w-0 flex-1" : "min-w-[88px]"} rounded-md`,
9139
+ children: action.label
9140
+ },
9141
+ action.key
9142
+ );
9143
+ return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9144
+ "div",
9145
+ {
9146
+ className: `${positionClass} z-20 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))] ${className}`,
9147
+ children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
8353
9148
  "div",
8354
9149
  {
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",
9150
+ className: `mx-auto flex w-full items-center gap-3 ${layoutMode === "approval" && !isMobile ? "justify-between" : "justify-end"}`,
9151
+ style: { maxWidth: maxWidthStyle },
9152
+ children: isMobile ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
9153
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-1 gap-2", children: primaryMobile.map((action) => renderButton(action, true)) }),
9154
+ moreMobile.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9155
+ import_antd24.Dropdown,
9156
+ {
9157
+ trigger: ["click"],
9158
+ placement: "topRight",
9159
+ menu: {
9160
+ items: moreMobile.map((action) => ({
9161
+ key: action.key,
9162
+ label: action.label,
9163
+ danger: action.type === "danger",
9164
+ disabled: action.disabled,
9165
+ icon: action.icon,
9166
+ onClick: () => runAction(action)
9167
+ }))
9168
+ },
9169
+ 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" })
9170
+ }
9171
+ )
9172
+ ] }) : layoutMode === "approval" && leftActions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
9173
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-wrap items-center gap-3", children: leftActions.map((action) => renderButton(action)) }),
9174
+ /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: rightActions.map((action) => renderButton(action)) })
9175
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-3", children: visibleActions.map((action) => renderButton(action)) })
9176
+ }
9177
+ )
9178
+ }
9179
+ );
9180
+ };
9181
+
9182
+ // src/modules/ApprovalActionBar.tsx
9183
+ var import_jsx_runtime82 = require("react/jsx-runtime");
9184
+ var actionPriority = {
9185
+ agree: 10,
9186
+ approved: 10,
9187
+ return: 20,
9188
+ transfer: 30,
9189
+ resubmit: 40,
9190
+ save: 80,
9191
+ withdraw: 90,
9192
+ rejected: 100,
9193
+ reject: 100
9194
+ };
9195
+ function getActionLabel(action) {
9196
+ return action.name?.zh_CN || action.text?.zh_CN || action.action;
9197
+ }
9198
+ function normalizeAction(action) {
9199
+ if (action === "approved") return "agree";
9200
+ if (action === "reject") return "rejected";
9201
+ if (action === "agree" || action === "rejected" || action === "withdraw" || action === "transfer" || action === "return" || action === "resubmit") {
9202
+ return action;
9203
+ }
9204
+ if (action === "save" || action === "callback") return action;
9205
+ return "agree";
9206
+ }
9207
+ function getModalTitle(action) {
9208
+ switch (action) {
9209
+ case "agree":
9210
+ return "\u5BA1\u6279\u610F\u89C1";
9211
+ case "rejected":
9212
+ return "\u62D2\u7EDD\u7406\u7531";
9213
+ case "withdraw":
9214
+ return "\u64A4\u9500\u6D41\u7A0B";
9215
+ case "transfer":
9216
+ return "\u8F6C\u4EA4\u4EFB\u52A1";
9217
+ case "return":
9218
+ return "\u9000\u56DE\u4EFB\u52A1";
9219
+ case "resubmit":
9220
+ return "\u91CD\u65B0\u63D0\u4EA4";
9221
+ default:
9222
+ return "\u786E\u8BA4\u64CD\u4F5C";
9223
+ }
9224
+ }
9225
+ var ApprovalActionBar = ({
9226
+ actions,
9227
+ onApprove,
9228
+ onReject,
9229
+ onTransfer,
9230
+ onReturn,
9231
+ onWithdraw,
9232
+ onSave,
9233
+ onResubmit,
9234
+ onCallback,
9235
+ returnableNodes = [],
9236
+ onLoadReturnableNodes,
9237
+ renderTransferSelector,
9238
+ renderReturnNodeLabel,
9239
+ renderActionModalExtra,
9240
+ maxMobileButtons = 2,
9241
+ className = "",
9242
+ inDrawer = false
9243
+ }) => {
9244
+ const [form] = import_antd25.Form.useForm();
9245
+ const [modalAction, setModalAction] = (0, import_react58.useState)(null);
9246
+ const [activeAction, setActiveAction] = (0, import_react58.useState)(null);
9247
+ const [loading, setLoading] = (0, import_react58.useState)(false);
9248
+ const visibleActions = (0, import_react58.useMemo)(
9249
+ () => actions.filter((action) => !action.hidden).sort((a, b) => (actionPriority[a.action] ?? 50) - (actionPriority[b.action] ?? 50)),
9250
+ [actions]
9251
+ );
9252
+ const openModal = async (action, target) => {
9253
+ setActiveAction(action);
9254
+ const defaultComments = action.remark?.content?.zh_CN;
9255
+ form.setFieldsValue({
9256
+ comments: defaultComments || "",
9257
+ reason: "",
9258
+ userId: void 0,
9259
+ nodeId: void 0
9260
+ });
9261
+ if (target === "return") await onLoadReturnableNodes?.();
9262
+ setModalAction(target);
9263
+ };
9264
+ const executeDirect = async (action) => {
9265
+ const normalized = normalizeAction(action.action);
9266
+ if (normalized === "save") {
9267
+ await onSave?.();
9268
+ return;
9269
+ }
9270
+ if (normalized === "callback") {
9271
+ await onCallback?.();
9272
+ return;
9273
+ }
9274
+ if (normalized === "agree") {
9275
+ await onApprove?.();
9276
+ }
9277
+ };
9278
+ const handleActionClick = async (action) => {
9279
+ const normalized = normalizeAction(action.action);
9280
+ if (normalized === "save" || normalized === "callback") {
9281
+ await executeDirect(action);
9282
+ return;
9283
+ }
9284
+ await openModal(action, normalized);
9285
+ };
9286
+ const handleOk = async () => {
9287
+ if (!modalAction) return;
9288
+ const values = await form.validateFields();
9289
+ setLoading(true);
9290
+ try {
9291
+ if (modalAction === "agree") await onApprove?.(values.comments || void 0);
9292
+ if (modalAction === "rejected") await onReject?.(values.comments || void 0);
9293
+ if (modalAction === "withdraw")
9294
+ await onWithdraw?.(values.reason || values.comments || void 0);
9295
+ if (modalAction === "transfer") await onTransfer?.(values.userId, values.reason || void 0);
9296
+ if (modalAction === "return") await onReturn?.(values.nodeId, values.reason || void 0);
9297
+ if (modalAction === "resubmit") await onResubmit?.(values.comments || void 0);
9298
+ setModalAction(null);
9299
+ setActiveAction(null);
9300
+ form.resetFields();
9301
+ } finally {
9302
+ setLoading(false);
9303
+ }
9304
+ };
9305
+ const actionConfigs = visibleActions.map((action) => {
9306
+ const normalized = normalizeAction(action.action);
9307
+ const danger = normalized === "rejected" || normalized === "withdraw";
9308
+ return {
9309
+ key: action.action,
9310
+ label: getActionLabel(action),
9311
+ type: normalized === "agree" ? "primary" : danger ? "danger" : "default",
9312
+ 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,
9313
+ onClick: () => handleActionClick(action),
9314
+ placement: danger || normalized === "save" ? "right" : "left",
9315
+ priority: actionPriority[action.action] ?? 50
9316
+ };
9317
+ });
9318
+ const requiredComment = activeAction?.remark?.required || modalAction === "rejected" || modalAction === "withdraw";
9319
+ return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_jsx_runtime82.Fragment, { children: [
9320
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9321
+ StickyActionBar,
9322
+ {
9323
+ actions: actionConfigs,
9324
+ layoutMode: "approval",
9325
+ maxMobileButtons,
9326
+ className,
9327
+ inDrawer
9328
+ }
9329
+ ),
9330
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9331
+ import_antd25.Modal,
9332
+ {
9333
+ getContainer: false,
9334
+ title: getModalTitle(modalAction),
9335
+ open: modalAction !== null,
9336
+ okText: "\u786E\u8BA4",
9337
+ cancelText: "\u53D6\u6D88",
9338
+ confirmLoading: loading,
9339
+ onOk: handleOk,
9340
+ onCancel: () => {
9341
+ setModalAction(null);
9342
+ setActiveAction(null);
9343
+ form.resetFields();
9344
+ },
9345
+ destroyOnClose: true,
9346
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)(import_antd25.Form, { form, layout: "vertical", children: [
9347
+ modalAction === "transfer" && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9348
+ import_antd25.Form.Item,
9349
+ {
9350
+ name: "userId",
9351
+ label: "\u8F6C\u4EA4\u7ED9",
9352
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u8F6C\u4EA4\u7528\u6237" }],
9353
+ children: renderTransferSelector ? renderTransferSelector({
9354
+ value: form.getFieldValue("userId"),
9355
+ onChange: (userId) => form.setFieldsValue({ userId })
9356
+ }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd25.Input, { placeholder: "\u8BF7\u8F93\u5165\u7528\u6237 ID" })
9357
+ }
9358
+ ),
9359
+ modalAction === "return" && /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9360
+ import_antd25.Form.Item,
9361
+ {
9362
+ name: "nodeId",
9363
+ label: "\u9000\u56DE\u5230\u8282\u70B9",
9364
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9" }],
9365
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9366
+ import_antd25.Select,
8361
9367
  {
8362
- className: `px-2 py-0.5 rounded-full text-xs font-medium ${toneClasses2[statusMeta.tone] || toneClasses2.neutral}`,
8363
- children: statusMeta.label
9368
+ placeholder: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9",
9369
+ getPopupContainer: (triggerNode) => triggerNode.parentElement || document.body,
9370
+ options: returnableNodes.map((node) => ({
9371
+ value: node.nodeId || node.id || "",
9372
+ label: renderReturnNodeLabel ? renderReturnNodeLabel(node) : node.nodeName || node.name || node.nodeId || node.id
9373
+ }))
8364
9374
  }
8365
9375
  )
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
- }) });
9376
+ }
9377
+ ),
9378
+ /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9379
+ import_antd25.Form.Item,
9380
+ {
9381
+ name: modalAction === "withdraw" || modalAction === "transfer" || modalAction === "return" ? "reason" : "comments",
9382
+ label: modalAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : modalAction === "transfer" ? "\u8F6C\u4EA4\u539F\u56E0" : modalAction === "return" ? "\u9000\u56DE\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1",
9383
+ rules: [{ required: requiredComment, message: "\u8BF7\u586B\u5199\u8BF4\u660E" }],
9384
+ children: /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(import_antd25.Input.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u8BF4\u660E" })
9385
+ }
9386
+ ),
9387
+ activeAction && renderActionModalExtra?.(activeAction)
9388
+ ] })
9389
+ }
9390
+ )
9391
+ ] });
8394
9392
  };
8395
9393
 
8396
9394
  // 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;
9395
+ var import_react59 = require("react");
9396
+ var import_antd26 = require("antd");
9397
+ var import_icons7 = require("@ant-design/icons");
9398
+ var import_jsx_runtime83 = require("react/jsx-runtime");
9399
+ var priority = {
9400
+ agree: 10,
9401
+ approved: 10,
9402
+ transfer: 20,
9403
+ return: 30,
9404
+ save: 40,
9405
+ withdraw: 90,
9406
+ rejected: 100,
9407
+ reject: 100
9408
+ };
9409
+ var getLabel = (action) => action.name?.zh_CN || action.text?.zh_CN || action.action;
8402
9410
  var ApprovalActions = ({
8403
9411
  actions,
8404
9412
  onApprove,
@@ -8411,167 +9419,150 @@ var ApprovalActions = ({
8411
9419
  maxVisible = 3,
8412
9420
  className = ""
8413
9421
  }) => {
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
- }
9422
+ const [form] = import_antd26.Form.useForm();
9423
+ const [modalAction, setModalAction] = (0, import_react59.useState)(null);
9424
+ const [activeAction, setActiveAction] = (0, import_react59.useState)(null);
9425
+ const [loading, setLoading] = (0, import_react59.useState)(false);
9426
+ const [saveLoading, setSaveLoading] = (0, import_react59.useState)(false);
9427
+ const renderableActions = (0, import_react59.useMemo)(
9428
+ () => actions.filter((action) => !action.hidden).sort((a, b) => (priority[a.action] ?? 50) - (priority[b.action] ?? 50)),
9429
+ [actions]
9430
+ );
9431
+ const openModal = (target, action) => {
9432
+ setActiveAction(action);
9433
+ form.setFieldsValue({ comments: action.remark?.content?.zh_CN || "" });
9434
+ setModalAction(target);
8436
9435
  };
8437
9436
  const handleSave = async () => {
8438
- if (!onSave) return;
8439
9437
  setSaveLoading(true);
8440
9438
  try {
8441
- await onSave();
9439
+ await onSave?.();
8442
9440
  } finally {
8443
9441
  setSaveLoading(false);
8444
9442
  }
8445
9443
  };
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;
9444
+ const handleAction = (action) => {
9445
+ if (action.action === "transfer") {
9446
+ onTransfer?.();
9447
+ return;
8492
9448
  }
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)(
9449
+ if (action.action === "return") {
9450
+ onReturn?.();
9451
+ return;
9452
+ }
9453
+ if (action.action === "save") {
9454
+ void handleSave();
9455
+ return;
9456
+ }
9457
+ if (action.action === "withdraw") {
9458
+ openModal("withdraw", action);
9459
+ return;
9460
+ }
9461
+ if (action.action === "rejected" || action.action === "reject") {
9462
+ openModal("reject", action);
9463
+ return;
9464
+ }
9465
+ openModal("approve", action);
9466
+ };
9467
+ const handleConfirm = async () => {
9468
+ const values = await form.validateFields();
9469
+ setLoading(true);
9470
+ try {
9471
+ if (modalAction === "approve") await onApprove?.(values.comments || void 0);
9472
+ if (modalAction === "reject") await onReject?.(values.comments || void 0);
9473
+ if (modalAction === "withdraw") await onWithdraw?.(values.comments || void 0);
9474
+ setModalAction(null);
9475
+ setActiveAction(null);
9476
+ form.resetFields();
9477
+ } finally {
9478
+ setLoading(false);
9479
+ }
9480
+ };
9481
+ const visibleButtons = renderableActions.slice(0, maxVisible);
9482
+ const moreButtons = renderableActions.slice(maxVisible);
9483
+ const title = modalAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : modalAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : "\u64A4\u9500\u539F\u56E0";
9484
+ const button = (action) => /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9485
+ import_antd26.Button,
9486
+ {
9487
+ type: action.action === "agree" || action.action === "approved" ? "primary" : "default",
9488
+ danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9489
+ onClick: () => handleAction(action),
9490
+ loading: action.action === "save" && saveLoading,
9491
+ children: getLabel(action)
9492
+ },
9493
+ action.action
9494
+ );
9495
+ return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(import_jsx_runtime83.Fragment, { children: [
9496
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)(
8500
9497
  "div",
8501
9498
  {
8502
9499
  className: `${layout === "horizontal" ? "flex items-center gap-3" : "flex flex-col gap-2"} ${className}`,
8503
9500
  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,
9501
+ visibleButtons.map(button),
9502
+ moreButtons.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9503
+ import_antd26.Dropdown,
8517
9504
  {
9505
+ trigger: ["click"],
9506
+ getPopupContainer: (triggerNode) => triggerNode.parentElement || document.body,
8518
9507
  menu: {
8519
- items: moreButtons.map(([key, btn]) => ({
8520
- key,
8521
- label: btn.label,
8522
- onClick: btn.handler
9508
+ items: moreButtons.map((action) => ({
9509
+ key: action.action,
9510
+ label: getLabel(action),
9511
+ danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9512
+ onClick: () => handleAction(action)
8523
9513
  }))
8524
9514
  },
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" })
9515
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd26.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_icons7.MoreOutlined, {}), children: "\u66F4\u591A" })
8527
9516
  }
8528
9517
  )
8529
9518
  ]
8530
9519
  }
8531
9520
  ),
8532
- /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
8533
- import_antd24.Drawer,
9521
+ /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9522
+ import_antd26.Modal,
8534
9523
  {
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
- ] }) })
9524
+ getContainer: false,
9525
+ title,
9526
+ open: modalAction !== null,
9527
+ okText: "\u786E\u8BA4",
9528
+ cancelText: "\u53D6\u6D88",
9529
+ confirmLoading: loading,
9530
+ onOk: handleConfirm,
9531
+ onCancel: () => {
9532
+ setModalAction(null);
9533
+ setActiveAction(null);
9534
+ form.resetFields();
9535
+ },
9536
+ destroyOnClose: true,
9537
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd26.Form, { form, layout: "vertical", children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
9538
+ import_antd26.Form.Item,
9539
+ {
9540
+ name: "comments",
9541
+ label: modalAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : "\u8BF7\u8F93\u5165\u7406\u7531",
9542
+ rules: [
9543
+ {
9544
+ required: Boolean(activeAction?.remark?.required) || modalAction !== "approve",
9545
+ message: "\u8BF7\u586B\u5199\u8BF4\u660E"
9546
+ }
9547
+ ],
9548
+ children: /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(import_antd26.Input.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u8BF4\u660E" })
9549
+ }
9550
+ ) })
8560
9551
  }
8561
9552
  )
8562
9553
  ] });
8563
9554
  };
8564
9555
 
8565
9556
  // 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");
9557
+ var import_react60 = require("react");
9558
+ var import_antd27 = require("antd");
9559
+ var import_jsx_runtime84 = require("react/jsx-runtime");
8569
9560
  var FormActionBar = ({
8570
9561
  actions,
8571
9562
  position = "bottom-fixed",
8572
9563
  className = ""
8573
9564
  }) => {
8574
- const [loadingKeys, setLoadingKeys] = (0, import_react57.useState)(/* @__PURE__ */ new Set());
9565
+ const [loadingKeys, setLoadingKeys] = (0, import_react60.useState)(/* @__PURE__ */ new Set());
8575
9566
  const visibleActions = actions.filter((a) => a.visible !== false);
8576
9567
  const sortedActions = [...visibleActions].sort((a, b) => {
8577
9568
  if (a.type === "danger" && b.type !== "danger") return -1;
@@ -8582,15 +9573,9 @@ var FormActionBar = ({
8582
9573
  });
8583
9574
  const handleClick = async (action) => {
8584
9575
  if (action.confirm) {
8585
- import_antd25.Modal.confirm({
8586
- title: action.confirm.title,
8587
- content: action.confirm.content,
8588
- okText: "\u786E\u8BA4",
8589
- cancelText: "\u53D6\u6D88",
8590
- onOk: async () => {
8591
- await executeAction(action);
8592
- }
8593
- });
9576
+ const confirmed = confirmAction(action.confirm.title, action.confirm.content);
9577
+ if (!confirmed) return;
9578
+ await executeAction(action);
8594
9579
  } else {
8595
9580
  await executeAction(action);
8596
9581
  }
@@ -8608,14 +9593,14 @@ var FormActionBar = ({
8608
9593
  }
8609
9594
  };
8610
9595
  const isFixed = position === "bottom-fixed";
8611
- const bar = /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
9596
+ const bar = /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
8612
9597
  "div",
8613
9598
  {
8614
9599
  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) => {
9600
+ 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
9601
  const isLoading = action.loading || loadingKeys.has(action.key);
8617
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
8618
- import_antd25.Button,
9602
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
9603
+ import_antd27.Button,
8619
9604
  {
8620
9605
  type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
8621
9606
  danger: action.type === "danger",
@@ -8632,18 +9617,137 @@ var FormActionBar = ({
8632
9617
  }
8633
9618
  );
8634
9619
  if (isFixed) {
8635
- return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(import_jsx_runtime81.Fragment, { children: [
9620
+ return /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)(import_jsx_runtime84.Fragment, { children: [
8636
9621
  bar,
8637
- /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "h-16" })
9622
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "h-16" })
8638
9623
  ] });
8639
9624
  }
8640
9625
  return bar;
8641
9626
  };
8642
9627
 
9628
+ // src/modules/RuntimePageShell.tsx
9629
+ var import_antd28 = require("antd");
9630
+ var import_jsx_runtime85 = require("react/jsx-runtime");
9631
+ var RuntimePageShell = ({
9632
+ children,
9633
+ actions,
9634
+ loading = false,
9635
+ loadingTip = "\u6B63\u5728\u52A0\u8F7D\u9875\u9762...",
9636
+ accessDenied = false,
9637
+ error,
9638
+ empty,
9639
+ className = "",
9640
+ contentClassName = "",
9641
+ maxWidth = 1120,
9642
+ inDrawer = false
9643
+ }) => {
9644
+ const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
9645
+ const renderState = () => {
9646
+ if (loading) {
9647
+ 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 }) });
9648
+ }
9649
+ if (accessDenied) {
9650
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd28.Empty, { description: "\u65E0\u6743\u9650\u67E5\u770B\u8BE6\u60C5" });
9651
+ }
9652
+ if (error) {
9653
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd28.Alert, { type: "error", showIcon: true, message: "\u9875\u9762\u52A0\u8F7D\u5931\u8D25", description: error });
9654
+ }
9655
+ if (empty) {
9656
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_jsx_runtime85.Fragment, { children: empty });
9657
+ }
9658
+ return children;
9659
+ };
9660
+ return /* @__PURE__ */ (0, import_jsx_runtime85.jsxs)("div", { className: `sy-runtime-page min-h-full bg-ant-bg-layout text-ant-text ${className}`, children: [
9661
+ /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(
9662
+ "div",
9663
+ {
9664
+ className: `sy-runtime-page__content mx-auto w-full px-4 py-6 pb-8 md:px-6 ${inDrawer ? "py-4 md:px-4" : ""} ${contentClassName}`,
9665
+ style: { maxWidth: maxWidthStyle },
9666
+ children: renderState()
9667
+ }
9668
+ ),
9669
+ actions
9670
+ ] });
9671
+ };
9672
+
9673
+ // src/modules/SummaryPanel.tsx
9674
+ var import_antd29 = require("antd");
9675
+ var import_icons8 = require("@ant-design/icons");
9676
+ var import_jsx_runtime86 = require("react/jsx-runtime");
9677
+ var toneClasses3 = {
9678
+ brand: "bg-blue-50 text-blue-700 border-blue-200",
9679
+ success: "bg-emerald-50 text-emerald-700 border-emerald-200",
9680
+ danger: "bg-red-50 text-red-700 border-red-200",
9681
+ neutral: "bg-gray-50 text-gray-600 border-gray-200",
9682
+ warning: "bg-amber-50 text-amber-700 border-amber-200"
9683
+ };
9684
+ var SummaryPanel = ({
9685
+ title = "\u8BE6\u60C5",
9686
+ eyebrow,
9687
+ status,
9688
+ creator,
9689
+ createdAt,
9690
+ metaItems,
9691
+ className = "",
9692
+ children
9693
+ }) => {
9694
+ const defaultItems = [
9695
+ {
9696
+ key: "creator",
9697
+ label: "\u521B\u5EFA\u4EBA",
9698
+ value: creator?.name || "\u672A\u77E5\u7528\u6237",
9699
+ 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" })
9700
+ },
9701
+ {
9702
+ key: "department",
9703
+ label: "\u6240\u5C5E\u90E8\u95E8",
9704
+ value: creator?.department || "-",
9705
+ icon: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_icons8.ApartmentOutlined, {})
9706
+ },
9707
+ {
9708
+ key: "createdAt",
9709
+ label: "\u521B\u5EFA\u65F6\u95F4",
9710
+ value: createdAt || "-",
9711
+ icon: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_icons8.CalendarOutlined, {})
9712
+ }
9713
+ ];
9714
+ const items = metaItems || defaultItems;
9715
+ return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9716
+ "section",
9717
+ {
9718
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
9719
+ children: /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "p-5 md:p-6", children: [
9720
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
9721
+ /* @__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: [
9722
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(import_icons8.FileTextOutlined, {}),
9723
+ "\u6570\u636E\u5B9E\u4F8B"
9724
+ ] }) }),
9725
+ status && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(
9726
+ "span",
9727
+ {
9728
+ className: `inline-flex min-h-6 items-center rounded-md border px-2.5 text-xs font-medium ${toneClasses3[status.tone] || toneClasses3.neutral}`,
9729
+ children: status.label
9730
+ }
9731
+ )
9732
+ ] }),
9733
+ /* @__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 }),
9734
+ 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: [
9735
+ /* @__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 }),
9736
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsxs)("span", { className: "min-w-0", children: [
9737
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "block text-xs leading-5 text-ant-text-tertiary", children: item.label }),
9738
+ /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("span", { className: "block break-words text-sm font-medium leading-6 text-ant-text", children: item.value || "-" })
9739
+ ] })
9740
+ ] }, item.key)) }),
9741
+ children && /* @__PURE__ */ (0, import_jsx_runtime86.jsx)("div", { className: "mt-5", children })
9742
+ ] })
9743
+ }
9744
+ );
9745
+ };
9746
+
8643
9747
  // 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");
9748
+ var import_antd30 = require("antd");
9749
+ var import_icons9 = require("@ant-design/icons");
9750
+ var import_jsx_runtime87 = require("react/jsx-runtime");
8647
9751
  function formatRelativeTime(timestamp) {
8648
9752
  const now = Date.now();
8649
9753
  const diff = now - timestamp;
@@ -8664,25 +9768,25 @@ var DraftManager = ({
8664
9768
  }) => {
8665
9769
  if (!hasDraft) return null;
8666
9770
  const timeLabel = draftTimestamp ? formatRelativeTime(draftTimestamp) : null;
8667
- return /* @__PURE__ */ (0, import_jsx_runtime82.jsx)(
9771
+ return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(
8668
9772
  "div",
8669
9773
  {
8670
9774
  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: [
9775
+ children: /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
9776
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
9777
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_icons9.EditOutlined, { className: "text-blue-500" }),
9778
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { children: [
8675
9779
  "\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: [
9780
+ timeLabel && /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("span", { className: "text-blue-500 ml-1", children: [
8677
9781
  "\uFF08\u4FDD\u5B58\u4E8E ",
8678
9782
  timeLabel,
8679
9783
  "\uFF09"
8680
9784
  ] })
8681
9785
  ] })
8682
9786
  ] }),
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" })
9787
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsxs)("div", { className: "flex items-center gap-2", children: [
9788
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_antd30.Button, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
9789
+ /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(import_antd30.Button, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
8686
9790
  ] })
8687
9791
  ] })
8688
9792
  }
@@ -8690,9 +9794,9 @@ var DraftManager = ({
8690
9794
  };
8691
9795
 
8692
9796
  // 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");
9797
+ var import_antd31 = require("antd");
9798
+ var import_icons10 = require("@ant-design/icons");
9799
+ var import_jsx_runtime88 = require("react/jsx-runtime");
8696
9800
  var ProcessPreview = ({
8697
9801
  open,
8698
9802
  onClose,
@@ -8700,49 +9804,1150 @@ var ProcessPreview = ({
8700
9804
  routes,
8701
9805
  loading = false
8702
9806
  }) => {
8703
- return /* @__PURE__ */ (0, import_jsx_runtime83.jsx)(
8704
- import_antd27.Modal,
9807
+ const routeList = Array.isArray(routes) ? routes : [];
9808
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
9809
+ import_antd31.Modal,
8705
9810
  {
9811
+ getContainer: false,
8706
9812
  title: "\u6D41\u7A0B\u9884\u89C8",
8707
9813
  open,
8708
9814
  onCancel: onClose,
8709
9815
  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" })
9816
+ footer: /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex justify-end gap-3", children: [
9817
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_antd31.Button, { onClick: onClose, children: "\u53D6\u6D88" }),
9818
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_antd31.Button, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
9819
+ ] }),
9820
+ children: loading && routeList.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_antd31.Skeleton, { active: true, paragraph: { rows: 4 } }) : routeList.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: routeList.map((route, index) => {
9821
+ const isLast = index === routeList.length - 1;
9822
+ return /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex gap-3", children: [
9823
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: "flex flex-col items-center", children: [
9824
+ /* @__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" }) }),
9825
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
9826
+ ] }),
9827
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsxs)("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
9828
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
9829
+ 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: [
9830
+ /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(import_icons10.UserOutlined, { className: "text-gray-400 text-xs" }),
9831
+ route.assignees.map((assignee) => /* @__PURE__ */ (0, import_jsx_runtime88.jsx)(
9832
+ "span",
9833
+ {
9834
+ className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
9835
+ children: assignee.name
9836
+ },
9837
+ assignee.id
9838
+ ))
9839
+ ] })
9840
+ ] })
9841
+ ] }, route.nodeId);
9842
+ }) })
9843
+ }
9844
+ );
9845
+ };
9846
+
9847
+ // src/modules/DataManagementList.tsx
9848
+ var import_react61 = require("react");
9849
+ var import_antd32 = require("antd");
9850
+ var import_icons11 = require("@ant-design/icons");
9851
+ var import_jsx_runtime89 = require("react/jsx-runtime");
9852
+ var createGroup = () => ({
9853
+ id: `group_${Date.now()}_${Math.random().toString(36).slice(2)}`,
9854
+ logic: "AND",
9855
+ rules: [],
9856
+ conditions: []
9857
+ });
9858
+ var createRule = (field) => ({
9859
+ id: `rule_${Date.now()}_${Math.random().toString(36).slice(2)}`,
9860
+ key: field?.fieldId || "",
9861
+ operator: "contains",
9862
+ value: "",
9863
+ componentName: field?.componentName
9864
+ });
9865
+ var getRecordId = (record) => record?.formInstanceId || record?.formInstId || record?.form_instance_id || record?.instanceId || record?.id || record?.processInstanceId;
9866
+ var getSelectedRecordId = (record, fallback) => record?.formInstId || record?.formInstanceId || record?.form_instance_id || record?.id || fallback;
9867
+ var hydrateFilterGroup = (group) => {
9868
+ if (!group) return createGroup();
9869
+ return {
9870
+ id: group.id || createGroup().id,
9871
+ logic: group.logic === "OR" ? "OR" : "AND",
9872
+ rules: Array.isArray(group.rules) ? group.rules.map((rule) => ({
9873
+ ...rule,
9874
+ id: rule.id || `rule_${Date.now()}_${Math.random().toString(36).slice(2)}`
9875
+ })) : [],
9876
+ conditions: Array.isArray(group.conditions) ? group.conditions.map(hydrateFilterGroup) : []
9877
+ };
9878
+ };
9879
+ var formatPrimitive = (value) => {
9880
+ if (value === void 0 || value === null || value === "")
9881
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("span", { className: "text-ant-color-text-quaternary", children: "--" });
9882
+ return String(value);
9883
+ };
9884
+ var pickOptionLabel = (field, value) => {
9885
+ const options = field.options || field.optionList || field.option_list || field.componentProps?.options || [];
9886
+ const scalar = typeof value === "object" ? value?.value ?? value?.id ?? value?.label ?? value?.name : value;
9887
+ const match = Array.isArray(options) ? options.find((option) => String(option.value ?? option.id) === String(scalar)) : void 0;
9888
+ return match?.label || match?.name || value?.label || value?.name || scalar;
9889
+ };
9890
+ var renderStatusTag = (value, fieldId) => {
9891
+ const raw = String(value || "");
9892
+ const statusMap = {
9893
+ pending: { label: "\u5F85\u5904\u7406", color: "processing" },
9894
+ running: { label: "\u5BA1\u6279\u4E2D", color: "processing" },
9895
+ waiting: { label: "\u7B49\u5F85\u4E2D", color: "default" },
9896
+ exception: { label: "\u6D41\u7A0B\u5F02\u5E38", color: "error" },
9897
+ completed: { label: "\u5DF2\u5B8C\u6210", color: "success" },
9898
+ terminated: { label: "\u5DF2\u62D2\u7EDD", color: "error" },
9899
+ withdrawn: { label: "\u5DF2\u64A4\u9500", color: "default" },
9900
+ processing: { label: "\u5BA1\u6279\u4E2D", color: "processing" },
9901
+ approved: { label: "\u540C\u610F", color: "success" },
9902
+ rejected: { label: "\u62D2\u7EDD", color: "error" }
9903
+ };
9904
+ if (fieldId !== "processInstanceStatus" && fieldId !== "approvalResult") return null;
9905
+ const meta = statusMap[raw];
9906
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Tag, { color: meta?.color, children: meta?.label || raw || "--" });
9907
+ };
9908
+ var renderCellValue = (value, field) => {
9909
+ const status = renderStatusTag(value, field.fieldId);
9910
+ if (status) return status;
9911
+ if (Array.isArray(value)) {
9912
+ if (value.length === 0) return formatPrimitive("");
9913
+ if (field.componentName === "ImageField") {
9914
+ 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)(
9915
+ "img",
9916
+ {
9917
+ alt: item?.name || field.label,
9918
+ src: item?.url || item?.previewUrl,
9919
+ className: "h-8 w-8 rounded object-cover"
9920
+ },
9921
+ item?.uid || item?.id || item?.url || index
9922
+ )) });
9923
+ }
9924
+ if (field.componentName === "AttachmentField") {
9925
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { size: 4, wrap: true, children: [
9926
+ 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)),
9927
+ value.length > 3 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Tag, { children: [
9928
+ "+",
9929
+ value.length - 3
9930
+ ] })
9931
+ ] });
9932
+ }
9933
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { size: 4, wrap: true, children: [
9934
+ value.slice(0, 4).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Tag, { children: pickOptionLabel(field, item) }, `${field.fieldId}_${index}`)),
9935
+ value.length > 4 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Tag, { children: [
9936
+ "+",
9937
+ value.length - 4
9938
+ ] })
9939
+ ] });
9940
+ }
9941
+ if (value && typeof value === "object") {
9942
+ if (field.componentName === "UserSelectField" || field.componentName === "DepartmentSelectField") {
9943
+ return value.name || value.label || value.username || formatPrimitive(value.id);
9944
+ }
9945
+ if (value.start || value.end) {
9946
+ return [value.start, value.end].filter(Boolean).join(" \u81F3 ");
9947
+ }
9948
+ if (value.label || value.name || value.value) {
9949
+ return pickOptionLabel(field, value);
9950
+ }
9951
+ 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" }) });
9952
+ }
9953
+ if (["SelectField", "RadioField", "CheckboxField", "MultiSelectField"].includes(field.componentName)) {
9954
+ return pickOptionLabel(field, value);
9955
+ }
9956
+ return formatPrimitive(value);
9957
+ };
9958
+ var fileToBase64 = (file) => new Promise((resolve, reject) => {
9959
+ const reader = new FileReader();
9960
+ reader.onload = () => {
9961
+ const result = String(reader.result || "");
9962
+ resolve(result.includes(",") ? result.split(",")[1] : result);
9963
+ };
9964
+ reader.onerror = reject;
9965
+ reader.readAsDataURL(file);
9966
+ });
9967
+ function FilterGroupEditor({
9968
+ group,
9969
+ fields,
9970
+ onChange,
9971
+ level = 0
9972
+ }) {
9973
+ const fieldOptions = fields.map((field) => ({ label: field.label, value: field.fieldId }));
9974
+ const updateRule = (ruleId, patch) => {
9975
+ onChange({
9976
+ ...group,
9977
+ rules: group.rules.map((rule) => rule.id === ruleId ? { ...rule, ...patch } : rule)
9978
+ });
9979
+ };
9980
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
9981
+ "div",
9982
+ {
9983
+ className: `${level > 0 ? "ml-4 border-l border-ant-border-secondary pl-4" : ""} space-y-3`,
9984
+ children: [
9985
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "flex items-center justify-between", children: [
9986
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
9987
+ import_antd32.Segmented,
9988
+ {
9989
+ size: "small",
9990
+ value: group.logic,
9991
+ options: [
9992
+ { label: "\u6EE1\u8DB3\u5168\u90E8", value: "AND" },
9993
+ { label: "\u6EE1\u8DB3\u4EFB\u4E00", value: "OR" }
9994
+ ],
9995
+ onChange: (value) => onChange({ ...group, logic: value })
9996
+ }
9997
+ ),
9998
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { children: [
9999
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10000
+ import_antd32.Button,
10001
+ {
10002
+ size: "small",
10003
+ onClick: () => onChange({ ...group, rules: [...group.rules, createRule(fields[0])] }),
10004
+ children: "\u6DFB\u52A0\u6761\u4EF6"
10005
+ }
10006
+ ),
10007
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10008
+ import_antd32.Button,
10009
+ {
10010
+ size: "small",
10011
+ onClick: () => onChange({ ...group, conditions: [...group.conditions, createGroup()] }),
10012
+ children: "\u6DFB\u52A0\u5206\u7EC4"
10013
+ }
10014
+ )
10015
+ ] })
10016
+ ] }),
10017
+ group.rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
10018
+ "div",
10019
+ {
10020
+ className: "grid grid-cols-[minmax(120px,1fr)_120px_minmax(160px,1fr)_auto] gap-2",
10021
+ children: [
10022
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10023
+ import_antd32.Select,
10024
+ {
10025
+ showSearch: true,
10026
+ placeholder: "\u5B57\u6BB5",
10027
+ value: rule.key,
10028
+ options: fieldOptions,
10029
+ optionFilterProp: "label",
10030
+ onChange: (fieldId) => {
10031
+ const field = fields.find((item) => item.fieldId === fieldId);
10032
+ updateRule(rule.id, { key: fieldId, componentName: field?.componentName });
10033
+ }
10034
+ }
10035
+ ),
10036
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10037
+ import_antd32.Select,
10038
+ {
10039
+ value: rule.operator,
10040
+ options: [
10041
+ { label: "\u5305\u542B", value: "contains" },
10042
+ { label: "\u7B49\u4E8E", value: "eq" },
10043
+ { label: "\u4E0D\u7B49\u4E8E", value: "ne" },
10044
+ { label: "\u5927\u4E8E", value: "gt" },
10045
+ { label: "\u5C0F\u4E8E", value: "lt" }
10046
+ ],
10047
+ onChange: (operator) => updateRule(rule.id, { operator })
10048
+ }
10049
+ ),
10050
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10051
+ import_antd32.Input,
10052
+ {
10053
+ value: rule.value,
10054
+ placeholder: "\u8F93\u5165\u7B5B\u9009\u503C",
10055
+ onChange: (event) => updateRule(rule.id, { value: event.target.value })
10056
+ }
10057
+ ),
10058
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10059
+ import_antd32.Button,
10060
+ {
10061
+ danger: true,
10062
+ type: "text",
10063
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DeleteOutlined, {}),
10064
+ onClick: () => onChange({ ...group, rules: group.rules.filter((item) => item.id !== rule.id) })
10065
+ }
10066
+ )
10067
+ ]
10068
+ },
10069
+ rule.id
10070
+ )),
10071
+ group.conditions.map((child) => /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10072
+ FilterGroupEditor,
10073
+ {
10074
+ group: child,
10075
+ fields,
10076
+ level: level + 1,
10077
+ onChange: (next) => onChange({
10078
+ ...group,
10079
+ conditions: group.conditions.map((item) => item.id === child.id ? next : item)
10080
+ })
10081
+ },
10082
+ child.id
10083
+ )),
10084
+ 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" })
10085
+ ]
10086
+ }
10087
+ );
10088
+ }
10089
+ var DataManagementList = ({
10090
+ appType,
10091
+ formUuid,
10092
+ menuFormUuid,
10093
+ readonly = false,
10094
+ fullHeight = true,
10095
+ configScope = "global",
10096
+ title,
10097
+ detailRenderer,
10098
+ submitRenderer,
10099
+ requestOverride,
10100
+ rowActions = []
10101
+ }) => {
10102
+ const rootRef = (0, import_react61.useRef)(null);
10103
+ const api = (0, import_react61.useMemo)(() => {
10104
+ if (typeof requestOverride === "function") {
10105
+ return createFormRuntimeApi({ request: requestOverride });
10106
+ }
10107
+ return createFormRuntimeApi(requestOverride);
10108
+ }, [requestOverride]);
10109
+ const [fields, setFields] = (0, import_react61.useState)([]);
10110
+ const [config, setConfig] = (0, import_react61.useState)({});
10111
+ const [showFields, setShowFields] = (0, import_react61.useState)([]);
10112
+ const [lockFieldIds, setLockFieldIds] = (0, import_react61.useState)([]);
10113
+ const [widths, setWidths] = (0, import_react61.useState)({});
10114
+ const [sort, setSort] = (0, import_react61.useState)([]);
10115
+ const [density, setDensity] = (0, import_react61.useState)("middle");
10116
+ const [detailOpenMode, setDetailOpenMode] = (0, import_react61.useState)("drawer");
10117
+ const [searchKeyWord, setSearchKeyWord] = (0, import_react61.useState)("");
10118
+ const [filterGroup, setFilterGroup] = (0, import_react61.useState)(createGroup);
10119
+ const [dataSource, setDataSource] = (0, import_react61.useState)([]);
10120
+ const [total, setTotal] = (0, import_react61.useState)(0);
10121
+ const [current, setCurrent] = (0, import_react61.useState)(1);
10122
+ const [pageSize, setPageSize] = (0, import_react61.useState)(10);
10123
+ const [loading, setLoading] = (0, import_react61.useState)(false);
10124
+ const [schemaLoading, setSchemaLoading] = (0, import_react61.useState)(true);
10125
+ const [selectedRowKeys, setSelectedRowKeys] = (0, import_react61.useState)([]);
10126
+ const [filterOpen, setFilterOpen] = (0, import_react61.useState)(false);
10127
+ const [columnOpen, setColumnOpen] = (0, import_react61.useState)(false);
10128
+ const [exportOpen, setExportOpen] = (0, import_react61.useState)(false);
10129
+ const [exportScope, setExportScope] = (0, import_react61.useState)("all");
10130
+ const [exportFields, setExportFields] = (0, import_react61.useState)([]);
10131
+ const [exporting, setExporting] = (0, import_react61.useState)(false);
10132
+ const [importOpen, setImportOpen] = (0, import_react61.useState)(false);
10133
+ const [importPreview, setImportPreview] = (0, import_react61.useState)([]);
10134
+ const [importBase64, setImportBase64] = (0, import_react61.useState)("");
10135
+ const [recordsOpen, setRecordsOpen] = (0, import_react61.useState)(false);
10136
+ const [recordTab, setRecordTab] = (0, import_react61.useState)("export");
10137
+ const [transferRecords, setTransferRecords] = (0, import_react61.useState)([]);
10138
+ const [batchApprovalOpen, setBatchApprovalOpen] = (0, import_react61.useState)(false);
10139
+ const [batchApprovalAction, setBatchApprovalAction] = (0, import_react61.useState)(
10140
+ "approved"
10141
+ );
10142
+ const [batchApprovalComments, setBatchApprovalComments] = (0, import_react61.useState)("");
10143
+ const [batchApproving, setBatchApproving] = (0, import_react61.useState)(false);
10144
+ const [activeRecord, setActiveRecord] = (0, import_react61.useState)(null);
10145
+ const [detailOpen, setDetailOpen] = (0, import_react61.useState)(false);
10146
+ const [submitOpen, setSubmitOpen] = (0, import_react61.useState)(false);
10147
+ const fetchStateRef = (0, import_react61.useRef)({});
10148
+ const request = api.request;
10149
+ const getPopupContainer = (0, import_react61.useCallback)(
10150
+ (triggerNode) => triggerNode?.parentElement || rootRef.current || document.body,
10151
+ []
10152
+ );
10153
+ const confirmDanger = (0, import_react61.useCallback)((title2, content, onOk) => {
10154
+ if (confirmAction(title2, content)) onOk();
10155
+ }, []);
10156
+ const visibleFields = (0, import_react61.useMemo)(
10157
+ () => showFields.map((fieldId) => fields.find((field) => field.fieldId === fieldId)).filter(Boolean),
10158
+ [fields, showFields]
10159
+ );
10160
+ (0, import_react61.useEffect)(() => {
10161
+ fetchStateRef.current = {
10162
+ current,
10163
+ pageSize,
10164
+ searchKeyWord,
10165
+ filterGroup,
10166
+ sort
10167
+ };
10168
+ }, [current, filterGroup, pageSize, searchKeyWord, sort]);
10169
+ const loadData = (0, import_react61.useCallback)(
10170
+ async (overrides = {}) => {
10171
+ if (!appType || !formUuid) return;
10172
+ const fetchState = { ...fetchStateRef.current, ...overrides };
10173
+ const nextCurrent = fetchState.current || 1;
10174
+ const nextPageSize = fetchState.pageSize || 10;
10175
+ fetchStateRef.current = {
10176
+ ...fetchState,
10177
+ current: nextCurrent,
10178
+ pageSize: nextPageSize
10179
+ };
10180
+ setLoading(true);
10181
+ try {
10182
+ const result = await advancedSearchDataManagement(request, {
10183
+ appType,
10184
+ formUuid,
10185
+ currentPage: nextCurrent,
10186
+ pageSize: nextPageSize,
10187
+ searchKeyWord: fetchState.searchKeyWord,
10188
+ filters: fetchState.filterGroup,
10189
+ order: fetchState.sort
10190
+ });
10191
+ setDataSource(result.records);
10192
+ setTotal(result.total);
10193
+ setCurrent(nextCurrent);
10194
+ setPageSize(nextPageSize);
10195
+ } catch (error) {
10196
+ console.error("[DataManagementList] loadData failed:", error);
10197
+ import_antd32.message.error("\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
10198
+ } finally {
10199
+ setLoading(false);
10200
+ }
10201
+ },
10202
+ [appType, formUuid, request]
10203
+ );
10204
+ (0, import_react61.useEffect)(() => {
10205
+ let mounted = true;
10206
+ const loadSchemaAndConfig = async () => {
10207
+ if (!appType || !formUuid) return;
10208
+ setSchemaLoading(true);
10209
+ setDataSource([]);
10210
+ setTotal(0);
10211
+ setSelectedRowKeys([]);
10212
+ try {
10213
+ const schemaResult = await getDataManagementSchema(request, { appType, formUuid });
10214
+ if (!mounted) return;
10215
+ const allFields = [
10216
+ ...schemaResult.fields,
10217
+ ...getSystemFieldsForFormType(schemaResult.formType)
10218
+ ];
10219
+ const saved = await getDataManagementConfig(request, {
10220
+ appType,
10221
+ formUuid,
10222
+ menuFormUuid,
10223
+ scope: configScope
10224
+ }).catch(() => void 0);
10225
+ if (!mounted) return;
10226
+ const resolved = normalizeColumnConfig(saved, allFields);
10227
+ const nextSearchKeyWord = saved?.filter?.searchKeyWord || "";
10228
+ const nextFilterGroup = hydrateFilterGroup(saved?.filter?.group);
10229
+ setFields(allFields);
10230
+ setConfig(saved || {});
10231
+ setShowFields(resolved.showFields);
10232
+ setWidths(resolved.widths);
10233
+ setLockFieldIds(resolved.lockFieldIds);
10234
+ setSort(resolved.sort);
10235
+ setDensity(resolved.density);
10236
+ setDetailOpenMode(resolved.detailOpenMode);
10237
+ setPageSize(resolved.pageSize);
10238
+ setSearchKeyWord(nextSearchKeyWord);
10239
+ setFilterGroup(nextFilterGroup);
10240
+ await loadData({
10241
+ current: 1,
10242
+ pageSize: resolved.pageSize,
10243
+ searchKeyWord: nextSearchKeyWord,
10244
+ filterGroup: nextFilterGroup,
10245
+ sort: resolved.sort
10246
+ });
10247
+ } catch (error) {
10248
+ console.error("[DataManagementList] load schema failed:", error);
10249
+ import_antd32.message.error("\u52A0\u8F7D\u8868\u5355\u914D\u7F6E\u5931\u8D25");
10250
+ } finally {
10251
+ if (mounted) setSchemaLoading(false);
10252
+ }
10253
+ };
10254
+ loadSchemaAndConfig();
10255
+ return () => {
10256
+ mounted = false;
10257
+ };
10258
+ }, [appType, configScope, formUuid, loadData, menuFormUuid, request]);
10259
+ const persistConfig = (0, import_react61.useCallback)(
10260
+ async (patch) => {
10261
+ const nextConfig = { ...config, ...patch };
10262
+ setConfig(nextConfig);
10263
+ await saveDataManagementConfig(request, {
10264
+ appType,
10265
+ formUuid,
10266
+ menuFormUuid,
10267
+ scope: configScope,
10268
+ config: nextConfig
10269
+ }).catch((error) => {
10270
+ console.error("[DataManagementList] save config failed:", error);
10271
+ import_antd32.message.warning("\u914D\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u672C\u6B21\u4EC5\u5728\u5F53\u524D\u9875\u9762\u751F\u6548");
10272
+ });
10273
+ },
10274
+ [appType, config, configScope, formUuid, menuFormUuid, request]
10275
+ );
10276
+ const handleColumnCommit = async () => {
10277
+ setColumnOpen(false);
10278
+ await persistConfig({
10279
+ showFields,
10280
+ lockFieldIds,
10281
+ widths,
10282
+ density,
10283
+ detailOpenMode,
10284
+ pageSize
10285
+ });
10286
+ };
10287
+ const handleDetail = (0, import_react61.useCallback)(
10288
+ (record) => {
10289
+ const formInstanceId = getRecordId(record);
10290
+ if (detailOpenMode === "newPage" && typeof window !== "undefined") {
10291
+ window.open(`/${appType}/forms/${formUuid}/detail/${formInstanceId}`, "_blank");
10292
+ return;
10293
+ }
10294
+ setActiveRecord(record);
10295
+ setDetailOpen(true);
10296
+ },
10297
+ [appType, detailOpenMode, formUuid]
10298
+ );
10299
+ const handleDelete = (0, import_react61.useCallback)(
10300
+ async (ids) => {
10301
+ if (ids.length === 0) return;
10302
+ await deleteDataManagementRows(request, { appType, formUuid, formInstanceIds: ids });
10303
+ setSelectedRowKeys([]);
10304
+ await loadData({ current, pageSize });
10305
+ },
10306
+ [appType, current, formUuid, loadData, pageSize, request]
10307
+ );
10308
+ const getSelectedRecordIds = (0, import_react61.useCallback)(
10309
+ () => selectedRowKeys.map((key) => {
10310
+ const record = dataSource.find((item) => String(getRecordId(item)) === String(key));
10311
+ return String(getSelectedRecordId(record, key));
10312
+ }),
10313
+ [dataSource, selectedRowKeys]
10314
+ );
10315
+ const handleBatchApprove = () => {
10316
+ if (selectedRowKeys.length === 0) return;
10317
+ setBatchApprovalOpen(true);
10318
+ };
10319
+ const handleBatchApprovalConfirm = async () => {
10320
+ const ids = getSelectedRecordIds();
10321
+ if (ids.length === 0) return;
10322
+ setBatchApproving(true);
10323
+ try {
10324
+ await batchApproveDataManagementRows(request, {
10325
+ appType,
10326
+ formUuid,
10327
+ formInstanceIds: ids,
10328
+ action: batchApprovalAction,
10329
+ comments: batchApprovalComments || void 0
10330
+ });
10331
+ import_antd32.message.success(`\u6279\u91CF${batchApprovalAction === "approved" ? "\u901A\u8FC7" : "\u62D2\u7EDD"}\u5DF2\u63D0\u4EA4`);
10332
+ setSelectedRowKeys([]);
10333
+ setBatchApprovalOpen(false);
10334
+ setBatchApprovalAction("approved");
10335
+ setBatchApprovalComments("");
10336
+ await loadData({ current, pageSize });
10337
+ } catch (error) {
10338
+ console.error("[DataManagementList] batch approval failed:", error);
10339
+ import_antd32.message.error("\u6279\u91CF\u5BA1\u6279\u5931\u8D25");
10340
+ } finally {
10341
+ setBatchApproving(false);
10342
+ }
10343
+ };
10344
+ const handleExport = async (scope) => {
10345
+ const selectedIds = scope === "selected" ? getSelectedRecordIds() : [];
10346
+ if (scope === "selected" && selectedIds.length === 0) {
10347
+ import_antd32.message.warning("\u8BF7\u5148\u9009\u62E9\u8981\u5BFC\u51FA\u7684\u8BB0\u5F55");
10348
+ return;
10349
+ }
10350
+ const selectedFilters = selectedIds.map((id) => ({
10351
+ key: "form_instance_id",
10352
+ operator: "EQ",
10353
+ value: id
10354
+ }));
10355
+ setExporting(true);
10356
+ try {
10357
+ await exportDataManagementRows(request, {
10358
+ appType,
10359
+ formUuid,
10360
+ currentPage: scope === "selected" ? 1 : current,
10361
+ pageSize: scope === "selected" ? selectedIds.length : pageSize,
10362
+ searchKeyWord: scope === "selected" ? void 0 : searchKeyWord,
10363
+ filters: scope === "selected" ? void 0 : filterGroup,
10364
+ rawFilters: scope === "selected" ? JSON.stringify(selectedFilters) : void 0,
10365
+ conditionType: scope === "selected" ? "OR" : void 0,
10366
+ order: sort,
10367
+ exportAll: scope === "all" ? "y" : "n",
10368
+ exportFields
10369
+ });
10370
+ import_antd32.message.success("\u5BFC\u51FA\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF0C\u53EF\u5728\u5BFC\u5165\u5BFC\u51FA\u8BB0\u5F55\u4E2D\u67E5\u770B");
10371
+ setExportOpen(false);
10372
+ } catch (error) {
10373
+ console.error("[DataManagementList] export failed:", error);
10374
+ import_antd32.message.error("\u5BFC\u51FA\u5931\u8D25");
10375
+ } finally {
10376
+ setExporting(false);
10377
+ }
10378
+ };
10379
+ const loadTransferRecords = async (type) => {
10380
+ setRecordTab(type);
10381
+ setRecordsOpen(true);
10382
+ const result = await getDataManagementTransferRecords(request, {
10383
+ appType,
10384
+ formUuid,
10385
+ type,
10386
+ currentPage: 1,
10387
+ pageSize: 10
10388
+ });
10389
+ setTransferRecords(result.records);
10390
+ };
10391
+ const handleImportPreview = async (file) => {
10392
+ const base64 = await fileToBase64(file);
10393
+ setImportBase64(base64);
10394
+ const result = await importPreviewDataManagementRows(request, {
10395
+ appType,
10396
+ formUuid,
10397
+ fileBase64: base64
10398
+ });
10399
+ const records = result?.data || result?.records || result?.list || result || [];
10400
+ setImportPreview(Array.isArray(records) ? records : []);
10401
+ return false;
10402
+ };
10403
+ const handleImportConfirm = async () => {
10404
+ if (!importBase64) return;
10405
+ await importDataManagementRows(request, { appType, formUuid, fileBase64: importBase64 });
10406
+ import_antd32.message.success("\u5BFC\u5165\u4EFB\u52A1\u5DF2\u521B\u5EFA");
10407
+ setImportOpen(false);
10408
+ setImportPreview([]);
10409
+ setImportBase64("");
10410
+ await loadData({ current: 1, pageSize });
10411
+ };
10412
+ const columns = (0, import_react61.useMemo)(() => {
10413
+ const baseColumns = visibleFields.map((field) => ({
10414
+ title: field.label,
10415
+ dataIndex: field.fieldId,
10416
+ key: field.fieldId,
10417
+ width: widths[field.fieldId] || field.width || 160,
10418
+ fixed: lockFieldIds.includes(field.fieldId) ? "left" : void 0,
10419
+ ellipsis: true,
10420
+ sorter: true,
10421
+ render: (value) => renderCellValue(value, field)
10422
+ })) || [];
10423
+ return [
10424
+ ...baseColumns,
10425
+ {
10426
+ title: "\u64CD\u4F5C",
10427
+ key: "__actions",
10428
+ width: 148,
10429
+ fixed: "right",
10430
+ render: (_, record) => /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { size: 4, children: [
10431
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { type: "link", size: "small", onClick: () => handleDetail(record), children: "\u8BE6\u60C5" }),
10432
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10433
+ import_antd32.Dropdown,
10434
+ {
10435
+ trigger: ["click"],
10436
+ getPopupContainer,
10437
+ menu: {
10438
+ items: [
10439
+ ...rowActions.map((action) => ({
10440
+ key: action.key,
10441
+ label: action.label,
10442
+ danger: action.danger,
10443
+ onClick: () => action.onClick(record)
10444
+ })),
10445
+ {
10446
+ key: "workflow",
10447
+ label: "\u6D41\u7A0B\u65E5\u5FD7",
10448
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.HistoryOutlined, {}),
10449
+ onClick: () => import_antd32.message.info("\u8BF7\u901A\u8FC7 detailRenderer \u63A5\u5165\u6D41\u7A0B\u65E5\u5FD7\u6216\u6D41\u7A0B\u56FE\u5165\u53E3")
10450
+ },
10451
+ ...!readonly ? [
10452
+ {
10453
+ key: "delete",
10454
+ label: "\u5220\u9664",
10455
+ danger: true,
10456
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DeleteOutlined, {}),
10457
+ onClick: () => confirmDanger(
10458
+ "\u786E\u8BA4\u5220\u9664",
10459
+ "\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F",
10460
+ () => handleDelete([String(getRecordId(record))])
10461
+ )
10462
+ }
10463
+ ] : []
10464
+ ]
10465
+ },
10466
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { type: "text", size: "small", icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.MoreOutlined, {}) })
10467
+ }
10468
+ )
10469
+ ] })
10470
+ }
10471
+ ];
10472
+ }, [
10473
+ confirmDanger,
10474
+ getPopupContainer,
10475
+ handleDelete,
10476
+ handleDetail,
10477
+ lockFieldIds,
10478
+ readonly,
10479
+ rowActions,
10480
+ visibleFields,
10481
+ widths
10482
+ ]);
10483
+ const tableSize = density === "compact" ? "small" : density === "loose" ? "large" : "middle";
10484
+ const importPreviewColumns = (0, import_react61.useMemo)(() => {
10485
+ const keys = Array.from(
10486
+ new Set(importPreview.flatMap((record) => Object.keys(record || {})))
10487
+ ).slice(0, 16);
10488
+ return keys.map((key) => {
10489
+ const field = fields.find((item) => item.fieldId === key || item.id === key);
10490
+ return {
10491
+ title: field?.label || key,
10492
+ dataIndex: key,
10493
+ key,
10494
+ width: 150,
10495
+ ellipsis: true,
10496
+ render: (value) => field ? renderCellValue(value, field) : formatPrimitive(value)
10497
+ };
10498
+ });
10499
+ }, [fields, importPreview]);
10500
+ return /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.ConfigProvider, { getPopupContainer, children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { ref: rootRef, className: `${fullHeight ? "h-full min-h-full" : ""} bg-ant-bg-layout`, children: [
10501
+ /* @__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: [
10502
+ /* @__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: [
10503
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10504
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("h1", { className: "text-xl font-semibold text-ant-color-text", children: title || "\u6570\u636E\u7BA1\u7406" }),
10505
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("p", { className: "mt-1 text-sm text-ant-color-text-secondary", children: [
10506
+ "\u5171 ",
10507
+ total,
10508
+ " \u6761\u6570\u636E\uFF0C\u5DF2\u9009\u62E9 ",
10509
+ selectedRowKeys.length,
10510
+ " \u6761"
10511
+ ] })
10512
+ ] }),
10513
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { wrap: true, children: [
10514
+ !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" }),
10515
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10516
+ import_antd32.Input.Search,
10517
+ {
10518
+ allowClear: true,
10519
+ className: "w-[260px]",
10520
+ placeholder: "\u641C\u7D22\u5173\u952E\u5B57",
10521
+ value: searchKeyWord,
10522
+ onChange: (event) => setSearchKeyWord(event.target.value),
10523
+ onSearch: (value) => {
10524
+ const nextSearchKeyWord = String(value || "");
10525
+ setSearchKeyWord(nextSearchKeyWord);
10526
+ persistConfig({
10527
+ filter: { searchKeyWord: nextSearchKeyWord, group: filterGroup }
10528
+ });
10529
+ loadData({
10530
+ current: 1,
10531
+ pageSize,
10532
+ searchKeyWord: nextSearchKeyWord,
10533
+ filterGroup
10534
+ });
10535
+ }
10536
+ }
10537
+ ),
10538
+ /* @__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" }),
10539
+ /* @__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" }),
10540
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10541
+ import_antd32.Dropdown,
10542
+ {
10543
+ getPopupContainer,
10544
+ menu: {
10545
+ items: [
10546
+ {
10547
+ key: "selected",
10548
+ label: "\u5BFC\u51FA\u9009\u4E2D",
10549
+ disabled: selectedRowKeys.length === 0,
10550
+ onClick: () => {
10551
+ setExportScope("selected");
10552
+ setExportFields(showFields);
10553
+ setExportOpen(true);
10554
+ }
10555
+ },
10556
+ {
10557
+ key: "all",
10558
+ label: "\u5BFC\u51FA\u5168\u90E8",
10559
+ onClick: () => {
10560
+ setExportScope("all");
10561
+ setExportFields(showFields);
10562
+ setExportOpen(true);
10563
+ }
10564
+ },
10565
+ {
10566
+ key: "records",
10567
+ label: "\u5BFC\u51FA\u8BB0\u5F55",
10568
+ onClick: () => loadTransferRecords("export")
10569
+ }
10570
+ ]
10571
+ },
10572
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DownloadOutlined, {}), children: "\u5BFC\u51FA" })
10573
+ }
10574
+ ),
10575
+ !readonly && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10576
+ import_antd32.Dropdown,
10577
+ {
10578
+ getPopupContainer,
10579
+ menu: {
10580
+ items: [
10581
+ { key: "import", label: "\u5BFC\u5165\u6570\u636E", onClick: () => setImportOpen(true) },
10582
+ {
10583
+ key: "records",
10584
+ label: "\u5BFC\u5165\u8BB0\u5F55",
10585
+ onClick: () => loadTransferRecords("import")
10586
+ }
10587
+ ]
10588
+ },
10589
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.ImportOutlined, {}), children: "\u5BFC\u5165" })
10590
+ }
10591
+ ),
10592
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.ReloadOutlined, {}), onClick: () => loadData({ current, pageSize }) })
10593
+ ] })
10594
+ ] }),
10595
+ selectedRowKeys.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "mb-3 flex flex-wrap items-center justify-between gap-3 rounded-lg border border-ant-border-secondary bg-ant-bg-container px-4 py-3 shadow-sm", children: [
10596
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("span", { className: "text-sm text-ant-color-text-secondary", children: [
10597
+ "\u5DF2\u9009 ",
10598
+ selectedRowKeys.length,
10599
+ " \u6761"
10600
+ ] }),
10601
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { wrap: true, children: [
10602
+ !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" }),
10603
+ !readonly && /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10604
+ import_antd32.Button,
10605
+ {
10606
+ danger: true,
10607
+ icon: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_icons11.DeleteOutlined, {}),
10608
+ onClick: () => confirmDanger(
10609
+ "\u786E\u8BA4\u6279\u91CF\u5220\u9664",
10610
+ `\u5C06\u5220\u9664 ${selectedRowKeys.length} \u6761\u6570\u636E\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F`,
10611
+ () => handleDelete(selectedRowKeys.map(String))
10612
+ ),
10613
+ children: "\u6279\u91CF\u5220\u9664"
10614
+ }
10615
+ ),
10616
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { type: "link", onClick: () => setSelectedRowKeys([]), children: "\u53D6\u6D88\u9009\u62E9" })
10617
+ ] })
8713
10618
  ] }),
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) => {
8715
- 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" })
10619
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "relative flex-1 overflow-hidden rounded-lg border border-ant-border-secondary bg-ant-bg-container", children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10620
+ import_antd32.Table,
10621
+ {
10622
+ rowKey: (record) => String(getRecordId(record)),
10623
+ loading: loading || schemaLoading,
10624
+ columns,
10625
+ dataSource,
10626
+ size: tableSize,
10627
+ scroll: {
10628
+ x: Math.max(900, visibleFields.length * 160),
10629
+ y: fullHeight ? selectedRowKeys.length > 0 ? "calc(100vh - 320px)" : "calc(100vh - 260px)" : void 0
10630
+ },
10631
+ rowSelection: {
10632
+ selectedRowKeys,
10633
+ onChange: setSelectedRowKeys
10634
+ },
10635
+ pagination: {
10636
+ current,
10637
+ pageSize,
10638
+ total,
10639
+ showSizeChanger: true,
10640
+ showTotal: (count) => `\u5171 ${count} \u6761`
10641
+ },
10642
+ onChange: (pagination, _filters, sorter) => {
10643
+ const sorters = Array.isArray(sorter) ? sorter : [sorter];
10644
+ const nextSort = sorters.filter((item) => item?.field && item?.order).map((item) => ({
10645
+ id: String(item.field),
10646
+ isAsc: item.order === "ascend" ? "y" : "n"
10647
+ }));
10648
+ setSort(nextSort);
10649
+ persistConfig({ sort: nextSort });
10650
+ loadData({
10651
+ current: pagination.current || 1,
10652
+ pageSize: pagination.pageSize || pageSize,
10653
+ sort: nextSort
10654
+ });
10655
+ }
10656
+ }
10657
+ ) })
10658
+ ] }),
10659
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10660
+ import_antd32.Modal,
10661
+ {
10662
+ getContainer: false,
10663
+ title: "\u9AD8\u7EA7\u7B5B\u9009",
10664
+ open: filterOpen,
10665
+ width: 760,
10666
+ onCancel: () => setFilterOpen(false),
10667
+ onOk: () => {
10668
+ setFilterOpen(false);
10669
+ persistConfig({ filter: { searchKeyWord, group: filterGroup } });
10670
+ loadData({ current: 1, pageSize, searchKeyWord, filterGroup });
10671
+ },
10672
+ okText: "\u5E94\u7528\u7B5B\u9009",
10673
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(FilterGroupEditor, { group: filterGroup, fields, onChange: setFilterGroup })
10674
+ }
10675
+ ),
10676
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10677
+ import_antd32.Modal,
10678
+ {
10679
+ getContainer: false,
10680
+ title: "\u5217\u8BBE\u7F6E",
10681
+ open: columnOpen,
10682
+ width: 720,
10683
+ onCancel: () => setColumnOpen(false),
10684
+ onOk: handleColumnCommit,
10685
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "space-y-5", children: [
10686
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10687
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u663E\u793A\u5217" }),
10688
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10689
+ import_antd32.Checkbox.Group,
10690
+ {
10691
+ className: "grid grid-cols-2 gap-2 md:grid-cols-3",
10692
+ value: showFields,
10693
+ options: fields.map((field) => ({ label: field.label, value: field.fieldId })),
10694
+ onChange: (values) => setShowFields(values.map(String))
10695
+ }
10696
+ )
8720
10697
  ] }),
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",
10698
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10699
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u51BB\u7ED3\u5217" }),
10700
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10701
+ import_antd32.Select,
10702
+ {
10703
+ mode: "multiple",
10704
+ className: "w-full",
10705
+ value: lockFieldIds,
10706
+ options: showFields.map((fieldId) => {
10707
+ const field = fields.find((item) => item.fieldId === fieldId);
10708
+ return { label: field?.label || fieldId, value: fieldId };
10709
+ }),
10710
+ onChange: setLockFieldIds
10711
+ }
10712
+ )
10713
+ ] }),
10714
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "grid gap-4 md:grid-cols-3", children: [
10715
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10716
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u8868\u683C\u5BC6\u5EA6" }),
10717
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10718
+ import_antd32.Segmented,
8727
10719
  {
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
- ))
10720
+ block: true,
10721
+ value: density,
10722
+ options: [
10723
+ { label: "\u7D27\u51D1", value: "compact" },
10724
+ { label: "\u6807\u51C6", value: "middle" },
10725
+ { label: "\u5BBD\u677E", value: "loose" }
10726
+ ],
10727
+ onChange: (value) => setDensity(value)
10728
+ }
10729
+ )
10730
+ ] }),
10731
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10732
+ /* @__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" }),
10733
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10734
+ import_antd32.Segmented,
10735
+ {
10736
+ block: true,
10737
+ value: detailOpenMode,
10738
+ options: [
10739
+ { label: "\u62BD\u5C49", value: "drawer" },
10740
+ { label: "\u65B0\u9875", value: "newPage" }
10741
+ ],
10742
+ onChange: (value) => setDetailOpenMode(value)
10743
+ }
10744
+ )
10745
+ ] }),
10746
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { children: [
10747
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u9875\u5927\u5C0F" }),
10748
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10749
+ import_antd32.Select,
10750
+ {
10751
+ className: "w-full",
10752
+ value: pageSize,
10753
+ options: [10, 20, 50, 100].map((value) => ({ label: `${value} \u6761`, value })),
10754
+ onChange: setPageSize
10755
+ }
10756
+ )
8733
10757
  ] })
8734
10758
  ] })
8735
- ] }, route.nodeId);
8736
- }) })
8737
- }
8738
- );
10759
+ ] })
10760
+ }
10761
+ ),
10762
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10763
+ import_antd32.Modal,
10764
+ {
10765
+ getContainer: false,
10766
+ title: exportScope === "selected" ? "\u5BFC\u51FA\u9009\u4E2D\u6570\u636E" : "\u5BFC\u51FA\u5168\u90E8\u6570\u636E",
10767
+ open: exportOpen,
10768
+ onCancel: () => setExportOpen(false),
10769
+ footer: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(import_antd32.Space, { children: [
10770
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Button, { onClick: () => setExportOpen(false), children: "\u53D6\u6D88" }),
10771
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10772
+ import_antd32.Button,
10773
+ {
10774
+ type: "primary",
10775
+ loading: exporting,
10776
+ disabled: exportScope === "selected" && selectedRowKeys.length === 0,
10777
+ onClick: () => handleExport(exportScope),
10778
+ children: exportScope === "selected" ? `\u5BFC\u51FA\u9009\u4E2D (${selectedRowKeys.length})` : "\u5BFC\u51FA\u5168\u90E8"
10779
+ }
10780
+ )
10781
+ ] }),
10782
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10783
+ import_antd32.Checkbox.Group,
10784
+ {
10785
+ className: "grid grid-cols-2 gap-2",
10786
+ value: exportFields,
10787
+ options: fields.map((field) => ({ label: field.label, value: field.fieldId })),
10788
+ onChange: (values) => setExportFields(values.map(String))
10789
+ }
10790
+ )
10791
+ }
10792
+ ),
10793
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10794
+ import_antd32.Modal,
10795
+ {
10796
+ getContainer: false,
10797
+ title: "\u6279\u91CF\u5BA1\u6279",
10798
+ open: batchApprovalOpen,
10799
+ onCancel: () => setBatchApprovalOpen(false),
10800
+ onOk: handleBatchApprovalConfirm,
10801
+ okText: batchApprovalAction === "approved" ? "\u786E\u8BA4\u901A\u8FC7" : "\u786E\u8BA4\u62D2\u7EDD",
10802
+ confirmLoading: batchApproving,
10803
+ children: /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "space-y-4", children: [
10804
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "text-sm text-ant-color-text-secondary", children: [
10805
+ "\u5DF2\u9009\u62E9 ",
10806
+ selectedRowKeys.length,
10807
+ " \u6761\u8BB0\u5F55"
10808
+ ] }),
10809
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10810
+ import_antd32.Segmented,
10811
+ {
10812
+ block: true,
10813
+ value: batchApprovalAction,
10814
+ options: [
10815
+ { label: "\u540C\u610F", value: "approved" },
10816
+ { label: "\u62D2\u7EDD", value: "rejected" }
10817
+ ],
10818
+ onChange: (value) => setBatchApprovalAction(value)
10819
+ }
10820
+ ),
10821
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10822
+ import_antd32.Input.TextArea,
10823
+ {
10824
+ value: batchApprovalComments,
10825
+ rows: 4,
10826
+ maxLength: 500,
10827
+ showCount: true,
10828
+ placeholder: "\u586B\u5199\u5BA1\u6279\u610F\u89C1",
10829
+ onChange: (event) => setBatchApprovalComments(event.target.value)
10830
+ }
10831
+ )
10832
+ ] })
10833
+ }
10834
+ ),
10835
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
10836
+ import_antd32.Modal,
10837
+ {
10838
+ getContainer: false,
10839
+ title: "\u5BFC\u5165\u6570\u636E",
10840
+ open: importOpen,
10841
+ width: 720,
10842
+ onCancel: () => setImportOpen(false),
10843
+ onOk: handleImportConfirm,
10844
+ okButtonProps: { disabled: !importBase64 },
10845
+ okText: "\u786E\u8BA4\u5BFC\u5165",
10846
+ children: [
10847
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10848
+ import_antd32.Upload.Dragger,
10849
+ {
10850
+ accept: ".xlsx,.xls",
10851
+ maxCount: 1,
10852
+ beforeUpload: handleImportPreview,
10853
+ onRemove: () => {
10854
+ setImportBase64("");
10855
+ setImportPreview([]);
10856
+ },
10857
+ 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" })
10858
+ }
10859
+ ),
10860
+ importPreview.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)("div", { className: "mt-4", children: [
10861
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u5BFC\u5165\u9884\u89C8" }),
10862
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10863
+ import_antd32.Table,
10864
+ {
10865
+ size: "small",
10866
+ dataSource: importPreview,
10867
+ columns: importPreviewColumns,
10868
+ scroll: { x: Math.max(600, (importPreviewColumns?.length || 0) * 150) },
10869
+ pagination: false,
10870
+ rowKey: (_, index) => String(index)
10871
+ }
10872
+ )
10873
+ ] })
10874
+ ]
10875
+ }
10876
+ ),
10877
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsxs)(
10878
+ import_antd32.Drawer,
10879
+ {
10880
+ getContainer: false,
10881
+ title: recordTab === "import" ? "\u5BFC\u5165\u8BB0\u5F55" : "\u5BFC\u51FA\u8BB0\u5F55",
10882
+ open: recordsOpen,
10883
+ width: 720,
10884
+ onClose: () => setRecordsOpen(false),
10885
+ children: [
10886
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10887
+ import_antd32.Segmented,
10888
+ {
10889
+ value: recordTab,
10890
+ options: [
10891
+ { label: "\u5BFC\u5165\u8BB0\u5F55", value: "import" },
10892
+ { label: "\u5BFC\u51FA\u8BB0\u5F55", value: "export" }
10893
+ ],
10894
+ onChange: (value) => loadTransferRecords(value)
10895
+ }
10896
+ ),
10897
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10898
+ import_antd32.Table,
10899
+ {
10900
+ className: "mt-4",
10901
+ size: "small",
10902
+ dataSource: transferRecords,
10903
+ rowKey: (record) => record.id || record.recordId
10904
+ }
10905
+ )
10906
+ ]
10907
+ }
10908
+ ),
10909
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10910
+ import_antd32.Drawer,
10911
+ {
10912
+ getContainer: false,
10913
+ title: "\u8BE6\u60C5",
10914
+ open: detailOpen,
10915
+ width: 720,
10916
+ onClose: () => setDetailOpen(false),
10917
+ destroyOnClose: true,
10918
+ children: activeRecord && detailRenderer ? detailRenderer({
10919
+ record: activeRecord,
10920
+ formInstanceId: String(getRecordId(activeRecord)),
10921
+ onClose: () => setDetailOpen(false)
10922
+ }) : /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Empty, { description: "\u8BF7\u901A\u8FC7 detailRenderer \u63A5\u5165\u8BE6\u60C5\u6A21\u677F" })
10923
+ }
10924
+ ),
10925
+ /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(
10926
+ import_antd32.Drawer,
10927
+ {
10928
+ getContainer: false,
10929
+ title: "\u65B0\u589E\u6570\u636E",
10930
+ open: submitOpen,
10931
+ width: 720,
10932
+ onClose: () => setSubmitOpen(false),
10933
+ destroyOnClose: true,
10934
+ children: submitRenderer ? submitRenderer({
10935
+ onClose: () => setSubmitOpen(false),
10936
+ onSubmitted: () => {
10937
+ setSubmitOpen(false);
10938
+ loadData({ current: 1, pageSize });
10939
+ }
10940
+ }) : /* @__PURE__ */ (0, import_jsx_runtime89.jsx)(import_antd32.Empty, { description: "\u8BF7\u901A\u8FC7 submitRenderer \u63A5\u5165\u63D0\u4EA4\u6A21\u677F" })
10941
+ }
10942
+ )
10943
+ ] }) });
8739
10944
  };
8740
10945
 
8741
10946
  // 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");
10947
+ var import_react62 = require("react");
10948
+ var import_antd33 = require("antd");
10949
+ var import_icons12 = require("@ant-design/icons");
10950
+ var import_jsx_runtime90 = require("react/jsx-runtime");
8746
10951
  var pickFormInstanceId = (value) => {
8747
10952
  if (!value) return void 0;
8748
10953
  if (typeof value === "string") return value;
@@ -8759,22 +10964,22 @@ var SubmitSuccessCard = ({
8759
10964
  renderSuccess
8760
10965
  }) => {
8761
10966
  if (renderSuccess) {
8762
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(import_jsx_runtime84.Fragment, { children: renderSuccess(info) });
10967
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_jsx_runtime90.Fragment, { children: renderSuccess(info) });
8763
10968
  }
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" })
10969
+ 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: [
10970
+ /* @__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" }) }),
10971
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
10972
+ /* @__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" }),
10973
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "flex gap-3", children: [
10974
+ (mode === "stay" || mode === "redirect") && /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_antd33.Button, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
10975
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(import_antd33.Button, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
8771
10976
  ] }),
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: [
10977
+ isRedirecting && /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "mt-6 w-48", children: [
10978
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
8774
10979
  countdown,
8775
10980
  "\u79D2\u540E\u81EA\u52A8\u8DF3\u8F6C"
8776
10981
  ] }),
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)(
10982
+ /* @__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
10983
  "div",
8779
10984
  {
8780
10985
  className: "h-full bg-blue-500 transition-all duration-1000",
@@ -8790,18 +10995,28 @@ var InnerFormContent = ({
8790
10995
  formType,
8791
10996
  submitSuccessMode,
8792
10997
  enableDraft,
10998
+ enableProcessPreview,
10999
+ enableSubmissionDepartmentSelect,
11000
+ departmentOptions,
8793
11001
  header,
8794
11002
  footer,
8795
11003
  beforeForm,
8796
11004
  afterForm,
11005
+ renderDepartmentSelector,
8797
11006
  renderForm,
8798
11007
  renderSuccess,
8799
- onSubmitSuccess
11008
+ onSubmitSuccess,
11009
+ inDrawer = false
8800
11010
  }) => {
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);
11011
+ const { validateAll, getFormData: getFormData2, setFieldValue, resetForm, api } = useFormContext();
11012
+ const [submitted, setSubmitted] = (0, import_react62.useState)(false);
11013
+ const [successInfo, setSuccessInfo] = (0, import_react62.useState)(null);
11014
+ const [submitting, setSubmitting] = (0, import_react62.useState)(false);
11015
+ const [departmentId, setDepartmentId] = (0, import_react62.useState)();
11016
+ const [previewOpen, setPreviewOpen] = (0, import_react62.useState)(false);
11017
+ const [previewLoading, setPreviewLoading] = (0, import_react62.useState)(false);
11018
+ const [previewRoutes, setPreviewRoutes] = (0, import_react62.useState)([]);
11019
+ const [pendingFormData, setPendingFormData] = (0, import_react62.useState)(null);
8805
11020
  const { hasDraft, draftTimestamp, saveDraft, restoreDraft, clearDraft } = useDraftStorage({
8806
11021
  appType: config.appType,
8807
11022
  formUuid: config.formUuid
@@ -8813,79 +11028,123 @@ var InnerFormContent = ({
8813
11028
  mode: submitSuccessMode === "continue" ? "stay" : submitSuccessMode,
8814
11029
  basePath: config.navigation?.basePath
8815
11030
  });
8816
- const handleSubmit = (0, import_react58.useCallback)(async () => {
11031
+ const performSubmit = (0, import_react62.useCallback)(
11032
+ async (formData) => {
11033
+ setSubmitting(true);
11034
+ try {
11035
+ const submitResponse = config.mode === "edit" && config.formInstanceId ? await api.updateFormData({
11036
+ appType: config.appType,
11037
+ formUuid: config.formUuid,
11038
+ formInstId: config.formInstanceId,
11039
+ formInstanceId: config.formInstanceId,
11040
+ updateFormDataJson: JSON.stringify(formData)
11041
+ }) : await api.submitFormData({
11042
+ appType: config.appType,
11043
+ formUuid: config.formUuid,
11044
+ data: formData,
11045
+ submissionDepartmentId: departmentId
11046
+ });
11047
+ const formInstId = pickFormInstanceId(submitResponse) || config.formInstanceId || `inst_${Date.now()}`;
11048
+ if (config.submit?.afterSubmit) {
11049
+ await config.submit.afterSubmit({
11050
+ formInstanceId: formInstId,
11051
+ data: formData,
11052
+ response: submitResponse
11053
+ });
11054
+ }
11055
+ if (enableDraft) {
11056
+ clearDraft();
11057
+ }
11058
+ onSubmitSuccess?.(formInstId);
11059
+ if (submitSuccessMode === "continue") {
11060
+ resetForm();
11061
+ } else {
11062
+ setSuccessInfo({ formInstanceId: formInstId });
11063
+ setSubmitted(true);
11064
+ handlePostSubmit(formInstId);
11065
+ }
11066
+ } catch (error) {
11067
+ console.error("[FormSubmitTemplate] Submit failed:", error);
11068
+ } finally {
11069
+ setSubmitting(false);
11070
+ }
11071
+ },
11072
+ [
11073
+ api,
11074
+ clearDraft,
11075
+ config,
11076
+ departmentId,
11077
+ enableDraft,
11078
+ handlePostSubmit,
11079
+ onSubmitSuccess,
11080
+ resetForm,
11081
+ submitSuccessMode
11082
+ ]
11083
+ );
11084
+ const prepareSubmit = (0, import_react62.useCallback)(async () => {
8817
11085
  const valid = await validateAll();
8818
11086
  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
- }
11087
+ const formData = getFormData2();
11088
+ if (config.submit?.beforeSubmit) {
11089
+ const shouldContinue = await config.submit.beforeSubmit(formData);
11090
+ if (shouldContinue === false) {
11091
+ return;
8828
11092
  }
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,
11093
+ }
11094
+ if (formType === "process" && enableProcessPreview) {
11095
+ setPendingFormData(formData);
11096
+ setPreviewOpen(true);
11097
+ setPreviewLoading(true);
11098
+ try {
11099
+ const routes = await previewProcess(api.request, {
11100
+ appType: config.appType,
11101
+ formUuid: config.formUuid,
8844
11102
  data: formData,
8845
- response: submitResponse
11103
+ submissionDepartmentId: departmentId
8846
11104
  });
11105
+ setPreviewRoutes(Array.isArray(routes) ? routes : []);
11106
+ } catch (error) {
11107
+ console.error("[FormSubmitTemplate] Preview failed:", error);
11108
+ setPreviewRoutes([]);
11109
+ } finally {
11110
+ setPreviewLoading(false);
8847
11111
  }
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);
11112
+ return;
8863
11113
  }
11114
+ await performSubmit(formData);
8864
11115
  }, [
8865
11116
  validateAll,
8866
11117
  getFormData2,
8867
11118
  config,
8868
11119
  api,
8869
- enableDraft,
8870
- clearDraft,
8871
- onSubmitSuccess,
8872
- submitSuccessMode,
8873
- resetForm,
8874
- handlePostSubmit
11120
+ formType,
11121
+ enableProcessPreview,
11122
+ departmentId,
11123
+ performSubmit
8875
11124
  ]);
8876
- const handleSaveDraft = (0, import_react58.useCallback)(() => {
11125
+ const handlePreviewConfirm = (0, import_react62.useCallback)(async () => {
11126
+ const data = pendingFormData ?? getFormData2();
11127
+ setPreviewOpen(false);
11128
+ setPendingFormData(null);
11129
+ await performSubmit(data);
11130
+ }, [getFormData2, pendingFormData, performSubmit]);
11131
+ const handleSaveDraft = (0, import_react62.useCallback)(() => {
8877
11132
  const data = getFormData2();
8878
11133
  saveDraft(data);
8879
11134
  }, [getFormData2, saveDraft]);
8880
- const handleRestoreDraft = (0, import_react58.useCallback)(() => {
8881
- restoreDraft();
8882
- }, [restoreDraft]);
8883
- const handleContinue = (0, import_react58.useCallback)(() => {
11135
+ const handleRestoreDraft = (0, import_react62.useCallback)(() => {
11136
+ const data = restoreDraft();
11137
+ if (!data) return;
11138
+ Object.entries(data).forEach(([fieldId, value]) => {
11139
+ setFieldValue(fieldId, value);
11140
+ });
11141
+ }, [restoreDraft, setFieldValue]);
11142
+ const handleContinue = (0, import_react62.useCallback)(() => {
8884
11143
  setSubmitted(false);
8885
11144
  setSuccessInfo(null);
8886
11145
  resetForm();
8887
11146
  }, [resetForm]);
8888
- const handleViewDetail = (0, import_react58.useCallback)(() => {
11147
+ const handleViewDetail = (0, import_react62.useCallback)(() => {
8889
11148
  if (!successInfo) return;
8890
11149
  if (formType === "process") {
8891
11150
  navigateToProcessDetail(successInfo.formInstanceId);
@@ -8913,15 +11172,39 @@ var InnerFormContent = ({
8913
11172
  label: "\u63D0\u4EA4",
8914
11173
  type: "primary",
8915
11174
  loading: submitting,
8916
- onClick: handleSubmit
11175
+ onClick: prepareSubmit
8917
11176
  });
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)(
11177
+ 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: [
11178
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u63D0\u4EA4\u90E8\u95E8" }),
11179
+ renderDepartmentSelector ? renderDepartmentSelector({
11180
+ value: departmentId,
11181
+ onChange: setDepartmentId,
11182
+ options: departmentOptions
11183
+ }) : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11184
+ import_antd33.Select,
11185
+ {
11186
+ allowClear: true,
11187
+ className: "w-full",
11188
+ placeholder: "\u8BF7\u9009\u62E9\u672C\u6B21\u63D0\u4EA4\u6D41\u7A0B\u6240\u5C5E\u90E8\u95E8",
11189
+ value: departmentId,
11190
+ options: departmentOptions,
11191
+ onChange: setDepartmentId
11192
+ }
11193
+ )
11194
+ ] }) : null;
11195
+ const actionsNode = !submitted ? /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11196
+ StickyActionBar,
11197
+ {
11198
+ actions,
11199
+ inDrawer,
11200
+ position: "inline",
11201
+ className: "mt-6 -mx-5 -mb-5 rounded-b-lg md:-mx-6 md:-mb-6"
11202
+ }
11203
+ ) : null;
11204
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)(RuntimePageShell, { inDrawer, children: [
11205
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsxs)("div", { className: "space-y-6", children: [
11206
+ header,
11207
+ enableDraft && hasDraft && !submitted && /* @__PURE__ */ (0, import_jsx_runtime90.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8925
11208
  DraftManager,
8926
11209
  {
8927
11210
  hasDraft,
@@ -8930,11 +11213,13 @@ var InnerFormContent = ({
8930
11213
  onDiscard: clearDraft
8931
11214
  }
8932
11215
  ) }),
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: [
11216
+ !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: [
11217
+ departmentSelector,
8934
11218
  beforeForm,
8935
- renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormRenderer, { columns: 2 }),
8936
- afterForm
8937
- ] }) : successInfo && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11219
+ renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(FormRenderer, { columns: 2 }),
11220
+ afterForm,
11221
+ actionsNode
11222
+ ] }) : successInfo && /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8938
11223
  SubmitSuccessCard,
8939
11224
  {
8940
11225
  info: successInfo,
@@ -8948,7 +11233,16 @@ var InnerFormContent = ({
8948
11233
  ),
8949
11234
  footer
8950
11235
  ] }),
8951
- !submitted && /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormActionBar, { actions, position: "bottom-fixed" })
11236
+ /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
11237
+ ProcessPreview,
11238
+ {
11239
+ open: previewOpen,
11240
+ routes: previewRoutes,
11241
+ loading: previewLoading,
11242
+ onClose: () => setPreviewOpen(false),
11243
+ onConfirm: handlePreviewConfirm
11244
+ }
11245
+ )
8952
11246
  ] });
8953
11247
  };
8954
11248
  var FormSubmitTemplate = ({
@@ -8957,15 +11251,20 @@ var FormSubmitTemplate = ({
8957
11251
  formType = "form",
8958
11252
  submitSuccessMode = "redirect",
8959
11253
  enableDraft = false,
11254
+ enableProcessPreview = false,
11255
+ enableSubmissionDepartmentSelect = false,
11256
+ departmentOptions = [],
8960
11257
  header,
8961
11258
  footer,
8962
11259
  beforeForm,
8963
11260
  afterForm,
11261
+ renderDepartmentSelector,
8964
11262
  renderForm,
8965
11263
  renderSuccess,
8966
- onSubmitSuccess
11264
+ onSubmitSuccess,
11265
+ inDrawer = false
8967
11266
  }) => {
8968
- return /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(FormProvider, { schema, config, children: /* @__PURE__ */ (0, import_jsx_runtime84.jsx)(
11267
+ return /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(FormProvider, { schema, config, children: /* @__PURE__ */ (0, import_jsx_runtime90.jsx)(
8969
11268
  InnerFormContent,
8970
11269
  {
8971
11270
  schema,
@@ -8973,83 +11272,95 @@ var FormSubmitTemplate = ({
8973
11272
  formType,
8974
11273
  submitSuccessMode,
8975
11274
  enableDraft,
11275
+ enableProcessPreview,
11276
+ enableSubmissionDepartmentSelect,
11277
+ departmentOptions,
8976
11278
  header,
8977
11279
  footer,
8978
11280
  beforeForm,
8979
11281
  afterForm,
11282
+ renderDepartmentSelector,
8980
11283
  renderForm,
8981
11284
  renderSuccess,
8982
- onSubmitSuccess
11285
+ onSubmitSuccess,
11286
+ inDrawer
8983
11287
  }
8984
11288
  ) });
8985
11289
  };
8986
11290
 
8987
11291
  // src/templates/FormDetailTemplate.tsx
8988
- var import_react59 = require("react");
11292
+ var import_react63 = require("react");
8989
11293
 
8990
11294
  // 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 } }) })
11295
+ var import_antd34 = require("antd");
11296
+ var import_jsx_runtime91 = require("react/jsx-runtime");
11297
+ var CardSkeleton = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
11298
+ var SummaryCardSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(CardSkeleton, { children: [
11299
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex items-start justify-between", children: [
11300
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex-1", children: [
11301
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
11302
+ /* @__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
11303
  ] }),
9000
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(import_antd29.Skeleton.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
11304
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
9001
11305
  ] }),
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 } })
11306
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex items-center gap-3 mt-4", children: [
11307
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Avatar, { active: true, size: "small" }),
11308
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 120 } })
9005
11309
  ] })
9006
11310
  ] });
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%" } })
11311
+ 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: [
11312
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 80 } }),
11313
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, block: true, style: { width: "100%" } })
9010
11314
  ] }, 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 } })
11315
+ 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: [
11316
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Button, { active: true, style: { width: 80 } }),
11317
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Button, { active: true, style: { width: 80 } })
9014
11318
  ] }) });
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" })
11319
+ var TimelineSkeleton = () => /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)(CardSkeleton, { children: [
11320
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
11321
+ /* @__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: [
11322
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "flex flex-col items-center", children: [
11323
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
11324
+ i < 2 && /* @__PURE__ */ (0, import_jsx_runtime91.jsx)("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
9021
11325
  ] }),
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%" } }) })
11326
+ /* @__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
11327
  ] }, i)) })
9024
11328
  ] });
9025
11329
  var PageSkeleton = ({ type }) => {
9026
11330
  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 } })
11331
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-6", children: [
11332
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-2", children: [
11333
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "large", style: { width: 200 } }),
11334
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(import_antd34.Skeleton.Input, { active: true, size: "small", style: { width: 300 } })
9031
11335
  ] }),
9032
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(FormGridSkeleton, {}),
9033
- /* @__PURE__ */ (0, import_jsx_runtime85.jsx)(ActionBarSkeleton, {})
11336
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FormGridSkeleton, {}),
11337
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ActionBarSkeleton, {})
9034
11338
  ] });
9035
11339
  }
9036
11340
  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, {})
11341
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-6", children: [
11342
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(SummaryCardSkeleton, {}),
11343
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FormGridSkeleton, {}),
11344
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ActionBarSkeleton, {})
9041
11345
  ] });
9042
11346
  }
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, {})
11347
+ return /* @__PURE__ */ (0, import_jsx_runtime91.jsxs)("div", { className: "space-y-6", children: [
11348
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(SummaryCardSkeleton, {}),
11349
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(FormGridSkeleton, {}),
11350
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(TimelineSkeleton, {}),
11351
+ /* @__PURE__ */ (0, import_jsx_runtime91.jsx)(ActionBarSkeleton, {})
9048
11352
  ] });
9049
11353
  };
9050
11354
 
9051
11355
  // src/templates/FormDetailTemplate.tsx
9052
- var import_jsx_runtime86 = require("react/jsx-runtime");
11356
+ var import_jsx_runtime92 = require("react/jsx-runtime");
11357
+ function FormDataBridge({
11358
+ formDataRef
11359
+ }) {
11360
+ const { getFormData: getFormData2 } = useFormContext();
11361
+ formDataRef.current = getFormData2;
11362
+ return null;
11363
+ }
9053
11364
  var InnerDetailContent = ({
9054
11365
  schema,
9055
11366
  formUuid,
@@ -9063,9 +11374,12 @@ var InnerDetailContent = ({
9063
11374
  renderSummary,
9064
11375
  renderActions,
9065
11376
  onDelete,
9066
- onSave
11377
+ onSave,
11378
+ inDrawer = false
9067
11379
  }) => {
9068
- const fieldIds = (0, import_react59.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11380
+ const formDataRef = (0, import_react63.useRef)(void 0);
11381
+ const [accessDenied, setAccessDenied] = (0, import_react63.useState)(false);
11382
+ const fieldIds = (0, import_react63.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
9069
11383
  const {
9070
11384
  loading,
9071
11385
  mode,
@@ -9079,7 +11393,13 @@ var InnerDetailContent = ({
9079
11393
  canEdit,
9080
11394
  canDelete,
9081
11395
  canViewChangeRecords
9082
- } = useFormDetail({ formUuid, appType, formInstanceId, fieldIds });
11396
+ } = useFormDetail({
11397
+ formUuid,
11398
+ appType,
11399
+ formInstanceId,
11400
+ fieldIds,
11401
+ onPermissionDenied: () => setAccessDenied(true)
11402
+ });
9083
11403
  const {
9084
11404
  records,
9085
11405
  loading: recordsLoading,
@@ -9092,20 +11412,21 @@ var InnerDetailContent = ({
9092
11412
  formInstanceId,
9093
11413
  autoLoad: enableChangeRecords && canViewChangeRecords
9094
11414
  });
9095
- const handleSave = (0, import_react59.useCallback)(async () => {
9096
- if (!formData) return;
9097
- const success = await saveChanges(formData);
11415
+ const handleSave = (0, import_react63.useCallback)(async () => {
11416
+ const values = formDataRef.current?.() ?? formData;
11417
+ if (!values) return;
11418
+ const success = await saveChanges(values);
9098
11419
  if (success) {
9099
- onSave?.(formData);
11420
+ onSave?.(values);
9100
11421
  }
9101
11422
  }, [formData, saveChanges, onSave]);
9102
- const handleDelete = (0, import_react59.useCallback)(async () => {
11423
+ const handleDelete = (0, import_react63.useCallback)(async () => {
9103
11424
  const success = await deleteInstance();
9104
11425
  if (success) {
9105
11426
  onDelete?.();
9106
11427
  }
9107
11428
  }, [deleteInstance, onDelete]);
9108
- const handleCancel = (0, import_react59.useCallback)(() => {
11429
+ const handleCancel = (0, import_react63.useCallback)(() => {
9109
11430
  switchToReadonly();
9110
11431
  }, [switchToReadonly]);
9111
11432
  const readonlyActions = [];
@@ -9142,41 +11463,44 @@ var InnerDetailContent = ({
9142
11463
  }
9143
11464
  };
9144
11465
  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" }) }) });
11466
+ 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
11467
  }
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
11468
+ const actionsNode = currentActions.length > 0 ? renderActions ? renderActions(currentActions) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(StickyActionBar, { actions: currentActions, inDrawer }) : null;
11469
+ 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: [
11470
+ header,
11471
+ renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
11472
+ SummaryPanel,
11473
+ {
11474
+ title: instanceInfo?.title || formData?.instanceTitle || schema.formMeta.title,
11475
+ eyebrow: `\u6570\u636E\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
11476
+ creator: instanceInfo?.creator ? {
11477
+ name: instanceInfo.creator.name,
11478
+ avatar: instanceInfo.creator.avatar,
11479
+ department: instanceInfo.creator.department
11480
+ } : void 0,
11481
+ createdAt: instanceInfo?.createdAt,
11482
+ status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
11483
+ }
11484
+ ),
11485
+ 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" }),
11486
+ /* @__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: [
11487
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FormDataBridge, { formDataRef }),
11488
+ /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FormRenderer, { columns: 2 })
9177
11489
  ] }) }),
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
- ] });
11490
+ enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("div", { className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(
11491
+ RecordChangePanel,
11492
+ {
11493
+ records,
11494
+ loading: recordsLoading,
11495
+ total: records.length,
11496
+ hasMore,
11497
+ onLoadMore: loadMore,
11498
+ onRefresh: refreshRecords,
11499
+ onExpand: refreshRecords
11500
+ }
11501
+ ) }),
11502
+ footer
11503
+ ] }) }) });
9180
11504
  };
9181
11505
  var FormDetailTemplate = (props) => {
9182
11506
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -9186,13 +11510,13 @@ var FormDetailTemplate = (props) => {
9186
11510
  appType,
9187
11511
  formInstanceId
9188
11512
  };
9189
- return /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime86.jsx)(InnerDetailContent, { ...props }) });
11513
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(InnerDetailContent, { ...props }) });
9190
11514
  };
9191
11515
 
9192
11516
  // src/templates/ProcessDetailTemplate.tsx
9193
- var import_react60 = require("react");
9194
- var import_jsx_runtime87 = require("react/jsx-runtime");
9195
- function FormDataBridge({
11517
+ var import_react64 = require("react");
11518
+ var import_jsx_runtime93 = require("react/jsx-runtime");
11519
+ function FormDataBridge2({
9196
11520
  formDataRef
9197
11521
  }) {
9198
11522
  const { getFormData: getFormData2 } = useFormContext();
@@ -9207,12 +11531,16 @@ var InnerProcessContent = ({
9207
11531
  header,
9208
11532
  renderTimeline,
9209
11533
  renderActions,
11534
+ renderTransferSelector,
11535
+ renderReturnNodeLabel,
11536
+ renderActionModalExtra,
9210
11537
  beforeForm,
9211
11538
  afterForm,
9212
- onActionComplete
11539
+ onActionComplete,
11540
+ inDrawer = false
9213
11541
  }) => {
9214
- const formDataRef = (0, import_react60.useRef)(void 0);
9215
- const fieldIds = (0, import_react60.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11542
+ const formDataRef = (0, import_react64.useRef)(void 0);
11543
+ const fieldIds = (0, import_react64.useMemo)(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
9216
11544
  const {
9217
11545
  loading,
9218
11546
  processInfo,
@@ -9220,6 +11548,7 @@ var InnerProcessContent = ({
9220
11548
  currentTask,
9221
11549
  progressList,
9222
11550
  formData,
11551
+ instanceInfo,
9223
11552
  isApprover,
9224
11553
  activeActions,
9225
11554
  fieldBehaviors,
@@ -9230,7 +11559,18 @@ var InnerProcessContent = ({
9230
11559
  switchToReadonly,
9231
11560
  refreshProgress
9232
11561
  } = useProcessDetail({ formUuid, appType, formInstanceId, fieldIds });
9233
- const { approve, reject, withdraw, save, resubmit } = useApprovalActions({
11562
+ const {
11563
+ approve,
11564
+ reject,
11565
+ transfer,
11566
+ returnTo,
11567
+ withdraw,
11568
+ save,
11569
+ resubmit,
11570
+ callbackTask,
11571
+ returnableNodes,
11572
+ loadReturnableNodes
11573
+ } = useApprovalActions({
9234
11574
  formInstanceId,
9235
11575
  formUuid,
9236
11576
  appType,
@@ -9239,72 +11579,102 @@ var InnerProcessContent = ({
9239
11579
  onActionComplete?.(action);
9240
11580
  await refreshProgress();
9241
11581
  },
9242
- getFormValues: () => formDataRef.current?.() ?? {}
11582
+ getFormValues: () => formDataRef.current?.() ?? formData ?? {}
9243
11583
  });
9244
- const handleApprove = (0, import_react60.useCallback)(
11584
+ const handleApprove = (0, import_react64.useCallback)(
9245
11585
  async (comments) => {
9246
11586
  await approve(comments);
9247
11587
  },
9248
11588
  [approve]
9249
11589
  );
9250
- const handleReject = (0, import_react60.useCallback)(
11590
+ const handleReject = (0, import_react64.useCallback)(
9251
11591
  async (comments) => {
9252
11592
  await reject(comments);
9253
11593
  },
9254
11594
  [reject]
9255
11595
  );
9256
- const handleWithdraw = (0, import_react60.useCallback)(
11596
+ const handleTransfer = (0, import_react64.useCallback)(
11597
+ async (userId, reason) => {
11598
+ await transfer(userId, reason);
11599
+ },
11600
+ [transfer]
11601
+ );
11602
+ const handleReturn = (0, import_react64.useCallback)(
11603
+ async (nodeId, reason) => {
11604
+ await returnTo(nodeId, reason);
11605
+ },
11606
+ [returnTo]
11607
+ );
11608
+ const handleWithdraw = (0, import_react64.useCallback)(
9257
11609
  async (reason) => {
9258
11610
  await withdraw(reason);
9259
11611
  },
9260
11612
  [withdraw]
9261
11613
  );
9262
- const handleSave = (0, import_react60.useCallback)(async () => {
11614
+ const handleSave = (0, import_react64.useCallback)(async () => {
9263
11615
  await save();
9264
11616
  }, [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
- }
11617
+ const handleResubmit = (0, import_react64.useCallback)(
11618
+ async (comments) => {
11619
+ await resubmit(comments);
11620
+ },
11621
+ [resubmit]
11622
+ );
11623
+ const handleCallback = (0, import_react64.useCallback)(async () => {
11624
+ await callbackTask();
11625
+ }, [callbackTask]);
11626
+ const bottomActions = (0, import_react64.useMemo)(() => {
11627
+ if (isApprover && activeActions.length > 0) return [];
9273
11628
  if (isOriginatorReturn) {
9274
11629
  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({
11630
+ return [
11631
+ {
11632
+ key: "edit",
11633
+ label: "\u7F16\u8F91",
11634
+ type: "primary",
11635
+ onClick: switchToEdit
11636
+ }
11637
+ ];
11638
+ }
11639
+ return [
11640
+ {
9283
11641
  key: "cancel",
9284
11642
  label: "\u53D6\u6D88",
9285
11643
  type: "default",
9286
- onClick: switchToReadonly
9287
- });
9288
- actions.push({
11644
+ onClick: switchToReadonly,
11645
+ placement: "left"
11646
+ },
11647
+ {
9289
11648
  key: "resubmit",
9290
11649
  label: "\u91CD\u65B0\u63D0\u4EA4",
9291
11650
  type: "primary",
9292
- onClick: handleResubmit
9293
- });
9294
- }
9295
- return actions;
11651
+ onClick: () => handleResubmit()
11652
+ }
11653
+ ];
9296
11654
  }
9297
11655
  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
- });
11656
+ return [
11657
+ {
11658
+ key: "withdraw",
11659
+ label: "\u64A4\u9500",
11660
+ type: "danger",
11661
+ onClick: () => handleWithdraw(),
11662
+ confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u64A4\u9500\u540E\u6D41\u7A0B\u5C06\u7EC8\u6B62\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F" }
11663
+ }
11664
+ ];
9305
11665
  }
9306
- return actions;
9307
- };
11666
+ return [];
11667
+ }, [
11668
+ activeActions.length,
11669
+ canWithdraw,
11670
+ handleResubmit,
11671
+ handleWithdraw,
11672
+ isApprover,
11673
+ isOriginatorReturn,
11674
+ mode,
11675
+ switchToEdit,
11676
+ switchToReadonly
11677
+ ]);
9308
11678
  const formConfig = {
9309
11679
  mode: mode === "edit" ? "edit" : "readonly",
9310
11680
  formUuid,
@@ -9316,50 +11686,68 @@ var InnerProcessContent = ({
9316
11686
  }
9317
11687
  };
9318
11688
  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" }) }) });
11689
+ 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
11690
  }
9321
- const bottomActions = buildActions();
9322
11691
  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,
11692
+ const actionsNode = showApprovalActions ? renderActions ? renderActions(activeActions) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
11693
+ ApprovalActionBar,
11694
+ {
11695
+ actions: activeActions,
11696
+ onApprove: handleApprove,
11697
+ onReject: handleReject,
11698
+ onTransfer: handleTransfer,
11699
+ onReturn: handleReturn,
11700
+ onWithdraw: handleWithdraw,
11701
+ onSave: handleSave,
11702
+ onResubmit: handleResubmit,
11703
+ onCallback: handleCallback,
11704
+ returnableNodes,
11705
+ onLoadReturnableNodes: loadReturnableNodes,
11706
+ renderTransferSelector,
11707
+ renderReturnNodeLabel,
11708
+ renderActionModalExtra,
11709
+ inDrawer
11710
+ }
11711
+ ) : bottomActions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(StickyActionBar, { actions: bottomActions, inDrawer }) : null;
11712
+ const statusMeta = processStatus ? PROCESS_STATUS_META[processStatus] : void 0;
11713
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(RuntimePageShell, { actions: actionsNode, inDrawer, children: /* @__PURE__ */ (0, import_jsx_runtime93.jsxs)("div", { className: "space-y-6", children: [
11714
+ header,
11715
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(
11716
+ SummaryPanel,
9353
11717
  {
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
- ] });
11718
+ title: processInfo?.title || instanceInfo?.title || schema.formMeta.title,
11719
+ eyebrow: `\u6D41\u7A0B\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
11720
+ creator: processInfo?.originatorName ? {
11721
+ name: processInfo.originatorName,
11722
+ department: processInfo.originatorDepartment
11723
+ } : void 0,
11724
+ createdAt: processInfo?.createdAt,
11725
+ status: statusMeta,
11726
+ metaItems: [
11727
+ { key: "currentTask", label: "\u5F53\u524D\u8282\u70B9", value: currentTask?.nodeName || "\u65E0" },
11728
+ {
11729
+ key: "processStatus",
11730
+ label: "\u5B9E\u4F8B\u72B6\u6001",
11731
+ value: statusMeta?.label || processStatus || "-"
11732
+ }
11733
+ ]
11734
+ }
11735
+ ),
11736
+ beforeForm,
11737
+ 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" }),
11738
+ /* @__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: [
11739
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FormDataBridge2, { formDataRef }),
11740
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FormRenderer, { columns: 2 })
11741
+ ] }) }),
11742
+ afterForm,
11743
+ /* @__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: [
11744
+ /* @__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: [
11745
+ /* @__PURE__ */ (0, import_jsx_runtime93.jsx)("h3", { className: "text-base font-semibold text-ant-color-text", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
11746
+ /* @__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" })
11747
+ ] }) }),
11748
+ renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(ApprovalTimeline, { tasks: progressList, showRemarks: true, showApproverInfo: true })
11749
+ ] })
11750
+ ] }) });
9363
11751
  };
9364
11752
  var ProcessDetailTemplate = (props) => {
9365
11753
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -9369,11 +11757,12 @@ var ProcessDetailTemplate = (props) => {
9369
11757
  appType,
9370
11758
  formInstanceId
9371
11759
  };
9372
- return /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime87.jsx)(InnerProcessContent, { ...props }) });
11760
+ return /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ (0, import_jsx_runtime93.jsx)(InnerProcessContent, { ...props }) });
9373
11761
  };
9374
11762
  // Annotate the CommonJS export names for ESM import in node:
9375
11763
  0 && (module.exports = {
9376
11764
  AddressField,
11765
+ ApprovalActionBar,
9377
11766
  ApprovalActions,
9378
11767
  ApprovalTimeline,
9379
11768
  AssociationFormField,
@@ -9384,6 +11773,7 @@ var ProcessDetailTemplate = (props) => {
9384
11773
  CheckboxField,
9385
11774
  ComponentRegistryContext,
9386
11775
  ComponentRegistryProvider,
11776
+ DataManagementList,
9387
11777
  DateField,
9388
11778
  DepartmentSelectField,
9389
11779
  DigitalSignatureField,
@@ -9415,34 +11805,58 @@ var ProcessDetailTemplate = (props) => {
9415
11805
  ProcessDetailTemplate,
9416
11806
  ProcessPreview,
9417
11807
  RadioField,
11808
+ RecordChangePanel,
11809
+ RuntimePageShell,
9418
11810
  SelectField,
9419
11811
  SerialNumberField,
11812
+ StickyActionBar,
9420
11813
  SubFormField,
11814
+ SummaryPanel,
9421
11815
  TASK_STATUS_META,
9422
11816
  TextAreaField,
9423
11817
  TextField,
9424
11818
  TextareaField,
9425
11819
  UserSelectField,
11820
+ advancedSearchDataManagement,
11821
+ batchApproveDataManagementRows,
11822
+ buildFilterPayload,
9426
11823
  checkUserApproval,
9427
11824
  createFormRuntimeApi,
9428
11825
  defaultComponentRegistry,
9429
11826
  defineFormSchema,
11827
+ deleteDataManagementRows,
9430
11828
  deleteFormData,
9431
11829
  evaluateEffects,
11830
+ exportDataManagementRows,
9432
11831
  extractFormValues,
9433
11832
  getChangeRecords,
11833
+ getDataManagementConfig,
11834
+ getDataManagementSchema,
11835
+ getDataManagementTransferRecords,
9434
11836
  getFormData,
9435
11837
  getProcessBasic,
9436
11838
  getProcessDefinition,
9437
11839
  getProcessProgress,
9438
11840
  getReturnableNodes,
11841
+ getSystemFieldsForFormType,
9439
11842
  getViewPermission,
9440
11843
  handleApproval,
11844
+ hasViewOperation,
11845
+ hasViewPermission,
11846
+ importDataManagementRows,
11847
+ importPreviewDataManagementRows,
11848
+ normalizeColumnConfig,
11849
+ normalizeDataManagementFields,
11850
+ normalizeDataManagementList,
11851
+ normalizeFieldBehaviors,
11852
+ normalizeOperation,
9441
11853
  previewProcess,
9442
11854
  resubmitTask,
9443
11855
  returnTask,
11856
+ saveDataManagementConfig,
9444
11857
  saveTask,
9445
11858
  transferTask,
11859
+ triggerCallbackTask,
9446
11860
  useApprovalActions,
9447
11861
  useChangeRecords,
9448
11862
  useComponent,