cloud-web-corejs 1.0.54-dev.800 → 1.0.54-dev.802

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 (59) hide show
  1. package/package.json +1 -1
  2. package/src/components/baseArea/index.vue +82 -27
  3. package/src/components/bizTab/BizBillActions.vue +2 -2
  4. package/src/components/bizTab/bizBillDetailMixin.js +27 -9
  5. package/src/components/excelExport/exportFieldDialog.vue +11 -9
  6. package/src/components/table/config.js +6 -4
  7. package/src/components/table/index.js +78 -22
  8. package/src/components/table/state.js +42 -0
  9. package/src/components/table/tableForm.vue +16 -5
  10. package/src/components/table/tableFormMixin.js +35 -7
  11. package/src/components/table/vxeFilter/index.js +4 -2
  12. package/src/components/table/vxeFilter/mixin.js +10 -4
  13. package/src/components/wf/content.vue +12 -0
  14. package/src/components/wf/wf.js +72 -23
  15. package/src/components/wf/wfActionDropdown.vue +85 -0
  16. package/src/components/wf/wfActionItems.js +136 -0
  17. package/src/components/wf/wfAutoConfirm.js +55 -0
  18. package/src/components/wf/wfUserRange.js +53 -0
  19. package/src/components/wf/wfUtil.js +46 -2
  20. package/src/components/xform/form-designer/designer.js +6 -1
  21. package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +9 -3
  22. package/src/components/xform/form-designer/form-widget/dialog/vabSearchDialog.vue +2 -1
  23. package/src/components/xform/form-designer/form-widget/field-widget/date-range-widget.vue +3 -2
  24. package/src/components/xform/form-designer/form-widget/field-widget/date-widget.vue +3 -12
  25. package/src/components/xform/form-designer/form-widget/field-widget/mixins/date-limit-mixin.js +2 -46
  26. package/src/components/xform/form-designer/form-widget/field-widget/mixins/relative-default-mixin.js +107 -0
  27. package/src/components/xform/form-designer/form-widget/field-widget/mixins/relativeDateUtil.js +321 -0
  28. package/src/components/xform/form-designer/form-widget/field-widget/mixins/time-limit-mixin.js +2 -17
  29. package/src/components/xform/form-designer/form-widget/field-widget/time-range-widget.vue +3 -2
  30. package/src/components/xform/form-designer/form-widget/field-widget/time-widget.vue +3 -12
  31. package/src/components/xform/form-designer/setting-panel/form-dynamicField-setting.vue +5 -5
  32. package/src/components/xform/form-designer/setting-panel/form-setting.vue +48 -26
  33. package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +16 -19
  34. package/src/components/xform/form-designer/setting-panel/property-editor/container-grid/gutter-editor.vue +13 -12
  35. package/src/components/xform/form-designer/setting-panel/property-editor/container-table/table-dynamicField-editor.vue +16 -18
  36. package/src/components/xform/form-designer/setting-panel/property-editor/event-handler/afterColumnsCreated-editor.vue +30 -0
  37. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/search-dialog-event-editor.vue +237 -237
  38. package/src/components/xform/form-designer/setting-panel/property-editor/field-common/keyName-editor.vue +4 -4
  39. package/src/components/xform/form-designer/setting-panel/property-editor/field-date/date-defaultValue-editor.vue +35 -36
  40. package/src/components/xform/form-designer/setting-panel/property-editor/field-date-range/date-range-defaultValue-editor.vue +35 -18
  41. package/src/components/xform/form-designer/setting-panel/property-editor/field-import-button/import2-button-editor.vue +1 -1
  42. package/src/components/xform/form-designer/setting-panel/property-editor/field-time/time-defaultValue-editor.vue +34 -36
  43. package/src/components/xform/form-designer/setting-panel/property-editor/field-time-range/time-range-defaultValue-editor.vue +35 -18
  44. package/src/components/xform/form-designer/setting-panel/property-editor/fixedQuery-editor.vue +39 -0
  45. package/src/components/xform/form-designer/setting-panel/property-editor/formScriptEnabled-editor.vue +20 -3
  46. package/src/components/xform/form-designer/setting-panel/property-editor/name-editor.vue +188 -178
  47. package/src/components/xform/form-designer/setting-panel/property-editor/relative-default-block.vue +369 -0
  48. package/src/components/xform/form-designer/setting-panel/property-editor/textFlag-editor.vue +1 -1
  49. package/src/components/xform/form-designer/setting-panel/propertyRegister.js +2 -0
  50. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +35 -2
  51. package/src/components/xform/form-render/container-item/data-table-mixin.js +150 -75
  52. package/src/components/xform/form-render/container-item/detail-item.vue +8 -12
  53. package/src/components/xform/lang/en-US.js +3 -0
  54. package/src/components/xform/lang/zh-CN.js +3 -0
  55. package/src/components/xform/mixins/defaultHandle.js +18 -3
  56. package/src/components/xform/utils/fixedQueryUtil.js +93 -0
  57. package/src/views/user/outLink/cc_form_view.vue +33 -30
  58. package/src/views/user/wf/wf_manage/list.vue +17 -1
  59. package/src/components/xform/form-render/container-item/data-table-mixin copy.js +0 -5910
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cloud-web-corejs",
3
3
  "private": false,
4
- "version": "1.0.54-dev.800",
4
+ "version": "1.0.54-dev.802",
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
7
7
  "dev:micro": "vue-cli-service serve --port 17527",
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div class="base-area">
3
3
  <el-popover
4
+ ref="popoverRef"
4
5
  v-model="popoverVisible"
5
6
  placement="bottom-start"
6
7
  trigger="click"
@@ -268,13 +269,28 @@ export default {
268
269
  if (this.labelValue) {
269
270
  return this.labelValue;
270
271
  }
271
- const pathLabel = this.selectedPath.length
272
+ /* 弹层浏览中的选择未确认,输入框只回显打开弹层时的已提交值 */
273
+ if (this.popoverVisible) {
274
+ return this.committedPathLabel;
275
+ }
276
+ if (!this.selectedPath.length) {
277
+ return "";
278
+ }
279
+ /* 外部未回传 label 时的兜底:仅当浏览路径与已绑定值一致才回显 */
280
+ const leafId = this.getLeafIdFromValue(this.value);
281
+ return this.isValueSynced(leafId)
272
282
  ? this.buildPathLabel(this.selectedPath)
273
283
  : "";
274
- if (this.popoverVisible && pathLabel) {
275
- return pathLabel;
284
+ },
285
+ committedPathLabel() {
286
+ const snapshot = this.committedBrowseSnapshot;
287
+ if (!snapshot || !snapshot.selectedPath || !snapshot.selectedPath.length) {
288
+ return "";
276
289
  }
277
- return pathLabel || "";
290
+ if (!this.isSameBoundValue(this.value, snapshot.boundValue)) {
291
+ return "";
292
+ }
293
+ return this.buildPathLabel(snapshot.selectedPath);
278
294
  },
279
295
  tabs() {
280
296
  const tabs = [];
@@ -336,8 +352,43 @@ export default {
336
352
  },
337
353
  beforeDestroy() {
338
354
  clearTimeout(this.searchTimer);
355
+ this.unbindOutsideClick();
339
356
  },
340
357
  methods: {
358
+ bindOutsideClick() {
359
+ /* 捕获阶段监听:外层若阻止了 click 冒泡,el-popover 自带的 document 监听收不到,弹层不会关闭 */
360
+ document.addEventListener("mousedown", this.handleOutsideClick, true);
361
+ },
362
+ unbindOutsideClick() {
363
+ document.removeEventListener("mousedown", this.handleOutsideClick, true);
364
+ },
365
+ isInsidePopover(target) {
366
+ if (!target || !target.nodeType) {
367
+ return false;
368
+ }
369
+ /* 触发器(含输入框)在组件根节点内 */
370
+ if (this.$el && this.$el.contains(target)) {
371
+ return true;
372
+ }
373
+ /* 弹层默认 append 到 body,需单独判断 */
374
+ const popoverRef = this.$refs.popoverRef;
375
+ const popper = popoverRef && popoverRef.$refs && popoverRef.$refs.popper;
376
+ return !!(popper && popper.contains(target));
377
+ },
378
+ handleOutsideClick(evt) {
379
+ if (!this.popoverVisible) {
380
+ return;
381
+ }
382
+ const target = evt.target;
383
+ /* 已从文档移除的节点无法判断归属,不做处理 */
384
+ if (!target || !document.contains(target)) {
385
+ return;
386
+ }
387
+ if (this.isInsidePopover(target)) {
388
+ return;
389
+ }
390
+ this.popoverVisible = false;
391
+ },
341
392
  getResolveDepthLimit(item) {
342
393
  if (item && item.treePath) {
343
394
  const ids = this.parseTreePathIds(item.treePath);
@@ -565,6 +616,7 @@ export default {
565
616
  },
566
617
  handlePopoverShow() {
567
618
  this.pendingLeaf = false;
619
+ this.bindOutsideClick();
568
620
  this.saveCommittedBrowseSnapshot();
569
621
  this.$emit("popover-open");
570
622
  this.$nextTick(() => {
@@ -1060,6 +1112,7 @@ export default {
1060
1112
  this.emitResolvedLabelIfNeeded();
1061
1113
  },
1062
1114
  handlePopoverHide() {
1115
+ this.unbindOutsideClick();
1063
1116
  this.searchKeyword = "";
1064
1117
  this.searchList = [];
1065
1118
  this.searchDropdownVisible = false;
@@ -1299,13 +1352,13 @@ export default {
1299
1352
  }
1300
1353
 
1301
1354
  .base-area-panel {
1302
- padding: 4px 0 0;
1355
+ padding: 0;
1303
1356
  overflow: visible;
1304
1357
  }
1305
1358
 
1306
1359
  .base-area-search {
1307
1360
  position: relative;
1308
- margin-bottom: 8px;
1361
+ margin-bottom: 6px;
1309
1362
  z-index: 2;
1310
1363
  }
1311
1364
 
@@ -1360,8 +1413,8 @@ export default {
1360
1413
  }
1361
1414
 
1362
1415
  .base-area-path {
1363
- padding: 6px 10px;
1364
- margin-bottom: 10px;
1416
+ padding: 3px 8px;
1417
+ margin-bottom: 6px;
1365
1418
  background: #f5f7fa;
1366
1419
  border: 1px solid #ebeef5;
1367
1420
  border-radius: 4px;
@@ -1380,7 +1433,7 @@ export default {
1380
1433
  padding: 0 2px;
1381
1434
  font-size: 12px;
1382
1435
  color: #c0c4cc;
1383
- line-height: 24px;
1436
+ line-height: 22px;
1384
1437
  user-select: none;
1385
1438
  }
1386
1439
 
@@ -1389,8 +1442,8 @@ export default {
1389
1442
  min-width: 0;
1390
1443
  max-width: 100%;
1391
1444
  padding: 0 4px;
1392
- height: 24px;
1393
- line-height: 24px;
1445
+ height: 22px;
1446
+ line-height: 22px;
1394
1447
  border: none;
1395
1448
  border-bottom: 2px solid transparent;
1396
1449
  border-radius: 0;
@@ -1427,7 +1480,7 @@ export default {
1427
1480
  }
1428
1481
 
1429
1482
  .base-area-grid-wrap {
1430
- padding: 8px;
1483
+ padding: 6px;
1431
1484
  background: #fff;
1432
1485
  border: 1px solid #eee;
1433
1486
  border-radius: 8px;
@@ -1436,20 +1489,22 @@ export default {
1436
1489
  .base-area-grid {
1437
1490
  display: flex;
1438
1491
  flex-wrap: wrap;
1439
- min-height: 120px;
1440
- max-height: 294px;
1492
+ align-content: flex-start;
1493
+ min-height: 82px;
1494
+ /* 5 行:(28 + 6) * 5 + 4 */
1495
+ max-height: 174px;
1441
1496
  overflow-y: auto;
1442
1497
  margin: 0 -4px;
1443
1498
  }
1444
1499
 
1445
1500
  .base-area-item {
1446
1501
  width: calc(25% - 8px);
1447
- margin: 0 4px 8px;
1502
+ margin: 0 4px 6px;
1448
1503
  padding: 0 10px;
1449
- height: 34px;
1450
- line-height: 34px;
1504
+ height: 28px;
1505
+ line-height: 28px;
1451
1506
  border: 1px solid #eee;
1452
- border-radius: 8px;
1507
+ border-radius: 6px;
1453
1508
  font-size: 12px;
1454
1509
  cursor: pointer;
1455
1510
  overflow: hidden;
@@ -1470,7 +1525,7 @@ export default {
1470
1525
 
1471
1526
  .base-area-empty {
1472
1527
  width: 100%;
1473
- padding: 24px 0;
1528
+ padding: 16px 0;
1474
1529
  text-align: center;
1475
1530
  color: #909399;
1476
1531
  font-size: 12px;
@@ -1480,12 +1535,12 @@ export default {
1480
1535
  display: flex;
1481
1536
  align-items: center;
1482
1537
  justify-content: space-between;
1483
- margin-top: 8px;
1538
+ margin-top: 6px;
1484
1539
 
1485
1540
  .base-area-nav-btn {
1486
1541
  min-width: 32px;
1487
- padding: 7px 10px;
1488
- border-radius: 8px;
1542
+ padding: 5px 10px;
1543
+ border-radius: 6px;
1489
1544
  color: #fff;
1490
1545
  border-color: $baseColor;
1491
1546
  background-color: $baseColor;
@@ -1522,7 +1577,7 @@ export default {
1522
1577
  text-align: center;
1523
1578
  font-size: 12px;
1524
1579
  color: #606266;
1525
- line-height: 28px;
1580
+ line-height: 24px;
1526
1581
  user-select: none;
1527
1582
  }
1528
1583
  }
@@ -1531,8 +1586,8 @@ export default {
1531
1586
  display: flex;
1532
1587
  align-items: center;
1533
1588
  justify-content: flex-end;
1534
- margin-top: 8px;
1535
- padding-top: 8px;
1589
+ margin-top: 6px;
1590
+ padding-top: 6px;
1536
1591
  border-top: 1px solid #ebeef5;
1537
1592
  }
1538
1593
  </style>
@@ -1577,7 +1632,7 @@ export default {
1577
1632
  }
1578
1633
 
1579
1634
  .base-area-popover {
1580
- padding: 10px 12px;
1635
+ padding: 8px 10px;
1581
1636
  overflow: visible;
1582
1637
  box-sizing: border-box;
1583
1638
 
@@ -1599,7 +1654,7 @@ export default {
1599
1654
  }
1600
1655
 
1601
1656
  .base-area-nav-btn.el-button {
1602
- border-radius: 8px;
1657
+ border-radius: 6px;
1603
1658
  color: #fff;
1604
1659
  border-color: $baseColor;
1605
1660
  background-color: $baseColor;
@@ -3,7 +3,7 @@
3
3
  <!-- 按钮顺序(.fr 里 DOM 次序即从左到右):
4
4
  翻单 → 提交流程 → 业务按钮(默认插槽) → 重置 → 保存
5
5
  #before 是留给"要排在翻单之前"的特例,一般不用。
6
- 另外 wfUtil 的「修改单据」按钮是 append 到本容器最前面的,会落在最左侧。 -->
6
+ 另外 wfUtil 的「流程操作」下拉 / 「修改单据」是 append 到本容器最前面的,会落在最左侧。 -->
7
7
  <slot name="before"></slot>
8
8
  <!-- ① 上一单 / 下一单:列表侧 openDetail 传了 navRows 才出现 -->
9
9
  <template v-if="showBillNav">
@@ -83,7 +83,7 @@
83
83
  * </div>
84
84
  *
85
85
  * 注意:根节点是 .d-header 里的 .fr,别再往外包一层,否则布局会散,
86
- * 而且 wfUtil 的「修改单据」按钮就是往 .el-form .d-header > .fr 里塞的。
86
+ * 而且 wfUtil 的「流程操作」下拉 / 「修改单据」就是往 .el-form .d-header > .fr 里塞的。
87
87
  */
88
88
  export default {
89
89
  name: "BizBillActions",
@@ -35,6 +35,14 @@ import {
35
35
  DEFAULT_SUBMIT_BTN,
36
36
  DEFAULT_SAVE_SUBMIT_BTN,
37
37
  } from "@base/components/wf/wfButtonName";
38
+ import {
39
+ isWfAutoConfirm,
40
+ loadWfAutoConfirm,
41
+ } from "@base/components/wf/wfAutoConfirm";
42
+ import {
43
+ isWfUserRangeEnabled,
44
+ loadWfUserRange,
45
+ } from "@base/components/wf/wfUserRange";
38
46
 
39
47
  // wf 组件回调 _handleCallback(flag) 的 flag → 页签行为类型
40
48
  const WF_FLAG_KIND = {
@@ -174,6 +182,9 @@ export default {
174
182
  let dataId = this.tab ? this.tab.dataId : this._dataId;
175
183
  this.dataId = dataId == null || dataId === 0 ? null : dataId;
176
184
  loadWfButtonNames(this);
185
+ //预热,点击路径上的 await 直接命中缓存
186
+ loadWfAutoConfirm(this);
187
+ loadWfUserRange(this);
177
188
  this.checkBillHooks();
178
189
  // 登记到宿主:关页签确认要问详情脏没脏、翻单要按 tabName 找回实例
179
190
  let host = this.bizTabHost;
@@ -252,9 +263,8 @@ export default {
252
263
  showModifyBtn: cfg.showModifyBtn !== false,
253
264
  // 自己控制 done 的时机:等详情数据渲染完再挂流程面板,避免取不到 .d-cont
254
265
  auto: false,
255
- // 启动确认文案跟随后台 param18 的按钮名,和「保存并提交」那条链路口径一致
256
- startConfirmText: () =>
257
- this.$t1(`您确定要${this.submitButtonName}吗?`),
266
+ // 不传 startConfirmText:启动确认文案由 wf.js 按后台 param18 的按钮名统一拼,
267
+ // 这里再拼一遍会让 wf.js 把它当成「模板脚本自定义的提示语」,param19 自动确认就失效了
258
268
  callback: (wfParam) => {
259
269
  this.wfParam = wfParam || {};
260
270
  this.hasWf = !!this.wfParam.hasWf;
@@ -339,11 +349,18 @@ export default {
339
349
  if (!(await this.guardSaving())) return false;
340
350
  let valid = await this.validateBill();
341
351
  if (!valid) return false;
342
- let confirmText = this.$t1(`您确定要${this.saveSubmitButtonName}吗?`);
343
- try {
344
- await this.$baseConfirm(confirmText);
345
- } catch (e) {
346
- return false;
352
+ // param19 + param12 都开:这道「保存前」的确认框不弹,把确认交给 wfStartDialog——
353
+ // 它在保存之后才探 preStart,探到候选人就由「修改候选人」弹框顶替,探不到才弹确认框。
354
+ // 任一为 false 都当场弹:param12 关着后面不可能有候选人弹框,延后没有意义。
355
+ await Promise.all([loadWfAutoConfirm(this), loadWfUserRange(this)]);
356
+ let autoConfirm = isWfAutoConfirm() && isWfUserRangeEnabled();
357
+ if (!autoConfirm) {
358
+ let confirmText = this.$t1(`您确定要${this.saveSubmitButtonName}吗?`);
359
+ try {
360
+ await this.$baseConfirm(confirmText);
361
+ } catch (e) {
362
+ return false;
363
+ }
347
364
  }
348
365
  let dataId = await this.runSave({ confirm: false, successMsg: false });
349
366
  if (dataId == null || dataId === "") return false;
@@ -355,7 +372,8 @@ export default {
355
372
  this,
356
373
  this.buildWfOption({
357
374
  objId: dataId,
358
- skipStartConfirm: true, // 已经确认过一次了,不再弹第二次
375
+ // 上面确认过就不再弹第二次;上面因 param19 跳过了,就得让弹框自己去确认
376
+ skipStartConfirm: !autoConfirm,
359
377
  onStart: null, // 校验/保存都做完了,不再走 wfStartBindSave 那套
360
378
  onBeforeStartSubmit: null,
361
379
  })
@@ -168,9 +168,11 @@ export default {
168
168
  let yesFields = [];
169
169
  let noFields = [];
170
170
 
171
- let exportColumns = !exportItem
172
- ? target.exportColumns || []
173
- : target.exportItemColumns || [];
171
+ let exportColumns =
172
+ this.$vxeTableUtil.getTableStateValue(
173
+ target,
174
+ !exportItem ? "exportColumns" : "exportItemColumns"
175
+ ) || [];
174
176
 
175
177
  this.loopColumnHandle(exportColumns, (item) => {
176
178
  if (item.field) {
@@ -201,7 +203,6 @@ export default {
201
203
  });
202
204
  } else {
203
205
  //导出子表数据
204
- let exportItemColumns = target.exportItemColumns || [];
205
206
  let originOption = target.params.originOption;
206
207
  let oriExportItemColumns = originOption.exportItemConfig?.columns || [];
207
208
 
@@ -246,9 +247,6 @@ export default {
246
247
  let leafColumns = this.$refs.tree.getCheckedNodes(true);
247
248
  let checkLeafIds = leafColumns.map((item) => item.id);
248
249
 
249
- // let syncEportItemColumns = $grid.exportItemColumns || [];
250
- // let syncExportColumns = $grid.exportColumns || [];
251
-
252
250
  if (!exportItem) {
253
251
  //导出主表数据
254
252
  let exportColumns = [];
@@ -262,7 +260,7 @@ export default {
262
260
  exportColumns.push(item);
263
261
  }
264
262
  });
265
- $grid.exportColumns = exportColumns;
263
+ this.$vxeTableUtil.setTableState($grid, "exportColumns", exportColumns);
266
264
  } else {
267
265
  //导出子表数据
268
266
  let exportItemColumns = [];
@@ -276,7 +274,11 @@ export default {
276
274
  exportItemColumns.push(item);
277
275
  }
278
276
  });
279
- $grid.exportItemColumns = exportItemColumns;
277
+ this.$vxeTableUtil.setTableState(
278
+ $grid,
279
+ "exportItemColumns",
280
+ exportItemColumns
281
+ );
280
282
  }
281
283
  }
282
284
  this.$vxeTableUtil.addTableJson(originOption.vue, $grid, originOption.tableName);
@@ -1,3 +1,5 @@
1
+ import { getTableStateValue } from './state';
2
+
1
3
  let modules = {};
2
4
 
3
5
  modules = {
@@ -33,7 +35,7 @@ modules = {
33
35
  }, ' ' + tableDataInfo.visibleData.length + ' ')
34
36
  ];
35
37
  if (pager) {
36
- if (pager && $grid.isQueryAllPage) {
38
+ if (pager && getTableStateValue($grid, 'isQueryAllPage')) {
37
39
  celems.push(h('span', '/'));
38
40
  celems.push(h('span', {
39
41
  attrs: {
@@ -42,7 +44,7 @@ modules = {
42
44
  }, ' ' + pager.total));
43
45
  }
44
46
 
45
- let iconClass = $grid.isQueryAllPage ? 'icon-yincang' : 'el-icon-view';
47
+ let iconClass = getTableStateValue($grid, 'isQueryAllPage') ? 'icon-yincang' : 'el-icon-view';
46
48
 
47
49
  celems.push(h('i', {
48
50
  attrs: {
@@ -53,8 +55,8 @@ modules = {
53
55
  let refTarget = $grid.$vnode.data.ref;
54
56
  let that = $grid.params.originOption.vue;
55
57
  let tableName = $grid.params.originOption.tableName;
56
- $grid.$vxeTableUtil.checkQueryTotal(that, refTarget, !$grid
57
- .isQueryAllPage);
58
+ $grid.$vxeTableUtil.checkQueryTotal(that, refTarget,
59
+ !getTableStateValue($grid, 'isQueryAllPage'));
58
60
  }
59
61
  }
60
62
  }));
@@ -8,6 +8,7 @@ import { extendDeeply } from "../../utils/index.js";
8
8
  import corejsConfig from "@/corejsConfig";
9
9
  import settingConfig from "@/settings.js";
10
10
  import { getCellValue, createParams } from "./util/index";
11
+ import { getTableStateValue, setTableState } from "./state";
11
12
 
12
13
  let configUtil = {
13
14
  Sortable,
@@ -78,6 +79,15 @@ async function initVxeTable(option) {
78
79
  $grid.originOption = originOption;
79
80
  option.vue = that;
80
81
 
82
+ // 运行时状态先收集到局部对象,末尾并入 nOption.params 随 vxeOption 传给表格实例,
83
+ // 保证页面 v-if 销毁重建 grid 后状态不丢(详见 ./state.js)
84
+ let tableState = {
85
+ tableName: tableName || null,
86
+ isQueryAllPage: true,
87
+ exportColumns: null,
88
+ exportItemColumns: null,
89
+ };
90
+
81
91
  let isQueryAllPage = true;
82
92
  if (option.isQueryAllPage !== null && option.isQueryAllPage !== undefined) {
83
93
  isQueryAllPage = option.isQueryAllPage;
@@ -85,7 +95,7 @@ async function initVxeTable(option) {
85
95
 
86
96
  let searchColumns = null;
87
97
  if (tableName) {
88
- $grid.tableName = tableName;
98
+ setTableState($grid, "tableName", tableName);
89
99
  if (option.path) {
90
100
  await getTableData(that, option.tableRef, "isQueryAllPage", (res1) => {
91
101
  let result = res1.objx ? res1.objx.data : null;
@@ -113,7 +123,7 @@ async function initVxeTable(option) {
113
123
  json.searchColumns
114
124
  );
115
125
  $grid.searchColumns = searchColumns;
116
- initExportColumns($grid, json);
126
+ initExportColumns($grid, tableState, json);
117
127
  }
118
128
  }
119
129
  if (!searchColumns || !searchColumns.length) {
@@ -137,10 +147,11 @@ async function initVxeTable(option) {
137
147
  option.isQueryAllPage = isQueryAllPage;
138
148
  let nOption = initOption(option);
139
149
 
140
- // isQueryAllPage 的唯一事实源是表格实例(checkQueryTotal 也写这里),
141
- // pager 插槽与代理 ajax.query 均读 $grid.isQueryAllPage,初始化必须回写,
150
+ // isQueryAllPage 的事实源是 $grid.params(checkQueryTotal 也写这里),
151
+ // pager 插槽与代理 ajax.query 均读它,初始化必须回写,
142
152
  // 否则首屏恒为 undefined:既丢用户存的偏好,也让页面配置的 false 不生效。
143
- $grid.isQueryAllPage = isQueryAllPage;
153
+ tableState.isQueryAllPage = isQueryAllPage;
154
+ setTableState($grid, "isQueryAllPage", isQueryAllPage);
144
155
 
145
156
  if (tableName) {
146
157
  nOption.tableName = tableName;
@@ -157,12 +168,14 @@ async function initVxeTable(option) {
157
168
  // nOption.getCellValue = getCellValue;
158
169
  // nOption.createParams = createParams;
159
170
  // nOption.searchColumns = searchColumns;
160
- // 注意:isQueryAllPage 不放 params——它是运行时可变状态,事实源在 $grid 上(见上方回写)
171
+ // 运行时可变状态(tableName / isQueryAllPage / exportColumns / exportItemColumns)
172
+ // 一并放进 params:params 随 vxeOption 由页面持有,grid 被 v-if 销毁重建后依然带着这些值
161
173
  let params = {
162
174
  originOption,
163
175
  getCellValue,
164
176
  createParams,
165
177
  searchColumns,
178
+ ...tableState,
166
179
  };
167
180
  if (!nOption.params) nOption.params = {};
168
181
  Object.assign(nOption.params, params);
@@ -193,6 +206,35 @@ function handleToolbar($grid, option) {
193
206
  }
194
207
  }
195
208
 
209
+ /**
210
+ * grid 被 v-if 销毁重建后调用(页面把 showTable 从 false 切回 true 之类)。
211
+ *
212
+ * 状态类(tableName / isQueryAllPage / exportColumns…)已经随 params 跨重建存活,
213
+ * 这里只重做「绑在实例或 DOM 上、params 带不走」的那部分:
214
+ * - columnDrop:Sortable 绑的是旧表头 DOM,重建后新表头上什么都没有,列拖拽会静默失效;
215
+ * - handleToolbar:$grid.connect(toolbar) 是实例间的连接,重建后失联。
216
+ * 必须等新 grid 渲染出表头再绑,所以整体放在 $nextTick 里。
217
+ */
218
+ function rebindGrid(that, tableRef) {
219
+ let $grid = getGrid(that, tableRef);
220
+ let originOption = $grid && $grid.params && $grid.params.originOption;
221
+ if (!originOption) {
222
+ // 没走过 initVxeTable 的表格没有 params.originOption,无从重绑
223
+ return Promise.resolve(false);
224
+ }
225
+ $grid.originOption = originOption;
226
+ // vxeFilter 已改为直接 import 工具函数,这里补挂只为兼容直接读 $table.getCellValue 的业务代码
227
+ if ($grid.$refs && $grid.$refs.xTable) {
228
+ $grid.$refs.xTable.getCellValue = getCellValue;
229
+ $grid.$refs.xTable.createParams = createParams;
230
+ }
231
+ return $grid.$nextTick().then(() => {
232
+ columnDrop(that, originOption.tableName, tableRef);
233
+ handleToolbar($grid, originOption);
234
+ return true;
235
+ });
236
+ }
237
+
196
238
  //操作列自动补全
197
239
  function handleCustomAlign(option) {
198
240
  let selfConfig = getSelfConfig();
@@ -270,6 +312,16 @@ function columnDrop(t, tableName, tableRef) {
270
312
  if (!$table) {
271
313
  return;
272
314
  }
315
+ // 表头尚未渲染(grid 刚被 v-if 重建、DOM 还没就绪)时 querySelector 返回 null,
316
+ // Sortable.create(null) 会直接抛错,这里降级为不绑定,由调用方在 $nextTick 后重试
317
+ const headerElem =
318
+ $table.$el &&
319
+ $table.$el.querySelector(
320
+ ".body--wrapper>.vxe-table--header .vxe-header--row"
321
+ );
322
+ if (!headerElem) {
323
+ return;
324
+ }
273
325
  // if (!$table.params) $table.params = {};
274
326
  if ($table.sortable) {
275
327
  $table.sortable.destroy();
@@ -278,9 +330,7 @@ function columnDrop(t, tableName, tableRef) {
278
330
  let dragStartIndex = -1;
279
331
  let dragEndIndex = -1;
280
332
  $table.sortable = configUtil.Sortable.create(
281
- $table.$el.querySelector(
282
- ".body--wrapper>.vxe-table--header .vxe-header--row"
283
- ),
333
+ headerElem,
284
334
  {
285
335
  handle: ".vxe-header--column:not(.col--fixed)",
286
336
  onMove: (a, b, c) => {
@@ -546,7 +596,7 @@ function initOption(opts) {
546
596
  " " + tableDataInfo.visibleData.length + " "
547
597
  ),
548
598
  ];
549
- if (pager && $grid.isQueryAllPage) {
599
+ if (pager && getTableStateValue($grid, "isQueryAllPage")) {
550
600
  celems.push(
551
601
  h(
552
602
  "span",
@@ -648,7 +698,7 @@ function initOption(opts) {
648
698
  }
649
699
 
650
700
  let $grid = getGrid(that, opts.tableRef);
651
- let isQueryAllPage = $grid.isQueryAllPage;
701
+ let isQueryAllPage = getTableStateValue($grid, "isQueryAllPage");
652
702
  let pathStr1 = "";
653
703
  if (isQueryAllPage === false) {
654
704
  queryParams.searchCount = false;
@@ -926,11 +976,13 @@ function addTableJson(that, $grid, tableName, columns, success) {
926
976
  columns: saveColumn,
927
977
  searchColumns: searchColumns,
928
978
  };
929
- if ($grid.exportColumns && $grid.exportColumns.length) {
930
- jsonData.exportColumns = $grid.exportColumns;
979
+ let exportColumns = getTableStateValue($grid, "exportColumns");
980
+ let exportItemColumns = getTableStateValue($grid, "exportItemColumns");
981
+ if (exportColumns && exportColumns.length) {
982
+ jsonData.exportColumns = exportColumns;
931
983
  }
932
- if ($grid.exportItemColumns && $grid.exportItemColumns.length) {
933
- jsonData.exportItemColumns = $grid.exportItemColumns;
984
+ if (exportItemColumns && exportItemColumns.length) {
985
+ jsonData.exportItemColumns = exportItemColumns;
934
986
  }
935
987
  let json = encodeURIComponent(JSON.stringify(jsonData));
936
988
 
@@ -1020,12 +1072,14 @@ function initColumn(option, syncColumns) {
1020
1072
  return newColumns;
1021
1073
  }
1022
1074
 
1023
- function initExportColumns($grid, json) {
1075
+ function initExportColumns($grid, tableState, json) {
1024
1076
  if (json?.exportColumns?.length) {
1025
- $grid.exportColumns = json.exportColumns;
1077
+ tableState.exportColumns = json.exportColumns;
1078
+ setTableState($grid, "exportColumns", json.exportColumns);
1026
1079
  }
1027
1080
  if (json?.exportItemColumns?.length) {
1028
- $grid.exportItemColumns = json.exportItemColumns;
1081
+ tableState.exportItemColumns = json.exportItemColumns;
1082
+ setTableState($grid, "exportItemColumns", json.exportItemColumns);
1029
1083
  }
1030
1084
  }
1031
1085
 
@@ -1141,7 +1195,7 @@ function getTableData(that, tableRef, type, success) {
1141
1195
  )
1142
1196
  return false;
1143
1197
  let $grid = getGrid(that, tableRef);
1144
- let tableName = $grid.tableName;
1198
+ let tableName = getTableStateValue($grid, "tableName");
1145
1199
  let url = USER_PREFIX + "/table_column/getTableData";
1146
1200
  let param = {
1147
1201
  tableName: tableName,
@@ -1163,7 +1217,7 @@ function addTableData(that, tableRef, value, success) {
1163
1217
  )
1164
1218
  return false;
1165
1219
  let $grid = getGrid(that, tableRef);
1166
- let tableName = $grid.tableName;
1220
+ let tableName = getTableStateValue($grid, "tableName");
1167
1221
  if (tableName) {
1168
1222
  that.$http({
1169
1223
  method: "post",
@@ -1180,8 +1234,7 @@ function addTableData(that, tableRef, value, success) {
1180
1234
 
1181
1235
  function checkQueryTotal(that, tableRef, value) {
1182
1236
  let $grid = getGrid(that, tableRef);
1183
- $grid.isQueryAllPage = value;
1184
- let tableName = $grid.tableName;
1237
+ setTableState($grid, "isQueryAllPage", value);
1185
1238
  let option = $grid.getProxyInfo();
1186
1239
  let pagerConfig = $grid.pagerConfig;
1187
1240
 
@@ -1201,6 +1254,7 @@ function getPagerConfigLayouts(opts) {
1201
1254
  modules = {
1202
1255
  initVxeTable,
1203
1256
  columnDrop,
1257
+ rebindGrid,
1204
1258
  initOption,
1205
1259
  getTableJson,
1206
1260
  addTableJson,
@@ -1212,6 +1266,8 @@ modules = {
1212
1266
  checkQueryTotal,
1213
1267
  getCellValue,
1214
1268
  createParams,
1269
+ getTableStateValue,
1270
+ setTableState,
1215
1271
  };
1216
1272
 
1217
1273
  if (!configUtil.Vue.prototype.$vxeTableUtil)