sohelp-eleplus 1.1.19 → 1.1.21

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.
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { Filter, Search, Sort, SortDown, SortUp,Setting,Tickets,Postcard, Files, Grid} from "@element-plus/icons-vue";
2
+ import { Filter, Search, Sort, SortDown, SortUp,Setting,Memo,Menu,Tickets,Postcard, Files, Grid, Refresh} from "@element-plus/icons-vue";
3
3
  import { useMobile } from "@/utils/use-mobile";
4
4
  import { usePermission } from "@/utils/use-permission";
5
5
  import DefaultProps from "./js/DefaultProps";
@@ -12,6 +12,7 @@ import { useFormData } from "@/utils/use-form-data";
12
12
  import { resetCommonConfig, updateCommonConfig } from "../http/ModuleHttp.js";
13
13
  import CrudHttp from "../http/CrudHttp.js";
14
14
  import {merge, cloneDeep } from "lodash-es";
15
+ import { uuid } from "../utils/core.js"
15
16
 
16
17
  import ApprovalModal from "../sohelp-workflow-drawer/components/approval-modal.vue";
17
18
  import WorkflowDrawer from "../sohelp-workflow-drawer/index.vue";
@@ -22,10 +23,11 @@ import FilterConditionItem from "./components/filter-condition-item.vue";
22
23
  import { useSohelpGridConfig } from "./js/useSohelpGridConfig.js";
23
24
  import { useI18n } from "vue-i18n";
24
25
  import SohelpEntityForm from "../sohelp-entity-form/index.vue";
25
- import * as ElementPlusIcons from '@element-plus/icons-vue';
26
- import * as EleAdminPlusIcons from '@/components/icons';
26
+ import * as ElementPlusIcons from '@element-plus/icons-vue';
27
+ import * as EleAdminPlusIcons from '@/components/icons';
27
28
  import { moduleCache } from "../cache/ModuleCache.js";
28
29
  import SohelpModal from "../sohelp-modal/index.vue";
30
+ import SohelpImport from "../sohelp-import/index.vue";
29
31
  import { useUserStore } from '@/store/modules/user';
30
32
  import { Alert } from "vxe-pc-ui";
31
33
  const { initial, isConfigDone } = useSohelpGridConfig();
@@ -49,6 +51,12 @@ const currentReportValue = ref(null);
49
51
  const visibleReport = ref(false);
50
52
  const reportData = ref([]);
51
53
  const currentRow = ref(null);
54
+
55
+ /** 自动生成ID */
56
+ const getId = () => {
57
+ return 'sohelp-grid-' + uuid();
58
+ }
59
+
52
60
  const loadReport = () => {
53
61
  SohelpHttp.get("/engine/web/report/list", { refid: props.refid }).then(res => {
54
62
  if (res.meta.success) {
@@ -89,6 +97,9 @@ const closeReport = () => {
89
97
  visibleReport.value = false;
90
98
  };
91
99
 
100
+ // 操作栏按钮配置
101
+ const operationsButtons = reactive({});
102
+
92
103
  const loading = ref(false);
93
104
  //显示实体表单
94
105
  const visibleEntityForm = ref(false);
@@ -190,12 +201,24 @@ const getCellValue = (rowIndex, name) => {
190
201
  return (gridData[rowIndex] && gridData[rowIndex][name]) ? gridData[rowIndex][name] : "";
191
202
  };
192
203
 
204
+ /**
205
+ * 获取行原始数据
206
+ */
207
+ const getRowDataByField = (column, row) => {
208
+ if(column.type === 'SohelpTableSelect'){
209
+ const {field} = column;
210
+ return gridData.find(item => item[field].id === row[field]) || row;
211
+ } else{
212
+ return row;
213
+ }
214
+ }
215
+
193
216
  /**
194
217
  * 获取关键字描述
195
218
  */
196
219
  const getKeywordsPlaceholder = computed(() => {
197
220
  if (sohelpConfig.value?.filter?.keywords?.length) {
198
- return t("grid.toolbar.keywords") + ",【" + sohelpConfig.value.filter?.keywords?.filter(key => propertiesMap.value[key]).map(key => t(propertiesMap.value[key].i18n) || propertiesMap.value[key].label).join("/") + "";
221
+ return t("grid.toolbar.keywords") + " [" + sohelpConfig.value.filter?.keywords?.filter(key => propertiesMap.value[key]).map(key => t(propertiesMap.value[key].i18n) || propertiesMap.value[key].label).join(",") + "]";
199
222
  }
200
223
  return t("grid.toolbar.keywords");
201
224
  });
@@ -208,6 +231,107 @@ const getCurrentFieldLabel = computed(() => {
208
231
  return (propertiesMap.value[textareaState["field"]]?.label || "") + "修改";
209
232
  });
210
233
 
234
+ const importVisible = ref(false);
235
+ const importAuthority = computed(() => {
236
+ try {
237
+ const prefix = (props.refid || '').split('!')[0] || '';
238
+ return prefix + ':batch.import';
239
+ } catch (e) {
240
+ return 'batch.import';
241
+ }
242
+ });
243
+ const exportAuthority = computed(() => {
244
+ try {
245
+ const prefix = (props.refid || '').split('!')[0] || '';
246
+ return prefix + ':batch.export';
247
+ } catch (e) {
248
+ return 'batch.export';
249
+ }
250
+ });
251
+
252
+ const openImport = () => {
253
+ try {
254
+ if (!permission.hasPermission(importAuthority.value)) {
255
+ EleMessage.error('暂无权限');
256
+ return;
257
+ }
258
+ if (!props.refid) {
259
+ EleMessage.error('列表地址缺失,无法打开导入');
260
+ return;
261
+ }
262
+ importVisible.value = true;
263
+ } catch (e) {
264
+ EleMessage.error(typeof e === 'string' ? e : e?.message || '打开导入失败');
265
+ }
266
+ };
267
+ const closeImport = () => {
268
+ importVisible.value = false;
269
+ };
270
+ const exportData = async (dataRange) => {
271
+ if (!permission.hasPermission(exportAuthority.value)) {
272
+ EleMessage.error('暂无权限');
273
+ return;
274
+ }
275
+ if (dataRange === 0) {
276
+ const $grid = sohelpVxeGridRef.value;
277
+ const selected = $grid?.getCheckboxRecords() || [];
278
+ if (!selected.length) {
279
+ EleMessage.error("请先勾选需要导出的记录");
280
+ return;
281
+ }
282
+ const ids = selected.map((item) => item.id).filter((id) => id !== undefined && id !== null);
283
+ if (!ids.length) {
284
+ EleMessage.error("选中记录未包含可导出的ID");
285
+ return;
286
+ }
287
+ let last = 0;
288
+ let loadingTip = EleMessage.loading("导出中 0%");
289
+ try {
290
+ await SohelpHttp.download("/engine/web/export/download", {
291
+ refid: props.refid,
292
+ exportRange: dataRange,
293
+ ...filterValue.value,
294
+ ids: ids
295
+ }, "导出数据.xlsx", (loaded, total) => {
296
+ if (total > 0) {
297
+ const p = Math.floor((loaded / total) * 100);
298
+ if (p - last >= 5) {
299
+ loadingTip.close();
300
+ loadingTip = EleMessage.loading(`导出中 ${p}%`);
301
+ last = p;
302
+ }
303
+ }
304
+ });
305
+ } catch (e) {
306
+ EleMessage.error(typeof e === "string" ? e : e?.message || "导出失败");
307
+ } finally {
308
+ loadingTip.close();
309
+ }
310
+ return;
311
+ }
312
+ let last = 0;
313
+ let loadingTip = EleMessage.loading("导出中 0%");
314
+ try {
315
+ await SohelpHttp.download("/engine/web/export/download", {
316
+ refid: props.refid,
317
+ exportRange: dataRange,
318
+ filterValue: JSON.stringify(filterValue.value)
319
+ }, "导出数据.xlsx", (loaded, total) => {
320
+ if (total > 0) {
321
+ const p = Math.floor((loaded / total) * 100);
322
+ if (p - last >= 5) {
323
+ loadingTip.close();
324
+ loadingTip = EleMessage.loading(`导出中 ${p}%`);
325
+ last = p;
326
+ }
327
+ }
328
+ });
329
+ } catch (e) {
330
+ EleMessage.error(typeof e === "string" ? e : e?.message || "导出失败");
331
+ } finally {
332
+ loadingTip.close();
333
+ }
334
+ };
211
335
  const keywordsChange = (val) => {
212
336
  filterValue.value = {
213
337
  ...filterValue.value,
@@ -302,6 +426,7 @@ const loadConfig = (param = {}) => {
302
426
  /**配置刷新功能 */
303
427
  config.gridOptions = {
304
428
  ...config.gridOptions,
429
+ params: gridOptions.params ?? {},
305
430
  toolbarConfig: {
306
431
  ...config.gridOptions?.toolbarConfig,
307
432
  refresh: true,
@@ -315,6 +440,7 @@ const loadConfig = (param = {}) => {
315
440
  }
316
441
  };
317
442
 
443
+
318
444
  //工具栏按钮权限
319
445
  Object.assign(formulaMap, config.formulaMap);
320
446
  Object.assign(gridOptions, config.gridOptions);
@@ -328,6 +454,10 @@ const loadConfig = (param = {}) => {
328
454
  batchButtonsIndex.value = config.batchButtonsIndex;
329
455
  sohelpConfig.value.list = config.sohelpConfig.list;
330
456
 
457
+
458
+
459
+ Object.assign(operationsButtons, config.operationsButtons);
460
+
331
461
  if (!filterValue.value.filter) {
332
462
  filterValue.value.filter = [];
333
463
  }
@@ -359,6 +489,7 @@ const load = async (params = {}, callback) => {
359
489
  gridOptions.params = params;
360
490
  await isConfigDone();
361
491
  const $grid = sohelpVxeGridRef.value;
492
+
362
493
  if ($grid) {
363
494
  const url = props.url || sohelpConfig.value.requestValue;
364
495
  if (sohelpConfig.value.requestType != "crud" && !url) {
@@ -366,6 +497,7 @@ const load = async (params = {}, callback) => {
366
497
  return { results: [], total: 0 };
367
498
  }
368
499
 
500
+
369
501
  let pageConfig = {};
370
502
  // 是否分页
371
503
  if (gridOptions.pagerConfig?.enabled) {
@@ -383,6 +515,7 @@ const load = async (params = {}, callback) => {
383
515
  });
384
516
 
385
517
 
518
+
386
519
  if (res?.meta?.success) {
387
520
  if (res.data) {
388
521
  gridOptions.pagerConfig.total = Number(res.data.total);
@@ -407,12 +540,17 @@ const load = async (params = {}, callback) => {
407
540
  callback(res);
408
541
  }
409
542
  }
543
+
410
544
  };
411
545
 
412
546
  /**
413
547
  * 重新加载数据
414
548
  */
415
549
  const reload = async (params = {}) => {
550
+ //取消选中
551
+ selections.value = [];
552
+ sohelpVxeGridRef.value?.clearCheckboxRow();
553
+
416
554
  Object.assign(gridOptions.params, params);
417
555
  load(gridOptions.params);
418
556
  };
@@ -475,55 +613,28 @@ const pageChangeEvent = (page) => {
475
613
  * 获取Common类型操作栏 并根据flw_id判断是否显示
476
614
  * @param row
477
615
  */
478
- const getOperationButtonsByType = (row, type = "common") => {
479
- let common = getOperationToolbars.value?.[type] || [];
480
- if (common.length > 0) {
481
- if (row.hasOwnProperty("flw_id")) {
482
- const field = row.flw_id === "0" ? "workflow.view" : "workflow.submit";
483
- common = common.filter(f => f.code != field);
484
- } else {
485
- common = common.filter(f => (f.code != "workflow.submit" || f.code != "workflow.view"));
486
- }
487
- return common;
488
- }
489
- return [];
490
- };
491
-
492
- /**
493
- * 获取操作栏
494
- */
495
- const getOperationToolbars = computed(() => {
496
- const buttonsMap = {};
497
- sohelpConfig.value.operationToolbars?.filter(f => !f.authority || permission.hasPermission(f.authority)).map(button => {
498
- const type = button.buttonType || "common";
499
- const code = button.type === "custom" ? button.id : button.type;
500
- if (!buttonsMap[type]) {
501
- buttonsMap[type] = [];
502
- }
503
- const title = (button.type === "custom") ? button.title : t("grid.toolbar." + button.type?.replaceAll(".", "-"));
504
- let params = button.params || {};
505
- if (button.params && typeof button.params === "string") {
506
- try {
507
- params = JSON.parse(button.params);
508
- } catch (e) {
509
- params = {};
510
- EleMessage.error("button.params配置JSON参数格式错误");
616
+ const getOperationButtonsByType = computed(() => {
617
+ return (row, column, type = "common") => {
618
+ const $grid = sohelpVxeGridRef.value;
619
+ let common = operationsButtons?.[type] || [];
620
+ if (common.length > 0) {
621
+ if (row.hasOwnProperty("flw_id")) {
622
+ const field = row.flw_id === "0" ? "workflow.view" : "workflow.submit";
623
+ common = common.filter(f => f.code != field);
624
+ } else {
625
+ common = common.filter(f => (f.code != "workflow.submit" || f.code != "workflow.view"));
511
626
  }
627
+ return common.map((item) => {
628
+ if(item.render && item.render?.length > 0) {
629
+ const func = new Function("row","item","column","$grid", `return (async () => { ${item.render} })()`);
630
+ func.call(undefined, row, item, column, $grid);
631
+ }
632
+ return item;
633
+ });
512
634
  }
513
- buttonsMap[type].push({
514
- title: title || button.title,
515
- "id": button.id,
516
- code: code,
517
- handler: button.handler,
518
- icon: button.iconCls,
519
- params: params,
520
- refid: button.refid,
521
- openType: button.openType
522
- });
523
- });
524
- return buttonsMap;
525
- });
526
-
635
+ return [];
636
+ };
637
+ })
527
638
 
528
639
  /**
529
640
  * 行操作栏点击事件
@@ -531,7 +642,10 @@ const getOperationToolbars = computed(() => {
531
642
  * @param item
532
643
  */
533
644
  const operationHandler = ({ item, row, $grid }) => {
645
+
534
646
  //操作栏事件执行
647
+ $grid.reload = reload;
648
+ $grid.refresh = refresh;
535
649
  if (item.handler && typeof item.handler === "string") {
536
650
  try {
537
651
  const func = new Function("row", "$grid", `return (async () => { ${item.handler} })()`);
@@ -560,13 +674,15 @@ const operationHandler = ({ item, row, $grid }) => {
560
674
  if (item.openType === "tab") {
561
675
  window.$SohelpModule.openTab(item.refid, { id: row.id }, item.params || {});
562
676
  } else if (item.openType === "drawer") {
563
- console.error("item", item.params);
564
677
  window.$SohelpModule.openDrawer(item.refid, { id: row.id }, item.params || {});
565
678
  } else {
566
679
  window.$SohelpModule.openModal(item.refid, { id: row.id }, item.params || {});
567
680
  }
568
681
  } else {
569
682
  switch (item.code) {
683
+ case "row.delete":
684
+ $grid?.remove(row)
685
+ break;
570
686
  case "crud.edit":
571
687
  visibleEntityForm.value = true;
572
688
  toolbarButtonParams.value = item.params || {};
@@ -577,7 +693,7 @@ const operationHandler = ({ item, row, $grid }) => {
577
693
  CrudHttp.detail(props.refid, { id: row.id }).then(res => {
578
694
  if (res.meta.success) {
579
695
  setTimeout(() => {
580
- entityFormRef.value.setFormData(res.data);
696
+ entityFormRef.value.setFormData({...res.data});
581
697
  }, 10);
582
698
  } else {
583
699
  EleMessage.error(res.meta.message);
@@ -608,6 +724,9 @@ const operationHandler = ({ item, row, $grid }) => {
608
724
  case "crud.delete" :
609
725
  remove({ id: [row.id] });
610
726
  break;
727
+ case "row.pre-delete":
728
+ $grid?.setPendingRow(row, true);
729
+ break;
611
730
  case "workflow.submit":
612
731
  submitWorkflow({ id: [row.id] });
613
732
  break;
@@ -666,6 +785,10 @@ const insertField = (data, index = -1) => {
666
785
  * 刷新列表
667
786
  */
668
787
  const refresh = () => {
788
+ //取消选中
789
+ selections.value = [];
790
+ sohelpVxeGridRef.value?.clearCheckboxRow();
791
+
669
792
  if (!isPage.value) {
670
793
  if (gridOptions.pagerConfig && gridOptions.pagerConfig.enabled) {
671
794
  gridOptions.pagerConfig.currentPage = 1;
@@ -826,12 +949,13 @@ const orgDatasource = computed(async () => {
826
949
  */
827
950
  const getCrudUpdater = () => {
828
951
  const $grid = sohelpVxeGridRef.value;
952
+ const _delete = [...$grid?.getRemoveRecords()?.map(item => item.id),...$grid?.getPendingRecords()?.map(item => item.id)];
829
953
  return {
830
954
  "inserted": $grid?.getInsertRecords().map(item => {
831
955
  return { ...item };
832
956
  }) || [],
833
957
  "updated": $grid?.getUpdateRecords(),
834
- "deleted": $grid?.getRemoveRecords().map(item => item.id) || []
958
+ "deleted": _delete
835
959
  };
836
960
  };
837
961
 
@@ -858,12 +982,16 @@ const remove = (params) => {
858
982
  */
859
983
  const executeToolbarCustomHandler = (button) => {
860
984
  const $grid = sohelpVxeGridRef.value;
985
+ $grid.refresh = refresh;
986
+ $grid.reload = reload;
861
987
  try {
862
- let isRows = button.code.includes("batch.");
988
+ let isRows = button.buttonType === 'batch';
863
989
  const func = new Function(isRows ? "rows" : "row", "$grid", `return (async () => { ${button.handler} })()`);
864
990
  (async () => {
865
991
  const context = {
866
992
  $message: EleMessage,
993
+ $SohelpModule: window.$SohelpModule,
994
+ $SohelpHttp: window.$SohelpHttp,
867
995
  $confirm: (title, callback) => {
868
996
  ElMessageBox.confirm(title, "提示", {
869
997
  confirmButtonText: "确定",
@@ -893,7 +1021,6 @@ const toolbarClick = async ({ button }) => {
893
1021
  let rowIndex = -1;
894
1022
  const row = {};
895
1023
 
896
-
897
1024
  const current = $grid?.getCurrentRecord();
898
1025
  if (current) {
899
1026
  rowIndex = $grid?.getVTRowIndex(current);
@@ -937,10 +1064,13 @@ const toolbarClick = async ({ button }) => {
937
1064
  if (!toolbarButtonParams.value["title"]) {
938
1065
  toolbarButtonParams.value["title"] = t("grid.toolbar.create");
939
1066
  }
1067
+
1068
+ const {title, ...params} = button.params;
1069
+
940
1070
  CrudHttp.initial(props.refid, { id: row.id }, (res) => {
941
1071
  if (res.meta.success) {
942
1072
  setTimeout(() => {
943
- entityFormRef.value.setFormData(res.data);
1073
+ entityFormRef.value.setFormData({...res.data}, params);
944
1074
  }, 10);
945
1075
  } else {
946
1076
  EleMessage.error(res.meta.message);
@@ -999,7 +1129,7 @@ const gridEvents = {
999
1129
 
1000
1130
  toolbarButtonClick(config) {
1001
1131
  toolbarClick(config);
1002
- emit("toolbarButtonClick", config);
1132
+ emit("toolbarButtonClick", config, selections.value);
1003
1133
  }
1004
1134
 
1005
1135
  };
@@ -1065,7 +1195,6 @@ const viewWorkflow = (id) => {
1065
1195
  * 筛选
1066
1196
  */
1067
1197
  const changeNameFilter = (option, val, column) => {
1068
- console.log("option", option, val, column);
1069
1198
  const $grid = sohelpVxeGridRef.value;
1070
1199
  if ($grid) {
1071
1200
  $grid.setFilter(column.field, [{
@@ -1335,10 +1464,14 @@ const settingClick = (command) => {
1335
1464
  const { refid,extendEntity,name } = sohelpConfig.value;
1336
1465
  if(refid && extendEntity && name){
1337
1466
  const url = {
1338
- form: baseUrl + `/dev/index.html#/dev/form?datasource=${name}&name=${extendEntity}&refid=${refid}`,
1339
- entity: baseUrl + `/dev/index.html#/dev/module/entity?datasource=${name}&name=${extendEntity}`,
1340
- workflow: baseUrl + `/dev/index.html#/dev/form?datasource=${name}&name=${extendEntity}&refid=${refid}`,
1341
- grid: baseUrl + `/dev/index.html#/dev/module/grid?refid=${refid}`
1467
+ form: baseUrl + `/dev/index.html#/dev/form?datasource=default&name=${extendEntity}&refid=${refid}`,
1468
+ entity: baseUrl + `/dev/index.html#/dev/module/entity?datasource=default&name=${extendEntity}`,
1469
+ workflow: baseUrl + `/dev/index.html#/dev/form?datasource=default&name=${extendEntity}&refid=${refid}&tab=workflow`,
1470
+ grid: baseUrl + `/dev/index.html#/dev/module/grid?refid=${refid}`,
1471
+ module: baseUrl+`/dev/index.html#/dev/module?name=${refid}`,
1472
+ }
1473
+ if(command === 'module' && !extendEntity){
1474
+ url.module = baseUrl+`/dev/index.html#/dev/module?name=${name}`;
1342
1475
  }
1343
1476
  window.open(url[command],'_blank');
1344
1477
  }
@@ -1388,7 +1521,7 @@ defineExpose({
1388
1521
  @checkboxChange="onCheckboxChange"
1389
1522
  @checkboxAll="onCheckboxChange"
1390
1523
  class="sohelp-grid-view"
1391
- id="sohelp-grid"
1524
+ :id="getId()"
1392
1525
  v-on="gridEvents"
1393
1526
  @filter-change="handleFilterChange"
1394
1527
  @custom="handleCustom"
@@ -1401,25 +1534,31 @@ defineExpose({
1401
1534
  @filter-visible="filterVisible"
1402
1535
  >
1403
1536
 
1537
+ <!-- 自定义列设置 -->
1404
1538
  <template #setting>
1405
1539
  <div class="column-setting">
1406
1540
  <vxe-checkbox @change="toggleAllEvent" v-model="columnCheckbox">全选</vxe-checkbox>
1407
- <vxe-pulldown trigger="click" :transfer="true" :show-popup-shadow="true" v-if="userStore.info.is_developer">
1408
- <template #default>
1409
- <el-link :icon="Setting" :underline="false"></el-link>
1410
- </template>
1411
- <template #dropdown>
1412
- <ele-text @click="settingClick('grid')">数据列表配置</ele-text>
1413
- <ele-text @click="settingClick('entity')">实体配置</ele-text>
1414
- </template>
1415
- </vxe-pulldown>
1541
+ <vxe-pulldown trigger="click" :transfer="true" :show-popup-shadow="true" v-if="userStore.info.is_developer">
1542
+ <template #default>
1543
+ <el-link :icon="Setting" :underline="false"/>
1544
+ </template>
1545
+ <template #dropdown>
1546
+ <ele-card shadow="always">
1547
+ <el-space direction="vertical" :size="5" alignment="flex-start">
1548
+ <el-link :icon="Memo" @click="settingClick('grid')" :underline="false" style="font-size:12px;"><span style="padding:0 5px;">列表配置</span></el-link>
1549
+ <el-link :icon="Menu" @click="settingClick('entity')" :underline="false" style="font-size: 12px;"><span style="padding:0 5px;">实体配置</span></el-link>
1550
+ <el-link :icon="Grid" @click="settingClick('module')" :underline="false" style="font-size: 12px;"><span style="padding:0 5px;">模块配置</span></el-link>
1551
+ </el-space>
1552
+ </ele-card>
1553
+ </template>
1554
+ </vxe-pulldown>
1416
1555
  </div>
1417
1556
  </template>
1418
1557
 
1419
1558
  <!--定义国际化I18n-->
1420
1559
  <template
1421
1560
  v-for="item in sohelpConfig?.properties?.map(item => item)"
1422
- v-slot:[`header_${item.name}`]="{ column, rowIndex }"
1561
+ #[`header_${item.name}`]="{ column, rowIndex }"
1423
1562
  :key="item.name"
1424
1563
  >
1425
1564
  {{ item.i18n ? t(item.i18n) : item.label }}
@@ -1432,12 +1571,12 @@ defineExpose({
1432
1571
  v-model:currentPage="gridOptions.pagerConfig.currentPage"
1433
1572
  v-model:pageSize="gridOptions.pagerConfig.pageSize"
1434
1573
  :total="gridOptions.pagerConfig.total"
1435
- @page-change="pageChangeEvent">
1436
- </vxe-pager>
1574
+ @page-change="pageChangeEvent"/>
1437
1575
  </template>
1438
1576
 
1439
1577
  <!-- 高级筛选 -->
1440
- <template v-for="field in Object.values(propertiesMap).filter(item => item.query)" :key="field.name"
1578
+ <template
1579
+ v-for="field in Object.values(propertiesMap).filter(item => item.query)" :key="field.name"
1441
1580
  #[`filter_${field.name}`]="{ column }">
1442
1581
  <div v-for="(option, index) in column.filters" :key="index" class="condition-box">
1443
1582
  <filter-condition-item
@@ -1454,13 +1593,14 @@ defineExpose({
1454
1593
  <div class="toolbar-box">
1455
1594
  <!-- 查看范围 -->
1456
1595
  <div class="power-box">
1457
- <sohelp-power @change="changePower" v-if="sohelpConfig?.filter?.config?.visibleDataRange"></sohelp-power>
1596
+ <sohelp-power @change="changePower" v-if="sohelpConfig?.filter?.config?.visibleDataRange"/>
1458
1597
  </div>
1459
1598
 
1460
1599
  <div class="search-box" v-if="sohelpConfig?.filter?.config?.visibleKeywords">
1461
1600
  <!-- 关键字 -->
1462
1601
  <ele-tooltip :content="getKeywordsPlaceholder" placement="top" :offset="3">
1463
- <sohelp-input :model-value="filterValue.keywords" @update:model-value="keywordsChange"
1602
+ <sohelp-input
1603
+ :model-value="filterValue.keywords" @update:model-value="keywordsChange"
1464
1604
  :placeholder="getKeywordsPlaceholder" clearable
1465
1605
  @keyup.enter="filter" size="small" style="width: 160px;">
1466
1606
  <template #append>
@@ -1468,34 +1608,62 @@ defineExpose({
1468
1608
  </template>
1469
1609
  </sohelp-input>
1470
1610
  </ele-tooltip>
1471
- <el-button size="small" @click="resetFilter">{{ t("grid.toolbar.reset") }}</el-button>
1611
+ <el-button size="small" :icon="Refresh" @click="resetFilter">{{ t("grid.toolbar.reset") }}</el-button>
1472
1612
  </div>
1473
1613
 
1474
1614
  <div class="tools-btns">
1475
- <sohelp-drop-card :title="t('grid.toolbar.sort')" :icon="Sort" ref="sohelpSortRef"
1615
+ <sohelp-drop-card
1616
+ :title="t('grid.toolbar.sort')" :icon="Sort" ref="sohelpSortRef"
1476
1617
  v-if="sohelpConfig?.filter?.config?.visibleSort && sortList.length > 0">
1477
1618
  <div class="sort-list">
1478
- <ele-card v-for="item in sortList" :key="item.title" :header="item.title"
1619
+ <ele-card
1620
+ v-for="item in sortList" :key="item.title" :header="item.title"
1479
1621
  :bodyStyle="{padding: '0'}"
1480
1622
  :headerStyle="{fontSize: '14px', fontWeight: 'normal', padding: '5px 0'}">
1481
1623
  <template #extra>
1482
- <ele-text :icon="SortUp" style="cursor: pointer;" :underline="false" size="sm"
1624
+ <ele-text
1625
+ :icon="SortUp" style="cursor: pointer;" :underline="false" size="sm"
1483
1626
  @click="sortCommand(item.field,'asc')" plain :type="isActiveSort(item.field,'asc')">
1484
- t("grid.toolbar.asc")
1627
+ {{ t("grid.toolbar.asc") }}
1485
1628
  </ele-text>
1486
- <ele-text :icon="SortDown" style="cursor: pointer;margin-left:5px!important" :underline="false"
1629
+ <ele-text
1630
+ :icon="SortDown" style="cursor: pointer;margin-left:5px!important" :underline="false"
1487
1631
  size="sm" @click="sortCommand(item.field,'desc')" plain
1488
- :type="isActiveSort(item.field,'desc')">t("grid.toolbar.desc")
1632
+ :type="isActiveSort(item.field,'desc')">{{t("grid.toolbar.desc")}}
1489
1633
  </ele-text>
1490
1634
  </template>
1491
1635
  </ele-card>
1492
1636
  </div>
1493
1637
  </sohelp-drop-card>
1494
- <el-button :icon="Filter" size="small" @click="showFilter()"
1638
+ <el-button
1639
+ :icon="Filter" size="small" @click="showFilter()"
1495
1640
  plain
1496
1641
  :type="(sohelpConfig?.filter?.config?.visibleFilter && sohelpConfig?.filter?.config?.filterPosition !== 'NONE')?'primary':''"
1497
- v-if="sohelpConfig?.filter?.config?._visibleFilter">
1498
- </el-button>
1642
+ v-if="sohelpConfig?.filter?.config?._visibleFilter"/>
1643
+ <ele-tooltip :content="'批量导入数据'" placement="top" :offset="3">
1644
+ <el-button size="small" plain :icon="ElementPlusIcons.Upload" @click="openImport" v-permission="importAuthority"/>
1645
+ </ele-tooltip>
1646
+ <ele-tooltip :content="'批量导出数据'" placement="top" :offset="3">
1647
+ <el-dropdown @command="exportData" v-permission="exportAuthority">
1648
+ <el-button size="small" plain :icon="ElementPlusIcons.Download"/>
1649
+ <template #dropdown>
1650
+ <el-dropdown-menu>
1651
+ <el-dropdown-item :command="0" :disabled="!selections || selections.length === 0">
1652
+ <el-icon><Memo /></el-icon>
1653
+ <span style="margin-left:6px;">导出选中数据</span>
1654
+ </el-dropdown-item>
1655
+ <el-dropdown-item :command="1">
1656
+ <el-icon><Files /></el-icon>
1657
+ <span style="margin-left:6px;">当前页数据</span>
1658
+ </el-dropdown-item>
1659
+ <el-dropdown-item :command="2">
1660
+ <el-icon><Grid /></el-icon>
1661
+ <span style="margin-left:6px;">全部记录数据</span>
1662
+ </el-dropdown-item>
1663
+ </el-dropdown-menu>
1664
+ </template>
1665
+ </el-dropdown>
1666
+ </ele-tooltip>
1499
1667
  </div>
1500
1668
  </div>
1501
1669
  </template>
@@ -1504,7 +1672,7 @@ defineExpose({
1504
1672
  <!-- 未编辑状态 -->
1505
1673
  <template
1506
1674
  v-for="name in sohelpConfig?.properties?.map(item => item.name)"
1507
- v-slot:[`default_${name}`]="{ row, column, rowIndex }"
1675
+ #[`default_${name}`]="{ row, column, rowIndex }"
1508
1676
  :key="name"
1509
1677
  >
1510
1678
 
@@ -1517,20 +1685,19 @@ defineExpose({
1517
1685
  />
1518
1686
 
1519
1687
  <!-- 图片 -->
1520
- <sohelp-image-upload v-else-if="column.type === 'SohelpImageUpload'"
1688
+ <sohelp-image-upload
1689
+ v-else-if="column.type === 'SohelpImageUpload'"
1521
1690
  v-model="row[name]"
1522
1691
  v-bind="column.editRender"
1523
1692
  :data="getCellValue(rowIndex,name)"
1524
- :readonly="!column.editRender.edit">
1525
- </sohelp-image-upload>
1693
+ :readonly="!column.editRender.edit"/>
1526
1694
  <!-- 附件 -->
1527
1695
  <sohelp-file-upload
1528
1696
  v-else-if="column.type === 'SohelpFileUpload'"
1529
1697
  v-model="row[name]"
1530
1698
  v-bind="column.editRender"
1531
1699
  :data="getCellValue(rowIndex,name)"
1532
- :readonly="!column.editRender.edit">
1533
- </sohelp-file-upload>
1700
+ :readonly="!column.editRender.edit"/>
1534
1701
 
1535
1702
  <!-- 下拉选择表格 -->
1536
1703
  <div v-else-if="column.type === 'SohelpTableSelect' || column.type === 'ORG' || column.type ==='USER'">
@@ -1555,7 +1722,7 @@ defineExpose({
1555
1722
  v-bind="column.editRender"
1556
1723
  style="width: 100%"
1557
1724
  :readonly="!column.editRender.edit"
1558
- ></sohelp-process>
1725
+ />
1559
1726
 
1560
1727
 
1561
1728
  <!-- 下拉用户选择 -->
@@ -1584,7 +1751,8 @@ defineExpose({
1584
1751
  </div>
1585
1752
 
1586
1753
  <!-- 文本域 -->
1587
- <p style="margin: 0;"
1754
+ <p
1755
+ style="margin: 0;"
1588
1756
  class="textarea-reference"
1589
1757
  @click="showTextareaModal(column, name, row)"
1590
1758
  v-bind="column.editRender"
@@ -1609,7 +1777,7 @@ defineExpose({
1609
1777
  <!-- 可编辑状态 -->
1610
1778
  <template
1611
1779
  v-for="name in sohelpConfig?.properties?.map(item => item.name)"
1612
- v-slot:[`edit_${name}`]="{ row, column, rowIndex }"
1780
+ #[`edit_${name}`]="{ row, column, rowIndex }"
1613
1781
  :key="name"
1614
1782
  >
1615
1783
  <div v-if="column.editRender.enabled">
@@ -1660,11 +1828,12 @@ defineExpose({
1660
1828
  />
1661
1829
 
1662
1830
  <!-- 外键关联 -->
1663
- <sohelp-table-select v-else-if="column.type==='SohelpTableSelect'"
1831
+ <sohelp-table-select
1832
+ v-else-if="column.type==='SohelpTableSelect'"
1664
1833
  v-model:value="row[name]"
1665
1834
  v-model:data="gridData[rowIndex][name]"
1666
1835
  v-bind="column.editRender"
1667
- ></sohelp-table-select>
1836
+ />
1668
1837
 
1669
1838
  <!-- 数值 -->
1670
1839
  <sohelp-number-input
@@ -1688,10 +1857,10 @@ defineExpose({
1688
1857
  </template>
1689
1858
 
1690
1859
  <!-- 操作栏 -->
1691
- <template #_operation="{ row }">
1860
+ <template #_operation="{ row, column }">
1692
1861
  <el-space :size="10">
1693
1862
  <el-link
1694
- v-for="item in getOperationButtonsByType(row)"
1863
+ v-for="(item) in getOperationButtonsByType(row, column)"
1695
1864
  :key="item.code"
1696
1865
  :type="item.code === 'crud.delete' ? 'danger' : 'primary'"
1697
1866
  v-bind="item.params"
@@ -1705,7 +1874,7 @@ defineExpose({
1705
1874
  {{ item.title }}
1706
1875
  </el-link>
1707
1876
  <!-- 更多 -->
1708
- <el-dropdown v-if="getOperationButtonsByType(row,'more')?.length > 0">
1877
+ <el-dropdown v-if="getOperationButtonsByType(row, column,'more')?.length > 0">
1709
1878
  <el-link :underline="false">
1710
1879
  <span>更多</span>
1711
1880
  <el-icon style="margin-left: 4px;">
@@ -1714,7 +1883,8 @@ defineExpose({
1714
1883
  </el-link>
1715
1884
  <template #dropdown>
1716
1885
  <el-dropdown-menu>
1717
- <el-dropdown-item v-for="item in getOperationButtonsByType(row,'more')" :key="item.code"
1886
+ <el-dropdown-item
1887
+ v-for="item in getOperationButtonsByType(row, column, 'more')" :key="item.code"
1718
1888
  @click.stop="operationHandler({item:item, row:row,$grid:sohelpVxeGridRef})"
1719
1889
  v-bind="item.props">
1720
1890
  <el-icon v-if="item.icon">
@@ -1734,7 +1904,7 @@ defineExpose({
1734
1904
  <!-- 统计 -->
1735
1905
  <template
1736
1906
  v-for="field in footerData"
1737
- v-slot:[`footer_${field["field"]}`]="{ row, column,rowIndex}"
1907
+ #[`footer_${field["field"]}`]="{ row, column,rowIndex}"
1738
1908
  :key="field['field']"
1739
1909
  >
1740
1910
  <div v-html="row[column.field]"></div>
@@ -1744,6 +1914,14 @@ defineExpose({
1744
1914
  <template #valid_slot="{content}">
1745
1915
  {{ content }}
1746
1916
  </template>
1917
+
1918
+
1919
+ <template v-for="(_,name) in $slots" #[name]="{row, column}">
1920
+
1921
+
1922
+ <slot :name="name" :row="getRowDataByField(column,row)" :column="column"></slot>
1923
+ </template>
1924
+
1747
1925
  </vxe-grid>
1748
1926
 
1749
1927
  <!-- workflow -->
@@ -1753,7 +1931,7 @@ defineExpose({
1753
1931
  :showOpera="false"
1754
1932
  ref="todoDrawerRef"
1755
1933
  :key="drawerKey"
1756
- ></workflow-drawer>
1934
+ />
1757
1935
 
1758
1936
  <!-- 提交审批 -->
1759
1937
  <approval-modal
@@ -1761,66 +1939,78 @@ defineExpose({
1761
1939
  type="submit"
1762
1940
  :data="approvalData"
1763
1941
  @confirm="reload"
1764
- ></approval-modal>
1942
+ />
1765
1943
 
1766
1944
  <!-- SohelpTextareaInput 编辑弹窗 -->
1767
1945
  <ele-modal :width="460" v-model="textareaState['visible']" :title="getCurrentFieldLabel">
1768
- <sohelp-textarea-input v-model="textareaState['value']" :rows="6"></sohelp-textarea-input>
1946
+ <sohelp-textarea-input v-model="textareaState['value']" :rows="6"/>
1769
1947
  <template #footer>
1770
1948
  <el-button @click="textareaCancel">{{ t("common.cancel") }}</el-button>
1771
1949
  <el-button type="primary" @click="textareaConfirm(row, column)">{{ t("common.save") }}</el-button>
1772
1950
  </template>
1773
- </ele-modal>
1774
-
1775
- <!--实体表单-->
1776
- <sohelp-modal
1777
- :title="toolbarButtonParams?.title || ''"
1778
- :width="toolbarButtonParams?.width || 860"
1779
- :draggable="false"
1780
- v-model="visibleEntityForm" v-loading="loading">
1781
- <template #setting v-if="userStore.info.is_developer">
1782
- <ele-dropdown
1783
- :items="[
1784
- { title: '表单配置', command: 'form' , icon:Postcard},
1785
- { title: '实体配置', command: 'entity', icon:Tickets},
1786
- { title: '流程配置', command: 'workflow', icon:Files }
1787
- ]"
1788
- @command="settingClick"
1789
- >
1790
- <el-link :icon="Setting" :underline="false"></el-link>
1791
- </ele-dropdown>
1792
- </template>
1951
+ </ele-modal>
1952
+
1953
+ <!--实体表单-->
1954
+ <sohelp-modal
1955
+ :title="toolbarButtonParams?.title || ''"
1956
+ :width="toolbarButtonParams?.width || 860"
1957
+ :draggable="false"
1958
+ v-model="visibleEntityForm" v-loading="loading">
1959
+ <template #setting v-if="userStore.info.is_developer">
1960
+ <ele-dropdown
1961
+ :items="[
1962
+ { title: '表单配置', command: 'form' , icon:Postcard},
1963
+ { title: '实体配置', command: 'entity', icon:Tickets},
1964
+ { title: '流程配置', command: 'workflow', icon:Files },
1965
+ { title: '模块配置', command: 'module', icon:Grid }
1966
+ ]"
1967
+ @command="settingClick"
1968
+ >
1969
+ <el-link :icon="Setting" :underline="false"/>
1970
+ </ele-dropdown>
1971
+ </template>
1972
+
1793
1973
 
1794
- <sohelp-entity-form ref="entityFormRef"
1795
- :refid="props.refid"
1796
- v-model="entityFormValue"
1797
- :data="entityFormData"
1798
- :config="entityFormConfig"
1799
- :readonly="toolbarButtonParams?.readonly"
1800
- ></sohelp-entity-form>
1801
- <template #footer v-if="!toolbarButtonParams?.readonly">
1802
- <el-button @click="closeEntityForm()">{{ t("common.close") }}</el-button>
1803
- <el-button type="primary" @click="saveEntityForm()" v-loading="loading">{{ t("common.save") }}</el-button>
1974
+ <sohelp-entity-form
1975
+ ref="entityFormRef"
1976
+ :refid="props.refid"
1977
+ v-model="entityFormValue"
1978
+ :data="entityFormData"
1979
+ :config="entityFormConfig"
1980
+ :readonly="toolbarButtonParams?.readonly"
1981
+ />
1982
+ <template #footer v-if="!toolbarButtonParams?.readonly">
1983
+ <el-button @click="closeEntityForm()">{{ t("common.close") }}</el-button>
1984
+ <el-button type="primary" @click="saveEntityForm()" v-loading="loading">{{ t("common.save") }}</el-button>
1985
+ </template>
1986
+ </sohelp-modal>
1987
+ <!--打印报表-->
1988
+ <ele-modal
1989
+ :title="toolbarButtonParams?.title|| t('grid.report.title')" :width="toolbarButtonParams?.width|| 600"
1990
+ v-model="visibleReport">
1991
+
1992
+ <ele-check-card v-model="currentReportValue" :items="reportData" :row="{ gutter: 2 }">
1993
+ <template #item="{ item }">
1994
+ <ele-text size="md" style="padding:10px;">{{ item.name }}</ele-text>
1995
+ </template>
1996
+ </ele-check-card>
1997
+
1998
+ <template #footer>
1999
+ <el-button @click="closeReport()">{{ t("common.close") }}</el-button>
2000
+ <el-button @click="designReport()" v-if="reportData && reportData.length>0">{{ t("common.design") }}</el-button>
2001
+ <el-button type="primary" @click="openReport()" v-if="reportData && reportData.length>0">{{ t("common.print") }}
2002
+ </el-button>
1804
2003
  </template>
1805
- </sohelp-modal>
1806
- <!--打印报表-->
1807
- <ele-modal :title="toolbarButtonParams?.title|| t('grid.report.title')" :width="toolbarButtonParams?.width|| 600"
1808
- v-model="visibleReport">
1809
-
1810
- <ele-check-card v-model="currentReportValue" :items="reportData" :row="{ gutter: 2 }">
1811
- <template #item="{ item }">
1812
- <ele-text size="md" style="padding:10px;">{{ item.name }}</ele-text>
2004
+ </ele-modal>
2005
+ <!--数据导入-->
2006
+ <sohelp-import
2007
+ :model-value="importVisible"
2008
+ :refid="props.refid"
2009
+ :fields="sohelpConfig?.properties || []"
2010
+ @update:modelValue="(v) => importVisible = v"
2011
+ @close="closeImport"
2012
+ />
1813
2013
  </template>
1814
- </ele-check-card>
1815
-
1816
- <template #footer>
1817
- <el-button @click="closeReport()">{{ t("common.close") }}</el-button>
1818
- <el-button @click="designReport()" v-if="reportData && reportData.length>0">{{ t("common.design") }}</el-button>
1819
- <el-button type="primary" @click="openReport()" v-if="reportData && reportData.length>0">{{ t("common.print") }}
1820
- </el-button>
1821
- </template>
1822
- </ele-modal>
1823
- </template>
1824
2014
 
1825
2015
  <style scoped lang="scss">
1826
2016
  .sohelp-grid-view {
@@ -1962,4 +2152,6 @@ defineExpose({
1962
2152
 
1963
2153
 
1964
2154
 
2155
+
2156
+
1965
2157
  </style>