@utogether/udp-core 1.0.0 → 1.0.1

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 (80) hide show
  1. package/dist/{403-B1R-4vXw.js → 403-JWjatlxJ.js} +1 -1
  2. package/dist/{404-fXPl8csw.js → 404-BcdMJfPb.js} +1 -1
  3. package/dist/{500-eI5842YB.js → 500-bsa3F_cc.js} +1 -1
  4. package/dist/{AuthorityInfo-CfVH6PaB.js → AuthorityInfo-CqItgNs5.js} +1 -1
  5. package/dist/{AuthorityInfo.vue_vue_type_style_index_0_lang-DbK-f8jH.js → AuthorityInfo.vue_vue_type_style_index_0_lang-32L40GY2.js} +1 -1
  6. package/dist/{Company-CYC9Avfz.js → Company-DVff9IA7.js} +3 -3
  7. package/dist/{CompanyPanel-B4MzoqN_.js → CompanyPanel-CNrdq4XE.js} +1 -1
  8. package/dist/{Department-B4BNSiYx.js → Department-CqcpfL4i.js} +3 -3
  9. package/dist/{DepartmentPanel-zJO89L2O.js → DepartmentPanel-Bvti4LGu.js} +1 -1
  10. package/dist/{DesignPanel-S8P0J97f.js → DesignPanel-CjykspE1.js} +1 -1
  11. package/dist/{DesignPanel.vue_vue_type_style_index_0_lang-DW-_Vqrr.js → DesignPanel.vue_vue_type_style_index_0_lang-BK9EERdd.js} +2 -2
  12. package/dist/{DictView-bIS5-rK-.js → DictView-q7kR9K--.js} +9 -9
  13. package/dist/InvOrganization-DI45LqZV.js +260 -0
  14. package/dist/{Org-kXHSjsgJ.js → Org-CZju_ZiR.js} +1 -1
  15. package/dist/{Preview-CRyiwUIR.js → Preview-Cm_7RhYU.js} +1 -1
  16. package/dist/{ReportDefine-WZYIx8Sm.js → ReportDefine-CJVlQ--7.js} +1 -1
  17. package/dist/{ReportDesign-D-7GKgpb.js → ReportDesign-B0unlrkt.js} +2 -2
  18. package/dist/{ReportQuery-BIIJny6w.js → ReportQuery-BKuMCEvF.js} +2 -2
  19. package/dist/{ReportQueryFrom-OoUl7N2O.js → ReportQueryFrom-DAngMJLU.js} +1 -1
  20. package/dist/{ReportQueryFrom.vue_vue_type_style_index_0_lang-B878fgj8.js → ReportQueryFrom.vue_vue_type_style_index_0_lang-CPpwmztJ.js} +1 -1
  21. package/dist/{ReportTemplate-Cfeq9US-.js → ReportTemplate-8YH3L8Pv.js} +1 -1
  22. package/dist/{Role-BwTV2QMH.js → Role-MxI30-0W.js} +3 -3
  23. package/dist/{RoleAssign-De1JjOun.js → RoleAssign-BzUY_y_y.js} +3 -3
  24. package/dist/{RolePanel-pUBXsqCM.js → RolePanel-CXdcvsR5.js} +1 -1
  25. package/dist/{RolePanel-E3RcdByM.js → RolePanel-DS_TErTn.js} +1 -1
  26. package/dist/{RolePanel.vue_vue_type_script_setup_true_lang-CTIad9_Q.js → RolePanel.vue_vue_type_script_setup_true_lang-DJKu6PXz.js} +1 -1
  27. package/dist/{RolePanel.vue_vue_type_script_setup_true_lang-B2pQwHb0.js → RolePanel.vue_vue_type_script_setup_true_lang-Ddl-A7Zh.js} +3 -3
  28. package/dist/{ScrollPanel.vue_vue_type_style_index_0_lang-vMR1fBi0.js → ScrollPanel.vue_vue_type_style_index_0_lang-DnchUgIF.js} +1 -1
  29. package/dist/{Staff-Czm7A8vI.js → Staff-D7tXo_Gn.js} +3 -3
  30. package/dist/StaffInfo-Bk8BY8PO.js +4 -0
  31. package/dist/{StaffInfo.vue_vue_type_style_index_0_lang-DMTL7KCh.js → StaffInfo.vue_vue_type_script_setup_true_lang-DqKwZi5f.js} +1 -1
  32. package/dist/{StaffPanel-CHk60LEz.js → StaffPanel-VtpGCTIq.js} +1 -1
  33. package/dist/{StaffPanel.vue_vue_type_script_setup_true_lang-iPKLb5wG.js → StaffPanel.vue_vue_type_script_setup_true_lang-C3Ixs12y.js} +46 -49
  34. package/dist/{SysUser-BGwbttRn.js → SysUser-D0Q6OvD7.js} +2 -2
  35. package/dist/{SysUserPanel-BCbKoLKt.js → SysUserPanel-1_vrsANQ.js} +1 -1
  36. package/dist/{SysUserPanel.vue_vue_type_script_setup_true_lang-0QUjnhjF.js → SysUserPanel.vue_vue_type_script_setup_true_lang-C5XEmxsV.js} +1 -2
  37. package/dist/{SystemMenu-BkqZSDKl.js → SystemMenu-9PG3vESE.js} +2 -2
  38. package/dist/{UserInfo-BsyAcT2d.js → UserInfo-qgXUEGwi.js} +1 -1
  39. package/dist/{UserInfo.vue_vue_type_style_index_0_lang-D0-KDxAh.js → UserInfo.vue_vue_type_style_index_0_lang-CN0C5rVk.js} +1 -1
  40. package/dist/{childView-CyuLTUqC.js → childView-C7ZSA5fR.js} +1 -1
  41. package/dist/{childView-CF83nhxb.js → childView-yV2QLwfA.js} +1 -1
  42. package/dist/{childView.vue_vue_type_style_index_0_lang-Cch4lE-i.js → childView.vue_vue_type_style_index_0_lang-DdKxPGdh.js} +1 -1
  43. package/dist/{childView.vue_vue_type_style_index_0_lang-CNSgGda3.js → childView.vue_vue_type_style_index_0_lang-bkmucBUL.js} +1 -1
  44. package/dist/{code-rule-Bz-gnktN.js → code-rule-95K1jr-u.js} +1 -1
  45. package/dist/core.es.js +1 -1
  46. package/dist/core.umd.js +63 -63
  47. package/dist/{cron-task-CIifSUdW.js → cron-task-DGrQwOHs.js} +1 -1
  48. package/dist/{frameView-_d2mqjjQ.js → frameView-7SmME93D.js} +1 -1
  49. package/dist/index-OswH7SsT.js +9937 -0
  50. package/dist/{layoutView-DLKVepB8.js → layoutView-C6WIVWGZ.js} +2 -2
  51. package/dist/{login-LREiDfFU.js → login-BhCMeCLS.js} +4 -4
  52. package/dist/{lov-view-DDrIVILB.js → lov-view-DoF5LqFQ.js} +2 -2
  53. package/dist/{menuInfo-B1FUV-Sk.js → menuInfo-CNzGQwOD.js} +1 -1
  54. package/dist/{menuInfo.vue_vue_type_style_index_0_lang-Cnk3vdtD.js → menuInfo.vue_vue_type_style_index_0_lang-51SYxVc_.js} +1 -1
  55. package/dist/{pda-app-CRhVGijN.js → pda-app-nn3llDUx.js} +1 -1
  56. package/dist/{redirect-DiaNDu8F.js → redirect-CmMplDV4.js} +1 -1
  57. package/dist/{resource-BCwx9fEv.js → resource-gVFFMO9l.js} +1 -1
  58. package/dist/{su-welcome-189A7N4r.js → su-welcome-BN_s_RX_.js} +1 -1
  59. package/dist/{sys-config-BZ3sejow.js → sys-config-DGutV-VX.js} +1 -1
  60. package/dist/udp-core.css +2 -2
  61. package/dist/{utogether-r08LNiIZ.js → utogether-wFDCI28t.js} +1 -1
  62. package/package.json +2 -1
  63. package/src/components/udp/form-upload.vue +132 -0
  64. package/src/components/udp/index.ts +4 -0
  65. package/src/components/udp/modal-form.vue +180 -0
  66. package/src/components/udp/utils.ts +40 -0
  67. package/src/main.ts +5 -4
  68. package/src/plugins/vxe-table/index.ts +3 -3
  69. package/src/plugins/vxe-table/render.tsx +604 -184
  70. package/src/utils/udp/useRender.ts +420 -0
  71. package/src/views/organization/inv-org/InvOrganization.vue +2 -1
  72. package/src/views/organization/staff/StaffInfo.vue +0 -30
  73. package/src/views/organization/staff/StaffPanel.vue +4 -3
  74. package/src/views/system/role/AuthorityInfo.vue +1 -19
  75. package/src/views/system/sysUser/SysUserPanel.vue +1 -1
  76. package/src/views/udev/dict/DictView.vue +2 -2
  77. package/src/views/ulogin/login.vue +1 -1
  78. package/dist/InvOrganization-MuM2jtsG.js +0 -66
  79. package/dist/StaffInfo-DJzvBuxy.js +0 -4
  80. package/dist/index-BKIw8tSn.js +0 -9195
@@ -1,22 +1,27 @@
1
1
  /*
2
- * @Author: levi7754 levi7754@163.com
3
- * @Date: 2023-10-12 13:53:07
2
+ * @Author: wei.li
3
+ * @Date: 2021-12-01 09:18:50
4
4
  * @LastEditors: levi7754 levi7754@163.com
5
- * @LastEditTime: 2025-04-29 14:10:34
6
- * @FilePath: /sitzone-mes/src/plugins/vxe-table/render.tsx
7
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
5
+ * @LastEditTime: 2025-07-14 18:17:16
6
+ * @Description: file content
8
7
  */
9
8
 
9
+ // @ts-nocheck
10
+
11
+ import dayjs from 'dayjs';
12
+ import { isArray, isEmpty, findTree, isObject, isPlainObject } from 'xe-utils';
10
13
  import type {
14
+ FormItemRenderOptions,
11
15
  FormItemContentRenderParams,
12
16
  VxeColumnPropTypes,
13
17
  VxeGlobalRendererHandles
14
18
  } from 'vxe-table';
15
19
 
16
- import { VxeUI } from 'vxe-pc-ui';
17
-
18
- import { findTree, isArray, isEmpty } from 'xe-utils';
20
+ import { cookies, storageLocal } from '@utogether/utils';
19
21
 
22
+ interface SuFormItemRenderOptions extends FormItemRenderOptions {
23
+ sourceData: IRecord;
24
+ }
20
25
  interface SuEditRender extends VxeColumnPropTypes.EditRender {
21
26
  sourceData: IRecord;
22
27
  }
@@ -24,115 +29,249 @@ interface SuRenderCellOptions extends VxeGlobalRendererHandles.RenderCellOptions
24
29
  sourceData: IRecord[];
25
30
  }
26
31
 
27
- VxeUI.renderer.add('#iconselect', {
28
- renderEdit(renderOpts, params) {
29
- const { row, column } = params;
30
- return [<iconSelect v-model={row[column.field]} teleported={false} />];
31
- },
32
- renderCell(renderOpts, params) {
33
- const { row, column } = params;
34
- return [<IconifyIconOffline icon={row[column.field]} style="font-size: 16px;" />];
35
- },
36
- renderItemContent(renderOpts, params) {
37
- const { data, field } = params;
38
- return [<iconSelect v-model={data[field]} teleported={true} />];
39
- }
40
- });
41
-
42
- VxeUI.renderer.add('$treeSelect', {
43
- renderEdit(renderOpts: SuEditRender, params) {
44
- const { row, column } = params;
45
- const { props, sourceData, events } = renderOpts;
46
-
47
- return [
48
- <el-tree-select
49
- v-model={row[column.field]}
50
- data={sourceData}
51
- check-strictly
52
- {...props}
53
- filterable
54
- onCheckChange={(node, selected, isLeaf) => onCheckChange(node, selected, isLeaf, events)}
55
- onNodeClick={(data, node, treeNode) => onNodeClick(data, node, treeNode, events)}
56
- onCurrentChange={(data, node) => onCurrentChange(data, node, events)}
57
- />
58
- ];
59
- },
60
- renderCell(renderOpts: SuRenderCellOptions, params) {
61
- const { row, column } = params;
62
- const { sourceData, props = {} } = renderOpts;
63
- const { children = 'children', label = 'label' } = props;
64
- const data = findTree(sourceData, item => item['value'] === row[column.field], { children });
65
- return data ? [<span>{data.item[label]}</span>] : null;
66
- },
67
- renderItemContent(renderOpts: SuFormItemRenderOptions, params) {
68
- const { data, field } = params;
69
- const { props, sourceData, events } = renderOpts;
70
- return [
71
- <el-tree-select
72
- v-model={data[field]}
73
- data={sourceData}
74
- check-strictly
75
- {...props}
76
- filterable
77
- onCheckChange={(node, selected, isLeaf) => onCheckChange(node, selected, isLeaf, events)}
78
- onNodeClick={(data, node, treeNode) => onNodeClick(data, node, treeNode, events)}
79
- onCurrentChange={(data, node) => onCurrentChange(data, node, events)}
80
- />
81
- ];
82
- }
83
- });
32
+ export const VxetableRender = (VXETable, { serviceApi, i18n }) => {
33
+ const dict = storageLocal.getItem('kLov');
84
34
 
85
- /**
86
- * 当复选框被点击的时候触发
87
- * @param node 传递给 data 属性的数组中该节点所对应的对象
88
- * @param selected 节点本身是否被选中
89
- * @param isLeaf 节点的子树中是否有被选中的节点
90
- */
91
- const onCheckChange = (node, selected, isLeaf, events) => {
92
- console.log(node, selected, isLeaf);
93
- events?.checkChange && events?.checkChange(node, selected, isLeaf);
94
- };
95
- /**
96
- * 节点被点击的时候触发
97
- * @param nodeObject 点击的节点对象
98
- * @param node TreeNode 的 node 属性
99
- * @param treeNode TreeNode
100
- */
101
- const onNodeClick = (nodeObject, node, treeNode, events) => {
102
- events?.checkChange && events?.checkChange(nodeObject, node, treeNode);
103
- };
104
- /**
105
- * 当前选中节点变化时触发的事件
106
- * @param data 当前节点的数据
107
- * @param node 当前节点的 Node 对象
108
- */
109
- const onCurrentChange = (data, node, events) => {
110
- events?.checkChange && events?.checkChange(data, node);
111
- };
35
+ // form render
36
+ VXETable.renderer.add('#SuSelect', {
37
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
38
+ const { row, column } = params;
39
+ const { options, props, optionProps = {}, events } = renderOpts;
40
+ // @ts-ignore
41
+ const { label = 'label', value = 'value' } = optionProps;
42
+ const { loading = false, multiple, mapField } = props;
43
+ const componentHook = useComponent();
112
44
 
113
- export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
114
- console.log(serviceApi, dict, i18n);
115
- VXETable.renderer.add('#select', {
116
- renderEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
45
+ // 多选时
46
+ const modelField = multiple ? `_${column.field}` : column.field;
47
+ // 默认值
48
+ componentHook.setDefaultValue(props, row, column.field);
49
+ /**
50
+ * @description: 远程搜索对应的函数
51
+ * @param {*} val 录入的参数
52
+ */
53
+ function remoteMethod(query) {
54
+ componentHook.remote(query, column.field, renderOpts);
55
+ }
56
+
57
+ /**
58
+ * @description: 选中值发生变化时触发
59
+ * @param {*} val 目前的选中值
60
+ */
61
+ function onChange(val) {
62
+ componentHook.selectChange(val, data, column.field, renderOpts, {
63
+ column,
64
+ datasource: 'row'
65
+ });
66
+ }
67
+
68
+ function onInput(val) {
69
+ events?.input && events.input(params, val);
70
+ }
71
+ /**
72
+ * @description: 可清空的单选模式下用户点击清空按钮时触发
73
+ */
74
+ function onClear() {
75
+ componentHook.clear(row, column.field, mapField, events, 'row');
76
+ }
77
+
78
+ function onFocus() {
79
+ !options.length && remoteMethod('');
80
+ events?.focus && events.focus(params, column.field);
81
+ }
82
+
83
+ return [
84
+ <el-select
85
+ v-model={row[modelField]}
86
+ filterable
87
+ remote
88
+ clearable
89
+ placeholder="请录入关键字搜索"
90
+ style="width: 100%"
91
+ remote-method={remoteMethod}
92
+ loading={loading}
93
+ {...props}
94
+ onFocus={() => onFocus()}
95
+ onChange={v => onChange(v)}
96
+ onClear={() => onClear()}
97
+ onInput={v => onInput(v)}
98
+ >
99
+ {options.map(item => {
100
+ return <el-option key={item[value]} label={item[label]} value={item[value]}></el-option>;
101
+ })}
102
+ </el-select>
103
+ ];
104
+ },
105
+ // 可编辑显示模板
106
+ renderTableCell(renderOpts, params) {
117
107
  const { row, column } = params;
108
+ const { props } = renderOpts;
109
+ const { textValue, multiple } = props;
110
+ let val = row[column.field];
111
+ if (textValue) {
112
+ val = eval(`row.${textValue}`) || row[column.field];
113
+ }
114
+ if (val && multiple && isArray(val)) {
115
+ val = val && val.join(',');
116
+ }
117
+ return [<span>{val}</span>];
118
+ },
119
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
120
+ const { data, field } = params;
118
121
  const { options, props, optionProps = {}, events } = renderOpts;
119
122
  // @ts-ignore
123
+ const { label = 'label', value = 'value' } = optionProps;
124
+ const { mapField, multiple, loading = false } = props;
125
+
126
+ const componentHook = useComponent();
127
+ // 多选时, model挂载到临时字段上
128
+ const modelField = multiple ? `_${field}` : field;
129
+ // 默认值
130
+ componentHook.setDefaultValue(props, data, field);
131
+
132
+ /**
133
+ * @description: 远程搜索对应的函数
134
+ * @param {*} val 录入的参数
135
+ */
136
+ async function remoteMethod(query) {
137
+ componentHook.remote(query, field, renderOpts);
138
+ }
139
+
140
+ /**
141
+ * @description: 选中值发生变化时触发
142
+ * @param {*} val 目前的选中值
143
+ */
144
+ function onChange(val) {
145
+ componentHook.selectChange(val, data, field, renderOpts, {
146
+ datasource: 'data'
147
+ });
148
+ }
149
+
150
+ function onInput(val) {
151
+ events?.input && events.input(params, val);
152
+ }
153
+ /**
154
+ * @description: 可清空的单选模式下用户点击清空按钮时触发
155
+ */
156
+ function onClear() {
157
+ componentHook.clear(data, field, mapField, events, 'data');
158
+ }
159
+
160
+ function onFocus() {
161
+ !options.length && remoteMethod('');
162
+ events?.focus && events.focus(params);
163
+ }
164
+
165
+ return [
166
+ <el-select
167
+ v-model={data[modelField]}
168
+ filterable
169
+ remote
170
+ clearable
171
+ style="width: 100%"
172
+ placeholder="请录入关键字搜索"
173
+ loading={loading}
174
+ remote-method={remoteMethod}
175
+ {...props}
176
+ onFocus={() => onFocus()}
177
+ onChange={v => onChange(v)}
178
+ onClear={() => onClear()}
179
+ onInput={() => onInput()}
180
+ >
181
+ {options.map(item => {
182
+ return <el-option key={item[value]} label={item[label]} value={item[value]}></el-option>;
183
+ })}
184
+ </el-select>
185
+ ];
186
+ }
187
+ });
188
+
189
+ // 时间范围
190
+ VXETable.renderer.add('#SuDateRange', {
191
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
192
+ const { data, field } = params;
193
+ const { props } = renderOpts;
194
+ if (props?.defaultValue && !data[field]) {
195
+ data[field] = props.defaultValue;
196
+ props.defaultValue = props.required ? props.defaultValue : null;
197
+ }
198
+
199
+ const end = new Date();
200
+ const shortcuts = [
201
+ {
202
+ text: i18n('message.udp.today', true),
203
+ value: () => [getTime(1, 'day'), end]
204
+ },
205
+ {
206
+ text: i18n('message.udp.yesterday', true),
207
+ value: () => [getTime(2, 'day'), getTime(2, 'day')]
208
+ },
209
+ {
210
+ text: i18n('message.udp.lastWeek', true),
211
+ value: () => [getTime(7, 'day'), end]
212
+ },
213
+ {
214
+ text: i18n('message.udp.lastMonth', true),
215
+ value: () => [getTime(1, 'month'), end]
216
+ },
217
+ {
218
+ text: i18n('message.udp.threeMonth', true),
219
+ value: () => [getTime(3, 'month'), end]
220
+ },
221
+ {
222
+ text: i18n('message.udp.halfYear', true),
223
+ value: () => [getTime(6, 'month'), end]
224
+ },
225
+ {
226
+ text: i18n('message.udp.anniversary', true),
227
+ value: () => [getTime(1, 'year'), end]
228
+ }
229
+ ];
230
+
231
+ const getTime = (offset, type) => {
232
+ return dayjs().subtract(offset, type).add('1', 'day').format();
233
+ };
234
+
235
+ return [
236
+ <el-date-picker
237
+ v-model={data[field]}
238
+ type={props?.type || 'daterange'}
239
+ shortcuts={shortcuts}
240
+ style="width: 100%"
241
+ range-separator={i18n('message.to', true)}
242
+ start-placeholder={i18n('message.startDate', true)}
243
+ end-placeholder={i18n('message.endDate', true)}
244
+ {...props}
245
+ />
246
+ ];
247
+ }
248
+ });
249
+ // 下拉选择
250
+ VXETable.renderer.add('#select', {
251
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
252
+ const { row, column } = params;
253
+ const { options, props, optionProps = {}, events } = renderOpts;
120
254
  const { label = 'label', value = 'value', extLabel } = optionProps;
121
- if (props.multiple && row[column.field]) {
122
- !isArray(row[column.field]) &&
123
- row[column.field].split(',').forEach(ff => {
124
- const isExit = options.some(s => s[label] === ff);
125
- !isExit && options.push({ [value]: ff, [label]: ff });
126
- });
255
+ const { mapField } = props;
256
+
257
+ const componentHook = useComponent();
258
+
259
+ if (props.multiple && row[column.field] && !isArray(row[column.field])) {
260
+ row[column.field].split(',').forEach(dv => {
261
+ const isExit = options.some(option => option[label] === dv);
262
+ !isExit && options.push({ [value]: dv, [label]: dv });
263
+ });
127
264
  }
128
265
 
129
266
  function onChange(val) {
130
- const item = val && options.find(option => val === option[value]);
131
- events?.change && events.change(params, val, item, column.field);
267
+ componentHook.selectChange(val, row, column.field, renderOpts, {
268
+ column,
269
+ datasource: 'row'
270
+ });
132
271
  }
133
272
 
134
273
  function onClear() {
135
- events?.clear && events.clear({ row, field: column.field });
274
+ componentHook.clear(row, column.field, mapField, events, 'row');
136
275
  }
137
276
 
138
277
  return [
@@ -141,7 +280,6 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
141
280
  filterable
142
281
  clearable
143
282
  {...props}
144
- size="small"
145
283
  style="width: 100%"
146
284
  onChange={v => onChange(v)}
147
285
  onClear={() => onClear()}
@@ -150,23 +288,64 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
150
288
  return (
151
289
  <el-option
152
290
  key={item[value]}
153
- label={item[extLabel] ? item[value] : item[label]}
291
+ label={extLabel && item[extLabel] ? item[value] : item[label]}
154
292
  value={item[value]}
155
- >
156
- <span style="float: left">
157
- {extLabel && item[extLabel] ? `${item[value]}-${item[extLabel]}` : item[value]}
158
- </span>
159
- {value !== label && !item[extLabel] ? (
160
- <span class="ut-coSelect-option">{item[label]}</span>
161
- ) : null}
162
- </el-option>
293
+ ></el-option>
294
+ );
295
+ })}
296
+ </el-select>
297
+ ];
298
+ },
299
+ renderTableDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
300
+ const { row, column } = params;
301
+ const { options, props, optionProps = {}, events } = renderOpts;
302
+ const { label = 'label', value = 'value', extLabel } = optionProps;
303
+ const { mapField } = props;
304
+
305
+ const componentHook = useComponent();
306
+
307
+ if (props.multiple && row[column.field] && !isArray(row[column.field])) {
308
+ row[column.field].split(',').forEach(dv => {
309
+ const isExit = options.some(option => option[label] === dv);
310
+ !isExit && options.push({ [value]: dv, [label]: dv });
311
+ });
312
+ }
313
+
314
+ function onChange(val) {
315
+ componentHook.selectChange(val, row, column.field, renderOpts, {
316
+ column,
317
+ datasource: 'row'
318
+ });
319
+ }
320
+
321
+ function onClear() {
322
+ componentHook.clear(row, column.field, mapField, events, 'row');
323
+ }
324
+
325
+ return [
326
+ <el-select
327
+ v-model={row[column.field]}
328
+ filterable
329
+ clearable
330
+ {...props}
331
+ style="width: 100%"
332
+ onChange={v => onChange(v)}
333
+ onClear={() => onClear()}
334
+ >
335
+ {options.map(item => {
336
+ return (
337
+ <el-option
338
+ key={item[value]}
339
+ label={extLabel && item[extLabel] ? item[value] : item[label]}
340
+ value={item[value]}
341
+ ></el-option>
163
342
  );
164
343
  })}
165
344
  </el-select>
166
345
  ];
167
346
  },
168
347
  // 可编辑显示模板
169
- renderCell(renderOpts, params) {
348
+ renderTableCell(renderOpts, params) {
170
349
  const { row, column } = params;
171
350
  const { props, options, optionProps } = renderOpts;
172
351
  // @ts-ignore
@@ -185,13 +364,14 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
185
364
  }
186
365
  return [<span>{val}</span>];
187
366
  },
188
- renderItemContent(renderOpts, params) {
367
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
189
368
  const { data, field } = params;
190
369
  const { options, props, optionProps = {}, events } = renderOpts;
191
- // @ts-ignore
192
370
  const { label = 'label', value = 'value' } = optionProps;
371
+ const componentHook = useComponent();
372
+
193
373
  // 默认值
194
- const { defaultValues } = props;
374
+ const { defaultValues, mapField } = props;
195
375
  if (defaultValues) {
196
376
  data[field] = defaultValues;
197
377
  }
@@ -200,53 +380,41 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
200
380
  * @param {*} val 目前的选中值
201
381
  */
202
382
  function onChange(val) {
203
- const { fieldMap = {} } = props;
204
- const item = options.find(option => val === option[value]);
205
- const keys = Object.keys(fieldMap);
206
- if (keys.length) {
207
- const values: string[] = Object.values(fieldMap);
208
- keys.forEach((key, idx) => {
209
- data[key] = val ? item[values[idx]] : null;
210
- });
211
- }
212
- const parm = { item, row: data, property: field };
213
- events?.change && events.change(parm);
383
+ componentHook.selectChange(val, data, field, renderOpts, {
384
+ datasource: 'data'
385
+ });
214
386
  }
215
387
 
216
388
  /**
217
389
  * @description: 可清空的单选模式下用户点击清空按钮时触发
218
390
  */
219
391
  function onClear() {
220
- events?.clear && events.clear({ data, field });
392
+ componentHook.clear(data, field, mapField, events, 'data');
221
393
  }
222
394
 
223
395
  return [
224
396
  <el-select
225
397
  v-model={data[field]}
226
- {...props}
227
398
  filterable
228
399
  clearable
229
- size="small"
230
400
  style="width: 100%"
401
+ {...props}
231
402
  onChange={v => onChange(v)}
232
403
  onClear={() => onClear()}
233
404
  >
234
405
  {options.map(item => {
235
- return (
236
- <el-option key={item[value]} label={item[label]} value={item[value]}>
237
- <span style="float: left">{item[label]}</span>
238
- <span class="ut-coSelect-option">{item[value]}</span>
239
- </el-option>
240
- );
406
+ return <el-option key={item[value]} label={item[label]} value={item[value]}></el-option>;
241
407
  })}
242
408
  </el-select>
243
409
  ];
244
410
  }
245
411
  });
412
+ // Lov
246
413
  VXETable.renderer.add('#lov', {
247
- renderItemContent(renderOpts, params: FormItemContentRenderParams) {
414
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
248
415
  const { data, field } = params;
249
416
  const { props, events } = renderOpts;
417
+ const componentHook = useComponent();
250
418
  // 默认值
251
419
  const { defaultValues, mapField } = props;
252
420
  if (defaultValues) {
@@ -257,8 +425,8 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
257
425
  * @param {*} val 目前的选中值
258
426
  */
259
427
  function onChange(record, displayField) {
260
- const { mapField, field, displayName, isMulti } = props;
261
- if (!isMulti) {
428
+ const { mapField, field, displayName, multiple } = props;
429
+ if (!multiple) {
262
430
  const obj = {
263
431
  [displayName || field]: record[displayField || displayName || field]
264
432
  };
@@ -266,7 +434,7 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
266
434
  obj[key] = record[mapField[key]];
267
435
  }
268
436
  Object.assign(data, obj);
269
- } else if (isMulti) {
437
+ } else if (multiple) {
270
438
  const obj = {};
271
439
  data[displayName || field] = record.reduce((curv, prev) => {
272
440
  for (const key in mapField) {
@@ -277,7 +445,7 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
277
445
  }, '');
278
446
  Object.assign(data, obj);
279
447
  }
280
- const parm = { row: data, field, item: record };
448
+ const parm = { row: data, property: field, item: record, field };
281
449
  events?.change && events.change(parm);
282
450
  }
283
451
 
@@ -285,13 +453,7 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
285
453
  * @description: 点击清空按钮时触发
286
454
  */
287
455
  function onClear() {
288
- data[field] = null;
289
- if (!isEmpty(mapField)) {
290
- for (const key in mapField) {
291
- data[key] = null;
292
- }
293
- }
294
- events?.clear && events.clear({ data, field: field });
456
+ componentHook.clear(data, field, mapField, events, 'data');
295
457
  }
296
458
 
297
459
  return [
@@ -305,14 +467,13 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
305
467
  ];
306
468
  },
307
469
  // 单元格编辑
308
- renderEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
309
- console.log('.......');
470
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
310
471
  const { row, column } = params;
311
472
  const { props, events } = renderOpts;
312
-
473
+ const componentHook = useComponent();
313
474
  function onChange(record, displayField) {
314
- const { mapField, field, displayName, isMulti } = props;
315
- if (!isMulti) {
475
+ const { mapField, field, displayName, multiple } = props;
476
+ if (!multiple) {
316
477
  const obj = {
317
478
  [displayName || field]: record[displayField || displayName || field]
318
479
  };
@@ -325,34 +486,27 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
325
486
  }
326
487
 
327
488
  function onClear() {
328
- const { mapField, field } = props;
329
- row[column.field] = null;
330
- if (!isEmpty(mapField)) {
331
- for (const key in mapField) {
332
- row[key] = null;
333
- }
334
- }
335
- events?.clear && events.clear({ row, field });
489
+ componentHook.clear(row, field, mapField, events, 'row');
336
490
  }
337
491
 
338
492
  return [
339
493
  <ut-lov
340
494
  record={row}
495
+ mode="vxe"
341
496
  {...props}
342
- mode="ele"
343
497
  onChange={(v, f) => onChange(v, f)}
344
498
  onClear={() => onClear()}
345
499
  />
346
500
  ];
347
501
  },
348
502
  // 单元格默认
349
- renderDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
503
+ renderTableDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
350
504
  const { row, column } = params;
351
505
  const { props, events } = renderOpts;
352
-
506
+ const componentHook = useComponent();
353
507
  function onChange(record, displayField) {
354
- const { mapField, field, displayName, isMulti } = props;
355
- if (!isMulti) {
508
+ const { mapField, field, displayName, multiple } = props;
509
+ if (!multiple) {
356
510
  const obj = {
357
511
  [displayName || field]: record[displayField || displayName || field]
358
512
  };
@@ -363,35 +517,301 @@ export const VxetableRender = (VXETable, { serviceApi, dict, i18n }) => {
363
517
  }
364
518
  events?.change && events.change(params, record, row[column.field]);
365
519
  }
366
-
520
+ /**
521
+ * @description 清空数据
522
+ */
367
523
  function onClear() {
368
- const { mapField, field } = props;
369
- row[column.field] = null;
370
- if (!isEmpty(mapField)) {
371
- for (const key in mapField) {
372
- row[key] = null;
373
- }
374
- }
375
- events?.clear && events.clear({ row, field });
524
+ componentHook.clear(row, field, mapField, events, 'row');
376
525
  }
377
526
 
378
527
  return [
379
528
  <ut-lov
380
529
  record={row}
381
- {...props}
382
530
  mode="ele"
531
+ {...props}
383
532
  onChange={(v, f) => onChange(v, f)}
384
533
  onClear={() => onClear()}
385
534
  />
386
535
  ];
387
536
  },
388
537
  // 可编辑显示模板
389
- renderCell(renderOpts, params) {
538
+ renderTableCell(renderOpts, params) {
390
539
  const { row, column } = params;
391
- // @ts-ignore
392
- // const { textValue } = props;
393
- const val = row[column.field];
394
- return [<span>{val}</span>];
540
+ return [<span>{row[column.field]}</span>];
541
+ }
542
+ });
543
+ // form upload
544
+ VXETable.renderer.add('#upload', {
545
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
546
+ const { data, field } = params;
547
+ const { props, events } = renderOpts;
548
+
549
+ /**
550
+ * @description: 点击清空按钮时触发
551
+ */
552
+ function onClear() {
553
+ data[field] = '';
554
+ componentHook.clear(data, field, props.mapField, events, 'data');
555
+ }
556
+
557
+ return [<form-upload2 record={data} field={field} {...props} onClear={() => onClear()} />];
395
558
  }
396
559
  });
560
+
561
+ // 创建一个简单的超链接渲染
562
+ VXETable.renderer.add('#tag', {
563
+ // 默认显示模板
564
+ renderTableDefault(renderOpts, params) {
565
+ const { row, column } = params;
566
+ const {
567
+ props: { code, tagMap }
568
+ } = renderOpts;
569
+ function getTagType() {
570
+ return row[column.field] ? tagMap[row[column.field]] : null;
571
+ }
572
+ return [
573
+ row[column.field] ? (
574
+ <el-tag effect="dark" type={getTagType()}>
575
+ {getValue(code, row[column.field])}
576
+ </el-tag>
577
+ ) : null
578
+ ];
579
+ }
580
+ });
581
+
582
+ VXETable.renderer.add('#switch', {
583
+ renderTableDefault(renderOpts, params) {
584
+ const { row, column } = params;
585
+ const {
586
+ props: { code, activeValue, inactiveValue },
587
+ events
588
+ } = renderOpts;
589
+ function onChange(value) {
590
+ const params = { row, column, value };
591
+ events?.change && events.change(params);
592
+ }
593
+ return [
594
+ row[column.field] ? (
595
+ <el-switch
596
+ v-model={row[column.field]}
597
+ inline-prompt
598
+ size="large"
599
+ style="--el-switch-on-color: #13ce66; --el-switch-off-color: #E6A23C"
600
+ {...renderOpts.props}
601
+ active-text={getValue(code, activeValue)}
602
+ inactive-text={getValue(code, inactiveValue)}
603
+ onChange={v => onChange(v)}
604
+ />
605
+ ) : null
606
+ ];
607
+ }
608
+ });
609
+
610
+ VXETable.renderer.add('#iconSelect', {
611
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
612
+ const { row, column } = params;
613
+ return [<SuIconSelect v-model={row[column.field]} teleported={false} />];
614
+ },
615
+ renderTableCell(renderOpts, params) {
616
+ const { row, column } = params;
617
+ return [<IconifyIconOffline icon={row[column.field]} style="font-size: 16px;" />];
618
+ },
619
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
620
+ const { data, field } = params;
621
+ return [<SuIconSelect v-model={data[field]} teleported />];
622
+ }
623
+ });
624
+
625
+ VXETable.renderer.add('#treeSelect', {
626
+ renderTableEdit(renderOpts: SuEditRender, params) {
627
+ const { row, column } = params;
628
+ const { props, sourceData, events } = renderOpts;
629
+
630
+ return [
631
+ <el-tree-select
632
+ v-model={row[column.field]}
633
+ data={sourceData}
634
+ check-strictly
635
+ {...props}
636
+ filterable
637
+ onCheckChange={(node, selected, isLeaf) => onCheckChange(node, selected, isLeaf, events)}
638
+ onNodeClick={(data, node, treeNode) => onNodeClick(data, node, treeNode, events)}
639
+ onCurrentChange={(data, node) => onCurrentChange(data, node, events)}
640
+ />
641
+ ];
642
+ },
643
+ renderTableCell(renderOpts: SuRenderCellOptions, params) {
644
+ const { row, column } = params;
645
+ const { sourceData, props = {} } = renderOpts;
646
+ const { children = 'children', label = 'label' } = props;
647
+ const data = findTree(sourceData, item => item['value'] === row[column.field], { children });
648
+ return data ? [<span>{data.item[label]}</span>] : null;
649
+ },
650
+ renderItemContent(renderOpts: SuFormItemRenderOptions, params: FormItemContentRenderParams) {
651
+ const { data, field } = params;
652
+ const { props, sourceData, events } = renderOpts;
653
+ return [
654
+ <el-tree-select
655
+ v-model={data[field]}
656
+ data={sourceData}
657
+ check-strictly
658
+ {...props}
659
+ filterable
660
+ onCheckChange={(node, selected, isLeaf) => onCheckChange(node, selected, isLeaf, events)}
661
+ onNodeClick={(data, node, treeNode) => onNodeClick(data, node, treeNode, events)}
662
+ onCurrentChange={(data, node) => onCurrentChange(data, node, events)}
663
+ />
664
+ ];
665
+ }
666
+ });
667
+
668
+ /**
669
+ * 组件公共方法
670
+ * @returns
671
+ */
672
+ const useComponent = () => {
673
+ // 下拉框选择
674
+ /**
675
+ * select下拉选择change事件
676
+ * @param value 选择值
677
+ * @param data 数据源
678
+ * @param field 字段
679
+ * @param renderOpts 渲染参数
680
+ * @param opts 数据源类型等
681
+ * @return `{ data: 数据源, field: 字段, options?: 选中的选项组, option?: 选中的选项, column?: 列信息 }`
682
+ */
683
+ const selectChange = (value, data, field, renderOpts, opts) => {
684
+ let option = null;
685
+
686
+ const { datasource } = opts;
687
+ const { options, props, optionProps = {}, events } = renderOpts;
688
+
689
+ const callData = { [datasource]: data, field };
690
+ // 1、清空原有数据
691
+ data[field] = null;
692
+ if (!isEmpty(value) && props?.multiple) {
693
+ // 2、给实际字段赋值
694
+ data[field] = value.join(',');
695
+ option = [];
696
+ // 多选
697
+ value.forEach(item => {
698
+ const selectOpt = options.find(opt => item === opt[optionProps?.value]);
699
+ if (selectOpt && !isEmpty(props.mapField) && isObject(props.mapField)) {
700
+ Object.keys(props.mapField).forEach(key => {
701
+ const val = selectOpt[props.mapField[key]];
702
+ const ov = data[key] ? data[key].toString() : '';
703
+ // 默认用逗号(,)分割
704
+ data[key] = ov && !ov.includes(val) ? `${ov},${val}` : val;
705
+ });
706
+ }
707
+ selectOpt && option.push(selectOpt);
708
+ });
709
+ Object.assign(callData, { options: option });
710
+ } else {
711
+ // 3、原字段赋值, 多选进来说明必定是空值
712
+ data[field] = props?.multiple ? null : value;
713
+ option = options.find(opt => value === opt[optionProps?.value]);
714
+ if (!isEmpty(props.mapField) && isObject(props.mapField)) {
715
+ Object.keys(props.mapField).forEach(key => {
716
+ data[key] = option ? option[props.mapField[key]] : null;
717
+ });
718
+ }
719
+ Object.assign(callData, { option });
720
+ }
721
+ datasource === 'row' && Object.assign(callData, { column: opts.column });
722
+ events?.change && events.change(callData);
723
+ };
724
+ const setDefaultValue = (props, data, field) => {
725
+ const { multiple, defaultValue } = props;
726
+ // 多选时, model挂载到临时字段上
727
+ const modelField = multiple ? `_${field}` : field;
728
+ // 默认值
729
+ if (!data[field] && defaultValue) {
730
+ data[field] = defaultValue;
731
+ if (isPlainObject(defaultValue)) {
732
+ const keys = Object.keys(defaultValue);
733
+ keys.forEach(key => {
734
+ data[key] = data[key] || defaultValue[key];
735
+ });
736
+ }
737
+ }
738
+ if (!data[modelField] && data[field]) {
739
+ data[modelField] = multiple ? data[field]?.split(',') : data[field];
740
+ }
741
+ };
742
+ const remote = async (query, field, renderOpts) => {
743
+ const { options, props, events } = renderOpts;
744
+ const { fetchField, url, defaultParams = {}, method = 'get' } = props;
745
+ const commonParam = getCookieParam();
746
+ const params = Object.assign(
747
+ { pageSize: 20, pageNum: 1, ...commonParam, ...defaultParams },
748
+ { [fetchField || field]: query }
749
+ );
750
+ if (props.loading) return;
751
+ let res;
752
+ try {
753
+ options.length = 0;
754
+ props.loading = true;
755
+ res = await serviceApi[method](url, params);
756
+ if (events?.filterMethod) {
757
+ options.push(...events.filterMethod(res.list || res));
758
+ } else if (res) {
759
+ res.list ? options.push(...res.list) : options.push(...res);
760
+ }
761
+ } finally {
762
+ props.loading = false;
763
+ }
764
+ };
765
+ // 清除数据
766
+ const clear = (data, field, mapField, events, datasource) => {
767
+ data[field] = null;
768
+ if (!isEmpty(mapField)) {
769
+ for (const key in mapField) {
770
+ data[key] = null;
771
+ }
772
+ }
773
+ events?.clear && events.clear({ [datasource]: data, field });
774
+ };
775
+ return { clear, remote, selectChange, setDefaultValue };
776
+ };
777
+
778
+ /**
779
+ * 当复选框被点击的时候触发
780
+ * @param node 传递给 data 属性的数组中该节点所对应的对象
781
+ * @param selected 节点本身是否被选中
782
+ * @param isLeaf 节点的子树中是否有被选中的节点
783
+ */
784
+ const onCheckChange = (node, selected, isLeaf, events) => {
785
+ console.log(node, selected, isLeaf);
786
+ events?.checkChange && events?.checkChange(node, selected, isLeaf);
787
+ };
788
+ /**
789
+ * 节点被点击的时候触发
790
+ * @param nodeObject 点击的节点对象
791
+ * @param node TreeNode 的 node 属性
792
+ * @param treeNode TreeNode
793
+ */
794
+ const onNodeClick = (nodeObject, node, treeNode, events) => {
795
+ events?.checkChange && events?.checkChange(nodeObject, node, treeNode);
796
+ };
797
+ /**
798
+ * 当前选中节点变化时触发的事件
799
+ * @param data 当前节点的数据
800
+ * @param node 当前节点的 Node 对象
801
+ */
802
+ const onCurrentChange = (data, node, events) => {
803
+ events?.checkChange && events?.checkChange(data, node);
804
+ };
805
+
806
+ function getValue(code, value) {
807
+ if (!value || !code || !dict) return value;
808
+ return dict[code]?.children?.find(item => item.dictCode === value)?.dictName;
809
+ }
810
+
811
+ return VXETable;
812
+ };
813
+
814
+ const getCookieParam = () => {
815
+ const kCOOKIES = 'kCookies_param';
816
+ return cookies.get(kCOOKIES) ? JSON.parse(cookies.get(kCOOKIES)) : {};
397
817
  };