@utogether/udp-core 1.0.1 → 1.0.3

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 (239) hide show
  1. package/build/plugins.ts +13 -2
  2. package/dist/{403-JWjatlxJ.js → 403-D6H3sArg.js} +7 -6
  3. package/dist/{404-BcdMJfPb.js → 404-DTyfysQ2.js} +14 -13
  4. package/dist/{500-bsa3F_cc.js → 500-DKaVDaBm.js} +10 -9
  5. package/dist/{AuthorityInfo-CqItgNs5.js → AuthorityInfo-DQULR69Y.js} +1 -1
  6. package/dist/AuthorityInfo.vue_vue_type_style_index_0_lang-CzAnoTnO.js +100 -0
  7. package/dist/{AuthorityPanel-BaLMwMgW.js → AuthorityPanel-BeBNiwqc.js} +1 -1
  8. package/dist/{AuthorityPanel.vue_vue_type_style_index_0_lang-C_bkqLD9.js → AuthorityPanel.vue_vue_type_style_index_0_lang-CIYmnP9-.js} +6 -6
  9. package/dist/{Company-DVff9IA7.js → Company-BWFrR-Cq.js} +3 -3
  10. package/dist/{CompanyPanel-CNrdq4XE.js → CompanyPanel-Dh814lsw.js} +16 -16
  11. package/dist/{Department-CqcpfL4i.js → Department-DagPxerl.js} +10 -10
  12. package/dist/{DepartmentPanel-Bvti4LGu.js → DepartmentPanel-BVy2YGED.js} +108 -78
  13. package/dist/{DesignPanel-CjykspE1.js → DesignPanel-DKfjfj2S.js} +1 -1
  14. package/dist/{DesignPanel.vue_vue_type_style_index_0_lang-BK9EERdd.js → DesignPanel.vue_vue_type_style_index_0_lang-D-a8W08Y.js} +24 -26
  15. package/dist/DictView-CE5nEiKu.js +110 -0
  16. package/dist/InvOrganization-CZk_EbFZ.js +74 -0
  17. package/dist/Org-BO8jfnqN.js +39 -0
  18. package/dist/{Preview-Cm_7RhYU.js → Preview-DYJaP96f.js} +2 -2
  19. package/dist/{ReportDefine-CJVlQ--7.js → ReportDefine-DZXbs7iX.js} +1 -1
  20. package/dist/{ReportDesign-B0unlrkt.js → ReportDesign-CSdqOQ1D.js} +46 -46
  21. package/dist/{ReportQuery-BKuMCEvF.js → ReportQuery-_Vdt3CnA.js} +5 -5
  22. package/dist/{ReportQueryFrom-DAngMJLU.js → ReportQueryFrom-BWKddh9p.js} +1 -1
  23. package/dist/{ReportQueryFrom.vue_vue_type_style_index_0_lang-CPpwmztJ.js → ReportQueryFrom.vue_vue_type_style_index_0_lang-DbdGwioi.js} +6 -5
  24. package/dist/{ReportTemplate-8YH3L8Pv.js → ReportTemplate-DS-DGao8.js} +26 -26
  25. package/dist/{Role-MxI30-0W.js → Role-BM0kEu7y.js} +6 -6
  26. package/dist/{RoleAssign-BzUY_y_y.js → RoleAssign-Cp05HUWn.js} +9 -9
  27. package/dist/{RolePanel-DS_TErTn.js → RolePanel-DeuHpCdK.js} +1 -1
  28. package/dist/{RolePanel-CXdcvsR5.js → RolePanel-hXeshcCZ.js} +1 -1
  29. package/dist/{RolePanel.vue_vue_type_script_setup_true_lang-Ddl-A7Zh.js → RolePanel.vue_vue_type_script_setup_true_lang-Bf0pSCTN.js} +42 -36
  30. package/dist/RolePanel.vue_vue_type_script_setup_true_lang-CNyWCIJm.js +132 -0
  31. package/dist/{ScrollPanel.vue_vue_type_style_index_0_lang-DnchUgIF.js → ScrollPanel.vue_vue_type_style_index_0_lang-BiKe39xG.js} +20 -20
  32. package/dist/{Staff-D7tXo_Gn.js → Staff-DLltLFMl.js} +3 -3
  33. package/dist/{StaffInfo-Bk8BY8PO.js → StaffInfo-pfELaI_i.js} +1 -1
  34. package/dist/{StaffInfo.vue_vue_type_script_setup_true_lang-DqKwZi5f.js → StaffInfo.vue_vue_type_script_setup_true_lang-BKKdNggm.js} +13 -13
  35. package/dist/{StaffPanel-VtpGCTIq.js → StaffPanel-D3Pk28JN.js} +1 -1
  36. package/dist/StaffPanel.vue_vue_type_script_setup_true_lang-D9HLeyKe.js +143 -0
  37. package/dist/{SysUser-D0Q6OvD7.js → SysUser-BOh7ejz3.js} +2 -2
  38. package/dist/{SysUserPanel-1_vrsANQ.js → SysUserPanel-RElVo0BV.js} +1 -1
  39. package/dist/SysUserPanel.vue_vue_type_script_setup_true_lang-DoW0v5y9.js +341 -0
  40. package/dist/{SystemMenu-9PG3vESE.js → SystemMenu-DZneBqKO.js} +53 -51
  41. package/dist/{UserInfo-qgXUEGwi.js → UserInfo-D9qo_f_9.js} +1 -1
  42. package/dist/{UserInfo.vue_vue_type_style_index_0_lang-CN0C5rVk.js → UserInfo.vue_vue_type_style_index_0_lang-CY4dtMnZ.js} +35 -33
  43. package/dist/{childView-C7ZSA5fR.js → childView-CmlGxD9G.js} +1 -1
  44. package/dist/{childView-yV2QLwfA.js → childView-DStrPumM.js} +1 -1
  45. package/dist/{childView.vue_vue_type_style_index_0_lang-DdKxPGdh.js → childView.vue_vue_type_style_index_0_lang-B9k694be.js} +23 -24
  46. package/dist/childView.vue_vue_type_style_index_0_lang-Dtv1rrdP.js +177 -0
  47. package/dist/{code-rule-95K1jr-u.js → code-rule-CxzgQDH_.js} +42 -41
  48. package/dist/core.es.js +19 -10
  49. package/dist/{cron-task-DGrQwOHs.js → cron-task-kbyRTz97.js} +5 -5
  50. package/dist/flow-task-B07st2aD.js +10 -0
  51. package/dist/{frameView-7SmME93D.js → frameView-BawZlIge.js} +15 -14
  52. package/dist/img/l_img.svg +1 -1
  53. package/dist/img/minicolors.png +0 -0
  54. package/dist/img/v_img.svg +1 -1
  55. package/dist/index-nkstuOxE.js +5533 -0
  56. package/dist/{layoutView-C6WIVWGZ.js → layoutView-DVGqPJmA.js} +1776 -1764
  57. package/dist/{log-in-e7D5Ss1P.js → log-in-j2PZGLQH.js} +36 -29
  58. package/dist/log-out-DIJU-Vpf.js +130 -0
  59. package/dist/login-DvmHMcgD.js +251 -0
  60. package/dist/{login-log-CvVnyGi3.js → login-log-DJBGJVV0.js} +10 -8
  61. package/dist/{lov-view-DoF5LqFQ.js → lov-view-C-dIDLh8.js} +9 -9
  62. package/dist/{menuInfo-CNzGQwOD.js → menuInfo-D0mcKmrT.js} +1 -1
  63. package/dist/{menuInfo.vue_vue_type_style_index_0_lang-51SYxVc_.js → menuInfo.vue_vue_type_style_index_0_lang-CbwS7aGl.js} +144 -121
  64. package/dist/pda-app-BjvyTDkw.js +710 -0
  65. package/dist/redirect-BqegffKC.js +15 -0
  66. package/dist/{resource-gVFFMO9l.js → resource-BknIxaTQ.js} +17 -17
  67. package/dist/{su-welcome-BN_s_RX_.js → su-welcome-CwtvamZC.js} +137 -139
  68. package/dist/sys-config-CCKhGcCL.js +370 -0
  69. package/dist/udp-core.css +1 -9
  70. package/dist/utogether-MlnyYtNS.js +4 -0
  71. package/index.ts +19 -6
  72. package/package.json +18 -17
  73. package/src/App.vue +2 -7
  74. package/src/api/http.ts +1 -4
  75. package/src/api/index.ts +5 -3
  76. package/src/api/user.ts +2 -2
  77. package/src/components/SuCharts/src/UserInfo.vue +3 -3
  78. package/src/components/SuScrollTree/ScrollPanel.vue +4 -9
  79. package/src/components/udp/content/index.vue +88 -0
  80. package/src/components/udp/form/form.vue +109 -0
  81. package/src/components/udp/grid/index.vue +524 -0
  82. package/src/components/udp/index.ts +5 -4
  83. package/src/components/udp/ut-stamp-badge/index.vue +271 -0
  84. package/src/components/udp/utils.ts +408 -40
  85. package/src/directives/permission/index.ts +1 -1
  86. package/src/layout/components/lay-navbar/index.vue +9 -7
  87. package/src/layout/components/lay-panel/index.vue +3 -3
  88. package/src/layout/components/lay-search/index.vue +1 -1
  89. package/src/layout/components/lay-select-org/index.vue +4 -9
  90. package/src/layout/components/lay-setting/index.vue +503 -510
  91. package/src/layout/components/lay-sidebar/breadCrumb.vue +1 -1
  92. package/src/layout/components/lay-sidebar/horizontal.vue +8 -6
  93. package/src/layout/components/lay-sidebar/mixNav.vue +260 -258
  94. package/src/layout/components/lay-sidebar/sidebar-logo.vue +101 -98
  95. package/src/layout/components/lay-tag/index.vue +598 -625
  96. package/src/layout/hooks/useDataThemeChange.ts +1 -1
  97. package/src/layout/hooks/useNav.ts +176 -173
  98. package/src/layout/hooks/useTag.ts +227 -233
  99. package/src/layout/layoutView.vue +215 -215
  100. package/src/layout/types.ts +93 -92
  101. package/src/main.ts +115 -109
  102. package/src/plugins/i18n/en.ts +26 -13
  103. package/src/plugins/i18n/module/u-workflow.ts +1 -1
  104. package/src/plugins/i18n/zh.ts +363 -337
  105. package/src/plugins/vxe-table/index.ts +116 -46
  106. package/src/plugins/vxe-table/render.tsx +950 -817
  107. package/src/router/index.ts +187 -183
  108. package/src/router/modules/flow.ts +35 -0
  109. package/src/router/modules/home.ts +32 -32
  110. package/src/router/modules/remaining.ts +1 -26
  111. package/src/router/utils.ts +420 -377
  112. package/src/store/modules/app.ts +2 -4
  113. package/src/store/modules/epTheme.ts +48 -49
  114. package/src/store/modules/multiTags.ts +15 -14
  115. package/src/store/modules/permission.ts +25 -15
  116. package/src/store/modules/system.ts +1 -3
  117. package/src/style/button.scss +11 -4
  118. package/src/style/login.css +1 -1
  119. package/src/style/tailwind.css +1 -68
  120. package/src/style/vxetable.scss +103 -11
  121. package/src/utils/authority/index.ts +1 -1
  122. package/src/utils/dataFormat/index.ts +222 -223
  123. package/src/utils/index.ts +3 -1
  124. package/src/utils/lifecycle.ts +39 -20
  125. package/src/utils/propTypes.ts +1 -6
  126. package/src/utils/storage/index.ts +2 -2
  127. package/src/utils/{http → udp/http}/index.ts +27 -30
  128. package/src/utils/{http → udp/http}/types.d.ts +2 -6
  129. package/src/views/login/login-view.vue +6 -20
  130. package/src/views/organization/company/CompanyPanel.vue +2 -2
  131. package/src/views/organization/department/Department.vue +58 -58
  132. package/src/views/organization/department/DepartmentPanel.vue +303 -283
  133. package/src/views/organization/inv-org/InvOrganization.vue +23 -9
  134. package/src/views/organization/org/Org.vue +9 -5
  135. package/src/views/organization/staff/StaffInfo.vue +127 -133
  136. package/src/views/organization/staff/StaffPanel.vue +171 -145
  137. package/src/views/system/cron/cron-task.vue +2 -12
  138. package/src/views/system/menu/AuthorityPanel.vue +2 -2
  139. package/src/views/system/menu/SystemMenu.vue +185 -191
  140. package/src/views/system/menu/menuInfo.vue +39 -23
  141. package/src/views/system/role/AuthorityInfo.vue +19 -15
  142. package/src/views/system/role/Role.vue +1 -5
  143. package/src/views/system/role/RolePanel.vue +11 -2
  144. package/src/views/system/role/UserInfo.vue +11 -9
  145. package/src/views/system/role-assign/RoleAssign.vue +2 -2
  146. package/src/views/system/role-assign/RolePanel.vue +12 -9
  147. package/src/views/system/sys/sys-config.vue +70 -21
  148. package/src/views/system/sysUser/SysUserPanel.vue +347 -278
  149. package/src/views/uapp/pda/pda-app.vue +48 -16
  150. package/src/views/udev/coderule/code-rule.vue +132 -121
  151. package/src/views/udev/dict/DictView.vue +118 -106
  152. package/src/views/udev/dict/childView.vue +183 -222
  153. package/src/views/udev/lov/childView.vue +174 -180
  154. package/src/views/ufile/aggregation/File.vue +5 -5
  155. package/src/views/ufile/file/water-mark.vue +14 -14
  156. package/src/views/uhome/components/menu-favorite.vue +315 -331
  157. package/src/views/uhome/su-welcome.vue +319 -339
  158. package/src/views/ulogin/login.vue +325 -316
  159. package/src/views/upms/interface/log-in.vue +100 -106
  160. package/src/views/upms/interface/log-out.vue +104 -107
  161. package/src/views/upms/user/login-log.vue +54 -60
  162. package/src/views/urpt/design/DesignPanel.vue +16 -35
  163. package/src/views/urpt/design/Preview.vue +1 -0
  164. package/src/views/urpt/design/ReportDesign.vue +17 -23
  165. package/src/views/urpt/static-resource/resource.vue +3 -3
  166. package/src/views/urpt/template/ReportTemplate.vue +7 -7
  167. package/src/views/utask/flow-task.vue +18 -0
  168. package/types/global.d.ts +231 -236
  169. package/vite.config.ts +13 -2
  170. package/dist/AuthorityInfo.vue_vue_type_style_index_0_lang-32L40GY2.js +0 -102
  171. package/dist/DictView-q7kR9K--.js +0 -95
  172. package/dist/InvOrganization-DI45LqZV.js +0 -260
  173. package/dist/Org-CZju_ZiR.js +0 -35
  174. package/dist/RolePanel.vue_vue_type_script_setup_true_lang-DJKu6PXz.js +0 -126
  175. package/dist/StaffPanel.vue_vue_type_script_setup_true_lang-C3Ixs12y.js +0 -111
  176. package/dist/SysUserPanel.vue_vue_type_script_setup_true_lang-C5XEmxsV.js +0 -288
  177. package/dist/childView.vue_vue_type_style_index_0_lang-bkmucBUL.js +0 -187
  178. package/dist/core.umd.js +0 -173
  179. package/dist/index-OswH7SsT.js +0 -9937
  180. package/dist/log-out--RRncZhN.js +0 -120
  181. package/dist/login-BhCMeCLS.js +0 -251
  182. package/dist/pda-app-nn3llDUx.js +0 -2209
  183. package/dist/redirect-CmMplDV4.js +0 -15
  184. package/dist/sys-config-DGutV-VX.js +0 -277
  185. package/dist/utogether-wFDCI28t.js +0 -182
  186. package/src/assets/images/empty.png +0 -0
  187. package/src/assets/images/logo.png +0 -0
  188. package/src/components/ReCountTo/README.md +0 -2
  189. package/src/components/ReCountTo/index.ts +0 -18
  190. package/src/components/ReCountTo/src/normal/index.tsx +0 -165
  191. package/src/components/ReCountTo/src/normal/props.ts +0 -37
  192. package/src/components/ReCountTo/src/rebound/index.tsx +0 -67
  193. package/src/components/ReCountTo/src/rebound/props.ts +0 -14
  194. package/src/components/ReCountTo/src/rebound/rebound.css +0 -77
  195. package/src/components/ReCropper/index.ts +0 -14
  196. package/src/components/ReCropper/src/index.tsx +0 -141
  197. package/src/components/ReFlicker/index.css +0 -39
  198. package/src/components/ReFlicker/index.ts +0 -50
  199. package/src/components/ReFlop/index.ts +0 -14
  200. package/src/components/ReFlop/src/Filpper.tsx +0 -99
  201. package/src/components/ReFlop/src/filpper.css +0 -184
  202. package/src/components/ReFlop/src/index.vue +0 -126
  203. package/src/components/ReFlowChart/index.ts +0 -24
  204. package/src/components/ReFlowChart/src/Control.vue +0 -139
  205. package/src/components/ReFlowChart/src/DataDialog.vue +0 -12
  206. package/src/components/ReFlowChart/src/NodePanel.vue +0 -151
  207. package/src/components/ReFlowChart/src/adpterForTurbo.ts +0 -160
  208. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.css +0 -49
  209. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.eot +0 -0
  210. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.js +0 -61
  211. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.json +0 -58
  212. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.svg +0 -47
  213. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.ttf +0 -0
  214. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.woff +0 -0
  215. package/src/components/ReFlowChart/src/assets/iconfont/iconfont.woff2 +0 -0
  216. package/src/components/ReFlowChart/src/config.ts +0 -62
  217. package/src/components/ReSplitPane/index.css +0 -49
  218. package/src/components/ReSplitPane/index.tsx +0 -119
  219. package/src/components/ReSplitPane/resizer.css +0 -45
  220. package/src/components/ReSplitPane/resizer.tsx +0 -30
  221. package/src/components/SuCommon/card/components/Card.vue +0 -148
  222. package/src/components/SuCommon/card/components/DialogForm.vue +0 -127
  223. package/src/components/SuCommon/card/index.vue +0 -142
  224. package/src/components/SuCommon/icon-select/index.vue +0 -241
  225. package/src/components/SuCommon/table/index.vue +0 -208
  226. package/src/components/SuCommon/utils/index.ts +0 -103
  227. package/src/components/SuCommon/utils/slot.tsx +0 -50
  228. package/src/components/udp/form-upload.vue +0 -132
  229. package/src/components/udp/modal-form.vue +0 -180
  230. package/src/utils/udp/useRender.ts +0 -420
  231. package/src/views/components/contextmenu/basic.vue +0 -74
  232. package/src/views/components/contextmenu/context-menu.vue +0 -40
  233. package/src/views/components/contextmenu/menuDynamic.vue +0 -99
  234. package/src/views/components/contextmenu/menuGroup.vue +0 -71
  235. package/src/views/components/count-to/index.vue +0 -43
  236. package/src/views/components/cropping/index.vue +0 -59
  237. package/src/views/components/cropping/picture.jpeg +0 -0
  238. package/src/views/components/split-pane/index.vue +0 -82
  239. package/src/views/components/video/index.vue +0 -57
@@ -1,817 +1,950 @@
1
- /*
2
- * @Author: wei.li
3
- * @Date: 2021-12-01 09:18:50
4
- * @LastEditors: levi7754 levi7754@163.com
5
- * @LastEditTime: 2025-07-14 18:17:16
6
- * @Description: file content
7
- */
8
-
9
- // @ts-nocheck
10
-
11
- import dayjs from 'dayjs';
12
- import { isArray, isEmpty, findTree, isObject, isPlainObject } from 'xe-utils';
13
- import type {
14
- FormItemRenderOptions,
15
- FormItemContentRenderParams,
16
- VxeColumnPropTypes,
17
- VxeGlobalRendererHandles
18
- } from 'vxe-table';
19
-
20
- import { cookies, storageLocal } from '@utogether/utils';
21
-
22
- interface SuFormItemRenderOptions extends FormItemRenderOptions {
23
- sourceData: IRecord;
24
- }
25
- interface SuEditRender extends VxeColumnPropTypes.EditRender {
26
- sourceData: IRecord;
27
- }
28
- interface SuRenderCellOptions extends VxeGlobalRendererHandles.RenderCellOptions {
29
- sourceData: IRecord[];
30
- }
31
-
32
- export const VxetableRender = (VXETable, { serviceApi, i18n }) => {
33
- const dict = storageLocal.getItem('kLov');
34
-
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();
44
-
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) {
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;
121
- const { options, props, optionProps = {}, events } = renderOpts;
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;
254
- const { label = 'label', value = 'value', extLabel } = optionProps;
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
- });
264
- }
265
-
266
- function onChange(val) {
267
- componentHook.selectChange(val, row, column.field, renderOpts, {
268
- column,
269
- datasource: 'row'
270
- });
271
- }
272
-
273
- function onClear() {
274
- componentHook.clear(row, column.field, mapField, events, 'row');
275
- }
276
-
277
- return [
278
- <el-select
279
- v-model={row[column.field]}
280
- filterable
281
- clearable
282
- {...props}
283
- style="width: 100%"
284
- onChange={v => onChange(v)}
285
- onClear={() => onClear()}
286
- >
287
- {options.map(item => {
288
- return (
289
- <el-option
290
- key={item[value]}
291
- label={extLabel && item[extLabel] ? item[value] : item[label]}
292
- value={item[value]}
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>
342
- );
343
- })}
344
- </el-select>
345
- ];
346
- },
347
- // 可编辑显示模板
348
- renderTableCell(renderOpts, params) {
349
- const { row, column } = params;
350
- const { props, options, optionProps } = renderOpts;
351
- // @ts-ignore
352
- const { label = 'label', value = 'value', extLabel } = optionProps;
353
- const { textValue } = props;
354
- let val = row[column.field];
355
- const item = options.find(opt => opt[value] === val);
356
- if (textValue) {
357
- val = eval(`row.${textValue}`) || row[column.field];
358
- }
359
- if (item) {
360
- val = extLabel ? item[value] : item[label];
361
- }
362
- if (val && props?.multiple && isArray(val)) {
363
- val = val && val.join(',');
364
- }
365
- return [<span>{val}</span>];
366
- },
367
- renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
368
- const { data, field } = params;
369
- const { options, props, optionProps = {}, events } = renderOpts;
370
- const { label = 'label', value = 'value' } = optionProps;
371
- const componentHook = useComponent();
372
-
373
- // 默认值
374
- const { defaultValues, mapField } = props;
375
- if (defaultValues) {
376
- data[field] = defaultValues;
377
- }
378
- /**
379
- * @description: 选中值发生变化时触发
380
- * @param {*} val 目前的选中值
381
- */
382
- function onChange(val) {
383
- componentHook.selectChange(val, data, field, renderOpts, {
384
- datasource: 'data'
385
- });
386
- }
387
-
388
- /**
389
- * @description: 可清空的单选模式下用户点击清空按钮时触发
390
- */
391
- function onClear() {
392
- componentHook.clear(data, field, mapField, events, 'data');
393
- }
394
-
395
- return [
396
- <el-select
397
- v-model={data[field]}
398
- filterable
399
- clearable
400
- style="width: 100%"
401
- {...props}
402
- onChange={v => onChange(v)}
403
- onClear={() => onClear()}
404
- >
405
- {options.map(item => {
406
- return <el-option key={item[value]} label={item[label]} value={item[value]}></el-option>;
407
- })}
408
- </el-select>
409
- ];
410
- }
411
- });
412
- // Lov
413
- VXETable.renderer.add('#lov', {
414
- renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
415
- const { data, field } = params;
416
- const { props, events } = renderOpts;
417
- const componentHook = useComponent();
418
- // 默认值
419
- const { defaultValues, mapField } = props;
420
- if (defaultValues) {
421
- data[field] = defaultValues;
422
- }
423
- /**
424
- * @description: 选中值发生变化时触发
425
- * @param {*} val 目前的选中值
426
- */
427
- function onChange(record, displayField) {
428
- const { mapField, field, displayName, multiple } = props;
429
- if (!multiple) {
430
- const obj = {
431
- [displayName || field]: record[displayField || displayName || field]
432
- };
433
- for (const key in mapField) {
434
- obj[key] = record[mapField[key]];
435
- }
436
- Object.assign(data, obj);
437
- } else if (multiple) {
438
- const obj = {};
439
- data[displayName || field] = record.reduce((curv, prev) => {
440
- for (const key in mapField) {
441
- obj[key] = !curv ? prev[mapField[key]] : obj[key] + ',' + prev[mapField[key]];
442
- }
443
- curv = !curv ? prev[displayName || field] : curv + ',' + prev[displayName || field];
444
- return curv;
445
- }, '');
446
- Object.assign(data, obj);
447
- }
448
- const parm = { row: data, property: field, item: record, field };
449
- events?.change && events.change(parm);
450
- }
451
-
452
- /**
453
- * @description: 点击清空按钮时触发
454
- */
455
- function onClear() {
456
- componentHook.clear(data, field, mapField, events, 'data');
457
- }
458
-
459
- return [
460
- <ut-lov
461
- record={data}
462
- {...props}
463
- mode="vxe"
464
- onChange={(v, f) => onChange(v, f)}
465
- onClear={() => onClear()}
466
- />
467
- ];
468
- },
469
- // 单元格编辑
470
- renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
471
- const { row, column } = params;
472
- const { props, events } = renderOpts;
473
- const componentHook = useComponent();
474
- function onChange(record, displayField) {
475
- const { mapField, field, displayName, multiple } = props;
476
- if (!multiple) {
477
- const obj = {
478
- [displayName || field]: record[displayField || displayName || field]
479
- };
480
- for (const key in mapField) {
481
- obj[key] = record[mapField[key]];
482
- }
483
- Object.assign(row, obj);
484
- }
485
- events?.change && events.change(params, record, row[column.field]);
486
- }
487
-
488
- function onClear() {
489
- componentHook.clear(row, field, mapField, events, 'row');
490
- }
491
-
492
- return [
493
- <ut-lov
494
- record={row}
495
- mode="vxe"
496
- {...props}
497
- onChange={(v, f) => onChange(v, f)}
498
- onClear={() => onClear()}
499
- />
500
- ];
501
- },
502
- // 单元格默认
503
- renderTableDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
504
- const { row, column } = params;
505
- const { props, events } = renderOpts;
506
- const componentHook = useComponent();
507
- function onChange(record, displayField) {
508
- const { mapField, field, displayName, multiple } = props;
509
- if (!multiple) {
510
- const obj = {
511
- [displayName || field]: record[displayField || displayName || field]
512
- };
513
- for (const key in mapField) {
514
- obj[key] = record[mapField[key]];
515
- }
516
- Object.assign(row, obj);
517
- }
518
- events?.change && events.change(params, record, row[column.field]);
519
- }
520
- /**
521
- * @description 清空数据
522
- */
523
- function onClear() {
524
- componentHook.clear(row, field, mapField, events, 'row');
525
- }
526
-
527
- return [
528
- <ut-lov
529
- record={row}
530
- mode="ele"
531
- {...props}
532
- onChange={(v, f) => onChange(v, f)}
533
- onClear={() => onClear()}
534
- />
535
- ];
536
- },
537
- // 可编辑显示模板
538
- renderTableCell(renderOpts, params) {
539
- const { row, column } = params;
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()} />];
558
- }
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)) : {};
817
- };
1
+ /*
2
+ * @Author: wei.li
3
+ * @Date: 2021-12-01 09:18:50
4
+ * @LastEditors: levi7754 levi7754@163.com
5
+ * @LastEditTime: 2025-12-05 18:23:19
6
+ * @Description: file content
7
+ */
8
+
9
+ // @ts-nocheck
10
+
11
+ import dayjs from 'dayjs';
12
+ import { isArray, isEmpty, findTree, isObject, isPlainObject } from 'xe-utils';
13
+ import type {
14
+ FormItemRenderOptions,
15
+ FormItemContentRenderParams,
16
+ VxeColumnPropTypes,
17
+ VxeGlobalRendererHandles
18
+ } from 'vxe-table';
19
+
20
+ import { cookies, storageLocal } from '@utogether/utils';
21
+
22
+ interface SuFormItemRenderOptions extends FormItemRenderOptions {
23
+ sourceData: IRecord;
24
+ }
25
+ interface SuEditRender extends VxeColumnPropTypes.EditRender {
26
+ sourceData: IRecord;
27
+ }
28
+ interface SuRenderCellOptions extends VxeGlobalRendererHandles.RenderCellOptions {
29
+ sourceData: IRecord[];
30
+ }
31
+
32
+ export const VxetableRender = (VXETable, { serviceApi, i18n }) => {
33
+ const dict = storageLocal.getItem('kLov');
34
+
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 } = props;
43
+ const componentHook = useComponent();
44
+
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, row, 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, renderOpts, '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) {
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;
121
+ const { options, props, optionProps = {}, events } = renderOpts;
122
+ // @ts-ignore
123
+ const { label = 'label', value = 'value' } = optionProps;
124
+ const { 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, renderOpts, '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 = {} } = renderOpts;
254
+ const { label = 'label', value = 'value' } = optionProps;
255
+ const { multiple } = props;
256
+ console.log('ssssss');
257
+ const componentHook = useComponent();
258
+
259
+ // 多选时
260
+ const modelField = multiple ? `_${column.field}` : column.field;
261
+ // 默认值
262
+ componentHook.setDefaultValue(props, row, column.field);
263
+
264
+ function onChange(val) {
265
+ componentHook.selectChange(val, row, column.field, renderOpts, {
266
+ column,
267
+ datasource: 'row'
268
+ });
269
+ }
270
+
271
+ function onClear() {
272
+ componentHook.clear(row, column.field, renderOpts, 'row');
273
+ }
274
+
275
+ return [
276
+ <el-select
277
+ v-model={row[modelField]}
278
+ filterable
279
+ clearable
280
+ {...props}
281
+ style="width: 100%"
282
+ class="udp-select-wrapper"
283
+ onChange={v => onChange(v)}
284
+ onClear={() => onClear()}
285
+ >
286
+ {options.map(item => {
287
+ return <el-option key={item[value]} label={item[label]} value={item[value]}></el-option>;
288
+ })}
289
+ </el-select>
290
+ ];
291
+ },
292
+ renderTableDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
293
+ const { row, column } = params;
294
+ const { options, props, optionProps = {} } = renderOpts;
295
+ const { label = 'label', value = 'value', extLabel } = optionProps;
296
+ const { multiple } = props;
297
+ console.log('defaultParams');
298
+ // 多选时
299
+ const modelField = multiple ? `_${column.field}` : column.field;
300
+ // 默认值
301
+ componentHook.setDefaultValue(props, row, column.field);
302
+ function onChange(val) {
303
+ componentHook.selectChange(val, row, column.field, renderOpts, {
304
+ column,
305
+ datasource: 'row'
306
+ });
307
+ }
308
+
309
+ function onClear() {
310
+ componentHook.clear(row, column.field, renderOpts, 'row');
311
+ }
312
+
313
+ return [
314
+ <el-select
315
+ v-model={row[modelField]}
316
+ filterable
317
+ clearable
318
+ {...props}
319
+ style="width: 100%"
320
+ onChange={v => onChange(v)}
321
+ onClear={() => onClear()}
322
+ >
323
+ {options.map(item => {
324
+ return (
325
+ <el-option
326
+ key={item[value]}
327
+ label={extLabel && item[extLabel] ? item[value] : item[label]}
328
+ value={item[value]}
329
+ ></el-option>
330
+ );
331
+ })}
332
+ </el-select>
333
+ ];
334
+ },
335
+ // 可编辑显示模板
336
+ renderTableCell(renderOpts, params) {
337
+ const { row, column } = params;
338
+ const { props, options, optionProps } = renderOpts;
339
+ // @ts-ignore
340
+ const { label = 'label', value = 'value', extLabel } = optionProps;
341
+ console.log('defaultParams');
342
+ const { textValue } = props;
343
+ let val = row[column.field];
344
+ const item = options.find(opt => opt[value] === val);
345
+ if (textValue) {
346
+ val = eval(`row.${textValue}`) || row[column.field];
347
+ }
348
+ if (item) {
349
+ val = extLabel ? item[value] : item[label];
350
+ }
351
+ if (val && props?.multiple && isArray(val)) {
352
+ val = val && val.join(',');
353
+ }
354
+ return [<span>{val}</span>];
355
+ },
356
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
357
+ const { data, field } = params;
358
+ const { options, props, optionProps = {} } = renderOpts;
359
+ const { label = 'label', value = 'value' } = optionProps;
360
+
361
+ const { multiple } = props;
362
+
363
+ const componentHook = useComponent();
364
+
365
+ // 多选时, model挂载到临时字段上
366
+ const modelField = multiple ? `_${field}` : field;
367
+ // 默认值
368
+ multiple && componentHook.setDefaultValue(props, data, field);
369
+ /**
370
+ * @description: 选中值发生变化时触发
371
+ * @param {*} val 目前的选中值
372
+ */
373
+ function onChange(val) {
374
+ componentHook.selectChange(val, data, field, renderOpts, {
375
+ datasource: 'data'
376
+ });
377
+ }
378
+
379
+ /**
380
+ * @description: 可清空的单选模式下用户点击清空按钮时触发
381
+ */
382
+ function onClear() {
383
+ debugger;
384
+ componentHook.clear(data, field, renderOpts, 'data');
385
+ }
386
+
387
+ return [
388
+ <el-select
389
+ v-model={data[modelField]}
390
+ filterable
391
+ clearable
392
+ style="width: 100%"
393
+ {...props}
394
+ onChange={v => onChange(v)}
395
+ onClear={() => onClear()}
396
+ >
397
+ {options.map(item => {
398
+ return <el-option key={item[value]} label={item[label]} value={item[value]}></el-option>;
399
+ })}
400
+ </el-select>
401
+ ];
402
+ }
403
+ });
404
+ // 下拉选择
405
+ VXETable.renderer.add('#textarea', {
406
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
407
+ const { row, column } = params;
408
+ const { props } = renderOpts;
409
+
410
+ const componentHook = useComponent();
411
+ function onChange(val) {
412
+ componentHook.change(val, row, column.field, renderOpts, { column, datasource: 'row' });
413
+ }
414
+
415
+ function onClear() {
416
+ componentHook.clear(row, column.field, renderOpts, 'row');
417
+ }
418
+
419
+ return [
420
+ <vxe-textarea
421
+ v-model={row[column.field]}
422
+ {...props}
423
+ style="width: 100%"
424
+ onChange={v => onChange(v)}
425
+ onClear={() => onClear()}
426
+ />
427
+ ];
428
+ },
429
+ renderTableDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
430
+ const { row, column } = params;
431
+ const { props } = renderOpts;
432
+
433
+ const componentHook = useComponent();
434
+
435
+ function onChange(val) {
436
+ componentHook.change(val, row, column.field, renderOpts, { column, datasource: 'row' });
437
+ }
438
+
439
+ function onClear() {
440
+ componentHook.clear(row, column.field, renderOpts, 'row');
441
+ }
442
+
443
+ return [
444
+ <vxe-textarea v-model={row[column.field]} {...props} onChange={v => onChange(v)} onClear={() => onClear()} />
445
+ ];
446
+ },
447
+ // 可编辑显示模板
448
+ renderTableCell(renderOpts, params) {
449
+ const { row, column } = params;
450
+ return row[column.field];
451
+ },
452
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
453
+ const { data, field } = params;
454
+ const { props } = renderOpts;
455
+ const componentHook = useComponent();
456
+
457
+ // 默认值
458
+ const { defaultValue } = props;
459
+ if (defaultValue) {
460
+ data[field] = defaultValue;
461
+ }
462
+ /**
463
+ * @description: 选中值发生变化时触发
464
+ * @param {*} val 目前的选中值
465
+ */
466
+ function onChange(val) {
467
+ componentHook.change(val, data, field, renderOpts, { datasource: 'data' });
468
+ }
469
+
470
+ /**
471
+ * @description: 可清空的单选模式下用户点击清空按钮时触发
472
+ */
473
+ function onClear() {
474
+ componentHook.clear(data, field, renderOpts, 'data');
475
+ }
476
+
477
+ return [<vxe-textarea v-model={data[field]} {...props} onChange={v => onChange(v)} onClear={() => onClear()} />];
478
+ }
479
+ });
480
+ // Lov
481
+ VXETable.renderer.add('#lov', {
482
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
483
+ const { data, field } = params;
484
+ const { props, events } = renderOpts;
485
+ const componentHook = useComponent();
486
+ // 默认值
487
+ const { defaultValues } = props;
488
+ if (defaultValues) {
489
+ data[field] = defaultValues;
490
+ }
491
+ /**
492
+ * @description: 选中值发生变化时触发
493
+ * @param {*} val 目前的选中值
494
+ */
495
+ function onChange(record, displayField) {
496
+ const { mapField, field, displayName, multiple } = props;
497
+ if (!multiple) {
498
+ const obj = {
499
+ [displayName || field]: record[displayField || displayName || field]
500
+ };
501
+ for (const key in mapField) {
502
+ obj[key] = record[mapField[key]];
503
+ }
504
+ Object.assign(data, obj);
505
+ } else if (multiple) {
506
+ const obj = {};
507
+ data[displayName || field] = record.reduce((curv, prev) => {
508
+ for (const key in mapField) {
509
+ obj[key] = !curv ? prev[mapField[key]] : obj[key] + ',' + prev[mapField[key]];
510
+ }
511
+ curv = !curv ? prev[displayName || field] : curv + ',' + prev[displayName || field];
512
+ return curv;
513
+ }, '');
514
+ Object.assign(data, obj);
515
+ }
516
+ const parm = { data, options: record, field };
517
+ events?.change && events.change(parm);
518
+ }
519
+
520
+ /**
521
+ * @description: 点击清空按钮时触发
522
+ */
523
+ function onClear() {
524
+ componentHook.clear(data, field, renderOpts, 'data');
525
+ }
526
+
527
+ return [
528
+ <ut-lov record={data} {...props} mode="vxe" onChange={(v, f) => onChange(v, f)} onClear={() => onClear()} />
529
+ ];
530
+ },
531
+ // 单元格编辑
532
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
533
+ const { row, column } = params;
534
+ const { props, events } = renderOpts;
535
+ const componentHook = useComponent();
536
+ console.log('lov====');
537
+ function onChange(record, displayField) {
538
+ const { mapField, field, displayName, multiple } = props;
539
+ if (!multiple) {
540
+ const obj = {
541
+ [displayName || field]: record[displayField || displayName || field]
542
+ };
543
+ for (const key in mapField) {
544
+ obj[key] = record[mapField[key]];
545
+ }
546
+ Object.assign(row, obj);
547
+ }
548
+ const params = { row, options: record, field: column.field, column };
549
+ events?.change && events.change(params);
550
+ }
551
+
552
+ function onClear() {
553
+ componentHook.clear(row, field, renderOpts, 'row');
554
+ }
555
+
556
+ return [
557
+ <ut-lov
558
+ record={row}
559
+ mode="vxe"
560
+ transfer
561
+ {...props}
562
+ onChange={(v, f) => onChange(v, f)}
563
+ onClear={() => onClear()}
564
+ />
565
+ ];
566
+ },
567
+ // 单元格默认
568
+ renderTableDefault(renderOpts: VxeColumnPropTypes.EditRender, params) {
569
+ const { row, column } = params;
570
+ const { props, events } = renderOpts;
571
+ const componentHook = useComponent();
572
+ function onChange(record, displayField) {
573
+ const { mapField, field, displayName, multiple } = props;
574
+ if (!multiple) {
575
+ const obj = {
576
+ [displayName || field]: record[displayField || displayName || field]
577
+ };
578
+ for (const key in mapField) {
579
+ obj[key] = record[mapField[key]];
580
+ }
581
+ Object.assign(row, obj);
582
+ }
583
+ const params = { row, options: record, field: column.field, column };
584
+ events?.change && events.change(params);
585
+ }
586
+ /**
587
+ * @description 清空数据
588
+ */
589
+ function onClear() {
590
+ componentHook.clear(row, field, renderOpts, 'row');
591
+ }
592
+
593
+ return [
594
+ <ut-lov record={row} mode="ele" {...props} onChange={(v, f) => onChange(v, f)} onClear={() => onClear()} />
595
+ ];
596
+ },
597
+ // 可编辑显示模板
598
+ renderTableCell(renderOpts, params) {
599
+ const { row, column } = params;
600
+ return [<span>{row[column.field]}</span>];
601
+ }
602
+ });
603
+ // form upload
604
+ VXETable.renderer.add('#upload', {
605
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
606
+ const { row, column } = params;
607
+ const { props, events } = renderOpts;
608
+
609
+ /**
610
+ * @description: 点击清空按钮时触发
611
+ */
612
+ function onClear(file, fielist) {
613
+ row[column.field] = '';
614
+ events?.remove && events?.remove(file, fielist);
615
+ }
616
+
617
+ return [
618
+ <form-upload2
619
+ record={row}
620
+ field={column.field}
621
+ size="mini"
622
+ {...props}
623
+ render-mode="column"
624
+ data-status="edit"
625
+ onRemove={(file, fielist) => onClear(file, fielist)}
626
+ />
627
+ ];
628
+ },
629
+
630
+ // 可编辑显示模板
631
+ renderTableCell(renderOpts, params) {
632
+ const { row, column } = params;
633
+ const { props } = renderOpts;
634
+ return [
635
+ <form-upload2
636
+ record={row}
637
+ field={column.field}
638
+ size="mini"
639
+ {...props}
640
+ mode="image"
641
+ render-mode="column"
642
+ data-status="detail"
643
+ />
644
+ ];
645
+ },
646
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
647
+ const { data, field } = params;
648
+ const { props, events } = renderOpts;
649
+ /**
650
+ * @description: 点击清空按钮时触发
651
+ */
652
+ function onClear(file, fielist) {
653
+ data[field] = '';
654
+ events?.remove && events?.remove(file, fielist);
655
+ }
656
+
657
+ if (props.singleMode) {
658
+ // 单个模式下,限制只能单个上传
659
+ Object.assign(props, { multiple: false, limitCount: 1, autoHiddenButton: true });
660
+ }
661
+ if (!props.mode || props.mode === 'image') {
662
+ props.imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'apk'];
663
+ }
664
+
665
+ console.log({ props });
666
+
667
+ return [
668
+ <form-upload2
669
+ record={data}
670
+ field={field}
671
+ mode="image"
672
+ {...props}
673
+ onRemove={(file, fielist) => onClear(file, fielist)}
674
+ />
675
+ ];
676
+ }
677
+ });
678
+
679
+ // 创建一个简单的超链接渲染
680
+ VXETable.renderer.add('#tag', {
681
+ // 默认显示模板
682
+ renderTableDefault(renderOpts, params) {
683
+ const { row, column } = params;
684
+ const {
685
+ props: { code, tagMap }
686
+ } = renderOpts;
687
+ function getTagType() {
688
+ return row[column.field] ? tagMap[row[column.field]] : null;
689
+ }
690
+ return [
691
+ row[column.field] ? (
692
+ <el-tag effect="dark" type={getTagType()}>
693
+ {getValue(code, row[column.field])}
694
+ </el-tag>
695
+ ) : null
696
+ ];
697
+ }
698
+ });
699
+
700
+ VXETable.renderer.add('#switch', {
701
+ renderTableDefault(renderOpts, params) {
702
+ const { row, column } = params;
703
+ const {
704
+ props: { code, activeValue, inactiveValue },
705
+ events
706
+ } = renderOpts;
707
+ function onChange(value) {
708
+ const params = { row, column, value };
709
+ events?.change && events.change(params);
710
+ }
711
+ return [
712
+ row[column.field] ? (
713
+ <el-switch
714
+ v-model={row[column.field]}
715
+ inline-prompt
716
+ size="large"
717
+ style="--el-switch-on-color: #13ce66; --el-switch-off-color: #E6A23C"
718
+ {...renderOpts.props}
719
+ active-text={getValue(code, activeValue)}
720
+ inactive-text={getValue(code, inactiveValue)}
721
+ onChange={v => onChange(v)}
722
+ />
723
+ ) : null
724
+ ];
725
+ }
726
+ });
727
+
728
+ VXETable.renderer.add('#iconSelect', {
729
+ renderTableEdit(renderOpts: VxeColumnPropTypes.EditRender, params) {
730
+ const { row, column } = params;
731
+ return [<SuIconSelect v-model={row[column.field]} teleported={false} />];
732
+ },
733
+ renderTableCell(renderOpts, params) {
734
+ const { row, column } = params;
735
+ return [<IconifyIconOffline icon={row[column.field]} style="font-size: 16px;" />];
736
+ },
737
+ renderItemContent(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
738
+ const { data, field } = params;
739
+ return [<SuIconSelect v-model={data[field]} teleported />];
740
+ }
741
+ });
742
+
743
+ VXETable.renderer.add('#treeSelect', {
744
+ renderTableEdit(renderOpts: SuEditRender, params) {
745
+ const { row, column } = params;
746
+ const { props, sourceData, events } = renderOpts;
747
+
748
+ return [
749
+ <el-tree-select
750
+ v-model={row[column.field]}
751
+ data={sourceData}
752
+ check-strictly
753
+ {...props}
754
+ filterable
755
+ onCheckChange={(node, selected, isLeaf) => onCheckChange(node, selected, isLeaf, events)}
756
+ onNodeClick={(data, node, treeNode) => onNodeClick(data, node, treeNode, events)}
757
+ onCurrentChange={(data, node) => onCurrentChange(data, node, events)}
758
+ />
759
+ ];
760
+ },
761
+ renderTableCell(renderOpts: SuRenderCellOptions, params) {
762
+ const { row, column } = params;
763
+ const { sourceData, props = {} } = renderOpts;
764
+ const { children = 'children', label = 'label' } = props;
765
+ const data = findTree(sourceData, item => item['value'] === row[column.field], { children });
766
+ return data ? [<span>{data.item[label]}</span>] : null;
767
+ },
768
+ renderItemContent(renderOpts: SuFormItemRenderOptions, params: FormItemContentRenderParams) {
769
+ const { data, field } = params;
770
+ const { props, sourceData, events } = renderOpts;
771
+ return [
772
+ <el-tree-select
773
+ v-model={data[field]}
774
+ data={sourceData}
775
+ check-strictly
776
+ {...props}
777
+ filterable
778
+ onCheckChange={(node, selected, isLeaf) => onCheckChange(node, selected, isLeaf, events)}
779
+ onNodeClick={(data, node, treeNode) => onNodeClick(data, node, treeNode, events)}
780
+ onCurrentChange={(data, node) => onCurrentChange(data, node, events)}
781
+ />
782
+ ];
783
+ }
784
+ });
785
+
786
+ /**
787
+ * 组件公共方法
788
+ * @returns
789
+ */
790
+ const useComponent = () => {
791
+ // 下拉框选择
792
+ /**
793
+ * select下拉选择change事件
794
+ * @param value 选择值
795
+ * @param data 数据源
796
+ * @param field 字段
797
+ * @param renderOpts 渲染参数
798
+ * @param opts 数据源类型等
799
+ * @return `{ data: 数据源, field: 字段, options?: 选中的选项组, option?: 选中的选项, column?: 列信息 }`
800
+ */
801
+ const selectChange = (value, data, field, renderOpts, opts) => {
802
+ let option = null;
803
+
804
+ const { datasource } = opts;
805
+ const { options, props, optionProps = {}, events } = renderOpts;
806
+
807
+ const callData = { [datasource]: data, field };
808
+ // 1、清空原有数据
809
+ data[field] = null;
810
+ if (!isEmpty(value) && props?.multiple) {
811
+ // 2、给实际字段赋值
812
+ data[field] = value.join(',');
813
+ option = [];
814
+ // 多选
815
+ value.forEach(item => {
816
+ const selectOpt = options.find(opt => item === opt[optionProps?.value]);
817
+ if (selectOpt && !isEmpty(props.mapField) && isObject(props.mapField)) {
818
+ Object.keys(props.mapField).forEach(key => {
819
+ const val = selectOpt[props.mapField[key]];
820
+ const ov = data[key] ? data[key].toString() : '';
821
+ // 默认用逗号(,)分割
822
+ data[key] = ov && !ov.includes(val) ? `${ov},${val}` : val;
823
+ });
824
+ }
825
+ selectOpt && option.push(selectOpt);
826
+ });
827
+ Object.assign(callData, { options: option });
828
+ } else {
829
+ // 3、原字段赋值, 多选进来说明必定是空值
830
+ data[field] = props?.multiple ? null : value;
831
+ option = options.find(opt => value === opt[optionProps?.value]);
832
+ if (!isEmpty(props.mapField) && isObject(props.mapField)) {
833
+ Object.keys(props.mapField).forEach(key => {
834
+ data[key] = option ? option[props.mapField[key]] : null;
835
+ });
836
+ }
837
+ Object.assign(callData, { option });
838
+ }
839
+ datasource === 'row' && Object.assign(callData, { column: opts.column });
840
+ events?.change && events.change(callData);
841
+ };
842
+ const setDefaultValue = (props, data, field) => {
843
+ const { multiple, defaultValue } = props;
844
+ // 多选时, model挂载到临时字段上
845
+ const modelField = multiple ? `_${field}` : field;
846
+ // 默认值
847
+ if (!data[field] && defaultValue) {
848
+ data[field] = defaultValue;
849
+ if (isPlainObject(defaultValue)) {
850
+ const keys = Object.keys(defaultValue);
851
+ keys.forEach(key => {
852
+ data[key] = data[key] || defaultValue[key];
853
+ });
854
+ }
855
+ }
856
+ if (!data[modelField] && data[field]) {
857
+ data[modelField] = multiple ? data[field]?.split(',') : data[field];
858
+ }
859
+ };
860
+ const remote = async (query, field, renderOpts) => {
861
+ const { options, props, events } = renderOpts;
862
+ const { fetchField, url, defaultParams = {}, method = 'get' } = props;
863
+ const commonParam = getCookieParam();
864
+ const params = Object.assign(
865
+ { pageSize: 20, pageNum: 1, ...commonParam, ...defaultParams },
866
+ { [fetchField || field]: query }
867
+ );
868
+ if (props.loading) return;
869
+ let res;
870
+ try {
871
+ options.length = 0;
872
+ props.loading = true;
873
+ res = await serviceApi[method](url, params);
874
+ if (events?.filterMethod) {
875
+ options.push(...events.filterMethod(res.list || res));
876
+ } else if (res) {
877
+ res.list ? options.push(...res.list) : options.push(...res);
878
+ }
879
+ } finally {
880
+ props.loading = false;
881
+ }
882
+ };
883
+ // 清除数据
884
+ const clear = (data, field, renderOpts, datasource) => {
885
+ const { props, events } = renderOpts;
886
+ debugger;
887
+ const { mapField } = props;
888
+ data[field] = null;
889
+ if (props?.multiple) {
890
+ data[`_${field}`] = [];
891
+ }
892
+ if (!isEmpty(mapField)) {
893
+ for (const key in mapField) {
894
+ data[key] = null;
895
+ }
896
+ }
897
+ events?.clear && events.clear({ [datasource]: data, field });
898
+ };
899
+ const change = (data, field, mapField, events, datasource) => {
900
+ data[field] = null;
901
+ if (!isEmpty(mapField)) {
902
+ for (const key in mapField) {
903
+ data[key] = null;
904
+ }
905
+ }
906
+ events?.change && events.change({ [datasource]: data, field });
907
+ };
908
+ return { clear, change, remote, selectChange, setDefaultValue };
909
+ };
910
+
911
+ /**
912
+ * 当复选框被点击的时候触发
913
+ * @param node 传递给 data 属性的数组中该节点所对应的对象
914
+ * @param selected 节点本身是否被选中
915
+ * @param isLeaf 节点的子树中是否有被选中的节点
916
+ */
917
+ const onCheckChange = (node, selected, isLeaf, events) => {
918
+ console.log(node, selected, isLeaf);
919
+ events?.checkChange && events?.checkChange(node, selected, isLeaf);
920
+ };
921
+ /**
922
+ * 节点被点击的时候触发
923
+ * @param nodeObject 点击的节点对象
924
+ * @param node TreeNode 的 node 属性
925
+ * @param treeNode TreeNode
926
+ */
927
+ const onNodeClick = (nodeObject, node, treeNode, events) => {
928
+ events?.checkChange && events?.checkChange(nodeObject, node, treeNode);
929
+ };
930
+ /**
931
+ * 当前选中节点变化时触发的事件
932
+ * @param data 当前节点的数据
933
+ * @param node 当前节点的 Node 对象
934
+ */
935
+ const onCurrentChange = (data, node, events) => {
936
+ events?.checkChange && events?.checkChange(data, node);
937
+ };
938
+
939
+ function getValue(code, value) {
940
+ if (!value || !code || !dict) return value;
941
+ return dict[code]?.children?.find(item => item.dictCode === value)?.dictName;
942
+ }
943
+
944
+ return VXETable;
945
+ };
946
+
947
+ const getCookieParam = () => {
948
+ const kCOOKIES = 'kCookies_param';
949
+ return cookies.get(kCOOKIES) ? JSON.parse(cookies.get(kCOOKIES)) : {};
950
+ };