107 lines
3.9 KiB
TypeScript
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' })
|
|
}
|