From e45c8ec800f5236852417efcc62de368bd461d99 Mon Sep 17 00:00:00 2001 From: SonderXiaoming <1316864423@qq.com> Date: Thu, 2 Jul 2026 01:11:25 -0400 Subject: [PATCH 1/2] tw support --- src/api/Account.ts | 19 +++- src/components/Account/Info.tsx | 96 ++++++++++++------- src/components/SideBar/Index.tsx | 2 +- src/interfaces/Account.ts | 4 + .../daily/_sidebar/account/$account.tsx | 14 ++- vite.config.ts | 40 ++++---- 6 files changed, 110 insertions(+), 65 deletions(-) diff --git a/src/api/Account.ts b/src/api/Account.ts index 0ea0f42..7c2df56 100644 --- a/src/api/Account.ts +++ b/src/api/Account.ts @@ -85,13 +85,24 @@ export async function delAccount(alias: string) { return response.data; } -export async function putAccount(alias: string, account: string, password: string, channel: string, batch_accounts: (string | number)[]) { - const response = await API.put(`/account/${alias}`, { +export async function putAccount( + alias: string, + account: string, + password: string, + channel: string, + batch_accounts: (string | number)[], + viewer_id?: number, +) { + const payload: Record = { username: account, password: password, channel: channel, - batch_accounts: batch_accounts - }); + batch_accounts: batch_accounts, + }; + if (channel === '台服') { + payload.viewer_id = viewer_id ?? 0; + } + const response = await API.put(`/account/${alias}`, payload); return response.data; } diff --git a/src/components/Account/Info.tsx b/src/components/Account/Info.tsx index 0b13902..49c2ca5 100644 --- a/src/components/Account/Info.tsx +++ b/src/components/Account/Info.tsx @@ -23,9 +23,11 @@ import { toaster } from '../../components/ui/toaster'; interface InfoProps { accountInfo: AccountResponse; - onSaveSuccess?: () => void; // 添加回调函数属性 + onSaveSuccess?: () => void; } +const TW_CHANNEL = '台服'; + const fadeEntry = keyframes` from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } @@ -35,32 +37,42 @@ export default function Info({ accountInfo, onSaveSuccess }: InfoProps) { const [username, setUsername] = useState(accountInfo?.username); const [password, setPassword] = useState(accountInfo?.password); const [channel, setChannel] = useState(accountInfo?.channel); + const [viewerId, setViewerId] = useState( + accountInfo?.viewer_id ? String(accountInfo.viewer_id) : '', + ); const [batchAccounts, setBatchAccounts] = useState<(string | number)[]>(accountInfo?.batch_accounts || []); const { open: isOpen, onOpen, onClose } = useDisclosure(); - // 全选状态 const [allChecked, setAllChecked] = useState(false); - // 未选择的账号列表 const [unselectedAccounts, setUnselectedAccounts] = useState<(string | number)[]>([]); + const isTw = channel === TW_CHANNEL; + + useEffect(() => { + setUsername(accountInfo?.username); + setPassword(accountInfo?.password); + setChannel(accountInfo?.channel); + setViewerId(accountInfo?.viewer_id ? String(accountInfo.viewer_id) : ''); + }, [accountInfo]); - // 初始化未选择的账号列表 useEffect(() => { if (accountInfo?.all_accounts && accountInfo?.batch_accounts) { const unselected = accountInfo.all_accounts.filter((account) => !accountInfo.batch_accounts.includes(account)); setUnselectedAccounts(unselected); - - // 检查是否全选 setAllChecked(accountInfo.batch_accounts.length === accountInfo.all_accounts.length); } }, [accountInfo]); const handleSave = (e: React.FormEvent) => { e.preventDefault(); + if (isTw && !viewerId.trim()) { + toaster.create({ title: '保存失败', description: '台服账号需要填写 Viewer ID', type: 'error' }); + return; + } onOpen(); - putAccount(accountInfo?.alias, username, password, channel, batchAccounts) + const parsedViewerId = isTw ? Number(viewerId.trim()) : undefined; + putAccount(accountInfo?.alias, username, password, channel, batchAccounts, parsedViewerId) .then((res) => { toaster.create({ title: '保存成功', description: res, type: 'success' }); - // 调用回调函数通知父组件更新数据 if (onSaveSuccess) { onSaveSuccess(); } @@ -78,30 +90,24 @@ export default function Info({ accountInfo, onSaveSuccess }: InfoProps) { setAllChecked(isChecked); if (isChecked) { - // 全选 setBatchAccounts(accountInfo?.all_accounts ? [...accountInfo.all_accounts] : []); setUnselectedAccounts([]); } else { - // 取消全选 setBatchAccounts([]); setUnselectedAccounts(accountInfo?.all_accounts ? [...accountInfo.all_accounts] : []); } } - // 处理单个账号选择 const handleAccountToggle = (account: string | number) => { if (batchAccounts.includes(account)) { - // 取消选择 setBatchAccounts(batchAccounts.filter((item) => item !== account)); setUnselectedAccounts([...unselectedAccounts, account]); } else { - // 选择 setBatchAccounts([...batchAccounts, account]); setUnselectedAccounts(unselectedAccounts.filter((item) => item !== account)); } }; - // 当选择变化时,更新全选状态 useEffect(() => { if (accountInfo?.all_accounts) { setAllChecked(batchAccounts.length === accountInfo.all_accounts.length); @@ -136,40 +142,60 @@ export default function Info({ accountInfo, onSaveSuccess }: InfoProps) { {accountInfo?.alias !== 'BATCH_RUNNER' && ( <> - + + + setChannel(e.target.value)} + > + {accountInfo?.channel_option.map((option) => ( + + ))} + + + + {isTw && ( + + setViewerId(e.target.value)} + /> + + )} + setUsername(e.target.value)} /> - + setPassword(e.target.value)} /> - - - setChannel(e.target.value)} - > - {accountInfo?.channel_option.map((option) => ( - - ))} - - -