cd-personselector 1.3.5 → 1.3.7

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": "cd-personselector",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "人员选择器组件 - 支持多Tab、树形结构、搜索、懒加载、输入框选择模式",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -25,40 +25,50 @@
25
25
  @tag-change="handleTagChange"
26
26
  >
27
27
  <template #panel>
28
- <div v-if="currentSearchResults.length > 0" class="cd-input-select__panel">
29
- <t-checkbox
30
- v-for="result in currentSearchResults"
31
- :key="result.id"
32
- :value="result.id"
33
- :checked="isSelected(result.id)"
34
- class="cd-input-select__option"
35
- @change="(checked: boolean) => handleCheckboxChange(checked, result)"
36
- >
37
- <div class="cd-input-select__option-content">
38
- <div v-if="result.avatar" class="cd-input-select__option-avatar">
39
- <img :src="result.avatar" :alt="result.name" />
40
- </div>
41
- <div v-else class="cd-input-select__option-avatar cd-input-select__option-avatar--placeholder"
42
- :style="{
43
- backgroundColor: getNodeTypeColor(result.nodeType),
44
- color: '#fff'
45
- }">
46
- {{ getNodeTypeIcon(result.nodeType) }}
47
- </div>
48
- <div class="cd-input-select__option-info">
49
- <div class="cd-input-select__option-name">{{ result.name }}</div>
50
- <div v-if="result.isUser && (result.department || result.post)" class="cd-input-select__option-desc">
51
- {{ result.department }}{{ result.department && result.post ? ' · ' : '' }}{{ result.post }}
28
+ <div v-if="currentSearchResults.length > 0" class="cd-input-select__panel" @mousedown.stop>
29
+ <div class="cd-input-select__grid">
30
+ <t-checkbox
31
+ v-for="result in paginatedSearchResults"
32
+ :key="result.id"
33
+ :value="result.id"
34
+ :checked="isSelected(result.id)"
35
+ class="cd-input-select__option"
36
+ @change="(checked: boolean) => handleCheckboxChange(checked, result)"
37
+ >
38
+ <div class="cd-input-select__option-content">
39
+ <div v-if="result.avatar" class="cd-input-select__option-avatar">
40
+ <img :src="result.avatar" :alt="result.name" />
52
41
  </div>
53
- <div v-else-if="result.fnumber" class="cd-input-select__option-desc">
54
- {{ result.fnumber }}
42
+ <div v-else class="cd-input-select__option-avatar cd-input-select__option-avatar--placeholder"
43
+ :style="{
44
+ backgroundColor: getNodeTypeColor(result.nodeType),
45
+ color: '#fff'
46
+ }">
47
+ {{ getNodeTypeIcon(result.nodeType) }}
55
48
  </div>
49
+ <div class="cd-input-select__option-info">
50
+ <div class="cd-input-select__option-name">{{ result.name }}</div>
51
+ <div v-if="result.isUser && (result.department || result.post)" class="cd-input-select__option-desc">
52
+ {{ result.department }}{{ result.department && result.post ? ' · ' : '' }}{{ result.post }}
53
+ </div>
54
+ <div v-else-if="result.fnumber" class="cd-input-select__option-desc">
55
+ {{ result.fnumber }}
56
+ </div>
57
+ </div>
58
+ <span class="cd-input-select__option-tag" :style="{ backgroundColor: getNodeTypeColor(result.nodeType) + '18', color: getNodeTypeColor(result.nodeType) }">
59
+ {{ getNodeTypeLabel(result.nodeType) }}
60
+ </span>
56
61
  </div>
57
- <span class="cd-input-select__option-tag" :style="{ backgroundColor: getNodeTypeColor(result.nodeType) + '18', color: getNodeTypeColor(result.nodeType) }">
58
- {{ getNodeTypeLabel(result.nodeType) }}
59
- </span>
62
+ </t-checkbox>
63
+ </div>
64
+ <div v-if="searchTotalPages > 1" class="cd-input-select__pager">
65
+ <span class="cd-input-select__pager-info">{{ currentSearchResults.length }} 条结果</span>
66
+ <div class="cd-input-select__pager-btns">
67
+ <t-button size="small" variant="text" :disabled="searchPage <= 1" @click="searchPage--">上一页</t-button>
68
+ <span class="cd-input-select__pager-num">{{ searchPage }}/{{ searchTotalPages }}</span>
69
+ <t-button size="small" variant="text" :disabled="searchPage >= searchTotalPages" @click="searchPage++">下一页</t-button>
60
70
  </div>
61
- </t-checkbox>
71
+ </div>
62
72
  </div>
63
73
  <div v-else-if="searchLoading" class="cd-input-select__loading">
64
74
  搜索中...
@@ -113,6 +123,13 @@ const emit = defineEmits<{
113
123
  }>();
114
124
  const searchLoading = ref(false);
115
125
  const currentSearchResults = ref<UserItem[]>([]);
126
+ const searchPage = ref(1);
127
+ const searchPageSize = 10;
128
+ const paginatedSearchResults = computed(() => {
129
+ const start = (searchPage.value - 1) * searchPageSize;
130
+ return currentSearchResults.value.slice(start, start + searchPageSize);
131
+ });
132
+ const searchTotalPages = computed(() => Math.ceil(currentSearchResults.value.length / searchPageSize));
116
133
  const showPersonSelector = ref(false);
117
134
  const selectedIds = ref<(string | number)[]>([]);
118
135
  const selectedOptions = ref<UserItem[]>([]);
@@ -295,6 +312,7 @@ watch(inputValue, (keyword) => {
295
312
  keyword,
296
313
  callback: (results: UserItem[]) => {
297
314
  currentSearchResults.value = results;
315
+ searchPage.value = 1;
298
316
  searchLoading.value = false;
299
317
  if (results.length > 0) {
300
318
  popupVisible.value = true;
@@ -331,10 +349,37 @@ watch(inputValue, (keyword) => {
331
349
  margin: 0 !important;
332
350
  }
333
351
  &__panel {
334
- max-height: 300px;
352
+ max-height: 400px;
335
353
  overflow-y: auto;
336
354
  width: 100%;
337
355
  box-sizing: border-box;
356
+ padding: 4px;
357
+ }
358
+ &__grid {
359
+ display: grid;
360
+ grid-template-columns: 1fr 1fr;
361
+ gap: 4px;
362
+ }
363
+ &__pager {
364
+ display: flex;
365
+ align-items: center;
366
+ justify-content: space-between;
367
+ padding: 6px 8px;
368
+ border-top: 1px solid #e5e7eb;
369
+ margin-top: 4px;
370
+ &-info {
371
+ font-size: 12px;
372
+ color: #999;
373
+ }
374
+ &-btns {
375
+ display: flex;
376
+ align-items: center;
377
+ gap: 4px;
378
+ }
379
+ &-num {
380
+ font-size: 12px;
381
+ color: #666;
382
+ }
338
383
  }
339
384
  &__loading,
340
385
  &__empty {