n20-common-lib 3.0.99 → 3.1.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n20-common-lib",
3
- "version": "3.0.99",
3
+ "version": "3.1.1",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -95,21 +95,22 @@
95
95
  <div slot="prefix">
96
96
  <slot name="prefix"></slot>
97
97
  </div>
98
- <template v-for="filter in slotFiltersWithValue" #[filter.slotName]="{ model }">
98
+ <template v-for="filter in slotFilters" #[filter.slotName]="{ model }">
99
+ <!-- 有 value 的 slot:传递单个值及 input 回调 -->
99
100
  <slot
101
+ v-if="filter.value"
100
102
  :name="filter.slotName"
101
103
  :model="model"
102
104
  :value="searchValue[filter.value]"
103
105
  :input="(val) => handleSlotInput(filter.value, val)"
104
106
  ></slot>
105
- </template>
106
- <!-- 无 value 的 slot(如 startDate/endDate 多值绑定),传递 searchValue 让父组件自行管理 -->
107
- <template v-for="filter in slotFiltersWithoutValue" #[filter.slotName]="{ model }">
107
+ <!-- 无 value 的 slot(如 startDate/endDate 多值绑定),传递 searchValue 让父组件自行管理 -->
108
108
  <slot
109
+ v-else
109
110
  :name="filter.slotName"
110
111
  :model="model"
111
112
  :search-value="searchValue"
112
- :update-search-value="updateSearchValue"
113
+ :update-search-value="(updates) => Object.assign(searchValue, updates)"
113
114
  ></slot>
114
115
  </template>
115
116
  <div slot="suffix">
@@ -152,17 +153,18 @@
152
153
  :check-ids="form.keyIds"
153
154
  @saveCheckData="saveCheckData"
154
155
  >
155
- <template v-for="filter in slotFiltersWithValue" #[filter.slotName]="{ model }">
156
+ <template v-for="filter in slotFilters" #[filter.slotName]="{ model }">
157
+ <!-- 有 value 的 slot:传递单个值及 input 回调 -->
156
158
  <slot
159
+ v-if="filter.value"
157
160
  :name="filter.slotName"
158
161
  :model="model"
159
162
  :value="searchForm[filter.value]"
160
163
  :input="(val) => (searchForm[filter.value] = val)"
161
164
  ></slot>
162
- </template>
163
- <!-- 无 value 的 slot(如 startDate/endDate 多值绑定),传递 searchForm 让父组件自行管理 -->
164
- <template v-for="filter in slotFiltersWithoutValue" #[filter.slotName]="{ model }">
165
+ <!-- 无 value 的 slot(如 startDate/endDate 多值绑定),传递 searchForm 让父组件自行管理 -->
165
166
  <slot
167
+ v-else
166
168
  :name="filter.slotName"
167
169
  :model="model"
168
170
  :search-value="searchForm"
@@ -178,18 +180,19 @@
178
180
  :filter-id="filterId"
179
181
  :buss-id="bussId"
180
182
  >
181
- <template v-for="filter in slotFiltersWithValue" #[filter.slotName]="{ model, value, input, disabled }">
183
+ <template v-for="filter in slotFilters" #[filter.slotName]="{ model, value, input, disabled }">
184
+ <!-- 有 value 的 slot:传递单个值及 input 回调 -->
182
185
  <slot
186
+ v-if="filter.value"
183
187
  :name="filter.slotName"
184
188
  :model="model"
185
189
  :value="searchForm[filter.value]"
186
190
  :input="(val) => (searchForm[filter.value] = val)"
187
191
  :disabled="disabled"
188
192
  ></slot>
189
- </template>
190
- <!-- 无 value 的 slot(如 startDate/endDate 多值绑定),传递 searchForm 让父组件自行管理 -->
191
- <template v-for="filter in slotFiltersWithoutValue" #[filter.slotName]="{ model, value, input, disabled }">
193
+ <!-- 无 value 的 slot(如 startDate/endDate 多值绑定),传递 searchForm 让父组件自行管理 -->
192
194
  <slot
195
+ v-else
193
196
  :name="filter.slotName"
194
197
  :model="model"
195
198
  :search-value="searchForm"
@@ -292,14 +295,7 @@ export default {
292
295
  slotFilters() {
293
296
  return this.filterList.filter((item) => item.type === 'slot' && this.$scopedSlots[item.slotName])
294
297
  },
295
- // 筛选出有 value 字段的 slot 类型筛选项(用于 searchValue 初始化和值传递)
296
- slotFiltersWithValue() {
297
- return this.slotFilters.filter((item) => item.value)
298
- },
299
- // 筛选出无 value 字段的 slot 类型筛选项(如 startDate/endDate 多值绑定)
300
- slotFiltersWithoutValue() {
301
- return this.slotFilters.filter((item) => !item.value)
302
- },
298
+
303
299
  getInitialSearchValue() {
304
300
  const obj = {}
305
301
  // 遍历 filterList,为每个 type 为 slot 且有 value 字段的项初始化值
@@ -366,10 +362,6 @@ export default {
366
362
  this.searchValue = { ...this.getInitialSearchValue, ...this.initialValue }
367
363
  },
368
364
  methods: {
369
- updateSearchValue(updates) {
370
- console.log(updates, 'updates')
371
- Object.assign(searchValue, updates)
372
- },
373
365
  // 处理 slot 类型字段的输入事件,同时更新 searchValue 和 initialValue
374
366
  handleSlotInput(fieldName, val) {
375
367
  // 防御性检查:如果 fieldName 无效,不执行任何操作
@@ -28,7 +28,7 @@
28
28
  }}</el-checkbox>
29
29
  </div>
30
30
  </div>
31
- <div class="flex-item p-r" style="height: 50%; overflow: auto">
31
+ <div class="flex-item p-r" style="height: 80%; overflow: auto">
32
32
  <!-- :value 需包含 static 列的 label,使其显示为选中状态 -->
33
33
  <el-checkbox-group :value="checkedLabelValues" @change="handleCheckedChange">
34
34
  <template v-if="!columnsGroups">
@@ -587,7 +587,7 @@ export default {
587
587
  },
588
588
  reset() {
589
589
  const baseCols = this.columns.length
590
- ? this.columns
590
+ ? this.columns.filter((col) => !col.defaultHidden)
591
591
  : this.checkColumns.filter((col) => col.static !== 'pre' && col.static !== 'next')
592
592
  this.fixedColumns = baseCols.filter((col) => col.fixed)
593
593
  this.dragList = baseCols.filter((col) => !col.fixed && !col.static)
@@ -642,14 +642,16 @@ export default {
642
642
  }
643
643
  }
644
644
 
645
- function saveTransform(list, labelKey, isFilter) {
645
+ export function saveTransform(list, labelKey, isFilter) {
646
646
  let listN = []
647
647
  if (!isFilter) {
648
648
  // 遍历列配置列表,将每列转换为存储格式
649
649
  list.forEach((c) => {
650
650
  // 普通列:有prop属性、无子列、非新增列、无宽度设置
651
651
  if (c.prop && !c.children && !c.isNew && !c.width & !c.isNew) {
652
- listN.push({ _colKey: 'prop', _colVal: c.prop })
652
+ const entry = { _colKey: 'prop', _colVal: c.prop }
653
+ if (c.fixed) entry.fixed = c.fixed
654
+ listN.push(entry)
653
655
  }
654
656
  // 特殊类型列:多选/序号/展开列
655
657
  else if (c.type && ['selection', 'index', 'expand'].includes(c.type)) {
@@ -703,8 +705,15 @@ function getTransform(list, columnsT, labelKey = 'label') {
703
705
  if (d._colKey) {
704
706
  // 从columnsT中找到d._colKey等于d._colVal的项
705
707
  let column = columnsT.find((c) => c[d._colKey] === d._colVal)
706
- // 如果找到,则将其添加到columns中
707
- column && columns.push(column)
708
+ if (column) {
709
+ // 将保存的 fixed、width 合并到列对象上(避免直接修改 props)
710
+ if (d.fixed !== undefined || d.width !== undefined) {
711
+ column = { ...column }
712
+ if (d.fixed !== undefined) column.fixed = d.fixed
713
+ if (d.width !== undefined) column.width = d.width
714
+ }
715
+ columns.push(column)
716
+ }
708
717
  // 如果d中没有_colKey属性
709
718
  } else {
710
719
  // 将d添加到columns中
@@ -302,7 +302,7 @@
302
302
  @resize="sizeSet"
303
303
  @toggle-expand="toggleExpand"
304
304
  @toggle-operate-fixed="handleToggleOperateFixed"
305
- @visible-column="dialogVisible = !dialogVisible"
305
+ @visible-column="handleVisibleColumn"
306
306
  />
307
307
  <!-- 操作列的悬浮按钮组 -->
308
308
  <transition name="hover-btns-fade">
@@ -387,7 +387,9 @@
387
387
  import empty from '../../Empty'
388
388
  import tableOperate from '../../TableOperate/index.vue'
389
389
  import tableShowColumn from '../../ShowColumn/index.vue'
390
+ import { saveTransform } from '../../ShowColumn/index.vue'
390
391
  import OperateBtns from '../../TableProOperateColumn/OperateBtns.vue'
392
+ import axios from '../../../utils/axios'
391
393
 
392
394
  import { $lc } from '../../../utils/i18n/index.js'
393
395
 
@@ -590,7 +592,7 @@ export default {
590
592
  isExpand: false,
591
593
  isExport: false, // 是否导出
592
594
  dialogVisible: false, // 显示列设置对话框
593
- checkColumns: this.columns.slice() // 显示列设置对话框中已选择的列(默认使用 columns prop)
595
+ checkColumns: this.filterDefaultHidden(this.columns) // 显示列设置对话框中已选择的列(默认过滤 defaultHidden 列)
594
596
  }
595
597
  },
596
598
  computed: {
@@ -648,7 +650,7 @@ export default {
648
650
  this.colsKey = this.colsKey + 1
649
651
  // 没有 pageId 时,columns 变更同步更新 checkColumns
650
652
  if (!this.pageId) {
651
- this.checkColumns = this.columns.slice()
653
+ this.checkColumns = this.filterDefaultHidden(this.columns)
652
654
  }
653
655
  },
654
656
  size(val) {
@@ -678,32 +680,87 @@ export default {
678
680
  }
679
681
  },
680
682
  methods: {
683
+ handleVisibleColumn() {
684
+ this.isExport = false
685
+ this.dialogVisible = !this.dialogVisible
686
+ },
681
687
  openExportColumn() {
682
688
  this.dialogVisible = true
683
689
  this.isExport = true
684
690
  },
685
691
  resizableChange({ resizeWidth, columnIndex }) {
686
692
  this.checkColumns[columnIndex].width = resizeWidth
687
- if(this.showColumn && this.pageId) {
688
- this.$refs.showColumn.saveColumns(this.checkColumns)
693
+ if (this.showColumn && this.pageId) {
694
+ this.saveColumns()
689
695
  }
690
696
  },
697
+ // 过滤 defaultHidden 列:仅在用户未设置过显示列时作为 fallback 使用
698
+ filterDefaultHidden(columns) {
699
+ return columns.filter((col) => !col.defaultHidden)
700
+ },
701
+ // 保存列配置到后端(固定列、列宽调整等场景复用)
702
+ saveColumns() {
703
+ const userNo = sessionStorage.getItem('userNo')
704
+ const columns = saveTransform(this.checkColumns, this.labelKey, this.isFilter)
705
+ axios.post(
706
+ `/bems/prod_1.0/user/pageHabit?t=${Math.random()}`,
707
+ {
708
+ userNo,
709
+ pageId: this.pageId,
710
+ showStructure: JSON.stringify(columns)
711
+ },
712
+ { loading: false }
713
+ )
714
+ },
691
715
  setColumns(list) {
692
716
  if (this.isExport) {
693
717
  this.exportFn(list)
718
+ this.isExport = false
694
719
  } else {
695
720
  this.checkColumns = list
696
721
  }
697
722
  },
698
723
  async getColumns() {
699
724
  try {
700
- const columns = await this.$refs.showColumn.getColumns(this.pageId)
701
- this.checkColumns = columns?.length ? columns : this.columns
725
+ const columns = await this.$refs?.showColumn?.getColumns(this.pageId)
726
+
727
+ if (columns?.length) {
728
+ this.checkColumns = columns
729
+ // 将 remote: true 的远程列同步写入 this.columns,保持位置一致
730
+ this.syncRemoteColumns(columns)
731
+ } else {
732
+ this.checkColumns = this.filterDefaultHidden(this.columns)
733
+ }
702
734
  } catch (err) {
703
- // API 请求失败时回退到 columns prop
704
- this.checkColumns = this.columns
735
+ // API 请求失败时回退到过滤后的 columns prop
736
+ this.checkColumns = this.filterDefaultHidden(this.columns)
737
+ }
738
+ },
739
+ // 供组件外部调用,刷新表头数据(重新请求 getColumns 并同步远程列)
740
+ async refreshColumns() {
741
+ if (this.showColumn && this.pageId) {
742
+ await this.getColumns()
743
+ // 强制重建 vxe-table,确保列变更后视图正确刷新
744
+ this.colsKey++
705
745
  }
706
746
  },
747
+ // 将 API 返回中标记 remote: true 的列同步到 this.columns,保持对应位置一致
748
+ syncRemoteColumns(apiColumns) {
749
+ apiColumns.forEach((apiCol, index) => {
750
+ if (!apiCol.remote) return
751
+ // 按 prop 或 labelKey 匹配 this.columns 中是否已存在
752
+ const matchKey = apiCol.prop ? 'prop' : this.labelKey
753
+ const existingIdx = this.columns.findIndex((c) => c[matchKey] === apiCol[matchKey])
754
+ if (existingIdx !== -1) {
755
+ // 已存在则替换,保持位置以 API 返回为准
756
+ this.$set(this.columns, existingIdx, apiCol)
757
+ } else {
758
+ // 不存在则插入到对应位置(避免 $set 索引超出长度产生稀疏数组)
759
+ const insertIdx = Math.min(index, this.columns.length)
760
+ this.columns.splice(insertIdx, 0, apiCol)
761
+ }
762
+ })
763
+ },
707
764
  /**
708
765
  * 一键展开/折叠表格树形行(仅处理第一层级数据行)
709
766
  * 通过 vxe-table 的 setTreeExpand API 批量设置顶层行的展开状态,
@@ -742,6 +799,10 @@ export default {
742
799
  this.$set(item, 'fixed', 'left')
743
800
  // 手动触发 colsKey 刷新,让 vxe-table 重新渲染列配置
744
801
  this.colsKey = this.colsKey + 1
802
+ // 固定列后自动保存到后端
803
+ if (this.showColumn && this.pageId) {
804
+ this.saveColumns()
805
+ }
745
806
  },
746
807
  // 解锁列:移除 fixed 属性,将该列恢复为普通列
747
808
  unlockColumn(item) {
@@ -749,6 +810,10 @@ export default {
749
810
  this.$delete(item, 'fixed')
750
811
  // 手动触发 colsKey 刷新,让 vxe-table 重新渲染列配置
751
812
  this.colsKey = this.colsKey + 1
813
+ // 取消固定后自动保存到后端
814
+ if (this.showColumn && this.pageId) {
815
+ this.saveColumns()
816
+ }
752
817
  },
753
818
  // 固定操作列为内联列
754
819
  fixOperateColumn() {
@@ -1222,11 +1287,21 @@ export default {
1222
1287
  }
1223
1288
  },
1224
1289
  // ========== 列宽计算相关方法 ==========
1225
- getRowClassName({ row }) {
1290
+ getRowClassName(args) {
1291
+ const rowClassName = this.$attrs['row-class-name'] || this.$attrs.rowClassName
1292
+ // 用户传入了 row-class-name,以传入的为准
1293
+ if (rowClassName && typeof rowClassName === 'function') {
1294
+ return rowClassName(args)
1295
+ }
1296
+ if (rowClassName && typeof rowClassName === 'string') {
1297
+ return rowClassName
1298
+ }
1299
+ // 用户未传入,选中行高亮
1226
1300
  const checkedRows = this.$refs.vxeTable?.getCheckboxRecords(false) || []
1227
1301
  const checkedSet = new Set(checkedRows)
1228
- return checkedSet.has(row) ? 'v3-n20-table-pro__row-checked' : ''
1302
+ return checkedSet.has(args.row) ? 'v3-n20-table-pro__row-checked' : ''
1229
1303
  },
1304
+
1230
1305
  calcColumnWidth(columns) {
1231
1306
  // 常量配置
1232
1307
  const CHAR_WIDTH = 20 // 每个字符的平均宽度(像素)
@@ -1,551 +0,0 @@
1
- <template>
2
- <dialog-wrap
3
- ref="dialog"
4
- v-drag
5
- class="p-t-0"
6
- v-bind="$attrs"
7
- :visible.sync="visible"
8
- :title="title"
9
- :width="width"
10
- :close-on-click-modal="false"
11
- @open="popOpen"
12
- >
13
- <div class="dialog-view">
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>
25
- </div>
26
- <div class="flex-item p-r" style="height: 50%; overflow: auto">
27
- <el-checkbox-group :value="dragListN.map((d) => d[labelKey])">
28
- <template v-if="!columnsGroups">
29
- <el-checkbox
30
- v-for="(column, i) in columnsAs"
31
- :key="i"
32
- v-hover-tooltip="column[labelKey]"
33
- :label="column[labelKey]"
34
- :disabled="column.checked"
35
- class="m-t"
36
- @change="(val) => checkChange(val, column)"
37
- >{{ column[labelKey] }}</el-checkbox
38
- >
39
- </template>
40
- <template v-else>
41
- <div v-for="gp in columnsGroups" :key="gp.groupId" class="m-b">
42
- <div class="f-s-b font-w600">{{ gp.groupName }}</div>
43
- <template v-for="(column, i) in columnsAs">
44
- <el-checkbox
45
- v-if="column.groupId === gp.groupId"
46
- :key="i"
47
- v-hover-tooltip="column[labelKey]"
48
- :label="column[labelKey]"
49
- :disabled="column.checked"
50
- class="m-t"
51
- @change="(val) => checkChange(val, column)"
52
- >{{ column[labelKey] }}</el-checkbox
53
- >
54
- </template>
55
- </div>
56
- </template>
57
- </el-checkbox-group>
58
- </div>
59
- </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>
64
- </div>
65
- <div class="flex-1 overflow-y">
66
- <drag-list :list="dragList" :label-key="labelKey" :in-show-column="true" />
67
- </div>
68
- </div>
69
- <div v-else class="right-tree flex-column p-t-m">
70
- <div class="m-b flex-box flex-lr flex-v">
71
- {{ '当前选定项' | $lc }}
72
- <el-link class="m-r-s" :underline="false" icon="n20-icon-xinzeng" @click="add">{{
73
- '新增字段' | $lc
74
- }}</el-link>
75
- </div>
76
- <el-tree
77
- ref="menu-tree"
78
- class="menu-tree"
79
- :data="dragList"
80
- :props="{
81
- children: 'children',
82
- label: 'label'
83
- }"
84
- node-key="prop"
85
- draggable
86
- style="width: 200px"
87
- :allow-drop="allowDrop"
88
- >
89
- <span slot-scope="{ node, data }" class="menu-item flex-item flex-box flex-lr flex-v">
90
- <span>
91
- <i class="n20-drag-icon n20-icon-tuodong"></i>
92
- <span
93
- :class="data.isNew ? 'color-success' : 'color-primary'"
94
- class="text-ellipsis pointer"
95
- @click="clickItem(data)"
96
- >{{ data.label }}</span
97
- >
98
- </span>
99
- <el-link
100
- class="n20-icon-shanchu"
101
- :underline="false"
102
- :disabled="data.checked"
103
- @click.stop="() => removeMenu(node, data)"
104
- />
105
- </span>
106
- </el-tree>
107
- </div>
108
- </div>
109
- </div>
110
- <dialogWrap
111
- v-drag
112
- :visible.sync="configVisible"
113
- :title="'表头设置' | $lc"
114
- width="350px"
115
- :close-on-click-modal="false"
116
- >
117
- <el-form :model="configModel">
118
- <el-form-item>
119
- {{ configModel.label }}
120
- </el-form-item>
121
- <el-form-item
122
- :label="'表头宽度' | $lc"
123
- :rules="[
124
- {
125
- type: 'number',
126
- trigger: ['change', 'blur'],
127
- validator: validator
128
- }
129
- ]"
130
- prop="width"
131
- >
132
- <el-input v-model="configModel.width" class="w-224" />
133
- </el-form-item>
134
- <el-form-item :label="'是否折行' | $lc">
135
- <el-radio-group v-model="configModel.wrap">
136
- <el-radio :label="true">{{ $lc('是') }}</el-radio>
137
- <el-radio :label="false">{{ $lc('否') }}</el-radio>
138
- </el-radio-group>
139
- </el-form-item>
140
- <el-form-item :label="'是否加粗' | $lc">
141
- <el-radio-group v-model="configModel.bold">
142
- <el-radio :label="true">{{ $lc('是') }}</el-radio>
143
- <el-radio :label="false">{{ $lc('否') }}</el-radio>
144
- </el-radio-group>
145
- </el-form-item>
146
- <el-form-item :label="'对齐方式' | $lc">
147
- <el-radio-group v-model="configModel.align">
148
- <el-radio :label="'right'">{{ $lc('右对齐') }}</el-radio>
149
- <el-radio :label="'left'">{{ $lc('左对齐') }}</el-radio>
150
- <el-radio :label="'center'">{{ $lc('居中对齐') }}</el-radio>
151
- </el-radio-group>
152
- </el-form-item>
153
- </el-form>
154
- <div slot="footer">
155
- <el-button type="primary" @click="configSave">{{ '确定' | $lc }}</el-button>
156
- </div>
157
- </dialogWrap>
158
- <dialogWrap v-drag :visible.sync="configVisibleN" :title="'新增' | $lc" width="350px" :close-on-click-modal="false">
159
- <el-form :model="configModelN">
160
- <el-form-item :label="'名称' | $lc" required>
161
- <el-input v-model="configModelN.label" class="input-w" :placeholder="'请输入' | $lc" />
162
- </el-form-item>
163
- </el-form>
164
- <div slot="footer">
165
- <el-button type="primary" @click="configSaveN">{{ '确定' | $lc }}</el-button>
166
- </div>
167
- </dialogWrap>
168
- <div slot="footer" class="text-c">
169
- <el-button type="primary" @click="setChange">{{ '确定' | $lc }}</el-button>
170
- <el-button plain @click="reset">{{ '恢复默认' | $lc }}</el-button>
171
- </div>
172
- </dialog-wrap>
173
- </template>
174
-
175
- <script>
176
- import axios from '../../utils/axios'
177
- import { $lc } from '../../utils/i18n/index'
178
-
179
- import { Message } from 'element-ui'
180
- import forEachs from '../../utils/forEachs'
181
- import dialogWrap from '../Dialog/index.vue'
182
- import dragList from '../DragList/index.vue'
183
- export default {
184
- name: 'ShowColumn',
185
- components: { dialogWrap, dragList },
186
- inheritAttrs: false,
187
- props: {
188
- dialogVisible: {
189
- type: Boolean,
190
- default: false
191
- },
192
- columns: {
193
- type: Array,
194
- default: () => []
195
- },
196
- columnsGroups: {
197
- type: Array,
198
- default: undefined
199
- },
200
- checkColumns: {
201
- type: Array,
202
- default: () => []
203
- },
204
- isExport: {
205
- type: Boolean,
206
- default: false
207
- },
208
- isFilter: {
209
- type: Boolean,
210
- default: false
211
- },
212
- labelKey: {
213
- type: String,
214
- default: 'label'
215
- },
216
- pageId: {
217
- type: String,
218
- default: undefined
219
- },
220
- autoSave: {
221
- type: Boolean,
222
- default: false
223
- },
224
- width: {
225
- type: String,
226
- default: '1000px'
227
- },
228
- hasPX: {
229
- type: Boolean,
230
- default: false
231
- }
232
- },
233
- data() {
234
- return {
235
- dragList: [],
236
- configVisible: false,
237
- enabled: false,
238
- configModel: {
239
- wrap: false,
240
- bold: false,
241
- align: 'center'
242
- },
243
- configModelN: {
244
- label: '',
245
- prop: '',
246
- width: 120,
247
- isNew: true,
248
- children: []
249
- },
250
- userNo: sessionStorage.getItem('userNo'),
251
- configVisibleN: false,
252
- dragListN: []
253
- }
254
- },
255
- computed: {
256
- title() {
257
- if (this.isExport) {
258
- return $lc('导出')
259
- } else if (this.isFilter) {
260
- return $lc('筛选')
261
- } else {
262
- return $lc('设置显示列')
263
- }
264
- },
265
- header() {
266
- if (this.isExport) {
267
- return $lc('导出')
268
- } else if (this.isFilter) {
269
- return $lc('筛选')
270
- } else {
271
- return $lc('显示列')
272
- }
273
- },
274
- visible: {
275
- get() {
276
- return this.dialogVisible
277
- },
278
- set(val) {
279
- this.$emit('update:dialogVisible', val)
280
- }
281
- },
282
- 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
289
- },
290
- columnsAs: {
291
- get() {
292
- return this.columns.filter((col) => !col.static)
293
- },
294
- set(val) {
295
- return val
296
- }
297
- },
298
- columnsN() {
299
- return this.columns || []
300
- }
301
- },
302
- watch: {
303
- dragList: {
304
- 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
- }) */
319
- },
320
- immediate: true,
321
- deep: true
322
- }
323
- },
324
- methods: {
325
- validator(rule, value, callback) {
326
- if (value) {
327
- if (value > 300) {
328
- return callback(new Error($lc('输入最大宽度不能大于300')))
329
- } else if (!/^[1-9]\d*$/.test(value)) {
330
- return callback(new Error($lc('表头宽度只能输入正整数')))
331
- }
332
- }
333
- callback()
334
- },
335
- add() {
336
- this.configVisibleN = true
337
- this.configModelN.prop = `prop${Date.now()}`
338
- },
339
- configSaveN() {
340
- if (!this.configModelN.label) {
341
- return this.$message.warning($lc('请填写名称'))
342
- }
343
- const hasLabel = this.dragListN.find((item) => {
344
- return item.label === this.configModelN.label
345
- })
346
- if (hasLabel) {
347
- return this.$message.warning($lc('已有重名字段,请修改'))
348
- }
349
- this.dragList.unshift(this.configModelN)
350
- // this.columns = [this.configModelN, ...this.columns]
351
- this.$message.success($lc('添加成功'))
352
- this.configVisibleN = false
353
- this.configModelN = {
354
- label: '',
355
- prop: '',
356
- width: 120,
357
- isNew: true,
358
- children: []
359
- }
360
- },
361
- removeMenu(node, data) {
362
- const parent = node.parent
363
- const children = parent.data.children || parent.data
364
- const index = children.findIndex((d) => d.prop === data.prop)
365
- children.splice(index, 1)
366
- },
367
- allowDrop(draggingNode, dropNode, type) {
368
- if (type === 'inner' && draggingNode.data.isNew) {
369
- return !(draggingNode.level <= dropNode.level)
370
- } else if (type === 'inner' && !draggingNode.data.isNew) {
371
- return !(draggingNode.level <= dropNode.level && !dropNode.data.isNew)
372
- } else {
373
- return true
374
- }
375
- },
376
- clickItem(item) {
377
- this.configModel = item
378
- this.configVisible = true
379
- },
380
- configSave() {
381
- this.configVisible = false
382
- },
383
- popOpen() {
384
- this.dragList = this.checkColumns.filter((col) => !col.static)
385
- },
386
- setAll() {
387
- if (this.setState) {
388
- this.dragList = this.dragList.filter((c) => c.checked)
389
- } else {
390
- this.dragList = [...this.columnsAs]
391
- }
392
- },
393
- checkChange(val, column) {
394
- if (val === false) {
395
- let index = this.dragList.findIndex((d) => d[this.labelKey] === column[this.labelKey])
396
- index !== -1 && this.dragList.splice(index, 1)
397
- } else {
398
- let index = this.dragListN.findIndex((d) => d[this.labelKey] === column[this.labelKey])
399
- if (index !== -1) {
400
- Message.warning($lc(`子级请在右侧删除!`))
401
- return false
402
- }
403
- this.dragList.push(column)
404
- }
405
- },
406
- reset() {
407
- let dragList = this.columns.filter((col) => col.isDefault)
408
- this.dragList = dragList.length ? dragList : this.checkColumns.filter((col) => !col.static)
409
- },
410
- setChange() {
411
- if (this.dragList.length < 1) {
412
- this.$message.error(
413
- `${$lc(`至少设置`)}${
414
- this.isExport ? $lc('一列导出数据') : this.isFilter ? $lc('一个筛选条件') : $lc('一列显示列')
415
- }!`
416
- )
417
- return
418
- }
419
-
420
- let list = []
421
- let preCols = this.columns.filter((col) => col.static === 'pre')
422
- let nextCols = this.columns.filter((col) => col.static === 'next')
423
- list.push(...preCols, ...this.dragList, ...nextCols)
424
- // 新增校验
425
- if (!this.isExport) {
426
- let state = list.findIndex((c) => c.isNew && c.children && c.children.length === 0)
427
- if (state !== -1) {
428
- Message.warning($lc(`新增字段必须包含子级!`))
429
- return false
430
- }
431
- }
432
- // 自动保存设置的显示列
433
- this.userNo = sessionStorage.getItem('userNo')
434
- !this.isExport && this.autoSave && this.saveColumns(list)
435
-
436
- this.$emit('setColumns', list)
437
- if (this.isExport) {
438
- this.visible = false
439
- }
440
- },
441
- saveColumns(list) {
442
- let columns = saveTransform(list, this.labelKey, this.isFilter)
443
- axios.post(
444
- `/bems/prod_1.0/user/pageHabit?t=${Math.random()}`,
445
- {
446
- userNo: this.userNo,
447
- pageId: this.pageId,
448
- showStructure: JSON.stringify(columns)
449
- },
450
- { loading: false }
451
- )
452
- this.visible = false
453
- },
454
- getColumns(pageId) {
455
- return getColumns(pageId || this.pageId, this.userNo, this.columnsN, this.labelKey)
456
- }
457
- }
458
- }
459
-
460
- function saveTransform(list, labelKey, isFilter) {
461
- let listN = []
462
- if (!isFilter) {
463
- list.forEach((c) => {
464
- if (c.prop && !c.children && !c.isNew && !c.width & !c.isNew) {
465
- listN.push({ _colKey: 'prop', _colVal: c.prop })
466
- } else if (c.type && ['selection', 'index', 'expand'].includes(c.type)) {
467
- listN.push({ _colKey: 'type', _colVal: c.type })
468
- } else {
469
- let sFn = false
470
- for (let k in c) {
471
- if (typeof c[k] === 'function') sFn = true
472
- }
473
- if (sFn && c[labelKey]) {
474
- listN.push({ _colKey: labelKey, _colVal: c[labelKey] })
475
- } else {
476
- listN.push(c)
477
- }
478
- }
479
- })
480
- } else {
481
- list.forEach((c) => {
482
- if (c.value) {
483
- listN.push({ _colKey: 'value', _colVal: c.value })
484
- } else if (c.startValue) {
485
- listN.push({ _colKey: 'startValue', _colVal: c.startValue })
486
- } else if (c.startDate) {
487
- listN.push({ _colKey: 'startDate', _colVal: c.startDate })
488
- } else {
489
- listN.push(c)
490
- }
491
- })
492
- }
493
- return listN
494
- }
495
-
496
- function getTransform(list, columnsT, labelKey = 'label') {
497
- let columns = []
498
- list.forEach((d) => {
499
- // 如果list中的每一项是字符串
500
- if (typeof d === 'string') {
501
- // 从columnsT中找到label等于d的项
502
- let column = columnsT.find((c) => c[labelKey] === d)
503
- // 如果找到,则将其添加到columns中
504
- column && columns.push(column)
505
- // 如果list中的每一项是对象
506
- } else if (typeof d === 'object') {
507
- // 如果d中有_colKey属性
508
- if (d._colKey) {
509
- // 从columnsT中找到d._colKey等于d._colVal的项
510
- let column = columnsT.find((c) => c[d._colKey] === d._colVal)
511
- // 如果找到,则将其添加到columns中
512
- column && columns.push(column)
513
- // 如果d中没有_colKey属性
514
- } else {
515
- // 将d添加到columns中
516
- columns.push(d)
517
- }
518
- }
519
- })
520
- // 返回columns
521
- return columns
522
- }
523
-
524
- // 这段代码在筛选组件中复用
525
- export function getColumns(pageId, userNo, columnsT, labelKey = 'label') {
526
- return new Promise((resolve, reject) => {
527
- axios
528
- .post(
529
- `/bems/prod_1.0/user/pageHabit/list?t=${Math.random()}`,
530
- {
531
- userNo: userNo,
532
- pageId: pageId
533
- },
534
- { loading: false }
535
- )
536
- .then(({ data }) => {
537
- if (data) {
538
- let _data = JSON.parse(data)
539
- if (_data && _data.length > 0) {
540
- let columns = getTransform(_data, columnsT, labelKey)
541
- return resolve(columns)
542
- }
543
- }
544
- return resolve(null)
545
- })
546
- .catch((err) => {
547
- reject(err)
548
- })
549
- })
550
- }
551
- </script>