feat: Refactor channel management and UI components
- Removed hardcoded channel data from `channel.ts` and replaced it with a dynamic channel dictionary. - Introduced a new Pinia store `channel.ts` to manage selected and available channels. - Reworked `AddChannelDialog.vue` to allow users to search and select channels dynamically. - Updated `TaskCenter.vue` to utilize the new channel store and handle empty channel selections gracefully. - Enhanced IPC communication for loading and saving selected channels in the configuration. - Adjusted `runTaskOperationService.ts` to ensure proper handling of channel data. - Improved styling and structure of UI components for better user experience.
This commit is contained in:
85
src/stores/channel.ts
Normal file
85
src/stores/channel.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useScriptStore } from '@stores/script'
|
||||
import { resolveChannel } from '@constant/channel'
|
||||
import { IPC_EVENTS, CONFIG_KEYS } from '@lib/constants'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
export interface ChannelItem {
|
||||
id: string
|
||||
channelName: string
|
||||
channelUrl: string
|
||||
}
|
||||
|
||||
export const useChannelStore = defineStore('channel', () => {
|
||||
const scriptStore = useScriptStore()
|
||||
|
||||
// 用户选中的"一键打开"渠道(持久化到 electron-store)
|
||||
const selectedChannels = ref<ChannelItem[]>([])
|
||||
|
||||
// 从脚本 store 动态聚合可用渠道(按 URL 去重)
|
||||
const availableChannels = computed<ChannelItem[]>(() => {
|
||||
const map = new Map<string, ChannelItem>()
|
||||
for (const script of scriptStore.safeScripts) {
|
||||
if (!script.channel) continue
|
||||
const resolved = resolveChannel(script.channel)
|
||||
const url = resolved.url
|
||||
if (url && !map.has(url)) {
|
||||
map.set(url, {
|
||||
id: uuidv4(),
|
||||
channelName: resolved.name || url,
|
||||
channelUrl: url,
|
||||
})
|
||||
}
|
||||
}
|
||||
return Array.from(map.values())
|
||||
})
|
||||
|
||||
const loadSelectedChannels = async () => {
|
||||
try {
|
||||
const result = await window.api.invoke(IPC_EVENTS.GET_CONFIG, CONFIG_KEYS.SELECTED_CHANNELS)
|
||||
if (Array.isArray(result)) {
|
||||
selectedChannels.value = result
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[channelStore] loadSelectedChannels failed:', err)
|
||||
}
|
||||
selectedChannels.value = []
|
||||
}
|
||||
|
||||
const saveSelectedChannels = async () => {
|
||||
try {
|
||||
// 深拷贝剥离 Vue Proxy,避免 IPC structured clone 失败
|
||||
const payload = JSON.parse(JSON.stringify(selectedChannels.value))
|
||||
await window.api.invoke(IPC_EVENTS.SET_CONFIG, CONFIG_KEYS.SELECTED_CHANNELS, payload)
|
||||
} catch (err) {
|
||||
console.error('[channelStore] saveSelectedChannels failed:', err)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
const addSelectedChannel = (item: ChannelItem) => {
|
||||
if (!selectedChannels.value.some((c) => c.channelUrl === item.channelUrl)) {
|
||||
selectedChannels.value.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
const removeSelectedChannel = (id: string) => {
|
||||
selectedChannels.value = selectedChannels.value.filter((c) => c.id !== id)
|
||||
}
|
||||
|
||||
const setSelectedChannels = (items: ChannelItem[]) => {
|
||||
selectedChannels.value = items
|
||||
}
|
||||
|
||||
return {
|
||||
selectedChannels,
|
||||
availableChannels,
|
||||
loadSelectedChannels,
|
||||
saveSelectedChannels,
|
||||
addSelectedChannel,
|
||||
removeSelectedChannel,
|
||||
setSelectedChannels,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user