From 9f36f2301f6ee81b4aebf0b19b7b0439ac0c84a9 Mon Sep 17 00:00:00 2001 From: panda <1565636758@qq.com> Date: Tue, 23 Dec 2025 10:50:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EAI=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- src/api/ai/chat/index.ts | 44 ++ src/api/ai/message/index.ts | 127 ++++ src/api/ai/model/index.ts | 20 + src/components/markdown-view/index.vue | 196 ++++++ .../chat/components/chat/ChatLoading.vue | 9 + .../chat/components/chat/ChatSettings.vue | 334 ++++++++++ .../chat/components/chat/chat-item.vue | 315 +++++++++ .../chat/components/message/MessageList.vue | 296 +++++++++ .../components/message/MessageListEmpty.vue | 59 ++ .../components/message/MessageLoading.vue | 9 + .../components/message/MessageReasoning.vue | 85 +++ src/pages-ai/chat/conversation.vue | 599 ++++++++++++++++++ src/pages-ai/chat/index.vue | 228 +++++++ src/pages/ai/index.vue | 42 ++ src/pages/ai/utils/constants.ts | 25 + src/pages/index/index.ts | 15 + src/static/images/avatar.jpg | Bin 0 -> 6264 bytes src/static/images/gpt.svg | 1 + src/tabbar/config.ts | 7 + src/utils/index.ts | 16 + uno.config.ts | 2 +- vite.config.ts | 1 + 23 files changed, 2431 insertions(+), 2 deletions(-) create mode 100644 src/api/ai/chat/index.ts create mode 100644 src/api/ai/message/index.ts create mode 100644 src/api/ai/model/index.ts create mode 100644 src/components/markdown-view/index.vue create mode 100644 src/pages-ai/chat/components/chat/ChatLoading.vue create mode 100644 src/pages-ai/chat/components/chat/ChatSettings.vue create mode 100644 src/pages-ai/chat/components/chat/chat-item.vue create mode 100644 src/pages-ai/chat/components/message/MessageList.vue create mode 100644 src/pages-ai/chat/components/message/MessageListEmpty.vue create mode 100644 src/pages-ai/chat/components/message/MessageLoading.vue create mode 100644 src/pages-ai/chat/components/message/MessageReasoning.vue create mode 100644 src/pages-ai/chat/conversation.vue create mode 100644 src/pages-ai/chat/index.vue create mode 100644 src/pages/ai/index.vue create mode 100644 src/pages/ai/utils/constants.ts create mode 100644 src/static/images/avatar.jpg create mode 100644 src/static/images/gpt.svg diff --git a/package.json b/package.json index ea7a96e..dac3f03 100644 --- a/package.json +++ b/package.json @@ -112,9 +112,10 @@ "@dcloudio/uni-mp-weixin": "3.0.0-4070620250821001", "@dcloudio/uni-mp-xhs": "3.0.0-4070620250821001", "@dcloudio/uni-quickapp-webview": "3.0.0-4070620250821001", - "abortcontroller-polyfill": "^1.7.8", "crypto-js": "^4.2.0", "dayjs": "1.11.10", + "highlight": "^0.2.4", + "markdown-it": "^14.1.0", "pinia": "2.0.36", "pinia-plugin-persistedstate": "3.2.1", "vue": "^3.4.21", diff --git a/src/api/ai/chat/index.ts b/src/api/ai/chat/index.ts new file mode 100644 index 0000000..f077e56 --- /dev/null +++ b/src/api/ai/chat/index.ts @@ -0,0 +1,44 @@ +import { http } from '@/http/http' + +export interface ChatConversationModel { + id: string + userId: number + title: string + pinned: boolean + roleId: number | null + modelId: number + model: string + modelName: string + systemMessage: string | null + temperature: number + maxTokens: number + maxContexts: number + createTime: number + roleAvatar: string | null + roleName: string | null + messageCount: number | null + transMap: Record +} + +/** 获取我的对话列表 */ +export async function getConversationList() { + return http.get('/ai/chat/conversation/my-list') +} + +/** 获取我的对话详情 */ +export async function getChatConversationMy(id: number) { + return http.get(`/ai/chat/conversation/get-my?id=${id}`) +} + +// 新增【我的】聊天对话 +export async function createChatConversationMy(data?: ChatConversationModel) { + return http.post('/ai/chat/conversation/create-my', data) +} +// 更新【我的】聊天对话 +export async function updateChatConversationMy(data: ChatConversationModel) { + return http.put(`/ai/chat/conversation/update-my`, data) +} +// 删除【我的】聊天对话 +export async function deleteChatConversationMy(id: number) { + return http.delete(`/ai/chat/conversation/delete-my?id=${id}`) +} diff --git a/src/api/ai/message/index.ts b/src/api/ai/message/index.ts new file mode 100644 index 0000000..1ed4d36 --- /dev/null +++ b/src/api/ai/message/index.ts @@ -0,0 +1,127 @@ +import { http } from '@/http/http' +import { useTokenStore } from '@/store/token' +import { getEnvBaseUrl } from '@/utils' +// 聊天VO +export interface ChatMessageVO { + id: number // 编号 + conversationId: number // 对话编号 + type: string // 消息类型 + userId: string // 用户编号 + roleId: string // 角色编号 + model: number // 模型标志 + modelId: number // 模型编号 + content: string // 聊天内容 + reasoningContent?: string // 推理内容 + attachmentUrls?: string[] // 附件 URL 数组 + tokens: number // 消耗 Token 数量 + segmentIds?: number[] // 段落编号 + segments?: { + id: number // 段落编号 + content: string // 段落内容 + documentId: number // 文档编号 + documentName: string // 文档名称 + }[] + webSearchPages?: { + name: string // 名称 + icon: string // 图标 + title: string // 标题 + url: string // URL + snippet: string // 内容的简短描述 + summary: string // 内容的文本摘要 + }[] + createTime: Date // 创建时间 + roleAvatar: string // 角色头像 + userAvatar: string // 用户头像 +} + +/** + * 获取对话的消息列表 + */ +export function getChatMessageListByConversationId(conversationId: number) { + return http.get(`/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`) +} + +// 发送 Stream 消息 +// @modify by panda 使用uni.request的sse支持,手动解释stream +export async function sendChatMessageStream( + conversationId: number, + content: string, + ctrl, + enableContext: boolean, + enableWebSearch: boolean, + onMessage, + onError, + onClose, + attachmentUrls?: string[], +) { + const tokenStore = useTokenStore() + const token = tokenStore.validToken + const baseUrl = getEnvBaseUrl() + let requestTask: any + try { + requestTask = uni.request({ + url: `${baseUrl}/ai/chat/message/send-stream`, + method: 'POST', + enableChunked: true, // 这个地方需要开 + responseType: 'arraybuffer', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + 'Accept': 'text/event-stream', + }, + data: JSON.stringify({ + conversationId, + content, + useContext: enableContext, + useSearch: enableWebSearch, + attachmentUrls: attachmentUrls || [], + }), + success() { + onClose() + }, + fail(err) { onError(err) }, + }) + } catch (error) { + onError(error) + } finally { + let buffer = '' // 用于存储不完整的消息片段 + requestTask.onChunkReceived((res) => { + const arrayBuffer = res.data + const uint8Array = new Uint8Array(arrayBuffer) + // 将 ArrayBuffer 转换为字符串 + const textChunk = new TextDecoder().decode(uint8Array) + + // --- 手动解析 SSE 格式 --- + buffer += textChunk + const messages = buffer.split('\n\n') + + // 最后一个消息可能不完整,保留在 buffer 中 + buffer = messages.pop() + + messages.forEach((msg) => { + if (msg.startsWith('data:')) { + const dataStr = msg.substring(5) // 去掉 "data: " + if (dataStr === '[DONE]') { + return + } + try { + const data = JSON.parse(dataStr) + if (onMessage) + onMessage(data) + } catch (e) { + onError(e) + } + } + }) + }) + + requestTask.offHeadersReceived(() => onClose()) + } + + return requestTask +} + +// 删除消息 +export function deleteChatMessage(id: number) { + return http.delete(`/ai/chat/message/delete?id=${id}`) +} diff --git a/src/api/ai/model/index.ts b/src/api/ai/model/index.ts new file mode 100644 index 0000000..c4d2e50 --- /dev/null +++ b/src/api/ai/model/index.ts @@ -0,0 +1,20 @@ +import { http } from '@/http/http' + +export interface ModelVO { + id: number // 编号 + keyId: number // API 秘钥编号 + name: string // 模型名字 + model: string // 模型标识 + platform: string // 模型平台 + type: number // 模型类型 + sort: number // 排序 + status: number // 状态 + temperature?: number // 温度参数 + maxTokens?: number // 单条回复的最大 Token 数量 + maxContexts?: number // 上下文的最大 Message 数量 +} + +// 获得模型列表 +export async function getModelSimpleList(type?: number) { + return http.get('/ai/model/simple-list', { type }) +} diff --git a/src/components/markdown-view/index.vue b/src/components/markdown-view/index.vue new file mode 100644 index 0000000..9a97b7b --- /dev/null +++ b/src/components/markdown-view/index.vue @@ -0,0 +1,196 @@ + + + + + diff --git a/src/pages-ai/chat/components/chat/ChatLoading.vue b/src/pages-ai/chat/components/chat/ChatLoading.vue new file mode 100644 index 0000000..a53df10 --- /dev/null +++ b/src/pages-ai/chat/components/chat/ChatLoading.vue @@ -0,0 +1,9 @@ + + diff --git a/src/pages-ai/chat/components/chat/ChatSettings.vue b/src/pages-ai/chat/components/chat/ChatSettings.vue new file mode 100644 index 0000000..ef84583 --- /dev/null +++ b/src/pages-ai/chat/components/chat/ChatSettings.vue @@ -0,0 +1,334 @@ + + + + + diff --git a/src/pages-ai/chat/components/chat/chat-item.vue b/src/pages-ai/chat/components/chat/chat-item.vue new file mode 100644 index 0000000..ff4eaf7 --- /dev/null +++ b/src/pages-ai/chat/components/chat/chat-item.vue @@ -0,0 +1,315 @@ + + + + + diff --git a/src/pages-ai/chat/components/message/MessageList.vue b/src/pages-ai/chat/components/message/MessageList.vue new file mode 100644 index 0000000..9aa02dc --- /dev/null +++ b/src/pages-ai/chat/components/message/MessageList.vue @@ -0,0 +1,296 @@ + + + + + diff --git a/src/pages-ai/chat/components/message/MessageListEmpty.vue b/src/pages-ai/chat/components/message/MessageListEmpty.vue new file mode 100644 index 0000000..62ffe72 --- /dev/null +++ b/src/pages-ai/chat/components/message/MessageListEmpty.vue @@ -0,0 +1,59 @@ + + + + + + diff --git a/src/pages-ai/chat/components/message/MessageLoading.vue b/src/pages-ai/chat/components/message/MessageLoading.vue new file mode 100644 index 0000000..813410a --- /dev/null +++ b/src/pages-ai/chat/components/message/MessageLoading.vue @@ -0,0 +1,9 @@ + + diff --git a/src/pages-ai/chat/components/message/MessageReasoning.vue b/src/pages-ai/chat/components/message/MessageReasoning.vue new file mode 100644 index 0000000..25da80c --- /dev/null +++ b/src/pages-ai/chat/components/message/MessageReasoning.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/pages-ai/chat/conversation.vue b/src/pages-ai/chat/conversation.vue new file mode 100644 index 0000000..0ed270e --- /dev/null +++ b/src/pages-ai/chat/conversation.vue @@ -0,0 +1,599 @@ + + + + + diff --git a/src/pages-ai/chat/index.vue b/src/pages-ai/chat/index.vue new file mode 100644 index 0000000..c293fd3 --- /dev/null +++ b/src/pages-ai/chat/index.vue @@ -0,0 +1,228 @@ + + + + + diff --git a/src/pages/ai/index.vue b/src/pages/ai/index.vue new file mode 100644 index 0000000..424d75a --- /dev/null +++ b/src/pages/ai/index.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/pages/ai/utils/constants.ts b/src/pages/ai/utils/constants.ts new file mode 100644 index 0000000..3fee920 --- /dev/null +++ b/src/pages/ai/utils/constants.ts @@ -0,0 +1,25 @@ +/** + * AI 平台的枚举 + */ +export const AiPlatformEnum = { + TONG_YI: 'TongYi', // 阿里 + YI_YAN: 'YiYan', // 百度 + DEEP_SEEK: 'DeepSeek', // DeepSeek + ZHI_PU: 'ZhiPu', // 智谱 AI + XING_HUO: 'XingHuo', // 讯飞 + SiliconFlow: 'SiliconFlow', // 硅基流动 + OPENAI: 'OpenAI', + Ollama: 'Ollama', + STABLE_DIFFUSION: 'StableDiffusion', // Stability AI + MIDJOURNEY: 'Midjourney', // Midjourney + SUNO: 'Suno', // Suno AI +} + +export const AiModelTypeEnum = { + CHAT: 1, // 聊天 + IMAGE: 2, // 图像 + VOICE: 3, // 音频 + VIDEO: 4, // 视频 + EMBEDDING: 5, // 向量 + RERANK: 6, // 重排 +} diff --git a/src/pages/index/index.ts b/src/pages/index/index.ts index c5c8913..60d2f35 100644 --- a/src/pages/index/index.ts +++ b/src/pages/index/index.ts @@ -146,6 +146,21 @@ const menuGroupsData: MenuGroup[] = [ }, ], }, + { + key: 'ai', + name: 'AI功能', + menus: [ + { + key: 'aiChat', + name: 'AI对话', + icon: 'chat', + url: '/pages-ai/chat/index', + iconColor: '#597ef7', + permission: '', + }, + + ], + }, ] /** diff --git a/src/static/images/avatar.jpg b/src/static/images/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d46a70a46430e31744420865138cc7eedb8b77e1 GIT binary patch literal 6264 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 BLq7lj literal 0 HcmV?d00001 diff --git a/src/static/images/gpt.svg b/src/static/images/gpt.svg new file mode 100644 index 0000000..603e2e9 --- /dev/null +++ b/src/static/images/gpt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/tabbar/config.ts b/src/tabbar/config.ts index 4e09d2c..4aad027 100644 --- a/src/tabbar/config.ts +++ b/src/tabbar/config.ts @@ -111,6 +111,13 @@ export const customTabbarList: CustomTabBarItem[] = [ iconType: 'unocss', icon: 'i-carbon-chat', }, + // add by panda 25.12.17:添加 AI 对话 + { + text: '大模型', + pagePath: 'pages/ai/index', + iconType: 'unocss', + icon: 'i-carbon-ai', + }, { text: '我的', pagePath: 'pages/user/index', diff --git a/src/utils/index.ts b/src/utils/index.ts index 3229424..c24baee 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -224,3 +224,19 @@ export function navigateBackPlus(fallbackUrl?: string) { uni.reLaunch({ url: targetUrl }) } } +/** + * 复制文本到剪贴板 + * @param text 要复制的文本 + */ +export function copyToClipboard(text: string) { + uni.setClipboardData({ + data: text, + success: () => { + uni.showToast({ + title: '复制成功!', + icon: 'success', + duration: 2000, + }) + }, + }) +} diff --git a/uno.config.ts b/uno.config.ts index 4a4401f..a1b406e 100644 --- a/uno.config.ts +++ b/uno.config.ts @@ -71,7 +71,7 @@ export default defineConfig({ }, ], // 动态图标需要在这里配置,或者写在vue页面中注释掉 - safelist: ['i-carbon-code', 'i-carbon-home', 'i-carbon-user', 'i-carbon-document', 'i-carbon-chat', 'i-carbon-user-avatar'], + safelist: ['i-carbon-code', 'i-carbon-home', 'i-carbon-user', 'i-carbon-document', 'i-carbon-chat', 'i-carbon-user-avatar', 'i-carbon-ai'], rules: [ [ 'p-safe', diff --git a/vite.config.ts b/vite.config.ts index 66fb3b5..c5031c8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -77,6 +77,7 @@ export default defineConfig(({ command, mode }) => { 'src/pages-system', // “系统管理”模块 'src/pages-infra', // “基础设施”模块 'src/pages-bpm', // “工作流程”模块 + 'src/pages-ai', // “AI 功能”模块 ], dts: 'src/types/uni-pages.d.ts', }), -- Gitee From 55118381b0a36e136fb26985ce7d2e749d3894db Mon Sep 17 00:00:00 2001 From: panda <1565636758@qq.com> Date: Wed, 24 Dec 2025 14:42:47 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index b8ef3c6..1881d53 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -239,7 +239,7 @@ export function copyToClipboard(text: string) { }) }, }) - +} /** 获取 wd-navbar 导航栏高度 */ export function getNavbarHeight() { const systemInfo = uni.getSystemInfoSync() @@ -255,4 +255,4 @@ export function getNavbarHeight() { // H5/App:状态栏高度 + 导航栏高度(44px) return statusBarHeight + 44 // #endif -} \ No newline at end of file +} -- Gitee