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);