feat: 多主机纳管、用户认证、noVNC控制台、深色主题
主要功能: - 多主机管理: 支持TCP/SSH方式纳管远程KVM主机 - 用户认证: JWT token认证, 默认admin/admin123 - noVNC控制台: 前端集成noVNC, WebSocket代理VNC连接 - 深色主题: 全局Element Plus深色主题覆盖 - 虚拟机操作: 克隆、迁移、XML编辑、快照管理 - 资源监控: CPU/内存/磁盘IO/网络流量实时监控 Bug修复: - libvirt getInfo()内存单位修正(MiB非KiB) - 远程主机VNC 0.0.0.0监听地址连接策略修复 - Dashboard定时器内存泄漏修复 - bcrypt版本兼容性修复
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="名称" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="$router.push(`/vm/${row.name}`)">{{ row.name }}</el-link>
|
||||
<el-link type="primary" @click="$router.push(`/vm/${row.name}?host_id=${hostId()}`)">{{ row.name }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
@@ -77,7 +77,7 @@
|
||||
<el-button v-if="row.state === 'running'" type="danger" size="small"
|
||||
@click="doAction(row.name, 'force_stop')">强制关</el-button>
|
||||
<el-button type="primary" size="small"
|
||||
@click="$router.push(`/vm/${row.name}`)">详情</el-button>
|
||||
@click="$router.push(`/vm/${row.name}?host_id=${hostId()}`)">详情</el-button>
|
||||
<el-button type="danger" size="small"
|
||||
@click="deleteVM(row)">删除</el-button>
|
||||
</el-button-group>
|
||||
@@ -133,10 +133,14 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Refresh } from '@element-plus/icons-vue'
|
||||
import api from '../api'
|
||||
|
||||
const route = useRoute()
|
||||
const hostId = () => route.query.host_id || 'local'
|
||||
|
||||
const loading = ref(false)
|
||||
const creating = ref(false)
|
||||
const vms = ref([])
|
||||
@@ -173,7 +177,7 @@ function formatMem(mb) {
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get('/vm/list')
|
||||
const data = await api.get('/vm/list', { params: { host_id: hostId() } })
|
||||
vms.value = data.vms || []
|
||||
} catch (e) {}
|
||||
loading.value = false
|
||||
@@ -182,9 +186,9 @@ async function loadData() {
|
||||
async function loadOptions() {
|
||||
try {
|
||||
const [pools, nets, isos] = await Promise.all([
|
||||
api.get('/storage/pools'),
|
||||
api.get('/network/list'),
|
||||
api.get('/storage/isos'),
|
||||
api.get('/storage/pools', { params: { host_id: hostId() } }),
|
||||
api.get('/network/list', { params: { host_id: hostId() } }),
|
||||
api.get('/storage/isos', { params: { host_id: hostId() } }),
|
||||
])
|
||||
poolOptions.value = (pools.pools || []).map(p => p.name)
|
||||
networkOptions.value = (nets.networks || []).map(n => n.name)
|
||||
@@ -196,7 +200,7 @@ async function doAction(name, action) {
|
||||
const labels = { start: '启动', stop: '关机', force_stop: '强制关机', pause: '暂停', resume: '恢复' }
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定要${labels[action]}虚拟机 ${name} 吗?`, '确认', { type: 'info' })
|
||||
await api.post(`/vm/action/${name}`, { action })
|
||||
await api.post(`/vm/action/${name}`, { action }, { params: { host_id: hostId() } })
|
||||
ElMessage.success(`${labels[action]}操作已发送`)
|
||||
setTimeout(loadData, 2000)
|
||||
} catch (e) {
|
||||
@@ -211,7 +215,7 @@ async function createVM() {
|
||||
}
|
||||
creating.value = true
|
||||
try {
|
||||
await api.post('/vm/create', createForm.value)
|
||||
await api.post('/vm/create', createForm.value, { params: { host_id: hostId() } })
|
||||
ElMessage.success('虚拟机创建成功')
|
||||
showCreateDialog.value = false
|
||||
loadData()
|
||||
@@ -228,7 +232,7 @@ async function deleteVM(row) {
|
||||
'危险操作',
|
||||
{ type: 'error', confirmButtonText: '确定删除', confirmButtonClass: 'el-button--danger' }
|
||||
)
|
||||
await api.delete(`/vm/delete/${row.name}`, { params: { force: row.state === 'running' } })
|
||||
await api.delete(`/vm/delete/${row.name}`, { params: { force: row.state === 'running', host_id: hostId() } })
|
||||
ElMessage.success('虚拟机已删除')
|
||||
loadData()
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user