n20-common-lib 3.0.35 → 3.0.37

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,29 @@
1
+ <svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_4435_91993)">
3
+ <path d="M17.5 5H71.3365L92.5 26.3423V85C92.5 90.5229 88.0229 95 82.5 95H17.5C11.9772 95 7.5 90.5229 7.5 85V15C7.5 9.47715 11.9772 5 17.5 5Z" fill="#D1D5DB"/>
4
+ <mask id="mask0_4435_91993" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="7" y="5" width="86" height="90">
5
+ <path d="M17.5 5H71.3365L92.5 26.3423V85C92.5 90.5229 88.0229 95 82.5 95H17.5C11.9772 95 7.5 90.5229 7.5 85V15C7.5 9.47715 11.9772 5 17.5 5Z" fill="white"/>
6
+ </mask>
7
+ <g mask="url(#mask0_4435_91993)">
8
+ <g filter="url(#filter0_d_4435_91993)">
9
+ <path d="M71.2602 16.3363L71.2602 4.9999L92.5001 26.3363L81.2602 26.3363C75.7374 26.3363 71.2602 21.8592 71.2602 16.3363Z" fill="black"/>
10
+ </g>
11
+ <path d="M71.2602 16.3363L71.2602 4.9999L92.5001 26.3363L81.2602 26.3363C75.7374 26.3363 71.2602 21.8592 71.2602 16.3363Z" fill="white" fill-opacity="0.92"/>
12
+ </g>
13
+ </g>
14
+ <defs>
15
+ <filter id="filter0_d_4435_91993" x="53.2603" y="-16" width="57.2397" height="57.3359" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
16
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
17
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
18
+ <feOffset dy="-3"/>
19
+ <feGaussianBlur stdDeviation="9"/>
20
+ <feComposite in2="hardAlpha" operator="out"/>
21
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
22
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_4435_91993"/>
23
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_4435_91993" result="shape"/>
24
+ </filter>
25
+ <clipPath id="clip0_4435_91993">
26
+ <rect width="100" height="100" fill="white"/>
27
+ </clipPath>
28
+ </defs>
29
+ </svg>
@@ -177,7 +177,7 @@
177
177
  <el-button v-if="value.length > 0" type="text" class="add-condition-btn" @click.stop="addCondition(0)">
178
178
  <i class="v3-icon-add-fill"></i> 添加条件
179
179
  </el-button>
180
- <el-button type="text" class="add-group-btn" @click.stop="addConditionGroup(groupIndex)">
180
+ <el-button type="text" class="add-group-btn" @click.stop="addConditionGroup()">
181
181
  <i class="v3-icon-add-fill"></i> 添加条件组
182
182
  </el-button>
183
183
  </div>
@@ -461,35 +461,39 @@ export default {
461
461
  },
462
462
  methods: {
463
463
  // 查询支持可配置高级查询的字段
464
- getAdvancedQueryFields() {
465
- axios.get('/bems/query/viewColumn/getColumnInfo', { bussId: this.bussId }, { loading: false }).then((res) => {
466
- //res.data=[]
467
- // 过滤可筛选的字段,保留完整对象信息
468
- const searchableFields = res.data.filter((item) => {
469
- return item.searchable === '1'
470
- })
471
- // 用 filterList 去匹配可搜索的字段,并设置 advancedQueryType
472
- this.canSetFilter = this.filterList
473
- .filter((item) => {
474
- return searchableFields.some(
475
- (field) => field.fieldCode === item.fieldCode || field.fieldCode === item.value
476
- )
477
- })
478
- .map((item) => {
479
- // 查找匹配的字段配置,获取 fieldType
480
- const matchedField = searchableFields.find(
481
- (field) => field.fieldCode === item.fieldCode || field.fieldCode === item.value
482
- )
483
- if (matchedField) {
484
- // 设置 advancedQueryType 为 fieldType
485
- this.$set(item, 'advancedQueryType', Number(matchedField.fieldType))
486
- this.$set(item, 'value', matchedField.fieldCode)
487
- }
488
- return item
489
- })
490
- // 再次过滤,确保数据正确
491
- this.filterInvalidConditions()
464
+ async getAdvancedQueryFields() {
465
+ const { code, data } = await axios.get(
466
+ '/bems/query/viewColumn/getColumnInfo',
467
+ { bussId: this.bussId },
468
+ { loading: false }
469
+ )
470
+ if (code !== 200) return
471
+
472
+ // 过滤可筛选的字段,保留完整对象信息
473
+ const searchableFields = data.filter((item) => {
474
+ return item.searchable === '1'
492
475
  })
476
+ console.log(this.filterList, '10086')
477
+
478
+ // 用 filterList 去匹配可搜索的字段,并设置 advancedQueryType
479
+ this.canSetFilter = this.filterList
480
+ .filter((item) => {
481
+ return searchableFields.some((field) => field.fieldCode === item.fieldCode || field.fieldCode === item.value)
482
+ })
483
+ .map((item) => {
484
+ // 查找匹配的字段配置,获取 fieldType
485
+ const matchedField = searchableFields.find(
486
+ (field) => field.fieldCode === item.fieldCode || field.fieldCode === item.value
487
+ )
488
+ if (matchedField) {
489
+ // 设置 advancedQueryType 为 fieldType
490
+ this.$set(item, 'advancedQueryType', Number(matchedField.fieldType))
491
+ this.$set(item, 'value', matchedField.fieldCode)
492
+ }
493
+ return item
494
+ })
495
+ // 再次过滤,确保数据正确
496
+ this.filterInvalidConditions()
493
497
  },
494
498
  // 过滤掉无效的条件(字段不在可筛选列表中)
495
499
  filterInvalidConditions() {
@@ -2,43 +2,48 @@
2
2
  <div class="ProFilterView">
3
3
  <div class="flex-box flex-lr flex-v top">
4
4
  <div class="flex-box flex-v">
5
- <el-popover v-model="stVisible" placement="bottom" trigger="click" class="m-r">
6
- <el-button slot="reference" class="botton" :class="{ activiti: selectedItem !== '所有的' }">
5
+ <el-popover
6
+ v-model="stVisible"
7
+ popper-class="pro-filter-view-popover"
8
+ placement="bottom-start"
9
+ trigger="click"
10
+ class="m-r"
11
+ >
12
+ <el-button slot="reference" class="botton" :class="{ activiti: selectedItem !== '无视图' }">
7
13
  <div class="flex-box flex-v m-r">
8
14
  <i class="v3-icon-inbox"></i>
9
- <div style="margin: 0 8px">{{ selectedItem }}</div>
15
+ <div class="popover-title" style="margin: 0 8px" :title="selectedItem">{{ selectedItem }}</div>
10
16
  <i class="n20-icon-xiala-moren"></i>
11
17
  </div>
12
18
  </el-button>
13
19
  <div class="p-s">
14
- <cl-input-search v-model="val" class="input-w" placeholder="请输入" />
15
- <div style="color: var(--color-text-secondary); margin-top: 8px">{{ $lc('自定义视图') }}</div>
16
- <cl-drag-list class="flex-item" :list="filteredList" :hide-delete="true" @change="fn">
17
- <template v-slot="{ item }">
18
- <div
19
- class="proFilterView-list-item"
20
- :class="{ 'is-selected': selectedItem === item.viewName }"
21
- @click="handleSelect(item)"
22
- >
23
- <span>{{ item.viewName }}</span>
24
- <i v-if="selectedItem === item.viewName" class="el-icon-check selected-icon"></i>
25
- <el-button
26
- v-if="selectedItem !== item.viewName && item.viewName !== '所有的'"
27
- type="text"
28
- size="mini"
29
- @click.stop="edit(item)"
30
- >{{ $lc('编辑') }}</el-button
31
- >
32
- <el-button
33
- v-if="selectedItem !== item.viewName && item.viewName !== '所有的'"
34
- type="text"
35
- size="mini"
36
- @click.stop="deleteOne(item)"
37
- >{{ $lc('删除') }}</el-button
38
- >
39
- </div>
40
- </template>
41
- </cl-drag-list>
20
+ <cl-input-search v-model="val" class="w-100p" placeholder="请输入关键字" />
21
+ <div style="color: var(--color-text-secondary); margin: 12px 0 8px 0">{{ $lc('自定义视图') }}</div>
22
+ <div class="filter-view-wrapper">
23
+ <cl-drag-list class="flex-item" :list="filteredList" :hide-delete="true" @change="fn">
24
+ <template v-slot="{ item }">
25
+ <div class="proFilterView-list-item" :class="{ 'is-selected': selectedItem === item.viewName }">
26
+ <span class="proFilterView-list-item__name" :title="item.viewName" @click="handleSelect(item)">{{
27
+ item.viewName
28
+ }}</span>
29
+ <i v-if="selectedItem === item.viewName" class="el-icon-check selected-icon"></i>
30
+ <el-dropdown
31
+ v-if="selectedItem !== item.viewName && item.viewName !== '无视图'"
32
+ trigger="click"
33
+ class="proFilterView-list-item__more"
34
+ @command="(command) => handleCommand(command, item)"
35
+ >
36
+ <i class="v3-icon-more"></i>
37
+ <el-dropdown-menu slot="dropdown">
38
+ <el-dropdown-item command="edit">{{ $lc('编辑') }}</el-dropdown-item>
39
+ <el-dropdown-item command="delete">{{ $lc('删除') }}</el-dropdown-item>
40
+ </el-dropdown-menu>
41
+ </el-dropdown>
42
+ </div>
43
+ </template>
44
+ </cl-drag-list>
45
+ </div>
46
+ <div class="ProFilterView_divider"></div>
42
47
  <div class="flex-box flex-v flex-l ProFilterView-add">
43
48
  <img src="./plus.svg" alt="" />
44
49
  <div @click="add">{{ $lc('新建视图') }}</div>
@@ -104,7 +109,7 @@
104
109
  prop="viewName"
105
110
  :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
106
111
  >
107
- <el-input maxlength="30" show-word-limit v-model="form.viewName" />
112
+ <el-input v-model="form.viewName" maxlength="30" show-word-limit />
108
113
  </el-form-item>
109
114
  <div class="flex-box flex-lr flex-v">
110
115
  <div>{{ $lc('数据范围') }}</div>
@@ -201,8 +206,8 @@ export default {
201
206
  data() {
202
207
  return {
203
208
  val: '',
204
- list: ['所有的'],
205
- selectedItem: '所有的', // 默认选中第一项
209
+ list: ['无视图'],
210
+ selectedItem: '无视图', // 默认选中第一项
206
211
  stVisible: false,
207
212
  visible: false,
208
213
  isAdd: false,
@@ -225,11 +230,16 @@ export default {
225
230
  }
226
231
  },
227
232
  computed: {
233
+ /**
234
+ * 本地搜索过滤视图列表
235
+ * @returns {Array} 根据 val 关键字过滤后的视图列表;val 为空时返回完整列表
236
+ */
228
237
  filteredList() {
229
238
  if (!this.val) {
230
239
  return this.list
231
240
  }
232
- return this.list.filter((item) => item.toLowerCase().includes(this.val.toLowerCase()))
241
+ const keyword = this.val.toLowerCase()
242
+ return this.list.filter((item) => item.viewName && item.viewName.toLowerCase().includes(keyword))
233
243
  },
234
244
  getInitialSearchValue() {
235
245
  const obj = {}
@@ -262,6 +272,13 @@ export default {
262
272
  this.searchValue = { ...this.getInitialSearchValue }
263
273
  },
264
274
  methods: {
275
+ handleCommand(command, item) {
276
+ const commandMap = {
277
+ edit: () => this.edit(item),
278
+ delete: () => this.deleteOne(item)
279
+ }
280
+ commandMap[command]()
281
+ },
265
282
  setOptions(id, opts) {
266
283
  this.$refs.filter.setOptions(id, opts)
267
284
  this.filterList.forEach((item) => {
@@ -305,7 +322,7 @@ export default {
305
322
  })
306
323
  this.list = [
307
324
  {
308
- viewName: '所有的'
325
+ viewName: '无视图'
309
326
  },
310
327
  ...list
311
328
  ]
@@ -320,7 +337,7 @@ export default {
320
337
  .catch((err) => {
321
338
  this.list = [
322
339
  {
323
- viewName: '所有的'
340
+ viewName: '无视图'
324
341
  }
325
342
  ]
326
343
  })
@@ -342,6 +359,8 @@ export default {
342
359
  this.searchForm = {
343
360
  ...this.getInitialSearchValue
344
361
  }
362
+ // 新建时重置切换缓存
363
+ this._savedViewConfigs = {}
345
364
  },
346
365
  // 修改
347
366
  edit(item, isRefresh = false) {
@@ -354,10 +373,17 @@ export default {
354
373
  // 赋值操作
355
374
  this.form = item
356
375
  this.viewId = item.viewId
376
+ // 初始化两种类型的已保存数据缓存,供 typeChange 切换时恢复使用
377
+ this._savedViewConfigs = {}
357
378
  if (item.viewType === '0') {
358
- this.searchForm = { ...this.getInitialSearchValue, ...JSON.parse(item.viewConfig) }
379
+ const parsed = JSON.parse(item.viewConfig || '{}')
380
+ this.searchForm = { ...this.getInitialSearchValue, ...parsed }
381
+ this._savedViewConfigs['0'] = { ...parsed }
359
382
  } else {
360
- this.conditionGroups = JSON.parse(item.viewConfig)?.conditionGroups || []
383
+ const parsed = JSON.parse(item.viewConfig || '{}')
384
+ this.conditionGroups = parsed.conditionGroups || []
385
+
386
+ this._savedViewConfigs['1'] = { conditionGroups: this.conditionGroups }
361
387
  }
362
388
  },
363
389
  // 保存筛选条件
@@ -377,29 +403,51 @@ export default {
377
403
  viewConfig = JSON.stringify({ conditionGroups: this.conditionGroups })
378
404
  keyIds = []
379
405
  }
406
+ console.log(this.conditionGroups)
380
407
  this.form.viewConfig = viewConfig
381
- if (this.isAdd) {
382
- if (this.form.viewName === '') {
408
+
409
+ const hasEmptyValue = this.conditionGroups.some((group) =>
410
+ group.conditions.some((condition) => {
411
+ const val = condition.value
412
+ return val === null || val === undefined || val === '' || (Array.isArray(val) && val.length === 0)
413
+ })
414
+ )
415
+
416
+ this.$refs.form.validate(async (valid) => {
417
+ if (!valid) {
383
418
  this.$message.error('请输入视图名称')
384
- return false
419
+ return
385
420
  }
386
- }
387
- // 保存筛选视图
388
- const obj = {
389
- viewName: this.form.viewName,
390
- viewType: this.form.viewType,
391
- bussId: this.bussId,
392
- viewConfig: this.form.viewConfig,
393
- keyIds: JSON.stringify(keyIds),
394
- viewId: this.viewId
395
- }
396
- axios.post('/bems/query/viewColumn/saveOrUpdateViewInfo', obj).then((res) => {
397
- if (res.code !== 200) {
398
- return false
421
+
422
+ if (this.form.viewType === '0' && !keyIds.length) {
423
+ this.$message.warning('至少添加一个条件')
424
+ return
425
+ }
426
+ if (this.form.viewType === '1') {
427
+ if (!this.conditionGroups.length || hasEmptyValue) {
428
+ this.$message.warning('至少添加一个条件')
429
+ return
430
+ }
399
431
  }
400
- this.visible = false
401
- this.$message.success('保存成功')
402
- this.getFilterList(this.viewId)
432
+
433
+ // 保存筛选视图
434
+ const obj = {
435
+ viewName: this.form.viewName,
436
+ viewType: this.form.viewType,
437
+ bussId: this.bussId,
438
+ viewConfig: this.form.viewConfig,
439
+ keyIds: JSON.stringify(keyIds),
440
+ viewId: this.viewId
441
+ }
442
+
443
+ axios.post('/bems/query/viewColumn/saveOrUpdateViewInfo', obj).then((res) => {
444
+ if (res.code !== 200) {
445
+ return false
446
+ }
447
+ this.visible = false
448
+ this.$message.success('保存成功')
449
+ this.getFilterList(this.viewId)
450
+ })
403
451
  })
404
452
  },
405
453
  // 删除
@@ -423,7 +471,7 @@ export default {
423
471
  this.stVisible = false
424
472
  this.selectItem = item
425
473
  this.selectedItem = item.viewName
426
- if (item.viewName === '所有的') {
474
+ if (item.viewName === '无视图') {
427
475
  this.selectItem = ''
428
476
  this.searchValue = {}
429
477
  this.conditionGroups = []
@@ -441,12 +489,34 @@ export default {
441
489
  fn(list) {
442
490
  console.log('当前list:', list)
443
491
  },
444
- // 查询切换
492
+ /**
493
+ * 查询类型切换(基础查询 <-> 高级查询)
494
+ * 切换时优先从已保存的 viewConfig 中恢复对应类型的数据,
495
+ * 若无已保存数据则重置为初始值
496
+ */
445
497
  typeChange() {
446
498
  this.form.viewType = this.form.viewType === '0' ? '1' : '0'
499
+ // 切换到基础查询(viewType === '0')
447
500
  if (this.form.viewType === '0') {
448
501
  this.conditionGroups = []
502
+ // 若已有保存的 viewConfig 且原始类型也是基础查询,则恢复已保存的搜索条件
503
+ const savedConfig = this._savedViewConfigs && this._savedViewConfigs['0']
504
+ if (savedConfig) {
505
+ this.searchForm = { ...this.getInitialSearchValue, ...savedConfig }
506
+ } else {
507
+ this.searchForm = { ...this.getInitialSearchValue }
508
+ }
449
509
  } else {
510
+ // 切换到高级查询(viewType === '1'),先保存当前基础查询数据
511
+ if (!this._savedViewConfigs) this._savedViewConfigs = {}
512
+ this._savedViewConfigs['0'] = { ...this.searchForm }
513
+ // 恢复已保存的高级查询数据,若无则重置
514
+ const savedConfig = this._savedViewConfigs['1']
515
+ if (savedConfig) {
516
+ this.conditionGroups = savedConfig.conditionGroups || []
517
+ } else {
518
+ this.conditionGroups = []
519
+ }
450
520
  this.searchForm = { ...this.getInitialSearchValue }
451
521
  }
452
522
  }