diff --git a/pages/message/common-phrases.vue b/pages/message/common-phrases.vue index aca2274..f338ded 100644 --- a/pages/message/common-phrases.vue +++ b/pages/message/common-phrases.vue @@ -82,6 +82,16 @@ 已收藏 + + + @@ -168,6 +178,23 @@ :auto-height="false" > {{ phraseForm.content.length }}/500 + + + + + + × + + + + + + + @@ -200,6 +227,16 @@ 收藏后将添加到所选目录 {{ collectingPhrase?.content || "" }} + + + @@ -239,6 +276,7 @@ import { ref, computed, onMounted } from "vue"; import { storeToRefs } from "pinia"; import api from "@/utils/api"; import useAccountStore from "@/store/account"; +import { chooseAndUploadImage, normalizeFileUrl } from "@/utils/file"; const { doctorInfo } = storeToRefs(useAccountStore()); @@ -262,6 +300,7 @@ const collectingPhrase = ref(null); const phraseForm = ref({ content: "", cateId: "", + files: [], }); const collectForm = ref({ @@ -348,12 +387,29 @@ const normalizeCategory = (item, categoryType) => ({ deletable: categoryType === "user", }); +const normalizeFiles = (files) => { + if (!Array.isArray(files)) return []; + return files + .map((item) => { + if (typeof item === "string") return { type: "image", url: normalizeFileUrl(item) }; + const url = item?.url || item?.URL || item?.download_url; + if (!url) return null; + return { + type: item.type || "image", + url: normalizeFileUrl(url), + name: item.name || item.fileName || "", + }; + }) + .filter(Boolean); +}; + const normalizePhrase = (item, phraseType) => ({ id: item._id || item.id, cateId: item.cateId || item.categoryId, content: item.content || "", createTime: item.createTime, updateTime: item.updateTime, + files: normalizeFiles(item.files), sourceType: item.sourceType, sourceCommonWordId: item.sourceCommonWordId, sourceCateId: item.sourceCateId, @@ -398,7 +454,7 @@ const sendPhrase = (phrase) => { const prevPage = pages[pages.length - 2]; if (prevPage) { - prevPage.$vm.sendCommonPhrase(phrase.content); + prevPage.$vm.sendCommonPhrase(phrase); } uni.navigateBack(); @@ -409,6 +465,7 @@ const showAddPhraseDialog = () => { phraseForm.value = { content: "", cateId: currentCategory.value || firstMyCategory.value?.id || "", + files: [], }; showPhrasePopup.value = true; }; @@ -418,6 +475,7 @@ const editPhrase = (phrase) => { phraseForm.value = { content: phrase.content, cateId: phrase.cateId || firstMyCategory.value?.id || "", + files: normalizeFiles(phrase.files), }; showPhrasePopup.value = true; }; @@ -427,6 +485,26 @@ const handlePhraseCategoryChange = (event) => { phraseForm.value.cateId = myCategories.value[index]?.id || ""; }; +const previewFiles = (files, index = 0) => { + const urls = normalizeFiles(files).map((item) => item.url).filter(Boolean); + if (!urls.length) return; + uni.previewImage({ urls, current: urls[index] || urls[0] }); +}; + +const addPhraseImage = async () => { + if (phraseForm.value.files.length >= 9) { + uni.showToast({ title: "最多上传9张图片", icon: "none" }); + return; + } + const url = await chooseAndUploadImage({ count: 1 }); + if (!url) return; + phraseForm.value.files.push({ type: "image", url: normalizeFileUrl(url), name: "图片" }); +}; + +const removePhraseImage = (index) => { + phraseForm.value.files.splice(index, 1); +}; + const savePhrase = async () => { if (!phraseForm.value.cateId) { uni.showToast({ title: "请选择目录", icon: "none" }); @@ -448,6 +526,7 @@ const savePhrase = async () => { id: editingPhrase.value?.id, cateId: phraseForm.value.cateId, content: phraseForm.value.content, + files: normalizeFiles(phraseForm.value.files), corpId, userId, }); @@ -459,6 +538,7 @@ const savePhrase = async () => { _id: editingPhrase.value?.id || result.data?._id, cateId: phraseForm.value.cateId, content: phraseForm.value.content.trim(), + files: normalizeFiles(phraseForm.value.files), }, "user"); if (editingPhrase.value) { @@ -583,6 +663,7 @@ const confirmFavorite = async () => { sourceCommonWordId: phrase.id, sourceCateId: phrase.cateId, collectClient: "wxapp", + files: normalizeFiles(phrase.files), }); if (result.success && result.data) { @@ -1071,6 +1152,20 @@ $border-color: #edf0f5; } } +.phrase-images { + display: flex; + flex-wrap: wrap; + gap: 12rpx; + margin-top: 18rpx; +} + +.phrase-image { + width: 96rpx; + height: 96rpx; + border-radius: 10rpx; + background: #f2f4f7; +} + .collect-tip { padding: 8rpx 0 28rpx; color: #98a2b3; @@ -1235,6 +1330,60 @@ $border-color: #edf0f5; border: 1px solid $border-color; } +.collect-images { + margin: -14rpx 0 32rpx; +} + +.image-grid { + display: flex; + flex-wrap: wrap; + gap: 16rpx; + margin-bottom: 30rpx; +} + +.image-item, +.image-add { + position: relative; + width: 142rpx; + height: 142rpx; + border-radius: 12rpx; + overflow: hidden; + background: #f7f8fb; +} + +.image-thumb { + width: 100%; + height: 100%; +} + +.image-remove { + position: absolute; + top: 6rpx; + right: 6rpx; + width: 34rpx; + height: 34rpx; + line-height: 34rpx; + text-align: center; + color: #fff; + font-size: 26rpx; + border-radius: 50%; + background: rgba(0, 0, 0, 0.55); +} + +.image-add { + display: flex; + align-items: center; + justify-content: center; + color: #98a2b3; + border: 1px dashed #cfd3dc; + box-sizing: border-box; +} + +.image-add-icon { + font-size: 52rpx; + line-height: 52rpx; +} + .phrase-textarea { width: 100%; height: 220rpx; diff --git a/pages/message/index.vue b/pages/message/index.vue index d3a1250..67e16a5 100644 --- a/pages/message/index.vue +++ b/pages/message/index.vue @@ -992,12 +992,13 @@ onHide(() => { console.log("✓ 页面隐藏,已清空当前会话ID"); }); -const sendCommonPhrase = (content) => { - if (chatInputRef.value) { - // 覆盖输入框内容,而不是直接发送 - chatInputRef.value.setInputText(content); - } -}; +const sendCommonPhrase = (phraseOrContent) => { + const content = typeof phraseOrContent === "string" ? phraseOrContent : phraseOrContent?.content || ""; + if (chatInputRef.value) { + // 覆盖输入框内容,而不是直接发送 + chatInputRef.value.setInputText(content); + } +}; // 处理流式文本输入 const handleStreamText = (char) => {