feat:对接虚拟机实例接口
This commit is contained in:
Generated
+2131
File diff suppressed because it is too large
Load Diff
@@ -192,6 +192,16 @@ const routes = [
|
|||||||
title: '服务器详情',
|
title: '服务器详情',
|
||||||
hidden: true
|
hidden: true
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// 虚拟机详情页面路由
|
||||||
|
{
|
||||||
|
path: 'servers/vm',
|
||||||
|
name: 'VmDetail',
|
||||||
|
component: () => import('../views/acs/nodes/VmDetail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '虚拟机详情',
|
||||||
|
hidden: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -83,6 +83,13 @@ export const getContainer = data => {
|
|||||||
`/v1/admin/container/get_container_list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}`
|
`/v1/admin/container/get_container_list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**获取虚拟机列表 */
|
||||||
|
export const getInstanceList = data => {
|
||||||
|
return http2.get(
|
||||||
|
`/v1/admin/instance/list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}`
|
||||||
|
);
|
||||||
|
};
|
||||||
/**获取单个指定容器 */
|
/**获取单个指定容器 */
|
||||||
export const getOneContainer = data => {
|
export const getOneContainer = data => {
|
||||||
return http2.post("/v1/admin/container/get_container_detail", data, {
|
return http2.post("/v1/admin/container/get_container_detail", data, {
|
||||||
@@ -453,3 +460,12 @@ export const changeInstancePasswordUser = (id, data) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**删除端口 */
|
||||||
|
export const deletePort = data => {
|
||||||
|
return http2.post("/v1/admin/instance_port/delete", data, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import router from '@/router'
|
|||||||
|
|
||||||
// 基础URL
|
// 基础URL
|
||||||
const baseUrl = 'https://apiservertest.s1f.ren'
|
const baseUrl = 'https://apiservertest.s1f.ren'
|
||||||
|
// const baseUrl = 'https://cloudapi.007yjs.com'
|
||||||
|
|
||||||
// 检查URL是否需要认证
|
// 检查URL是否需要认证
|
||||||
const urlNeedAuth = (url) => {
|
const urlNeedAuth = (url) => {
|
||||||
@@ -105,7 +106,7 @@ class Request {
|
|||||||
// 创建默认实例
|
// 创建默认实例
|
||||||
const request = new Request({
|
const request = new Request({
|
||||||
baseURL: baseUrl,
|
baseURL: baseUrl,
|
||||||
timeout: 5000,
|
timeout: 30000,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
'Content-Type': 'multipart/form-data'
|
||||||
}
|
}
|
||||||
@@ -115,7 +116,7 @@ export const mainUrl = baseUrl + "/acs"
|
|||||||
|
|
||||||
export const http2 = axios.create({
|
export const http2 = axios.create({
|
||||||
baseURL: baseUrl,
|
baseURL: baseUrl,
|
||||||
timeout: 5000,
|
timeout: 30000,
|
||||||
headers: {},
|
headers: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -900,5 +900,4 @@ onMounted(() => {
|
|||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
</style>
|
</style>
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="内存">
|
<el-form-item label="内存">
|
||||||
<el-input v-model="serverForm.memory" placeholder="内存大小">
|
<el-input v-model="serverForm.memory" placeholder="内存大小">
|
||||||
<template #append>GB</template>
|
<template #append>MB</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="CPU">
|
<el-form-item label="CPU">
|
||||||
@@ -708,58 +708,74 @@ onMounted(async () => {
|
|||||||
// 加载地区数据
|
// 加载地区数据
|
||||||
// 实际项目中应该从API获取或使用静态JSON文件
|
// 实际项目中应该从API获取或使用静态JSON文件
|
||||||
regionsBuff.value = [
|
regionsBuff.value = [
|
||||||
{
|
{
|
||||||
value: 'china',
|
value: 'china',
|
||||||
label: '中国',
|
label: '中国',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
value: 'north',
|
value: 'southwest',
|
||||||
label: '华北',
|
label: '西南',
|
||||||
children: [
|
children: [
|
||||||
{ value: 'beijing', label: '北京' },
|
{ value: 'sichuan', label: '四川' },
|
||||||
{ value: 'tianjin', label: '天津' },
|
{ value: 'chongqing', label: '重庆' },
|
||||||
{ value: 'hebei', label: '河北' }
|
{ value: 'yunnan', label: '云南' },
|
||||||
]
|
{ value: 'guizhou', label: '贵州' },
|
||||||
},
|
{ value: 'xizang', label: '西藏' }
|
||||||
{
|
]
|
||||||
value: 'east',
|
},
|
||||||
label: '华东',
|
{
|
||||||
children: [
|
value: 'northeast',
|
||||||
{ value: 'shanghai', label: '上海' },
|
label: '东北',
|
||||||
{ value: 'jiangsu', label: '江苏' },
|
children: [
|
||||||
{ value: 'zhejiang', label: '浙江' }
|
{ value: 'liaoning', label: '辽宁' },
|
||||||
]
|
{ value: 'jilin', label: '吉林' },
|
||||||
},
|
{ value: 'heilongjiang', label: '黑龙江' }
|
||||||
{
|
]
|
||||||
value: 'south',
|
},
|
||||||
label: '华南',
|
{
|
||||||
children: [
|
value: 'northwest',
|
||||||
{ value: 'guangdong', label: '广东' },
|
label: '西北',
|
||||||
{ value: 'guangxi', label: '广西' },
|
children: [
|
||||||
{ value: 'hainan', label: '海南' }
|
{ value: 'shaanxi', label: '陕西' },
|
||||||
]
|
{ value: 'gansu', label: '甘肃' },
|
||||||
},
|
{ value: 'qinghai', label: '青海' },
|
||||||
{
|
{ value: 'ningxia', label: '宁夏' },
|
||||||
value: 'southwest',
|
{ value: 'xinjiang', label: '新疆' }
|
||||||
label: '西南',
|
]
|
||||||
children: [
|
},
|
||||||
{ value: 'sichuan', label: '四川' },
|
{
|
||||||
{ value: 'chongqing', label: '重庆' },
|
value: 'central',
|
||||||
{ value: 'yunnan', label: '云南' }
|
label: '华中',
|
||||||
]
|
children: [
|
||||||
}
|
{ value: 'henan', label: '河南' },
|
||||||
|
{ value: 'hubei', label: '湖北' },
|
||||||
|
{ value: 'hunan', label: '湖南' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'northchina',
|
||||||
|
label: '华北',
|
||||||
|
children: [
|
||||||
|
{ value: 'tianjin', label: '天津' },
|
||||||
|
{ value: 'hebei', label: '河北' },
|
||||||
|
{ value: 'shanxi', label: '山西' },
|
||||||
|
{ value: 'neimenggu', label: '内蒙古' }
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'foreign',
|
value: 'foreign',
|
||||||
label: '国外',
|
label: '国外',
|
||||||
children: [
|
children: [
|
||||||
{ value: 'asia', label: '亚洲' },
|
{ value: 'asia', label: '亚洲' },
|
||||||
{ value: 'europe', label: '欧洲' },
|
{ value: 'europe', label: '欧洲' },
|
||||||
{ value: 'america', label: '美洲' }
|
{ value: 'america', label: '美洲' },
|
||||||
|
{ value: 'africa', label: '非洲' },
|
||||||
|
{ value: 'oceania', label: '大洋洲' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
// 设置对话框宽度响应式
|
// 设置对话框宽度响应式
|
||||||
updateDialogWidth()
|
updateDialogWidth()
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,8 +22,7 @@
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
border
|
border
|
||||||
>
|
>
|
||||||
<el-table-column prop="instance_id" label="ID" width="100" />
|
<el-table-column prop="id" label="ID" width="100" />
|
||||||
<el-table-column prop="name" label="名称" />
|
|
||||||
<el-table-column prop="user_id" label="用户ID" width="100" />
|
<el-table-column prop="user_id" label="用户ID" width="100" />
|
||||||
<el-table-column label="创建时间" width="180">
|
<el-table-column label="创建时间" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -37,12 +36,33 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="状态" width="100">
|
<el-table-column label="状态" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag :type="getStatusType(scope.row.state)">
|
<el-tag :type="scope.row.state == 0 || scope.row.state == 1
|
||||||
{{ getStatusText(scope.row.state) }}
|
? 'info'
|
||||||
</el-tag>
|
: scope.row.state == 2
|
||||||
|
? 'success'
|
||||||
|
: scope.row.state == 4 || scope.row.state == 5 || scope.row.state == 6
|
||||||
|
? 'warning'
|
||||||
|
: 'danger'
|
||||||
|
">{{
|
||||||
|
scope.row.state == 0
|
||||||
|
? "未支付"
|
||||||
|
: scope.row.state == 1
|
||||||
|
? "未创建"
|
||||||
|
: scope.row.state == 2
|
||||||
|
? "已启动"
|
||||||
|
: scope.row.state == 3
|
||||||
|
? "已关机"
|
||||||
|
: scope.row.state == 4
|
||||||
|
? "重装中"
|
||||||
|
: scope.row.state == 5
|
||||||
|
? "创建快照中"
|
||||||
|
: scope.row.state == 6
|
||||||
|
? "恢复快照中"
|
||||||
|
: "未知状态"
|
||||||
|
}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="250" fixed="right">
|
<el-table-column label="操作" width="300" fixed="right">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -52,33 +72,43 @@
|
|||||||
>
|
>
|
||||||
<el-icon><menu /></el-icon>管理
|
<el-icon><menu /></el-icon>管理
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<!-- <el-button
|
||||||
type="success"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click="handleStart(scope.row)"
|
@click="handleStart(scope.row)"
|
||||||
:disabled="scope.row.state === 'running'"
|
:disabled="scope.row.state == 2 || scope.row.state == 0 || scope.row.state == 1 || scope.row.state == 4 || scope.row.state == 5 || scope.row.state == 6"
|
||||||
>
|
>
|
||||||
<el-icon><video-play /></el-icon>启动
|
开机
|
||||||
</el-button>
|
</el-button> -->
|
||||||
<el-button
|
<!-- <el-button
|
||||||
type="warning"
|
type="primary"
|
||||||
link
|
link
|
||||||
size="small"
|
size="small"
|
||||||
@click="handleStop(scope.row)"
|
@click="handleStop(scope.row)"
|
||||||
:disabled="scope.row.state === 'stopped'"
|
:disabled="scope.row.state != 2"
|
||||||
>
|
>
|
||||||
<el-icon><video-pause /></el-icon>停止
|
关机
|
||||||
</el-button>
|
</el-button> -->
|
||||||
<el-button
|
<!-- <el-dropdown trigger="click" @command="(command) => handleCommand(command, scope.row)" style="transform: translateY(3px) translateX(10px);">
|
||||||
type="info"
|
<el-button
|
||||||
link
|
type="primary"
|
||||||
size="small"
|
link
|
||||||
@click="handleRestart(scope.row)"
|
size="small"
|
||||||
:disabled="scope.row.state !== 'running'"
|
>
|
||||||
>
|
更多
|
||||||
<el-icon><refresh-right /></el-icon>重启
|
</el-button>
|
||||||
</el-button>
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item :disabled="scope.row.state != 2" command="restart">重启</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided :disabled="scope.row.state == 0 || scope.row.state == 1 || scope.row.state == 4 || scope.row.state == 5 || scope.row.state == 6" command="reinstall">重装系统</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="scope.row.state == 0 || scope.row.state == 1 || scope.row.state == 4 || scope.row.state == 5 || scope.row.state == 6" command="snapshot">快照管理</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="scope.row.state == 0 || scope.row.state == 1 || scope.row.state == 4 || scope.row.state == 5 || scope.row.state == 6" command="enterRescue">进入救援系统</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="scope.row.state == 0 || scope.row.state == 1 || scope.row.state == 4 || scope.row.state == 5 || scope.row.state == 6" command="exitRescue">退出救援系统</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided :disabled="scope.row.state == 0 || scope.row.state == 1" command="console">虚拟机控制台</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown> -->
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -102,13 +132,17 @@ import { ref, onMounted, defineProps, watch } from 'vue';
|
|||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import {
|
import {
|
||||||
Search, Refresh, Menu, VideoPlay, VideoPause, RefreshRight
|
Search, Refresh, Menu, VideoPlay, VideoPause, RefreshRight, ArrowDown
|
||||||
} from '@element-plus/icons-vue';
|
} from '@element-plus/icons-vue';
|
||||||
import {
|
import {
|
||||||
getContainer,
|
getContainer,
|
||||||
startInstance,
|
startInstance,
|
||||||
stopInstance,
|
stopInstance,
|
||||||
restartInstance
|
restartInstance,
|
||||||
|
getInstanceList,
|
||||||
|
reinstallI,
|
||||||
|
rescueInstance,
|
||||||
|
exitRescueInstance
|
||||||
} from '@/utils/acs/server';
|
} from '@/utils/acs/server';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -130,13 +164,14 @@ const searchKey = ref('');
|
|||||||
const fetchVmList = async () => {
|
const fetchVmList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const response = await getContainer({
|
const response = await getInstanceList({
|
||||||
server_id: props.ID,
|
server_id: props.ID,
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
count: pageSize.value,
|
count: pageSize.value,
|
||||||
key: searchKey.value,
|
key: searchKey.value,
|
||||||
user_id: ''
|
user_id: ''
|
||||||
});
|
});
|
||||||
|
console.log("获取虚拟机列表:",response);
|
||||||
|
|
||||||
if (response && response.data && response.data.code === 200) {
|
if (response && response.data && response.data.code === 200) {
|
||||||
vmList.value = response.data.data || [];
|
vmList.value = response.data.data || [];
|
||||||
@@ -152,14 +187,19 @@ const fetchVmList = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function Formater(row){
|
||||||
|
return row.hostname || '未设置'
|
||||||
|
}
|
||||||
|
|
||||||
// 获取状态类型
|
// 获取状态类型
|
||||||
const getStatusType = (state) => {
|
const getStatusType = (state) => {
|
||||||
|
console.log("获取状态类型:",state)
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'running':
|
case '0':
|
||||||
return 'success';
|
return 'success';
|
||||||
case 'stopped':
|
case '1':
|
||||||
return 'danger';
|
return 'danger';
|
||||||
case 'paused':
|
case '2':
|
||||||
return 'warning';
|
return 'warning';
|
||||||
default:
|
default:
|
||||||
return 'info';
|
return 'info';
|
||||||
@@ -169,15 +209,15 @@ const getStatusType = (state) => {
|
|||||||
// 获取状态文本
|
// 获取状态文本
|
||||||
const getStatusText = (state) => {
|
const getStatusText = (state) => {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case 'running':
|
case '0':
|
||||||
return '运行中';
|
return '运行中';
|
||||||
case 'stopped':
|
case '1':
|
||||||
return '已停止';
|
return '已停止';
|
||||||
case 'paused':
|
case '2':
|
||||||
return '已暂停';
|
return '已暂停';
|
||||||
case 'creating':
|
case '3':
|
||||||
return '创建中';
|
return '创建中';
|
||||||
case 'error':
|
case '4':
|
||||||
return '错误';
|
return '错误';
|
||||||
default:
|
default:
|
||||||
return '未知';
|
return '未知';
|
||||||
@@ -212,7 +252,7 @@ const handleSizeChange = (val) => {
|
|||||||
|
|
||||||
// 管理虚拟机
|
// 管理虚拟机
|
||||||
const handleManage = (row) => {
|
const handleManage = (row) => {
|
||||||
router.push(`/servers/vm?instance_id=${row.instance_id}`);
|
router.push(`/servers/vm?instance_id=${row.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 启动虚拟机
|
// 启动虚拟机
|
||||||
@@ -281,6 +321,112 @@ const handleRestart = async (row) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 重装系统
|
||||||
|
const handleReinstall = async (row) => {
|
||||||
|
try {
|
||||||
|
ElMessageBox.confirm('重装系统将清除所有数据,确定要继续吗?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
router.push(`/servers/reinstall?instance_id=${row.instance_id}`);
|
||||||
|
}).catch(() => {});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('重装系统出错:', error);
|
||||||
|
ElMessage.error('重装系统出错');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 快照管理
|
||||||
|
const handleSnapshot = (row) => {
|
||||||
|
router.push(`/servers/snapshots?instance_id=${row.instance_id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 进入救援系统
|
||||||
|
const handleEnterRescue = async (row) => {
|
||||||
|
try {
|
||||||
|
ElMessageBox.confirm('确定要进入救援系统吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
const res = await rescueInstance(row.instance_id);
|
||||||
|
if (res && res.data && res.data.code === 200) {
|
||||||
|
ElMessage.success('已进入救援系统');
|
||||||
|
setTimeout(() => {
|
||||||
|
fetchVmList();
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
ElMessage.error('操作失败: ' + (res.data.message || '未知错误'));
|
||||||
|
}
|
||||||
|
}).catch(() => {});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('进入救援系统出错:', error);
|
||||||
|
ElMessage.error('进入救援系统出错');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 退出救援系统
|
||||||
|
const handleExitRescue = async (row) => {
|
||||||
|
try {
|
||||||
|
ElMessageBox.confirm('确定要退出救援系统吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
const res = await exitRescueInstance(row.instance_id);
|
||||||
|
if (res && res.data && res.data.code === 200) {
|
||||||
|
ElMessage.success('已退出救援系统');
|
||||||
|
setTimeout(() => {
|
||||||
|
fetchVmList();
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
ElMessage.error('操作失败: ' + (res.data.message || '未知错误'));
|
||||||
|
}
|
||||||
|
}).catch(() => {});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('退出救援系统出错:', error);
|
||||||
|
ElMessage.error('退出救援系统出错');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开虚拟机控制台
|
||||||
|
const handleConsole = (row) => {
|
||||||
|
window.open(`/console?instance_id=${row.instance_id}`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理下拉菜单命令
|
||||||
|
const handleCommand = (command, row) => {
|
||||||
|
switch (command) {
|
||||||
|
case 'start':
|
||||||
|
handleStart(row);
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
handleStop(row);
|
||||||
|
break;
|
||||||
|
case 'restart':
|
||||||
|
handleRestart(row);
|
||||||
|
break;
|
||||||
|
case 'reinstall':
|
||||||
|
handleReinstall(row);
|
||||||
|
break;
|
||||||
|
case 'snapshot':
|
||||||
|
handleSnapshot(row);
|
||||||
|
break;
|
||||||
|
case 'enterRescue':
|
||||||
|
handleEnterRescue(row);
|
||||||
|
break;
|
||||||
|
case 'exitRescue':
|
||||||
|
handleExitRescue(row);
|
||||||
|
break;
|
||||||
|
case 'console':
|
||||||
|
handleConsole(row);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 监听ID变化
|
// 监听ID变化
|
||||||
watch(() => props.ID, (newVal) => {
|
watch(() => props.ID, (newVal) => {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
@@ -311,4 +457,26 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 添加下拉菜单样式 */
|
||||||
|
:deep(.el-dropdown-menu) {
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-dropdown-menu__item) {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-dropdown-menu__item--divided) {
|
||||||
|
margin-top: 6px;
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-dropdown-menu__item--divided:before) {
|
||||||
|
height: 6px;
|
||||||
|
margin-top: -6px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -225,18 +225,22 @@
|
|||||||
:type="scope.row.container_state == 0 || scope.row.container_state == 1
|
:type="scope.row.container_state == 0 || scope.row.container_state == 1
|
||||||
? 'info'
|
? 'info'
|
||||||
: scope.row.container_state == 2
|
: scope.row.container_state == 2
|
||||||
? 'success'
|
? 'danger'
|
||||||
: 'danger'"
|
: scope.row.container_state == 3
|
||||||
|
? 'danger'
|
||||||
|
: 'success'"
|
||||||
effect="light"
|
effect="light"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
scope.row.container_state == 0
|
scope.row.container_state == 0
|
||||||
? "未支付"
|
? "未构建"
|
||||||
: scope.row.container_state == 1
|
: scope.row.container_state == 1
|
||||||
? "未开通"
|
? "已构建"
|
||||||
: scope.row.container_state == 2
|
: scope.row.container_state == 2
|
||||||
? "开机"
|
? "构建失败"
|
||||||
: "关机"
|
: scope.row.container_state == 3
|
||||||
|
? "已删除"
|
||||||
|
: "未知状态"
|
||||||
}}
|
}}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
@@ -378,6 +382,7 @@
|
|||||||
v-model="spec_form.cpu"
|
v-model="spec_form.cpu"
|
||||||
:placeholder="TypeData == 'dockerContainer' ? 'CPU 限制 (1核=1000毫核)' : 'CPU 限制'"
|
:placeholder="TypeData == 'dockerContainer' ? 'CPU 限制 (1核=1000毫核)' : 'CPU 限制'"
|
||||||
type="number"
|
type="number"
|
||||||
|
min="1"
|
||||||
>
|
>
|
||||||
<template #append>{{ TypeData == 'dockerContainer' ? '毫核' : '核' }}</template>
|
<template #append>{{ TypeData == 'dockerContainer' ? '毫核' : '核' }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
@@ -432,28 +437,28 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="允许开放端口数">
|
<el-form-item label="允许开放端口数">
|
||||||
<el-input v-model="spec_form.port_num" placeholder="默认允许开放端口数" type="number">
|
<el-input v-model="spec_form.port_num" placeholder="默认允许开放端口数" type="number" :value="spec_form.port_num || 5">
|
||||||
<template #append>个</template>
|
<template #append>个</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="允许快照数">
|
<el-form-item label="允许快照数">
|
||||||
<el-input v-model="spec_form.snapshot_num" placeholder="默认允许快照数" type="number">
|
<el-input v-model="spec_form.snapshot_num" placeholder="默认允许快照数" type="number" :value="spec_form.snapshot_num || 3">
|
||||||
<template #append>个</template>
|
<template #append>个</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="读写限制">
|
<el-form-item label="读写限制">
|
||||||
<el-input v-model="spec_form.min_iops" placeholder="读写限制(1iops=8kb/s)" type="number">
|
<el-input v-model="spec_form.min_iops" placeholder="读写限制(1iops=8kb/s)" type="number" :value="spec_form.min_iops || 1000">
|
||||||
<template #append>IOPS</template>
|
<template #append>IOPS</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="读写最大突发">
|
<el-form-item label="读写最大突发">
|
||||||
<el-input v-model="spec_form.max_iops" placeholder="读写最大突发" type="number">
|
<el-input v-model="spec_form.max_iops" placeholder="读写最大突发" type="number" :value="spec_form.max_iops || 5000">
|
||||||
<template #append>IOPS</template>
|
<template #append>IOPS</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -609,6 +614,8 @@ import {
|
|||||||
} from "@/utils/acs/server";
|
} from "@/utils/acs/server";
|
||||||
import { ElMessage, ElNotification } from 'element-plus';
|
import { ElMessage, ElNotification } from 'element-plus';
|
||||||
import { copyDomText } from "@/utils/hide";
|
import { copyDomText } from "@/utils/hide";
|
||||||
|
import { getUserInfoV1 } from "@/utils/acs/user";
|
||||||
|
import {getUserInfo, userLogin} from "@/api/login.js";
|
||||||
import {
|
import {
|
||||||
Plus,
|
Plus,
|
||||||
Edit,
|
Edit,
|
||||||
@@ -660,11 +667,30 @@ const initData = async () => {
|
|||||||
// 获取实例规格
|
// 获取实例规格
|
||||||
await GetSpecs();
|
await GetSpecs();
|
||||||
|
|
||||||
|
// 获取用户信息并设置用户类型
|
||||||
|
try {
|
||||||
|
const userInfoRes = await getUserInfo();
|
||||||
|
console.log("获取用户信息", userInfoRes);
|
||||||
|
if (userInfoRes && userInfoRes.data && userInfoRes.data.data) {
|
||||||
|
// 根据API返回的用户信息设置用户类型
|
||||||
|
const userType = userInfoRes.data.is_admin == true ? "1" : "0";
|
||||||
|
localStorage.setItem("user_id", userInfoRes.real_name.UserId);
|
||||||
|
localStorage.setItem("user_type", userType);
|
||||||
|
console.log("获取到用户类型", userType);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取用户信息失败:", error);
|
||||||
|
// 如果获取失败,默认设置为管理员权限确保功能可用
|
||||||
|
localStorage.setItem("user_type", "1");
|
||||||
|
}
|
||||||
|
|
||||||
// 获取所有容器
|
// 获取所有容器
|
||||||
let usertype = localStorage.getItem("user_type");
|
let usertype = localStorage.getItem("user_type");
|
||||||
|
console.log("用户类型", usertype);
|
||||||
if (usertype == "1") {
|
if (usertype == "1") {
|
||||||
containerBox.server_id = route.query.server_id;
|
containerBox.server_id = route.query.server_id;
|
||||||
let cons = await getContainer(containerBox);
|
let cons = await getContainer(containerBox);
|
||||||
|
console.log("获取容器列表", cons);
|
||||||
if (cons && cons.data) {
|
if (cons && cons.data) {
|
||||||
user_servers.value = cons.data.data || [];
|
user_servers.value = cons.data.data || [];
|
||||||
total.value = cons.data.count || 0;
|
total.value = cons.data.count || 0;
|
||||||
@@ -900,10 +926,11 @@ const editSpec = async () => {
|
|||||||
if (addOrChange.value) {
|
if (addOrChange.value) {
|
||||||
const res = await addServerPlan({
|
const res = await addServerPlan({
|
||||||
...spec_form,
|
...spec_form,
|
||||||
server_id: route.query.server_id
|
server_id: route.query.server_id,
|
||||||
|
server_type:TypeData.value
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.data.code == 200) {
|
if (res.code == 200) {
|
||||||
ElNotification({
|
ElNotification({
|
||||||
title: '添加成功',
|
title: '添加成功',
|
||||||
message: `已成功添加规格 "${spec_form.name}"`,
|
message: `已成功添加规格 "${spec_form.name}"`,
|
||||||
@@ -916,7 +943,32 @@ const editSpec = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const res = await editServerPlan(spec_form);
|
const submitData = {
|
||||||
|
...spec_form,
|
||||||
|
server_id:route.query.server_id,
|
||||||
|
server_type:TypeData.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理虚拟机特有字段
|
||||||
|
if (TypeData.value === 'hyperV') {
|
||||||
|
// 确保数值类型字段有默认值
|
||||||
|
submitData.port_num = submitData.port_num || 5;
|
||||||
|
submitData.snapshot_num = submitData.snapshot_num || 3;
|
||||||
|
submitData.min_iops = submitData.min_iops || 1000;
|
||||||
|
submitData.max_iops = submitData.max_iops || 5000;
|
||||||
|
|
||||||
|
// 容器特有字段设为空
|
||||||
|
submitData.bandwidth_rx = '0';
|
||||||
|
submitData.bandwidth_tx = '0';
|
||||||
|
submitData.threshold_rx = '0';
|
||||||
|
submitData.threshold_tx = '0';
|
||||||
|
} else {
|
||||||
|
// 处理容器特有字段
|
||||||
|
submitData.bandwidth_rx = submitData.bandwidth_rx || '100';
|
||||||
|
submitData.bandwidth_tx = submitData.bandwidth_tx || '100';
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await editServerPlan(submitData);
|
||||||
|
|
||||||
if (res.data.code == 200) {
|
if (res.data.code == 200) {
|
||||||
ElNotification({
|
ElNotification({
|
||||||
@@ -1018,7 +1070,7 @@ const spec_form = reactive({
|
|||||||
bandwidth_tx: "",
|
bandwidth_tx: "",
|
||||||
threshold_rx: "",
|
threshold_rx: "",
|
||||||
threshold_tx: "",
|
threshold_tx: "",
|
||||||
port_num: "",
|
port_num: 0,
|
||||||
snapshot_num: "",
|
snapshot_num: "",
|
||||||
number: "",
|
number: "",
|
||||||
volume_price: "",
|
volume_price: "",
|
||||||
@@ -1030,22 +1082,33 @@ const spec_form = reactive({
|
|||||||
|
|
||||||
function show_spec(data = null) {
|
function show_spec(data = null) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// 当data未传值,视为新增实例规格
|
// 重置表单时根据服务器类型设置不同默认值
|
||||||
// 遍历form对象的每个键值对
|
|
||||||
Object.keys(spec_form).forEach(key => {
|
Object.keys(spec_form).forEach(key => {
|
||||||
spec_form[key] = key === 'must_real_name' ? 0 : '';
|
spec_form[key] = key === 'must_real_name' ? 0 : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置默认类型
|
// 设置服务器类型和类型相关默认值
|
||||||
spec_form.server_type = TypeData.value;
|
spec_form.server_type = TypeData.value;
|
||||||
|
|
||||||
|
if (TypeData.value === 'dockerContainer') {
|
||||||
|
spec_form.bandwidth_rx = '100';
|
||||||
|
spec_form.bandwidth_tx = '100';
|
||||||
|
} else {
|
||||||
|
// 虚拟机默认值
|
||||||
|
spec_form.port_num = '5';
|
||||||
|
spec_form.snapshot_num = '3';
|
||||||
|
spec_form.min_iops = '1000';
|
||||||
|
spec_form.max_iops = '5000';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// data传值,视为修改实例规格
|
// 复制传入的数据
|
||||||
// 遍历data对象的每个键值对
|
|
||||||
Object.keys(data).forEach(key => {
|
Object.keys(data).forEach(key => {
|
||||||
if (key in spec_form) {
|
if (key in spec_form) {
|
||||||
spec_form[key] = data[key];
|
spec_form[key] = data[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 确保服务器类型正确
|
||||||
|
spec_form.server_type = TypeData.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user