zhengnaiwen_citu 7 月之前
父節點
當前提交
02fe83edc3
共有 6 個文件被更改,包括 248 次插入101 次删除
  1. 24 15
      hooks/useIM.js
  2. 10 1
      layout/index.vue
  3. 2 2
      pages.json
  4. 55 13
      pages/index/communicate.vue
  5. 8 62
      pages/index/welfare.vue
  6. 149 8
      pagesA/chart/index.vue

+ 24 - 15
hooks/useIM.js

@@ -65,7 +65,7 @@ function initRegister (type) {
     }
   }
   // 注册101类型为面试
-  WKSDK.shared().register(type, () => new ObjectContent())
+  WKSDK.shared().register(type, () => new ObjectContent(''))
   return {
     ObjectContent
   }
@@ -73,7 +73,7 @@ function initRegister (type) {
 
 
 const HISTORY_QUERY = {
-  limit: 30,
+  limit: 20,
   startMessageSeq: 0,
   endMessageSeq: 0,
   pullMode: 1
@@ -97,7 +97,7 @@ export function useDataSource () {
     const resultConversations = []
     const resp = await getConversationSync(query)
     // console.log(resp)
-    const conversationList = resp
+    const { data:conversationList } = resp
     if (conversationList) {
       conversationList.forEach(conversation => {
         conversation.channel = new Channel(conversation.channel_id, conversation.channel_type)
@@ -126,7 +126,8 @@ export function useDataSource () {
       pull_mode,
     }
 
-    const resp = await getMessageSync(query)
+    const { data } = await getMessageSync(query)
+    const resp = data
     const messageList = resp && resp["messages"]
     if (messageList) {
       messageList.forEach((msg) => {
@@ -155,9 +156,9 @@ async function getKey () {
     userId: useUserStore.accountInfo.userId
   }
 
-  const { uid, wsUrl, token } = await getChatKey(keyQuery)
+  const { data } = await getChatKey(keyQuery)
   return {
-    uid, wsUrl, token
+    ...data
   }
 }
 
@@ -167,15 +168,8 @@ export const useIM = () => {
   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 (需要在悟空通讯端注册过)
+    await resetConfig()
     // 连接状态监听
     WKSDK.shared().connectManager.addConnectStatusListener(connectStatusListener)
     // 常规消息监听
@@ -216,6 +210,20 @@ export const useIM = () => {
     IM.setUnreadCount(count)
     console.log('未读消息总数', count)
   }
+
+  async function resetConfig () {
+    const { uid, wssUrl, token } = await getKey()
+    console.log(uid, wssUrl, token)
+    IM.setUid(uid)
+    // 单机模式可以直接设置地址
+    WKSDK.shared().config.addr = 'wss://' + wssUrl// 默认端口为5200 + wsUrl 
+    // 认证信息
+    WKSDK.shared().config.uid = uid // 用户uid(需要在悟空通讯端注册过)
+    WKSDK.shared().config.token = token // 用户token (需要在悟空通讯端注册过)
+  }
+  return {
+    resetConfig
+  }
 }
 
 export function initConnect (callback = () => {}) {
@@ -320,7 +328,8 @@ export async function initChart (userId, enterpriseId) {
     enterpriseId
   }
   // 创建聊天频道
-  const { uid } = await getChatKey(query)
+  const { data } = await getChatKey(query)
+  const { uid } = data
   const _channel = new Channel(uid, ChannelTypePerson)
   channel.value = _channel
   const conversation = WKSDK.shared().conversationManager.findConversation(_channel)

+ 10 - 1
layout/index.vue

@@ -22,7 +22,16 @@
 <script setup>
 import authModal from './components/auth-modal.vue'
 import { useIM } from '@/hooks/useIM'
-useIM()
+import { watch } from 'vue'
+import { userStore } from '@/store/user'
+const { resetConfig } = useIM()
+const useUserStore = userStore()
+watch(() => useUserStore.accountInfo.userId, (newVal, oldVal) => {
+  if (useUserStore.isLogin) {
+		// 监听登录状态
+    resetConfig()
+	}
+})
 
 </script>
 <style lang="scss" scoped>

+ 2 - 2
pages.json

@@ -34,7 +34,7 @@
 		{
 			"path": "pages/index/communicate",
 			"style": {
-				"navigationBarTitleText": "沟通"
+				"navigationBarTitleText": "最近联系人"
 			}
 		}
 	],
@@ -81,7 +81,7 @@
 				{
 					"path": "chart/index",
 					"style": {
-						"navigationBarTitleText": "聊天"
+						"navigationBarTitleText": "我的聊天"
 					}
 				}
 			]

+ 55 - 13
pages/index/communicate.vue

@@ -2,17 +2,33 @@
   <layout-page class="ss-m-x-15">
     <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>
+				<template v-if="item.unread === '0'">
+					<image
+						class="enterAvatar"
+						:src="getUserAvatar(item?.userInfoVo?.userInfoResp?.avatar, item?.userInfoVo?.userInfoResp?.sex)"
+					></image>
+				</template>
+				<template v-else>
+					<uni-badge class="uni-badge-left-margin" :text="item.unread" absolute="rightTop" size="small">
+						<image
+							class="enterAvatar"
+							:src="getUserAvatar(item?.userInfoVo?.userInfoResp?.avatar, item?.userInfoVo?.userInfoResp?.sex)"
+						></image>
+					</uni-badge>
+				</template>
+				
 			</view>
 			<view class="box-content">
 				<view class="box-content-names">
-					<view class="name">{{ item.name }}</view>
-					<view class="time">{{ item.updateTime }}</view>
+					<view class="name">
+						{{ item.thatName }}
+						<text class="nameSub">{{ item.enterpriseAnotherName }}</text>
+						<span class="line" v-if="item.postNameCn && item.enterpriseAnotherName"></span>
+						<text class="nameSub">{{ item.postNameCn }}</text>
+					</view>
+					<!-- <view class="time">{{ item.updateTime }}</view> -->
 				</view>
-				<view class="box-content-text">{{ item.history }}</view>
+				<view class="box-content-text">{{ timesTampChange(+item.timestamp.padEnd(13, '0')) }}</view>
 			</view>
 		</view>
 		<image
@@ -31,7 +47,8 @@ import { getAccessToken } from '@/utils/request'
 import { showAuthModal } from '@/hooks/useModal'
 import { getConversationSync } from '@/api/common'
 import { onShow } from '@dcloudio/uni-app'
-
+import { getUserAvatar } from '@/utils/avatar'
+import { timesTampChange } from '@/utils/date'
 import { userStore } from '@/store/user'
 
 const useUserStore = userStore()
@@ -52,9 +69,14 @@ onShow(() => {
 
 
 
-const handleTo = (item) => {
+const handleTo = ({ userInfoVo, thatName, postNameCn, enterpriseAnotherName  }) => {
+	const id = `id=${userInfoVo.userInfoResp.userId}`
+	const name = `name=${thatName}`
+	const postName = `postName=${postNameCn}`
+	const enterpriseName = `enterpriseName=${enterpriseAnotherName}`
+	const enterpriseId = `enterpriseId=${userInfoVo?.userInfoResp?.enterpriseId}`
 	uni.navigateTo({
-    url: `/pagesA/chart/index?id=${item.id}&name=${item.name}`
+    url: `/pagesA/chart/index?${id}&${name}&${postName}&${enterpriseName}&${enterpriseId}`
   })
 }
 
@@ -69,11 +91,18 @@ const handleTo = (item) => {
 
 async function init () {
 	try {
-		const resp = await getConversationSync({ msg_count: 1 })
-		if (!resp) {
+		const { data } = await getConversationSync({ msg_count: 1 })
+		if (!data || !data.length) {
 			return
 		}
-		console.log(resp)
+		items.value = data.map(item => {
+			return {
+				thatName: item.userInfoVo ? (item.userInfoVo.userInfoResp.name ? item.userInfoVo.userInfoResp.name : '游客') : '系统消息',
+				enterpriseAnotherName: item.userInfoVo?.userInfoResp?.enterpriseAnotherName ?? '',
+				postNameCn: item.userInfoVo?.userInfoResp?.postNameCn ?? '',
+				...item
+			}
+		})
 	} catch (error) {
 
 	}
@@ -93,6 +122,7 @@ async function init () {
 	&-header {
 		width: 120rpx;
 		height: 100%;
+		position: relative;
 	}
 	&-content {
 		flex: 1;
@@ -109,6 +139,18 @@ async function init () {
 				overflow: hidden;
 				white-space: nowrap;
 				text-overflow: ellipsis;
+				.nameSub {
+					font-size: 0.75em;
+					color: #999;
+				}
+				.line {
+					display: inline-block;
+					width: 2rpx;
+					height: 24rpx;
+					vertical-align: middle;
+					background-color: #e0e0e0;
+					margin: 0 6rpx;
+				}
 			}
 			.time {
 				color: #999;

+ 8 - 62
pages/index/welfare.vue

@@ -1,76 +1,22 @@
 <template>
   <layout-page>
-		<view class="ss-p-b-30">
-			<view class="d-flex">
-				<view v-for="(item, index) in itemList" :key="index" class="parent">
-					<view class="d-flex justify-space-between">
-						<view>
-							<view class="colors">
-								<span>查看更多</span>
-								<uni-icons color="#c8c5c4" type="right" size="15" class="ml"/>
-							</view>
-							<view class="size-16">{{ item.title }}</view>
-						</view>
-						<view>
-							<uni-icons color="#00897B" :type="item.icon" size="45"/>
-						</view>
-					</view>
-				</view>
-			</view>
-	
-			<view style="height: 10rpx; background-color: #f8f8fa;"></view>
-	
-			<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 || ''"></uni-list-item>
-				</uni-list>
-			</view>
+		<view class="box">
+			<SwiperAd :list="swiperAdList"></SwiperAd>
+			<view class=""></view>
 		</view>
 	</layout-page>
 </template>
 
 <script setup>
+import { ref } from 'vue'
 import layoutPage from '@/layout'
+import SwiperAd from '@/components/SwiperAd'
 
-const itemList = [
-	{ title: "面试管理", path: "/pagesA/interview/index", icon: "list" },
-	{ title:'谁看过我', path:'/pagesA/seenMe/index', icon:'staff' }
-]
+import { swiperAdListTest } from '@/utils/testData'
 
-const list = [
-	{	title: '附件简历',	path: '/pagesA/resume/index'	},					
-	{ title: '我的收藏', path: '/pagesA/collect/index' },
-	{ title: '前往门墩儿甄选商城', appId: 'wx6decdf12f9e7a061' },
-	{ title: '切换为招聘者', rightTex: '我要招人' }
-]
+const swiperAdList = ref(swiperAdListTest)
 </script>
 
 <style scoped lang="scss">
-::v-deep .uni-list-item{
-	height: 140rpx !important;
-	line-height: 140rpx !important;
-}
-::v-deep .uni-list-item__content-title{
-	font-size: 32rpx !important;
-	font-weight: 500;
-}
-.colors{
-	font-size: 24rpx;
-	color: #606266;
-}
-.size-16{
-	color: #3f424f;
-	font-size: 32rpx;
-	margin: 13rpx 0 5rpx 0;
-}
-.parent{
-	width: 50%;
-	border: 1px solid #f4f4f4;
-	border-radius: 10rpx;
-	margin: 0 30rpx 20rpx 30rpx;
-	padding: 20rpx;
-}
-.parent:first-child{
-	margin: 0 0 20rpx 30rpx;
-}
+
 </style>

+ 149 - 8
pagesA/chart/index.vue

@@ -2,25 +2,87 @@
   <view class="box">
     <view class="box-top">
       {{ info.name }}
+      <text class="subText">
+        {{ info.postName }}
+        <text v-if="info.postName && info.enterpriseName" class="gun">|</text>
+        {{ info.enterpriseName }}
+      </text>
+    </view>
+    <view class="box-main"  ref="chatRef">
+      <view v-for="val in items" :key="val.id">
+        <view class="box-main-time">{{ timesTampChange(+(val.timestamp.padEnd(13, '0'))) }}</view>
+        <view :class="['message-view_item', val.from_uid === IM.uid ? 'is-self' : 'is-other']">
+          <view class="image">
+            
+            <image
+              class="header"
+              :src="(val.from_uid === IM.uid ? mAvatar : getUserAvatar(info.avatar, info.sex)) || 'https://minio.citupro.com/dev/menduner/7.png'"
+            ></image>
+          </view>
+          <view class="message-text" :class="{ active: val.from_uid === IM.uid}">
+            {{ val.payload?.content }}
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="box-bottom">
+      <textarea
+        auto-height
+        confirm-type="send"
+        @confirm="handleSend"
+      />
     </view>
-    <view class="box-main"></view>
-    <view class="box-bottom"></view>
   </view>
 </template>
 
 <script setup>
-import { ref } from 'vue'
+import { ref, nextTick } from 'vue'
+import { useIMStore } from '@/store/im'
+import { userStore } from '@/store/user'
+import { timesTampChange } from '@/utils/date'
+import { getUserAvatar } from '@/utils/avatar'
+import { initConnect, send, initChart, getMoreMessages, checkConversation } from '@/hooks/useIM'
 import { onLoad } from '@dcloudio/uni-app'
 
+const useUserStore = userStore()
+const IM = useIMStore()
+const mAvatar = getUserAvatar(useUserStore.baseInfo?.avatar, useUserStore.baseInfo?.sex)
 const info = ref({})
+const chatRef = ref()
+const items = ref([])
+
 
+async function init(userId, enterpriseId) {
+  const { channel, list, more } = await initChart(userId, enterpriseId)
+  console.log(channel.value, list.value, more)
+  items.value = list.value
+  setTimeout(() => {
+    scrollBottom()
+    console.log('滚动')
+  }, 1500)
+}
 
+function handleSend () {
+  console.log('发送')
+}
 
-onLoad((options) => {
-  console.log(options.id)
-  info.value = {
-    name: options.name
+function scrollBottom () {
+  const chat = chatRef.value
+  if (chat) {
+    nextTick(function () {
+      console.log(chat.scrollHeight)
+      chat.scrollTop = chat.scrollHeight
+      uni.pageScrollTo({
+        scrollTop: 0,
+        duration: 300
+      })
+    })
   }
+}
+
+onLoad((options) => {
+  info.value = options
+  init(options.id, options.enterpriseId)
 })
 </script>
 
@@ -28,7 +90,9 @@ onLoad((options) => {
 .box {
   width: 100%;
   height: calc(100vh - 88rpx);
-  .box-top {
+  display: flex;
+  flex-direction: column;
+  &-top {
     padding: 0 60rpx;
     box-sizing: border-box;
     width: 100%;
@@ -39,6 +103,83 @@ onLoad((options) => {
     overflow: hidden;
     white-space: nowrap;
     text-overflow: ellipsis;
+    .subText {
+      font-size: .85em;
+      color: #999;
+      .gun {
+        padding: 0 10rpx;
+      }
+    }
+  }
+
+  &-main {
+    flex: 1;
+    height: 0;
+    padding: 40rpx;
+    overflow-y: auto;
+    &-time {
+      user-select: none;
+      position: relative;
+      top: 16rpx;
+      margin: 40rpx 0;
+      text-align: center;
+      max-height: 40rpx;
+      text-align: center;
+      font-weight: 400;
+      font-size: .85em;
+      color: #999;
+    }
+    .message-view_item {
+      display: flex;
+      flex-direction: row;
+      align-items: flex-start;
+      margin: 16rpx 0;
+      position: relative;
+      .image {
+        width: 60rpx;
+        height: 60rpx;
+        border-radius: 180rpx;
+        // flex-grow: 1;
+        // flex-shrink: 0;
+        overflow: hidden;
+        .header {
+          width: 60rpx;
+          height: 60rpx;
+        }
+      }
+      .message-text {
+        overflow-wrap: break-word;
+        background-color: #f0f2f5;
+        border-radius: 12rpx;
+        max-width: 80%;
+        padding: 20rpx;
+        &.active {
+          background: #d5e6e8;
+        }
+      }
+    }
+    .is-self {
+      flex-direction: row-reverse;
+      display: flex;
+      .message-text {
+        margin-right: 20rpx;
+      }
+    }
+    .is-other {
+      .message-text {
+        margin-left: 20rpx;
+      }
+    }
+  }
+  &-bottom {
+    max-height: 300rpx;
+    border-top: 2rpx solid #EEE;
+    textarea {
+      width: 100%;
+      min-height: 40rpx;
+      padding: 20rpx;
+      background: rgba(211, 211, 211, 0.05);
+    }
   }
 }
 </style>