Files
dygou_go/frontend/src/composables/useAccounts.ts
T
yml2213 2c88edb741 重构: 应用代码移入 internal/app 包,根目录只留入口
根目录原 7 个 app*.go 平铺,现收进 internal/app/ 子包:
- package main → package app
- NewApp → New(导出)
- startup/shutdown → Startup/Shutdown(导出,供 main.go 引用)
- main.go 改为薄入口,仅导入 internal/app 并装配 Wails

前端同步更新(Wails 绑定路径 go/main → go/app):
- window.go.main.App → window.go.app.App(10 处)
- env.d.ts 类型声明路径 wailsjs/go/main/App → wailsjs/go/app/App

根目录 Go 文件从 7 个减至 1 个(main.go),元文件更清晰
2026-07-29 13:27:08 +08:00

230 lines
5.8 KiB
TypeScript

import { ref } from 'vue'
import { useToast } from './useToast'
export interface Account {
index: number
name: string
cookie: string
}
export interface AccountStatus {
ok?: boolean
pending?: boolean
message?: string
}
const App = window.go.app.App
const accounts = ref<Account[]>([])
const selectedIndices = ref<Set<number>>(new Set())
const statusMap = ref<Record<string, AccountStatus | boolean>>({})
const scoreMap = ref<Record<string, string>>({})
export function useAccounts() {
const { showToast } = useToast()
const loadAccounts = async () => {
const data = await App.GetAccounts()
accounts.value = data || []
// 清理无效选择
selectedIndices.value = new Set(
[...selectedIndices.value].filter(i => i >= 0 && i < accounts.value.length)
)
saveSelection()
}
const reloadAccounts = async () => {
const data = await App.ReloadAccounts()
await loadAccounts()
showToast('账号已刷新', `共 ${data.count} 个账号`, 'success')
}
const toggleAccount = (index: number) => {
if (selectedIndices.value.has(index)) {
selectedIndices.value.delete(index)
} else {
selectedIndices.value.add(index)
}
saveSelection()
}
const toggleAll = () => {
if (selectedIndices.value.size === accounts.value.length) {
selectedIndices.value.clear()
} else {
accounts.value.forEach((_, i) => selectedIndices.value.add(i))
}
saveSelection()
}
const saveSelection = () => {
localStorage.setItem('selAccs', JSON.stringify([...selectedIndices.value]))
}
const restoreSelection = () => {
const saved = localStorage.getItem('selAccs')
if (saved) {
try {
selectedIndices.value = new Set(JSON.parse(saved))
} catch {}
}
const savedStatus = localStorage.getItem('statusMap')
if (savedStatus) {
try {
statusMap.value = JSON.parse(savedStatus)
} catch {}
}
}
const queryAllScore = async () => {
showToast('查询积分', '正在并发查询...', 'info')
const tasks = accounts.value.map(async (a) => {
try {
const d = await App.QueryScore(a.name)
const score = d.score ?? 'N/A'
scoreMap.value[a.name] = String(score)
localStorage.setItem('accScore_' + a.name, String(score))
} catch {}
})
await Promise.all(tasks)
showToast('积分查询完成', '', 'success')
}
const getScore = (name: string): string => {
return scoreMap.value[name] || localStorage.getItem('accScore_' + name) || '-'
}
const resetStatus = () => {
statusMap.value = {}
localStorage.removeItem('statusMap')
}
const setStatuses = (statuses: Record<string, AccountStatus | boolean>) => {
statusMap.value = statuses
if (Object.keys(statusMap.value).length > 0) {
localStorage.setItem('statusMap', JSON.stringify(statusMap.value))
} else {
localStorage.removeItem('statusMap')
}
}
const mergeStatuses = (statuses: Record<string, AccountStatus | boolean>) => {
setStatuses({
...statusMap.value,
...statuses
})
}
const setStatus = (name: string, status: AccountStatus | boolean) => {
mergeStatuses({ [name]: status })
}
const selectedAccountNames = (): string[] => {
return [...selectedIndices.value]
.map(i => accounts.value[i]?.name)
.filter(Boolean) as string[]
}
const markSelectedStatus = (status: AccountStatus | boolean) => {
const next: Record<string, AccountStatus | boolean> = {}
selectedAccountNames().forEach(name => {
next[name] = typeof status === 'object' ? { ...status } : status
})
mergeStatuses(next)
}
const markSelectedPending = (message = '抢购中,等待后端结果') => {
markSelectedStatus({ pending: true, message })
}
const buildAccountProducts = (productId: string): Record<string, string> | null => {
if (selectedIndices.value.size === 0) {
showToast('提示', '请勾选要抢购的账号', 'warn')
return null
}
if (!productId) {
showToast('提示', '请先选择商品', 'warn')
return null
}
const ap: Record<string, string> = {}
selectedIndices.value.forEach(i => {
const account = accounts.value[i]
if (account) {
ap[account.name] = productId
}
})
if (Object.keys(ap).length === 0) {
showToast('提示', '没有有效账号可提交', 'warn')
return null
}
return ap
}
return {
accounts,
selectedIndices,
statusMap,
scoreMap,
loadAccounts,
reloadAccounts,
toggleAccount,
toggleAll,
restoreSelection,
queryAllScore,
getScore,
resetStatus,
setStatuses,
mergeStatuses,
setStatus,
markSelectedStatus,
markSelectedPending,
selectedAccountNames,
buildAccountProducts
}
}
export function useVerifyExchange() {
const { accounts } = useAccounts()
const verifyResults = ref<Record<string, any>>({})
const verifying = ref(false)
const verifyAccount = async (accountName: string) => {
try {
const result = await App.VerifyExchange(accountName)
verifyResults.value[accountName] = result
return result
} catch (e: any) {
verifyResults.value[accountName] = { success: false, error: e.message }
return { success: false, error: e.message }
}
}
const verifyAll = async () => {
verifying.value = true
try {
// 使用后端批量查询接口,自带间隔
const results = await App.VerifyAllExchange()
verifyResults.value = results || {}
} catch (e: any) {
console.error('批量复验失败:', e)
} finally {
verifying.value = false
}
}
const clearResults = () => {
verifyResults.value = {}
}
return {
verifyResults,
verifying,
verifyAccount,
verifyAll,
clearResults
}
}