From 8548651d80946d16e38b1a1400f0d632e6b0d287 Mon Sep 17 00:00:00 2001 From: Jafeng <2998840497@qq.com> Date: Tue, 26 May 2026 19:54:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=B8=B8=E7=94=A8?= =?UTF-8?q?=E8=AF=AD=E5=8A=9F=E8=83=BD=EF=BC=8C=E8=B0=83=E6=95=B4=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=9B=AE=E5=BD=95=E9=80=BB=E8=BE=91=E5=B9=B6=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=E5=9B=BE=E7=89=87=E5=8F=91=E9=80=81=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/message/common-phrases.vue | 196 ++++++++++++++---------- pages/message/components/chat-input.vue | 12 +- pages/message/index.vue | 154 +++++++++---------- 3 files changed, 187 insertions(+), 175 deletions(-) diff --git a/pages/message/common-phrases.vue b/pages/message/common-phrases.vue index 3453049..116f87c 100644 --- a/pages/message/common-phrases.vue +++ b/pages/message/common-phrases.vue @@ -135,7 +135,7 @@ - 收藏时请选择保存到“我的常用语”的真实目录 + 收藏时默认保存到“我的常用语 > 默认”,可调整目录 @@ -311,6 +311,8 @@ const categoryForm = ref({ name: "", }); +const DEFAULT_CATEGORY_NAME = "默认"; + const currentCategories = computed(() => { return activeTab.value === "more" ? corpCategories.value : myCategories.value; }); @@ -324,6 +326,10 @@ const firstMyCategory = computed(() => { return myCategories.value[0]; }); +const defaultMyCategory = computed(() => { + return myCategories.value.find((item) => item.name === DEFAULT_CATEGORY_NAME); +}); + const getFavoriteKey = (id) => (id ? String(id) : ""); const favoriteMap = computed(() => { @@ -380,15 +386,21 @@ const selectedCollectCategoryName = computed(() => { return myCategories.value[collectCategoryIndex.value]?.name || "请选择目录"; }); -const normalizeCategory = (item, categoryType) => ({ - id: item._id || item.id, - name: item.label || item.name || "未命名", - sort: item.sort || 0, - level: item.level || 1, - parentId: item.parentId || "", - type: categoryType, - deletable: categoryType === "user", -}); +const normalizeCategory = (item, categoryType) => { + const name = item.label || item.name || "未命名"; + const isDefault = categoryType === "user" && name === DEFAULT_CATEGORY_NAME; + + return { + id: item._id || item.id, + name, + sort: item.sort || 0, + level: item.level || 1, + parentId: item.parentId || "", + type: categoryType, + deletable: categoryType === "user" && !isDefault, + isDefault, + }; +}; const normalizeFiles = (files) => { if (!Array.isArray(files)) return []; @@ -436,7 +448,7 @@ const switchTab = (tab) => { searchKeyword.value = ""; currentCategory.value = tab === "mine" - ? firstMyCategory.value?.id || "" + ? defaultMyCategory.value?.id || firstMyCategory.value?.id || "" : corpCategories.value[0]?.id || ""; }; @@ -456,14 +468,6 @@ const sendPhrase = (phrase) => { const pages = getCurrentPages(); const prevPage = pages[pages.length - 2]; const files = normalizeFiles(phrase.files); - console.log("[common-phrases] sendPhrase click", { - phraseId: phrase?.id, - rawFiles: phrase?.files, - normalizedFiles: files, - pageCount: pages.length, - hasPrevPage: Boolean(prevPage), - hasSendCommonPhrase: Boolean(prevPage?.$vm?.sendCommonPhrase), - }); const phraseToSend = { ...phrase, files, @@ -473,14 +477,9 @@ const sendPhrase = (phrase) => { success: () => { setTimeout(() => { if (!prevPage?.$vm?.sendCommonPhrase) return; - console.log("[common-phrases] call prevPage.sendCommonPhrase", phraseToSend); const result = prevPage.$vm.sendCommonPhrase(phraseToSend); if (result && typeof result.then === "function") { - result.then(() => { - console.log("[common-phrases] prevPage.sendCommonPhrase done", { - phraseId: phrase?.id, - }); - }); + result.catch((error) => console.error("发送常用语失败:", error)); } }, 200); }, @@ -491,7 +490,7 @@ const showAddPhraseDialog = () => { editingPhrase.value = null; phraseForm.value = { content: "", - cateId: currentCategory.value || firstMyCategory.value?.id || "", + cateId: defaultMyCategory.value?.id || currentCategory.value || firstMyCategory.value?.id || "", files: [], }; showPhrasePopup.value = true; @@ -524,8 +523,12 @@ const handlePhraseFilesChange = ({ value }) => { const savePhrase = async () => { if (!phraseForm.value.cateId) { - uni.showToast({ title: "请选择目录", icon: "none" }); - return; + const category = await ensureDefaultMyCategory(); + if (!category?.id) { + uni.showToast({ title: "默认目录不存在", icon: "none" }); + return; + } + phraseForm.value.cateId = category.id; } if (!phraseForm.value.content.trim()) { uni.showToast({ title: "请输入内容", icon: "none" }); @@ -593,6 +596,77 @@ const removeMyPhrase = async (phrase) => { return result; }; +const createDefaultMyCategory = async () => { + const { corpId, userId } = getAccountParams(); + if (!corpId || !userId) return null; + + const result = await api("addUserCommonWordCate", { + label: DEFAULT_CATEGORY_NAME, + corpId, + userId, + }); + + if (!result.success) { + uni.showToast({ title: result.message || "默认目录创建失败", icon: "none" }); + return null; + } + + await loadMyCategories({ ensureDefault: false }); + return defaultMyCategory.value || firstMyCategory.value || null; +}; + +const ensureDefaultMyCategory = async () => { + if (defaultMyCategory.value?.id) return defaultMyCategory.value; + return await createDefaultMyCategory(); +}; + +const collectPhraseToCategory = async (phrase, cateId) => { + const { corpId, userId } = getAccountParams(); + const result = await api("setCommonWords", { + cateId, + content: phrase.content, + corpId, + userId, + sourceType: "common-words", + sourceCommonWordId: phrase.id, + sourceCateId: phrase.cateId, + collectClient: "wxapp", + files: normalizeFiles(phrase.files), + }); + + if (result.success) { + const collectedData = result.data || {}; + const nextPhrase = normalizePhrase({ + ...collectedData, + _id: collectedData._id || collectedData.id, + cateId: collectedData.cateId || cateId, + content: collectedData.content || phrase.content, + files: collectedData.files || normalizeFiles(phrase.files), + sourceType: collectedData.sourceType || "common-words", + sourceCommonWordId: collectedData.sourceCommonWordId || phrase.id, + sourceCateId: collectedData.sourceCateId || phrase.cateId, + collectClient: collectedData.collectClient || "wxapp", + collectTime: collectedData.collectTime || Date.now(), + }, "user"); + + if (nextPhrase.id) { + const favoriteKey = getFavoriteKey(phrase.id); + const index = myPhrases.value.findIndex((item) => { + return item.id === nextPhrase.id || getFavoriteKey(item.sourceCommonWordId) === favoriteKey; + }); + if (index > -1) { + myPhrases.value.splice(index, 1, nextPhrase); + } else { + myPhrases.value.unshift(nextPhrase); + } + } else { + await loadMyPhrases(); + } + } + + return result; +}; + const deletePhrase = (phrase) => { uni.showModal({ title: "提示", @@ -633,13 +707,14 @@ const toggleFavorite = async (phrase) => { return; } - if (myCategories.value.length === 0) { - uni.showToast({ title: "请先新增目录", icon: "none" }); + const category = await ensureDefaultMyCategory(); + if (!category?.id) { + uni.showToast({ title: "默认目录不存在", icon: "none" }); return; } collectingPhrase.value = phrase; - collectForm.value.cateId = firstMyCategory.value?.id || ""; + collectForm.value.cateId = category.id; showCollectPopup.value = true; } catch (error) { console.error("收藏操作失败:", error); @@ -664,54 +739,9 @@ const confirmFavorite = async () => { return; } - const { corpId, userId } = getAccountParams(); - if (!corpId || !userId) { - uni.showToast({ title: "请先登录", icon: "none" }); - return; - } - try { - const result = await api("setCommonWords", { - cateId: collectForm.value.cateId, - content: phrase.content, - corpId, - userId, - sourceType: "common-words", - sourceCommonWordId: phrase.id, - sourceCateId: phrase.cateId, - collectClient: "wxapp", - files: normalizeFiles(phrase.files), - }); - + const result = await collectPhraseToCategory(phrase, collectForm.value.cateId); if (result.success) { - const collectedData = result.data || {}; - const nextPhrase = normalizePhrase({ - ...collectedData, - _id: collectedData._id || collectedData.id, - cateId: collectedData.cateId || collectForm.value.cateId, - content: collectedData.content || phrase.content, - files: collectedData.files || normalizeFiles(phrase.files), - sourceType: collectedData.sourceType || "common-words", - sourceCommonWordId: collectedData.sourceCommonWordId || phrase.id, - sourceCateId: collectedData.sourceCateId || phrase.cateId, - collectClient: collectedData.collectClient || "wxapp", - collectTime: collectedData.collectTime || Date.now(), - }, "user"); - - if (nextPhrase.id) { - const favoriteKey = getFavoriteKey(phrase.id); - const index = myPhrases.value.findIndex((item) => { - return item.id === nextPhrase.id || getFavoriteKey(item.sourceCommonWordId) === favoriteKey; - }); - if (index > -1) { - myPhrases.value.splice(index, 1, nextPhrase); - } else { - myPhrases.value.unshift(nextPhrase); - } - } else { - await loadMyPhrases(); - } - uni.showToast({ title: "收藏成功", icon: "success" }); closeCollectPopup(); } else { @@ -730,6 +760,8 @@ const showAddCategoryDialog = () => { }; const editCategory = (category) => { + if (!category.deletable) return; + editingCategory.value = category; categoryForm.value.name = category.name; showCategoryPopup.value = true; @@ -797,7 +829,7 @@ const deleteCategory = async (category) => { if (result.success) { await loadMyCategories(); await loadMyPhrases(); - currentCategory.value = firstMyCategory.value?.id || ""; + currentCategory.value = defaultMyCategory.value?.id || firstMyCategory.value?.id || ""; uni.showToast({ title: "删除成功", icon: "success" }); } else { uni.showToast({ title: result.message || "删除失败", icon: "none" }); @@ -824,14 +856,18 @@ const closeCategoryPopup = () => { editingCategory.value = null; }; -const loadMyCategories = async () => { +const loadMyCategories = async ({ ensureDefault = true } = {}) => { const { corpId, userId } = getAccountParams(); const result = await api("getUserCommonWordCate", { corpId, userId }); if (result.success) { const list = Array.isArray(result.list) ? result.list : []; myCategories.value = list.map((item) => normalizeCategory(item, "user")).filter((item) => item.id); + if (ensureDefault && !defaultMyCategory.value) { + await createDefaultMyCategory(); + return; + } if (activeTab.value === "mine") { - currentCategory.value = currentCategory.value || firstMyCategory.value?.id || ""; + currentCategory.value = currentCategory.value || defaultMyCategory.value?.id || firstMyCategory.value?.id || ""; } } else { uni.showToast({ title: result.message || "加载失败", icon: "none" }); diff --git a/pages/message/components/chat-input.vue b/pages/message/components/chat-input.vue index fbb9005..a4b5429 100644 --- a/pages/message/components/chat-input.vue +++ b/pages/message/components/chat-input.vue @@ -208,9 +208,7 @@ const normalizePhraseImageFile = (file) => { ? file : file?.url || file?.URL || file?.download_url || file?.tempFilePath || file?.path; - console.log("[chat-input] normalizePhraseImageFile start", { file, imageUrl }); if (!imageUrl) { - console.log("[chat-input] normalizePhraseImageFile missing imageUrl", { file }); resolve(null); return; } @@ -231,21 +229,18 @@ const normalizePhraseImageFile = (file) => { }); if (/^https?:\/\//.test(imageUrl)) { - console.log("[chat-input] download phrase image", { imageUrl }); uni.downloadFile({ url: imageUrl, success: (res) => { - console.log("[chat-input] download phrase image success", res); if (res.statusCode === 200 && res.tempFilePath) { const imageFile = makeImageFile(res.tempFilePath, file?.size || 0); - console.log("[chat-input] normalized downloaded phrase image", imageFile); resolve(imageFile); } else { resolve(null); } }, fail: (error) => { - console.log("[chat-input] download phrase image fail", error); + console.error("常用语图片下载失败:", error); resolve(null); }, }); @@ -253,23 +248,18 @@ const normalizePhraseImageFile = (file) => { } const imageFile = makeImageFile(imageUrl, file?.size || 0); - console.log("[chat-input] normalized local phrase image", imageFile); resolve(imageFile); }); }; const sendImageMessageFromPhrase = async (file) => { - console.log("[chat-input] sendImageMessageFromPhrase start", { file }); const imageFile = await normalizePhraseImageFile(file); if (!imageFile) { - console.log("[chat-input] sendImageMessageFromPhrase normalize failed", { file }); uni.showToast({ title: "图片发送失败", icon: "none" }); return; } - console.log("[chat-input] sendImageMessageFromPhrase call sendImageMessage", imageFile); await sendImageMessage(imageFile); - console.log("[chat-input] sendImageMessageFromPhrase done", imageFile); }; // 设置输入框文本(覆盖原内容) diff --git a/pages/message/index.vue b/pages/message/index.vue index 0646971..926aa1c 100644 --- a/pages/message/index.vue +++ b/pages/message/index.vue @@ -3,22 +3,22 @@ - - {{ patientInfo.name }} - {{ patientInfo.sex }} · {{ patientInfo.age }}岁 - - - - 查看档案 - - - 接收提醒 - - - - + + {{ patientInfo.name }} + {{ patientInfo.sex }} · {{ patientInfo.age }}岁 + + + + 查看档案 + + + 接收提醒 + + + + { }); const sendCommonPhrase = async (phraseOrContent) => { - console.log("[message-index] sendCommonPhrase start", phraseOrContent); if (!chatInputRef.value) return; - - const content = - typeof phraseOrContent === "string" + + const content = + typeof phraseOrContent === "string" ? phraseOrContent : phraseOrContent?.content || ""; const files = Array.isArray(phraseOrContent?.files) ? phraseOrContent.files : []; - console.log("[message-index] sendCommonPhrase parsed", { - hasChatInputRef: Boolean(chatInputRef.value), - contentLength: content.length, - files, - fileCount: files.length, - }); if (content.trim()) { - console.log("[message-index] sendCommonPhrase set input text"); chatInputRef.value.setInputText(content); } if (files.length === 0) { - console.log("[message-index] sendCommonPhrase done without images"); return; } const shouldSendImages = await new Promise((resolve) => { - console.log("[message-index] confirm phrase images open", { count: files.length }); uni.showModal({ - title: "提示", - content: `该常用语包含${files.length}张图片,是否发送图片?`, - cancelText: "不发", + title: "提示", + content: `该常用语包含${files.length}张图片,是否发送图片?`, + cancelText: "取消", confirmText: "发送", success: (res) => { - console.log("[message-index] confirm phrase images success", res); resolve(Boolean(res.confirm)); }, fail: (error) => { - console.log("[message-index] confirm phrase images fail", error); + console.error("常用语图片发送确认失败:", error); resolve(false); }, - }); - }); + }); + }); if (!shouldSendImages) { - console.log("[message-index] sendCommonPhrase skip images"); return; } - for (const [index, file] of files.entries()) { - console.log("[message-index] sendCommonPhrase send image", { index, file }); + for (const file of files) { await chatInputRef.value.sendImageMessageFromPhrase(file); } - console.log("[message-index] sendCommonPhrase done"); }; // 处理流式文本输入 @@ -1303,42 +1289,42 @@ const handleRejectReasonCancel = () => { }; // 处理查看患者详情 -const handleViewPatientDetail = () => { - if (!patientId.value) { - uni.showToast({ - title: "患者信息不完整", +const handleViewPatientDetail = () => { + if (!patientId.value) { + uni.showToast({ + title: "患者信息不完整", icon: "none", }); return; } - uni.navigateTo({ - url: `/pages/case/archive-detail?id=${patientId.value}`, - }); -}; - -const handleSubscribeReminder = async () => { - await requestConversationSubscribeMessage({ - role: SUBSCRIBE_MESSAGE_ROLE.DOCTOR, - scene: SUBSCRIBE_MESSAGE_SCENE.CHAT, - conversationId: chatInfo.value.conversationID || "", - groupId: groupId.value || "", - corpId: corpId || "", - teamId: teamId.value || "", - patientId: patientId.value || "", - doctorId: doctorInfo.value?.userid || "", - userId: doctorInfo.value?.userid || account.value?.userId || "", - openid: openid.value || account.value?.openid || "", - unionid: account.value?.unionid || "", - extraData: { - orderStatus: orderStatus.value || "", - page: "pages/message/index", - }, - }); -}; - -// 处理结束问诊 -const handleEndConsult = async () => { + uni.navigateTo({ + url: `/pages/case/archive-detail?id=${patientId.value}`, + }); +}; + +const handleSubscribeReminder = async () => { + await requestConversationSubscribeMessage({ + role: SUBSCRIBE_MESSAGE_ROLE.DOCTOR, + scene: SUBSCRIBE_MESSAGE_SCENE.CHAT, + conversationId: chatInfo.value.conversationID || "", + groupId: groupId.value || "", + corpId: corpId || "", + teamId: teamId.value || "", + patientId: patientId.value || "", + doctorId: doctorInfo.value?.userid || "", + userId: doctorInfo.value?.userid || account.value?.userId || "", + openid: openid.value || account.value?.openid || "", + unionid: account.value?.unionid || "", + extraData: { + orderStatus: orderStatus.value || "", + page: "pages/message/index", + }, + }); +}; + +// 处理结束问诊 +const handleEndConsult = async () => { try { uni.showLoading({ title: "处理中...",