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.mjs CHANGED
@@ -5886,8 +5886,8 @@ var parseResponse = async (response) => {
5886
5886
  const contentType = response.headers.get("content-type") || "";
5887
5887
  const payload = contentType.includes("application/json") ? await response.json() : await response.text();
5888
5888
  if (!response.ok) {
5889
- const message = typeof payload === "object" && payload ? payload.message || payload.error || response.statusText : response.statusText;
5890
- throw new Error(message || "\u8BF7\u6C42\u5931\u8D25");
5889
+ const message2 = typeof payload === "object" && payload ? payload.message || payload.error || response.statusText : response.statusText;
5890
+ throw new Error(message2 || "\u8BF7\u6C42\u5931\u8D25");
5891
5891
  }
5892
5892
  if (typeof payload === "object" && payload) {
5893
5893
  return payload;
@@ -6568,6 +6568,26 @@ var normalizeApprovalPermission = (value) => {
6568
6568
  currentTasks
6569
6569
  };
6570
6570
  };
6571
+ var normalizeReturnableNodes = (value) => {
6572
+ const raw = value?.candidates || value?.nodes || value?.data || value;
6573
+ if (!Array.isArray(raw)) return [];
6574
+ return raw.map((node) => ({
6575
+ ...node,
6576
+ nodeId: node?.nodeId || node?.id || "",
6577
+ nodeName: node?.nodeName || node?.name || node?.title || node?.id || ""
6578
+ }));
6579
+ };
6580
+ var normalizeProcessDefinition = (value) => {
6581
+ const raw = value?.definitionJson || value?.viewJson || value || {};
6582
+ const nodes = Array.isArray(raw.nodes) ? raw.nodes : [];
6583
+ const startNode = nodes.find((node) => node?.type === "start" || node?.nodeType === "start");
6584
+ return {
6585
+ ...raw,
6586
+ processId: raw.processId || raw.id || value?.id || "",
6587
+ flowConfig: raw.flowConfig || value?.flowConfig || {},
6588
+ startNodeId: raw.startNodeId || startNode?.id || value?.startNodeId
6589
+ };
6590
+ };
6571
6591
  async function getProcessBasic(request, formInstId) {
6572
6592
  const response = await request({
6573
6593
  url: `/workflow/instance/${formInstId}/basic`,
@@ -6647,7 +6667,7 @@ async function getReturnableNodes(request, taskId) {
6647
6667
  url: `/workflow/task/${taskId}/returnable-nodes`,
6648
6668
  method: "get"
6649
6669
  });
6650
- return response.data || response.result || [];
6670
+ return normalizeReturnableNodes(response.data || response.result);
6651
6671
  }
6652
6672
  async function previewProcess(request, params) {
6653
6673
  const response = await request({
@@ -6663,6 +6683,14 @@ async function getProcessDefinition(request, formUuid) {
6663
6683
  method: "get",
6664
6684
  params: { formUuid }
6665
6685
  });
6686
+ return normalizeProcessDefinition(response.data || response.result);
6687
+ }
6688
+ async function triggerCallbackTask(request, params) {
6689
+ const response = await request({
6690
+ url: `/workflow/task/${params.taskId}/callback`,
6691
+ method: "post",
6692
+ data: params.payload || {}
6693
+ });
6666
6694
  return response.data || response.result;
6667
6695
  }
6668
6696
  async function getFormData(request, params) {
@@ -6698,6 +6726,256 @@ async function getViewPermission(request, params) {
6698
6726
  return response.data || response.result;
6699
6727
  }
6700
6728
 
6729
+ // src/core/dataManagementApi.ts
6730
+ var unwrap = (response) => {
6731
+ if (response instanceof Blob) return response;
6732
+ if (response?.data?.result !== void 0) return response.data.result;
6733
+ if (response?.result !== void 0) return response.result;
6734
+ if (response?.data !== void 0) return response.data;
6735
+ return response;
6736
+ };
6737
+ var pickData = (value) => value?.data ?? value?.result ?? value;
6738
+ var normalizeComponentName = (field) => field?.componentName || field?.component_name || field?.component_type || field?.componentType || field?.type || "TextField";
6739
+ var normalizeField = (key, field, system = false) => ({
6740
+ ...field,
6741
+ id: field?.id || field?.fieldId || key,
6742
+ fieldId: field?.fieldId || field?.id || key,
6743
+ componentName: normalizeComponentName(field),
6744
+ label: field?.label || field?.title || field?.name || key,
6745
+ width: field?.width,
6746
+ system
6747
+ });
6748
+ var PROCESS_INSTANCE_STATUS_OPTIONS = [
6749
+ { label: "\u5F85\u5904\u7406", value: "pending" },
6750
+ { label: "\u5BA1\u6279\u4E2D", value: "running" },
6751
+ { label: "\u7B49\u5F85\u4E2D", value: "waiting" },
6752
+ { label: "\u6D41\u7A0B\u5F02\u5E38", value: "exception" },
6753
+ { label: "\u5DF2\u5B8C\u6210", value: "completed" },
6754
+ { label: "\u5DF2\u62D2\u7EDD", value: "terminated" },
6755
+ { label: "\u5DF2\u64A4\u9500", value: "withdrawn" }
6756
+ ];
6757
+ var APPROVAL_RESULT_OPTIONS = [
6758
+ { label: "\u5BA1\u6279\u4E2D", value: "processing" },
6759
+ { label: "\u540C\u610F", value: "approved" },
6760
+ { label: "\u62D2\u7EDD", value: "rejected" },
6761
+ { label: "\u64A4\u9500", value: "withdrawn" },
6762
+ { label: "\u5F02\u5E38", value: "exception" }
6763
+ ];
6764
+ var PROCESS_SYSTEM_FIELDS = [
6765
+ normalizeField(
6766
+ "currentApprovalNodeName",
6767
+ {
6768
+ label: "\u5F53\u524D\u5BA1\u6279\u8282\u70B9",
6769
+ componentName: "TextField",
6770
+ width: 140,
6771
+ processOnly: true,
6772
+ displayable: true
6773
+ },
6774
+ true
6775
+ ),
6776
+ normalizeField(
6777
+ "processInstanceStatus",
6778
+ {
6779
+ label: "\u5B9E\u4F8B\u72B6\u6001",
6780
+ componentName: "SelectField",
6781
+ width: 110,
6782
+ options: PROCESS_INSTANCE_STATUS_OPTIONS,
6783
+ processOnly: true,
6784
+ displayable: true
6785
+ },
6786
+ true
6787
+ ),
6788
+ normalizeField(
6789
+ "approvalResult",
6790
+ {
6791
+ label: "\u5BA1\u6279\u7ED3\u679C",
6792
+ componentName: "SelectField",
6793
+ width: 110,
6794
+ options: APPROVAL_RESULT_OPTIONS,
6795
+ processOnly: true,
6796
+ displayable: true
6797
+ },
6798
+ true
6799
+ )
6800
+ ];
6801
+ var BASE_SYSTEM_FIELDS = [
6802
+ normalizeField("createTime", { label: "\u521B\u5EFA\u65F6\u95F4", componentName: "DateField", width: 170 }, true),
6803
+ normalizeField(
6804
+ "modifiedTime",
6805
+ { label: "\u66F4\u65B0\u65F6\u95F4", componentName: "DateField", width: 170 },
6806
+ true
6807
+ ),
6808
+ normalizeField(
6809
+ "originatorName",
6810
+ { label: "\u521B\u5EFA\u4EBA", componentName: "TextField", width: 130 },
6811
+ true
6812
+ )
6813
+ ];
6814
+ var getSystemFieldsForFormType = (formType) => formType === "process" ? [...BASE_SYSTEM_FIELDS, ...PROCESS_SYSTEM_FIELDS] : BASE_SYSTEM_FIELDS;
6815
+ var normalizeDataManagementFields = (payload) => {
6816
+ const data = pickData(payload);
6817
+ const formType = data?.formType || data?.schema?.formType || data?.type;
6818
+ const rawFields = data?.formFields || data?.schema?.formFields || data?.fields || data?.schema?.fields || data?.formSchema?.fields || [];
6819
+ const fields = Array.isArray(rawFields) ? rawFields.map((field) => normalizeField(field?.fieldId || field?.id, field)) : Object.entries(rawFields).map(([key, field]) => normalizeField(key, field));
6820
+ return {
6821
+ fields: fields.filter((field) => field.componentName !== "PageSection"),
6822
+ formType
6823
+ };
6824
+ };
6825
+ var normalizeDataManagementList = (payload) => {
6826
+ const data = unwrap(payload);
6827
+ const body = data?.result || data;
6828
+ const records = body?.data || body?.records || body?.list || body?.items || [];
6829
+ const total = body?.totalCount ?? body?.total ?? body?.count ?? records.length;
6830
+ return {
6831
+ records: Array.isArray(records) ? records : [],
6832
+ total: Number(total) || 0
6833
+ };
6834
+ };
6835
+ var buildFilterPayload = (group) => {
6836
+ if (!group) return void 0;
6837
+ const trimGroup = (current) => ({
6838
+ ...current,
6839
+ rules: (current.rules || []).filter(
6840
+ (rule) => rule.key && rule.operator && rule.value !== void 0 && rule.value !== ""
6841
+ ),
6842
+ conditions: (current.conditions || []).map(trimGroup).filter((item) => item.rules.length > 0 || item.conditions.length > 0)
6843
+ });
6844
+ const payload = trimGroup(group);
6845
+ if (payload.rules.length === 0 && payload.conditions.length === 0) return void 0;
6846
+ return JSON.stringify(payload);
6847
+ };
6848
+ var normalizeColumnConfig = (cfg, fields) => {
6849
+ const allowed = new Set(fields.map((field) => field.fieldId));
6850
+ const configured = Array.isArray(cfg?.showFields) ? cfg.showFields.filter((fieldId) => allowed.has(fieldId)) : [];
6851
+ const defaultShow = fields.filter((field) => !field.system || field.displayable).slice(0, 8).map((field) => field.fieldId);
6852
+ return {
6853
+ showFields: configured.length > 0 ? configured : defaultShow,
6854
+ widths: cfg?.widths || {},
6855
+ lockFieldIds: cfg?.lockFieldIds || [],
6856
+ sort: Array.isArray(cfg?.sort) ? cfg.sort : [],
6857
+ density: cfg?.density || "middle",
6858
+ detailOpenMode: cfg?.detailOpenMode === "newPage" ? "newPage" : "drawer",
6859
+ pageSize: cfg?.pageSize || 10
6860
+ };
6861
+ };
6862
+ async function getDataManagementSchema(request, params) {
6863
+ const response = await request({
6864
+ url: "/form/getFormSchemaAndPackages",
6865
+ method: "get",
6866
+ params
6867
+ });
6868
+ return normalizeDataManagementFields(response);
6869
+ }
6870
+ async function getDataManagementConfig(request, options) {
6871
+ const targetFormUuid = options.menuFormUuid || options.formUuid;
6872
+ const personal = options.scope === "personal";
6873
+ const response = await request({
6874
+ url: `/${options.appType}/v1/form/dataManagement/config/${personal ? "personal/" : ""}get.json`,
6875
+ method: "get",
6876
+ params: { formUuid: targetFormUuid }
6877
+ });
6878
+ return unwrap(response);
6879
+ }
6880
+ async function saveDataManagementConfig(request, options) {
6881
+ const targetFormUuid = options.menuFormUuid || options.formUuid;
6882
+ const personal = options.scope === "personal";
6883
+ const response = await request({
6884
+ url: `/${options.appType}/v1/form/dataManagement/config/${personal ? "personal/" : ""}save.json`,
6885
+ method: "post",
6886
+ data: { formUuid: targetFormUuid, config: options.config }
6887
+ });
6888
+ return unwrap(response);
6889
+ }
6890
+ async function advancedSearchDataManagement(request, query) {
6891
+ const response = await request({
6892
+ url: `/${query.appType}/v1/form/advancedSearch.json`,
6893
+ method: "get",
6894
+ params: {
6895
+ appType: query.appType,
6896
+ formUuid: query.formUuid,
6897
+ filters: query.rawFilters ?? buildFilterPayload(query.filters),
6898
+ conditionType: query.conditionType,
6899
+ searchKeyWord: query.searchKeyWord,
6900
+ currentPage: query.currentPage || 1,
6901
+ pageSize: query.pageSize || 10,
6902
+ order: JSON.stringify(query.order || []),
6903
+ instanceStatus: query.instanceStatus
6904
+ }
6905
+ });
6906
+ return normalizeDataManagementList(response);
6907
+ }
6908
+ async function deleteDataManagementRows(request, params) {
6909
+ const response = await request({
6910
+ url: `/${params.appType}/v1/form/deleteFormData.json`,
6911
+ method: "post",
6912
+ data: {
6913
+ appType: params.appType,
6914
+ formUuid: params.formUuid,
6915
+ formInstIds: params.formInstanceIds,
6916
+ formInstanceIds: params.formInstanceIds
6917
+ }
6918
+ });
6919
+ return unwrap(response);
6920
+ }
6921
+ async function batchApproveDataManagementRows(request, params) {
6922
+ const response = await request({
6923
+ url: "/workflow/approve/batch",
6924
+ method: "post",
6925
+ data: {
6926
+ instanceIds: params.formInstanceIds,
6927
+ action: params.action,
6928
+ comments: params.comments
6929
+ }
6930
+ });
6931
+ return unwrap(response);
6932
+ }
6933
+ async function exportDataManagementRows(request, params) {
6934
+ return request({
6935
+ url: `/${params.appType}/v1/form/advancedExport.xlsx`,
6936
+ method: "get",
6937
+ responseType: "blob",
6938
+ params: {
6939
+ appType: params.appType,
6940
+ formUuid: params.formUuid,
6941
+ filters: params.rawFilters ?? buildFilterPayload(params.filters),
6942
+ conditionType: params.conditionType,
6943
+ searchKeyWord: params.searchKeyWord,
6944
+ currentPage: params.currentPage,
6945
+ pageSize: params.pageSize,
6946
+ order: JSON.stringify(params.order || []),
6947
+ instanceStatus: params.instanceStatus,
6948
+ exportAll: params.exportAll || "n",
6949
+ embedImages: params.embedImages || "n",
6950
+ exportFields: (params.exportFields || []).join(",")
6951
+ }
6952
+ });
6953
+ }
6954
+ async function importPreviewDataManagementRows(request, params) {
6955
+ const response = await request({
6956
+ url: `/${params.appType}/v1/form/importPreview.xlsx`,
6957
+ method: "post",
6958
+ data: { formUuid: params.formUuid, fileBase64: params.fileBase64 }
6959
+ });
6960
+ return unwrap(response);
6961
+ }
6962
+ async function importDataManagementRows(request, params) {
6963
+ const response = await request({
6964
+ url: `/${params.appType}/v1/form/import.xlsx`,
6965
+ method: "post",
6966
+ data: { formUuid: params.formUuid, fileBase64: params.fileBase64 }
6967
+ });
6968
+ return unwrap(response);
6969
+ }
6970
+ async function getDataManagementTransferRecords(request, params) {
6971
+ const response = await request({
6972
+ url: `/${params.appType}/v1/form/${params.type}Records.json`,
6973
+ method: "get",
6974
+ params
6975
+ });
6976
+ return normalizeDataManagementList(response);
6977
+ }
6978
+
6701
6979
  // src/layout/FormSection/index.tsx
6702
6980
  import { useState as useState18 } from "react";
6703
6981
  import { jsx as jsx72, jsxs as jsxs25 } from "react/jsx-runtime";
@@ -7104,37 +7382,91 @@ function useFormSubmit(config) {
7104
7382
 
7105
7383
  // src/hooks/useFieldPermission.ts
7106
7384
  import { useMemo as useMemo12, useCallback as useCallback10 } from "react";
7385
+
7386
+ // src/utils/permissions.ts
7387
+ var OPERATION_ALIASES = {
7388
+ VIEW: "view",
7389
+ EDIT: "edit",
7390
+ DELETE: "delete",
7391
+ VIEW_CHANGE_RECORDS: "change_records",
7392
+ CHANGE_RECORDS: "change_records",
7393
+ VIEW_PROCESS: "workflow",
7394
+ WORKFLOW: "workflow"
7395
+ };
7396
+ function normalizeOperation(operation) {
7397
+ const raw = String(operation || "").trim();
7398
+ if (!raw) return "";
7399
+ const upper = raw.toUpperCase();
7400
+ return OPERATION_ALIASES[upper] || raw.toLowerCase();
7401
+ }
7402
+ function hasViewOperation(operations, expected) {
7403
+ const normalized = new Set((operations || []).map(normalizeOperation));
7404
+ return normalized.has(normalizeOperation(expected));
7405
+ }
7406
+ function normalizeFieldBehaviors(permissions, mode) {
7407
+ const behaviors = {};
7408
+ Object.entries(permissions?.fieldPermissions || {}).forEach(([fieldId, value]) => {
7409
+ if (value === "FORM_FILED_HIDDEN") {
7410
+ behaviors[fieldId] = "HIDDEN";
7411
+ } else if (value === "FORM_FILED_EDIT") {
7412
+ behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7413
+ } else {
7414
+ behaviors[fieldId] = "READONLY";
7415
+ }
7416
+ });
7417
+ return behaviors;
7418
+ }
7419
+ function hasViewPermission(permissions) {
7420
+ const operations = permissions?.operations || [];
7421
+ return operations.length === 0 ? false : hasViewOperation(operations, "view");
7422
+ }
7423
+
7424
+ // src/hooks/useFieldPermission.ts
7425
+ var normalizeBehavior = (value) => {
7426
+ if (value === "EDITABLE") return "NORMAL";
7427
+ if (value === "READ_ONLY") return "READONLY";
7428
+ if (value === "DISABLED") return "DISABLED";
7429
+ if (value === "HIDDEN") return "HIDDEN";
7430
+ if (value === "NORMAL" || value === "READONLY") return value;
7431
+ return "READONLY";
7432
+ };
7433
+ var normalizeFlowConfig = (config) => {
7434
+ if (!config) return null;
7435
+ if (Array.isArray(config)) {
7436
+ const result = {};
7437
+ config.forEach((item) => {
7438
+ const fieldId = item?.fieldId || item?.field_id || item?.id;
7439
+ if (!fieldId) return;
7440
+ result[fieldId] = normalizeBehavior(item?.fieldBehavior || item?.behavior || item?.value);
7441
+ });
7442
+ return Object.keys(result).length > 0 ? result : null;
7443
+ }
7444
+ if (typeof config === "object") {
7445
+ const result = {};
7446
+ Object.entries(config).forEach(([fieldId, value]) => {
7447
+ result[fieldId] = normalizeBehavior(
7448
+ typeof value === "string" ? value : value?.fieldBehavior || value?.behavior
7449
+ );
7450
+ });
7451
+ return result;
7452
+ }
7453
+ return null;
7454
+ };
7107
7455
  function useFieldPermission(options) {
7108
7456
  const { viewPermissions, processDefinition, currentTask, isApprover, mode } = options;
7109
7457
  const computeBehaviors = useCallback10(() => {
7110
7458
  const behaviors = {};
7111
7459
  if (!currentTask && viewPermissions) {
7112
- const { fieldPermissions } = viewPermissions;
7113
- for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
7114
- if (perm === "FORM_FILED_HIDDEN") {
7115
- behaviors[fieldId] = "HIDDEN";
7116
- } else if (perm === "FORM_FILED_VIEW") {
7117
- behaviors[fieldId] = "READONLY";
7118
- } else if (perm === "FORM_FILED_EDIT") {
7119
- behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7120
- }
7121
- }
7122
- return behaviors;
7460
+ return normalizeFieldBehaviors(viewPermissions, mode);
7123
7461
  }
7124
7462
  if (currentTask && !isApprover && viewPermissions) {
7125
- const { fieldPermissions } = viewPermissions;
7126
- for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
7127
- if (perm === "FORM_FILED_HIDDEN") {
7128
- behaviors[fieldId] = "HIDDEN";
7129
- } else {
7130
- behaviors[fieldId] = "READONLY";
7131
- }
7132
- }
7133
- return behaviors;
7463
+ return normalizeFieldBehaviors(viewPermissions, "readonly");
7134
7464
  }
7135
7465
  if (currentTask && isApprover && currentTask.nodeType === "originator_return") {
7136
7466
  if (processDefinition?.flowConfig && processDefinition.startNodeId) {
7137
- const startConfig = processDefinition.flowConfig[processDefinition.startNodeId];
7467
+ const startConfig = normalizeFlowConfig(
7468
+ processDefinition.flowConfig[processDefinition.startNodeId]
7469
+ );
7138
7470
  if (startConfig) {
7139
7471
  for (const [fieldId, behavior] of Object.entries(startConfig)) {
7140
7472
  behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
@@ -7154,7 +7486,7 @@ function useFieldPermission(options) {
7154
7486
  return behaviors;
7155
7487
  }
7156
7488
  if (currentTask && isApprover && processDefinition?.flowConfig) {
7157
- const nodeConfig = processDefinition.flowConfig[currentTask.nodeId];
7489
+ const nodeConfig = normalizeFlowConfig(processDefinition.flowConfig[currentTask.nodeId]);
7158
7490
  if (nodeConfig) {
7159
7491
  for (const [fieldId, behavior] of Object.entries(nodeConfig)) {
7160
7492
  behaviors[fieldId] = mode === "edit" ? behavior : "READONLY";
@@ -7163,16 +7495,7 @@ function useFieldPermission(options) {
7163
7495
  }
7164
7496
  }
7165
7497
  if (viewPermissions) {
7166
- const { fieldPermissions } = viewPermissions;
7167
- for (const [fieldId, perm] of Object.entries(fieldPermissions)) {
7168
- if (perm === "FORM_FILED_HIDDEN") {
7169
- behaviors[fieldId] = "HIDDEN";
7170
- } else if (perm === "FORM_FILED_VIEW") {
7171
- behaviors[fieldId] = "READONLY";
7172
- } else if (perm === "FORM_FILED_EDIT") {
7173
- behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7174
- }
7175
- }
7498
+ return normalizeFieldBehaviors(viewPermissions, mode);
7176
7499
  }
7177
7500
  return behaviors;
7178
7501
  }, [viewPermissions, processDefinition, currentTask, isApprover, mode]);
@@ -7251,20 +7574,6 @@ var extractFormValues = (formInstance, fieldIds) => {
7251
7574
  };
7252
7575
 
7253
7576
  // src/hooks/useFormDetail.ts
7254
- function buildFieldBehaviors(permissions, mode) {
7255
- const behaviors = {};
7256
- if (!permissions) return behaviors;
7257
- for (const [fieldId, perm] of Object.entries(permissions.fieldPermissions)) {
7258
- if (perm === "FORM_FILED_HIDDEN") {
7259
- behaviors[fieldId] = "HIDDEN";
7260
- } else if (perm === "FORM_FILED_VIEW") {
7261
- behaviors[fieldId] = "READONLY";
7262
- } else if (perm === "FORM_FILED_EDIT") {
7263
- behaviors[fieldId] = mode === "edit" ? "NORMAL" : "READONLY";
7264
- }
7265
- }
7266
- return behaviors;
7267
- }
7268
7577
  function useFormDetail(options) {
7269
7578
  const { formUuid, appType, formInstanceId, fieldIds, onPermissionDenied } = options;
7270
7579
  const { api } = useFormContext();
@@ -7290,7 +7599,7 @@ function useFormDetail(options) {
7290
7599
  getFormData(request, { formInstanceId, appType, formUuid })
7291
7600
  ]);
7292
7601
  if (!mountedRef.current) return;
7293
- if (!permResult || !permResult.operations || permResult.operations.length === 0) {
7602
+ if (!permResult || !hasViewOperation(permResult.operations, "view")) {
7294
7603
  onPermissionDenied?.();
7295
7604
  }
7296
7605
  setPermissions(permResult);
@@ -7312,10 +7621,10 @@ function useFormDetail(options) {
7312
7621
  useEffect29(() => {
7313
7622
  loadData();
7314
7623
  }, [loadData]);
7315
- const fieldBehaviors = buildFieldBehaviors(permissions, mode);
7316
- const canEdit = permissions?.operations?.includes("EDIT") ?? false;
7317
- const canDelete = permissions?.operations?.includes("DELETE") ?? false;
7318
- const canViewChangeRecords = permissions?.operations?.includes("VIEW_CHANGE_RECORDS") ?? false;
7624
+ const fieldBehaviors = normalizeFieldBehaviors(permissions, mode);
7625
+ const canEdit = hasViewOperation(permissions?.operations, "edit");
7626
+ const canDelete = hasViewOperation(permissions?.operations, "delete");
7627
+ const canViewChangeRecords = hasViewOperation(permissions?.operations, "change_records");
7319
7628
  const switchToEdit = useCallback11(() => {
7320
7629
  setMode("edit");
7321
7630
  loadData();
@@ -7719,6 +8028,30 @@ function useApprovalActions(options) {
7719
8028
  },
7720
8029
  [request, currentTaskId, formUuid, appType, getFormValues, onActionComplete, resetLoading]
7721
8030
  );
8031
+ const callbackTask = useCallback13(
8032
+ async (payload) => {
8033
+ if (!currentTaskId) {
8034
+ console.error("[useApprovalActions] callbackTask failed: no currentTaskId");
8035
+ return false;
8036
+ }
8037
+ setIsLoading(true);
8038
+ setCurrentAction("callback");
8039
+ try {
8040
+ await triggerCallbackTask(request, {
8041
+ taskId: currentTaskId,
8042
+ payload
8043
+ });
8044
+ resetLoading();
8045
+ onActionComplete?.("callback");
8046
+ return true;
8047
+ } catch (error) {
8048
+ console.error("[useApprovalActions] callbackTask failed:", error);
8049
+ resetLoading();
8050
+ return false;
8051
+ }
8052
+ },
8053
+ [request, currentTaskId, onActionComplete, resetLoading]
8054
+ );
7722
8055
  const loadReturnableNodes = useCallback13(async () => {
7723
8056
  if (!currentTaskId) return;
7724
8057
  try {
@@ -7738,6 +8071,7 @@ function useApprovalActions(options) {
7738
8071
  withdraw,
7739
8072
  save,
7740
8073
  resubmit,
8074
+ callbackTask,
7741
8075
  isLoading,
7742
8076
  currentAction,
7743
8077
  returnableNodes,
@@ -7747,6 +8081,16 @@ function useApprovalActions(options) {
7747
8081
 
7748
8082
  // src/hooks/useChangeRecords.ts
7749
8083
  import { useState as useState27, useEffect as useEffect32, useCallback as useCallback14, useRef as useRef12 } from "react";
8084
+ var normalizeChangeRecordList = (value) => {
8085
+ const body = value?.data ?? value?.result ?? value ?? {};
8086
+ const records = body.records ?? body.data ?? body.list ?? body.items ?? [];
8087
+ return {
8088
+ records: Array.isArray(records) ? records : [],
8089
+ total: Number(body.total ?? body.totalCount ?? body.count ?? records.length) || 0,
8090
+ page: Number(body.page ?? body.currentPage ?? 1) || 1,
8091
+ pageSize: Number(body.pageSize ?? body.limit ?? 20) || 20
8092
+ };
8093
+ };
7750
8094
  function useChangeRecords(options) {
7751
8095
  const { formUuid, appType, formInstanceId, pageSize = 20, autoLoad = true } = options;
7752
8096
  const { api } = useFormContext();
@@ -7775,13 +8119,14 @@ function useChangeRecords(options) {
7775
8119
  pageSize
7776
8120
  });
7777
8121
  if (!mountedRef.current) return;
8122
+ const normalized = normalizeChangeRecordList(result);
7778
8123
  if (append) {
7779
- setRecords((prev) => [...prev, ...result.records]);
8124
+ setRecords((prev) => [...prev, ...normalized.records]);
7780
8125
  } else {
7781
- setRecords(result.records);
8126
+ setRecords(normalized.records);
7782
8127
  }
7783
- setTotal(result.total);
7784
- setPage(pageNum);
8128
+ setTotal(normalized.total);
8129
+ setPage(normalized.page || pageNum);
7785
8130
  } catch (error) {
7786
8131
  console.error("[useChangeRecords] Failed to load change records:", error);
7787
8132
  } finally {
@@ -7797,7 +8142,8 @@ function useChangeRecords(options) {
7797
8142
  fetchRecords(1, false);
7798
8143
  }
7799
8144
  }, [autoLoad, fetchRecords]);
7800
- const hasMore = records.length < total;
8145
+ const safeRecords = Array.isArray(records) ? records : [];
8146
+ const hasMore = safeRecords.length < total;
7801
8147
  const loadMore = useCallback14(async () => {
7802
8148
  if (!hasMore || loading) return;
7803
8149
  await fetchRecords(page + 1, true);
@@ -7809,7 +8155,7 @@ function useChangeRecords(options) {
7809
8155
  await fetchRecords(1, false);
7810
8156
  }, [fetchRecords]);
7811
8157
  return {
7812
- records,
8158
+ records: safeRecords,
7813
8159
  loading,
7814
8160
  total,
7815
8161
  page,
@@ -8105,178 +8451,840 @@ var FormSummaryCard = ({
8105
8451
  ] });
8106
8452
  };
8107
8453
 
8108
- // src/modules/ChangeRecords.tsx
8454
+ // src/modules/RecordChangePanel.tsx
8109
8455
  import { useState as useState30 } from "react";
8110
- import { Skeleton } from "antd";
8111
- import { DownOutlined, UpOutlined } from "@ant-design/icons";
8456
+ import { Button as Button9, Empty as Empty3, Pagination, Skeleton, Tag as Tag4, Tooltip } from "antd";
8457
+ import {
8458
+ ArrowRightOutlined,
8459
+ DownOutlined,
8460
+ HistoryOutlined,
8461
+ ReloadOutlined,
8462
+ UpOutlined
8463
+ } from "@ant-design/icons";
8112
8464
  import { jsx as jsx78, jsxs as jsxs30 } from "react/jsx-runtime";
8113
- var ChangeRecords = ({
8465
+ var sourceLabels = {
8466
+ frontend: "\u524D\u7AEF",
8467
+ integration: "\u96C6\u6210",
8468
+ automation: "\u81EA\u52A8\u5316",
8469
+ import: "\u5BFC\u5165"
8470
+ };
8471
+ var typeLabels = {
8472
+ create: "\u65B0\u589E",
8473
+ update: "\u4FEE\u6539",
8474
+ delete: "\u5220\u9664"
8475
+ };
8476
+ function formatValue(value) {
8477
+ if (value === null || value === void 0 || value === "")
8478
+ return /* @__PURE__ */ jsx78("span", { className: "text-ant-text-tertiary", children: "\u7A7A" });
8479
+ if (Array.isArray(value)) {
8480
+ return /* @__PURE__ */ jsx78("span", { className: "inline-flex flex-wrap gap-1", children: value.map((item, index) => /* @__PURE__ */ jsx78(Tag4, { className: "m-0", children: String(
8481
+ typeof item === "object" ? item.label || item.value || JSON.stringify(item) : item
8482
+ ) }, `${index}-${String(item)}`)) });
8483
+ }
8484
+ if (typeof value === "object") {
8485
+ const label = value.label ?? value.value;
8486
+ return label ? String(label) : /* @__PURE__ */ jsx78("code", { className: "text-xs", children: JSON.stringify(value) });
8487
+ }
8488
+ return String(value);
8489
+ }
8490
+ function getInitial(name) {
8491
+ return String(name || "?").trim().slice(0, 1).toUpperCase() || "?";
8492
+ }
8493
+ var RecordChangePanel = ({
8114
8494
  records = [],
8115
8495
  loading = false,
8496
+ total,
8497
+ page = 1,
8498
+ pageSize = 20,
8116
8499
  defaultExpanded = false,
8117
8500
  hasMore = false,
8118
8501
  onLoadMore,
8502
+ onRefresh,
8119
8503
  onExpand,
8120
- className = "",
8121
- renderItem
8504
+ onPageChange,
8505
+ className = ""
8122
8506
  }) => {
8123
8507
  const [expanded, setExpanded] = useState30(defaultExpanded);
8508
+ const count = total ?? records.length;
8124
8509
  const handleToggle = () => {
8125
8510
  const next = !expanded;
8126
8511
  setExpanded(next);
8127
- if (next && onExpand) {
8128
- onExpand();
8129
- }
8512
+ if (next) onExpand?.();
8130
8513
  };
8131
- const defaultRenderItem = (record) => /* @__PURE__ */ jsxs30("div", { className: "pl-4 py-3 border-l-2 border-gray-200 ml-1", children: [
8132
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2 text-xs text-gray-400", children: [
8133
- /* @__PURE__ */ jsx78("span", { children: record.operatedAt }),
8134
- /* @__PURE__ */ jsx78("span", { className: "text-gray-600 font-medium", children: record.operatorName }),
8135
- /* @__PURE__ */ jsx78("span", { children: "\u4FEE\u6539\u4E86" }),
8136
- /* @__PURE__ */ jsx78("span", { className: "text-gray-800 font-medium", children: record.fieldLabel })
8137
- ] }),
8138
- /* @__PURE__ */ jsxs30("div", { className: "mt-1.5 text-sm text-gray-600 flex items-center gap-2", children: [
8139
- /* @__PURE__ */ jsx78("span", { className: "bg-red-50 text-red-600 px-1.5 py-0.5 rounded text-xs line-through", children: formatValue(record.oldValue) }),
8140
- /* @__PURE__ */ jsx78("span", { className: "text-gray-400", children: "\u2192" }),
8141
- /* @__PURE__ */ jsx78("span", { className: "bg-green-50 text-green-600 px-1.5 py-0.5 rounded text-xs", children: formatValue(record.newValue) })
8142
- ] })
8143
- ] });
8144
- return /* @__PURE__ */ jsxs30("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 ${className}`, children: [
8145
- /* @__PURE__ */ jsxs30(
8146
- "button",
8514
+ return /* @__PURE__ */ jsxs30(
8515
+ "section",
8516
+ {
8517
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
8518
+ children: [
8519
+ /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between gap-3 border-b border-ant-border-secondary px-5 py-4", children: [
8520
+ /* @__PURE__ */ jsxs30(
8521
+ "button",
8522
+ {
8523
+ type: "button",
8524
+ className: "flex min-w-0 items-center gap-2 bg-transparent p-0 text-left",
8525
+ onClick: handleToggle,
8526
+ children: [
8527
+ /* @__PURE__ */ jsx78(HistoryOutlined, { className: "text-ant-primary" }),
8528
+ /* @__PURE__ */ jsx78("span", { className: "font-semibold text-ant-text", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8529
+ /* @__PURE__ */ jsxs30("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-xs text-ant-text-tertiary", children: [
8530
+ count,
8531
+ " \u6761"
8532
+ ] }),
8533
+ expanded ? /* @__PURE__ */ jsx78(UpOutlined, { className: "text-xs" }) : /* @__PURE__ */ jsx78(DownOutlined, { className: "text-xs" })
8534
+ ]
8535
+ }
8536
+ ),
8537
+ expanded && /* @__PURE__ */ jsx78(
8538
+ Button9,
8539
+ {
8540
+ type: "text",
8541
+ size: "small",
8542
+ icon: /* @__PURE__ */ jsx78(ReloadOutlined, {}),
8543
+ onClick: onRefresh,
8544
+ disabled: loading,
8545
+ children: "\u5237\u65B0"
8546
+ }
8547
+ )
8548
+ ] }),
8549
+ expanded ? /* @__PURE__ */ jsxs30("div", { className: "p-5", children: [
8550
+ loading && records.length === 0 ? /* @__PURE__ */ jsx78(Skeleton, { active: true, paragraph: { rows: 3 } }) : records.length === 0 ? /* @__PURE__ */ jsx78(Empty3, { description: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ jsx78("div", { className: "space-y-4", children: records.map((record) => {
8551
+ const changes = record.changes && record.changes.length > 0 ? record.changes : [
8552
+ {
8553
+ fieldKey: record.fieldId,
8554
+ fieldLabel: record.fieldLabel,
8555
+ beforeValue: record.oldValue,
8556
+ afterValue: record.newValue
8557
+ }
8558
+ ];
8559
+ const operator = record.operatorName || (record.changeSource ? "\u7CFB\u7EDF" : "\u672A\u77E5");
8560
+ const operatedAt = record.operatedAt || record.createdAt || "-";
8561
+ return /* @__PURE__ */ jsxs30(
8562
+ "article",
8563
+ {
8564
+ className: "rounded-md border border-ant-border-secondary p-4",
8565
+ children: [
8566
+ /* @__PURE__ */ jsxs30("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
8567
+ /* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-center gap-3", children: [
8568
+ /* @__PURE__ */ jsx78("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) }),
8569
+ /* @__PURE__ */ jsxs30("span", { className: "min-w-0", children: [
8570
+ /* @__PURE__ */ jsxs30("span", { className: "block text-sm font-medium text-ant-text", children: [
8571
+ operator,
8572
+ record.operatorDepartmentName && /* @__PURE__ */ jsx78("span", { className: "ml-2 font-normal text-ant-text-tertiary", children: record.operatorDepartmentName })
8573
+ ] }),
8574
+ /* @__PURE__ */ jsxs30("span", { className: "block text-xs text-ant-text-tertiary", children: [
8575
+ "\u53D8\u66F4 ",
8576
+ record.changedCount || changes.length,
8577
+ " \u9879 \xB7 ",
8578
+ operatedAt
8579
+ ] })
8580
+ ] })
8581
+ ] }),
8582
+ /* @__PURE__ */ jsxs30("span", { className: "flex flex-wrap justify-end gap-2", children: [
8583
+ record.changeType && /* @__PURE__ */ jsx78(Tag4, { children: typeLabels[record.changeType] || record.changeType }),
8584
+ record.changeSource && /* @__PURE__ */ jsx78(Tag4, { color: "blue", children: sourceLabels[record.changeSource] || record.changeSource }),
8585
+ record.operationId && /* @__PURE__ */ jsx78(Tooltip, { title: `\u64CD\u4F5CID\uFF1A${record.operationId}`, children: /* @__PURE__ */ jsx78(Tag4, { children: record.operationId.slice(0, 8) }) })
8586
+ ] })
8587
+ ] }),
8588
+ /* @__PURE__ */ jsx78("div", { className: "mt-4 space-y-3", children: changes.map((change) => /* @__PURE__ */ jsxs30(
8589
+ "div",
8590
+ {
8591
+ className: "grid gap-2 md:grid-cols-[160px_1fr]",
8592
+ children: [
8593
+ /* @__PURE__ */ jsx78("div", { className: "text-sm font-medium text-ant-text-secondary", children: change.fieldLabel || change.fieldKey || "-" }),
8594
+ /* @__PURE__ */ jsxs30("div", { className: "grid min-w-0 grid-cols-[1fr_auto_1fr] items-start gap-2 text-sm", children: [
8595
+ /* @__PURE__ */ jsx78("div", { className: "min-w-0 rounded bg-red-50 px-2 py-1 text-red-700", children: formatValue(change.beforeValue) }),
8596
+ /* @__PURE__ */ jsx78(ArrowRightOutlined, { className: "mt-1 text-xs text-ant-text-tertiary" }),
8597
+ /* @__PURE__ */ jsx78("div", { className: "min-w-0 rounded bg-emerald-50 px-2 py-1 text-emerald-700", children: formatValue(change.afterValue) })
8598
+ ] })
8599
+ ]
8600
+ },
8601
+ change.fieldKey || change.fieldLabel
8602
+ )) })
8603
+ ]
8604
+ },
8605
+ record.id || record.operationId
8606
+ );
8607
+ }) }),
8608
+ onPageChange && count > pageSize ? /* @__PURE__ */ jsx78("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsx78(
8609
+ Pagination,
8610
+ {
8611
+ size: "small",
8612
+ current: page,
8613
+ pageSize,
8614
+ total: count,
8615
+ onChange: onPageChange,
8616
+ showSizeChanger: true
8617
+ }
8618
+ ) }) : hasMore ? /* @__PURE__ */ jsx78(Button9, { block: true, className: "mt-4", onClick: onLoadMore, loading, children: "\u52A0\u8F7D\u66F4\u591A" }) : null
8619
+ ] }) : /* @__PURE__ */ jsx78("div", { className: "px-5 py-4 text-sm text-ant-text-tertiary", children: "\u70B9\u51FB\u5C55\u5F00\u67E5\u770B\u53D8\u66F4\u8BB0\u5F55" })
8620
+ ]
8621
+ }
8622
+ );
8623
+ };
8624
+
8625
+ // src/modules/ChangeRecords.tsx
8626
+ import { jsx as jsx79, jsxs as jsxs31 } from "react/jsx-runtime";
8627
+ var ChangeRecords = ({
8628
+ records = [],
8629
+ loading = false,
8630
+ defaultExpanded = false,
8631
+ hasMore = false,
8632
+ onLoadMore,
8633
+ onExpand,
8634
+ className = "",
8635
+ renderItem
8636
+ }) => {
8637
+ if (renderItem) {
8638
+ return /* @__PURE__ */ jsxs31(
8639
+ "section",
8147
8640
  {
8148
- type: "button",
8149
- className: "w-full flex items-center justify-between p-6 text-left hover:bg-gray-50/50 transition-colors rounded-xl",
8150
- onClick: handleToggle,
8641
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
8151
8642
  children: [
8152
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
8153
- /* @__PURE__ */ jsx78("h3", { className: "text-lg font-semibold text-gray-900", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8154
- /* @__PURE__ */ jsx78("span", { className: "text-xs text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded-full", children: records.length })
8155
- ] }),
8156
- /* @__PURE__ */ jsx78("span", { className: "text-gray-400 text-xs", children: expanded ? /* @__PURE__ */ jsx78(UpOutlined, {}) : /* @__PURE__ */ jsx78(DownOutlined, {}) })
8643
+ /* @__PURE__ */ jsx79("div", { className: "border-b border-ant-border-secondary px-5 py-4 font-semibold", children: "\u53D8\u66F4\u8BB0\u5F55" }),
8644
+ /* @__PURE__ */ jsxs31("div", { className: "p-5", children: [
8645
+ records.length === 0 ? /* @__PURE__ */ jsx79("p", { className: "m-0 text-center text-sm text-ant-text-tertiary", children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ jsx79("div", { className: "space-y-2", children: records.map((record) => /* @__PURE__ */ jsx79("div", { children: renderItem(record) }, record.id)) }),
8646
+ hasMore && /* @__PURE__ */ jsx79(
8647
+ "button",
8648
+ {
8649
+ type: "button",
8650
+ className: "mt-4 w-full rounded-md border border-ant-border-secondary py-2 text-sm text-ant-primary",
8651
+ onClick: onLoadMore,
8652
+ disabled: loading,
8653
+ children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
8654
+ }
8655
+ )
8656
+ ] })
8157
8657
  ]
8158
8658
  }
8159
- ),
8160
- expanded && /* @__PURE__ */ jsxs30("div", { className: "px-6 pb-6", children: [
8161
- loading && records.length === 0 ? /* @__PURE__ */ jsx78(Skeleton, { active: true, paragraph: { rows: 3 } }) : records.length === 0 ? /* @__PURE__ */ jsx78("p", { className: "text-sm text-gray-400 text-center py-4", children: "\u6682\u65E0\u53D8\u66F4\u8BB0\u5F55" }) : /* @__PURE__ */ jsx78("div", { className: "space-y-1", children: records.map((record) => /* @__PURE__ */ jsx78("div", { children: renderItem ? renderItem(record) : defaultRenderItem(record) }, record.id)) }),
8162
- hasMore && /* @__PURE__ */ jsx78(
8163
- "button",
8164
- {
8165
- type: "button",
8166
- 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",
8167
- onClick: onLoadMore,
8168
- disabled: loading,
8169
- children: loading ? "\u52A0\u8F7D\u4E2D..." : "\u52A0\u8F7D\u66F4\u591A"
8170
- }
8171
- )
8172
- ] })
8173
- ] });
8659
+ );
8660
+ }
8661
+ return /* @__PURE__ */ jsx79(
8662
+ RecordChangePanel,
8663
+ {
8664
+ records,
8665
+ loading,
8666
+ defaultExpanded,
8667
+ hasMore,
8668
+ onLoadMore,
8669
+ onRefresh: onExpand,
8670
+ onExpand,
8671
+ className
8672
+ }
8673
+ );
8174
8674
  };
8175
- function formatValue(value) {
8176
- if (value === null || value === void 0) return "\u7A7A";
8177
- if (typeof value === "object") return JSON.stringify(value);
8178
- return String(value);
8179
- }
8180
8675
 
8181
8676
  // src/modules/ApprovalTimeline.tsx
8182
- import { Fragment as Fragment2, jsx as jsx79, jsxs as jsxs31 } from "react/jsx-runtime";
8677
+ import { useMemo as useMemo14 } from "react";
8678
+ import {
8679
+ ApiOutlined,
8680
+ CheckCircleFilled,
8681
+ ClockCircleOutlined,
8682
+ CloseCircleFilled,
8683
+ CodeOutlined,
8684
+ CopyOutlined,
8685
+ EditOutlined,
8686
+ FileTextOutlined,
8687
+ LoadingOutlined,
8688
+ NotificationOutlined,
8689
+ ReloadOutlined as ReloadOutlined2,
8690
+ RollbackOutlined,
8691
+ UserOutlined as UserOutlined2
8692
+ } from "@ant-design/icons";
8693
+ import { jsx as jsx80, jsxs as jsxs32 } from "react/jsx-runtime";
8694
+ var systemNodeTypes = /* @__PURE__ */ new Set([
8695
+ "condition",
8696
+ "condition_branch",
8697
+ "js_code",
8698
+ "data_retrieve_single",
8699
+ "data_retrieve_batch",
8700
+ "data_create",
8701
+ "data_update",
8702
+ "connector_call",
8703
+ "loop_container",
8704
+ "work_notification",
8705
+ "dingtalk_card",
8706
+ "system"
8707
+ ]);
8708
+ var systemLabels = {
8709
+ condition: "\u6761\u4EF6\u5224\u65AD",
8710
+ condition_branch: "\u6761\u4EF6\u5206\u652F",
8711
+ js_code: "JS \u4EE3\u7801",
8712
+ data_retrieve_single: "\u6570\u636E\u8BFB\u53D6",
8713
+ data_retrieve_batch: "\u6279\u91CF\u8BFB\u53D6",
8714
+ data_create: "\u6570\u636E\u521B\u5EFA",
8715
+ data_update: "\u6570\u636E\u66F4\u65B0",
8716
+ connector_call: "\u8FDE\u63A5\u5668\u8C03\u7528",
8717
+ loop_container: "\u5FAA\u73AF\u8282\u70B9",
8718
+ work_notification: "\u5DE5\u4F5C\u901A\u77E5",
8719
+ dingtalk_card: "\u9489\u9489\u5361\u7247",
8720
+ system: "\u7CFB\u7EDF\u52A8\u4F5C"
8721
+ };
8183
8722
  var toneClasses2 = {
8184
- brand: "bg-blue-50 text-blue-600",
8185
- success: "bg-green-50 text-green-600",
8186
- danger: "bg-red-50 text-red-600",
8187
- neutral: "bg-gray-100 text-gray-500",
8188
- warning: "bg-amber-50 text-amber-600"
8723
+ brand: "bg-blue-600 text-white border-blue-600",
8724
+ success: "bg-emerald-50 text-emerald-700 border-emerald-200",
8725
+ danger: "bg-red-50 text-red-700 border-red-200",
8726
+ neutral: "bg-gray-50 text-gray-600 border-gray-200",
8727
+ warning: "bg-amber-50 text-amber-700 border-amber-200",
8728
+ return: "bg-amber-50 text-amber-700 border-amber-200",
8729
+ future: "bg-gray-50 text-gray-400 border-gray-200"
8189
8730
  };
8190
- function getNodePhase(task) {
8191
- if (task.status === "approved" || task.status === "rejected" || task.status === "returned" || task.status === "copied") {
8731
+ function groupTasks(tasks) {
8732
+ const groups = /* @__PURE__ */ new Map();
8733
+ tasks.forEach((task, index) => {
8734
+ const key = task.nodeVisitId || `${task.nodeId || "node"}-${task.id || task.taskId || index}`;
8735
+ const group = groups.get(key) || [];
8736
+ group.push(task);
8737
+ groups.set(key, group);
8738
+ });
8739
+ return Array.from(groups.values()).map((group) => {
8740
+ const hasOrSignResult = group.some(
8741
+ (task) => task.nodeType === "approval" && task.multiApproveMode === "or" && !task.isSimulated && ["approved", "rejected", "returned"].includes(task.status)
8742
+ );
8743
+ if (!hasOrSignResult) return group;
8744
+ const outcome = group.filter(
8745
+ (task) => !task.isSimulated && ["approved", "rejected", "returned"].includes(task.status)
8746
+ );
8747
+ return outcome.length > 0 ? outcome : group;
8748
+ });
8749
+ }
8750
+ function isCompactNode(task) {
8751
+ return task.nodeType === "start" || task.nodeType === "copy" || task.nodeType === "end" || systemNodeTypes.has(task.nodeType);
8752
+ }
8753
+ function getNodeTitle(task) {
8754
+ if (task.nodeType === "start") return task.title || task.nodeName || "\u6D41\u7A0B\u63D0\u4EA4";
8755
+ if (task.nodeType === "originator_return") return task.title || task.nodeName || "\u53D1\u8D77\u4EBA\u4FEE\u6539";
8756
+ if (task.nodeType === "copy") return task.title || task.nodeName || "\u6284\u9001\u901A\u77E5";
8757
+ if (task.nodeType === "callback_wait") return task.title || task.nodeName || "\u7B49\u5F85\u7B2C\u4E09\u65B9\u56DE\u8C03";
8758
+ if (task.nodeType === "end") return task.title || task.nodeName || "\u6D41\u7A0B\u5B8C\u6210";
8759
+ if (systemNodeTypes.has(task.nodeType))
8760
+ return task.title || task.nodeName || systemLabels[task.nodeType] || "\u7CFB\u7EDF\u52A8\u4F5C";
8761
+ return task.title || task.nodeName || "\u5BA1\u6279";
8762
+ }
8763
+ function getVisualState(task, isFutureGroup) {
8764
+ if (isFutureGroup || task.isSimulated || task.status === "simulated") return "future";
8765
+ if (task.status === "rejected") return "rejected";
8766
+ if (task.status === "returned") return "returned";
8767
+ if (task.status === "pending" || task.status === "waiting" || task.canApprove)
8768
+ return task.canApprove ? "current" : "waiting";
8769
+ if (task.status === "approved" || task.status === "copied" || task.nodeType === "start" || task.nodeType === "end") {
8192
8770
  return "completed";
8193
8771
  }
8194
- if (task.status === "pending" || task.status === "waiting") {
8195
- return "active";
8772
+ return "neutral";
8773
+ }
8774
+ function getStatusMeta(task, state, compact) {
8775
+ if (state === "future") return { label: "\u672A\u5F00\u59CB", tone: "neutral" };
8776
+ if (state === "current")
8777
+ return { label: task.nodeType === "callback_wait" ? "\u7B49\u5F85\u56DE\u8C03" : "\u5BA1\u6279\u4E2D", tone: "brand" };
8778
+ if (state === "waiting") return { label: "\u7B49\u5F85\u5904\u7406\u4E2D", tone: "neutral" };
8779
+ if (state === "rejected") return TASK_STATUS_META.rejected;
8780
+ if (state === "returned") return TASK_STATUS_META.returned;
8781
+ if (task.nodeType === "copy" || task.status === "copied") return TASK_STATUS_META.copied;
8782
+ if (compact) return { label: "\u5DF2\u5B8C\u6210", tone: "neutral" };
8783
+ return TASK_STATUS_META[task.status] || TASK_STATUS_META.approved;
8784
+ }
8785
+ function getIcon(task, state) {
8786
+ if (state === "current")
8787
+ return task.nodeType === "callback_wait" ? /* @__PURE__ */ jsx80(ClockCircleOutlined, {}) : /* @__PURE__ */ jsx80(LoadingOutlined, {});
8788
+ if (state === "future" || state === "waiting")
8789
+ return task.nodeType === "approval" ? /* @__PURE__ */ jsx80(UserOutlined2, {}) : /* @__PURE__ */ jsx80(ClockCircleOutlined, {});
8790
+ if (state === "rejected") return /* @__PURE__ */ jsx80(CloseCircleFilled, {});
8791
+ if (state === "returned") return /* @__PURE__ */ jsx80(RollbackOutlined, {});
8792
+ switch (task.nodeType) {
8793
+ case "start":
8794
+ return /* @__PURE__ */ jsx80(FileTextOutlined, {});
8795
+ case "approval":
8796
+ return /* @__PURE__ */ jsx80(CheckCircleFilled, {});
8797
+ case "originator_return":
8798
+ return /* @__PURE__ */ jsx80(EditOutlined, {});
8799
+ case "copy":
8800
+ return /* @__PURE__ */ jsx80(CopyOutlined, {});
8801
+ case "callback_wait":
8802
+ return /* @__PURE__ */ jsx80(ClockCircleOutlined, {});
8803
+ case "js_code":
8804
+ return /* @__PURE__ */ jsx80(CodeOutlined, {});
8805
+ case "connector_call":
8806
+ return /* @__PURE__ */ jsx80(ApiOutlined, {});
8807
+ case "work_notification":
8808
+ case "dingtalk_card":
8809
+ return /* @__PURE__ */ jsx80(NotificationOutlined, {});
8810
+ case "data_retrieve_single":
8811
+ case "data_retrieve_batch":
8812
+ case "data_create":
8813
+ case "data_update":
8814
+ case "loop_container":
8815
+ return /* @__PURE__ */ jsx80(ReloadOutlined2, {});
8816
+ default:
8817
+ return /* @__PURE__ */ jsx80(CheckCircleFilled, {});
8196
8818
  }
8197
- return "pending";
8819
+ }
8820
+ function getDotClass(state) {
8821
+ const map = {
8822
+ completed: "border-emerald-500 text-emerald-600 bg-white",
8823
+ current: "border-blue-600 bg-blue-600 text-white",
8824
+ waiting: "border-gray-200 text-gray-300 bg-white",
8825
+ future: "border-dashed border-gray-300 text-gray-300 bg-white",
8826
+ rejected: "border-red-500 text-red-600 bg-white",
8827
+ returned: "border-amber-500 text-amber-600 bg-white",
8828
+ neutral: "border-gray-200 text-gray-400 bg-white"
8829
+ };
8830
+ return map[state];
8198
8831
  }
8199
8832
  var ApprovalTimeline = ({
8200
8833
  tasks,
8201
8834
  className = "",
8202
8835
  renderNode,
8203
8836
  showRemarks = true,
8204
- compactMode = false
8837
+ compactMode = false,
8838
+ showApproverInfo = true
8205
8839
  }) => {
8206
- const taskList = Array.isArray(tasks) ? tasks : [];
8840
+ const taskList = useMemo14(() => Array.isArray(tasks) ? tasks : [], [tasks]);
8841
+ const groups = useMemo14(() => groupTasks(taskList), [taskList]);
8207
8842
  if (taskList.length === 0) {
8208
- return /* @__PURE__ */ jsx79("div", { className: `bg-white rounded-xl shadow-sm border border-gray-100 p-6 ${className}`, children: /* @__PURE__ */ jsx79("p", { className: "text-sm text-gray-400 text-center", children: "\u6682\u65E0\u5BA1\u6279\u8BB0\u5F55" }) });
8843
+ return /* @__PURE__ */ jsx80(
8844
+ "div",
8845
+ {
8846
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container p-6 ${className}`,
8847
+ children: /* @__PURE__ */ jsx80("p", { className: "m-0 text-center text-sm text-ant-text-tertiary", children: "\u6682\u65E0\u5BA1\u6279\u8BB0\u5F55" })
8848
+ }
8849
+ );
8209
8850
  }
8210
- return /* @__PURE__ */ jsx79("div", { className: `${className}`, children: taskList.map((task, index) => {
8211
- const taskKey = task.taskId || task.id || `${task.nodeId}-${index}`;
8212
- if (renderNode) {
8213
- return /* @__PURE__ */ jsx79("div", { children: renderNode(task, index) }, taskKey);
8214
- }
8215
- const phase = getNodePhase(task);
8216
- const isLast = index === taskList.length - 1;
8217
- const statusMeta = TASK_STATUS_META[task.status];
8218
- return /* @__PURE__ */ jsxs31("div", { className: "flex gap-4", children: [
8219
- /* @__PURE__ */ jsxs31("div", { className: "flex flex-col items-center", children: [
8220
- phase === "completed" && /* @__PURE__ */ jsx79("div", { className: "w-3 h-3 rounded-full bg-green-500 flex-shrink-0" }),
8221
- phase === "active" && /* @__PURE__ */ jsx79("div", { className: "w-3 h-3 rounded-full bg-blue-500 ring-4 ring-blue-100 flex-shrink-0" }),
8222
- phase === "pending" && /* @__PURE__ */ jsx79("div", { className: "w-3 h-3 rounded-full bg-gray-300 flex-shrink-0" }),
8223
- !isLast && /* @__PURE__ */ jsx79(
8224
- "div",
8225
- {
8226
- 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"}`
8227
- }
8228
- )
8229
- ] }),
8230
- /* @__PURE__ */ jsx79("div", { className: `flex-1 pb-6 ${isLast ? "pb-0" : ""}`, children: /* @__PURE__ */ jsxs31(
8851
+ if (renderNode) {
8852
+ return /* @__PURE__ */ jsx80("div", { className, children: taskList.map((task, index) => /* @__PURE__ */ jsx80("div", { children: renderNode(task, index) }, task.taskId || task.id || index)) });
8853
+ }
8854
+ return /* @__PURE__ */ jsx80("div", { className: `approval-timeline ${className}`, children: groups.map((group, index) => {
8855
+ const node = group[0];
8856
+ const isLast = index === groups.length - 1;
8857
+ const isFutureGroup = group.some((task) => task.isSimulated || task.status === "simulated");
8858
+ const compact = compactMode || isCompactNode(node);
8859
+ const state = getVisualState(node, isFutureGroup);
8860
+ const statusMeta = getStatusMeta(node, state, compact);
8861
+ const title = getNodeTitle(node);
8862
+ const time = node.actionAt || node.createdAt;
8863
+ return /* @__PURE__ */ jsxs32(
8864
+ "div",
8865
+ {
8866
+ className: `relative flex gap-4 pb-5 ${isLast ? "pb-0" : ""}`,
8867
+ children: [
8868
+ !isLast && /* @__PURE__ */ jsx80(
8869
+ "div",
8870
+ {
8871
+ className: `absolute bottom-0 left-[21px] top-11 w-px ${state === "future" ? "border-l border-dashed border-gray-300" : "bg-ant-border-secondary"}`
8872
+ }
8873
+ ),
8874
+ /* @__PURE__ */ jsx80(
8875
+ "div",
8876
+ {
8877
+ 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)}`,
8878
+ children: getIcon(node, state)
8879
+ }
8880
+ ),
8881
+ /* @__PURE__ */ jsx80("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxs32(
8882
+ "div",
8883
+ {
8884
+ 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"}`,
8885
+ children: [
8886
+ /* @__PURE__ */ jsxs32("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
8887
+ /* @__PURE__ */ jsxs32("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
8888
+ /* @__PURE__ */ jsx80("span", { className: "font-medium text-ant-text", children: title }),
8889
+ /* @__PURE__ */ jsx80(
8890
+ "span",
8891
+ {
8892
+ className: `inline-flex min-h-6 items-center rounded-md border px-2 text-xs font-medium ${state === "future" ? toneClasses2.future : toneClasses2[statusMeta.tone]}`,
8893
+ children: statusMeta.label
8894
+ }
8895
+ ),
8896
+ node.nodeType === "originator_return" && /* @__PURE__ */ jsx80("span", { className: "rounded-md bg-amber-50 px-2 py-1 text-xs text-amber-700", children: "\u53D1\u8D77\u4EBA\u64CD\u4F5C" })
8897
+ ] }),
8898
+ !isFutureGroup && time && /* @__PURE__ */ jsx80("span", { className: "text-xs text-ant-text-tertiary", children: time })
8899
+ ] }),
8900
+ showApproverInfo && !compact && group.length > 0 && /* @__PURE__ */ jsxs32("div", { className: "mt-3 flex flex-wrap gap-3", children: [
8901
+ /* @__PURE__ */ jsx80("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" }),
8902
+ group.map((assignee) => /* @__PURE__ */ jsxs32(
8903
+ "span",
8904
+ {
8905
+ className: "inline-flex min-w-0 items-center gap-2",
8906
+ children: [
8907
+ /* @__PURE__ */ jsx80("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) || "?" }),
8908
+ /* @__PURE__ */ jsxs32("span", { className: "min-w-0", children: [
8909
+ /* @__PURE__ */ jsx80("span", { className: "block text-sm font-medium text-ant-text", children: assignee.assigneeName || "\u7CFB\u7EDF" }),
8910
+ /* @__PURE__ */ jsx80("span", { className: "block text-xs text-ant-text-tertiary", children: assignee.departmentName || assignee.actionAt || assignee.createdAt || "" })
8911
+ ] })
8912
+ ]
8913
+ },
8914
+ assignee.taskId || assignee.id
8915
+ ))
8916
+ ] }),
8917
+ showApproverInfo && compact && /* @__PURE__ */ jsx80("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" : "") }),
8918
+ showRemarks && node.comments && /* @__PURE__ */ jsx80(
8919
+ "div",
8920
+ {
8921
+ 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"}`,
8922
+ children: node.comments
8923
+ }
8924
+ )
8925
+ ]
8926
+ }
8927
+ ) })
8928
+ ]
8929
+ },
8930
+ node.nodeVisitId || `${node.nodeId}-${node.taskId}-${index}`
8931
+ );
8932
+ }) });
8933
+ };
8934
+
8935
+ // src/modules/ApprovalActionBar.tsx
8936
+ import { useMemo as useMemo16, useState as useState32 } from "react";
8937
+ import { Form, Input as Input10, Modal as Modal5, Select as Select5 } from "antd";
8938
+ import {
8939
+ CheckOutlined,
8940
+ CloseOutlined,
8941
+ RollbackOutlined as RollbackOutlined2,
8942
+ SaveOutlined,
8943
+ SwapOutlined
8944
+ } from "@ant-design/icons";
8945
+
8946
+ // src/modules/StickyActionBar.tsx
8947
+ import { useEffect as useEffect35, useMemo as useMemo15, useState as useState31 } from "react";
8948
+ import { Button as Button10, Dropdown } from "antd";
8949
+ import { MoreOutlined } from "@ant-design/icons";
8950
+
8951
+ // src/utils/confirmAction.ts
8952
+ var confirmAction = (title, content) => {
8953
+ const message2 = [title, content].filter(Boolean).join("\n") || "\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F";
8954
+ if (typeof window === "undefined" || typeof window.confirm !== "function") {
8955
+ return true;
8956
+ }
8957
+ try {
8958
+ return window.confirm(message2);
8959
+ } catch {
8960
+ return true;
8961
+ }
8962
+ };
8963
+
8964
+ // src/modules/StickyActionBar.tsx
8965
+ import { Fragment as Fragment2, jsx as jsx81, jsxs as jsxs33 } from "react/jsx-runtime";
8966
+ var getActionPriority = (action) => {
8967
+ const maybePriority = action.priority;
8968
+ if (typeof maybePriority === "number") return maybePriority;
8969
+ if (action.type === "primary") return 10;
8970
+ if (action.type === "danger") return 90;
8971
+ return 50;
8972
+ };
8973
+ var getPlacement = (action) => action.placement;
8974
+ var StickyActionBar = ({
8975
+ actions,
8976
+ className = "",
8977
+ maxMobileButtons = 2,
8978
+ layoutMode = "default",
8979
+ maxWidth = 1120,
8980
+ position = "sticky"
8981
+ }) => {
8982
+ const [isMobile, setIsMobile] = useState31(false);
8983
+ useEffect35(() => {
8984
+ const update = () => setIsMobile(typeof window !== "undefined" && window.innerWidth <= 768);
8985
+ update();
8986
+ window.addEventListener("resize", update);
8987
+ return () => window.removeEventListener("resize", update);
8988
+ }, []);
8989
+ const visibleActions = useMemo15(
8990
+ () => actions.filter((action) => action.visible !== false).sort((left, right) => getActionPriority(left) - getActionPriority(right)),
8991
+ [actions]
8992
+ );
8993
+ if (visibleActions.length === 0) return null;
8994
+ const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
8995
+ const primaryMobile = visibleActions.slice(0, maxMobileButtons);
8996
+ const moreMobile = visibleActions.slice(maxMobileButtons);
8997
+ const leftActions = visibleActions.filter((action) => getPlacement(action) === "left");
8998
+ const rightActions = visibleActions.filter((action) => getPlacement(action) !== "left");
8999
+ const positionClass = position === "fixed" ? "fixed bottom-0 left-0 right-0" : position === "inline" ? "relative" : "sticky bottom-0";
9000
+ const runAction = (action) => {
9001
+ if (action.confirm) {
9002
+ const confirmed = confirmAction(action.confirm.title, action.confirm.content);
9003
+ if (!confirmed) return;
9004
+ }
9005
+ action.onClick();
9006
+ };
9007
+ const renderButton = (action, mobile = false) => /* @__PURE__ */ jsx81(
9008
+ Button10,
9009
+ {
9010
+ type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
9011
+ danger: action.type === "danger",
9012
+ loading: action.loading,
9013
+ disabled: action.disabled,
9014
+ icon: action.icon,
9015
+ onClick: () => runAction(action),
9016
+ className: `${mobile ? "min-w-0 flex-1" : "min-w-[88px]"} rounded-md`,
9017
+ children: action.label
9018
+ },
9019
+ action.key
9020
+ );
9021
+ return /* @__PURE__ */ jsx81(
9022
+ "div",
9023
+ {
9024
+ 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}`,
9025
+ children: /* @__PURE__ */ jsx81(
8231
9026
  "div",
8232
9027
  {
8233
- 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"}`,
8234
- children: [
8235
- /* @__PURE__ */ jsxs31("div", { className: "flex items-center justify-between", children: [
8236
- /* @__PURE__ */ jsx79("span", { className: "text-sm font-medium text-gray-900", children: task.nodeName }),
8237
- statusMeta && /* @__PURE__ */ jsx79(
8238
- "span",
9028
+ className: `mx-auto flex w-full items-center gap-3 ${layoutMode === "approval" && !isMobile ? "justify-between" : "justify-end"}`,
9029
+ style: { maxWidth: maxWidthStyle },
9030
+ children: isMobile ? /* @__PURE__ */ jsxs33(Fragment2, { children: [
9031
+ /* @__PURE__ */ jsx81("div", { className: "flex flex-1 gap-2", children: primaryMobile.map((action) => renderButton(action, true)) }),
9032
+ moreMobile.length > 0 && /* @__PURE__ */ jsx81(
9033
+ Dropdown,
9034
+ {
9035
+ trigger: ["click"],
9036
+ placement: "topRight",
9037
+ menu: {
9038
+ items: moreMobile.map((action) => ({
9039
+ key: action.key,
9040
+ label: action.label,
9041
+ danger: action.type === "danger",
9042
+ disabled: action.disabled,
9043
+ icon: action.icon,
9044
+ onClick: () => runAction(action)
9045
+ }))
9046
+ },
9047
+ children: /* @__PURE__ */ jsx81(Button10, { icon: /* @__PURE__ */ jsx81(MoreOutlined, {}), className: "rounded-md", children: "\u66F4\u591A" })
9048
+ }
9049
+ )
9050
+ ] }) : layoutMode === "approval" && leftActions.length > 0 ? /* @__PURE__ */ jsxs33(Fragment2, { children: [
9051
+ /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center gap-3", children: leftActions.map((action) => renderButton(action)) }),
9052
+ /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center justify-end gap-3", children: rightActions.map((action) => renderButton(action)) })
9053
+ ] }) : /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center justify-end gap-3", children: visibleActions.map((action) => renderButton(action)) })
9054
+ }
9055
+ )
9056
+ }
9057
+ );
9058
+ };
9059
+
9060
+ // src/modules/ApprovalActionBar.tsx
9061
+ import { Fragment as Fragment3, jsx as jsx82, jsxs as jsxs34 } from "react/jsx-runtime";
9062
+ var actionPriority = {
9063
+ agree: 10,
9064
+ approved: 10,
9065
+ return: 20,
9066
+ transfer: 30,
9067
+ resubmit: 40,
9068
+ save: 80,
9069
+ withdraw: 90,
9070
+ rejected: 100,
9071
+ reject: 100
9072
+ };
9073
+ function getActionLabel(action) {
9074
+ return action.name?.zh_CN || action.text?.zh_CN || action.action;
9075
+ }
9076
+ function normalizeAction(action) {
9077
+ if (action === "approved") return "agree";
9078
+ if (action === "reject") return "rejected";
9079
+ if (action === "agree" || action === "rejected" || action === "withdraw" || action === "transfer" || action === "return" || action === "resubmit") {
9080
+ return action;
9081
+ }
9082
+ if (action === "save" || action === "callback") return action;
9083
+ return "agree";
9084
+ }
9085
+ function getModalTitle(action) {
9086
+ switch (action) {
9087
+ case "agree":
9088
+ return "\u5BA1\u6279\u610F\u89C1";
9089
+ case "rejected":
9090
+ return "\u62D2\u7EDD\u7406\u7531";
9091
+ case "withdraw":
9092
+ return "\u64A4\u9500\u6D41\u7A0B";
9093
+ case "transfer":
9094
+ return "\u8F6C\u4EA4\u4EFB\u52A1";
9095
+ case "return":
9096
+ return "\u9000\u56DE\u4EFB\u52A1";
9097
+ case "resubmit":
9098
+ return "\u91CD\u65B0\u63D0\u4EA4";
9099
+ default:
9100
+ return "\u786E\u8BA4\u64CD\u4F5C";
9101
+ }
9102
+ }
9103
+ var ApprovalActionBar = ({
9104
+ actions,
9105
+ onApprove,
9106
+ onReject,
9107
+ onTransfer,
9108
+ onReturn,
9109
+ onWithdraw,
9110
+ onSave,
9111
+ onResubmit,
9112
+ onCallback,
9113
+ returnableNodes = [],
9114
+ onLoadReturnableNodes,
9115
+ renderTransferSelector,
9116
+ renderReturnNodeLabel,
9117
+ renderActionModalExtra,
9118
+ maxMobileButtons = 2,
9119
+ className = "",
9120
+ inDrawer = false
9121
+ }) => {
9122
+ const [form] = Form.useForm();
9123
+ const [modalAction, setModalAction] = useState32(null);
9124
+ const [activeAction, setActiveAction] = useState32(null);
9125
+ const [loading, setLoading] = useState32(false);
9126
+ const visibleActions = useMemo16(
9127
+ () => actions.filter((action) => !action.hidden).sort((a, b) => (actionPriority[a.action] ?? 50) - (actionPriority[b.action] ?? 50)),
9128
+ [actions]
9129
+ );
9130
+ const openModal = async (action, target) => {
9131
+ setActiveAction(action);
9132
+ const defaultComments = action.remark?.content?.zh_CN;
9133
+ form.setFieldsValue({
9134
+ comments: defaultComments || "",
9135
+ reason: "",
9136
+ userId: void 0,
9137
+ nodeId: void 0
9138
+ });
9139
+ if (target === "return") await onLoadReturnableNodes?.();
9140
+ setModalAction(target);
9141
+ };
9142
+ const executeDirect = async (action) => {
9143
+ const normalized = normalizeAction(action.action);
9144
+ if (normalized === "save") {
9145
+ await onSave?.();
9146
+ return;
9147
+ }
9148
+ if (normalized === "callback") {
9149
+ await onCallback?.();
9150
+ return;
9151
+ }
9152
+ if (normalized === "agree") {
9153
+ await onApprove?.();
9154
+ }
9155
+ };
9156
+ const handleActionClick = async (action) => {
9157
+ const normalized = normalizeAction(action.action);
9158
+ if (normalized === "save" || normalized === "callback") {
9159
+ await executeDirect(action);
9160
+ return;
9161
+ }
9162
+ await openModal(action, normalized);
9163
+ };
9164
+ const handleOk = async () => {
9165
+ if (!modalAction) return;
9166
+ const values = await form.validateFields();
9167
+ setLoading(true);
9168
+ try {
9169
+ if (modalAction === "agree") await onApprove?.(values.comments || void 0);
9170
+ if (modalAction === "rejected") await onReject?.(values.comments || void 0);
9171
+ if (modalAction === "withdraw")
9172
+ await onWithdraw?.(values.reason || values.comments || void 0);
9173
+ if (modalAction === "transfer") await onTransfer?.(values.userId, values.reason || void 0);
9174
+ if (modalAction === "return") await onReturn?.(values.nodeId, values.reason || void 0);
9175
+ if (modalAction === "resubmit") await onResubmit?.(values.comments || void 0);
9176
+ setModalAction(null);
9177
+ setActiveAction(null);
9178
+ form.resetFields();
9179
+ } finally {
9180
+ setLoading(false);
9181
+ }
9182
+ };
9183
+ const actionConfigs = visibleActions.map((action) => {
9184
+ const normalized = normalizeAction(action.action);
9185
+ const danger = normalized === "rejected" || normalized === "withdraw";
9186
+ return {
9187
+ key: action.action,
9188
+ label: getActionLabel(action),
9189
+ type: normalized === "agree" ? "primary" : danger ? "danger" : "default",
9190
+ icon: normalized === "agree" ? /* @__PURE__ */ jsx82(CheckOutlined, {}) : normalized === "rejected" ? /* @__PURE__ */ jsx82(CloseOutlined, {}) : normalized === "transfer" ? /* @__PURE__ */ jsx82(SwapOutlined, {}) : normalized === "return" || normalized === "withdraw" ? /* @__PURE__ */ jsx82(RollbackOutlined2, {}) : normalized === "save" ? /* @__PURE__ */ jsx82(SaveOutlined, {}) : void 0,
9191
+ onClick: () => handleActionClick(action),
9192
+ placement: danger || normalized === "save" ? "right" : "left",
9193
+ priority: actionPriority[action.action] ?? 50
9194
+ };
9195
+ });
9196
+ const requiredComment = activeAction?.remark?.required || modalAction === "rejected" || modalAction === "withdraw";
9197
+ return /* @__PURE__ */ jsxs34(Fragment3, { children: [
9198
+ /* @__PURE__ */ jsx82(
9199
+ StickyActionBar,
9200
+ {
9201
+ actions: actionConfigs,
9202
+ layoutMode: "approval",
9203
+ maxMobileButtons,
9204
+ className,
9205
+ inDrawer
9206
+ }
9207
+ ),
9208
+ /* @__PURE__ */ jsx82(
9209
+ Modal5,
9210
+ {
9211
+ getContainer: false,
9212
+ title: getModalTitle(modalAction),
9213
+ open: modalAction !== null,
9214
+ okText: "\u786E\u8BA4",
9215
+ cancelText: "\u53D6\u6D88",
9216
+ confirmLoading: loading,
9217
+ onOk: handleOk,
9218
+ onCancel: () => {
9219
+ setModalAction(null);
9220
+ setActiveAction(null);
9221
+ form.resetFields();
9222
+ },
9223
+ destroyOnClose: true,
9224
+ children: /* @__PURE__ */ jsxs34(Form, { form, layout: "vertical", children: [
9225
+ modalAction === "transfer" && /* @__PURE__ */ jsx82(
9226
+ Form.Item,
9227
+ {
9228
+ name: "userId",
9229
+ label: "\u8F6C\u4EA4\u7ED9",
9230
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u8F6C\u4EA4\u7528\u6237" }],
9231
+ children: renderTransferSelector ? renderTransferSelector({
9232
+ value: form.getFieldValue("userId"),
9233
+ onChange: (userId) => form.setFieldsValue({ userId })
9234
+ }) : /* @__PURE__ */ jsx82(Input10, { placeholder: "\u8BF7\u8F93\u5165\u7528\u6237 ID" })
9235
+ }
9236
+ ),
9237
+ modalAction === "return" && /* @__PURE__ */ jsx82(
9238
+ Form.Item,
9239
+ {
9240
+ name: "nodeId",
9241
+ label: "\u9000\u56DE\u5230\u8282\u70B9",
9242
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9" }],
9243
+ children: /* @__PURE__ */ jsx82(
9244
+ Select5,
8239
9245
  {
8240
- className: `px-2 py-0.5 rounded-full text-xs font-medium ${toneClasses2[statusMeta.tone] || toneClasses2.neutral}`,
8241
- children: statusMeta.label
9246
+ placeholder: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9",
9247
+ getPopupContainer: (triggerNode) => triggerNode.parentElement || document.body,
9248
+ options: returnableNodes.map((node) => ({
9249
+ value: node.nodeId || node.id || "",
9250
+ label: renderReturnNodeLabel ? renderReturnNodeLabel(node) : node.nodeName || node.name || node.nodeId || node.id
9251
+ }))
8242
9252
  }
8243
9253
  )
8244
- ] }),
8245
- task.assigneeName && /* @__PURE__ */ jsxs31("div", { className: "mt-2 flex items-center gap-1.5 text-sm text-gray-600", children: [
8246
- /* @__PURE__ */ jsx79("span", { className: "text-gray-400", children: "\u{1F464}" }),
8247
- /* @__PURE__ */ jsxs31("span", { children: [
8248
- phase === "active" ? "\u5F53\u524D\u5BA1\u6279\u4EBA: " : "",
8249
- task.assigneeName
8250
- ] }),
8251
- task.departmentName && /* @__PURE__ */ jsxs31(Fragment2, { children: [
8252
- /* @__PURE__ */ jsx79("span", { className: "text-gray-300", children: "\xB7" }),
8253
- /* @__PURE__ */ jsx79("span", { className: "text-gray-400", children: task.departmentName })
8254
- ] })
8255
- ] }),
8256
- !compactMode && showRemarks && task.comments && /* @__PURE__ */ jsxs31("div", { className: "mt-2 bg-gray-50 rounded-md p-3 text-sm text-gray-600 italic", children: [
8257
- "\u{1F4AC} \u201C",
8258
- task.comments,
8259
- "\u201D"
8260
- ] }),
8261
- !compactMode && phase === "active" && !task.comments && /* @__PURE__ */ jsx79("div", { className: "mt-2 text-xs text-gray-400", children: "\u23F3 \u7B49\u5F85\u5904\u7406\u4E2D..." }),
8262
- !compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ jsxs31("div", { className: "mt-2 text-xs text-gray-400", children: [
8263
- "\u{1F550} ",
8264
- task.actionAt || task.createdAt
8265
- ] }),
8266
- compactMode && (task.actionAt || task.createdAt) && /* @__PURE__ */ jsx79("div", { className: "mt-1 text-xs text-gray-400", children: task.actionAt || task.createdAt })
8267
- ]
8268
- }
8269
- ) })
8270
- ] }, taskKey);
8271
- }) });
9254
+ }
9255
+ ),
9256
+ /* @__PURE__ */ jsx82(
9257
+ Form.Item,
9258
+ {
9259
+ name: modalAction === "withdraw" || modalAction === "transfer" || modalAction === "return" ? "reason" : "comments",
9260
+ label: modalAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : modalAction === "transfer" ? "\u8F6C\u4EA4\u539F\u56E0" : modalAction === "return" ? "\u9000\u56DE\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1",
9261
+ rules: [{ required: requiredComment, message: "\u8BF7\u586B\u5199\u8BF4\u660E" }],
9262
+ children: /* @__PURE__ */ jsx82(Input10.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u8BF4\u660E" })
9263
+ }
9264
+ ),
9265
+ activeAction && renderActionModalExtra?.(activeAction)
9266
+ ] })
9267
+ }
9268
+ )
9269
+ ] });
8272
9270
  };
8273
9271
 
8274
9272
  // src/modules/ApprovalActions.tsx
8275
- import { useState as useState31 } from "react";
8276
- import { Button as Button9, Drawer as Drawer2, Input as Input10, Dropdown } from "antd";
8277
- import { MoreOutlined, LoadingOutlined } from "@ant-design/icons";
8278
- import { Fragment as Fragment3, jsx as jsx80, jsxs as jsxs32 } from "react/jsx-runtime";
8279
- var { TextArea: TextArea3 } = Input10;
9273
+ import { useMemo as useMemo17, useState as useState33 } from "react";
9274
+ import { Button as Button11, Dropdown as Dropdown2, Form as Form2, Input as Input11, Modal as Modal6 } from "antd";
9275
+ import { MoreOutlined as MoreOutlined2 } from "@ant-design/icons";
9276
+ import { Fragment as Fragment4, jsx as jsx83, jsxs as jsxs35 } from "react/jsx-runtime";
9277
+ var priority = {
9278
+ agree: 10,
9279
+ approved: 10,
9280
+ transfer: 20,
9281
+ return: 30,
9282
+ save: 40,
9283
+ withdraw: 90,
9284
+ rejected: 100,
9285
+ reject: 100
9286
+ };
9287
+ var getLabel = (action) => action.name?.zh_CN || action.text?.zh_CN || action.action;
8280
9288
  var ApprovalActions = ({
8281
9289
  actions,
8282
9290
  onApprove,
@@ -8289,167 +9297,150 @@ var ApprovalActions = ({
8289
9297
  maxVisible = 3,
8290
9298
  className = ""
8291
9299
  }) => {
8292
- const [drawerAction, setDrawerAction] = useState31(null);
8293
- const [comments, setComments] = useState31("");
8294
- const [loading, setLoading] = useState31(false);
8295
- const [saveLoading, setSaveLoading] = useState31(false);
8296
- const handleOpenDrawer = (action) => {
8297
- setComments("");
8298
- setDrawerAction(action);
8299
- };
8300
- const handleConfirm = async () => {
8301
- setLoading(true);
8302
- try {
8303
- if (drawerAction === "approve" && onApprove) {
8304
- await onApprove(comments || void 0);
8305
- } else if (drawerAction === "reject" && onReject) {
8306
- await onReject(comments || void 0);
8307
- } else if (drawerAction === "withdraw" && onWithdraw) {
8308
- await onWithdraw(comments || void 0);
8309
- }
8310
- setDrawerAction(null);
8311
- } finally {
8312
- setLoading(false);
8313
- }
9300
+ const [form] = Form2.useForm();
9301
+ const [modalAction, setModalAction] = useState33(null);
9302
+ const [activeAction, setActiveAction] = useState33(null);
9303
+ const [loading, setLoading] = useState33(false);
9304
+ const [saveLoading, setSaveLoading] = useState33(false);
9305
+ const renderableActions = useMemo17(
9306
+ () => actions.filter((action) => !action.hidden).sort((a, b) => (priority[a.action] ?? 50) - (priority[b.action] ?? 50)),
9307
+ [actions]
9308
+ );
9309
+ const openModal = (target, action) => {
9310
+ setActiveAction(action);
9311
+ form.setFieldsValue({ comments: action.remark?.content?.zh_CN || "" });
9312
+ setModalAction(target);
8314
9313
  };
8315
9314
  const handleSave = async () => {
8316
- if (!onSave) return;
8317
9315
  setSaveLoading(true);
8318
9316
  try {
8319
- await onSave();
9317
+ await onSave?.();
8320
9318
  } finally {
8321
9319
  setSaveLoading(false);
8322
9320
  }
8323
9321
  };
8324
- const actionMap = {};
8325
- actions.forEach((action) => {
8326
- switch (action.action) {
8327
- case "agree":
8328
- actionMap["agree"] = {
8329
- label: action.name.zh_CN || "\u540C\u610F",
8330
- handler: () => handleOpenDrawer("approve"),
8331
- type: "primary",
8332
- color: "green"
8333
- };
8334
- break;
8335
- case "rejected":
8336
- actionMap["rejected"] = {
8337
- label: action.name.zh_CN || "\u62D2\u7EDD",
8338
- handler: () => handleOpenDrawer("reject"),
8339
- type: "default"
8340
- };
8341
- break;
8342
- case "transfer":
8343
- actionMap["transfer"] = {
8344
- label: action.name.zh_CN || "\u8F6C\u4EA4",
8345
- handler: () => onTransfer?.(),
8346
- type: "default"
8347
- };
8348
- break;
8349
- case "return":
8350
- actionMap["return"] = {
8351
- label: action.name.zh_CN || "\u9000\u56DE",
8352
- handler: () => onReturn?.(),
8353
- type: "default"
8354
- };
8355
- break;
8356
- case "withdraw":
8357
- actionMap["withdraw"] = {
8358
- label: action.name.zh_CN || "\u64A4\u9500",
8359
- handler: () => handleOpenDrawer("withdraw"),
8360
- type: "default"
8361
- };
8362
- break;
8363
- case "save":
8364
- actionMap["save"] = {
8365
- label: action.name.zh_CN || "\u6682\u5B58",
8366
- handler: handleSave,
8367
- type: "default"
8368
- };
8369
- break;
9322
+ const handleAction = (action) => {
9323
+ if (action.action === "transfer") {
9324
+ onTransfer?.();
9325
+ return;
8370
9326
  }
8371
- });
8372
- const allButtons = Object.entries(actionMap);
8373
- const visibleButtons = allButtons.slice(0, maxVisible);
8374
- const moreButtons = allButtons.slice(maxVisible);
8375
- const drawerTitle = drawerAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : drawerAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : drawerAction === "withdraw" ? "\u64A4\u9500\u539F\u56E0" : "\u5BA1\u6279\u610F\u89C1";
8376
- return /* @__PURE__ */ jsxs32(Fragment3, { children: [
8377
- /* @__PURE__ */ jsxs32(
9327
+ if (action.action === "return") {
9328
+ onReturn?.();
9329
+ return;
9330
+ }
9331
+ if (action.action === "save") {
9332
+ void handleSave();
9333
+ return;
9334
+ }
9335
+ if (action.action === "withdraw") {
9336
+ openModal("withdraw", action);
9337
+ return;
9338
+ }
9339
+ if (action.action === "rejected" || action.action === "reject") {
9340
+ openModal("reject", action);
9341
+ return;
9342
+ }
9343
+ openModal("approve", action);
9344
+ };
9345
+ const handleConfirm = async () => {
9346
+ const values = await form.validateFields();
9347
+ setLoading(true);
9348
+ try {
9349
+ if (modalAction === "approve") await onApprove?.(values.comments || void 0);
9350
+ if (modalAction === "reject") await onReject?.(values.comments || void 0);
9351
+ if (modalAction === "withdraw") await onWithdraw?.(values.comments || void 0);
9352
+ setModalAction(null);
9353
+ setActiveAction(null);
9354
+ form.resetFields();
9355
+ } finally {
9356
+ setLoading(false);
9357
+ }
9358
+ };
9359
+ const visibleButtons = renderableActions.slice(0, maxVisible);
9360
+ const moreButtons = renderableActions.slice(maxVisible);
9361
+ const title = modalAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : modalAction === "reject" ? "\u62D2\u7EDD\u7406\u7531" : "\u64A4\u9500\u539F\u56E0";
9362
+ const button = (action) => /* @__PURE__ */ jsx83(
9363
+ Button11,
9364
+ {
9365
+ type: action.action === "agree" || action.action === "approved" ? "primary" : "default",
9366
+ danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9367
+ onClick: () => handleAction(action),
9368
+ loading: action.action === "save" && saveLoading,
9369
+ children: getLabel(action)
9370
+ },
9371
+ action.action
9372
+ );
9373
+ return /* @__PURE__ */ jsxs35(Fragment4, { children: [
9374
+ /* @__PURE__ */ jsxs35(
8378
9375
  "div",
8379
9376
  {
8380
9377
  className: `${layout === "horizontal" ? "flex items-center gap-3" : "flex flex-col gap-2"} ${className}`,
8381
9378
  children: [
8382
- visibleButtons.map(([key, btn]) => /* @__PURE__ */ jsx80(
8383
- Button9,
8384
- {
8385
- type: btn.type === "primary" ? "primary" : "default",
8386
- className: btn.color === "green" ? "!bg-green-600 !border-green-600 hover:!bg-green-700" : "",
8387
- onClick: btn.handler,
8388
- loading: key === "save" && saveLoading,
8389
- children: btn.label
8390
- },
8391
- key
8392
- )),
8393
- moreButtons.length > 0 && /* @__PURE__ */ jsx80(
8394
- Dropdown,
9379
+ visibleButtons.map(button),
9380
+ moreButtons.length > 0 && /* @__PURE__ */ jsx83(
9381
+ Dropdown2,
8395
9382
  {
9383
+ trigger: ["click"],
9384
+ getPopupContainer: (triggerNode) => triggerNode.parentElement || document.body,
8396
9385
  menu: {
8397
- items: moreButtons.map(([key, btn]) => ({
8398
- key,
8399
- label: btn.label,
8400
- onClick: btn.handler
9386
+ items: moreButtons.map((action) => ({
9387
+ key: action.action,
9388
+ label: getLabel(action),
9389
+ danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9390
+ onClick: () => handleAction(action)
8401
9391
  }))
8402
9392
  },
8403
- trigger: ["click"],
8404
- children: /* @__PURE__ */ jsx80(Button9, { icon: /* @__PURE__ */ jsx80(MoreOutlined, {}), children: "\u66F4\u591A" })
9393
+ children: /* @__PURE__ */ jsx83(Button11, { icon: /* @__PURE__ */ jsx83(MoreOutlined2, {}), children: "\u66F4\u591A" })
8405
9394
  }
8406
9395
  )
8407
9396
  ]
8408
9397
  }
8409
9398
  ),
8410
- /* @__PURE__ */ jsx80(
8411
- Drawer2,
9399
+ /* @__PURE__ */ jsx83(
9400
+ Modal6,
8412
9401
  {
8413
- title: drawerTitle,
8414
- open: drawerAction !== null,
8415
- onClose: () => setDrawerAction(null),
8416
- width: 400,
8417
- footer: /* @__PURE__ */ jsxs32("div", { className: "flex justify-end gap-3", children: [
8418
- /* @__PURE__ */ jsx80(Button9, { onClick: () => setDrawerAction(null), children: "\u53D6\u6D88" }),
8419
- /* @__PURE__ */ jsxs32(Button9, { type: "primary", onClick: handleConfirm, loading, children: [
8420
- loading && /* @__PURE__ */ jsx80(LoadingOutlined, {}),
8421
- "\u786E\u8BA4"
8422
- ] })
8423
- ] }),
8424
- children: /* @__PURE__ */ jsx80("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs32("div", { children: [
8425
- /* @__PURE__ */ jsx80("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" }),
8426
- /* @__PURE__ */ jsx80(
8427
- TextArea3,
8428
- {
8429
- rows: 4,
8430
- value: comments,
8431
- onChange: (e) => setComments(e.target.value),
8432
- 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...",
8433
- maxLength: 500,
8434
- showCount: true
8435
- }
8436
- )
8437
- ] }) })
9402
+ getContainer: false,
9403
+ title,
9404
+ open: modalAction !== null,
9405
+ okText: "\u786E\u8BA4",
9406
+ cancelText: "\u53D6\u6D88",
9407
+ confirmLoading: loading,
9408
+ onOk: handleConfirm,
9409
+ onCancel: () => {
9410
+ setModalAction(null);
9411
+ setActiveAction(null);
9412
+ form.resetFields();
9413
+ },
9414
+ destroyOnClose: true,
9415
+ children: /* @__PURE__ */ jsx83(Form2, { form, layout: "vertical", children: /* @__PURE__ */ jsx83(
9416
+ Form2.Item,
9417
+ {
9418
+ name: "comments",
9419
+ label: modalAction === "approve" ? "\u5BA1\u6279\u610F\u89C1" : "\u8BF7\u8F93\u5165\u7406\u7531",
9420
+ rules: [
9421
+ {
9422
+ required: Boolean(activeAction?.remark?.required) || modalAction !== "approve",
9423
+ message: "\u8BF7\u586B\u5199\u8BF4\u660E"
9424
+ }
9425
+ ],
9426
+ children: /* @__PURE__ */ jsx83(Input11.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u8BF4\u660E" })
9427
+ }
9428
+ ) })
8438
9429
  }
8439
9430
  )
8440
9431
  ] });
8441
9432
  };
8442
9433
 
8443
9434
  // src/modules/FormActionBar.tsx
8444
- import { useState as useState32 } from "react";
8445
- import { Button as Button10, Modal as Modal5 } from "antd";
8446
- import { Fragment as Fragment4, jsx as jsx81, jsxs as jsxs33 } from "react/jsx-runtime";
9435
+ import { useState as useState34 } from "react";
9436
+ import { Button as Button12 } from "antd";
9437
+ import { Fragment as Fragment5, jsx as jsx84, jsxs as jsxs36 } from "react/jsx-runtime";
8447
9438
  var FormActionBar = ({
8448
9439
  actions,
8449
9440
  position = "bottom-fixed",
8450
9441
  className = ""
8451
9442
  }) => {
8452
- const [loadingKeys, setLoadingKeys] = useState32(/* @__PURE__ */ new Set());
9443
+ const [loadingKeys, setLoadingKeys] = useState34(/* @__PURE__ */ new Set());
8453
9444
  const visibleActions = actions.filter((a) => a.visible !== false);
8454
9445
  const sortedActions = [...visibleActions].sort((a, b) => {
8455
9446
  if (a.type === "danger" && b.type !== "danger") return -1;
@@ -8460,15 +9451,9 @@ var FormActionBar = ({
8460
9451
  });
8461
9452
  const handleClick = async (action) => {
8462
9453
  if (action.confirm) {
8463
- Modal5.confirm({
8464
- title: action.confirm.title,
8465
- content: action.confirm.content,
8466
- okText: "\u786E\u8BA4",
8467
- cancelText: "\u53D6\u6D88",
8468
- onOk: async () => {
8469
- await executeAction(action);
8470
- }
8471
- });
9454
+ const confirmed = confirmAction(action.confirm.title, action.confirm.content);
9455
+ if (!confirmed) return;
9456
+ await executeAction(action);
8472
9457
  } else {
8473
9458
  await executeAction(action);
8474
9459
  }
@@ -8486,14 +9471,14 @@ var FormActionBar = ({
8486
9471
  }
8487
9472
  };
8488
9473
  const isFixed = position === "bottom-fixed";
8489
- const bar = /* @__PURE__ */ jsx81(
9474
+ const bar = /* @__PURE__ */ jsx84(
8490
9475
  "div",
8491
9476
  {
8492
9477
  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}`,
8493
- children: /* @__PURE__ */ jsx81("div", { className: "flex items-center justify-end gap-3 flex-wrap md:flex-nowrap", children: sortedActions.map((action) => {
9478
+ children: /* @__PURE__ */ jsx84("div", { className: "flex items-center justify-end gap-3 flex-wrap md:flex-nowrap", children: sortedActions.map((action) => {
8494
9479
  const isLoading = action.loading || loadingKeys.has(action.key);
8495
- return /* @__PURE__ */ jsx81(
8496
- Button10,
9480
+ return /* @__PURE__ */ jsx84(
9481
+ Button12,
8497
9482
  {
8498
9483
  type: action.type === "danger" ? "primary" : action.type === "text" ? "text" : action.type || "default",
8499
9484
  danger: action.type === "danger",
@@ -8510,18 +9495,137 @@ var FormActionBar = ({
8510
9495
  }
8511
9496
  );
8512
9497
  if (isFixed) {
8513
- return /* @__PURE__ */ jsxs33(Fragment4, { children: [
9498
+ return /* @__PURE__ */ jsxs36(Fragment5, { children: [
8514
9499
  bar,
8515
- /* @__PURE__ */ jsx81("div", { className: "h-16" })
9500
+ /* @__PURE__ */ jsx84("div", { className: "h-16" })
8516
9501
  ] });
8517
9502
  }
8518
9503
  return bar;
8519
9504
  };
8520
9505
 
9506
+ // src/modules/RuntimePageShell.tsx
9507
+ import { Alert, Empty as Empty4, Spin as Spin5 } from "antd";
9508
+ import { Fragment as Fragment6, jsx as jsx85, jsxs as jsxs37 } from "react/jsx-runtime";
9509
+ var RuntimePageShell = ({
9510
+ children,
9511
+ actions,
9512
+ loading = false,
9513
+ loadingTip = "\u6B63\u5728\u52A0\u8F7D\u9875\u9762...",
9514
+ accessDenied = false,
9515
+ error,
9516
+ empty,
9517
+ className = "",
9518
+ contentClassName = "",
9519
+ maxWidth = 1120,
9520
+ inDrawer = false
9521
+ }) => {
9522
+ const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
9523
+ const renderState = () => {
9524
+ if (loading) {
9525
+ return /* @__PURE__ */ jsx85("div", { className: "min-h-[360px] flex items-center justify-center", children: /* @__PURE__ */ jsx85(Spin5, { tip: loadingTip }) });
9526
+ }
9527
+ if (accessDenied) {
9528
+ return /* @__PURE__ */ jsx85(Empty4, { description: "\u65E0\u6743\u9650\u67E5\u770B\u8BE6\u60C5" });
9529
+ }
9530
+ if (error) {
9531
+ return /* @__PURE__ */ jsx85(Alert, { type: "error", showIcon: true, message: "\u9875\u9762\u52A0\u8F7D\u5931\u8D25", description: error });
9532
+ }
9533
+ if (empty) {
9534
+ return /* @__PURE__ */ jsx85(Fragment6, { children: empty });
9535
+ }
9536
+ return children;
9537
+ };
9538
+ return /* @__PURE__ */ jsxs37("div", { className: `sy-runtime-page min-h-full bg-ant-bg-layout text-ant-text ${className}`, children: [
9539
+ /* @__PURE__ */ jsx85(
9540
+ "div",
9541
+ {
9542
+ 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}`,
9543
+ style: { maxWidth: maxWidthStyle },
9544
+ children: renderState()
9545
+ }
9546
+ ),
9547
+ actions
9548
+ ] });
9549
+ };
9550
+
9551
+ // src/modules/SummaryPanel.tsx
9552
+ import { Avatar as Avatar2 } from "antd";
9553
+ import { ApartmentOutlined as ApartmentOutlined2, CalendarOutlined, FileTextOutlined as FileTextOutlined2 } from "@ant-design/icons";
9554
+ import { jsx as jsx86, jsxs as jsxs38 } from "react/jsx-runtime";
9555
+ var toneClasses3 = {
9556
+ brand: "bg-blue-50 text-blue-700 border-blue-200",
9557
+ success: "bg-emerald-50 text-emerald-700 border-emerald-200",
9558
+ danger: "bg-red-50 text-red-700 border-red-200",
9559
+ neutral: "bg-gray-50 text-gray-600 border-gray-200",
9560
+ warning: "bg-amber-50 text-amber-700 border-amber-200"
9561
+ };
9562
+ var SummaryPanel = ({
9563
+ title = "\u8BE6\u60C5",
9564
+ eyebrow,
9565
+ status,
9566
+ creator,
9567
+ createdAt,
9568
+ metaItems,
9569
+ className = "",
9570
+ children
9571
+ }) => {
9572
+ const defaultItems = [
9573
+ {
9574
+ key: "creator",
9575
+ label: "\u521B\u5EFA\u4EBA",
9576
+ value: creator?.name || "\u672A\u77E5\u7528\u6237",
9577
+ icon: creator?.avatar ? /* @__PURE__ */ jsx86(Avatar2, { size: 24, src: creator.avatar }) : /* @__PURE__ */ jsx86(Avatar2, { size: 24, children: creator?.name?.slice(0, 1) || "\u8868" })
9578
+ },
9579
+ {
9580
+ key: "department",
9581
+ label: "\u6240\u5C5E\u90E8\u95E8",
9582
+ value: creator?.department || "-",
9583
+ icon: /* @__PURE__ */ jsx86(ApartmentOutlined2, {})
9584
+ },
9585
+ {
9586
+ key: "createdAt",
9587
+ label: "\u521B\u5EFA\u65F6\u95F4",
9588
+ value: createdAt || "-",
9589
+ icon: /* @__PURE__ */ jsx86(CalendarOutlined, {})
9590
+ }
9591
+ ];
9592
+ const items = metaItems || defaultItems;
9593
+ return /* @__PURE__ */ jsx86(
9594
+ "section",
9595
+ {
9596
+ className: `rounded-lg border border-ant-border-secondary bg-ant-bg-container ${className}`,
9597
+ children: /* @__PURE__ */ jsxs38("div", { className: "p-5 md:p-6", children: [
9598
+ /* @__PURE__ */ jsxs38("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
9599
+ /* @__PURE__ */ jsx86("div", { className: "min-w-0 text-sm text-ant-text-tertiary", children: eyebrow || /* @__PURE__ */ jsxs38("span", { className: "inline-flex items-center gap-2", children: [
9600
+ /* @__PURE__ */ jsx86(FileTextOutlined2, {}),
9601
+ "\u6570\u636E\u5B9E\u4F8B"
9602
+ ] }) }),
9603
+ status && /* @__PURE__ */ jsx86(
9604
+ "span",
9605
+ {
9606
+ className: `inline-flex min-h-6 items-center rounded-md border px-2.5 text-xs font-medium ${toneClasses3[status.tone] || toneClasses3.neutral}`,
9607
+ children: status.label
9608
+ }
9609
+ )
9610
+ ] }),
9611
+ /* @__PURE__ */ jsx86("h1", { className: "m-0 break-words text-2xl font-semibold leading-9 text-ant-text md:text-[28px]", children: title }),
9612
+ items.length > 0 && /* @__PURE__ */ jsx86("div", { className: "mt-5 grid grid-cols-1 gap-4 md:grid-cols-3", children: items.map((item) => /* @__PURE__ */ jsxs38("div", { className: "flex min-w-0 items-center gap-3", children: [
9613
+ /* @__PURE__ */ jsx86("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 }),
9614
+ /* @__PURE__ */ jsxs38("span", { className: "min-w-0", children: [
9615
+ /* @__PURE__ */ jsx86("span", { className: "block text-xs leading-5 text-ant-text-tertiary", children: item.label }),
9616
+ /* @__PURE__ */ jsx86("span", { className: "block break-words text-sm font-medium leading-6 text-ant-text", children: item.value || "-" })
9617
+ ] })
9618
+ ] }, item.key)) }),
9619
+ children && /* @__PURE__ */ jsx86("div", { className: "mt-5", children })
9620
+ ] })
9621
+ }
9622
+ );
9623
+ };
9624
+
8521
9625
  // src/modules/DraftManager.tsx
8522
- import { Button as Button11 } from "antd";
8523
- import { EditOutlined } from "@ant-design/icons";
8524
- import { jsx as jsx82, jsxs as jsxs34 } from "react/jsx-runtime";
9626
+ import { Button as Button13 } from "antd";
9627
+ import { EditOutlined as EditOutlined2 } from "@ant-design/icons";
9628
+ import { jsx as jsx87, jsxs as jsxs39 } from "react/jsx-runtime";
8525
9629
  function formatRelativeTime(timestamp) {
8526
9630
  const now = Date.now();
8527
9631
  const diff = now - timestamp;
@@ -8542,85 +9646,1214 @@ var DraftManager = ({
8542
9646
  }) => {
8543
9647
  if (!hasDraft) return null;
8544
9648
  const timeLabel = draftTimestamp ? formatRelativeTime(draftTimestamp) : null;
8545
- return /* @__PURE__ */ jsx82(
9649
+ return /* @__PURE__ */ jsx87(
8546
9650
  "div",
8547
9651
  {
8548
9652
  className: `bg-blue-50 border border-blue-200 rounded-lg p-4 animate-[slideDown_0.3s_ease-out] ${className}`,
8549
- children: /* @__PURE__ */ jsxs34("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
8550
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
8551
- /* @__PURE__ */ jsx82(EditOutlined, { className: "text-blue-500" }),
8552
- /* @__PURE__ */ jsxs34("span", { children: [
9653
+ children: /* @__PURE__ */ jsxs39("div", { className: "flex items-center justify-between flex-wrap gap-3", children: [
9654
+ /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2 text-sm text-blue-700", children: [
9655
+ /* @__PURE__ */ jsx87(EditOutlined2, { className: "text-blue-500" }),
9656
+ /* @__PURE__ */ jsxs39("span", { children: [
8553
9657
  "\u68C0\u6D4B\u5230\u672A\u63D0\u4EA4\u7684\u8349\u7A3F",
8554
- timeLabel && /* @__PURE__ */ jsxs34("span", { className: "text-blue-500 ml-1", children: [
9658
+ timeLabel && /* @__PURE__ */ jsxs39("span", { className: "text-blue-500 ml-1", children: [
8555
9659
  "\uFF08\u4FDD\u5B58\u4E8E ",
8556
9660
  timeLabel,
8557
9661
  "\uFF09"
8558
9662
  ] })
8559
9663
  ] })
8560
- ] }),
8561
- /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
8562
- /* @__PURE__ */ jsx82(Button11, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
8563
- /* @__PURE__ */ jsx82(Button11, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
9664
+ ] }),
9665
+ /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-2", children: [
9666
+ /* @__PURE__ */ jsx87(Button13, { type: "text", size: "small", onClick: onDiscard, className: "!text-gray-500", children: "\u4E22\u5F03" }),
9667
+ /* @__PURE__ */ jsx87(Button13, { type: "primary", size: "small", onClick: onRestore, children: "\u6062\u590D\u586B\u5199" })
9668
+ ] })
9669
+ ] })
9670
+ }
9671
+ );
9672
+ };
9673
+
9674
+ // src/modules/ProcessPreview.tsx
9675
+ import { Modal as Modal7, Skeleton as Skeleton2, Button as Button14 } from "antd";
9676
+ import { CheckCircleOutlined, UserOutlined as UserOutlined3 } from "@ant-design/icons";
9677
+ import { jsx as jsx88, jsxs as jsxs40 } from "react/jsx-runtime";
9678
+ var ProcessPreview = ({
9679
+ open,
9680
+ onClose,
9681
+ onConfirm,
9682
+ routes,
9683
+ loading = false
9684
+ }) => {
9685
+ const routeList = Array.isArray(routes) ? routes : [];
9686
+ return /* @__PURE__ */ jsx88(
9687
+ Modal7,
9688
+ {
9689
+ getContainer: false,
9690
+ title: "\u6D41\u7A0B\u9884\u89C8",
9691
+ open,
9692
+ onCancel: onClose,
9693
+ width: 520,
9694
+ footer: /* @__PURE__ */ jsxs40("div", { className: "flex justify-end gap-3", children: [
9695
+ /* @__PURE__ */ jsx88(Button14, { onClick: onClose, children: "\u53D6\u6D88" }),
9696
+ /* @__PURE__ */ jsx88(Button14, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
9697
+ ] }),
9698
+ children: loading && routeList.length === 0 ? /* @__PURE__ */ jsx88(Skeleton2, { active: true, paragraph: { rows: 4 } }) : routeList.length === 0 ? /* @__PURE__ */ jsx88("p", { className: "text-sm text-gray-400 text-center py-8", children: "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) : /* @__PURE__ */ jsx88("div", { className: "py-2", children: routeList.map((route, index) => {
9699
+ const isLast = index === routeList.length - 1;
9700
+ return /* @__PURE__ */ jsxs40("div", { className: "flex gap-3", children: [
9701
+ /* @__PURE__ */ jsxs40("div", { className: "flex flex-col items-center", children: [
9702
+ /* @__PURE__ */ jsx88("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__ */ jsx88(CheckCircleOutlined, { className: "text-blue-500 text-xs" }) }),
9703
+ !isLast && /* @__PURE__ */ jsx88("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
9704
+ ] }),
9705
+ /* @__PURE__ */ jsxs40("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
9706
+ /* @__PURE__ */ jsx88("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
9707
+ route.assignees && route.assignees.length > 0 && /* @__PURE__ */ jsxs40("div", { className: "mt-1 flex items-center gap-1.5 flex-wrap", children: [
9708
+ /* @__PURE__ */ jsx88(UserOutlined3, { className: "text-gray-400 text-xs" }),
9709
+ route.assignees.map((assignee) => /* @__PURE__ */ jsx88(
9710
+ "span",
9711
+ {
9712
+ className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
9713
+ children: assignee.name
9714
+ },
9715
+ assignee.id
9716
+ ))
9717
+ ] })
9718
+ ] })
9719
+ ] }, route.nodeId);
9720
+ }) })
9721
+ }
9722
+ );
9723
+ };
9724
+
9725
+ // src/modules/DataManagementList.tsx
9726
+ import { useCallback as useCallback17, useEffect as useEffect36, useMemo as useMemo18, useRef as useRef14, useState as useState35 } from "react";
9727
+ import {
9728
+ Button as Button15,
9729
+ Checkbox as Checkbox5,
9730
+ ConfigProvider,
9731
+ Drawer as Drawer2,
9732
+ Dropdown as Dropdown3,
9733
+ Empty as Empty5,
9734
+ Input as Input12,
9735
+ Modal as Modal8,
9736
+ Segmented,
9737
+ Select as Select6,
9738
+ Space as Space9,
9739
+ Table as Table3,
9740
+ Tag as Tag5,
9741
+ Tooltip as Tooltip2,
9742
+ Upload as Upload3,
9743
+ message
9744
+ } from "antd";
9745
+ import {
9746
+ DeleteOutlined,
9747
+ DownloadOutlined,
9748
+ FilterOutlined,
9749
+ HistoryOutlined as HistoryOutlined2,
9750
+ ImportOutlined,
9751
+ MoreOutlined as MoreOutlined3,
9752
+ PlusOutlined,
9753
+ ReloadOutlined as ReloadOutlined3,
9754
+ SettingOutlined,
9755
+ SwapOutlined as SwapOutlined2
9756
+ } from "@ant-design/icons";
9757
+ import { jsx as jsx89, jsxs as jsxs41 } from "react/jsx-runtime";
9758
+ var createGroup = () => ({
9759
+ id: `group_${Date.now()}_${Math.random().toString(36).slice(2)}`,
9760
+ logic: "AND",
9761
+ rules: [],
9762
+ conditions: []
9763
+ });
9764
+ var createRule = (field) => ({
9765
+ id: `rule_${Date.now()}_${Math.random().toString(36).slice(2)}`,
9766
+ key: field?.fieldId || "",
9767
+ operator: "contains",
9768
+ value: "",
9769
+ componentName: field?.componentName
9770
+ });
9771
+ var getRecordId = (record) => record?.formInstanceId || record?.formInstId || record?.form_instance_id || record?.instanceId || record?.id || record?.processInstanceId;
9772
+ var getSelectedRecordId = (record, fallback) => record?.formInstId || record?.formInstanceId || record?.form_instance_id || record?.id || fallback;
9773
+ var hydrateFilterGroup = (group) => {
9774
+ if (!group) return createGroup();
9775
+ return {
9776
+ id: group.id || createGroup().id,
9777
+ logic: group.logic === "OR" ? "OR" : "AND",
9778
+ rules: Array.isArray(group.rules) ? group.rules.map((rule) => ({
9779
+ ...rule,
9780
+ id: rule.id || `rule_${Date.now()}_${Math.random().toString(36).slice(2)}`
9781
+ })) : [],
9782
+ conditions: Array.isArray(group.conditions) ? group.conditions.map(hydrateFilterGroup) : []
9783
+ };
9784
+ };
9785
+ var formatPrimitive = (value) => {
9786
+ if (value === void 0 || value === null || value === "")
9787
+ return /* @__PURE__ */ jsx89("span", { className: "text-ant-color-text-quaternary", children: "--" });
9788
+ return String(value);
9789
+ };
9790
+ var pickOptionLabel = (field, value) => {
9791
+ const options = field.options || field.optionList || field.option_list || field.componentProps?.options || [];
9792
+ const scalar = typeof value === "object" ? value?.value ?? value?.id ?? value?.label ?? value?.name : value;
9793
+ const match = Array.isArray(options) ? options.find((option) => String(option.value ?? option.id) === String(scalar)) : void 0;
9794
+ return match?.label || match?.name || value?.label || value?.name || scalar;
9795
+ };
9796
+ var renderStatusTag = (value, fieldId) => {
9797
+ const raw = String(value || "");
9798
+ const statusMap = {
9799
+ pending: { label: "\u5F85\u5904\u7406", color: "processing" },
9800
+ running: { label: "\u5BA1\u6279\u4E2D", color: "processing" },
9801
+ waiting: { label: "\u7B49\u5F85\u4E2D", color: "default" },
9802
+ exception: { label: "\u6D41\u7A0B\u5F02\u5E38", color: "error" },
9803
+ completed: { label: "\u5DF2\u5B8C\u6210", color: "success" },
9804
+ terminated: { label: "\u5DF2\u62D2\u7EDD", color: "error" },
9805
+ withdrawn: { label: "\u5DF2\u64A4\u9500", color: "default" },
9806
+ processing: { label: "\u5BA1\u6279\u4E2D", color: "processing" },
9807
+ approved: { label: "\u540C\u610F", color: "success" },
9808
+ rejected: { label: "\u62D2\u7EDD", color: "error" }
9809
+ };
9810
+ if (fieldId !== "processInstanceStatus" && fieldId !== "approvalResult") return null;
9811
+ const meta = statusMap[raw];
9812
+ return /* @__PURE__ */ jsx89(Tag5, { color: meta?.color, children: meta?.label || raw || "--" });
9813
+ };
9814
+ var renderCellValue = (value, field) => {
9815
+ const status = renderStatusTag(value, field.fieldId);
9816
+ if (status) return status;
9817
+ if (Array.isArray(value)) {
9818
+ if (value.length === 0) return formatPrimitive("");
9819
+ if (field.componentName === "ImageField") {
9820
+ return /* @__PURE__ */ jsx89("div", { className: "flex max-w-[180px] gap-1 overflow-hidden", children: value.slice(0, 3).map((item, index) => /* @__PURE__ */ jsx89(
9821
+ "img",
9822
+ {
9823
+ alt: item?.name || field.label,
9824
+ src: item?.url || item?.previewUrl,
9825
+ className: "h-8 w-8 rounded object-cover"
9826
+ },
9827
+ item?.uid || item?.id || item?.url || index
9828
+ )) });
9829
+ }
9830
+ if (field.componentName === "AttachmentField") {
9831
+ return /* @__PURE__ */ jsxs41(Space9, { size: 4, wrap: true, children: [
9832
+ value.slice(0, 3).map((item, index) => /* @__PURE__ */ jsx89(Tag5, { children: item?.name || item?.originalName || `\u9644\u4EF6${index + 1}` }, item?.uid || item?.id || index)),
9833
+ value.length > 3 && /* @__PURE__ */ jsxs41(Tag5, { children: [
9834
+ "+",
9835
+ value.length - 3
9836
+ ] })
9837
+ ] });
9838
+ }
9839
+ return /* @__PURE__ */ jsxs41(Space9, { size: 4, wrap: true, children: [
9840
+ value.slice(0, 4).map((item, index) => /* @__PURE__ */ jsx89(Tag5, { children: pickOptionLabel(field, item) }, `${field.fieldId}_${index}`)),
9841
+ value.length > 4 && /* @__PURE__ */ jsxs41(Tag5, { children: [
9842
+ "+",
9843
+ value.length - 4
9844
+ ] })
9845
+ ] });
9846
+ }
9847
+ if (value && typeof value === "object") {
9848
+ if (field.componentName === "UserSelectField" || field.componentName === "DepartmentSelectField") {
9849
+ return value.name || value.label || value.username || formatPrimitive(value.id);
9850
+ }
9851
+ if (value.start || value.end) {
9852
+ return [value.start, value.end].filter(Boolean).join(" \u81F3 ");
9853
+ }
9854
+ if (value.label || value.name || value.value) {
9855
+ return pickOptionLabel(field, value);
9856
+ }
9857
+ return /* @__PURE__ */ jsx89(Tooltip2, { title: JSON.stringify(value), children: /* @__PURE__ */ jsx89("span", { className: "text-ant-color-text-secondary", children: "\u5BF9\u8C61\u6570\u636E" }) });
9858
+ }
9859
+ if (["SelectField", "RadioField", "CheckboxField", "MultiSelectField"].includes(field.componentName)) {
9860
+ return pickOptionLabel(field, value);
9861
+ }
9862
+ return formatPrimitive(value);
9863
+ };
9864
+ var fileToBase64 = (file) => new Promise((resolve, reject) => {
9865
+ const reader = new FileReader();
9866
+ reader.onload = () => {
9867
+ const result = String(reader.result || "");
9868
+ resolve(result.includes(",") ? result.split(",")[1] : result);
9869
+ };
9870
+ reader.onerror = reject;
9871
+ reader.readAsDataURL(file);
9872
+ });
9873
+ function FilterGroupEditor({
9874
+ group,
9875
+ fields,
9876
+ onChange,
9877
+ level = 0
9878
+ }) {
9879
+ const fieldOptions = fields.map((field) => ({ label: field.label, value: field.fieldId }));
9880
+ const updateRule = (ruleId, patch) => {
9881
+ onChange({
9882
+ ...group,
9883
+ rules: group.rules.map((rule) => rule.id === ruleId ? { ...rule, ...patch } : rule)
9884
+ });
9885
+ };
9886
+ return /* @__PURE__ */ jsxs41(
9887
+ "div",
9888
+ {
9889
+ className: `${level > 0 ? "ml-4 border-l border-ant-border-secondary pl-4" : ""} space-y-3`,
9890
+ children: [
9891
+ /* @__PURE__ */ jsxs41("div", { className: "flex items-center justify-between", children: [
9892
+ /* @__PURE__ */ jsx89(
9893
+ Segmented,
9894
+ {
9895
+ size: "small",
9896
+ value: group.logic,
9897
+ options: [
9898
+ { label: "\u6EE1\u8DB3\u5168\u90E8", value: "AND" },
9899
+ { label: "\u6EE1\u8DB3\u4EFB\u4E00", value: "OR" }
9900
+ ],
9901
+ onChange: (value) => onChange({ ...group, logic: value })
9902
+ }
9903
+ ),
9904
+ /* @__PURE__ */ jsxs41(Space9, { children: [
9905
+ /* @__PURE__ */ jsx89(
9906
+ Button15,
9907
+ {
9908
+ size: "small",
9909
+ onClick: () => onChange({ ...group, rules: [...group.rules, createRule(fields[0])] }),
9910
+ children: "\u6DFB\u52A0\u6761\u4EF6"
9911
+ }
9912
+ ),
9913
+ /* @__PURE__ */ jsx89(
9914
+ Button15,
9915
+ {
9916
+ size: "small",
9917
+ onClick: () => onChange({ ...group, conditions: [...group.conditions, createGroup()] }),
9918
+ children: "\u6DFB\u52A0\u5206\u7EC4"
9919
+ }
9920
+ )
9921
+ ] })
9922
+ ] }),
9923
+ group.rules.map((rule) => /* @__PURE__ */ jsxs41(
9924
+ "div",
9925
+ {
9926
+ className: "grid grid-cols-[minmax(120px,1fr)_120px_minmax(160px,1fr)_auto] gap-2",
9927
+ children: [
9928
+ /* @__PURE__ */ jsx89(
9929
+ Select6,
9930
+ {
9931
+ showSearch: true,
9932
+ placeholder: "\u5B57\u6BB5",
9933
+ value: rule.key,
9934
+ options: fieldOptions,
9935
+ optionFilterProp: "label",
9936
+ onChange: (fieldId) => {
9937
+ const field = fields.find((item) => item.fieldId === fieldId);
9938
+ updateRule(rule.id, { key: fieldId, componentName: field?.componentName });
9939
+ }
9940
+ }
9941
+ ),
9942
+ /* @__PURE__ */ jsx89(
9943
+ Select6,
9944
+ {
9945
+ value: rule.operator,
9946
+ options: [
9947
+ { label: "\u5305\u542B", value: "contains" },
9948
+ { label: "\u7B49\u4E8E", value: "eq" },
9949
+ { label: "\u4E0D\u7B49\u4E8E", value: "ne" },
9950
+ { label: "\u5927\u4E8E", value: "gt" },
9951
+ { label: "\u5C0F\u4E8E", value: "lt" }
9952
+ ],
9953
+ onChange: (operator) => updateRule(rule.id, { operator })
9954
+ }
9955
+ ),
9956
+ /* @__PURE__ */ jsx89(
9957
+ Input12,
9958
+ {
9959
+ value: rule.value,
9960
+ placeholder: "\u8F93\u5165\u7B5B\u9009\u503C",
9961
+ onChange: (event) => updateRule(rule.id, { value: event.target.value })
9962
+ }
9963
+ ),
9964
+ /* @__PURE__ */ jsx89(
9965
+ Button15,
9966
+ {
9967
+ danger: true,
9968
+ type: "text",
9969
+ icon: /* @__PURE__ */ jsx89(DeleteOutlined, {}),
9970
+ onClick: () => onChange({ ...group, rules: group.rules.filter((item) => item.id !== rule.id) })
9971
+ }
9972
+ )
9973
+ ]
9974
+ },
9975
+ rule.id
9976
+ )),
9977
+ group.conditions.map((child) => /* @__PURE__ */ jsx89(
9978
+ FilterGroupEditor,
9979
+ {
9980
+ group: child,
9981
+ fields,
9982
+ level: level + 1,
9983
+ onChange: (next) => onChange({
9984
+ ...group,
9985
+ conditions: group.conditions.map((item) => item.id === child.id ? next : item)
9986
+ })
9987
+ },
9988
+ child.id
9989
+ )),
9990
+ group.rules.length === 0 && group.conditions.length === 0 && /* @__PURE__ */ jsx89(Empty5, { image: Empty5.PRESENTED_IMAGE_SIMPLE, description: "\u6682\u65E0\u7B5B\u9009\u6761\u4EF6" })
9991
+ ]
9992
+ }
9993
+ );
9994
+ }
9995
+ var DataManagementList = ({
9996
+ appType,
9997
+ formUuid,
9998
+ menuFormUuid,
9999
+ readonly = false,
10000
+ fullHeight = true,
10001
+ configScope = "global",
10002
+ title,
10003
+ detailRenderer,
10004
+ submitRenderer,
10005
+ requestOverride,
10006
+ rowActions = []
10007
+ }) => {
10008
+ const rootRef = useRef14(null);
10009
+ const api = useMemo18(() => {
10010
+ if (typeof requestOverride === "function") {
10011
+ return createFormRuntimeApi({ request: requestOverride });
10012
+ }
10013
+ return createFormRuntimeApi(requestOverride);
10014
+ }, [requestOverride]);
10015
+ const [fields, setFields] = useState35([]);
10016
+ const [config, setConfig] = useState35({});
10017
+ const [showFields, setShowFields] = useState35([]);
10018
+ const [lockFieldIds, setLockFieldIds] = useState35([]);
10019
+ const [widths, setWidths] = useState35({});
10020
+ const [sort, setSort] = useState35([]);
10021
+ const [density, setDensity] = useState35("middle");
10022
+ const [detailOpenMode, setDetailOpenMode] = useState35("drawer");
10023
+ const [searchKeyWord, setSearchKeyWord] = useState35("");
10024
+ const [filterGroup, setFilterGroup] = useState35(createGroup);
10025
+ const [dataSource, setDataSource] = useState35([]);
10026
+ const [total, setTotal] = useState35(0);
10027
+ const [current, setCurrent] = useState35(1);
10028
+ const [pageSize, setPageSize] = useState35(10);
10029
+ const [loading, setLoading] = useState35(false);
10030
+ const [schemaLoading, setSchemaLoading] = useState35(true);
10031
+ const [selectedRowKeys, setSelectedRowKeys] = useState35([]);
10032
+ const [filterOpen, setFilterOpen] = useState35(false);
10033
+ const [columnOpen, setColumnOpen] = useState35(false);
10034
+ const [exportOpen, setExportOpen] = useState35(false);
10035
+ const [exportScope, setExportScope] = useState35("all");
10036
+ const [exportFields, setExportFields] = useState35([]);
10037
+ const [exporting, setExporting] = useState35(false);
10038
+ const [importOpen, setImportOpen] = useState35(false);
10039
+ const [importPreview, setImportPreview] = useState35([]);
10040
+ const [importBase64, setImportBase64] = useState35("");
10041
+ const [recordsOpen, setRecordsOpen] = useState35(false);
10042
+ const [recordTab, setRecordTab] = useState35("export");
10043
+ const [transferRecords, setTransferRecords] = useState35([]);
10044
+ const [batchApprovalOpen, setBatchApprovalOpen] = useState35(false);
10045
+ const [batchApprovalAction, setBatchApprovalAction] = useState35(
10046
+ "approved"
10047
+ );
10048
+ const [batchApprovalComments, setBatchApprovalComments] = useState35("");
10049
+ const [batchApproving, setBatchApproving] = useState35(false);
10050
+ const [activeRecord, setActiveRecord] = useState35(null);
10051
+ const [detailOpen, setDetailOpen] = useState35(false);
10052
+ const [submitOpen, setSubmitOpen] = useState35(false);
10053
+ const fetchStateRef = useRef14({});
10054
+ const request = api.request;
10055
+ const getPopupContainer = useCallback17(
10056
+ (triggerNode) => triggerNode?.parentElement || rootRef.current || document.body,
10057
+ []
10058
+ );
10059
+ const confirmDanger = useCallback17((title2, content, onOk) => {
10060
+ if (confirmAction(title2, content)) onOk();
10061
+ }, []);
10062
+ const visibleFields = useMemo18(
10063
+ () => showFields.map((fieldId) => fields.find((field) => field.fieldId === fieldId)).filter(Boolean),
10064
+ [fields, showFields]
10065
+ );
10066
+ useEffect36(() => {
10067
+ fetchStateRef.current = {
10068
+ current,
10069
+ pageSize,
10070
+ searchKeyWord,
10071
+ filterGroup,
10072
+ sort
10073
+ };
10074
+ }, [current, filterGroup, pageSize, searchKeyWord, sort]);
10075
+ const loadData = useCallback17(
10076
+ async (overrides = {}) => {
10077
+ if (!appType || !formUuid) return;
10078
+ const fetchState = { ...fetchStateRef.current, ...overrides };
10079
+ const nextCurrent = fetchState.current || 1;
10080
+ const nextPageSize = fetchState.pageSize || 10;
10081
+ fetchStateRef.current = {
10082
+ ...fetchState,
10083
+ current: nextCurrent,
10084
+ pageSize: nextPageSize
10085
+ };
10086
+ setLoading(true);
10087
+ try {
10088
+ const result = await advancedSearchDataManagement(request, {
10089
+ appType,
10090
+ formUuid,
10091
+ currentPage: nextCurrent,
10092
+ pageSize: nextPageSize,
10093
+ searchKeyWord: fetchState.searchKeyWord,
10094
+ filters: fetchState.filterGroup,
10095
+ order: fetchState.sort
10096
+ });
10097
+ setDataSource(result.records);
10098
+ setTotal(result.total);
10099
+ setCurrent(nextCurrent);
10100
+ setPageSize(nextPageSize);
10101
+ } catch (error) {
10102
+ console.error("[DataManagementList] loadData failed:", error);
10103
+ message.error("\u52A0\u8F7D\u6570\u636E\u5931\u8D25");
10104
+ } finally {
10105
+ setLoading(false);
10106
+ }
10107
+ },
10108
+ [appType, formUuid, request]
10109
+ );
10110
+ useEffect36(() => {
10111
+ let mounted = true;
10112
+ const loadSchemaAndConfig = async () => {
10113
+ if (!appType || !formUuid) return;
10114
+ setSchemaLoading(true);
10115
+ setDataSource([]);
10116
+ setTotal(0);
10117
+ setSelectedRowKeys([]);
10118
+ try {
10119
+ const schemaResult = await getDataManagementSchema(request, { appType, formUuid });
10120
+ if (!mounted) return;
10121
+ const allFields = [
10122
+ ...schemaResult.fields,
10123
+ ...getSystemFieldsForFormType(schemaResult.formType)
10124
+ ];
10125
+ const saved = await getDataManagementConfig(request, {
10126
+ appType,
10127
+ formUuid,
10128
+ menuFormUuid,
10129
+ scope: configScope
10130
+ }).catch(() => void 0);
10131
+ if (!mounted) return;
10132
+ const resolved = normalizeColumnConfig(saved, allFields);
10133
+ const nextSearchKeyWord = saved?.filter?.searchKeyWord || "";
10134
+ const nextFilterGroup = hydrateFilterGroup(saved?.filter?.group);
10135
+ setFields(allFields);
10136
+ setConfig(saved || {});
10137
+ setShowFields(resolved.showFields);
10138
+ setWidths(resolved.widths);
10139
+ setLockFieldIds(resolved.lockFieldIds);
10140
+ setSort(resolved.sort);
10141
+ setDensity(resolved.density);
10142
+ setDetailOpenMode(resolved.detailOpenMode);
10143
+ setPageSize(resolved.pageSize);
10144
+ setSearchKeyWord(nextSearchKeyWord);
10145
+ setFilterGroup(nextFilterGroup);
10146
+ await loadData({
10147
+ current: 1,
10148
+ pageSize: resolved.pageSize,
10149
+ searchKeyWord: nextSearchKeyWord,
10150
+ filterGroup: nextFilterGroup,
10151
+ sort: resolved.sort
10152
+ });
10153
+ } catch (error) {
10154
+ console.error("[DataManagementList] load schema failed:", error);
10155
+ message.error("\u52A0\u8F7D\u8868\u5355\u914D\u7F6E\u5931\u8D25");
10156
+ } finally {
10157
+ if (mounted) setSchemaLoading(false);
10158
+ }
10159
+ };
10160
+ loadSchemaAndConfig();
10161
+ return () => {
10162
+ mounted = false;
10163
+ };
10164
+ }, [appType, configScope, formUuid, loadData, menuFormUuid, request]);
10165
+ const persistConfig = useCallback17(
10166
+ async (patch) => {
10167
+ const nextConfig = { ...config, ...patch };
10168
+ setConfig(nextConfig);
10169
+ await saveDataManagementConfig(request, {
10170
+ appType,
10171
+ formUuid,
10172
+ menuFormUuid,
10173
+ scope: configScope,
10174
+ config: nextConfig
10175
+ }).catch((error) => {
10176
+ console.error("[DataManagementList] save config failed:", error);
10177
+ message.warning("\u914D\u7F6E\u4FDD\u5B58\u5931\u8D25\uFF0C\u672C\u6B21\u4EC5\u5728\u5F53\u524D\u9875\u9762\u751F\u6548");
10178
+ });
10179
+ },
10180
+ [appType, config, configScope, formUuid, menuFormUuid, request]
10181
+ );
10182
+ const handleColumnCommit = async () => {
10183
+ setColumnOpen(false);
10184
+ await persistConfig({
10185
+ showFields,
10186
+ lockFieldIds,
10187
+ widths,
10188
+ density,
10189
+ detailOpenMode,
10190
+ pageSize
10191
+ });
10192
+ };
10193
+ const handleDetail = useCallback17(
10194
+ (record) => {
10195
+ const formInstanceId = getRecordId(record);
10196
+ if (detailOpenMode === "newPage" && typeof window !== "undefined") {
10197
+ window.open(`/${appType}/forms/${formUuid}/detail/${formInstanceId}`, "_blank");
10198
+ return;
10199
+ }
10200
+ setActiveRecord(record);
10201
+ setDetailOpen(true);
10202
+ },
10203
+ [appType, detailOpenMode, formUuid]
10204
+ );
10205
+ const handleDelete = useCallback17(
10206
+ async (ids) => {
10207
+ if (ids.length === 0) return;
10208
+ await deleteDataManagementRows(request, { appType, formUuid, formInstanceIds: ids });
10209
+ setSelectedRowKeys([]);
10210
+ await loadData({ current, pageSize });
10211
+ },
10212
+ [appType, current, formUuid, loadData, pageSize, request]
10213
+ );
10214
+ const getSelectedRecordIds = useCallback17(
10215
+ () => selectedRowKeys.map((key) => {
10216
+ const record = dataSource.find((item) => String(getRecordId(item)) === String(key));
10217
+ return String(getSelectedRecordId(record, key));
10218
+ }),
10219
+ [dataSource, selectedRowKeys]
10220
+ );
10221
+ const handleBatchApprove = () => {
10222
+ if (selectedRowKeys.length === 0) return;
10223
+ setBatchApprovalOpen(true);
10224
+ };
10225
+ const handleBatchApprovalConfirm = async () => {
10226
+ const ids = getSelectedRecordIds();
10227
+ if (ids.length === 0) return;
10228
+ setBatchApproving(true);
10229
+ try {
10230
+ await batchApproveDataManagementRows(request, {
10231
+ appType,
10232
+ formUuid,
10233
+ formInstanceIds: ids,
10234
+ action: batchApprovalAction,
10235
+ comments: batchApprovalComments || void 0
10236
+ });
10237
+ message.success(`\u6279\u91CF${batchApprovalAction === "approved" ? "\u901A\u8FC7" : "\u62D2\u7EDD"}\u5DF2\u63D0\u4EA4`);
10238
+ setSelectedRowKeys([]);
10239
+ setBatchApprovalOpen(false);
10240
+ setBatchApprovalAction("approved");
10241
+ setBatchApprovalComments("");
10242
+ await loadData({ current, pageSize });
10243
+ } catch (error) {
10244
+ console.error("[DataManagementList] batch approval failed:", error);
10245
+ message.error("\u6279\u91CF\u5BA1\u6279\u5931\u8D25");
10246
+ } finally {
10247
+ setBatchApproving(false);
10248
+ }
10249
+ };
10250
+ const handleExport = async (scope) => {
10251
+ const selectedIds = scope === "selected" ? getSelectedRecordIds() : [];
10252
+ if (scope === "selected" && selectedIds.length === 0) {
10253
+ message.warning("\u8BF7\u5148\u9009\u62E9\u8981\u5BFC\u51FA\u7684\u8BB0\u5F55");
10254
+ return;
10255
+ }
10256
+ const selectedFilters = selectedIds.map((id) => ({
10257
+ key: "form_instance_id",
10258
+ operator: "EQ",
10259
+ value: id
10260
+ }));
10261
+ setExporting(true);
10262
+ try {
10263
+ await exportDataManagementRows(request, {
10264
+ appType,
10265
+ formUuid,
10266
+ currentPage: scope === "selected" ? 1 : current,
10267
+ pageSize: scope === "selected" ? selectedIds.length : pageSize,
10268
+ searchKeyWord: scope === "selected" ? void 0 : searchKeyWord,
10269
+ filters: scope === "selected" ? void 0 : filterGroup,
10270
+ rawFilters: scope === "selected" ? JSON.stringify(selectedFilters) : void 0,
10271
+ conditionType: scope === "selected" ? "OR" : void 0,
10272
+ order: sort,
10273
+ exportAll: scope === "all" ? "y" : "n",
10274
+ exportFields
10275
+ });
10276
+ message.success("\u5BFC\u51FA\u4EFB\u52A1\u5DF2\u521B\u5EFA\uFF0C\u53EF\u5728\u5BFC\u5165\u5BFC\u51FA\u8BB0\u5F55\u4E2D\u67E5\u770B");
10277
+ setExportOpen(false);
10278
+ } catch (error) {
10279
+ console.error("[DataManagementList] export failed:", error);
10280
+ message.error("\u5BFC\u51FA\u5931\u8D25");
10281
+ } finally {
10282
+ setExporting(false);
10283
+ }
10284
+ };
10285
+ const loadTransferRecords = async (type) => {
10286
+ setRecordTab(type);
10287
+ setRecordsOpen(true);
10288
+ const result = await getDataManagementTransferRecords(request, {
10289
+ appType,
10290
+ formUuid,
10291
+ type,
10292
+ currentPage: 1,
10293
+ pageSize: 10
10294
+ });
10295
+ setTransferRecords(result.records);
10296
+ };
10297
+ const handleImportPreview = async (file) => {
10298
+ const base64 = await fileToBase64(file);
10299
+ setImportBase64(base64);
10300
+ const result = await importPreviewDataManagementRows(request, {
10301
+ appType,
10302
+ formUuid,
10303
+ fileBase64: base64
10304
+ });
10305
+ const records = result?.data || result?.records || result?.list || result || [];
10306
+ setImportPreview(Array.isArray(records) ? records : []);
10307
+ return false;
10308
+ };
10309
+ const handleImportConfirm = async () => {
10310
+ if (!importBase64) return;
10311
+ await importDataManagementRows(request, { appType, formUuid, fileBase64: importBase64 });
10312
+ message.success("\u5BFC\u5165\u4EFB\u52A1\u5DF2\u521B\u5EFA");
10313
+ setImportOpen(false);
10314
+ setImportPreview([]);
10315
+ setImportBase64("");
10316
+ await loadData({ current: 1, pageSize });
10317
+ };
10318
+ const columns = useMemo18(() => {
10319
+ const baseColumns = visibleFields.map((field) => ({
10320
+ title: field.label,
10321
+ dataIndex: field.fieldId,
10322
+ key: field.fieldId,
10323
+ width: widths[field.fieldId] || field.width || 160,
10324
+ fixed: lockFieldIds.includes(field.fieldId) ? "left" : void 0,
10325
+ ellipsis: true,
10326
+ sorter: true,
10327
+ render: (value) => renderCellValue(value, field)
10328
+ })) || [];
10329
+ return [
10330
+ ...baseColumns,
10331
+ {
10332
+ title: "\u64CD\u4F5C",
10333
+ key: "__actions",
10334
+ width: 148,
10335
+ fixed: "right",
10336
+ render: (_, record) => /* @__PURE__ */ jsxs41(Space9, { size: 4, children: [
10337
+ /* @__PURE__ */ jsx89(Button15, { type: "link", size: "small", onClick: () => handleDetail(record), children: "\u8BE6\u60C5" }),
10338
+ /* @__PURE__ */ jsx89(
10339
+ Dropdown3,
10340
+ {
10341
+ trigger: ["click"],
10342
+ getPopupContainer,
10343
+ menu: {
10344
+ items: [
10345
+ ...rowActions.map((action) => ({
10346
+ key: action.key,
10347
+ label: action.label,
10348
+ danger: action.danger,
10349
+ onClick: () => action.onClick(record)
10350
+ })),
10351
+ {
10352
+ key: "workflow",
10353
+ label: "\u6D41\u7A0B\u65E5\u5FD7",
10354
+ icon: /* @__PURE__ */ jsx89(HistoryOutlined2, {}),
10355
+ onClick: () => message.info("\u8BF7\u901A\u8FC7 detailRenderer \u63A5\u5165\u6D41\u7A0B\u65E5\u5FD7\u6216\u6D41\u7A0B\u56FE\u5165\u53E3")
10356
+ },
10357
+ ...!readonly ? [
10358
+ {
10359
+ key: "delete",
10360
+ label: "\u5220\u9664",
10361
+ danger: true,
10362
+ icon: /* @__PURE__ */ jsx89(DeleteOutlined, {}),
10363
+ onClick: () => confirmDanger(
10364
+ "\u786E\u8BA4\u5220\u9664",
10365
+ "\u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F",
10366
+ () => handleDelete([String(getRecordId(record))])
10367
+ )
10368
+ }
10369
+ ] : []
10370
+ ]
10371
+ },
10372
+ children: /* @__PURE__ */ jsx89(Button15, { type: "text", size: "small", icon: /* @__PURE__ */ jsx89(MoreOutlined3, {}) })
10373
+ }
10374
+ )
10375
+ ] })
10376
+ }
10377
+ ];
10378
+ }, [
10379
+ confirmDanger,
10380
+ getPopupContainer,
10381
+ handleDelete,
10382
+ handleDetail,
10383
+ lockFieldIds,
10384
+ readonly,
10385
+ rowActions,
10386
+ visibleFields,
10387
+ widths
10388
+ ]);
10389
+ const tableSize = density === "compact" ? "small" : density === "loose" ? "large" : "middle";
10390
+ const importPreviewColumns = useMemo18(() => {
10391
+ const keys = Array.from(
10392
+ new Set(importPreview.flatMap((record) => Object.keys(record || {})))
10393
+ ).slice(0, 16);
10394
+ return keys.map((key) => {
10395
+ const field = fields.find((item) => item.fieldId === key || item.id === key);
10396
+ return {
10397
+ title: field?.label || key,
10398
+ dataIndex: key,
10399
+ key,
10400
+ width: 150,
10401
+ ellipsis: true,
10402
+ render: (value) => field ? renderCellValue(value, field) : formatPrimitive(value)
10403
+ };
10404
+ });
10405
+ }, [fields, importPreview]);
10406
+ return /* @__PURE__ */ jsx89(ConfigProvider, { getPopupContainer, children: /* @__PURE__ */ jsxs41("div", { ref: rootRef, className: `${fullHeight ? "h-full min-h-full" : ""} bg-ant-bg-layout`, children: [
10407
+ /* @__PURE__ */ jsxs41("div", { className: "mx-auto flex h-full max-w-[1440px] flex-col px-4 py-4 md:px-6", children: [
10408
+ /* @__PURE__ */ jsxs41("div", { className: "mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between", children: [
10409
+ /* @__PURE__ */ jsxs41("div", { children: [
10410
+ /* @__PURE__ */ jsx89("h1", { className: "text-xl font-semibold text-ant-color-text", children: title || "\u6570\u636E\u7BA1\u7406" }),
10411
+ /* @__PURE__ */ jsxs41("p", { className: "mt-1 text-sm text-ant-color-text-secondary", children: [
10412
+ "\u5171 ",
10413
+ total,
10414
+ " \u6761\u6570\u636E\uFF0C\u5DF2\u9009\u62E9 ",
10415
+ selectedRowKeys.length,
10416
+ " \u6761"
10417
+ ] })
10418
+ ] }),
10419
+ /* @__PURE__ */ jsxs41(Space9, { wrap: true, children: [
10420
+ !readonly && submitRenderer && /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(PlusOutlined, {}), type: "primary", onClick: () => setSubmitOpen(true), children: "\u65B0\u589E" }),
10421
+ /* @__PURE__ */ jsx89(
10422
+ Input12.Search,
10423
+ {
10424
+ allowClear: true,
10425
+ className: "w-[260px]",
10426
+ placeholder: "\u641C\u7D22\u5173\u952E\u5B57",
10427
+ value: searchKeyWord,
10428
+ onChange: (event) => setSearchKeyWord(event.target.value),
10429
+ onSearch: (value) => {
10430
+ const nextSearchKeyWord = String(value || "");
10431
+ setSearchKeyWord(nextSearchKeyWord);
10432
+ persistConfig({
10433
+ filter: { searchKeyWord: nextSearchKeyWord, group: filterGroup }
10434
+ });
10435
+ loadData({
10436
+ current: 1,
10437
+ pageSize,
10438
+ searchKeyWord: nextSearchKeyWord,
10439
+ filterGroup
10440
+ });
10441
+ }
10442
+ }
10443
+ ),
10444
+ /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(FilterOutlined, {}), onClick: () => setFilterOpen(true), children: "\u7B5B\u9009" }),
10445
+ /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(SettingOutlined, {}), onClick: () => setColumnOpen(true), children: "\u5217\u8BBE\u7F6E" }),
10446
+ /* @__PURE__ */ jsx89(
10447
+ Dropdown3,
10448
+ {
10449
+ getPopupContainer,
10450
+ menu: {
10451
+ items: [
10452
+ {
10453
+ key: "selected",
10454
+ label: "\u5BFC\u51FA\u9009\u4E2D",
10455
+ disabled: selectedRowKeys.length === 0,
10456
+ onClick: () => {
10457
+ setExportScope("selected");
10458
+ setExportFields(showFields);
10459
+ setExportOpen(true);
10460
+ }
10461
+ },
10462
+ {
10463
+ key: "all",
10464
+ label: "\u5BFC\u51FA\u5168\u90E8",
10465
+ onClick: () => {
10466
+ setExportScope("all");
10467
+ setExportFields(showFields);
10468
+ setExportOpen(true);
10469
+ }
10470
+ },
10471
+ {
10472
+ key: "records",
10473
+ label: "\u5BFC\u51FA\u8BB0\u5F55",
10474
+ onClick: () => loadTransferRecords("export")
10475
+ }
10476
+ ]
10477
+ },
10478
+ children: /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(DownloadOutlined, {}), children: "\u5BFC\u51FA" })
10479
+ }
10480
+ ),
10481
+ !readonly && /* @__PURE__ */ jsx89(
10482
+ Dropdown3,
10483
+ {
10484
+ getPopupContainer,
10485
+ menu: {
10486
+ items: [
10487
+ { key: "import", label: "\u5BFC\u5165\u6570\u636E", onClick: () => setImportOpen(true) },
10488
+ {
10489
+ key: "records",
10490
+ label: "\u5BFC\u5165\u8BB0\u5F55",
10491
+ onClick: () => loadTransferRecords("import")
10492
+ }
10493
+ ]
10494
+ },
10495
+ children: /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(ImportOutlined, {}), children: "\u5BFC\u5165" })
10496
+ }
10497
+ ),
10498
+ /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(ReloadOutlined3, {}), onClick: () => loadData({ current, pageSize }) })
10499
+ ] })
10500
+ ] }),
10501
+ selectedRowKeys.length > 0 && /* @__PURE__ */ jsxs41("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: [
10502
+ /* @__PURE__ */ jsxs41("span", { className: "text-sm text-ant-color-text-secondary", children: [
10503
+ "\u5DF2\u9009 ",
10504
+ selectedRowKeys.length,
10505
+ " \u6761"
10506
+ ] }),
10507
+ /* @__PURE__ */ jsxs41(Space9, { wrap: true, children: [
10508
+ !readonly && /* @__PURE__ */ jsx89(Button15, { icon: /* @__PURE__ */ jsx89(SwapOutlined2, {}), onClick: handleBatchApprove, children: "\u6279\u91CF\u5BA1\u6279" }),
10509
+ !readonly && /* @__PURE__ */ jsx89(
10510
+ Button15,
10511
+ {
10512
+ danger: true,
10513
+ icon: /* @__PURE__ */ jsx89(DeleteOutlined, {}),
10514
+ onClick: () => confirmDanger(
10515
+ "\u786E\u8BA4\u6279\u91CF\u5220\u9664",
10516
+ `\u5C06\u5220\u9664 ${selectedRowKeys.length} \u6761\u6570\u636E\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F`,
10517
+ () => handleDelete(selectedRowKeys.map(String))
10518
+ ),
10519
+ children: "\u6279\u91CF\u5220\u9664"
10520
+ }
10521
+ ),
10522
+ /* @__PURE__ */ jsx89(Button15, { type: "link", onClick: () => setSelectedRowKeys([]), children: "\u53D6\u6D88\u9009\u62E9" })
10523
+ ] })
10524
+ ] }),
10525
+ /* @__PURE__ */ jsx89("div", { className: "relative flex-1 overflow-hidden rounded-lg border border-ant-border-secondary bg-ant-bg-container", children: /* @__PURE__ */ jsx89(
10526
+ Table3,
10527
+ {
10528
+ rowKey: (record) => String(getRecordId(record)),
10529
+ loading: loading || schemaLoading,
10530
+ columns,
10531
+ dataSource,
10532
+ size: tableSize,
10533
+ scroll: {
10534
+ x: Math.max(900, visibleFields.length * 160),
10535
+ y: fullHeight ? selectedRowKeys.length > 0 ? "calc(100vh - 320px)" : "calc(100vh - 260px)" : void 0
10536
+ },
10537
+ rowSelection: {
10538
+ selectedRowKeys,
10539
+ onChange: setSelectedRowKeys
10540
+ },
10541
+ pagination: {
10542
+ current,
10543
+ pageSize,
10544
+ total,
10545
+ showSizeChanger: true,
10546
+ showTotal: (count) => `\u5171 ${count} \u6761`
10547
+ },
10548
+ onChange: (pagination, _filters, sorter) => {
10549
+ const sorters = Array.isArray(sorter) ? sorter : [sorter];
10550
+ const nextSort = sorters.filter((item) => item?.field && item?.order).map((item) => ({
10551
+ id: String(item.field),
10552
+ isAsc: item.order === "ascend" ? "y" : "n"
10553
+ }));
10554
+ setSort(nextSort);
10555
+ persistConfig({ sort: nextSort });
10556
+ loadData({
10557
+ current: pagination.current || 1,
10558
+ pageSize: pagination.pageSize || pageSize,
10559
+ sort: nextSort
10560
+ });
10561
+ }
10562
+ }
10563
+ ) })
10564
+ ] }),
10565
+ /* @__PURE__ */ jsx89(
10566
+ Modal8,
10567
+ {
10568
+ getContainer: false,
10569
+ title: "\u9AD8\u7EA7\u7B5B\u9009",
10570
+ open: filterOpen,
10571
+ width: 760,
10572
+ onCancel: () => setFilterOpen(false),
10573
+ onOk: () => {
10574
+ setFilterOpen(false);
10575
+ persistConfig({ filter: { searchKeyWord, group: filterGroup } });
10576
+ loadData({ current: 1, pageSize, searchKeyWord, filterGroup });
10577
+ },
10578
+ okText: "\u5E94\u7528\u7B5B\u9009",
10579
+ children: /* @__PURE__ */ jsx89(FilterGroupEditor, { group: filterGroup, fields, onChange: setFilterGroup })
10580
+ }
10581
+ ),
10582
+ /* @__PURE__ */ jsx89(
10583
+ Modal8,
10584
+ {
10585
+ getContainer: false,
10586
+ title: "\u5217\u8BBE\u7F6E",
10587
+ open: columnOpen,
10588
+ width: 720,
10589
+ onCancel: () => setColumnOpen(false),
10590
+ onOk: handleColumnCommit,
10591
+ children: /* @__PURE__ */ jsxs41("div", { className: "space-y-5", children: [
10592
+ /* @__PURE__ */ jsxs41("div", { children: [
10593
+ /* @__PURE__ */ jsx89("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u663E\u793A\u5217" }),
10594
+ /* @__PURE__ */ jsx89(
10595
+ Checkbox5.Group,
10596
+ {
10597
+ className: "grid grid-cols-2 gap-2 md:grid-cols-3",
10598
+ value: showFields,
10599
+ options: fields.map((field) => ({ label: field.label, value: field.fieldId })),
10600
+ onChange: (values) => setShowFields(values.map(String))
10601
+ }
10602
+ )
10603
+ ] }),
10604
+ /* @__PURE__ */ jsxs41("div", { children: [
10605
+ /* @__PURE__ */ jsx89("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u51BB\u7ED3\u5217" }),
10606
+ /* @__PURE__ */ jsx89(
10607
+ Select6,
10608
+ {
10609
+ mode: "multiple",
10610
+ className: "w-full",
10611
+ value: lockFieldIds,
10612
+ options: showFields.map((fieldId) => {
10613
+ const field = fields.find((item) => item.fieldId === fieldId);
10614
+ return { label: field?.label || fieldId, value: fieldId };
10615
+ }),
10616
+ onChange: setLockFieldIds
10617
+ }
10618
+ )
10619
+ ] }),
10620
+ /* @__PURE__ */ jsxs41("div", { className: "grid gap-4 md:grid-cols-3", children: [
10621
+ /* @__PURE__ */ jsxs41("div", { children: [
10622
+ /* @__PURE__ */ jsx89("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u8868\u683C\u5BC6\u5EA6" }),
10623
+ /* @__PURE__ */ jsx89(
10624
+ Segmented,
10625
+ {
10626
+ block: true,
10627
+ value: density,
10628
+ options: [
10629
+ { label: "\u7D27\u51D1", value: "compact" },
10630
+ { label: "\u6807\u51C6", value: "middle" },
10631
+ { label: "\u5BBD\u677E", value: "loose" }
10632
+ ],
10633
+ onChange: (value) => setDensity(value)
10634
+ }
10635
+ )
10636
+ ] }),
10637
+ /* @__PURE__ */ jsxs41("div", { children: [
10638
+ /* @__PURE__ */ jsx89("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u8BE6\u60C5\u6253\u5F00\u65B9\u5F0F" }),
10639
+ /* @__PURE__ */ jsx89(
10640
+ Segmented,
10641
+ {
10642
+ block: true,
10643
+ value: detailOpenMode,
10644
+ options: [
10645
+ { label: "\u62BD\u5C49", value: "drawer" },
10646
+ { label: "\u65B0\u9875", value: "newPage" }
10647
+ ],
10648
+ onChange: (value) => setDetailOpenMode(value)
10649
+ }
10650
+ )
10651
+ ] }),
10652
+ /* @__PURE__ */ jsxs41("div", { children: [
10653
+ /* @__PURE__ */ jsx89("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u9875\u5927\u5C0F" }),
10654
+ /* @__PURE__ */ jsx89(
10655
+ Select6,
10656
+ {
10657
+ className: "w-full",
10658
+ value: pageSize,
10659
+ options: [10, 20, 50, 100].map((value) => ({ label: `${value} \u6761`, value })),
10660
+ onChange: setPageSize
10661
+ }
10662
+ )
10663
+ ] })
10664
+ ] })
8564
10665
  ] })
8565
- ] })
8566
- }
8567
- );
8568
- };
8569
-
8570
- // src/modules/ProcessPreview.tsx
8571
- import { Modal as Modal6, Skeleton as Skeleton2, Button as Button12 } from "antd";
8572
- import { CheckCircleOutlined, UserOutlined as UserOutlined2 } from "@ant-design/icons";
8573
- import { jsx as jsx83, jsxs as jsxs35 } from "react/jsx-runtime";
8574
- var ProcessPreview = ({
8575
- open,
8576
- onClose,
8577
- onConfirm,
8578
- routes,
8579
- loading = false
8580
- }) => {
8581
- return /* @__PURE__ */ jsx83(
8582
- Modal6,
8583
- {
8584
- title: "\u6D41\u7A0B\u9884\u89C8",
8585
- open,
8586
- onCancel: onClose,
8587
- width: 520,
8588
- footer: /* @__PURE__ */ jsxs35("div", { className: "flex justify-end gap-3", children: [
8589
- /* @__PURE__ */ jsx83(Button12, { onClick: onClose, children: "\u53D6\u6D88" }),
8590
- /* @__PURE__ */ jsx83(Button12, { type: "primary", onClick: onConfirm, loading, children: "\u786E\u8BA4\u63D0\u4EA4" })
8591
- ] }),
8592
- children: loading && routes.length === 0 ? /* @__PURE__ */ jsx83(Skeleton2, { active: true, paragraph: { rows: 4 } }) : routes.length === 0 ? /* @__PURE__ */ jsx83("p", { className: "text-sm text-gray-400 text-center py-8", children: "\u6682\u65E0\u6D41\u7A0B\u8282\u70B9" }) : /* @__PURE__ */ jsx83("div", { className: "py-2", children: routes.map((route, index) => {
8593
- const isLast = index === routes.length - 1;
8594
- return /* @__PURE__ */ jsxs35("div", { className: "flex gap-3", children: [
8595
- /* @__PURE__ */ jsxs35("div", { className: "flex flex-col items-center", children: [
8596
- /* @__PURE__ */ jsx83("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__ */ jsx83(CheckCircleOutlined, { className: "text-blue-500 text-xs" }) }),
8597
- !isLast && /* @__PURE__ */ jsx83("div", { className: "w-0.5 flex-1 bg-blue-200 mt-1" })
10666
+ }
10667
+ ),
10668
+ /* @__PURE__ */ jsx89(
10669
+ Modal8,
10670
+ {
10671
+ getContainer: false,
10672
+ title: exportScope === "selected" ? "\u5BFC\u51FA\u9009\u4E2D\u6570\u636E" : "\u5BFC\u51FA\u5168\u90E8\u6570\u636E",
10673
+ open: exportOpen,
10674
+ onCancel: () => setExportOpen(false),
10675
+ footer: /* @__PURE__ */ jsxs41(Space9, { children: [
10676
+ /* @__PURE__ */ jsx89(Button15, { onClick: () => setExportOpen(false), children: "\u53D6\u6D88" }),
10677
+ /* @__PURE__ */ jsx89(
10678
+ Button15,
10679
+ {
10680
+ type: "primary",
10681
+ loading: exporting,
10682
+ disabled: exportScope === "selected" && selectedRowKeys.length === 0,
10683
+ onClick: () => handleExport(exportScope),
10684
+ children: exportScope === "selected" ? `\u5BFC\u51FA\u9009\u4E2D (${selectedRowKeys.length})` : "\u5BFC\u51FA\u5168\u90E8"
10685
+ }
10686
+ )
10687
+ ] }),
10688
+ children: /* @__PURE__ */ jsx89(
10689
+ Checkbox5.Group,
10690
+ {
10691
+ className: "grid grid-cols-2 gap-2",
10692
+ value: exportFields,
10693
+ options: fields.map((field) => ({ label: field.label, value: field.fieldId })),
10694
+ onChange: (values) => setExportFields(values.map(String))
10695
+ }
10696
+ )
10697
+ }
10698
+ ),
10699
+ /* @__PURE__ */ jsx89(
10700
+ Modal8,
10701
+ {
10702
+ getContainer: false,
10703
+ title: "\u6279\u91CF\u5BA1\u6279",
10704
+ open: batchApprovalOpen,
10705
+ onCancel: () => setBatchApprovalOpen(false),
10706
+ onOk: handleBatchApprovalConfirm,
10707
+ okText: batchApprovalAction === "approved" ? "\u786E\u8BA4\u901A\u8FC7" : "\u786E\u8BA4\u62D2\u7EDD",
10708
+ confirmLoading: batchApproving,
10709
+ children: /* @__PURE__ */ jsxs41("div", { className: "space-y-4", children: [
10710
+ /* @__PURE__ */ jsxs41("div", { className: "text-sm text-ant-color-text-secondary", children: [
10711
+ "\u5DF2\u9009\u62E9 ",
10712
+ selectedRowKeys.length,
10713
+ " \u6761\u8BB0\u5F55"
8598
10714
  ] }),
8599
- /* @__PURE__ */ jsxs35("div", { className: `flex-1 ${isLast ? "pb-0" : "pb-5"}`, children: [
8600
- /* @__PURE__ */ jsx83("div", { className: "text-sm font-medium text-gray-900", children: route.nodeName }),
8601
- route.assignees && route.assignees.length > 0 && /* @__PURE__ */ jsxs35("div", { className: "mt-1 flex items-center gap-1.5 flex-wrap", children: [
8602
- /* @__PURE__ */ jsx83(UserOutlined2, { className: "text-gray-400 text-xs" }),
8603
- route.assignees.map((assignee) => /* @__PURE__ */ jsx83(
8604
- "span",
8605
- {
8606
- className: "text-xs text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded",
8607
- children: assignee.name
8608
- },
8609
- assignee.id
8610
- ))
8611
- ] })
10715
+ /* @__PURE__ */ jsx89(
10716
+ Segmented,
10717
+ {
10718
+ block: true,
10719
+ value: batchApprovalAction,
10720
+ options: [
10721
+ { label: "\u540C\u610F", value: "approved" },
10722
+ { label: "\u62D2\u7EDD", value: "rejected" }
10723
+ ],
10724
+ onChange: (value) => setBatchApprovalAction(value)
10725
+ }
10726
+ ),
10727
+ /* @__PURE__ */ jsx89(
10728
+ Input12.TextArea,
10729
+ {
10730
+ value: batchApprovalComments,
10731
+ rows: 4,
10732
+ maxLength: 500,
10733
+ showCount: true,
10734
+ placeholder: "\u586B\u5199\u5BA1\u6279\u610F\u89C1",
10735
+ onChange: (event) => setBatchApprovalComments(event.target.value)
10736
+ }
10737
+ )
10738
+ ] })
10739
+ }
10740
+ ),
10741
+ /* @__PURE__ */ jsxs41(
10742
+ Modal8,
10743
+ {
10744
+ getContainer: false,
10745
+ title: "\u5BFC\u5165\u6570\u636E",
10746
+ open: importOpen,
10747
+ width: 720,
10748
+ onCancel: () => setImportOpen(false),
10749
+ onOk: handleImportConfirm,
10750
+ okButtonProps: { disabled: !importBase64 },
10751
+ okText: "\u786E\u8BA4\u5BFC\u5165",
10752
+ children: [
10753
+ /* @__PURE__ */ jsx89(
10754
+ Upload3.Dragger,
10755
+ {
10756
+ accept: ".xlsx,.xls",
10757
+ maxCount: 1,
10758
+ beforeUpload: handleImportPreview,
10759
+ onRemove: () => {
10760
+ setImportBase64("");
10761
+ setImportPreview([]);
10762
+ },
10763
+ children: /* @__PURE__ */ jsx89("p", { className: "text-ant-color-text-secondary", children: "\u62D6\u62FD Excel \u6587\u4EF6\u5230\u6B64\u5904\uFF0C\u6216\u70B9\u51FB\u9009\u62E9\u6587\u4EF6" })
10764
+ }
10765
+ ),
10766
+ importPreview.length > 0 && /* @__PURE__ */ jsxs41("div", { className: "mt-4", children: [
10767
+ /* @__PURE__ */ jsx89("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u5BFC\u5165\u9884\u89C8" }),
10768
+ /* @__PURE__ */ jsx89(
10769
+ Table3,
10770
+ {
10771
+ size: "small",
10772
+ dataSource: importPreview,
10773
+ columns: importPreviewColumns,
10774
+ scroll: { x: Math.max(600, (importPreviewColumns?.length || 0) * 150) },
10775
+ pagination: false,
10776
+ rowKey: (_, index) => String(index)
10777
+ }
10778
+ )
8612
10779
  ] })
8613
- ] }, route.nodeId);
8614
- }) })
8615
- }
8616
- );
10780
+ ]
10781
+ }
10782
+ ),
10783
+ /* @__PURE__ */ jsxs41(
10784
+ Drawer2,
10785
+ {
10786
+ getContainer: false,
10787
+ title: recordTab === "import" ? "\u5BFC\u5165\u8BB0\u5F55" : "\u5BFC\u51FA\u8BB0\u5F55",
10788
+ open: recordsOpen,
10789
+ width: 720,
10790
+ onClose: () => setRecordsOpen(false),
10791
+ children: [
10792
+ /* @__PURE__ */ jsx89(
10793
+ Segmented,
10794
+ {
10795
+ value: recordTab,
10796
+ options: [
10797
+ { label: "\u5BFC\u5165\u8BB0\u5F55", value: "import" },
10798
+ { label: "\u5BFC\u51FA\u8BB0\u5F55", value: "export" }
10799
+ ],
10800
+ onChange: (value) => loadTransferRecords(value)
10801
+ }
10802
+ ),
10803
+ /* @__PURE__ */ jsx89(
10804
+ Table3,
10805
+ {
10806
+ className: "mt-4",
10807
+ size: "small",
10808
+ dataSource: transferRecords,
10809
+ rowKey: (record) => record.id || record.recordId
10810
+ }
10811
+ )
10812
+ ]
10813
+ }
10814
+ ),
10815
+ /* @__PURE__ */ jsx89(
10816
+ Drawer2,
10817
+ {
10818
+ getContainer: false,
10819
+ title: "\u8BE6\u60C5",
10820
+ open: detailOpen,
10821
+ width: 720,
10822
+ onClose: () => setDetailOpen(false),
10823
+ destroyOnClose: true,
10824
+ children: activeRecord && detailRenderer ? detailRenderer({
10825
+ record: activeRecord,
10826
+ formInstanceId: String(getRecordId(activeRecord)),
10827
+ onClose: () => setDetailOpen(false)
10828
+ }) : /* @__PURE__ */ jsx89(Empty5, { description: "\u8BF7\u901A\u8FC7 detailRenderer \u63A5\u5165\u8BE6\u60C5\u6A21\u677F" })
10829
+ }
10830
+ ),
10831
+ /* @__PURE__ */ jsx89(
10832
+ Drawer2,
10833
+ {
10834
+ getContainer: false,
10835
+ title: "\u65B0\u589E\u6570\u636E",
10836
+ open: submitOpen,
10837
+ width: 720,
10838
+ onClose: () => setSubmitOpen(false),
10839
+ destroyOnClose: true,
10840
+ children: submitRenderer ? submitRenderer({
10841
+ onClose: () => setSubmitOpen(false),
10842
+ onSubmitted: () => {
10843
+ setSubmitOpen(false);
10844
+ loadData({ current: 1, pageSize });
10845
+ }
10846
+ }) : /* @__PURE__ */ jsx89(Empty5, { description: "\u8BF7\u901A\u8FC7 submitRenderer \u63A5\u5165\u63D0\u4EA4\u6A21\u677F" })
10847
+ }
10848
+ )
10849
+ ] }) });
8617
10850
  };
8618
10851
 
8619
10852
  // src/templates/FormSubmitTemplate.tsx
8620
- import { useState as useState33, useCallback as useCallback17 } from "react";
8621
- import { Button as Button13 } from "antd";
8622
- import { CheckCircleFilled } from "@ant-design/icons";
8623
- import { Fragment as Fragment5, jsx as jsx84, jsxs as jsxs36 } from "react/jsx-runtime";
10853
+ import { useState as useState36, useCallback as useCallback18 } from "react";
10854
+ import { Button as Button16, Select as Select7 } from "antd";
10855
+ import { CheckCircleFilled as CheckCircleFilled2 } from "@ant-design/icons";
10856
+ import { Fragment as Fragment7, jsx as jsx90, jsxs as jsxs42 } from "react/jsx-runtime";
8624
10857
  var pickFormInstanceId = (value) => {
8625
10858
  if (!value) return void 0;
8626
10859
  if (typeof value === "string") return value;
@@ -8637,22 +10870,22 @@ var SubmitSuccessCard = ({
8637
10870
  renderSuccess
8638
10871
  }) => {
8639
10872
  if (renderSuccess) {
8640
- return /* @__PURE__ */ jsx84(Fragment5, { children: renderSuccess(info) });
10873
+ return /* @__PURE__ */ jsx90(Fragment7, { children: renderSuccess(info) });
8641
10874
  }
8642
- return /* @__PURE__ */ jsx84("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsxs36("div", { className: "flex flex-col items-center py-16 animate-[fadeIn_0.3s_ease-out,scaleIn_0.3s_ease-out]", children: [
8643
- /* @__PURE__ */ jsx84("div", { className: "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx84(CheckCircleFilled, { className: "text-2xl text-green-500" }) }),
8644
- /* @__PURE__ */ jsx84("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
8645
- /* @__PURE__ */ jsx84("p", { className: "text-sm text-gray-500 mb-6", children: info.message || "\u5DF2\u6210\u529F\u521B\u5EFA\u4E00\u6761\u65B0\u8BB0\u5F55" }),
8646
- /* @__PURE__ */ jsxs36("div", { className: "flex gap-3", children: [
8647
- (mode === "stay" || mode === "redirect") && /* @__PURE__ */ jsx84(Button13, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
8648
- /* @__PURE__ */ jsx84(Button13, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
10875
+ return /* @__PURE__ */ jsx90("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsxs42("div", { className: "flex flex-col items-center py-16 animate-[fadeIn_0.3s_ease-out,scaleIn_0.3s_ease-out]", children: [
10876
+ /* @__PURE__ */ jsx90("div", { className: "w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx90(CheckCircleFilled2, { className: "text-2xl text-green-500" }) }),
10877
+ /* @__PURE__ */ jsx90("h2", { className: "text-lg font-semibold text-gray-900 mb-1", children: "\u63D0\u4EA4\u6210\u529F" }),
10878
+ /* @__PURE__ */ jsx90("p", { className: "text-sm text-gray-500 mb-6", children: info.message || "\u5DF2\u6210\u529F\u521B\u5EFA\u4E00\u6761\u65B0\u8BB0\u5F55" }),
10879
+ /* @__PURE__ */ jsxs42("div", { className: "flex gap-3", children: [
10880
+ (mode === "stay" || mode === "redirect") && /* @__PURE__ */ jsx90(Button16, { onClick: onContinue, children: "\u7EE7\u7EED\u63D0\u4EA4" }),
10881
+ /* @__PURE__ */ jsx90(Button16, { type: "primary", onClick: onViewDetail, children: "\u67E5\u770B\u8BE6\u60C5" })
8649
10882
  ] }),
8650
- isRedirecting && /* @__PURE__ */ jsxs36("div", { className: "mt-6 w-48", children: [
8651
- /* @__PURE__ */ jsxs36("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
10883
+ isRedirecting && /* @__PURE__ */ jsxs42("div", { className: "mt-6 w-48", children: [
10884
+ /* @__PURE__ */ jsxs42("div", { className: "text-xs text-gray-400 text-center mb-1", children: [
8652
10885
  countdown,
8653
10886
  "\u79D2\u540E\u81EA\u52A8\u8DF3\u8F6C"
8654
10887
  ] }),
8655
- /* @__PURE__ */ jsx84("div", { className: "h-1 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx84(
10888
+ /* @__PURE__ */ jsx90("div", { className: "h-1 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx90(
8656
10889
  "div",
8657
10890
  {
8658
10891
  className: "h-full bg-blue-500 transition-all duration-1000",
@@ -8668,18 +10901,28 @@ var InnerFormContent = ({
8668
10901
  formType,
8669
10902
  submitSuccessMode,
8670
10903
  enableDraft,
10904
+ enableProcessPreview,
10905
+ enableSubmissionDepartmentSelect,
10906
+ departmentOptions,
8671
10907
  header,
8672
10908
  footer,
8673
10909
  beforeForm,
8674
10910
  afterForm,
10911
+ renderDepartmentSelector,
8675
10912
  renderForm,
8676
10913
  renderSuccess,
8677
- onSubmitSuccess
10914
+ onSubmitSuccess,
10915
+ inDrawer = false
8678
10916
  }) => {
8679
- const { validateAll, getFormData: getFormData2, resetForm, api } = useFormContext();
8680
- const [submitted, setSubmitted] = useState33(false);
8681
- const [successInfo, setSuccessInfo] = useState33(null);
8682
- const [submitting, setSubmitting] = useState33(false);
10917
+ const { validateAll, getFormData: getFormData2, setFieldValue, resetForm, api } = useFormContext();
10918
+ const [submitted, setSubmitted] = useState36(false);
10919
+ const [successInfo, setSuccessInfo] = useState36(null);
10920
+ const [submitting, setSubmitting] = useState36(false);
10921
+ const [departmentId, setDepartmentId] = useState36();
10922
+ const [previewOpen, setPreviewOpen] = useState36(false);
10923
+ const [previewLoading, setPreviewLoading] = useState36(false);
10924
+ const [previewRoutes, setPreviewRoutes] = useState36([]);
10925
+ const [pendingFormData, setPendingFormData] = useState36(null);
8683
10926
  const { hasDraft, draftTimestamp, saveDraft, restoreDraft, clearDraft } = useDraftStorage({
8684
10927
  appType: config.appType,
8685
10928
  formUuid: config.formUuid
@@ -8691,79 +10934,123 @@ var InnerFormContent = ({
8691
10934
  mode: submitSuccessMode === "continue" ? "stay" : submitSuccessMode,
8692
10935
  basePath: config.navigation?.basePath
8693
10936
  });
8694
- const handleSubmit = useCallback17(async () => {
10937
+ const performSubmit = useCallback18(
10938
+ async (formData) => {
10939
+ setSubmitting(true);
10940
+ try {
10941
+ const submitResponse = config.mode === "edit" && config.formInstanceId ? await api.updateFormData({
10942
+ appType: config.appType,
10943
+ formUuid: config.formUuid,
10944
+ formInstId: config.formInstanceId,
10945
+ formInstanceId: config.formInstanceId,
10946
+ updateFormDataJson: JSON.stringify(formData)
10947
+ }) : await api.submitFormData({
10948
+ appType: config.appType,
10949
+ formUuid: config.formUuid,
10950
+ data: formData,
10951
+ submissionDepartmentId: departmentId
10952
+ });
10953
+ const formInstId = pickFormInstanceId(submitResponse) || config.formInstanceId || `inst_${Date.now()}`;
10954
+ if (config.submit?.afterSubmit) {
10955
+ await config.submit.afterSubmit({
10956
+ formInstanceId: formInstId,
10957
+ data: formData,
10958
+ response: submitResponse
10959
+ });
10960
+ }
10961
+ if (enableDraft) {
10962
+ clearDraft();
10963
+ }
10964
+ onSubmitSuccess?.(formInstId);
10965
+ if (submitSuccessMode === "continue") {
10966
+ resetForm();
10967
+ } else {
10968
+ setSuccessInfo({ formInstanceId: formInstId });
10969
+ setSubmitted(true);
10970
+ handlePostSubmit(formInstId);
10971
+ }
10972
+ } catch (error) {
10973
+ console.error("[FormSubmitTemplate] Submit failed:", error);
10974
+ } finally {
10975
+ setSubmitting(false);
10976
+ }
10977
+ },
10978
+ [
10979
+ api,
10980
+ clearDraft,
10981
+ config,
10982
+ departmentId,
10983
+ enableDraft,
10984
+ handlePostSubmit,
10985
+ onSubmitSuccess,
10986
+ resetForm,
10987
+ submitSuccessMode
10988
+ ]
10989
+ );
10990
+ const prepareSubmit = useCallback18(async () => {
8695
10991
  const valid = await validateAll();
8696
10992
  if (!valid) return;
8697
- setSubmitting(true);
8698
- try {
8699
- const formData = getFormData2();
8700
- if (config.submit?.beforeSubmit) {
8701
- const shouldContinue = await config.submit.beforeSubmit(formData);
8702
- if (shouldContinue === false) {
8703
- setSubmitting(false);
8704
- return;
8705
- }
10993
+ const formData = getFormData2();
10994
+ if (config.submit?.beforeSubmit) {
10995
+ const shouldContinue = await config.submit.beforeSubmit(formData);
10996
+ if (shouldContinue === false) {
10997
+ return;
8706
10998
  }
8707
- const submitResponse = config.mode === "edit" && config.formInstanceId ? await api.updateFormData({
8708
- appType: config.appType,
8709
- formUuid: config.formUuid,
8710
- formInstId: config.formInstanceId,
8711
- formInstanceId: config.formInstanceId,
8712
- updateFormDataJson: JSON.stringify(formData)
8713
- }) : await api.submitFormData({
8714
- appType: config.appType,
8715
- formUuid: config.formUuid,
8716
- data: formData
8717
- });
8718
- const formInstId = pickFormInstanceId(submitResponse) || config.formInstanceId || `inst_${Date.now()}`;
8719
- if (config.submit?.afterSubmit) {
8720
- await config.submit.afterSubmit({
8721
- formInstanceId: formInstId,
10999
+ }
11000
+ if (formType === "process" && enableProcessPreview) {
11001
+ setPendingFormData(formData);
11002
+ setPreviewOpen(true);
11003
+ setPreviewLoading(true);
11004
+ try {
11005
+ const routes = await previewProcess(api.request, {
11006
+ appType: config.appType,
11007
+ formUuid: config.formUuid,
8722
11008
  data: formData,
8723
- response: submitResponse
11009
+ submissionDepartmentId: departmentId
8724
11010
  });
11011
+ setPreviewRoutes(Array.isArray(routes) ? routes : []);
11012
+ } catch (error) {
11013
+ console.error("[FormSubmitTemplate] Preview failed:", error);
11014
+ setPreviewRoutes([]);
11015
+ } finally {
11016
+ setPreviewLoading(false);
8725
11017
  }
8726
- if (enableDraft) {
8727
- clearDraft();
8728
- }
8729
- onSubmitSuccess?.(formInstId);
8730
- if (submitSuccessMode === "continue") {
8731
- resetForm();
8732
- } else {
8733
- setSuccessInfo({ formInstanceId: formInstId });
8734
- setSubmitted(true);
8735
- handlePostSubmit(formInstId);
8736
- }
8737
- } catch (error) {
8738
- console.error("[FormSubmitTemplate] Submit failed:", error);
8739
- } finally {
8740
- setSubmitting(false);
11018
+ return;
8741
11019
  }
11020
+ await performSubmit(formData);
8742
11021
  }, [
8743
11022
  validateAll,
8744
11023
  getFormData2,
8745
11024
  config,
8746
11025
  api,
8747
- enableDraft,
8748
- clearDraft,
8749
- onSubmitSuccess,
8750
- submitSuccessMode,
8751
- resetForm,
8752
- handlePostSubmit
11026
+ formType,
11027
+ enableProcessPreview,
11028
+ departmentId,
11029
+ performSubmit
8753
11030
  ]);
8754
- const handleSaveDraft = useCallback17(() => {
11031
+ const handlePreviewConfirm = useCallback18(async () => {
11032
+ const data = pendingFormData ?? getFormData2();
11033
+ setPreviewOpen(false);
11034
+ setPendingFormData(null);
11035
+ await performSubmit(data);
11036
+ }, [getFormData2, pendingFormData, performSubmit]);
11037
+ const handleSaveDraft = useCallback18(() => {
8755
11038
  const data = getFormData2();
8756
11039
  saveDraft(data);
8757
11040
  }, [getFormData2, saveDraft]);
8758
- const handleRestoreDraft = useCallback17(() => {
8759
- restoreDraft();
8760
- }, [restoreDraft]);
8761
- const handleContinue = useCallback17(() => {
11041
+ const handleRestoreDraft = useCallback18(() => {
11042
+ const data = restoreDraft();
11043
+ if (!data) return;
11044
+ Object.entries(data).forEach(([fieldId, value]) => {
11045
+ setFieldValue(fieldId, value);
11046
+ });
11047
+ }, [restoreDraft, setFieldValue]);
11048
+ const handleContinue = useCallback18(() => {
8762
11049
  setSubmitted(false);
8763
11050
  setSuccessInfo(null);
8764
11051
  resetForm();
8765
11052
  }, [resetForm]);
8766
- const handleViewDetail = useCallback17(() => {
11053
+ const handleViewDetail = useCallback18(() => {
8767
11054
  if (!successInfo) return;
8768
11055
  if (formType === "process") {
8769
11056
  navigateToProcessDetail(successInfo.formInstanceId);
@@ -8791,15 +11078,39 @@ var InnerFormContent = ({
8791
11078
  label: "\u63D0\u4EA4",
8792
11079
  type: "primary",
8793
11080
  loading: submitting,
8794
- onClick: handleSubmit
11081
+ onClick: prepareSubmit
8795
11082
  });
8796
- return /* @__PURE__ */ jsxs36("div", { className: "min-h-screen bg-gray-50/50", children: [
8797
- /* @__PURE__ */ jsxs36("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: [
8798
- header || /* @__PURE__ */ jsxs36("div", { className: "mb-6", children: [
8799
- /* @__PURE__ */ jsx84("h1", { className: "text-2xl font-bold text-gray-900", children: schema.formMeta.title }),
8800
- /* @__PURE__ */ jsx84("p", { className: "text-sm text-gray-500 mt-1", children: "\u8BF7\u586B\u5199\u4EE5\u4E0B\u4FE1\u606F" })
8801
- ] }),
8802
- enableDraft && hasDraft && !submitted && /* @__PURE__ */ jsx84("div", { className: "mb-6", children: /* @__PURE__ */ jsx84(
11083
+ const departmentSelector = formType === "process" && enableSubmissionDepartmentSelect ? /* @__PURE__ */ jsxs42("div", { className: "mb-5 rounded-lg border border-ant-border-secondary bg-ant-bg-elevated px-4 py-3", children: [
11084
+ /* @__PURE__ */ jsx90("div", { className: "mb-2 text-sm font-medium text-ant-color-text", children: "\u63D0\u4EA4\u90E8\u95E8" }),
11085
+ renderDepartmentSelector ? renderDepartmentSelector({
11086
+ value: departmentId,
11087
+ onChange: setDepartmentId,
11088
+ options: departmentOptions
11089
+ }) : /* @__PURE__ */ jsx90(
11090
+ Select7,
11091
+ {
11092
+ allowClear: true,
11093
+ className: "w-full",
11094
+ placeholder: "\u8BF7\u9009\u62E9\u672C\u6B21\u63D0\u4EA4\u6D41\u7A0B\u6240\u5C5E\u90E8\u95E8",
11095
+ value: departmentId,
11096
+ options: departmentOptions,
11097
+ onChange: setDepartmentId
11098
+ }
11099
+ )
11100
+ ] }) : null;
11101
+ const actionsNode = !submitted ? /* @__PURE__ */ jsx90(
11102
+ StickyActionBar,
11103
+ {
11104
+ actions,
11105
+ inDrawer,
11106
+ position: "inline",
11107
+ className: "mt-6 -mx-5 -mb-5 rounded-b-lg md:-mx-6 md:-mb-6"
11108
+ }
11109
+ ) : null;
11110
+ return /* @__PURE__ */ jsxs42(RuntimePageShell, { inDrawer, children: [
11111
+ /* @__PURE__ */ jsxs42("div", { className: "space-y-6", children: [
11112
+ header,
11113
+ enableDraft && hasDraft && !submitted && /* @__PURE__ */ jsx90("div", { children: /* @__PURE__ */ jsx90(
8803
11114
  DraftManager,
8804
11115
  {
8805
11116
  hasDraft,
@@ -8808,11 +11119,13 @@ var InnerFormContent = ({
8808
11119
  onDiscard: clearDraft
8809
11120
  }
8810
11121
  ) }),
8811
- !submitted ? /* @__PURE__ */ jsxs36("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6 animate-[fadeIn_0.2s_ease-out]", children: [
11122
+ !submitted ? /* @__PURE__ */ jsxs42("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: [
11123
+ departmentSelector,
8812
11124
  beforeForm,
8813
- renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ jsx84(FormRenderer, { columns: 2 }),
8814
- afterForm
8815
- ] }) : successInfo && /* @__PURE__ */ jsx84(
11125
+ renderForm ? renderForm({ schema, config }) : /* @__PURE__ */ jsx90(FormRenderer, { columns: 2 }),
11126
+ afterForm,
11127
+ actionsNode
11128
+ ] }) : successInfo && /* @__PURE__ */ jsx90(
8816
11129
  SubmitSuccessCard,
8817
11130
  {
8818
11131
  info: successInfo,
@@ -8826,7 +11139,16 @@ var InnerFormContent = ({
8826
11139
  ),
8827
11140
  footer
8828
11141
  ] }),
8829
- !submitted && /* @__PURE__ */ jsx84(FormActionBar, { actions, position: "bottom-fixed" })
11142
+ /* @__PURE__ */ jsx90(
11143
+ ProcessPreview,
11144
+ {
11145
+ open: previewOpen,
11146
+ routes: previewRoutes,
11147
+ loading: previewLoading,
11148
+ onClose: () => setPreviewOpen(false),
11149
+ onConfirm: handlePreviewConfirm
11150
+ }
11151
+ )
8830
11152
  ] });
8831
11153
  };
8832
11154
  var FormSubmitTemplate = ({
@@ -8835,15 +11157,20 @@ var FormSubmitTemplate = ({
8835
11157
  formType = "form",
8836
11158
  submitSuccessMode = "redirect",
8837
11159
  enableDraft = false,
11160
+ enableProcessPreview = false,
11161
+ enableSubmissionDepartmentSelect = false,
11162
+ departmentOptions = [],
8838
11163
  header,
8839
11164
  footer,
8840
11165
  beforeForm,
8841
11166
  afterForm,
11167
+ renderDepartmentSelector,
8842
11168
  renderForm,
8843
11169
  renderSuccess,
8844
- onSubmitSuccess
11170
+ onSubmitSuccess,
11171
+ inDrawer = false
8845
11172
  }) => {
8846
- return /* @__PURE__ */ jsx84(FormProvider, { schema, config, children: /* @__PURE__ */ jsx84(
11173
+ return /* @__PURE__ */ jsx90(FormProvider, { schema, config, children: /* @__PURE__ */ jsx90(
8847
11174
  InnerFormContent,
8848
11175
  {
8849
11176
  schema,
@@ -8851,83 +11178,95 @@ var FormSubmitTemplate = ({
8851
11178
  formType,
8852
11179
  submitSuccessMode,
8853
11180
  enableDraft,
11181
+ enableProcessPreview,
11182
+ enableSubmissionDepartmentSelect,
11183
+ departmentOptions,
8854
11184
  header,
8855
11185
  footer,
8856
11186
  beforeForm,
8857
11187
  afterForm,
11188
+ renderDepartmentSelector,
8858
11189
  renderForm,
8859
11190
  renderSuccess,
8860
- onSubmitSuccess
11191
+ onSubmitSuccess,
11192
+ inDrawer
8861
11193
  }
8862
11194
  ) });
8863
11195
  };
8864
11196
 
8865
11197
  // src/templates/FormDetailTemplate.tsx
8866
- import { useCallback as useCallback18, useMemo as useMemo14 } from "react";
11198
+ import { useCallback as useCallback19, useMemo as useMemo19, useRef as useRef15, useState as useState37 } from "react";
8867
11199
 
8868
11200
  // src/templates/PageSkeleton.tsx
8869
11201
  import { Skeleton as Skeleton3 } from "antd";
8870
- import { jsx as jsx85, jsxs as jsxs37 } from "react/jsx-runtime";
8871
- var CardSkeleton = ({ children }) => /* @__PURE__ */ jsx85("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
8872
- var SummaryCardSkeleton = () => /* @__PURE__ */ jsxs37(CardSkeleton, { children: [
8873
- /* @__PURE__ */ jsxs37("div", { className: "flex items-start justify-between", children: [
8874
- /* @__PURE__ */ jsxs37("div", { className: "flex-1", children: [
8875
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "large", style: { width: 200 } }),
8876
- /* @__PURE__ */ jsx85("div", { className: "mt-2", children: /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "small", style: { width: 80 } }) })
11202
+ import { jsx as jsx91, jsxs as jsxs43 } from "react/jsx-runtime";
11203
+ var CardSkeleton = ({ children }) => /* @__PURE__ */ jsx91("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children });
11204
+ var SummaryCardSkeleton = () => /* @__PURE__ */ jsxs43(CardSkeleton, { children: [
11205
+ /* @__PURE__ */ jsxs43("div", { className: "flex items-start justify-between", children: [
11206
+ /* @__PURE__ */ jsxs43("div", { className: "flex-1", children: [
11207
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "large", style: { width: 200 } }),
11208
+ /* @__PURE__ */ jsx91("div", { className: "mt-2", children: /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "small", style: { width: 80 } }) })
8877
11209
  ] }),
8878
- /* @__PURE__ */ jsx85(Skeleton3.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
11210
+ /* @__PURE__ */ jsx91(Skeleton3.Button, { active: true, size: "small", shape: "round", style: { width: 60 } })
8879
11211
  ] }),
8880
- /* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-3 mt-4", children: [
8881
- /* @__PURE__ */ jsx85(Skeleton3.Avatar, { active: true, size: "small" }),
8882
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "small", style: { width: 120 } })
11212
+ /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-3 mt-4", children: [
11213
+ /* @__PURE__ */ jsx91(Skeleton3.Avatar, { active: true, size: "small" }),
11214
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "small", style: { width: 120 } })
8883
11215
  ] })
8884
11216
  ] });
8885
- var FormGridSkeleton = () => /* @__PURE__ */ jsx85(CardSkeleton, { children: /* @__PURE__ */ jsx85("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs37("div", { className: "space-y-2", children: [
8886
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "small", style: { width: 80 } }),
8887
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, block: true, style: { width: "100%" } })
11217
+ var FormGridSkeleton = () => /* @__PURE__ */ jsx91(CardSkeleton, { children: /* @__PURE__ */ jsx91("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs43("div", { className: "space-y-2", children: [
11218
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "small", style: { width: 80 } }),
11219
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, block: true, style: { width: "100%" } })
8888
11220
  ] }, i)) }) });
8889
- var ActionBarSkeleton = () => /* @__PURE__ */ jsx85("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__ */ jsxs37("div", { className: "flex items-center justify-end gap-3", children: [
8890
- /* @__PURE__ */ jsx85(Skeleton3.Button, { active: true, style: { width: 80 } }),
8891
- /* @__PURE__ */ jsx85(Skeleton3.Button, { active: true, style: { width: 80 } })
11221
+ var ActionBarSkeleton = () => /* @__PURE__ */ jsx91("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__ */ jsxs43("div", { className: "flex items-center justify-end gap-3", children: [
11222
+ /* @__PURE__ */ jsx91(Skeleton3.Button, { active: true, style: { width: 80 } }),
11223
+ /* @__PURE__ */ jsx91(Skeleton3.Button, { active: true, style: { width: 80 } })
8892
11224
  ] }) });
8893
- var TimelineSkeleton = () => /* @__PURE__ */ jsxs37(CardSkeleton, { children: [
8894
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
8895
- /* @__PURE__ */ jsx85("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs37("div", { className: "flex gap-4", children: [
8896
- /* @__PURE__ */ jsxs37("div", { className: "flex flex-col items-center", children: [
8897
- /* @__PURE__ */ jsx85("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
8898
- i < 2 && /* @__PURE__ */ jsx85("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
11225
+ var TimelineSkeleton = () => /* @__PURE__ */ jsxs43(CardSkeleton, { children: [
11226
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "default", style: { width: 100, marginBottom: 16 } }),
11227
+ /* @__PURE__ */ jsx91("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs43("div", { className: "flex gap-4", children: [
11228
+ /* @__PURE__ */ jsxs43("div", { className: "flex flex-col items-center", children: [
11229
+ /* @__PURE__ */ jsx91("div", { className: "w-3 h-3 rounded-full bg-gray-200 animate-pulse" }),
11230
+ i < 2 && /* @__PURE__ */ jsx91("div", { className: "w-0.5 flex-1 bg-gray-200 mt-1" })
8899
11231
  ] }),
8900
- /* @__PURE__ */ jsx85("div", { className: "flex-1 pb-4", children: /* @__PURE__ */ jsx85(Skeleton3, { active: true, paragraph: { rows: 1 }, title: { width: "60%" } }) })
11232
+ /* @__PURE__ */ jsx91("div", { className: "flex-1 pb-4", children: /* @__PURE__ */ jsx91(Skeleton3, { active: true, paragraph: { rows: 1 }, title: { width: "60%" } }) })
8901
11233
  ] }, i)) })
8902
11234
  ] });
8903
11235
  var PageSkeleton = ({ type }) => {
8904
11236
  if (type === "submit") {
8905
- return /* @__PURE__ */ jsxs37("div", { className: "space-y-6", children: [
8906
- /* @__PURE__ */ jsxs37("div", { className: "space-y-2", children: [
8907
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "large", style: { width: 200 } }),
8908
- /* @__PURE__ */ jsx85(Skeleton3.Input, { active: true, size: "small", style: { width: 300 } })
11237
+ return /* @__PURE__ */ jsxs43("div", { className: "space-y-6", children: [
11238
+ /* @__PURE__ */ jsxs43("div", { className: "space-y-2", children: [
11239
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "large", style: { width: 200 } }),
11240
+ /* @__PURE__ */ jsx91(Skeleton3.Input, { active: true, size: "small", style: { width: 300 } })
8909
11241
  ] }),
8910
- /* @__PURE__ */ jsx85(FormGridSkeleton, {}),
8911
- /* @__PURE__ */ jsx85(ActionBarSkeleton, {})
11242
+ /* @__PURE__ */ jsx91(FormGridSkeleton, {}),
11243
+ /* @__PURE__ */ jsx91(ActionBarSkeleton, {})
8912
11244
  ] });
8913
11245
  }
8914
11246
  if (type === "detail") {
8915
- return /* @__PURE__ */ jsxs37("div", { className: "space-y-6", children: [
8916
- /* @__PURE__ */ jsx85(SummaryCardSkeleton, {}),
8917
- /* @__PURE__ */ jsx85(FormGridSkeleton, {}),
8918
- /* @__PURE__ */ jsx85(ActionBarSkeleton, {})
11247
+ return /* @__PURE__ */ jsxs43("div", { className: "space-y-6", children: [
11248
+ /* @__PURE__ */ jsx91(SummaryCardSkeleton, {}),
11249
+ /* @__PURE__ */ jsx91(FormGridSkeleton, {}),
11250
+ /* @__PURE__ */ jsx91(ActionBarSkeleton, {})
8919
11251
  ] });
8920
11252
  }
8921
- return /* @__PURE__ */ jsxs37("div", { className: "space-y-6", children: [
8922
- /* @__PURE__ */ jsx85(SummaryCardSkeleton, {}),
8923
- /* @__PURE__ */ jsx85(FormGridSkeleton, {}),
8924
- /* @__PURE__ */ jsx85(TimelineSkeleton, {}),
8925
- /* @__PURE__ */ jsx85(ActionBarSkeleton, {})
11253
+ return /* @__PURE__ */ jsxs43("div", { className: "space-y-6", children: [
11254
+ /* @__PURE__ */ jsx91(SummaryCardSkeleton, {}),
11255
+ /* @__PURE__ */ jsx91(FormGridSkeleton, {}),
11256
+ /* @__PURE__ */ jsx91(TimelineSkeleton, {}),
11257
+ /* @__PURE__ */ jsx91(ActionBarSkeleton, {})
8926
11258
  ] });
8927
11259
  };
8928
11260
 
8929
11261
  // src/templates/FormDetailTemplate.tsx
8930
- import { Fragment as Fragment6, jsx as jsx86, jsxs as jsxs38 } from "react/jsx-runtime";
11262
+ import { jsx as jsx92, jsxs as jsxs44 } from "react/jsx-runtime";
11263
+ function FormDataBridge({
11264
+ formDataRef
11265
+ }) {
11266
+ const { getFormData: getFormData2 } = useFormContext();
11267
+ formDataRef.current = getFormData2;
11268
+ return null;
11269
+ }
8931
11270
  var InnerDetailContent = ({
8932
11271
  schema,
8933
11272
  formUuid,
@@ -8941,9 +11280,12 @@ var InnerDetailContent = ({
8941
11280
  renderSummary,
8942
11281
  renderActions,
8943
11282
  onDelete,
8944
- onSave
11283
+ onSave,
11284
+ inDrawer = false
8945
11285
  }) => {
8946
- const fieldIds = useMemo14(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11286
+ const formDataRef = useRef15(void 0);
11287
+ const [accessDenied, setAccessDenied] = useState37(false);
11288
+ const fieldIds = useMemo19(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
8947
11289
  const {
8948
11290
  loading,
8949
11291
  mode,
@@ -8957,7 +11299,13 @@ var InnerDetailContent = ({
8957
11299
  canEdit,
8958
11300
  canDelete,
8959
11301
  canViewChangeRecords
8960
- } = useFormDetail({ formUuid, appType, formInstanceId, fieldIds });
11302
+ } = useFormDetail({
11303
+ formUuid,
11304
+ appType,
11305
+ formInstanceId,
11306
+ fieldIds,
11307
+ onPermissionDenied: () => setAccessDenied(true)
11308
+ });
8961
11309
  const {
8962
11310
  records,
8963
11311
  loading: recordsLoading,
@@ -8970,20 +11318,21 @@ var InnerDetailContent = ({
8970
11318
  formInstanceId,
8971
11319
  autoLoad: enableChangeRecords && canViewChangeRecords
8972
11320
  });
8973
- const handleSave = useCallback18(async () => {
8974
- if (!formData) return;
8975
- const success = await saveChanges(formData);
11321
+ const handleSave = useCallback19(async () => {
11322
+ const values = formDataRef.current?.() ?? formData;
11323
+ if (!values) return;
11324
+ const success = await saveChanges(values);
8976
11325
  if (success) {
8977
- onSave?.(formData);
11326
+ onSave?.(values);
8978
11327
  }
8979
11328
  }, [formData, saveChanges, onSave]);
8980
- const handleDelete = useCallback18(async () => {
11329
+ const handleDelete = useCallback19(async () => {
8981
11330
  const success = await deleteInstance();
8982
11331
  if (success) {
8983
11332
  onDelete?.();
8984
11333
  }
8985
11334
  }, [deleteInstance, onDelete]);
8986
- const handleCancel = useCallback18(() => {
11335
+ const handleCancel = useCallback19(() => {
8987
11336
  switchToReadonly();
8988
11337
  }, [switchToReadonly]);
8989
11338
  const readonlyActions = [];
@@ -9020,41 +11369,44 @@ var InnerDetailContent = ({
9020
11369
  }
9021
11370
  };
9022
11371
  if (loading) {
9023
- return /* @__PURE__ */ jsx86("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ jsx86("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ jsx86(PageSkeleton, { type: "detail" }) }) });
11372
+ return /* @__PURE__ */ jsx92("div", { className: "min-h-screen bg-ant-bg-layout", children: /* @__PURE__ */ jsx92("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ jsx92(PageSkeleton, { type: "detail" }) }) });
9024
11373
  }
9025
- return /* @__PURE__ */ jsxs38("div", { className: "min-h-screen bg-gray-50/50", children: [
9026
- /* @__PURE__ */ jsx86("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ jsxs38("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
9027
- header,
9028
- renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ jsx86(
9029
- FormSummaryCard,
9030
- {
9031
- title: schema.formMeta.title,
9032
- formInstanceId,
9033
- creator: instanceInfo?.creator ? {
9034
- name: instanceInfo.creator.name,
9035
- avatar: instanceInfo.creator.avatar,
9036
- department: instanceInfo.creator.department
9037
- } : void 0,
9038
- createdAt: instanceInfo?.createdAt,
9039
- status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
9040
- }
9041
- ),
9042
- mode === "edit" && /* @__PURE__ */ jsx86("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" }),
9043
- /* @__PURE__ */ jsx86("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsx86(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: /* @__PURE__ */ jsx86(FormRenderer, { columns: 2 }) }) }),
9044
- enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ jsx86(
9045
- ChangeRecords,
9046
- {
9047
- records,
9048
- loading: recordsLoading,
9049
- hasMore,
9050
- onLoadMore: loadMore,
9051
- onExpand: refreshRecords
9052
- }
9053
- ),
9054
- footer
11374
+ const actionsNode = currentActions.length > 0 ? renderActions ? renderActions(currentActions) : /* @__PURE__ */ jsx92(StickyActionBar, { actions: currentActions, inDrawer }) : null;
11375
+ return /* @__PURE__ */ jsx92(RuntimePageShell, { actions: actionsNode, accessDenied, inDrawer, children: /* @__PURE__ */ jsx92("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs44("div", { children: [
11376
+ header,
11377
+ renderSummary && instanceInfo ? renderSummary(instanceInfo) : /* @__PURE__ */ jsx92(
11378
+ SummaryPanel,
11379
+ {
11380
+ title: instanceInfo?.title || formData?.instanceTitle || schema.formMeta.title,
11381
+ eyebrow: `\u6570\u636E\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
11382
+ creator: instanceInfo?.creator ? {
11383
+ name: instanceInfo.creator.name,
11384
+ avatar: instanceInfo.creator.avatar,
11385
+ department: instanceInfo.creator.department
11386
+ } : void 0,
11387
+ createdAt: instanceInfo?.createdAt,
11388
+ status: mode === "edit" ? { label: "\u7F16\u8F91\u4E2D", tone: "brand" } : void 0
11389
+ }
11390
+ ),
11391
+ mode === "edit" && /* @__PURE__ */ jsx92("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" }),
11392
+ /* @__PURE__ */ jsx92("div", { className: "mt-6 rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: /* @__PURE__ */ jsxs44(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
11393
+ /* @__PURE__ */ jsx92(FormDataBridge, { formDataRef }),
11394
+ /* @__PURE__ */ jsx92(FormRenderer, { columns: 2 })
9055
11395
  ] }) }),
9056
- currentActions.length > 0 && (renderActions ? /* @__PURE__ */ jsx86(Fragment6, { children: renderActions(currentActions) }) : /* @__PURE__ */ jsx86(FormActionBar, { position: "bottom-fixed", actions: currentActions }))
9057
- ] });
11396
+ enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ jsx92("div", { className: "mt-6", children: /* @__PURE__ */ jsx92(
11397
+ RecordChangePanel,
11398
+ {
11399
+ records,
11400
+ loading: recordsLoading,
11401
+ total: records.length,
11402
+ hasMore,
11403
+ onLoadMore: loadMore,
11404
+ onRefresh: refreshRecords,
11405
+ onExpand: refreshRecords
11406
+ }
11407
+ ) }),
11408
+ footer
11409
+ ] }) }) });
9058
11410
  };
9059
11411
  var FormDetailTemplate = (props) => {
9060
11412
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -9064,13 +11416,13 @@ var FormDetailTemplate = (props) => {
9064
11416
  appType,
9065
11417
  formInstanceId
9066
11418
  };
9067
- return /* @__PURE__ */ jsx86(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ jsx86(InnerDetailContent, { ...props }) });
11419
+ return /* @__PURE__ */ jsx92(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ jsx92(InnerDetailContent, { ...props }) });
9068
11420
  };
9069
11421
 
9070
11422
  // src/templates/ProcessDetailTemplate.tsx
9071
- import { useCallback as useCallback19, useMemo as useMemo15, useRef as useRef14 } from "react";
9072
- import { Fragment as Fragment7, jsx as jsx87, jsxs as jsxs39 } from "react/jsx-runtime";
9073
- function FormDataBridge({
11423
+ import { useCallback as useCallback20, useMemo as useMemo20, useRef as useRef16 } from "react";
11424
+ import { jsx as jsx93, jsxs as jsxs45 } from "react/jsx-runtime";
11425
+ function FormDataBridge2({
9074
11426
  formDataRef
9075
11427
  }) {
9076
11428
  const { getFormData: getFormData2 } = useFormContext();
@@ -9085,12 +11437,16 @@ var InnerProcessContent = ({
9085
11437
  header,
9086
11438
  renderTimeline,
9087
11439
  renderActions,
11440
+ renderTransferSelector,
11441
+ renderReturnNodeLabel,
11442
+ renderActionModalExtra,
9088
11443
  beforeForm,
9089
11444
  afterForm,
9090
- onActionComplete
11445
+ onActionComplete,
11446
+ inDrawer = false
9091
11447
  }) => {
9092
- const formDataRef = useRef14(void 0);
9093
- const fieldIds = useMemo15(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11448
+ const formDataRef = useRef16(void 0);
11449
+ const fieldIds = useMemo20(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
9094
11450
  const {
9095
11451
  loading,
9096
11452
  processInfo,
@@ -9098,6 +11454,7 @@ var InnerProcessContent = ({
9098
11454
  currentTask,
9099
11455
  progressList,
9100
11456
  formData,
11457
+ instanceInfo,
9101
11458
  isApprover,
9102
11459
  activeActions,
9103
11460
  fieldBehaviors,
@@ -9108,7 +11465,18 @@ var InnerProcessContent = ({
9108
11465
  switchToReadonly,
9109
11466
  refreshProgress
9110
11467
  } = useProcessDetail({ formUuid, appType, formInstanceId, fieldIds });
9111
- const { approve, reject, withdraw, save, resubmit } = useApprovalActions({
11468
+ const {
11469
+ approve,
11470
+ reject,
11471
+ transfer,
11472
+ returnTo,
11473
+ withdraw,
11474
+ save,
11475
+ resubmit,
11476
+ callbackTask,
11477
+ returnableNodes,
11478
+ loadReturnableNodes
11479
+ } = useApprovalActions({
9112
11480
  formInstanceId,
9113
11481
  formUuid,
9114
11482
  appType,
@@ -9117,72 +11485,102 @@ var InnerProcessContent = ({
9117
11485
  onActionComplete?.(action);
9118
11486
  await refreshProgress();
9119
11487
  },
9120
- getFormValues: () => formDataRef.current?.() ?? {}
11488
+ getFormValues: () => formDataRef.current?.() ?? formData ?? {}
9121
11489
  });
9122
- const handleApprove = useCallback19(
11490
+ const handleApprove = useCallback20(
9123
11491
  async (comments) => {
9124
11492
  await approve(comments);
9125
11493
  },
9126
11494
  [approve]
9127
11495
  );
9128
- const handleReject = useCallback19(
11496
+ const handleReject = useCallback20(
9129
11497
  async (comments) => {
9130
11498
  await reject(comments);
9131
11499
  },
9132
11500
  [reject]
9133
11501
  );
9134
- const handleWithdraw = useCallback19(
11502
+ const handleTransfer = useCallback20(
11503
+ async (userId, reason) => {
11504
+ await transfer(userId, reason);
11505
+ },
11506
+ [transfer]
11507
+ );
11508
+ const handleReturn = useCallback20(
11509
+ async (nodeId, reason) => {
11510
+ await returnTo(nodeId, reason);
11511
+ },
11512
+ [returnTo]
11513
+ );
11514
+ const handleWithdraw = useCallback20(
9135
11515
  async (reason) => {
9136
11516
  await withdraw(reason);
9137
11517
  },
9138
11518
  [withdraw]
9139
11519
  );
9140
- const handleSave = useCallback19(async () => {
11520
+ const handleSave = useCallback20(async () => {
9141
11521
  await save();
9142
11522
  }, [save]);
9143
- const handleResubmit = useCallback19(async () => {
9144
- await resubmit();
9145
- }, [resubmit]);
9146
- const buildActions = () => {
9147
- const actions = [];
9148
- if (isApprover && activeActions.length > 0) {
9149
- return [];
9150
- }
11523
+ const handleResubmit = useCallback20(
11524
+ async (comments) => {
11525
+ await resubmit(comments);
11526
+ },
11527
+ [resubmit]
11528
+ );
11529
+ const handleCallback = useCallback20(async () => {
11530
+ await callbackTask();
11531
+ }, [callbackTask]);
11532
+ const bottomActions = useMemo20(() => {
11533
+ if (isApprover && activeActions.length > 0) return [];
9151
11534
  if (isOriginatorReturn) {
9152
11535
  if (mode === "readonly") {
9153
- actions.push({
9154
- key: "edit",
9155
- label: "\u7F16\u8F91",
9156
- type: "primary",
9157
- onClick: switchToEdit
9158
- });
9159
- } else {
9160
- actions.push({
11536
+ return [
11537
+ {
11538
+ key: "edit",
11539
+ label: "\u7F16\u8F91",
11540
+ type: "primary",
11541
+ onClick: switchToEdit
11542
+ }
11543
+ ];
11544
+ }
11545
+ return [
11546
+ {
9161
11547
  key: "cancel",
9162
11548
  label: "\u53D6\u6D88",
9163
11549
  type: "default",
9164
- onClick: switchToReadonly
9165
- });
9166
- actions.push({
11550
+ onClick: switchToReadonly,
11551
+ placement: "left"
11552
+ },
11553
+ {
9167
11554
  key: "resubmit",
9168
11555
  label: "\u91CD\u65B0\u63D0\u4EA4",
9169
11556
  type: "primary",
9170
- onClick: handleResubmit
9171
- });
9172
- }
9173
- return actions;
11557
+ onClick: () => handleResubmit()
11558
+ }
11559
+ ];
9174
11560
  }
9175
11561
  if (canWithdraw) {
9176
- actions.push({
9177
- key: "withdraw",
9178
- label: "\u64A4\u9500",
9179
- type: "default",
9180
- onClick: () => handleWithdraw(),
9181
- confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u786E\u8BA4\u8981\u64A4\u9500\u6B64\u6D41\u7A0B\u5417\uFF1F" }
9182
- });
11562
+ return [
11563
+ {
11564
+ key: "withdraw",
11565
+ label: "\u64A4\u9500",
11566
+ type: "danger",
11567
+ onClick: () => handleWithdraw(),
11568
+ confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u64A4\u9500\u540E\u6D41\u7A0B\u5C06\u7EC8\u6B62\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F" }
11569
+ }
11570
+ ];
9183
11571
  }
9184
- return actions;
9185
- };
11572
+ return [];
11573
+ }, [
11574
+ activeActions.length,
11575
+ canWithdraw,
11576
+ handleResubmit,
11577
+ handleWithdraw,
11578
+ isApprover,
11579
+ isOriginatorReturn,
11580
+ mode,
11581
+ switchToEdit,
11582
+ switchToReadonly
11583
+ ]);
9186
11584
  const formConfig = {
9187
11585
  mode: mode === "edit" ? "edit" : "readonly",
9188
11586
  formUuid,
@@ -9194,50 +11592,68 @@ var InnerProcessContent = ({
9194
11592
  }
9195
11593
  };
9196
11594
  if (loading) {
9197
- return /* @__PURE__ */ jsx87("div", { className: "min-h-screen bg-gray-50/50", children: /* @__PURE__ */ jsx87("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24", children: /* @__PURE__ */ jsx87(PageSkeleton, { type: "process" }) }) });
11595
+ return /* @__PURE__ */ jsx93("div", { className: "min-h-screen bg-ant-bg-layout", children: /* @__PURE__ */ jsx93("div", { className: "mx-auto max-w-4xl px-6 py-8 pb-24", children: /* @__PURE__ */ jsx93(PageSkeleton, { type: "process" }) }) });
9198
11596
  }
9199
- const bottomActions = buildActions();
9200
11597
  const showApprovalActions = isApprover && activeActions.length > 0;
9201
- return /* @__PURE__ */ jsxs39("div", { className: "min-h-screen bg-gray-50/50", children: [
9202
- /* @__PURE__ */ jsx87("div", { className: "max-w-4xl mx-auto py-8 px-6 pb-24 space-y-6", children: /* @__PURE__ */ jsxs39("div", { className: "animate-[fadeIn_0.2s_ease-out]", children: [
9203
- header,
9204
- /* @__PURE__ */ jsx87(
9205
- FormSummaryCard,
9206
- {
9207
- title: schema.formMeta.title,
9208
- formInstanceId,
9209
- creator: processInfo?.originatorName ? {
9210
- name: processInfo.originatorName,
9211
- department: processInfo.originatorDepartment
9212
- } : void 0,
9213
- createdAt: processInfo?.createdAt,
9214
- status: processStatus ? PROCESS_STATUS_META[processStatus] : void 0
9215
- }
9216
- ),
9217
- beforeForm,
9218
- mode === "edit" && /* @__PURE__ */ jsx87("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" }),
9219
- /* @__PURE__ */ jsx87("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: /* @__PURE__ */ jsxs39(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
9220
- /* @__PURE__ */ jsx87(FormDataBridge, { formDataRef }),
9221
- /* @__PURE__ */ jsx87(FormRenderer, { columns: 2 })
9222
- ] }) }),
9223
- afterForm,
9224
- /* @__PURE__ */ jsxs39("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
9225
- /* @__PURE__ */ jsx87("h3", { className: "text-lg font-semibold text-gray-900 mb-4", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
9226
- renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ jsx87(ApprovalTimeline, { tasks: progressList, showRemarks: true })
9227
- ] })
9228
- ] }) }),
9229
- showApprovalActions && (renderActions ? /* @__PURE__ */ jsx87(Fragment7, { children: renderActions(activeActions) }) : /* @__PURE__ */ jsx87("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__ */ jsx87("div", { className: "max-w-4xl mx-auto flex items-center justify-end", children: /* @__PURE__ */ jsx87(
9230
- ApprovalActions,
11598
+ const actionsNode = showApprovalActions ? renderActions ? renderActions(activeActions) : /* @__PURE__ */ jsx93(
11599
+ ApprovalActionBar,
11600
+ {
11601
+ actions: activeActions,
11602
+ onApprove: handleApprove,
11603
+ onReject: handleReject,
11604
+ onTransfer: handleTransfer,
11605
+ onReturn: handleReturn,
11606
+ onWithdraw: handleWithdraw,
11607
+ onSave: handleSave,
11608
+ onResubmit: handleResubmit,
11609
+ onCallback: handleCallback,
11610
+ returnableNodes,
11611
+ onLoadReturnableNodes: loadReturnableNodes,
11612
+ renderTransferSelector,
11613
+ renderReturnNodeLabel,
11614
+ renderActionModalExtra,
11615
+ inDrawer
11616
+ }
11617
+ ) : bottomActions.length > 0 ? /* @__PURE__ */ jsx93(StickyActionBar, { actions: bottomActions, inDrawer }) : null;
11618
+ const statusMeta = processStatus ? PROCESS_STATUS_META[processStatus] : void 0;
11619
+ return /* @__PURE__ */ jsx93(RuntimePageShell, { actions: actionsNode, inDrawer, children: /* @__PURE__ */ jsxs45("div", { className: "space-y-6", children: [
11620
+ header,
11621
+ /* @__PURE__ */ jsx93(
11622
+ SummaryPanel,
9231
11623
  {
9232
- actions: activeActions,
9233
- onApprove: handleApprove,
9234
- onReject: handleReject,
9235
- onWithdraw: handleWithdraw,
9236
- onSave: handleSave
9237
- }
9238
- ) }) })),
9239
- !showApprovalActions && bottomActions.length > 0 && /* @__PURE__ */ jsx87(FormActionBar, { position: "bottom-fixed", actions: bottomActions })
9240
- ] });
11624
+ title: processInfo?.title || instanceInfo?.title || schema.formMeta.title,
11625
+ eyebrow: `\u6D41\u7A0B\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
11626
+ creator: processInfo?.originatorName ? {
11627
+ name: processInfo.originatorName,
11628
+ department: processInfo.originatorDepartment
11629
+ } : void 0,
11630
+ createdAt: processInfo?.createdAt,
11631
+ status: statusMeta,
11632
+ metaItems: [
11633
+ { key: "currentTask", label: "\u5F53\u524D\u8282\u70B9", value: currentTask?.nodeName || "\u65E0" },
11634
+ {
11635
+ key: "processStatus",
11636
+ label: "\u5B9E\u4F8B\u72B6\u6001",
11637
+ value: statusMeta?.label || processStatus || "-"
11638
+ }
11639
+ ]
11640
+ }
11641
+ ),
11642
+ beforeForm,
11643
+ mode === "edit" && /* @__PURE__ */ jsx93("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" }),
11644
+ /* @__PURE__ */ jsx93("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: /* @__PURE__ */ jsxs45(FormProvider, { schema, config: formConfig, initialValues: formData ?? void 0, children: [
11645
+ /* @__PURE__ */ jsx93(FormDataBridge2, { formDataRef }),
11646
+ /* @__PURE__ */ jsx93(FormRenderer, { columns: 2 })
11647
+ ] }) }),
11648
+ afterForm,
11649
+ /* @__PURE__ */ jsxs45("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: [
11650
+ /* @__PURE__ */ jsx93("div", { className: "mb-4 flex items-center justify-between gap-3", children: /* @__PURE__ */ jsxs45("div", { children: [
11651
+ /* @__PURE__ */ jsx93("h3", { className: "text-base font-semibold text-ant-color-text", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
11652
+ /* @__PURE__ */ jsx93("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" })
11653
+ ] }) }),
11654
+ renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ jsx93(ApprovalTimeline, { tasks: progressList, showRemarks: true, showApproverInfo: true })
11655
+ ] })
11656
+ ] }) });
9241
11657
  };
9242
11658
  var ProcessDetailTemplate = (props) => {
9243
11659
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -9247,10 +11663,11 @@ var ProcessDetailTemplate = (props) => {
9247
11663
  appType,
9248
11664
  formInstanceId
9249
11665
  };
9250
- return /* @__PURE__ */ jsx87(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ jsx87(InnerProcessContent, { ...props }) });
11666
+ return /* @__PURE__ */ jsx93(FormProvider, { schema, config: wrapperConfig, children: /* @__PURE__ */ jsx93(InnerProcessContent, { ...props }) });
9251
11667
  };
9252
11668
  export {
9253
11669
  AddressField,
11670
+ ApprovalActionBar,
9254
11671
  ApprovalActions,
9255
11672
  ApprovalTimeline,
9256
11673
  AssociationFormField,
@@ -9261,6 +11678,7 @@ export {
9261
11678
  CheckboxField,
9262
11679
  ComponentRegistryContext,
9263
11680
  ComponentRegistryProvider,
11681
+ DataManagementList,
9264
11682
  DateField,
9265
11683
  DepartmentSelectField,
9266
11684
  DigitalSignatureField,
@@ -9292,34 +11710,58 @@ export {
9292
11710
  ProcessDetailTemplate,
9293
11711
  ProcessPreview,
9294
11712
  RadioField,
11713
+ RecordChangePanel,
11714
+ RuntimePageShell,
9295
11715
  SelectField,
9296
11716
  SerialNumberField,
11717
+ StickyActionBar,
9297
11718
  SubFormField,
11719
+ SummaryPanel,
9298
11720
  TASK_STATUS_META,
9299
11721
  TextAreaField,
9300
11722
  TextField,
9301
11723
  TextAreaField as TextareaField,
9302
11724
  UserSelectField,
11725
+ advancedSearchDataManagement,
11726
+ batchApproveDataManagementRows,
11727
+ buildFilterPayload,
9303
11728
  checkUserApproval,
9304
11729
  createFormRuntimeApi,
9305
11730
  defaultComponentRegistry,
9306
11731
  defineFormSchema,
11732
+ deleteDataManagementRows,
9307
11733
  deleteFormData,
9308
11734
  evaluateEffects,
11735
+ exportDataManagementRows,
9309
11736
  extractFormValues,
9310
11737
  getChangeRecords,
11738
+ getDataManagementConfig,
11739
+ getDataManagementSchema,
11740
+ getDataManagementTransferRecords,
9311
11741
  getFormData,
9312
11742
  getProcessBasic,
9313
11743
  getProcessDefinition,
9314
11744
  getProcessProgress,
9315
11745
  getReturnableNodes,
11746
+ getSystemFieldsForFormType,
9316
11747
  getViewPermission,
9317
11748
  handleApproval,
11749
+ hasViewOperation,
11750
+ hasViewPermission,
11751
+ importDataManagementRows,
11752
+ importPreviewDataManagementRows,
11753
+ normalizeColumnConfig,
11754
+ normalizeDataManagementFields,
11755
+ normalizeDataManagementList,
11756
+ normalizeFieldBehaviors,
11757
+ normalizeOperation,
9318
11758
  previewProcess,
9319
11759
  resubmitTask,
9320
11760
  returnTask,
11761
+ saveDataManagementConfig,
9321
11762
  saveTask,
9322
11763
  transferTask,
11764
+ triggerCallbackTask,
9323
11765
  useApprovalActions,
9324
11766
  useChangeRecords,
9325
11767
  useComponent,