n20-common-lib 3.0.22 → 3.0.23

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 (38) hide show
  1. package/package.json +4 -3
  2. package/src/assets/css/drag-list.scss +22 -14
  3. package/src/assets/css/normalize.scss +6 -0
  4. package/src/assets/css/show-column.scss +72 -14
  5. package/src/assets/css/table copy.scss +234 -0
  6. package/src/assets/css/table.scss +159 -13
  7. package/src/assets/realUrl.js +2 -1
  8. package/src/components/AdvancedFilter/index.vue +1 -1
  9. package/src/components/ApprovalButtons/showOtherAttrNew.vue +1 -1
  10. package/src/components/ApprovalRecord/index.vue +5 -5
  11. package/src/components/DragList/index.vue +33 -12
  12. package/src/components/Empty/img/searchNoData.png +0 -0
  13. package/src/components/HandlingAdvice/index.vue +1 -0
  14. package/src/components/ShowColumn/index copy.vue +18 -33
  15. package/src/components/ShowColumn/index.vue +244 -59
  16. package/src/components/TablePro/index copy.vue +462 -0
  17. package/src/components/TablePro/index.js +9 -2
  18. package/src/components/TablePro/index.vue +542 -28
  19. package/src/components/TableSetSize/index copy.vue +69 -0
  20. package/src/components/TableSetSize/index.vue +10 -13
  21. package/src/plugins/Print/print-js/src/js/print.js +0 -6
  22. package/theme/blue.css +3 -0
  23. package/theme/cctcRed.css +3 -0
  24. package/theme/fonts/SIMSUN.5e0c362c.ttf +0 -0
  25. package/theme/fonts/element-icons.535877f5.woff +0 -0
  26. package/theme/fonts/element-icons.732389de.ttf +0 -0
  27. package/theme/fonts/iconfont.09d221ee.woff +0 -0
  28. package/theme/fonts/iconfont.1c4bfacc.ttf +0 -0
  29. package/theme/fonts/iconfont.a6f34dc7.woff2 +0 -0
  30. package/theme/fonts/iconfont.f4c32765.ttf +0 -0
  31. package/theme/green.css +3 -0
  32. package/theme/lightBlue.css +3 -0
  33. package/theme/mapleLeafRed.css +3 -0
  34. package/theme/orange.css +3 -0
  35. package/theme/purple.css +3 -0
  36. package/theme/red.css +3 -0
  37. package/theme/yellow.css +3 -0
  38. package/src/components/ShowColumn/index copy 2.vue +0 -545
@@ -4,23 +4,34 @@
4
4
  :animation="200"
5
5
  :group="group"
6
6
  :disabled="disabled"
7
- :handle="'.n20-icon-tuodong'"
7
+ :handle="'.icon-drag'"
8
8
  @change="change"
9
9
  >
10
- <div v-for="(item, index) in list" :key="index" class="n20-drag-list-item">
11
- <i class="n20-drag-icon n20-icon-tuodong"></i>
10
+ <div
11
+ v-for="(item, index) in list"
12
+ :key="index"
13
+ class="n20-drag-list-item"
14
+ @mouseenter="hoverIndex = index"
15
+ @mouseleave="hoverIndex = -1"
16
+ >
17
+ <i class="iconfont icon-drag f-s-b pointer m-r-s"></i>
12
18
  <slot :item="item" :index="index">
13
- <span
14
- v-hover-tooltip:158="item[labelKey] || item"
15
- class="text-ellipsis pointer color-primary"
16
- @click="$emit('click', item)"
17
- >{{ item[labelKey] || item }}</span
18
- >
19
+ <span v-hover-tooltip:158="item[labelKey] || item" class="drag-item-text" @click="$emit('click', item)">{{
20
+ item[labelKey] || item
21
+ }}</span>
19
22
  </slot>
20
- <el-link
23
+ <!-- hover 时显示锁定图标,点击将该项固定到 fixedColumns -->
24
+ <i
25
+ v-if="inSC && !disabled && !hideDelete"
26
+ v-show="hoverIndex === index"
27
+ class="iconfont icon-unlock icon-class"
28
+ :disabled="item.checked"
29
+ @click="lock(index)"
30
+ />
31
+ <i
32
+ v-show="hoverIndex === index"
21
33
  v-if="!disabled && !hideDelete"
22
- class="n20-icon-shanchu"
23
- :underline="false"
34
+ class="iconfont icon-delete icon-class"
24
35
  :disabled="inSC && item.checked"
25
36
  @click="remove(index)"
26
37
  />
@@ -57,6 +68,11 @@ export default {
57
68
  default: 'label'
58
69
  }
59
70
  },
71
+ data() {
72
+ return {
73
+ hoverIndex: -1
74
+ }
75
+ },
60
76
  computed: {
61
77
  inSC() {
62
78
  return !!this.$attrs['in-show-column']
@@ -66,6 +82,11 @@ export default {
66
82
  change() {
67
83
  this.$emit('change', this.list)
68
84
  },
85
+ lock(index) {
86
+ const item = this.list[index]
87
+ if (item.checked) return
88
+ this.$emit('lock', { index, item })
89
+ },
69
90
  remove(index) {
70
91
  let item = this.list[index]
71
92
  if (this.$listeners.remove) {
@@ -8,6 +8,7 @@
8
8
  @closed="$emit('closed')"
9
9
  @open="$emit('open')"
10
10
  @opened="$emit('opened')"
11
+ :close-on-click-modal="false"
11
12
  >
12
13
  <el-form v-if="whether" style="margin-bottom: 50px">
13
14
  <el-form-item>
@@ -280,7 +280,12 @@ export default {
280
280
  }
281
281
  },
282
282
  setState() {
283
- return this.columnsAs.length && this.columnsAs.length === this.dragListN.length
283
+ const columnsAs = []
284
+ forEachs(this.columnsAs, (item) => {
285
+ columnsAs.push(item)
286
+ })
287
+ return columnsAs.length && columnsAs.length === this.dragListN.length
288
+ // return this.columnsAs.length && this.columnsAs.length === this.dragListN.length
284
289
  },
285
290
  columnsAs: {
286
291
  get() {
@@ -289,6 +294,9 @@ export default {
289
294
  set(val) {
290
295
  return val
291
296
  }
297
+ },
298
+ columnsN() {
299
+ return this.columns || []
292
300
  }
293
301
  },
294
302
  watch: {
@@ -373,8 +381,7 @@ export default {
373
381
  this.configVisible = false
374
382
  },
375
383
  popOpen() {
376
- // 深拷贝一下,防止修改
377
- this.dragList = JSON.parse(JSON.stringify(this.checkColumns)).filter((col) => !col.static)
384
+ this.dragList = this.checkColumns.filter((col) => !col.static)
378
385
  },
379
386
  setAll() {
380
387
  if (this.setState) {
@@ -425,30 +432,27 @@ export default {
425
432
  // 自动保存设置的显示列
426
433
  this.userNo = sessionStorage.getItem('userNo')
427
434
  !this.isExport && this.autoSave && this.saveColumns(list)
435
+
436
+ this.$emit('setColumns', list)
428
437
  if (this.isExport) {
429
438
  this.visible = false
430
- this.$emit('setColumns', list)
431
439
  }
432
440
  },
433
441
  saveColumns(list) {
434
442
  let columns = saveTransform(list, this.labelKey, this.isFilter)
435
443
  axios.post(
436
- '/bems/prod_1.0/user/pageHabit',
444
+ `/bems/prod_1.0/user/pageHabit?t=${Math.random()}`,
437
445
  {
438
446
  userNo: this.userNo,
439
447
  pageId: this.pageId,
440
448
  showStructure: JSON.stringify(columns)
441
449
  },
442
450
  { loading: false }
443
- ).then(() => {
444
- this.getColumns(this.pageId).then(list => {
445
- this.visible = false
446
- this.$emit('setColumns', list)
447
- })
448
- })
451
+ )
452
+ this.visible = false
449
453
  },
450
454
  getColumns(pageId) {
451
- return getColumns(pageId || this.pageId, this.userNo, this.columns, this.labelKey)
455
+ return getColumns(pageId || this.pageId, this.userNo, this.columnsN, this.labelKey)
452
456
  }
453
457
  }
454
458
  }
@@ -459,14 +463,12 @@ function saveTransform(list, labelKey, isFilter) {
459
463
  list.forEach((c) => {
460
464
  if (c.prop && !c.children && !c.isNew && !c.width & !c.isNew) {
461
465
  listN.push({ _colKey: 'prop', _colVal: c.prop })
462
- } else if (c.slotName) {
463
- listN.push({ _colKey: 'slotName', _colVal: c.slotName })
464
466
  } else if (c.type && ['selection', 'index', 'expand'].includes(c.type)) {
465
467
  listN.push({ _colKey: 'type', _colVal: c.type })
466
468
  } else {
467
469
  let sFn = false
468
470
  for (let k in c) {
469
- // if (typeof c[k] === 'function') sFn = true
471
+ if (typeof c[k] === 'function') sFn = true
470
472
  }
471
473
  if (sFn && c[labelKey]) {
472
474
  listN.push({ _colKey: labelKey, _colVal: c[labelKey] })
@@ -483,8 +485,6 @@ function saveTransform(list, labelKey, isFilter) {
483
485
  listN.push({ _colKey: 'startValue', _colVal: c.startValue })
484
486
  } else if (c.startDate) {
485
487
  listN.push({ _colKey: 'startDate', _colVal: c.startDate })
486
- } else if (c.slotName) {
487
- listN.push({ _colKey: 'slotName', _colVal: c.slotName })
488
488
  } else {
489
489
  listN.push(c)
490
490
  }
@@ -495,7 +495,6 @@ function saveTransform(list, labelKey, isFilter) {
495
495
 
496
496
  function getTransform(list, columnsT, labelKey = 'label') {
497
497
  let columns = []
498
-
499
498
  list.forEach((d) => {
500
499
  // 如果list中的每一项是字符串
501
500
  if (typeof d === 'string') {
@@ -505,16 +504,6 @@ function getTransform(list, columnsT, labelKey = 'label') {
505
504
  column && columns.push(column)
506
505
  // 如果list中的每一项是对象
507
506
  } else if (typeof d === 'object') {
508
- if (d.children) {
509
- d.children.forEach((item, index) => {
510
- let column = columnsT.find((c) => c.prop === d.children[index].prop)
511
- // 如果找到,则将其添加到columns中
512
- if (column.formatter) {
513
- d.children[index].formatter = column.formatter
514
- }
515
- })
516
- columns.push(d)
517
- } else {
518
507
  // 如果d中有_colKey属性
519
508
  if (d._colKey) {
520
509
  // 从columnsT中找到d._colKey等于d._colVal的项
@@ -523,15 +512,11 @@ function getTransform(list, columnsT, labelKey = 'label') {
523
512
  column && columns.push(column)
524
513
  // 如果d中没有_colKey属性
525
514
  } else {
526
- let column = columnsT.find((c) => c.prop === d.prop)
527
- d.formatter = column.formatter
528
515
  // 将d添加到columns中
529
516
  columns.push(d)
530
- }
531
517
  }
532
518
  }
533
519
  })
534
- console.log(columns)
535
520
  // 返回columns
536
521
  return columns
537
522
  }
@@ -541,7 +526,7 @@ export function getColumns(pageId, userNo, columnsT, labelKey = 'label') {
541
526
  return new Promise((resolve, reject) => {
542
527
  axios
543
528
  .post(
544
- '/bems/prod_1.0/user/pageHabit/list',
529
+ `/bems/prod_1.0/user/pageHabit/list?t=${Math.random()}`,
545
530
  {
546
531
  userNo: userNo,
547
532
  pageId: pageId
@@ -2,7 +2,7 @@
2
2
  <dialog-wrap
3
3
  ref="dialog"
4
4
  v-drag
5
- class="p-t-0"
5
+ class="p-a-0"
6
6
  v-bind="$attrs"
7
7
  :visible.sync="visible"
8
8
  :title="title"
@@ -12,26 +12,32 @@
12
12
  >
13
13
  <div class="dialog-view">
14
14
  <div class="flex-box">
15
- <div class="left-c flex-column p-t-m bd-r">
16
- <div class="flex-box flex-v p-r m-b">
17
- <span>{{ header }}</span>
18
- <span class="m-l-m color-999">
19
- {{ '已选' | $lc }}
20
- <span class="color-main">{{ dragList.length }}</span>
21
- </span>
22
- <el-link :underline="false" type="primary" class="m-l-auto" @click="setAll">{{
23
- setState ? $lc('全部清空') : $lc('全部选中')
24
- }}</el-link>
15
+ <div class="left-c">
16
+ <div>
17
+ <el-input
18
+ v-model="searchKeyword"
19
+ class="dialog-view-search"
20
+ :placeholder="$lc('搜索')"
21
+ suffix-icon="el-icon-search"
22
+ clearable
23
+ ></el-input>
24
+
25
+ <div class="m-t-m">
26
+ <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="setAll">{{
27
+ $lc('全部')
28
+ }}</el-checkbox>
29
+ </div>
25
30
  </div>
26
31
  <div class="flex-item p-r" style="height: 50%; overflow: auto">
27
- <el-checkbox-group :value="dragListN.map((d) => d[labelKey])">
32
+ <!-- :value 需包含 static 列的 label,使其显示为选中状态 -->
33
+ <el-checkbox-group :value="checkedLabelValues" @change="handleCheckedChange">
28
34
  <template v-if="!columnsGroups">
29
35
  <el-checkbox
30
- v-for="(column, i) in columnsAs"
36
+ v-for="(column, i) in filteredColumnsAs"
31
37
  :key="i"
32
38
  v-hover-tooltip="column[labelKey]"
33
39
  :label="column[labelKey]"
34
- :disabled="column.checked"
40
+ :disabled="column.checked || !!column.static"
35
41
  class="m-t"
36
42
  @change="(val) => checkChange(val, column)"
37
43
  >{{ column[labelKey] }}</el-checkbox
@@ -40,13 +46,13 @@
40
46
  <template v-else>
41
47
  <div v-for="gp in columnsGroups" :key="gp.groupId" class="m-b">
42
48
  <div class="f-s-b font-w600">{{ gp.groupName }}</div>
43
- <template v-for="(column, i) in columnsAs">
49
+ <template v-for="(column, i) in filteredColumnsAs">
44
50
  <el-checkbox
45
51
  v-if="column.groupId === gp.groupId"
46
52
  :key="i"
47
53
  v-hover-tooltip="column[labelKey]"
48
54
  :label="column[labelKey]"
49
- :disabled="column.checked"
55
+ :disabled="column.checked || !!column.static"
50
56
  class="m-t"
51
57
  @change="(val) => checkChange(val, column)"
52
58
  >{{ column[labelKey] }}</el-checkbox
@@ -57,13 +63,68 @@
57
63
  </el-checkbox-group>
58
64
  </div>
59
65
  </div>
60
- <div v-if="!hasPX" class="right-c flex-column p-t-m">
61
- <div class="m-b">
62
- {{ '当前选定项' | $lc }}
63
- <el-link type="primary" style="visibility: hidden">{{ '当前选定项' | $lc }}</el-link>
66
+ <div v-if="!hasPX" class="right-c">
67
+ <div class="right-header m-b-s">
68
+ <div>
69
+ {{ '当前选定项' | $lc }}
70
+ <span class="right-count"> ({{ rightTotalCount }}) </span>
71
+ </div>
72
+ <i class="iconfont icon-delete pointer icon-class" @click="clearAll"></i>
64
73
  </div>
65
- <div class="flex-1 overflow-y">
66
- <drag-list :list="dragList" :label-key="labelKey" :in-show-column="true" />
74
+ <div class="overflow-y w-100p darg-list-wrap">
75
+ <!-- 纯静态列(static=true),不可拖拽,无删除 -->
76
+ <div v-for="(item, index) in pureStaticColumns" :key="'ps-' + index" class="n20-drag-list-item">
77
+ <i class="iconfont icon-lock f-s-b m-r-s"></i>
78
+ <span v-hover-tooltip:158="item[labelKey] || item" class="drag-item-text">{{
79
+ item[labelKey] || item
80
+ }}</span>
81
+ </div>
82
+ <!-- 固定列(fixed=true),可拖拽排序,可解锁,可删除 -->
83
+ <template v-if="fixedColumns.length > 0">
84
+ <vue-draggable
85
+ :list="fixedColumns"
86
+ :animation="200"
87
+ group="fixedBox"
88
+ handle=".icon-drag"
89
+ @change="onFixedDragChange"
90
+ >
91
+ <div
92
+ v-for="(item, index) in fixedColumns"
93
+ :key="'fx-' + index"
94
+ class="n20-drag-list-item"
95
+ @mouseenter="fixedHoverIndex = index"
96
+ @mouseleave="fixedHoverIndex = -1"
97
+ >
98
+ <i class="iconfont icon-drag f-s-b pointer m-r-s"></i>
99
+ <span v-hover-tooltip:158="item[labelKey] || item" class="drag-item-text flex-item">{{
100
+ item[labelKey] || item
101
+ }}</span>
102
+ <!-- hover 时显示解锁图标,点击将该项移回 dragList -->
103
+ <i
104
+ v-show="fixedHoverIndex === index"
105
+ class="iconfont icon-unlock icon-class m-r-s"
106
+ @click="unlockFixed(item, index)"
107
+ />
108
+ <i
109
+ v-show="fixedHoverIndex === index"
110
+ class="iconfont icon-delete icon-class"
111
+ @click="removeFixed(item)"
112
+ />
113
+ </div>
114
+ </vue-draggable>
115
+ </template>
116
+ <!-- 分隔线 -->
117
+ <div class="fixed-divider">
118
+ <span class="fixed-divider-text">{{ '以上为已固定列' | $lc }}</span>
119
+ </div>
120
+ <!-- 可拖拽列 -->
121
+ <drag-list
122
+ :list="dragList"
123
+ :label-key="labelKey"
124
+ :in-show-column="true"
125
+ @change="onDragChange"
126
+ @lock="onDragLock"
127
+ />
67
128
  </div>
68
129
  </div>
69
130
  <div v-else class="right-tree flex-column p-t-m">
@@ -88,7 +149,7 @@
88
149
  >
89
150
  <span slot-scope="{ node, data }" class="menu-item flex-item flex-box flex-lr flex-v">
90
151
  <span>
91
- <i class="n20-drag-icon n20-icon-tuodong"></i>
152
+ <i class="iconfont icon-drag pointer"></i>
92
153
  <span
93
154
  :class="data.isNew ? 'color-success' : 'color-primary'"
94
155
  class="text-ellipsis pointer"
@@ -165,9 +226,12 @@
165
226
  <el-button type="primary" @click="configSaveN">{{ '确定' | $lc }}</el-button>
166
227
  </div>
167
228
  </dialogWrap>
168
- <div slot="footer" class="text-c">
169
- <el-button type="primary" @click="setChange">{{ '确定' | $lc }}</el-button>
229
+ <div slot="footer" class="flex-box flex-lr">
170
230
  <el-button plain @click="reset">{{ '恢复默认' | $lc }}</el-button>
231
+ <div>
232
+ <el-button type="primary" plain @click="setChange">{{ '取消' | $lc }}</el-button>
233
+ <el-button type="primary" @click="setChange">{{ '确定' | $lc }}</el-button>
234
+ </div>
171
235
  </div>
172
236
  </dialog-wrap>
173
237
  </template>
@@ -178,11 +242,16 @@ import { $lc } from '../../utils/i18n/index'
178
242
 
179
243
  import { Message } from 'element-ui'
180
244
  import forEachs from '../../utils/forEachs'
245
+ import importG from '../../utils/importGlobal.js'
181
246
  import dialogWrap from '../Dialog/index.vue'
182
247
  import dragList from '../DragList/index.vue'
183
248
  export default {
184
249
  name: 'ShowColumn',
185
- components: { dialogWrap, dragList },
250
+ components: {
251
+ dialogWrap,
252
+ dragList,
253
+ vueDraggable: () => importG('vuedraggable', () => import(/*webpackChunkName: "vuedraggable"*/ 'vuedraggable'))
254
+ },
186
255
  inheritAttrs: false,
187
256
  props: {
188
257
  dialogVisible: {
@@ -233,6 +302,9 @@ export default {
233
302
  data() {
234
303
  return {
235
304
  dragList: [],
305
+ fixedColumns: [], // fixed属性的列(固定但可删除)
306
+ fixedHoverIndex: -1, // 固定列区域当前 hover 的项索引
307
+ searchKeyword: '', // 左侧搜索关键词
236
308
  configVisible: false,
237
309
  enabled: false,
238
310
  configModel: {
@@ -247,9 +319,12 @@ export default {
247
319
  isNew: true,
248
320
  children: []
249
321
  },
322
+ staticColumn: [], // 静态列
250
323
  userNo: sessionStorage.getItem('userNo'),
251
324
  configVisibleN: false,
252
- dragListN: []
325
+ dragListN: [],
326
+ isIndeterminate: false,
327
+ checkAll: false
253
328
  }
254
329
  },
255
330
  computed: {
@@ -280,21 +355,50 @@ export default {
280
355
  }
281
356
  },
282
357
  setState() {
283
- const columnsAs = []
284
- forEachs(this.columnsAs, (item) => {
285
- columnsAs.push(item)
286
- })
287
- return columnsAs.length && columnsAs.length === this.dragListN.length
288
- // return this.columnsAs.length && this.columnsAs.length === this.dragListN.length
358
+ // 只用非 static 的可操作列判断全选状态,static 列不参与全选计算
359
+ const operableCols = this.columnsAs.filter((col) => !col.static)
360
+ return operableCols.length > 0 && operableCols.length === this.dragListN.length
361
+ },
362
+ // 纯静态列(static===true,即非 'pre'/'next' 的固定占位列,且非 fixed 可删列)
363
+ // checkColumns(已选中列)中读取,在右侧顶部固定展示,不可删除不可拖拽
364
+ // static='pre'/'next' 的列在 setChange 中单独拼接到首尾,不在右侧展示
365
+ pureStaticColumns() {
366
+ return this.checkColumns.filter((col) => col.static && col.type !== 'checkbox' && !col.fixed)
367
+ },
368
+ // 右侧总数
369
+ rightTotalCount() {
370
+ return this.pureStaticColumns.length + this.fixedColumns.length + this.dragList.length
289
371
  },
372
+ // 左侧可选列:
373
+ // 1. 优先排除 type=checkbox/selection 的纯工具列(无论是否有 static)
374
+ // 3. 保留其余所有列:static 列(禁用已勾选)和普通可操作列
290
375
  columnsAs: {
291
376
  get() {
292
- return this.columns.filter((col) => !col.static)
377
+ return this.columns.filter((col) => {
378
+ // 优先排除 type=checkbox/selection
379
+ if (col.type === 'checkbox' || col.type === 'selection') return false
380
+ return true
381
+ })
293
382
  },
294
383
  set(val) {
295
384
  return val
296
385
  }
297
386
  },
387
+ // 搜索过滤后的左侧列表,支持中英文实时过滤
388
+ filteredColumnsAs() {
389
+ const kw = (this.searchKeyword || '').trim().toLowerCase()
390
+ if (!kw) return this.columnsAs
391
+ return this.columnsAs.filter((col) => {
392
+ const label = (col[this.labelKey] || '').toLowerCase()
393
+ return label.includes(kw)
394
+ })
395
+ },
396
+ // checkbox-group 的已选中列表:包含当前选中的普通列 + 所有 static 列(默认选中且禁用)
397
+ checkedLabelValues() {
398
+ const selectedLabels = this.dragListN.map((d) => d[this.labelKey])
399
+ const staticLabels = this.columnsAs.filter((col) => col.static).map((col) => col[this.labelKey])
400
+ return [...new Set([...selectedLabels, ...staticLabels])]
401
+ },
298
402
  columnsN() {
299
403
  return this.columns || []
300
404
  }
@@ -302,26 +406,48 @@ export default {
302
406
  watch: {
303
407
  dragList: {
304
408
  handler() {
305
- let arr = []
306
- forEachs(this.dragList, (item) => {
307
- arr.push(item)
308
- })
309
- this.dragListN = arr
310
- /* const newArr = arr.filter((item) => {
311
- return item.isNew
312
- })
313
- newArr.forEach((item) => {
314
- const index = this.columns.findIndex((col) => col.prop === item.prop || col.label === item.label)
315
- if (index === -1) {
316
- this.columns.push(item)
317
- }
318
- }) */
409
+ this._syncDragListN()
319
410
  },
320
411
  immediate: true,
321
412
  deep: true
413
+ },
414
+ fixedColumns: {
415
+ handler() {
416
+ this._syncDragListN()
417
+ },
418
+ deep: true
322
419
  }
323
420
  },
324
421
  methods: {
422
+ _syncDragListN() {
423
+ let arr = []
424
+ forEachs(this.fixedColumns, (item) => {
425
+ arr.push(item)
426
+ })
427
+ forEachs(this.dragList, (item) => {
428
+ arr.push(item)
429
+ })
430
+ this.dragListN = arr
431
+ // 同步更新全选状态
432
+ this._syncCheckAllState()
433
+ },
434
+ _syncCheckAllState() {
435
+ // 只计算非 static 的可操作列数量,static 列禁用且默认选中,不参与全选状态计算
436
+ const operableCols = this.columnsAs.filter((col) => !col.static)
437
+ const total = operableCols.length
438
+ const checkedCount = this.dragListN.length
439
+ if (total === 0) {
440
+ this.checkAll = false
441
+ this.isIndeterminate = false
442
+ } else {
443
+ this.checkAll = checkedCount >= total
444
+ this.isIndeterminate = checkedCount > 0 && checkedCount < total
445
+ }
446
+ },
447
+ handleCheckedChange() {
448
+ // dragListN 由 watch 异步同步,此处不需要额外处理
449
+ // 全选状态由 _syncDragListN 结尾的 _syncCheckAllState 继序保证
450
+ },
325
451
  validator(rule, value, callback) {
326
452
  if (value) {
327
453
  if (value > 300) {
@@ -381,31 +507,90 @@ export default {
381
507
  this.configVisible = false
382
508
  },
383
509
  popOpen() {
384
- this.dragList = this.checkColumns.filter((col) => !col.static)
510
+ // 每次开启弹窗重置搜索词
511
+ this.searchKeyword = ''
512
+ // static='pre'/'next' 是列表首尾占位列,在 setChange 中单独拼接,不进 data
513
+ // static===true 且带 fixed 的列需要进 fixedColumns;其他列进 dragList
514
+ const checked = this.checkColumns.filter((col) => col.static !== 'pre' && col.static !== 'next')
515
+ this.fixedColumns = checked.filter((col) => col.fixed)
516
+ this.dragList = checked.filter((col) => !col.fixed && !col.static)
385
517
  },
386
- setAll() {
387
- if (this.setState) {
388
- this.dragList = this.dragList.filter((c) => c.checked)
518
+ setAll(val) {
519
+ if (val) {
520
+ // 点击全选:只操作非 static 的可操作列
521
+ const operableCols = this.columnsAs.filter((c) => !c.static)
522
+ this.fixedColumns = operableCols.filter((c) => c.fixed)
523
+ this.dragList = operableCols.filter((c) => !c.fixed)
389
524
  } else {
390
- this.dragList = [...this.columnsAs]
525
+ // 点击反选:清空所有非锁定项(保留 checked=true 的常亮锁定项)
526
+ this.fixedColumns = this.fixedColumns.filter((c) => c.checked)
527
+ this.dragList = this.dragList.filter((c) => c.checked)
391
528
  }
529
+ // 手动同步确保当前 tick 内 dragListN 和全选状态就绪
530
+ this._syncDragListN()
392
531
  },
393
532
  checkChange(val, column) {
394
533
  if (val === false) {
534
+ // 从 fixedColumns 中移除
535
+ let fixedIdx = this.fixedColumns.findIndex((d) => d[this.labelKey] === column[this.labelKey])
536
+ if (fixedIdx !== -1) {
537
+ this.fixedColumns.splice(fixedIdx, 1)
538
+ return
539
+ }
540
+ // 从 dragList 中移除
395
541
  let index = this.dragList.findIndex((d) => d[this.labelKey] === column[this.labelKey])
396
542
  index !== -1 && this.dragList.splice(index, 1)
397
543
  } else {
544
+ // 检查是否已在 dragListN(同步列表)中
398
545
  let index = this.dragListN.findIndex((d) => d[this.labelKey] === column[this.labelKey])
399
546
  if (index !== -1) {
400
547
  Message.warning($lc(`子级请在右侧删除!`))
401
548
  return false
402
549
  }
403
- this.dragList.push(column)
550
+ if (column.fixed) {
551
+ this.fixedColumns.push(column)
552
+ } else {
553
+ this.dragList.push(column)
554
+ }
555
+ }
556
+ },
557
+ removeFixed(item) {
558
+ let index = this.fixedColumns.findIndex((d) => d[this.labelKey] === item[this.labelKey])
559
+ if (index !== -1) {
560
+ this.fixedColumns.splice(index, 1)
404
561
  }
405
562
  },
563
+ unlockFixed(item, index) {
564
+ // 移除 fixed 属性,将该项从 fixedColumns 移回 dragList
565
+ const target = Object.assign({}, item, { fixed: false })
566
+ delete target.fixed
567
+ this.dragList.push(target)
568
+ this.fixedColumns.splice(index, 1)
569
+ this.fixedHoverIndex = -1
570
+ },
571
+ clearAll() {
572
+ this.fixedColumns = this.fixedColumns.filter((c) => c.checked)
573
+ this.dragList = this.dragList.filter((c) => c.checked)
574
+ },
575
+ onDragChange(list) {
576
+ this.dragList = list
577
+ },
578
+ onFixedDragChange() {
579
+ // vue-draggable 直接操作 fixedColumns 引用内容,触发 watch 同步 dragListN
580
+ this._syncDragListN()
581
+ },
582
+ onDragLock({ index, item }) {
583
+ // 将该项 fixed 设为 'left',移入 fixedColumns,从 dragList 移除
584
+ const target = Object.assign({}, item, { fixed: 'left' })
585
+ this.fixedColumns.push(target)
586
+ this.dragList.splice(index, 1)
587
+ },
406
588
  reset() {
407
- let dragList = this.columns.filter((col) => col.isDefault)
408
- this.dragList = dragList.length ? dragList : this.checkColumns.filter((col) => !col.static)
589
+ const baseCols = this.columns.length
590
+ ? this.columns
591
+ : this.checkColumns.filter((col) => col.static !== 'pre' && col.static !== 'next')
592
+ this.fixedColumns = baseCols.filter((col) => col.fixed)
593
+ this.dragList = baseCols.filter((col) => !col.fixed && !col.static)
409
594
  },
410
595
  setChange() {
411
596
  if (this.dragList.length < 1) {
@@ -420,7 +605,7 @@ export default {
420
605
  let list = []
421
606
  let preCols = this.columns.filter((col) => col.static === 'pre')
422
607
  let nextCols = this.columns.filter((col) => col.static === 'next')
423
- list.push(...preCols, ...this.dragList, ...nextCols)
608
+ list.push(...preCols, ...this.fixedColumns, ...this.dragList, ...nextCols)
424
609
  // 新增校验
425
610
  if (!this.isExport) {
426
611
  let state = list.findIndex((c) => c.isNew && c.children && c.children.length === 0)
@@ -441,7 +626,7 @@ export default {
441
626
  saveColumns(list) {
442
627
  let columns = saveTransform(list, this.labelKey, this.isFilter)
443
628
  axios.post(
444
- '/bems/prod_1.0/user/pageHabit',
629
+ `/bems/prod_1.0/user/pageHabit?t=${Math.random()}`,
445
630
  {
446
631
  userNo: this.userNo,
447
632
  pageId: this.pageId,
@@ -526,7 +711,7 @@ export function getColumns(pageId, userNo, columnsT, labelKey = 'label') {
526
711
  return new Promise((resolve, reject) => {
527
712
  axios
528
713
  .post(
529
- '/bems/prod_1.0/user/pageHabit/list',
714
+ `/bems/prod_1.0/user/pageHabit/list?t=${Math.random()}`,
530
715
  {
531
716
  userNo: userNo,
532
717
  pageId: pageId