Browse Source

企业: 从精英管理发起聊天

lifanagju_citu 9 months ago
parent
commit
ea4f685766

+ 13 - 2
src/hooks/web/useIM.js

@@ -24,6 +24,8 @@ import {
 // 默认招呼语
 export const defaultText = '您好,关注到您发布该职位信息,请问有机会与您进一步沟通吗?'
 
+// 企业默认招呼语
+export const defaultTextEnt = '您好,我们正在寻找充满激情、勇于挑战的您,快来和我聊一聊吧~'
 
 const ObjType = [ 101, 102, 103, 104 ]
 
@@ -400,12 +402,18 @@ export function send (text, _channel, type) {
   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 = {
@@ -416,11 +424,14 @@ export async function checkConversation (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
+    channel: _channel,
+    isNewTalk: isNewTalk.value
   }
 }

+ 23 - 23
src/views/recruit/components/message/components/chatting.vue

@@ -58,8 +58,8 @@
         <div v-for="(val, i) in items" :key="i" :id="val.id">
           <div class="time-box">{{ timesTampChange(+(val.timestamp.padEnd(13, '0'))) }}</div>
           
-          <!-- <template v-if="val.payload.type === 102 && val.from_uid !== IM.uid"> -->
-          <template v-if="val.payload.type === 102">
+          <!-- <template v-if="val.payload?.type === 102 && val.from_uid !== IM.uid"> -->
+          <template v-if="val.payload?.type === 102">
             <v-card
               color="teal"
               variant="tonal"
@@ -69,12 +69,12 @@
               :elevation="3"
             >
               <div class="pa-3">
-                <div class="text-h6"> {{ val.payload.content.positionInfo.name }}</div>
-                <div class="text-subtitle-2">薪酬待遇: {{ val.payload.content.positionInfo.payFrom }} - {{ val.payload.content.positionInfo.payTo }}</div>
+                <div class="text-h6"> {{ val.payload?.content.positionInfo.name }}</div>
+                <div class="text-subtitle-2">薪酬待遇: {{ val.payload?.content.positionInfo.payFrom }} - {{ val.payload?.content.positionInfo.payTo }}</div>
                 <div>
                   <v-chip
                     color="secondary"
-                    v-for="(v, i) in val.payload.content.positionInfo.enterprise.welfareList"
+                    v-for="(v, i) in val.payload?.content.positionInfo.enterprise.welfareList"
                     :key="val.message_id + v + i"
                     x-small
                     class="mt-1 mr-1"
@@ -85,14 +85,14 @@
                 <v-divider class="my-3"></v-divider>
                 <div class="text-subtitle-2 text-right">
                   <v-avatar size="24">
-                    <v-img :src="val.payload.content.positionInfo.contact.avatar"></v-img>
+                    <v-img :src="val.payload?.content.positionInfo.contact.avatar"></v-img>
                   </v-avatar>
-                  {{ val.payload.content.positionInfo.contact.name }}
-                  {{ val.payload.content.positionInfo.contact.postNameCn }}
-                  {{ val.payload.content.positionInfo.enterprise.name }}
+                  {{ val.payload?.content.positionInfo.contact.name }}
+                  {{ val.payload?.content.positionInfo.contact.postNameCn }}
+                  {{ val.payload?.content.positionInfo.enterprise.name }}
                 </div>
                 <div class="text-subtitle-2 text-right">
-                  地址:{{ val.payload.content.positionInfo.address }}
+                  地址:{{ val.payload?.content.positionInfo.address }}
                 </div>
               </div>
             </v-card>
@@ -109,36 +109,36 @@
               </v-avatar>
             </div>
             <!-- 显示沟通职位 -->
-            <template v-if="val.payload.type === 102">              
+            <template v-if="val.payload?.type === 102">              
               <div  class="message-text" :class="{ active: val.from_uid === IM.uid}">
-                {{ val.payload.content.text }}
+                {{ val.payload?.content.text }}
               </div>
             </template>
             <!-- 发起面试邀请 -->
-            <div v-else-if="val.payload.type === 101">
+            <div v-else-if="val.payload?.type === 101">
               <v-chip class="ma-2" color="teal" label>
                 <v-icon icon="mdi-email-newsletter" start></v-icon>
                 发起了面试邀请
               </v-chip>
             </div>
-            <div v-else-if="val.payload.type === 103">
+            <div v-else-if="val.payload?.type === 103">
               <v-chip class="ma-2" label color="error">
                 <v-icon icon="mdi-close" start></v-icon>
                 拒绝了面试邀请
               </v-chip>
             </div>
-            <div v-else-if="val.payload.type === 104">
+            <div v-else-if="val.payload?.type === 104">
               <v-chip class="ma-2" label color="primary">
                 <v-icon icon="mdi-check" start></v-icon>
                 接受了面试邀请
               </v-chip>
             </div>
             <div v-else class="message-text" :class="{ active: val.from_uid === IM.uid}">
-              {{ val.payload.content }}
+              {{ val.payload?.content }}
             </div>
           </div>
           <!-- 插入个人-面试职位邀请:同意、拒绝 -->
-          <div v-if="isEnterprise && val.payload.type === 101" class="d-flex justify-center">
+          <div v-if="isEnterprise && val.payload?.type === 101" class="d-flex justify-center">
             <v-card
               color="teal"
               variant="tonal"
@@ -154,17 +154,17 @@
                   </div>
                   <div class=" d-flex justify-space-between">
                     <div class="text-h6 mb-1">
-                      {{ val.payload.content.positionInfo.data.name }}
+                      {{ val.payload?.content.positionInfo.data.name }}
                     </div>
                     <div>
-                      {{ val.payload.content.positionInfo.data.payFrom }} - 
-                      {{ val.payload.content.positionInfo.data.payTo }}
+                      {{ val.payload?.content.positionInfo.data.payFrom }} - 
+                      {{ val.payload?.content.positionInfo.data.payTo }}
                     </div>
                   </div>
 
-                  <div class="text-caption">面试时间: {{ timesTampChange(val.payload.content?.time) }}</div>
-                  <div class="text-caption">面试地点: {{ val.payload.content.address }}</div>
-                  <div class="text-caption">联系电话: {{ val.payload.content.invitePhone }}</div>
+                  <div class="text-caption">面试时间: {{ timesTampChange(val.payload?.content?.time) }}</div>
+                  <div class="text-caption">面试地点: {{ val.payload?.content.address }}</div>
+                  <div class="text-caption">联系电话: {{ val.payload?.content.invitePhone }}</div>
                 </div>
               </v-card-item>
             </v-card>

+ 3 - 2
src/views/recruit/components/message/index.vue

@@ -159,14 +159,15 @@ if (!IM) {
 if (route.query.id) {
   const api = route.query.enterprise ? getPositionDetails : getUserInfo
   const res = await api({ id: route.query.id })
+  const query = route.query.enterprise ? [res.contact?.userId, res.contact?.enterpriseId] : [res?.id]
   onMounted(() => {
     nextTick(async () => {
-      const { channel } = await checkConversation(res.contact.userId, res.contact.enterpriseId)
+      const { channel } = await checkConversation(...query)
       const items = [
         {
           channel,
           userInfoVo: {
-            userInfoResp: res.contact
+            userInfoResp: route.query.enterprise ? res.contact : { ...res, userId: res.id}
           }
         }
       ]

+ 22 - 9
src/views/recruit/enterprise/elite/components/table.vue

@@ -10,7 +10,7 @@
       item-value="id"
     >
       <template #bottom></template>
-      <template v-slot:item.name="{ item }">
+      <template v-slot:[`item.name`]="{ item }">
         <div class="d-flex align-center cursor-pointer" @click="handleToPersonDetail(item)">
           <v-badge
             bordered
@@ -22,13 +22,14 @@
           <span class="defaultLink ml-3">{{ item?.person?.name }}</span>
         </div>
       </template>
-      <template v-slot:item.status="{ item }">
+      <template v-slot:[`item.status`]="{ item }">
         <span v-if="tab === 0">{{ item.status && item.status === '0' ? '未查看' : '已查看' }}</span>
         <span v-else>{{ item.status ? props.statusList.find(i => i.value === item.status).label : '' }}</span>
       </template>
-      <template v-slot:item.actions="{ item }">
+      <template v-slot:[`item.actions`]="{ item }">
         <v-btn v-if="tab === 0" color="primary" variant="text" @click="handlePreviewResume(item)">查看附件</v-btn>
-        <!-- <v-btn v-if="tab === 0" color="primary" variant="text" @click="handleInterviewInvite(item)">邀请面试</v-btn> -->
+        <v-btn v-if="tab === 0" color="primary" variant="text" @click="handleInterviewInvite(item)">邀请面试</v-btn>
+        <v-btn v-if="tab === 0" color="primary" variant="text" @click="handleToCommunicate(item)">立即沟通</v-btn>
         <v-btn v-if="tab === 0 || tab === 1" color="primary" variant="text" @click="handleEliminate(item)">不合适</v-btn>
         <v-btn v-if="tab === 1 && (item.status === '3' || item.status === '4')" color="primary" variant="text" @click="handleEnterByEnterprise(item)">入职</v-btn>
         <v-btn v-if="tab === 4" color="primary" variant="text" @click="handleCancelEliminate(item)">取消不合适</v-btn>
@@ -56,6 +57,8 @@ import { useUserStore } from '@/store/user'
 import Snackbar from '@/plugins/snackbar'
 import InvitePage from './invite.vue'
 import { getUserAvatar } from '@/utils/avatar'
+import { talkToUser, defaultTextEnt } from '@/hooks/web/useIM'
+import { useRouter } from 'vue-router'; const router = useRouter()
 // import PublicPage from './public.vue'
 
 const { t } = useI18n()
@@ -156,11 +159,21 @@ const handlePreviewResume = async ({ url, id }) => {
 // 邀请面试
 const itemData = ref({})
 // const inviteType = ref(false)
-// const handleInterviewInvite = (item) => {
-//   // if (item?.job?.hire) inviteType.value = true
-//   itemData.value = item
-//   showInvite.value = true
-// }
+const handleInterviewInvite = (item) => {
+  // if (item?.job?.hire) inviteType.value = true
+  itemData.value = item
+  showInvite.value = true
+}
+
+const handleToCommunicate = async (item) => {
+  const userId = item.userId
+  // const textObj = { text: defaultTextEnt }
+  await talkToUser({userId, text: defaultTextEnt})
+  // const url = '/recruit/enterprise/communication'
+  let url = `/recruit/enterprise/communication?id=${userId}`
+
+  router.push(url)
+}
 
 const handleEditClose = () => {
   showInvite.value = false