feat: Implement core backend server with file upload, monitoring, S2A API proxy, and team processing features.

This commit is contained in:
2026-01-30 10:15:31 +08:00
parent cefbb2f38f
commit 38dde08648
5 changed files with 307 additions and 32 deletions

View File

@@ -98,7 +98,7 @@ export default function FileDropzone({ onFileSelect, disabled = false, error }:
</div>
<div className="text-xs text-slate-400 dark:text-slate-500">
: [&#123;"account": "email", "password": "pwd", "token": "..."&#125;]
支持格式: JSON //JSONL
</div>
</div>
</div>

View File

@@ -65,31 +65,29 @@ export default function Monitor() {
const [pollingEnabled, setPollingEnabled] = useState(false)
const [pollingInterval, setPollingInterval] = useState(60)
// 使用后端代理路径
const proxyBase = '/api/s2a/proxy'
// 监控接口属于本地后端服务(通常在 8088 端口)
const localBase = window.location.protocol + '//' + window.location.hostname + ':8088'
// 辅助函数:解包 S2A 响应
const requestS2A = async (url: string, options: RequestInit = {}) => {
const res = await fetch(url, options)
// 辅助函数:处理本地请求
const requestLocal = async (path: string, options: RequestInit = {}) => {
const res = await fetch(`${localBase}${path}`, options)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
const data = await res.json()
if (data && typeof data === 'object' && 'code' in data && 'data' in data) {
if (data.code !== 0) throw new Error(data.message || 'API error')
return data.data
}
return data
return res.json()
}
// 获取号池状态
const fetchPoolStatus = useCallback(async () => {
try {
const data = await requestS2A(`${proxyBase}/api/pool/status`)
setPoolStatus(data)
setTargetInput(data.target)
setAutoAdd(data.auto_add)
setMinInterval(data.min_interval)
setPollingEnabled(data.polling_enabled)
setPollingInterval(data.polling_interval)
const res = await requestLocal('/api/pool/status')
if (res.code === 0) {
const data = res.data
setPoolStatus(data)
setTargetInput(data.target)
setAutoAdd(data.auto_add)
setMinInterval(data.min_interval)
setPollingEnabled(data.polling_enabled)
setPollingInterval(data.polling_interval)
}
} catch (e) {
console.error('获取号池状态失败:', e)
}
@@ -99,8 +97,10 @@ export default function Monitor() {
const refreshStats = useCallback(async () => {
setRefreshing(true)
try {
const data = await requestS2A(`${proxyBase}/api/pool/refresh`, { method: 'POST' })
setStats(data)
const res = await requestLocal('/api/pool/refresh', { method: 'POST' })
if (res.code === 0) {
setStats(res.data)
}
await fetchPoolStatus()
} catch (e) {
console.error('刷新统计失败:', e)
@@ -112,7 +112,7 @@ export default function Monitor() {
const handleSetTarget = async () => {
setLoading(true)
try {
await requestS2A(`${proxyBase}/api/pool/target`, {
await requestLocal('/api/pool/target', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
@@ -132,7 +132,7 @@ export default function Monitor() {
const handleTogglePolling = async () => {
setLoading(true)
try {
await requestS2A(`${proxyBase}/api/pool/polling`, {
await requestLocal('/api/pool/polling', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
@@ -152,7 +152,7 @@ export default function Monitor() {
const handleHealthCheck = async (autoPause: boolean = false) => {
setCheckingHealth(true)
try {
await requestS2A(`${proxyBase}/api/health-check/start`, {
await requestLocal('/api/health-check/start', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ auto_pause: autoPause }),
@@ -160,8 +160,10 @@ export default function Monitor() {
// 等待一会儿再获取结果
setTimeout(async () => {
try {
const data = await requestS2A(`${proxyBase}/api/health-check/results`)
setHealthResults(data || [])
const res = await requestLocal('/api/health-check/results')
if (res.code === 0) {
setHealthResults(res.data || [])
}
} catch (e) {
console.error('获取健康检查结果失败:', e)
}
@@ -176,8 +178,10 @@ export default function Monitor() {
// 获取自动补号日志
const fetchAutoAddLogs = async () => {
try {
const data = await requestS2A(`${proxyBase}/api/auto-add/logs`)
setAutoAddLogs(data || [])
const res = await requestLocal('/api/auto-add/logs')
if (res.code === 0) {
setAutoAddLogs(res.data || [])
}
} catch (e) {
console.error('获取日志失败:', e)
}

View File

@@ -120,13 +120,10 @@ export default function Upload() {
try {
const text = await file.text()
const json = JSON.parse(text)
const accounts = Array.isArray(json) ? json : [json]
const res = await fetch('/api/upload/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ accounts }),
body: JSON.stringify({ content: text, filename: file.name }),
})
const data = await res.json()