枚举基本语法
作用: 表示一组明确可选的值,和字面量类型配合联合类型类似。
解释: 枚举可以定义一组常量,使用该类型后,约定只能使用这组常量中的其中一个。
// // 一组数据,Up Down Left Right 对应的值分布式 0 1 2 3 你的类型只能在这组数组中使用其中一个
// enum Direction {
// Up = 0,
// Down = 1,
// Left = 2,
// Right = 3
// }
// // 值从0开始,以此类推(0,1,2,3)
// enum Direction {
// Up,
// Down,
// Left,
// Right
// }
// // 第一个值5开始,从5开始加
// enum Direction {
// Up = 5,
// Down,
// Left,
// Right
// }
// 可以是字符串
enum Direction {
Up = 'Up',
Down = 'Down',
Left = 'Left',
Right = 'Right'
}
const changeDirection = (d: Direction) => {
console.log('方向值', d)
}
changeDirection(Direction.Left)
枚举的应用场景:
// 男 0 女 1
enum Gender {
Boy,
Girl
}
const changeGender = (gender: Gender) => {
if (gender === Gender.Boy) {
console.log('男')
}
}
changeGender(Gender.Boy)
// 待付款 1 已付款 5 已完成 8
enum OrderStatus {
Unpay = 1,
Payed = 5,
Complete = 8
}
const changeStatus = (status: OrderStatus) => {
if (status === OrderStatus.Complete) {
console.log('订单已完成')
}
}
changeStatus(OrderStatus.Complete)
项目中
创建enums/index.ts中,创建类型。并在对象类型文件d.ts中使用。
// 问诊类型
export enum ConsultType {
Doctor = 1, // 找医生
Fast = 2, // 快速问诊
Medication = 3 // 开药问诊
}
// 问诊时间
export enum ConsultTime {
Week = 1, // 一周内
Month, // 一月内
HalfYear, // 半年内
More // 半年以上
}
d.ts文件中:
export type Consult = {
type: ConsultType // 问诊类型
illnessTime: ConsultTime // 问诊时间
}
聊天室
websocket 可以实现双向通信
是一种网络通信协议,和 HTTP 协议 一样。
为什么需要websocket ?
因为 HTTP 协议有一个缺陷:通信只能由客户端发起。
socket.io
socket.io 是一个基于 WebSocket 的 CS(客户端-服务端)的实时通信库
使用它可以在后端提供一个即时通讯服务
它也提供一个 js 库,在前端可以去链接后端的 socket.io 创建的服务
总结: 它是一套基于 websocket 前后端即时通讯解决方案
安装: pnpm add socket.io-client
import { MsgType } from '@/enums/index'
import type { TimeMessages, Message } from '@/types/room'
import { io } from 'socket.io-client'
import type { Socket } from 'socket.io-client'
import { baseURL } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
const store = useUserStore()
const route = useRoute()
let socket: Socket
onMounted(() => {
// 1、建立连接 (组件挂载完毕时,建立连接、组件卸载、关闭连接)
// 参数一:服务器地址 参数二:配置参数
socket = io(baseURL, {
// 身份认证
auth: {
token: `Bearer ${store.user?.token}` // 格式要求
},
// 订单id(从地址栏中取下来)
query: {
orderId: route.query.orderId
}
})
// 2、连接成功(可在浏览器network中的WS查看连接情况)
socket.on('connect', () => {
console.log('连接成功')
})
// 关闭连接
socket.on('disconnect', () => {
console.log('断开连接')
})
// 发生错误
socket.on('error', (err) => {
console.log('发生错误', err)
})
// 获取消息记录(默认消息) (前面是解构的语法,后面是类型(自定义))
socket.on('chatMsgList', ({ data }: { data: TimeMessages[] }) => {
const arr: Message[] = []
data.forEach((item, i) => {
// 记录消息分组的起始时间,作为下次获取聊天记录的时间
if (i === 0) time.value = item.createTime
arr.push({
id: item.createTime,
msgType: MsgType.Notify,
createTime: item.createTime,
msg: {
content: item.createTime
}
})
// 给每一组数据的最后面加上 是否需要滚动(因为图片信息接收的时候会自动滚动到最后)
item.items.forEach((item) => {
arr.push({ ...item, notScroll: initialMsg.value === false })
})
})
// 将处理好的数据放入list中(新消息要放到最上方)
list.value.unshift(...arr)
// 关闭刷新效果
loading.value = false
if (!data.length) {
showToast('没有更多了')
}
// 第一次获取默认消息滚动到最底部
nextTick(() => {
if (initialMsg.value) {
// 把默认加载到的消息全部改为已读
socket.emit('updateMsgStatus', arr[arr.length - 1].id)
window.scrollTo(0, document.body.scrollHeight)
initialMsg.value = false
}
})
})
// 通讯状态改变(有多种,比如未接诊,进行中,已结束等,每次变化都获取一次订单详情)
socket.on('statusChange', async () => {
const res = await getConsultOrderDetail(route.query.orderId as string)
consult.value = res.data
})
// 接收消息
socket.on('receiveChatMsg', (msg: Message) => {
list.value.push(msg)
await nextTick() // 因为是收信息是异步的,所以要等渲染完再操作
// 修改消息为已读
socket.emit('updateMsgStatus', msg.id)
window.scrollTo(0, document.body.scrollHeight) // 将消息展示区滚动到最底部
})
})
// 3、关闭连接
onUnmounted(() => {
socket.close()
})
// 发送文字消息
const sendText = (text: string) => {
socket.emit('sendChatMsg', {
from: store.user?.id, // 发送人
to: consult.value?.docInfo?.id, // 接收人
msgType: MsgType.MsgText, // 消息类型
msg: {
content: text
} // 消息内容(文字,图片)
})
// 加载更多聊天记录
// 1. 默认的聊天记录滚动到最底部
// 2. 实现下拉刷新效果
// 3. 下拉刷新后,发送一个获取聊天记录的消息给后台
// 4. 触发聊天记录事件,记录当前时间段最早的时间,作为发送聊天记录消息的参数给后台
// 4.1 判断如果有数据,追加到数组,如果没有数据,轻提示没有数据
// 4.2 之后获取消息不需要滚动到底部
// 5. 再次连接socket的时候,要清空聊天记录,反之有重复出现消息
const initialMsg = ref(true)
const loading = ref(false)
const time = ref(moment().format('YYYY-MM-DD HH:mm:ss'))
const onRefresh = () => {
// 获取更多消息(下拉刷新) (消息内容实际还是靠chatMsgList获取)
socket.emit('getChatMsgList', 20, time.value, consult.value?.id) // 后台要求的参数是20条数据,时间和用户id
}