feat: 作品库优化

This commit is contained in:
old burden 2026-04-13 17:14:44 +08:00
parent 8032c35cea
commit 5913ff8044
7 changed files with 207 additions and 62 deletions

View File

@ -12,6 +12,5 @@ export default {
moneyInvite: '有獎邀請',
assetGroupManage: '資源組管理',
assetManage: '素材管理',
thirdPartyAsset: '三方素材管理',
generatedAssets: '生成庫'
generatedAssets: '作品库'
}

View File

@ -47,7 +47,7 @@ import { constantRoutes } from '@/router/index'
import { generateTitle, generateLang } from '@/utils/i18n'
/** 左侧导航仅显示这些路由name 与 router/index.js 一致) */
const SIDEBAR_ONLY_ROUTE_NAMES = ['video-gen', 'third-party-asset', 'generated-assets']
const SIDEBAR_ONLY_ROUTE_NAMES = ['video-gen', 'asset-group-manage', 'asset-manage', 'generatedAssets']
defineProps({
collapsed: Boolean

View File

@ -169,6 +169,16 @@ export const constantRoutes = [{
permission: "pass",
icon: 'btn_video'
}
}, {
path: 'generated-assets',
name: 'generatedAssets',
component: () => import('@/views/GeneratedAssets.vue'),
meta: {
title: 'generatedAssets',
menuItem: true,
permission: "pass",
icon: 'btn_video'
}
}, {
path: 'recharge',
name: 'recharge',

View File

@ -1,9 +1,14 @@
<template>
<div class="generated-assets-page">
<div class="page-header">
<div class="panel-title">生成资产管理</div>
<div class="panel-title">作品库</div>
</div>
<div class="view-tabs">
<a-tabs v-model="activeTab" @change="handleTabChange" type="card">
<a-tab-pane key="personal" title="个人" />
<a-tab-pane key="department" title="部门" />
</a-tabs>
</div>
<!-- 查询区域 -->
<div class="query-section">
<div class="form-grid">
@ -145,8 +150,8 @@
<div class="value">{{ formatType(detailData.type) }}</div>
</div>
<div class="detail-row">
<div class="label">扣除金额</div>
<div class="value">{{ detailData.amount ? detailData.amount + ' 金币' : '-' }}</div>
<div class="label">扣除积分</div>
<div class="value">{{ detailData.amount ? detailData.amount + ' 积分' : '-' }}</div>
</div>
<div class="detail-row">
<div class="label">订单状态</div>
@ -298,6 +303,7 @@ export default {
beginTime: '',
endTime: ''
},
activeTab: 'personal', // 'personal', 'department'
pagination: {
total: 0,
pageNum: 1,
@ -324,6 +330,11 @@ export default {
pageNum: this.pagination.pageNum,
pageSize: this.pagination.pageSize
}
console.log("this.activeTab", this.activeTab)
// personal = , department = dept=true
if (this.activeTab === 'department') {
params.dept = true
}
// - 使 is_top
if (this.filters.isTop != null && String(this.filters.isTop) !== '') {
@ -333,7 +344,6 @@ export default {
} else {
params.is_top = String(this.filters.isTop)
}
console.log('传递 is_top 参数:', params.is_top)
}
if (this.filters.beginTime) {
params.beginTime = this.formatDate(this.filters.beginTime)
@ -342,7 +352,6 @@ export default {
params.endTime = this.formatDate(this.filters.endTime)
}
console.log('查询参数:', params) //
this.$axios({
url: 'api/portal/assets/list',
@ -370,6 +379,14 @@ export default {
this.filters.endTime = ''
this.search(1)
},
// Tabs personal/
handleTabChange(tabKey) {
if (tabKey) {
this.activeTab = tabKey
}
this.pagination.pageNum = 1
this.search(1)
},
//
changePage(page) {
this.pagination.pageNum = page
@ -697,12 +714,13 @@ export default {
padding: 40px 0;
}
/* 详情弹窗 - label:value 形式 */
/* 详情弹窗 - label:value 形式(深色背景白字) */
.detail-content {
padding: 20px;
font-size: 14px;
background: #1f2329;
border-radius: 8px;
background: #1a1f2e;
color: rgba(255, 255, 255, 0.95);
min-height: 100%;
.detail-form {
display: flex;
@ -711,27 +729,26 @@ export default {
}
.detail-group {
background: rgba(255, 255, 255, 0.95);
border: 1px solid rgba(0, 0, 0, 0.1);
background: rgba(22, 24, 30, 0.8);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 18px;
color: #1a1f2e;
padding: 16px;
}
.group-title {
font-size: 15px;
font-weight: 600;
color: #0066cc;
margin-bottom: 16px;
padding-bottom: 10px;
border-bottom: 2px solid #e6f0ff;
color: #00cae0;
margin-bottom: 14px;
padding-bottom: 8px;
border-bottom: 1px solid rgba(0, 202, 224, 0.2);
}
.detail-row {
display: flex;
align-items: flex-start;
padding: 10px 0;
border-bottom: 1px solid #e8e8e8;
padding: 8px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
&:last-child {
border-bottom: none;
@ -739,34 +756,30 @@ export default {
}
.label {
width: 110px;
width: 100px;
flex-shrink: 0;
color: #555;
font-weight: 500;
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
padding-top: 3px;
padding-top: 2px;
}
.value {
flex: 1;
color: #222;
color: rgba(255, 255, 255, 0.95);
word-break: break-all;
line-height: 1.6;
font-size: 13.5px;
line-height: 1.5;
&.long-text {
max-height: 120px;
max-height: 110px;
overflow-y: auto;
background: #f8f9fa;
padding: 12px;
background: rgba(0, 0, 0, 0.3);
padding: 10px;
border-radius: 6px;
border: 1px solid #e0e0e0;
font-size: 13px;
line-height: 1.5;
}
.text-muted {
color: #888;
color: rgba(255, 255, 255, 0.45);
}
}
@ -781,7 +794,6 @@ export default {
max-width: 420px;
border-radius: 8px;
background: #000;
border: 1px solid #ddd;
}
.detail-image {
@ -789,14 +801,12 @@ export default {
max-height: 260px;
border-radius: 8px;
cursor: pointer;
border: 2px solid #e0e0e0;
border: 1px solid rgba(255, 255, 255, 0.1);
transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
&:hover {
transform: scale(1.02);
border-color: #0066cc;
box-shadow: 0 4px 16px rgba(0,102,204,0.2);
transform: scale(1.03);
box-shadow: 0 0 0 3px rgba(0, 202, 224, 0.3);
}
&.small {
@ -805,32 +815,84 @@ export default {
}
.result-text {
color: #666;
color: rgba(255, 255, 255, 0.5);
font-style: italic;
padding: 14px;
background: #f5f5f5;
padding: 12px;
background: rgba(255, 255, 255, 0.05);
border-radius: 6px;
border-left: 4px solid #999;
}
.json-block {
background: #f8f9fa;
color: #1a2a44;
padding: 16px;
background: #1a1f2e;
color: #a5d6ff;
padding: 14px;
border-radius: 8px;
font-size: 12.5px;
max-height: 260px;
font-size: 12px;
max-height: 220px;
overflow: auto;
white-space: pre;
font-family: 'Consolas', 'Courier New', monospace;
line-height: 1.45;
border: 1px solid #d0d7e0;
max-width: 70%;
box-shadow: inset 0 2px 6px rgba(0,0,0,0.05);
font-family: 'Consolas', monospace;
line-height: 1.4;
border: 1px solid rgba(165, 214, 255, 0.1);
}
}
//
// Tabs - Arco Design Vue + UI
.view-tabs {
margin-bottom: 20px;
padding: 0 4px;
::v-deep(.arco-tabs) {
.arco-tabs-nav {
background: rgba(22, 24, 30, 0.98) !important;
border: 1px solid rgba(255, 255, 255, 0.12) !important;
border-radius: 12px !important;
padding: 6px !important;
margin-bottom: 0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
.arco-tabs-tab {
color: rgba(255, 255, 255, 0.85) !important;
margin: 0 4px !important;
padding: 10px 28px !important;
border-radius: 8px !important;
transition: all 0.2s ease !important;
font-size: 14px;
font-weight: 500;
border: 1px solid transparent !important;
}
.arco-tabs-tab:hover {
color: white !important;
background: rgba(0, 102, 204, 0.25) !important;
border-color: rgba(0, 102, 204, 0.3) !important;
}
.arco-tabs-tab-active {
color: white !important;
background: #0066cc !important;
border-color: #0066cc !important;
font-weight: 600 !important;
box-shadow: 0 4px 15px rgba(0, 102, 204, 0.5) !important;
}
.arco-tabs-ink-bar {
display: none !important;
}
// tabs
.arco-tabs-content {
display: none !important;
}
}
}
.tabs-field {
grid-column: span 2;
}
.preview-content {
display: flex;
justify-content: center;
@ -848,4 +910,51 @@ export default {
border-radius: 8px;
}
}
/* 作品详情弹窗深色底样式 - 严格符合 GeneratedAssets.vue 深色主题(适配 Arco Design */
::v-deep(.arco-modal) {
.arco-modal-content {
background-color: #1a1f2e !important;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.arco-modal-header {
background: transparent !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
padding: 20px 24px 16px;
}
.arco-modal-title {
color: rgba(255, 255, 255, 0.95) !important;
font-size: 17px;
font-weight: 600;
}
.arco-modal-close {
color: rgba(255, 255, 255, 0.65) !important;
top: 18px;
right: 20px;
&:hover {
color: #fff !important;
background: rgba(255, 255, 255, 0.1);
}
}
.arco-modal-body {
padding: 0 !important;
background: transparent;
color: rgba(255, 255, 255, 0.9);
}
// detail-content
.detail-content {
background: #1a1f2e !important;
color: rgba(255, 255, 255, 0.95) !important;
padding: 20px !important;
min-height: 200px;
}
}
</style>

View File

@ -2,8 +2,10 @@ package com.ruoyi.api;
import com.ruoyi.ai.domain.AiOrder;
import com.ruoyi.ai.service.IAiOrderService;
import com.ruoyi.ai.service.IAiUserService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.AiUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import io.swagger.annotations.Api;
@ -25,22 +27,43 @@ public class PortalAssetsController extends BaseController {
private final IAiOrderService aiOrderService;
private final IAiUserService aiUserService;
/**
* 查询当前用户的生成资产列表
* 支持dept=true参数查询当前用户所在部门的所有作品
*/
@GetMapping("/list")
@ApiOperation("查询生成资产列表(支持收藏筛选和时间范围")
@ApiOperation("查询生成资产列表(支持收藏筛选、时间范围、dept部门查询")
public TableDataInfo list(
@RequestParam(required = false) String is_top,
@RequestParam(required = false) String beginTime,
@RequestParam(required = false) String endTime) {
@RequestParam(required = false) String endTime,
@RequestParam(required = false, defaultValue = "false") Boolean dept) {
AiOrder query = new AiOrder();
// 只查询当前用户的数据
query.setUserId(SecurityUtils.getAiUserId());
Long currentUserId = SecurityUtils.getAiUserId();
if (Boolean.TRUE.equals(dept)) {
// 查询当前用户所在部门的所有作品包括自己
AiUser currentUser = aiUserService.selectAiUserById(currentUserId);
if (currentUser != null && currentUser.getDeptId() != null) {
// 通过部门查询所有用户在XML中通过IN子查询实现
query.getParams().put("deptId", currentUser.getDeptId());
System.out.println("=== 查询部门作品deptId=" + currentUser.getDeptId() + " ===");
} else {
// 兜底只查个人
query.setUserId(currentUserId);
System.out.println("=== 部门ID为空兜底查询个人作品 ===");
}
} else {
// 默认只查询当前用户的数据
query.setUserId(currentUserId);
System.out.println("=== 查询个人作品 userId=" + currentUserId + " ===");
}
System.out.println("=== PortalAssetsController DEBUG START ===");
System.out.println("收到参数: is_top=" + is_top + ", beginTime=" + beginTime + ", endTime=" + endTime);
System.out.println("收到参数: is_top=" + is_top + ", beginTime=" + beginTime + ", endTime=" + endTime + ", dept=" + dept);
// 收藏状态筛选 - is_top: Y=已收藏, N=未收藏
if (is_top != null && !is_top.trim().isEmpty()) {
@ -62,7 +85,6 @@ public class PortalAssetsController extends BaseController {
System.out.println("✓ 设置 endTime = " + endTime);
}
System.out.println("查询对象状态: isTop=" + query.getIsTop() + ", params=" + query.getParams());
System.out.println("=== PortalAssetsController DEBUG END ===");
startPage();

View File

@ -94,7 +94,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="type != null">type = #{type},</if>
<if test="jumpUrl != null">jump_url = #{jumpUrl},</if>
<if test="status != null">status = #{status},</if>
<if test="position != null">status = #{position},</if>
<if test="position != null">position = #{position},</if>
</trim>
where id = #{id}
</update>

View File

@ -50,6 +50,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="status != null "> and ao.status = #{status}</if>
<if test="extStatus != null "> and ao.ext_status = #{extStatus}</if>
<if test="source != null "> and ao.source = #{source}</if>
<if test="extStatus != null "> and ao.ext_status = #{extStatus}</if>
<if test="params.deptId != null">
<!-- 查询部门下所有用户的作品 -->
AND ao.user_id IN (SELECT id FROM ai_user WHERE dept_id = #{params.deptId} AND del_flag = '0')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(ao.create_time,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
</if>