388 lines
8.8 KiB
Vue
388 lines
8.8 KiB
Vue
<template>
|
||
<div class="asset-group-page">
|
||
<section class="ag-panel">
|
||
<h3 class="ag-title">新增资源组</h3>
|
||
<div class="ag-form">
|
||
<div class="ag-field">
|
||
<label>名称</label>
|
||
<a-input v-model="createForm.name" placeholder="请输入资源组名称(<=64字符)" />
|
||
</div>
|
||
<div class="ag-field">
|
||
<label>描述</label>
|
||
<a-textarea
|
||
v-model="createForm.description"
|
||
:max-length="300"
|
||
show-word-limit
|
||
placeholder="请输入描述(<=300字符)" />
|
||
</div>
|
||
<div class="ag-field">
|
||
<label>GroupType</label>
|
||
<a-select v-model="createForm.groupType" :disabled="true">
|
||
<a-option value="AIGC">AIGC</a-option>
|
||
</a-select>
|
||
</div>
|
||
<div class="ag-actions">
|
||
<a-button type="primary" :loading="createLoading" @click="createGroup">新增</a-button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="ag-panel">
|
||
<h3 class="ag-title">查询资源组</h3>
|
||
<div class="ag-filter">
|
||
<div class="ag-field">
|
||
<label>名称</label>
|
||
<a-input v-model="filters.name" placeholder="按名称过滤" />
|
||
</div>
|
||
<div class="ag-field">
|
||
<label>GroupIds</label>
|
||
<a-input v-model="filters.groupIdsText" placeholder="多个ID用英文逗号分隔" />
|
||
</div>
|
||
<div class="ag-field">
|
||
<label>GroupType</label>
|
||
<a-select v-model="filters.groupType">
|
||
<a-option value="AIGC">AIGC</a-option>
|
||
</a-select>
|
||
</div>
|
||
<div class="ag-field">
|
||
<label>SortBy</label>
|
||
<a-select v-model="filters.sortBy">
|
||
<a-option value="CreateTime">CreateTime</a-option>
|
||
<a-option value="UpdateTime">UpdateTime</a-option>
|
||
</a-select>
|
||
</div>
|
||
<div class="ag-field">
|
||
<label>SortOrder</label>
|
||
<a-select v-model="filters.sortOrder">
|
||
<a-option value="Desc">Desc</a-option>
|
||
<a-option value="Asc">Asc</a-option>
|
||
</a-select>
|
||
</div>
|
||
<div class="ag-actions">
|
||
<a-button type="primary" :loading="listLoading" @click="search(1)">查询</a-button>
|
||
<a-button @click="resetFilters">重置</a-button>
|
||
</div>
|
||
</div>
|
||
|
||
<a-spin :loading="listLoading">
|
||
<div class="ag-total">总数:{{ totalCount }}</div>
|
||
<div class="ag-table-wrap">
|
||
<table class="ag-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Name</th>
|
||
<th>Description</th>
|
||
<th>GroupType</th>
|
||
<th>ProjectName</th>
|
||
<th>CreateTime</th>
|
||
<th>UpdateTime</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr v-for="item in items" :key="item.Id || item.id">
|
||
<td>{{ item.Id || item.id }}</td>
|
||
<td>{{ item.Name || item.name }}</td>
|
||
<td>{{ item.Description || item.description || '-' }}</td>
|
||
<td>{{ item.GroupType || item.groupType || '-' }}</td>
|
||
<td>{{ item.ProjectName || item.projectName || '-' }}</td>
|
||
<td>{{ item.CreateTime || item.createTime || '-' }}</td>
|
||
<td>{{ item.UpdateTime || item.updateTime || '-' }}</td>
|
||
<td>
|
||
<a-button
|
||
size="mini"
|
||
type="outline"
|
||
:loading="detailLoadingId === (item.Id || item.id)"
|
||
@click="getDetail(item)">
|
||
详情
|
||
</a-button>
|
||
</td>
|
||
</tr>
|
||
<tr v-if="!items.length">
|
||
<td colspan="8" class="ag-empty">暂无数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="ag-pagination">
|
||
<a-pagination
|
||
:total="totalCount"
|
||
:current="filters.pageNumber"
|
||
:page-size="filters.pageSize"
|
||
show-total
|
||
show-jumper
|
||
@change="search"
|
||
@page-size-change="onPageSizeChange" />
|
||
</div>
|
||
</a-spin>
|
||
</section>
|
||
|
||
<a-modal v-model:visible="detailVisible" title="资源组详情" :footer="false" width="680px">
|
||
<pre class="ag-detail">{{ prettyDetail }}</pre>
|
||
</a-modal>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'AssetGroupManage',
|
||
data() {
|
||
return {
|
||
createLoading: false,
|
||
listLoading: false,
|
||
detailLoadingId: '',
|
||
detailVisible: false,
|
||
detailData: null,
|
||
createForm: {
|
||
name: '',
|
||
description: '',
|
||
groupType: 'AIGC'
|
||
},
|
||
filters: {
|
||
name: '',
|
||
groupIdsText: '',
|
||
groupType: 'AIGC',
|
||
pageNumber: 1,
|
||
pageSize: 10,
|
||
sortBy: 'CreateTime',
|
||
sortOrder: 'Desc'
|
||
},
|
||
totalCount: 0,
|
||
items: []
|
||
}
|
||
},
|
||
computed: {
|
||
prettyDetail() {
|
||
return this.detailData ? JSON.stringify(this.detailData, null, 2) : '{}'
|
||
}
|
||
},
|
||
mounted() {
|
||
this.search(1)
|
||
},
|
||
methods: {
|
||
buildGroupIds() {
|
||
return String(this.filters.groupIdsText || '')
|
||
.split(',')
|
||
.map((x) => x.trim())
|
||
.filter((x) => !!x)
|
||
},
|
||
async createGroup() {
|
||
const name = String(this.createForm.name || '').trim()
|
||
if (!name) {
|
||
this.$message.error('请填写名称')
|
||
return
|
||
}
|
||
this.createLoading = true
|
||
try {
|
||
const res = await this.$axios({
|
||
url: 'api/portal/asset/post',
|
||
method: 'POST',
|
||
data: {
|
||
Name: name,
|
||
Description: String(this.createForm.description || '').trim(),
|
||
GroupType: 'AIGC'
|
||
}
|
||
})
|
||
if (res.code === 200) {
|
||
this.$message.success('新增成功')
|
||
this.createForm.name = ''
|
||
this.createForm.description = ''
|
||
this.search(1)
|
||
} else {
|
||
this.$message.error(res.msg || '新增失败')
|
||
}
|
||
} catch (e) {
|
||
this.$message.error(e?.message || '新增失败')
|
||
} finally {
|
||
this.createLoading = false
|
||
}
|
||
},
|
||
async search(page = this.filters.pageNumber) {
|
||
this.filters.pageNumber = Number(page) || 1
|
||
this.listLoading = true
|
||
try {
|
||
const payload = {
|
||
Filter: {
|
||
GroupType: this.filters.groupType || 'AIGC'
|
||
},
|
||
PageNumber: this.filters.pageNumber,
|
||
PageSize: this.filters.pageSize,
|
||
SortBy: this.filters.sortBy,
|
||
SortOrder: this.filters.sortOrder
|
||
}
|
||
const name = String(this.filters.name || '').trim()
|
||
if (name) payload.Filter.name = name
|
||
const ids = this.buildGroupIds()
|
||
if (ids.length) payload.Filter.GroupIds = ids
|
||
|
||
const res = await this.$axios({
|
||
url: 'api/portal/asset/list',
|
||
method: 'POST',
|
||
data: payload
|
||
})
|
||
const data = res.data || {}
|
||
this.totalCount = Number(data.TotalCount || 0)
|
||
this.items = Array.isArray(data.Items) ? data.Items : []
|
||
if (res.code !== 200) {
|
||
this.$message.error(res.msg || '查询失败')
|
||
}
|
||
} catch (e) {
|
||
this.$message.error(e?.message || '查询失败')
|
||
} finally {
|
||
this.listLoading = false
|
||
}
|
||
},
|
||
onPageSizeChange(size) {
|
||
this.filters.pageSize = Number(size) || 10
|
||
this.search(1)
|
||
},
|
||
resetFilters() {
|
||
this.filters = {
|
||
name: '',
|
||
groupIdsText: '',
|
||
groupType: 'AIGC',
|
||
pageNumber: 1,
|
||
pageSize: 10,
|
||
sortBy: 'CreateTime',
|
||
sortOrder: 'Desc'
|
||
}
|
||
this.search(1)
|
||
},
|
||
async getDetail(item) {
|
||
const id = item?.Id || item?.id
|
||
if (!id) return
|
||
this.detailLoadingId = id
|
||
try {
|
||
const res = await this.$axios({
|
||
url: 'api/portal/asset/get',
|
||
method: 'POST',
|
||
data: { Id: id }
|
||
})
|
||
if (res.code === 200) {
|
||
this.detailData = res.data || {}
|
||
this.detailVisible = true
|
||
} else {
|
||
this.$message.error(res.msg || '查询详情失败')
|
||
}
|
||
} catch (e) {
|
||
this.$message.error(e?.message || '查询详情失败')
|
||
} finally {
|
||
this.detailLoadingId = ''
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.asset-group-page {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16px;
|
||
padding: 18px;
|
||
background: #0a0b0d;
|
||
color: rgba(255, 255, 255, 0.88);
|
||
min-height: 100%;
|
||
}
|
||
|
||
.ag-panel {
|
||
background: rgba(22, 24, 30, 0.92);
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
border-radius: 14px;
|
||
padding: 14px;
|
||
}
|
||
|
||
.ag-title {
|
||
margin: 0 0 14px;
|
||
font-size: 15px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.ag-form,
|
||
.ag-filter {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(180px, 1fr));
|
||
gap: 12px;
|
||
}
|
||
|
||
.ag-field {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
}
|
||
|
||
.ag-field label {
|
||
font-size: 12px;
|
||
color: rgba(255, 255, 255, 0.65);
|
||
}
|
||
|
||
.ag-actions {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
gap: 8px;
|
||
}
|
||
|
||
.ag-total {
|
||
margin: 6px 0 10px;
|
||
font-size: 12px;
|
||
color: rgba(255, 255, 255, 0.65);
|
||
}
|
||
|
||
.ag-table-wrap {
|
||
overflow: auto;
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.ag-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.ag-table th,
|
||
.ag-table td {
|
||
padding: 10px;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||
text-align: left;
|
||
vertical-align: top;
|
||
}
|
||
|
||
.ag-table th {
|
||
color: rgba(255, 255, 255, 0.7);
|
||
font-weight: 600;
|
||
background: rgba(255, 255, 255, 0.02);
|
||
}
|
||
|
||
.ag-empty {
|
||
text-align: center;
|
||
color: rgba(255, 255, 255, 0.5);
|
||
}
|
||
|
||
.ag-pagination {
|
||
margin-top: 12px;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.ag-detail {
|
||
margin: 0;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
background: rgba(0, 0, 0, 0.35);
|
||
color: #d8f4f7;
|
||
max-height: 420px;
|
||
overflow: auto;
|
||
white-space: pre-wrap;
|
||
word-break: break-all;
|
||
}
|
||
|
||
@media (max-width: 960px) {
|
||
.ag-form,
|
||
.ag-filter {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|