feat: update delivery and resource frontends

This commit is contained in:
mac
2026-07-28 17:56:58 +08:00
parent f7be87c7d9
commit 93981b9aad
7 changed files with 561 additions and 133 deletions
+36
View File
@@ -34,6 +34,33 @@ export interface ContainerWorkload {
statusClass: string
}
export interface ContainerCluster {
name: string
zone: string
zoneClass: string
status: string
statusClass: string
nodes: number
readyNodes: number
cpu: number
cpuClass: string
version: string
calico: string
}
export interface ContainerNode {
cluster: string
name: string
ip: string
label: string
taint: string
spec: string
cpu: number
cpuClass: string
status: string
statusClass: string
}
export const emptyContainerServiceSummary: ContainerServiceSummary = {
businessLineId: 0,
businessLineName: '',
@@ -65,6 +92,15 @@ export const containerServiceApi = {
summary: data.summary || emptyContainerServiceSummary,
}
},
async listClusters(businessLineId: number): Promise<{ items: ContainerCluster[]; nodes: ContainerNode[]; summary: ContainerServiceSummary }> {
const data = await authRequest(`/auth/api/v1/container-services/business-lines/${businessLineId}/clusters`)
return {
items: Array.isArray(data.items) ? data.items : [],
nodes: Array.isArray(data.nodes) ? data.nodes : [],
summary: data.summary || emptyContainerServiceSummary,
}
},
}
async function authRequest(path: string, init: RequestInit = {}) {
+18
View File
@@ -83,6 +83,19 @@ export interface DeliveryTaskSnapshot {
events: TaskEvent[]
}
export interface MySQLServiceLedgerItem {
name: string
datacenter: string
business_tag: string
instances: number
healthy: number
address: string
status: string
status_class: string
version: string
namespace: string
}
export const deliveryApi = {
async listTargets(): Promise<DeliveryTarget[]> {
const data = await authRequest('/auth/api/v1/delivery/targets?component=mysql')
@@ -115,6 +128,11 @@ export const deliveryApi = {
return Array.isArray(data.items) ? data.items : []
},
async listMySQLServices(businessLineId: number): Promise<MySQLServiceLedgerItem[]> {
const data = await authRequest(`/auth/api/v1/delivery/business-lines/${businessLineId}/mysql-services`)
return Array.isArray(data.items) ? data.items : []
},
async getTask(taskId: string): Promise<{ task: DeliveryTask; events: TaskEvent[] }> {
const data = await authRequest(`/auth/api/v1/delivery/tasks/${encodeURIComponent(taskId)}`)
return {
+144
View File
@@ -0,0 +1,144 @@
import { getToken } from '@/utils/auth'
export interface MachineOverview {
total: number
physical: number
virtual: number
cmdb: {
total: number
physical: number
virtual: number
}
aliyun: {
total: number
label: string
}
awsQiniu: {
total: number
aws: number
qiniu: number
}
lastSync: {
status: string
time: string
created: number
error?: string
}
}
export interface MachineResource {
hostname: string
assetNumber: string
type: string
location: string
ip: string
spec: string
businessLine: string
source: string
status: string
}
export interface MachineResourceList {
total: number
items: MachineResource[]
}
export interface MachineResourceQuery {
page: number
size: number
hostname?: string
assetNumber?: string
type?: string
location?: string
ip?: string
spec?: string
businessLine?: string
source?: string
status?: string
}
export const emptyMachineOverview: MachineOverview = {
total: 0,
physical: 0,
virtual: 0,
cmdb: {
total: 0,
physical: 0,
virtual: 0,
},
aliyun: {
total: 0,
label: 'ECS · 增量同步',
},
awsQiniu: {
total: 0,
aws: 0,
qiniu: 0,
},
lastSync: {
status: 'unknown',
time: '—',
created: 0,
},
}
export const machineApi = {
async getOverview(): Promise<MachineOverview> {
return authRequest('/auth/api/v1/machines/overview')
},
async listResources(query: MachineResourceQuery): Promise<MachineResourceList> {
const params = new URLSearchParams()
params.set('page', String(query.page))
params.set('size', String(query.size))
if (query.hostname) params.set('hostname', query.hostname)
if (query.assetNumber) params.set('assetNumber', query.assetNumber)
if (query.type) params.set('type', query.type)
if (query.location) params.set('location', query.location)
if (query.ip) params.set('ip', query.ip)
if (query.spec) params.set('spec', query.spec)
if (query.businessLine) params.set('businessLine', query.businessLine)
if (query.source) params.set('source', query.source)
if (query.status) params.set('status', query.status)
const data = await authRequest(`/auth/api/v1/machines/resources?${params.toString()}`)
return {
total: Number(data.total || 0),
items: Array.isArray(data.items) ? data.items : [],
}
},
async sync(): Promise<void> {
await authRequest('/auth/api/v1/machines/sync', { method: 'POST' })
},
}
async function authRequest(path: string, init: RequestInit = {}) {
const token = getToken()
const response = await fetch(path, {
...init,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...init.headers,
},
})
const text = await response.text()
const data = parseResponseBody(text)
if (!response.ok) {
const message = data?.error || data?.message || text || `HTTP ${response.status}`
throw new Error(message)
}
return data || {}
}
function parseResponseBody(text: string) {
if (!text.trim()) {
return {}
}
try {
return JSON.parse(text)
} catch {
return { error: text }
}
}