feat
This commit is contained in:
@@ -16,6 +16,8 @@ export interface LoginData {
|
|||||||
export interface UserItem {
|
export interface UserItem {
|
||||||
id?: number
|
id?: number
|
||||||
account?: string
|
account?: string
|
||||||
|
password?: string
|
||||||
|
confirmPassword?: string
|
||||||
name?: string
|
name?: string
|
||||||
username?: string
|
username?: string
|
||||||
nickname?: string
|
nickname?: string
|
||||||
|
|||||||
@@ -204,6 +204,11 @@ import {
|
|||||||
} from '@/api/ops/server'
|
} from '@/api/ops/server'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
// 创建独立的 axios 实例用于请求外部 agent,绕过全局拦截器
|
||||||
|
const agentAxios = axios.create({
|
||||||
|
timeout: 5000,
|
||||||
|
})
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// 状态管理
|
// 状态管理
|
||||||
@@ -290,7 +295,7 @@ const fetchServers = async () => {
|
|||||||
|
|
||||||
const res: any = await fetchServerList(params)
|
const res: any = await fetchServerList(params)
|
||||||
|
|
||||||
if (res.code === 200 || res.code === 0) {
|
if (res.code === 0) {
|
||||||
const responseData = res.data || res.details || {}
|
const responseData = res.data || res.details || {}
|
||||||
tableData.value = responseData.data || []
|
tableData.value = responseData.data || []
|
||||||
pagination.total = responseData.total || 0
|
pagination.total = responseData.total || 0
|
||||||
@@ -414,7 +419,7 @@ const handleDelete = async (record: any) => {
|
|||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
const res: any = await deleteServer(record.id)
|
const res: any = await deleteServer(record.id)
|
||||||
if (res.code === 200 || res.code === 0) {
|
if (res.code === 0) {
|
||||||
Message.success('删除成功')
|
Message.success('删除成功')
|
||||||
fetchServers()
|
fetchServers()
|
||||||
} else {
|
} else {
|
||||||
@@ -445,33 +450,30 @@ const getAllMetrics = async () => {
|
|||||||
} catch (urlError) {
|
} catch (urlError) {
|
||||||
console.warn(`服务器 ${record.name} 的 agent_config 不是合法的 URL:`, metricsUrl)
|
console.warn(`服务器 ${record.name} 的 agent_config 不是合法的 URL:`, metricsUrl)
|
||||||
// 设置默认值 0
|
// 设置默认值 0
|
||||||
record.cpu_state = { value: 0, total: '', used: '' }
|
record.cpu_info = { value: 0, total: '', used: '' }
|
||||||
record.memory_state = { value: 0, total: '', used: '' }
|
record.memory_info = { value: 0, total: '', used: '' }
|
||||||
record.disk_state = { value: 0, total: '', used: '' }
|
record.disk_info = { value: 0, total: '', used: '' }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// 使用独立的 axios 实例请求外部 agent,绕过全局拦截器
|
||||||
// 发送请求获取指标数据
|
const response = await agentAxios.get(metricsUrl)
|
||||||
const response = await axios.get(metricsUrl, {
|
console.log('获取指标数据:', response.data)
|
||||||
timeout: 5000, // 5 秒超时
|
|
||||||
})
|
|
||||||
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
// 更新记录的监控数据
|
// 更新记录的监控数据
|
||||||
record.cpu_state = {
|
record.cpu_info = {
|
||||||
value: response.data.cpu_usage || 0,
|
value: Number((response.data.cpu_usage || 0).toFixed(2)),
|
||||||
total: response.data.cpu?.[0]?.cores ? `${response.data.cpu[0].cores}核` : '',
|
total: response.data.cpu?.length ? `${response.data.cpu.length}核` : '',
|
||||||
used: '',
|
used: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
record.memory_state = {
|
record.memory_info = {
|
||||||
value: response.data.mem_usage?.used_percent || 0,
|
value: Number((response.data.mem_usage?.used_percent || 0).toFixed(2)),
|
||||||
total: response.data.mem_usage?.total ? `${(response.data.mem_usage.total / 1024 / 1024 / 1024).toFixed(1)}GB` : '',
|
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` : '',
|
used: response.data.mem_usage?.used ? `${(response.data.mem_usage.used / 1024 / 1024 / 1024).toFixed(1)}GB` : '',
|
||||||
}
|
}
|
||||||
|
|
||||||
record.disk_state = {
|
record.disk_info = {
|
||||||
value: response.data.disk_usage?.used_percent || 0,
|
value: Number((response.data.disk_usage?.used_percent || 0).toFixed(2)),
|
||||||
total: response.data.disk_usage?.total ? `${(response.data.disk_usage.total / 1024 / 1024 / 1024).toFixed(0)}GB` : '',
|
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` : '',
|
used: response.data.disk_usage?.used ? `${(response.data.disk_usage.used / 1024 / 1024 / 1024).toFixed(0)}GB` : '',
|
||||||
}
|
}
|
||||||
@@ -479,15 +481,15 @@ const getAllMetrics = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`获取服务器 ${record.name} 的监控指标失败:`, error)
|
console.warn(`获取服务器 ${record.name} 的监控指标失败:`, error)
|
||||||
// 初始化默认值
|
// 初始化默认值
|
||||||
record.cpu_state = { value: 0, total: '', used: '' }
|
record.cpu_info = { value: 0, total: '', used: '' }
|
||||||
record.memory_state = { value: 0, total: '', used: '' }
|
record.memory_info = { value: 0, total: '', used: '' }
|
||||||
record.disk_state = { value: 0, total: '', used: '' }
|
record.disk_info = { value: 0, total: '', used: '' }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 没有配置 agent,设置默认值
|
// 没有配置 agent,设置默认值
|
||||||
record.cpu_state = { value: 0, total: '', used: '' }
|
record.cpu_info = { value: 0, total: '', used: '' }
|
||||||
record.memory_state = { value: 0, total: '', used: '' }
|
record.memory_info = { value: 0, total: '', used: '' }
|
||||||
record.disk_state = { value: 0, total: '', used: '' }
|
record.disk_info = { value: 0, total: '', used: '' }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,20 @@
|
|||||||
:disabled="isEdit"
|
:disabled="isEdit"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item v-if="!isEdit" field="password" label="密码" validate-trigger="blur">
|
||||||
|
<a-input-password
|
||||||
|
v-model="formData.password"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item v-if="!isEdit" field="confirmPassword" label="确认密码" validate-trigger="blur">
|
||||||
|
<a-input-password
|
||||||
|
v-model="formData.confirmPassword"
|
||||||
|
placeholder="请再次输入密码"
|
||||||
|
allow-clear
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item field="name" label="姓名" validate-trigger="blur">
|
<a-form-item field="name" label="姓名" validate-trigger="blur">
|
||||||
<a-input v-model="formData.name" placeholder="请输入姓名" />
|
<a-input v-model="formData.name" placeholder="请输入姓名" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -120,6 +134,7 @@
|
|||||||
import { ref, reactive, computed, onMounted } from 'vue'
|
import { ref, reactive, computed, onMounted } from 'vue'
|
||||||
import { Message } from '@arco-design/web-vue'
|
import { Message } from '@arco-design/web-vue'
|
||||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'
|
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import SearchTable from '@/components/search-table/index.vue'
|
import SearchTable from '@/components/search-table/index.vue'
|
||||||
import type { FormItem } from '@/components/search-form/types'
|
import type { FormItem } from '@/components/search-form/types'
|
||||||
import type { UserItem } from '@/api/types'
|
import type { UserItem } from '@/api/types'
|
||||||
@@ -180,6 +195,9 @@ const columns: TableColumnData[] = [
|
|||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
width: 180,
|
width: 180,
|
||||||
|
render: ({ record }: any) => {
|
||||||
|
return record.created_at ? dayjs(record.created_at).format('YYYY-MM-DD HH:mm') : '-'
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
@@ -212,18 +230,39 @@ const formRef = ref()
|
|||||||
const formData = reactive<UserItem>({
|
const formData = reactive<UserItem>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
account: '',
|
account: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
name: '',
|
name: '',
|
||||||
email: '',
|
email: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
status: 1,
|
status: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 确认密码验证
|
||||||
|
const validateConfirmPassword = (value: string | undefined, callback: (error?: string) => void) => {
|
||||||
|
if (!value) {
|
||||||
|
callback('请再次输入密码')
|
||||||
|
} else if (value !== formData.password) {
|
||||||
|
callback('两次输入的密码不一致')
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 表单验证规则
|
// 表单验证规则
|
||||||
const formRules = {
|
const formRules = {
|
||||||
account: [
|
account: [
|
||||||
{ required: true, message: '请输入账号' },
|
{ required: true, message: '请输入账号' },
|
||||||
{ minLength: 3, message: '账号至少3个字符' },
|
{ minLength: 3, message: '账号至少3个字符' },
|
||||||
],
|
],
|
||||||
|
password: [
|
||||||
|
{ required: true, message: '请输入密码' },
|
||||||
|
{ minLength: 6, message: '密码至少6个字符' },
|
||||||
|
],
|
||||||
|
confirmPassword: [
|
||||||
|
{ required: true, message: '请再次输入密码' },
|
||||||
|
{ validator: validateConfirmPassword },
|
||||||
|
],
|
||||||
name: [
|
name: [
|
||||||
{ required: true, message: '请输入姓名' },
|
{ required: true, message: '请输入姓名' },
|
||||||
],
|
],
|
||||||
@@ -401,6 +440,8 @@ const resetFormData = () => {
|
|||||||
Object.assign(formData, {
|
Object.assign(formData, {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
account: '',
|
account: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
name: '',
|
name: '',
|
||||||
email: '',
|
email: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
|
|||||||
Reference in New Issue
Block a user