Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1f847553
authored
Oct 10, 2025
by
Jony.L
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
算力资源重构-算力资源SKU管理修改1.0
parent
9d78ba94
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
373 additions
and
0 deletions
+373
-0
src/store/modules/compute/hardwareConfig.ts
+91
-0
src/views/compute/resourcespu/ResourceSpuSelectDialog.vue
+282
-0
No files found.
src/store/modules/compute/hardwareConfig.ts
0 → 100644
View file @
1f847553
import
{
defineStore
}
from
'pinia'
import
{
ResourceConfigApi
}
from
'@/api/compute/resourceconfig'
interface
ResourceConfig
{
cpuOptions
:
any
[]
gpuOptions
:
any
[]
ramOptions
:
any
[]
storageOptions
:
any
[]
locationOptions
:
any
[]
lastFetched
:
number
|
null
}
export
const
useResourceConfigStore
=
defineStore
(
'resourceConfig'
,
{
state
:
():
ResourceConfig
=>
({
cpuOptions
:
[],
gpuOptions
:
[],
ramOptions
:
[],
storageOptions
:
[],
locationOptions
:
[],
lastFetched
:
null
}),
getters
:
{
// 判断是否需要重新获取数据(缓存5分钟)
needsRefresh
():
boolean
{
if
(
!
this
.
lastFetched
)
return
true
const
now
=
Date
.
now
()
const
fiveMinutes
=
5
*
60
*
1000
return
now
-
this
.
lastFetched
>
fiveMinutes
},
// 获取所有配置选项
allOptions
()
{
return
{
cpu
:
this
.
cpuOptions
,
gpu
:
this
.
gpuOptions
,
ram
:
this
.
ramOptions
,
storage
:
this
.
storageOptions
,
location
:
this
.
locationOptions
}
}
},
actions
:
{
// 加载硬件配置选项
async
loadConfigOptions
(
forceRefresh
=
false
)
{
// 如果不需要刷新且不是强制刷新,直接返回缓存数据
if
(
!
forceRefresh
&&
!
this
.
needsRefresh
)
{
return
this
.
allOptions
}
try
{
const
[
cpuRes
,
gpuRes
,
ramRes
,
storageRes
,
locationRes
]
=
await
Promise
.
all
([
ResourceConfigApi
.
listSimpleConfigByCategory
(
'cpu'
),
ResourceConfigApi
.
listSimpleConfigByCategory
(
'gpu'
),
ResourceConfigApi
.
listSimpleConfigByCategory
(
'ram'
),
ResourceConfigApi
.
listSimpleConfigByCategory
(
'storage'
),
ResourceConfigApi
.
listSimpleConfigByCategory
(
'location'
)
])
this
.
cpuOptions
=
cpuRes
this
.
gpuOptions
=
gpuRes
this
.
ramOptions
=
ramRes
this
.
storageOptions
=
storageRes
this
.
locationOptions
=
locationRes
this
.
lastFetched
=
Date
.
now
()
return
this
.
allOptions
}
catch
(
error
)
{
console
.
error
(
'加载资源配置选项失败:'
,
error
)
throw
error
}
},
// 清除缓存
clearCache
()
{
this
.
cpuOptions
=
[]
this
.
gpuOptions
=
[]
this
.
ramOptions
=
[]
this
.
storageOptions
=
[]
this
.
locationOptions
=
[]
this
.
lastFetched
=
null
},
// 根据类型获取选项
getOptionsByType
(
type
:
'cpu'
|
'gpu'
|
'ram'
|
'storage'
|
'location'
)
{
return
this
[
type
+
'Options'
]
}
}
})
\ No newline at end of file
src/views/compute/resourcespu/ResourceSpuSelectDialog.vue
0 → 100644
View file @
1f847553
<
template
>
<Dialog
:title=
"dialogTitle"
v-model=
"dialogVisible"
:width=
"1000"
>
<!-- 搜索区域 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"资源名称"
prop=
"name"
>
<el-input
v-model=
"queryParams.name"
placeholder=
"请输入算力资源名称"
clearable
@
keyup
.
enter=
"handleQuery"
class=
"!w-200px"
/>
</el-form-item>
<el-form-item
label=
"CPU"
prop=
"cpu"
>
<el-select
v-model=
"queryParams.cpu"
placeholder=
"请选择CPU配置"
clearable
class=
"!w-160px"
>
<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-160px"
>
<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=
"categoryId"
>
<el-select
v-model=
"queryParams.categoryId"
placeholder=
"请选择资源分类"
clearable
class=
"!w-160px"
>
<el-option
v-for=
"category in categoryList"
:key=
"category.id"
:label=
"category.name"
:value=
"category.id"
/>
</el-select>
</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>
<!-- SPU列表 -->
<el-table
ref=
"tableRef"
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
@
row-click=
"handleRowClick"
height=
"400"
highlight-current-row
>
<el-table-column
width=
"55"
>
<template
#
default=
"
{ row }">
<el-radio
v-model=
"selectedRowId"
:label=
"row.id"
@
change=
"handleRadioChange(row)"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"算力资源"
min-width=
"200"
>
<
template
#
default=
"{ row }"
>
<div
class=
"flex items-center"
>
<el-image
fit=
"cover"
:src=
"row.picUrl"
class=
"flex-none w-40px h-40px rounded"
:preview-src-list=
"[row.picUrl]"
/>
<div
class=
"ml-3"
>
<div
class=
"font-medium"
>
{{
row
.
name
}}
</div>
<div
class=
"text-gray-500 text-sm"
>
{{
row
.
categoryName
}}
</div>
</div>
</div>
</
template
>
</el-table-column>
<el-table-column
label=
"硬件配置"
min-width=
"300"
>
<
template
#
default=
"{ row }"
>
<div
class=
"space-y-1"
>
<div
class=
"text-sm"
>
CPU:
{{
row
.
cpu
||
'-'
}}
</div>
<div
class=
"text-sm"
>
GPU:
{{
row
.
gpu
||
'-'
}}
</div>
<div
class=
"text-sm"
>
内存:
{{
row
.
ram
||
'-'
}}
</div>
<div
class=
"text-sm"
>
存储:
{{
row
.
storage
||
'-'
}}
</div>
</div>
</
template
>
</el-table-column>
<el-table-column
label=
"服务器所在地"
width=
"120"
prop=
"location"
/>
<el-table-column
label=
"库存"
width=
"80"
prop=
"stock"
/>
<el-table-column
label=
"销量"
width=
"80"
prop=
"sales"
/>
<el-table-column
label=
"状态"
width=
"80"
prop=
"status"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.COMPUTE_RESOURCE_SPU_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
</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"
:disabled=
"!selectedRows.length"
@
click=
"handleConfirm"
>
确定选择 (
{{
selectedRows
.
length
}}
)
</el-button>
</
template
>
</Dialog>
</template>
<
script
setup
lang=
"ts"
>
import
{
ref
,
reactive
,
computed
,
watch
}
from
'vue'
import
{
DICT_TYPE
}
from
"@/utils/dict"
import
{
ResourceSpuApi
,
ResourceSpu
}
from
'@/api/compute/resourcespu'
import
{
useResourceConfigStore
}
from
'@/store/modules/compute/hardwareConfig'
interface
Props
{
modelValue
:
boolean
title
?:
string
multiple
?:
boolean
// 默认只显示上架的SPU
defaultStatus
?:
number
}
interface
Emits
{
(
e
:
'update:modelValue'
,
value
:
boolean
):
void
(
e
:
'confirm'
,
selections
:
ResourceSpu
[]):
void
}
const
props
=
withDefaults
(
defineProps
<
Props
>
(),
{
title
:
'选择算力资源SPU'
,
multiple
:
false
,
defaultStatus
:
1
// 默认只显示上架的
})
const
emit
=
defineEmits
<
Emits
>
()
const
dialogVisible
=
computed
({
get
:
()
=>
props
.
modelValue
,
set
:
(
val
)
=>
emit
(
'update:modelValue'
,
val
)
})
const
dialogTitle
=
computed
(()
=>
props
.
title
)
const
resourceConfigStore
=
useResourceConfigStore
()
const
loading
=
ref
(
false
)
const
list
=
ref
<
ResourceSpu
[]
>
([])
const
total
=
ref
(
0
)
const
selectedRows
=
ref
<
ResourceSpu
[]
>
([])
const
selectedRowId
=
ref
<
number
|
null
>
(
null
)
const
tableRef
=
ref
()
const
categoryList
=
ref
<
any
[]
>
([])
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
name
:
undefined
,
cpu
:
undefined
,
gpu
:
undefined
,
ram
:
undefined
,
storage
:
undefined
,
categoryId
:
undefined
,
status
:
props
.
defaultStatus
})
const
queryFormRef
=
ref
()
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ResourceSpuApi
.
getResourceSpuPage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
.
value
?.
resetFields
()
queryParams
.
status
=
props
.
defaultStatus
handleQuery
()
}
/** 处理单选框变化 */
const
handleRadioChange
=
(
row
:
ResourceSpu
)
=>
{
selectedRows
.
value
=
[
row
]
selectedRowId
.
value
=
row
.
id
}
/** 处理行点击 */
const
handleRowClick
=
(
row
:
ResourceSpu
)
=>
{
selectedRowId
.
value
=
row
.
id
selectedRows
.
value
=
[
row
]
}
/** 确认选择 */
const
handleConfirm
=
()
=>
{
emit
(
'confirm'
,
selectedRows
.
value
)
dialogVisible
.
value
=
false
}
/** 打开弹窗时加载数据 */
const
handleOpen
=
async
()
=>
{
// 清除之前的选择状态
selectedRows
.
value
=
[]
selectedRowId
.
value
=
null
// 加载分类列表
const
categoryResponse
=
await
ResourceSpuApi
.
listSimpleCategory
()
categoryList
.
value
=
categoryResponse
// 预加载硬件配置
resourceConfigStore
.
loadConfigOptions
().
catch
(
error
=>
{
console
.
error
(
'预加载资源配置失败:'
,
error
)
})
// 加载列表数据
getList
()
}
// 监听弹窗打开
watch
(
()
=>
props
.
modelValue
,
(
val
)
=>
{
if
(
val
)
{
handleOpen
()
}
},
{
immediate
:
true
}
)
</
script
>
<
style
scoped
>
.text-orange-500
{
color
:
#f97316
;
}
</
style
>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment