diff --git a/package.json b/package.json index 5f737e3..8a22e8f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "autopcr_web", "private": true, - "version": "1.8.0", + "version": "1.8.0-tw", "type": "module", "scripts": { "dev": "vite", diff --git a/src/api/Account.ts b/src/api/Account.ts index e1e2ef4..f3432d1 100644 --- a/src/api/Account.ts +++ b/src/api/Account.ts @@ -151,13 +151,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 2a6409e..e82c392 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); } @@ -41,32 +43,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(); } @@ -84,30 +96,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); @@ -142,40 +148,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) => ( - - ))} - - -