zhengnaiwen_citu 7 ماه پیش
والد
کامیت
15fb685ee2

+ 67 - 0
api/common.js

@@ -178,4 +178,71 @@ export const getAreaTreeData = () => {
       auth: false
     }
   })
+}
+
+
+
+
+// 同步最近会话
+export const getConversationSync = async (data) => {
+  return request({
+    url: '/app-api/im/conversation/sync',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false,
+      auth: true
+    }
+  })
+}
+
+
+// 获取聊天秘钥信息
+export const getChatKey = async (data) => {
+  return request({
+    url: '/app-api/im/user/get',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false,
+      auth: true
+    }
+  })
+}
+
+// 同步最近会话
+export const getMessageSync = async (data) => {
+  return request({
+    url: '/app-api/im/im/channel/messagesync',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false,
+      auth: true
+    }
+  })
+}
+// 设置最近会话未读数量
+export const setUnread = async (data) => {
+  return request({
+    url: '/app-api/im/conversations/setUnread',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false,
+      auth: true
+    }
+  })
+}
+// 设置最近会话未读数量
+export const deleteConversation = async (data) => {
+  return request({
+    url: '/app-api/im/conversation/delete',
+    method: 'POST',
+    data,
+    custom: {
+      showLoading: false,
+      auth: true
+    }
+  })
 }

+ 428 - 0
hooks/useIM.js

@@ -0,0 +1,428 @@
+
+
+
+import { ref, onMounted, onUnmounted, watch } from 'vue';
+import { getConversationSync, getMessageSync, getChatKey, setUnread, deleteConversation } from '@/api/common'
+import { Base64 } from 'js-base64'
+
+import { userStore } from '@/store/user'
+import { useIMStore } from '@/store/im'
+
+
+// 配置悟空IM
+import {
+  MessageText,
+  Channel,
+  WKSDK,
+  ChannelTypePerson,
+  MessageContent,
+} from "wukongimjssdk"
+
+// 默认招呼语
+export const defaultText = '您好,关注到您发布该职位信息,请问有机会与您进一步沟通吗?'
+
+// 企业默认招呼语
+// export const defaultTextEnt = '您好,我们正在寻找充满激情、勇于挑战的您,快来和我聊一聊吧~'
+
+
+const { ObjectContent } = initRegister(101)
+const { ObjectContent: ObjectContent2 } = initRegister(102)
+const { ObjectContent: ObjectContent3 } = initRegister(103)
+const { ObjectContent: ObjectContent4 } = initRegister(104)
+const { ObjectContent: ObjectContent5 } = initRegister(105) // 发送简历
+
+
+const contentType = {
+  101: ObjectContent,
+  102: ObjectContent2,
+  103: ObjectContent3,
+  104: ObjectContent4,
+  105: ObjectContent5, // 发送简历
+}
+
+// 注册消息体
+function initRegister (type) {
+  class ObjectContent extends MessageContent {
+    constructor(text) {
+      super();
+      this.content = text
+    }
+    get conversationDigest() {
+        // 这里需要实现具体的逻辑
+        return this.content
+    }
+    get contentType() {
+        // 这里需要实现具体的逻辑
+        return type; // 示例实现
+    }
+    decodeJSON(content) {
+        this.content = content.text;
+    }
+    encodeJSON() {
+        return {
+          content: this.content
+        };
+    }
+  }
+  // 注册101类型为面试
+  WKSDK.shared().register(type, () => new ObjectContent())
+  return {
+    ObjectContent
+  }
+}
+
+
+const HISTORY_QUERY = {
+  limit: 30,
+  startMessageSeq: 0,
+  endMessageSeq: 0,
+  pullMode: 1
+}
+
+const ConnectStatus = {
+  Disconnect: 0, // 断开连接
+  Connected: 1, // 连接成功
+  Connecting: 2, // 连接中
+  ConnectFail: 3, // 连接错误
+  ConnectKick: 4, // 连接被踢,服务器要求客户端断开(一般是账号在其他地方登录,被踢)
+}
+// api 接入
+export function useDataSource () {
+  // 最近会话数据源
+  WKSDK.shared().config.provider.syncConversationsCallback  = async () => {
+    const query = {
+      msg_count: 1
+    }
+
+    const resultConversations = []
+    const resp = await getConversationSync(query)
+    // console.log(resp)
+    const conversationList = resp
+    if (conversationList) {
+      conversationList.forEach(conversation => {
+        conversation.channel = new Channel(conversation.channel_id, conversation.channel_type)
+        conversation.unread = +(conversation.unread || 0)
+        resultConversations.push(conversation)
+      })
+    }
+    return resultConversations
+  }
+    // 同步频道消息数据源
+  WKSDK.shared().config.provider.syncMessagesCallback = async function(channel) {
+    // 后端提供的获取频道消息列表的接口数据 然后构建成 Message对象数组返回
+    let resultMessages  = new Array()
+    const {
+      startMessageSeq: start_message_seq,
+      endMessageSeq: end_message_seq,
+      limit,
+      pullMode: pull_mode
+    } = HISTORY_QUERY
+    const query = {
+      channel_id: channel.channelID,
+      channel_type: channel.channelType,
+      start_message_seq,
+      end_message_seq,
+      limit,
+      pull_mode,
+    }
+
+    const resp = await getMessageSync(query)
+    const messageList = resp && resp["messages"]
+    if (messageList) {
+      messageList.forEach((msg) => {
+        // const message = Convert.toMessage(msg);
+        // msg.channel = new Channel(msg.channel_id, msg.channel_type)
+        msg.payload = JSON.parse(Base64.decode(msg.payload))
+        if (contentType[msg.payload.type]) {
+          msg.payload.content = JSON.parse(msg.payload.content ?? '{}')
+        }
+        resultMessages.push(msg)
+      })
+    }
+    // console.log(resultMessages)
+    const more = resp.more === 1
+    return {
+      more,
+      resultMessages
+    }
+  }
+}
+
+async function getKey () {
+  const useUserStore = userStore()
+
+  const keyQuery = {
+    userId: useUserStore.accountInfo.userId
+  }
+
+  const { uid, wsUrl, token } = await getChatKey(keyQuery)
+  return {
+    uid, wsUrl, token
+  }
+}
+
+export const useIM = () => {
+  useDataSource()
+  const key = ref(0)
+  const IM = useIMStore()
+  
+  onMounted( async () => {
+    
+    // 通过自身userId和企业id获取token和uid
+    const { uid, wsUrl, token } = await getKey()
+    IM.setUid(uid)
+    // 单机模式可以直接设置地址
+    WKSDK.shared().config.addr = 'wss://' + wsUrl // 默认端口为5200
+    // 认证信息
+    WKSDK.shared().config.uid = uid // 用户uid(需要在悟空通讯端注册过)
+    WKSDK.shared().config.token = token // 用户token (需要在悟空通讯端注册过)
+    // 连接状态监听
+    WKSDK.shared().connectManager.addConnectStatusListener(connectStatusListener)
+    // 常规消息监听
+    WKSDK.shared().chatManager.addMessageListener(messageListen)
+    // 连接
+    WKSDK.shared().connectManager.connect()
+  })
+  onUnmounted(() => {
+    WKSDK.shared().connectManager.removeConnectStatusListener(connectStatusListener)
+    // 常规消息监听移除
+    WKSDK.shared().chatManager.removeMessageListener(messageListen)
+    // 连接状态监听移除
+    WKSDK.shared().connectManager.disconnect()
+  })
+  
+  async function messageListen (message) {
+    // console.log('收到消息', message)
+    IM.setFromChannel(message.channel.channelID)
+    setUnreadCount()
+  }
+
+  async function connectStatusListener (status) {
+    // console.log('连接状态', status === ConnectStatus.Connected)
+    // 连接成功 获取点击数
+    const connected = status === ConnectStatus.Connected
+    IM.setConnected(connected)
+    if (connected) {
+      // 必须同步最近会话才能获取未读总数
+      await syncConversation()
+      setUnreadCount()
+    }
+  }
+
+  function setUnreadCount () {
+    const count = WKSDK.shared().conversationManager.getAllUnreadCount()
+    key.value++
+    IM.setNewMsg(key.value)
+    IM.setUnreadCount(count)
+    console.log('未读消息总数', count)
+  }
+}
+
+export function initConnect (callback = () => {}) {
+  useDataSource()
+  const IM = useIMStore()
+  const conversationList = ref([])
+  const messageItems = ref([])
+
+  watch(
+    () => IM.newMsg,
+    async () => {
+      // 未读消息变化
+      updateConversation()
+      // 拉取最新消息 查看是否是自己的数据
+    },
+    {
+      deep: true,
+      immediate: true
+    }
+  )
+  onMounted(async () => {
+    // 消息发送状态监听
+    WKSDK.shared().chatManager.addMessageStatusListener(statusListen)
+    // 常规消息监听
+    // WKSDK.shared().chatManager.addMessageListener(messageListen)
+  })
+  onUnmounted(() => {
+    // 消息发送状态监听移除
+    WKSDK.shared().chatManager.removeMessageStatusListener(statusListen)
+    // 常规消息监听移除
+    // WKSDK.shared().chatManager.removeMessageListener(messageListen)
+  })
+
+  // 消息发送状态监听
+  function statusListen (packet) {
+    if (packet.reasonCode === 1) {
+      // 发送成功
+      console.log('发送成功')
+      // 添加一组成功数据
+      callback(true)
+    } else {
+      // 发送失败
+      console.log('发送失败')
+      // 添加一组失败数据
+      callback(false)
+    }
+  }
+
+  async function updateConversation () {
+    const res = await syncConversation()
+    conversationList.value = res
+  }
+
+  function updateUnreadCount () {
+    const count = WKSDK.shared().conversationManager.getAllUnreadCount()
+    IM.setUnreadCount(count)
+  } 
+
+  async function deleteConversations (channel, enterpriseId) {
+    const query = {
+      channel_id: channel.channelID,
+      channel_type: channel.channelType,
+      enterpriseId
+    }
+    await deleteConversation(query)
+  }
+
+  async function resetUnread (channel, enterpriseId) {
+    const query = {
+      channel_id: channel.channelID,
+      channel_type: channel.channelType,
+      enterpriseId,
+      unread: 0
+    }
+    const res = await setUnread(query)
+    return res
+  }
+
+  return {
+    resetUnread,
+    deleteConversations,
+    updateConversation,
+    updateUnreadCount,
+    conversationList,
+    messageItems,
+    // channel
+  }
+}
+
+// 同步最近会话
+async function syncConversation () {
+  const res = await WKSDK.shared().conversationManager.sync()
+  return res
+}
+
+// 发起聊天
+export async function initChart (userId, enterpriseId) {
+  const channel = ref()
+  // const list = ref([])
+  const query = {
+    userId,
+    enterpriseId
+  }
+  // 创建聊天频道
+  const { uid } = await getChatKey(query)
+  const _channel = new Channel(uid, ChannelTypePerson)
+  channel.value = _channel
+  const conversation = WKSDK.shared().conversationManager.findConversation(_channel)
+  if(!conversation) {
+    // 如果最近会话不存在,则创建一个空的会话
+    WKSDK.shared().conversationManager.createEmptyConversation(_channel)
+  }
+  const res = await getMoreMessages(1, _channel)
+  return {
+    channel,
+    ...res
+  }
+}
+
+// 翻页
+export async function getMoreMessages (pageSize, channel) {
+  const list = ref([])
+  Object.assign(HISTORY_QUERY, {
+    startMessageSeq: (pageSize - 1) * HISTORY_QUERY.limit
+  })
+  const { resultMessages, more } = await WKSDK.shared().chatManager.syncMessages(channel)
+  list.value = resultMessages
+  return {
+    list,
+    more
+  }
+}
+
+/**
+ * 
+ * @param {*} text 
+ * @param {*} _channel 
+ * @param { Number } type : 101 面试主体 
+ * @returns 
+ */
+  // 发送职位使用101
+export function send (text, _channel, type) {
+  let _text
+  if (contentType[type]) {
+    _text = new contentType[type](text)
+    WKSDK.shared().chatManager.send(_text, _channel)
+    return
+  }
+  // if (type === 101) {
+  //   _text = new ObjectContent(text)
+  //   WKSDK.shared().chatManager.send(_text, _channel)
+  //   // console.log(_text)
+  //   return
+  // }
+  // if (type === 102) {
+  //   _text = new ObjectContent2(text)
+  //   WKSDK.shared().chatManager.send(_text, _channel)
+  //   // console.log(_text)
+  //   return
+  // }
+  // // 求职者拒绝面试邀请
+  // if (type === 103) {
+  //   _text = new ObjectContent3(text)
+  //   WKSDK.shared().chatManager.send(_text, _channel)
+  //   return
+  // }
+  // // 求职者接受面试邀请
+  // if (type === 104) {
+  //   _text = new ObjectContent4(text)
+  //   WKSDK.shared().chatManager.send(_text, _channel)
+  //   return
+  // }
+  _text = new MessageText(text)
+  // console.log(_text)
+  WKSDK.shared().chatManager.send(_text, _channel)
+}
+
+// 对话开场白 用户 to 企业
+export async function prologue ({userId, enterpriseId, text}) {
+  const { channel } = await checkConversation(userId, enterpriseId)
+  send(text, channel, 102)
+}
+
+// 企业 to 用户
+export async function talkToUser ({userId, text}) {
+  const { channel, isNewTalk } = await checkConversation(userId)
+  if (!isNewTalk) send(text, channel)
+}
+
+// 检测是否存在频道
+export async function checkConversation (userId, enterpriseId) {
+  const query = {
+    userId,
+    enterpriseId
+  }
+  // 创建聊天频道
+  const { uid } = await getChatKey(query)
+  const _channel = new Channel(uid, ChannelTypePerson)
+  const conversation = WKSDK.shared().conversationManager.findConversation(_channel)
+  const isNewTalk = ref(false)
+  if(!conversation) {
+    // 如果最近会话不存在,则创建一个空的会话
+    WKSDK.shared().conversationManager.createEmptyConversation(_channel)
+    isNewTalk.value = true
+  }
+  return {
+    channel: _channel,
+    isNewTalk: isNewTalk.value
+  }
+}

+ 5 - 1
layout/components/authModal/login/index.vue

@@ -133,7 +133,11 @@ const handleLogin = async () => {
   if (!protocol.value) return uni.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
   const validate = await unref(current.value === 0 ? smsLoginRef : accountLoginRef).validate()
   if (!validate) return
-  await useUserStore.handleSmsLogin(current.value === 0 ? state.value.sms : state.value.account, current.value === 0 ? true : false)
+  const query = current.value === 0 ? state.value.sms : state.value.account
+  Object.assign(query, {
+    account: query.phone
+  })
+  await useUserStore.handleSmsLogin(query, current.value === 0 ? true : false)
 }
 </script>
 

+ 2 - 0
layout/index.vue

@@ -21,6 +21,8 @@
 
 <script setup>
 import authModal from './components/auth-modal.vue'
+import { useIM } from '@/hooks/useIM'
+useIM()
 
 </script>
 <style lang="scss" scoped>

+ 120 - 1
package-lock.json

@@ -6,12 +6,14 @@
     "": {
       "dependencies": {
         "dayjs": "^1.11.13",
+        "js-base64": "^3.7.7",
         "lodash-es": "^4.17.21",
         "luch-request": "^3.1.1",
         "pinia": "^2.2.2",
         "pinia-plugin-persist-uni": "^1.3.1",
         "pinia-plugin-persistedstate": "^4.0.1",
-        "qs": "^6.13.0"
+        "qs": "^6.13.0",
+        "wukongimjssdk": "^1.2.10"
       }
     },
     "node_modules/@ampproject/remapping": {
@@ -450,6 +452,20 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/@types/bignumber.js": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz",
+      "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==",
+      "deprecated": "This is a stub types definition for bignumber.js (https://github.com/MikeMcl/bignumber.js/). bignumber.js provides its own type definitions, so you don't need @types/bignumber.js installed!",
+      "dependencies": {
+        "bignumber.js": "*"
+      }
+    },
+    "node_modules/@types/crypto-js": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmmirror.com/@types/crypto-js/-/crypto-js-4.2.2.tgz",
+      "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="
+    },
     "node_modules/@types/estree": {
       "version": "1.0.6",
       "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
@@ -494,6 +510,33 @@
         "node": ">= 8"
       }
     },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/bignumber.js": {
+      "version": "9.1.2",
+      "resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.1.2.tgz",
+      "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==",
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/binary-extensions": {
       "version": "2.3.0",
       "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -547,6 +590,29 @@
         "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
       }
     },
+    "node_modules/buffer": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz",
+      "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.2.1"
+      }
+    },
     "node_modules/c12": {
       "version": "1.11.2",
       "resolved": "https://registry.npmmirror.com/c12/-/c12-1.11.2.tgz",
@@ -720,6 +786,16 @@
         "node": ">= 8"
       }
     },
+    "node_modules/crypto-js": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
+      "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
+    },
+    "node_modules/curve25519-js": {
+      "version": "0.0.4",
+      "resolved": "https://registry.npmmirror.com/curve25519-js/-/curve25519-js-0.0.4.tgz",
+      "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w=="
+    },
     "node_modules/dayjs": {
       "version": "1.11.13",
       "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
@@ -1107,6 +1183,25 @@
         "node": ">=16.17.0"
       }
     },
+    "node_modules/ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
     "node_modules/ignore": {
       "version": "5.3.2",
       "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz",
@@ -1177,6 +1272,11 @@
         "jiti": "bin/jiti.js"
       }
     },
+    "node_modules/js-base64": {
+      "version": "3.7.7",
+      "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.7.tgz",
+      "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw=="
+    },
     "node_modules/js-tokens": {
       "version": "9.0.0",
       "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.0.tgz",
@@ -1266,6 +1366,11 @@
         "@jridgewell/sourcemap-codec": "^1.5.0"
       }
     },
+    "node_modules/md5-typescript": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/md5-typescript/-/md5-typescript-1.0.5.tgz",
+      "integrity": "sha512-ovAc4EtiNt2dY8JPhPr/wkC9h4U5k/nuClNVcG0Ga3V1rMlYpAY24ZaaymFXJlz+ccJ6UMPo3FSaVKe7czBsXw=="
+    },
     "node_modules/merge-stream": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -2022,6 +2127,20 @@
         "node": ">= 8"
       }
     },
+    "node_modules/wukongimjssdk": {
+      "version": "1.2.10",
+      "resolved": "https://registry.npmmirror.com/wukongimjssdk/-/wukongimjssdk-1.2.10.tgz",
+      "integrity": "sha512-MX4NJoXGV+KnxZ6kK8UwsjLWEewGQudmCGV2d4/vrtI99Z78EkfWARPyVGX3jkqX0vwDzxid2JrcQewuo3vXGA==",
+      "dependencies": {
+        "@types/bignumber.js": "^5.0.0",
+        "@types/crypto-js": "^4.0.2",
+        "bignumber.js": "^9.0.1",
+        "buffer": "^6.0.3",
+        "crypto-js": "^4.1.1",
+        "curve25519-js": "^0.0.4",
+        "md5-typescript": "^1.0.5"
+      }
+    },
     "node_modules/yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",

+ 3 - 1
package.json

@@ -1,11 +1,13 @@
 {
   "dependencies": {
     "dayjs": "^1.11.13",
+    "js-base64": "^3.7.7",
     "lodash-es": "^4.17.21",
     "luch-request": "^3.1.1",
     "pinia": "^2.2.2",
     "pinia-plugin-persist-uni": "^1.3.1",
     "pinia-plugin-persistedstate": "^4.0.1",
-    "qs": "^6.13.0"
+    "qs": "^6.13.0",
+    "wukongimjssdk": "^1.2.10"
   }
 }

+ 6 - 0
pages.json

@@ -77,6 +77,12 @@
 					"style": {
 						"navigationBarTitleText": "我的推荐"
 					}
+				},
+				{
+					"path": "chart/index",
+					"style": {
+						"navigationBarTitleText": "聊天"
+					}
 				}
 			]
 		},

+ 113 - 39
pages/index/communicate.vue

@@ -1,59 +1,133 @@
 <template>
   <layout-page class="ss-m-x-15">
-    <SwiperAd :list="swiperAdListTest"></SwiperAd>
-    <view class="card">
-			<uni-list>
-				<uni-list-item v-for="item in list" :clickable="true" :key="item.title" :title="item.title" showArrow :rightText="item.rightTex || ''" @click="handleToLink(item)"></uni-list-item>
-			</uni-list>
+    <view class="box" v-for="item in items" :key="item.id" @tap="handleTo(item)">
+			<view class="box-header">
+				<image
+					class="enterAvatar"
+					:src="item.headers"
+				></image>
+			</view>
+			<view class="box-content">
+				<view class="box-content-names">
+					<view class="name">{{ item.name }}</view>
+					<view class="time">{{ item.updateTime }}</view>
+				</view>
+				<view class="box-content-text">{{ item.history }}</view>
+			</view>
 		</view>
+		<image
+			v-if=" items.length===0 "
+			src="https://minio.citupro.com/dev/static/nodata.png"
+			mode="widthFix"
+			style="width: 100vw;height: 100vh;">
+		</image>
   </layout-page>
 </template>
 
 <script setup>
-import SwiperAd from '@/components/SwiperAd'
+import { ref, watch } from 'vue'
 import layoutPage from '@/layout'
-import { swiperAdListTest } from '@/utils/testData'
 import { getAccessToken } from '@/utils/request'
 import { showAuthModal } from '@/hooks/useModal'
+import { getConversationSync } from '@/api/common'
+import { onShow } from '@dcloudio/uni-app'
 
-const list = [
-	{	title: '附件简历',	path: '/pagesA/resume/index'	},					
-	{ title: '我的收藏', path: '/pagesA/collect/index' },
-	{ title: '前往门墩儿甄选商城', appId: 'wx6decdf12f9e7a061' },
-	{ title: '切换为招聘者', rightTex: '我要招人' }
-]
-
-// 列表跳转
-const handleToLink = (item) => {
-	if (item.appId) {
-		uni.navigateToMiniProgram({
-			appId: item.appId,
-			// extraData: {} // 要传递的数据
-		})
-		return
-	}
-	if (!item.path) return
-  if (!getAccessToken()) {
-		uni.showToast({
-			title: '请先登录',
-			icon: 'none'
-		})
-		showAuthModal()
-		return
+import { userStore } from '@/store/user'
+
+const useUserStore = userStore()
+
+const items = ref([])
+
+watch(() => useUserStore.isLogin, (newVal, oldVal) => {
+  if (useUserStore.isLogin) {
+		// 监听登录状态
+		console.log('重新登录了')
+		init()
 	}
+})
+
+onShow(() => {
+	init()
+})
+
+
+
+const handleTo = (item) => {
 	uni.navigateTo({
-		url: item.path
-	})
+    url: `/pagesA/chart/index?id=${item.id}&name=${item.name}`
+  })
+}
+
+// if (!getAccessToken()) {
+// 	uni.showToast({
+// 		title: '请先登录',
+// 		icon: 'none'
+// 	})
+// 	showAuthModal()
+// 	return
+// }
+
+async function init () {
+	try {
+		const resp = await getConversationSync({ msg_count: 1 })
+		if (!resp) {
+			return
+		}
+		console.log(resp)
+	} catch (error) {
+
+	}
 }
+
+
+
 </script>
 
 <style scoped lang="scss">
-::v-deep .uni-list-item{
-	height: 140rpx !important;
-	line-height: 140rpx !important;
+.box {
+	height: 130rpx;
+	padding: 20rpx;
+	box-sizing: border-box;
+	display: flex;
+	border-bottom: 2rpx solid #eee;
+	&-header {
+		width: 120rpx;
+		height: 100%;
+	}
+	&-content {
+		flex: 1;
+		width: 0;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		&-names {
+			display: flex;
+			justify-content: space-between;
+			
+			.name {
+				flex: 1;
+				overflow: hidden;
+				white-space: nowrap;
+				text-overflow: ellipsis;
+			}
+			.time {
+				color: #999;
+				font-size: .85em;
+			}
+		}
+		&-text {
+			color: #999;
+			font-size: .85em;
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+		}
+	}
 }
-::v-deep .uni-list-item__content-title{
-	font-size: 32rpx !important;
-	font-weight: 500;
+.enterAvatar{
+	width: 80rpx;
+	height: 80rpx;
+	border-radius: 50%;
+	margin: 0 auto;
 }
 </style>

+ 1 - 1
pages/index/crowdsourcing.vue

@@ -37,7 +37,7 @@
 </template>
 
 <script setup>
-import { ref, reactive, watch } from 'vue'
+import { ref, reactive } from 'vue'
 import SwiperAd from '@/components/SwiperAd'
 import { showAuthModal } from '@/hooks/useModal'
 import { swiperAdListTest } from '@/utils/testData'

+ 44 - 0
pagesA/chart/index.vue

@@ -0,0 +1,44 @@
+<template>
+  <view class="box">
+    <view class="box-top">
+      {{ info.name }}
+    </view>
+    <view class="box-main"></view>
+    <view class="box-bottom"></view>
+  </view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+
+const info = ref({})
+
+
+
+onLoad((options) => {
+  console.log(options.id)
+  info.value = {
+    name: options.name
+  }
+})
+</script>
+
+<style lang="scss" scoped>
+.box {
+  width: 100%;
+  height: calc(100vh - 88rpx);
+  .box-top {
+    padding: 0 60rpx;
+    box-sizing: border-box;
+    width: 100%;
+    height: 80rpx;
+    line-height: 80rpx;
+    // text-align: center;
+    border-bottom: 2rpx solid #EEE;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+  }
+}
+</style>

+ 40 - 0
store/im.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+
+export const useIMStore = defineStore('IM', 
+  () => {
+    const uid = ref('')
+    const connected = ref(false)
+
+    const newMsg = ref(0)
+    const fromChannel = ref('')
+    const unreadCount = ref(0)
+
+    const setConnected = (val) => {
+      connected.value = val
+    }
+    const setUid = (val) => {
+      uid.value = val
+    }
+    const setNewMsg = (val) => {
+      newMsg.value = val
+    }
+    const setFromChannel = (val) => {
+      fromChannel.value = val
+    }
+    const setUnreadCount = (val) => {
+      unreadCount.value = val
+    }
+    return {
+      connected,
+      uid,
+      newMsg,
+      fromChannel,
+      unreadCount,
+      setUnreadCount,
+      setFromChannel,
+      setNewMsg,
+      setUid,
+      setConnected
+    }
+})

+ 22 - 10
unpackage/dist/cache/.vite/deps/_metadata.json

@@ -1,43 +1,55 @@
 {
-  "hash": "40cda080",
+  "hash": "47dcb4f1",
   "configHash": "06645ce3",
-  "lockfileHash": "a208743b",
-  "browserHash": "67856db3",
+  "lockfileHash": "8c101f21",
+  "browserHash": "f0bed5f8",
   "optimized": {
     "pinia-plugin-persistedstate": {
       "src": "../../../../../node_modules/pinia-plugin-persistedstate/dist/index.js",
       "file": "pinia-plugin-persistedstate.js",
-      "fileHash": "77c0d607",
+      "fileHash": "de8dc243",
       "needsInterop": false
     },
     "luch-request": {
       "src": "../../../../../node_modules/luch-request/src/lib/luch-request.js",
       "file": "luch-request.js",
-      "fileHash": "e2d71767",
+      "fileHash": "c5810002",
       "needsInterop": false
     },
     "qs": {
       "src": "../../../../../node_modules/qs/lib/index.js",
       "file": "qs.js",
-      "fileHash": "3bec4625",
+      "fileHash": "e4fd86e6",
       "needsInterop": true
     },
     "lodash-es": {
       "src": "../../../../../node_modules/lodash-es/lodash.js",
       "file": "lodash-es.js",
-      "fileHash": "02319e8d",
+      "fileHash": "cc0e5b4c",
       "needsInterop": false
     },
     "dayjs": {
       "src": "../../../../../node_modules/dayjs/dayjs.min.js",
       "file": "dayjs.js",
-      "fileHash": "f23d519e",
+      "fileHash": "faa24560",
       "needsInterop": true
+    },
+    "js-base64": {
+      "src": "../../../../../node_modules/js-base64/base64.mjs",
+      "file": "js-base64.js",
+      "fileHash": "9be10531",
+      "needsInterop": false
+    },
+    "wukongimjssdk": {
+      "src": "../../../../../node_modules/wukongimjssdk/lib/wukongimjssdk.esm.js",
+      "file": "wukongimjssdk.js",
+      "fileHash": "1f9bb9cc",
+      "needsInterop": false
     }
   },
   "chunks": {
-    "chunk-Y2F7D3TJ": {
-      "file": "chunk-Y2F7D3TJ.js"
+    "chunk-BQWMX7FD": {
+      "file": "chunk-BQWMX7FD.js"
     }
   }
 }