zhengnaiwen_citu 9 months ago
parent
commit
8e3f20be6f
5 changed files with 388 additions and 183 deletions
  1. 26 0
      api/personalCenter.js
  2. 7 2
      hooks/useIM.js
  3. 6 8
      pages/index/communicate.vue
  4. 289 168
      pagesA/chart/index.vue
  5. 60 5
      pagesB/positionDetail/index.vue

+ 26 - 0
api/personalCenter.js

@@ -0,0 +1,26 @@
+
+import request from "@/utils/request"
+// 同意邀约面试
+export const userInterviewInviteConsent = async (params) => {
+  return request({
+    url: '/app-api/menduner/system/interview-invite/consent',
+    method: 'POST',
+    params,
+    custom: {
+      showLoading: false,
+      auth: false
+    }
+  })
+}
+
+// 拒绝邀约面试
+export const userInterviewInviteReject = async (id) => {
+  return request({
+    url: `/app-api/menduner/system/interview-invite/reject?id=${id}`,
+    method: 'POST',
+    custom: {
+      showLoading: false,
+      auth: false
+    }
+  })
+}

+ 7 - 2
hooks/useIM.js

@@ -225,7 +225,7 @@ export const useIM = () => {
   }
 }
 
-export function initConnect (callback = () => {}) {
+export function initConnect (callback = () => {}, mounted = () => {}) {
   useDataSource()
   const IM = useIMStore()
   const conversationList = ref([])
@@ -248,6 +248,8 @@ export function initConnect (callback = () => {}) {
     WKSDK.shared().chatManager.addMessageStatusListener(statusListen)
     // 常规消息监听
     // WKSDK.shared().chatManager.addMessageListener(messageListen)
+
+    mounted()
   })
   onUnmounted(() => {
     // 消息发送状态监听移除
@@ -405,6 +407,7 @@ export function send (text, _channel, type) {
 export async function prologue ({userId, enterpriseId, text}) {
   const { channel } = await checkConversation(userId, enterpriseId)
   send(text, channel, 102)
+  return channel
 }
 
 // 企业 to 用户
@@ -420,8 +423,10 @@ export async function checkConversation (userId, enterpriseId) {
     enterpriseId
   }
   // 创建聊天频道
-  const { uid } = await getChatKey(query)
+  const { data } = await getChatKey(query)
+  const { uid } = data
   const _channel = new Channel(uid, ChannelTypePerson)
+  console.log('生成channel', _channel)
   const conversation = WKSDK.shared().conversationManager.findConversation(_channel)
   const isNewTalk = ref(false)
   if(!conversation) {

+ 6 - 8
pages/index/communicate.vue

@@ -50,18 +50,16 @@ import { onShow } from '@dcloudio/uni-app'
 import { getUserAvatar } from '@/utils/avatar'
 import { timesTampChange } from '@/utils/date'
 import { userStore } from '@/store/user'
+import { useIMStore } from '@/store/im'
+  const IM = useIMStore()
 
 const useUserStore = userStore()
 
 const items = ref([])
-
-watch(
-	() => useUserStore.refreshToken, (newVal, oldVal) => {
-		// 监听登录状态
-		console.log('重新登录, 更新列表')
-		init()
-	}
-)
+watch([() => useUserStore.refreshToken, () => IM.newMsg], () => {  
+	console.log('变了')
+	init()
+})
 
 onShow(() => {
 	init()

+ 289 - 168
pagesA/chart/index.vue

@@ -17,7 +17,7 @@
               <text v-if="!val.job.payFrom && !val.job.payTo" class="ml-3">面议</text>
               <text v-else class="ml-3">{{ val.job.payFrom ? val.job.payFrom + '-' : '' }}{{ val.job.payTo }}</text>
             </view>
-            <view :style="`color: ${val.statusColor}`" >
+            <view :style="`color: ${val.statusColor};`" >
               {{ val.statusText }}
             </view>
           </view>
@@ -28,120 +28,123 @@
           </view>
           <view class="bottom">
             <view class="tipsText" @click="handleToCenter">在“个人中心-面试”中管理我的面试</view>
-            <view v-if="val.status === '0'">
-              <v-btn class="mr-3" variant="outlined" color="error" size="small" @click="handleRefuse(val)">拒绝邀请</v-btn>
-              <v-btn variant="outlined" color="primary" size="small" @click="handleAgree(val)">接受邀请</v-btn>
+            <view v-if="val.status === '0'" class="btnBox">
+              <button size="mini" type="warn" @click="handleRefuse(val)">拒绝邀请</button>
+              <button size="mini" type="primary" @click="handleAgree(val)">接受邀请</button>
             </view>
           </view>
         </view>
       </view>
     </view>
-    <view class="box-main"  ref="chatRef">
-      <view class="box-main-more" v-if="hasMore">
-        <text @click="handleMore">查看更多</text>
-      </view>
-      <view v-for="val in items" :key="val.id">
-        <view class="box-main-time">{{ timesTampChange(+(val.timestamp.padEnd(13, '0'))) }}</view>
-        <template v-if="val.payload?.type === 102">
-          <view class="jobCard">
-            <view class="jobCard-title"> {{ val.payload?.content?.positionInfo?.name }}</view>
-            <view
-              v-if="!val.payload?.content?.positionInfo?.payFrom && !val.payload?.content?.positionInfo?.payTo"
-              class="jobCard-subtitle">
-              薪酬待遇: 面议
-            </view>
-            <view
-              v-else
-              class="jobCard-subtitle"
-            >
-              薪酬待遇: 
-              {{ val.payload?.content?.positionInfo?.payFrom ? val.payload?.content?.positionInfo?.payFrom + ' - ' : '' }}
-              {{ val.payload?.content?.positionInfo?.payTo }}
-            </view>
-            <view class="jobCard-tag">
+    <!-- <view class="box-main"  ref="chatRef"> -->
+      <scroll-view class="box-main"  ref="chatRef" scroll-y="true" :scroll-top="scrollInto"  >
+        <view class="box-main-more" v-if="hasMore">
+          <text @click="handleMore">查看更多</text>
+        </view>
+        <view v-for="val in items" :key="val.id" :id="'s'+val.id+index">
+          <view class="box-main-time">{{ timesTampChange(+(val.timestamp.padEnd(13, '0'))) }}</view>
+          <template v-if="val.payload?.type === 102">
+            <view class="jobCard">
+              <view class="jobCard-title"> {{ val.payload?.content?.positionInfo?.name }}</view>
+              <view
+                v-if="!val.payload?.content?.positionInfo?.payFrom && !val.payload?.content?.positionInfo?.payTo"
+                class="jobCard-subtitle">
+                薪酬待遇: 面议
+              </view>
               <view
-                v-for="(v, i) in (val.payload?.content?.positionInfo?.enterprise?.welfareList || [])"
-                :key="val.message_id + v + i"
-                style="margin: 10rpx"
+                v-else
+                class="jobCard-subtitle"
               >
-                <uni-tag
-                  :text="v"
-                  type="success"
-                />
+                薪酬待遇: 
+                {{ val.payload?.content?.positionInfo?.payFrom ? val.payload?.content?.positionInfo?.payFrom + ' - ' : '' }}
+                {{ val.payload?.content?.positionInfo?.payTo }}
               </view>
-            </view>
-            <view class="jobCard-divider"></view>
-            <view class="jobCard-subtitle text-right">
-              <v-avatar size="24">
-                <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 }}
-            </view>
-            <div class="jobCard-subtitle text-right">
-              地址:{{ val.payload?.content?.positionInfo?.address }}
-            </div>
-          </view>
-        </template>
-        <view :class="['message-view_item', val.from_uid === IM.uid ? 'is-self' : 'is-other']">
-          <view class="image">
-            <image
-              :data-target="getUserAvatar(info.avatar, info.sex)"
-              class="header"
-              :src="(
-                val.from_uid === IM.uid ?
-                getUserAvatar(useUserStore.baseInfo?.avatar, useUserStore.baseInfo?.sex) :
-                getUserAvatar(info.avatar, info.sex)
-              )"
-            ></image>
-          </view>
-          <!-- 显示沟通职位 -->
-          <template v-if="val.payload?.type === 102">              
-            <view class="message-text" :class="val.from_uid === IM.uid ? 'active' : ''">
-              {{ val.payload?.content.text }}
+              <view class="jobCard-tag">
+                <view
+                  v-for="(v, i) in (val.payload?.content?.positionInfo?.enterprise?.welfareList || [])"
+                  :key="val.message_id + v + i"
+                  style="margin: 10rpx"
+                >
+                  <uni-tag
+                    :text="v"
+                    type="success"
+                  />
+                </view>
+              </view>
+              <view class="jobCard-divider"></view>
+              <view class="jobCard-subtitle text-right">
+                <v-avatar size="24">
+                  <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 }}
+              </view>
+              <div class="jobCard-subtitle text-right">
+                地址:{{ val.payload?.content?.positionInfo?.address }}
+              </div>
             </view>
           </template>
-          <!-- 发起面试邀请 -->
-          <view class="message-text none" v-else-if="val.payload?.type === 101">
-            <uni-tag text="发起了面试邀请" type="primary" />
-          </view>
-          <view class="message-text none" v-else-if="val.payload?.type === 103">
-            <uni-tag text="拒绝了面试邀请" type="error" />
-          </view>
-          <view class="message-text none" v-else-if="val.payload?.type === 104">
-            <uni-tag text="接受了面试邀请" type="success" />
-          </view>
-          <view v-else-if="val.payload.type === 105" class="text-end">
-            <uni-tag
-              v-if="val.from_uid === IM.uid"
-              :text="val.payload.content?.type === 1 ? '附件简历已发送' : '简历请求已发送'"
-              type="success"
-            />
-            <view
-              v-if="val.payload.content?.type !== 2 || val.from_uid !== IM.uid"
-              class="message-text card"
-            >
-              <view class="text-left">
-                <text v-if="val.payload.content?.type === 1">{{
-                  val.payload.content?.query?.title || '附件简历' }}
-                </text>
-                <text v-if="val.payload.content?.type === 2">
-                  我想要一份您的简历,您是否同意
-                </text>
+          <view :class="['message-view_item', val.from_uid === IM.uid ? 'is-self' : 'is-other']">
+            <view class="image">
+              <image
+                :data-target="getUserAvatar(info.avatar, info.sex)"
+                class="header"
+                :src="(
+                  val.from_uid === IM.uid ?
+                  getUserAvatar(useUserStore.baseInfo?.avatar, useUserStore.baseInfo?.sex) :
+                  getUserAvatar(info.avatar, info.sex)
+                )"
+              ></image>
+            </view>
+            <!-- 显示沟通职位 -->
+            <template v-if="val.payload?.type === 102">              
+              <view class="message-text" :class="val.from_uid === IM.uid ? 'active' : ''">
+                {{ val.payload?.content.text }}
               </view>
-              <view class="btn-actions">
-                <text class="btn" v-if="val.payload.content?.type === 1" @tap="handlePreview(val.payload)">点击预览附件简历</text>
-                <text class="btn" v-if="val.payload.content?.type === 2" @tap="handleFindResume">点击发送附件简历</text>
+            </template>
+            <!-- 发起面试邀请 -->
+            <view class="message-text none" v-else-if="val.payload?.type === 101">
+              <uni-tag text="发起了面试邀请" type="primary" />
+            </view>
+            <view class="message-text none" v-else-if="val.payload?.type === 103">
+              <uni-tag text="拒绝了面试邀请" type="error" />
+            </view>
+            <view class="message-text none" v-else-if="val.payload?.type === 104">
+              <uni-tag text="接受了面试邀请" type="success" />
+            </view>
+            <view v-else-if="val.payload.type === 105" class="text-end">
+              <uni-tag
+                v-if="val.from_uid === IM.uid"
+                :text="val.payload.content?.type === 1 ? '附件简历已发送' : '简历请求已发送'"
+                type="success"
+              />
+              <view
+                v-if="val.payload.content?.type !== 2 || val.from_uid !== IM.uid"
+                class="message-text card"
+              >
+                <view class="text-left">
+                  <text v-if="val.payload.content?.type === 1">{{
+                    val.payload.content?.query?.title || '附件简历' }}
+                  </text>
+                  <text v-if="val.payload.content?.type === 2">
+                    我想要一份您的简历,您是否同意
+                  </text>
+                </view>
+                <view class="btn-actions">
+                  <text class="btn" v-if="val.payload.content?.type === 1" @tap="handlePreview(val.payload)">点击预览附件简历</text>
+                  <text class="btn" v-if="val.payload.content?.type === 2" @tap="handleFindResume">点击发送附件简历</text>
+                </view>
               </view>
             </view>
-          </view>
-          <view v-else class="message-text" :class="{ active: val.from_uid === IM.uid}">
-            {{ val.payload?.content }}
+            <view v-else class="message-text" :class="{ active: val.from_uid === IM.uid}">
+              {{ val.payload?.content }}
+            </view>
           </view>
         </view>
-      </view>
-    </view>
+      </scroll-view>
+      
+    <!-- </view> -->
     <view class="box-bottom">
       <view class="box-bottom-tool">
         <uni-tag text="发送简历" type="success" @tap="handleFindResume"/>
@@ -169,24 +172,44 @@
         </view>
         <text class="text" :class="resumeCheck.id === resume.id ? 'active' : ''">{{ resume.title }}</text>
       </view>
-      <view class="popup-actions">
+      <view v-if="!resumeList.length" class="popup-upload" @click="handleUploadResume">
+        <view class="popup-upload-box">
+          <uni-icons type="plusempty" size="50" color="#f1f1f1"></uni-icons>
+        </view>
+        <text>请先上传简历</text>
+      </view>
+      <view v-if="resumeList.length" class="popup-actions">
         <button class="default" type="default" @click="handleSendResume">发送简历</button>
       </view>
     </uni-popup>
+
+    <uni-popup ref="confirm" type="dialog">
+      <uni-popup-dialog
+        :type="isAgree ? 'success' : 'warn'"
+        cancelText="取消"
+        confirmText="确认" 
+        title="系统提示"
+        :content="isAgree ? '确认接受面试吗?' : '确认拒绝面试吗?'"
+        @confirm="handleConfirm"
+        @close="handleCloseConfirm"
+      ></uni-popup-dialog>
+    </uni-popup>
   </view>
 </template>
 
 <script setup>
 import { ref, nextTick, watch, computed } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
 import { useIMStore } from '@/store/im'
 import { userStore } from '@/store/user'
+import { initConnect, send, initChart, getMoreMessages } from '@/hooks/useIM'
+import { getDict } from '@/hooks/useDictionaries'
 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'
-import { getPersonResumeCv } from '@/api/user'
+import { preview } from '@/utils/preview'
+import { getPersonResumeCv, saveResume } from '@/api/user'
 import { getInterviewInviteListByInviteUserId } from '@/api/common'
-import { getDict } from '@/hooks/useDictionaries'
+import { userInterviewInviteReject, userInterviewInviteConsent } from '@/api/personalCenter'
 
 const useUserStore = userStore()
 const IM = useIMStore()
@@ -207,11 +230,18 @@ const interview = ref([])
 // 求职端-获取求职者与当前邀请人的面试记录
 const statusList = ref([])
 const inputValue = ref('')
+
+const isAgree = ref(false)
+const confirm = ref()
+const chooseInvite = ref(null)
+
+const scrollInto = ref(0)
+
 const {
   conversationList,
-  updateConversation,
+  // updateConversation,
   updateUnreadCount,
-  deleteConversations,
+  // deleteConversations,
   resetUnread
 } = initConnect(async (successful) => {
   if (!successful) {
@@ -234,13 +264,22 @@ const {
 watch(
   () => conversationList.value,
   async (val) => {
-    console.log(val.value)
     if (!channelItem.value) {
       return
     }
     const { list } = await getMoreMessages(1, channelItem.value)
+    if (list.value.length) {
+      const item = list.value[list.value.length - 1]
+      const arr = [101, 103, 104]
+      if (arr.includes(item.payload?.type)) {
+        getInterviewInviteList()
+      }
+    }
+    
     items.value = list.value
-    // if (Object.keys(info.value).length) updateUnreadMessageCount(val)
+    setScrollBottom()
+    // 清除未读消息
+    resetUnread(channelItem.value)
   },
   {
     deep: true,
@@ -253,15 +292,18 @@ async function init(userId, enterpriseId) {
   hasMore.value = more
   channelItem.value = channel.value
   items.value = list.value
+  setScrollBottom()
 }
 
-function showStatus (status) {
-  return statusList.value.find(e => e.value === status)?.label
+// 滑动到底部
+function setScrollBottom () {
+  // scrollInto.value = 200
 }
 
 async function getInterviewInviteList () {
   if (!info.value.id) return
   const { data } = await getInterviewInviteListByInviteUserId(info.value.id)
+  console.log(data, statusList)
   interview.value = data.slice(0, 1).map(e => {
     const statusItem = statusList.value.find(_e => _e.value === e.status)
     const statusText = statusItem?.label || ''
@@ -274,65 +316,28 @@ async function getInterviewInviteList () {
   })
 }
 
-const getStatusList = () => {
-  getDict('menduner_interview_invite_status').then(({data}) => {
-    if (data.length) statusList.value = data
-  })
+const getStatusList = async () => {
+  try {
+    const { data } = await getDict('menduner_interview_invite_status')
+    if (data.data.length) {
+      statusList.value = data.data
+    }
+  } catch (error) {
+
+  }
 }
 
 function handleSend () {
   send(inputValue.value, channelItem.value)
 }
 
-const getFileType = (url) => {  
-  const extension = url.split('.').pop().toLowerCase();  
-  switch (extension) {  
-    case 'pdf':  
-      return 'pdf';  
-    case 'doc':  
-    case 'docx':  
-      return 'doc';  
-    case 'xls':  
-    case 'xlsx':  
-      return 'xls';  
-    case 'ppt':  
-    case 'pptx':  
-      return 'ppt';  
-    case 'txt':  
-      return 'txt';  
-    default:  
-      return ''; // 不支持的文件类型  
-  }  
-}
 // 预览简历
 function handlePreview (payload) {
-  // 使用 wx.downloadFile 下载文档  
-  wx.downloadFile({  
-    url: payload.content.query.src,  
-    success: function (res) {  
-      // 下载成功后,打开文档  
-      if (res.statusCode === 200) {  
-        const fileType = getFileType(payload.content.query.src); // 动态获取文件类型  
-        if (fileType) {  
-          wx.openDocument({  
-            filePath: res.tempFilePath,  
-            fileType: fileType,  
-            success: function () {  
-              console.log('打开文档成功');  
-            },  
-            fail: function (error) {  
-              console.error('打开文档失败', error);  
-            }  
-          });  
-        } else {  
-          console.error('不支持的文件类型');  
-        }  
-      }  
-    },  
-    fail: function (error) {  
-      console.error('下载文件失败', error);  
-    }  
-  })
+  if (!payload?.content?.query?.src) {
+    uni.showToast({ title: '简历地址不存在', icon: 'none' })
+    return
+  }
+  preview(payload.content.query.src)
 }
 // 获取简历
 async function handleFindResume () {
@@ -358,12 +363,62 @@ async function handleFindResume () {
   }
 }
 
+// 关闭简历窗口
 function handleClose () {
   popup.value.close()
 }
 
-function handleSendResume () {}
+// 发送简历
+function handleSendResume () {
+  if (!Object.keys(resumeCheck.value).length) {
+    uni.showToast({ title: '请选择要投递的简历', icon: 'none' })
+    return
+  }
+  const text = {
+    remark: '发送简历',
+    query: {
+      src: resumeCheck.url,
+      title: resumeCheck.title,
+      id: resumeCheck.id,
+    },
+    type: 1
+  }
+  send (JSON.stringify(text), channelItem.value, 105)
+  popup.value.close()
+}
+
+// 拒绝邀请
+function handleRefuse (val) {
+  isAgree.value = false
+  chooseInvite.value = val
+  confirm.value.open()
+}
+
+// 接受邀请
+function handleAgree (val) {
+  isAgree.value = true
+  chooseInvite.value = val
+  confirm.value.open()
+}
 
+// 确认
+async function handleConfirm () {
+  // 拒绝
+  if (!isAgree.value) {
+    await userInterviewInviteReject(chooseInvite.value.id)
+  } else {
+    await userInterviewInviteReject(chooseInvite.value.id)
+  }
+  uni.showToast({ title: '操作成功', icon: 'none' })
+  send(JSON.stringify({ id: chooseInvite.value.id }), channelItem.value, isAgree.value ? 104 : 103)
+}
+
+// 关闭
+function handleCloseConfirm () {
+  confirm.value.close()
+}
+
+// 查看更多
 async function handleMore () {
   try {
     uni.showLoading({
@@ -378,14 +433,55 @@ async function handleMore () {
   }
 }
 
+// 上传简历
+function handleUploadResume () {
+  wx.chooseMessageFile({
+    count: 1,
+    type: 'file',
+    success (res) {
+      const title = res.tempFiles[0].name
+      const path = res.tempFiles[0].path
+      const test = /\.(pdf|docx|doc)$/.test(title)
+      if (!test) {
+        uni.showToast({
+          icon: 'none',
+          title: '请上传pdf、word类型的文件',
+          duration: 2000
+        })
+        return
+      }
+      //效验是否为支持的文件格式
+      uploadFile(path).then(async (res) => {
+        if (!res.data) {
+          uni.showToast({
+            title: '上传失败',
+            icon: 'none'
+          })
+          return
+        }
+        await saveResume({ title, url: res.data })
+        uni.showToast({
+          title: '上传成功',
+          icon: 'success'
+        })
+        handleFindResume()
+      })
+    }
+  })
+}
+
 onLoad(async (options) => {
   info.value = Object.keys(options).reduce((r, k) => {
     r[k] = decodeURIComponent(options[k])
     return r
   }, {})
-  getStatusList()
+  await init(options.id, options.enterpriseId)
+  await getStatusList()
   getInterviewInviteList()
-  init(options.id, options.enterpriseId)
+  // 清除未读消息
+  resetUnread(channelItem.value)
+  // 更新未读消息
+  updateUnreadCount()
 })
 </script>
 
@@ -457,6 +553,11 @@ onLoad(async (options) => {
         display: flex;
         justify-content: space-between;
       }
+      .btnBox {
+        display: flex;
+        padding: 20rpx 60rpx;
+        justify-content: space-around;
+      }
     }
   }
 
@@ -464,7 +565,8 @@ onLoad(async (options) => {
     flex: 1;
     height: 0;
     padding: 40rpx;
-    overflow-y: auto;
+    // overflow-y: auto;
+    box-sizing: border-box;
     &-more {
       display: flex;
       justify-content: center;
@@ -619,14 +721,33 @@ onLoad(async (options) => {
     .text {
       margin-left: 20rpx;
       &.active {
-        color: #43AC57;
+        color: #00897b;
       }
     }
   }
+  .popup-upload {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    width: 400rpx;
+    font-size: .75em;
+    color: #999;
+    padding-bottom: 40rpx;
+    &-box {
+      margin-top: 20rpx;
+      width: 200rpx;
+      height: 200rpx;
+      text-align: center;
+      line-height: 200rpx;
+      border: 4rpx solid #ddd;
+      border-radius: 8rpx;
+    }
+  }
   .popup-actions {
     padding: 60rpx;
     .default {
-      background: #43AC57;
+      background: #00897b;
       color: #DDD;
       font-size: .9em;
     }

+ 60 - 5
pagesB/positionDetail/index.vue

@@ -83,13 +83,14 @@
     </scroll-view>
     <!-- 分享 投递 -->
     <view class="bottom-sticky" v-if="!loading && jobId">
-      <view style="display: flex;justify-content: space-evenly;align-items: center;width: 100%;margin: 20rpx 0;">
-        <view @click="handleClickShare" style="display: flex;justify-content: center;flex-direction: column;align-items: center;">
+      <view class="bottom-content">
+        <view @click="handleClickShare" class="bottom-content-tool">
           <uni-icons type="redo-filled" size="24" color="#00897B"/>
           <span style="color:#00897B;font-weight:bold;">分享</span>
         </view>
-        <button v-if="delivery" :disabled="true" class="buttons disable">我已投递</button>
-        <button v-else class="buttons" @click="handleDelivery">我要投递</button>
+        <button class="btnStyle bgButtons" @tap="handleSend">立即沟通</button>
+        <button v-if="delivery" :disabled="true" class="buttons btnStyle disable">我已投递</button>
+        <button v-else class="buttons btnStyle" @click="handleDelivery">我要投递</button>
       </view>
     </view>
     <!-- 选择简历 -->
@@ -192,6 +193,7 @@ import { getPersonResumeCv, saveResume } from '@/api/user'
 import { dealDictObjData } from '@/utils/position'
 import { getAccessToken } from '@/utils/request'
 import { onLoad,onShareAppMessage,onShareTimeline } from '@dcloudio/uni-app'
+import { prologue, defaultText } from '@/hooks/useIM'
 
 const sharePopup = ref()
 const loading = ref(false)
@@ -210,7 +212,6 @@ const getPositionDetail = async () => {
     info.value = data
     positionInfo.value = { ...dealDictObjData({}, info.value), ...info.value }
     loading.value = false
-    console.log('positionInfo', positionInfo.value)
   } finally {
   }
 }
@@ -306,6 +307,36 @@ const popupClose = () => {
   popup.value.close()
 }
 
+// 发起聊天
+async function handleSend () {
+  const userId = info.value.contact.userId
+  const enterpriseId = info.value.contact.enterpriseId
+  const textObj = {
+    text: defaultText,
+    positionInfo: positionInfo.value
+  }
+  const channel = await prologue({userId, enterpriseId, text: JSON.stringify(textObj)})
+  console.log('channel', channel)
+  // 跳转
+  const query = {
+		id: userId,
+		name: info.value?.contact?.name,
+		postName: info.value?.contact?.postNameCn,
+		enterpriseName: info.value?.enterprise?.anotherName,
+		enterpriseId: info.value?.enterpriseId,
+		channelId: channel.channel_id,
+		avatar: info.value?.contact?.avatar,
+		sex: info.value?.contact?.sex,
+	}
+  console.log('query', query)
+	const queryStr = Object.keys(query).reduce((r, v) => {
+		return r += `${v}=${encodeURIComponent(query[v])}&`
+	}, '?')
+	uni.navigateTo({
+    url: `/pagesA/chart/index${queryStr.slice(0, -1)}`
+  })
+}
+
 // 效验求职者是否有收藏该职位
 const isCollection = ref(false)
 const getCollectionStatus = async () => {
@@ -385,6 +416,30 @@ const createPoster = async () => {
 </script>
 <style scoped lang="scss">
 @import '../../static/style/position/index.scss';
+.bottom-content {
+  display: flex;
+  justify-content: space-evenly;
+  align-items: center;
+  width: 100%;
+  margin: 20rpx 0;
+  .btnStyle {
+    flex: 1;
+    margin-right: 20rpx;
+  }
+  .bgButtons {
+    border: 2rpx solid #00897b;
+    color: #00897b;
+    background: #FFF;
+    border-radius: 50rpx;
+  }
+  &-tool {
+    width: 160rpx;
+    display: flex;
+    justify-content: center;
+    flex-direction: column;
+    align-items: center;
+  }
+}
 .share-pop {
     width: 100%;
     // height:300rpx;