This commit is contained in:
ygx
2026-03-28 17:51:28 +08:00
6 changed files with 573 additions and 413 deletions

View File

@@ -1,40 +1,31 @@
import { request } from "@/api/request";
/** 获取服务器列表(分页) */
export const fetchServerList = (data?: {
export const fetchServerList = (params?: {
page?: number;
page_size?: number;
size?: number;
keyword?: string;
datacenter_id?: number;
rack_id?: number;
status?: string;
sort?: string;
order?: string;
collect_on?: boolean;
}) => {
return request.post("/Assets/v1/server/list", data || {});
return request.get("/DC-Control/v1/servers", { params });
};
/** 获取服务器详情 */
export const fetchServerDetail = (id: number) => {
return request.get(`/Assets/v1/server/detail/${id}`);
return request.get(`/DC-Control/v1/servers/${id}`);
};
/** 创建服务器 */
export const createServer = (data: any) => {
return request.post("/Assets/v1/server/create", data);
return request.post("/DC-Control/v1/servers", data);
};
/** 更新服务器 */
export const updateServer = (data: any) => {
return request.put("/Assets/v1/server/update", data);
export const updateServer = (id: number, data: any) => {
return request.put(`/DC-Control/v1/servers/${id}`, data);
};
/** 删除服务器 */
export const deleteServer = (id: number) => {
return request.delete(`/Assets/v1/server/delete/${id}`);
};
/** 获取机柜列表(用于下拉选择) */
export const fetchRackListForSelect = (datacenterId?: number) => {
return request.get("/Assets/v1/rack/all", { params: { datacenter_id: datacenterId } });
return request.delete(`/DC-Control/v1/servers/${id}`);
};

View File

@@ -0,0 +1,365 @@
# 服务器管理接口文档
## 基础信息
- **文档索引**: [README.md](README.md)
- **服务前缀**: `/DC-Control/v1/servers`
- **认证方式**: JWT认证所有接口都需要JWT Token
- **Content-Type**: `application/json`
---
## 1. 获取服务器列表
### 接口信息
- **路径**: `GET /DC-Control/v1/servers`
- **描述**: 分页获取服务器列表,支持关键词搜索、按是否启用采集(`collect_on`)过滤
### 请求参数
#### 查询参数 (Query Parameters)
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|--------|------|------|--------|------|
| page | int | 否 | 1 | 页码(必须为正整数) |
| size | int | 否 | 20 | 每页数量必须为正整数最大100 |
| keyword | string | 否 | - | 搜索关键词(按**名称、主机地址**模糊匹配,实现见 `ListServers` |
| collect_on | bool | 否 | - | 是否启用采集过滤,仅 `true`/`false`;缺省或空串不按该条件过滤,非法值返回 400 |
### 请求示例
```http
GET /DC-Control/v1/servers?page=1&size=20&keyword=&collect_on=true
Authorization: Bearer {JWT_TOKEN}
```
### 返回参数
```json
{
"code": 200,
"message": "success",
"data": {
"total": 50,
"page": 1,
"page_size": 20,
"data": [
{
"id": 1,
"created_at": "2024-01-01T10:00:00Z",
"updated_at": "2024-01-01T10:00:00Z",
"deleted_at": null,
"server_identity": "server-001",
"name": "生产服务器-001",
"host": "192.168.1.100",
"ip_address": "192.168.1.100",
"description": "生产环境主服务器",
"os": "Linux",
"os_version": "22.04",
"kernel": "x86",
"server_type": "physical",
"tags": "production,web",
"location": "机房A-机架01",
"remote_access": "ssh://user@host",
"agent_config": "",
"status": "online",
"last_check_time": "2024-01-01T10:00:00Z",
"collect_on": true,
"collect_args": "",
"collect_interval": 60,
"collect_last_result": ""
}
]
}
}
```
### 返回字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| total | int64 | 总记录数 |
| page | int | 当前页码 |
| page_size | int | 每页数量 |
| data | array | 服务器列表 |
| data[].id | uint | 服务器ID |
| data[].created_at | string | 创建时间 |
| data[].updated_at | string | 更新时间 |
| data[].deleted_at | string\|null | 删除时间(软删除) |
| data[].server_identity | string | 服务器唯一标识(唯一索引) |
| data[].name | string | 服务器名称 |
| data[].host | string | 服务器地址 |
| data[].ip_address | string | IP地址 |
| data[].description | string | 描述信息 |
| data[].os | string | 操作系统Windows/Linux/Mac/Other 等 |
| data[].os_version | string | 操作系统版本 |
| data[].kernel | string | 内核类型x86/arm 等 |
| data[].server_type | string | 服务器类型physical物理/virtual虚拟/cloud |
| data[].tags | string | 标签,逗号分隔的字符串(如 `prod,web`),可为空 |
| data[].location | string | 位置/机房信息 |
| data[].remote_access | string | 远程访问信息 |
| data[].agent_config | string | Agent 配置 |
| data[].status | string | 状态online在线/offline离线/unknown未知 |
| data[].last_check_time | string | 最后检查时间 |
| data[].collect_on | bool | 是否启用采集 |
| data[].collect_args | string | 采集参数 |
| data[].collect_interval | int | 采集间隔(秒),默认 60 |
| data[].collect_last_result | string | 采集最后结果 |
---
## 2. 获取服务器详情
### 接口信息
- **路径**: `GET /DC-Control/v1/servers/:id`
- **描述**: 根据ID获取单个服务器的详细信息
### 请求参数
#### 路径参数 (Path Parameters)
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|--------|
| id | uint | 是 | 服务器ID必须大于0 |
### 请求示例
```http
GET /DC-Control/v1/servers/1
Authorization: Bearer {JWT_TOKEN}
```
### 返回参数
返回单体字段与列表项一致(见上一节 `data[]` 字段说明),无嵌套 `collectors` 字段;采集器与服务器通过采集器表 `server_id` 关联,需通过采集器管理接口查询。
---
## 3. 创建服务器
### 接口信息
- **路径**: `POST /DC-Control/v1/servers`
- **描述**: 创建新的服务器记录
### 请求参数
#### 请求体 (Request Body)
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|--------|
| server_identity | string | 否 | 服务器唯一标识;**不传或空串时服务端生成 ULID** |
| name | string | 是 | 服务器名称最大100字符 |
| host | string | 是 | 服务器地址最大255字符 |
| ip_address | string | 否 | IP地址最大50字符 |
| description | string | 否 | 描述信息 |
| os | string | 否 | 操作系统类型 |
| os_version | string | 否 | 操作系统版本 |
| kernel | string | 否 | 内核类型 |
| server_type | string | 否 | 服务器类型physical/virtual/cloud最大50字符 |
| tags | string | 否 | 标签,逗号分隔(如 `env,role,tier`),最大约 500 字符,可为空 |
| location | string | 否 | 位置/机房信息最大200字符 |
| remote_access | string | 否 | 远程访问 |
| agent_config | string | 否 | Agent 配置 |
| status | string | 否 | 状态online/offline/unknown默认由库表 default 为 unknown |
| last_check_time | string (RFC3339) | 否 | 最后检查时间 |
| collect_on | bool | 否 | 是否启用采集,默认 true |
| collect_args | string | 否 | 采集参数 |
| collect_interval | int | 否 | 采集间隔(秒),默认 60 |
| collect_last_result | string | 否 | 采集最后结果 |
### 请求示例
```http
POST /DC-Control/v1/servers
Authorization: Bearer {JWT_TOKEN}
Content-Type: application/json
{
"server_identity": "server-001",
"name": "-001",
"host": "192.168.1.100",
"ip_address": "192.168.1.100",
"description": "",
"server_type": "physical",
"tags": "production,web,tier1",
"location": "A-01",
"remote_access": "ssh://ops@192.168.1.100",
"status": "online",
"collect_on": true,
"collect_interval": 60
}
```
### 返回参数
```json
{
"code": 200,
"message": "success",
"data": {
"id": 1,
"created_at": "2024-01-01T10:00:00Z",
"updated_at": "2024-01-01T10:00:00Z",
"deleted_at": null,
"server_identity": "server-001",
"name": "生产服务器-001",
"host": "192.168.1.100",
"ip_address": "192.168.1.100",
"description": "生产环境主服务器",
"os": "",
"os_version": "",
"kernel": "",
"server_type": "physical",
"tags": "production,web,tier1",
"location": "机房A-机架01",
"remote_access": "ssh://ops@192.168.1.100",
"agent_config": "",
"status": "online",
"last_check_time": "0001-01-01T00:00:00Z",
"collect_on": true,
"collect_args": "",
"collect_interval": 60,
"collect_last_result": ""
}
}
```
> 创建接口直接返回内存中的 `server` 对象。采集器与服务器的关联请在**采集器管理**接口中维护(如设置采集器的 `server_id`)。
### 错误响应
当达到许可证限制时,会返回以下错误:
```json
{
"code": 400,
"message": "已达到许可证允许的最大服务器数量限制({max_server}),无法创建更多服务器",
"data": null
}
```
---
## 4. 更新服务器
### 接口信息
- **路径**: `PUT /DC-Control/v1/servers/:id`
- **描述**: 更新服务器信息
### 请求参数
#### 路径参数 (Path Parameters)
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|--------|
| id | uint | 是 | 服务器ID必须大于0 |
#### 请求体 (Request Body)
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|--------|
| server_identity | string | 否 | 服务器唯一标识 |
| name | string | 否 | 服务器名称 |
| host | string | 否 | 服务器地址 |
| ip_address | string | 否 | IP地址 |
| description | string | 否 | 描述信息 |
| server_type | string | 否 | 服务器类型 |
| tags | string | 否 | 标签,逗号分隔 |
| location | string | 否 | 位置/机房信息 |
| remote_access | string | 否 | 远程访问 |
| agent_config | string | 否 | Agent 配置 |
| status | string | 否 | 状态 |
| last_check_time | string (RFC3339) | 否 | 最后检查时间 |
| collect_on | bool | 否 | 是否启用采集(可显式更新为 false |
| collect_args | string | 否 | 采集参数 |
| collect_interval | int | 否 | 采集间隔(秒) |
| collect_last_result | string | 否 | 采集最后结果 |
| os / os_version / kernel | string | 否 | 操作系统与内核字段 |
**注意**: 只传需要更新的字段;未出现的列不修改。更新使用 `map` 写入,可将 `collect_on``collect_interval` 等设为 `false`/`0`
### 请求示例
```http
PUT /DC-Control/v1/servers/1
Authorization: Bearer {JWT_TOKEN}
Content-Type: application/json
{
"description": "",
"status": "offline",
"collect_on": false
}
```
### 返回参数
```json
{
"code": 200,
"message": "success",
"data": {
"message": "updated"
}
}
```
---
## 5. 删除服务器
### 接口信息
- **路径**: `DELETE /DC-Control/v1/servers/:id`
- **描述**: 删除服务器(软删除)
### 请求参数
#### 路径参数 (Path Parameters)
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|--------|
| id | uint | 是 | 服务器ID必须大于0 |
### 请求示例
```http
DELETE /DC-Control/v1/servers/1
Authorization: Bearer {JWT_TOKEN}
```
### 返回参数
```json
{
"code": 200,
"message": "success",
"data": {
"message": "deleted"
}
}
```
---
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 成功 |
| 400 | 参数验证失败如ID为0、page/size无效等 |
| 401 | 未授权JWT Token无效或过期 |
| 404 | 资源不存在 |
| 500 | 服务器内部错误 |
## 注意事项
1. 所有接口都需要在请求头中携带JWT Token`Authorization: Bearer {JWT_TOKEN}`
2. 服务器ID必须大于0
3. 分页参数page和size必须为正整数size最大为100
4. `server_identity` 在库中必须唯一;若创建时不传则由服务端生成 ULID
5. 服务器类型(`server_type`支持physical物理、virtual虚拟、cloud
6. 服务器状态online在线、offline离线、unknown未知
7. 删除服务器为软删除,数据不会真正删除
8. **tags** 为可选,任意逗号分隔字符串(如 `env,app,tier`),长度受模型 `varchar(500)` 限制
9. **许可证限制**:创建服务器时会检查**服务器总条数**是否达到许可证 `MaxServer` 上限,超出则拒绝创建
10. 服务器 CRUD **不处理**采集器绑定;关联关系通过**采集器管理**接口(更新采集器 `server_id` 等)维护。列表与详情不内嵌采集器数组。

View File

@@ -121,6 +121,7 @@ import { Message } from '@arco-design/web-vue'
import { v4 as uuidv4 } from 'uuid'
import type { FormInstance } from '@arco-design/web-vue'
import DatacenterSelector from './DatacenterSelector.vue'
import { createServer, updateServer } from '@/api/ops/server'
interface Props {
visible: boolean
@@ -216,17 +217,52 @@ const handleOk = async () => {
try {
await formRef.value?.validate()
if (!formData.unique_id) {
formData.unique_id = uuidv4()
}
confirmLoading.value = true
await new Promise(resolve => setTimeout(resolve, 1000))
// 准备提交数据
const submitData: any = {
name: formData.name,
host: formData.ip,
ip_address: formData.ip,
description: formData.remark,
os: formData.os,
server_type: formData.server_type,
kernel: formData.kernel,
tags: formData.tags,
remote_access: formData.remote_access,
agent_config: formData.agent_config,
collect_on: formData.data_collection,
collect_interval: formData.collection_interval,
}
Message.success(isEdit.value ? '更新成功' : '创建成功')
emit('success')
handleCancel()
// 编辑模式或唯一标识
if (isEdit.value && props.record?.id) {
// 更新服务器
const res: any = await updateServer(props.record.id, submitData)
if (res.code === 200 || res.code === 0) {
Message.success('更新成功')
emit('success')
handleCancel()
} else {
Message.error(res.message || '更新失败')
}
} else {
// 创建服务器
if (!formData.unique_id) {
submitData.server_identity = uuidv4()
} else {
submitData.server_identity = formData.unique_id
}
const res: any = await createServer(submitData)
if (res.code === 200 || res.code === 0) {
Message.success('创建成功')
emit('success')
handleCancel()
} else {
Message.error(res.message || '创建失败')
}
}
} catch (error) {
console.error('验证失败:', error)
} finally {

View File

@@ -6,7 +6,7 @@ export const columns = [
slotName: 'id',
},
{
dataIndex: 'service_identity',
dataIndex: 'server_identity',
title: '唯一标识',
width: 150,
},
@@ -15,34 +15,34 @@ export const columns = [
title: '名称',
width: 150,
},
{
dataIndex: 'host',
title: '主机地址',
width: 150,
},
{
dataIndex: 'ip_address',
title: 'IP 地址',
width: 150,
},
{
dataIndex: 'os',
title: '操作系统',
width: 120,
},
{
dataIndex: 'os_version',
title: '系统版本',
width: 120,
},
{
dataIndex: 'server_type',
title: '类型',
width: 120,
},
{
dataIndex: 'os',
title: '操作系统',
width: 150,
},
{
dataIndex: 'kernel',
title: '内核类型',
width: 150,
},
{
dataIndex: 'location',
title: '位置信息',
width: 150,
},
{
dataIndex: 'tags',
title: '标签',
width: 120,
},
{
dataIndex: 'ip',
title: 'IP地址',
width: 150,
},
{
@@ -53,30 +53,12 @@ export const columns = [
},
{
dataIndex: 'agent_config',
title: 'Agent配置',
width: 150,
title: 'Agent 配置',
width: 100,
slotName: 'agent_config',
},
{
dataIndex: 'cpu',
title: 'CPU使用率',
width: 150,
slotName: 'cpu',
},
{
dataIndex: 'memory',
title: '内存使用率',
width: 150,
slotName: 'memory',
},
{
dataIndex: 'disk',
title: '硬盘使用率',
width: 150,
slotName: 'disk',
},
{
dataIndex: 'data_collection',
dataIndex: 'collect_on',
title: '数据采集',
width: 100,
slotName: 'data_collection',

View File

@@ -5,36 +5,18 @@ export const searchFormConfig: FormItem[] = [
field: 'keyword',
label: '关键词',
type: 'input',
placeholder: '请输入服务器名称、编码或IP',
span: 6,
placeholder: '请输入服务器名称、主机地址',
span: 8,
},
{
field: 'datacenter_id',
label: '数据中心',
field: 'collect_on',
label: '数据采集',
type: 'select',
placeholder: '请选择数据中心',
options: [], // 需要动态加载
span: 6,
},
{
field: 'rack_id',
label: '机柜',
type: 'select',
placeholder: '请选择机柜',
options: [], // 需要动态加载
span: 6,
},
{
field: 'status',
label: '状态',
type: 'select',
placeholder: '请选择状态',
placeholder: '请选择采集状态',
options: [
{ label: '在线', value: 'online' },
{ label: '离线', value: 'offline' },
{ label: '维护中', value: 'maintenance' },
{ label: '已退役', value: 'retired' },
{ label: '启用', value: true },
{ label: '禁用', value: false },
],
span: 6,
span: 8,
},
]

View File

@@ -37,13 +37,13 @@
</a-tag>
</template>
<!-- Agent配置 -->
<!-- Agent 配置 -->
<template #agent_config="{ record }">
<a-tag :color="record.agent_config ? 'green' : 'gray'">
{{ record.agent_config ? '已配置' : '未配置' }}
</a-tag>
</template>
<!-- CPU -->
<template #cpu="{ record }">
<div class="resource-display">
@@ -64,7 +64,7 @@
<template #memory="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-laebl">内存</span>
<span class="resource-label">内存</span>
<span class="resource-value">{{ record.memory_info?.value || 0 }}%</span>
</div>
<a-progress
@@ -91,11 +91,11 @@
/>
</div>
</template>
<!-- 数据采集 -->
<template #data_collection="{ record }">
<a-tag :color="record.data_collection ? 'green' : 'gray'">
{{ record.data_collection ? '已启用' : '未启用' }}
<a-tag :color="record.collect_on ? 'green' : 'gray'">
{{ record.collect_on ? '已启用' : '未启用' }}
</a-tag>
</template>
@@ -202,215 +202,10 @@ import {
fetchServerList,
deleteServer,
} from '@/api/ops/server'
import { fetchDatacenterAll } from '@/api/ops/datacenter'
import { fetchRackListByDatacenter } from '@/api/ops/rack'
import axios from 'axios'
const router = useRouter()
// Mock 假数据
const mockServerData = [
{
id: 1,
unique_id: 'SRV-2024-0001',
name: 'Web服务器-01',
type: 'Web服务器',
os: 'CentOS 7.9',
location: '数据中心A-1楼-机柜01-U1',
tags: 'Web,应用',
ip: '192.168.1.101',
remote_access: true,
agent_config: true,
cpu: '8核 Intel Xeon',
memory: '32GB',
disk: '1TB SSD',
cpu_info: { value: 45, total: '8核', used: '3.6核' },
memory_info: { value: 62, total: '32GB', used: '19.8GB' },
disk_info: { value: 78, total: '1TB', used: '780GB' },
data_collection: true,
status: 'online',
},
{
id: 2,
unique_id: 'SRV-2024-0002',
name: '数据库服务器-01',
type: '数据库服务器',
os: 'Ubuntu 22.04',
location: '数据中心A-1楼-机柜02-U1',
tags: '数据库,MySQL',
ip: '192.168.1.102',
remote_access: true,
agent_config: true,
cpu: '16核 AMD EPYC',
memory: '64GB',
disk: '2TB NVMe',
cpu_info: { value: 78, total: '16核', used: '12.5核' },
memory_info: { value: 85, total: '64GB', used: '54.4GB' },
disk_info: { value: 92, total: '2TB', used: '1.84TB' },
data_collection: true,
status: 'online',
},
{
id: 3,
unique_id: 'SRV-2024-0003',
name: '应用服务器-01',
type: '应用服务器',
os: 'Windows Server 2019',
location: '数据中心A-2楼-机柜05-U2',
tags: '应用,.NET',
ip: '192.168.1.103',
remote_access: false,
agent_config: false,
cpu: '4核 Intel Xeon',
memory: '16GB',
disk: '500GB SSD',
cpu_info: { value: 0, total: '4核', used: '0核' },
memory_info: { value: 0, total: '16GB', used: '0GB' },
disk_info: { value: 0, total: '500GB', used: '0GB' },
data_collection: false,
status: 'offline',
},
{
id: 4,
unique_id: 'SRV-2024-0004',
name: '缓存服务器-01',
type: '缓存服务器',
os: 'CentOS 8.5',
location: '数据中心A-2楼-机柜06-U1',
tags: '缓存,Redis',
ip: '192.168.1.104',
remote_access: true,
agent_config: true,
cpu: '8核 Intel Xeon',
memory: '32GB',
disk: '1TB SSD',
cpu_info: { value: 35, total: '8核', used: '2.8核' },
memory_info: { value: 68, total: '32GB', used: '21.8GB' },
disk_info: { value: 42, total: '1TB', used: '420GB' },
data_collection: true,
status: 'online',
},
{
id: 5,
unique_id: 'SRV-2024-0005',
name: '文件服务器-01',
type: '文件服务器',
os: 'Debian 11',
location: '数据中心B-1楼-机柜03-U1',
tags: '文件,NFS',
ip: '192.168.2.101',
remote_access: true,
agent_config: true,
cpu: '12核 Intel Xeon',
memory: '48GB',
disk: '10TB HDD',
cpu_info: { value: 28, total: '12核', used: '3.4核' },
memory_info: { value: 45, total: '48GB', used: '21.6GB' },
disk_info: { value: 88, total: '10TB', used: '8.8TB' },
data_collection: true,
status: 'maintenance',
},
{
id: 6,
unique_id: 'SRV-2024-0006',
name: '测试服务器-01',
type: '测试服务器',
os: 'CentOS 7.9',
location: '数据中心B-2楼-机柜10-U1',
tags: '测试,开发',
ip: '192.168.2.102',
remote_access: false,
agent_config: false,
cpu: '4核 Intel Xeon',
memory: '8GB',
disk: '256GB SSD',
cpu_info: { value: 0, total: '4核', used: '0核' },
memory_info: { value: 0, total: '8GB', used: '0GB' },
disk_info: { value: 0, total: '256GB', used: '0GB' },
data_collection: false,
status: 'retired',
},
{
id: 7,
unique_id: 'SRV-2024-0007',
name: '监控服务器-01',
type: '监控服务器',
os: 'Ubuntu 20.04',
location: '数据中心A-1楼-机柜08-U1',
tags: '监控,Prometheus',
ip: '192.168.1.105',
remote_access: true,
agent_config: true,
cpu: '8核 Intel Xeon',
memory: '32GB',
disk: '1TB SSD',
cpu_info: { value: 55, total: '8核', used: '4.4核' },
memory_info: { value: 72, total: '32GB', used: '23.0GB' },
disk_info: { value: 65, total: '1TB', used: '650GB' },
data_collection: true,
status: 'online',
},
{
id: 8,
unique_id: 'SRV-2024-0008',
name: '备份服务器-01',
type: '备份服务器',
os: 'Rocky Linux 9',
location: '数据中心B-1楼-机柜04-U1',
tags: '备份,存储',
ip: '192.168.2.103',
remote_access: true,
agent_config: true,
cpu: '16核 AMD EPYC',
memory: '64GB',
disk: '20TB HDD',
cpu_info: { value: 42, total: '16核', used: '6.7核' },
memory_info: { value: 38, total: '64GB', used: '24.3GB' },
disk_info: { value: 75, total: '20TB', used: '15TB' },
data_collection: true,
status: 'online',
},
{
id: 9,
unique_id: 'SRV-2024-0009',
name: 'CI/CD服务器-01',
type: 'CI/CD服务器',
os: 'Ubuntu 22.04',
location: '数据中心A-2楼-机柜07-U1',
tags: 'CI/CD,Jenkins',
ip: '192.168.1.106',
remote_access: true,
agent_config: true,
cpu: '8核 Intel Xeon',
memory: '16GB',
disk: '500GB SSD',
cpu_info: { value: 68, total: '8核', used: '5.4核' },
memory_info: { value: 75, total: '16GB', used: '12GB' },
disk_info: { value: 55, total: '500GB', used: '275GB' },
data_collection: true,
status: 'online',
},
{
id: 10,
unique_id: 'SRV-2024-0010',
name: '日志服务器-01',
type: '日志服务器',
os: 'CentOS Stream 9',
location: '数据中心B-2楼-机柜12-U1',
tags: '日志,ELK',
ip: '192.168.2.104',
remote_access: true,
agent_config: true,
cpu: '12核 Intel Xeon',
memory: '48GB',
disk: '2TB SSD',
cpu_info: { value: 0, total: '12核', used: '0核' },
memory_info: { value: 0, total: '48GB', used: '0GB' },
disk_info: { value: 0, total: '2TB', used: '0TB' },
data_collection: true,
status: 'offline',
},
]
// 状态管理
const loading = ref(false)
const tableData = ref<any[]>([])
@@ -419,9 +214,7 @@ const quickConfigVisible = ref(false)
const currentRecord = ref<any>(null)
const formModel = ref({
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
collect_on: undefined as boolean | undefined,
})
const pagination = reactive({
@@ -430,69 +223,16 @@ const pagination = reactive({
total: 0,
})
const datacenterSelectOptions = ref<{ label: string; value: number }[]>([])
const rackSelectOptions = ref<{ label: string; value: number }[]>([])
const loadDatacenterOptions = async () => {
try {
const res: any = await fetchDatacenterAll()
if (res.code === 0) {
const list = res.details?.data ?? res.data ?? res.details ?? []
const rows = Array.isArray(list) ? list : []
datacenterSelectOptions.value = rows.map((d: any) => ({
label: d.name || d.code || String(d.id),
value: d.id,
}))
}
} catch (error) {
console.error('加载数据中心列表失败:', error)
Message.error('加载数据中心列表失败')
}
}
const loadRackOptions = async (datacenterId: number) => {
try {
const res: any = await fetchRackListByDatacenter(datacenterId)
if (res.code === 0) {
const list = res.details?.data ?? res.data ?? res.details ?? []
const rows = Array.isArray(list) ? list : []
rackSelectOptions.value = rows.map((r: any) => ({
label: r.floor?.name ? `${r.name}${r.floor.name}` : r.name || r.code || String(r.id),
value: r.id,
}))
}
} catch (error) {
console.error('加载机柜列表失败:', error)
Message.error('加载机柜列表失败')
rackSelectOptions.value = []
}
}
watch(
() => formModel.value.datacenter_id,
(newId, oldId) => {
if (newId !== oldId) {
formModel.value.rack_id = undefined
}
if (newId) {
loadRackOptions(newId)
} else {
rackSelectOptions.value = []
}
}
)
// 表单项配置数据中心GET /Assets/v1/datacenter/all机柜GET /Assets/v1/rack/datacenter/:id
// 表单项配置
const formItems = computed<FormItem[]>(() =>
searchFormConfig.map((item) => {
if (item.field === 'datacenter_id') {
return { ...item, options: datacenterSelectOptions.value }
}
if (item.field === 'rack_id') {
if (item.field === 'collect_on') {
return {
...item,
options: rackSelectOptions.value,
disabled: !formModel.value.datacenter_id,
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
}
}
return item
@@ -507,8 +247,7 @@ const getStatusColor = (status?: string) => {
const colorMap: Record<string, string> = {
online: 'green',
offline: 'red',
maintenance: 'orange',
retired: 'gray',
unknown: 'gray',
}
return colorMap[status || ''] || 'gray'
}
@@ -518,8 +257,7 @@ const getStatusText = (status?: string) => {
const textMap: Record<string, string> = {
online: '在线',
offline: '离线',
maintenance: '维护中',
retired: '已退役',
unknown: '未知',
}
return textMap[status || ''] || '-'
}
@@ -532,37 +270,37 @@ const getProgressColor = (value: number) => {
return '#00B42A' // 绿色
}
// 获取服务器列表(使用 Mock 数据)
// 获取服务器列表
const fetchServers = async () => {
loading.value = true
try {
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 500))
const params: any = {
page: pagination.current,
size: pagination.pageSize,
}
// 使用 Mock 数据
tableData.value = mockServerData
pagination.total = mockServerData.length
if (formModel.value.keyword) {
params.keyword = formModel.value.keyword
}
// 如果有搜索条件,进行过滤
if (formModel.value.keyword || formModel.value.status) {
let filteredData = [...mockServerData]
if (formModel.value.collect_on !== undefined) {
params.collect_on = formModel.value.collect_on
}
const res: any = await fetchServerList(params)
if (res.code === 200 || res.code === 0) {
const responseData = res.data || res.details || {}
tableData.value = responseData.data || []
pagination.total = responseData.total || 0
if (formModel.value.keyword) {
const keyword = formModel.value.keyword.toLowerCase()
filteredData = filteredData.filter(item =>
item.name.toLowerCase().includes(keyword) ||
item.unique_id.toLowerCase().includes(keyword) ||
item.ip.toLowerCase().includes(keyword)
)
}
if (formModel.value.status) {
filteredData = filteredData.filter(item => item.status === formModel.value.status)
}
tableData.value = filteredData
pagination.total = filteredData.length
// 列表加载成功后,获取监控指标
await getAllMetrics()
} else {
Message.error(res.message || '获取服务器列表失败')
tableData.value = []
pagination.total = 0
}
} catch (error) {
console.error('获取服务器列表失败:', error)
@@ -589,11 +327,8 @@ const handleFormModelUpdate = (value: any) => {
const handleReset = () => {
formModel.value = {
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
collect_on: undefined,
}
rackSelectOptions.value = []
pagination.current = 1
fetchServers()
}
@@ -673,31 +408,100 @@ const handleRemoteControl = (record: any) => {
// 删除服务器
const handleDelete = async (record: any) => {
try {
Modal.confirm({
title: '确认删除',
content: `确认删除服务器 ${record.name} 吗?`,
onOk: async () => {
// Mock 删除操作
const index = mockServerData.findIndex(item => item.id === record.id)
if (index > -1) {
mockServerData.splice(index, 1)
Modal.confirm({
title: '确认删除',
content: `确认删除服务器 ${record.name} 吗?`,
onOk: async () => {
try {
const res: any = await deleteServer(record.id)
if (res.code === 200 || res.code === 0) {
Message.success('删除成功')
fetchServers()
} else {
Message.error('删除失败')
Message.error(res.message || '删除失败')
}
},
} catch (error) {
console.error('删除服务器失败:', error)
Message.error('删除失败')
}
},
})
}
// 获取所有服务器的监控指标
const getAllMetrics = async () => {
try {
// 遍历每个服务器记录
const metricsPromises = tableData.value.map(async (record) => {
// 检查是否有 agent_config 配置
if (record.agent_config) {
try {
// 从 agent_config 中解析 URL
let metricsUrl = record.agent_config
// 验证 URL 是否合法
try {
new URL(metricsUrl)
} catch (urlError) {
console.warn(`服务器 ${record.name} 的 agent_config 不是合法的 URL:`, metricsUrl)
// 设置默认值 0
record.cpu_info = { value: 0, total: '', used: '' }
record.memory_info = { value: 0, total: '', used: '' }
record.disk_info = { value: 0, total: '', used: '' }
return
}
// 发送请求获取指标数据
const response = await axios.get(metricsUrl, {
timeout: 5000, // 5 秒超时
})
if (response.data) {
// 更新记录的监控数据
record.cpu_info = {
value: response.data.cpu_usage || 0,
total: response.data.cpu?.[0]?.cores ? `${response.data.cpu[0].cores}` : '',
used: '',
}
record.memory_info = {
value: response.data.mem_usage?.used_percent || 0,
total: response.data.mem_usage?.total ? `${(response.data.mem_usage.total / 1024 / 1024 / 1024).toFixed(1)}GB` : '',
used: response.data.mem_usage?.used ? `${(response.data.mem_usage.used / 1024 / 1024 / 1024).toFixed(1)}GB` : '',
}
record.disk_info = {
value: response.data.disk_usage?.used_percent || 0,
total: response.data.disk_usage?.total ? `${(response.data.disk_usage.total / 1024 / 1024 / 1024).toFixed(0)}GB` : '',
used: response.data.disk_usage?.used ? `${(response.data.disk_usage.used / 1024 / 1024 / 1024).toFixed(0)}GB` : '',
}
}
} catch (error) {
console.warn(`获取服务器 ${record.name} 的监控指标失败:`, error)
// 初始化默认值
record.cpu_info = { value: 0, total: '', used: '' }
record.memory_info = { value: 0, total: '', used: '' }
record.disk_info = { value: 0, total: '', used: '' }
}
} else {
// 没有配置 agent设置默认值
record.cpu_info = { value: 0, total: '', used: '' }
record.memory_info = { value: 0, total: '', used: '' }
record.disk_info = { value: 0, total: '', used: '' }
}
})
// 等待所有请求完成
await Promise.all(metricsPromises)
} catch (error) {
console.error('删除服务器失败:', error)
console.error('获取所有服务器监控指标失败:', error)
}
}
onMounted(() => {
loadDatacenterOptions()
fetchServers()
})
</script>
<script lang="ts">