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

View File

@ -75,7 +75,8 @@
<view <view
v-if="!loading && articleList.length >= total" v-if="!loading && articleList.length >= total"
class="no-more"> class="no-more"
>
没有更多了 没有更多了
</view> </view>
</view> </view>
@ -107,14 +108,26 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; 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 useAccountStore from "@/store/account.js";
import EmptyData from "@/components/empty-data.vue"; import EmptyData from "@/components/empty-data.vue";
const env = __VITE_ENV__;
const accountStore = useAccountStore(); const accountStore = useAccountStore();
const env = __VITE_ENV__;
const corpId = env.MP_CORP_ID; const corpId = env.MP_CORP_ID;
const userId = ref("");
//
const pageParams = ref({
groupId: "",
userId: "",
corpId: "",
});
// //
const searchTitle = ref(""); const searchTitle = ref("");
@ -241,7 +254,7 @@ const loadMore = () => {
// 使 // 使
const processRichTextContent = (html) => { const processRichTextContent = (html) => {
if (!html) return ''; if (!html) return "";
// img // img
let processedHtml = html.replace( let processedHtml = html.replace(
@ -253,7 +266,7 @@ const processRichTextContent = (html) => {
processedHtml = processedHtml.replace( processedHtml = processedHtml.replace(
/style="[^"]*width:\s*\d+px[^"]*"/gi, /style="[^"]*width:\s*\d+px[^"]*"/gi,
(match) => { (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 sendArticle = async (article) => {
// try {
const pages = getCurrentPages(); const { doctorInfo } = useAccountStore();
const prevPage = pages[pages.length - 2]; const result = await sendArticleMessage({
groupId: pageParams.value.groupId,
if (prevPage) { fromAccount: doctorInfo.weChatOpenId,
// articleId: article._id,
const doctorInfo = accountStore.doctorInfo; title: article.title || "宣教文章",
userId.value = doctorInfo?.userid || accountStore.openid; imgUrl: article.cover || "",
desc: "点击查看详情",
// 线
uni.$emit("sendArticle", {
article: article,
corpId: corpId,
userId: userId.value,
}); });
uni.showToast({ if (result.success) {
title: "已选择文章",
icon: "success",
});
//
setTimeout(() => {
uni.navigateBack(); 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(); 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(() => { onMounted(() => {
getCategoryList(); getCategoryList();
loadArticleList(); loadArticleList();
@ -400,9 +425,9 @@ onMounted(() => {
.category-item.active { .category-item.active {
background-color: #fff; background-color: #fff;
color: #0877F1; color: #0877f1;
font-weight: bold; font-weight: bold;
border-left: 4rpx solid #0877F1; border-left: 4rpx solid #0877f1;
} }
.article-list { .article-list {

View File

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

View File

@ -73,6 +73,9 @@ const props = defineProps({
patientInfo: { type: Object, default: () => ({}) }, patientInfo: { type: Object, default: () => ({}) },
chatRoomBusiness: { type: Object, default: () => ({}) }, chatRoomBusiness: { type: Object, default: () => ({}) },
formatTime: { type: Function, required: true }, formatTime: { type: Function, required: true },
groupId: { type: String, default: '' },
userId: { type: String, default: '' },
corpId: { type: String, default: '' },
}); });
// Emits // Emits
@ -364,7 +367,7 @@ const goToCommonPhrases = () => {
// //
const goToArticleList = () => { const goToArticleList = () => {
uni.navigateTo({ 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 { try {
if (message.payload && message.payload.data) { if (message.payload && message.payload.data) {
const data = JSON.parse(message.payload.data); const data = JSON.parse(message.payload.data);
return data.type || ''; return data.type || "";
} }
} catch (error) { } catch (error) {
console.error('解析自定义消息失败:', error); console.error("解析自定义消息失败:", error);
} }
return ''; return "";
}; };
// //
@ -220,45 +220,25 @@ const getArticleData = (message) => {
try { try {
if (message.payload && message.payload.data) { if (message.payload && message.payload.data) {
const data = JSON.parse(message.payload.data); const data = JSON.parse(message.payload.data);
return { return data;
title: data.title || '宣教文章',
desc: data.desc || '宣教文章',
url: data.url || '',
imgUrl: data.imgUrl || ''
};
} }
} catch (error) { } catch (error) {
console.error('解析文章数据失败:', error); console.error("解析文章数据失败:", error);
} }
return { return {
title: '宣教文章', title: "宣教文章",
desc: '宣教文章', desc: "宣教文章",
url: '', url: "",
imgUrl: '' imgUrl: "",
}; };
}; };
// //
const handleArticleClick = (message) => { const handleArticleClick = (message) => {
const articleData = getArticleData(message); const { articleId } = getArticleData(message);
if (articleData.url) { uni.navigateTo({
// IDcorpId url: `/pages/message/article-detail?id=${articleId}`,
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)}`
});
}
}
}; };
// //
@ -267,20 +247,20 @@ const getSurveyData = (message) => {
if (message.payload && message.payload.data) { if (message.payload && message.payload.data) {
const data = JSON.parse(message.payload.data); const data = JSON.parse(message.payload.data);
return { return {
title: data.title || '填写问卷', title: data.title || "填写问卷",
desc: data.desc || '请填写问卷', desc: data.desc || "请填写问卷",
url: data.url || '', url: data.url || "",
imgUrl: data.imgUrl || '' imgUrl: data.imgUrl || "",
}; };
} }
} catch (error) { } catch (error) {
console.error('解析问卷数据失败:', error); console.error("解析问卷数据失败:", error);
} }
return { return {
title: '填写问卷', title: "填写问卷",
desc: '请填写问卷', desc: "请填写问卷",
url: '', url: "",
imgUrl: '' imgUrl: "",
}; };
}; };
@ -289,7 +269,7 @@ const handleSurveyClick = (message) => {
const surveyData = getSurveyData(message); const surveyData = getSurveyData(message);
if (surveyData.url) { if (surveyData.url) {
// //
console.log('打开问卷:', surveyData.url); console.log("打开问卷:", surveyData.url);
// uni.navigateTo({ // uni.navigateTo({
// url: `/pages/survey/fill?url=${encodeURIComponent(surveyData.url)}` // url: `/pages/survey/fill?url=${encodeURIComponent(surveyData.url)}`
// }); // });

View File

@ -85,7 +85,7 @@
}}</text> }}</text>
</view> </view>
<!-- 消息气泡 -->
<view class="message-bubble" :class="getBubbleClass(message)"> <view class="message-bubble" :class="getBubbleClass(message)">
<!-- 消息内容 --> <!-- 消息内容 -->
<MessageTypes <MessageTypes
@ -132,6 +132,9 @@
ref="chatInputRef" ref="chatInputRef"
:timChatManager="timChatManager" :timChatManager="timChatManager"
:formatTime="formatTime" :formatTime="formatTime"
:groupId="chatInfo.conversationID ? chatInfo.conversationID.replace('GROUP', '') : ''"
:userId="openid"
:corpId="corpId"
@scrollToBottom="() => scrollToBottom(true)" @scrollToBottom="() => scrollToBottom(true)"
@messageSent="() => scrollToBottom(true)" @messageSent="() => scrollToBottom(true)"
@endConsult="handleEndConsult" @endConsult="handleEndConsult"
@ -162,7 +165,7 @@ import {
handleViewDetail, handleViewDetail,
checkIMConnectionStatus, checkIMConnectionStatus,
} from "@/utils/chat-utils.js"; } 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 useGroupChat from "./hooks/use-group-chat";
import MessageTypes from "./components/message-types.vue"; import MessageTypes from "./components/message-types.vue";
import ChatInput from "./components/chat-input.vue"; import ChatInput from "./components/chat-input.vue";
@ -172,6 +175,10 @@ import RejectReasonModal from "./components/reject-reason-modal.vue";
const timChatManager = globalTimChatManager; const timChatManager = globalTimChatManager;
//
const env = __VITE_ENV__;
const corpId = env.MP_CORP_ID || '';
// //
const { account, openid, isIMInitialized } = storeToRefs(useAccountStore()); const { account, openid, isIMInitialized } = storeToRefs(useAccountStore());
const { initIMAfterLogin } = useAccountStore(); const { initIMAfterLogin } = useAccountStore();
@ -300,7 +307,7 @@ function getBubbleClass(message) {
return "image-bubble"; return "image-bubble";
} }
if (message.type === "TIMCustomElem") { 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"; return message.flow === "out" ? "user-bubble" : "doctor-bubble";
} }
@ -696,13 +703,12 @@ onHide(() => {
stopIMMonitoring(); stopIMMonitoring();
}); });
//
const sendCommonPhrase = (content) => { const sendCommonPhrase = (content) => {
if (chatInputRef.value) { if (chatInputRef.value) {
chatInputRef.value.sendTextMessageFromPhrase(content); chatInputRef.value.sendTextMessageFromPhrase(content);
} }
}; };
// //
defineExpose({ defineExpose({
sendCommonPhrase, sendCommonPhrase,
@ -808,14 +814,12 @@ const handleRejectReasonConfirm = async (reason) => {
const handleRejectReasonCancel = () => { const handleRejectReasonCancel = () => {
showRejectReasonModal.value = false; showRejectReasonModal.value = false;
}; };
// //
const handleEndConsult = async () => { const handleEndConsult = async () => {
try { try {
uni.showLoading({ uni.showLoading({
title: "处理中...", title: "处理中...",
}); });
// groupId // groupId
const result = await endConsultation({ const result = await endConsultation({
groupId: groupId.value, groupId: groupId.value,
@ -826,9 +830,7 @@ const handleEndConsult = async () => {
endReason: "问诊完成", endReason: "问诊完成",
}, },
}); });
uni.hideLoading(); uni.hideLoading();
if (result.success) { if (result.success) {
uni.showToast({ uni.showToast({
title: "问诊已结束", title: "问诊已结束",
@ -856,80 +858,10 @@ onUnmounted(() => {
timChatManager.setCallback("onMessageReceived", null); timChatManager.setCallback("onMessageReceived", null);
timChatManager.setCallback("onMessageListLoaded", null); timChatManager.setCallback("onMessageListLoaded", null);
timChatManager.setCallback("onError", null); timChatManager.setCallback("onError", null);
//
uni.$off("sendArticle");
// //
uni.$off("sendSurvey"); 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) => { uni.$on("sendSurvey", async (data) => {
@ -942,7 +874,6 @@ uni.$on("sendSurvey", async (data) => {
}); });
return; return;
} }
try { try {
// //
const env = __VITE_ENV__; 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) { export async function endConsultation(data) {
return request({ return request({