@bit-sun/business-component 4.2.0-alpha.6.8 → 4.2.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/components/Business/AddSelectBusiness/index.d.ts +3 -4
  2. package/dist/components/Business/BsLayouts/Components/AllFunc/drawContent.d.ts +1 -2
  3. package/dist/components/Business/BsLayouts/Components/ChooseStore/index.d.ts +1 -2
  4. package/dist/components/Business/BsLayouts/Components/CustomerMenu/MenuSetting/index.d.ts +1 -1
  5. package/dist/components/Business/BsLayouts/Components/CustomerMenu/MenuSetting/leftTree.d.ts +1 -1
  6. package/dist/components/Business/BsLayouts/Components/CustomerMenu/MenuSetting/rightTree.d.ts +2 -2
  7. package/dist/components/Business/BsLayouts/Components/CustomerMenu/globalMenu/DrawContent.d.ts +1 -2
  8. package/dist/components/Business/BsLayouts/Components/CustomerMenu/globalMenu/customMenuHeader.d.ts +1 -2
  9. package/dist/components/Business/BsLayouts/Components/CustomerMenu/index.d.ts +1 -1
  10. package/dist/components/Business/BsLayouts/Components/GlobalHeader/index.d.ts +1 -2
  11. package/dist/components/Business/BsLayouts/Components/RightContent/LoginModal.d.ts +1 -2
  12. package/dist/components/Business/BsLayouts/index.d.ts +1 -1
  13. package/dist/components/Business/BsSulaQueryTable/SearchItemSetting.d.ts +5 -5
  14. package/dist/components/Business/BsSulaQueryTable/index.d.ts +1 -2
  15. package/dist/components/Business/BsSulaQueryTable/setting.d.ts +6 -6
  16. package/dist/components/Business/BsSulaQueryTable/utils.d.ts +14 -15
  17. package/dist/components/Business/CommodityEntry/index.d.ts +1 -2
  18. package/dist/components/Business/CommonAlert/index.d.ts +1 -2
  19. package/dist/components/Business/CommonGuideWrapper/index.d.ts +3 -3
  20. package/dist/components/Business/DetailPageWrapper/index.d.ts +12 -12
  21. package/dist/components/Business/HomePageWrapper/index.d.ts +1 -2
  22. package/dist/components/Business/ItemPropertySelector/index.d.ts +1 -2
  23. package/dist/components/Business/JsonQueryTable/components/FieldsModifyModal.d.ts +1 -2
  24. package/dist/components/Business/JsonQueryTable/components/FieldsSettingsTable.d.ts +1 -2
  25. package/dist/components/Business/JsonQueryTable/components/Formula.d.ts +1 -2
  26. package/dist/components/Business/JsonQueryTable/components/MaintainOptions.d.ts +1 -2
  27. package/dist/components/Business/JsonQueryTable/drawer/index.d.ts +1 -2
  28. package/dist/components/Business/PropertyModal/index.d.ts +1 -2
  29. package/dist/components/Business/PropertyModal/propertyGroup.d.ts +1 -1
  30. package/dist/components/Business/SearchSelect/index.d.ts +1 -1
  31. package/dist/components/Business/StateFlow/index.d.ts +1 -2
  32. package/dist/components/Business/TreeSearchSelect/index.d.ts +1 -1
  33. package/dist/components/Business/columnSettingTable/columnSetting.d.ts +6 -6
  34. package/dist/components/Business/columnSettingTable/components/TableSumComponent.d.ts +1 -2
  35. package/dist/components/Business/columnSettingTable/index.d.ts +3 -3
  36. package/dist/components/Business/columnSettingTable/sulaSettingTable.d.ts +3 -3
  37. package/dist/components/Business/columnSettingTable/utils.d.ts +1 -2
  38. package/dist/components/Business/moreTreeTable/FixedScrollBar.d.ts +1 -1
  39. package/dist/components/Common/ParagraphCopier/index.d.ts +1 -1
  40. package/dist/components/Common/Section/index.d.ts +1 -1
  41. package/dist/components/Functional/AddSelect/index.d.ts +1 -2
  42. package/dist/components/Functional/AuthButton/index.d.ts +1 -2
  43. package/dist/components/Functional/DataImport/index.d.ts +3 -3
  44. package/dist/components/Functional/DataValidation/index.d.ts +5 -5
  45. package/dist/components/Functional/ExportFunctions/ExportIcon/index.d.ts +1 -2
  46. package/dist/components/Functional/QueryMutipleInput/index.d.ts +1 -2
  47. package/dist/components/Functional/QueryMutipleSelect/index.d.ts +1 -2
  48. package/dist/components/Functional/SearchSelect/index.d.ts +1 -1
  49. package/dist/components/Functional/SearchSelect/utils.d.ts +2 -3
  50. package/dist/components/Functional/TreeSearchSelect/index.d.ts +1 -2
  51. package/dist/components/Solution/RuleComponent/CustomPlugin/CustomSelector/CustomSelectorModal.d.ts +1 -1
  52. package/dist/components/Solution/RuleComponent/CustomPlugin/CustomSelector/index.d.ts +1 -2
  53. package/dist/components/Solution/RuleComponent/Formula.d.ts +1 -2
  54. package/dist/components/Solution/RuleComponent/InnerSelect.d.ts +1 -2
  55. package/dist/components/Solution/RuleComponent/RenderCompItem.d.ts +1 -2
  56. package/dist/components/Solution/RuleSetter/RuleInstance.d.ts +1 -2
  57. package/dist/components/Solution/RuleSetter/baseRule.d.ts +1 -1
  58. package/dist/components/Solution/RuleSetter/index.d.ts +1 -1
  59. package/dist/index.d.ts +1 -0
  60. package/dist/index.esm.js +1383 -1151
  61. package/dist/index.js +1383 -1150
  62. package/dist/plugin/TableColumnSetting/index.d.ts +5 -5
  63. package/dist/utils/TableUtils.d.ts +18 -19
  64. package/package.json +1 -1
  65. package/src/components/Business/BsSulaQueryTable/index.md +57 -4
  66. package/src/components/Business/BsSulaQueryTable/index.tsx +164 -7
  67. package/src/components/Business/BsSulaQueryTable/setting.tsx +6 -0
  68. package/src/components/Business/DetailPageWrapper/index.tsx +81 -1
  69. package/src/components/Business/DetailPageWrapper/readme.md +89 -0
  70. package/src/components/Business/SearchSelect/BusinessUtils.tsx +45 -12
  71. package/src/components/Functional/AddSelect/index.tsx +92 -0
  72. package/src/components/Functional/DataValidation/index.tsx +22 -3
  73. package/src/components/Functional/SearchSelect/index.tsx +5 -2
  74. package/src/components/Solution/RuleComponent/RenderCompItem.tsx +9 -1
  75. package/src/components/Solution/RuleComponent/index.js +1 -0
  76. package/src/components/Solution/RuleComponent/ruleFiled.js +25 -1
  77. package/src/index.ts +4 -0
@@ -38,14 +38,14 @@ declare class TableColumnSetting extends React.Component<TableColumnSettingProps
38
38
  } | {
39
39
  title: string;
40
40
  dataIndex: string;
41
- render: (text: any, record: any) => React.JSX.Element;
41
+ render: (text: any, record: any) => JSX.Element;
42
42
  className?: undefined;
43
43
  width?: undefined;
44
44
  } | {
45
45
  title: string;
46
46
  dataIndex: string;
47
47
  className: string;
48
- render: () => React.JSX.Element;
48
+ render: () => JSX.Element;
49
49
  width?: undefined;
50
50
  })[];
51
51
  showModal: () => void;
@@ -53,13 +53,13 @@ declare class TableColumnSetting extends React.Component<TableColumnSettingProps
53
53
  handleCancel: (e: React.MouseEvent<HTMLElement>) => void;
54
54
  handleTableHeadHidden: (title: string) => void;
55
55
  onSortEnd: ({ oldIndex, newIndex }: any) => void;
56
- DraggableContainer: (props: any) => React.JSX.Element;
57
- DraggableBodyRow: ({ className, style, ...restProps }: any) => React.JSX.Element;
56
+ DraggableContainer: (props: any) => JSX.Element;
57
+ DraggableBodyRow: ({ className, style, ...restProps }: any) => JSX.Element;
58
58
  onChange: (e: any, title: any) => void;
59
59
  handleReset: () => void;
60
60
  handleResetSetting: () => Promise<unknown>;
61
61
  onSearch: (e: any) => void;
62
62
  onSearchSort: (e: any) => void;
63
- render(): React.JSX.Element;
63
+ render(): JSX.Element;
64
64
  }
65
65
  export default TableColumnSetting;
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import moment from 'moment';
3
2
  type mediaListType = {
4
3
  type: number;
@@ -49,24 +48,24 @@ declare const updateGuanDate: (requestParams: any, dateKeyParams?: any) => {
49
48
  };
50
49
  submit: any;
51
50
  };
52
- declare const textIcon: (type: string | number, text?: string) => React.JSX.Element | undefined;
53
- declare const handleTextDoubleOrId: (textOne: string | undefined, textTwo: string | undefined) => React.JSX.Element;
54
- declare const handleTextDouble: (textOne: string | undefined, textTwo: string | undefined) => React.JSX.Element;
55
- declare const handleTextOverflow: (text: string | undefined, width?: number) => React.JSX.Element;
56
- declare const handleTextLineFeed: (text: string | undefined, width?: number) => React.JSX.Element;
57
- declare const handleTextTooltip: (text: any) => React.JSX.Element;
58
- declare const handleTextBreakSpaces: (text: any) => React.JSX.Element;
59
- declare const handleStatusBadge: (text: any, color: any) => React.JSX.Element;
60
- declare const HandleTotalCount: (totalParams: any) => React.JSX.Element;
51
+ declare const textIcon: (type: string | number, text?: string) => JSX.Element | undefined;
52
+ declare const handleTextDoubleOrId: (textOne: string | undefined, textTwo: string | undefined) => JSX.Element;
53
+ declare const handleTextDouble: (textOne: string | undefined, textTwo: string | undefined) => JSX.Element;
54
+ declare const handleTextOverflow: (text: string | undefined, width?: number) => JSX.Element;
55
+ declare const handleTextLineFeed: (text: string | undefined, width?: number) => JSX.Element;
56
+ declare const handleTextTooltip: (text: any) => JSX.Element;
57
+ declare const handleTextBreakSpaces: (text: any) => JSX.Element;
58
+ declare const handleStatusBadge: (text: any, color: any) => JSX.Element;
59
+ declare const HandleTotalCount: (totalParams: any) => JSX.Element;
61
60
  declare const handleCommonTimeRender: (text: any, format?: any) => any;
62
- declare const handleTooltip: (text: any, timeTrue?: boolean) => React.JSX.Element;
63
- declare const handleTooltipHours: (text: any, timeTrue?: boolean) => React.JSX.Element;
61
+ declare const handleTooltip: (text: any, timeTrue?: boolean) => JSX.Element;
62
+ declare const handleTooltipHours: (text: any, timeTrue?: boolean) => JSX.Element;
64
63
  type tableColumnsImageType = {
65
64
  width?: number | string;
66
65
  height?: number | string;
67
66
  [key: string]: any;
68
67
  };
69
- declare const tableColumnsImage: (url?: string, paramsObj?: tableColumnsImageType) => React.JSX.Element;
68
+ declare const tableColumnsImage: (url?: string, paramsObj?: tableColumnsImageType) => JSX.Element;
70
69
  interface ColumnsEditInterfave {
71
70
  text?: string;
72
71
  record?: any;
@@ -82,7 +81,7 @@ interface ColumnsEditInterfave {
82
81
  };
83
82
  [key: string]: any;
84
83
  }
85
- declare const ColumnsEdit: (props: ColumnsEditInterfave) => React.JSX.Element;
84
+ declare const ColumnsEdit: (props: ColumnsEditInterfave) => JSX.Element;
86
85
  type UserColumnsType = {
87
86
  name: string;
88
87
  department?: string;
@@ -90,13 +89,13 @@ type UserColumnsType = {
90
89
  company?: string;
91
90
  avatar?: string;
92
91
  };
93
- declare const userColumns: (props: UserColumnsType) => React.JSX.Element;
94
- declare const userInfoCard: (props: any) => React.JSX.Element;
92
+ declare const userColumns: (props: UserColumnsType) => JSX.Element;
93
+ declare const userInfoCard: (props: any) => JSX.Element;
95
94
  declare const getItemDefaultWidth: (item: any) => number;
96
- declare const sulaTableRenderTooltip: ({ text }: any) => React.JSX.Element;
95
+ declare const sulaTableRenderTooltip: ({ text }: any) => JSX.Element;
97
96
  declare const renderNumberText: ({ text }: any) => any;
98
97
  declare const renderFixed2: (text: any) => any;
99
- declare const handleTextWarpCustom: (text: any, style?: {}) => React.JSX.Element;
98
+ declare const handleTextWarpCustom: (text: any, style?: {}) => JSX.Element;
100
99
  declare const calculateValidPeriod: (start: any, end: any) => string;
101
- declare const handleTextWarp: (text: any) => React.JSX.Element;
100
+ declare const handleTextWarp: (text: any) => JSX.Element;
102
101
  export { getSkuImg, updateGuanDate, textIcon, handleTextDoubleOrId, handleTextDouble, handleTextOverflow, handleTextLineFeed, handleTextTooltip, handleTextBreakSpaces, handleStatusBadge, HandleTotalCount, handleTooltip, handleCommonTimeRender, handleTooltipHours, tableColumnsImage, ColumnsEdit, userColumns, userInfoCard, getItemDefaultWidth, renderNumberText, sulaTableRenderTooltip, renderFixed2, handleTextWarpCustom, handleTextWarp, calculateValidPeriod };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bit-sun/business-component",
3
- "version": "4.2.0-alpha.6.8",
3
+ "version": "4.2.0-alpha.7",
4
4
  "scripts": {
5
5
  "start": "dumi dev",
6
6
  "docs:build": "dumi build",
@@ -16,11 +16,32 @@ order: 1
16
16
  ### BsSulaQueryTable
17
17
 
18
18
  ```tsx
19
- import React, { useState } from 'react';
20
- import { Tabs } from 'antd';
19
+ import React, { useState, useEffect } from 'react';
20
+ import { Tabs, Button } from 'antd';
21
21
  import { BsSulaQueryTable } from '../../../index.ts';
22
22
 
23
23
  export default () => {
24
+ const [rows, setRows] = useState([]);
25
+ useEffect(() => {
26
+ // @ts-ignore
27
+ window.__POWERED_BY_WUJIE__ = true;
28
+ const flowConfig = [
29
+ {
30
+ tradeType: 180,
31
+ controlButtons: ['DRP_Sale_Order_edit'],
32
+ config: [
33
+ { fromStatus: 1, buttons: ['DRP_Sale_Order_edit'] },
34
+ { fromStatus: 25, buttons: [] },
35
+ ],
36
+ },
37
+ ];
38
+ localStorage.setItem('BUSINESS_FLOW_BUTTONS', JSON.stringify(flowConfig));
39
+ const authCodes = [
40
+ 'User_ApplicationList_add',
41
+ 'DRP_Sale_Order_edit',
42
+ ];
43
+ localStorage.setItem('menuAuth_mainProject', JSON.stringify(authCodes));
44
+ }, []);
24
45
  const config = {
25
46
  needPageHeader: false,
26
47
  remoteDataSource: {
@@ -38,7 +59,8 @@ export default () => {
38
59
  return {
39
60
  ...item,
40
61
  id: `${index}`,
41
- orderStatus: index === 1 ? '-1' : '',
62
+ orderStatus: index % 2 === 0 ? 1 : 25,
63
+ saleInfo: { tradeStatus: index % 2 === 0 ? 1 : 25 },
42
64
  name: `${item.name.first} ${item.name.last}`,
43
65
  };
44
66
  }),
@@ -73,6 +95,14 @@ export default () => {
73
95
  },
74
96
  action: ['refreshTable'],
75
97
  },
98
+ {
99
+ type: 'button',
100
+ code: 'User_ApplicationList_delete',
101
+ props: {
102
+ children: '删除',
103
+ },
104
+ action: ['refreshTable'],
105
+ },
76
106
  ],
77
107
  fields: [
78
108
  {
@@ -191,6 +221,28 @@ export default () => {
191
221
  key: 'email3',
192
222
  title: '邮箱3',
193
223
  },
224
+ {
225
+ key: 'operate',
226
+ title: '操作',
227
+ isPermissionColumn: true,
228
+ fixed: 'right',
229
+ render: [
230
+ {
231
+ type: 'link',
232
+ props: {
233
+ children: '编辑',
234
+ type: 'primary',
235
+ },
236
+ visible: '#{record.saleInfo.tradeStatus == 1}',
237
+ code: 'DRP_Sale_Order_edit',
238
+ action: {
239
+ type: 'route',
240
+ path: '/sales-management/sales-order/edit/#{record.id}',
241
+ },
242
+ },
243
+
244
+ ],
245
+ },
194
246
  ],
195
247
  rowSelection: {
196
248
  onChange: (rowKey: any, rows: any) => {
@@ -199,6 +251,8 @@ export default () => {
199
251
  },
200
252
  },
201
253
  rowKey: 'id',
254
+ tradeType: 180,
255
+ statusFieldPath: 'saleInfo.tradeStatus',
202
256
  tableProps: {
203
257
  initialPaging: {
204
258
  pagination: {
@@ -216,4 +270,3 @@ export default () => {
216
270
  );
217
271
  };
218
272
  ```
219
-
@@ -607,10 +607,24 @@ export default (props: any) => {
607
607
  ...value?.tableProps || {}
608
608
  };
609
609
 
610
- // @ts-ignore
611
610
  if (tableProps?.initialPaging?.pagination) {
612
- // @ts-ignore
613
611
  tableProps.initialPaging.pagination.showSizeChanger = true;
612
+
613
+ // 分页大小改变时,更新本地存储
614
+ const onShowSizeChange = (current: number, size: number) => {
615
+ let allPaginationData = JSON.parse(localStorage.getItem('paginationData') || "{}");
616
+ allPaginationData[bsTableCode] = size;
617
+ localStorage.setItem('paginationData', JSON.stringify(allPaginationData || {}));
618
+ };
619
+ tableProps.initialPaging.pagination.onShowSizeChange = onShowSizeChange;
620
+
621
+ // 从本地存储中获取分页大小
622
+ const pageSize = JSON.parse(localStorage.getItem('paginationData') || "{}")[bsTableCode];
623
+ if (pageSize) {
624
+ tableProps.initialPaging.pagination.pageSize = pageSize;
625
+ tableProps.pageSize = pageSize;
626
+ tableProps.defaultPageSize = pageSize;
627
+ }
614
628
  }
615
629
  return tableProps;
616
630
  };
@@ -735,9 +749,103 @@ export default (props: any) => {
735
749
  if (value.rowSelection) {
736
750
  value.rowSelection.columnWidth = 50;
737
751
  }
752
+ if (typeof props.tradeType !== 'number') {
753
+ return {
754
+ ...value,
755
+ actionsRender,
756
+ };
757
+ }
758
+ try {
759
+ const raw = JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
760
+ const entry = raw.find((i: any) => i?.tradeType === props.tradeType);
761
+ if (entry) {
762
+ const ctrlSet = new Set((entry?.controlButtons || []).filter(Boolean));
763
+ const allowedTopSet: any = new Set();
764
+ (entry?.config || []).forEach((c: any) => {
765
+ (c?.buttons || []).filter(Boolean).forEach((b: any) => {
766
+ if (!ctrlSet.size || ctrlSet.has(b)) allowedTopSet.add(b);
767
+ });
768
+ });
769
+ console.debug('[FlowCtrl:top]', { ctrlSize: ctrlSet.size, allowedTopSize: allowedTopSet.size });
770
+ actionsRender = actionsRender.filter((ui: any) => {
771
+ const code = ui?.code;
772
+ if (!code) return true;
773
+ if (ctrlSet.size && !ctrlSet.has(code)) return true; // 非流程控制按钮不处理
774
+ const keep = allowedTopSet.has(code);
775
+ if (code) console.debug('[FlowCtrl:top-element]', { code, keep });
776
+ return keep;
777
+ });
778
+ }
779
+ } catch (e) {}
780
+ let remoteDataSource = value?.remoteDataSource;
781
+ if (remoteDataSource) {
782
+ let ctrlSet: any = new Set();
783
+ let btnStatusMap: any = new Map();
784
+ try {
785
+ const raw = JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
786
+ const entry = raw.find((i: any) => i?.tradeType === props.tradeType);
787
+ if (entry) {
788
+ ctrlSet = new Set((entry?.controlButtons || []).filter(Boolean));
789
+ (entry?.config || []).forEach((c: any) => {
790
+ (c?.buttons || []).filter(Boolean).forEach((b: any) => {
791
+ if (!ctrlSet.size || ctrlSet.has(b)) {
792
+ const set = btnStatusMap.get(b) || new Set();
793
+ set.add(c?.fromStatus);
794
+ btnStatusMap.set(b, set);
795
+ }
796
+ });
797
+ });
798
+ }
799
+ } catch (e) {}
800
+ const getByPath = (obj: any, path: string) => {
801
+ if (!obj || !path) return undefined;
802
+ const parts = path.split('.');
803
+ let cur = obj;
804
+ for (let i = 0; i < parts.length; i++) {
805
+ cur = cur?.[parts[i]];
806
+ if (cur === undefined) return undefined;
807
+ }
808
+ return cur;
809
+ };
810
+ const statusPath = props?.statusFieldPath;
811
+ const augment = (result: any) => {
812
+ if (!btnStatusMap || btnStatusMap.size === 0) return result;
813
+ if (result && Array.isArray(result.list)) {
814
+ result.list = result.list.map((rec: any) => {
815
+ const status = statusPath ? getByPath(rec, statusPath) : (rec?.status ?? rec?.orderStatus ?? rec?.flowStatus ?? rec?.tradeStatus ?? rec?.currentStatus);
816
+ const map: any = {};
817
+ btnStatusMap.forEach((set: any, code: string) => {
818
+ map[code] = set.has(status) ? true : undefined;
819
+ });
820
+ return { ...rec, __flowAllowedMap: map };
821
+ });
822
+ }
823
+ return result;
824
+ };
825
+ if (Array.isArray(remoteDataSource.converter)) {
826
+ const stages = remoteDataSource.converter;
827
+ const pipeline = (args: any) => {
828
+ let res = args;
829
+ for (let i = 0; i < stages.length; i++) {
830
+ res = stages[i](res);
831
+ }
832
+ res = augment(res);
833
+ return res;
834
+ };
835
+ remoteDataSource = { ...remoteDataSource, converter: pipeline };
836
+ } else if (typeof remoteDataSource.converter === 'function') {
837
+ const orig = remoteDataSource.converter;
838
+ const wrap = (args: any) => {
839
+ const res = orig(args);
840
+ return augment(res);
841
+ };
842
+ remoteDataSource = { ...remoteDataSource, converter: wrap };
843
+ }
844
+ }
738
845
  return {
739
846
  ...value,
740
847
  actionsRender,
848
+ remoteDataSource,
741
849
  };
742
850
  };
743
851
 
@@ -773,11 +881,59 @@ export default (props: any) => {
773
881
  // 优化一下 减少复杂度
774
882
  const titleMap = toMapByKey(value.columns, 'title');
775
883
  // 加上排序
776
- const cols = showColumn.map((i) => ({
777
- ...i,
778
- isPermissionColumn: titleMap[renderToString(i.title)]?.isPermissionColumn,
779
- render: titleMap[renderToString(i.title)]?.render,
780
- }));
884
+ const hasFlowEntry = (typeof props.tradeType === 'number') && (() => {
885
+ try {
886
+ const raw = JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
887
+ return !!raw.find((i: any) => i?.tradeType === props.tradeType);
888
+ } catch (e) { return false; }
889
+ })();
890
+ const hasControlRange = (typeof props.tradeType === 'number') && (() => {
891
+ try {
892
+ const raw = JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
893
+ const entry = raw.find((i: any) => i?.tradeType === props.tradeType);
894
+ if (!entry) return false;
895
+ const ctrlSet = new Set((entry?.controlButtons || []).filter(Boolean));
896
+ return ctrlSet.size > 0;
897
+ } catch (e) { return false; }
898
+ })();
899
+ const toExpr = (v: any) => {
900
+ if (typeof v === 'string') return v.replace(/^#\{|\}$/g, '');
901
+ if (v === undefined) return 'true';
902
+ return v ? 'true' : 'false';
903
+ };
904
+ // 读取当前 tradeType 的控制范围,用于只在控制按钮上追加流程表达式
905
+ let ctrlSet: any = new Set();
906
+ if (hasFlowEntry) {
907
+ try {
908
+ const raw = JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
909
+ const entry = raw.find((i: any) => i?.tradeType === props.tradeType);
910
+ if (entry) ctrlSet = new Set((entry?.controlButtons || []).filter(Boolean));
911
+ } catch (e) {}
912
+ }
913
+ const augmentPermissionRender = (arr: any[], set: Set<string>) => {
914
+ return arr.map((el: any) => {
915
+ const code = el?.code;
916
+ if (!code) return el;
917
+ // 非控制范围按钮不追加流程控制,保持原 visible
918
+ if (!set || set.size === 0 || !set.has(code)) return el;
919
+ const base = toExpr(el.visible);
920
+ const flow = `record.__flowAllowedMap['${code}'] == true`;
921
+ return { ...el, visible: `#{(${base}) && (${flow})}` };
922
+ });
923
+ };
924
+ const cols = showColumn.map((i) => {
925
+ const orig = titleMap[renderToString(i.title)] || {};
926
+ const origRender = orig.render;
927
+ const isPerm = orig.isPermissionColumn;
928
+ const newRender = (Array.isArray(origRender) && isPerm && hasFlowEntry && hasControlRange)
929
+ ? augmentPermissionRender(origRender, ctrlSet)
930
+ : origRender;
931
+ return {
932
+ ...i,
933
+ isPermissionColumn: isPerm,
934
+ render: newRender,
935
+ };
936
+ });
781
937
  cols.forEach((i) => handleBssulaColumnsSpecialParams(i));
782
938
  return cols;
783
939
  };
@@ -967,6 +1123,7 @@ export default (props: any) => {
967
1123
  {/* 列设置弹出框表格 */}
968
1124
  <SortableTable
969
1125
  ref={sortTableRef}
1126
+ disableColumnFixed={props.tableProps?.isVirtualTable}
970
1127
  setShowColumns={setResizeShowColumns}
971
1128
  showColumn={showColumn}
972
1129
  setInitialTableInfo={setInitialTableInfo}
@@ -288,6 +288,9 @@ class SortableTable extends React.Component {
288
288
  title: '列首',
289
289
  dataIndex: 'fixedLeft',
290
290
  render: (text, record) => {
291
+ if(this.props.disableColumnFixed) {
292
+ return null
293
+ }
291
294
  return (
292
295
  <span
293
296
  onClick={() => {
@@ -375,6 +378,9 @@ class SortableTable extends React.Component {
375
378
  title: '列尾',
376
379
  dataIndex: 'fixedRight',
377
380
  render: (text, record) => {
381
+ if(this.props.disableColumnFixed) {
382
+ return null
383
+ }
378
384
  return (
379
385
  <span
380
386
  onClick={() => {
@@ -78,6 +78,8 @@ const DetailWrapper = React.memo(
78
78
  pathToRegexp,
79
79
  backHistoryPath,
80
80
  onBack,
81
+ tradeType,
82
+ fromStatus,
81
83
  }: any) => {
82
84
  const [isFullScreen, setIsFnllScreen]: any = useState(false);
83
85
  const [breadcrumbArr, setBreadCrumbArr]: any = useState([]);
@@ -195,6 +197,34 @@ const DetailWrapper = React.memo(
195
197
  }
196
198
  };
197
199
 
200
+ const getFlowButtons = () => {
201
+ try {
202
+ return JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
203
+ } catch (e) { return []; }
204
+ };
205
+ const matchByRule = (ui: any, flow: any, ctx: any) => {
206
+ if (flow.tradeType !== ctx.tradeType) return false;
207
+ if (typeof ctx.status === 'number' && flow.fromStatus !== ctx.status) return false;
208
+ const uiCode = ui.code || ui.buttonCode || ui?.props?.code || ui?.props?.buttonCode;
209
+ if (!uiCode || !flow.buttonCode) return false;
210
+ return uiCode === flow.buttonCode;
211
+ };
212
+ const filterByFlowRules = (list: Array<any>, ctx: any) => {
213
+ const flowList = getFlowButtons();
214
+ if (!flowList?.length || typeof ctx.tradeType !== 'number') return list;
215
+ const entry = flowList.find((i: any) => i?.tradeType === ctx.tradeType);
216
+ if (!entry) return list;
217
+ const ctrlSet = new Set((entry?.controlButtons || []).filter(Boolean));
218
+ const statButtons = (entry?.config || []).find((c: any) => c?.fromStatus === ctx.status)?.buttons || [];
219
+ const allowedSet = new Set((statButtons || []).filter(Boolean).filter((b: any) => ctrlSet.size ? ctrlSet.has(b) : true));
220
+ return list.filter((ui) => {
221
+ const uiCode = ui.code || ui.buttonCode || ui?.props?.code || ui?.props?.buttonCode;
222
+ if (!uiCode) return true;
223
+ if (ctrlSet.size && !ctrlSet.has(uiCode)) return true; // 非流程控制按钮不处理
224
+ return allowedSet.has(uiCode);
225
+ });
226
+ };
227
+
198
228
  const renderPageActionList = (actionLists: Array<actionItem>) => {
199
229
  const authButton = localStorage.getItem(getMenuAuthDataKey())
200
230
  ? JSON.parse(localStorage.getItem(getMenuAuthDataKey()) as string)
@@ -202,9 +232,13 @@ const DetailWrapper = React.memo(
202
232
  let visibleActions = actionLists.filter(
203
233
  (action) =>
204
234
  ((action.visible && action.visible !== 'false') || judgeIsEmpty(action.visible)) &&
205
- (!shouldUseAuth() || (judgeIsEmpty(action.code) || authButton.filter(item => item === action.code))),
235
+ (!shouldUseAuth() || (judgeIsEmpty(action.code) || authButton.some((item: any) => item === action.code))),
206
236
  );
207
237
 
238
+ if (typeof tradeType === 'number') {
239
+ visibleActions = filterByFlowRules(visibleActions, { tradeType, status: fromStatus });
240
+ }
241
+
208
242
  const renderButton = (item: actionItem, type?: any) => {
209
243
  return (
210
244
  <Button
@@ -348,3 +382,49 @@ const DetailWrapper = React.memo(
348
382
  return true;
349
383
  },
350
384
  );
385
+
386
+ export const processDetailButtonsVisible = (buttons: any[], params: any) => {
387
+ const { tradeType, fromStatus } = params || {};
388
+ const getFlowButtons = () => {
389
+ try {
390
+ return JSON.parse(localStorage.getItem('BUSINESS_FLOW_BUTTONS') || '[]');
391
+ } catch (e) { return []; }
392
+ };
393
+ const evalVisible = (v: any, ctx: any) => {
394
+ if (typeof v === 'string') {
395
+ const expr = v.replace(/^#\{|\}$/g, '');
396
+ try {
397
+ const keys = Object.keys(ctx || {});
398
+ const vals = keys.map((k) => ctx[k]);
399
+ // eslint-disable-next-line no-new-func
400
+ return Function(...keys, `return (${expr});`)(...vals);
401
+ } catch (e) { return true; }
402
+ }
403
+ if (v === undefined) return true;
404
+ return !!v;
405
+ };
406
+ let ctrlSet: any = new Set();
407
+ let allowedSet: any = new Set();
408
+ if (typeof tradeType === 'number') {
409
+ const flowList = getFlowButtons();
410
+ const entry = flowList.find((i: any) => i?.tradeType === tradeType);
411
+ if (entry) {
412
+ ctrlSet = new Set((entry?.controlButtons || []).filter(Boolean));
413
+ const statButtons = (entry?.config || []).find((c: any) => c?.fromStatus === fromStatus)?.buttons || [];
414
+ allowedSet = new Set((statButtons || []).filter(Boolean).filter((b: any) => ctrlSet.size ? ctrlSet.has(b) : true));
415
+ }
416
+ }
417
+ const processed = (buttons || []).map((btn: any) => {
418
+ const visBase = evalVisible(btn?.visible, params);
419
+ let vis = visBase;
420
+ if (typeof tradeType === 'number' && ctrlSet && allowedSet && btn?.code) {
421
+ if (ctrlSet.size === 0 || !ctrlSet.has(btn.code)) {
422
+ vis = visBase;
423
+ } else {
424
+ vis = visBase && allowedSet.has(btn.code);
425
+ }
426
+ }
427
+ return { ...btn, visible: vis };
428
+ });
429
+ return processed;
430
+ };
@@ -0,0 +1,89 @@
1
+ # DetailPageWrapper 按钮过滤测试
2
+
3
+ 演示目标:验证详情页在仅传入 `tradeType` 与 `fromStatus` 时,按钮按本地基础数据源与资源 `code` 精确匹配过滤、并叠加权限过滤是否生效。
4
+
5
+ ## 使用步骤
6
+
7
+ 1. 初始化本地数据源与权限
8
+
9
+ ```tsx
10
+ import React, { useEffect } from 'react';
11
+ import DetailPageWrapper from './index.tsx';
12
+
13
+ export default () => {
14
+ useEffect(() => {
15
+ // 开启权限过滤演示
16
+ // @ts-ignore
17
+ window.__POWERED_BY_WUJIE__ = true;
18
+
19
+ // 流程基础数据源(新结构示例)
20
+ const flowConfig = [
21
+ {
22
+ tradeType: 180,
23
+ controlButtons: ['Detail_Submit','Detail_Audit','Detail_ReAudit'],
24
+ config: [
25
+ { fromStatus: 1, buttons: ['Detail_Submit'] },
26
+ { fromStatus: 25, buttons: ['Detail_Audit'] },
27
+ { fromStatus: 26, buttons: ['Detail_ReAudit'] },
28
+ ],
29
+ },
30
+ ];
31
+ localStorage.setItem('BUSINESS_FLOW_BUTTONS', JSON.stringify(flowConfig));
32
+
33
+ // 菜单按钮授权(仅示例)
34
+ const authCodes = ['Detail_Submit', 'Detail_Audit', 'Detail_ReAudit'];
35
+ localStorage.setItem('menuAuth_mainProject', JSON.stringify(authCodes));
36
+ }, []);
37
+
38
+ const actionList = [
39
+ {
40
+ name: '提交',
41
+ code: 'Detail_Submit',
42
+ type: 'button',
43
+ action: () => console.log('提交'),
44
+ },
45
+ {
46
+ name: '审核',
47
+ code: 'Detail_Audit',
48
+ type: 'button',
49
+ action: () => console.log('审核'),
50
+ },
51
+ {
52
+ name: '反审核',
53
+ code: 'Detail_ReAudit',
54
+ type: 'button',
55
+ action: () => console.log('反审核'),
56
+ },
57
+ ];
58
+
59
+ return (
60
+ <DetailPageWrapper
61
+ title="详情页演示"
62
+ actionList={actionList}
63
+ tradeType={180}
64
+ fromStatus={1}
65
+ >
66
+ <div style={{ padding: 16 }}>这里是详情内容区域</div>
67
+ </DetailPageWrapper>
68
+ );
69
+ };
70
+ ```
71
+
72
+ 2. 切换 `fromStatus` 验证按钮显示
73
+
74
+ - `fromStatus=1`:显示 `Detail_Submit`
75
+ - `fromStatus=25`:显示 `Detail_Audit`
76
+ - `fromStatus=26`:显示 `Detail_ReAudit`
77
+
78
+ 3. 权限过滤验证
79
+
80
+ - 从 `localStorage.menuAuth_mainProject` 移除某个 `code`,对应按钮不会显示
81
+
82
+ ## 说明
83
+
84
+ - 详情页按钮显示条件:
85
+ - 资源 `code` 与 `BUSINESS_FLOW_BUTTONS.buttonCode` 完全一致
86
+ - `tradeType` 匹配
87
+ - `fromStatus` 匹配
88
+ - 权限启用且授权通过
89
+ - 其余属性(`routes`、`pathToRegexp` 等)非必需,可按页面实际需要补充。