Compare commits

...

2 Commits

Author SHA1 Message Date
Leo_Ding
9e6da05991 防抖 2026-01-30 14:05:07 +08:00
Leo_Ding
f6ece66b1a 算力平台实例管理 2026-01-20 09:05:51 +08:00
14 changed files with 502 additions and 428 deletions

View File

@ -2,5 +2,5 @@
NODE_ENV=development
# api
VITE_API_BASIC="http://10.10.1.30:8888"
VITE_API_BASIC="http://10.10.1.11:8888"

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>GxDL算力</title>
<title>FAST亼算</title>
</head>
<body>
<div id="app"></div>

View File

@ -52,3 +52,8 @@ export const exchangePoint=(params:any)=>request.put('/v1/balance/exchange_point
//创建实例
export const createHost=(params:any)=>request.post('/v1/host/host_case',params)
//释放实例
export const releaseCase=(caseId:string)=>request.post(`/v1/host_case/release_case/${caseId}`)
//重置实例
export const reStartCase=(caseId:string)=>request.post(`/v1/host_case/restart_case/${caseId}`)

7
src/utils/debounce.js Normal file
View File

@ -0,0 +1,7 @@
export function debounce(func, delay = 500) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, args), delay);
};
}

15
src/utils/dict.ts Normal file
View File

@ -0,0 +1,15 @@
export const payTypeDic = new Map([
["PayOnTime", "按量计费"],
["PayOnDay", "包日"],
["PayOnWeek", "包周"],
["PayOnMonth", "包月"],
["PayOnYear", "包年"],
]);
export const instanceStatus = new Map([
["RUNNING", { text: "运行中", color: "#67C23A" }],
["STOPPED", { text: "已停止", color: "#909399" }],
["CREATING", { text: "创建中", color: "#E6A23C" }],
["RESTARTING", { text: "重启中", color: "#E6A23C" }],
["RELEASED", { text: "已释放", color: "#F56C6C" }],
]);

View File

@ -199,6 +199,7 @@ import {
} from '@ant-design/icons-vue'
import { useRouter } from 'vue-router'
import { message } from 'ant-design-vue'
import { debounce } from '@/utils/debounce.js'
const router = useRouter()
//
const switch1 = ref(true)
@ -246,10 +247,14 @@ const fetchUserAssets = () => {
//
const generateInviteLink = () => {
// API
message.success('邀请链接生成成功!')
debouncedSubmit()
// API
// const link = await api.generateInviteLink()
}
const debouncedSubmit = debounce(() => {
message.success('邀请链接生成成功!')
}, 800)
//
const goToRules = () => {

View File

@ -6,8 +6,8 @@
<div class="header-left">
<span class="page-title">容器实例</span>
<span class="warning-tip">
<exclamation-circle-outlined class="warning-icon" />
实例连续关机15天会释放实例实例释放会导致数据清空且不可恢复释放前实例数据仍在
<!-- <exclamation-circle-outlined class="warning-icon" /> -->
<!-- 实例连续关机15天会释放实例实例释放会导致数据清空且不可恢复释放前实例数据仍在 -->
</span>
</div>
</div>
@ -23,10 +23,8 @@
<div class="header-filter">
<a-select v-model:value="filterStatus" placeholder="筛选状态" style="width: 160px;" size="large"
@change="handleSearch">
<a-select-option value="all">全部状态</a-select-option>
<a-select-option value="running">运行中</a-select-option>
<a-select-option value="stopped">已停止</a-select-option>
<a-select-option value="error">异常</a-select-option>
<a-select-option value="">全部状态</a-select-option>
<a-select-option v-for="[key, config] in instanceStatus" :value="key">{{ config.text }}</a-select-option>
</a-select>
<a-input-search v-model:value="searchKeyword" placeholder="搜索实例名称/ID" style="width: 240px; margin-left: 12px;"
size="large" @search="handleSearch" />
@ -41,9 +39,8 @@
<!-- 状态列 -->
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<span :class="`status-${record.status}`">
{{ getStatusText(record.status) }}
</span>
<span :style="{ color: instanceStatus.get(record.status)?.color }">{{ instanceStatus.get(record.status)?.text
}}</span>
</template>
<!-- 规格详情列 -->
@ -64,7 +61,11 @@
{{ getHealthStatusText(record.health_status) }}
</span>
</template>
<template v-else-if="column.key === 'price_type'">
<span>
{{ payTypeDic.get(record.price_type) }}
</span>
</template>
<!-- 操作列 -->
<template v-else-if="column.key === 'actions'">
<div class="action-buttons">
@ -147,14 +148,10 @@
<p style="color: #666;"> 实例配置和网络设置保持不变</p>
</div>
</div>
<template #okText>
<span style="color: #ff4d4f;">确认重置</span>
</template>
</a-modal>
<!-- 释放确认模态框 -->
<a-modal v-model:open="releaseModalVisible" title="确认释放" @ok="confirmRelease" @cancel="releaseModalVisible = false"
:ok-button-props="{ danger: true }">
<a-modal v-model:open="releaseModalVisible" title="确认释放" @ok="confirmRelease" @cancel="releaseModalVisible = false" >
<div class="modal-content">
<exclamation-circle-outlined class="warning-icon"
style="color: #ff4d4f; font-size: 24px; margin-right: 12px;" />
@ -173,15 +170,17 @@
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import {ExclamationCircleOutlined,ReloadOutlined,EyeOutlined,DownOutlined,RedoOutlined,DeleteOutlined} from '@ant-design/icons-vue'
import { ExclamationCircleOutlined, ReloadOutlined, EyeOutlined, DownOutlined, RedoOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import type { TableColumnType } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { hostCaseList } from '@/apis/admin'
import { releaseCase, reStartCase } from '@/apis/home'
import { get } from 'http'
import { payTypeDic, instanceStatus } from '@/utils/dict'
const router = useRouter()
//
const filterStatus = ref('all')
const filterStatus = ref('')
const searchKeyword = ref('')
const loading = ref(false)
const specModalVisible = ref(false)
@ -217,7 +216,6 @@ const columns = ref<TableColumnType[]>([
{ title: '名称', dataIndex: 'name', key: 'name', width: 180 },
{ title: '状态', dataIndex: 'status', key: 'status', width: 100 },
{ title: '规格详情', dataIndex: 'spec', key: 'spec', width: 200 },
{ title: '本地磁盘', dataIndex: 'system_disk', key: 'system_disk', width: 120 },
{ title: '健康状态', dataIndex: 'health_status', key: 'health_status', width: 120 },
{ title: '付费方式', dataIndex: 'price_type', key: 'price_type', width: 120 },
{ title: '释放时间', dataIndex: 'release_at', key: 'release_at', width: 120 },
@ -232,7 +230,9 @@ const getDataList = async () => {
loading.value = true
const params = {
page_num: paginationState.value.current,
page_size: paginationState.value.pageSize
page_size: paginationState.value.pageSize,
status: filterStatus.value,
name: searchKeyword.value
}
const res = await hostCaseList(params)
mockData.value = res.data
@ -247,23 +247,11 @@ const getDataList = async () => {
getDataList()
//
const getStatusText = (status: string) => {
const map: Record<string, any> = {
"RUNNING": '运行中',
"STOPPED": '已停止',
"CREATING": '创建中',
"RESTARTING": '重启中',
}
return map[status] || status
}
//
const getHealthStatusText = (status: string) => {
const map: Record<string, string> = {
healthy: '健康',
warning: '警告',
error: '异常'
Normal: '正常',
Abnormal: '异常'
}
return map[status] || status
}
@ -325,32 +313,32 @@ const handleMenuClick = (key: string, record: any) => {
}
//
const confirmReset = () => {
const confirmReset = async () => {
if (!currentInstance.value) return
message.loading({ content: '正在重置实例...', key: 'reset', duration: 0 })
setTimeout(() => {
//
currentInstance.value.health_status = 'healthy'
try {
const res = await reStartCase(currentInstance.value.id)
message.success({ content: '实例重置成功', key: 'reset' })
resetModalVisible.value = false
}, 2000)
getDataList()
} catch (error: any) {
message.error(error)
resetModalVisible.value = false
}
}
//
const confirmRelease = () => {
const confirmRelease = async () => {
if (!currentInstance.value) return
message.loading({ content: '正在释放实例...', key: 'release', duration: 0 })
setTimeout(() => {
//
const index = mockData.value.findIndex(item => item.id === currentInstance.value.id)
if (index !== -1) {
mockData.value.splice(index, 1)
}
try {
const res = await releaseCase(currentInstance.value.id)
message.success({ content: '实例释放成功', key: 'release' })
releaseModalVisible.value = false
}, 2000)
getDataList()
} catch (error: any) {
message.error(error)
releaseModalVisible.value = false
}
}
//
@ -366,6 +354,7 @@ const refreshData = () => {
//
const handleSearch = () => {
paginationState.value.current = 1
getDataList()
}
//
@ -379,7 +368,7 @@ const onTableChange = (pag: any) => {
//
const handleRent = () => {
router.push('/layout/admin/instanceCreate')
router.push('/layout/market')
}
onMounted(() => {
@ -572,7 +561,7 @@ onMounted(() => {
}
//
.health-healthy {
.health-Normal {
color: #52c41a;
background: #f6ffed;
padding: 4px 8px;
@ -581,16 +570,16 @@ onMounted(() => {
display: inline-block;
}
.health-warning {
color: #faad14;
background: #fffbe6;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
display: inline-block;
}
// .health-Abnormal {
// color: #faad14;
// background: #fffbe6;
// padding: 4px 8px;
// border-radius: 4px;
// font-size: 12px;
// display: inline-block;
// }
.health-error {
.health-Abnormal {
color: #ff4d4f;
background: #fff2f0;
padding: 4px 8px;

View File

@ -15,12 +15,13 @@
<a-card class="card" title="计费方式">
<div class="billing-content">
<a-radio-group v-model:value="billingType" button-style="solid" @change="handleBillingTypeChange">
<a-radio-button value="payg">按量计费</a-radio-button>
<a-radio-button value="daily">包日</a-radio-button>
<a-radio-button value="weekly">包周</a-radio-button>
<a-radio-button value="monthly">包月</a-radio-button>
<a-radio-button value="PayOnTime">按量计费</a-radio-button>
<a-radio-button value="PayOnDay">包日</a-radio-button>
<a-radio-button value="PayOnWeek">包周</a-radio-button>
<a-radio-button value="PayOnMonth">包月</a-radio-button>
<a-radio-button value="PayOnYear">包年</a-radio-button>
</a-radio-group>
<a href="/docs/price/" target="_blank" class="billing-link">计费规则</a>
<!-- <a href="/docs/price/" target="_blank" class="billing-link">计费规则</a> -->
</div>
<div class="note">
创建完主机后仍然可以转换计费方式如选择按量计费价格发生变动以实例开机时的价格为准
@ -320,7 +321,7 @@ interface Coupon {
}
//
const billingType = ref('weekly')
const billingType = ref('PayOnTime')
const selectedRegion = ref('beijingDC2')
const selectedZone = ref('')
const selectedGpuModels = ref<string[]>(['RTX 5090'])
@ -1193,7 +1194,8 @@ const showPriceBreakdown = computed(() => {
}
.price-breakdown {
display: none; /* 移动端隐藏价格明细 */
display: none;
/* 移动端隐藏价格明细 */
}
.action-buttons {

View File

@ -1,7 +1,7 @@
<template>
<div class="gx_layout">
<div :class="isHome ? 'gx_layout_header_home' : 'gx_layout_header_noHome'" class="gx_layout_header">
<div class="logo">GxDL算力</div>
<div class="logo">FAST亼算</div>
</div>
<div style="height: 60px;width: 100%;"></div>
<div class="gx_layout_content">

View File

@ -19,7 +19,7 @@
</div>
<div class="one">
<div v-for="item in oneList" style="display: flex;justify-content: center;align-items: center;cursor: pointer;"
@click="router.push(item.path)">
@click="router.push(item.link_url)">
<div style="margin-right: 10px;"><img :src="item.img" alt="" srcset="" width="50" height="50"></div>
<div>
<h3>{{ item.title }}</h3>
@ -179,39 +179,39 @@ const fetchBannerList = async () => {
};
//
const getOneList = async () => {
try {
const res: any = await getApiOneList();
//
if (res && Array.isArray(res) && res.length > 0) {
oneList.value = res;
} else {
// API使
oneList.value = [{ id: 0, image_url: defaultBanner }];
}
} catch (error: any) {
console.error('轮播图请求失败:', error);
// try {
// const res: any = await getApiOneList();
// //
// if (res && Array.isArray(res) && res.length > 0) {
// oneList.value = res;
// } else {
// // API使
// oneList.value = [{ id: 0, image_url: defaultBanner }];
// }
// } catch (error: any) {
// console.error(':', error);
// 使
oneList.value = [
{
img: youhuiquan,
title: '算力免费领',
description: '完成认证/问卷获得算力券',
path: '/active/newUser'
link_url: '/active/newUser'
},
{
img: yaoqinghaoyou,
title: '邀约优算友',
description: '邀请好友可获得算力券',
path: '/active/invite'
link_url: '/active/invite'
},
{
img: goumaijilu,
title: '开业重磅福利',
description: '购算力,享豪礼',
path: '/active/newUser'
link_url: '/active/newUser'
}
]
}
// }
};
// GPU
const getGPUList = async () => {
@ -231,17 +231,17 @@ const getAdvantageList = async () => {
const res: any = await getAdvantage();
const list = res || [];
// item img
// list.forEach((item: any, index: number) => {
// if (index === 0) {
// item.img = one;
// } else if (index === 1) {
// item.img = two;
// } else if (index === 2) {
// item.img = three;
// } else {
// item.img = firth;
// }
// });
list.forEach((item: any, index: number) => {
if (index === 0) {
item.img = one;
} else if (index === 1) {
item.img = two;
} else if (index === 2) {
item.img = three;
} else {
item.img = firth;
}
});
advantageList.value = list;
} catch (error: any) {

View File

@ -1,5 +1,6 @@
<template>
<div class="container">
<a-spin :spinning="spinning">
<div class="instance-create-container">
<!-- 服务器选择 -->
<a-card class="card select-server" title="服务器选择">
@ -22,10 +23,19 @@
</a-radio-group>
</div>
</div>
<div class="filter-item" v-if="billingType != 'PayOnTime'">
<span class="filter-label">租用时长<span style="color: #ff4d4f;margin: 0 2px">*</span>:</span>
<div class="filter-content">
<a-select ref="select" v-model:value="priceCount" style="width: 300px">
<a-select-option v-for="item in priceCounts" :value="item.id">{{ item.label
}}</a-select-option>
</a-select>
</div>
</div>
<!-- GPU数量 -->
<div class="filter-item">
<span class="filter-label">GPU数量<span style="color: #ff4d4f;margin: 0 2px">*</span><span>:</span></span>
<span class="filter-label">GPU数量<span
style="color: #ff4d4f;margin: 0 2px">*</span><span>:</span></span>
<div class="filter-content">
<a-radio-group v-model:value="gpuCount" button-style="solid">
<a-radio-button v-for="count in gpuCountOptions" :key="count" :value="count">
@ -77,7 +87,8 @@
<span>{{ '数据盘:' + serviceInfo.dataDisk + 'GB' }}</span><br>
<span>{{ '系统盘:' + serviceInfo.systemDisk + "GB" }}</span>
</a-descriptions-item>
<a-descriptions-item label="驱动/CUDA">{{ serviceInfo.gpuDriver + '/' + serviceInfo.cudaVersion
<a-descriptions-item label="驱动/CUDA">{{ serviceInfo.gpuDriver + '/' +
serviceInfo.cudaVersion
}}</a-descriptions-item>
<a-descriptions-item label="消耗算力点(单卡)">{{ serviceInfo.price }}</a-descriptions-item>
</a-descriptions>
@ -85,17 +96,27 @@
</a-card>
<!-- 优惠券 -->
<a-card class="card coupon-selection">
<a-checkbox v-model:checked="checked">是否使用算力券<span style="color:#f34646;">{{ ' ( 可用点数:'+couponTotal+' 点 )' }}</span></a-checkbox>
<div style="display: flex;align-items: center;">
<div>算力券</div>
<a-select ref="select" v-model:value="voucherId" style="width:300px" @change="handleChange">
<a-select-option :value="''">不使用算力券</a-select-option>
<a-select-option v-for="value in voucherList" :value="value.id">{{ value.name + ' - '+''+value.amount }}</a-select-option>
</a-select>
</div>
</a-card>
<!-- 底部操作栏 -->
</div>
</a-spin>
<div class="footer-actions">
<div class="price-summary">
<div>消耗算力点{{totalMoney }}</div>
<div>消耗算力点{{ totalMoney }}</div>
<!-- 账户余额信息 -->
<div class="account-info" style="display: flex;align-items: center;">
<div class="balance-label" style="margin-right: 10px;">可用算力点{{ userInfo.computingPowerPoint+' 点' }}</div>
<div class="balance-label" style="margin-right: 10px;">可用算力点{{ userInfo.computingPowerPoint + ' 点'
}}
</div>
<!-- <div v-if="isShow" style="color: #ff4d4f;font-size: 12px;cursor: pointer;"
@click="router.push('/layout/admin/balance')">
算力点不足去充值</div> -->
@ -115,7 +136,7 @@
取消
</a-button>
<a-button type="primary" size="large" @click="handleCreate" :loading="creating"
:disabled="selectedImage==''" class="create-btn">
:disabled="selectedImage == ''" class="create-btn">
<template #icon>
<PlusOutlined />
</template>
@ -132,10 +153,10 @@
import { ref, computed, reactive, watch, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import type { TableColumnsType } from 'ant-design-vue'
import { useRoute,useRouter } from 'vue-router'
import { getImages } from "@/apis/home"
import { getMyCouponTotal, getTotalCost, getHostInfo,createHost } from "@/apis/home"
const router=useRouter()
import { useRoute, useRouter } from 'vue-router'
import { getImages, getRecommendList } from "@/apis/home"
import { getMyCouponTotal, getTotalCost, getHostInfo, createHost } from "@/apis/home"
const router = useRouter()
interface GpuModelOption {
value: string
label: string
@ -143,10 +164,12 @@ interface GpuModelOption {
total: number
regions: string[]
}
const instanceName=ref('')
const voucherList = ref<any[]>([])
const instanceName = ref('')
const checked = ref(false)
const totalMoney = ref(0)
const priceCount = ref(1)
const voucherId = ref('')
//
const billingType = ref('PayOnTime')
const gpuCount = ref(5)
@ -156,25 +179,33 @@ const selectedImage = ref<string>("")
const creating = ref(false)
const serviceInfo = ref<any>({})
const userInfo = ref<any>({})
const HostId=ref(0)
const computingPowerPoint=ref(0)
const couponTotal=ref(0)
onMounted(() => {
const HostId = ref(0)
const computingPowerPoint = ref(0)
const couponTotal = ref(0)
const spinning = ref(false)
onMounted(async () => {
spinning.value = true
const userInfoStr = localStorage.getItem("userInfo")
if (userInfoStr) {
userInfo.value = JSON.parse(userInfoStr)
}
serviceInfo.value = useRoute().query
HostId.value=serviceInfo.value.id
console.log('1111',serviceInfo.value)
HostId.value = serviceInfo.value.id
instanceName.value = serviceInfo.value.name
gpuCountOptions.value = Array.from({ length: Number(serviceInfo.value.gpuAvailableNum) }, (_, i) => i + 1)
gpuCount.value = gpuCountOptions.value[0]
getServiceImages()
getCoupon()
fetchTotalCost()
await getServiceImages()
await getCoupon()
await fetchTotalCost()
await getVoucherList()
spinning.value = false
})
async function getVoucherList() {
const res = await getRecommendList()
voucherList.value = res.data
}
async function getCoupon() {
const res:any=await getMyCouponTotal()
const res: any = await getMyCouponTotal()
couponTotal.value = res;
}
//
@ -182,14 +213,26 @@ async function fetchTotalCost() {
const res: any = await getTotalCost({
billingMethod: billingType.value,
gpuNum: gpuCount.value,
host_id: HostId.value
host_id: HostId.value,
price_count:priceCount.value
})
totalMoney.value = res.amount
computingPowerPoint.value=res.computingPowerPoint
computingPowerPoint.value = res.computingPowerPoint
}
const dayList = ref([{ id: 1, label: '1日' }, { id: 2, label: '2日' }, { id: 3, label: '3日' }, { id: 4, label: '4日' }, { id: 5, label: '5日' }, { id: 6, label: '6日' }])
const weekList = ref([{ id: 1, label: '1周' }, { id: 2, label: '2周' }, { id: 3, label: '3周' }])
const weekMonth = ref([{ id: 1, label: '1个月' }, { id: 2, label: '2个月' }, { id: 3, label: '3个月' }, { id: 3, label: '4个月' }, { id: 3, label: '5个月' }, { id: 3, label: '6个月' }, { id: 3, label: '7个月' }, { id: 3, label: '8个月' }, { id: 3, label: '9个月' }, { id: 3, label: '10个月' }, { id: 3, label: '11个月' }])
const priceCounts = computed(() => {
if (billingType.value === 'PayOnDay') {
return dayList.value
} else if (billingType.value === 'PayOnWeek') {
return weekList.value
} else if (billingType.value === 'PayOnMonth') {
return weekMonth.value
}
})
//
watch([billingType, gpuCount], () => {
watch([billingType, gpuCount,priceCount], () => {
fetchTotalCost()
getSingleHost()
}) //
@ -222,23 +265,23 @@ const handleChange = (e: any) => {
console.log(e)
}
const isShow=computed(()=>{
return userInfo.value.balance<computingPowerPoint.value
const isShow = computed(() => {
return userInfo.value.balance < computingPowerPoint.value
})
const handleCreate = async () => {
creating.value = true
try {
const params={
host_id:HostId.value,
billingMethod:billingType.value,
gpuNum:gpuCount.value,
case_name:instanceName.value,
image_id:selectedImage.value,
is_use_voucher:checked.value
const params = {
host_id: HostId.value,
billingMethod: billingType.value,
gpuNum: gpuCount.value,
case_name: instanceName.value,
image_id: selectedImage.value,
voucher_id: voucherId.value
}
const res=await createHost(params)
const res = await createHost(params)
message.success('实例创建成功!')
creating.value=false
creating.value = false
} catch (error) {
message.error('创建失败,请重试')
} finally {

View File

@ -1,7 +1,7 @@
<template>
<div class="gx_layout">
<div :class="isHome ? 'gx_layout_header_home' : 'gx_layout_header_noHome'" class="gx_layout_header">
<div class="logo">GxDL算力</div>
<div class="logo">FAST亼算</div>
<div class="menu">
<a-menu v-model:selectedKeys="current" :class="isHome ? 'custom-menu' : ''" mode="horizontal"
:items="leftRoutes" @click="({ key }) => handleMenuClick(key)" />

View File

@ -1,5 +1,6 @@
<template>
<div class="instance-create-container">
<a-spin :spinning="spinning">
<div class="header">
<h1>算力中心</h1>
<h2>聚焦高效算力服务为数字产业智能应用提供强支撑</h2>
@ -42,8 +43,8 @@
<!-- 机器列表 -->
<a-card class="card machine-list">
<template v-if="allMachineList.length > 0">
<a-spin :spinning="tableLoading">
<div class="image-card-container" style="min-height:300px;">
<div v-for="record in allMachineList" :key="record.id" class="image-card"
:class="{ selected: selectedMachineId === record.id }" @click="handleSelectMachine(record.id)">
<!-- 顶部 -->
@ -85,34 +86,36 @@
</div>
<a-button type="primary" class="buy-btn" :disabled="record.freeGpu === 0"
@click.stop="handleRentMachine(record)">
立即购买
立即创建
</a-button>
</div>
</div>
</div>
</a-spin>
</template>
<template v-else>
<a-empty />
</template>
<!-- 分页 -->
<div class="pagination-container">
<a-pagination v-model:current="currentPage" v-model:pageSize="pageSize" :total="hostTotal"
show-size-changer show-quick-jumper />
<a-pagination v-model:current="currentPage" v-model:pageSize="pageSize" :total="hostTotal" show-size-changer
show-quick-jumper />
</div>
</a-card>
</div>
</a-spin>
</div>
</template>
<script setup lang="ts">
import { ref, computed, reactive, watch } from 'vue'
import { ref, computed, reactive, watch, onMounted } from 'vue'
import { hostList, getAreaListApi, getGpuListApi } from '@/apis/market'
import { message } from 'ant-design-vue'
import type { TableColumnsType } from 'ant-design-vue'
import { useRouter } from 'vue-router'
const spinning = ref(false)
const router = useRouter();
//
const hostTotal = ref(0)
@ -127,9 +130,14 @@ const tableLoading = ref(false)
//
const currentPage = ref(1)
const pageSize = ref(10)
getHostList()
getAreaList()
getGpuList()
onMounted(async () => {
spinning.value = true
await getHostList()
await getAreaList()
await getGpuList()
spinning.value = false
})
async function getHostList() {
tableLoading.value = true
try {
@ -187,13 +195,13 @@ const handleSelectMachine = (id: string) => {
}
//
const handleRentMachine = (record: any) => {
router.push({path:"/layout/create",query:record})
router.push({ path: "/layout/create", query: record })
}
const handleGpuCountChange = (e:any) => {
const handleGpuCountChange = (e: any) => {
// console.log(e)
gpuCount.value=e
gpuCount.value = e
getHostList()
selectedMachineId.value = ''
currentPage.value = 1

View File

@ -21,7 +21,7 @@ export default defineConfig({
open: true, // 可选:启动时自动打开浏览器
proxy: {
'/api': {
target: 'http://10.10.1.34:8888', // 目标服务器的地址
target: 'http://10.10.1.11:8888', // 目标服务器的地址
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},