8.vue3医疗在线问诊项目 - _问诊室模块-websocket学习 ==> 消息卡片、websocket、socket.io、约定通讯规则、建立连接
问诊室-路由与组件
目标:配置路由和分析结构
1)路由配置
{
path: '/room',
component: () => import('@/views/room/index.vue'),
meta: { title: '问诊室' }
},
问诊室-消息卡片
目标:了解问诊室消息卡片类型
组件 Room/components/RoomMessage.vue
- 病情描述
<div class="msg msg-illness">
<div class="patient van-hairline--bottom">
<p>李富贵 男 31岁</p>
<p>一周内 | 未去医院就诊</p>
</div>
<van-row>
<van-col span="6">病情描述</van-col>
<van-col span="18">头痛、头晕、恶心</van-col>
<van-col span="6">图片</van-col>
<van-col span="18">点击查看</van-col>
</van-row>
</div>
- 温馨提示-通知
<div class="msg msg-tip">
<div class="content">
<span class="green">温馨提示:</span>
<span>在线咨询不能代替面诊,医护人员建议仅供参考</span>
</div>
</div>
- 通知
<div class="msg msg-tip">
<div class="content">
<span>医护人员正在赶来,请耐心等候</span>
</div>
</div>
- 发送文字
<div class="msg msg-to">
<div class="content">
<div class="time">20:12</div>
<div class="pao">大夫你好?</div>
</div>
<van-image src="https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/popular_3.jpg" />
</div>
- 发送图片
<div class="msg msg-to">
<div class="content">
<div class="time">20:12</div>
<van-image
fit="contain"
src="https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/popular_3.jpg"
/>
</div>
<van-image src="https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/popular_3.jpg" />
</div>
- 接收文字
<div class="msg msg-from">
<van-image src="https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/popular_3.jpg" />
<div class="content">
<div class="time">20:12</div>
<div class="pao">哪里不舒服</div>
</div>
</div>
- 处方消息
<div class="msg msg-recipe">
<div class="content">
<div class="head van-hairline--bottom">
<div class="head-tit">
<h3>电子处方</h3>
<p>原始处方 <van-icon name="arrow"></van-icon></p>
</div>
<p>李富贵 男 31岁 血管性头痛</p>
<p>开方时间:2022-01-15 14:21:42</p>
</div>
<div class="body">
<div class="body-item" v-for="i in 2" :key="i">
<div class="durg">
<p>优赛明 维生素E乳</p>
<p>口服,每次1袋,每天3次,用药3天</p>
</div>
<div class="num">x1</div>
</div>
</div>
<div class="foot"><span>购买药品</span></div>
</div>
</div>
- 订单取消
<div class="msg msg-tip msg-tip-cancel">
<div class="content">
<span>订单取消</span>
</div>
</div>
小结:
- 知道问诊室大概有哪些消息卡片(类型)
问诊室-websocket
目标:认识websocket
什么是 websocket ? https://websocket.org/
- 是一种网络通信协议,和 HTTP 协议 一样。
为什么需要websocket ?
- 因为 HTTP 协议有一个缺陷:通信只能由客户端发起。
理解 websokect 通讯过程
了解 websocket api含义
// 创建ws实例,建立连接
var ws = new WebSocket("wss://javascript.info/article/websocket/demo/hello");
// 连接成功事件
ws.onopen = function(evt) {
console.log("Connection open ...");
// 发送消息
ws.send("Hello WebSockets!");
};
// 接受消息事件
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
// 关闭连接
ws.close();
};
// 关闭连接事件
ws.onclose = function(evt) {
console.log("Connection closed.");
};
说明:我们项目中使用 socket.io-client 来实现客户端代码,它是基于 websocket 的库。
问诊室-socket.io使用
目的:掌握 socket.io 的基本使用
- socket.io 什么?
- socket.io 是一个基于 WebSocket 的 CS(客户端-服务端)的实时通信库
- 使用它可以在后端提供一个即时通讯服务
- 它也提供一个 js 库,在前端可以去链接后端的 socket.io 创建的服务
- 总结:它是一套基于 websocket 前后端即时通讯解决方案
- 我们需要掌握的客户端几个 api 的基本使用
如何使用客户端js库?
pnpm add socket.io-client
如何建立连接?
import { io } from 'socket.io-client'
// 参数1:不传默认是当前服务域名,开发中传入服务器地址
// 参数2:配置参数,根据需要再来介绍
const socket = io()
如何确定连接成功?
socket.on('connect', () => {
// 建立连接成功
})
如何发送消息?
// chat message 发送消息事件,由后台约定,可变
socket.emit('chat message', '消息内容')
如何接收消息?
// chat message 接收消息事件,由后台约定,可变
socket.on('chat message', (ev) => {
// ev 是服务器发送的消息
})
如何关闭连接?
// 离开组件需要使用
socket.close()
小结:
- sockt.io 在前端使用的js库需要知道哪些内容?
- 如何建立链接
io('地址')
- 连接成功的事件
connect
- 如何发消息
emit
+ 事件 - 如何收消息
on
+ 事件 - 如果关闭连接
close()
- 如何建立链接
问诊室-通讯规则
知道前后端ws通信事件以及定义数据的类型
- 前后台约定通讯的一些事件
chatMsgList
接收聊天记录
sendChatMsg
发送消息
receiveChatMsg
接收消息
statusChange
接收订单状态改变
- 前后台约定的消息数据的类型
enums/index.ts
// 消息类型
export enum MsgType {
// 文字
MsgText = 1,
// 图片
MsgImage = 4,
// 患者
CardPat = 21,
// 处方
CardPre = 22,
// 未评价
CardEvaForm = 23,
// 已评价
CardEva = 24,
// 通用系统
Notify = 31,
// 温馨提示
NotifyTip = 32,
// 取消订单
NotifyCancel = 33
}
// 处方状态
export enum PrescriptionStatus {
// 未支付
NotPayment = 1,
// 已支付
Payment = 2,
// 无效
Invalid = 3
}
// 问诊订单状态
export enum OrderType {
// ----------------问诊订单------------------
// 待支付
ConsultPay = 1,
// 待接诊
ConsultWait = 2,
// 咨询中
ConsultChat = 3,
// 已完成
ConsultComplete = 4,
// 已取消
ConsultCancel = 5,
// ----------------药品订单------------------
// 待支付
MedicinePay = 10,
// 待发货
MedicineSend = 11,
// 待收货
MedicineTake = 12,
// 已完成
MedicineComplete = 13,
// 已取消
MedicineCancel = 14
}
types/room.d.ts
import { MsgType, PrescriptionStatus } from '@/enums'
import type { Consult, Image } from './consult'
import type { Patient } from './user'
// 1. 聊天-消息中包含处方和药品类型
// 药品
export type Medical = {
id: string
name: string
amount: string
avatar: string
specs: string
// 用量
usageDosag: string
quantity: string
// 是否是处方药
prescriptionFlag: 0 | 1
}
// 处方
export type Prescription = {
id: string
orderId: string
createTime: string
name: string
recordId: string
gender: 0 | 1
genderValue: string
age: number
// 诊断信息
diagnosis: string
status: PrescriptionStatus
// 药品订单
medicines: Medical[]
}
// 2. 聊天-评价医生
export type EvaluateDoc = {
id?: string
score?: number
content?: string
createTime?: string
creator?: string
}
// 3. 聊天-消息类型
// 消息类型:聊天-接收对话信息api
export type Message = {
id: string
msgType: MsgType
// 发消息的人ID
from?: string
fromAvatar?: string
// 收消息的人ID
to?: string
toAvatar?: string
createTime: string
// 具体消息内容
msg: {
// 文字类型
content?: string
// 图片类型
picture?: Image
// 患者卡片
consultRecord?: Consult & {
patientInfo: Patient
}
// 处方信息
prescription?: Prescription
// 评价信息
evaluateDoc?: EvaluateDoc
}
// 是否需要滚动
notScroll?: boolean
}
// 消息分组:聊天-查询历史聊天记录api
export type TimeMessages = {
createTime: string
items: Message[]
orderId: string
sid: string
}
问诊室-建立连接
实现:问诊app和后台ws服务建立连接
步骤:
- 安装 sokect.io-client 包
- 在组件挂载完毕,进行socket连接
- 监听连接成功,监听错误消息,监听关闭连接
- 组件卸载关闭连接
代码:
- 安装 sokect.io-client 包
pnpm add sokect.io-client
- 建立连接
views/room/index.vue
import { onMounted, onUnmounted } from 'vue'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
import { io, type Socket } from 'socket.io-client'
import { baseURL } from '@/utils/request'
const store = useUserStore()
const route = useRoute()
let socket: Socket
// 组件销毁时关闭连接
onUnmounted(() => {
socket.close()
})
// 组件挂载建立连接
onMounted(async () => {
// 建立链接,创建 socket.io 实例
socket = io(baseURL, {
auth: {
token: `Bearer ${store.user?.token}``
},
query: {
orderId: route.query.orderId
}
})
// 如果连接建立成功就会执行这个函数
socket.on('connect', () => {
// 建立连接成功
console.log('connect')
})
// 捕捉错误
socket.on('error', (event) => {
// 错误异常消息
console.log('error')
})
// 断开连接时执行这里
socket.on('disconnect', ()=> {
// 已经断开连接
console.log('disconnect')
})
})