Files
sionrui/frontend/app/web-gold/src/api/chat.js
sion123 36195ea55a feat: 重构 IdentifyFace.vue 为 Hooks 架构
- 新增 hooks/ 目录,包含三个专用 Hook:
  * useVoiceGeneration - 语音生成和校验逻辑
  * useDigitalHumanGeneration - 数字人视频生成逻辑
  * useIdentifyFaceController - 协调两个子 Hook 的控制器

- 新增 types/identify-face.ts 完整类型定义

- 重构 IdentifyFace.vue 使用 hooks 架构:
  * 视图层与业务逻辑分离
  * 状态管理清晰化
  * 模块解耦,逻辑清晰

- 遵循单一职责原则,每个 Hook 只负责一个领域
- 提升代码可测试性和可维护性
- 支持两种视频素材来源:素材库选择和直接上传
- 实现语音生成优先校验的业务规则

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-28 00:19:17 +08:00

78 lines
2.0 KiB
JavaScript

import request from '@/api/http'
import { fetchEventSource } from '@microsoft/fetch-event-source'
// 直接使用 tokenManager 实例(最简单、最可靠)
import tokenManager from '@gold/utils/token-manager'
// 使用公共配置
import { API_BASE } from '@gold/config/api'
// C 端使用 APP_AI
const SERVER_BASE_AI = API_BASE.APP_AI
// AI chat 聊天
export const ChatMessageApi = {
// 创建【我的】聊天对话
createChatConversationMy: async (data) => {
return await request.post(`${SERVER_BASE_AI}/chat/conversation/create-my`, data)
},
// 发送 Stream 消息(对象入参,便于维护)
// 为什么不用 axios 呢?因为它不支持 SSE 调用
sendChatMessageStream: async (options) => {
const {
conversationId,
content,
ctrl,
enableContext = true,
enableWebSearch = false,
onMessage,
onError,
onClose,
attachmentUrls = []
} = options || {}
const token = tokenManager.getAccessToken()
let retryCount = 0
const maxRetries = 0 // 禁用自动重试
return fetchEventSource(`${SERVER_BASE_AI}/chat/message/send-stream`, {
method: 'post',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
'tenant-id': import.meta.env?.VITE_TENANT_ID
},
openWhenHidden: true,
body: JSON.stringify({
conversationId,
content,
useContext: enableContext,
useSearch: enableWebSearch,
attachmentUrls: attachmentUrls || []
}),
onmessage: onMessage,
onerror: (err) => {
retryCount++
if (typeof onError === 'function') {
onError(err)
}
if (retryCount > maxRetries) {
throw err
}
},
onclose: () => {
// 调用自定义关闭处理
if (typeof onClose === 'function') {
onClose()
}
},
signal: ctrl ? ctrl.signal : undefined
})
},
}