useIM.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. import { ref, onMounted, onUnmounted, watch } from 'vue';
  2. import { getConversationSync, getMessageSync, getChatKey, setUnread, deleteConversation } from '@/api/common'
  3. import { Base64 } from 'js-base64'
  4. import { useUserStore } from '@/store/user'
  5. import { useLoginType } from '@/store/loginType'
  6. import { useIMStore } from '@/store/im'
  7. // 配置悟空IM
  8. import {
  9. MessageText,
  10. Channel,
  11. WKSDK,
  12. ChannelTypePerson,
  13. // Conversation,
  14. MessageContent,
  15. // Message, StreamItem, ChannelTypeGroup, MessageStatus, SyncOptions, MessageExtra, MessageContent
  16. } from "wukongimjssdk"
  17. // 注册消息体
  18. class ObjectContent extends MessageContent {
  19. constructor(text) {
  20. super();
  21. this.content = text;
  22. }
  23. get conversationDigest() {
  24. // 这里需要实现具体的逻辑
  25. return this.content
  26. }
  27. get contentType() {
  28. // 这里需要实现具体的逻辑
  29. return 101; // 示例实现
  30. }
  31. decodeJSON(content) {
  32. this.content = content.text;
  33. }
  34. encodeJSON() {
  35. return {
  36. content: this.content
  37. };
  38. }
  39. }
  40. // 注册101类型为面试
  41. WKSDK.shared().register(101, () => new ObjectContent())
  42. const HISTORY_QUERY = {
  43. limit: 30,
  44. startMessageSeq: 0,
  45. endMessageSeq: 0,
  46. pullMode: 1
  47. }
  48. const ConnectStatus = {
  49. Disconnect: 0, // 断开连接
  50. Connected: 1, // 连接成功
  51. Connecting: 2, // 连接中
  52. ConnectFail: 3, // 连接错误
  53. ConnectKick: 4, // 连接被踢,服务器要求客户端断开(一般是账号在其他地方登录,被踢)
  54. }
  55. // api 接入
  56. export function useDataSource () {
  57. const userStore = useUserStore()
  58. const loginType = useLoginType()
  59. // 最近会话数据源
  60. WKSDK.shared().config.provider.syncConversationsCallback = async () => {
  61. const query = {
  62. msg_count: 100
  63. }
  64. if (loginType.loginType === 'enterprise') {
  65. Object.assign(query, { enterpriseId: userStore.baseInfo.enterpriseId })
  66. }
  67. const resultConversations = []
  68. const resp = await getConversationSync(query)
  69. // console.log(resp)
  70. const conversationList = resp
  71. if (conversationList) {
  72. conversationList.forEach(conversation => {
  73. conversation.channel = new Channel(conversation.channel_id, conversation.channel_type)
  74. conversation.unread = +(conversation.unread || 0)
  75. resultConversations.push(conversation)
  76. })
  77. }
  78. return resultConversations
  79. }
  80. // 同步频道消息数据源
  81. WKSDK.shared().config.provider.syncMessagesCallback = async function(channel) {
  82. // 后端提供的获取频道消息列表的接口数据 然后构建成 Message对象数组返回
  83. let resultMessages = new Array()
  84. const {
  85. startMessageSeq: start_message_seq,
  86. endMessageSeq: end_message_seq,
  87. limit,
  88. pullMode: pull_mode
  89. } = HISTORY_QUERY
  90. const query = {
  91. channel_id: channel.channelID,
  92. channel_type: channel.channelType,
  93. start_message_seq,
  94. end_message_seq,
  95. limit,
  96. pull_mode,
  97. }
  98. if (loginType.loginType === 'enterprise') {
  99. Object.assign(query, { enterpriseId: userStore.baseInfo.enterpriseId })
  100. }
  101. const resp = await getMessageSync(query)
  102. const messageList = resp && resp["messages"]
  103. if (messageList) {
  104. messageList.forEach((msg) => {
  105. // const message = Convert.toMessage(msg);
  106. // msg.channel = new Channel(msg.channel_id, msg.channel_type)
  107. msg.payload = JSON.parse(Base64.decode(msg.payload))
  108. if (msg.payload.type === 101) {
  109. msg.payload.content = JSON.parse(msg.payload.content ?? '{}')
  110. }
  111. resultMessages.push(msg);
  112. });
  113. }
  114. console.log(resultMessages)
  115. const more = resp.more === 1
  116. return {
  117. more,
  118. resultMessages
  119. }
  120. }
  121. }
  122. async function getKey () {
  123. const userStore = useUserStore()
  124. const loginType = useLoginType()
  125. const keyQuery = {
  126. userId: userStore.userInfo.id
  127. }
  128. if (loginType.loginType === 'enterprise') {
  129. Object.assign(keyQuery, { enterpriseId: userStore.baseInfo.enterpriseId })
  130. }
  131. const { uid, wsUrl, token } = await getChatKey(keyQuery)
  132. return {
  133. uid, wsUrl, token
  134. }
  135. }
  136. export const useIM = () => {
  137. useDataSource()
  138. const key = ref(0)
  139. const IM = useIMStore()
  140. onMounted( async () => {
  141. // 通过自身userId和企业id获取token和uid
  142. const { uid, wsUrl, token } = await getKey()
  143. IM.setUid(uid)
  144. // 单机模式可以直接设置地址
  145. WKSDK.shared().config.addr = 'ws://' + wsUrl // 默认端口为5200
  146. // 认证信息
  147. WKSDK.shared().config.uid = uid // 用户uid(需要在悟空通讯端注册过)
  148. WKSDK.shared().config.token = token // 用户token (需要在悟空通讯端注册过)
  149. // 连接状态监听
  150. WKSDK.shared().connectManager.addConnectStatusListener(connectStatusListener)
  151. // 常规消息监听
  152. WKSDK.shared().chatManager.addMessageListener(messageListen)
  153. // 连接
  154. WKSDK.shared().connectManager.connect()
  155. })
  156. onUnmounted(() => {
  157. WKSDK.shared().connectManager.removeConnectStatusListener(connectStatusListener)
  158. // 常规消息监听移除
  159. WKSDK.shared().chatManager.removeMessageListener(messageListen)
  160. // 连接状态监听移除
  161. WKSDK.shared().connectManager.disconnect()
  162. })
  163. async function messageListen (message) {
  164. console.log('收到消息', message)
  165. IM.setFromChannel(message.channel.channelID)
  166. setUnreadCount()
  167. }
  168. async function connectStatusListener (status) {
  169. // console.log('连接状态', status === ConnectStatus.Connected)
  170. // 连接成功 获取点击数
  171. const connected = status === ConnectStatus.Connected
  172. IM.setConnected(connected)
  173. if (connected) {
  174. // 必须同步最近会话才能获取未读总数
  175. await syncConversation()
  176. setUnreadCount()
  177. }
  178. }
  179. function setUnreadCount () {
  180. const count = WKSDK.shared().conversationManager.getAllUnreadCount()
  181. key.value++
  182. IM.setNewMsg(key.value)
  183. IM.setUnreadCount(count)
  184. console.log('未读消息总数', count)
  185. }
  186. }
  187. export function initConnect (callback = () => {}) {
  188. useDataSource()
  189. const IM = useIMStore()
  190. const conversationList = ref([])
  191. const messageItems = ref([])
  192. watch(
  193. () => IM.newMsg,
  194. async () => {
  195. // 未读消息变化
  196. updateConversation()
  197. // 拉取最新消息 查看是否是自己的数据
  198. },
  199. {
  200. deep: true,
  201. immediate: true
  202. }
  203. )
  204. onMounted(async () => {
  205. // 消息发送状态监听
  206. WKSDK.shared().chatManager.addMessageStatusListener(statusListen)
  207. // 常规消息监听
  208. // WKSDK.shared().chatManager.addMessageListener(messageListen)
  209. })
  210. onUnmounted(() => {
  211. // 消息发送状态监听移除
  212. WKSDK.shared().chatManager.removeMessageStatusListener(statusListen)
  213. // 常规消息监听移除
  214. // WKSDK.shared().chatManager.removeMessageListener(messageListen)
  215. })
  216. // 消息发送状态监听
  217. function statusListen (packet) {
  218. if (packet.reasonCode === 1) {
  219. // 发送成功
  220. console.log('发送成功')
  221. // 添加一组成功数据
  222. callback(true)
  223. } else {
  224. // 发送失败
  225. console.log('发送失败')
  226. // 添加一组失败数据
  227. callback(false)
  228. }
  229. }
  230. async function updateConversation () {
  231. const res = await syncConversation()
  232. conversationList.value = res
  233. }
  234. function updateUnreadCount () {
  235. const count = WKSDK.shared().conversationManager.getAllUnreadCount()
  236. IM.setUnreadCount(count)
  237. }
  238. async function deleteConversations (channel, enterpriseId) {
  239. const query = {
  240. channel_id: channel.channelID,
  241. channel_type: channel.channelType,
  242. enterpriseId
  243. }
  244. await deleteConversation(query)
  245. }
  246. async function resetUnread (channel, enterpriseId) {
  247. const query = {
  248. channel_id: channel.channelID,
  249. channel_type: channel.channelType,
  250. enterpriseId,
  251. unread: 0
  252. }
  253. const res = await setUnread(query)
  254. return res
  255. }
  256. return {
  257. resetUnread,
  258. deleteConversations,
  259. updateConversation,
  260. updateUnreadCount,
  261. conversationList,
  262. messageItems,
  263. // channel
  264. }
  265. }
  266. // 同步最近会话
  267. async function syncConversation () {
  268. const res = await WKSDK.shared().conversationManager.sync()
  269. return res
  270. }
  271. // 发起聊天
  272. export async function initChart (userId, enterpriseId) {
  273. const channel = ref()
  274. // const list = ref([])
  275. const query = {
  276. userId,
  277. enterpriseId
  278. }
  279. // 创建聊天频道
  280. const { uid } = await getChatKey(query)
  281. const _channel = new Channel(uid, ChannelTypePerson)
  282. channel.value = _channel
  283. const conversation = WKSDK.shared().conversationManager.findConversation(_channel)
  284. if(!conversation) {
  285. // 如果最近会话不存在,则创建一个空的会话
  286. WKSDK.shared().conversationManager.createEmptyConversation(_channel)
  287. }
  288. const res = await getMoreMessages(1, _channel)
  289. return {
  290. channel,
  291. ...res
  292. }
  293. }
  294. // 翻页
  295. export async function getMoreMessages (pageSize, channel) {
  296. const list = ref([])
  297. Object.assign(HISTORY_QUERY, {
  298. startMessageSeq: (pageSize - 1) * HISTORY_QUERY.limit
  299. })
  300. const { resultMessages, more } = await WKSDK.shared().chatManager.syncMessages(channel)
  301. list.value = resultMessages
  302. return {
  303. list,
  304. more
  305. }
  306. }
  307. /**
  308. *
  309. * @param {*} text
  310. * @param {*} _channel
  311. * @param { Number } type : 101 面试主体
  312. * @returns
  313. */
  314. export function send (text, _channel, type) {
  315. let _text
  316. if (type === 101) {
  317. _text = new ObjectContent(text)
  318. WKSDK.shared().chatManager.send(_text, _channel)
  319. console.log(_text)
  320. return
  321. }
  322. _text = new MessageText(text)
  323. console.log(_text)
  324. WKSDK.shared().chatManager.send(_text, _channel)
  325. }
  326. // 对话开场白
  327. export async function prologue ({userId, enterpriseId, text}) {
  328. const { channel } = await checkConversation(userId, enterpriseId)
  329. send(text, channel)
  330. }
  331. // 检测是否存在频道
  332. export async function checkConversation (userId, enterpriseId) {
  333. const query = {
  334. userId,
  335. enterpriseId
  336. }
  337. // 创建聊天频道
  338. const { uid } = await getChatKey(query)
  339. const _channel = new Channel(uid, ChannelTypePerson)
  340. const conversation = WKSDK.shared().conversationManager.findConversation(_channel)
  341. if(!conversation) {
  342. // 如果最近会话不存在,则创建一个空的会话
  343. WKSDK.shared().conversationManager.createEmptyConversation(_channel)
  344. }
  345. return {
  346. channel: _channel
  347. }
  348. }