ai_images/portal-ui/src/views/AssetGroupManage.vue

388 lines
8.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>