sy-form-components 0.2.13 → 0.2.15

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
@@ -1,5 +1,5 @@
1
1
  // src/core/FormProvider.tsx
2
- import React34, { useCallback as useCallback5, useRef as useRef6, useState as useState16, useMemo as useMemo9 } from "react";
2
+ import React36, { useCallback as useCallback5, useRef as useRef6, useState as useState16, useMemo as useMemo9 } from "react";
3
3
 
4
4
  // src/core/FormContext.ts
5
5
  import { createContext, useContext } from "react";
@@ -1356,6 +1356,7 @@ function CascadeDateField(props) {
1356
1356
  import { useEffect as useEffect10 } from "react";
1357
1357
 
1358
1358
  // src/fields/AttachmentField/AttachmentFieldPC.tsx
1359
+ import React14 from "react";
1359
1360
  import { Upload, Button } from "antd";
1360
1361
 
1361
1362
  // src/fields/shared/fieldFormat.ts
@@ -1462,6 +1463,31 @@ function normalizeAttachmentItem(item, fallback) {
1462
1463
  extension: item?.extension || fallback?.extension || getFileExtension(name)
1463
1464
  };
1464
1465
  }
1466
+ function getAttachmentItemIdentity(item) {
1467
+ return String(item?.uid || item?.id || item?.objectName || item?.url || item?.name || "");
1468
+ }
1469
+ function dedupeAttachmentItems(items) {
1470
+ const result = [];
1471
+ const indexes = /* @__PURE__ */ new Map();
1472
+ for (const item of items) {
1473
+ const key = getAttachmentItemIdentity(item);
1474
+ if (!key) {
1475
+ result.push(item);
1476
+ continue;
1477
+ }
1478
+ const existingIndex = indexes.get(key);
1479
+ if (existingIndex === void 0) {
1480
+ indexes.set(key, result.length);
1481
+ result.push(item);
1482
+ continue;
1483
+ }
1484
+ result[existingIndex] = {
1485
+ ...result[existingIndex],
1486
+ ...item
1487
+ };
1488
+ }
1489
+ return result;
1490
+ }
1465
1491
 
1466
1492
  // src/fields/AttachmentField/AttachmentFieldPC.tsx
1467
1493
  import { jsx as jsx38, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -1516,38 +1542,47 @@ function AttachmentFieldPC({
1516
1542
  onChange
1517
1543
  }) {
1518
1544
  const { formData, setFieldValue, api } = useFormContext();
1519
- const value = formData[fieldId] ?? [];
1545
+ const value = React14.useMemo(
1546
+ () => dedupeAttachmentItems(
1547
+ Array.isArray(formData[fieldId]) ? formData[fieldId] : []
1548
+ ),
1549
+ [fieldId, formData]
1550
+ );
1551
+ const valueRef = React14.useRef(value);
1520
1552
  const disabled = behavior === "DISABLED";
1553
+ React14.useEffect(() => {
1554
+ valueRef.current = value;
1555
+ }, [value]);
1521
1556
  const setValue = (items) => {
1522
- setFieldValue(fieldId, items);
1523
- onChange?.(items);
1524
- };
1525
- const handleChange = (info) => {
1526
- const fileList2 = info.fileList ?? [];
1527
- const items = fileList2.map((f) => {
1528
- if (f.uid === void 0 && f.name === void 0 && f.url === void 0 && !f.response) {
1529
- return { url: "", name: "", id: "" };
1530
- }
1531
- return normalizeAttachmentItem({
1532
- url: f.url ?? f.response?.url ?? "",
1533
- name: f.name,
1534
- id: f.uid ?? f.response?.id,
1535
- uid: f.uid ?? f.response?.uid,
1536
- status: f.status,
1537
- percent: f.percent,
1538
- objectName: f.objectName ?? f.response?.objectName,
1539
- bucketName: f.bucketName ?? f.response?.bucketName,
1540
- size: f.size ?? f.response?.size,
1541
- contentType: f.type ?? f.response?.contentType,
1542
- downloadUrl: f.downloadUrl ?? f.response?.downloadUrl,
1543
- previewUrl: f.previewUrl ?? f.response?.previewUrl
1544
- });
1557
+ const nextItems = dedupeAttachmentItems(items).slice(0, maxCount ?? Infinity);
1558
+ valueRef.current = nextItems;
1559
+ setFieldValue(fieldId, nextItems);
1560
+ onChange?.(nextItems);
1561
+ };
1562
+ const replaceItem = (target, nextItem) => {
1563
+ const targetKeys = new Set(
1564
+ [target.id, target.uid, target.objectName, getAttachmentItemIdentity(target)].filter(Boolean)
1565
+ );
1566
+ let replaced = false;
1567
+ const nextItems = valueRef.current.map((item) => {
1568
+ const currentKeys = [item.id, item.uid, item.objectName, getAttachmentItemIdentity(item)];
1569
+ if (currentKeys.some((key) => key && targetKeys.has(key))) {
1570
+ replaced = true;
1571
+ return nextItem;
1572
+ }
1573
+ return item;
1545
1574
  });
1546
- setValue(items);
1575
+ if (!replaced) nextItems.push(nextItem);
1576
+ setValue(nextItems);
1547
1577
  };
1548
1578
  const handleRemove = (file) => {
1549
- const removed = value.find((item) => item.id === file.uid || item.uid === file.uid);
1550
- const newValue = value.filter((item) => item.id !== file.uid && item.uid !== file.uid);
1579
+ const fileKey = String(file.uid || file.id || file.objectName || "");
1580
+ const removed = valueRef.current.find(
1581
+ (item) => item.id === fileKey || item.uid === fileKey || item.objectName === fileKey
1582
+ );
1583
+ const newValue = valueRef.current.filter(
1584
+ (item) => item.id !== fileKey && item.uid !== fileKey && item.objectName !== fileKey
1585
+ );
1551
1586
  setValue(newValue);
1552
1587
  if (removed?.objectName) {
1553
1588
  api.deleteFile(removed.objectName, removed.bucketName || bucketName).catch(() => void 0);
@@ -1588,7 +1623,9 @@ function AttachmentFieldPC({
1588
1623
  return url;
1589
1624
  };
1590
1625
  const handlePreview = async (file) => {
1591
- const item = value.find((current) => current.id === file.uid || current.uid === file.uid);
1626
+ const item = valueRef.current.find(
1627
+ (current) => current.id === file.uid || current.uid === file.uid || current.objectName === file.uid
1628
+ );
1592
1629
  const url = item ? await resolvePreviewUrl(item) : file.url;
1593
1630
  if (url) window.open(url, "_blank", "noopener,noreferrer");
1594
1631
  };
@@ -1596,14 +1633,10 @@ function AttachmentFieldPC({
1596
1633
  const url = await resolveDownloadUrl(item);
1597
1634
  if (url) window.open(url, "_blank", "noopener,noreferrer");
1598
1635
  };
1599
- const fileList = value.map((item) => ({
1600
- uid: item.id,
1601
- name: item.name,
1602
- url: item.url,
1603
- status: item.status ?? "done",
1604
- percent: item.percent
1605
- }));
1606
1636
  const beforeUpload = (file) => {
1637
+ if (maxCount && valueRef.current.length >= maxCount) {
1638
+ return false;
1639
+ }
1607
1640
  if (maxSize && file.size / 1024 / 1024 > maxSize) {
1608
1641
  return false;
1609
1642
  }
@@ -1616,27 +1649,26 @@ function AttachmentFieldPC({
1616
1649
  const customRequest = async ({ file, onProgress, onSuccess, onError }) => {
1617
1650
  const currentFile = file;
1618
1651
  const localItem = createLocalItem(currentFile);
1619
- const nextValue = multiple ? [...value, localItem].slice(0, maxCount ?? Infinity) : [localItem];
1652
+ const currentValue = valueRef.current.filter(
1653
+ (item) => item.id !== localItem.id && item.uid !== localItem.uid
1654
+ );
1655
+ const nextValue = multiple ? [...currentValue, localItem] : [localItem];
1620
1656
  setValue(nextValue);
1621
1657
  try {
1622
1658
  const uploaded = await api.uploadFile(currentFile, bucketName, (percent) => {
1623
1659
  onProgress?.({ percent });
1624
- setValue(
1625
- nextValue.map(
1626
- (item) => item.id === localItem.id ? { ...item, percent, status: "uploading" } : item
1627
- )
1628
- );
1660
+ replaceItem(localItem, { ...localItem, percent, status: "uploading" });
1629
1661
  });
1630
- const completed = normalizeAttachmentItem({
1631
- ...uploaded,
1632
- id: uploaded.id || localItem.id,
1633
- uid: uploaded.uid || localItem.uid,
1634
- url: uploaded.url || localItem.url,
1635
- status: "done",
1636
- percent: 100,
1637
- extension: uploaded.extension || getFileExtension(uploaded.name || localItem.name)
1638
- });
1639
- setValue(nextValue.map((item) => item.id === localItem.id ? completed : item));
1662
+ const completed = normalizeAttachmentItem(
1663
+ {
1664
+ ...uploaded,
1665
+ status: "done",
1666
+ percent: 100,
1667
+ extension: uploaded.extension || getFileExtension(uploaded.name || localItem.name)
1668
+ },
1669
+ localItem
1670
+ );
1671
+ replaceItem(localItem, completed);
1640
1672
  onSuccess?.(completed);
1641
1673
  } catch (error) {
1642
1674
  const failed = {
@@ -1644,7 +1676,7 @@ function AttachmentFieldPC({
1644
1676
  status: "error",
1645
1677
  error: error?.message || "\u4E0A\u4F20\u5931\u8D25"
1646
1678
  };
1647
- setValue(nextValue.map((item) => item.id === localItem.id ? failed : item));
1679
+ replaceItem(localItem, failed);
1648
1680
  onError?.(error);
1649
1681
  }
1650
1682
  };
@@ -1653,61 +1685,71 @@ function AttachmentFieldPC({
1653
1685
  Upload,
1654
1686
  {
1655
1687
  "data-testid": `attachmentfield-input-${fieldId}`,
1656
- fileList,
1688
+ fileList: [],
1657
1689
  customRequest,
1658
1690
  accept,
1659
1691
  maxCount,
1660
1692
  multiple,
1661
1693
  disabled,
1662
- onChange: handleChange,
1694
+ showUploadList: false,
1663
1695
  onRemove: handleRemove,
1664
1696
  onPreview: handlePreview,
1665
1697
  beforeUpload,
1666
1698
  children: /* @__PURE__ */ jsx38(Button, { disabled, "data-testid": `attachmentfield-upload-btn-${fieldId}`, children: "\u4E0A\u4F20\u6587\u4EF6" })
1667
1699
  }
1668
1700
  ),
1669
- value.length > 0 && /* @__PURE__ */ jsx38("div", { className: "sy-file-list", "data-testid": `attachmentfield-rich-list-${fieldId}`, children: value.map((item) => {
1701
+ value.length > 0 && /* @__PURE__ */ jsx38("div", { className: "sy-file-list", "data-testid": `attachmentfield-rich-list-${fieldId}`, children: value.map((item, index) => {
1670
1702
  const category = getFileCategory(item.name, item.contentType);
1671
1703
  const extension = getFileExtension(item.name);
1672
- return /* @__PURE__ */ jsxs5("div", { className: "sy-file-item", children: [
1673
- /* @__PURE__ */ jsx38("span", { className: `sy-file-icon sy-file-icon-${category}`, "aria-hidden": "true", children: category === "image" ? "IMG" : extension || "FILE" }),
1674
- /* @__PURE__ */ jsxs5("div", { className: "sy-file-meta", children: [
1675
- /* @__PURE__ */ jsx38("span", { className: "sy-file-name", title: item.name, children: item.name }),
1676
- /* @__PURE__ */ jsx38("span", { className: "sy-file-sub", children: item.status === "uploading" ? `\u4E0A\u4F20\u4E2D ${Math.round(item.percent ?? 0)}%` : item.status === "error" ? item.error || "\u4E0A\u4F20\u5931\u8D25" : [
1677
- showFileTypeBadge && extension ? extension.toUpperCase() : "",
1678
- showFileSize ? formatFileSize(item.size) : ""
1679
- ].filter(Boolean).join(" \xB7 ") || "\u5DF2\u4E0A\u4F20" })
1680
- ] }),
1681
- /* @__PURE__ */ jsxs5("div", { className: "sy-file-actions", children: [
1682
- showPreview && canPreview(item) && /* @__PURE__ */ jsx38(
1683
- "button",
1684
- {
1685
- type: "button",
1686
- disabled: item.status !== "done",
1687
- onClick: () => handlePreview({ uid: item.uid || item.id, url: item.url }),
1688
- children: "\u9884\u89C8"
1689
- }
1690
- ),
1691
- showDownload && /* @__PURE__ */ jsx38(
1692
- "button",
1693
- {
1694
- type: "button",
1695
- disabled: item.status !== "done",
1696
- onClick: () => handleDownload(item),
1697
- children: "\u4E0B\u8F7D"
1698
- }
1699
- ),
1700
- /* @__PURE__ */ jsx38(
1701
- "button",
1702
- {
1703
- type: "button",
1704
- disabled,
1705
- onClick: () => handleRemove({ uid: item.uid || item.id }),
1706
- children: "\u5220\u9664"
1707
- }
1708
- )
1709
- ] })
1710
- ] }, item.id || item.uid || item.name);
1704
+ const itemKey = getAttachmentItemIdentity(item) || `${fieldId}-attachment-${String(index)}`;
1705
+ return /* @__PURE__ */ jsxs5(
1706
+ "div",
1707
+ {
1708
+ className: "sy-file-item",
1709
+ "data-testid": `attachmentfield-item-${itemKey}`,
1710
+ children: [
1711
+ /* @__PURE__ */ jsx38("span", { className: `sy-file-icon sy-file-icon-${category}`, "aria-hidden": "true", children: category === "image" ? "IMG" : extension || "FILE" }),
1712
+ /* @__PURE__ */ jsxs5("div", { className: "sy-file-meta", children: [
1713
+ /* @__PURE__ */ jsx38("span", { className: "sy-file-name", title: item.name, children: item.name }),
1714
+ /* @__PURE__ */ jsx38("span", { className: "sy-file-sub", children: item.status === "uploading" ? `\u4E0A\u4F20\u4E2D ${Math.round(item.percent ?? 0)}%` : item.status === "error" ? item.error || "\u4E0A\u4F20\u5931\u8D25" : [
1715
+ showFileTypeBadge && extension ? extension.toUpperCase() : "",
1716
+ showFileSize ? formatFileSize(item.size) : ""
1717
+ ].filter(Boolean).join(" \xB7 ") || "\u5DF2\u4E0A\u4F20" })
1718
+ ] }),
1719
+ /* @__PURE__ */ jsxs5("div", { className: "sy-file-actions", children: [
1720
+ showPreview && canPreview(item) && /* @__PURE__ */ jsx38(
1721
+ "button",
1722
+ {
1723
+ type: "button",
1724
+ disabled: item.status !== "done",
1725
+ onClick: () => handlePreview({ uid: item.uid || item.id, url: item.url }),
1726
+ children: "\u9884\u89C8"
1727
+ }
1728
+ ),
1729
+ showDownload && /* @__PURE__ */ jsx38(
1730
+ "button",
1731
+ {
1732
+ type: "button",
1733
+ disabled: item.status !== "done",
1734
+ onClick: () => handleDownload(item),
1735
+ children: "\u4E0B\u8F7D"
1736
+ }
1737
+ ),
1738
+ /* @__PURE__ */ jsx38(
1739
+ "button",
1740
+ {
1741
+ type: "button",
1742
+ disabled,
1743
+ onClick: () => handleRemove({ uid: item.uid || item.id }),
1744
+ "data-testid": `attachmentfield-remove-${itemKey}`,
1745
+ children: "\u5220\u9664"
1746
+ }
1747
+ )
1748
+ ] })
1749
+ ]
1750
+ },
1751
+ `${itemKey}-${index}`
1752
+ );
1711
1753
  }) })
1712
1754
  ] });
1713
1755
  }
@@ -1888,8 +1930,9 @@ function AttachmentField(props) {
1888
1930
  import { useEffect as useEffect11 } from "react";
1889
1931
 
1890
1932
  // src/fields/ImageField/ImageFieldPC.tsx
1933
+ import React16 from "react";
1891
1934
  import { Upload as Upload2 } from "antd";
1892
- import { jsx as jsx42, jsxs as jsxs7 } from "react/jsx-runtime";
1935
+ import { Fragment, jsx as jsx42, jsxs as jsxs7 } from "react/jsx-runtime";
1893
1936
  var createLocalItem2 = (file) => {
1894
1937
  const uid = file.uid || createUid("image");
1895
1938
  return {
@@ -1905,6 +1948,23 @@ var createLocalItem2 = (file) => {
1905
1948
  extension: getFileExtension(file.name)
1906
1949
  };
1907
1950
  };
1951
+ function ImageThumbContent({ item }) {
1952
+ const [imageFailed, setImageFailed] = React16.useState(false);
1953
+ const src = item.previewUrl || item.url;
1954
+ React16.useEffect(() => {
1955
+ setImageFailed(false);
1956
+ }, [src]);
1957
+ if (src && !imageFailed) {
1958
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
1959
+ /* @__PURE__ */ jsx42("img", { src, alt: item.name, onError: () => setImageFailed(true) }),
1960
+ item.status === "uploading" && /* @__PURE__ */ jsxs7("span", { className: "sy-image-state", children: [
1961
+ Math.round(item.percent ?? 0),
1962
+ "%"
1963
+ ] })
1964
+ ] });
1965
+ }
1966
+ return /* @__PURE__ */ jsx42("span", { className: "sy-image-state", children: item.status === "uploading" ? `${Math.round(item.percent ?? 0)}%` : item.status === "error" ? item.error || "\u4E0A\u4F20\u5931\u8D25" : item.name || "\u56FE\u7247" });
1967
+ }
1908
1968
  function ImageFieldPC({
1909
1969
  fieldId,
1910
1970
  behavior,
@@ -1920,44 +1980,56 @@ function ImageFieldPC({
1920
1980
  onChange
1921
1981
  }) {
1922
1982
  const { formData, setFieldValue, api } = useFormContext();
1923
- const value = formData[fieldId] ?? [];
1983
+ const value = React16.useMemo(
1984
+ () => dedupeAttachmentItems(
1985
+ Array.isArray(formData[fieldId]) ? formData[fieldId] : []
1986
+ ),
1987
+ [fieldId, formData]
1988
+ );
1989
+ const valueRef = React16.useRef(value);
1924
1990
  const disabled = behavior === "DISABLED";
1991
+ React16.useEffect(() => {
1992
+ valueRef.current = value;
1993
+ }, [value]);
1925
1994
  const setValue = (items) => {
1926
- setFieldValue(fieldId, items);
1927
- onChange?.(items);
1928
- };
1929
- const handleChange = (info) => {
1930
- const fileList2 = info.fileList ?? [];
1931
- const items = fileList2.map((f) => {
1932
- if (f.uid === void 0 && f.name === void 0 && f.url === void 0 && f.thumbUrl === void 0 && !f.response) {
1933
- return { url: "", name: "", id: "" };
1934
- }
1935
- return normalizeAttachmentItem({
1936
- url: f.url ?? f.thumbUrl ?? f.response?.url ?? "",
1937
- previewUrl: f.previewUrl ?? f.thumbUrl ?? f.response?.previewUrl,
1938
- name: f.name,
1939
- id: f.uid ?? f.response?.id,
1940
- uid: f.uid ?? f.response?.uid,
1941
- status: f.status,
1942
- percent: f.percent,
1943
- objectName: f.objectName ?? f.response?.objectName,
1944
- bucketName: f.bucketName ?? f.response?.bucketName,
1945
- size: f.size ?? f.response?.size,
1946
- contentType: f.type ?? f.response?.contentType
1947
- });
1995
+ const nextItems = dedupeAttachmentItems(items).slice(0, maxCount ?? Infinity);
1996
+ valueRef.current = nextItems;
1997
+ setFieldValue(fieldId, nextItems);
1998
+ onChange?.(nextItems);
1999
+ };
2000
+ const replaceItem = (target, nextItem) => {
2001
+ const targetKeys = new Set(
2002
+ [target.id, target.uid, target.objectName, getAttachmentItemIdentity(target)].filter(Boolean)
2003
+ );
2004
+ let replaced = false;
2005
+ const nextItems = valueRef.current.map((item) => {
2006
+ const currentKeys = [item.id, item.uid, item.objectName, getAttachmentItemIdentity(item)];
2007
+ if (currentKeys.some((key) => key && targetKeys.has(key))) {
2008
+ replaced = true;
2009
+ return nextItem;
2010
+ }
2011
+ return item;
1948
2012
  });
1949
- setValue(items);
2013
+ if (!replaced) nextItems.push(nextItem);
2014
+ setValue(nextItems);
1950
2015
  };
1951
2016
  const handleRemove = (file) => {
1952
- const removed = value.find((item) => item.id === file.uid || item.uid === file.uid);
1953
- const newValue = value.filter((item) => item.id !== file.uid && item.uid !== file.uid);
2017
+ const fileKey = String(file.uid || file.id || file.objectName || "");
2018
+ const removed = valueRef.current.find(
2019
+ (item) => item.id === fileKey || item.uid === fileKey || item.objectName === fileKey
2020
+ );
2021
+ const newValue = valueRef.current.filter(
2022
+ (item) => item.id !== fileKey && item.uid !== fileKey && item.objectName !== fileKey
2023
+ );
1954
2024
  setValue(newValue);
1955
2025
  if (removed?.objectName) {
1956
2026
  api.deleteFile(removed.objectName, removed.bucketName || bucketName).catch(() => void 0);
1957
2027
  }
1958
2028
  };
1959
2029
  const handlePreview = async (file) => {
1960
- const item = value.find((current) => current.id === file.uid || current.uid === file.uid);
2030
+ const item = valueRef.current.find(
2031
+ (current) => current.id === file.uid || current.uid === file.uid || current.objectName === file.uid
2032
+ );
1961
2033
  let url = item?.previewUrl || item?.url || file.url || file.thumbUrl;
1962
2034
  if (item?.objectName) {
1963
2035
  const ticket = await api.createFileAccessTicket(
@@ -1970,15 +2042,22 @@ function ImageFieldPC({
1970
2042
  }
1971
2043
  if (url) window.open(url, "_blank", "noopener,noreferrer");
1972
2044
  };
1973
- const fileList = value.map((item) => ({
1974
- uid: item.id,
1975
- name: item.name,
1976
- url: item.url,
1977
- thumbUrl: item.url,
1978
- status: item.status ?? "done",
1979
- percent: item.percent
1980
- }));
2045
+ const handleDownload = async (item) => {
2046
+ let url = item.downloadUrl || item.url;
2047
+ if (item.objectName) {
2048
+ const ticket = await api.createDownloadTicket(
2049
+ item.bucketName || bucketName,
2050
+ item.objectName,
2051
+ item.name
2052
+ );
2053
+ url = typeof ticket === "string" ? ticket : ticket?.downloadUrl || ticket?.relayUrl || ticket?.url || url;
2054
+ }
2055
+ if (url) window.open(url, "_blank", "noopener,noreferrer");
2056
+ };
1981
2057
  const beforeUpload = (file) => {
2058
+ if (maxCount && valueRef.current.length >= maxCount) {
2059
+ return false;
2060
+ }
1982
2061
  if (!String(file.type || "").startsWith("image/") && !/\.(png|jpe?g|gif|bmp|svg|webp)$/i.test(file.name)) {
1983
2062
  return false;
1984
2063
  }
@@ -1990,26 +2069,27 @@ function ImageFieldPC({
1990
2069
  const customRequest = async ({ file, onProgress, onSuccess, onError }) => {
1991
2070
  const currentFile = file;
1992
2071
  const localItem = createLocalItem2(currentFile);
1993
- const nextValue = multiple ? [...value, localItem].slice(0, maxCount ?? Infinity) : [localItem];
2072
+ const currentValue = valueRef.current.filter(
2073
+ (item) => item.id !== localItem.id && item.uid !== localItem.uid
2074
+ );
2075
+ const nextValue = multiple ? [...currentValue, localItem] : [localItem];
1994
2076
  setValue(nextValue);
1995
2077
  try {
1996
2078
  const uploaded = await api.uploadFile(currentFile, bucketName, (percent) => {
1997
2079
  onProgress?.({ percent });
1998
- setValue(
1999
- nextValue.map(
2000
- (item) => item.id === localItem.id ? { ...item, percent, status: "uploading" } : item
2001
- )
2002
- );
2003
- });
2004
- const completed = normalizeAttachmentItem({
2005
- ...uploaded,
2006
- id: uploaded.id || localItem.id,
2007
- uid: uploaded.uid || localItem.uid,
2008
- url: uploaded.previewUrl || uploaded.url || localItem.url,
2009
- status: "done",
2010
- percent: 100
2080
+ replaceItem(localItem, { ...localItem, percent, status: "uploading" });
2011
2081
  });
2012
- setValue(nextValue.map((item) => item.id === localItem.id ? completed : item));
2082
+ const completed = normalizeAttachmentItem(
2083
+ {
2084
+ ...uploaded,
2085
+ url: uploaded.previewUrl || uploaded.url || localItem.url,
2086
+ previewUrl: uploaded.previewUrl || uploaded.url || localItem.url,
2087
+ status: "done",
2088
+ percent: 100
2089
+ },
2090
+ localItem
2091
+ );
2092
+ replaceItem(localItem, completed);
2013
2093
  onSuccess?.(completed);
2014
2094
  } catch (error) {
2015
2095
  const failed = {
@@ -2017,7 +2097,7 @@ function ImageFieldPC({
2017
2097
  status: "error",
2018
2098
  error: error?.message || "\u4E0A\u4F20\u5931\u8D25"
2019
2099
  };
2020
- setValue(nextValue.map((item) => item.id === localItem.id ? failed : item));
2100
+ replaceItem(localItem, failed);
2021
2101
  onError?.(error);
2022
2102
  }
2023
2103
  };
@@ -2027,42 +2107,74 @@ function ImageFieldPC({
2027
2107
  {
2028
2108
  "data-testid": `imagefield-input-${fieldId}`,
2029
2109
  listType,
2030
- fileList,
2110
+ fileList: [],
2031
2111
  customRequest,
2032
2112
  accept: accept ?? "image/*",
2033
2113
  maxCount,
2034
2114
  multiple,
2035
2115
  disabled,
2036
- showUploadList: {
2037
- showPreviewIcon,
2038
- showRemoveIcon,
2039
- showDownloadIcon
2040
- },
2041
- onChange: handleChange,
2116
+ showUploadList: false,
2042
2117
  onRemove: handleRemove,
2043
2118
  onPreview: handlePreview,
2044
2119
  beforeUpload,
2045
2120
  children: (!maxCount || value.length < maxCount) && /* @__PURE__ */ jsx42("div", { "data-testid": `imagefield-upload-btn-${fieldId}`, children: "+ \u4E0A\u4F20\u56FE\u7247" })
2046
2121
  }
2047
2122
  ),
2048
- value.length > 0 && /* @__PURE__ */ jsx42("div", { className: "sy-image-grid", "data-testid": `imagefield-rich-grid-${fieldId}`, children: value.map((item) => /* @__PURE__ */ jsx42(
2049
- "button",
2050
- {
2051
- type: "button",
2052
- className: "sy-image-thumb",
2053
- disabled: item.status !== "done",
2054
- onClick: () => handlePreview({
2055
- uid: item.uid || item.id,
2056
- url: item.url,
2057
- thumbUrl: item.previewUrl
2058
- }),
2059
- children: item.url || item.previewUrl ? /* @__PURE__ */ jsx42("img", { src: item.previewUrl || item.url, alt: item.name }) : /* @__PURE__ */ jsxs7("span", { children: [
2060
- Math.round(item.percent ?? 0),
2061
- "%"
2062
- ] })
2063
- },
2064
- item.id || item.uid || item.name
2065
- )) })
2123
+ value.length > 0 && /* @__PURE__ */ jsx42("div", { className: "sy-image-grid", "data-testid": `imagefield-rich-grid-${fieldId}`, children: value.map((item, index) => {
2124
+ const itemKey = getAttachmentItemIdentity(item) || `${fieldId}-image-${String(index)}`;
2125
+ const canAct = item.status === "done";
2126
+ return /* @__PURE__ */ jsxs7(
2127
+ "div",
2128
+ {
2129
+ className: "sy-image-thumb",
2130
+ "data-testid": `imagefield-thumb-${itemKey}`,
2131
+ children: [
2132
+ /* @__PURE__ */ jsx42(
2133
+ "button",
2134
+ {
2135
+ type: "button",
2136
+ className: "sy-image-preview",
2137
+ disabled: !canAct && !(item.previewUrl || item.url),
2138
+ onClick: () => handlePreview({
2139
+ uid: item.uid || item.id,
2140
+ url: item.url,
2141
+ thumbUrl: item.previewUrl
2142
+ }),
2143
+ children: /* @__PURE__ */ jsx42(ImageThumbContent, { item })
2144
+ }
2145
+ ),
2146
+ /* @__PURE__ */ jsxs7("div", { className: "sy-image-actions", children: [
2147
+ showPreviewIcon && /* @__PURE__ */ jsx42(
2148
+ "button",
2149
+ {
2150
+ type: "button",
2151
+ disabled: !canAct,
2152
+ onClick: () => handlePreview({
2153
+ uid: item.uid || item.id,
2154
+ url: item.url,
2155
+ thumbUrl: item.previewUrl
2156
+ }),
2157
+ children: "\u9884\u89C8"
2158
+ }
2159
+ ),
2160
+ showDownloadIcon && /* @__PURE__ */ jsx42("button", { type: "button", disabled: !canAct, onClick: () => handleDownload(item), children: "\u4E0B\u8F7D" }),
2161
+ showRemoveIcon && /* @__PURE__ */ jsx42(
2162
+ "button",
2163
+ {
2164
+ type: "button",
2165
+ disabled,
2166
+ onClick: () => handleRemove({ uid: item.uid || item.id }),
2167
+ "data-testid": `remove-btn-${itemKey}`,
2168
+ children: "\u5220\u9664"
2169
+ }
2170
+ )
2171
+ ] }),
2172
+ canAct && item.size ? /* @__PURE__ */ jsx42("span", { className: "sy-image-meta", children: formatFileSize(item.size) }) : null
2173
+ ]
2174
+ },
2175
+ `${itemKey}-${index}`
2176
+ );
2177
+ }) })
2066
2178
  ] });
2067
2179
  }
2068
2180
 
@@ -6346,15 +6458,15 @@ function FormProvider({
6346
6458
  ]
6347
6459
  );
6348
6460
  const registryComponents = components ?? defaultComponentRegistry;
6349
- return React34.createElement(
6461
+ return React36.createElement(
6350
6462
  FormContext.Provider,
6351
6463
  { value: contextValue },
6352
- React34.createElement(ComponentRegistryProvider, { components: registryComponents, children })
6464
+ React36.createElement(ComponentRegistryProvider, { components: registryComponents, children })
6353
6465
  );
6354
6466
  }
6355
6467
 
6356
6468
  // src/core/FormRenderer.tsx
6357
- import React35 from "react";
6469
+ import React37 from "react";
6358
6470
  import { jsx as jsx69 } from "react/jsx-runtime";
6359
6471
  var columnsClassMap = {
6360
6472
  1: "sy-grid-cols-1",
@@ -6378,7 +6490,7 @@ function FieldRenderer({ field, fieldClassName }) {
6378
6490
  return null;
6379
6491
  }
6380
6492
  const { fieldId, componentName: _, ...fieldProps } = field;
6381
- return React35.createElement(Component, {
6493
+ return React37.createElement(Component, {
6382
6494
  ...fieldProps,
6383
6495
  fieldId,
6384
6496
  className: fieldClassName ?? fieldProps.className
@@ -6563,12 +6675,13 @@ var normalizeProcessBasic = (value) => {
6563
6675
  processStatus: raw.processStatus ?? raw.status ?? instance.processStatus ?? instance.status,
6564
6676
  formUuid: raw.formUuid ?? instance.formUuid ?? instance.definition?.formUuid,
6565
6677
  appType: raw.appType ?? instance.appType ?? instance.definition?.appType,
6566
- title: raw.title ?? instance.title,
6678
+ title: raw.title ?? instance.title ?? instance.instanceTitle,
6567
6679
  originatorId: raw.originatorId ?? instance.originatorId ?? instance.startedBy,
6568
6680
  originatorName: raw.originatorName ?? instance.originatorName ?? instance.startedByName,
6569
6681
  originatorDepartment: raw.originatorDepartment ?? instance.originatorDepartment ?? instance.startedDepartmentName,
6570
6682
  createdAt: raw.createdAt ?? instance.createdAt ?? instance.startedAt,
6571
- currentTask
6683
+ currentTask,
6684
+ isExecuting: raw.isExecuting ?? instance.isExecuting
6572
6685
  };
6573
6686
  };
6574
6687
  var normalizeApprovalPermission = (value) => {
@@ -6592,6 +6705,13 @@ var normalizeReturnableNodes = (value) => {
6592
6705
  nodeName: node?.nodeName || node?.name || node?.title || node?.id || ""
6593
6706
  }));
6594
6707
  };
6708
+ var normalizeReturnableNodeResult = (value) => {
6709
+ const raw = value?.data || value || {};
6710
+ return {
6711
+ nodes: normalizeReturnableNodes(raw),
6712
+ policy: raw?.policy || null
6713
+ };
6714
+ };
6595
6715
  var normalizeProcessDefinition = (value) => {
6596
6716
  const raw = value?.definitionJson || value?.viewJson || value || {};
6597
6717
  const nodes = Array.isArray(raw.nodes) ? raw.nodes : [];
@@ -6678,11 +6798,15 @@ async function saveTask(request, params) {
6678
6798
  return response.data || response.result;
6679
6799
  }
6680
6800
  async function getReturnableNodes(request, taskId) {
6801
+ const result = await getReturnableNodeResult(request, taskId);
6802
+ return result.nodes;
6803
+ }
6804
+ async function getReturnableNodeResult(request, taskId) {
6681
6805
  const response = await request({
6682
6806
  url: `/workflow/task/${taskId}/returnable-nodes`,
6683
6807
  method: "get"
6684
6808
  });
6685
- return normalizeReturnableNodes(response.data || response.result);
6809
+ return normalizeReturnableNodeResult(response.data || response.result);
6686
6810
  }
6687
6811
  async function previewProcess(request, params) {
6688
6812
  const response = await request({
@@ -7166,7 +7290,7 @@ function FormTabs({ items, defaultActiveKey, className, tabClassName }) {
7166
7290
  }
7167
7291
 
7168
7292
  // src/layout/FormSteps/index.tsx
7169
- import React39, { useState as useState20 } from "react";
7293
+ import React41, { useState as useState20 } from "react";
7170
7294
  import { jsx as jsx75, jsxs as jsxs27 } from "react/jsx-runtime";
7171
7295
  function FormSteps({ items, className, onStepChange }) {
7172
7296
  const [currentStep, setCurrentStep] = useState20(0);
@@ -7185,7 +7309,7 @@ function FormSteps({ items, className, onStepChange }) {
7185
7309
  }
7186
7310
  };
7187
7311
  return /* @__PURE__ */ jsxs27("div", { className: className ?? "w-full", "data-testid": "form-steps", children: [
7188
- /* @__PURE__ */ jsx75("div", { className: "flex items-center mb-6", "data-testid": "form-steps-indicator", children: items.map((item, index) => /* @__PURE__ */ jsxs27(React39.Fragment, { children: [
7312
+ /* @__PURE__ */ jsx75("div", { className: "flex items-center mb-6", "data-testid": "form-steps-indicator", children: items.map((item, index) => /* @__PURE__ */ jsxs27(React41.Fragment, { children: [
7189
7313
  /* @__PURE__ */ jsxs27("div", { className: "flex items-center", children: [
7190
7314
  /* @__PURE__ */ jsx75(
7191
7315
  "div",
@@ -7860,6 +7984,13 @@ var DEFAULT_APPROVAL_ACTIONS = [
7860
7984
  { action: "rejected", name: { zh_CN: "\u62D2\u7EDD" } }
7861
7985
  ];
7862
7986
  var WITHDRAW_ACTION = { action: "withdraw", name: { zh_CN: "\u64A4\u9500" } };
7987
+ var FINAL_PROCESS_STATUSES = /* @__PURE__ */ new Set([
7988
+ "completed",
7989
+ "terminated",
7990
+ "withdrawn",
7991
+ "cancelled"
7992
+ ]);
7993
+ var EDITABLE_COMPLETED_STATUSES = /* @__PURE__ */ new Set(["completed", "terminated"]);
7863
7994
  function mergeCurrentTask(processTask, approvalTask) {
7864
7995
  if (!approvalTask) return processTask ?? null;
7865
7996
  if (!processTask) return approvalTask;
@@ -7881,11 +8012,14 @@ function useProcessDetail(options) {
7881
8012
  const [progressList, setProgressList] = useState25([]);
7882
8013
  const [formData, setFormData] = useState25(null);
7883
8014
  const [instanceInfo, setInstanceInfo] = useState25(null);
8015
+ const [accessDenied, setAccessDenied] = useState25(false);
8016
+ const [loadError, setLoadError] = useState25(null);
7884
8017
  const [isApprover, setIsApprover] = useState25(false);
7885
8018
  const [canWithdraw, setCanWithdraw] = useState25(false);
7886
8019
  const [approvalTasks, setApprovalTasks] = useState25([]);
7887
8020
  const [permissions, setPermissions] = useState25(null);
7888
8021
  const [processDefinition, setProcessDefinition] = useState25(null);
8022
+ const [dataVersion, setDataVersion] = useState25(0);
7889
8023
  const mountedRef = useRef10(true);
7890
8024
  const fieldIdsKey = fieldIds?.join("") ?? "";
7891
8025
  useEffect30(() => {
@@ -7899,26 +8033,34 @@ function useProcessDetail(options) {
7899
8033
  [processInfo?.currentTask, approvalTasks]
7900
8034
  );
7901
8035
  const processStatus = processInfo?.processStatus ?? null;
7902
- const isOriginatorReturn = currentTask?.nodeType === "originator_return";
7903
- const isProcessCompleted = processStatus === "completed" || processStatus === "terminated";
8036
+ const isProcessFinal = processStatus ? FINAL_PROCESS_STATUSES.has(processStatus) : false;
8037
+ const isOriginatorReturn = !isProcessFinal && currentTask?.nodeType === "originator_return";
8038
+ const isProcessCompleted = processStatus ? EDITABLE_COMPLETED_STATUSES.has(processStatus) : false;
8039
+ const canEdit = hasViewOperation(permissions?.operations, "edit");
8040
+ const canDelete = hasViewOperation(permissions?.operations, "delete");
8041
+ const canViewWorkflow = hasViewOperation(permissions?.operations, "workflow");
8042
+ const canViewChangeRecords = hasViewOperation(permissions?.operations, "change_records");
8043
+ const fieldPermissionTask = isProcessFinal ? void 0 : currentTask ?? void 0;
7904
8044
  const { fieldBehaviors } = useFieldPermission({
7905
8045
  viewPermissions: permissions ?? void 0,
7906
8046
  processDefinition: processDefinition ?? void 0,
7907
- currentTask: currentTask ?? void 0,
7908
- isApprover,
8047
+ currentTask: fieldPermissionTask,
8048
+ isApprover: isProcessFinal ? false : isApprover,
7909
8049
  mode
7910
8050
  });
7911
8051
  const activeActions = useMemo13(() => {
7912
- if (!isApprover) return [];
8052
+ if (!isApprover || isProcessFinal) return [];
7913
8053
  const actions = currentTask?.actions && currentTask.actions.length > 0 ? [...currentTask.actions] : [...DEFAULT_APPROVAL_ACTIONS];
7914
8054
  if (canWithdraw && !actions.some((action) => action.action === "withdraw")) {
7915
8055
  actions.push(WITHDRAW_ACTION);
7916
8056
  }
7917
8057
  return actions;
7918
- }, [isApprover, currentTask?.actions, canWithdraw]);
8058
+ }, [isApprover, isProcessFinal, currentTask?.actions, canWithdraw]);
7919
8059
  const loadData = useCallback12(async () => {
7920
8060
  if (!mountedRef.current) return;
7921
8061
  setLoading(true);
8062
+ setAccessDenied(false);
8063
+ setLoadError(null);
7922
8064
  try {
7923
8065
  const [basicResult, approvalResult, permResult, formResult] = await Promise.all([
7924
8066
  getProcessBasic(request, formInstanceId),
@@ -7927,16 +8069,35 @@ function useProcessDetail(options) {
7927
8069
  getFormData(request, { formInstanceId, appType, formUuid })
7928
8070
  ]);
7929
8071
  if (!mountedRef.current) return;
8072
+ if (!hasViewPermission(permResult)) {
8073
+ setAccessDenied(true);
8074
+ setProcessInfo(null);
8075
+ setIsApprover(false);
8076
+ setCanWithdraw(false);
8077
+ setApprovalTasks([]);
8078
+ setPermissions(permResult);
8079
+ setInstanceInfo(null);
8080
+ setFormData(null);
8081
+ setProgressList([]);
8082
+ setProcessDefinition(null);
8083
+ return;
8084
+ }
7930
8085
  setProcessInfo(basicResult);
7931
- setIsApprover(approvalResult?.isApprover ?? false);
7932
- setCanWithdraw(approvalResult?.canUndo ?? false);
7933
- setApprovalTasks(approvalResult?.currentTasks ?? []);
8086
+ const nextProcessStatus = basicResult?.processStatus ?? null;
8087
+ const nextIsProcessFinal = nextProcessStatus ? FINAL_PROCESS_STATUSES.has(nextProcessStatus) : false;
8088
+ const nextCanWithdraw = Boolean(
8089
+ approvalResult?.canUndo && nextProcessStatus === "running" && basicResult?.isExecuting !== true
8090
+ );
8091
+ setIsApprover(nextIsProcessFinal ? false : approvalResult?.isApprover ?? false);
8092
+ setCanWithdraw(nextCanWithdraw);
8093
+ setApprovalTasks(nextIsProcessFinal ? [] : approvalResult?.currentTasks ?? []);
7934
8094
  setPermissions(permResult);
7935
8095
  setInstanceInfo(formResult);
7936
8096
  setFormData(
7937
8097
  extractFormValues(formResult, fieldIdsKey ? fieldIdsKey.split("") : void 0)
7938
8098
  );
7939
- if (permResult?.operations?.includes("VIEW_PROCESS") || permResult?.operations?.length > 0) {
8099
+ setDataVersion((version) => version + 1);
8100
+ if (hasViewOperation(permResult?.operations, "workflow")) {
7940
8101
  try {
7941
8102
  const progress = await getProcessProgress(request, formInstanceId);
7942
8103
  if (mountedRef.current) {
@@ -7946,8 +8107,8 @@ function useProcessDetail(options) {
7946
8107
  console.error("[useProcessDetail] Failed to load progress:", error);
7947
8108
  }
7948
8109
  }
7949
- const task = basicResult?.currentTask;
7950
- if (approvalResult?.isApprover && task && (task.nodeType === "originator_return" || task.nodeType === "approval")) {
8110
+ const task = mergeCurrentTask(basicResult?.currentTask, approvalResult?.currentTasks?.[0]);
8111
+ if (!nextIsProcessFinal && approvalResult?.isApprover && task && (task.nodeType === "originator_return" || task.nodeType === "approval")) {
7951
8112
  try {
7952
8113
  const definition = await getProcessDefinition(request, formUuid);
7953
8114
  if (mountedRef.current) {
@@ -7956,14 +8117,20 @@ function useProcessDetail(options) {
7956
8117
  } catch (error) {
7957
8118
  console.error("[useProcessDetail] Failed to load process definition:", error);
7958
8119
  }
8120
+ } else if (mountedRef.current) {
8121
+ setProcessDefinition(null);
7959
8122
  }
7960
8123
  } catch (error) {
7961
8124
  console.error("[useProcessDetail] Failed to load data:", error);
7962
8125
  if (mountedRef.current) {
8126
+ setLoadError(error instanceof Error ? error.message : "\u9875\u9762\u52A0\u8F7D\u5931\u8D25");
8127
+ setAccessDenied(false);
7963
8128
  setProcessInfo(null);
7964
8129
  setFormData(null);
7965
8130
  setInstanceInfo(null);
7966
8131
  setApprovalTasks([]);
8132
+ setProgressList([]);
8133
+ setProcessDefinition(null);
7967
8134
  }
7968
8135
  } finally {
7969
8136
  if (mountedRef.current) {
@@ -7976,24 +8143,46 @@ function useProcessDetail(options) {
7976
8143
  }, [loadData]);
7977
8144
  const switchToEdit = useCallback12(() => {
7978
8145
  setMode("edit");
7979
- }, []);
8146
+ void loadData();
8147
+ }, [loadData]);
7980
8148
  const switchToReadonly = useCallback12(() => {
7981
8149
  setMode("readonly");
7982
8150
  }, []);
8151
+ const refreshDetail = useCallback12(async () => {
8152
+ setMode("readonly");
8153
+ await loadData();
8154
+ }, [loadData]);
7983
8155
  const refreshProgress = useCallback12(async () => {
7984
- try {
7985
- const [progress, basicResult] = await Promise.all([
7986
- getProcessProgress(request, formInstanceId),
7987
- getProcessBasic(request, formInstanceId)
7988
- ]);
7989
- if (mountedRef.current) {
7990
- setProgressList(progress);
7991
- setProcessInfo(basicResult);
8156
+ await refreshDetail();
8157
+ }, [refreshDetail]);
8158
+ const saveChanges = useCallback12(
8159
+ async (values) => {
8160
+ try {
8161
+ await api.updateFormData({
8162
+ formInstanceId,
8163
+ formUuid,
8164
+ appType,
8165
+ updateFormDataJson: JSON.stringify(values)
8166
+ });
8167
+ setMode("readonly");
8168
+ await loadData();
8169
+ return true;
8170
+ } catch (error) {
8171
+ console.error("[useProcessDetail] Failed to save changes:", error);
8172
+ return false;
7992
8173
  }
8174
+ },
8175
+ [api, formInstanceId, formUuid, appType, loadData]
8176
+ );
8177
+ const deleteInstance = useCallback12(async () => {
8178
+ try {
8179
+ await deleteFormData(request, { formInstanceId, appType, formUuid });
8180
+ return true;
7993
8181
  } catch (error) {
7994
- console.error("[useProcessDetail] Failed to refresh progress:", error);
8182
+ console.error("[useProcessDetail] Failed to delete instance:", error);
8183
+ return false;
7995
8184
  }
7996
- }, [request, formInstanceId]);
8185
+ }, [request, formInstanceId, appType, formUuid]);
7997
8186
  return {
7998
8187
  loading,
7999
8188
  processInfo,
@@ -8002,6 +8191,8 @@ function useProcessDetail(options) {
8002
8191
  progressList,
8003
8192
  formData,
8004
8193
  instanceInfo,
8194
+ accessDenied,
8195
+ loadError,
8005
8196
  isApprover,
8006
8197
  activeActions,
8007
8198
  fieldBehaviors,
@@ -8009,8 +8200,16 @@ function useProcessDetail(options) {
8009
8200
  isOriginatorReturn,
8010
8201
  isProcessCompleted,
8011
8202
  canWithdraw,
8203
+ canEdit,
8204
+ canDelete,
8205
+ canViewWorkflow,
8206
+ canViewChangeRecords,
8207
+ dataVersion,
8012
8208
  switchToEdit,
8013
8209
  switchToReadonly,
8210
+ saveChanges,
8211
+ deleteInstance,
8212
+ refreshDetail,
8014
8213
  refreshProgress
8015
8214
  };
8016
8215
  }
@@ -8024,6 +8223,7 @@ function useApprovalActions(options) {
8024
8223
  const [isLoading, setIsLoading] = useState26(false);
8025
8224
  const [currentAction, setCurrentAction] = useState26(null);
8026
8225
  const [returnableNodes, setReturnableNodes] = useState26([]);
8226
+ const [returnPolicy, setReturnPolicy] = useState26(null);
8027
8227
  const mountedRef = useRef11(true);
8028
8228
  useEffect31(() => {
8029
8229
  mountedRef.current = true;
@@ -8051,8 +8251,8 @@ function useApprovalActions(options) {
8051
8251
  formUuid,
8052
8252
  updateFormDataJson: formValues ? JSON.stringify(formValues) : void 0
8053
8253
  });
8254
+ await onActionComplete?.("approve");
8054
8255
  resetLoading();
8055
- onActionComplete?.("approve");
8056
8256
  return true;
8057
8257
  } catch (error) {
8058
8258
  console.error("[useApprovalActions] approve failed:", error);
@@ -8067,17 +8267,13 @@ function useApprovalActions(options) {
8067
8267
  setIsLoading(true);
8068
8268
  setCurrentAction("reject");
8069
8269
  try {
8070
- const formValues = getFormValues?.();
8071
8270
  await handleApproval(request, {
8072
8271
  instanceId: formInstanceId,
8073
8272
  action: "rejected",
8074
- comments,
8075
- appType,
8076
- formUuid,
8077
- updateFormDataJson: formValues ? JSON.stringify(formValues) : void 0
8273
+ comments
8078
8274
  });
8275
+ await onActionComplete?.("reject");
8079
8276
  resetLoading();
8080
- onActionComplete?.("reject");
8081
8277
  return true;
8082
8278
  } catch (error) {
8083
8279
  console.error("[useApprovalActions] reject failed:", error);
@@ -8085,7 +8281,7 @@ function useApprovalActions(options) {
8085
8281
  return false;
8086
8282
  }
8087
8283
  },
8088
- [request, formInstanceId, appType, formUuid, getFormValues, onActionComplete, resetLoading]
8284
+ [request, formInstanceId, onActionComplete, resetLoading]
8089
8285
  );
8090
8286
  const transfer = useCallback13(
8091
8287
  async (userId, reason) => {
@@ -8101,8 +8297,8 @@ function useApprovalActions(options) {
8101
8297
  newAssignee: userId,
8102
8298
  reason
8103
8299
  });
8300
+ await onActionComplete?.("transfer");
8104
8301
  resetLoading();
8105
- onActionComplete?.("transfer");
8106
8302
  return true;
8107
8303
  } catch (error) {
8108
8304
  console.error("[useApprovalActions] transfer failed:", error);
@@ -8126,8 +8322,8 @@ function useApprovalActions(options) {
8126
8322
  targetNodeId: nodeId,
8127
8323
  reason
8128
8324
  });
8325
+ await onActionComplete?.("return");
8129
8326
  resetLoading();
8130
- onActionComplete?.("return");
8131
8327
  return true;
8132
8328
  } catch (error) {
8133
8329
  console.error("[useApprovalActions] returnTo failed:", error);
@@ -8146,8 +8342,8 @@ function useApprovalActions(options) {
8146
8342
  instanceId: formInstanceId,
8147
8343
  reason
8148
8344
  });
8345
+ await onActionComplete?.("withdraw");
8149
8346
  resetLoading();
8150
- onActionComplete?.("withdraw");
8151
8347
  return true;
8152
8348
  } catch (error) {
8153
8349
  console.error("[useApprovalActions] withdraw failed:", error);
@@ -8168,8 +8364,8 @@ function useApprovalActions(options) {
8168
8364
  appType,
8169
8365
  updateFormDataJson: JSON.stringify(formValues)
8170
8366
  });
8367
+ await onActionComplete?.("save");
8171
8368
  resetLoading();
8172
- onActionComplete?.("save");
8173
8369
  return true;
8174
8370
  } catch (error) {
8175
8371
  console.error("[useApprovalActions] save failed:", error);
@@ -8194,8 +8390,8 @@ function useApprovalActions(options) {
8194
8390
  updateFormDataJson: JSON.stringify(formValues),
8195
8391
  comments
8196
8392
  });
8393
+ await onActionComplete?.("resubmit");
8197
8394
  resetLoading();
8198
- onActionComplete?.("resubmit");
8199
8395
  return true;
8200
8396
  } catch (error) {
8201
8397
  console.error("[useApprovalActions] resubmit failed:", error);
@@ -8218,8 +8414,8 @@ function useApprovalActions(options) {
8218
8414
  taskId: currentTaskId,
8219
8415
  payload
8220
8416
  });
8417
+ await onActionComplete?.("callback");
8221
8418
  resetLoading();
8222
- onActionComplete?.("callback");
8223
8419
  return true;
8224
8420
  } catch (error) {
8225
8421
  console.error("[useApprovalActions] callbackTask failed:", error);
@@ -8230,14 +8426,21 @@ function useApprovalActions(options) {
8230
8426
  [request, currentTaskId, onActionComplete, resetLoading]
8231
8427
  );
8232
8428
  const loadReturnableNodes = useCallback13(async () => {
8233
- if (!currentTaskId) return;
8429
+ if (!currentTaskId) return [];
8234
8430
  try {
8235
- const nodes = await getReturnableNodes(request, currentTaskId);
8431
+ const result = await getReturnableNodeResult(request, currentTaskId);
8236
8432
  if (mountedRef.current) {
8237
- setReturnableNodes(nodes);
8433
+ setReturnableNodes(result.nodes);
8434
+ setReturnPolicy(result.policy || null);
8238
8435
  }
8436
+ return result.nodes;
8239
8437
  } catch (error) {
8240
8438
  console.error("[useApprovalActions] loadReturnableNodes failed:", error);
8439
+ if (mountedRef.current) {
8440
+ setReturnableNodes([]);
8441
+ setReturnPolicy(null);
8442
+ }
8443
+ return [];
8241
8444
  }
8242
8445
  }, [request, currentTaskId]);
8243
8446
  return {
@@ -8252,6 +8455,7 @@ function useApprovalActions(options) {
8252
8455
  isLoading,
8253
8456
  currentAction,
8254
8457
  returnableNodes,
8458
+ returnPolicy,
8255
8459
  loadReturnableNodes
8256
8460
  };
8257
8461
  }
@@ -8562,7 +8766,7 @@ function defineFormSchema(schema) {
8562
8766
  }
8563
8767
 
8564
8768
  // src/modules/FormSummaryCard.tsx
8565
- import { Fragment, jsx as jsx77, jsxs as jsxs29 } from "react/jsx-runtime";
8769
+ import { Fragment as Fragment2, jsx as jsx77, jsxs as jsxs29 } from "react/jsx-runtime";
8566
8770
  var toneClasses = {
8567
8771
  brand: "bg-blue-50 text-blue-600",
8568
8772
  success: "bg-green-50 text-green-600",
@@ -8615,11 +8819,11 @@ var FormSummaryCard = ({
8615
8819
  creator && /* @__PURE__ */ jsxs29("div", { className: "flex items-center gap-2 mt-4 text-sm text-gray-600", children: [
8616
8820
  renderAvatar(),
8617
8821
  /* @__PURE__ */ jsx77("span", { className: "font-medium", children: creator.name }),
8618
- creator.department && /* @__PURE__ */ jsxs29(Fragment, { children: [
8822
+ creator.department && /* @__PURE__ */ jsxs29(Fragment2, { children: [
8619
8823
  /* @__PURE__ */ jsx77("span", { className: "text-gray-300", children: "\xB7" }),
8620
8824
  /* @__PURE__ */ jsx77("span", { children: creator.department })
8621
8825
  ] }),
8622
- createdAt && /* @__PURE__ */ jsxs29(Fragment, { children: [
8826
+ createdAt && /* @__PURE__ */ jsxs29(Fragment2, { children: [
8623
8827
  /* @__PURE__ */ jsx77("span", { className: "text-gray-300", children: "\xB7" }),
8624
8828
  /* @__PURE__ */ jsx77("span", { className: "text-gray-400", children: createdAt })
8625
8829
  ] })
@@ -9110,7 +9314,7 @@ var ApprovalTimeline = ({
9110
9314
  };
9111
9315
 
9112
9316
  // src/modules/ApprovalActionBar.tsx
9113
- import { useMemo as useMemo16, useState as useState32 } from "react";
9317
+ import React45, { useMemo as useMemo16, useState as useState32 } from "react";
9114
9318
  import { Form, Input as Input10, Modal as Modal5, Select as Select5 } from "antd";
9115
9319
  import {
9116
9320
  CheckOutlined,
@@ -9139,7 +9343,7 @@ var confirmAction = (title, content) => {
9139
9343
  };
9140
9344
 
9141
9345
  // src/modules/StickyActionBar.tsx
9142
- import { Fragment as Fragment2, jsx as jsx81, jsxs as jsxs33 } from "react/jsx-runtime";
9346
+ import { Fragment as Fragment3, jsx as jsx81, jsxs as jsxs33 } from "react/jsx-runtime";
9143
9347
  var getActionPriority = (action) => {
9144
9348
  const maybePriority = action.priority;
9145
9349
  if (typeof maybePriority === "number") return maybePriority;
@@ -9147,7 +9351,6 @@ var getActionPriority = (action) => {
9147
9351
  if (action.type === "danger") return 90;
9148
9352
  return 50;
9149
9353
  };
9150
- var getPlacement = (action) => action.placement;
9151
9354
  var StickyActionBar = ({
9152
9355
  actions,
9153
9356
  className = "",
@@ -9171,8 +9374,6 @@ var StickyActionBar = ({
9171
9374
  const maxWidthStyle = typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth;
9172
9375
  const primaryMobile = visibleActions.slice(0, maxMobileButtons);
9173
9376
  const moreMobile = visibleActions.slice(maxMobileButtons);
9174
- const leftActions = visibleActions.filter((action) => getPlacement(action) === "left");
9175
- const rightActions = visibleActions.filter((action) => getPlacement(action) !== "left");
9176
9377
  const positionClass = position === "fixed" ? "fixed bottom-0 left-0 right-0" : position === "inline" ? "relative" : "sticky bottom-0";
9177
9378
  const runAction = (action) => {
9178
9379
  if (action.confirm) {
@@ -9202,9 +9403,9 @@ var StickyActionBar = ({
9202
9403
  children: /* @__PURE__ */ jsx81(
9203
9404
  "div",
9204
9405
  {
9205
- className: `mx-auto flex w-full items-center gap-3 ${layoutMode === "approval" && !isMobile ? "justify-between" : "justify-end"}`,
9406
+ className: `mx-auto flex w-full items-center gap-3 ${layoutMode === "approval" && !isMobile ? "justify-center" : "justify-end"}`,
9206
9407
  style: { maxWidth: maxWidthStyle },
9207
- children: isMobile ? /* @__PURE__ */ jsxs33(Fragment2, { children: [
9408
+ children: isMobile ? /* @__PURE__ */ jsxs33(Fragment3, { children: [
9208
9409
  /* @__PURE__ */ jsx81("div", { className: "flex flex-1 gap-2", children: primaryMobile.map((action) => renderButton(action, true)) }),
9209
9410
  moreMobile.length > 0 && /* @__PURE__ */ jsx81(
9210
9411
  Dropdown,
@@ -9224,10 +9425,7 @@ var StickyActionBar = ({
9224
9425
  children: /* @__PURE__ */ jsx81(Button10, { icon: /* @__PURE__ */ jsx81(MoreOutlined, {}), className: "rounded-md", children: "\u66F4\u591A" })
9225
9426
  }
9226
9427
  )
9227
- ] }) : layoutMode === "approval" && leftActions.length > 0 ? /* @__PURE__ */ jsxs33(Fragment2, { children: [
9228
- /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center gap-3", children: leftActions.map((action) => renderButton(action)) }),
9229
- /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center justify-end gap-3", children: rightActions.map((action) => renderButton(action)) })
9230
- ] }) : /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center justify-end gap-3", children: visibleActions.map((action) => renderButton(action)) })
9428
+ ] }) : layoutMode === "approval" ? /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center justify-center gap-3", children: visibleActions.map((action) => renderButton(action)) }) : /* @__PURE__ */ jsx81("div", { className: "flex flex-wrap items-center justify-end gap-3", children: visibleActions.map((action) => renderButton(action)) })
9231
9429
  }
9232
9430
  )
9233
9431
  }
@@ -9235,7 +9433,7 @@ var StickyActionBar = ({
9235
9433
  };
9236
9434
 
9237
9435
  // src/modules/ApprovalActionBar.tsx
9238
- import { Fragment as Fragment3, jsx as jsx82, jsxs as jsxs34 } from "react/jsx-runtime";
9436
+ import { Fragment as Fragment4, jsx as jsx82, jsxs as jsxs34 } from "react/jsx-runtime";
9239
9437
  var actionPriority = {
9240
9438
  agree: 10,
9241
9439
  approved: 10,
@@ -9277,6 +9475,50 @@ function getModalTitle(action) {
9277
9475
  return "\u786E\u8BA4\u64CD\u4F5C";
9278
9476
  }
9279
9477
  }
9478
+ function formatReturnPolicy(policy) {
9479
+ if (!policy?.resubmitMode) return null;
9480
+ return policy.resubmitMode === "resume_current" ? "\u4ECE\u5F53\u524D\u8282\u70B9\u5BA1\u6279" : "\u91CD\u65B0\u4F9D\u6B21\u5BA1\u6279";
9481
+ }
9482
+ function DefaultTransferSelector({
9483
+ value,
9484
+ onChange
9485
+ }) {
9486
+ const formContext = React45.useContext(FormContext);
9487
+ const [open, setOpen] = useState32(false);
9488
+ const [selectedUsers, setSelectedUsers] = useState32([]);
9489
+ if (!formContext) {
9490
+ return /* @__PURE__ */ jsx82(Input10, { value, onChange: (event) => onChange(event.target.value) });
9491
+ }
9492
+ const selectedLabel = selectedUsers[0] ? getUserName(selectedUsers[0]) : value;
9493
+ return /* @__PURE__ */ jsxs34(Fragment4, { children: [
9494
+ /* @__PURE__ */ jsx82(
9495
+ Input10,
9496
+ {
9497
+ readOnly: true,
9498
+ value: selectedLabel,
9499
+ placeholder: "\u8BF7\u9009\u62E9\u8F6C\u4EA4\u7528\u6237",
9500
+ addonAfter: /* @__PURE__ */ jsx82("span", { className: "cursor-pointer text-blue-600", onClick: () => setOpen(true), children: "\u9009\u62E9" })
9501
+ }
9502
+ ),
9503
+ /* @__PURE__ */ jsx82(
9504
+ UserPicker,
9505
+ {
9506
+ api: formContext.api,
9507
+ open,
9508
+ onOpenChange: setOpen,
9509
+ multiple: false,
9510
+ value: selectedUsers,
9511
+ onCancel: () => setOpen(false),
9512
+ onConfirm: (items) => {
9513
+ const next = items.slice(0, 1);
9514
+ setSelectedUsers(next);
9515
+ const userId = next[0] ? getUserId(next[0]) : "";
9516
+ onChange(userId);
9517
+ }
9518
+ }
9519
+ )
9520
+ ] });
9521
+ }
9280
9522
  var ApprovalActionBar = ({
9281
9523
  actions,
9282
9524
  onApprove,
@@ -9288,6 +9530,7 @@ var ApprovalActionBar = ({
9288
9530
  onResubmit,
9289
9531
  onCallback,
9290
9532
  returnableNodes = [],
9533
+ returnPolicy,
9291
9534
  onLoadReturnableNodes,
9292
9535
  renderTransferSelector,
9293
9536
  renderReturnNodeLabel,
@@ -9313,7 +9556,12 @@ var ApprovalActionBar = ({
9313
9556
  userId: void 0,
9314
9557
  nodeId: void 0
9315
9558
  });
9316
- if (target === "return") await onLoadReturnableNodes?.();
9559
+ if (target === "return") {
9560
+ const loadedNodes = await onLoadReturnableNodes?.() || returnableNodes;
9561
+ if (loadedNodes.length === 1) {
9562
+ form.setFieldsValue({ nodeId: loadedNodes[0].nodeId || loadedNodes[0].id || "" });
9563
+ }
9564
+ }
9317
9565
  setModalAction(target);
9318
9566
  };
9319
9567
  const executeDirect = async (action) => {
@@ -9328,6 +9576,14 @@ var ApprovalActionBar = ({
9328
9576
  }
9329
9577
  if (normalized === "agree") {
9330
9578
  await onApprove?.();
9579
+ return;
9580
+ }
9581
+ if (normalized === "rejected") {
9582
+ await onReject?.();
9583
+ return;
9584
+ }
9585
+ if (normalized === "resubmit") {
9586
+ await onResubmit?.();
9331
9587
  }
9332
9588
  };
9333
9589
  const handleActionClick = async (action) => {
@@ -9336,6 +9592,10 @@ var ApprovalActionBar = ({
9336
9592
  await executeDirect(action);
9337
9593
  return;
9338
9594
  }
9595
+ if ((normalized === "agree" || normalized === "rejected" || normalized === "resubmit") && !action.remark?.popUp) {
9596
+ await executeDirect(action);
9597
+ return;
9598
+ }
9339
9599
  await openModal(action, normalized);
9340
9600
  };
9341
9601
  const handleOk = async () => {
@@ -9371,7 +9631,7 @@ var ApprovalActionBar = ({
9371
9631
  };
9372
9632
  });
9373
9633
  const requiredComment = activeAction?.remark?.required || modalAction === "rejected" || modalAction === "withdraw";
9374
- return /* @__PURE__ */ jsxs34(Fragment3, { children: [
9634
+ return /* @__PURE__ */ jsxs34(Fragment4, { children: [
9375
9635
  /* @__PURE__ */ jsx82(
9376
9636
  StickyActionBar,
9377
9637
  {
@@ -9397,7 +9657,7 @@ var ApprovalActionBar = ({
9397
9657
  setActiveAction(null);
9398
9658
  form.resetFields();
9399
9659
  },
9400
- destroyOnClose: true,
9660
+ destroyOnHidden: true,
9401
9661
  children: /* @__PURE__ */ jsxs34(Form, { form, layout: "vertical", children: [
9402
9662
  modalAction === "transfer" && /* @__PURE__ */ jsx82(
9403
9663
  Form.Item,
@@ -9408,28 +9668,40 @@ var ApprovalActionBar = ({
9408
9668
  children: renderTransferSelector ? renderTransferSelector({
9409
9669
  value: form.getFieldValue("userId"),
9410
9670
  onChange: (userId) => form.setFieldsValue({ userId })
9411
- }) : /* @__PURE__ */ jsx82(Input10, { placeholder: "\u8BF7\u8F93\u5165\u7528\u6237 ID" })
9412
- }
9413
- ),
9414
- modalAction === "return" && /* @__PURE__ */ jsx82(
9415
- Form.Item,
9416
- {
9417
- name: "nodeId",
9418
- label: "\u9000\u56DE\u5230\u8282\u70B9",
9419
- rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9" }],
9420
- children: /* @__PURE__ */ jsx82(
9421
- Select5,
9671
+ }) : /* @__PURE__ */ jsx82(
9672
+ DefaultTransferSelector,
9422
9673
  {
9423
- placeholder: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9",
9424
- getPopupContainer: (triggerNode) => triggerNode.parentElement || document.body,
9425
- options: returnableNodes.map((node) => ({
9426
- value: node.nodeId || node.id || "",
9427
- label: renderReturnNodeLabel ? renderReturnNodeLabel(node) : node.nodeName || node.name || node.nodeId || node.id
9428
- }))
9674
+ value: form.getFieldValue("userId"),
9675
+ onChange: (userId) => form.setFieldsValue({ userId })
9429
9676
  }
9430
9677
  )
9431
9678
  }
9432
9679
  ),
9680
+ modalAction === "return" && /* @__PURE__ */ jsxs34(Fragment4, { children: [
9681
+ formatReturnPolicy(returnPolicy) && /* @__PURE__ */ jsxs34("div", { className: "mb-3 text-sm text-gray-500", children: [
9682
+ "\u9000\u56DE\u540E\u5BA1\u6279\u903B\u8F91\uFF1A",
9683
+ formatReturnPolicy(returnPolicy)
9684
+ ] }),
9685
+ /* @__PURE__ */ jsx82(
9686
+ Form.Item,
9687
+ {
9688
+ name: "nodeId",
9689
+ label: "\u9000\u56DE\u5230\u8282\u70B9",
9690
+ rules: [{ required: true, message: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9" }],
9691
+ children: /* @__PURE__ */ jsx82(
9692
+ Select5,
9693
+ {
9694
+ placeholder: "\u8BF7\u9009\u62E9\u9000\u56DE\u8282\u70B9",
9695
+ getPopupContainer: (triggerNode) => triggerNode.parentElement || document.body,
9696
+ options: returnableNodes.map((node) => ({
9697
+ value: node.nodeId || node.id || "",
9698
+ label: renderReturnNodeLabel ? renderReturnNodeLabel(node) : node.nodeName || node.name || node.nodeId || node.id
9699
+ }))
9700
+ }
9701
+ )
9702
+ }
9703
+ )
9704
+ ] }),
9433
9705
  /* @__PURE__ */ jsx82(
9434
9706
  Form.Item,
9435
9707
  {
@@ -9450,7 +9722,7 @@ var ApprovalActionBar = ({
9450
9722
  import { useMemo as useMemo17, useState as useState33 } from "react";
9451
9723
  import { Button as Button11, Dropdown as Dropdown2, Form as Form2, Input as Input11, Modal as Modal6 } from "antd";
9452
9724
  import { MoreOutlined as MoreOutlined2 } from "@ant-design/icons";
9453
- import { Fragment as Fragment4, jsx as jsx83, jsxs as jsxs35 } from "react/jsx-runtime";
9725
+ import { Fragment as Fragment5, jsx as jsx83, jsxs as jsxs35 } from "react/jsx-runtime";
9454
9726
  var priority = {
9455
9727
  agree: 10,
9456
9728
  approved: 10,
@@ -9479,6 +9751,7 @@ var ApprovalActions = ({
9479
9751
  const [activeAction, setActiveAction] = useState33(null);
9480
9752
  const [loading, setLoading] = useState33(false);
9481
9753
  const [saveLoading, setSaveLoading] = useState33(false);
9754
+ const [directLoading, setDirectLoading] = useState33(null);
9482
9755
  const renderableActions = useMemo17(
9483
9756
  () => actions.filter((action) => !action.hidden).sort((a, b) => (priority[a.action] ?? 50) - (priority[b.action] ?? 50)),
9484
9757
  [actions]
@@ -9496,6 +9769,14 @@ var ApprovalActions = ({
9496
9769
  setSaveLoading(false);
9497
9770
  }
9498
9771
  };
9772
+ const executeDirect = async (action, fn) => {
9773
+ setDirectLoading(action.action);
9774
+ try {
9775
+ await fn?.();
9776
+ } finally {
9777
+ setDirectLoading(null);
9778
+ }
9779
+ };
9499
9780
  const handleAction = (action) => {
9500
9781
  if (action.action === "transfer") {
9501
9782
  onTransfer?.();
@@ -9514,9 +9795,17 @@ var ApprovalActions = ({
9514
9795
  return;
9515
9796
  }
9516
9797
  if (action.action === "rejected" || action.action === "reject") {
9798
+ if (!action.remark?.popUp) {
9799
+ void executeDirect(action, onReject);
9800
+ return;
9801
+ }
9517
9802
  openModal("reject", action);
9518
9803
  return;
9519
9804
  }
9805
+ if (!action.remark?.popUp) {
9806
+ void executeDirect(action, onApprove);
9807
+ return;
9808
+ }
9520
9809
  openModal("approve", action);
9521
9810
  };
9522
9811
  const handleConfirm = async () => {
@@ -9542,16 +9831,16 @@ var ApprovalActions = ({
9542
9831
  type: action.action === "agree" || action.action === "approved" ? "primary" : "default",
9543
9832
  danger: action.action === "rejected" || action.action === "reject" || action.action === "withdraw",
9544
9833
  onClick: () => handleAction(action),
9545
- loading: action.action === "save" && saveLoading,
9834
+ loading: action.action === "save" && saveLoading || directLoading === action.action,
9546
9835
  children: getLabel(action)
9547
9836
  },
9548
9837
  action.action
9549
9838
  );
9550
- return /* @__PURE__ */ jsxs35(Fragment4, { children: [
9839
+ return /* @__PURE__ */ jsxs35(Fragment5, { children: [
9551
9840
  /* @__PURE__ */ jsxs35(
9552
9841
  "div",
9553
9842
  {
9554
- className: `${layout === "horizontal" ? "flex items-center gap-3" : "flex flex-col gap-2"} ${className}`,
9843
+ className: `${layout === "horizontal" ? "flex items-center justify-center gap-3" : "flex flex-col items-center gap-2"} ${className}`,
9555
9844
  children: [
9556
9845
  visibleButtons.map(button),
9557
9846
  moreButtons.length > 0 && /* @__PURE__ */ jsx83(
@@ -9588,7 +9877,7 @@ var ApprovalActions = ({
9588
9877
  setActiveAction(null);
9589
9878
  form.resetFields();
9590
9879
  },
9591
- destroyOnClose: true,
9880
+ destroyOnHidden: true,
9592
9881
  children: /* @__PURE__ */ jsx83(Form2, { form, layout: "vertical", children: /* @__PURE__ */ jsx83(
9593
9882
  Form2.Item,
9594
9883
  {
@@ -9611,7 +9900,7 @@ var ApprovalActions = ({
9611
9900
  // src/modules/FormActionBar.tsx
9612
9901
  import { useState as useState34 } from "react";
9613
9902
  import { Button as Button12 } from "antd";
9614
- import { Fragment as Fragment5, jsx as jsx84, jsxs as jsxs36 } from "react/jsx-runtime";
9903
+ import { Fragment as Fragment6, jsx as jsx84, jsxs as jsxs36 } from "react/jsx-runtime";
9615
9904
  var FormActionBar = ({
9616
9905
  actions,
9617
9906
  position = "bottom-fixed",
@@ -9672,7 +9961,7 @@ var FormActionBar = ({
9672
9961
  }
9673
9962
  );
9674
9963
  if (isFixed) {
9675
- return /* @__PURE__ */ jsxs36(Fragment5, { children: [
9964
+ return /* @__PURE__ */ jsxs36(Fragment6, { children: [
9676
9965
  bar,
9677
9966
  /* @__PURE__ */ jsx84("div", { className: "h-16" })
9678
9967
  ] });
@@ -9682,7 +9971,7 @@ var FormActionBar = ({
9682
9971
 
9683
9972
  // src/modules/RuntimePageShell.tsx
9684
9973
  import { Alert, Empty as Empty4, Spin as Spin5 } from "antd";
9685
- import { Fragment as Fragment6, jsx as jsx85, jsxs as jsxs37 } from "react/jsx-runtime";
9974
+ import { Fragment as Fragment7, jsx as jsx85, jsxs as jsxs37 } from "react/jsx-runtime";
9686
9975
  var RuntimePageShell = ({
9687
9976
  children,
9688
9977
  actions,
@@ -9708,7 +9997,7 @@ var RuntimePageShell = ({
9708
9997
  return /* @__PURE__ */ jsx85(Alert, { type: "error", showIcon: true, message: "\u9875\u9762\u52A0\u8F7D\u5931\u8D25", description: error });
9709
9998
  }
9710
9999
  if (empty) {
9711
- return /* @__PURE__ */ jsx85(Fragment6, { children: empty });
10000
+ return /* @__PURE__ */ jsx85(Fragment7, { children: empty });
9712
10001
  }
9713
10002
  return children;
9714
10003
  };
@@ -11306,7 +11595,7 @@ var DataManagementList = ({
11306
11595
  import { useState as useState36, useCallback as useCallback18 } from "react";
11307
11596
  import { Button as Button16, Select as Select7 } from "antd";
11308
11597
  import { CheckCircleFilled as CheckCircleFilled2 } from "@ant-design/icons";
11309
- import { Fragment as Fragment7, jsx as jsx90, jsxs as jsxs42 } from "react/jsx-runtime";
11598
+ import { Fragment as Fragment8, jsx as jsx90, jsxs as jsxs42 } from "react/jsx-runtime";
11310
11599
  var pickFormInstanceId = (value) => {
11311
11600
  if (!value) return void 0;
11312
11601
  if (typeof value === "string") return value;
@@ -11323,7 +11612,7 @@ var SubmitSuccessCard = ({
11323
11612
  renderSuccess
11324
11613
  }) => {
11325
11614
  if (renderSuccess) {
11326
- return /* @__PURE__ */ jsx90(Fragment7, { children: renderSuccess(info) });
11615
+ return /* @__PURE__ */ jsx90(Fragment8, { children: renderSuccess(info) });
11327
11616
  }
11328
11617
  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: [
11329
11618
  /* @__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" }) }),
@@ -11918,13 +12207,16 @@ var FormDetailTemplate = (props) => {
11918
12207
  };
11919
12208
 
11920
12209
  // src/templates/ProcessDetailTemplate.tsx
11921
- import { useCallback as useCallback20, useMemo as useMemo20, useRef as useRef16 } from "react";
12210
+ import { useCallback as useCallback20, useMemo as useMemo20, useRef as useRef16, useState as useState38 } from "react";
12211
+ import { Form as AntForm, Input as Input13, Modal as Modal9 } from "antd";
11922
12212
  import { jsx as jsx93, jsxs as jsxs45 } from "react/jsx-runtime";
11923
12213
  function FormDataBridge2({
11924
- formDataRef
12214
+ formDataRef,
12215
+ validateRef
11925
12216
  }) {
11926
- const { getFormData: getFormData2 } = useFormContext();
12217
+ const { getFormData: getFormData2, validateAll } = useFormContext();
11927
12218
  formDataRef.current = getFormData2;
12219
+ validateRef.current = validateAll;
11928
12220
  return null;
11929
12221
  }
11930
12222
  var InnerProcessContent = ({
@@ -11932,18 +12224,31 @@ var InnerProcessContent = ({
11932
12224
  formUuid,
11933
12225
  appType,
11934
12226
  formInstanceId,
12227
+ enableEdit = true,
12228
+ enableDelete = true,
12229
+ enableChangeRecords = true,
12230
+ showApproverInfo = true,
11935
12231
  header,
11936
12232
  renderTimeline,
11937
12233
  renderActions,
12234
+ renderFooterActions,
11938
12235
  renderTransferSelector,
11939
12236
  renderReturnNodeLabel,
11940
12237
  renderActionModalExtra,
11941
12238
  beforeForm,
11942
12239
  afterForm,
11943
12240
  onActionComplete,
12241
+ onSave,
12242
+ onDelete,
11944
12243
  inDrawer = false
11945
12244
  }) => {
11946
12245
  const formDataRef = useRef16(void 0);
12246
+ const validateRef = useRef16(void 0);
12247
+ const [withdrawForm] = AntForm.useForm();
12248
+ const [withdrawOpen, setWithdrawOpen] = useState38(false);
12249
+ const [withdrawLoading, setWithdrawLoading] = useState38(false);
12250
+ const [saveLoading, setSaveLoading] = useState38(false);
12251
+ const [deleteLoading, setDeleteLoading] = useState38(false);
11947
12252
  const fieldIds = useMemo20(() => schema.fields.map((field) => field.fieldId), [schema.fields]);
11948
12253
  const {
11949
12254
  loading,
@@ -11953,15 +12258,25 @@ var InnerProcessContent = ({
11953
12258
  progressList,
11954
12259
  formData,
11955
12260
  instanceInfo,
12261
+ accessDenied,
12262
+ loadError,
11956
12263
  isApprover,
11957
12264
  activeActions,
11958
12265
  fieldBehaviors,
11959
12266
  mode,
11960
12267
  isOriginatorReturn,
12268
+ isProcessCompleted,
11961
12269
  canWithdraw,
12270
+ canEdit,
12271
+ canDelete,
12272
+ canViewWorkflow,
12273
+ canViewChangeRecords,
12274
+ dataVersion,
11962
12275
  switchToEdit,
11963
12276
  switchToReadonly,
11964
- refreshProgress
12277
+ saveChanges,
12278
+ deleteInstance,
12279
+ refreshDetail
11965
12280
  } = useProcessDetail({ formUuid, appType, formInstanceId, fieldIds });
11966
12281
  const {
11967
12282
  approve,
@@ -11973,6 +12288,7 @@ var InnerProcessContent = ({
11973
12288
  resubmit,
11974
12289
  callbackTask,
11975
12290
  returnableNodes,
12291
+ returnPolicy,
11976
12292
  loadReturnableNodes
11977
12293
  } = useApprovalActions({
11978
12294
  formInstanceId,
@@ -11980,16 +12296,34 @@ var InnerProcessContent = ({
11980
12296
  appType,
11981
12297
  currentTaskId: currentTask?.taskId ?? currentTask?.id,
11982
12298
  onActionComplete: async (action) => {
11983
- onActionComplete?.(action);
11984
- await refreshProgress();
12299
+ await onActionComplete?.(action);
12300
+ await refreshDetail();
11985
12301
  },
11986
12302
  getFormValues: () => formDataRef.current?.() ?? formData ?? {}
11987
12303
  });
12304
+ const {
12305
+ records,
12306
+ loading: recordsLoading,
12307
+ total: recordsTotal,
12308
+ page: recordsPage,
12309
+ hasMore,
12310
+ loadMore,
12311
+ refresh: refreshRecords
12312
+ } = useChangeRecords({
12313
+ formUuid,
12314
+ appType,
12315
+ formInstanceId,
12316
+ autoLoad: enableChangeRecords && canViewChangeRecords
12317
+ });
12318
+ const validateForm = useCallback20(async () => {
12319
+ return validateRef.current ? validateRef.current() : true;
12320
+ }, []);
11988
12321
  const handleApprove = useCallback20(
11989
12322
  async (comments) => {
12323
+ if (!await validateForm()) return;
11990
12324
  await approve(comments);
11991
12325
  },
11992
- [approve]
12326
+ [approve, validateForm]
11993
12327
  );
11994
12328
  const handleReject = useCallback20(
11995
12329
  async (comments) => {
@@ -12016,22 +12350,104 @@ var InnerProcessContent = ({
12016
12350
  [withdraw]
12017
12351
  );
12018
12352
  const handleSave = useCallback20(async () => {
12353
+ if (!await validateForm()) return;
12019
12354
  await save();
12020
- }, [save]);
12355
+ }, [save, validateForm]);
12021
12356
  const handleResubmit = useCallback20(
12022
12357
  async (comments) => {
12358
+ if (!await validateForm()) return;
12023
12359
  await resubmit(comments);
12024
12360
  },
12025
- [resubmit]
12361
+ [resubmit, validateForm]
12026
12362
  );
12027
12363
  const handleCallback = useCallback20(async () => {
12028
12364
  await callbackTask();
12029
12365
  }, [callbackTask]);
12366
+ const handleCompletedSave = useCallback20(async () => {
12367
+ if (!await validateForm()) return;
12368
+ const values = formDataRef.current?.() ?? formData;
12369
+ if (!values) return;
12370
+ setSaveLoading(true);
12371
+ try {
12372
+ const success = await saveChanges(values);
12373
+ if (success) {
12374
+ await onSave?.(values);
12375
+ }
12376
+ } finally {
12377
+ setSaveLoading(false);
12378
+ }
12379
+ }, [formData, onSave, saveChanges, validateForm]);
12380
+ const handleCompletedDelete = useCallback20(async () => {
12381
+ setDeleteLoading(true);
12382
+ try {
12383
+ const success = await deleteInstance();
12384
+ if (success) {
12385
+ await onDelete?.();
12386
+ }
12387
+ } finally {
12388
+ setDeleteLoading(false);
12389
+ }
12390
+ }, [deleteInstance, onDelete]);
12391
+ const handleFooterWithdraw = useCallback20(async () => {
12392
+ const values = await withdrawForm.validateFields();
12393
+ setWithdrawLoading(true);
12394
+ try {
12395
+ await handleWithdraw(values.reason || void 0);
12396
+ setWithdrawOpen(false);
12397
+ withdrawForm.resetFields();
12398
+ } finally {
12399
+ setWithdrawLoading(false);
12400
+ }
12401
+ }, [handleWithdraw, withdrawForm]);
12402
+ const handleFooterWithdrawCancel = useCallback20(() => {
12403
+ setWithdrawOpen(false);
12404
+ withdrawForm.resetFields();
12405
+ }, [withdrawForm]);
12030
12406
  const bottomActions = useMemo20(() => {
12031
- if (isApprover && activeActions.length > 0) return [];
12407
+ if (isApprover && !isOriginatorReturn && activeActions.length > 0) return [];
12408
+ if (isProcessCompleted) {
12409
+ if (mode === "readonly") {
12410
+ const actions = [];
12411
+ if (enableEdit && canEdit) {
12412
+ actions.push({
12413
+ key: "edit",
12414
+ label: "\u7F16\u8F91",
12415
+ type: "primary",
12416
+ onClick: switchToEdit
12417
+ });
12418
+ }
12419
+ if (enableDelete && canDelete) {
12420
+ actions.push({
12421
+ key: "delete",
12422
+ label: "\u5220\u9664",
12423
+ type: "danger",
12424
+ loading: deleteLoading,
12425
+ onClick: handleCompletedDelete,
12426
+ confirm: { title: "\u786E\u8BA4\u5220\u9664", content: "\u5220\u9664\u540E\u5C06\u65E0\u6CD5\u6062\u590D\uFF0C\u786E\u8BA4\u8981\u5220\u9664\u5417\uFF1F" }
12427
+ });
12428
+ }
12429
+ return actions;
12430
+ }
12431
+ return [
12432
+ {
12433
+ key: "cancel",
12434
+ label: "\u53D6\u6D88",
12435
+ type: "default",
12436
+ onClick: switchToReadonly,
12437
+ placement: "left"
12438
+ },
12439
+ {
12440
+ key: "save",
12441
+ label: "\u4FDD\u5B58",
12442
+ type: "primary",
12443
+ loading: saveLoading,
12444
+ onClick: handleCompletedSave
12445
+ }
12446
+ ];
12447
+ }
12032
12448
  if (isOriginatorReturn) {
12033
12449
  if (mode === "readonly") {
12034
- return [
12450
+ const actions2 = [
12035
12451
  {
12036
12452
  key: "edit",
12037
12453
  label: "\u7F16\u8F91",
@@ -12039,8 +12455,23 @@ var InnerProcessContent = ({
12039
12455
  onClick: switchToEdit
12040
12456
  }
12041
12457
  ];
12458
+ actions2.push({
12459
+ key: "resubmit",
12460
+ label: "\u91CD\u65B0\u63D0\u4EA4",
12461
+ type: "default",
12462
+ onClick: () => handleResubmit()
12463
+ });
12464
+ if (canWithdraw) {
12465
+ actions2.push({
12466
+ key: "withdraw",
12467
+ label: "\u64A4\u9500",
12468
+ type: "danger",
12469
+ onClick: () => setWithdrawOpen(true)
12470
+ });
12471
+ }
12472
+ return actions2;
12042
12473
  }
12043
- return [
12474
+ const actions = [
12044
12475
  {
12045
12476
  key: "cancel",
12046
12477
  label: "\u53D6\u6D88",
@@ -12055,6 +12486,15 @@ var InnerProcessContent = ({
12055
12486
  onClick: () => handleResubmit()
12056
12487
  }
12057
12488
  ];
12489
+ if (canWithdraw) {
12490
+ actions.push({
12491
+ key: "withdraw",
12492
+ label: "\u64A4\u9500",
12493
+ type: "danger",
12494
+ onClick: () => setWithdrawOpen(true)
12495
+ });
12496
+ }
12497
+ return actions;
12058
12498
  }
12059
12499
  if (canWithdraw) {
12060
12500
  return [
@@ -12062,22 +12502,31 @@ var InnerProcessContent = ({
12062
12502
  key: "withdraw",
12063
12503
  label: "\u64A4\u9500",
12064
12504
  type: "danger",
12065
- onClick: () => handleWithdraw(),
12066
- confirm: { title: "\u786E\u8BA4\u64A4\u9500", content: "\u64A4\u9500\u540E\u6D41\u7A0B\u5C06\u7EC8\u6B62\uFF0C\u786E\u8BA4\u7EE7\u7EED\u5417\uFF1F" }
12505
+ loading: withdrawLoading,
12506
+ onClick: () => setWithdrawOpen(true)
12067
12507
  }
12068
12508
  ];
12069
12509
  }
12070
12510
  return [];
12071
12511
  }, [
12072
12512
  activeActions.length,
12513
+ canDelete,
12514
+ canEdit,
12073
12515
  canWithdraw,
12516
+ deleteLoading,
12517
+ enableDelete,
12518
+ enableEdit,
12519
+ handleCompletedDelete,
12520
+ handleCompletedSave,
12074
12521
  handleResubmit,
12075
- handleWithdraw,
12076
12522
  isApprover,
12077
12523
  isOriginatorReturn,
12524
+ isProcessCompleted,
12078
12525
  mode,
12526
+ saveLoading,
12079
12527
  switchToEdit,
12080
- switchToReadonly
12528
+ switchToReadonly,
12529
+ withdrawLoading
12081
12530
  ]);
12082
12531
  const formConfig = {
12083
12532
  mode: mode === "edit" ? "edit" : "readonly",
@@ -12092,7 +12541,10 @@ var InnerProcessContent = ({
12092
12541
  if (loading) {
12093
12542
  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" }) }) });
12094
12543
  }
12095
- const showApprovalActions = isApprover && activeActions.length > 0;
12544
+ if (accessDenied || loadError) {
12545
+ return /* @__PURE__ */ jsx93(RuntimePageShell, { accessDenied, error: loadError, inDrawer, children: /* @__PURE__ */ jsx93("div", {}) });
12546
+ }
12547
+ const showApprovalActions = isApprover && !isOriginatorReturn && activeActions.length > 0;
12096
12548
  const actionsNode = showApprovalActions ? renderActions ? renderActions(activeActions) : /* @__PURE__ */ jsx93(
12097
12549
  ApprovalActionBar,
12098
12550
  {
@@ -12106,52 +12558,108 @@ var InnerProcessContent = ({
12106
12558
  onResubmit: handleResubmit,
12107
12559
  onCallback: handleCallback,
12108
12560
  returnableNodes,
12561
+ returnPolicy,
12109
12562
  onLoadReturnableNodes: loadReturnableNodes,
12110
12563
  renderTransferSelector,
12111
12564
  renderReturnNodeLabel,
12112
12565
  renderActionModalExtra,
12113
12566
  inDrawer
12114
12567
  }
12115
- ) : bottomActions.length > 0 ? /* @__PURE__ */ jsx93(StickyActionBar, { actions: bottomActions, inDrawer }) : null;
12568
+ ) : bottomActions.length > 0 ? renderFooterActions ? renderFooterActions(bottomActions) : /* @__PURE__ */ jsx93(StickyActionBar, { actions: bottomActions, inDrawer }) : null;
12116
12569
  const statusMeta = processStatus ? PROCESS_STATUS_META[processStatus] : void 0;
12117
- return /* @__PURE__ */ jsx93(RuntimePageShell, { actions: actionsNode, inDrawer, children: /* @__PURE__ */ jsxs45("div", { className: "space-y-6", children: [
12118
- header,
12570
+ return /* @__PURE__ */ jsxs45(RuntimePageShell, { actions: actionsNode, inDrawer, children: [
12571
+ /* @__PURE__ */ jsxs45("div", { className: "space-y-6", children: [
12572
+ header,
12573
+ /* @__PURE__ */ jsx93(
12574
+ SummaryPanel,
12575
+ {
12576
+ title: processInfo?.title || instanceInfo?.title || schema.formMeta.title,
12577
+ eyebrow: `\u6D41\u7A0B\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
12578
+ creator: processInfo?.originatorName ? {
12579
+ name: processInfo.originatorName,
12580
+ department: processInfo.originatorDepartment
12581
+ } : void 0,
12582
+ createdAt: processInfo?.createdAt,
12583
+ status: statusMeta,
12584
+ metaItems: [
12585
+ { key: "currentTask", label: "\u5F53\u524D\u8282\u70B9", value: currentTask?.nodeName || "\u65E0" },
12586
+ {
12587
+ key: "processStatus",
12588
+ label: "\u5B9E\u4F8B\u72B6\u6001",
12589
+ value: statusMeta?.label || processStatus || "-"
12590
+ }
12591
+ ]
12592
+ }
12593
+ ),
12594
+ beforeForm,
12595
+ 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: isProcessCompleted ? "\u6B63\u5728\u7F16\u8F91\uFF0C\u4FEE\u6539\u540E\u8BF7\u4FDD\u5B58" : "\u6B63\u5728\u7F16\u8F91\u8868\u5355\uFF0C\u4FEE\u6539\u540E\u8BF7\u91CD\u65B0\u63D0\u4EA4" }),
12596
+ /* @__PURE__ */ jsx93("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: /* @__PURE__ */ jsxs45(
12597
+ FormProvider,
12598
+ {
12599
+ schema,
12600
+ config: formConfig,
12601
+ initialValues: formData ?? void 0,
12602
+ children: [
12603
+ /* @__PURE__ */ jsx93(FormDataBridge2, { formDataRef, validateRef }),
12604
+ /* @__PURE__ */ jsx93(FormRenderer, { columns: 2 })
12605
+ ]
12606
+ },
12607
+ `${mode}-${dataVersion}`
12608
+ ) }),
12609
+ afterForm,
12610
+ canViewWorkflow && /* @__PURE__ */ jsxs45("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: [
12611
+ /* @__PURE__ */ jsx93("div", { className: "mb-4 flex items-center justify-between gap-3", children: /* @__PURE__ */ jsxs45("div", { children: [
12612
+ /* @__PURE__ */ jsx93("h3", { className: "text-base font-semibold text-ant-color-text", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
12613
+ /* @__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" })
12614
+ ] }) }),
12615
+ renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ jsx93(
12616
+ ApprovalTimeline,
12617
+ {
12618
+ tasks: progressList,
12619
+ showRemarks: true,
12620
+ showApproverInfo
12621
+ }
12622
+ )
12623
+ ] }),
12624
+ enableChangeRecords && canViewChangeRecords && /* @__PURE__ */ jsx93(
12625
+ RecordChangePanel,
12626
+ {
12627
+ records,
12628
+ loading: recordsLoading,
12629
+ total: recordsTotal,
12630
+ page: recordsPage,
12631
+ hasMore,
12632
+ onLoadMore: loadMore,
12633
+ onRefresh: refreshRecords,
12634
+ onExpand: refreshRecords
12635
+ }
12636
+ )
12637
+ ] }),
12119
12638
  /* @__PURE__ */ jsx93(
12120
- SummaryPanel,
12639
+ Modal9,
12121
12640
  {
12122
- title: processInfo?.title || instanceInfo?.title || schema.formMeta.title,
12123
- eyebrow: `\u6D41\u7A0B\u5B9E\u4F8B ${formInstanceId?.slice(0, 8) || "-"}`,
12124
- creator: processInfo?.originatorName ? {
12125
- name: processInfo.originatorName,
12126
- department: processInfo.originatorDepartment
12127
- } : void 0,
12128
- createdAt: processInfo?.createdAt,
12129
- status: statusMeta,
12130
- metaItems: [
12131
- { key: "currentTask", label: "\u5F53\u524D\u8282\u70B9", value: currentTask?.nodeName || "\u65E0" },
12641
+ getContainer: false,
12642
+ title: "\u64A4\u9500\u6D41\u7A0B",
12643
+ open: withdrawOpen,
12644
+ okText: "\u786E\u8BA4\u64A4\u9500",
12645
+ cancelText: "\u53D6\u6D88",
12646
+ confirmLoading: withdrawLoading,
12647
+ okButtonProps: { danger: true },
12648
+ onOk: handleFooterWithdraw,
12649
+ onCancel: handleFooterWithdrawCancel,
12650
+ destroyOnHidden: true,
12651
+ children: /* @__PURE__ */ jsx93(AntForm, { form: withdrawForm, layout: "vertical", children: /* @__PURE__ */ jsx93(
12652
+ AntForm.Item,
12132
12653
  {
12133
- key: "processStatus",
12134
- label: "\u5B9E\u4F8B\u72B6\u6001",
12135
- value: statusMeta?.label || processStatus || "-"
12654
+ name: "reason",
12655
+ label: "\u64A4\u9500\u539F\u56E0",
12656
+ rules: [{ required: true, message: "\u8BF7\u586B\u5199\u64A4\u9500\u539F\u56E0" }],
12657
+ children: /* @__PURE__ */ jsx93(Input13.TextArea, { rows: 4, maxLength: 500, showCount: true, placeholder: "\u8BF7\u8F93\u5165\u64A4\u9500\u539F\u56E0" })
12136
12658
  }
12137
- ]
12659
+ ) })
12138
12660
  }
12139
- ),
12140
- beforeForm,
12141
- 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" }),
12142
- /* @__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: [
12143
- /* @__PURE__ */ jsx93(FormDataBridge2, { formDataRef }),
12144
- /* @__PURE__ */ jsx93(FormRenderer, { columns: 2 })
12145
- ] }) }),
12146
- afterForm,
12147
- /* @__PURE__ */ jsxs45("div", { className: "rounded-lg border border-ant-border-secondary bg-ant-bg-container p-5 md:p-6", children: [
12148
- /* @__PURE__ */ jsx93("div", { className: "mb-4 flex items-center justify-between gap-3", children: /* @__PURE__ */ jsxs45("div", { children: [
12149
- /* @__PURE__ */ jsx93("h3", { className: "text-base font-semibold text-ant-color-text", children: "\u5BA1\u6279\u8FDB\u5EA6" }),
12150
- /* @__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" })
12151
- ] }) }),
12152
- renderTimeline ? renderTimeline(progressList) : /* @__PURE__ */ jsx93(ApprovalTimeline, { tasks: progressList, showRemarks: true, showApproverInfo: true })
12153
- ] })
12154
- ] }) });
12661
+ )
12662
+ ] });
12155
12663
  };
12156
12664
  var ProcessDetailTemplate = (props) => {
12157
12665
  const { schema, formUuid, appType, formInstanceId } = props;
@@ -12241,6 +12749,7 @@ export {
12241
12749
  getProcessBasic,
12242
12750
  getProcessDefinition,
12243
12751
  getProcessProgress,
12752
+ getReturnableNodeResult,
12244
12753
  getReturnableNodes,
12245
12754
  getSystemFieldsForFormType,
12246
12755
  getViewPermission,