116 lines
3.3 KiB
TypeScript
116 lines
3.3 KiB
TypeScript
|
|
import { ref, computed, type Ref } from 'vue'
|
||
|
|
import { http } from '@/api'
|
||
|
|
import type { PushServerItem } from './types'
|
||
|
|
|
||
|
|
export function usePushServers(pushStatus: Ref<Record<number, string>>) {
|
||
|
|
const servers = ref<PushServerItem[]>([])
|
||
|
|
const serversLoading = ref(false)
|
||
|
|
const serverSearch = ref('')
|
||
|
|
const selectedIds = ref<Set<number>>(new Set())
|
||
|
|
|
||
|
|
let refreshTimer: ReturnType<typeof setInterval> | null = null
|
||
|
|
|
||
|
|
async function loadServers() {
|
||
|
|
serversLoading.value = true
|
||
|
|
try {
|
||
|
|
const res = await http.get<{ items: PushServerItem[] }>('/servers/', { per_page: 200 })
|
||
|
|
servers.value = res.items || []
|
||
|
|
} catch {
|
||
|
|
servers.value = []
|
||
|
|
} finally {
|
||
|
|
serversLoading.value = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function startAutoRefresh(isPushing: () => boolean) {
|
||
|
|
stopAutoRefresh()
|
||
|
|
refreshTimer = setInterval(() => {
|
||
|
|
if (!isPushing()) loadServers()
|
||
|
|
}, 60_000)
|
||
|
|
}
|
||
|
|
|
||
|
|
function stopAutoRefresh() {
|
||
|
|
if (refreshTimer) {
|
||
|
|
clearInterval(refreshTimer)
|
||
|
|
refreshTimer = null
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const filteredServers = computed(() => {
|
||
|
|
if (!serverSearch.value) return servers.value
|
||
|
|
const q = serverSearch.value.toLowerCase()
|
||
|
|
return servers.value.filter(
|
||
|
|
s => s.name.toLowerCase().includes(q) || (s.domain || '').toLowerCase().includes(q),
|
||
|
|
)
|
||
|
|
})
|
||
|
|
|
||
|
|
const selectAll = computed(() => {
|
||
|
|
const visible = filteredServers.value
|
||
|
|
return visible.length > 0 && visible.every(s => selectedIds.value.has(s.id))
|
||
|
|
})
|
||
|
|
|
||
|
|
const serversByCategory = computed(() => {
|
||
|
|
const groups: Record<string, PushServerItem[]> = {}
|
||
|
|
for (const s of filteredServers.value) {
|
||
|
|
const cat = s.category || '未分类'
|
||
|
|
if (!groups[cat]) groups[cat] = []
|
||
|
|
groups[cat].push(s)
|
||
|
|
}
|
||
|
|
return Object.entries(groups).map(([category, list]) => ({ category, servers: list }))
|
||
|
|
})
|
||
|
|
|
||
|
|
function isCategoryAllSelected(category: string): boolean {
|
||
|
|
const group = serversByCategory.value.find(g => g.category === category)
|
||
|
|
if (!group || group.servers.length === 0) return false
|
||
|
|
return group.servers.every(s => selectedIds.value.has(s.id))
|
||
|
|
}
|
||
|
|
|
||
|
|
function toggleCategory(category: string) {
|
||
|
|
const group = serversByCategory.value.find(g => g.category === category)
|
||
|
|
if (!group) return
|
||
|
|
const next = new Set(selectedIds.value)
|
||
|
|
const allSelected = group.servers.every(srv => next.has(srv.id))
|
||
|
|
for (const srv of group.servers) {
|
||
|
|
if (allSelected) next.delete(srv.id)
|
||
|
|
else next.add(srv.id)
|
||
|
|
}
|
||
|
|
selectedIds.value = next
|
||
|
|
}
|
||
|
|
|
||
|
|
function toggleServer(id: number) {
|
||
|
|
const next = new Set(selectedIds.value)
|
||
|
|
if (next.has(id)) next.delete(id)
|
||
|
|
else next.add(id)
|
||
|
|
selectedIds.value = next
|
||
|
|
}
|
||
|
|
|
||
|
|
function toggleAll() {
|
||
|
|
const visible = filteredServers.value
|
||
|
|
const allSelected = visible.length > 0 && visible.every(s => selectedIds.value.has(s.id))
|
||
|
|
const next = new Set(selectedIds.value)
|
||
|
|
for (const srv of visible) {
|
||
|
|
if (allSelected) next.delete(srv.id)
|
||
|
|
else next.add(srv.id)
|
||
|
|
}
|
||
|
|
selectedIds.value = next
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
servers,
|
||
|
|
serversLoading,
|
||
|
|
serverSearch,
|
||
|
|
selectedIds,
|
||
|
|
pushStatus,
|
||
|
|
filteredServers,
|
||
|
|
selectAll,
|
||
|
|
serversByCategory,
|
||
|
|
loadServers,
|
||
|
|
startAutoRefresh,
|
||
|
|
stopAutoRefresh,
|
||
|
|
isCategoryAllSelected,
|
||
|
|
toggleCategory,
|
||
|
|
toggleServer,
|
||
|
|
toggleAll,
|
||
|
|
}
|
||
|
|
}
|