diff --git a/portal-ui/src/lang/i18n.js b/portal-ui/src/lang/i18n.js index 6062337..b29b0da 100644 --- a/portal-ui/src/lang/i18n.js +++ b/portal-ui/src/lang/i18n.js @@ -1,13 +1,14 @@ import { createI18n } from 'vue-i18n' import Cookies from 'js-cookie' import zh_HK from '@/lang/zh_HK/index.js' +/** import en_US from '@/lang/en_US/index.js' -import es_ES from '@/lang/es_ES/index.js' +mport es_ES from '@/lang/es_ES/index.js' import pt_BR from '@/lang/pt_BR/index.js' import hi_IN from '@/lang/hi_IN/index.js' import ru_RU from '@/lang/ru_RU/index.js' import ar_SA from '@/lang/ar_SA/index.js' -import fr_FR from '@/lang/fr_FR/index.js' +import fr_FR from '@/lang/fr_FR/index.js'**/ // 多语言切换已禁用:全站固定繁体中文 let locale = 'zh_HK' @@ -15,13 +16,13 @@ let locale = 'zh_HK' /** 各语言在界面上的显示名称 */ export const LOCALE_NAMES = { zh_HK: '繁体中文', - en_US: 'English', +/** en_US: 'English', es_ES: 'Español', pt_BR: 'Português', hi_IN: 'हिन्दी', ru_RU: 'Русский', ar_SA: 'العربية', - fr_FR: 'Français' + fr_FR: 'Français'**/ } const i18n = createI18n({ @@ -29,13 +30,13 @@ const i18n = createI18n({ locale, messages: { zh_HK, - en_US, +/** en_US, es_ES, pt_BR, hi_IN, ru_RU, ar_SA, - fr_FR + fr_FR**/ } }) diff --git a/portal-ui/src/lang/index.js b/portal-ui/src/lang/index.js index e2712c4..de73253 100644 --- a/portal-ui/src/lang/index.js +++ b/portal-ui/src/lang/index.js @@ -1,7 +1,7 @@ -import en_USLocale from './en/index' +//import en_USLocale from './en/index' import zh_HKLocale from './zh_HK/index' export default { - en_US: en_USLocale, + //en_US: en_USLocale, zh_HK: zh_HKLocale } diff --git a/portal-ui/src/lang/zh_HK/route.js b/portal-ui/src/lang/zh_HK/route.js index d452cbc..7a96fc3 100644 --- a/portal-ui/src/lang/zh_HK/route.js +++ b/portal-ui/src/lang/zh_HK/route.js @@ -11,5 +11,6 @@ export default { help: '幫助中心', moneyInvite: '有獎邀請', assetGroupManage: '資源組管理', - assetManage: '素材管理' + assetManage: '素材管理', + generatedAssets: '作品库' } \ No newline at end of file diff --git a/portal-ui/src/layout/components/Menu.vue b/portal-ui/src/layout/components/Menu.vue index 9ff8af2..3727cf5 100644 --- a/portal-ui/src/layout/components/Menu.vue +++ b/portal-ui/src/layout/components/Menu.vue @@ -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', 'asset-group-manage', 'asset-manage'] +const SIDEBAR_ONLY_ROUTE_NAMES = ['video-gen', 'asset-group-manage', 'asset-manage', 'generatedAssets'] defineProps({ collapsed: Boolean diff --git a/portal-ui/src/router/index.js b/portal-ui/src/router/index.js index c3c96ae..15d0920 100644 --- a/portal-ui/src/router/index.js +++ b/portal-ui/src/router/index.js @@ -149,6 +149,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', diff --git a/portal-ui/src/views/GeneratedAssets.vue b/portal-ui/src/views/GeneratedAssets.vue new file mode 100644 index 0000000..8dc24b5 --- /dev/null +++ b/portal-ui/src/views/GeneratedAssets.vue @@ -0,0 +1,961 @@ + + + + + diff --git a/portal-ui/src/views/VideoGen.vue b/portal-ui/src/views/VideoGen.vue index 7d4b582..4ff0f6e 100644 --- a/portal-ui/src/views/VideoGen.vue +++ b/portal-ui/src/views/VideoGen.vue @@ -68,6 +68,18 @@ @click="regenerateFromTaskRow(row)"> 重新生成 +
{{ formatCreateTime(row.createTime) }}
@@ -118,6 +130,18 @@ @click="regenerateFromTaskRow(row)"> 重新生成 +
{{ formatCreateTime(row.createTime) }}
@@ -1132,8 +1156,9 @@ export default { // 展示用仍然可以是 https url,但提交 content/reference_url 要与 assetId 关联。 const firstPreview = attachments.find((x) => x?.mediaType === 'image') if (firstPreview) { + const au = String(firstPreview?.assetUrl || '').trim() const aid = String(firstPreview?.assetId || '').trim() - params.referenceUrl = aid ? `asset://${aid}` : firstPreview.url + params.referenceUrl = au || (aid ? `asset://${aid}` : firstPreview.url) } } @@ -1285,6 +1310,37 @@ export default { onCancel: () => resolve() }) }) + }, + + // 收藏/取消收藏 - 复用生成库接口 + async toggleFavorite(row) { + if (!row || !row.id) { + this.$message.error('无效的任务记录') + return + } + + const newIsTop = row.isTop === 'Y' ? 'N' : 'Y' + + try { + const res = await this.$axios({ + url: '/api/portal/assets/favorite', + method: 'POST', + data: { + id: row.id, + isTop: newIsTop + } + }) + + if (res.code === 200) { + // 更新本地数据 + row.isTop = newIsTop + this.$message.success(newIsTop === 'Y' ? '收藏成功' : '已取消收藏') + } else { + this.$message.error(res.msg || '操作失败') + } + } catch (err) { + this.$message.error(err?.message || '收藏操作失败') + } } } } @@ -2055,6 +2111,15 @@ export default { cursor: not-allowed; } +.favorite-btn { + color: #ff9800 !important; +} + +.favorite-btn.is-favorited { + color: #ffeb3b !important; + font-weight: 600; +} + .vg-chat-ai-top { display: flex; align-items: center; diff --git a/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalAssetsController.java b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalAssetsController.java new file mode 100644 index 0000000..0118864 --- /dev/null +++ b/web-api/ruoyi-admin/src/main/java/com/ruoyi/api/PortalAssetsController.java @@ -0,0 +1,146 @@ +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; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 门户-生成资产管理:展示当前用户的AI订单记录,支持收藏功能 + */ +@Api(tags = "门户-生成资产") +@RestController +@RequestMapping("/api/portal/assets") +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class PortalAssetsController extends BaseController { + + private final IAiOrderService aiOrderService; + + private final IAiUserService aiUserService; + + /** + * 查询当前用户的生成资产列表 + * 支持dept=true参数查询当前用户所在部门的所有作品 + */ + @GetMapping("/list") + @ApiOperation("查询生成资产列表(支持收藏筛选、时间范围、dept部门查询)") + public TableDataInfo list( + @RequestParam(required = false) String is_top, + @RequestParam(required = false) String beginTime, + @RequestParam(required = false) String endTime, + @RequestParam(required = false, defaultValue = "false") Boolean dept) { + + AiOrder query = new AiOrder(); + 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 + ", dept=" + dept); + + // 收藏状态筛选 - is_top: Y=已收藏, N=未收藏 + if (is_top != null && !is_top.trim().isEmpty()) { + String trimmedIsTop = is_top.trim(); + query.setIsTop(trimmedIsTop); + System.out.println("✓ 设置 isTop = [" + trimmedIsTop + "]"); + System.out.println(" query.getIsTop() = " + query.getIsTop()); + } else { + System.out.println("✗ is_top 参数为空或未提供,不设置筛选条件"); + } + + // 时间范围筛选 + if (beginTime != null && !beginTime.isEmpty()) { + query.getParams().put("beginTime", beginTime); + System.out.println("✓ 设置 beginTime = " + beginTime); + } + if (endTime != null && !endTime.isEmpty()) { + query.getParams().put("endTime", endTime); + System.out.println("✓ 设置 endTime = " + endTime); + } + + System.out.println("查询对象状态: isTop=" + query.getIsTop() + ", userId=" + query.getUserId() + ", params=" + query.getParams()); + System.out.println("=== PortalAssetsController DEBUG END ==="); + + startPage(); + List list = aiOrderService.selectAiOrderList(query); + System.out.println("PortalAssetsController - 查询返回 " + (list != null ? list.size() : 0) + " 条记录"); + return getDataTable(list); + } + + /** + * 收藏/取消收藏 + */ + @PostMapping("/favorite") + @ApiOperation("收藏或取消收藏生成资产") + public AjaxResult favorite(@RequestBody FavoriteRequest request) { + Long userId = SecurityUtils.getAiUserId(); + + // 验证订单归属 + AiOrder order = aiOrderService.selectAiOrderById(request.getId()); + if (order == null) { + return AjaxResult.error("订单不存在"); + } + if (!userId.equals(order.getUserId())) { + return AjaxResult.error("无权操作该订单"); + } + + // 更新收藏状态 + AiOrder update = new AiOrder(); + update.setId(request.getId()); + update.setIsTop(request.getIsTop()); + + int result = aiOrderService.updateAiOrder(update); + return toAjax(result); + } + + /** + * 收藏请求体 + */ + public static class FavoriteRequest { + private Long id; + private String isTop; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getIsTop() { + return isTop; + } + + public void setIsTop(String isTop) { + this.isTop = isTop; + } + } +} diff --git a/web-api/ruoyi-system/src/main/resources/mapper/system/AiBannerMapper.xml b/web-api/ruoyi-system/src/main/resources/mapper/system/AiBannerMapper.xml index 62b694e..472eb2f 100644 --- a/web-api/ruoyi-system/src/main/resources/mapper/system/AiBannerMapper.xml +++ b/web-api/ruoyi-system/src/main/resources/mapper/system/AiBannerMapper.xml @@ -94,7 +94,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" type = #{type}, jump_url = #{jumpUrl}, status = #{status}, - status = #{position}, + position = #{position}, where id = #{id} diff --git a/web-api/ruoyi-system/src/main/resources/mapper/system/AiOrderMapper.xml b/web-api/ruoyi-system/src/main/resources/mapper/system/AiOrderMapper.xml index 293cf2e..89122fb 100644 --- a/web-api/ruoyi-system/src/main/resources/mapper/system/AiOrderMapper.xml +++ b/web-api/ruoyi-system/src/main/resources/mapper/system/AiOrderMapper.xml @@ -49,6 +49,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and ao.result = #{result} and ao.status = #{status} and ao.source = #{source} + and ao.ext_status = #{extStatus} + + + AND ao.user_id IN (SELECT id FROM ai_user WHERE dept_id = #{params.deptId} AND del_flag = '0') + AND date_format(ao.create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')