初始提交:OCI 面板前端(含 GenAI 网关一期)

This commit is contained in:
Wang Defa
2026-07-09 15:31:29 +08:00
commit db45a669e3
135 changed files with 25220 additions and 0 deletions
+380
View File
@@ -0,0 +1,380 @@
import {
mockAds,
mockBvAttachments,
mockConsoleConns,
mockImages,
mockInstances,
mockShapes,
mockVolAttachments,
mockVolumes,
} from './mock'
import { mockOn, mocked, request } from './request'
import type {
AttachVnicRequest,
BootVolumeAttachment,
ComputeShape,
ConsoleConnection,
CreateInstanceRequest,
CreateInstancesResponse,
ImageInfo,
Instance,
PowerAction,
UpdateInstanceRequest,
Vnic,
Volume,
VolumeAttachment,
} from '@/types/api'
// ---- 创建实例前置查询 ----
export interface ImagesQuery {
region?: string
operatingSystem?: string
shape?: string
}
export function listImages(cfgId: number, query: ImagesQuery = {}): Promise<ImageInfo[]> {
if (mockOn) return mocked(mockImages)
return request(`/oci-configs/${cfgId}/images`, { query: { ...query } })
}
export function getImage(cfgId: number, imageId: string, region?: string): Promise<ImageInfo> {
if (mockOn) {
const found = mockImages.find((i) => i.id === imageId) ?? {
...mockImages[0],
id: imageId,
displayName: 'Canonical-Ubuntu-24.04-aarch64-2026.05.20-0',
}
return mocked(found)
}
return request(`/oci-configs/${cfgId}/images/${encodeURIComponent(imageId)}`, {
query: { region },
})
}
export function listAvailabilityDomains(cfgId: number, region?: string): Promise<string[]> {
if (mockOn) return mocked(mockAds)
return request(`/oci-configs/${cfgId}/availability-domains`, { query: { region } })
}
export function listShapes(
cfgId: number,
region?: string,
availabilityDomain?: string,
): Promise<ComputeShape[]> {
if (mockOn) return mocked(mockShapes)
return request(`/oci-configs/${cfgId}/shapes`, { query: { region, availabilityDomain } })
}
export function listVolumes(
cfgId: number,
availabilityDomain?: string,
compartmentId?: string,
region?: string,
): Promise<Volume[]> {
if (mockOn) return mocked(mockVolumes[cfgId] ?? [])
return request(`/oci-configs/${cfgId}/volumes`, {
query: { availabilityDomain, compartmentId, region },
})
}
export function listInstances(
cfgId: number,
region?: string,
compartmentId?: string,
): Promise<Instance[]> {
if (mockOn) return mocked(compartmentId ? [] : (mockInstances[cfgId] ?? []))
return request(`/oci-configs/${cfgId}/instances`, { query: { region, compartmentId } })
}
export function getInstance(cfgId: number, instanceId: string, region?: string): Promise<Instance> {
if (mockOn) {
const all = Object.values(mockInstances).flat()
const found = all.find((i) => i.id === instanceId)
return found ? mocked(found) : Promise.reject(new Error('实例不存在'))
}
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}`, {
query: { region },
})
}
export function createInstances(
cfgId: number,
body: CreateInstanceRequest,
): Promise<CreateInstancesResponse> {
if (mockOn) return mocked({ instances: [mockInstances[1][0]], errors: [] }, 1200)
return request(`/oci-configs/${cfgId}/instances`, { method: 'POST', body })
}
export function updateInstance(
cfgId: number,
instanceId: string,
body: UpdateInstanceRequest,
region?: string,
): Promise<Instance> {
if (mockOn) return mocked({ ...mockInstances[1][0], ...body })
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}`, {
method: 'PUT',
body: { region: region ?? '', ...body },
})
}
export function terminateInstance(
cfgId: number,
instanceId: string,
preserveBootVolume: boolean,
region?: string,
): Promise<void> {
if (mockOn) return mocked(undefined, 600)
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}`, {
method: 'DELETE',
query: { preserveBootVolume, region },
})
}
export function instanceAction(
cfgId: number,
instanceId: string,
action: PowerAction,
region?: string,
): Promise<Instance> {
if (mockOn) {
const next = action === 'STOP' || action === 'SOFTSTOP' ? 'STOPPING' : 'STARTING'
return mocked({ ...mockInstances[1][0], lifecycleState: next }, 600)
}
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/action`, {
method: 'POST',
body: { region: region ?? '', action },
})
}
export function changePublicIp(
cfgId: number,
instanceId: string,
region?: string,
): Promise<{ publicIp: string }> {
if (mockOn) return mocked({ publicIp: '130.61.99.201' }, 900)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/change-public-ip`,
{ method: 'POST', body: { region: region ?? '' } },
)
}
export function addIpv6(
cfgId: number,
instanceId: string,
address = '',
region?: string,
): Promise<{ ipv6Address: string }> {
if (mockOn) return mocked({ ipv6Address: address || '2603:c020:400d:aa01::2' }, 700)
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/ipv6-addresses`, {
method: 'POST',
body: { region: region ?? '', address },
})
}
export function removeIpv6(
cfgId: number,
instanceId: string,
address: string,
region?: string,
): Promise<void> {
if (mockOn) return mocked(undefined)
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/ipv6-addresses`, {
method: 'DELETE',
query: { address, region },
})
}
// ---- VNIC 管理 ----
export function listVnics(cfgId: number, instanceId: string, region?: string): Promise<Vnic[]> {
if (mockOn) return mocked([])
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/vnics`, {
query: { region },
})
}
export function attachVnic(
cfgId: number,
instanceId: string,
body: AttachVnicRequest,
): Promise<Vnic> {
if (mockOn) return Promise.reject(new Error('mock 环境不支持附加 VNIC'))
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/vnics`, {
method: 'POST',
body: { ...body, region: body.region ?? '' },
})
}
export function detachVnic(cfgId: number, attachmentId: string, region?: string): Promise<void> {
if (mockOn) return mocked(undefined)
return request(`/oci-configs/${cfgId}/vnic-attachments/${encodeURIComponent(attachmentId)}`, {
method: 'DELETE',
query: { region },
})
}
/** 为指定 VNIC 添加 IPv6;address 留空自动分配。删除复用实例级 removeIpv6(按地址遍历全部网卡) */
export function addVnicIpv6(
cfgId: number,
vnicId: string,
address = '',
region?: string,
): Promise<{ address: string }> {
if (mockOn) return mocked({ address: address || '2603:c020:400d:aa01::3' }, 700)
return request(`/oci-configs/${cfgId}/vnics/${encodeURIComponent(vnicId)}/ipv6-addresses`, {
method: 'POST',
body: { region: region ?? '', address },
})
}
// ---- 网页控制台(串行 / VNC)----
export type ConsoleSessionType = 'serial' | 'vnc'
export function createConsoleSession(
cfgId: number,
instanceId: string,
type: ConsoleSessionType,
region?: string,
): Promise<{ sessionId: string; type: ConsoleSessionType }> {
if (mockOn) return Promise.reject(new Error('mock 环境不支持网页控制台'))
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/console-sessions`,
{ method: 'POST', body: { type, region: region ?? '' } },
)
}
export function deleteConsoleSession(sessionId: string): Promise<void> {
if (mockOn) return mocked(undefined)
return request(`/console-sessions/${encodeURIComponent(sessionId)}`, { method: 'DELETE' })
}
/** 控制台数据面 WS 地址:浏览器 WS 无法带自定义头,token 走 query */
export function consoleSessionWsUrl(sessionId: string, token: string, extra?: string): string {
const proto = location.protocol === 'https:' ? 'wss' : 'ws'
const q = extra ? `&${extra}` : ''
return `${proto}://${location.host}/api/v1/console-sessions/${encodeURIComponent(sessionId)}/ws?token=${encodeURIComponent(token)}${q}`
}
// ---- 控制台连接 ----
export function listConsoleConnections(
cfgId: number,
instanceId: string,
region?: string,
): Promise<ConsoleConnection[]> {
if (mockOn) return mocked(mockConsoleConns)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/console-connections`,
{ query: { region } },
)
}
export function createConsoleConnection(
cfgId: number,
instanceId: string,
sshPublicKey: string,
region?: string,
): Promise<ConsoleConnection> {
if (mockOn) return mocked(mockConsoleConns[0], 1500)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/console-connections`,
{ method: 'POST', body: { region: region ?? '', sshPublicKey } },
)
}
export function deleteConsoleConnection(
cfgId: number,
connectionId: string,
region?: string,
): Promise<void> {
if (mockOn) return mocked(undefined)
return request(`/oci-configs/${cfgId}/console-connections/${encodeURIComponent(connectionId)}`, {
method: 'DELETE',
query: { region },
})
}
// ---- 引导卷挂载 ----
export function listBootVolumeAttachments(
cfgId: number,
instanceId: string,
region?: string,
): Promise<BootVolumeAttachment[]> {
if (mockOn) return mocked(mockBvAttachments)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/boot-volume-attachments`,
{ query: { region } },
)
}
export function attachBootVolume(
cfgId: number,
instanceId: string,
bootVolumeId: string,
region?: string,
): Promise<BootVolumeAttachment> {
if (mockOn) return mocked(mockBvAttachments[0], 1200)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/boot-volume-attachments`,
{ method: 'POST', body: { region: region ?? '', bootVolumeId } },
)
}
export function replaceBootVolume(
cfgId: number,
instanceId: string,
bootVolumeId: string,
region?: string,
): Promise<BootVolumeAttachment> {
if (mockOn) return mocked(mockBvAttachments[0], 1500)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/replace-boot-volume`,
{ method: 'POST', body: { region: region ?? '', bootVolumeId } },
)
}
export function detachBootVolume(
cfgId: number,
attachmentId: string,
region?: string,
): Promise<void> {
if (mockOn) return mocked(undefined)
return request(`/oci-configs/${cfgId}/boot-volume-attachments/${encodeURIComponent(attachmentId)}`, {
method: 'DELETE',
query: { region },
})
}
// ---- 块卷挂载 ----
export function listVolumeAttachments(
cfgId: number,
instanceId: string,
region?: string,
): Promise<VolumeAttachment[]> {
if (mockOn) return mocked(mockVolAttachments)
return request(
`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/volume-attachments`,
{ query: { region } },
)
}
export function attachVolume(
cfgId: number,
instanceId: string,
volumeId: string,
readOnly = false,
region?: string,
): Promise<VolumeAttachment> {
if (mockOn) return mocked(mockVolAttachments[0], 1000)
return request(`/oci-configs/${cfgId}/instances/${encodeURIComponent(instanceId)}/volume-attachments`, {
method: 'POST',
body: { region: region ?? '', volumeId, readOnly },
})
}
export function detachVolume(cfgId: number, attachmentId: string, region?: string): Promise<void> {
if (mockOn) return mocked(undefined)
return request(`/oci-configs/${cfgId}/volume-attachments/${encodeURIComponent(attachmentId)}`, {
method: 'DELETE',
query: { region },
})
}