@utogether/udp-core 2.0.0-beta.24 → 2.0.0-beta.26

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 (155) hide show
  1. package/dist/403-D6Wb3JJh.js +72 -0
  2. package/dist/404-B_HNbPNV.js +72 -0
  3. package/dist/500-BMemTTy1.js +77 -0
  4. package/dist/AuthorityInfo-6wHxwiFM.js +91 -0
  5. package/dist/AuthorityPanel-OqF_DvXA.js +98 -0
  6. package/dist/Company-BLXSfow0.js +21 -0
  7. package/dist/CompanyPanel-B4kRZ5Cg.js +199 -0
  8. package/dist/DataSet-CuGZcKC-.js +141 -0
  9. package/dist/Department-oFhsa7cd.js +21 -0
  10. package/dist/DepartmentPanel-B1UGpu-r.js +242 -0
  11. package/dist/DepartmentPanel-BL58AdoT.js +2 -0
  12. package/dist/DesignPanel-DmkFVw1N.js +1196 -0
  13. package/dist/DictView-CC5yMzOq.js +100 -0
  14. package/dist/File-WJXjGYxr.js +89 -0
  15. package/dist/InvOrganization-BwMmD8Ua.js +76 -0
  16. package/dist/Org-HgnOWubi.js +76 -0
  17. package/dist/Preview-CAzWxLmP.js +45 -0
  18. package/dist/ReIcon-DecitXmg.js +413 -0
  19. package/dist/ReportDefine-BgLM-Rjk.js +10 -0
  20. package/dist/ReportDesign-DwchGG2P.js +158 -0
  21. package/dist/ReportQuery-D5jaRJEn.js +101 -0
  22. package/dist/ReportQueryFrom-CNlmtYey.js +198 -0
  23. package/dist/ReportTemplate-CNcTmccs.js +162 -0
  24. package/dist/Role-Be8WfdCA.js +21 -0
  25. package/dist/RoleAssign-CtehGAUf.js +22 -0
  26. package/dist/RolePanel-CAwITg_q.js +131 -0
  27. package/dist/RolePanel-SN0FGFZ7.js +176 -0
  28. package/dist/ScrollPanel-DW30pGz1.js +88 -0
  29. package/dist/Staff-V2YsNKcj.js +22 -0
  30. package/dist/StaffInfo-CKRPW0r4.js +149 -0
  31. package/dist/StaffPanel-BxcgMg7u.js +143 -0
  32. package/dist/SysUser-Dxyj5w5m.js +12 -0
  33. package/dist/SysUserPanel-DI6CWcZo.js +365 -0
  34. package/dist/SystemMenu-BBHREM8T.js +154 -0
  35. package/dist/UserInfo-BMVQ0xwE.js +194 -0
  36. package/dist/_plugin-vue_export-helper-C6QCLu9I.js +8 -0
  37. package/dist/api-BFNxcxSN.js +30 -0
  38. package/dist/authority-BJFEUdrh.js +20 -0
  39. package/dist/await-to-js.es5-DkWYmPXW.js +10 -0
  40. package/dist/childView-BBjPEraB.js +184 -0
  41. package/dist/childView-DNqG2UVm.js +181 -0
  42. package/dist/code-rule-QFrhqFrW.js +151 -0
  43. package/dist/contant-Q77dU_V3.js +4 -0
  44. package/dist/core.es.js +6 -23
  45. package/dist/cron-task-BpUDKEAU.js +131 -0
  46. package/dist/flow-task-DAc2NrDU.js +11 -0
  47. package/dist/frameView-Di0zJZUR.js +39 -0
  48. package/dist/img/v_img.svg +1 -1
  49. package/dist/layout-home-BVp7vYLR.js +239 -0
  50. package/dist/layoutView-B6Mx2ERA.js +2662 -0
  51. package/dist/log-in-BrNB0mLz.js +117 -0
  52. package/dist/log-out-dYfqvzy6.js +111 -0
  53. package/dist/login-D_Hjy3Jd.js +231 -0
  54. package/dist/login-log-CJak-ANA.js +79 -0
  55. package/dist/lov-view-DM5Nm5tW.js +95 -0
  56. package/dist/menuInfo-BlOY1KZW.js +346 -0
  57. package/dist/mitt-CQgI7DYU.js +27 -0
  58. package/dist/pda-app-CA7YI37u.js +589 -0
  59. package/dist/redirect-N0k4tImU.js +16 -0
  60. package/dist/resource-CfQTHFcs.js +94 -0
  61. package/dist/su-welcome-DVD3S_du.js +799 -0
  62. package/dist/sys-config-Ddb3vBpK.js +316 -0
  63. package/dist/system-Cm3lyBas.js +1528 -0
  64. package/dist/udp-core-DaQd5CF1.js +2028 -0
  65. package/dist/udp-core.css +2 -1
  66. package/dist/useDataThemeChange-DJ4K3VGp.js +226 -0
  67. package/dist/useNav-BhOJIdrJ.js +106 -0
  68. package/dist/utogether-l7JXs4Lv.js +4 -0
  69. package/dist/water-mark-WDQZ9YqB.js +119 -0
  70. package/dist/wecom-push-kWkAVRCj.js +77 -0
  71. package/package.json +1 -1
  72. package/src/App.vue +5 -0
  73. package/src/api/index.ts +51 -51
  74. package/src/components/udp/grid/index.vue +9 -11
  75. package/src/components/udp/index.ts +9 -8
  76. package/src/components/udp/lov/index.vue +430 -0
  77. package/src/components/udp/upload/index.vue +444 -444
  78. package/src/components/udp/utils.ts +420 -414
  79. package/src/main.ts +4 -6
  80. package/src/plugins/vxe-table/index.ts +1 -1
  81. package/src/plugins/vxe-table/render.tsx +999 -998
  82. package/src/router/utils.ts +2 -3
  83. package/src/views/login/login-view.vue +297 -301
  84. package/src/views/ulogin/login.vue +3 -32
  85. package/tsconfig.json +1 -1
  86. package/vite.config.ts +8 -3
  87. package/dist/403-DDCAPCYb.js +0 -65
  88. package/dist/404-BclWW4UB.js +0 -65
  89. package/dist/500-BAggMgTl.js +0 -67
  90. package/dist/AuthorityInfo-liCxYVNc.js +0 -4
  91. package/dist/AuthorityInfo.vue_vue_type_style_index_0_lang-Bd5A4CD-.js +0 -100
  92. package/dist/AuthorityPanel-CRlAwbaI.js +0 -4
  93. package/dist/AuthorityPanel.vue_vue_type_style_index_0_lang-DxhZjp1S.js +0 -114
  94. package/dist/Company-DjaOAaWM.js +0 -25
  95. package/dist/CompanyPanel-Dp_2z717.js +0 -206
  96. package/dist/DataSet-DT-rGICv.js +0 -147
  97. package/dist/Department-Bp5RGbl9.js +0 -25
  98. package/dist/DepartmentPanel-Bg4xM4Lx.js +0 -254
  99. package/dist/DesignPanel-BS2ioHd_.js +0 -4
  100. package/dist/DesignPanel.vue_vue_type_style_index_0_lang-DWwfRVCj.js +0 -1013
  101. package/dist/DictView-pYJXt6IS.js +0 -111
  102. package/dist/InvOrganization-D90gRzlN.js +0 -74
  103. package/dist/Org-Dk4KuIx2.js +0 -39
  104. package/dist/Preview-DpZR6uKs.js +0 -48
  105. package/dist/ReportDefine-PtJnfaLw.js +0 -10
  106. package/dist/ReportDesign-4HWkcTtA.js +0 -165
  107. package/dist/ReportQuery-BPY1lWFn.js +0 -75
  108. package/dist/ReportQueryFrom-CHFlkZ42.js +0 -4
  109. package/dist/ReportQueryFrom.vue_vue_type_style_index_0_lang-DbbQydKz.js +0 -178
  110. package/dist/ReportTemplate-C2F3oy8I.js +0 -161
  111. package/dist/Role-iTP6DYOi.js +0 -25
  112. package/dist/RoleAssign-DIYNHQeF.js +0 -26
  113. package/dist/RolePanel-0ojFIz9G.js +0 -4
  114. package/dist/RolePanel-B0Yr5vjo.js +0 -4
  115. package/dist/RolePanel.vue_vue_type_script_setup_true_lang-CHAj3dCD.js +0 -132
  116. package/dist/RolePanel.vue_vue_type_script_setup_true_lang-CXZBxePU.js +0 -154
  117. package/dist/ScrollPanel.vue_vue_type_style_index_0_lang-DtNzPRjS.js +0 -101
  118. package/dist/Staff-sftZ0bIV.js +0 -26
  119. package/dist/StaffInfo-BG2FMXzR.js +0 -4
  120. package/dist/StaffInfo.vue_vue_type_script_setup_true_lang-DzGn0pYY.js +0 -108
  121. package/dist/StaffPanel-BydqiitC.js +0 -4
  122. package/dist/StaffPanel.vue_vue_type_script_setup_true_lang-C42Pnb-b.js +0 -154
  123. package/dist/SysUser-qMGVHpJ_.js +0 -15
  124. package/dist/SysUserPanel-Bh1HgSAr.js +0 -4
  125. package/dist/SysUserPanel.vue_vue_type_script_setup_true_lang-BBEMYLQN.js +0 -356
  126. package/dist/SystemMenu-DUbWmLip.js +0 -156
  127. package/dist/UserInfo-DNkiTdWm.js +0 -4
  128. package/dist/UserInfo.vue_vue_type_style_index_0_lang-B1eNklEd.js +0 -160
  129. package/dist/await-to-js.es5-Bv3Eu4mi.js +0 -10
  130. package/dist/childView-CjUjh8Da.js +0 -4
  131. package/dist/childView-DT9luEEK.js +0 -4
  132. package/dist/childView.vue_vue_type_style_index_0_lang-CgqosFJQ.js +0 -183
  133. package/dist/childView.vue_vue_type_style_index_0_lang-DkXHMFPd.js +0 -143
  134. package/dist/code-rule-uOazxFfn.js +0 -148
  135. package/dist/cron-task-DEykunjo.js +0 -135
  136. package/dist/flow-task-B07st2aD.js +0 -10
  137. package/dist/frameView-FxzlbkeM.js +0 -44
  138. package/dist/index-BnxyUGKa.js +0 -7944
  139. package/dist/layout-home-C0jme8Ju.js +0 -232
  140. package/dist/layoutView-BqMAHIxF.js +0 -3239
  141. package/dist/log-in-skZaWMBY.js +0 -117
  142. package/dist/log-out-BiND7muW.js +0 -130
  143. package/dist/login-C-184YPO.js +0 -235
  144. package/dist/login-log-BEHYT0v0.js +0 -70
  145. package/dist/lov-view-Df-swRfy.js +0 -99
  146. package/dist/menuInfo-CpyjX4a4.js +0 -4
  147. package/dist/menuInfo.vue_vue_type_style_index_0_lang-D09-OKji.js +0 -363
  148. package/dist/pda-app-DP87aTBc.js +0 -710
  149. package/dist/redirect-BqegffKC.js +0 -15
  150. package/dist/resource-CAldbnw4.js +0 -97
  151. package/dist/su-welcome-DoBUqadB.js +0 -42225
  152. package/dist/sys-config-hGuE7DUf.js +0 -385
  153. package/dist/useNav-Cf_e5pBY.js +0 -92
  154. package/dist/utogether-MlnyYtNS.js +0 -4
  155. package/dist/wecom-push-DR7NsNro.js +0 -70
@@ -1,444 +1,444 @@
1
- <!--
2
- * @Author: wei.li
3
- * @Date: 2022-06-21 14:50:52
4
- * @LastEditors: levi7754 levi7754@163.com
5
- * @LastEditTime: 2026-03-23 14:39:47
6
- * @Description: excel数据导入
7
- -->
8
- <template>
9
- <vxe-modal v-model="visible" :show-header="false" fullscreen remember @close="onClose">
10
- <template #default>
11
- <vxe-grid ref="xgrid" v-bind="gridOptions" v-on="gridEvents">
12
- <template v-for="col in columns" :key="col.field" #[col.field!]="{ row }">
13
- <el-select v-if="col.dictCode && !col.disabled" v-model.trim="row[col.field!]" clearable>
14
- <el-option
15
- v-for="child in dict[col.dictCode]?.children"
16
- :key="child.dictCode"
17
- :value="child.dictCode"
18
- :label="child.dictName"
19
- />
20
- </el-select>
21
- <el-date-picker
22
- v-else-if="['date', 'month', 'datetime'].includes(col.dataType) && !col.disabled"
23
- v-model.trim="row[col.field!]"
24
- :type="col.dataType"
25
- value-format="YYYY-MM-DD hh:mm:ss"
26
- />
27
- <input v-else-if="!col.da && !col.disabled" v-model.trim="row[col.field!]" class="ut-input" />
28
- <span v-else-if="!showErrorMsg">{{ row[col.field!] }}</span>
29
- <span v-else>{{ row[col.field!] }}</span>
30
- </template>
31
- <template #pager>
32
- <vxe-pager
33
- v-model:current-page="listQuery.currentPage"
34
- v-model:page-size="listQuery.pageSize"
35
- :layouts="layouts"
36
- :page-sizes="[200, 500, 1000, 2000, 5000, 10000]"
37
- :total="listQuery.total"
38
- @page-change="handlePageChange"
39
- /></template>
40
- </vxe-grid>
41
- </template>
42
- </vxe-modal>
43
- </template>
44
-
45
- <script lang="ts">
46
- export default {
47
- name: 'UtUpload'
48
- };
49
- </script>
50
- <script setup lang="ts">
51
- import { reactive, ref, watch, getCurrentInstance } from 'vue';
52
- import { toDateString } from 'xe-utils';
53
- import { storageLocal, cookies, warnMessage } from '@utogether/utils';
54
- import accounting from 'accounting';
55
- import { useI18n } from 'vue-i18n';
56
- import { VxeTableInstance, VxeGridProps, VxeGridListeners } from 'vxe-table';
57
- import { VxeUI } from 'vxe-pc-ui';
58
- import type { VxePagerPropTypes, VxePagerEvents } from 'vxe-pc-ui';
59
-
60
- export interface IProps {
61
- defaultParams?: IRecord;
62
- options?: IRecord;
63
- columns: Array<ITableColProps>;
64
- templateData?: Array<ITableColProps>;
65
- serviceCode?: string;
66
- url?: string;
67
- sourceList?: string;
68
- }
69
-
70
- // const importOptions = {
71
- // template: [
72
- // {
73
- // [t('message.seqNum')]: 10,
74
- // [t('message.valueCode')]: 'red',
75
- // [t('message.valueDesc')]: '红色',
76
- // [t('message.valueDescEn')]: '1000,88.00'
77
- // }
78
- // ],
79
- // columns: [
80
- // { field: t('message.seqNum'), mapField: 'seqNum' },
81
- // { field: t('message.valueCode'), mapField: 'valueCode' },
82
- // { field: t('message.valueDesc'), mapField: 'valueDesc' },
83
- // { field: t('message.valueDescEn'), mapField: 'valueDescEn', valueType: 'number', decimal: 2 },
84
- // { field: '异常信息', mapField: 'errorMessage', disabled: true, minWidth: 150 }
85
- // ],
86
- // options: {
87
- // errorField: 'errorMessage',
88
- // filename: '值集导入模板'
89
- // }
90
- // }
91
-
92
- const props = withDefaults(defineProps<IProps>(), {
93
- defaultParams: (): IRecord => {
94
- return {};
95
- },
96
- options: (): IRecord => {
97
- return {
98
- filename: '数据模板',
99
- errorField: 'errorMsg',
100
- errListField: 'list'
101
- };
102
- },
103
- columns: () => [],
104
- templateData: () => [],
105
- sourceList: 'list'
106
- });
107
-
108
- const instance = getCurrentInstance()!;
109
- const serviceApi = instance.appContext.config.globalProperties.$serviceApi;
110
- const visible = defineModel<boolean>('visible');
111
-
112
- const { t } = useI18n();
113
-
114
- const showErrorMsg = ref(false);
115
-
116
- const dict = storageLocal.getItem('kLov');
117
-
118
- watch(
119
- () => visible.value,
120
- nv => {
121
- if (nv) {
122
- gridOptions.data = [];
123
- }
124
- }
125
- );
126
-
127
- const getColumns = () => {
128
- const columns = props.columns.map(col => {
129
- col.slots = { default: col.field };
130
- col.title = col.field;
131
- col.decimal = col.decimal;
132
- return col;
133
- });
134
- const col = {
135
- type: 'checkbox',
136
- width: 40,
137
- align: 'center',
138
- fixed: 'left'
139
- };
140
- columns.unshift(col);
141
- console.log('columns===', columns);
142
- return columns;
143
- };
144
-
145
- const listQuery = ref({ pageSize: 200, currentPage: 1, total: 0 });
146
-
147
- const layouts: VxePagerPropTypes.Layouts = [
148
- 'Sizes',
149
- 'PrevJump',
150
- 'PrevPage',
151
- 'Number',
152
- 'NextPage',
153
- 'NextJump',
154
- 'FullJump',
155
- 'Total'
156
- ];
157
-
158
- const height = window.innerHeight - 20;
159
-
160
- const xgrid = ref<VxeTableInstance>();
161
- // 导入的所有数据
162
- let dataList = [];
163
-
164
- const importConfig = {
165
- mode: 'covering',
166
- types: ['csv', 'xlsx'],
167
- afterImportMethod: onImportMethod
168
- };
169
-
170
- const gridOptions = reactive<VxeGridProps>({
171
- border: true,
172
- height,
173
- data: [],
174
- importConfig,
175
- showOverflow: true,
176
- loading: false,
177
- toolbarConfig: {
178
- buttons: [
179
- {
180
- code: 'import_plus',
181
- name: t('message.btn.upload'),
182
- icon: 'ri-upload-2-line',
183
- status: 'primary'
184
- },
185
- {
186
- code: 'save_plus',
187
- name: t('message.btn.save'),
188
- icon: 'ri-save-3-line',
189
- status: 'success'
190
- },
191
- {
192
- code: 'del_plus',
193
- name: t('message.btn.delete'),
194
- icon: 'ri-delete-bin-line',
195
- status: 'danger'
196
- },
197
- {
198
- code: 'export_plus',
199
- name: t('message.btn.downloadTemp'),
200
- icon: 'ri-download-2-line',
201
- status: 'warning'
202
- }
203
- ],
204
- tools: [
205
- {
206
- code: 'question',
207
- name: t('message.btn.FAQ'),
208
- status: 'primary',
209
- icon: 'vxe-icon-info-circle-fill'
210
- },
211
- {
212
- code: 'replay',
213
- name: t('message.btn.back'),
214
- status: 'info',
215
- icon: 'vxe-icon-undo'
216
- }
217
- ]
218
- },
219
- columns: getColumns()
220
- });
221
-
222
- const gridEvents: VxeGridListeners = {
223
- toolbarButtonClick({ code }) {
224
- // const $grid = xgrid.value;
225
- switch (code) {
226
- case 'import_plus': {
227
- handleImport();
228
- break;
229
- }
230
- case 'save_plus': {
231
- handleSave();
232
- break;
233
- }
234
- case 'del_plus': {
235
- handleDelete();
236
- break;
237
- }
238
- case 'export_plus': {
239
- handleDownLoadFile();
240
- break;
241
- }
242
- }
243
- },
244
- toolbarToolClick({ code }) {
245
- // const $grid = xgrid.value;
246
- switch (code) {
247
- case 'replay': {
248
- onClose();
249
- break;
250
- }
251
- case 'question': {
252
- showImportQuestion();
253
- break;
254
- }
255
- }
256
- }
257
- };
258
-
259
- const handleImport = () => {
260
- dataList = [];
261
- xgrid.value?.openImport();
262
- };
263
- // 导入后获取数据
264
- function onImportMethod(options: any) {
265
- dataList = options.$table.getTableData().fullData;
266
- // 标题会默认导入,删除第一行
267
- // dataList.splice(0, 1);
268
- const columns = getColumns().filter(f => !f.type && f.mapField !== props.options.errorField);
269
- columns.forEach(col => {
270
- const idx = dataList.findIndex(data => data[col.field!] === col.field);
271
- idx !== -1 && dataList.splice(idx, 1);
272
- });
273
- props.columns.forEach(col => {
274
- if (col.dateFormatter || col.valueType === 'number') {
275
- dataList.forEach(data => {
276
- if (col.dateFormatter) {
277
- data[col.field!] = toDateString(data[col.field!], col.dateFormatter || 'yyyy-MM-dd HH:mm:ss');
278
- } else {
279
- data[col.field!] = accounting.unformat(data[col.field]).toFixed(col.decimal || 6);
280
- }
281
- });
282
- }
283
- });
284
- listQuery.value.total = dataList.length;
285
- getDataList();
286
- }
287
-
288
- const getDataList = () => {
289
- const { currentPage, pageSize } = listQuery.value;
290
- gridOptions.data = dataList.filter(
291
- (data, idx) => idx < pageSize * currentPage && idx >= pageSize * (currentPage - 1)
292
- );
293
- };
294
- // 切换页数
295
- const handlePageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }) => {
296
- listQuery.value.currentPage = currentPage;
297
- listQuery.value.pageSize = pageSize;
298
- getDataList();
299
- };
300
- // 模板下载
301
- const handleDownLoadFile = () => {
302
- const data: ITableColProps[] = [];
303
- if (props.templateData.length) {
304
- data.push(...props.templateData);
305
- } else {
306
- const obj: ITableColProps = {};
307
- getColumns()
308
- .filter(f => f.type !== 'checkbox')
309
- .forEach(col => {
310
- obj[col.field!] = '案例';
311
- });
312
- data.push(obj);
313
- }
314
- const opt: IRecord = {
315
- filename: props.options.filename,
316
- type: 'xlsx',
317
- columns: getColumns().filter(f => f.mapField !== props.options.errorField && f.type !== 'checkbox'),
318
- data
319
- };
320
- xgrid.value?.exportData(opt);
321
- };
322
-
323
- const handleSave = async () => {
324
- if (!dataList.length) {
325
- return warnMessage(t('message.importEmpty'));
326
- }
327
- const type = await VxeUI.modal.confirm(t('message.importRecord'));
328
- if (type === 'confirm') {
329
- gridOptions.loading = true;
330
- const { url } = props;
331
- formatterData('toSave');
332
- serviceApi
333
- .post(url, dataList)
334
- .then((res: any) => {
335
- if (res?.status === 'error' || res?.length) {
336
- showErrorMsg.value = true;
337
- setErrorMessage(res?.length ? res : res[props.options.errListField || props.sourceList]);
338
- VxeUI.modal.message({
339
- content: t('message.importFailed'),
340
- status: 'error'
341
- });
342
- } else {
343
- VxeUI.modal.message({
344
- content: t('message.importSuccess'),
345
- status: 'success'
346
- });
347
- onClose();
348
- }
349
- })
350
- .finally(() => {
351
- showErrorMsg.value = false;
352
- gridOptions.loading = false;
353
- });
354
- }
355
- };
356
-
357
- /**
358
- * @description:删除行
359
- */
360
- const handleDelete = () => {
361
- const checkboxRecords = xgrid.value?.getCheckboxRecords();
362
- if (!checkboxRecords?.length) {
363
- return VxeUI.modal.message({
364
- content: t('message.selectedRecord'),
365
- status: 'warning'
366
- });
367
- }
368
- checkboxRecords.forEach(record => {
369
- const idx = dataList.findIndex(data => data._X_ROW_KEY === record._X_ROW_KEY)!;
370
- idx !== -1 && dataList.splice(idx, 1);
371
- });
372
- gridOptions.data = dataList;
373
- };
374
-
375
- const setErrorMessage = (array: ITableColProps[]) => {
376
- listQuery.value.total = array.length;
377
- dataList = array.map((item, idx) => {
378
- item._X_ROW_KEY = idx;
379
- return item;
380
- });
381
- formatterData('toShow');
382
- getDataList();
383
- };
384
- const formatterData = (formatterType: string) => {
385
- gridOptions.columns!.forEach((col: any) => {
386
- if (formatterType === 'toSave') {
387
- const commonParam = cookies.get('kCookies_param') ? JSON.parse(cookies.get('kCookies_param')!) : {};
388
- dataList.forEach(data => {
389
- data[col.mapField] = data[col.field];
390
- Object.assign(data, commonParam, props.defaultParams);
391
- });
392
- } else {
393
- dataList.forEach(data => {
394
- data[col.field] = data[col.mapField];
395
- });
396
- }
397
- });
398
- };
399
-
400
- const showImportQuestion = () => {
401
- VxeUI.modal.alert(t('message.importTip'), t('message.udp.tip'));
402
- };
403
-
404
- const emit = defineEmits<{ (e: 'close'): void }>();
405
-
406
- const onClose = () => {
407
- visible.value = false;
408
- emit('close');
409
- };
410
- </script>
411
-
412
- <style lang="scss" scoped>
413
- .ut-input {
414
- box-sizing: border-box;
415
- display: inline-block;
416
- width: 100%;
417
- height: 28px;
418
- padding: 0 15px;
419
- font-size: 13px;
420
- line-height: 28px;
421
- color: #606266;
422
- appearance: none;
423
- outline: 0;
424
- background-color: #fff;
425
- background-image: none;
426
- border: 1px solid #dcdfe6;
427
- border-radius: 4px;
428
- transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
429
-
430
- &:hover {
431
- border-color: #c0c4cc;
432
- }
433
-
434
- &:focus {
435
- outline: 0;
436
- border-color: #409eff;
437
- }
438
-
439
- &:disabled {
440
- outline: none;
441
- background-color: #f5f7fa;
442
- }
443
- }
444
- </style>
1
+ <!--
2
+ * @Author: wei.li
3
+ * @Date: 2022-06-21 14:50:52
4
+ * @LastEditors: levi7754 levi7754@163.com
5
+ * @LastEditTime: 2026-04-07 10:10:16
6
+ * @Description: excel数据导入
7
+ -->
8
+ <template>
9
+ <vxe-modal v-model="visible" :show-header="false" fullscreen remember @close="onClose">
10
+ <template #default>
11
+ <vxe-grid ref="xgrid" v-bind="gridOptions" v-on="gridEvents">
12
+ <template v-for="col in columns" :key="col.field" #[col.field!]="{ row }">
13
+ <el-select v-if="col.dictCode && !col.disabled" v-model.trim="row[col.field!]" clearable>
14
+ <el-option
15
+ v-for="child in dict[col.dictCode]?.children"
16
+ :key="child.dictCode"
17
+ :value="child.dictCode"
18
+ :label="child.dictName"
19
+ />
20
+ </el-select>
21
+ <el-date-picker
22
+ v-else-if="['date', 'month', 'datetime'].includes(col.dataType) && !col.disabled"
23
+ v-model.trim="row[col.field!]"
24
+ :type="col.dataType"
25
+ value-format="YYYY-MM-DD hh:mm:ss"
26
+ />
27
+ <input v-else-if="!col.da && !col.disabled" v-model.trim="row[col.field!]" class="ut-input" />
28
+ <span v-else-if="!showErrorMsg">{{ row[col.field!] }}</span>
29
+ <span v-else>{{ row[col.field!] }}</span>
30
+ </template>
31
+ <template #pager>
32
+ <vxe-pager
33
+ v-model:current-page="listQuery.currentPage"
34
+ v-model:page-size="listQuery.pageSize"
35
+ :layouts="layouts"
36
+ :page-sizes="[200, 500, 1000, 2000, 5000, 10000]"
37
+ :total="listQuery.total"
38
+ @page-change="handlePageChange"
39
+ /></template>
40
+ </vxe-grid>
41
+ </template>
42
+ </vxe-modal>
43
+ </template>
44
+
45
+ <script lang="ts">
46
+ export default {
47
+ name: 'UtUpload'
48
+ };
49
+ </script>
50
+ <script setup lang="ts">
51
+ import { reactive, ref, watch, getCurrentInstance } from 'vue';
52
+ import { toDateString } from 'xe-utils';
53
+ import { storageLocal, cookies, warnMessage } from '@utogether/utils';
54
+ import accounting from 'accounting';
55
+ import { useI18n } from 'vue-i18n';
56
+ import { VxeTableInstance, VxeGridProps, VxeGridListeners } from 'vxe-table';
57
+ import { VxeUI } from 'vxe-pc-ui';
58
+ import type { VxePagerPropTypes, VxePagerEvents } from 'vxe-pc-ui';
59
+
60
+ export interface IProps {
61
+ defaultParams?: IRecord;
62
+ options?: IRecord;
63
+ columns: Array<ITableColProps>;
64
+ templateData?: Array<ITableColProps>;
65
+ serviceCode?: string;
66
+ url?: string;
67
+ sourceList?: string;
68
+ }
69
+
70
+ // const importOptions = {
71
+ // template: [
72
+ // {
73
+ // [t('message.seqNum')]: 10,
74
+ // [t('message.valueCode')]: 'red',
75
+ // [t('message.valueDesc')]: '红色',
76
+ // [t('message.valueDescEn')]: '1000,88.00'
77
+ // }
78
+ // ],
79
+ // columns: [
80
+ // { field: t('message.seqNum'), mapField: 'seqNum' },
81
+ // { field: t('message.valueCode'), mapField: 'valueCode' },
82
+ // { field: t('message.valueDesc'), mapField: 'valueDesc' },
83
+ // { field: t('message.valueDescEn'), mapField: 'valueDescEn', valueType: 'number', decimal: 2 },
84
+ // { field: '异常信息', mapField: 'errorMessage', disabled: true, minWidth: 150 }
85
+ // ],
86
+ // options: {
87
+ // errorField: 'errorMessage',
88
+ // filename: '值集导入模板'
89
+ // }
90
+ // }
91
+
92
+ const props = withDefaults(defineProps<IProps>(), {
93
+ defaultParams: (): IRecord => {
94
+ return {};
95
+ },
96
+ options: (): IRecord => {
97
+ return {
98
+ filename: '数据模板',
99
+ errorField: 'errorMsg',
100
+ errListField: 'list'
101
+ };
102
+ },
103
+ columns: () => [],
104
+ templateData: () => [],
105
+ sourceList: 'list'
106
+ });
107
+
108
+ const instance = getCurrentInstance()!;
109
+ const serviceApi = instance.appContext.config.globalProperties.$serviceApi;
110
+ const visible = defineModel<boolean>('visible');
111
+
112
+ const { t } = useI18n();
113
+
114
+ const showErrorMsg = ref(false);
115
+
116
+ const dict = storageLocal.getItem('kLov');
117
+
118
+ watch(
119
+ () => visible.value,
120
+ nv => {
121
+ if (nv) {
122
+ gridOptions.data = [];
123
+ }
124
+ }
125
+ );
126
+
127
+ const getColumns = () => {
128
+ const columns = props.columns.map(col => {
129
+ col.slots = { default: col.field };
130
+ col.title = col.field;
131
+ col.decimal = col.decimal;
132
+ return col;
133
+ });
134
+ const col = {
135
+ type: 'checkbox',
136
+ width: 40,
137
+ align: 'center',
138
+ fixed: 'left'
139
+ };
140
+ columns.unshift(col);
141
+ console.log('columns===', columns);
142
+ return columns;
143
+ };
144
+
145
+ const listQuery = ref({ pageSize: 200, currentPage: 1, total: 0 });
146
+
147
+ const layouts: VxePagerPropTypes.Layouts = [
148
+ 'Sizes',
149
+ 'PrevJump',
150
+ 'PrevPage',
151
+ 'Number',
152
+ 'NextPage',
153
+ 'NextJump',
154
+ 'FullJump',
155
+ 'Total'
156
+ ];
157
+
158
+ const height = window.innerHeight - 20;
159
+
160
+ const xgrid = ref<VxeTableInstance>();
161
+ // 导入的所有数据
162
+ let dataList = [];
163
+
164
+ const importConfig = {
165
+ mode: 'covering',
166
+ types: ['csv', 'xlsx'],
167
+ afterImportMethod: onImportMethod
168
+ };
169
+
170
+ const gridOptions = reactive<VxeGridProps>({
171
+ border: true,
172
+ height,
173
+ data: [],
174
+ importConfig,
175
+ showOverflow: true,
176
+ loading: false,
177
+ toolbarConfig: {
178
+ buttons: [
179
+ {
180
+ code: 'import_plus',
181
+ name: t('message.btn.upload'),
182
+ icon: 'ri-upload-2-line',
183
+ status: 'primary'
184
+ },
185
+ {
186
+ code: 'save_plus',
187
+ name: t('message.btn.save'),
188
+ icon: 'ri-save-3-line',
189
+ status: 'success'
190
+ },
191
+ {
192
+ code: 'del_plus',
193
+ name: t('message.btn.delete'),
194
+ icon: 'ri-delete-bin-line',
195
+ status: 'danger'
196
+ },
197
+ {
198
+ code: 'export_plus',
199
+ name: t('message.btn.downloadTemp'),
200
+ icon: 'ri-download-2-line',
201
+ status: 'warning'
202
+ }
203
+ ],
204
+ tools: [
205
+ {
206
+ code: 'question',
207
+ name: t('message.btn.FAQ'),
208
+ status: 'primary',
209
+ icon: 'vxe-icon-info-circle-fill'
210
+ },
211
+ {
212
+ code: 'replay',
213
+ name: t('message.btn.back'),
214
+ status: 'info',
215
+ icon: 'vxe-icon-undo'
216
+ }
217
+ ]
218
+ },
219
+ columns: getColumns()
220
+ });
221
+
222
+ const gridEvents: VxeGridListeners = {
223
+ toolbarButtonClick({ code }) {
224
+ // const $grid = xgrid.value;
225
+ switch (code) {
226
+ case 'import_plus': {
227
+ handleImport();
228
+ break;
229
+ }
230
+ case 'save_plus': {
231
+ handleSave();
232
+ break;
233
+ }
234
+ case 'del_plus': {
235
+ handleDelete();
236
+ break;
237
+ }
238
+ case 'export_plus': {
239
+ handleDownLoadFile();
240
+ break;
241
+ }
242
+ }
243
+ },
244
+ toolbarToolClick({ code }) {
245
+ // const $grid = xgrid.value;
246
+ switch (code) {
247
+ case 'replay': {
248
+ onClose();
249
+ break;
250
+ }
251
+ case 'question': {
252
+ showImportQuestion();
253
+ break;
254
+ }
255
+ }
256
+ }
257
+ };
258
+
259
+ const handleImport = () => {
260
+ dataList = [];
261
+ xgrid.value?.openImport();
262
+ };
263
+ // 导入后获取数据
264
+ function onImportMethod(options: any) {
265
+ dataList = options.$table.getTableData().fullData;
266
+ // 标题会默认导入,删除第一行
267
+ // dataList.splice(0, 1);
268
+ const columns = getColumns().filter(f => !f.type && f.mapField !== props.options.errorField);
269
+ columns.forEach(col => {
270
+ const idx = dataList.findIndex(data => data[col.field!] === col.field);
271
+ idx !== -1 && dataList.splice(idx, 1);
272
+ });
273
+ props.columns.forEach(col => {
274
+ if (col.dateFormatter || col.valueType === 'number') {
275
+ dataList.forEach(data => {
276
+ if (col.dateFormatter) {
277
+ data[col.field!] = toDateString(data[col.field!], col.dateFormatter || 'yyyy-MM-dd HH:mm:ss');
278
+ } else {
279
+ data[col.field!] = accounting.unformat(data[col.field]).toFixed(col.decimal || 6);
280
+ }
281
+ });
282
+ }
283
+ });
284
+ listQuery.value.total = dataList.length;
285
+ getDataList();
286
+ }
287
+
288
+ const getDataList = () => {
289
+ const { currentPage, pageSize } = listQuery.value;
290
+ gridOptions.data = dataList.filter(
291
+ (data, idx) => idx < pageSize * currentPage && idx >= pageSize * (currentPage - 1)
292
+ );
293
+ };
294
+ // 切换页数
295
+ const handlePageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }) => {
296
+ listQuery.value.currentPage = currentPage;
297
+ listQuery.value.pageSize = pageSize;
298
+ getDataList();
299
+ };
300
+ // 模板下载
301
+ const handleDownLoadFile = () => {
302
+ const data: ITableColProps[] = [];
303
+ if (props.templateData.length) {
304
+ data.push(...props.templateData);
305
+ } else {
306
+ const obj: ITableColProps = {};
307
+ getColumns()
308
+ .filter(f => f.type !== 'checkbox')
309
+ .forEach(col => {
310
+ obj[col.field!] = '案例';
311
+ });
312
+ data.push(obj);
313
+ }
314
+ const opt: IRecord = {
315
+ filename: props.options.filename,
316
+ type: 'xlsx',
317
+ columns: getColumns().filter(f => f.mapField !== props.options.errorField && f.type !== 'checkbox'),
318
+ data
319
+ };
320
+ xgrid.value?.exportData(opt);
321
+ };
322
+
323
+ const handleSave = async () => {
324
+ if (!dataList.length) {
325
+ return warnMessage(t('message.importEmpty'));
326
+ }
327
+ const type = await VxeUI.modal.confirm(t('message.importRecord'));
328
+ if (type === 'confirm') {
329
+ gridOptions.loading = true;
330
+ const { url } = props;
331
+ formatterData('toSave');
332
+ serviceApi
333
+ .post(url, dataList)
334
+ .then((res: any) => {
335
+ if (res?.status === 'error' || res?.length) {
336
+ showErrorMsg.value = true;
337
+ setErrorMessage(res?.length ? res : res[props.options.errListField || props.sourceList]);
338
+ VxeUI.modal.message({
339
+ content: t('message.importFailed'),
340
+ status: 'error'
341
+ });
342
+ } else {
343
+ VxeUI.modal.message({
344
+ content: t('message.importSuccess'),
345
+ status: 'success'
346
+ });
347
+ onClose();
348
+ }
349
+ })
350
+ .finally(() => {
351
+ showErrorMsg.value = false;
352
+ gridOptions.loading = false;
353
+ });
354
+ }
355
+ };
356
+
357
+ /**
358
+ * @description:删除行
359
+ */
360
+ const handleDelete = () => {
361
+ const checkboxRecords = xgrid.value?.getCheckboxRecords();
362
+ if (!checkboxRecords?.length) {
363
+ return VxeUI.modal.message({
364
+ content: t('message.selectedRecord'),
365
+ status: 'warning'
366
+ });
367
+ }
368
+ checkboxRecords.forEach(record => {
369
+ const idx = dataList.findIndex(data => data._X_ROW_KEY === record._X_ROW_KEY)!;
370
+ idx !== -1 && dataList.splice(idx, 1);
371
+ });
372
+ gridOptions.data = dataList;
373
+ };
374
+
375
+ const setErrorMessage = (array: ITableColProps[]) => {
376
+ listQuery.value.total = array.length;
377
+ dataList = array.map((item, idx) => {
378
+ item._X_ROW_KEY = idx;
379
+ return item;
380
+ });
381
+ formatterData('toShow');
382
+ getDataList();
383
+ };
384
+ const formatterData = (formatterType: string) => {
385
+ gridOptions.columns!.forEach((col: any) => {
386
+ if (formatterType === 'toSave') {
387
+ const commonParam = cookies.get('kCookies_param') ? JSON.parse(cookies.get('kCookies_param')!) : {};
388
+ dataList.forEach(data => {
389
+ data[col.mapField] = data[col.field];
390
+ Object.assign(data, commonParam, props.defaultParams);
391
+ });
392
+ } else {
393
+ dataList.forEach(data => {
394
+ data[col.field] = data[col.mapField];
395
+ });
396
+ }
397
+ });
398
+ };
399
+
400
+ const showImportQuestion = () => {
401
+ VxeUI.modal.alert(t('message.importTip'), t('message.udp.tip'));
402
+ };
403
+
404
+ const emit = defineEmits<{ (e: 'close'): void }>();
405
+
406
+ const onClose = () => {
407
+ visible.value = false;
408
+ emit('close');
409
+ };
410
+ </script>
411
+
412
+ <style lang="scss" scoped>
413
+ .ut-input {
414
+ box-sizing: border-box;
415
+ display: inline-block;
416
+ width: 100%;
417
+ height: 28px;
418
+ padding: 0 15px;
419
+ font-size: 13px;
420
+ line-height: 28px;
421
+ color: #606266;
422
+ appearance: none;
423
+ outline: 0;
424
+ background-color: #fff;
425
+ background-image: none;
426
+ border: 1px solid #dcdfe6;
427
+ border-radius: 4px;
428
+ transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
429
+
430
+ &:hover {
431
+ border-color: #c0c4cc;
432
+ }
433
+
434
+ &:focus {
435
+ outline: 0;
436
+ border-color: #409eff;
437
+ }
438
+
439
+ &:disabled {
440
+ outline: none;
441
+ background-color: #f5f7fa;
442
+ }
443
+ }
444
+ </style>