diff --git a/backend/design/AGENTS.md b/backend/design/AGENTS.md deleted file mode 100644 index cbc02ff..0000000 --- a/backend/design/AGENTS.md +++ /dev/null @@ -1,227 +0,0 @@ -# AGENTS.md(Backend) - -## 一、项目定位 - -这是一个 **智能语音识别与总结系统的后台服务**,主要职责包括: - -* 后台管理(用户 / 角色 / 权限) -* 设备接入与管理 -* 任务调度与数据管理 -* 对接外部 AI 转录服务(仅接口调用,不实现 AI) - -本模块为 **Java 后端服务**,不包含前端页面逻辑。 - ---- - -## 二、技术栈(必须遵守) - -* Java: **17** -* Spring Boot: **3.x** -* Web: Spring MVC -* Security: **Spring Security + JWT** -* ORM: **MyBatis / MyBatis-Plus(禁止 Hibernate / JPA)** -* Database: **PostgreSQL** -* Cache: Redis -* Build Tool: Maven - -⚠️ 禁止引入与以上技术选型冲突的框架与中间件。 - ---- - -## 三、架构与包结构约定 - -### 基础包结构 - -``` -com.xxx.project -├── common # 通用工具、常量、异常 -├── config # Spring / 安全 / Web 配置 -├── security # JWT、Filter、Security 配置 -├── auth # 登录、鉴权 -├── user # 用户管理 -├── role # 角色管理 -├── permission # 权限管理 -├── device # 设备管理 -├── dict # 字典/配置 -└── task # 转录/业务任务 -``` - -### 分层规范 - -* Controller:仅负责协议与参数校验 -* Service:业务编排与事务边界 -* Mapper:只写数据库访问 -* DTO/VO:显式数据模型,不透传实体 -* 禁止 Controller 直接调用 Mapper - ---- - -## 四、角色与定位 - -你是一位**务实型后端开发者 Agent**,目标是: - -> 以最清晰、最朴素、最可验证的方式交付可工作的 Java 服务。 -> 基本原则 -> 1. 生成内容必须完整、可运行、不可省略。 -> 2. 不允许伪代码。 -> 3. 不允许使用"示例代码"字样。 -> 4. 不允许省略 import。 -> 5. 不允许省略异常处理。 -> 6. 所有写操作必须考虑事务控制。 -> 7. 所有删除操作必须为逻辑删除(is_deleted)。 -> 8. 所有表必须包含: -> - created_at TIMESTAMP(6) -> - updated_at TIMESTAMP(6) -> - is_deleted SMALLINT DEFAULT 0 -### 核心理念 - -* 清晰的意图胜于巧妙的代码 -* 显而易见 > 精妙复杂 -* 奥卡姆剃刀:不应无必要地增加复杂度 -* 组合优于继承 -* 接口优于单例 -* 显式数据流优于隐式魔法 - -### 风格约束 - -* 准确、简洁、可维护 -* 小修改**不输出摘要** -* 不炫技、不做“聪明设计” - ---- - -## 五、工作流程(强制) - -### 5.1 规划阶段(复杂任务必需) - -### 行为约束 -1. 在执行任何修改前,必须**阅读并遵守**本项目的设计文档(位于 `docs/design/`)。 -2. 所有功能改动都必须更新设计文档 -3. 遵循代码风格、目录结构和 Git 工作流规则 - -需求必须先创建: - -`IMPLEMENTATION_PLAN.md` - -``` -## Stage N: [Name] - -Goal: -- 明确可交付物 - -Success Criteria: -- 可测试的验收标准 - -Tests: -- 具体测试用例 - -Status: -- Not Started | In Progress | Complete -``` - -规则: - -* 3–5 个阶段 -* 未完成前不得删除 -* 未规划禁止直接写实现 - ---- - -### 5.2 实现循环(TDD Only) - -严格顺序: - -1. 理解 - - * 查找 ≥3 个相似实现 - * 遵循现有项目约定 - -2. 测试(Red) - - * 先写失败测试 - * 只描述行为 - -3. 实现(Green) - - * 最小代码通过 - * 拒绝过度设计 - -4. 重构(Refactor) - - * 在测试保护下清理 - ---- - -### 5.3 三次机会规则 - -同一问题最多尝试 **3 次**: - -若失败,必须停止并输出: - -* 已尝试操作 -* 完整错误 -* 2–3 个相似方案 -* 根本性反思 - ---- -### 5.4. 变更同步规则 - -当数据库结构发生变更时,必须同步生成: - -- Entity -- Mapper -- Service -- Controller -- DTO -- VO -- 前端类型定义 -- API 封装 -- 权限校验调整 - 同步修改backend/design/db_schema.md和backend/design/db_schema_pgsql.sql -禁止只修改数据库而不同步代码。 - - -## 六、质量关卡(DoD) - -交付前必须: - -* 可编译 -* 通过全部测试 -* 新功能必有测试 -* 无警告 -* 不得随意引入新依赖 - ---- - -## 七、后端设计准则 - -* 显式优于隐式 -* 数据流可追踪 -* 依赖可替换 -* 行为可测试 -* 错误可观测 - -**禁止:** - -* 魔法单例 -* 全局状态 -* 过早抽象 -* 与技术栈冲突的框架 - ---- - -## 八、接口与安全规范 - -* 统一返回:`Result` -* 必须参数校验 -* 认证:JWT -* 权限:Spring Security -* 日志:结构化 -* 异常:统一处理 - ---- - -**一句话原则:** - -> 用最朴素的设计 + 最小的改动 + 最确定的测试, -> 构建显而易见正确的 Java 后端。 diff --git a/backend/src/main/java/com/imeeting/dto/biz/HotWordDTO.java b/backend/src/main/java/com/imeeting/dto/biz/HotWordDTO.java index f6bb7ce..d0302e9 100644 --- a/backend/src/main/java/com/imeeting/dto/biz/HotWordDTO.java +++ b/backend/src/main/java/com/imeeting/dto/biz/HotWordDTO.java @@ -9,10 +9,10 @@ import java.util.List; @Schema(description = "热词请求参数") public class HotWordDTO { - @Schema(description = "热词 ID") + @Schema(description = "热词ID") private Long id; - @Schema(description = "租户 ID,平台管理员可传 0 表示平台范围") + @Schema(description = "租户ID,平台管理员可传0表示平台范围") private Long tenantId; @Schema(description = "热词内容") @@ -27,7 +27,7 @@ public class HotWordDTO { @Schema(description = "热词分类") private String category; - @Schema(description = "所属热词组 ID") + @Schema(description = "所属热词组ID") private Long hotWordGroupId; @Schema(description = "权重") diff --git a/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupDTO.java b/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupDTO.java index 4e442ad..415f566 100644 --- a/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupDTO.java +++ b/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupDTO.java @@ -7,15 +7,18 @@ import lombok.Data; @Schema(description = "热词组请求参数") public class HotWordGroupDTO { - @Schema(description = "热词组 ID") + @Schema(description = "热词组ID") private Long id; - @Schema(description = "租户 ID,平台管理员可传 0 表示平台范围") + @Schema(description = "租户ID,平台管理员可传0表示平台范围") private Long tenantId; @Schema(description = "热词组名称") private String groupName; + @Schema(description = "排序值,越小越靠前") + private Integer sortOrder; + @Schema(description = "状态:1-启用,0-禁用") private Integer status; diff --git a/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupVO.java b/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupVO.java index 545780b..e0b7220 100644 --- a/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupVO.java +++ b/backend/src/main/java/com/imeeting/dto/biz/HotWordGroupVO.java @@ -9,21 +9,24 @@ import java.time.LocalDateTime; @Schema(description = "热词组信息") public class HotWordGroupVO { - @Schema(description = "热词组 ID") + @Schema(description = "热词组ID") private Long id; - @Schema(description = "租户 ID") + @Schema(description = "租户ID") private Long tenantId; @Schema(description = "热词组名称") private String groupName; - @Schema(description = "创建人 ID") + @Schema(description = "创建者ID") private Long creatorId; @Schema(description = "状态:1-启用,0-禁用") private Integer status; + @Schema(description = "排序值,越小越靠前") + private Integer sortOrder; + @Schema(description = "组内热词数量") private Long hotWordCount; diff --git a/backend/src/main/java/com/imeeting/dto/biz/HotWordVO.java b/backend/src/main/java/com/imeeting/dto/biz/HotWordVO.java index 24c017e..a24dcaf 100644 --- a/backend/src/main/java/com/imeeting/dto/biz/HotWordVO.java +++ b/backend/src/main/java/com/imeeting/dto/biz/HotWordVO.java @@ -10,7 +10,7 @@ import java.util.List; @Schema(description = "热词信息") public class HotWordVO { - @Schema(description = "热词 ID") + @Schema(description = "热词ID") private Long id; @Schema(description = "热词内容") @@ -22,7 +22,7 @@ public class HotWordVO { @Schema(description = "是否公开,当前固定为公开") private Integer isPublic; - @Schema(description = "创建人 ID") + @Schema(description = "创建者ID") private Long creatorId; @Schema(description = "匹配策略") @@ -31,7 +31,7 @@ public class HotWordVO { @Schema(description = "热词分类") private String category; - @Schema(description = "所属热词组 ID") + @Schema(description = "所属热词组ID") private Long hotWordGroupId; @Schema(description = "所属热词组名称") diff --git a/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateDTO.java b/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateDTO.java index d239ef8..20725f4 100644 --- a/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateDTO.java +++ b/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateDTO.java @@ -31,6 +31,9 @@ public class PromptTemplateDTO { @Schema(description = "绑定热词组 ID") private Long hotWordGroupId; + @Schema(description = "鎺掑簭鍊硷紝瓒婂皬瓒婇潬鍓?") + private Integer sortOrder; + @Schema(description = "模板内容") private String promptContent; diff --git a/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateVO.java b/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateVO.java index 3dbbe4e..68a5a9e 100644 --- a/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateVO.java +++ b/backend/src/main/java/com/imeeting/dto/biz/PromptTemplateVO.java @@ -30,6 +30,8 @@ public class PromptTemplateVO { private String hotWordGroupName; @Schema(description = "绑定热词列表") private List hotWords; + @Schema(description = "排序字段") + private Integer sortOrder; @Schema(description = "使用次数") private Integer usageCount; @Schema(description = "提示词正文") diff --git a/backend/src/main/java/com/imeeting/entity/biz/HotWord.java b/backend/src/main/java/com/imeeting/entity/biz/HotWord.java index 79cebd2..b62a987 100644 --- a/backend/src/main/java/com/imeeting/entity/biz/HotWord.java +++ b/backend/src/main/java/com/imeeting/entity/biz/HotWord.java @@ -27,7 +27,7 @@ public class HotWord extends BaseEntity { @Schema(description = "是否公共热词") private Integer isPublic; - @Schema(description = "创建人ID") + @Schema(description = "创建者ID") private Long creatorId; @TableField(typeHandler = JacksonTypeHandler.class) @@ -40,7 +40,7 @@ public class HotWord extends BaseEntity { @Schema(description = "热词分类") private String category; - @Schema(description = "所属热词组 ID") + @Schema(description = "所属热词组ID") private Long hotWordGroupId; @Schema(description = "权重") diff --git a/backend/src/main/java/com/imeeting/entity/biz/HotWordGroup.java b/backend/src/main/java/com/imeeting/entity/biz/HotWordGroup.java index 333cde7..ea4bad8 100644 --- a/backend/src/main/java/com/imeeting/entity/biz/HotWordGroup.java +++ b/backend/src/main/java/com/imeeting/entity/biz/HotWordGroup.java @@ -15,15 +15,18 @@ import lombok.EqualsAndHashCode; public class HotWordGroup extends BaseEntity { @TableId(value = "id", type = IdType.AUTO) - @Schema(description = "热词组 ID") + @Schema(description = "热词组ID") private Long id; @Schema(description = "热词组名称") private String groupName; - @Schema(description = "创建人 ID") + @Schema(description = "创建者ID") private Long creatorId; + @Schema(description = "排序值,越小越靠前") + private Integer sortOrder; + @Schema(description = "备注") private String remark; } diff --git a/backend/src/main/java/com/imeeting/entity/biz/PromptTemplate.java b/backend/src/main/java/com/imeeting/entity/biz/PromptTemplate.java index d24cd8b..1578fe3 100644 --- a/backend/src/main/java/com/imeeting/entity/biz/PromptTemplate.java +++ b/backend/src/main/java/com/imeeting/entity/biz/PromptTemplate.java @@ -39,6 +39,9 @@ public class PromptTemplate extends BaseEntity { @Schema(description = "绑定热词组 ID") private Long hotWordGroupId; + @Schema(description = "鎺掑簭鍊硷紝瓒婂皬瓒婇潬鍓?") + private Integer sortOrder; + @Schema(description = "使用次数") private Integer usageCount; diff --git a/backend/src/main/java/com/imeeting/service/biz/impl/HotWordGroupServiceImpl.java b/backend/src/main/java/com/imeeting/service/biz/impl/HotWordGroupServiceImpl.java index 0fc4909..5961736 100644 --- a/backend/src/main/java/com/imeeting/service/biz/impl/HotWordGroupServiceImpl.java +++ b/backend/src/main/java/com/imeeting/service/biz/impl/HotWordGroupServiceImpl.java @@ -27,6 +27,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class HotWordGroupServiceImpl extends ServiceImpl implements HotWordGroupService { + private static final int DEFAULT_SORT_ORDER = 0; + private final HotWordMapper hotWordMapper; private final PromptTemplateMapper promptTemplateMapper; @@ -84,6 +86,7 @@ public class HotWordGroupServiceImpl extends ServiceImpl wrapper = new LambdaQueryWrapper() .like(name != null && !name.isBlank(), HotWordGroup::getGroupName, name) .eq(status != null, HotWordGroup::getStatus, status) + .orderByAsc(HotWordGroup::getSortOrder) .orderByDesc(HotWordGroup::getCreatedAt); wrapper.eq(tenantId != null, HotWordGroup::getTenantId, tenantId); Page page = this.page(new Page<>(current, size), wrapper); @@ -101,6 +104,7 @@ public class HotWordGroupServiceImpl extends ServiceImpl listVisibleOptions(Long tenantId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .eq(HotWordGroup::getStatus, 1) + .orderByAsc(HotWordGroup::getSortOrder) .orderByDesc(HotWordGroup::getCreatedAt); wrapper.eq(tenantId != null, HotWordGroup::getTenantId, tenantId); List groups = this.list(wrapper); @@ -129,6 +133,7 @@ public class HotWordGroupServiceImpl extends ServiceImpl impl } return vo; } + } diff --git a/backend/src/main/java/com/imeeting/service/biz/impl/MeetingRuntimeProfileResolverImpl.java b/backend/src/main/java/com/imeeting/service/biz/impl/MeetingRuntimeProfileResolverImpl.java index 157c170..748c6f6 100644 --- a/backend/src/main/java/com/imeeting/service/biz/impl/MeetingRuntimeProfileResolverImpl.java +++ b/backend/src/main/java/com/imeeting/service/biz/impl/MeetingRuntimeProfileResolverImpl.java @@ -209,6 +209,7 @@ public class MeetingRuntimeProfileResolverImpl implements MeetingRuntimeProfileR .eq(PromptTemplate::getIsSystem, 1) .and(wrapper -> wrapper.eq(PromptTemplate::getTenantId, tenantId).or().eq(PromptTemplate::getTenantId, 0L)) .orderByDesc(PromptTemplate::getTenantId) + .orderByAsc(PromptTemplate::getSortOrder) .orderByDesc(PromptTemplate::getCreatedAt) .last("LIMIT 1")); if (template != null) { @@ -220,6 +221,7 @@ public class MeetingRuntimeProfileResolverImpl implements MeetingRuntimeProfileR .and(wrapper -> wrapper.eq(PromptTemplate::getTenantId, tenantId).or().eq(PromptTemplate::getTenantId, 0L)) .orderByDesc(PromptTemplate::getTenantId) .orderByDesc(PromptTemplate::getIsSystem) + .orderByAsc(PromptTemplate::getSortOrder) .orderByDesc(PromptTemplate::getCreatedAt) .last("LIMIT 1")); if (template == null) { diff --git a/backend/src/main/java/com/imeeting/service/biz/impl/PromptTemplateServiceImpl.java b/backend/src/main/java/com/imeeting/service/biz/impl/PromptTemplateServiceImpl.java index e1738cb..cf43c47 100644 --- a/backend/src/main/java/com/imeeting/service/biz/impl/PromptTemplateServiceImpl.java +++ b/backend/src/main/java/com/imeeting/service/biz/impl/PromptTemplateServiceImpl.java @@ -29,6 +29,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class PromptTemplateServiceImpl extends ServiceImpl implements PromptTemplateService { + private static final int DEFAULT_SORT_ORDER = 0; + private final PromptTemplateUserConfigMapper userConfigMapper; private final HotWordGroupMapper hotWordGroupMapper; private final HotWordService hotWordService; @@ -71,6 +73,7 @@ public class PromptTemplateServiceImpl extends ServiceImpl page = this.page(new Page<>(current, size), wrapper); @@ -256,11 +259,16 @@ public class PromptTemplateServiceImpl extends ServiceImpl hotWordGroupMap) { PromptTemplateVO vo = new PromptTemplateVO(); vo.setId(entity.getId()); @@ -275,6 +283,7 @@ public class PromptTemplateServiceImpl extends ServiceImpl + + + + + diff --git a/frontend/src/api/business/hotword.ts b/frontend/src/api/business/hotword.ts index 7c71380..205914c 100644 --- a/frontend/src/api/business/hotword.ts +++ b/frontend/src/api/business/hotword.ts @@ -1,4 +1,4 @@ -import http from "../http"; +import http from "../http"; export interface HotWordVO { id: number; @@ -110,3 +110,6 @@ export const getPinyinSuggestion = (word: string) => { { params: { word } } ); }; + + + diff --git a/frontend/src/api/business/hotwordGroup.ts b/frontend/src/api/business/hotwordGroup.ts index 4461fb9..701547b 100644 --- a/frontend/src/api/business/hotwordGroup.ts +++ b/frontend/src/api/business/hotwordGroup.ts @@ -6,6 +6,7 @@ export interface HotWordGroupVO { groupName: string; creatorId: number; status: number; + sortOrder?: number; hotWordCount: number; remark?: string; createdAt: string; @@ -15,6 +16,7 @@ export interface HotWordGroupVO { export interface HotWordGroupDTO { id?: number; groupName: string; + sortOrder?: number; status: number; remark?: string; } diff --git a/frontend/src/api/business/prompt.ts b/frontend/src/api/business/prompt.ts index 8128247..1f8d9e0 100644 --- a/frontend/src/api/business/prompt.ts +++ b/frontend/src/api/business/prompt.ts @@ -12,6 +12,7 @@ export interface PromptTemplateVO { hotWordGroupId?: number; hotWordGroupName?: string; hotWords?: string[]; + sortOrder?: number; usageCount: number; promptContent: string; status: number; @@ -28,6 +29,7 @@ export interface PromptTemplateDTO { isSystem: number; tags?: string[]; hotWordGroupId?: number; + sortOrder?: number; promptContent: string; status: number; remark?: string; diff --git a/frontend/src/locales/en-US.json b/frontend/src/locales/en-US.json index 57f4432..9ea44bc 100644 --- a/frontend/src/locales/en-US.json +++ b/frontend/src/locales/en-US.json @@ -276,6 +276,7 @@ "botCredentialHint": "Use this credential pair to access /mcp with X-Bot-Id and X-Bot-Secret.", "botCredentialHintDesc": "The secret is shown only after generation. Store it securely after copying.", "botBindStatus": "Binding Status", + "mcpAddress": "MCP Address", "botBound": "Bound", "botUnbound": "Not Generated", "botSecretHidden": "Hidden. Generate or reset to get a new secret.", diff --git a/frontend/src/locales/zh-CN.json b/frontend/src/locales/zh-CN.json index aa2cf32..0c958f2 100644 --- a/frontend/src/locales/zh-CN.json +++ b/frontend/src/locales/zh-CN.json @@ -276,6 +276,7 @@ "botCredentialHint": "使用这组凭证通过 X-Bot-Id 和 X-Bot-Secret 访问 /mcp。", "botCredentialHintDesc": "Secret 只会在生成后显示一次,请复制后妥善保管。", "botBindStatus": "绑定状态", + "mcpAddress": "MCP 地址", "botBound": "已绑定", "botUnbound": "未生成", "botSecretHidden": "已隐藏。如需查看新的 Secret,请重新生成。", diff --git a/frontend/src/pages/business/AiModels.tsx b/frontend/src/pages/business/AiModels.tsx index 2fe9b94..38dbb66 100644 --- a/frontend/src/pages/business/AiModels.tsx +++ b/frontend/src/pages/business/AiModels.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from "react"; +import React, { useEffect, useMemo, useRef, useState } from "react"; import { App, AutoComplete, @@ -238,7 +238,7 @@ const AiModels: React.FC = () => { const values = form.getFieldsValue(["provider", "baseUrl", "apiKey"]); if (!values.provider || !values.baseUrl) { - message.warning("请先填写提供商和 Base URL"); + message.warning("璇峰厛濉啓鎻愪緵鍟嗗拰 Base URL"); return; } @@ -248,7 +248,7 @@ const AiModels: React.FC = () => { const rawModels = (res as any)?.data?.data ?? (Array.isArray(res) ? res : []); const models = Array.isArray(rawModels) ? rawModels : []; setRemoteModels(models); - message.success(`获取到 ${models.length} 个模型`); + message.success(`鑾峰彇鍒?${models.length} 涓ā鍨媊); } finally { setFetchLoading(false); } @@ -292,7 +292,7 @@ const AiModels: React.FC = () => { const handleSubmit = async () => { const values = await form.validateFields(); if (values.isDefaultChecked && !values.statusChecked) { - message.warning("默认模型必须保持启用状态"); + message.warning("????????????"); return; } @@ -334,10 +334,10 @@ const AiModels: React.FC = () => { try { if (editingId) { await updateAiModel(payload); - message.success("更新成功"); + message.success("鏇存柊鎴愬姛"); } else { await saveAiModel(payload); - message.success("新增成功"); + message.success("鏂板鎴愬姛"); } setDrawerVisible(false); void fetchData(); @@ -363,7 +363,7 @@ const AiModels: React.FC = () => { max_tokens: extraValues.max_tokens, testMessage: DEFAULT_LLM_TEST_MESSAGE, }); - message.success("LLM 连通性测试成功"); + message.success("LLM ???????"); } finally { setConnectivityLoading(false); } @@ -372,7 +372,7 @@ const AiModels: React.FC = () => { const values = await form.validateFields(["provider", "baseUrl"]); if (String(values.provider || "").toLowerCase() !== "local") { - message.warning("只有本地 ASR 支持该连通性测试"); + message.warning("???? ASR ????????"); return; } @@ -385,7 +385,7 @@ const AiModels: React.FC = () => { }); const profile = (res as any)?.data?.data ?? (res as any)?.data ?? (res as any); applyLocalProfile(profile as AiLocalProfileVO, values.baseUrl); - message.success("本地模型连通性测试成功"); + message.success("???????????"); } finally { setConnectivityLoading(false); } @@ -393,63 +393,65 @@ const AiModels: React.FC = () => { const handleDelete = async (record: AiModelVO) => { await deleteAiModelByType(record.id, record.modelType); - message.success("删除成功"); + message.success("鍒犻櫎鎴愬姛"); void fetchData(); }; const handleTenantToggle = async (record: AiModelVO, checked: boolean) => { if (checked) { await tenantEnableModel(record.id, activeType); - message.success(activeType === "ASR" ? "已切换当前 ASR" : "已启用当前 LLM"); + message.success(activeType === "ASR" ? "宸插垏鎹㈠綋鍓?ASR" : "宸插惎鐢ㄥ綋鍓?LLM"); } else { await tenantDisableModel(record.id, activeType); - message.success(activeType === "ASR" ? "已关闭当前 ASR" : "已关闭当前 LLM"); + message.success(activeType === "ASR" ? "宸插叧闂綋鍓?ASR" : "宸插叧闂綋鍓?LLM"); } await fetchData(); }; const handlePlatformStatusToggle = async (record: AiModelVO, checked: boolean) => { await updatePlatformModelStatus(record.id, activeType, checked ? 1 : 0); - message.success(checked ? `平台级 ${activeType} 已启用` : `平台级 ${activeType} 已禁用`); + message.success(checked ? `骞冲彴绾?${activeType} 宸插惎鐢╜ : `骞冲彴绾 ? ${activeType} + 宸茬鐢╜) + ; await fetchData(); }; const handleSyncCurrentAsr = async () => { await syncCurrentAsrSpeakers(); - message.success("已提交后台同步任务"); + message.success("?????????"); }; const handleSetTenantDefault = async (record: AiModelVO) => { await setTenantDefaultModel(record.id, "LLM"); - message.success("已设置为默认 LLM"); + message.success("宸茶缃负榛樿 LLM"); await fetchData(); }; const resolvedTableColumns = [ { - title: "模型名称", + title: "妯″瀷鍚嶇О", dataIndex: "modelName", key: "modelName", render: (text: string, record: AiModelVO) => ( {text} - {record.isDefault === 1 && 系统默认} - {record.tenantDefault === 1 && 租户默认} + {record.isDefault === 1 && 绯荤粺榛樿} + {record.tenantDefault === 1 && 绉熸埛榛樿} {record.tenantId === 0 && ( - + )} {record.scope && ( - {record.scope === "PLATFORM" ? "平台级" : "租户级"} + {record.scope === "PLATFORM" ? "骞冲彴绾? : "绉熸埛绾 ?} )} ), }, { - title: "提供商", + title: "???", dataIndex: "provider", key: "provider", render: (value: string) => { @@ -458,18 +460,18 @@ const AiModels: React.FC = () => { }, }, { - title: "模型编码", + title: "妯″瀷缂栫爜", dataIndex: "modelCode", key: "modelCode", }, { - title: "排序", + title: "鎺掑簭", dataIndex: "sortOrder", key: "sortOrder", render: (value: number | undefined) => value ?? 0, }, { - title: "状态", + title: "??", dataIndex: "status", key: "status", render: (status: number, record: AiModelVO) => { @@ -477,8 +479,8 @@ const AiModels: React.FC = () => { return ( void handlePlatformStatusToggle(record, checked)} /> ); @@ -486,8 +488,8 @@ const AiModels: React.FC = () => { return ( void handleTenantToggle(record, checked)} /> @@ -495,7 +497,7 @@ const AiModels: React.FC = () => { }, }, { - title: "操作", + title: "鎿嶄綔", key: "action", render: (_: unknown, record: AiModelVO) => { const canEdit = record.canEditConfig ?? (record.tenantId !== 0 || isPlatformAdmin); @@ -504,18 +506,18 @@ const AiModels: React.FC = () => { {canSetDefault && ( )} {canEdit && ( )} {canEdit && ( - handleDelete(record)}> + handleDelete(record)}> )} @@ -528,11 +530,11 @@ const AiModels: React.FC = () => { const leftActions = ( {activeType === "ASR" && ( )} @@ -541,8 +543,8 @@ const AiModels: React.FC = () => { return ( { setCurrent(1); }} items={[ - { key: "ASR", label: "ASR 模型" }, - { key: "LLM", label: "LLM 模型" }, + {key: "ASR", label: "ASR 妯″瀷"}, + {key: "LLM", label: "LLM 妯″瀷"}, ]} size="middle" type="card" @@ -566,7 +568,7 @@ const AiModels: React.FC = () => { rightActions={ } className="ai-models-search" onSearch={(value) => { @@ -603,13 +605,13 @@ const AiModels: React.FC = () => { width={600} open={drawerVisible} onClose={() => setDrawerVisible(false)} - title={{editingId ? "编辑模型" : "新增模型"}} + title={{editingId ? "缂栬緫妯″瀷" : "鏂板妯″瀷"}} forceRender extra={ - + } @@ -619,9 +621,9 @@ const AiModels: React.FC = () => { - + - {activeType === "ASR" ? "语音识别 (ASR)" : "大语言模型 (LLM)"} + {activeType === "ASR" ? "璇煶璇嗗埆 (ASR)" : "澶ц瑷€妯″瀷 (LLM)"} @@ -629,21 +631,21 @@ const AiModels: React.FC = () => { { modelNameAutoFilledRef.current = false; - }}/> + }} maxLength={15} showCount/> - {providers.map((item) => (