feat: 优化常用语功能,调整默认目录逻辑并增强图片发送确认提示

This commit is contained in:
Jafeng 2026-05-26 19:54:08 +08:00
parent 371801a758
commit 8548651d80
3 changed files with 187 additions and 175 deletions

View File

@ -135,7 +135,7 @@
</view> </view>
<view v-if="activeTab === 'more' && currentPhrases.length > 0" class="collect-tip"> <view v-if="activeTab === 'more' && currentPhrases.length > 0" class="collect-tip">
收藏时请选择保存到我的常用语的真实目录 收藏时默认保存到我的常用语 > 默认可调整目录
</view> </view>
</scroll-view> </scroll-view>
@ -311,6 +311,8 @@ const categoryForm = ref({
name: "", name: "",
}); });
const DEFAULT_CATEGORY_NAME = "默认";
const currentCategories = computed(() => { const currentCategories = computed(() => {
return activeTab.value === "more" ? corpCategories.value : myCategories.value; return activeTab.value === "more" ? corpCategories.value : myCategories.value;
}); });
@ -324,6 +326,10 @@ const firstMyCategory = computed(() => {
return myCategories.value[0]; return myCategories.value[0];
}); });
const defaultMyCategory = computed(() => {
return myCategories.value.find((item) => item.name === DEFAULT_CATEGORY_NAME);
});
const getFavoriteKey = (id) => (id ? String(id) : ""); const getFavoriteKey = (id) => (id ? String(id) : "");
const favoriteMap = computed(() => { const favoriteMap = computed(() => {
@ -380,15 +386,21 @@ const selectedCollectCategoryName = computed(() => {
return myCategories.value[collectCategoryIndex.value]?.name || "请选择目录"; return myCategories.value[collectCategoryIndex.value]?.name || "请选择目录";
}); });
const normalizeCategory = (item, categoryType) => ({ const normalizeCategory = (item, categoryType) => {
id: item._id || item.id, const name = item.label || item.name || "未命名";
name: item.label || item.name || "未命名", const isDefault = categoryType === "user" && name === DEFAULT_CATEGORY_NAME;
sort: item.sort || 0,
level: item.level || 1, return {
parentId: item.parentId || "", id: item._id || item.id,
type: categoryType, name,
deletable: categoryType === "user", sort: item.sort || 0,
}); level: item.level || 1,
parentId: item.parentId || "",
type: categoryType,
deletable: categoryType === "user" && !isDefault,
isDefault,
};
};
const normalizeFiles = (files) => { const normalizeFiles = (files) => {
if (!Array.isArray(files)) return []; if (!Array.isArray(files)) return [];
@ -436,7 +448,7 @@ const switchTab = (tab) => {
searchKeyword.value = ""; searchKeyword.value = "";
currentCategory.value = currentCategory.value =
tab === "mine" tab === "mine"
? firstMyCategory.value?.id || "" ? defaultMyCategory.value?.id || firstMyCategory.value?.id || ""
: corpCategories.value[0]?.id || ""; : corpCategories.value[0]?.id || "";
}; };
@ -456,14 +468,6 @@ const sendPhrase = (phrase) => {
const pages = getCurrentPages(); const pages = getCurrentPages();
const prevPage = pages[pages.length - 2]; const prevPage = pages[pages.length - 2];
const files = normalizeFiles(phrase.files); 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 = { const phraseToSend = {
...phrase, ...phrase,
files, files,
@ -473,14 +477,9 @@ const sendPhrase = (phrase) => {
success: () => { success: () => {
setTimeout(() => { setTimeout(() => {
if (!prevPage?.$vm?.sendCommonPhrase) return; if (!prevPage?.$vm?.sendCommonPhrase) return;
console.log("[common-phrases] call prevPage.sendCommonPhrase", phraseToSend);
const result = prevPage.$vm.sendCommonPhrase(phraseToSend); const result = prevPage.$vm.sendCommonPhrase(phraseToSend);
if (result && typeof result.then === "function") { if (result && typeof result.then === "function") {
result.then(() => { result.catch((error) => console.error("发送常用语失败:", error));
console.log("[common-phrases] prevPage.sendCommonPhrase done", {
phraseId: phrase?.id,
});
});
} }
}, 200); }, 200);
}, },
@ -491,7 +490,7 @@ const showAddPhraseDialog = () => {
editingPhrase.value = null; editingPhrase.value = null;
phraseForm.value = { phraseForm.value = {
content: "", content: "",
cateId: currentCategory.value || firstMyCategory.value?.id || "", cateId: defaultMyCategory.value?.id || currentCategory.value || firstMyCategory.value?.id || "",
files: [], files: [],
}; };
showPhrasePopup.value = true; showPhrasePopup.value = true;
@ -524,8 +523,12 @@ const handlePhraseFilesChange = ({ value }) => {
const savePhrase = async () => { const savePhrase = async () => {
if (!phraseForm.value.cateId) { if (!phraseForm.value.cateId) {
uni.showToast({ title: "请选择目录", icon: "none" }); const category = await ensureDefaultMyCategory();
return; if (!category?.id) {
uni.showToast({ title: "默认目录不存在", icon: "none" });
return;
}
phraseForm.value.cateId = category.id;
} }
if (!phraseForm.value.content.trim()) { if (!phraseForm.value.content.trim()) {
uni.showToast({ title: "请输入内容", icon: "none" }); uni.showToast({ title: "请输入内容", icon: "none" });
@ -593,6 +596,77 @@ const removeMyPhrase = async (phrase) => {
return result; 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) => { const deletePhrase = (phrase) => {
uni.showModal({ uni.showModal({
title: "提示", title: "提示",
@ -633,13 +707,14 @@ const toggleFavorite = async (phrase) => {
return; return;
} }
if (myCategories.value.length === 0) { const category = await ensureDefaultMyCategory();
uni.showToast({ title: "请先新增目录", icon: "none" }); if (!category?.id) {
uni.showToast({ title: "默认目录不存在", icon: "none" });
return; return;
} }
collectingPhrase.value = phrase; collectingPhrase.value = phrase;
collectForm.value.cateId = firstMyCategory.value?.id || ""; collectForm.value.cateId = category.id;
showCollectPopup.value = true; showCollectPopup.value = true;
} catch (error) { } catch (error) {
console.error("收藏操作失败:", error); console.error("收藏操作失败:", error);
@ -664,54 +739,9 @@ const confirmFavorite = async () => {
return; return;
} }
const { corpId, userId } = getAccountParams();
if (!corpId || !userId) {
uni.showToast({ title: "请先登录", icon: "none" });
return;
}
try { try {
const result = await api("setCommonWords", { const result = await collectPhraseToCategory(phrase, collectForm.value.cateId);
cateId: collectForm.value.cateId,
content: phrase.content,
corpId,
userId,
sourceType: "common-words",
sourceCommonWordId: phrase.id,
sourceCateId: phrase.cateId,
collectClient: "wxapp",
files: normalizeFiles(phrase.files),
});
if (result.success) { 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" }); uni.showToast({ title: "收藏成功", icon: "success" });
closeCollectPopup(); closeCollectPopup();
} else { } else {
@ -730,6 +760,8 @@ const showAddCategoryDialog = () => {
}; };
const editCategory = (category) => { const editCategory = (category) => {
if (!category.deletable) return;
editingCategory.value = category; editingCategory.value = category;
categoryForm.value.name = category.name; categoryForm.value.name = category.name;
showCategoryPopup.value = true; showCategoryPopup.value = true;
@ -797,7 +829,7 @@ const deleteCategory = async (category) => {
if (result.success) { if (result.success) {
await loadMyCategories(); await loadMyCategories();
await loadMyPhrases(); await loadMyPhrases();
currentCategory.value = firstMyCategory.value?.id || ""; currentCategory.value = defaultMyCategory.value?.id || firstMyCategory.value?.id || "";
uni.showToast({ title: "删除成功", icon: "success" }); uni.showToast({ title: "删除成功", icon: "success" });
} else { } else {
uni.showToast({ title: result.message || "删除失败", icon: "none" }); uni.showToast({ title: result.message || "删除失败", icon: "none" });
@ -824,14 +856,18 @@ const closeCategoryPopup = () => {
editingCategory.value = null; editingCategory.value = null;
}; };
const loadMyCategories = async () => { const loadMyCategories = async ({ ensureDefault = true } = {}) => {
const { corpId, userId } = getAccountParams(); const { corpId, userId } = getAccountParams();
const result = await api("getUserCommonWordCate", { corpId, userId }); const result = await api("getUserCommonWordCate", { corpId, userId });
if (result.success) { if (result.success) {
const list = Array.isArray(result.list) ? result.list : []; const list = Array.isArray(result.list) ? result.list : [];
myCategories.value = list.map((item) => normalizeCategory(item, "user")).filter((item) => item.id); myCategories.value = list.map((item) => normalizeCategory(item, "user")).filter((item) => item.id);
if (ensureDefault && !defaultMyCategory.value) {
await createDefaultMyCategory();
return;
}
if (activeTab.value === "mine") { if (activeTab.value === "mine") {
currentCategory.value = currentCategory.value || firstMyCategory.value?.id || ""; currentCategory.value = currentCategory.value || defaultMyCategory.value?.id || firstMyCategory.value?.id || "";
} }
} else { } else {
uni.showToast({ title: result.message || "加载失败", icon: "none" }); uni.showToast({ title: result.message || "加载失败", icon: "none" });

View File

@ -208,9 +208,7 @@ const normalizePhraseImageFile = (file) => {
? file ? file
: file?.url || file?.URL || file?.download_url || file?.tempFilePath || file?.path; : file?.url || file?.URL || file?.download_url || file?.tempFilePath || file?.path;
console.log("[chat-input] normalizePhraseImageFile start", { file, imageUrl });
if (!imageUrl) { if (!imageUrl) {
console.log("[chat-input] normalizePhraseImageFile missing imageUrl", { file });
resolve(null); resolve(null);
return; return;
} }
@ -231,21 +229,18 @@ const normalizePhraseImageFile = (file) => {
}); });
if (/^https?:\/\//.test(imageUrl)) { if (/^https?:\/\//.test(imageUrl)) {
console.log("[chat-input] download phrase image", { imageUrl });
uni.downloadFile({ uni.downloadFile({
url: imageUrl, url: imageUrl,
success: (res) => { success: (res) => {
console.log("[chat-input] download phrase image success", res);
if (res.statusCode === 200 && res.tempFilePath) { if (res.statusCode === 200 && res.tempFilePath) {
const imageFile = makeImageFile(res.tempFilePath, file?.size || 0); const imageFile = makeImageFile(res.tempFilePath, file?.size || 0);
console.log("[chat-input] normalized downloaded phrase image", imageFile);
resolve(imageFile); resolve(imageFile);
} else { } else {
resolve(null); resolve(null);
} }
}, },
fail: (error) => { fail: (error) => {
console.log("[chat-input] download phrase image fail", error); console.error("常用语图片下载失败:", error);
resolve(null); resolve(null);
}, },
}); });
@ -253,23 +248,18 @@ const normalizePhraseImageFile = (file) => {
} }
const imageFile = makeImageFile(imageUrl, file?.size || 0); const imageFile = makeImageFile(imageUrl, file?.size || 0);
console.log("[chat-input] normalized local phrase image", imageFile);
resolve(imageFile); resolve(imageFile);
}); });
}; };
const sendImageMessageFromPhrase = async (file) => { const sendImageMessageFromPhrase = async (file) => {
console.log("[chat-input] sendImageMessageFromPhrase start", { file });
const imageFile = await normalizePhraseImageFile(file); const imageFile = await normalizePhraseImageFile(file);
if (!imageFile) { if (!imageFile) {
console.log("[chat-input] sendImageMessageFromPhrase normalize failed", { file });
uni.showToast({ title: "图片发送失败", icon: "none" }); uni.showToast({ title: "图片发送失败", icon: "none" });
return; return;
} }
console.log("[chat-input] sendImageMessageFromPhrase call sendImageMessage", imageFile);
await sendImageMessage(imageFile); await sendImageMessage(imageFile);
console.log("[chat-input] sendImageMessageFromPhrase done", imageFile);
}; };
// //

View File

@ -993,7 +993,6 @@ onHide(() => {
}); });
const sendCommonPhrase = async (phraseOrContent) => { const sendCommonPhrase = async (phraseOrContent) => {
console.log("[message-index] sendCommonPhrase start", phraseOrContent);
if (!chatInputRef.value) return; if (!chatInputRef.value) return;
const content = const content =
@ -1001,51 +1000,38 @@ const sendCommonPhrase = async (phraseOrContent) => {
? phraseOrContent ? phraseOrContent
: phraseOrContent?.content || ""; : phraseOrContent?.content || "";
const files = Array.isArray(phraseOrContent?.files) ? phraseOrContent.files : []; 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()) { if (content.trim()) {
console.log("[message-index] sendCommonPhrase set input text");
chatInputRef.value.setInputText(content); chatInputRef.value.setInputText(content);
} }
if (files.length === 0) { if (files.length === 0) {
console.log("[message-index] sendCommonPhrase done without images");
return; return;
} }
const shouldSendImages = await new Promise((resolve) => { const shouldSendImages = await new Promise((resolve) => {
console.log("[message-index] confirm phrase images open", { count: files.length });
uni.showModal({ uni.showModal({
title: "提示", title: "提示",
content: `该常用语包含${files.length}张图片,是否发送图片?`, content: `该常用语包含${files.length}张图片,是否发送图片?`,
cancelText: "不发", cancelText: "取消",
confirmText: "发送", confirmText: "发送",
success: (res) => { success: (res) => {
console.log("[message-index] confirm phrase images success", res);
resolve(Boolean(res.confirm)); resolve(Boolean(res.confirm));
}, },
fail: (error) => { fail: (error) => {
console.log("[message-index] confirm phrase images fail", error); console.error("常用语图片发送确认失败:", error);
resolve(false); resolve(false);
}, },
}); });
}); });
if (!shouldSendImages) { if (!shouldSendImages) {
console.log("[message-index] sendCommonPhrase skip images");
return; return;
} }
for (const [index, file] of files.entries()) { for (const file of files) {
console.log("[message-index] sendCommonPhrase send image", { index, file });
await chatInputRef.value.sendImageMessageFromPhrase(file); await chatInputRef.value.sendImageMessageFromPhrase(file);
} }
console.log("[message-index] sendCommonPhrase done");
}; };
// //