Commit 04340bf7 by renyizhao

动态规格

parent 5d3142e4
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" :width="1000">
<!-- 搜索区域 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="82px"
>
<el-form-item label="配置类别" prop="configCategory">
<el-select
v-model="queryParams.configCategory"
placeholder="请选择配置类别"
clearable
class="!w-200px"
>
<el-option
v-for="dict in categoryOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="配置选项" prop="configOption">
<el-input
v-model="queryParams.configOption"
placeholder="请输入配置选项"
clearable
@keyup.enter="handleQuery"
class="!w-200px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
</el-form-item>
</el-form>
<!-- 规格配置列表 -->
<el-table
ref="tableRef"
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
@selection-change="handleSelectionChange"
height="400"
>
<el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column label="配置类别" align="center" prop="configCategory" min-width="160">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMPUTE_RESOURCE_CONFIG_CATEGORY" :value="scope.row.configCategory" />
</template>
</el-table-column>
<el-table-column label="配置选项" align="center" prop="configOption" min-width="180" />
<el-table-column label="详情备注" align="center" prop="detailRemark" min-width="200" />
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
class="mt-4"
/>
<!-- 底部按钮 -->
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleConfirm">
确定选择 ({{ selectedCount }})
</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { ResourceConfigApi, ResourceConfig } from '@/api/compute/resourceconfig'
interface Props {
modelValue: boolean
title?: string
/** 已选中的规格 ID 列表(用于回显勾选状态) */
selectedIds?: number[]
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
(e: 'confirm', selections: ResourceConfig[]): void
}
const props = withDefaults(defineProps<Props>(), {
title: '选择规格',
selectedIds: () => []
})
const emit = defineEmits<Emits>()
const dialogVisible = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
const dialogTitle = computed(() => props.title)
// 字典选项
const categoryOptions = getStrDictOptions(DICT_TYPE.COMPUTE_RESOURCE_CONFIG_CATEGORY)
const loading = ref(false)
const list = ref<ResourceConfig[]>([])
const total = ref(0)
const tableRef = ref()
// 跨分页的全量已选规格(key: id,value: 完整规格对象)
// 用于支持多选 + 翻页 + 取消勾选场景
const allSelectedMap = reactive(new Map<number, ResourceConfig>())
const selectedCount = computed(() => allSelectedMap.size)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
configCategory: undefined,
configOption: undefined,
status: 0 // 默认只查询启用的规格
})
const queryFormRef = ref()
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ResourceConfigApi.getResourceConfigPage(queryParams)
list.value = data.list
total.value = data.total
// 数据加载完后回显已选中的项
await nextTick()
restoreSelection()
} finally {
loading.value = false
}
}
/** 回显已选中的规格(跨分页) */
const restoreSelection = () => {
if (!props.selectedIds?.length || !tableRef.value) return
const idSet = new Set(props.selectedIds)
for (const row of list.value) {
if (idSet.has(row.id)) {
tableRef.value.toggleRowSelection(row, true)
}
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields()
queryParams.status = 0
handleQuery()
}
/** 处理表格多选变化
* el-table 的 selection-change 只会带当前页可见的已选行;
* 这里用 allSelectedMap 维护所有分页的全量已选规格。
* 策略:把当前页 id 全部从 map 中移除,再把 rows(当前页最新已选)写入 map,
* 这样能正确处理「取消勾选」和「翻页」两种场景。
*/
const handleSelectionChange = (rows: ResourceConfig[]) => {
const currentPageIds = list.value.map((r) => r.id)
const visibleSelectedIds = new Set(rows.map((r) => r.id))
for (const id of currentPageIds) {
if (!visibleSelectedIds.has(id)) {
allSelectedMap.delete(id)
}
}
for (const row of rows) {
allSelectedMap.set(row.id, row)
}
}
/** 确认选择 - 提交全量已选(跨分页) */
const handleConfirm = () => {
emit('confirm', Array.from(allSelectedMap.values()))
dialogVisible.value = false
}
/** 打开弹窗时加载数据
* 弹窗只展示启用规格,但 props.selectedIds 里可能既有启用的也有禁用的;
* 跨分页的已选规格在第一页打开时不会触发 selection-change,所以这里要主动
* 预加载所有已选的启用规格到 allSelectedMap,让底部计数从一开始就是全量。
*/
const handleOpen = async () => {
allSelectedMap.clear()
if (props.selectedIds?.length) {
const results = await Promise.all(
props.selectedIds.map((id) => ResourceConfigApi.getResourceConfig(id).catch(() => null))
)
for (const cfg of results) {
// 只统计启用规格(弹窗只展示启用规格,禁用的不在计数范围内)
if (cfg && cfg.status !== 1) {
allSelectedMap.set(cfg.id, cfg)
}
}
}
getList()
}
// 监听弹窗打开
watch(
() => props.modelValue,
(val) => {
if (val) {
handleOpen()
} else {
// 关闭时清空全量选择
allSelectedMap.clear()
}
},
{ immediate: true }
)
</script>
...@@ -59,26 +59,35 @@ ...@@ -59,26 +59,35 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 4. 规格配置 - 按 configCategory 分组多选 --> <!-- 4. 规格配置 - 弹窗多选 -->
<el-form-item label="规格配置" prop="specConfigIds"> <el-form-item label="规格配置" prop="specConfigIds">
<div class="spec-config-wrapper"> <div class="spec-config-wrapper">
<div v-for="category in specCategories" :key="category.value" class="spec-category-row"> <div v-if="selectedConfigs.length" class="spec-tag-list">
<span class="spec-category-label">{{ category.label }}</span> <el-tag
<el-checkbox-group v-for="item in selectedConfigs"
v-model="formData.specConfigIdsByCategory[category.value]" :key="item.id"
:disabled="isDetailMode" :type="isDisabledConfig(item) ? 'danger' : 'primary'"
:effect="isDisabledConfig(item) ? 'dark' : 'light'"
closable
:disable-transitions="true"
class="!mr-2 !mb-2"
@close="removeSpecConfig(item.id)"
> >
<el-checkbox v-for="opt in category.options" :key="opt.id" :value="opt.id"> {{ getCategoryLabel(item.configCategory) }}: {{ item.configOption }}
{{ opt.configOption }} <el-text v-if="isDisabledConfig(item)" type="danger" size="small" class="!ml-1">
<el-tooltip v-if="opt.detailRemark" :content="opt.detailRemark" placement="top"> (已禁用)
<Icon icon="ep:info-filled" class="ml-1" /> </el-text>
</el-tooltip> </el-tag>
</el-checkbox>
</el-checkbox-group>
</div> </div>
<div v-if="!specCategories.length" class="spec-empty" <el-text v-else type="info">暂未选择规格</el-text>
>暂无规格类别,请在「系统管理 → 字典管理」配置</div <el-button
type="primary"
plain
:disabled="isDetailMode"
@click="configDialogVisible = true"
> >
<Icon icon="ep:plus" class="mr-5px" /> 选择规格
</el-button>
</div> </div>
</el-form-item> </el-form-item>
...@@ -181,6 +190,13 @@ ...@@ -181,6 +190,13 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
</ContentWrap> </ContentWrap>
<!-- 规格选择弹窗 -->
<ResourceConfigSelectDialog
v-model="configDialogVisible"
:selected-ids="formData.specConfigIds || []"
@confirm="handleConfigConfirm"
/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
...@@ -188,8 +204,9 @@ import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' ...@@ -188,8 +204,9 @@ import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
import { UploadImg } from '@/components/UploadFile' import { UploadImg } from '@/components/UploadFile'
import { useTagsViewStore } from '@/store/modules/tagsView' import { useTagsViewStore } from '@/store/modules/tagsView'
import { ResourceSpu, ResourceSpuApi } from '@/api/compute/resourcespu' import { ResourceSpu, ResourceSpuApi } from '@/api/compute/resourcespu'
import { ResourceConfigApi } from '@/api/compute/resourceconfig' import { ResourceConfigApi, ResourceConfig } from '@/api/compute/resourceconfig'
import * as AreaApi from '@/api/system/area' import * as AreaApi from '@/api/system/area'
import ResourceConfigSelectDialog from '../ResourceConfigSelectDialog.vue'
defineOptions({ name: 'ResourceSpuAdd' }) defineOptions({ name: 'ResourceSpuAdd' })
...@@ -213,18 +230,22 @@ const formRef = ref() // 表单 Ref ...@@ -213,18 +230,22 @@ const formRef = ref() // 表单 Ref
const categoryList = ref<any[]>([]) const categoryList = ref<any[]>([])
const areaList = ref<any[]>([]) // 地区树数据 const areaList = ref<any[]>([]) // 地区树数据
// 规格分组(按 configCategory 分组多选) // 已选规格(仅前端用于回显 tag,需提交时只取 id 列表)
interface SpecOption { const selectedConfigs = ref<ResourceConfig[]>([])
id: number const configDialogVisible = ref(false) // 规格选择弹窗可见性
configOption: string // 类别字典:用于把 configCategory 转为中文 label
detailRemark?: string const categoryDictMap = computed(() => {
} const map: Record<string, string> = {}
interface SpecCategory { for (const d of getStrDictOptions(DICT_TYPE.COMPUTE_RESOURCE_CONFIG_CATEGORY)) {
value: string // 字典 value(对应 configCategory) map[d.value as string] = d.label
label: string // 字典 label }
options: SpecOption[] return map
} })
const specCategories = ref<SpecCategory[]>([]) const getCategoryLabel = (category?: string) =>
(category && categoryDictMap.value[category]) || category || ''
/** 判断已选规格是否已禁用 */
const isDisabledConfig = (item: ResourceConfig) => item.status === 1
const formData = ref<ResourceSpu>({ const formData = ref<ResourceSpu>({
id: undefined, id: undefined,
...@@ -236,8 +257,9 @@ const formData = ref<ResourceSpu>({ ...@@ -236,8 +257,9 @@ const formData = ref<ResourceSpu>({
sliderPicUrls: undefined, sliderPicUrls: undefined,
sales: undefined, sales: undefined,
status: undefined, status: undefined,
// 规格相关 // 规格相关(提交时使用)
specConfigIds: [], specConfigIds: [],
// 前端辅助字段(不再使用分组多选,但保留以兼容类型)
specConfigIdsByCategory: {} specConfigIdsByCategory: {}
}) })
...@@ -249,53 +271,42 @@ const formRules = reactive({ ...@@ -249,53 +271,42 @@ const formRules = reactive({
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }] status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
}) })
/** /** 删除单个已选规格 */
* 加载规格分组选项: const removeSpecConfig = (id: number) => {
* 1. 从字典 compute_resource_config_category 读取所有类别 selectedConfigs.value = selectedConfigs.value.filter((c) => c.id !== id)
* 2. 对每个类别调 listSimpleConfigByCategory 拿该类别的所有规格项 formData.value.specConfigIds = selectedConfigs.value.map((c) => c.id)
*/
const loadSpecOptions = async () => {
const categoryDicts = getStrDictOptions(DICT_TYPE.COMPUTE_RESOURCE_CONFIG_CATEGORY)
if (!categoryDicts.length) {
specCategories.value = []
return
}
const results = await Promise.all(
categoryDicts.map(async (cat) => {
const options = await ResourceConfigApi.listSimpleConfigByCategory(cat.value as string)
return {
value: cat.value as string,
label: cat.label,
options: (options || []) as SpecOption[]
}
})
)
specCategories.value = results
// 预填 specConfigIdsByCategory 键,确保 el-checkbox-group v-model 能正常绑定
for (const cat of specCategories.value) {
if (!formData.value.specConfigIdsByCategory[cat.value]) {
formData.value.specConfigIdsByCategory[cat.value] = []
}
}
} }
/** /** 规格选择弹窗 - 确认回调
* 把后端返回的扁平 specConfigIds 按 configCategory 分布到各分组 * dialog 只展示启用规格,selections 是「全量已选的启用规格」;
* 表单里已有的禁用规格(status===1)需要保留,避免从弹窗走一圈就丢了。
*/ */
const distributeSpecConfigIds = () => { const handleConfigConfirm = (selections: ResourceConfig[]) => {
const flat = new Set(formData.value.specConfigIds || []) const map = new Map<number, ResourceConfig>()
// 先清空所有分组 // 先放禁用规格(保留)
for (const cat of specCategories.value) { for (const c of selectedConfigs.value) {
formData.value.specConfigIdsByCategory[cat.value] = [] if (isDisabledConfig(c)) {
map.set(c.id, c)
} }
// 再按 configId 匹配回填
for (const cat of specCategories.value) {
for (const opt of cat.options) {
if (flat.has(opt.id)) {
formData.value.specConfigIdsByCategory[cat.value].push(opt.id)
} }
// 再用弹窗返回的启用规格覆盖(支持取消勾选、新增)
for (const c of selections) {
map.set(c.id, c)
} }
selectedConfigs.value = Array.from(map.values())
formData.value.specConfigIds = selectedConfigs.value.map((c) => c.id)
}
/** 根据 id 列表加载完整规格对象(用于编辑模式回显) */
const loadSelectedConfigs = async (ids: number[]) => {
if (!ids?.length) {
selectedConfigs.value = []
return
} }
const results = await Promise.all(
ids.map((id) => ResourceConfigApi.getResourceConfig(id).catch(() => null))
)
selectedConfigs.value = results.filter(Boolean) as ResourceConfig[]
} }
/** 地区选择变化时,自动设置 location 为市级名称(第二级) */ /** 地区选择变化时,自动设置 location 为市级名称(第二级) */
...@@ -334,14 +345,19 @@ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成 ...@@ -334,14 +345,19 @@ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成
const submitForm = async () => { const submitForm = async () => {
await formRef.value.validate() await formRef.value.validate()
// 校验:至少选 1 个规格 // 校验:至少选 1 个规格
const allSpecIds = (Object.values(formData.value.specConfigIdsByCategory || {}).flat() || if (!formData.value.specConfigIds?.length) {
[]) as number[]
if (!allSpecIds.length) {
message.error('请至少选择 1 个规格') message.error('请至少选择 1 个规格')
return return
} }
// 扁平化写入 formData.specConfigIds // 校验:所选规格不能包含已禁用的项
formData.value.specConfigIds = allSpecIds const disabledItems = selectedConfigs.value.filter(isDisabledConfig)
if (disabledItems.length) {
const names = disabledItems
.map((c) => `${getCategoryLabel(c.configCategory)}: ${c.configOption}`)
.join('、')
message.error(`已选规格包含已禁用的项:${names},请移除后重新选择`)
return
}
formLoading.value = true formLoading.value = true
try { try {
const data = { ...formData.value } as unknown as ResourceSpu const data = { ...formData.value } as unknown as ResourceSpu
...@@ -373,11 +389,10 @@ const close = () => { ...@@ -373,11 +389,10 @@ const close = () => {
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {
try { try {
// 并行加载分类列表、地区树和规格分组 // 并行加载分类列表、地区树
const [categoryResponse, areaResponse] = await Promise.all([ const [categoryResponse, areaResponse] = await Promise.all([
ResourceSpuApi.listSimpleCategory(), ResourceSpuApi.listSimpleCategory(),
AreaApi.getAreaTree(), AreaApi.getAreaTree()
loadSpecOptions()
]) ])
categoryList.value = categoryResponse categoryList.value = categoryResponse
areaList.value = areaResponse areaList.value = areaResponse
...@@ -391,8 +406,8 @@ onMounted(async () => { ...@@ -391,8 +406,8 @@ onMounted(async () => {
if (!formData.value.specConfigIdsByCategory) { if (!formData.value.specConfigIdsByCategory) {
formData.value.specConfigIdsByCategory = {} formData.value.specConfigIdsByCategory = {}
} }
// 把 specConfigIds 分布到各分组 // 加载已选规格的完整对象(用于回显 tag)
distributeSpecConfigIds() await loadSelectedConfigs(formData.value.specConfigIds || [])
} finally { } finally {
formLoading.value = false formLoading.value = false
} }
...@@ -405,24 +420,16 @@ onMounted(async () => { ...@@ -405,24 +420,16 @@ onMounted(async () => {
<style scoped> <style scoped>
.spec-config-wrapper { .spec-config-wrapper {
display: flex;
flex-direction: column;
align-items: flex-start;
width: 100%; width: 100%;
} }
.spec-category-row { .spec-tag-list {
display: flex; display: flex;
align-items: flex-start; flex-wrap: wrap;
align-items: center;
width: 100%;
margin-bottom: 12px; margin-bottom: 12px;
} }
.spec-category-label {
width: 80px;
text-align: right;
padding-right: 12px;
color: #606266;
line-height: 32px;
flex-shrink: 0;
}
.spec-empty {
color: #909399;
font-size: 13px;
padding: 8px 0;
}
</style> </style>
...@@ -17,83 +17,6 @@ ...@@ -17,83 +17,6 @@
class="!w-240px" class="!w-240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="CPU" prop="cpu">
<el-select v-model="queryParams.cpu" placeholder="请选择CPU配置" clearable class="!w-240px">
<el-option
v-for="option in resourceConfigStore.getOptionsByType('cpu')"
:key="option.id"
:label="option.configOption"
:value="option.configOption"
/>
</el-select>
</el-form-item>
<el-form-item label="GPU" prop="gpu">
<el-select v-model="queryParams.gpu" placeholder="请选择GPU配置" clearable class="!w-240px">
<el-option
v-for="option in resourceConfigStore.getOptionsByType('gpu')"
:key="option.id"
:label="option.configOption"
:value="option.configOption"
/>
</el-select>
</el-form-item>
<el-form-item label="内存" prop="ram">
<el-select
v-model="queryParams.ram"
placeholder="请选择内存配置"
clearable
class="!w-240px"
>
<el-option
v-for="option in resourceConfigStore.getOptionsByType('ram')"
:key="option.id"
:label="option.configOption"
:value="option.configOption"
/>
</el-select>
</el-form-item>
<el-form-item label="存储" prop="storage">
<el-select
v-model="queryParams.storage"
placeholder="请选择存储配置"
clearable
class="!w-240px"
>
<el-option
v-for="option in resourceConfigStore.getOptionsByType('storage')"
:key="option.id"
:label="option.configOption"
:value="option.configOption"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="服务器ip" prop="ip">-->
<!-- <el-input-->
<!-- v-model="queryParams.ip"-->
<!-- placeholder="请输入服务器ip"-->
<!-- clearable-->
<!-- @keyup.enter="handleQuery"-->
<!-- class="!w-240px"-->
<!-- />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="初始用户名" prop="initUsername">-->
<!-- <el-input-->
<!-- v-model="queryParams.initUsername"-->
<!-- placeholder="请输入初始用户名"-->
<!-- clearable-->
<!-- @keyup.enter="handleQuery"-->
<!-- class="!w-240px"-->
<!-- />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="初始密码" prop="initPassword">-->
<!-- <el-input-->
<!-- v-model="queryParams.initPassword"-->
<!-- placeholder="请输入初始密码"-->
<!-- clearable-->
<!-- @keyup.enter="handleQuery"-->
<!-- class="!w-240px"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item label="商品简介" prop="intro"> <el-form-item label="商品简介" prop="intro">
<el-input <el-input
v-model="queryParams.intro" v-model="queryParams.intro"
...@@ -133,21 +56,6 @@ ...@@ -133,21 +56,6 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="服务器所在地" prop="location">
<el-select
v-model="queryParams.location"
placeholder="请选择服务器所在地"
clearable
class="!w-240px"
>
<el-option
v-for="option in resourceConfigStore.getOptionsByType('location')"
:key="option.id"
:label="option.configOption"
:value="option.configOption"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="商品封面图" prop="picUrl">--> <!-- <el-form-item label="商品封面图" prop="picUrl">-->
<!-- <el-input--> <!-- <el-input-->
<!-- v-model="queryParams.picUrl"--> <!-- v-model="queryParams.picUrl"-->
...@@ -216,7 +124,7 @@ ...@@ -216,7 +124,7 @@
> >
<Icon icon="ep:plus" class="mr-5px" /> 新增 <Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button> </el-button>
<el-button <!-- <el-button
type="success" type="success"
plain plain
@click="handleExport" @click="handleExport"
...@@ -224,7 +132,7 @@ ...@@ -224,7 +132,7 @@
v-hasPermi="['compute:resource-spu:export']" v-hasPermi="['compute:resource-spu:export']"
> >
<Icon icon="ep:download" class="mr-5px" /> 导出 <Icon icon="ep:download" class="mr-5px" /> 导出
</el-button> </el-button> -->
<el-button <el-button
type="danger" type="danger"
plain plain
...@@ -268,16 +176,11 @@ ...@@ -268,16 +176,11 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 硬件配置字段已隐藏 --> <!-- 硬件配置字段已隐藏 -->
<!-- <el-table-column label="算力资源分类编号" align="center" prop="categoryId" />--> <!-- <el-table-column label="算力资源分类编号" align="center" prop="categoryId" />-->
<el-table-column label="算力资源分类" align="center" prop="categoryName" min-width="150" /> <el-table-column label="算力资源分类" align="center" prop="categoryName" min-width="150" />
<el-table-column label="规格" min-width="240"> <el-table-column label="规格" min-width="240">
<template #default="{ row }"> <template #default="{ row }">
<el-tag <el-tag v-for="(value, key) in row.specMap" :key="key" size="small" class="!mr-1">
v-for="(value, key) in row.specMap"
:key="key"
size="small"
class="!mr-1"
>
{{ key }}: {{ value }} {{ key }}: {{ value }}
</el-tag> </el-tag>
</template> </template>
...@@ -351,10 +254,8 @@ import download from '@/utils/download' ...@@ -351,10 +254,8 @@ import download from '@/utils/download'
import { createImageViewer } from '@/components/ImageViewer' import { createImageViewer } from '@/components/ImageViewer'
import { ResourceSpuApi, ResourceSpu } from '@/api/compute/resourcespu' import { ResourceSpuApi, ResourceSpu } from '@/api/compute/resourcespu'
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
import { useResourceConfigStore } from '@/store/modules/compute/hardwareConfig'
const { push } = useRouter() const { push } = useRouter()
const resourceConfigStore = useResourceConfigStore()
/** 算力资源SPU表(基础配置信息) 列表 */ /** 算力资源SPU表(基础配置信息) 列表 */
defineOptions({ name: 'ResourceSpu' }) defineOptions({ name: 'ResourceSpu' })
...@@ -370,20 +271,9 @@ const queryParams = reactive({ ...@@ -370,20 +271,9 @@ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
name: undefined, name: undefined,
cpu: undefined,
gpu: undefined,
ram: undefined,
storage: undefined,
ip: undefined,
initUsername: undefined,
initPassword: undefined,
intro: undefined, intro: undefined,
categoryId: undefined, categoryId: undefined,
source: undefined, source: undefined,
location: undefined,
picUrl: undefined,
sliderPicUrls: undefined,
sales: undefined,
status: undefined, status: undefined,
createTime: [] createTime: []
}) })
...@@ -485,15 +375,9 @@ const handleExport = async () => { ...@@ -485,15 +375,9 @@ const handleExport = async () => {
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
try { try {
// 并行加载数据 // 加载分类列表 + 列表数据
const [categoryResponse] = await Promise.all([ const [categoryResponse] = await Promise.all([ResourceSpuApi.listSimpleCategory(), getList()])
ResourceSpuApi.listSimpleCategory(),
resourceConfigStore.loadConfigOptions()
])
categoryList.value = categoryResponse categoryList.value = categoryResponse
// 加载列表数据
getList()
} catch (error) { } catch (error) {
console.error('初始化失败:', error) console.error('初始化失败:', error)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment