This commit is contained in:
2026-03-21 21:46:55 +08:00
parent d59c591951
commit 8ebb29174f
10 changed files with 2427 additions and 3 deletions

View File

@@ -0,0 +1,92 @@
export const columns = [
{
dataIndex: 'id',
title: 'ID',
width: 80,
slotName: 'id',
},
{
dataIndex: 'unique_id',
title: '唯一标识',
width: 150,
},
{
dataIndex: 'name',
title: '名称',
width: 150,
},
{
dataIndex: 'type',
title: '类型',
width: 120,
},
{
dataIndex: 'os',
title: '操作系统',
width: 150,
},
{
dataIndex: 'location',
title: '位置信息',
width: 150,
},
{
dataIndex: 'tags',
title: '标签',
width: 120,
},
{
dataIndex: 'ip',
title: 'IP地址',
width: 150,
},
{
dataIndex: 'remote_access',
title: '远程访问',
width: 100,
slotName: 'remote_access',
},
{
dataIndex: 'agent_config',
title: 'Agent配置',
width: 150,
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',
title: '数据采集',
width: 100,
slotName: 'data_collection',
},
{
dataIndex: 'status',
title: '状态',
width: 100,
slotName: 'status',
},
{
dataIndex: 'actions',
title: '操作',
width: 180,
fixed: 'right' as const,
slotName: 'actions',
},
]

View File

@@ -0,0 +1,40 @@
import type { FormItem } from '@/components/search-form/types'
export const searchFormConfig: FormItem[] = [
{
field: 'keyword',
label: '关键词',
type: 'input',
placeholder: '请输入服务器名称、编码或IP',
span: 6,
},
{
field: 'datacenter_id',
label: '数据中心',
type: 'select',
placeholder: '请选择数据中心',
options: [], // 需要动态加载
span: 6,
},
{
field: 'rack_id',
label: '机柜',
type: 'select',
placeholder: '请选择机柜',
options: [], // 需要动态加载
span: 6,
},
{
field: 'status',
label: '状态',
type: 'select',
placeholder: '请选择状态',
options: [
{ label: '在线', value: 'online' },
{ label: '离线', value: 'offline' },
{ label: '维护中', value: 'maintenance' },
{ label: '已退役', value: 'retired' },
],
span: 6,
},
]

View File

@@ -0,0 +1,676 @@
<template>
<div class="container">
<search-table
:form-model="formModel"
:form-items="formItems"
:data="tableData"
:columns="columns"
:loading="loading"
:pagination="pagination"
title="数据库管理"
search-button-text="查询"
reset-button-text="重置"
@update:form-model="handleFormModelUpdate"
@search="handleSearch"
@reset="handleReset"
@page-change="handlePageChange"
@refresh="handleRefresh"
>
<template #toolbar-left>
<a-button type="primary" @click="handleAdd">
<template #icon>
<icon-plus />
</template>
新增数据库
</a-button>
</template>
<!-- ID -->
<template #id="{ record }">
{{ record.id }}
</template>
<!-- 远程访问 -->
<template #remote_access="{ record }">
<a-tag :color="record.remote_access ? 'green' : 'gray'">
{{ record.remote_access ? '已开启' : '未开启' }}
</a-tag>
</template>
<!-- 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">
<div class="resource-info">
<span class="resource-label">CPU</span>
<span class="resource-value">{{ record.cpu_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.cpu_info?.value || 0) / 100"
:color="getProgressColor(record.cpu_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 内存 -->
<template #memory="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-laebl">内存</span>
<span class="resource-value">{{ record.memory_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.memory_info?.value || 0) / 100"
:color="getProgressColor(record.memory_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 硬盘 -->
<template #disk="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-label">硬盘</span>
<span class="resource-value">{{ record.disk_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.disk_info?.value || 0) / 100"
:color="getProgressColor(record.disk_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 数据采集 -->
<template #data_collection="{ record }">
<a-tag :color="record.data_collection ? 'green' : 'gray'">
{{ record.data_collection ? '已启用' : '未启用' }}
</a-tag>
</template>
<!-- 状态 -->
<template #status="{ record }">
<a-tag :color="getStatusColor(record.status)">
{{ getStatusText(record.status) }}
</a-tag>
</template>
<!-- 操作栏 - 下拉菜单 -->
<template #actions="{ record }">
<a-space>
<a-button
v-if="!record.agent_config"
type="outline"
size="small"
@click="handleQuickConfig(record)"
>
<template #icon>
<icon-settings />
</template>
快捷配置
</a-button>
<a-dropdown trigger="hover">
<a-button type="primary" size="small">
管理
<icon-down />
</a-button>
<template #content>
<a-doption @click="handleRestart(record)">
<template #icon>
<icon-refresh />
</template>
重启
</a-doption>
<a-doption @click="handleDetail(record)">
<template #icon>
<icon-eye />
</template>
详情
</a-doption>
<a-doption @click="handleEdit(record)">
<template #icon>
<icon-edit />
</template>
编辑
</a-doption>
<a-doption @click="handleRemoteControl(record)">
<template #icon>
<icon-desktop />
</template>
远程控制
</a-doption>
<a-doption @click="handleDelete(record)" style="color: rgb(var(--danger-6))">
<template #icon>
<icon-delete />
</template>
删除
</a-doption>
</template>
</a-dropdown>
</a-space>
</template>
</search-table>
<!-- 新增/编辑对话框 -->
<ServerFormDialog
v-model:visible="formDialogVisible"
:record="currentRecord"
@success="handleFormSuccess"
/>
<!-- 快捷配置对话框 -->
<QuickConfigDialog
v-model:visible="quickConfigVisible"
:record="currentRecord"
@success="handleFormSuccess"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { useRouter } from 'vue-router'
import { Message, Modal } from '@arco-design/web-vue'
import {
IconPlus,
IconDown,
IconEdit,
IconDesktop,
IconDelete,
IconRefresh,
IconEye,
IconSettings
} from '@arco-design/web-vue/es/icon'
import type { FormItem } from '@/components/search-form/types'
import SearchTable from '@/components/search-table/index.vue'
import { searchFormConfig } from './config/search-form'
import ServerFormDialog from '../pc/components/ServerFormDialog.vue'
import QuickConfigDialog from '../pc/components/QuickConfigDialog.vue'
import { columns as columnsConfig } from './config/columns'
import {
fetchServerList,
deleteServer,
} from '@/api/ops/server'
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[]>([])
const formDialogVisible = ref(false)
const quickConfigVisible = ref(false)
const currentRecord = ref<any>(null)
const formModel = ref({
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
})
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0,
})
// 表单项配置
const formItems = computed<FormItem[]>(() => searchFormConfig)
// 表格列配置
const columns = computed(() => columnsConfig)
// 获取状态颜色
const getStatusColor = (status?: string) => {
const colorMap: Record<string, string> = {
online: 'green',
offline: 'red',
maintenance: 'orange',
retired: 'gray',
}
return colorMap[status || ''] || 'gray'
}
// 获取状态文本
const getStatusText = (status?: string) => {
const textMap: Record<string, string> = {
online: '在线',
offline: '离线',
maintenance: '维护中',
retired: '已退役',
}
return textMap[status || ''] || '-'
}
// 获取进度条颜色
const getProgressColor = (value: number) => {
if (value >= 90) return '#F53F3F' // 红色
if (value >= 70) return '#FF7D00' // 橙色
if (value >= 50) return '#FFD00B' // 黄色
return '#00B42A' // 绿色
}
// 获取数据库列表(使用 Mock 数据)
const fetchServers = async () => {
loading.value = true
try {
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 500))
// 使用 Mock 数据
tableData.value = mockServerData
pagination.total = mockServerData.length
// 如果有搜索条件,进行过滤
if (formModel.value.keyword || formModel.value.status) {
let filteredData = [...mockServerData]
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
}
} catch (error) {
console.error('获取数据库列表失败:', error)
Message.error('获取数据库列表失败')
tableData.value = []
pagination.total = 0
} finally {
loading.value = false
}
}
// 搜索
const handleSearch = () => {
pagination.current = 1
fetchServers()
}
// 处理表单模型更新
const handleFormModelUpdate = (value: any) => {
formModel.value = value
}
// 重置
const handleReset = () => {
formModel.value = {
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
}
pagination.current = 1
fetchServers()
}
// 分页变化
const handlePageChange = (current: number) => {
pagination.current = current
fetchServers()
}
// 刷新
const handleRefresh = () => {
fetchServers()
Message.success('数据已刷新')
}
// 新增数据库
const handleAdd = () => {
currentRecord.value = null
formDialogVisible.value = true
}
// 快捷配置
const handleQuickConfig = (record: any) => {
currentRecord.value = record
quickConfigVisible.value = true
}
// 编辑数据库
const handleEdit = (record: any) => {
currentRecord.value = record
formDialogVisible.value = true
}
// 表单提交成功
const handleFormSuccess = () => {
fetchServers()
}
// 重启数据库
const handleRestart = (record: any) => {
Modal.confirm({
title: '确认重启',
content: `确认重启数据库 ${record.name} 吗?`,
onOk: () => {
Message.info('正在发送重启指令...')
},
})
}
// 查看详情 - 在当前窗口打开
const handleDetail = (record: any) => {
router.push({
path: '/dc/detail',
query: {
id: record.id,
name: record.name,
ip: record.ip,
status: record.status,
},
})
}
// 远程控制 - 在新窗口打开
const handleRemoteControl = (record: any) => {
const url = router.resolve({
path: '/dc/remote',
query: {
id: record.id,
name: record.name,
ip: record.ip,
status: record.status,
},
}).href
window.open(url, '_blank')
}
// 删除数据库
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)
Message.success('删除成功')
fetchServers()
} else {
Message.error('删除失败')
}
},
})
} catch (error) {
console.error('删除数据库失败:', error)
}
}
// 初始化加载数据
fetchServers()
</script>
<script lang="ts">
export default {
name: 'DataCenterServer',
}
</script>
<style scoped lang="less">
.container {
margin-top: 20px;
}
.resource-display {
display: flex;
flex-direction: column;
gap: 4px;
padding: 4px 0;
.resource-info {
display: flex;
align-items: center;
justify-content: space-between;
> div {
display: inline-block;
}
.resource-value {
font-size: 12px;
font-weight: 500;
color: rgb(var(--text-1));
}
}
:deep(.arco-progress) {
margin: 0;
.arco-progress-bar-bg {
border-radius: 2px;
}
.arco-progress-bar {
border-radius: 2px;
transition: all 0.3s ease;
}
}
}
</style>

View File

@@ -0,0 +1,92 @@
export const columns = [
{
dataIndex: 'id',
title: 'ID',
width: 80,
slotName: 'id',
},
{
dataIndex: 'unique_id',
title: '唯一标识',
width: 150,
},
{
dataIndex: 'name',
title: '名称',
width: 150,
},
{
dataIndex: 'type',
title: '类型',
width: 120,
},
{
dataIndex: 'os',
title: '操作系统',
width: 150,
},
{
dataIndex: 'location',
title: '位置信息',
width: 150,
},
{
dataIndex: 'tags',
title: '标签',
width: 120,
},
{
dataIndex: 'ip',
title: 'IP地址',
width: 150,
},
{
dataIndex: 'remote_access',
title: '远程访问',
width: 100,
slotName: 'remote_access',
},
{
dataIndex: 'agent_config',
title: 'Agent配置',
width: 150,
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',
title: '数据采集',
width: 100,
slotName: 'data_collection',
},
{
dataIndex: 'status',
title: '状态',
width: 100,
slotName: 'status',
},
{
dataIndex: 'actions',
title: '操作',
width: 180,
fixed: 'right' as const,
slotName: 'actions',
},
]

View File

@@ -0,0 +1,40 @@
import type { FormItem } from '@/components/search-form/types'
export const searchFormConfig: FormItem[] = [
{
field: 'keyword',
label: '关键词',
type: 'input',
placeholder: '请输入服务器名称、编码或IP',
span: 6,
},
{
field: 'datacenter_id',
label: '数据中心',
type: 'select',
placeholder: '请选择数据中心',
options: [], // 需要动态加载
span: 6,
},
{
field: 'rack_id',
label: '机柜',
type: 'select',
placeholder: '请选择机柜',
options: [], // 需要动态加载
span: 6,
},
{
field: 'status',
label: '状态',
type: 'select',
placeholder: '请选择状态',
options: [
{ label: '在线', value: 'online' },
{ label: '离线', value: 'offline' },
{ label: '维护中', value: 'maintenance' },
{ label: '已退役', value: 'retired' },
],
span: 6,
},
]

View File

@@ -0,0 +1,676 @@
<template>
<div class="container">
<search-table
:form-model="formModel"
:form-items="formItems"
:data="tableData"
:columns="columns"
:loading="loading"
:pagination="pagination"
title="中间件管理"
search-button-text="查询"
reset-button-text="重置"
@update:form-model="handleFormModelUpdate"
@search="handleSearch"
@reset="handleReset"
@page-change="handlePageChange"
@refresh="handleRefresh"
>
<template #toolbar-left>
<a-button type="primary" @click="handleAdd">
<template #icon>
<icon-plus />
</template>
新增中间件
</a-button>
</template>
<!-- ID -->
<template #id="{ record }">
{{ record.id }}
</template>
<!-- 远程访问 -->
<template #remote_access="{ record }">
<a-tag :color="record.remote_access ? 'green' : 'gray'">
{{ record.remote_access ? '已开启' : '未开启' }}
</a-tag>
</template>
<!-- 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">
<div class="resource-info">
<span class="resource-label">CPU</span>
<span class="resource-value">{{ record.cpu_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.cpu_info?.value || 0) / 100"
:color="getProgressColor(record.cpu_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 内存 -->
<template #memory="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-laebl">内存</span>
<span class="resource-value">{{ record.memory_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.memory_info?.value || 0) / 100"
:color="getProgressColor(record.memory_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 硬盘 -->
<template #disk="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-label">硬盘</span>
<span class="resource-value">{{ record.disk_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.disk_info?.value || 0) / 100"
:color="getProgressColor(record.disk_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 数据采集 -->
<template #data_collection="{ record }">
<a-tag :color="record.data_collection ? 'green' : 'gray'">
{{ record.data_collection ? '已启用' : '未启用' }}
</a-tag>
</template>
<!-- 状态 -->
<template #status="{ record }">
<a-tag :color="getStatusColor(record.status)">
{{ getStatusText(record.status) }}
</a-tag>
</template>
<!-- 操作栏 - 下拉菜单 -->
<template #actions="{ record }">
<a-space>
<a-button
v-if="!record.agent_config"
type="outline"
size="small"
@click="handleQuickConfig(record)"
>
<template #icon>
<icon-settings />
</template>
快捷配置
</a-button>
<a-dropdown trigger="hover">
<a-button type="primary" size="small">
管理
<icon-down />
</a-button>
<template #content>
<a-doption @click="handleRestart(record)">
<template #icon>
<icon-refresh />
</template>
重启
</a-doption>
<a-doption @click="handleDetail(record)">
<template #icon>
<icon-eye />
</template>
详情
</a-doption>
<a-doption @click="handleEdit(record)">
<template #icon>
<icon-edit />
</template>
编辑
</a-doption>
<a-doption @click="handleRemoteControl(record)">
<template #icon>
<icon-desktop />
</template>
远程控制
</a-doption>
<a-doption @click="handleDelete(record)" style="color: rgb(var(--danger-6))">
<template #icon>
<icon-delete />
</template>
删除
</a-doption>
</template>
</a-dropdown>
</a-space>
</template>
</search-table>
<!-- 新增/编辑对话框 -->
<ServerFormDialog
v-model:visible="formDialogVisible"
:record="currentRecord"
@success="handleFormSuccess"
/>
<!-- 快捷配置对话框 -->
<QuickConfigDialog
v-model:visible="quickConfigVisible"
:record="currentRecord"
@success="handleFormSuccess"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { useRouter } from 'vue-router'
import { Message, Modal } from '@arco-design/web-vue'
import {
IconPlus,
IconDown,
IconEdit,
IconDesktop,
IconDelete,
IconRefresh,
IconEye,
IconSettings
} from '@arco-design/web-vue/es/icon'
import type { FormItem } from '@/components/search-form/types'
import SearchTable from '@/components/search-table/index.vue'
import { searchFormConfig } from './config/search-form'
import ServerFormDialog from '../pc/components/ServerFormDialog.vue'
import QuickConfigDialog from '../pc/components/QuickConfigDialog.vue'
import { columns as columnsConfig } from './config/columns'
import {
fetchServerList,
deleteServer,
} from '@/api/ops/server'
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[]>([])
const formDialogVisible = ref(false)
const quickConfigVisible = ref(false)
const currentRecord = ref<any>(null)
const formModel = ref({
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
})
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0,
})
// 表单项配置
const formItems = computed<FormItem[]>(() => searchFormConfig)
// 表格列配置
const columns = computed(() => columnsConfig)
// 获取状态颜色
const getStatusColor = (status?: string) => {
const colorMap: Record<string, string> = {
online: 'green',
offline: 'red',
maintenance: 'orange',
retired: 'gray',
}
return colorMap[status || ''] || 'gray'
}
// 获取状态文本
const getStatusText = (status?: string) => {
const textMap: Record<string, string> = {
online: '在线',
offline: '离线',
maintenance: '维护中',
retired: '已退役',
}
return textMap[status || ''] || '-'
}
// 获取进度条颜色
const getProgressColor = (value: number) => {
if (value >= 90) return '#F53F3F' // 红色
if (value >= 70) return '#FF7D00' // 橙色
if (value >= 50) return '#FFD00B' // 黄色
return '#00B42A' // 绿色
}
// 获取中间件列表(使用 Mock 数据)
const fetchServers = async () => {
loading.value = true
try {
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 500))
// 使用 Mock 数据
tableData.value = mockServerData
pagination.total = mockServerData.length
// 如果有搜索条件,进行过滤
if (formModel.value.keyword || formModel.value.status) {
let filteredData = [...mockServerData]
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
}
} catch (error) {
console.error('获取中间件列表失败:', error)
Message.error('获取中间件列表失败')
tableData.value = []
pagination.total = 0
} finally {
loading.value = false
}
}
// 搜索
const handleSearch = () => {
pagination.current = 1
fetchServers()
}
// 处理表单模型更新
const handleFormModelUpdate = (value: any) => {
formModel.value = value
}
// 重置
const handleReset = () => {
formModel.value = {
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
}
pagination.current = 1
fetchServers()
}
// 分页变化
const handlePageChange = (current: number) => {
pagination.current = current
fetchServers()
}
// 刷新
const handleRefresh = () => {
fetchServers()
Message.success('数据已刷新')
}
// 新增中间件
const handleAdd = () => {
currentRecord.value = null
formDialogVisible.value = true
}
// 快捷配置
const handleQuickConfig = (record: any) => {
currentRecord.value = record
quickConfigVisible.value = true
}
// 编辑中间件
const handleEdit = (record: any) => {
currentRecord.value = record
formDialogVisible.value = true
}
// 表单提交成功
const handleFormSuccess = () => {
fetchServers()
}
// 重启中间件
const handleRestart = (record: any) => {
Modal.confirm({
title: '确认重启',
content: `确认重启中间件 ${record.name} 吗?`,
onOk: () => {
Message.info('正在发送重启指令...')
},
})
}
// 查看详情 - 在当前窗口打开
const handleDetail = (record: any) => {
router.push({
path: '/dc/detail',
query: {
id: record.id,
name: record.name,
ip: record.ip,
status: record.status,
},
})
}
// 远程控制 - 在新窗口打开
const handleRemoteControl = (record: any) => {
const url = router.resolve({
path: '/dc/remote',
query: {
id: record.id,
name: record.name,
ip: record.ip,
status: record.status,
},
}).href
window.open(url, '_blank')
}
// 删除中间件
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)
Message.success('删除成功')
fetchServers()
} else {
Message.error('删除失败')
}
},
})
} catch (error) {
console.error('删除中间件失败:', error)
}
}
// 初始化加载数据
fetchServers()
</script>
<script lang="ts">
export default {
name: 'DataCenterServer',
}
</script>
<style scoped lang="less">
.container {
margin-top: 20px;
}
.resource-display {
display: flex;
flex-direction: column;
gap: 4px;
padding: 4px 0;
.resource-info {
display: flex;
align-items: center;
justify-content: space-between;
> div {
display: inline-block;
}
.resource-value {
font-size: 12px;
font-weight: 500;
color: rgb(var(--text-1));
}
}
:deep(.arco-progress) {
margin: 0;
.arco-progress-bar-bg {
border-radius: 2px;
}
.arco-progress-bar {
border-radius: 2px;
transition: all 0.3s ease;
}
}
}
</style>

View File

@@ -0,0 +1,92 @@
export const columns = [
{
dataIndex: 'id',
title: 'ID',
width: 80,
slotName: 'id',
},
{
dataIndex: 'unique_id',
title: '唯一标识',
width: 150,
},
{
dataIndex: 'name',
title: '名称',
width: 150,
},
{
dataIndex: 'type',
title: '类型',
width: 120,
},
{
dataIndex: 'os',
title: '操作系统',
width: 150,
},
{
dataIndex: 'location',
title: '位置信息',
width: 150,
},
{
dataIndex: 'tags',
title: '标签',
width: 120,
},
{
dataIndex: 'ip',
title: 'IP地址',
width: 150,
},
{
dataIndex: 'remote_access',
title: '远程访问',
width: 100,
slotName: 'remote_access',
},
{
dataIndex: 'agent_config',
title: 'Agent配置',
width: 150,
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',
title: '数据采集',
width: 100,
slotName: 'data_collection',
},
{
dataIndex: 'status',
title: '状态',
width: 100,
slotName: 'status',
},
{
dataIndex: 'actions',
title: '操作',
width: 180,
fixed: 'right' as const,
slotName: 'actions',
},
]

View File

@@ -0,0 +1,40 @@
import type { FormItem } from '@/components/search-form/types'
export const searchFormConfig: FormItem[] = [
{
field: 'keyword',
label: '关键词',
type: 'input',
placeholder: '请输入服务器名称、编码或IP',
span: 6,
},
{
field: 'datacenter_id',
label: '数据中心',
type: 'select',
placeholder: '请选择数据中心',
options: [], // 需要动态加载
span: 6,
},
{
field: 'rack_id',
label: '机柜',
type: 'select',
placeholder: '请选择机柜',
options: [], // 需要动态加载
span: 6,
},
{
field: 'status',
label: '状态',
type: 'select',
placeholder: '请选择状态',
options: [
{ label: '在线', value: 'online' },
{ label: '离线', value: 'offline' },
{ label: '维护中', value: 'maintenance' },
{ label: '已退役', value: 'retired' },
],
span: 6,
},
]

View File

@@ -0,0 +1,676 @@
<template>
<div class="container">
<search-table
:form-model="formModel"
:form-items="formItems"
:data="tableData"
:columns="columns"
:loading="loading"
:pagination="pagination"
title="网络设备管理"
search-button-text="查询"
reset-button-text="重置"
@update:form-model="handleFormModelUpdate"
@search="handleSearch"
@reset="handleReset"
@page-change="handlePageChange"
@refresh="handleRefresh"
>
<template #toolbar-left>
<a-button type="primary" @click="handleAdd">
<template #icon>
<icon-plus />
</template>
新增网络设备
</a-button>
</template>
<!-- ID -->
<template #id="{ record }">
{{ record.id }}
</template>
<!-- 远程访问 -->
<template #remote_access="{ record }">
<a-tag :color="record.remote_access ? 'green' : 'gray'">
{{ record.remote_access ? '已开启' : '未开启' }}
</a-tag>
</template>
<!-- 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">
<div class="resource-info">
<span class="resource-label">CPU</span>
<span class="resource-value">{{ record.cpu_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.cpu_info?.value || 0) / 100"
:color="getProgressColor(record.cpu_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 内存 -->
<template #memory="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-laebl">内存</span>
<span class="resource-value">{{ record.memory_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.memory_info?.value || 0) / 100"
:color="getProgressColor(record.memory_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 硬盘 -->
<template #disk="{ record }">
<div class="resource-display">
<div class="resource-info">
<span class="resource-label">硬盘</span>
<span class="resource-value">{{ record.disk_info?.value || 0 }}%</span>
</div>
<a-progress
:percent="(record.disk_info?.value || 0) / 100"
:color="getProgressColor(record.disk_info?.value || 0)"
size="small"
:show-text="false"
/>
</div>
</template>
<!-- 数据采集 -->
<template #data_collection="{ record }">
<a-tag :color="record.data_collection ? 'green' : 'gray'">
{{ record.data_collection ? '已启用' : '未启用' }}
</a-tag>
</template>
<!-- 状态 -->
<template #status="{ record }">
<a-tag :color="getStatusColor(record.status)">
{{ getStatusText(record.status) }}
</a-tag>
</template>
<!-- 操作栏 - 下拉菜单 -->
<template #actions="{ record }">
<a-space>
<a-button
v-if="!record.agent_config"
type="outline"
size="small"
@click="handleQuickConfig(record)"
>
<template #icon>
<icon-settings />
</template>
快捷配置
</a-button>
<a-dropdown trigger="hover">
<a-button type="primary" size="small">
管理
<icon-down />
</a-button>
<template #content>
<a-doption @click="handleRestart(record)">
<template #icon>
<icon-refresh />
</template>
重启
</a-doption>
<a-doption @click="handleDetail(record)">
<template #icon>
<icon-eye />
</template>
详情
</a-doption>
<a-doption @click="handleEdit(record)">
<template #icon>
<icon-edit />
</template>
编辑
</a-doption>
<a-doption @click="handleRemoteControl(record)">
<template #icon>
<icon-desktop />
</template>
远程控制
</a-doption>
<a-doption @click="handleDelete(record)" style="color: rgb(var(--danger-6))">
<template #icon>
<icon-delete />
</template>
删除
</a-doption>
</template>
</a-dropdown>
</a-space>
</template>
</search-table>
<!-- 新增/编辑对话框 -->
<ServerFormDialog
v-model:visible="formDialogVisible"
:record="currentRecord"
@success="handleFormSuccess"
/>
<!-- 快捷配置对话框 -->
<QuickConfigDialog
v-model:visible="quickConfigVisible"
:record="currentRecord"
@success="handleFormSuccess"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { useRouter } from 'vue-router'
import { Message, Modal } from '@arco-design/web-vue'
import {
IconPlus,
IconDown,
IconEdit,
IconDesktop,
IconDelete,
IconRefresh,
IconEye,
IconSettings
} from '@arco-design/web-vue/es/icon'
import type { FormItem } from '@/components/search-form/types'
import SearchTable from '@/components/search-table/index.vue'
import { searchFormConfig } from './config/search-form'
import ServerFormDialog from '../pc/components/ServerFormDialog.vue'
import QuickConfigDialog from '../pc/components/QuickConfigDialog.vue'
import { columns as columnsConfig } from './config/columns'
import {
fetchServerList,
deleteServer,
} from '@/api/ops/server'
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[]>([])
const formDialogVisible = ref(false)
const quickConfigVisible = ref(false)
const currentRecord = ref<any>(null)
const formModel = ref({
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
})
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0,
})
// 表单项配置
const formItems = computed<FormItem[]>(() => searchFormConfig)
// 表格列配置
const columns = computed(() => columnsConfig)
// 获取状态颜色
const getStatusColor = (status?: string) => {
const colorMap: Record<string, string> = {
online: 'green',
offline: 'red',
maintenance: 'orange',
retired: 'gray',
}
return colorMap[status || ''] || 'gray'
}
// 获取状态文本
const getStatusText = (status?: string) => {
const textMap: Record<string, string> = {
online: '在线',
offline: '离线',
maintenance: '维护中',
retired: '已退役',
}
return textMap[status || ''] || '-'
}
// 获取进度条颜色
const getProgressColor = (value: number) => {
if (value >= 90) return '#F53F3F' // 红色
if (value >= 70) return '#FF7D00' // 橙色
if (value >= 50) return '#FFD00B' // 黄色
return '#00B42A' // 绿色
}
// 获取网络设备列表(使用 Mock 数据)
const fetchServers = async () => {
loading.value = true
try {
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 500))
// 使用 Mock 数据
tableData.value = mockServerData
pagination.total = mockServerData.length
// 如果有搜索条件,进行过滤
if (formModel.value.keyword || formModel.value.status) {
let filteredData = [...mockServerData]
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
}
} catch (error) {
console.error('获取网络设备列表失败:', error)
Message.error('获取网络设备列表失败')
tableData.value = []
pagination.total = 0
} finally {
loading.value = false
}
}
// 搜索
const handleSearch = () => {
pagination.current = 1
fetchServers()
}
// 处理表单模型更新
const handleFormModelUpdate = (value: any) => {
formModel.value = value
}
// 重置
const handleReset = () => {
formModel.value = {
keyword: '',
datacenter_id: undefined,
rack_id: undefined,
status: undefined,
}
pagination.current = 1
fetchServers()
}
// 分页变化
const handlePageChange = (current: number) => {
pagination.current = current
fetchServers()
}
// 刷新
const handleRefresh = () => {
fetchServers()
Message.success('数据已刷新')
}
// 新增网络设备
const handleAdd = () => {
currentRecord.value = null
formDialogVisible.value = true
}
// 快捷配置
const handleQuickConfig = (record: any) => {
currentRecord.value = record
quickConfigVisible.value = true
}
// 编辑网络设备
const handleEdit = (record: any) => {
currentRecord.value = record
formDialogVisible.value = true
}
// 表单提交成功
const handleFormSuccess = () => {
fetchServers()
}
// 重启网络设备
const handleRestart = (record: any) => {
Modal.confirm({
title: '确认重启',
content: `确认重启网络设备 ${record.name} 吗?`,
onOk: () => {
Message.info('正在发送重启指令...')
},
})
}
// 查看详情 - 在当前窗口打开
const handleDetail = (record: any) => {
router.push({
path: '/dc/detail',
query: {
id: record.id,
name: record.name,
ip: record.ip,
status: record.status,
},
})
}
// 远程控制 - 在新窗口打开
const handleRemoteControl = (record: any) => {
const url = router.resolve({
path: '/dc/remote',
query: {
id: record.id,
name: record.name,
ip: record.ip,
status: record.status,
},
}).href
window.open(url, '_blank')
}
// 删除网络设备
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)
Message.success('删除成功')
fetchServers()
} else {
Message.error('删除失败')
}
},
})
} catch (error) {
console.error('删除网络设备失败:', error)
}
}
// 初始化加载数据
fetchServers()
</script>
<script lang="ts">
export default {
name: 'DataCenterServer',
}
</script>
<style scoped lang="less">
.container {
margin-top: 20px;
}
.resource-display {
display: flex;
flex-direction: column;
gap: 4px;
padding: 4px 0;
.resource-info {
display: flex;
align-items: center;
justify-content: space-between;
> div {
display: inline-block;
}
.resource-value {
font-size: 12px;
font-weight: 500;
color: rgb(var(--text-1));
}
}
:deep(.arco-progress) {
margin: 0;
.arco-progress-bar-bg {
border-radius: 2px;
}
.arco-progress-bar {
border-radius: 2px;
transition: all 0.3s ease;
}
}
}
</style>

View File

@@ -7,7 +7,7 @@
:columns="columns"
:loading="loading"
:pagination="pagination"
title="服务器及PC管理"
title="办公PC管理"
search-button-text="查询"
reset-button-text="重置"
@update:form-model="handleFormModelUpdate"
@@ -21,7 +21,7 @@
<template #icon>
<icon-plus />
</template>
新增
新增办公PC
</a-button>
</template>
@@ -492,7 +492,7 @@ const handleDetail = (record: any) => {
const handleRestart = (record: any) => {
Modal.confirm({
title: '确认重启',
content: `确认重启服务器/PC ${record.name} 吗?`,
content: `确认重启办公PC ${record.name} 吗?`,
onOk: () => {
Message.info('正在发送重启指令...')
},