mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-08 10:25:28 +08:00
387 lines
14 KiB
JavaScript
387 lines
14 KiB
JavaScript
import { useState } from 'react'
|
|
|
|
export function useAccountActions({ apiFetch, t, onMessage, onRefresh, config, fetchAccounts, resolveAccountIdentifier }) {
|
|
const [showAddKey, setShowAddKey] = useState(false)
|
|
const [editingKey, setEditingKey] = useState(null)
|
|
const [showAddAccount, setShowAddAccount] = useState(false)
|
|
const [showEditAccount, setShowEditAccount] = useState(false)
|
|
const [editingAccount, setEditingAccount] = useState(null)
|
|
const [newKey, setNewKey] = useState({ key: '', name: '', remark: '' })
|
|
const [copiedKey, setCopiedKey] = useState(null)
|
|
const [newAccount, setNewAccount] = useState({ name: '', remark: '', email: '', mobile: '', password: '' })
|
|
const [editAccount, setEditAccount] = useState({ name: '', remark: '' })
|
|
const [loading, setLoading] = useState(false)
|
|
const [testing, setTesting] = useState({})
|
|
const [testingAll, setTestingAll] = useState(false)
|
|
const [batchProgress, setBatchProgress] = useState({ current: 0, total: 0, results: [] })
|
|
const [sessionCounts, setSessionCounts] = useState({})
|
|
const [deletingSessions, setDeletingSessions] = useState({})
|
|
const [updatingProxy, setUpdatingProxy] = useState({})
|
|
|
|
const openAddKey = () => {
|
|
setEditingKey(null)
|
|
setNewKey({ key: '', name: '', remark: '' })
|
|
setShowAddKey(true)
|
|
}
|
|
|
|
const openEditKey = (item) => {
|
|
if (!item?.key) return
|
|
setEditingKey(item)
|
|
setNewKey({
|
|
key: item.key || '',
|
|
name: item.name || '',
|
|
remark: item.remark || '',
|
|
})
|
|
setShowAddKey(true)
|
|
}
|
|
|
|
const closeKeyModal = () => {
|
|
setShowAddKey(false)
|
|
setEditingKey(null)
|
|
setNewKey({ key: '', name: '', remark: '' })
|
|
}
|
|
|
|
const openAddAccount = () => {
|
|
setShowEditAccount(false)
|
|
setEditingAccount(null)
|
|
setEditAccount({ name: '', remark: '' })
|
|
setNewAccount({ name: '', remark: '', email: '', mobile: '', password: '' })
|
|
setShowAddAccount(true)
|
|
}
|
|
|
|
const closeAddAccount = () => {
|
|
setShowAddAccount(false)
|
|
setNewAccount({ name: '', remark: '', email: '', mobile: '', password: '' })
|
|
}
|
|
|
|
const openEditAccount = (account) => {
|
|
const identifier = resolveAccountIdentifier(account)
|
|
if (!identifier) {
|
|
onMessage('error', t('accountManager.invalidIdentifier'))
|
|
return
|
|
}
|
|
setShowAddAccount(false)
|
|
setEditingAccount({
|
|
identifier,
|
|
})
|
|
setEditAccount({
|
|
name: account?.name || '',
|
|
remark: account?.remark || '',
|
|
})
|
|
setShowEditAccount(true)
|
|
}
|
|
|
|
const closeEditAccount = () => {
|
|
setShowEditAccount(false)
|
|
setEditingAccount(null)
|
|
setEditAccount({ name: '', remark: '' })
|
|
}
|
|
|
|
const addKey = async () => {
|
|
const isEditing = Boolean(editingKey?.key)
|
|
if (!isEditing && !newKey.key.trim()) {
|
|
return
|
|
}
|
|
setLoading(true)
|
|
try {
|
|
const endpoint = isEditing
|
|
? `/admin/keys/${encodeURIComponent(editingKey.key)}`
|
|
: '/admin/keys'
|
|
const method = isEditing ? 'PUT' : 'POST'
|
|
const payload = isEditing
|
|
? { name: newKey.name, remark: newKey.remark }
|
|
: { key: newKey.key.trim(), name: newKey.name, remark: newKey.remark }
|
|
if (!isEditing && !payload.key) {
|
|
return
|
|
}
|
|
const res = await apiFetch(endpoint, {
|
|
method,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(payload),
|
|
})
|
|
if (res.ok) {
|
|
onMessage('success', isEditing ? t('accountManager.updateKeySuccess') : t('accountManager.addKeySuccess'))
|
|
closeKeyModal()
|
|
onRefresh()
|
|
} else {
|
|
const data = await res.json()
|
|
onMessage('error', data.detail || (isEditing ? t('messages.requestFailed') : t('messages.failedToAdd')))
|
|
}
|
|
} catch (e) {
|
|
onMessage('error', t('messages.networkError'))
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const deleteKey = async (key) => {
|
|
if (!confirm(t('accountManager.deleteKeyConfirm'))) return
|
|
try {
|
|
const res = await apiFetch(`/admin/keys/${encodeURIComponent(key)}`, { method: 'DELETE' })
|
|
if (res.ok) {
|
|
onMessage('success', t('messages.deleted'))
|
|
onRefresh()
|
|
} else {
|
|
onMessage('error', t('messages.deleteFailed'))
|
|
}
|
|
} catch (e) {
|
|
onMessage('error', t('messages.networkError'))
|
|
}
|
|
}
|
|
|
|
const addAccount = async () => {
|
|
if (!newAccount.password || (!newAccount.email && !newAccount.mobile)) {
|
|
onMessage('error', t('accountManager.requiredFields'))
|
|
return
|
|
}
|
|
setLoading(true)
|
|
try {
|
|
const res = await apiFetch('/admin/accounts', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(newAccount),
|
|
})
|
|
if (res.ok) {
|
|
onMessage('success', t('accountManager.addAccountSuccess'))
|
|
closeAddAccount()
|
|
fetchAccounts(1)
|
|
onRefresh()
|
|
} else {
|
|
const data = await res.json()
|
|
onMessage('error', data.detail || t('messages.failedToAdd'))
|
|
}
|
|
} catch (e) {
|
|
onMessage('error', t('messages.networkError'))
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const updateAccount = async () => {
|
|
const identifier = String(editingAccount?.identifier || '').trim()
|
|
if (!identifier) {
|
|
onMessage('error', t('accountManager.invalidIdentifier'))
|
|
return
|
|
}
|
|
setLoading(true)
|
|
try {
|
|
const res = await apiFetch(`/admin/accounts/${encodeURIComponent(identifier)}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(editAccount),
|
|
})
|
|
if (res.ok) {
|
|
onMessage('success', t('accountManager.updateAccountSuccess'))
|
|
closeEditAccount()
|
|
fetchAccounts()
|
|
onRefresh()
|
|
} else {
|
|
const data = await res.json()
|
|
onMessage('error', data.detail || t('messages.requestFailed'))
|
|
}
|
|
} catch (e) {
|
|
onMessage('error', t('messages.networkError'))
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const deleteAccount = async (id) => {
|
|
const identifier = String(id || '').trim()
|
|
if (!identifier) {
|
|
onMessage('error', t('accountManager.invalidIdentifier'))
|
|
return
|
|
}
|
|
if (!confirm(t('accountManager.deleteAccountConfirm'))) return
|
|
try {
|
|
const res = await apiFetch(`/admin/accounts/${encodeURIComponent(identifier)}`, { method: 'DELETE' })
|
|
if (res.ok) {
|
|
onMessage('success', t('messages.deleted'))
|
|
fetchAccounts()
|
|
onRefresh()
|
|
} else {
|
|
onMessage('error', t('messages.deleteFailed'))
|
|
}
|
|
} catch (e) {
|
|
onMessage('error', t('messages.networkError'))
|
|
}
|
|
}
|
|
|
|
const testAccount = async (identifier) => {
|
|
const accountID = String(identifier || '').trim()
|
|
if (!accountID) {
|
|
onMessage('error', t('accountManager.invalidIdentifier'))
|
|
return
|
|
}
|
|
setTesting(prev => ({ ...prev, [accountID]: true }))
|
|
try {
|
|
const res = await apiFetch('/admin/accounts/test', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ identifier: accountID }),
|
|
})
|
|
const data = await res.json()
|
|
|
|
// 更新会话数
|
|
if (data.session_count !== undefined) {
|
|
setSessionCounts(prev => ({ ...prev, [accountID]: data.session_count }))
|
|
}
|
|
|
|
const statusMessage = data.success
|
|
? t('apiTester.testSuccess', { account: accountID, time: data.response_time })
|
|
: `${accountID}: ${data.message}`
|
|
onMessage(data.success ? 'success' : 'error', statusMessage)
|
|
fetchAccounts()
|
|
onRefresh()
|
|
} catch (e) {
|
|
onMessage('error', t('accountManager.testFailed', { error: e.message }))
|
|
} finally {
|
|
setTesting(prev => ({ ...prev, [accountID]: false }))
|
|
}
|
|
}
|
|
|
|
const testAllAccounts = async () => {
|
|
if (!confirm(t('accountManager.testAllConfirm'))) return
|
|
const allAccounts = config.accounts || []
|
|
if (allAccounts.length === 0) return
|
|
|
|
setTestingAll(true)
|
|
setBatchProgress({ current: 0, total: allAccounts.length, results: [] })
|
|
|
|
let successCount = 0
|
|
const results = []
|
|
|
|
for (let i = 0; i < allAccounts.length; i++) {
|
|
const acc = allAccounts[i]
|
|
const id = resolveAccountIdentifier(acc)
|
|
if (!id) {
|
|
results.push({ id: '-', success: false, message: t('accountManager.invalidIdentifier') })
|
|
setBatchProgress({ current: i + 1, total: allAccounts.length, results: [...results] })
|
|
continue
|
|
}
|
|
|
|
try {
|
|
const res = await apiFetch('/admin/accounts/test', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ identifier: id }),
|
|
})
|
|
const data = await res.json()
|
|
results.push({ id, success: data.success, message: data.message, time: data.response_time })
|
|
if (data.success) successCount++
|
|
} catch (e) {
|
|
results.push({ id, success: false, message: e.message })
|
|
}
|
|
|
|
setBatchProgress({ current: i + 1, total: allAccounts.length, results: [...results] })
|
|
}
|
|
|
|
onMessage('success', t('accountManager.testAllCompleted', { success: successCount, total: allAccounts.length }))
|
|
fetchAccounts()
|
|
onRefresh()
|
|
setTestingAll(false)
|
|
}
|
|
|
|
const deleteAllSessions = async (identifier) => {
|
|
const accountID = String(identifier || '').trim()
|
|
if (!accountID) {
|
|
onMessage('error', t('accountManager.invalidIdentifier'))
|
|
return
|
|
}
|
|
if (!confirm(t('accountManager.deleteAllSessionsConfirm'))) return
|
|
|
|
setDeletingSessions(prev => ({ ...prev, [accountID]: true }))
|
|
try {
|
|
const res = await apiFetch('/admin/accounts/sessions/delete-all', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ identifier: accountID }),
|
|
})
|
|
const data = await res.json()
|
|
|
|
if (data.success) {
|
|
onMessage('success', t('accountManager.deleteAllSessionsSuccess'))
|
|
// 清除会话数显示
|
|
setSessionCounts(prev => {
|
|
const newCounts = { ...prev }
|
|
delete newCounts[accountID]
|
|
return newCounts
|
|
})
|
|
} else {
|
|
onMessage('error', data.message || t('messages.requestFailed'))
|
|
}
|
|
} catch (e) {
|
|
onMessage('error', t('messages.networkError'))
|
|
} finally {
|
|
setDeletingSessions(prev => ({ ...prev, [accountID]: false }))
|
|
}
|
|
}
|
|
|
|
const updateAccountProxy = async (identifier, proxyID) => {
|
|
const accountID = String(identifier || '').trim()
|
|
if (!accountID) {
|
|
onMessage('error', t('accountManager.invalidIdentifier'))
|
|
return
|
|
}
|
|
setUpdatingProxy(prev => ({ ...prev, [accountID]: true }))
|
|
try {
|
|
const res = await apiFetch(`/admin/accounts/${encodeURIComponent(accountID)}/proxy`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ proxy_id: proxyID || '' }),
|
|
})
|
|
const data = await res.json()
|
|
if (!res.ok) {
|
|
onMessage('error', data.detail || t('messages.requestFailed'))
|
|
return
|
|
}
|
|
onMessage('success', t('accountManager.proxyUpdateSuccess'))
|
|
fetchAccounts()
|
|
onRefresh()
|
|
} catch (_err) {
|
|
onMessage('error', t('messages.networkError'))
|
|
} finally {
|
|
setUpdatingProxy(prev => ({ ...prev, [accountID]: false }))
|
|
}
|
|
}
|
|
|
|
return {
|
|
showAddKey,
|
|
openAddKey,
|
|
openEditKey,
|
|
closeKeyModal,
|
|
editingKey,
|
|
showAddAccount,
|
|
openAddAccount,
|
|
closeAddAccount,
|
|
showEditAccount,
|
|
editingAccount,
|
|
editAccount,
|
|
setEditAccount,
|
|
openEditAccount,
|
|
closeEditAccount,
|
|
newKey,
|
|
setNewKey,
|
|
copiedKey,
|
|
setCopiedKey,
|
|
newAccount,
|
|
setNewAccount,
|
|
loading,
|
|
testing,
|
|
testingAll,
|
|
batchProgress,
|
|
sessionCounts,
|
|
deletingSessions,
|
|
updatingProxy,
|
|
addKey,
|
|
deleteKey,
|
|
addAccount,
|
|
updateAccount,
|
|
deleteAccount,
|
|
testAccount,
|
|
testAllAccounts,
|
|
deleteAllSessions,
|
|
updateAccountProxy,
|
|
}
|
|
}
|