IM 问卷、文章

This commit is contained in:
wangdongbo 2026-01-27 15:07:39 +08:00
parent 5d03f0fc79
commit ec27449eab
7 changed files with 148 additions and 205 deletions

View File

@ -25,24 +25,24 @@
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app';
import { getArticle } from '@/utils/api.js';
import { ref } from 'vue';
import { onLoad } from "@dcloudio/uni-app";
import { getArticle } from "@/utils/api.js";
import { ref } from "vue";
const env = __VITE_ENV__;
const corpId = env.MP_CORP_ID;
const loading = ref(true);
const error = ref('');
const error = ref("");
const articleData = ref({
title: '',
content: '',
date: ''
title: "",
content: "",
date: "",
});
let articleId = '';
let corpId = '';
let articleId = "";
// 使
const processRichTextContent = (html) => {
if (!html) return '';
if (!html) return "";
// img
let processedHtml = html.replace(
@ -54,7 +54,7 @@ const processRichTextContent = (html) => {
processedHtml = processedHtml.replace(
/style="[^"]*width:\s*\d+px[^"]*"/gi,
(match) => {
return match.replace(/width:\s*\d+px;?/gi, 'max-width:100%;');
return match.replace(/width:\s*\d+px;?/gi, "max-width:100%;");
}
);
@ -72,52 +72,44 @@ const processRichTextContent = (html) => {
//
const loadArticle = async () => {
if (!articleId || !corpId) {
error.value = '文章信息不完整';
loading.value = false;
return;
}
loading.value = true;
error.value = '';
error.value = "";
try {
const res = await getArticle({ id: articleId, corpId: corpId });
const res = await getArticle({ id: articleId, corpId });
if (res.success && res.data) {
//
let date = '';
let date = "";
if (res.data.createTime) {
const d = new Date(res.data.createTime);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
date = `${year}-${month}-${day}`;
}
articleData.value = {
title: res.data.title || '宣教文章',
content: processRichTextContent(res.data.content || ''),
date: date
title: res.data.title || "宣教文章",
content: processRichTextContent(res.data.content || ""),
date: date,
};
} else {
error.value = res.message || '加载文章失败';
error.value = res.message || "加载文章失败";
}
} catch (err) {
console.error('加载文章失败:', err);
error.value = '加载失败,请重试';
console.error("加载文章失败:", err);
error.value = "加载失败,请重试";
} finally {
loading.value = false;
}
};
onLoad((options) => {
if (options.id && options.corpId) {
if (options.id) {
articleId = options.id;
corpId = options.corpId;
loadArticle();
} else {
error.value = '文章信息不完整';
error.value = "文章信息不完整";
loading.value = false;
}
});
@ -155,7 +147,7 @@ onLoad((options) => {
.retry-btn {
padding: 16rpx 60rpx;
background-color: #0877F1;
background-color: #0877f1;
color: #fff;
border: none;
border-radius: 8rpx;

View File

@ -75,7 +75,8 @@
<view
v-if="!loading && articleList.length >= total"
class="no-more">
class="no-more"
>
没有更多了
</view>
</view>
@ -107,14 +108,26 @@
<script setup>
import { ref, onMounted } from "vue";
import { getArticleCateList, getArticleList, getArticle } from "@/utils/api.js";
import { onLoad } from "@dcloudio/uni-app";
import {
getArticleCateList,
getArticleList,
getArticle,
sendArticleMessage,
} from "@/utils/api.js";
import useAccountStore from "@/store/account.js";
import EmptyData from "@/components/empty-data.vue";
const env = __VITE_ENV__;
const accountStore = useAccountStore();
const env = __VITE_ENV__;
const corpId = env.MP_CORP_ID;
const userId = ref("");
//
const pageParams = ref({
groupId: "",
userId: "",
corpId: "",
});
//
const searchTitle = ref("");
@ -241,7 +254,7 @@ const loadMore = () => {
// 使
const processRichTextContent = (html) => {
if (!html) return '';
if (!html) return "";
// img
let processedHtml = html.replace(
@ -253,7 +266,7 @@ const processRichTextContent = (html) => {
processedHtml = processedHtml.replace(
/style="[^"]*width:\s*\d+px[^"]*"/gi,
(match) => {
return match.replace(/width:\s*\d+px;?/gi, 'max-width:100%;');
return match.replace(/width:\s*\d+px;?/gi, "max-width:100%;");
}
);
@ -304,32 +317,31 @@ const closePreview = () => {
};
//
const sendArticle = (article) => {
//
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2];
if (prevPage) {
//
const doctorInfo = accountStore.doctorInfo;
userId.value = doctorInfo?.userid || accountStore.openid;
// 线
uni.$emit("sendArticle", {
article: article,
corpId: corpId,
userId: userId.value,
const sendArticle = async (article) => {
try {
const { doctorInfo } = useAccountStore();
const result = await sendArticleMessage({
groupId: pageParams.value.groupId,
fromAccount: doctorInfo.weChatOpenId,
articleId: article._id,
title: article.title || "宣教文章",
imgUrl: article.cover || "",
desc: "点击查看详情",
});
uni.showToast({
title: "已选择文章",
icon: "success",
});
//
setTimeout(() => {
if (result.success) {
uni.navigateBack();
}, 500);
} else {
throw new Error(result.message || "发送失败");
}
} catch (error) {
console.error("发送文章失败:", error);
uni.showToast({
title: error.message || "发送失败",
icon: "none",
});
} finally {
loading.value = false;
}
};
@ -338,6 +350,19 @@ const goBack = () => {
uni.navigateBack();
};
//
onLoad((options) => {
if (options.groupId) {
pageParams.value.groupId = options.groupId;
}
if (options.userId) {
pageParams.value.userId = options.userId;
}
if (options.corpId) {
pageParams.value.corpId = options.corpId;
}
});
onMounted(() => {
getCategoryList();
loadArticleList();
@ -400,9 +425,9 @@ onMounted(() => {
.category-item.active {
background-color: #fff;
color: #0877F1;
color: #0877f1;
font-weight: bold;
border-left: 4rpx solid #0877F1;
border-left: 4rpx solid #0877f1;
}
.article-list {

View File

@ -1254,11 +1254,12 @@ $primary-color: #0877F1;
.article-card {
display: flex;
align-items: center;
background-color: #fff;
background-color: transparent;
border-radius: 12rpx;
padding: 24rpx;
max-width: 500rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
box-shadow: none;
background-color: #fff;
}
.article-content {
@ -1297,11 +1298,11 @@ $primary-color: #0877F1;
/* 文章卡片在不同消息流中的样式 */
.message-right .article-card {
background-color: #e8f4ff;
background-color: transparent;
}
.message-left .article-card {
background-color: #fff;
background-color: transparent;
}
/* 问卷卡片样式 */

View File

@ -73,6 +73,9 @@ const props = defineProps({
patientInfo: { type: Object, default: () => ({}) },
chatRoomBusiness: { type: Object, default: () => ({}) },
formatTime: { type: Function, required: true },
groupId: { type: String, default: '' },
userId: { type: String, default: '' },
corpId: { type: String, default: '' },
});
// Emits
@ -364,7 +367,7 @@ const goToCommonPhrases = () => {
//
const goToArticleList = () => {
uni.navigateTo({
url: '/pages/message/article-list'
url: `/pages/message/article-list?groupId=${props.groupId}&userId=${props.userId}&corpId=${props.corpId}`
});
};

View File

@ -207,12 +207,12 @@ const getCustomMessageType = (message) => {
try {
if (message.payload && message.payload.data) {
const data = JSON.parse(message.payload.data);
return data.type || '';
return data.type || "";
}
} catch (error) {
console.error('解析自定义消息失败:', error);
console.error("解析自定义消息失败:", error);
}
return '';
return "";
};
//
@ -220,45 +220,25 @@ const getArticleData = (message) => {
try {
if (message.payload && message.payload.data) {
const data = JSON.parse(message.payload.data);
return {
title: data.title || '宣教文章',
desc: data.desc || '宣教文章',
url: data.url || '',
imgUrl: data.imgUrl || ''
};
return data;
}
} catch (error) {
console.error('解析文章数据失败:', error);
console.error("解析文章数据失败:", error);
}
return {
title: '宣教文章',
desc: '宣教文章',
url: '',
imgUrl: ''
title: "宣教文章",
desc: "宣教文章",
url: "",
imgUrl: "",
};
};
//
const handleArticleClick = (message) => {
const articleData = getArticleData(message);
if (articleData.url) {
// IDcorpId
const urlParams = new URLSearchParams(articleData.url.split('?')[1]);
const articleId = urlParams.get('id');
const corpId = urlParams.get('corpId');
if (articleId && corpId) {
//
uni.navigateTo({
url: `/pages/message/article-detail?id=${articleId}&corpId=${corpId}`
});
} else {
// ID使webview
uni.navigateTo({
url: `/pages/webview/webview?url=${encodeURIComponent(articleData.url)}`
});
}
}
const { articleId } = getArticleData(message);
uni.navigateTo({
url: `/pages/message/article-detail?id=${articleId}`,
});
};
//
@ -267,20 +247,20 @@ const getSurveyData = (message) => {
if (message.payload && message.payload.data) {
const data = JSON.parse(message.payload.data);
return {
title: data.title || '填写问卷',
desc: data.desc || '请填写问卷',
url: data.url || '',
imgUrl: data.imgUrl || ''
title: data.title || "填写问卷",
desc: data.desc || "请填写问卷",
url: data.url || "",
imgUrl: data.imgUrl || "",
};
}
} catch (error) {
console.error('解析问卷数据失败:', error);
console.error("解析问卷数据失败:", error);
}
return {
title: '填写问卷',
desc: '请填写问卷',
url: '',
imgUrl: ''
title: "填写问卷",
desc: "请填写问卷",
url: "",
imgUrl: "",
};
};
@ -289,7 +269,7 @@ const handleSurveyClick = (message) => {
const surveyData = getSurveyData(message);
if (surveyData.url) {
//
console.log('打开问卷:', surveyData.url);
console.log("打开问卷:", surveyData.url);
// uni.navigateTo({
// url: `/pages/survey/fill?url=${encodeURIComponent(surveyData.url)}`
// });

View File

@ -85,7 +85,7 @@
}}</text>
</view>
<!-- 消息气泡 -->
<view class="message-bubble" :class="getBubbleClass(message)">
<!-- 消息内容 -->
<MessageTypes
@ -132,6 +132,9 @@
ref="chatInputRef"
:timChatManager="timChatManager"
:formatTime="formatTime"
:groupId="chatInfo.conversationID ? chatInfo.conversationID.replace('GROUP', '') : ''"
:userId="openid"
:corpId="corpId"
@scrollToBottom="() => scrollToBottom(true)"
@messageSent="() => scrollToBottom(true)"
@endConsult="handleEndConsult"
@ -162,7 +165,7 @@ import {
handleViewDetail,
checkIMConnectionStatus,
} from "@/utils/chat-utils.js";
import { sendConsultRejectedMessage, endConsultation } from "@/utils/api.js";
import { sendConsultRejectedMessage, endConsultation, sendArticleMessage } from "@/utils/api.js";
import useGroupChat from "./hooks/use-group-chat";
import MessageTypes from "./components/message-types.vue";
import ChatInput from "./components/chat-input.vue";
@ -172,6 +175,10 @@ import RejectReasonModal from "./components/reject-reason-modal.vue";
const timChatManager = globalTimChatManager;
//
const env = __VITE_ENV__;
const corpId = env.MP_CORP_ID || '';
//
const { account, openid, isIMInitialized } = storeToRefs(useAccountStore());
const { initIMAfterLogin } = useAccountStore();
@ -300,7 +307,7 @@ function getBubbleClass(message) {
return "image-bubble";
}
if (message.type === "TIMCustomElem") {
return message.flow === "out" ? "user-bubble" : "doctor-bubble-blue";
return message.flow === "out" ? "" : "";
}
return message.flow === "out" ? "user-bubble" : "doctor-bubble";
}
@ -696,13 +703,12 @@ onHide(() => {
stopIMMonitoring();
});
//
const sendCommonPhrase = (content) => {
if (chatInputRef.value) {
chatInputRef.value.sendTextMessageFromPhrase(content);
}
};
//
defineExpose({
sendCommonPhrase,
@ -808,14 +814,12 @@ const handleRejectReasonConfirm = async (reason) => {
const handleRejectReasonCancel = () => {
showRejectReasonModal.value = false;
};
//
const handleEndConsult = async () => {
try {
uni.showLoading({
title: "处理中...",
});
// groupId
const result = await endConsultation({
groupId: groupId.value,
@ -826,9 +830,7 @@ const handleEndConsult = async () => {
endReason: "问诊完成",
},
});
uni.hideLoading();
if (result.success) {
uni.showToast({
title: "问诊已结束",
@ -856,80 +858,10 @@ onUnmounted(() => {
timChatManager.setCallback("onMessageReceived", null);
timChatManager.setCallback("onMessageListLoaded", null);
timChatManager.setCallback("onError", null);
//
uni.$off("sendArticle");
//
uni.$off("sendSurvey");
});
//
uni.$on("sendArticle", async (data) => {
const { article, corpId, userId } = data;
if (!article || !article._id) {
uni.showToast({
title: "文章信息不完整",
icon: "none",
});
return;
}
try {
//
const env = __VITE_ENV__;
const baseUrl = env.VITE_PATIENT_PAGE_BASE_URL || "";
//
const articleUrl = `${baseUrl}pages/article/index?id=${article._id}&corpId=${corpId}`;
//
const customMessage = {
data: JSON.stringify({
type: "article",
title: article.title || "宣教文章",
desc: "点击查看详情",
url: articleUrl,
imgUrl: "https://796f-youcan-clouddev-1-8ewcqf31dbb2b5-1317294507.tcb.qcloud.la/other/article-icon.png",
articleId: article._id
}),
description: "ARTICLE",
extension: "",
};
//
const message = timChatManager.tim.createCustomMessage({
to: chatInfo.value.conversationID.replace("GROUP", ""),
conversationType: timChatManager.TIM.TYPES.CONV_GROUP,
payload: customMessage,
});
const sendResult = await timChatManager.tim.sendMessage(message);
if (sendResult.code === 0) {
uni.showToast({
title: "发送成功",
icon: "success",
});
//
// await addArticleSendRecord({
// corpId,
// userId,
// articleId: article._id,
// customerId: chatInfo.value.userID
// });
} else {
throw new Error(sendResult.message || "发送失败");
}
} catch (error) {
console.error("发送文章失败:", error);
uni.showToast({
title: error.message || "发送失败",
icon: "none",
});
}
});
//
uni.$on("sendSurvey", async (data) => {
@ -942,7 +874,6 @@ uni.$on("sendSurvey", async (data) => {
});
return;
}
try {
//
const env = __VITE_ENV__;

View File

@ -144,6 +144,17 @@ export async function sendConsultRejectedMessage(data) {
});
}
// 发送宣教文章消息
export async function sendArticleMessage(data) {
return request({
url: '/getYoucanData/im',
data: {
type: 'sendArticleMessage',
...data
}
});
}
// 结束问诊接口
export async function endConsultation(data) {
return request({