n20-project-component 1.0.1 → 1.0.5

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.
@@ -0,0 +1,895 @@
1
+ <template>
2
+ <div :class="prefixCls">
3
+ <el-form v-show="visible" ref="advancedFilter" :class="prefixCls + '-body'" @submit.native.prevent="() => {}">
4
+ <slot name="prefix"></slot>
5
+ <el-form-item
6
+ v-for="item in GroupData"
7
+ :key="getOnlyKey(item)"
8
+ :class="[prefixCls + '-item', activeClassMap[item.value || item[onlyKey]] || '']"
9
+ :label="item.label"
10
+ :required="!!item.required"
11
+ :disabled="item.props && item.props.disabled"
12
+ >
13
+ <div :class="prefixCls + '-content'">
14
+ <slot v-if="item.slotName && $scopedSlots[item.slotName]" :name="item.slotName"></slot>
15
+ <formItemRender
16
+ v-else
17
+ :form="model"
18
+ :item="item"
19
+ @blur="$emit('blur')"
20
+ @clean="$emit('clean')"
21
+ @enter="$emit('enter')"
22
+ @filter="$emit('filter', model)"
23
+ @change="$emit('change', $event)"
24
+ />
25
+ </div>
26
+ <i
27
+ v-if="!item.isNotClose && !filterReadonly"
28
+ :key="getOnlyKey(item)"
29
+ :class="['filter_remove', 'n20-icon-yichu']"
30
+ @click="handleClose(item)"
31
+ ></i>
32
+ </el-form-item>
33
+ <slot name="suffix"></slot>
34
+ <el-form-item :class="prefixCls + '-add'">
35
+ <el-button v-show="!filterReadonly" v-popover:advanced_popover onlyicon plain>
36
+ <i class="v3-icon-plus"></i>
37
+ {{ $lc('添加条件') }}
38
+ </el-button>
39
+ <el-popover ref="advanced_popover" placement="bottom-start" trigger="click">
40
+ <el-input v-model="keyword" clearable class="input-w m-b-s" :placeholder="$lc('搜索筛选条件')" />
41
+ <div class="flex-box flex-lr">
42
+ <el-button type="text" @click="allCheck">{{
43
+ isAllNonFixedChecked ? $lc('取消全选') : $lc('全选')
44
+ }}</el-button>
45
+ <el-button v-if="filterId" type="text" @click="defaultCheck">{{ $lc('恢复默认') }}</el-button>
46
+ </div>
47
+ <filterItem
48
+ :filter-list="filterListS"
49
+ :max-length="maxLength"
50
+ :check-array.sync="checkList"
51
+ @checked="check"
52
+ />
53
+ <div class="flex-box flex-c m-t-m">
54
+ <el-button size="mini" type="primary" @click="savaCheck">{{ $lc('确认') }}</el-button>
55
+ <el-button plain type="primary" @click="cancel">{{ $lc('取消') }}</el-button>
56
+ </div>
57
+ </el-popover>
58
+ <span v-if="filterId" class="m-l-s color-primary" :underline="false" @click="$emit('search')">
59
+ <i class="v3-icon-search"></i>
60
+ {{ '查询' | $lc }}</span
61
+ >
62
+ <span
63
+ v-if="bussId && !filterReadonly"
64
+ class="m-l-s"
65
+ style="
66
+ display: inline-block;
67
+ border-radius: 4px;
68
+ background: var(--fill-1, #f7f8fa);
69
+ padding: 3px 12px;
70
+ height: 24px;
71
+ line-height: 24px;
72
+ "
73
+ @click="addView"
74
+ >
75
+ <i class="v3-icon-folder-add"></i>
76
+ {{ '另存为视图' | $lc }}
77
+ </span>
78
+ <span v-if="filterId" class="m-l-s color-primary" :underline="false" @click="cleared">
79
+ <i class="v3-icon-delete"></i>
80
+ {{ '清空条件' | $lc }}</span
81
+ >
82
+ </el-form-item>
83
+ </el-form>
84
+ <cl-dialog
85
+ v-drag
86
+ :visible.sync="stVisible"
87
+ :title="$lc('另存为视图')"
88
+ width="400px"
89
+ :destroy-on-close="true"
90
+ :close-on-click-modal="false"
91
+ >
92
+ <el-form ref="stform" :model="form" label-width="80px" :inline="false" size="normal" label-position="top">
93
+ <el-form-item
94
+ :label="$lc('视图名称')"
95
+ prop="viewName"
96
+ :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
97
+ >
98
+ <el-input v-model="form.viewName" maxlength="30" show-word-limit />
99
+ </el-form-item>
100
+ </el-form>
101
+ <div slot="footer" class="flex-box flex-c flex-v page-button-shadow">
102
+ <el-button type="primary" @click="saveSt">{{ $lc('确认') }}</el-button>
103
+ <el-button plain @click="stVisible = false">{{ $lc('取消') }}</el-button>
104
+ </div>
105
+ </cl-dialog>
106
+ </div>
107
+ </template>
108
+
109
+ <script>
110
+ import XEUtils from 'xe-utils'
111
+
112
+ import filterItem from './filterItem.vue'
113
+ import formItemRender from './formItemRender.vue'
114
+
115
+ import axios from 'n20-common-lib/src/utils/axios.js'
116
+ import ClDialog from 'n20-common-lib/src/components/Dialog/index.vue'
117
+ import InputSearch from 'n20-common-lib/src/components/InputSearch/index.vue'
118
+
119
+ const getOnlyKeys = (key, data) => (key ? data[key] : Date.now().toString(36) + Math.random().toString(36).slice(2, 7))
120
+
121
+ const prefixCls = 'n20-advanced-filter'
122
+ export default {
123
+ name: 'AdvancedFilter',
124
+ components: {
125
+ ClDialog,
126
+ // formItemInput,
127
+ formItemRender,
128
+ InputSearch,
129
+ // FormItem,
130
+ filterItem
131
+ },
132
+ provide() {
133
+ return {
134
+ prefixCls,
135
+ nFilter: this
136
+ }
137
+ },
138
+ props: {
139
+ maxLength: {
140
+ type: Number
141
+ },
142
+ removeLoad: {
143
+ type: Boolean,
144
+ default: true
145
+ },
146
+ visible: {
147
+ type: Boolean,
148
+ default: false
149
+ },
150
+ filterList: {
151
+ type: Array,
152
+ default: () => []
153
+ },
154
+ onlyKey: {
155
+ type: String,
156
+ default: ''
157
+ },
158
+ model: {
159
+ type: Object,
160
+ default: () => ({})
161
+ },
162
+ filterId: {
163
+ type: String,
164
+ default: ''
165
+ },
166
+ // 选中的Id数据
167
+ checkIds: {
168
+ type: Array,
169
+ default: () => []
170
+ },
171
+ bussId: {
172
+ type: String,
173
+ default: ''
174
+ },
175
+ // 视图模式下只读,隐藏“添加条件”按钮和字段移除图标
176
+ filterReadonly: {
177
+ type: Boolean,
178
+ default: false
179
+ }
180
+ },
181
+ data() {
182
+ return {
183
+ keyword: '',
184
+ prefixCls,
185
+ remoteList: [],
186
+ GroupData: [],
187
+ checkList: [],
188
+ defineCheckList: [],
189
+ cancelCheck: [],
190
+ userNo: sessionStorage.getItem('userNo'),
191
+ form: {
192
+ userNo: sessionStorage.getItem('userNo'),
193
+ pageNo: this.filterId,
194
+ name: ''
195
+ },
196
+ stVisible: false,
197
+ optionsMap: {}
198
+ }
199
+ },
200
+ computed: {
201
+ filterListS: {
202
+ get() {
203
+ if (!this.keyword) {
204
+ return this.filterList
205
+ } else {
206
+ const keywordLowerCase = this.keyword
207
+ return this.filterList.filter((item) => item.label.includes(keywordLowerCase))
208
+ }
209
+ },
210
+ set(v) {
211
+ return v
212
+ }
213
+ },
214
+ // 判断所有非固定(非static、非isNotClose)项目是否都已选中
215
+ isAllNonFixedChecked() {
216
+ const nonFixedItems = this.filterListS.filter((res) => !res.static && !res.isNotClose)
217
+ if (nonFixedItems.length === 0) return false
218
+
219
+ const nonFixedItemIds = nonFixedItems.map((item) => item[this.onlyKey])
220
+ return nonFixedItemIds.every((id) => this.checkList.includes(id))
221
+ },
222
+ // 通过深度遍历 model 所有属性触发 getter,建立完整响应式依赖
223
+ // 同时收集对象级 __ob__.dep,确保 $set 新增属性时也能触发重算
224
+ _modelValues() {
225
+ const model = this.model
226
+ // 遍历所有自有属性触发 getter(收集属性级 dep)
227
+ // Object.keys 在 Vue 2 内部会触发对象级 dep 收集
228
+ const keys = Object.keys(model)
229
+ const values = []
230
+ for (let i = 0; i < keys.length; i++) {
231
+ values.push(model[keys[i]])
232
+ }
233
+ return values
234
+ },
235
+ activeClassMap() {
236
+ // 访问 _modelValues 建立深度依赖,确保 model 任何值变化都能触发重算
237
+ void this._modelValues
238
+
239
+ const model = this.model
240
+ const hasValue = (val) => {
241
+ if (Array.isArray(val)) return val.length > 0
242
+ return val !== null && val !== undefined && val !== ''
243
+ }
244
+ const hasRange = (start, end) => hasValue(model[start]) && hasValue(model[end])
245
+ const rangeTypes = ['daterange', 'datetimerange', 'monthrange']
246
+
247
+ const map = {}
248
+ this.GroupData.forEach((item) => {
249
+ const key = item.value || item[this.onlyKey]
250
+ let isActive = false
251
+ if (item.type === 'numberrange') {
252
+ isActive = hasRange(item.startValue, item.endValue)
253
+ } else if (rangeTypes.includes(item.type)) {
254
+ isActive = hasRange(item.startDate, item.endDate)
255
+ } else if (item.slotFields && item.slotFields.length > 0) {
256
+ isActive = item.slotFields.some((field) => hasValue(model[field]))
257
+ } else {
258
+ isActive = hasValue(model[item.value])
259
+ }
260
+ map[key] = isActive ? this.prefixCls + '-active' : ''
261
+ })
262
+ return map
263
+ }
264
+ },
265
+ watch: {
266
+ // visible: {
267
+ // handler(val) {
268
+ // val && this.getFilterList()
269
+ // }
270
+ // },
271
+ // 当 filterList 中某几项的 options 异步更新后,同步到 GroupData 保证渲染更新
272
+ filterList: {
273
+ handler(newList) {
274
+ if (!this.GroupData || this.GroupData.length === 0) return
275
+ this.GroupData.forEach((groupItem) => {
276
+ const filterItem = newList.find((f) => f[this.onlyKey] === groupItem[this.onlyKey])
277
+ // 仅在 options 引用确实发生变化时才同步,避免:
278
+ // 1. mackData 排序 filterList 后重复更新 GroupData(两者引用相同)
279
+ // 2. 用 filterList 中的空数组覆盖 reqOptions 已获取的正确数据
280
+ if (filterItem && filterItem.options !== undefined && filterItem.options !== groupItem.options) {
281
+ this.$set(groupItem, 'options', filterItem.options)
282
+ }
283
+ })
284
+ },
285
+ deep: true
286
+ }
287
+ },
288
+ created() {
289
+ this.getFilterList()
290
+ this.getDefaultCheck()
291
+ },
292
+ beforeDestroy() {
293
+ this.optionsMap = {}
294
+ },
295
+ methods: {
296
+ // 保存视图
297
+ saveSt() {
298
+ this.$refs.stform.validate(async (valid) => {
299
+ if (valid) {
300
+ // 如果没有 bussId,不保存视图
301
+ if (!this.bussId) {
302
+ this.$message.warning('缺少业务ID,无法保存视图')
303
+ return
304
+ }
305
+
306
+ // 保存筛选视图
307
+ const obj = {
308
+ viewName: this.form.viewName,
309
+ viewType: '0',
310
+ bussId: this.bussId,
311
+ viewConfig: JSON.stringify(this.model),
312
+ keyIds: JSON.stringify(this.checkList)
313
+ }
314
+ const { code } = await axios.post(`/bems/query/viewColumn/saveOrUpdateViewInfo`, obj)
315
+ if (code === 200) {
316
+ this.stVisible = false
317
+ this.$message.success('保存成功')
318
+ this.$emit('refresh')
319
+ }
320
+ }
321
+ })
322
+ },
323
+ // 另存为视图
324
+ addView() {
325
+ this.stVisible = true
326
+ this.form.type = 1
327
+ this.form.keyIds = this.checkList
328
+ },
329
+ getDefaultCheck() {
330
+ let _checkList = this.filterList
331
+ .filter((item) => {
332
+ if (item.isDefault) {
333
+ return item
334
+ }
335
+ })
336
+ .map((item) => item[this.onlyKey])
337
+ this.defineCheckList = XEUtils.clone(_checkList, true)
338
+ },
339
+ getOnlyKey(data) {
340
+ return getOnlyKeys(this.onlyKey, data)
341
+ },
342
+ setOptions(id, opts) {
343
+ this.optionsMap[id] = opts
344
+ this.setChoices(id, opts)
345
+ },
346
+ setChoices(id, data) {
347
+ let item = this.GroupData.find((f) => f[this.onlyKey] === id)
348
+ if (item) {
349
+ item.options = data || []
350
+ } else {
351
+ item = this.GroupData.find((f) => f.value === id)
352
+ if (item) {
353
+ item.options = data || []
354
+ }
355
+ }
356
+ },
357
+ filter() {
358
+ return this.model
359
+ },
360
+
361
+ handleClose(item) {
362
+ const key = item[this.onlyKey] || item.value
363
+ if (this.optionsMap[key]) {
364
+ delete this.optionsMap[key]
365
+ }
366
+
367
+ switch (item.type) {
368
+ case 'select':
369
+ this.$set(this.model, item.value, item.multiple ? [] : null)
370
+ break
371
+ case 'text':
372
+ case 'search':
373
+ case 'number':
374
+ case 'date':
375
+ case 'datetime':
376
+ case 'year':
377
+ case 'month':
378
+ case 'radio':
379
+ case 'week':
380
+ this.$set(this.model, item.value, null)
381
+
382
+ break
383
+ case 'checkbox':
384
+ this.$set(this.model, item.value, [])
385
+ break
386
+ case 'numberrange':
387
+ this.$set(this.model, item.startValue, null)
388
+ this.$set(this.model, item.endValue, null)
389
+
390
+ break
391
+ case 'daterange':
392
+ case 'datetimerange':
393
+ case 'monthrange':
394
+ this.$set(this.model, item.startDate, null)
395
+ this.$set(this.model, item.endDate, null)
396
+ break
397
+ case 'slot': {
398
+ this.$set(this.model, item.value, null)
399
+ // 清空 slotFields 中定义的所有字段
400
+ if (item.slotFields?.length) {
401
+ item.slotFields.forEach((field) => {
402
+ this.$set(this.model, field, null)
403
+ })
404
+ }
405
+ break
406
+ }
407
+ }
408
+ let data = this.GroupData.filter((s) => {
409
+ return s.id !== item.id
410
+ })
411
+ this.saveFilter(data).then(({ code }) => {
412
+ if (code === 200) {
413
+ this.getFilterList()
414
+ }
415
+ })
416
+ this.$emit('clean', this.model)
417
+ },
418
+ cleared() {
419
+ this.$emit('clear')
420
+ },
421
+ setModelData(list) {
422
+ // 收集当前选中列表中的所有字段
423
+ const selectedFields = new Set()
424
+ list.forEach((res) => {
425
+ if (res.value) selectedFields.add(res.value)
426
+ if (res.startDate) selectedFields.add(res.startDate)
427
+ if (res.endDate) selectedFields.add(res.endDate)
428
+ if (res.startValue) selectedFields.add(res.startValue)
429
+ if (res.endValue) selectedFields.add(res.endValue)
430
+ if (res.type === 'slot' && Array.isArray(res?.slotFields)) {
431
+ res?.slotFields.forEach((field) => {
432
+ if (field) selectedFields.add(field)
433
+ })
434
+ }
435
+ })
436
+
437
+ // 收集 filterList 中定义的所有字段
438
+ const allDefinedFields = new Set()
439
+ this.filterList.forEach((item) => {
440
+ if (item.value) allDefinedFields.add(item.value)
441
+ if (item.startDate) allDefinedFields.add(item.startDate)
442
+ if (item.endDate) allDefinedFields.add(item.endDate)
443
+ if (item.startValue) allDefinedFields.add(item.startValue)
444
+ if (item.endValue) allDefinedFields.add(item.endValue)
445
+ if (item.type === 'slot' && Array.isArray(item?.slotFields)) {
446
+ item?.slotFields.forEach((field) => {
447
+ if (field) allDefinedFields.add(field)
448
+ })
449
+ }
450
+ })
451
+
452
+ // 只清除:在 filterList 中定义但不在选中列表中的字段
453
+ for (const key in this.model) {
454
+ if (Object.hasOwnProperty.call(this.model, key)) {
455
+ // 仅当该字段在 filterList 中定义且未被选中时才清除
456
+ if (allDefinedFields.has(key) && !selectedFields.has(key)) {
457
+ this.$delete(this.model, key)
458
+ }
459
+ }
460
+ }
461
+ },
462
+ allCheck() {
463
+ // 获取非固定(非static、非isNotClose)的项目
464
+ const nonFixedItems = this.filterListS.filter((res) => !res.static && !res.isNotClose)
465
+ const nonFixedItemIds = nonFixedItems.map((item) => item[this.onlyKey])
466
+
467
+ // 检查所有非固定项目是否都已选中
468
+ const allNonFixedChecked =
469
+ nonFixedItemIds.length > 0 && nonFixedItemIds.every((id) => this.checkList.includes(id))
470
+
471
+ // 获取固定项目的ID
472
+ const fixedItemIds = this.filterListS
473
+ .filter((res) => res.static || res.isNotClose)
474
+ .map((item) => item[this.onlyKey])
475
+
476
+ if (allNonFixedChecked) {
477
+ // 取消全选:只保留固定项目
478
+ this.checkList = [...fixedItemIds]
479
+ } else {
480
+ // 全选:选中所有项目
481
+ if (this.maxLength) {
482
+ this.checkList = this.filterListS.slice(0, this.maxLength)?.map((res) => res[this.onlyKey])
483
+ } else {
484
+ this.checkList = this.filterListS?.map((res) => res[this.onlyKey])
485
+ }
486
+ }
487
+ },
488
+ defaultCheck() {
489
+ this.checkList = this.defineCheckList
490
+ },
491
+ cancel() {
492
+ this.checkList = this.cancelCheck
493
+ this.$refs.advanced_popover.showPopper = false
494
+ },
495
+ savaCheck() {
496
+ let saveCheckArr = []
497
+ // 如果keys数组不为空
498
+ if (this.checkList.length > 0) {
499
+ this.filterList.forEach((item) => {
500
+ if (this.checkList.includes(item[this.onlyKey])) {
501
+ saveCheckArr.push(item)
502
+ }
503
+ })
504
+ }
505
+ this.setModelData(saveCheckArr)
506
+ this.saveFilter(saveCheckArr).then(({ code }) => {
507
+ // 如果保存成功
508
+ if (code === 200) {
509
+ // 重新获取过滤条件列表
510
+ this.getFilterList()
511
+ }
512
+ })
513
+ this.$refs.advanced_popover.showPopper = false
514
+ this.$emit('check', saveCheckArr)
515
+ },
516
+ check(keys) {
517
+ this.checkList = keys
518
+ },
519
+ /**
520
+ * 保存筛选条件
521
+ * @param data
522
+ */
523
+ saveFilter(data) {
524
+ return new Promise((resolve) => {
525
+ if (!this.filterId) {
526
+ this.mackData(data)
527
+ this.$refs.advanced_popover.showPopper = false
528
+ this.$emit('saveCheckData', data)
529
+ resolve({ code: 500 }) // 返回一个成功状态的 Promise
530
+ return
531
+ }
532
+
533
+ axios
534
+ .post(
535
+ `/bems/prod_1.0/user/pageHabit?t=${Date.now()}`,
536
+ {
537
+ userNo: this.userNo,
538
+ pageId: this.filterId,
539
+ showStructure: JSON.stringify(data)
540
+ },
541
+ { loading: false }
542
+ )
543
+ .then((res) => {
544
+ resolve(res)
545
+ })
546
+ })
547
+ },
548
+ /**
549
+ * 获取筛选条件
550
+ */
551
+ getFilterList() {
552
+ if (!this.filterId) {
553
+ if (this.checkIds.length === 0) {
554
+ this.GroupData = []
555
+ } else {
556
+ // 按照 checkIds 的顺序过滤和排序
557
+ const sortedList = this.filterList
558
+ .filter((item) => this.checkIds.includes(item[this.onlyKey]))
559
+ .sort((a, b) => {
560
+ const indexA = this.checkIds.indexOf(a[this.onlyKey])
561
+ const indexB = this.checkIds.indexOf(b[this.onlyKey])
562
+ return indexA - indexB
563
+ })
564
+ this.mackData(sortedList)
565
+ }
566
+
567
+ return false
568
+ }
569
+ axios
570
+ .post(
571
+ `/bems/prod_1.0/user/pageHabit/list?t=${Date.now()}`,
572
+ {
573
+ userNo: this.userNo,
574
+ pageId: this.filterId
575
+ },
576
+ { loading: false, noMsg: true }
577
+ )
578
+ .then(({ data }) => {
579
+ let _data = JSON.parse(data)
580
+ this.mackData(_data)
581
+ })
582
+ .finally(() => {
583
+ for (const key in this.optionsMap) {
584
+ if (Object.hasOwnProperty.call(this.optionsMap, key)) {
585
+ const data = this.optionsMap[key]
586
+ this.setChoices(key, data)
587
+ }
588
+ }
589
+ })
590
+ },
591
+ // 处理数据
592
+ mackData(data) {
593
+ let _data = data
594
+ if (_data && _data.length > 0) {
595
+ // 先过滤出在 filterList 中存在的项目,避免使用已删除的筛选条件
596
+ _data = _data.filter((item) => {
597
+ return this.filterList.some((filterItem) => filterItem[this.onlyKey] === item[this.onlyKey])
598
+ })
599
+
600
+ // 如果过滤后没有有效数据,使用默认逻辑
601
+ if (_data.length === 0) {
602
+ if (this.removeLoad) {
603
+ this.GroupData = this.filterList.filter((item) => {
604
+ if (item.isDefault) {
605
+ return item
606
+ }
607
+ })
608
+ } else {
609
+ this.GroupData = []
610
+ }
611
+ } else {
612
+ // 更新有效数据的 label 和 options
613
+ this.GroupData = _data.map((item) => {
614
+ const originItem = this.filterList.find((filter) => filter[this.onlyKey] === item[this.onlyKey])
615
+ if (originItem) {
616
+ item.label = originItem.label
617
+ if (originItem.options) {
618
+ item.options = originItem.options
619
+ }
620
+ }
621
+ return item
622
+ })
623
+ }
624
+ } else {
625
+ if (this.removeLoad) {
626
+ this.GroupData = this.filterList.filter((item) => {
627
+ if (item.isDefault) {
628
+ return item
629
+ }
630
+ })
631
+ } else {
632
+ this.GroupData = []
633
+ }
634
+ }
635
+
636
+ // ✨ 确保 static: true 的项目自动添加并勾选
637
+ const staticItemsInFilterList = this.filterList.filter((item) => item.static)
638
+ const existingIds = this.GroupData.map((item) => item[this.onlyKey])
639
+
640
+ // 找出不在 GroupData 中的 static 项目
641
+ const missingStaticItems = staticItemsInFilterList.filter((item) => !existingIds.includes(item[this.onlyKey]))
642
+
643
+ // 将缺失的 static 项目添加到 GroupData 开头
644
+ if (missingStaticItems.length > 0) {
645
+ const staticItemsToAdd = missingStaticItems.map((item) => ({ ...item }))
646
+ this.GroupData = [...staticItemsToAdd, ...this.GroupData]
647
+ }
648
+
649
+ // ✨ 强制将所有 static: true 的项目移到最前面
650
+ if (this.GroupData && this.GroupData.length > 0) {
651
+ const staticItems = this.GroupData.filter((item) => item.static)
652
+ const otherItems = this.GroupData.filter((item) => !item.static)
653
+ this.GroupData = [...staticItems, ...otherItems]
654
+ }
655
+
656
+ this.checkList = this.GroupData.map((res) => res.id)
657
+ console.log(this.checkList)
658
+ this.cancelCheck = XEUtils.clone(this.checkList, true)
659
+ // 查找排序,在this.filterList中查找this.checkList中的每一项,并将其排在前面
660
+ this.filterList = this.filterList.sort((a, b) => {
661
+ const indexA = this.checkList.indexOf(a[this.onlyKey])
662
+ const indexB = this.checkList.indexOf(b[this.onlyKey])
663
+
664
+ // 如果两个都在 checkList 中,按照 checkList 的顺序
665
+ if (indexA !== -1 && indexB !== -1) {
666
+ return indexA - indexB
667
+ }
668
+ // 如果只有 a 在 checkList 中,a 排在前面
669
+ if (indexA !== -1) {
670
+ return -1
671
+ }
672
+ // 如果只有 b 在 checkList 中,b 排在前面
673
+ if (indexB !== -1) {
674
+ return 1
675
+ }
676
+ // 如果都不在 checkList 中,保持原有顺序
677
+ return 0
678
+ })
679
+
680
+ console.log(this.filterList)
681
+ }
682
+ }
683
+ }
684
+ </script>
685
+
686
+ <style lang="scss" scoped>
687
+ $--border-color-base: #dcdfe6;
688
+ $--color-primary: #409eff;
689
+
690
+ .n20-advanced-filter {
691
+ box-sizing: border-box;
692
+ position: relative;
693
+ display: flex;
694
+ align-items: center;
695
+ flex: 1;
696
+ padding: 8px 0;
697
+
698
+ &-item.n20-advanced-filter-active {
699
+ border-color: #b3d0ff;
700
+ background: #e9f2ff !important;
701
+ }
702
+
703
+ &-body {
704
+ display: flex;
705
+ align-items: center;
706
+ flex-wrap: wrap;
707
+ gap: 6px 0px;
708
+
709
+ .el-form-item,
710
+ .el-form-item--small.el-form-item {
711
+ margin-bottom: 8px;
712
+ }
713
+
714
+ .el-form-item__content {
715
+ display: inline-block;
716
+ vertical-align: middle;
717
+ }
718
+ }
719
+
720
+ &-item {
721
+ box-sizing: border-box;
722
+ display: inline-block;
723
+ vertical-align: middle;
724
+ max-width: 426px !important;
725
+ min-width: 120px;
726
+ margin-right: 8px;
727
+ border: 1px solid $--border-color-base;
728
+ padding: 0 0 0 8px;
729
+ border-radius: 4px;
730
+ white-space: nowrap;
731
+ cursor: pointer;
732
+
733
+ .el-form-item__label {
734
+ padding: 0;
735
+ max-width: 168px;
736
+ display: inline-block;
737
+ vertical-align: middle;
738
+ white-space: nowrap;
739
+ overflow: hidden;
740
+ text-overflow: ellipsis;
741
+ margin-right: 4px;
742
+ }
743
+
744
+ .el-range-editor.el-input__inner {
745
+ min-width: 168px;
746
+ max-width: 224px;
747
+
748
+ .el-range-input {
749
+ background-color: transparent;
750
+ }
751
+ }
752
+
753
+ .n20-date-editor.el-date-editor--datetimerange.el-range-editor--small.has-value {
754
+ min-width: 168px;
755
+ max-width: 380px;
756
+ }
757
+
758
+ .n20-date-editor .el-input__prefix {
759
+ display: none;
760
+ }
761
+
762
+ .el-input,
763
+ .el-input__inner {
764
+ padding-left: 0;
765
+ border: none;
766
+ width: 100%;
767
+ white-space: nowrap;
768
+ text-overflow: ellipsis;
769
+ background-color: transparent;
770
+ }
771
+
772
+ .el-select__input.is-small {
773
+ margin-left: 0;
774
+ }
775
+
776
+ .el-input__inner:active,
777
+ .el-input__inner:focus {
778
+ box-shadow: none;
779
+ border: none;
780
+ border-color: #fff;
781
+ }
782
+
783
+ .el-checkbox-group {
784
+ height: 32px;
785
+ line-height: 32px;
786
+ vertical-align: middle;
787
+ padding: 0 10px;
788
+ }
789
+
790
+ .el-radio-group {
791
+ padding: 0 10px;
792
+ }
793
+
794
+ .el-date-editor .el-range-separator {
795
+ padding: 0;
796
+ }
797
+
798
+ .n20-num-w {
799
+ .el-input,
800
+ .el-input__inner {
801
+ padding-left: 0;
802
+ }
803
+
804
+ .el-input--suffix .el-input__inner {
805
+ padding-right: 25px;
806
+ }
807
+ }
808
+
809
+ .n20-numberRange {
810
+ padding-right: 8px;
811
+ }
812
+
813
+ .filter_remove {
814
+ display: none;
815
+ position: absolute;
816
+ height: 13px;
817
+ width: 13px;
818
+ background: #f1f1f1;
819
+ right: -5px;
820
+ top: -7px;
821
+ font-size: 14px;
822
+ z-index: 1;
823
+ border-radius: 50%;
824
+ cursor: pointer;
825
+ }
826
+ }
827
+
828
+ &-item:hover {
829
+ .filter_remove {
830
+ display: block;
831
+ }
832
+ }
833
+
834
+ &-item.el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label:before {
835
+ font-size: 16px;
836
+ }
837
+
838
+ &-item.el-form-item[disabled] {
839
+ background-color: #f5f5f5 !important;
840
+ border-color: #e4e7ed !important;
841
+ color: #333333 !important;
842
+ cursor: not-allowed;
843
+ }
844
+
845
+ &-item.el-form-item.is-error {
846
+ border-color: #f56c6c !important;
847
+
848
+ input::placeholder {
849
+ color: #f56c6c !important;
850
+ }
851
+ }
852
+
853
+ &-content {
854
+ display: inline-block;
855
+ white-space: nowrap;
856
+ text-overflow: ellipsis;
857
+ line-height: 1;
858
+
859
+ .el-select.el-select--small {
860
+ .el-select__tags {
861
+ max-width: 88px !important;
862
+ display: flex;
863
+ flex-wrap: nowrap;
864
+ }
865
+ }
866
+
867
+ .n20-date-editor.el-date-editor--datetimerange.el-range-editor--small.has-value {
868
+ min-width: 168px;
869
+ max-width: 380px;
870
+ }
871
+
872
+ .el-range-editor.el-input__inner {
873
+ padding: 3px 30px 3px 0px;
874
+ }
875
+
876
+ .el-select .el-tag.el-tag--info {
877
+ background: #e1f0ff;
878
+ }
879
+ }
880
+
881
+ :hover {
882
+ border-color: $--color-primary;
883
+ cursor: pointer;
884
+ }
885
+
886
+ &-add {
887
+ display: inline-block;
888
+ vertical-align: middle;
889
+ }
890
+ }
891
+
892
+ .popover-check-box .el-checkbox.is-checked .el-checkbox__label {
893
+ color: inherit !important;
894
+ }
895
+ </style>