From d70750c7ee7e7b31c73d3ad2d988565cfe33d0fb Mon Sep 17 00:00:00 2001 From: Jafeng <2998840497@qq.com> Date: Tue, 10 Feb 2026 16:12:24 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=9B=9E=E8=AE=BF?= =?UTF-8?q?=E8=AE=A1=E5=88=92=E6=98=BE=E7=A4=BAbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../archive-detail/follow-up-manage-tab.vue | 333 +++++++++++++----- 1 file changed, 251 insertions(+), 82 deletions(-) diff --git a/pages/case/components/archive-detail/follow-up-manage-tab.vue b/pages/case/components/archive-detail/follow-up-manage-tab.vue index 50ceea6..80f22ae 100644 --- a/pages/case/components/archive-detail/follow-up-manage-tab.vue +++ b/pages/case/components/archive-detail/follow-up-manage-tab.vue @@ -91,13 +91,11 @@ { if (loading.value) return "loading"; @@ -383,11 +380,43 @@ function resolveUserName(userId) { } function refreshChatRoom() { - if (!props.fromChat) return; - const pending = uni.getStorageSync(PENDING_FOLLOWUP_SEND_STORAGE_KEY); - if (pending && typeof pending === "object") { - chatGroupId.value = String(pending.chatGroupId || pending.groupId || ""); + // 兼容:优先用档案详情数据里已有的 chatGroupId + const fromArchive = + props?.data && typeof props.data === "object" ? props.data : {}; + const direct = String(fromArchive?.chatGroupId || fromArchive?.groupId || ""); + if (direct) { + chatGroupId.value = direct; + return; } + + // 如果没有,走接口探测可用会话 + refreshChatRoomByApi(); +} + +function getConversationIdForChat(groupId) { + const gid = normalizeGroupId(groupId || ""); + return gid ? `GROUP${gid}` : ""; +} + +function hasSendContent(todo) { + return ( + Boolean(todo?.sendContent) || + (Array.isArray(todo?.fileList) && todo.fileList.length > 0) + ); +} + +function isExecutorMe(todo) { + const me = String(getUserId() || ""); + const executor = String(todo?.executorUserId || ""); + if (!me || !executor) return false; + return me === executor; +} + +function canShowSendButton(todo) { + if (!hasSendContent(todo)) return false; + if (!isExecutorMe(todo)) return false; + // 当前患者无会话则不展示 + return Boolean(currentChatGroupId.value); } function formatTodo(todo) { @@ -558,90 +587,153 @@ function toDetail(todo) { }); } -async function sendFollowUp(todo) { - if (sendingFollowUp.value) { - toast("正在发送中,请稍候..."); - return; +function buildFollowUpMessages(todo) { + const messages = []; + if (todo?.sendContent) { + messages.push({ type: "text", content: String(todo.sendContent) }); } - if (!todo.sendContent && (!todo.fileList || todo.fileList.length === 0)) { - toast("没有发送内容"); - return; - } + if (Array.isArray(todo?.fileList)) { + for (const file of todo.fileList) { + const outerType = String(file?.type || ""); - sendingFollowUp.value = true; - try { - const messages = []; - - // 1. 发送文字内容 - if (todo.sendContent) { - messages.push({ - type: "text", - content: todo.sendContent, - }); - } - console.log("==============>fileList", todo.fileList); - - // 2. 处理文件列表(图片、宣教文章、问卷) - if (Array.isArray(todo.fileList)) { - for (const file of todo.fileList) { - if (file.type === "image" && file.URL) { - // 发送图片 - messages.push({ - type: "image", - content: file.URL, - name: file.file?.name || file.name || "图片", - }); - } else if (file.file.type === "article" && file.file?.url) { - // 发送宣教文章 - 从 URL 中解析 id - const articleId = extractIdFromUrl(file.file.url); - messages.push({ - type: "article", - content: { - _id: articleId, - title: file.file?.name || "宣教文章", - url: file.file?.url || file.URL, - subtitle: file.file?.subtitle || "", - cover: file.file?.cover || "", - articleId: articleId, - }, - }); - } else if ( - file.file.type === "questionnaire" && - (file.file?.url || file.URL) - ) { - // 发送问卷 - 从 URL 中解析 surveryId - const surveryUrl = file.file?.url || file.URL; - const surveryId = extractSurveryIdFromUrl(surveryUrl); - messages.push({ - type: "questionnaire", - content: { - _id: surveryId, - name: file.file?.name || file.name || "问卷", - surveryId: surveryId, - url: surveryUrl, - }, - }); + let innerFile = file?.file; + if (typeof innerFile === "string") { + try { + innerFile = JSON.parse(innerFile); + } catch { + // ignore } } - } + innerFile = innerFile && typeof innerFile === "object" ? innerFile : null; - // 调用统一的消息发送处理函数 - const success = await handleFollowUpMessages(messages, { + const innerType = String(innerFile?.type || ""); + const outerUrl = String(file?.URL || file?.url || ""); + const innerUrl = String(innerFile?.url || ""); + + let fileType = ""; + if (outerType === "image" || innerType.includes("image")) fileType = "image"; + else if (innerType === "article") fileType = "article"; + else if (innerType === "questionnaire") fileType = "questionnaire"; + else fileType = outerType; + + const url = + fileType === "article" || fileType === "questionnaire" + ? innerUrl || outerUrl + : outerUrl || innerUrl; + + if (fileType === "image" && url) { + messages.push({ + type: "image", + content: url, + name: innerFile?.name || file?.name || "图片", + }); + continue; + } + + if (fileType === "article") { + const fallbackArticleId = + String( + innerFile?._id || + file?._id || + innerFile?.articleId || + file?.articleId || + "" + ) || ""; + const extractedId = extractIdFromUrl(url); + const articleId = String(extractedId || fallbackArticleId || ""); + + let articleUrl = String(url || ""); + if (!articleUrl && articleId) { + const corpId = getCorpId(); + articleUrl = `${__VITE_ENV__?.MP_PATIENT_PAGE_BASE_URL || ""}pages/article/index?id=${encodeURIComponent( + articleId + )}&corpId=${encodeURIComponent(corpId || "")}`; + } + + if (!articleId && !articleUrl) continue; + + messages.push({ + type: "article", + content: { + _id: articleId, + title: innerFile?.name || file?.name || "宣教文章", + url: articleUrl, + subtitle: innerFile?.subtitle || "", + cover: innerFile?.cover || file?.URL || "", + articleId: articleId, + }, + }); + continue; + } + + if (fileType === "questionnaire") { + const surveryId = innerFile?.surveryId || file?.surveryId; + if (!surveryId) continue; + const surveyId = + String(innerFile?._id || file?._id || surveryId || "") || ""; + messages.push({ + type: "questionnaire", + content: { + _id: surveyId, + name: innerFile?.name || file?.name || "问卷", + surveryId, + url: String(url || ""), + createBy: innerFile?.createBy, + }, + }); + } + } + } + + return messages; +} + +async function goChatAndSend(todo) { + if (!canShowSendButton(todo)) return; + if (!props.archiveId) return; + + let gid = normalizeGroupId(currentChatGroupId.value || ""); + if (!gid) { + await refreshChatRoomByApi(); + gid = normalizeGroupId(currentChatGroupId.value || ""); + } + if (!gid) { + toast("暂无可进入的会话"); + return; + } + + const messages = buildFollowUpMessages(todo); + if (!messages.length) { + console.warn("[followup] buildFollowUpMessages empty:", { + sendContent: todo?.sendContent, + fileList: todo?.fileList, + }); + toast("发送内容解析失败"); + return; + } + + const conversationID = `GROUP${gid}`; + + uni.setStorageSync(PENDING_FOLLOWUP_SEND_STORAGE_KEY, { + createdAt: Date.now(), + groupId: gid, + conversationID, + messages, + context: { userId: getUserId(), customerId: props.archiveId, customerName: props.data?.name || "", corpId: getCorpId(), env: __VITE_ENV__, - }); + }, + }); - if (success) { - toast("消息已发送"); - uni.navigateBack(); - } - } finally { - sendingFollowUp.value = false; - } + uni.navigateTo({ + url: `/pages/message/index?conversationID=${encodeURIComponent( + conversationID + )}&groupID=${encodeURIComponent(gid)}&fromCase=true&pendingFollowUpSend=1`, + }); } /** @@ -686,6 +778,83 @@ function extractSurveryIdFromUrl(url) { } } +const isRefreshingChatRoom = ref(false); +let lastRefreshChatRoomAt = 0; + +function parseAnyTimeMs(v) { + if (v === null || v === undefined) return 0; + if (typeof v === "number") return v; + const s = String(v).trim(); + if (!s) return 0; + if (/^\d{10,13}$/.test(s)) return Number(s.length === 10 ? `${s}000` : s); + const d = dayjs(s); + return d.isValid() ? d.valueOf() : 0; +} + +async function refreshChatRoomByApi() { + const customerId = String(props.archiveId || ""); + if (!customerId) return; + if (isRefreshingChatRoom.value) return; + const now = Date.now(); + if (now - lastRefreshChatRoomAt < 5000) return; + lastRefreshChatRoomAt = now; + + isRefreshingChatRoom.value = true; + try { + await ensureDoctor(); + const corpId = getCorpId(); + const teamId = getCurrentTeamId(); + + const baseQuery = { + corpId, + customerId, + page: 1, + pageSize: 50, + }; + + const queryWithTeam = teamId ? { ...baseQuery, teamId } : baseQuery; + let detailRes = await api("getGroupList", queryWithTeam, false); + let details = Array.isArray(detailRes?.data?.list) ? detailRes.data.list : []; + if (!details.length && teamId) { + detailRes = await api("getGroupList", baseQuery, false); + details = Array.isArray(detailRes?.data?.list) ? detailRes.data.list : []; + } + + if (!detailRes?.success || !details.length) { + chatGroupId.value = ""; + return; + } + + const currentTeamId = getCurrentTeamId(); + const detailsForCurrentTeam = currentTeamId + ? details.filter( + (g) => + String(g?.teamId || g?.team?._id || g?.team?.teamId || "") === + currentTeamId + ) + : []; + const candidates = detailsForCurrentTeam.length ? detailsForCurrentTeam : details; + + const statusRank = (s) => (s === "processing" ? 3 : s === "pending" ? 2 : 1); + candidates.sort((a, b) => { + const ra = statusRank(String(a?.orderStatus || "")); + const rb = statusRank(String(b?.orderStatus || "")); + if (rb !== ra) return rb - ra; + const ta = parseAnyTimeMs(a?.updatedAt) || parseAnyTimeMs(a?.createdAt); + const tb = parseAnyTimeMs(b?.updatedAt) || parseAnyTimeMs(b?.createdAt); + return tb - ta; + }); + + const best = candidates[0] || {}; + const gid = normalizeGroupId(best.groupId || best.groupID || best.group_id || ""); + chatGroupId.value = gid ? String(gid) : ""; + } catch (e) { + // ignore + } finally { + isRefreshingChatRoom.value = false; + } +} + // ---- filter popup ---- const filterPopupRef = ref(null); const state = ref(null);