sohelp-eleplus 1.1.27 → 1.1.28

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 (202) hide show
  1. package/components.js +1 -0
  2. package/package.json +2 -2
  3. package/sohelp-ace-editor/README.md +32 -42
  4. package/sohelp-ace-editor/index.vue +166 -156
  5. package/sohelp-api-doc/README.md +36 -0
  6. package/sohelp-api-doc/index.vue +160 -0
  7. package/sohelp-application-select/README.md +9 -7
  8. package/sohelp-application-select/index.vue +10 -13
  9. package/sohelp-autocode/README.md +14 -26
  10. package/sohelp-calendar-view/README.md +9 -7
  11. package/sohelp-calendar-view/index.vue +10 -9
  12. package/sohelp-card/README.md +15 -17
  13. package/sohelp-card/index.vue +1 -1
  14. package/sohelp-card-view/README.md +9 -7
  15. package/sohelp-card-view/index.vue +10 -9
  16. package/sohelp-condition/README.md +29 -49
  17. package/sohelp-condition/index.vue +2 -1
  18. package/sohelp-country-select/README.md +15 -123
  19. package/sohelp-cry-input/README.md +19 -195
  20. package/sohelp-cry-input/index.vue +5 -1
  21. package/sohelp-date/README.md +12 -15
  22. package/sohelp-datetime/README.md +15 -17
  23. package/sohelp-datetime-picker/README.md +18 -18
  24. package/sohelp-datetime-picker/index.vue +11 -4
  25. package/sohelp-datetime-range/README.md +20 -23
  26. package/sohelp-demo-block/README.md +43 -0
  27. package/sohelp-demo-block/index.vue +229 -0
  28. package/sohelp-dict/README.md +28 -23
  29. package/sohelp-dict/index.vue +17 -17
  30. package/sohelp-drawer/README.md +28 -26
  31. package/sohelp-drop-card/README.md +29 -28
  32. package/sohelp-drop-card/index.vue +0 -1
  33. package/sohelp-dyn-select/README.md +31 -16
  34. package/sohelp-dyn-select/index.vue +65 -67
  35. package/sohelp-dyn-tree/README.md +26 -20
  36. package/sohelp-dyn-tree/index.vue +2 -2
  37. package/sohelp-dyn-tree-select/README.md +28 -19
  38. package/sohelp-dyn-tree-select/index.vue +23 -7
  39. package/sohelp-entity-form/README.md +65 -30
  40. package/sohelp-entity-form/index.vue +3 -2
  41. package/sohelp-entity-grid/README.md +13 -11
  42. package/sohelp-entity-grid/index.vue +1 -1
  43. package/sohelp-file-upload/README.md +25 -27
  44. package/sohelp-file-upload/index.vue +1 -1
  45. package/sohelp-filter-scheme/README.md +34 -30
  46. package/sohelp-filter-scheme/index.vue +2 -2
  47. package/sohelp-grid/README.md +52 -33
  48. package/sohelp-grid/index.vue +2217 -2210
  49. package/sohelp-grid/js/SohelpGridConfig.js +3 -3
  50. package/sohelp-grid/js/useSohelpGridConfig.js +641 -642
  51. package/sohelp-grid-select/README.md +32 -27
  52. package/sohelp-grid-select/index.vue +6 -5
  53. package/sohelp-grid-view/README.md +51 -22
  54. package/sohelp-grid-view-select/README.md +33 -25
  55. package/sohelp-grid-view-select/index.vue +2 -1
  56. package/sohelp-group-view/README.md +14 -4
  57. package/sohelp-group-view/index.vue +10 -9
  58. package/sohelp-icon-select/README.md +14 -12
  59. package/sohelp-image-upload/README.md +27 -27
  60. package/sohelp-image-upload/index.vue +2 -2
  61. package/sohelp-import/README.md +25 -24
  62. package/sohelp-input/README.md +27 -11
  63. package/sohelp-input/index.vue +15 -2
  64. package/sohelp-input-tag/README.md +53 -0
  65. package/sohelp-input-tag/index.vue +337 -0
  66. package/sohelp-modal/README.md +42 -16
  67. package/sohelp-modal/index.vue +21 -4
  68. package/sohelp-modal-select/README.md +745 -0
  69. package/sohelp-modal-select/index.vue +705 -0
  70. package/sohelp-module/README.md +24 -13
  71. package/sohelp-number-input/README.md +15 -8
  72. package/sohelp-number-input/index.vue +3 -0
  73. package/sohelp-number-range/README.md +22 -12
  74. package/sohelp-number-range/index.vue +3 -11
  75. package/sohelp-org-modal-select/README.md +47 -0
  76. package/sohelp-org-modal-select/index.vue +411 -0
  77. package/sohelp-org-select/README.md +23 -10
  78. package/sohelp-org-select/index.vue +41 -24
  79. package/sohelp-org-tree/README.md +19 -7
  80. package/sohelp-org-tree/index.vue +1 -2
  81. package/sohelp-org-tree-select/README.md +22 -11
  82. package/sohelp-org-tree-select/index.vue +1 -2
  83. package/sohelp-org-user-tree/README.md +19 -7
  84. package/sohelp-org-user-tree/index.vue +1 -2
  85. package/sohelp-org-user-tree-select/README.md +8 -3
  86. package/sohelp-org-user-tree-select/index.vue +8 -7
  87. package/sohelp-page/README.md +20 -11
  88. package/sohelp-page/index.vue +1 -1
  89. package/sohelp-pagination/README.md +14 -6
  90. package/sohelp-pagination/index.vue +1 -1
  91. package/sohelp-power/README.md +34 -19
  92. package/sohelp-power/index.vue +2 -2
  93. package/sohelp-pro-form/README.md +64 -21
  94. package/sohelp-pro-layout/README.md +10 -4
  95. package/sohelp-pro-layout/index.vue +8 -7
  96. package/sohelp-pro-table/README.md +30 -6
  97. package/sohelp-process/README.md +26 -13
  98. package/sohelp-process/index.vue +6 -6
  99. package/sohelp-rate/README.md +24 -12
  100. package/sohelp-rate/index.vue +5 -1
  101. package/sohelp-relation/README.md +10 -4
  102. package/sohelp-relation/index.vue +8 -7
  103. package/sohelp-relation-modal-select/README.md +41 -0
  104. package/sohelp-relation-modal-select/index.vue +70 -0
  105. package/sohelp-rich-text/README.md +29 -11
  106. package/sohelp-rich-text/index.vue +21 -20
  107. package/sohelp-richtext/README.md +12 -2
  108. package/sohelp-richtext/index.vue +8 -6
  109. package/sohelp-role-modal-select/README.md +45 -0
  110. package/sohelp-role-modal-select/index.vue +111 -0
  111. package/sohelp-role-select/README.md +18 -10
  112. package/sohelp-role-select/index.vue +36 -27
  113. package/sohelp-search/README.md +12 -4
  114. package/sohelp-search/index.vue +2 -2
  115. package/sohelp-search-pro-form/README.md +15 -1
  116. package/sohelp-search-pro-form/index.vue +2 -1
  117. package/sohelp-select/README.md +31 -30
  118. package/sohelp-select/index.vue +79 -84
  119. package/sohelp-split-panel/README.md +17 -18
  120. package/sohelp-switch/README.md +21 -19
  121. package/sohelp-switch/index.vue +34 -33
  122. package/sohelp-table/README.md +35 -27
  123. package/sohelp-table/index.vue +110 -109
  124. package/sohelp-table-select/README.md +55 -0
  125. package/sohelp-tenant-select/README.md +19 -18
  126. package/sohelp-tenant-select/index.vue +105 -109
  127. package/sohelp-text/README.md +16 -10
  128. package/sohelp-text/index.vue +5 -5
  129. package/sohelp-textarea-input/README.md +19 -12
  130. package/sohelp-time/README.md +11 -10
  131. package/sohelp-tree/README.md +24 -19
  132. package/sohelp-tree/index.vue +21 -23
  133. package/sohelp-tree-select/README.md +23 -10
  134. package/sohelp-user-modal-select/README.md +739 -0
  135. package/sohelp-user-modal-select/index.vue +87 -0
  136. package/sohelp-user-select/README.md +26 -15
  137. package/sohelp-user-select/index.vue +6 -2
  138. package/sohelp-user-tag/README.md +5 -7
  139. package/sohelp-user-tag/index.vue +8 -8
  140. package/sohelp-user-tree/README.md +5 -8
  141. package/sohelp-user-tree/index.vue +8 -7
  142. package/sohelp-vform-drawer/README.md +36 -18
  143. package/sohelp-vform-drawer/index.vue +2 -2
  144. package/sohelp-vform-eleplus/README.md +33 -31
  145. package/sohelp-vform-eleplus/index.vue +2 -2
  146. package/sohelp-vform-eleplus/tinymce/langs/zh_CN.js +461 -461
  147. package/sohelp-vform-eleplus/tinymce/langs/zh_TW.js +418 -418
  148. package/sohelp-vform-eleplus/tinymce/skins/content/dark/content.css +72 -72
  149. package/sohelp-vform-eleplus/tinymce/skins/content/dark/content.min.css +7 -7
  150. package/sohelp-vform-eleplus/tinymce/skins/content/default/content.css +67 -67
  151. package/sohelp-vform-eleplus/tinymce/skins/content/default/content.min.css +7 -7
  152. package/sohelp-vform-eleplus/tinymce/skins/content/document/content.css +72 -72
  153. package/sohelp-vform-eleplus/tinymce/skins/content/document/content.min.css +7 -7
  154. package/sohelp-vform-eleplus/tinymce/skins/content/writer/content.css +68 -68
  155. package/sohelp-vform-eleplus/tinymce/skins/content/writer/content.min.css +7 -7
  156. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.css +732 -732
  157. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.inline.css +726 -726
  158. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.inline.min.css +7 -7
  159. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.min.css +7 -7
  160. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.mobile.css +29 -29
  161. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.mobile.min.css +7 -7
  162. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.css +3047 -3047
  163. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.min.css +7 -7
  164. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.mobile.css +673 -673
  165. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.mobile.min.css +7 -7
  166. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.shadowdom.css +37 -37
  167. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.shadowdom.min.css +7 -7
  168. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.css +714 -714
  169. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.inline.css +726 -726
  170. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.inline.min.css +7 -7
  171. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.min.css +7 -7
  172. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.mobile.css +29 -29
  173. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.mobile.min.css +7 -7
  174. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.css +3047 -3047
  175. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.min.css +7 -7
  176. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.mobile.css +673 -673
  177. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.mobile.min.css +7 -7
  178. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.shadowdom.css +37 -37
  179. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css +7 -7
  180. package/sohelp-vform-modal/README.md +36 -18
  181. package/sohelp-vform-modal/index.vue +2 -2
  182. package/sohelp-vform-select/README.md +9 -7
  183. package/sohelp-vform-select/index.vue +8 -7
  184. package/sohelp-vxe-grid/DefaultGridOptions.js +5 -3
  185. package/sohelp-vxe-grid/DefaultProps.js +0 -1
  186. package/sohelp-vxe-grid/README.md +540 -35
  187. package/sohelp-vxe-grid/SohelpGridConfig.js +8 -6
  188. package/sohelp-vxe-grid/index.vue +141 -94
  189. package/sohelp-vxe-grid-select/README.md +41 -26
  190. package/sohelp-vxe-table/README.md +23 -20
  191. package/sohelp-vxe-table/index.vue +5 -4
  192. package/sohelp-workflow/README.md +21 -17
  193. package/sohelp-workflow/index.vue +25 -22
  194. package/sohelp-workflow-drawer/README.md +41 -28
  195. package/sohelp-workflow-drawer/components/table.vue +158 -158
  196. package/sohelp-workflow-drawer/index.vue +86 -71
  197. package/sohelp-workflow-drawer/js/index.js +15 -13
  198. package/style/index.scss +0 -0
  199. package/utils/safe-eval.js +89 -0
  200. package/sohelp-dyn-select/props.js +0 -67
  201. package/sohelp-user-select/index.vue~ +0 -53
  202. package/sohelp-user-select/props.js +0 -71
@@ -1,642 +1,641 @@
1
- import { reactive, ref } from 'vue';
2
- import _DefaultGridOptions from '../js/DefaultGridOptions';
3
- import { moduleCache } from '../../cache/ModuleCache';
4
- import { usePermission } from '@/utils/use-permission';
5
- import { useMobile } from '@/utils/use-mobile';
6
- import { useI18n } from 'vue-i18n';
7
- import { EleMessage } from '@/components/ele-admin-plus/components';
8
-
9
- /**
10
- * 深拷贝
11
- * @param obj
12
- * @returns {any}
13
- */
14
- function deepClone(obj) {
15
- return JSON.parse(JSON.stringify(obj));
16
- }
17
-
18
- // 动态生成cellStyle函数
19
- function createDynamicStyle(styleConfigs = [], isCell = true) {
20
- // 预编译条件表达式为函数
21
- const compiledConfigs = styleConfigs.map((config) => ({
22
- ...config,
23
- conditionFn: new Function('$row', `return ${config.condition}`)
24
- }));
25
- return function ({ row, column }) {
26
- const _config = isCell ? compiledConfigs.filter((c) => c.name === column.field) : compiledConfigs;
27
- if (!_config || !_config.length) return null;
28
- try {
29
- for (const config of _config) {
30
- const conditionFn = new Function('$row', `return ${config.condition}`);
31
- if (conditionFn(row)) {
32
- return {
33
- color: config.fontColor,
34
- backgroundColor: config.bgColor,
35
- fontWeight: config?.bold ? 'bold' : '',
36
- fontStyle: config.italic ? 'italic' : '',
37
- textDecoration: config.strikethrough ? 'line-through' : config.underline ? 'underline' : ''
38
- };
39
- }
40
- }
41
- } catch (e) {
42
- console.error('条件解析错误:', e);
43
- }
44
- return null;
45
- };
46
- }
47
-
48
- const createDynamicCellStyle = (styleConfigs = []) => createDynamicStyle(styleConfigs, true);
49
- const createDynamicRowStyle = (styleConfigs = []) => createDynamicStyle(styleConfigs, false);
50
-
51
- /**
52
- * 商邦网格列配置列转化成VxeGrid列配置
53
- * @param property
54
- * @param sortList
55
- * @param f
56
- * @param formulaMap
57
- * @returns
58
- **/
59
- const switchVxeProperty = (property, sortList, f, formulaMap) => {
60
- let editor = {
61
- field: property.name,
62
- title: property.label,
63
- i18n: property.i18n,
64
- query: property.query,
65
- width: property.width || 120,
66
- type: property.editor || property.type,
67
- align: property.align || 'left',
68
- titleSuffix: property.tooltip ? { content: property.tooltip, placement: 'top' } : '',
69
-
70
- showOverflow: true,
71
- editRender: {
72
- enabled: property.edit,
73
- edit: property.edit,
74
- ...property.editorParam
75
- },
76
- fixed: !property.lock ? false : property.lockAlign,
77
- slots: {
78
- default: 'default_' + property.name,
79
- header: 'header_' + property.name
80
- },
81
- contentRender: {
82
- name: property.render,
83
- props: property.renderParam || {},
84
- event: 'event'
85
- }
86
- };
87
-
88
- /**
89
- * 自定义格式化渲然
90
- */
91
-
92
- if (property.render && property.render === 'customFormatter') {
93
- delete editor.slots.default;
94
- editor.type = 'html';
95
- editor.formatter = function ({ row, column, cellValue }) {
96
- if (property.renderParam) {
97
- try {
98
- const func = new Function('$row', '$column', '$value', `return ( () => { ${property.renderParam} })()`);
99
- return func(row, column, cellValue);
100
- } catch (e) {
101
- console.error('customFormatter 执行错误:', e);
102
- return cellValue; // 异常时返回原始值
103
- }
104
- } else {
105
- return cellValue;
106
- }
107
- };
108
- }
109
-
110
- if (property.length > 0) {
111
- editor.editRender.maxlength = property.length;
112
- }
113
-
114
- // 字典
115
- if (property.type === 'SohelpDict') {
116
- editor.editRender['code'] = property.editRender?.code || property.dict;
117
- }
118
-
119
- // 取默认显示值
120
- if (property.type === 'RELATION' && editor.labelField === '') {
121
- const fields = property.relationList?.split(',');
122
- editor.labelField = fields.includes('id') && fields.length > 1 ? fields[1] : fields[0];
123
- }
124
-
125
- // 自定义编辑插槽
126
- if (property.edit) {
127
- editor.slots.edit = 'edit_' + property.name;
128
- }
129
-
130
- if (
131
- ['SohelpImageUpload', 'SohelpFileUpload', 'SohelpRate', 'SohelpSwitch', 'SohelpProcess'].includes(property.editor)
132
- ) {
133
- delete editor.slots.edit; //不渲染编辑
134
- editor.editRender.enabled = false;
135
- }
136
-
137
- //筛选项配置
138
- if (editor.query) {
139
- switchFilterConfig(editor);
140
- }
141
-
142
- //是否统计
143
- const isSummary = f.find((item) => item.field === property.name);
144
-
145
- if (isSummary) {
146
- editor.slots['footer'] = 'footer_' + property.name;
147
- }
148
-
149
- // 排序
150
- if (sortList?.includes(property.name)) {
151
- editor['sortable'] = true;
152
- }
153
-
154
- if (property.name === 'id') {
155
- editor['width'] = 150;
156
- }
157
-
158
- return editor;
159
- };
160
-
161
- /**
162
- * 筛选配置
163
- */
164
- const switchFilterConfig = (editor) => {
165
- editor.filters = [{ data: '', checked: false }];
166
- editor.filterRender = {};
167
- editor.slots = {
168
- ...editor.slots,
169
- filter: 'filter_' + editor.field
170
- };
171
- };
172
-
173
- /**
174
- * properties中过滤掉删除的属性
175
- * @param {*} _filter
176
- * @returns
177
- */
178
- const filterFieldsByProperties = (_data) => {
179
- const data = { ..._data };
180
- const properties = new Set(data.properties?.map((item) => item.name));
181
-
182
- const filterArray = (list, key) => {
183
- return Array.isArray(list) ? list.filter((item) => properties.has(key ? item?.[key] : item)) : [];
184
- };
185
-
186
- let validProperties = Object.fromEntries(
187
- data.properties?.filter((item) => item.name && !item.hidden)?.map((item) => [item.name, item.label])
188
- );
189
-
190
- data.list = filterArray(data.list).filter((item) => {
191
- return item in validProperties;
192
- });
193
-
194
- data.filter.keywords = filterArray(data.filter.keywords);
195
-
196
- //过滤掉不在列表中的sort属性
197
- data.filter.sort = filterArray(data.filter.sort.filter((item) => data.list.some((f) => f === item)));
198
- data.properties = data.properties?.filter((item) => item.name && !item.hidden);
199
-
200
- data.filter.field = data.filter.field.filter((item) => {
201
- return item.name in validProperties;
202
- });
203
-
204
- return data;
205
- };
206
-
207
- /**
208
- * 工具栏默认图标
209
- */
210
- const defaultIcons = {
211
- 'crud.edit': 'vxe-icon-edit',
212
- 'crud.delete': 'vxe-icon-delete',
213
- 'crud.create': 'vxe-icon-add',
214
- 'crud.save': 'vxe-icon-save',
215
- 'crud.view': 'vxe-icon-eye-fill',
216
- 'workflow.submit': 'vxe-icon-success-circle',
217
- 'workflow.view': 'vxe-icon-file-txt',
218
- 'report.print': 'vxe-icon-print'
219
- };
220
-
221
- /**
222
- * 格式化工具栏
223
- */
224
- const getToolbarsButtons = (data) => {
225
- if (data?.length) {
226
- const groupedButtons = data.reduce((acc, button) => {
227
- const { buttonType } = button;
228
- if (!acc[buttonType]) {
229
- acc[buttonType] = [];
230
- }
231
-
232
- acc[buttonType].push(button);
233
- return acc;
234
- }, {});
235
-
236
- // 按钮格式化
237
- const formatterButton = (arr, type) => {
238
- return arr.map((item) => {
239
- let params = {};
240
- if (item.params && typeof item.params === 'string') {
241
- try {
242
- params = JSON.parse(item.params);
243
- } catch (e) {
244
- console.error('FormatterButton Error:', e);
245
- params = {};
246
- }
247
- }
248
- let obj = {
249
- code: item.id?.replace('-', '.') || item.type,
250
- name: item.title || item.name || '',
251
- id: item.id?.replace('-', '.'),
252
- pno: item.pno,
253
- handler: item.handler,
254
- buttonType: item.buttonType,
255
- icon: item.iconCls || defaultIcons[item.type],
256
- refid: item.refid,
257
- openType: item.openType,
258
- params: params,
259
- align: 'left'
260
- };
261
- return obj;
262
- });
263
- };
264
-
265
- const { common = [], more = [], batch = [] } = groupedButtons;
266
- let arr = [...formatterButton(common)];
267
- if (more.length > 0) {
268
- arr.push({
269
- code: 'more',
270
- name: '更多操作',
271
- dropdowns: formatterButton(more)
272
- });
273
- }
274
- if (batch.length > 0) {
275
- arr.push({
276
- code: 'batchMore',
277
- name: '批量操作',
278
- dropdowns: formatterButton(batch, 'batch'),
279
- disabled: true
280
- });
281
- }
282
- return arr;
283
- }
284
- return [];
285
- };
286
-
287
- /**
288
- * 网格列表配置
289
- * @returns
290
- */
291
- export function useSohelpGridConfig() {
292
- /**
293
- * 商邦网格列表配置参数
294
- * @type {UnwrapNestedRefs<{}>}
295
- */
296
- const SohelpConfig = reactive({});
297
- /**
298
- *
299
- * @type {UnwrapNestedRefs<{}>}
300
- */
301
- const propertiesMap = reactive({});
302
- /**
303
- * 网格列表统计
304
- */
305
- const footerData = reactive([]);
306
- /**
307
- *
308
- * @type {UnwrapNestedRefs<{}>}
309
- */
310
- const formulaMap = reactive({});
311
- /**
312
- * 配置是否加载完成
313
- */
314
- const isConfigInitialized = ref(false);
315
- const { t } = useI18n();
316
- /**
317
- * placeholder占位符映射
318
- */
319
- const placeholderMap = {
320
- SohelpSelect: '请选择ss',
321
- SohelpTreeSelect: '请选择',
322
- SohelpDict: '请选择',
323
- SohelpUserSelect: '请选择用户',
324
- SohelpDeptSelect: '请选择部门',
325
- SohelpRoleSelect: '请选择角色',
326
- SohelpDatePicker: '请选择日期',
327
- SohelpTimePicker: '请选择时间',
328
- SohelpDateTimePicker: '请选择日期时间',
329
- SohelpInput: '请输入',
330
- SohelpNumberInput: '请输入'
331
- };
332
-
333
- /**
334
- * 初始化商邦网格列表配置
335
- */
336
- const initial = async (isGridConfig, refid) => {
337
- if (!refid) throw new Error('配置列表请配置地址!');
338
- let _refid = refid;
339
- if (_refid.indexOf('!') === -1) _refid = refid + '!default';
340
-
341
- isConfigInitialized.value = false;
342
- const permission = usePermission();
343
- const { mobile } = useMobile();
344
-
345
- var batchButtonsIndex = -1;
346
- const DefaultGridOptions = reactive(deepClone(_DefaultGridOptions));
347
- /**获取列表配置*/
348
- const config = await moduleCache.getGrid(_refid);
349
-
350
- if (!config) {
351
- throw new Error(_refid + ' : 没有发现网格列表配置!');
352
- }
353
-
354
- try {
355
- Object.assign(SohelpConfig, filterFieldsByProperties(config));
356
- Object.assign(
357
- propertiesMap,
358
- (SohelpConfig?.properties || []).reduce((acc, cur) => {
359
- let param = {};
360
- if (cur?.editorParam && typeof cur.editorParam === 'string') {
361
- try {
362
- param = JSON.parse(cur.editorParam);
363
- } catch (e) {
364
- console.error('解析editorParam失败:', e);
365
- }
366
- }
367
- param.placeholder = param?.placeholder || placeholderMap[cur?.editor] || '';
368
- acc[cur.name] = { ...cur, editorParam: param };
369
- return acc;
370
- }, {})
371
- );
372
-
373
- // 计算公式
374
- if (config.formula && config.formula.length > 0) {
375
- Object.assign(
376
- formulaMap,
377
- config.formula.reduce((a, c) => (a[c.formulaField] || (a[c.formulaField] = c), a), {})
378
- );
379
- }
380
-
381
- // 按钮权限过滤
382
- const permissionButtons = config.toolbars.filter((f) => {
383
- if (!f.authority) {
384
- return true;
385
- }
386
- return permission.hasPermission(f.authority);
387
- });
388
- const buttons = getToolbarsButtons(permissionButtons);
389
- if (buttons && buttons.length > 0) {
390
- DefaultGridOptions.toolbarConfig.buttons = buttons;
391
- // 更多下拉菜单索引
392
- batchButtonsIndex = buttons.reduce((acc, curr, index) => {
393
- if (curr.code === 'batchMore') acc.push(index);
394
- return acc;
395
- }, []);
396
-
397
- //把标题转成国际化
398
- buttons.forEach((item) => {
399
- const code = item.code.replace('.', '-');
400
- const i18nKey = item.i18n === '' || code !== 'custom' ? 'grid.toolbar.' + code : item.i18n;
401
- if (i18nKey) {
402
- const i18n = t(i18nKey);
403
- item.name = i18n ? i18n : item.name;
404
- }
405
- });
406
- }
407
-
408
- //初始化属性列表配置
409
- let columns = [];
410
-
411
- //是否支持选择
412
- if (config?.selectionType === 'checkbox') {
413
- columns.push({
414
- field: '_checkbox',
415
- title: '',
416
- fixed: mobile.value ? false : 'left',
417
- type: 'checkbox',
418
- align: 'center',
419
- width: 40
420
- });
421
- }
422
-
423
- if (config?.selectionType === 'radio') {
424
- columns.push({
425
- field: '_radio',
426
- title: '',
427
- fixed: mobile.value ? false : 'left',
428
- type: 'radio',
429
- align: 'center',
430
- width: 40
431
- });
432
- }
433
-
434
- //是否显示行号
435
- if (config?.rowNumber) {
436
- columns.push({
437
- field: '_seq',
438
- type: 'seq',
439
- title: '#',
440
- fixed: mobile.value ? false : 'left',
441
- align: 'center',
442
- width: 40
443
- });
444
- }
445
-
446
- //是否支持拖动
447
- if (config?.rowDrag) {
448
- columns.unshift({
449
- title: '',
450
- fixed: mobile.value ? false : 'left',
451
- width: 40,
452
- align: 'center',
453
- dragSort: true,
454
- field: '_drag'
455
- });
456
- }
457
-
458
- //列拖动
459
- if (config?.columnDrag) {
460
- DefaultGridOptions.columnConfig.drag = true;
461
- }
462
-
463
- const requireData = {};
464
- //商邦列转换成Vxe列
465
- if (SohelpConfig.properties?.length > 0) {
466
- SohelpConfig.properties.forEach((column, index) => {
467
- let item = propertiesMap[column.name];
468
- const row = switchVxeProperty(item, SohelpConfig.filter?.sort, footerData, formulaMap);
469
-
470
- // 列表是否显示
471
- row.visible = SohelpConfig.list.includes(item.name);
472
- row.fixed = mobile.value ? false : row.fixed;
473
- // 添加操作栏插槽
474
- if (item.name === '_operation') {
475
- row.visible = true;
476
- row.slots = {
477
- default: '_operation'
478
- };
479
- }
480
-
481
- columns.push(row);
482
-
483
- // 校验规则,非空字段必填
484
- if (item.edit && item.notNull) {
485
- requireData[item.name] = [
486
- {
487
- required: true,
488
- message: row.title + '不能为空'
489
- }
490
- ];
491
- }
492
- });
493
-
494
- //没有工具栏则不显示操作拦
495
- if (config?.operations?.length == 0) {
496
- columns = columns.filter((item) => item.field != '_operation');
497
- }
498
-
499
- //将columns按照fields排序
500
- const sortColumns = columns
501
- .sort((a, b) => {
502
- if (a.field === '_operation') return 1;
503
- if (b.field === '_operation') return -1;
504
- return config.list.indexOf(a.field) - config.list.indexOf(b.field);
505
- })
506
- .sort((a, b) => {
507
- return b.visible - a.visible;
508
- });
509
-
510
- //_operation列安排最后一列
511
- DefaultGridOptions.columns = [
512
- ...sortColumns.filter((col) => col.field !== '_operation'),
513
- ...sortColumns.filter((col) => col.field === '_operation')
514
- ];
515
- DefaultGridOptions.editRules = { ...requireData };
516
- }
517
-
518
- //是否开启表尾
519
- Object.assign(
520
- footerData,
521
- (config.properties || [])
522
- .filter((item) => item.summaryType)
523
- ?.map((item) => {
524
- return {
525
- [item.name]: 0,
526
- summaryRender: item.summaryRender ? JSON.parse(item.summaryRender) : null,
527
- field: item.name,
528
- type: item.summaryType
529
- };
530
- })
531
- );
532
- DefaultGridOptions.showFooter = footerData?.length > 0;
533
-
534
- // 拦截编辑
535
- DefaultGridOptions.editConfig.beforeEditMethod = ({ row, column }) => {
536
- if (column.type === 'SohelpTextarea') {
537
- return false;
538
- }
539
- return true;
540
- };
541
-
542
- // 设置分页数据
543
- DefaultGridOptions.pagerConfig.enabled = config.paging;
544
- DefaultGridOptions.pagerConfig.pageSize = config.limit || 50;
545
-
546
- // 行列样式
547
- if (config.colors && config.colors.length > 0) {
548
- const rowData = config.colors.filter((item) => item.type !== 'c');
549
- const cellData = config.colors.filter((item) => item.type === 'c');
550
- if (rowData.length > 0) {
551
- DefaultGridOptions.rowStyle = createDynamicRowStyle(rowData);
552
- } else {
553
- DefaultGridOptions.stripe = true;
554
- }
555
- if (cellData.length > 0) {
556
- DefaultGridOptions.cellStyle = createDynamicCellStyle(cellData);
557
- }
558
- }
559
- isConfigInitialized.value = true;
560
-
561
- //序号列配置
562
- DefaultGridOptions.seqConfig = {
563
- seqMethod: ({ rowIndex }) => {
564
- const { pageSize, currentPage } = DefaultGridOptions.pagerConfig;
565
- return (currentPage - 1) * pageSize + rowIndex + 1;
566
- }
567
- };
568
-
569
- //转化初始化其他参数...
570
- } catch (error) {
571
- throw error; //重新抛出错误,以便调用者可以处理它
572
- }
573
-
574
- const operationsButtons = getOperationToolbars();
575
- return {
576
- gridOptions: DefaultGridOptions,
577
- sohelpConfig: SohelpConfig,
578
- propertiesMap: propertiesMap,
579
- batchButtonsIndex: batchButtonsIndex,
580
- footerData: footerData,
581
- formulaMap: formulaMap,
582
- operationsButtons: operationsButtons
583
- };
584
- };
585
-
586
- // 操作栏按钮分类
587
- const getOperationToolbars = () => {
588
- const buttonsMap = {};
589
- const permission = usePermission();
590
- SohelpConfig.operations
591
- ?.filter((f) => !f.authority || permission.hasPermission(f.authority))
592
- .map((button) => {
593
- const type = button.buttonType || 'common';
594
- const code = button.type === 'custom' ? button.id : button.type;
595
- if (!buttonsMap[type]) {
596
- buttonsMap[type] = [];
597
- }
598
- const title = button.type === 'custom' ? button.title : t('grid.toolbar.' + button.type?.replaceAll('.', '-'));
599
- let params = button.params || {};
600
- if (button.params && typeof button.params === 'string') {
601
- try {
602
- params = JSON.parse(button.params);
603
- } catch (e) {
604
- params = {};
605
- EleMessage.error('button.params配置JSON参数格式错误');
606
- }
607
- }
608
- buttonsMap[type].push({
609
- title: title || button.title,
610
- id: button.id,
611
- code: code,
612
- handler: button.handler,
613
- icon: button.iconCls,
614
- params: params,
615
- refid: button.refid,
616
- openType: button.openType,
617
- render: button.render
618
- });
619
- });
620
- return buttonsMap;
621
- };
622
-
623
- /**
624
- * 配置是否加载完成
625
- */
626
- const isConfigDone = async () => {
627
- return new Promise((resolve) => {
628
- if (isConfigInitialized.value) {
629
- resolve();
630
- } else {
631
- let timer = setInterval(() => {
632
- if (isConfigInitialized.value) {
633
- clearInterval(timer);
634
- resolve();
635
- }
636
- }, 10);
637
- }
638
- });
639
- };
640
-
641
- return { SohelpConfig, initial, isConfigDone, isConfigInitialized, moduleCache };
642
- }
1
+ import { reactive, ref } from 'vue';
2
+ import _DefaultGridOptions from '../js/DefaultGridOptions';
3
+ import { moduleCache } from '../../cache/ModuleCache';
4
+ import { usePermission } from '@/utils/use-permission';
5
+ import { useMobile } from '@/utils/use-mobile';
6
+ import { useI18n } from 'vue-i18n';
7
+ import { EleMessage } from '@/components/ele-admin-plus/components';
8
+ import { safeEval, safeFunctionExecSync } from '../../utils/safe-eval.js';
9
+
10
+ /**
11
+ * 深拷贝
12
+ * @param obj
13
+ * @returns {any}
14
+ */
15
+ function deepClone(obj) {
16
+ return JSON.parse(JSON.stringify(obj));
17
+ }
18
+
19
+ // 动态生成cellStyle函数
20
+ function createDynamicStyle(styleConfigs = [], isCell = true) {
21
+ // 预编译条件表达式为函数
22
+ const compiledConfigs = styleConfigs.map((config) => ({
23
+ ...config,
24
+ conditionFn: ($row) => safeEval(config.condition, { $row })
25
+ }));
26
+ return function ({ row, column }) {
27
+ const _config = isCell ? compiledConfigs.filter((c) => c.name === column.field) : compiledConfigs;
28
+ if (!_config || !_config.length) return null;
29
+ try {
30
+ for (const config of _config) {
31
+ if (config.conditionFn(row)) {
32
+ return {
33
+ color: config.fontColor,
34
+ backgroundColor: config.bgColor,
35
+ fontWeight: config?.bold ? 'bold' : '',
36
+ fontStyle: config.italic ? 'italic' : '',
37
+ textDecoration: config.strikethrough ? 'line-through' : config.underline ? 'underline' : ''
38
+ };
39
+ }
40
+ }
41
+ } catch (e) {
42
+ console.error('条件解析错误:', e);
43
+ }
44
+ return null;
45
+ };
46
+ }
47
+
48
+ const createDynamicCellStyle = (styleConfigs = []) => createDynamicStyle(styleConfigs, true);
49
+ const createDynamicRowStyle = (styleConfigs = []) => createDynamicStyle(styleConfigs, false);
50
+
51
+ /**
52
+ * 商邦网格列配置列转化成VxeGrid列配置
53
+ * @param property
54
+ * @param sortList
55
+ * @param f
56
+ * @param formulaMap
57
+ * @returns
58
+ **/
59
+ const switchVxeProperty = (property, sortList, f, formulaMap) => {
60
+ let editor = {
61
+ field: property.name,
62
+ title: property.label,
63
+ i18n: property.i18n,
64
+ query: property.query,
65
+ width: property.width || 120,
66
+ type: property.editor || property.type,
67
+ align: property.align || 'left',
68
+ titleSuffix: property.tooltip ? { content: property.tooltip, placement: 'top' } : '',
69
+
70
+ showOverflow: true,
71
+ editRender: {
72
+ enabled: property.edit,
73
+ edit: property.edit,
74
+ ...property.editorParam
75
+ },
76
+ fixed: !property.lock ? false : property.lockAlign,
77
+ slots: {
78
+ default: 'default_' + property.name,
79
+ header: 'header_' + property.name
80
+ },
81
+ contentRender: {
82
+ name: property.render,
83
+ props: property.renderParam || {},
84
+ event: 'event'
85
+ }
86
+ };
87
+
88
+ /**
89
+ * 自定义格式化渲然
90
+ */
91
+
92
+ if (property.render && property.render === 'customFormatter') {
93
+ delete editor.slots.default;
94
+ editor.type = 'html';
95
+ editor.formatter = function ({ row, column, cellValue }) {
96
+ if (property.renderParam) {
97
+ try {
98
+ return safeFunctionExecSync(property.renderParam, ['$row', '$column', '$value'], [row, column, cellValue]);
99
+ } catch (e) {
100
+ console.error('customFormatter 执行错误:', e);
101
+ return cellValue; // 异常时返回原始值
102
+ }
103
+ } else {
104
+ return cellValue;
105
+ }
106
+ };
107
+ }
108
+
109
+ if (property.length > 0) {
110
+ editor.editRender.maxlength = property.length;
111
+ }
112
+
113
+ // 字典
114
+ if (property.type === 'SohelpDict') {
115
+ editor.editRender['code'] = property.editRender?.code || property.dict;
116
+ }
117
+
118
+ // 取默认显示值
119
+ if (property.type === 'RELATION' && editor.labelField === '') {
120
+ const fields = property.relationList?.split(',');
121
+ editor.labelField = fields.includes('id') && fields.length > 1 ? fields[1] : fields[0];
122
+ }
123
+
124
+ // 自定义编辑插槽
125
+ if (property.edit) {
126
+ editor.slots.edit = 'edit_' + property.name;
127
+ }
128
+
129
+ if (
130
+ ['SohelpImageUpload', 'SohelpFileUpload', 'SohelpRate', 'SohelpSwitch', 'SohelpProcess'].includes(property.editor)
131
+ ) {
132
+ delete editor.slots.edit; //不渲染编辑
133
+ editor.editRender.enabled = false;
134
+ }
135
+
136
+ //筛选项配置
137
+ if (editor.query) {
138
+ switchFilterConfig(editor);
139
+ }
140
+
141
+ //是否统计
142
+ const isSummary = f.find((item) => item.field === property.name);
143
+
144
+ if (isSummary) {
145
+ editor.slots['footer'] = 'footer_' + property.name;
146
+ }
147
+
148
+ // 排序
149
+ if (sortList?.includes(property.name)) {
150
+ editor['sortable'] = true;
151
+ }
152
+
153
+ if (property.name === 'id') {
154
+ editor['width'] = 150;
155
+ }
156
+
157
+ return editor;
158
+ };
159
+
160
+ /**
161
+ * 筛选配置
162
+ */
163
+ const switchFilterConfig = (editor) => {
164
+ editor.filters = [{ data: '', checked: false }];
165
+ editor.filterRender = {};
166
+ editor.slots = {
167
+ ...editor.slots,
168
+ filter: 'filter_' + editor.field
169
+ };
170
+ };
171
+
172
+ /**
173
+ * properties中过滤掉删除的属性
174
+ * @param {*} _filter
175
+ * @returns
176
+ */
177
+ const filterFieldsByProperties = (_data) => {
178
+ const data = { ..._data };
179
+ const properties = new Set(data.properties?.map((item) => item.name));
180
+
181
+ const filterArray = (list, key) => {
182
+ return Array.isArray(list) ? list.filter((item) => properties.has(key ? item?.[key] : item)) : [];
183
+ };
184
+
185
+ let validProperties = Object.fromEntries(
186
+ data.properties?.filter((item) => item.name && !item.hidden)?.map((item) => [item.name, item.label])
187
+ );
188
+
189
+ data.list = filterArray(data.list).filter((item) => {
190
+ return item in validProperties;
191
+ });
192
+
193
+ data.filter.keywords = filterArray(data.filter.keywords);
194
+
195
+ //过滤掉不在列表中的sort属性
196
+ data.filter.sort = filterArray(data.filter.sort.filter((item) => data.list.some((f) => f === item)));
197
+ data.properties = data.properties?.filter((item) => item.name && !item.hidden);
198
+
199
+ data.filter.field = data.filter.field.filter((item) => {
200
+ return item.name in validProperties;
201
+ });
202
+
203
+ return data;
204
+ };
205
+
206
+ /**
207
+ * 工具栏默认图标
208
+ */
209
+ const defaultIcons = {
210
+ 'crud.edit': 'vxe-icon-edit',
211
+ 'crud.delete': 'vxe-icon-delete',
212
+ 'crud.create': 'vxe-icon-add',
213
+ 'crud.save': 'vxe-icon-save',
214
+ 'crud.view': 'vxe-icon-eye-fill',
215
+ 'workflow.submit': 'vxe-icon-success-circle',
216
+ 'workflow.view': 'vxe-icon-file-txt',
217
+ 'report.print': 'vxe-icon-print'
218
+ };
219
+
220
+ /**
221
+ * 格式化工具栏
222
+ */
223
+ const getToolbarsButtons = (data) => {
224
+ if (data?.length) {
225
+ const groupedButtons = data.reduce((acc, button) => {
226
+ const { buttonType } = button;
227
+ if (!acc[buttonType]) {
228
+ acc[buttonType] = [];
229
+ }
230
+
231
+ acc[buttonType].push(button);
232
+ return acc;
233
+ }, {});
234
+
235
+ // 按钮格式化
236
+ const formatterButton = (arr, type) => {
237
+ return arr.map((item) => {
238
+ let params = {};
239
+ if (item.params && typeof item.params === 'string') {
240
+ try {
241
+ params = JSON.parse(item.params);
242
+ } catch (e) {
243
+ console.error('FormatterButton Error:', e);
244
+ params = {};
245
+ }
246
+ }
247
+ let obj = {
248
+ code: item.id?.replace('-', '.') || item.type,
249
+ name: item.title || item.name || '',
250
+ id: item.id?.replace('-', '.'),
251
+ pno: item.pno,
252
+ handler: item.handler,
253
+ buttonType: item.buttonType,
254
+ icon: item.iconCls || defaultIcons[item.type],
255
+ refid: item.refid,
256
+ openType: item.openType,
257
+ params: params,
258
+ align: 'left'
259
+ };
260
+ return obj;
261
+ });
262
+ };
263
+
264
+ const { common = [], more = [], batch = [] } = groupedButtons;
265
+ let arr = [...formatterButton(common)];
266
+ if (more.length > 0) {
267
+ arr.push({
268
+ code: 'more',
269
+ name: '更多操作',
270
+ dropdowns: formatterButton(more)
271
+ });
272
+ }
273
+ if (batch.length > 0) {
274
+ arr.push({
275
+ code: 'batchMore',
276
+ name: '批量操作',
277
+ dropdowns: formatterButton(batch, 'batch'),
278
+ disabled: true
279
+ });
280
+ }
281
+ return arr;
282
+ }
283
+ return [];
284
+ };
285
+
286
+ /**
287
+ * 网格列表配置
288
+ * @returns
289
+ */
290
+ export function useSohelpGridConfig() {
291
+ /**
292
+ * 商邦网格列表配置参数
293
+ * @type {UnwrapNestedRefs<{}>}
294
+ */
295
+ const SohelpConfig = reactive({});
296
+ /**
297
+ *
298
+ * @type {UnwrapNestedRefs<{}>}
299
+ */
300
+ const propertiesMap = reactive({});
301
+ /**
302
+ * 网格列表统计
303
+ */
304
+ const footerData = reactive([]);
305
+ /**
306
+ *
307
+ * @type {UnwrapNestedRefs<{}>}
308
+ */
309
+ const formulaMap = reactive({});
310
+ /**
311
+ * 配置是否加载完成
312
+ */
313
+ const isConfigInitialized = ref(false);
314
+ const { t } = useI18n();
315
+ /**
316
+ * placeholder占位符映射
317
+ */
318
+ const placeholderMap = {
319
+ SohelpSelect: '请选择ss',
320
+ SohelpTreeSelect: '请选择',
321
+ SohelpDict: '请选择',
322
+ SohelpUserSelect: '请选择用户',
323
+ SohelpDeptSelect: '请选择部门',
324
+ SohelpRoleSelect: '请选择角色',
325
+ SohelpDatePicker: '请选择日期',
326
+ SohelpTimePicker: '请选择时间',
327
+ SohelpDateTimePicker: '请选择日期时间',
328
+ SohelpInput: '请输入',
329
+ SohelpNumberInput: '请输入'
330
+ };
331
+
332
+ /**
333
+ * 初始化商邦网格列表配置
334
+ */
335
+ const initial = async (isGridConfig, refid) => {
336
+ if (!refid) throw new Error('配置列表请配置地址!');
337
+ let _refid = refid;
338
+ if (_refid.indexOf('!') === -1) _refid = refid + '!default';
339
+
340
+ isConfigInitialized.value = false;
341
+ const permission = usePermission();
342
+ const { mobile } = useMobile();
343
+
344
+ var batchButtonsIndex = -1;
345
+ const DefaultGridOptions = reactive(deepClone(_DefaultGridOptions));
346
+ /**获取列表配置*/
347
+ const config = await moduleCache.getGrid(_refid);
348
+
349
+ if (!config) {
350
+ throw new Error(_refid + ' : 没有发现网格列表配置!');
351
+ }
352
+
353
+ try {
354
+ Object.assign(SohelpConfig, filterFieldsByProperties(config));
355
+ Object.assign(
356
+ propertiesMap,
357
+ (SohelpConfig?.properties || []).reduce((acc, cur) => {
358
+ let param = {};
359
+ if (cur?.editorParam && typeof cur.editorParam === 'string') {
360
+ try {
361
+ param = JSON.parse(cur.editorParam);
362
+ } catch (e) {
363
+ console.error('解析editorParam失败:', e);
364
+ }
365
+ }
366
+ param.placeholder = param?.placeholder || placeholderMap[cur?.editor] || '';
367
+ acc[cur.name] = { ...cur, editorParam: param };
368
+ return acc;
369
+ }, {})
370
+ );
371
+
372
+ // 计算公式
373
+ if (config.formula && config.formula.length > 0) {
374
+ Object.assign(
375
+ formulaMap,
376
+ config.formula.reduce((a, c) => (a[c.formulaField] || (a[c.formulaField] = c), a), {})
377
+ );
378
+ }
379
+
380
+ // 按钮权限过滤
381
+ const permissionButtons = config.toolbars.filter((f) => {
382
+ if (!f.authority) {
383
+ return true;
384
+ }
385
+ return permission.hasPermission(f.authority);
386
+ });
387
+ const buttons = getToolbarsButtons(permissionButtons);
388
+ if (buttons && buttons.length > 0) {
389
+ DefaultGridOptions.toolbarConfig.buttons = buttons;
390
+ // 更多下拉菜单索引
391
+ batchButtonsIndex = buttons.reduce((acc, curr, index) => {
392
+ if (curr.code === 'batchMore') acc.push(index);
393
+ return acc;
394
+ }, []);
395
+
396
+ //把标题转成国际化
397
+ buttons.forEach((item) => {
398
+ const code = item.code.replace('.', '-');
399
+ const i18nKey = item.i18n === '' || code !== 'custom' ? 'grid.toolbar.' + code : item.i18n;
400
+ if (i18nKey) {
401
+ const i18n = t(i18nKey);
402
+ item.name = i18n ? i18n : item.name;
403
+ }
404
+ });
405
+ }
406
+
407
+ //初始化属性列表配置
408
+ let columns = [];
409
+
410
+ //是否支持选择
411
+ if (config?.selectionType === 'checkbox') {
412
+ columns.push({
413
+ field: '_checkbox',
414
+ title: '',
415
+ fixed: mobile.value ? false : 'left',
416
+ type: 'checkbox',
417
+ align: 'center',
418
+ width: 40
419
+ });
420
+ }
421
+
422
+ if (config?.selectionType === 'radio') {
423
+ columns.push({
424
+ field: '_radio',
425
+ title: '',
426
+ fixed: mobile.value ? false : 'left',
427
+ type: 'radio',
428
+ align: 'center',
429
+ width: 40
430
+ });
431
+ }
432
+
433
+ //是否显示行号
434
+ if (config?.rowNumber) {
435
+ columns.push({
436
+ field: '_seq',
437
+ type: 'seq',
438
+ title: '#',
439
+ fixed: mobile.value ? false : 'left',
440
+ align: 'center',
441
+ width: 40
442
+ });
443
+ }
444
+
445
+ //是否支持拖动
446
+ if (config?.rowDrag) {
447
+ columns.unshift({
448
+ title: '',
449
+ fixed: mobile.value ? false : 'left',
450
+ width: 40,
451
+ align: 'center',
452
+ dragSort: true,
453
+ field: '_drag'
454
+ });
455
+ }
456
+
457
+ //列拖动
458
+ if (config?.columnDrag) {
459
+ DefaultGridOptions.columnConfig.drag = true;
460
+ }
461
+
462
+ const requireData = {};
463
+ //商邦列转换成Vxe列
464
+ if (SohelpConfig.properties?.length > 0) {
465
+ SohelpConfig.properties.forEach((column, index) => {
466
+ let item = propertiesMap[column.name];
467
+ const row = switchVxeProperty(item, SohelpConfig.filter?.sort, footerData, formulaMap);
468
+
469
+ // 列表是否显示
470
+ row.visible = SohelpConfig.list.includes(item.name);
471
+ row.fixed = mobile.value ? false : row.fixed;
472
+ // 添加操作栏插槽
473
+ if (item.name === '_operation') {
474
+ row.visible = true;
475
+ row.slots = {
476
+ default: '_operation'
477
+ };
478
+ }
479
+
480
+ columns.push(row);
481
+
482
+ // 校验规则,非空字段必填
483
+ if (item.edit && item.notNull) {
484
+ requireData[item.name] = [
485
+ {
486
+ required: true,
487
+ message: row.title + '不能为空'
488
+ }
489
+ ];
490
+ }
491
+ });
492
+
493
+ //没有工具栏则不显示操作拦
494
+ if (config?.operations?.length == 0) {
495
+ columns = columns.filter((item) => item.field != '_operation');
496
+ }
497
+
498
+ //将columns按照fields排序
499
+ const sortColumns = columns
500
+ .sort((a, b) => {
501
+ if (a.field === '_operation') return 1;
502
+ if (b.field === '_operation') return -1;
503
+ return config.list.indexOf(a.field) - config.list.indexOf(b.field);
504
+ })
505
+ .sort((a, b) => {
506
+ return b.visible - a.visible;
507
+ });
508
+
509
+ //_operation列安排最后一列
510
+ DefaultGridOptions.columns = [
511
+ ...sortColumns.filter((col) => col.field !== '_operation'),
512
+ ...sortColumns.filter((col) => col.field === '_operation')
513
+ ];
514
+ DefaultGridOptions.editRules = { ...requireData };
515
+ }
516
+
517
+ //是否开启表尾
518
+ Object.assign(
519
+ footerData,
520
+ (config.properties || [])
521
+ .filter((item) => item.summaryType)
522
+ ?.map((item) => {
523
+ return {
524
+ [item.name]: 0,
525
+ summaryRender: item.summaryRender ? JSON.parse(item.summaryRender) : null,
526
+ field: item.name,
527
+ type: item.summaryType
528
+ };
529
+ })
530
+ );
531
+ DefaultGridOptions.showFooter = footerData?.length > 0;
532
+
533
+ // 拦截编辑
534
+ DefaultGridOptions.editConfig.beforeEditMethod = ({ row, column }) => {
535
+ if (column.type === 'SohelpTextarea') {
536
+ return false;
537
+ }
538
+ return true;
539
+ };
540
+
541
+ // 设置分页数据
542
+ DefaultGridOptions.pagerConfig.enabled = config.paging;
543
+ DefaultGridOptions.pagerConfig.pageSize = config.limit || 50;
544
+
545
+ // 行列样式
546
+ if (config.colors && config.colors.length > 0) {
547
+ const rowData = config.colors.filter((item) => item.type !== 'c');
548
+ const cellData = config.colors.filter((item) => item.type === 'c');
549
+ if (rowData.length > 0) {
550
+ DefaultGridOptions.rowStyle = createDynamicRowStyle(rowData);
551
+ } else {
552
+ DefaultGridOptions.stripe = true;
553
+ }
554
+ if (cellData.length > 0) {
555
+ DefaultGridOptions.cellStyle = createDynamicCellStyle(cellData);
556
+ }
557
+ }
558
+ isConfigInitialized.value = true;
559
+
560
+ //序号列配置
561
+ DefaultGridOptions.seqConfig = {
562
+ seqMethod: ({ rowIndex }) => {
563
+ const { pageSize, currentPage } = DefaultGridOptions.pagerConfig;
564
+ return (currentPage - 1) * pageSize + rowIndex + 1;
565
+ }
566
+ };
567
+
568
+ //转化初始化其他参数...
569
+ } catch (error) {
570
+ throw error; //重新抛出错误,以便调用者可以处理它
571
+ }
572
+
573
+ const operationsButtons = getOperationToolbars();
574
+ return {
575
+ gridOptions: DefaultGridOptions,
576
+ sohelpConfig: SohelpConfig,
577
+ propertiesMap: propertiesMap,
578
+ batchButtonsIndex: batchButtonsIndex,
579
+ footerData: footerData,
580
+ formulaMap: formulaMap,
581
+ operationsButtons: operationsButtons
582
+ };
583
+ };
584
+
585
+ // 操作栏按钮分类
586
+ const getOperationToolbars = () => {
587
+ const buttonsMap = {};
588
+ const permission = usePermission();
589
+ SohelpConfig.operations
590
+ ?.filter((f) => !f.authority || permission.hasPermission(f.authority))
591
+ .map((button) => {
592
+ const type = button.buttonType || 'common';
593
+ const code = button.type === 'custom' ? button.id : button.type;
594
+ if (!buttonsMap[type]) {
595
+ buttonsMap[type] = [];
596
+ }
597
+ const title = button.type === 'custom' ? button.title : t('grid.toolbar.' + button.type?.replaceAll('.', '-'));
598
+ let params = button.params || {};
599
+ if (button.params && typeof button.params === 'string') {
600
+ try {
601
+ params = JSON.parse(button.params);
602
+ } catch (e) {
603
+ params = {};
604
+ EleMessage.error('button.params配置JSON参数格式错误');
605
+ }
606
+ }
607
+ buttonsMap[type].push({
608
+ title: title || button.title,
609
+ id: button.id,
610
+ code: code,
611
+ handler: button.handler,
612
+ icon: button.iconCls,
613
+ params: params,
614
+ refid: button.refid,
615
+ openType: button.openType,
616
+ render: button.render
617
+ });
618
+ });
619
+ return buttonsMap;
620
+ };
621
+
622
+ /**
623
+ * 配置是否加载完成
624
+ */
625
+ const isConfigDone = async () => {
626
+ return new Promise((resolve) => {
627
+ if (isConfigInitialized.value) {
628
+ resolve();
629
+ } else {
630
+ let timer = setInterval(() => {
631
+ if (isConfigInitialized.value) {
632
+ clearInterval(timer);
633
+ resolve();
634
+ }
635
+ }, 10);
636
+ }
637
+ });
638
+ };
639
+
640
+ return { SohelpConfig, initial, isConfigDone, isConfigInitialized, moduleCache };
641
+ }