Files
oci-portal-dash/src/api/proxies.ts
T
wangdefa aea00c2382
CI / test (push) Successful in 25s
Release / release (push) Successful in 25s
关于页运行状态、代理关联租户与步进框修复
2026-07-13 12:21:28 +08:00

107 lines
3.9 KiB
TypeScript

import { mockConfigs, mockProxies } from './mock'
import { mockOn, mocked, request } from './request'
import type { ProxyImportResult, ProxyInfo, ProxyInput } from '@/types/api'
export function listProxies(): Promise<{ items: ProxyInfo[] }> {
if (mockOn) return mocked({ items: mockProxies })
return request('/proxies')
}
/** mock 端复刻后端自动命名:留空生成 {type}-{host}:{port},冲突加序号 */
function mockAutoName(body: ProxyInput): string {
const base = `${body.type}-${body.host}:${body.port}`
let name = base
for (let i = 2; mockProxies.some((p) => p.name === name); i++) name = `${base}-${i}`
return name
}
function mockCreate(body: ProxyInput): ProxyInfo {
const created: ProxyInfo = {
id: Math.max(0, ...mockProxies.map((p) => p.id)) + 1,
name: body.name?.trim() || mockAutoName(body),
type: body.type,
host: body.host,
port: body.port,
username: body.username ?? '',
passwordSet: !!body.password,
country: '',
city: '',
geoAt: '',
usedBy: 0,
createdAt: new Date().toISOString(),
}
mockProxies.push(created)
return created
}
export function createProxy(body: ProxyInput): Promise<ProxyInfo> {
if (mockOn) return mocked(mockCreate(body))
return request('/proxies', { method: 'POST', body })
}
export function updateProxy(id: number, body: ProxyInput): Promise<ProxyInfo> {
if (mockOn) {
const found = mockProxies.find((p) => p.id === id)
if (!found) return Promise.reject(new Error('代理不存在'))
Object.assign(found, body, {
name: body.name?.trim() || found.name,
passwordSet: body.password ? true : found.passwordSet,
})
return mocked({ ...found })
}
return request(`/proxies/${id}`, { method: 'PUT', body })
}
export function deleteProxy(id: number): Promise<void> {
if (mockOn) {
const i = mockProxies.findIndex((p) => p.id === id)
if (i >= 0) mockProxies.splice(i, 1)
return mocked(undefined)
}
return request(`/proxies/${id}`, { method: 'DELETE' })
}
/** 批量导入:每行 scheme://[user:pass@]host:port 或 host:port[:user:pass] */
export function importProxies(text: string): Promise<ProxyImportResult> {
if (mockOn) {
const created = text
.split('\n')
.map((l) => l.trim())
.filter((l) => l && !l.startsWith('#'))
.map((l) => {
const m = /^(?:(socks5|http|https):\/\/)?(?:[^@]+@)?([^:@/]+):(\d+)/.exec(l)
return m ? mockCreate({ type: m[1] ?? 'socks5', host: m[2], port: Number(m[3]) }) : null
})
.filter((p): p is ProxyInfo => !!p)
return mocked({ created, failed: [] })
}
return request('/proxies/import', { method: 'POST', body: { text } })
}
/** 代理侧设置关联租户全集:选中即关联(含从其他代理改挂),未选中即解除 */
export function setProxyTenants(id: number, ociConfigIds: number[]): Promise<{ usedBy: number }> {
if (mockOn) {
const found = mockProxies.find((p) => p.id === id)
if (!found) return Promise.reject(new Error('代理不存在'))
for (const c of mockConfigs) {
if (ociConfigIds.includes(c.id)) Object.assign(c, { proxyId: id, proxyName: found.name })
else if (c.proxyId === id) Object.assign(c, { proxyId: null, proxyName: '' })
}
// 改挂会影响其他代理的引用数,全量重算保持一致
for (const p of mockProxies) p.usedBy = mockConfigs.filter((c) => c.proxyId === p.id).length
return mocked({ usedBy: found.usedBy })
}
return request(`/proxies/${id}/tenants`, { method: 'PUT', body: { ociConfigIds } })
}
/** 手动重测出口地区,同步返回最新视图 */
export function probeProxy(id: number): Promise<ProxyInfo> {
if (mockOn) {
const found = mockProxies.find((p) => p.id === id)
if (!found) return Promise.reject(new Error('代理不存在'))
Object.assign(found, { country: '日本', city: '大阪市', geoAt: new Date().toISOString() })
return mocked({ ...found })
}
return request(`/proxies/${id}/probe`, { method: 'POST' })
}