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: "处理中...",