@xuekl/cli-components 1.9.145 → 1.9.147

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/XklDict.vue CHANGED
@@ -2,11 +2,11 @@
2
2
  <div v-if="fakeRender && (!selectData || (selectData && !selectData.length))" class="fake-render el-input__wrapper"
3
3
  :class="{ 'el-select__wrapper is-disabled': disabled || readonly }" @click="updateRender">
4
4
  <span class="fs-14">{{ $attrs.placeholder
5
- }}</span>
5
+ }}</span>
6
6
  </div>
7
7
  <el-select v-else style="width: 100%;" ref="XklDictRef" v-model="selectData" :automatic-dropdown="true"
8
- :class="{ 'readony-input': readonly }" @change="changeHandle" :filterable="initFilterable"
9
- :disabled="disabled || readonly" :filter-method="filterMethod">
8
+ :class="{ 'readony-input': readonly }" @visible-change="visibleChange" @change="changeHandle"
9
+ :filterable="initFilterable" :disabled="disabled || readonly" :filter-method="filterMethod">
10
10
  <el-option v-for="item in list" :key="item.dictValue" :label="item.dictLabel"
11
11
  :value="item.dictValue"></el-option>
12
12
  </el-select>
@@ -24,12 +24,13 @@ import { nextTick } from 'vue';
24
24
  interface DictItem {
25
25
  dictCode: string, dictLabel: string, dictValue: string | number
26
26
  }
27
- const props = defineProps(['config', 'filterable', 'readonly', 'disabled', 'modelValue', 'fake'])
28
- const emit = defineEmits(['update:label', 'itemChange', 'loaded', 'update:modelValue'])
27
+ const props = defineProps(['config', 'filterable', 'readonly', 'disabled', 'modelValue', 'fake', 'displaySelectedDataFirst'])
28
+ const emit = defineEmits(['update:label', 'itemChange', 'loaded', 'update:modelValue', 'visibleChange'])
29
29
 
30
- const { config, filterable, readonly, fake } = props
30
+ const { config, filterable, readonly, fake, displaySelectedDataFirst } = props
31
31
  const list: Ref<DictItem[]> = ref([])
32
32
 
33
+ const isDisplaySelectedDataFirst = displaySelectedDataFirst !== false
33
34
  const isFake = typeof fake === 'undefined' ? true : fake
34
35
  const fakeRender = ref(isFake)
35
36
  const XklDictRef: any = ref(null)
@@ -67,6 +68,37 @@ const filterMethod = (val: any) => {
67
68
  }
68
69
  }
69
70
 
71
+ const visibleChange = (visible: boolean) => {
72
+ if (isDisplaySelectedDataFirst) {
73
+ if (visible) {
74
+ // ✅ 稳定排序逻辑:已选中的排前面,且两组内部都保留原数组顺序
75
+ list.value = list.value.sort((a, b) => {
76
+ // 1. 获取a、b的选中状态
77
+ const aIsSelected = selectData.value && (
78
+ Array.isArray(selectData.value)
79
+ ? selectData.value.includes(a.dictValue)
80
+ : selectData.value === a.dictValue
81
+ );
82
+ const bIsSelected = selectData.value && (
83
+ Array.isArray(selectData.value)
84
+ ? selectData.value.includes(b.dictValue)
85
+ : selectData.value === b.dictValue
86
+ );
87
+
88
+ // ✅ 核心稳定排序规则
89
+ if (aIsSelected && !bIsSelected) {
90
+ return -1; // a选中、b未选 → a排前面
91
+ } else if (!aIsSelected && bIsSelected) {
92
+ return 1; // a未选、b选中 → b排前面
93
+ } else {
94
+ return 0; // 同为选中/同为未选 → 保持原有相对顺序【关键】
95
+ }
96
+ })
97
+ }
98
+ }
99
+ emit('visibleChange', visible)
100
+ }
101
+
70
102
  const changeHandle = (val: string | number | string[] | number[]) => {
71
103
  if (Array.isArray(val)) {
72
104
  const values: (string | number)[] = val
package/XklSelect.vue CHANGED
@@ -2,12 +2,12 @@
2
2
  <div v-if="fakeRender && (!selectData || (selectData && !selectData.length))" class="fake-render el-input__wrapper"
3
3
  :class="{ 'el-select__wrapper is-disabled': disabled || readonly }" @click="updateRender">
4
4
  <span class="fs-14">{{ $attrs.placeholder
5
- }}</span>
5
+ }}</span>
6
6
  </div>
7
7
  <el-select v-else ref="XklSelectRef" :automatic-dropdown="true" v-model="selectData"
8
- :class="{ 'readony-input': readonly }" style="width: 100%;" @change="changeHandle" :filterable="initFilterable"
9
- :disabled="disabled || readonly" :filter-method="filterMethod" :allow-create="allowCreate"
10
- :multiple-limit="multipleLimit" @focus="onClick()">
8
+ :class="{ 'readony-input': readonly }" style="width: 100%;" @visible-change="visibleChange"
9
+ @change="changeHandle" :filterable="initFilterable" :disabled="disabled || readonly"
10
+ :filter-method="filterMethod" :allow-create="allowCreate" :multiple-limit="multipleLimit" @focus="onClick()">
11
11
  <!-- <template v-if="createAtFirst && filterVal" #header>
12
12
  <div class="el-select-dropdown__item" @click="headerClick()">
13
13
  <OptionComponent v-if="config && config.customOption" :item="creatingItem" />
@@ -49,9 +49,9 @@ interface OptionItem extends SelectItem {
49
49
  isChecked?: boolean
50
50
  isSpecial?: boolean
51
51
  }
52
- const props = defineProps(['config', 'list', 'modelValue', 'filterable', 'readonly', 'disabled', 'cache', 'allowCreate', 'multipleLimit', 'createAtFirst', 'fake'])
53
- const emit = defineEmits(['update:label', 'click', 'loaded', 'update:modelValue', 'itemChange'])
54
- const { config, list, filterable, readonly, cache, allowCreate, multipleLimit, createAtFirst, fake } = props
52
+ const props = defineProps(['config', 'list', 'modelValue', 'filterable', 'readonly', 'disabled', 'cache', 'allowCreate', 'multipleLimit', 'createAtFirst', 'fake', 'displaySelectedDataFirst'])
53
+ const emit = defineEmits(['update:label', 'click', 'loaded', 'update:modelValue', 'itemChange', 'visibleChange'])
54
+ const { config, list, filterable, readonly, cache, allowCreate, multipleLimit, createAtFirst, fake, displaySelectedDataFirst } = props
55
55
  const appStore = useApp()
56
56
 
57
57
  const dataCahe = cache !== false
@@ -60,6 +60,7 @@ const dataList: Ref<OptionItem[]> = ref([])
60
60
 
61
61
  const initFilterable = ref(false)
62
62
 
63
+ const isDisplaySelectedDataFirst = displaySelectedDataFirst !== false
63
64
 
64
65
  const isFake = typeof fake === 'undefined' ? true : fake
65
66
  const fakeRender = ref(isFake)
@@ -238,6 +239,39 @@ const valChangeHandle = (val: string | number | string[] | number[]) => {
238
239
  }
239
240
  }
240
241
 
242
+ const visibleChange = (visible: boolean) => {
243
+ if (isDisplaySelectedDataFirst) {
244
+ if (visible) {
245
+ const valueTarget = config?.valueTarget;
246
+ // 无匹配字段则不排序,避免报错
247
+ if (!valueTarget) return;
248
+ // ✅ 稳定排序核心:a、b两两对比 + 同状态返回0 保持原顺序
249
+ dataList.value = dataList.value.sort((a, b) => {
250
+ // 获取当前项的匹配字段值
251
+ const aVal = a[valueTarget];
252
+ const bVal = b[valueTarget];
253
+ // 判断a/b的选中状态
254
+ const aIsSelected = selectData.value && (
255
+ Array.isArray(selectData.value)
256
+ ? selectData.value.includes(aVal)
257
+ : selectData.value === aVal
258
+ );
259
+ const bIsSelected = selectData.value && (
260
+ Array.isArray(selectData.value)
261
+ ? selectData.value.includes(bVal)
262
+ : selectData.value === bVal
263
+ );
264
+
265
+ // ✅ 排序规则:选中的排前面,同状态则保持原顺序
266
+ if (aIsSelected && !bIsSelected) return -1;
267
+ if (!aIsSelected && bIsSelected) return 1;
268
+ return 0;
269
+ });
270
+ }
271
+ }
272
+ emit('visibleChange', visible)
273
+ }
274
+
241
275
  const changeHandle = (val: string | number | string[] | number[]) => {
242
276
  if (allowCreate && createAtFirst) {
243
277
  // 在自动创建时,第一条的点击事件是晚于change事件的,目前的使用场景是要早于change事件
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuekl/cli-components",
3
- "version": "1.9.145",
3
+ "version": "1.9.147",
4
4
  "description": "element-plus 组件二次封装",
5
5
  "main": "index.ts",
6
6
  "scripts": {