Merge pull request 'feat:添加新增虚拟机' (#3) from master into deploy
Reviewed-on: lin/ApiServer-Web-admin_dashboard_pc#3
This commit was merged in pull request #3.
This commit is contained in:
@@ -279,6 +279,14 @@ export const connectConsole = data => {
|
||||
}
|
||||
});
|
||||
};
|
||||
/**新增虚拟机 (管理员) */
|
||||
export const addInstance = data => {
|
||||
return http2.post("/v1/admin/instance/create_vm", data, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data"
|
||||
}
|
||||
});
|
||||
};
|
||||
/**获取虚拟机控制台 */
|
||||
export const getInstanceConsole = data => {
|
||||
return http2.get(`/v1/admin/instance/console/${data}`);
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
<el-button @click="resetSearch">
|
||||
<el-icon><refresh /></el-icon>重置
|
||||
</el-button>
|
||||
<el-button type="success" @click="showAddVmDialog">
|
||||
<el-icon><plus /></el-icon>新增虚拟机
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
@@ -124,6 +127,131 @@
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 新增虚拟机对话框 -->
|
||||
<el-dialog
|
||||
v-model="addVmDialogVisible"
|
||||
title="新增虚拟机"
|
||||
width="600px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="addVmFormRef"
|
||||
:model="addVmForm"
|
||||
:rules="addVmRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="用户ID" prop="user_id">
|
||||
<el-input
|
||||
v-model="addVmForm.user_id"
|
||||
placeholder="请输入用户ID"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="套餐" prop="plan_id">
|
||||
<el-select
|
||||
v-model="addVmForm.plan_id"
|
||||
placeholder="请选择套餐"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
:loading="planLoading"
|
||||
@focus="fetchPlanList"
|
||||
>
|
||||
<el-option
|
||||
v-for="plan in planList"
|
||||
:key="plan.id"
|
||||
:label="plan.name"
|
||||
:value="plan.plan_id"
|
||||
>
|
||||
<span style="float: left">{{ plan.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">
|
||||
{{ plan.price }}元/月
|
||||
</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="额外数据卷大小" prop="volume_size">
|
||||
<el-input-number
|
||||
v-model="addVmForm.volume_size"
|
||||
:min="0"
|
||||
:max="10000"
|
||||
placeholder="请输入额外数据卷大小(GB)"
|
||||
style="width: 100%"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="购买时间(月)" prop="pay_months">
|
||||
<el-input-number
|
||||
v-model="addVmForm.pay_months"
|
||||
:min="1"
|
||||
:max="120"
|
||||
placeholder="请输入购买月数"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="支付类型" prop="pay_type">
|
||||
<el-select
|
||||
v-model="addVmForm.pay_type"
|
||||
placeholder="请选择支付类型"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
>
|
||||
<!-- <el-option label="支付宝" value="alipay" />
|
||||
<el-option label="微信支付" value="wechat" />
|
||||
<el-option label="银行卡" value="bank" /> -->
|
||||
<el-option label="余额" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="镜像" prop="image_id">
|
||||
<el-select
|
||||
v-model="addVmForm.image_id"
|
||||
placeholder="请选择镜像"
|
||||
style="width: 100%"
|
||||
clearable
|
||||
:loading="mirrorLoading"
|
||||
@focus="fetchMirrorList"
|
||||
>
|
||||
<el-option
|
||||
v-for="mirror in mirrorList"
|
||||
:key="mirror.id"
|
||||
:label="mirror.name"
|
||||
:value="mirror.id"
|
||||
>
|
||||
<span style="float: left">{{ mirror.name }}</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">
|
||||
{{ mirror.size }}MB
|
||||
</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="价格" prop="price">
|
||||
<el-input-number
|
||||
v-model="addVmForm.price"
|
||||
:min="0"
|
||||
:max="999999"
|
||||
:precision="2"
|
||||
placeholder="请输入价格"
|
||||
style="width: 100%"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancelAddVm">取消</el-button>
|
||||
<el-button type="primary" @click="confirmAddVm" :loading="addVmLoading">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -132,7 +260,7 @@ import { ref, onMounted, defineProps, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import {
|
||||
Search, Refresh, Menu, VideoPlay, VideoPause, RefreshRight, ArrowDown
|
||||
Search, Refresh, Menu, VideoPlay, VideoPause, RefreshRight, ArrowDown, Plus
|
||||
} from '@element-plus/icons-vue';
|
||||
import {
|
||||
getContainer,
|
||||
@@ -142,8 +270,11 @@ import {
|
||||
getInstanceList,
|
||||
reinstallI,
|
||||
rescueInstance,
|
||||
exitRescueInstance
|
||||
exitRescueInstance,
|
||||
addInstance,
|
||||
getServerPlan
|
||||
} from '@/utils/acs/server';
|
||||
import { getMirrorList } from '@/utils/acs/mirror';
|
||||
|
||||
const props = defineProps({
|
||||
ID: {
|
||||
@@ -160,6 +291,48 @@ const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const searchKey = ref('');
|
||||
|
||||
// 新增虚拟机相关状态
|
||||
const addVmDialogVisible = ref(false);
|
||||
const addVmLoading = ref(false);
|
||||
const addVmFormRef = ref(null);
|
||||
const addVmForm = ref({
|
||||
user_id: '',
|
||||
plan_id: '',
|
||||
volume_size: null,
|
||||
pay_months: null,
|
||||
pay_type: '',
|
||||
image_id: '',
|
||||
price: null
|
||||
});
|
||||
|
||||
// 套餐和镜像数据
|
||||
const planList = ref([]);
|
||||
const mirrorList = ref([]);
|
||||
const planLoading = ref(false);
|
||||
const mirrorLoading = ref(false);
|
||||
|
||||
// 表单验证规则
|
||||
const addVmRules = ref({
|
||||
user_id: [
|
||||
{ required: true, message: '请输入用户ID', trigger: 'blur' }
|
||||
],
|
||||
plan_id: [
|
||||
{ required: true, message: '请选择套餐', trigger: 'change' }
|
||||
],
|
||||
pay_months: [
|
||||
{ required: true, message: '请输入购买月数', trigger: 'blur' }
|
||||
],
|
||||
pay_type: [
|
||||
{ required: true, message: '请选择支付类型', trigger: 'change' }
|
||||
],
|
||||
image_id: [
|
||||
{ required: true, message: '请选择镜像', trigger: 'change' }
|
||||
],
|
||||
price: [
|
||||
{ required: true, message: '请输入价格', trigger: 'blur' }
|
||||
]
|
||||
});
|
||||
|
||||
// 获取虚拟机列表
|
||||
const fetchVmList = async () => {
|
||||
loading.value = true;
|
||||
@@ -437,6 +610,124 @@ watch(() => props.ID, (newVal) => {
|
||||
}
|
||||
});
|
||||
|
||||
// 获取套餐列表
|
||||
const fetchPlanList = async () => {
|
||||
if (planList.value.length > 0) return; // 已加载过,不重复加载
|
||||
|
||||
planLoading.value = true;
|
||||
try {
|
||||
const response = await getServerPlan({
|
||||
server_id: props.ID,
|
||||
count: 100
|
||||
});
|
||||
|
||||
if (response && response.data && response.data.code === 200) {
|
||||
planList.value = response.data.data || [];
|
||||
} else {
|
||||
ElMessage.error('获取套餐列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取套餐列表出错:', error);
|
||||
ElMessage.error('获取套餐列表出错');
|
||||
} finally {
|
||||
planLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取镜像列表
|
||||
const fetchMirrorList = async () => {
|
||||
if (mirrorList.value.length > 0) return; // 已加载过,不重复加载
|
||||
|
||||
mirrorLoading.value = true;
|
||||
try {
|
||||
const response = await getMirrorList(props.ID);
|
||||
|
||||
if (response && response.data && response.data.code === 200) {
|
||||
mirrorList.value = response.data.data || [];
|
||||
} else {
|
||||
ElMessage.error('获取镜像列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取镜像列表出错:', error);
|
||||
ElMessage.error('获取镜像列表出错');
|
||||
} finally {
|
||||
mirrorLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 显示新增虚拟机对话框
|
||||
const showAddVmDialog = () => {
|
||||
addVmDialogVisible.value = true;
|
||||
// 重置表单
|
||||
addVmForm.value = {
|
||||
user_id: '',
|
||||
plan_id: '',
|
||||
volume_size: null,
|
||||
pay_months: null,
|
||||
pay_type: '',
|
||||
image_id: '',
|
||||
price: null
|
||||
};
|
||||
// 清除验证
|
||||
if (addVmFormRef.value) {
|
||||
addVmFormRef.value.clearValidate();
|
||||
}
|
||||
// 预加载数据
|
||||
fetchPlanList();
|
||||
fetchMirrorList();
|
||||
};
|
||||
|
||||
// 取消新增虚拟机
|
||||
const cancelAddVm = () => {
|
||||
addVmDialogVisible.value = false;
|
||||
};
|
||||
|
||||
// 确认新增虚拟机
|
||||
const confirmAddVm = async () => {
|
||||
if (!addVmFormRef.value) return;
|
||||
|
||||
try {
|
||||
// 验证表单
|
||||
await addVmFormRef.value.validate();
|
||||
|
||||
addVmLoading.value = true;
|
||||
|
||||
// 准备API参数
|
||||
const apiParams = {
|
||||
user_id: addVmForm.value.user_id,
|
||||
plan_id: addVmForm.value.plan_id,
|
||||
volume_size: addVmForm.value.volume_size?.toString() || '',
|
||||
pay_months: addVmForm.value.pay_months?.toString() || '',
|
||||
pay_type: addVmForm.value.pay_type,
|
||||
image_id: addVmForm.value.image_id,
|
||||
price: addVmForm.value.price?.toString() || ''
|
||||
};
|
||||
|
||||
console.log('新增虚拟机参数:', apiParams);
|
||||
|
||||
// 调用API
|
||||
const response = await addInstance(apiParams);
|
||||
|
||||
if (response && response.data && response.data.code === 200) {
|
||||
ElMessage.success('虚拟机创建成功');
|
||||
addVmDialogVisible.value = false;
|
||||
// 刷新列表
|
||||
fetchVmList();
|
||||
} else {
|
||||
ElMessage.error('创建失败: ' + (response.data?.message || '未知错误'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('新增虚拟机出错:', error);
|
||||
if (error.message) {
|
||||
ElMessage.error('表单验证失败: ' + error.message);
|
||||
} else {
|
||||
ElMessage.error('新增虚拟机出错');
|
||||
}
|
||||
} finally {
|
||||
addVmLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (props.ID) {
|
||||
fetchVmList();
|
||||
|
||||
Reference in New Issue
Block a user