feat:对接虚拟机实例接口

This commit is contained in:
2025-08-14 11:31:13 +08:00
parent d636050aac
commit 67ce6f66ac
9 changed files with 4941 additions and 105 deletions
+2131
View File
File diff suppressed because it is too large Load Diff
+10
View File
@@ -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
}
} }
] ]
}, },
+16
View File
@@ -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"
}
});
};
+3 -2
View File
@@ -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: {},
}); });
-1
View File
@@ -900,5 +900,4 @@ onMounted(() => {
height: 60px; height: 60px;
} }
} }
</style>
</style> </style>
+61 -45
View File
@@ -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
+205 -37
View File
@@ -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>
+83 -20
View File
@@ -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;
} }
} }