Browse Source

聊天室联调

main
kola-web 4 months ago
parent
commit
b633caa483
  1. 7
      src/components/customRecord/index.scss
  2. 7
      src/components/customRecord/index.ts
  3. 5
      src/components/customRecord/index.wxml
  4. 7
      src/components/uploadFile/index.ts
  5. 4
      src/module1/pages/chatRoom/index.json
  6. 14
      src/module1/pages/chatRoom/index.scss
  7. 228
      src/module1/pages/chatRoom/index.ts
  8. 67
      src/module1/pages/chatRoom/index.wxml

7
src/components/customRecord/index.scss

@ -1,8 +1,9 @@ @@ -1,8 +1,9 @@
.record {
width: 107rpx;
height: 107rpx;
border: 10rpx solid #e6f7f9;
border-radius: 50%;
&.record-slot {
border: none;
}
.icon {
width: 107rpx;
height: 107rpx;
@ -39,7 +40,7 @@ @@ -39,7 +40,7 @@
position: absolute;
left: calc(50% - 6rpx);
bottom: -10rpx;
content: '';
content: "";
width: 0;
height: 0;
border-style: solid;

7
src/components/customRecord/index.ts

@ -5,7 +5,12 @@ Component({ @@ -5,7 +5,12 @@ Component({
/**
*
*/
properties: {},
properties: {
slotIcon: {
type: Boolean,
value: false,
},
},
/**
*

5
src/components/customRecord/index.wxml

@ -1,11 +1,12 @@ @@ -1,11 +1,12 @@
<view
class="record"
class="record {{slotIcon && 'record-slot'}}"
bind:touchstart="handleStart"
bind:longtap="handleShow"
bind:touchend="handleHide"
bind:touchcancel="handleHide"
>
<image class="icon" src="{{imageUrl}}record.png?t={{Timestamp}}"></image>
<slot wx:if="{{slotIcon}}"></slot>
<image wx:else class="icon" src="{{imageUrl}}record.png?t={{Timestamp}}"></image>
<view wx:if="{{startShow}}" class="record-page {{startShow && 'record-pape-start'}} {{show && 'record-page-active'}}">
<view class="record-line">
<image class="wave" src="{{imageUrl}}wave-white.gif?t={{Timestamp}}"></image>

7
src/components/uploadFile/index.ts

@ -133,8 +133,9 @@ Component({ @@ -133,8 +133,9 @@ Component({
let url = `${app.globalData.upFileUrl}?r=file-service/upload-`;
if (item.fileType === "image") {
url += "img";
} else if (item.fileType === "video") {
} else if (item.fileType === "video" || item.type === "video") {
url += "video";
item.tempFilePath = item.url;
} else if (item.fileType === "audio") {
url += "audio";
} else {
@ -162,8 +163,8 @@ Component({ @@ -162,8 +163,8 @@ Component({
};
if (item.fileType === "image") {
expandJson.imgUrl = data.data.Url;
} else if (item.fileType === "video") {
expandJson.videoUrl = data.data.SnapshotUrl;
} else if (item.fileType === "video" || item.type === "video") {
expandJson.imgUrl = data.data.SnapshotUrl;
} else if (item.fileType === "audio") {
expandJson.duration = Number.parseInt(String(item.duration / 1000));
}

4
src/module1/pages/chatRoom/index.json

@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
"navigationStyle": "default",
"usingComponents": {
"van-icon": "@vant/weapp/icon/index",
"van-popup": "@vant/weapp/popup/index"
"van-popup": "@vant/weapp/popup/index",
"customRecord": "/components/customRecord/index",
"uploadFile": "/components/uploadFile/index"
}
}

14
src/module1/pages/chatRoom/index.scss

@ -177,6 +177,7 @@ page { @@ -177,6 +177,7 @@ page {
}
}
.audio {
position: relative;
margin-bottom: 32rpx;
padding: 22rpx 24rpx;
border-radius: 0 32rpx 32rpx;
@ -188,6 +189,19 @@ page { @@ -188,6 +189,19 @@ page {
align-items: center;
gap: 12rpx;
box-sizing: border-box;
&.no-read {
&::after {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: -30rpx;
content: '';
width: 16rpx;
height: 16rpx;
background: #ed4f39;
border-radius: 50%;
}
}
.icon {
width: 32rpx;
height: 40rpx;

228
src/module1/pages/chatRoom/index.ts

@ -16,6 +16,7 @@ interface IMessageItem { @@ -16,6 +16,7 @@ interface IMessageItem {
hospitalName: string;
showTime?: boolean;
isPlay?: boolean;
uniqueCode?: string;
}
Page({
@ -43,7 +44,8 @@ Page({ @@ -43,7 +44,8 @@ Page({
userInfo: {} as any,
sendMessage: [],
sendMessage: "",
videoUrl: "",
},
innerAudioContext: null as WechatMiniprogram.InnerAudioContext | null,
videoContext: null as WechatMiniprogram.VideoContext | null,
@ -52,12 +54,14 @@ Page({ @@ -52,12 +54,14 @@ Page({
id: options.id,
});
this.videoContext = wx.createVideoContext("video");
this.innerAudioContext = wx.createInnerAudioContext({
useWebAudioImplement: true,
});
app.waitLogin().then(() => {
// this.getAgree();
this.getMessageList();
this.getDetail();
this.listenMessage();
app.getUserInfo(this);
});
},
@ -66,6 +70,9 @@ Page({ @@ -66,6 +70,9 @@ Page({
if (this.innerAudioContext) {
this.innerAudioContext.stop();
}
if (this.videoContext) {
this.videoContext.stop();
}
},
getAgree() {
wx.ajax({
@ -117,22 +124,17 @@ Page({ @@ -117,22 +124,17 @@ Page({
url: `/module1/pages/chatRoomInfo/index?id=${this.data.id}&cid=${this.data.case.caseId}`,
});
},
handleCaseDetail() {
wx.navigateTo({
url: `/module1/pages/casesDetail/index?id=${this.data.case.caseId}`,
});
},
handleView(index = -1) {
this.setData({
scrollIntoView: index > -1 ? `view${index}` : `place`,
});
},
listenMessage() {
wx.WebIM.conn.addEventHandler("room", {
onConnected: (message) => {
console.log("message: ", message);
},
onTextMessage: (meessage) => {
console.log("meessage1: ", meessage);
},
});
},
getMessageList() {
if (this.data.isLoad || this.data.isFinish) return;
this.setData({
@ -154,11 +156,7 @@ Page({ @@ -154,11 +156,7 @@ Page({
return;
}
res.map((item) => {
//消息内容类型,1-文本,2-语音,3-图片,4-视频,5-提示信息
if (["2", "3", "4"].includes(item.contentType)) {
item.msgContent = JSON.parse(item.msgContent);
}
return item;
return this.formatMessage(item);
});
this.setData({
messageList: [...res.reverse(), ...this.data.messageList],
@ -166,9 +164,7 @@ Page({ @@ -166,9 +164,7 @@ Page({
isLoad: false,
});
this.filterCreateTime();
if (!lastMsgId) {
this.handleView();
}
this.handleView();
});
},
scrolltoupper(e) {
@ -176,13 +172,6 @@ Page({ @@ -176,13 +172,6 @@ Page({
this.getMessageList();
}
},
WebIMLogin() {
const { chatDoctor } = this.data;
wx.WebIM.conn.open({
user: chatDoctor.chatUserId,
pwd: chatDoctor.chatUserPwd,
});
},
handleSendMessage() {
const { sendMessage, userInfo } = this.data;
if (!sendMessage) {
@ -199,13 +188,100 @@ Page({ @@ -199,13 +188,100 @@ Page({
fromDoctorId: userInfo.DoctorId,
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
isSelf: 1,
isRead: 1,
isRead: 2,
doctorImg: userInfo.Img,
doctorName: userInfo.Name,
hospitalName: userInfo.HospitalName,
};
this.setData({
sendMessage: "",
});
this.WebIMSendMessage(message);
},
handleSendAudio(e) {
const { userInfo } = this.data;
const contentStr = JSON.stringify({
url: e.detail.fileUrl,
duration: e.detail.duration,
});
const message: IMessageItem = {
msgId: "",
contentType: "2",
content: contentStr,
fromDoctorId: userInfo.DoctorId,
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
isSelf: 1,
isRead: 2,
doctorImg: userInfo.Img,
doctorName: userInfo.Name,
hospitalName: userInfo.HospitalName,
};
this.WebIMSendMessage(message);
},
handleSendPhoto(e) {
const { userInfo } = this.data;
const contentStr = JSON.stringify({
url: e.detail.fileUrl,
});
const message: IMessageItem = {
msgId: "",
contentType: "3",
content: contentStr,
fromDoctorId: userInfo.DoctorId,
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
isSelf: 1,
isRead: 2,
doctorImg: userInfo.Img,
doctorName: userInfo.Name,
hospitalName: userInfo.HospitalName,
};
this.WebIMSendMessage(message);
},
handleSendVideo(e) {
const { userInfo } = this.data;
const contentStr = JSON.stringify({
url: e.detail.fileUrl,
imgUrl: e.detail.imgUrl,
});
const message: IMessageItem = {
msgId: "",
contentType: "4",
content: contentStr,
fromDoctorId: userInfo.DoctorId,
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
isSelf: 1,
isRead: 2,
doctorImg: userInfo.Img,
doctorName: userInfo.Name,
hospitalName: userInfo.HospitalName,
};
this.WebIMSendMessage(message);
},
sendMessage({ uniqueCode, ...message }) {
wx.ajax({
method: "POST",
url: "?r=takeda/chat/send-message",
data: {
roomId: this.data.id,
message: {
contentType: message.contentType,
content: message.content,
uniqueCode,
},
},
});
},
WebIMLogin() {
const { chatDoctor } = this.data;
wx.WebIM.conn
.open({
user: chatDoctor.chatUserId,
pwd: chatDoctor.chatUserPwd,
})
.then(() => {
this.listenMessage();
});
},
WebIMSendMessage(message: IMessageItem) {
const { chatGroupInfo } = this.data;
const option = {
@ -223,8 +299,9 @@ Page({ @@ -223,8 +299,9 @@ Page({
.then((res) => {
this.sendMessage({ ...message, uniqueCode: res.serverMsgId });
this.setData({
messageList: [...this.data.messageList, message],
messageList: [...this.data.messageList, this.formatMessage(message)],
});
this.handleView();
})
.catch(() => {
wx.showToast({
@ -233,40 +310,35 @@ Page({ @@ -233,40 +310,35 @@ Page({
});
});
},
sendMessage({ uniqueCode, ...message }) {
wx.ajax({
method: "POST",
url: "?r=takeda/chat/send-message",
data: {
roomId: this.data.id,
message: {
contentType: message.contentType,
content: message.content,
uniqueCode,
},
listenMessage() {
const { chatGroupInfo } = this.data;
wx.WebIM.conn.addEventHandler("room", {
onTextMessage: (message) => {
if (message.error) {
return;
}
if (message.to === chatGroupInfo.ChatGroupId) {
this.setData({
messageList: [
...this.data.messageList,
this.formatMessage({
...message.ext,
isSelf: 2,
}),
],
});
this.handleReadAll();
this.handleView();
}
},
});
},
handleHot(e) {
const { index, mindex } = e.currentTarget.dataset;
const { messageList } = this.data;
const hotList = messageList[mindex].welcomeMsg?.hotQuestion;
const hot = hotList?.[index];
this.setData({
messageList: [
...messageList,
{
msgId: "",
contentType: "1",
msgContent: hot?.question,
msgVisitTime: "",
msgFromType: "1",
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
},
],
});
this.handleView();
this.sendQuestion(hot?.questionId);
formatMessage(message: IMessageItem) {
//消息内容类型,1-文本,2-语音,3-图片,4-视频,5-提示信息
if (["2", "3", "4"].includes(message.contentType)) {
message.content = JSON.parse(message.content);
}
return message;
},
formatTime(date: string) {
let createTimeName = "";
@ -308,7 +380,7 @@ Page({ @@ -308,7 +380,7 @@ Page({
this.setData({
fold: !this.data.fold,
});
if (this.data.fold) {
if (!this.data.fold) {
setTimeout(() => {
this.handleView();
}, 300);
@ -318,7 +390,7 @@ Page({ @@ -318,7 +390,7 @@ Page({
const { index } = e.currentTarget.dataset;
const { messageList } = this.data;
const messageItem = messageList[index];
const { url } = messageItem.content[0];
const { url } = messageItem.content;
if (this.innerAudioContext) {
if (messageItem.isPlay) {
this.innerAudioContext.stop();
@ -332,6 +404,13 @@ Page({ @@ -332,6 +404,13 @@ Page({
this.innerAudioContext.src = url;
this.innerAudioContext.play();
messageItem.isPlay = true;
if (messageItem.isRead === 2 && messageItem.isSelf === 2) {
messageItem.isRead = 1;
this.handleReadAudio({
msgId: messageItem.msgId,
uniqueCode: messageItem.uniqueCode,
});
}
this.innerAudioContext.onEnded(() => {
messageItem.isPlay = false;
this.setData({
@ -343,16 +422,39 @@ Page({ @@ -343,16 +422,39 @@ Page({
});
}
},
handleReadAudio({ msgId, uniqueCode }) {
wx.ajax({
method: "POST",
url: "?r=takeda/chat/read-message",
data: {
roomId: this.data.id,
msgId,
uniqueCode,
},
});
},
handlePreview(e) {
const { url } = e.currentTarget.dataset;
wx.previewImage({
urls: [url],
});
},
handleVideo() {
handleVideo(e) {
const { url } = e.currentTarget.dataset;
if (this.videoContext) {
this.setData({
videoUrl: url,
});
this.videoContext.play();
this.videoContext.requestFullScreen({});
}
},
handleReadAll() {
wx.ajax({
method: "POST",
url: "?r=takeda/chat/read-all-message",
data: { roomId: this.data.id },
});
},
});

67
src/module1/pages/chatRoom/index.wxml

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
<image class="photo" wx:for="{{newRoomDoctors}}" wx:key="doctorId" src="{{item.doctorImg}}"></image>
<view class="sealed" wx:if="{{case.caseStatus==='4'}}">已归档</view>
</view>
<view class="inner">
<view class="inner" bind:tap="handleCaseDetail">
<view class="c-header">
<view class="id">ID:{{case.caseNo}}</view>
<view class="detail">
@ -39,16 +39,17 @@ @@ -39,16 +39,17 @@
<view class="create" wx:if="{{message.contentType==='5'}}">{{message.content}}</view>
<view class="doctor" wx:elif="{{message.isSelf===2}}">
<view class="avatar">
<image
class="a-img"
mode="aspectFill"
src="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
></image>
<image class="a-img" mode="aspectFill" src="{{message.doctorImg}}"></image>
</view>
<view class="d-container">
<view class="user">李倩 中南大学湘雅医院李倩</view>
<view class="user">{{message.doctorName}} {{message.hospitalName}}</view>
<view class="message" wx:if="{{message.contentType==='1'}}">{{message.content}}</view>
<view class="audio" wx:elif="{{message.contentType==='2'}}" bind:tap="handleAudio" data-index="{{mIndex}}">
<view
class="audio {{message.isRead===2 && 'no-read'}}"
wx:elif="{{message.contentType==='2'}}"
bind:tap="handleAudio"
data-index="{{mIndex}}"
>
<image
wx:if="{{message.isPlay}}"
class="icon"
@ -56,26 +57,25 @@ @@ -56,26 +57,25 @@
mode="aspectFit"
></image>
<image wx:else class="icon" src="{{imageUrl}}/audio-right.png?t={{Timestamp}}" mode="aspectFit"></image>
{{message.msgContent[0].duration}}''
{{message.content.duration}}''
</view>
<view class="photo" wx:elif="{{message.contentType==='3'}}">
<image
class="p-img"
src="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
src="{{message.content.url}}"
mode="widthFix"
show-menu-by-longpress
bind:tap="handlePreview"
data-url="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
data-url="{{message.content.url}}"
></image>
</view>
<view class="video" wx:elif="{{message.contentType==='4'}}" bind:tap="handleVideo">
<view class="video" wx:elif="{{message.contentType==='4'}}">
<image
class="v-img"
src="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
src="{{message.content.imgUrl}}"
mode="aspectFill"
show-menu-by-longpress
bind:tap="handlePreview"
data-url="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
bind:tap="handleVideo"
data-url="{{message.content.url}}"
></image>
<image class="play" src="{{imageUrl}}icon-video-play.png?t={{Timestamp}}"></image>
</view>
@ -86,7 +86,7 @@ @@ -86,7 +86,7 @@
<view class="user">{{message.doctorName}} {{message.hospitalName}}</view>
<view class="message" wx:if="{{message.contentType==='1'}}">{{message.content}}</view>
<view class="audio" wx:elif="{{message.contentType==='2'}}" bind:tap="handleAudio" data-index="{{mIndex}}">
{{message.msgContent[0].duration}}''
{{message.content.duration}}''
<image
class="icon"
wx:if="{{message.isPlay}}"
@ -98,21 +98,20 @@ @@ -98,21 +98,20 @@
<view class="photo" wx:elif="{{message.contentType==='3'}}">
<image
class="p-img"
src="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
src="{{message.content.url}}"
mode="widthFix"
show-menu-by-longpress
bind:tap="handlePreview"
data-url="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
data-url="{{message.content.url}}"
></image>
</view>
<view class="video" wx:elif="{{message.contentType==='4'}}" bind:tap="handleVideo">
<view class="video" wx:elif="{{message.contentType==='4'}}">
<image
class="v-img"
src="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
src="{{message.content.imgUrl}}"
mode="aspectFill"
show-menu-by-longpress
bind:tap="handlePreview"
data-url="https://pic1.zhimg.com/50/v2-dcfbab1219ae4f7a7a6db168bb1580a2_720w.jpg?source=2c26e567"
bind:tap="handleVideo"
data-url="{{message.content.url}}"
></image>
<image class="play" src="{{imageUrl}}icon-video-play.png?t={{Timestamp}}"></image>
</view>
@ -127,13 +126,16 @@ @@ -127,13 +126,16 @@
</view>
<view class="page-footer">
<view class="header">
<image class="icon" src="{{imageUrl}}icon-voice.png?t={{Timestamp}}"></image>
<customRecord bind:file="handleSendAudio" slotIcon>
<image class="icon" src="{{imageUrl}}icon-voice.png?t={{Timestamp}}"></image>
</customRecord>
<input
class="input"
placeholder-class="place-class"
type="text"
model:value="{{sendMessage}}"
placeholder="请输入要查询的内容"
cursor-spacing="{{30}}"
confirm-type="send"
bindconfirm="handleSendMessage"
/>
@ -144,21 +146,18 @@ @@ -144,21 +146,18 @@
bind:tap="handleFooter"
></image>
</view>
<view class="fold-container {{!fold && 'unfold'}}">
<view class="f-item">
<view class="fold-container {{!fold && 'unfold'}}" bind:tap="handleFooter">
<uploadFile class="f-item" bind:file="handleSendPhoto">
<image class="icon" src="{{imageUrl}}icon-picture.png?t={{Timestamp}}"></image>
<view class="name">照片</view>
</view>
<view class="f-item">
</uploadFile>
<uploadFile class="f-item" accept="video" bind:file="handleSendVideo">
<image class="icon" src="{{imageUrl}}icon-video.png?t={{Timestamp}}"></image>
<view class="name">视频</view>
</view>
</uploadFile>
</view>
</view>
<video
id="video"
src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400"
></video>
<video id="video" src="{{videoUrl}}"></video>
</view>
<van-popup show="{{ show1 }}" bind:close="onAgreeClose" closeable round>

Loading…
Cancel
Save