From dc4f6b2132fe47cce66ee3b0bc6e15529b8ce4a0 Mon Sep 17 00:00:00 2001
From: YiLin <482244139@qq.com>
Date: Fri, 24 Jul 2026 09:18:10 +0800
Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8D=95=E6=B8=B2=E6=9F=93wyxd?=
=?UTF-8?q?=EF=BC=8C=E6=9C=AA=E6=95=B4=E5=90=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages.json | 22 +-
pages/text/IntuitiveAipptViewer.vue | 804 +++++
pages/text/text.vue | 1846 ++++++++++-
pages/text/text2.vue | 538 ----
.../dist/dev/app-plus/app-config-service.js | 4 +-
unpackage/dist/dev/app-plus/app-service.js | 2747 +++++++++++++----
unpackage/dist/dev/app-plus/manifest.json | 2 +-
.../dev/app-plus/pages/text/BookViewer.css | 526 ++++
.../pages/text/IntuitiveAipptViewer.css | 303 ++
.../dist/dev/app-plus/pages/text/text.css | 1841 +++++++++++
.../dist/dev/app-plus/pages/text/text2.css | 222 --
11 files changed, 7420 insertions(+), 1435 deletions(-)
create mode 100644 pages/text/IntuitiveAipptViewer.vue
delete mode 100644 pages/text/text2.vue
create mode 100644 unpackage/dist/dev/app-plus/pages/text/BookViewer.css
create mode 100644 unpackage/dist/dev/app-plus/pages/text/IntuitiveAipptViewer.css
create mode 100644 unpackage/dist/dev/app-plus/pages/text/text.css
delete mode 100644 unpackage/dist/dev/app-plus/pages/text/text2.css
diff --git a/pages.json b/pages.json
index 59b75b2..20220fa 100644
--- a/pages.json
+++ b/pages.json
@@ -78,16 +78,6 @@
}
}
},
- {
- "path" : "pages/text/text",
- "style" : {
- "navigationBarTitleText" : ""
- }
- },
- {
- "path" : "pages/text/text2",
- "style" : {}
- },
{
"path": "pages/CloudDatabase/CloudDatabase",
"style": {
@@ -111,6 +101,18 @@
"softinputMode": "adjustResize"
}
}
+ },
+ {
+ "path" : "pages/text/text",
+ "style" : {
+ "navigationBarTitleText" : ""
+ }
+ },
+ {
+ "path" : "pages/text/IntuitiveAipptViewer",
+ "style" : {
+ "navigationBarTitleText" : ""
+ }
}
],
"uniIdRouter" : {},
diff --git a/pages/text/IntuitiveAipptViewer.vue b/pages/text/IntuitiveAipptViewer.vue
new file mode 100644
index 0000000..a3ecaf0
--- /dev/null
+++ b/pages/text/IntuitiveAipptViewer.vue
@@ -0,0 +1,804 @@
+
+
+
+
+
+ PPT
+
+ {{ displayFilename }}
+ {{ slideStatusText }}
+
+
+
+
+ ↻
+
+
+ ✕
+
+
+
+
+
+
+
+
+ {{ emptyIconText }}
+ {{ emptyTitle }}
+ {{ emptyDescription }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ String(index + 1).padStart(2, '0') }}
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/text/text.vue b/pages/text/text.vue
index 30a53d2..e53e8b2 100644
--- a/pages/text/text.vue
+++ b/pages/text/text.vue
@@ -1,160 +1,1732 @@
-
-
+
+
+
+
+
+ 选择对话类型,开启全新会话体验
+
+
+
+
+
+
+ 普通会话
+ 与AI自由对话,探索任何话题
+
+
+
+
+
+
+
+
+ 智能体会话
+ 选择专属智能体,获得精准专业服务
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📄
+ {{ file.name }}
+ {{ formatFileSize(file.fileSize) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📄
+ {{ file.name }}
+ {{ formatFileSize(file.fileSize) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📄
+ {{ file.name }}
+ {{ formatFileSize(file.fileSize) }}
+
+
+
+
+
+
+
+
+
+
+
+ 拍照上传
+ 上传文件
+
+
+
+
+ {{ item.name }}
+ ×
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 文件 ({{ detailLinks.length }})
+
+ {{ link.name }}
+
+
+
+ 无可下载文件
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ downloadToast.type === 'success' ? '✓' : '✕' }}
+ {{ downloadToast.message }}
+
+
+
+
\ No newline at end of file
+ const showNewChatModal = ref(false)
+ const closeNewChatModal = () => {
+ showNewChatModal.value = false;
+ }
+
+ // 侧边栏相关
+ const isChatSidebar = ref(false)
+ const handleChatSidebar = () => {
+ isChatSidebar.value = !isChatSidebar.value
+ }
+
+ // 跳转到工作区
+ const goWorkSpace = () => {
+ // 保存当前会话id,确保从工作区返回时能恢复
+ if (currentSessionId.value) {
+ uni.setStorageSync('currentSessionId', currentSessionId.value)
+ }
+ uni.navigateTo({
+ url: '/pages/WorkSpace/WorkSpace'
+ })
+ }
+
+ // 跳转到云端数据库
+ const goCloudDatabase = () => {
+ // 保存当前会话id,确保从工作区返回时能恢复
+ if (currentSessionId.value) {
+ uni.setStorageSync('currentSessionId', currentSessionId.value)
+ }
+ uni.navigateTo({
+ url: '/pages/CloudDatabase/CloudDatabase'
+ })
+ }
+
+ const logOut = () => {
+ uni.reLaunch({
+ url: '/pages/Login/Login'
+ })
+ }
+
+ const previewFileArray = ref([])
+ const uploadPhoto = () => {
+ console.log('点击了拍照上传');
+ uni.chooseImage({
+ count: 1,
+ sourceType: ['camera', 'album'],
+ success: (res) => {
+ const tempFiles = res.tempFiles;
+ const tempFilePaths = res.tempFilePaths;
+ tempFiles.forEach((file, index) => {
+ previewFileArray.value.push({
+ path: tempFilePaths[index], // 图片路径(用于显示)
+ name: file.name || `photo_${Date.now()}_${index}.jpg`, // 文件名
+ size: file.size, // 文件大小
+ type: 'image', // 文件类型标识
+ tempFile: file // 原始文件对象
+ });
+ });
+ },
+ fail: (err) => {
+ console.error('选择图片失败', err);
+ }
+ })
+ }
+ // 删除指定图片
+ const deleteImage = (index) => {
+ previewFileArray.value.splice(index, 1);
+ };
+
+ const fileList = ref([])
+ const uploadFile = () => {
+ console.log('点击了上传文件');
+ chooseFile({
+ count: 5,
+ type: 'all',
+ success: (res) => {
+ console.log("成功了");
+ // 赋值文件列表
+ fileList.value = res.tempFiles;
+ // 把所有文件 push 到预览数组(展开运算符 ...)
+ previewFileArray.value.push(...res.tempFiles);
+ uni.showToast({
+ title: `已选择 ${res.tempFiles.length} 个文件`,
+ icon: 'success'
+ })
+ },
+ fail: (err) => {
+ console.error('选择失败:', err)
+ uni.showToast({
+ title: '选择失败',
+ icon: 'error'
+ })
+ }
+ })
+ }
+ // 连接socket
+ const handleConnect = () => {
+ return new Promise((resolve, reject) => {
+ if (socketStore.isConnected) return resolve()
+
+ // 监听连接成功
+ const unwatch = watch(() => socketStore.isConnected, (connected) => {
+ if (connected) {
+ unwatch()
+ resolve()
+ }
+ })
+
+ // 监听连接错误
+ const unwatchError = watch(() => socketStore.connectionStatus, (status) => {
+ if (status === 'error') {
+ unwatch()
+ unwatchError()
+ reject(new Error('连接失败'))
+ }
+ })
+
+ socketStore.connect({
+ token: userToken.value,
+ conversationId: currentSessionId.value
+ })
+ })
+ }
+
+ // // 监听socket连接是否成功
+ // watch(()=>socketStore.isConnected,(newVal)=>{
+ // if(newVal&&)
+ // })
+
+ const isThinking = ref(false)
+ const isSelfSent = ref(false) // 是否当前设备发起的 AI 对话(用于区分弹窗/仅锁输入)
+ const isUploading = ref(false)
+ const uploadedFiles = ref([])
+ const streamingMessageId = ref(null) // 流式消息的临时 ID,用于实时更新 AI 回复
+
+ // 消息详情弹窗
+ const showMessageModal = ref(false)
+ const detailLinks = ref([])
+ // 点击气泡内容:拦截链接点击,否则 AI 对话弹出详情
+ const handleChatContentClick = (e, message) => {
+ // 在事件路径中向上查找 .chat-inline-link 元素
+ let el = e.target
+ while (el && el.classList) {
+ if (el.classList.contains('chat-inline-link')) {
+ const url = el.getAttribute('data-url') || (el.dataset && el.dataset.url)
+ if (url) {
+ openLink(url)
+ }
+ return
+ }
+ el = el.parentElement
+ }
+ // 非链接点击:仅 AI 对话弹出详情窗
+ if (message.role) {
+ showMessageDetail(message)
+ }
+ }
+
+ const extractLinks = (text) => {
+ const seen = new Set()
+ const result = []
+ // 1. 匹配 Markdown 链接 [文件名](url)
+ const mdLinkRegex = /\[([^\]]*)\]\((https?:\/\/[^\s<>"{}|\\^`\[\]()]+)\)/gi
+ const mdLinks = [...text.matchAll(mdLinkRegex)]
+ mdLinks.forEach(m => {
+ const name = m[1].trim()
+ const url = m[2]
+ if (!seen.has(url)) {
+ seen.add(url)
+ result.push({
+ url,
+ name: name || url
+ })
+ }
+ })
+ // 2. 去除已匹配的 [xxx](url) 后,再搜裸 URL
+ let cleaned = text.replace(mdLinkRegex, '')
+ const bareRegex = /https?:\/\/[^\s<>"{}|\\^`\[\]()]+/gi
+ const bareMatches = cleaned.match(bareRegex)
+ if (bareMatches) {
+ bareMatches.forEach(url => {
+ if (!seen.has(url)) {
+ seen.add(url)
+ result.push({
+ url,
+ name: extractFileNameFromUrl(url)
+ })
+ }
+ })
+ }
+ return result
+ }
+ const extractFileNameFromUrl = (urlStr) => {
+ try {
+ const segments = new URL(urlStr).pathname.split('/').filter(s => s)
+ if (segments.length > 0) {
+ return decodeURIComponent(segments[segments.length - 1])
+ }
+ } catch (e) {
+ /* fallback */
+ }
+ const parts = urlStr.split('/').filter(s => s)
+ if (parts.length > 0) {
+ const last = parts[parts.length - 1]
+ const qIdx = last.indexOf('?')
+ return qIdx > -1 ? last.substring(0, qIdx) : last
+ }
+ return urlStr
+ }
+ const showMessageDetail = (message) => {
+ detailLinks.value = extractLinks(message.content || '')
+ showMessageModal.value = true
+ }
+ const closeMessageDetail = () => {
+ showMessageModal.value = false
+ detailLinks.value = []
+ }
+ const downloadToast = ref({
+ show: false,
+ type: 'loading',
+ message: ''
+ })
+ let downloadToastTimer = null
+
+ const showDownloadToast = (type, message, duration) => {
+ if (downloadToastTimer) clearTimeout(downloadToastTimer)
+ downloadToast.value = {
+ show: true,
+ type,
+ message
+ }
+ if (duration > 0) {
+ downloadToastTimer = setTimeout(() => {
+ downloadToast.value = {
+ show: false,
+ type: 'loading',
+ message: ''
+ }
+ }, duration)
+ }
+ }
+ const hideDownloadToast = () => {
+ if (downloadToastTimer) clearTimeout(downloadToastTimer)
+ downloadToast.value = {
+ show: false,
+ type: 'loading',
+ message: ''
+ }
+ }
+
+ const openLink = (url) => {
+ downloadAndHandle(url)
+ }
+
+ const downloadAndHandle = async (url) => {
+ try {
+ showDownloadToast('loading', '下载中...', 0)
+ const workspaceId = uni.getStorageSync('workspace_id') || ''
+ const result = await conversationMessageDownload(userToken.value, workspaceId, url)
+ const downloadUrl = typeof result === 'string' ? result : (result?.url || result?.download_url || '')
+ if (!downloadUrl) {
+ showDownloadToast('error', '获取下载地址失败', 2500)
+ return
+ }
+ uni.downloadFile({
+ url: downloadUrl,
+ success: (downloadRes) => {
+ if (downloadRes.statusCode === 200) {
+ hideDownloadToast()
+ uni.openDocument({
+ filePath: downloadRes.tempFilePath,
+ showMenu: true,
+ fail: () => {
+ showDownloadToast('error', '无法打开此文件', 2500)
+ }
+ })
+ } else {
+ showDownloadToast('error', '下载失败', 2500)
+ }
+ },
+ fail: () => {
+ showDownloadToast('error', '下载失败', 2500)
+ }
+ })
+ } catch (err) {
+ showDownloadToast('error', '下载失败: ' + (err.message || err), 2500)
+ }
+ }
+
+
+ const sendMessage = async () => {
+ const message = textMessage.value.trim()
+ if (!message && previewFileArray.value.length === 0) return
+
+ // 有文件时先上传
+ if (previewFileArray.value.length > 0) {
+ isUploading.value = true
+ uni.showLoading({
+ title: '上传文件中...',
+ mask: true
+ })
+ try {
+ const results = []
+ for (const item of previewFileArray.value) {
+ const result = await uploadFileToServer(item.path)
+ results.push(result)
+ }
+ uploadedFiles.value = results
+ previewFileArray.value = []
+ } catch (err) {
+ uni.hideLoading()
+ console.error('文件上传失败:', err)
+ uni.showToast({
+ title: '文件上传失败,请重试',
+ icon: 'error'
+ })
+ isUploading.value = false
+ return
+ }
+ uni.hideLoading()
+ isUploading.value = false
+ }
+
+ if (ChatType.value === 0) sendAIMessage();
+ if (ChatType.value === 1) sendFriendMessage();
+ if (ChatType.value === 2) sendGroupMessage();
+ }
+ // 发送好友消息
+ const sendFriendMessage = async () => {
+ if (!friendSocketStore.isConnecting) await handleFriendConnect();
+ const receiverId = getReceiverId()
+ const hasFiles = uploadedFiles.value.length > 0
+ const body = {
+ "command": 1,
+ "sender": UserId.value,
+ "receiver": receiverId,
+ "avatar": "",
+ "sessionId": currentSessionId.value,
+ "message": textMessage.value,
+ "callBackMessage": false
+ }
+ if (hasFiles) {
+ body.contentType = 1
+ body.uploadVos = uploadedFiles.value
+ }
+ const data = {
+ "version": "1.1",
+ "body": body
+ }
+ friendSocketStore.send(data)
+ const newMessageData = {
+ "sender": UserId.value,
+ "receiver": receiverId,
+ "content": textMessage.value,
+ "taskId": null,
+ "avatar": null,
+ "createTime": "",
+ "messageType": "null",
+ "contentJson": hasFiles ? JSON.stringify(uploadedFiles.value) : 'null'
+ }
+ allmessages.value = [...allmessages.value, newMessageData]
+ textMessage.value = ''
+ uploadedFiles.value = []
+ setTimeout(() => {
+ takeFriendMessages()
+ }, 1000)
+ }
+
+ // 发送群聊消息
+ const sendGroupMessage = async () => {
+ if (!friendSocketStore.isConnecting) await handleFriendConnect();
+ const hasFiles = uploadedFiles.value.length > 0
+ const body = {
+ "command": 9,
+ "groupId": currentSessionId.value,
+ "message": textMessage.value || "",
+ "callBackMessage": hasFiles ? false : true,
+ "messageType": hasFiles ? 1 : 0,
+ "sender": UserId.value
+ }
+ if (hasFiles) {
+ body.uploadVos = uploadedFiles.value
+ }
+ const data = {
+ "version": "1.1",
+ "body": body
+ }
+ friendSocketStore.send(data)
+ const newMessageData = {
+ "id": allmessages.value.length + 1,
+ "message": textMessage.value,
+ "messageType": hasFiles ? 1 : 0,
+ "groupId": null,
+ "createTime": '',
+ "contentJson": hasFiles ? JSON.stringify(uploadedFiles.value) : '',
+ "sender": UserId.value
+ }
+ allmessages.value = [...allmessages.value, newMessageData]
+ textMessage.value = ''
+ uploadedFiles.value = []
+ setTimeout(() => {
+ takeGroupMessages()
+ }, 1000)
+ }
+ // // 发送AI消息
+ // const sendAIMessage = async () => {
+ // try {
+ // handleConnect();
+ // let messageContent = textMessage.value
+ // if (uploadedFiles.value.length) {
+ // const fileJson = JSON.stringify(uploadedFiles.value)
+ // messageContent = messageContent ?
+ // `${messageContent}\n[文件信息:${fileJson}]` :
+ // `[文件信息:${fileJson}]`
+ // }
+ // const message_id = await addMessageDict(userToken.value, 'user', currentSessionId.value,
+ // messageContent)
+ // if (message_id) {
+ // textMessage.value = ''
+ // uploadedFiles.value = []
+ // isThinking.value = true
+ // }
+ // await waitForAIResponse();
+ // } catch (error) {
+ // isThinking.value = false
+ // uni.showToast({
+ // title: `用户发送消息失败${error}`,
+ // icon: 'error'
+ // })
+ // }
+ // }
+ // AI 回复超时定时器
+ // let aiResponseTimer = null
+
+ // 发送AI消息
+ const sendAIMessage = async () => {
+ try {
+ await handleConnect();
+ let messageContent = textMessage.value
+ if (uploadedFiles.value.length) {
+ const fileJson = JSON.stringify(uploadedFiles.value)
+ messageContent = messageContent ?
+ `${messageContent}\n[文件信息:${fileJson}]` :
+ `[文件信息:${fileJson}]`
+ }
+ const data = {
+ "type": "chat",
+ "conversation_id": currentSessionId.value,
+ "content": messageContent
+ }
+ socketStore.send(data)
+ isThinking.value = true
+ isSelfSent.value = true
+ // 立即添加用户消息到列表(使用完整的 messageContent,包含文件信息)
+ allmessages.value = [...allmessages.value, {
+ role: 'user',
+ content: messageContent
+ }]
+ // 添加流式消息气泡(加载中状态)
+ streamingMessageId.value = 'streaming-' + Date.now()
+ allmessages.value = [...allmessages.value, {
+ role: 'assistant',
+ content: '',
+ _streaming: true,
+ _id: streamingMessageId.value
+ }]
+ textMessage.value = ''
+ uploadedFiles.value = []
+ scrollToBottom()
+ } catch (error) {
+ isThinking.value = false
+ uni.showToast({
+ title: `用户发送消息失败${error}`,
+ icon: 'error'
+ })
+ }
+ }
+
+ // 中断 AI 对话
+ const stopConversation = async () => {
+ console.log('中断对话 - 当前会话ID:', currentSessionId.value)
+ try {
+ await socketStore.send({
+ type: 'stop',
+ conversation_id: currentSessionId.value
+ })
+ console.log('中断指令已发送成功')
+ } catch (err) {
+ console.error('中断指令发送失败:', err)
+ }
+ // 移除流式消息占位
+ if (streamingMessageId.value) {
+ allmessages.value = allmessages.value.filter(m => m._id !== streamingMessageId.value)
+ streamingMessageId.value = null
+ }
+ // 立即关闭弹窗,清除超时
+ // clearTimeout(aiResponseTimer)
+ isThinking.value = false
+ socketStore.isThinking = false
+ isSelfSent.value = false
+ textMessage.value = ''
+ uploadedFiles.value = []
+ // takeConversationMessages 由后端中断确认驱动(见 handleBusinessMessage)
+ uni.showToast({
+ title: '已中断',
+ icon: 'none',
+ duration: 1500
+ })
+ }
+
+ // 全局监听 socketStore.isThinking:跨设备同步思考状态,锁/解锁输入框
+ watch(() => socketStore.isThinking, (newVal, oldVal) => {
+ console.log("isThinking 变化:", oldVal, "→", newVal, "messageString:", socketStore.messageString);
+ // false → true:后端开始回复,锁定输入框
+ if (!oldVal && newVal) {
+ console.log('AI开始回复(跨设备同步),锁定输入框');
+ isThinking.value = true
+ // 非本设备发起时,也需要添加流式气泡
+ if (!streamingMessageId.value) {
+ streamingMessageId.value = 'streaming-' + Date.now()
+ allmessages.value = [...allmessages.value, {
+ role: 'assistant',
+ content: '',
+ _streaming: true,
+ _id: streamingMessageId.value
+ }]
+ }
+ return
+ }
+ // true → false:AI 回复结束或中断,解锁输入框并刷新消息列表
+ if (oldVal && !newVal) {
+ console.log('AI回复结束(正常/中断),解锁并刷新消息列表');
+ // 移除流式消息气泡,从服务器加载完整消息
+ if (streamingMessageId.value) {
+ allmessages.value = allmessages.value.filter(m => m._id !== streamingMessageId.value)
+ streamingMessageId.value = null
+ }
+ takeConversationMessages()
+ isThinking.value = false
+ isSelfSent.value = false
+ textMessage.value = ''
+ uploadedFiles.value = []
+ }
+ })
+
+ // 监听 auth_fail,当 pc 端不在线时弹窗提示并取消思考状态
+ watch(() => socketStore.authFailReason, (reason) => {
+ if (reason === 'pc offline') {
+ isThinking.value = false
+ socketStore.authFailReason = ''
+ nextTick(() => {
+ uni.showModal({
+ title: '提示',
+ content: 'PC端不在线,不可聊天',
+ showCancel: false,
+ confirmText: '知道了'
+ })
+ })
+ }
+ })
+
+ // 监听流式消息内容,实时更新 AI 回复(流式输出核心)
+ watch(() => socketStore.messageString, (newContent) => {
+ if (!streamingMessageId.value || !socketStore.isThinking) return
+
+ const idx = allmessages.value.findIndex(m => m._id === streamingMessageId.value)
+ if (idx >= 0) {
+ // 使用 splice 保证 Vue 响应式更新
+ const updated = {
+ ...allmessages.value[idx],
+ content: newContent
+ }
+ allmessages.value.splice(idx, 1, updated)
+ scrollToBottom()
+ }
+ })
+
+ const textMessage = ref('')
+
+ // 获取用户历史会话列表
+ const UserConversations = ref([])
+ // 当前会话id
+ const currentSessionId = ref('')
+ const userToken = ref('')
+ const UserId = ref('')
+ const UserAvatar = ref('')
+ const UserData = ref(null)
+
+ // 获取当前用户信息(提前加载,用于显示头像等)
+ const takeUserInfo = async () => {
+ try {
+ userToken.value = getToken();
+ UserData.value = await getUserInfo(userToken.value)
+ UserId.value = UserData.value._id;
+ UserAvatar.value = UserData.value.avatar || ''
+ console.log("用户信息已加载:", UserId.value, UserAvatar.value);
+ } catch (error) {
+ console.error("获取用户信息失败:", error);
+ }
+ }
+
+ // 获取对话列表
+ const takeUserConversations = async () => {
+ try {
+ userToken.value = getToken();
+ console.log("token:", userToken.value);
+ UserConversations.value = await getUserConversations(userToken.value) || [];
+ // console.log("UserConversations:", JSON.stringify(UserConversations.value) );
+ // 优先恢复已保存的会话id,避免刷新到列表第一个
+ const savedSessionId = getCurrentSessionId();
+ if (savedSessionId && UserConversations.value.some(c => c._id === savedSessionId)) {
+ currentSessionId.value = savedSessionId;
+ } else if (UserConversations.value.length > 0) {
+ currentSessionId.value = UserConversations.value[0]._id;
+ } else {
+ currentSessionId.value = '';
+ }
+ console.log('保存会话id:', currentSessionId.value);
+ uni.setStorageSync('currentSessionId', currentSessionId.value)
+ } catch (error) {
+ uni.showToast({
+ title: `获取会话列表失败${error}`,
+ icon: 'error'
+ })
+ }
+ }
+ // 好友列表
+ // 好友消息列表(不包括头像)
+ const FriendInfoList = ref([])
+ // 获取用户好友列表
+ const takeFriendList = async () => {
+ try {
+ console.log("开始获取好友列表");
+ // UserId 已在 takeUserInfo 中获取
+ const friendList = await getChatFriend(UserId.value)
+ console.log("friendList:", friendList);
+ if (friendList && friendList.length) {
+ FriendInfoList.value = await takeUserAvatar(friendList)
+ } else {
+ FriendInfoList.value = []
+ console.log("好友列表为空");
+ }
+ } catch (error) {
+ console.error("获取好友列表失败:", error);
+ FriendInfoList.value = []
+ } finally {
+ UserConversations.value = FriendInfoList.value
+ }
+ }
+
+ // 从好友列表中获取单个用户头像
+ const takeTalkUserAvatar = (userId) => {
+ if (!userId) return null
+ const user = FriendInfoList.value.find(item => item.receiver === userId)
+ return user?.avatar || null
+ }
+ // 获取好友头像
+ const takeUserAvatar = async (friendList) => {
+ if (!friendList?.length) return []
+ try {
+ const friendIds = friendList.map(item => item.receiver)
+ const friendAvatarList = await getUserAvatar(userToken.value, friendIds)
+ // 创建map,用于快速查找
+ const userMap = new Map(friendAvatarList.map(user => [user.user_id, user]) || [])
+ // 合并数据
+ return friendList.map(friend => {
+ const userInfo = userMap.get(friend.receiver)
+ return {
+ ...friend,
+ avatar: userInfo?.avatar || null
+ }
+ })
+ } catch (err) {
+ console.error('获取好友头像失败', err);
+ return friendList
+ }
+ }
+
+ // 群聊列表
+ const GroupList = ref([])
+ // 获取用户群聊列表
+ const takeGroupList = async () => {
+ try {
+ console.log("开始获取群聊列表");
+ // UserId 已在 takeUserInfo 中获取
+ GroupList.value = await getGroup(UserId.value)
+ // console.log("GroupList1:", JSON.stringify(GroupList.value));
+ } catch (error) {
+ console.error("获取群聊列表失败:", error);
+ GroupList.value = []
+ } finally {
+ UserConversations.value = GroupList.value
+ }
+ }
+
+ // 群成员列表(包含头像)
+ const groupMemberList = ref([])
+ // 获取群成员头像
+ const takeGroupMemberAvatar = async (memberList) => {
+ if (!memberList?.length) return []
+ try {
+ const memberIds = memberList.map(item => item.groupContactId)
+ console.log("请求头像的ID列表:", memberIds)
+ const memberAvatarList = await getUserAvatar(userToken.value, memberIds)
+ console.log("头像接口返回数据:", memberAvatarList)
+ // 创建map,用于快速查找
+ const userMap = new Map(memberAvatarList.map(user => [user.user_id, user]) || [])
+ console.log("userMap的keys:", Array.from(userMap.keys()))
+ // 合并数据
+ return memberList.map(member => {
+ const memberId = member.groupContactId
+ const userInfo = userMap.get(memberId)
+ console.log(`查找 ${memberId} 的头像:`, userInfo)
+ return {
+ ...member,
+ avatar: userInfo?.avatar || null
+ }
+ })
+ } catch (err) {
+ console.error('获取群成员头像失败', err);
+ return memberList
+ }
+ }
+
+ // 从群成员列表中获取单个用户头像
+ const getGroupMemberAvatarById = (userId) => {
+ if (!userId) return null
+ const member = groupMemberList.value.find(item => item.groupContactId === userId)
+ return member?.avatar || null
+ }
+
+ // 当前会话的消息
+ // const currentMessages = ref([])
+ const allmessages = ref([])
+ // const pageInfoNumber = 10;
+
+ const scrollToView = ref('')
+ const bottomToggle = ref(false)
+ // 加载状态和分页相关变量
+ const isLoadingMore = ref(false) // 是否正在加载更多
+ const currentPage = ref(1) // 当前页码(如果后端支持分页)
+ // 计算属性:自动根据 allmessages 和 currentPage 计算显示消息
+ const currentMessages = computed(() => {
+ // return allmessages.value.slice(-pageInfoNumber);
+ return allmessages.value;
+ })
+
+
+ // 获取对话消息
+ const takeConversationMessages = async () => {
+ try {
+ allmessages.value = await getConversationMessages(userToken.value, currentSessionId.value) || [];
+ // console.log("获取到的所有消息:", JSON.stringify(allmessages.value) );
+ // currentMessages.value = allmessages.value.slice(-pageInfoNumber);
+ // 数据获取后执行滚动
+ scrollToBottom();
+ } catch (error) {
+ uni.showToast({
+ title: `获取ai会话内容失败${error}`,
+ icon: 'none'
+ })
+ }
+ }
+ const takeFriendMessages = async () => {
+ try {
+ allmessages.value = await getFriendMessages(currentSessionId.value) || [];
+ // console.log("好友消息:", JSON.stringify(allmessages.value));
+ // 数据获取后执行滚动
+ scrollToBottom();
+ } catch (error) {
+ uni.showToast({
+ title: `获取好友会话消息失败${error}`,
+ icon: 'none'
+ })
+ }
+ }
+ const takeGroupMessages = async () => {
+ try {
+ allmessages.value = await getGroupMessages(currentSessionId.value) || [];
+ console.log("群聊消息:", allmessages.value);
+ // 获取群成员列表并获取头像
+ const memberList = await getGroupMemberList(currentSessionId.value)
+ console.log("获取到的群成员列表:", memberList);
+ if (memberList && memberList.length) {
+ groupMemberList.value = await takeGroupMemberAvatar(memberList)
+ console.log("群成员列表(带头像):", groupMemberList.value);
+ } else {
+ groupMemberList.value = []
+ }
+ // 数据获取后执行滚动
+ scrollToBottom();
+ } catch (error) {
+ uni.showToast({
+ title: `获取群聊会话失败${error}`,
+ icon: 'none'
+ })
+ }
+ }
+ // // 加载更多消息
+ // const loadMoreMessages = async () => {
+ // console.log('加载更多信息');
+ // if (allmessages.value.length > pageInfoNumber * currentPage.value) {
+ // currentPage.value += 1;
+ // const newMessages = allmessages.value.slice(-pageInfoNumber * currentPage.value);
+ // const addMessage = newMessages.length - currentMessages.value.length
+ // currentMessages.value = newMessages
+ // // 等待DOM更新
+ // await nextTick()
+ // scrollToView.value = 'msg-' + (addMessage + 1);
+
+ // }
+ // // currentMessages.value = allmessages.value.slice(-pageInfoNumber);
+ // }
+
+
+
+ // 监听滚动
+ const onScroll = (e) => {}
+ // 滑动到底部
+ const scrollToBottom = async () => {
+ await nextTick();
+ if (currentMessages.value.length > 0) {
+ // 两个锚点交替切换,确保每次调用都能触发滚动
+ bottomToggle.value = !bottomToggle.value
+ scrollToView.value = bottomToggle.value ? 'chat-bottom-a' : 'chat-bottom-b'
+ }
+ }
+
+ // 监听好友消息
+ watch(() => friendSocketStore.MessageReceived, (newId) => {
+ console.log("收到了好友消息");
+ if (newId) {
+ console.log("ChatType:", ChatType.value);
+ switch (ChatType.value) {
+ case 0:
+ takeConversationMessages();
+ friendSocketStore.MessageReceived = false
+ break;
+ case 1:
+ takeFriendMessages();
+ friendSocketStore.MessageReceived = false
+ break;
+ case 2:
+ takeGroupMessages();
+ friendSocketStore.MessageReceived = false
+ break;
+ // 可选:默认兜底
+ default:
+ console.log("default 分支");
+ friendSocketStore.MessageReceived = false
+ break;
+ }
+ }
+ }, {
+ immediate: true
+ })
+
+ watch(currentSessionId, (newId) => {
+ if (newId) {
+ uni.setStorageSync('currentSessionId', currentSessionId.value)
+ switch (ChatType.value) {
+ case 0:
+ takeConversationMessages();
+ // 切换 AI 会话时重新连接 socket(绑定新 conversationId)
+ socketStore.disconnect()
+ handleConnect()
+ break;
+ case 1:
+ takeFriendMessages();
+ break;
+ case 2:
+ takeGroupMessages();
+ break;
+ default:
+ takeConversationMessages();
+ break;
+ }
+ }
+ }, {
+ immediate: true
+ })
+
+ onMounted(() => {
+ // currentSessionId.value = getCurrentSessionId()
+ })
+ onShow(async () => {
+ // 优先获取用户信息(用于显示头像等)
+ await takeUserInfo();
+
+ const chatType = getChatType()
+ ChatType.value = chatType
+ const sessionId = getCurrentSessionId()
+
+ // 只有在会话ID存在时才获取消息
+ if (sessionId) {
+ currentSessionId.value = sessionId
+ }
+
+ if (chatType === 0) {
+ await takeUserConversations();
+ // 只有在会话ID存在时才获取消息
+ if (currentSessionId.value) {
+ takeConversationMessages();
+ }
+ // AI 对话页面:主动建立 socket 连接,确保消息实时推送
+ if (userToken.value && currentSessionId.value && !socketStore.isConnected) {
+ handleConnect()
+ }
+ } else if (chatType === 1) {
+ await takeFriendList()
+ takeFriendMessages();
+ handleFriendConnect()
+ } else if (chatType === 2) {
+ await takeGroupList()
+ await handleFriendConnect()
+ await takeGroupMessages()
+ }
+ })
+
+ // 离开 AI 对话页面时断开 socket
+ onUnload(() => {
+ socketStore.disconnect()
+ })
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/text/text2.vue b/pages/text/text2.vue
deleted file mode 100644
index bad66fb..0000000
--- a/pages/text/text2.vue
+++ /dev/null
@@ -1,538 +0,0 @@
-
-
-
-
- 连接状态
-
- {{ socketStore.getStatusText() }}
-
-
- 重连次数: {{ socketStore.reconnectAttempts }}
-
-
-
-
-
- 连接配置
-
- Token
-
-
-
- Conversation ID
-
-
-
-
-
-
-
-
-
-
-
-
-
- 发送消息
-
-
-
-
-
-
-
-
-
-
- 快捷消息:
-
-
-
-
-
-
-
-
-
-
-
- {{ log.time }}
- {{ log.content }}
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/unpackage/dist/dev/app-plus/app-config-service.js b/unpackage/dist/dev/app-plus/app-config-service.js
index 84270da..3dd7454 100644
--- a/unpackage/dist/dev/app-plus/app-config-service.js
+++ b/unpackage/dist/dev/app-plus/app-config-service.js
@@ -1,8 +1,8 @@
;(function(){
let u=void 0,isReady=false,onReadyCallbacks=[],isServiceReady=false,onServiceReadyCallbacks=[];
- const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#F8F8F8","navigationBar":{"backgroundColor":"#F8F8F8","titleText":"uni-app","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"test1","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"5.07","entryPagePath":"pages/Login/Login","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
- const __uniRoutes = [{"path":"pages/Login/Login","meta":{"isQuit":true,"isEntry":true,"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"登录页面","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/Chat/Chat","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"聊天页面(主页面)","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/WorkSpace/WorkSpace","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"工作区文件管理","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/UserProfileModal/UserProfileModal","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/ContactPages/ContactPages","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/WorkSpace/TemplateSpace/TemplateSpace","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/text/text","meta":{"navigationBar":{"titleText":"","type":"default"},"isNVue":false}},{"path":"pages/text/text2","meta":{"navigationBar":{"type":"default"},"isNVue":false}},{"path":"pages/CloudDatabase/CloudDatabase","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"云端数据","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/CloudDbDetail/CloudDbDetail","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"数据库详情","style":"custom","type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
+ const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#F8F8F8","navigationBar":{"backgroundColor":"#F8F8F8","titleText":"uni-app","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"test1","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"5.07","entryPagePath":"pages/text/IntuitiveAipptViewer","entryPageQuery":"","realEntryPagePath":"pages/Login/Login","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
+ const __uniRoutes = [{"path":"pages/Login/Login","meta":{"isQuit":true,"isEntry":true,"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"登录页面","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/Chat/Chat","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"聊天页面(主页面)","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/WorkSpace/WorkSpace","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"工作区文件管理","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/UserProfileModal/UserProfileModal","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/ContactPages/ContactPages","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/WorkSpace/TemplateSpace/TemplateSpace","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/CloudDatabase/CloudDatabase","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"云端数据","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/CloudDbDetail/CloudDbDetail","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"数据库详情","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/text/text","meta":{"navigationBar":{"titleText":"","type":"default"},"isNVue":false}},{"path":"pages/text/IntuitiveAipptViewer","meta":{"navigationBar":{"titleText":"","type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
__uniConfig.styles=[];//styles
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
diff --git a/unpackage/dist/dev/app-plus/app-service.js b/unpackage/dist/dev/app-plus/app-service.js
index b7ba86e..4c470f8 100644
--- a/unpackage/dist/dev/app-plus/app-service.js
+++ b/unpackage/dist/dev/app-plus/app-service.js
@@ -9766,524 +9766,6 @@ This will fail in production.`);
}
const PagesWorkSpaceTemplateSpaceTemplateSpace = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4], ["__scopeId", "data-v-769edd25"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/TemplateSpace/TemplateSpace.vue"]]);
const _sfc_main$4 = {
- __name: "text",
- setup(__props, { expose: __expose }) {
- __expose();
- const formHtml = vue.ref("");
- const sanitizeContent = (str) => {
- return str.replace(/<\/?script>/gi, (match) => {
- let result = "";
- for (let i = 0; i < match.length; i++) {
- result += "\\u" + match.charCodeAt(i).toString(16).padStart(4, "0");
- }
- return result;
- });
- };
- vue.onMounted(() => {
- formHtml.value = `
-明白了!您希望在我的回复中直接嵌入可编辑的表单卡片。让我试试:
-
----
-
-
-
-
-
----
-
-**✅ 您现在可以直接在上方的卡片中填写任务信息,点击"添加任务"即可!**
-
-填写完成后告诉我"已填好"或"添加",我会帮您确认是否成功!
-`;
- });
- const initForm = () => {
- setTimeout(() => {
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
- const startInput = document.getElementById("inlineStart");
- const endInput = document.getElementById("inlineEnd");
- if (startInput)
- startInput.value = today;
- if (endInput)
- endInput.value = today;
- const clearBtn = document.getElementById("clearBtn");
- const submitBtn = document.getElementById("submitBtn");
- if (clearBtn) {
- clearBtn.onclick = () => {
- const titleInput = document.getElementById("inlineTitle");
- const descInput = document.getElementById("inlineDesc");
- if (titleInput)
- titleInput.value = "";
- if (descInput)
- descInput.value = "";
- };
- }
- if (submitBtn) {
- submitBtn.onclick = () => {
- const titleInput = document.getElementById("inlineTitle");
- const title = titleInput == null ? void 0 : titleInput.value.trim();
- if (!title) {
- alert("请输入任务名称");
- return;
- }
- alert(`任务已添加:${title}`);
- if (titleInput)
- titleInput.value = "";
- if (document.getElementById("inlineDesc"))
- document.getElementById("inlineDesc").value = "";
- };
- }
- }, 100);
- };
- const __returned__ = { formHtml, sanitizeContent, initForm, ref: vue.ref, onMounted: vue.onMounted };
- Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
- return __returned__;
- }
- };
- function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
- return vue.openBlock(), vue.createElementBlock("view", null, [
- vue.createElementVNode("view", {
- innerHTML: $setup.sanitizeContent($setup.formHtml)
- }, null, 8, ["innerHTML"])
- ]);
- }
- const PagesTextText = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text.vue"]]);
- const _sfc_main$3 = {
- __name: "text2",
- setup(__props, { expose: __expose }) {
- __expose();
- const socketStore = useSocketStore();
- const config = vue.ref({
- token: getToken(),
- conversationId: getCurrentSessionId()
- });
- const sendMessage = vue.ref("");
- const quickMessages = vue.ref([
- {
- label: "Ping",
- data: {
- ws_event: "ping"
- }
- },
- {
- label: "认证",
- data: {
- ws_event: "auth",
- data: {
- token: "",
- conversation_id: ""
- }
- }
- },
- {
- label: "测试消息",
- data: {
- ws_event: "message",
- data: {
- task_call_id: getTaskCallId(),
- token: getToken(),
- conversation_id: getCurrentSessionId()
- }
- }
- }
- ]);
- const connectionStatusClass = vue.computed(() => {
- const status = socketStore.connectionStatus;
- return {
- "status-connected": status === "connected",
- "status-connecting": status === "connecting",
- "status-error": status === "error",
- "status-disconnected": status === "disconnected"
- };
- });
- const handleConnect = () => {
- if (!config.value.token) {
- uni.showToast({
- title: "请输入Token",
- icon: "none"
- });
- return;
- }
- socketStore.connect({
- token: config.value.token,
- conversationId: getCurrentSessionId()
- });
- };
- const handleDisconnect = () => {
- socketStore.disconnect();
- };
- const handleSendPing = async () => {
- try {
- await socketStore.sendPing();
- } catch (e2) {
- uni.showToast({
- title: "发送失败",
- icon: "none"
- });
- }
- };
- const handleSend = async () => {
- if (!sendMessage.value.trim())
- return;
- try {
- const messageData = {
- ws_event: "message",
- data: {
- task_call_id: getTaskCallId(),
- result: {
- tools: []
- }
- }
- };
- await socketStore.send(messageData);
- sendMessage.value = "";
- } catch (e2) {
- uni.showToast({
- title: "发送失败",
- icon: "none"
- });
- }
- };
- const sendQuickMessage = async (template) => {
- const messageData = {
- ws_event: "message",
- data: {
- task_call_id: getTaskCallId(),
- token: getToken(),
- conversation_id: getCurrentSessionId()
- }
- };
- try {
- await socketStore.send(messageData);
- } catch (e2) {
- uni.showToast({
- title: "发送失败",
- icon: "none"
- });
- }
- };
- const formatJson = () => {
- if (!sendMessage.value.trim())
- return;
- try {
- const obj = JSON.parse(sendMessage.value);
- sendMessage.value = JSON.stringify(obj, null, 2);
- } catch {
- uni.showToast({
- title: "不是有效的JSON",
- icon: "none"
- });
- }
- };
- const loadMoreLogs = () => {
- };
- vue.watch(() => socketStore.isDisconnected, (newVal) => {
- if (newVal && socketStore.messageString) {
- formatAppLog("log", "at pages/text/text2.vue:253", socketStore.messageString);
- }
- });
- vue.onMounted(() => {
- socketStore.addLog("info", "=== Socket测试页面 ===");
- socketStore.addLog("info", "页面已加载");
- if (socketStore.isConnected) {
- socketStore.addLog("info", "当前已处于连接状态");
- }
- });
- vue.onUnmounted(() => {
- socketStore.addLog("info", "页面卸载");
- });
- const __returned__ = { socketStore, config, sendMessage, quickMessages, connectionStatusClass, handleConnect, handleDisconnect, handleSendPing, handleSend, sendQuickMessage, formatJson, loadMoreLogs, ref: vue.ref, computed: vue.computed, onMounted: vue.onMounted, onUnmounted: vue.onUnmounted, watch: vue.watch, get useSocketStore() {
- return useSocketStore;
- }, get getToken() {
- return getToken;
- }, get getTaskCallId() {
- return getTaskCallId;
- }, get getCurrentSessionId() {
- return getCurrentSessionId;
- } };
- Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
- return __returned__;
- }
- };
- function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
- return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [
- vue.createElementVNode("view", { class: "status-card" }, [
- vue.createElementVNode("text", { class: "status-label" }, "连接状态"),
- vue.createElementVNode(
- "view",
- {
- class: vue.normalizeClass(["status-value", $setup.connectionStatusClass])
- },
- [
- vue.createElementVNode(
- "text",
- null,
- vue.toDisplayString($setup.socketStore.getStatusText()),
- 1
- /* TEXT */
- )
- ],
- 2
- /* CLASS */
- ),
- $setup.socketStore.reconnectAttempts > 0 ? (vue.openBlock(), vue.createElementBlock("view", {
- key: 0,
- class: "status-info"
- }, [
- vue.createElementVNode(
- "text",
- { class: "reconnect-info" },
- "重连次数: " + vue.toDisplayString($setup.socketStore.reconnectAttempts),
- 1
- /* TEXT */
- )
- ])) : vue.createCommentVNode("v-if", true)
- ]),
- vue.createElementVNode("view", { class: "config-card" }, [
- vue.createElementVNode("text", { class: "section-title" }, "连接配置"),
- vue.createElementVNode("view", { class: "input-group" }, [
- vue.createElementVNode("text", { class: "input-label" }, "Token"),
- vue.withDirectives(vue.createElementVNode(
- "input",
- {
- class: "input-field",
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.config.token = $event),
- placeholder: "请输入Token"
- },
- null,
- 512
- /* NEED_PATCH */
- ), [
- [vue.vModelText, $setup.config.token]
- ])
- ]),
- vue.createElementVNode("view", { class: "input-group" }, [
- vue.createElementVNode("text", { class: "input-label" }, "Conversation ID"),
- vue.withDirectives(vue.createElementVNode(
- "input",
- {
- class: "input-field",
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $setup.config.conversationId = $event),
- placeholder: "请输入会话ID(可选)"
- },
- null,
- 512
- /* NEED_PATCH */
- ), [
- [vue.vModelText, $setup.config.conversationId]
- ])
- ])
- ]),
- vue.createElementVNode("view", { class: "control-card" }, [
- vue.createElementVNode("button", {
- class: "btn btn-primary",
- disabled: $setup.socketStore.isConnected || $setup.socketStore.isConnecting,
- onClick: $setup.handleConnect
- }, vue.toDisplayString($setup.socketStore.isConnecting ? "连接中..." : "连接"), 9, ["disabled"]),
- vue.createElementVNode("button", {
- class: "btn btn-danger",
- disabled: !$setup.socketStore.isConnected,
- onClick: $setup.handleDisconnect
- }, " 断开 ", 8, ["disabled"]),
- vue.createElementVNode("button", {
- class: "btn btn-secondary",
- onClick: $setup.handleSendPing,
- disabled: !$setup.socketStore.isConnected
- }, " Ping ", 8, ["disabled"])
- ]),
- vue.createElementVNode("view", { class: "send-card" }, [
- vue.createElementVNode("text", { class: "section-title" }, "发送消息"),
- vue.createElementVNode("view", { class: "send-input-wrapper" }, [
- vue.withDirectives(vue.createElementVNode("textarea", {
- class: "send-input",
- "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.sendMessage = $event),
- placeholder: "输入要发送的消息(JSON格式)",
- disabled: !$setup.socketStore.isConnected
- }, null, 8, ["disabled"]), [
- [vue.vModelText, $setup.sendMessage]
- ]),
- vue.createElementVNode("view", { class: "send-buttons" }, [
- vue.createElementVNode("button", {
- class: "btn btn-primary btn-small",
- disabled: !$setup.socketStore.isConnected || !$setup.sendMessage.trim(),
- onClick: $setup.handleSend
- }, " 发送 ", 8, ["disabled"]),
- vue.createElementVNode("button", {
- class: "btn btn-outline btn-small",
- disabled: !$setup.sendMessage.trim(),
- onClick: $setup.formatJson
- }, " 格式化 ", 8, ["disabled"])
- ])
- ]),
- vue.createElementVNode("view", { class: "quick-messages" }, [
- vue.createElementVNode("text", { class: "quick-label" }, "快捷消息:"),
- vue.createElementVNode("view", { class: "quick-btns" }, [
- (vue.openBlock(true), vue.createElementBlock(
- vue.Fragment,
- null,
- vue.renderList($setup.quickMessages, (item) => {
- return vue.openBlock(), vue.createElementBlock("button", {
- key: item.label,
- class: "quick-btn",
- disabled: !$setup.socketStore.isConnected,
- onClick: ($event) => $setup.sendQuickMessage(item.data)
- }, vue.toDisplayString(item.label), 9, ["disabled", "onClick"]);
- }),
- 128
- /* KEYED_FRAGMENT */
- ))
- ])
- ])
- ]),
- vue.createElementVNode("view", { class: "log-card" }, [
- vue.createElementVNode("view", { class: "log-header" }, [
- vue.createElementVNode("view", { class: "log-title-wrapper" }, [
- vue.createElementVNode("text", { class: "section-title" }, "日志"),
- vue.createElementVNode(
- "text",
- { class: "log-count" },
- "(" + vue.toDisplayString($setup.socketStore.logs.length) + ")",
- 1
- /* TEXT */
- )
- ]),
- vue.createElementVNode("view", { class: "log-actions" }, [
- vue.createElementVNode("button", {
- class: "btn btn-small btn-secondary",
- onClick: _cache[3] || (_cache[3] = (...args) => $setup.socketStore.clearLogs && $setup.socketStore.clearLogs(...args))
- }, "清空")
- ])
- ]),
- vue.createElementVNode(
- "scroll-view",
- {
- class: "log-list",
- "scroll-y": "",
- onScrolltoupper: $setup.loadMoreLogs
- },
- [
- (vue.openBlock(true), vue.createElementBlock(
- vue.Fragment,
- null,
- vue.renderList($setup.socketStore.logs, (log, index) => {
- return vue.openBlock(), vue.createElementBlock(
- "view",
- {
- key: index,
- class: vue.normalizeClass(["log-item", "log-" + log.type])
- },
- [
- vue.createElementVNode(
- "text",
- { class: "log-time" },
- vue.toDisplayString(log.time),
- 1
- /* TEXT */
- ),
- vue.createElementVNode(
- "text",
- { class: "log-content" },
- vue.toDisplayString(log.content),
- 1
- /* TEXT */
- )
- ],
- 2
- /* CLASS */
- );
- }),
- 128
- /* KEYED_FRAGMENT */
- ))
- ],
- 32
- /* NEED_HYDRATION */
- )
- ])
- ]);
- }
- const PagesTextText2 = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__scopeId", "data-v-cd5869b7"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text2.vue"]]);
- const _sfc_main$2 = {
__name: "CloudDatabase",
setup(__props, { expose: __expose }) {
__expose();
@@ -11276,7 +10758,7 @@ This will fail in production.`);
return __returned__;
}
};
- function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
+ function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0);
return vue.openBlock(), vue.createElementBlock(
vue.Fragment,
@@ -12327,8 +11809,8 @@ This will fail in production.`);
/* STABLE_FRAGMENT */
);
}
- const PagesCloudDatabaseCloudDatabase = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__scopeId", "data-v-51006ffb"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/CloudDatabase/CloudDatabase.vue"]]);
- const _sfc_main$1 = {
+ const PagesCloudDatabaseCloudDatabase = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__scopeId", "data-v-51006ffb"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/CloudDatabase/CloudDatabase.vue"]]);
+ const _sfc_main$3 = {
__name: "CloudDbDetail",
props: {
databaseId: {
@@ -12817,7 +12299,7 @@ This will fail in production.`);
return __returned__;
}
};
- function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
+ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0);
return vue.openBlock(), vue.createElementBlock("view", { class: "cloud-db-detail-wrapper" }, [
vue.createElementVNode("view", { class: "status-bar" }),
@@ -13287,17 +12769,2232 @@ This will fail in production.`);
])
]);
}
- const PagesCloudDbDetailCloudDbDetail = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-96fa4671"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/CloudDbDetail/CloudDbDetail.vue"]]);
+ const PagesCloudDbDetailCloudDbDetail = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__scopeId", "data-v-96fa4671"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/CloudDbDetail/CloudDbDetail.vue"]]);
+ const _sfc_main$2 = {
+ __name: "text",
+ setup(__props, { expose: __expose }) {
+ __expose();
+ const friendSocketStore = useFriendSocketStore();
+ const handleFriendConnect = () => {
+ if (friendSocketStore.isConnected)
+ return;
+ if (!userToken.value || !UserId.value) {
+ formatAppLog("warn", "at pages/text/text.vue:334", "Token或UserId未准备好");
+ return;
+ }
+ friendSocketStore.connect({
+ token: userToken.value,
+ UserId: UserId.value
+ });
+ };
+ const socketStore = useSocketStore();
+ const ChatType = vue.ref(0);
+ const convertMarkdownTable = (text) => {
+ const lines = text.split("\n");
+ let result = [];
+ let inTable = false;
+ let tableRows = [];
+ let alignments = [];
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i].trim();
+ const isTableLine = /^\|.+\|$/.test(line);
+ if (isTableLine) {
+ if (/^\|[\s\-:]+\|[\s\-:]+\|$/.test(line)) {
+ alignments = line.split("|").filter((c) => c.trim()).map((c) => {
+ if (c.trim().startsWith(":") && c.trim().endsWith(":"))
+ return "center";
+ if (c.trim().endsWith(":"))
+ return "right";
+ return "left";
+ });
+ continue;
+ }
+ tableRows.push(line);
+ inTable = true;
+ } else {
+ if (inTable && tableRows.length > 0) {
+ result.push(renderTable(tableRows, alignments));
+ tableRows = [];
+ alignments = [];
+ inTable = false;
+ }
+ result.push(line);
+ }
+ }
+ if (inTable && tableRows.length > 0) {
+ result.push(renderTable(tableRows, alignments));
+ }
+ return result.join("\n");
+ };
+ const renderTable = (rows, alignments) => {
+ let html = '';
+ rows.forEach((row, index) => {
+ const tag = index === 0 ? "th" : "td";
+ const cells = row.split("|").filter((c) => c.trim() !== "");
+ html += "";
+ cells.forEach((cell, ci) => {
+ const align = alignments[ci] ? ` style="text-align:${alignments[ci]}"` : "";
+ let cellContent = cell.trim().replace(/_/g, "_").replace(/\*/g, "*");
+ html += `<${tag}${align} style="padding:6px 10px;border:1px solid #ddd">${cellContent}${tag}>`;
+ });
+ html += "
";
+ });
+ html += "
";
+ return html;
+ };
+ const escapeLoneUnderscores = (text) => {
+ text = text.replace(/__/g, "\0\0");
+ text = text.replace(/_/g, "_");
+ text = text.replace(/\x00\x00/g, "__");
+ return text;
+ };
+ const pareseMarkdown = (content) => {
+ if (!content)
+ return "";
+ content = sanitizeContent(content);
+ try {
+ content = escapeLoneUnderscores(content);
+ content = convertMarkdownTable(content);
+ let html = t(content);
+ html = html.replace(
+ /]*>(.*?)<\/a>/gi,
+ '$2'
+ );
+ return html;
+ } catch (e2) {
+ formatAppLog("error", "at pages/text/text.vue:455", "解析失败", e2);
+ return content;
+ }
+ };
+ const sanitizeContent = (str) => {
+ const hasScript = /