@@ -10,7 +10,7 @@ const props = defineProps({
1010 type: Array as PropType <Site []>,
1111 required: true ,
1212 },
13- selected: Array as PropType <Number []>,
13+ selected: Array as PropType <number []>,
1414})
1515
1616// 定义事件
@@ -20,38 +20,66 @@ const emit = defineEmits(['close', 'search', 'reload'])
2020const siteFilter = ref (' ' )
2121
2222// 已选择站点
23- const selectedSites = ref <any []>(props . selected || [])
23+ const selectedSites = ref <number []>([])
2424
25- watch (
26- () => props .selected ,
27- value => {
28- if (selectedSites .value .length == 0 && value ) {
29- selectedSites .value = value
25+ // 根据当前可用站点清理选中项,避免停用或已删除站点参与计数。
26+ function normalizeSelectedSites(selectedSiteIds : number [] = []) {
27+ const availableSiteIds = new Set (props .sites .map ((site : Site ) => site .id ))
28+ const normalizedSiteIds: number [] = []
29+
30+ selectedSiteIds .forEach (siteId => {
31+ if (availableSiteIds .has (siteId ) && ! normalizedSiteIds .includes (siteId )) {
32+ normalizedSiteIds .push (siteId )
3033 }
34+ })
35+
36+ return normalizedSiteIds
37+ }
38+
39+ watch (
40+ [() => props .selected , () => props .sites ],
41+ ([value ]) => {
42+ selectedSites .value = normalizeSelectedSites (value || [])
3143 },
44+ { immediate: true },
3245)
3346
3447// 全选/全不选按钮文字
3548const checkAllText = computed (() => {
36- return selectedSites .value .length < props .sites ? .length
49+ return selectedSites .value .length < props .sites .length
3750 ? t (' dialog.searchSite.selectAll' )
3851 : t (' dialog.searchSite.deselectAll' )
3952})
4053
4154// 全选/全不选
4255const checkAllSitesorNot = () => {
43- if (selectedSites .value .length < props .sites ? .length ) {
44- selectedSites .value = props .sites ? .map ((item : Site ) => item .id )
56+ if (selectedSites .value .length < props .sites .length ) {
57+ selectedSites .value = props .sites .map ((item : Site ) => item .id )
4558 } else {
4659 selectedSites .value = []
4760 }
4861}
4962
63+ // 切换单个站点的选择状态。
64+ function toggleSiteSelection(siteId : number ) {
65+ const index = selectedSites .value .indexOf (siteId )
66+ if (index === - 1 ) {
67+ selectedSites .value .push (siteId )
68+ } else {
69+ selectedSites .value .splice (index , 1 )
70+ }
71+ }
72+
73+ // 确认搜索时只提交当前可用站点。
74+ function confirmSearch() {
75+ emit (' search' , normalizeSelectedSites (selectedSites .value ))
76+ }
77+
5078// 根据筛选条件过滤站点
5179const filteredSites = computed (() => {
5280 if (! siteFilter .value ) return props .sites
5381 const filter = siteFilter .value .toLowerCase ()
54- return props .sites ? .filter ((site : Site ) => site .name .toLowerCase ().includes (filter ))
82+ return props .sites .filter ((site : Site ) => site .name .toLowerCase ().includes (filter ))
5583})
5684 </script >
5785<template >
@@ -107,16 +135,7 @@ const filteredSites = computed(() => {
107135 'site-hover': isHovering && !selectedSites.includes(site.id),
108136 },
109137 ]"
110- @click ="
111- () => {
112- const index = selectedSites.indexOf(site.id)
113- if (index === -1) {
114- selectedSites.push(site.id)
115- } else {
116- selectedSites.splice(index, 1)
117- }
118- }
119- "
138+ @click =" toggleSiteSelection(site.id)"
120139 >
121140 <VIcon
122141 :icon =" selectedSites.includes(site.id) ? 'mdi-check-circle' : 'mdi-checkbox-blank-circle-outline'"
@@ -161,7 +180,7 @@ const filteredSites = computed(() => {
161180 <VBtn
162181 color =" primary"
163182 :disabled =" selectedSites.length === 0"
164- @click =" emit('search', selectedSites) "
183+ @click =" confirmSearch "
165184 prepend-icon =" mdi-magnify"
166185 class =" d-flex align-center justify-center px-5"
167186 >
0 commit comments