Przeglądaj źródła

求简历 & 发送简历

zhengnaiwen_citu 9 miesięcy temu
rodzic
commit
10b19f8245

+ 11 - 11
src/hooks/web/useIM.js

@@ -21,14 +21,21 @@ import {
   // Message, StreamItem, ChannelTypeGroup, MessageStatus, SyncOptions, MessageExtra, MessageContent
 } from "wukongimjssdk"
 
-
-const ObjType = [ 101, 102, 103, 104 ]
-
 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 (contentType) {
   class ObjectContent extends MessageContent {
@@ -128,7 +135,7 @@ export function useDataSource () {
         // const message = Convert.toMessage(msg);
         // msg.channel = new Channel(msg.channel_id, msg.channel_type)
         msg.payload = JSON.parse(Base64.decode(msg.payload))
-        if (ObjType.includes(msg.payload.type)) {
+        if (contentType[msg.payload.type]) {
           msg.payload.content = JSON.parse(msg.payload.content ?? '{}')
         }
         resultMessages.push(msg)
@@ -354,13 +361,6 @@ export async function getMoreMessages (pageSize, channel) {
  * @returns 
  */
   // 发送职位使用101
-const contentType = {
-  101: ObjectContent,
-  102: ObjectContent2,
-  103: ObjectContent3,
-  104: ObjectContent4,
-  105: ObjectContent5, // 发送简历
-}
 export function send (text, _channel, type) {
   let _text
   if (contentType[type]) {

+ 1 - 0
src/locales/en.js

@@ -245,6 +245,7 @@ export default {
     uploadUpToFiveCopies: 'Upload up to 5 copies',
     accountWithdrawal: 'Account withdrawal',
     goldCoins: 'Remaining gold coins',
+    requestResume: 'I would like a copy of your resume, if you agree?'
   },
   setting: {
     accountSettings: 'Account Settings',

+ 1 - 0
src/locales/zh-CN.js

@@ -245,6 +245,7 @@ export default {
     uploadUpToFiveCopies: '最多上传5份',
     accountWithdrawal: '账户取现',
     goldCoins: '剩余金币',
+    requestResume: '我想要一份您的简历,您是否同意'
   },
   setting: {
     accountSettings: '账号设置',

+ 41 - 2
src/views/recruit/components/message/components/chatting.vue

@@ -101,7 +101,7 @@
             <div style="width: 40px; height: 40px;">
               <v-avatar>
                 <v-img
-                  :src="val.from_uid === IM.uid ? mAvatar : info.avatar"
+                  :src="(val.from_uid === IM.uid ? mAvatar : info.avatar) || 'https://minio.citupro.com/dev/menduner/7.png'"
                   :width="40"
                   height="40"
                   rounded
@@ -133,6 +133,23 @@
                 接受了面试邀请
               </v-chip>
             </div>
+            <div v-else-if="val.payload.type === 105">
+              <v-chip class="ma-2" label color="primary" v-if="val.from_uid === IM.uid">
+                <v-icon icon="mdi-check" start></v-icon>
+                {{ val.payload.content.type === 1 ? '附件简历已发送' : '简历请求已发送' }}
+              </v-chip>
+              <v-card v-else width="300" class="pa-3 ma-2" color="teal" variant="tonal" :elevation="3">
+                <v-card-text class="d-flex">
+                  <p v-if="val.payload.content.type === 1">{{ val.payload.content.query.title || t('resume.attachmentResume') }}</p>
+                  <p v-if="val.payload.content.type === 2">{{ t('resume.requestResume') }}</p>
+                </v-card-text>
+                <v-card-actions class="justify-center">
+                  <!-- <v-btn variant="tonal" flat size="small" color="error" @click="handleRejectReceive(val.payload)">拒绝</v-btn> -->
+                  <v-btn v-if="val.payload.content.type === 1" block  variant="tonal" flat size="small" color="success" @click="handlePreview(val.payload)">点击预览附件简历</v-btn>
+                  <v-btn v-if="val.payload.content.type === 2" block  variant="tonal" flat size="small" color="success" @click="handleSendResume(val.payload)">点击发送附件简历</v-btn>
+                </v-card-actions>
+              </v-card>
+            </div>
             <div v-else class="message-text" :class="{ active: val.from_uid === IM.uid}">
               {{ val.payload.content }}
             </div>
@@ -169,6 +186,9 @@
               </v-card-item>
             </v-card>
           </div>
+          <!-- <div class="d-flex justify-center" v-if="val.payload.type === 105">
+            <v-chip>已成功发送简历</v-chip>
+          </div> -->
         </div>
       </div>
     </div>
@@ -204,12 +224,14 @@ defineOptions({ name: 'message-chatting'})
 import { ref, nextTick, onMounted, inject } from 'vue'
 import { timesTampChange } from '@/utils/date'
 import { useIMStore } from '@/store/im'
+import { useI18n } from '@/hooks/web/useI18n'
 import { useRouter } from 'vue-router';
 import { getDict } from '@/hooks/web/useDictionaries'
-import { getDictValueWithLabel } from '@/utils/position'
+// import { getDictValueWithLabel } from '@/utils/position'
 
 import { useUserStore } from '@/store/user'
 const isEnterprise = inject('isEnterprise')
+const { t } = useI18n()
 
 const emits = defineEmits(['handleMore', 'handleSend', 'handleAgree', 'handleRefuse'])
 
@@ -333,6 +355,23 @@ const handleToCenter = () => {
   router.push({ path: '/recruit/personal/personalCenter', query: { showInterviewScheduleMore: true } })
 }
 
+// 简历预览
+const handlePreview = (val) => {
+  emits('handlePreview', val)
+}
+// 发送简历
+const handleSendResume = (val) => {
+  emits('handleSendResume', val)
+}
+// 拒绝接收简历
+// const handleRejectReceive = (val) => {
+//   emits('handleRejectReceive', val)
+// }
+// // 同意接收简历
+// const handleAccessReceive = (val) => {
+//   emits('handleAccessReceive', val)
+// }
+
 defineExpose({
   reset,
   changeLoading,

+ 119 - 21
src/views/recruit/components/message/index.vue

@@ -81,17 +81,27 @@
         @handleMore="handleGetMore"
         @handleAgree="handleAgree"
         @handleRefuse="handleRefuse"
+        @handlePreview="handlePreview"
+        @handleSendResume="handleSendResume"
       >
         <template #tools>
           <v-btn
             v-for="tool in tools"
             :key="tool.name"
             size="small"
-            :prepend-icon="tool.icon"
             class="mr-3"
             :color="tool.color"
             @click="tool.handle(tool)"
           >
+            <v-progress-circular
+              v-if="tool.loading"
+              :width="2"
+              :size="16"
+              color="white"
+              class="mr-2"
+              indeterminate
+            ></v-progress-circular>
+            <v-icon v-else class="mr-2">{{ tool.icon }}</v-icon>
             {{ tool.name }}
           </v-btn>
         </template>
@@ -102,6 +112,16 @@
   <CtDialog :visible="showInvite" :widthType="2" titleClass="text-h6" title="邀请面试" @close="showInvite = false" @submit="handleSubmit">
     <InvitePage v-if="showInvite" ref="inviteRef" :item-data="itemData" :position="positionList"></InvitePage>
   </CtDialog>
+
+  <CtDialog :visible="showResume" :widthType="2" titleClass="text-h6" title="发送简历" @close="showResume = false; selectResume = null " @submit="handleSubmitResume">
+    
+    <div style="position: relative; min-height: 200px">
+      <v-radio-group v-model="selectResume">
+        <v-radio v-for="val in resumeList" :key="val.id" :value="val.id" :label="val.title" color="primary"></v-radio>
+      </v-radio-group>
+    </div>
+    
+  </CtDialog>
 </template>
 
 <script setup>
@@ -124,6 +144,8 @@ import { dealDictArrayData } from '@/utils/position'
 import { saveInterviewInvite } from '@/api/recruit/enterprise/interview'
 import { useI18n } from '@/hooks/web/useI18n'
 import { userInterviewInviteReject, userInterviewInviteConsent } from '@/api/recruit/personal/personalCenter'
+import { getPersonResumeCv } from '@/api/recruit/personal/resume'
+import { previewFile } from '@/utils'
 import Confirm from '@/plugins/confirm'
 
 const { t } = useI18n()
@@ -151,6 +173,29 @@ const itemData = ref({})
 
 const inviteRef = ref()
 
+// 发送简历
+const showResume = ref(false)
+const resumeList = ref([])
+const selectResume = ref(null)
+
+// 求职者面试列表
+const interview = ref([])
+
+const showRightNoData = ref(false)
+
+const info = ref({})
+
+const enterpriseTools = ref([
+  { name: '求简历', icon: 'mdi-email', color:"primary", loading: false, handle: handleRequest },
+  { name: '面试邀约', icon: 'mdi-email', color:"primary", loading: false, handle: handleInvite }
+])
+
+const userTools = ref([
+  { name: '发送简历', icon: 'mdi-email', color:"primary", loading: false, handle: handleSendResume }
+])
+
+const tools = isEnterprise ? enterpriseTools.value : userTools.value
+
 if (!IM) {
   console.log('IM is disconnected')
 }
@@ -193,8 +238,7 @@ const {
   chatRef.value.scrollBottom()
 })
 
-// 求职者面试列表
-const interview = ref([])
+
 const getInterviewInviteList = async () => {
   if (!info.value.userId) return
   const data = await getInterviewInviteListByInviteUserId(info.value.userId)
@@ -221,24 +265,6 @@ watch(
 )
 
 
-const showRightNoData = ref(false)
-
-const info = ref({})
-
-const handleUpdate = (val) => {
-  send(val.value, channelItem.value)
-}
-
-
-const enterpriseTools = ref([
-  { name: '面试邀约', icon: 'mdi-email', color:"primary", loading: false, handle: handleInvite }
-])
-
-const userTools = ref([
-])
-
-const tools = isEnterprise ? enterpriseTools.value : userTools.value
-
 async function handleChange (items) {
   // console.log([...items])
   try {
@@ -251,6 +277,7 @@ async function handleChange (items) {
     const userId = userInfoVo.userInfoResp.userId
     const enterpriseId = userInfoVo.userInfoResp.enterpriseId || undefined
     const { channel, list, more } = await initChart(userId, enterpriseId)
+    // console.log('--------',list)
     channelItem.value = channel.value
     messageItems.value = list.value
     hasMore.value = more
@@ -267,6 +294,77 @@ async function handleChange (items) {
   }
 }
 
+// 普通消息
+const handleUpdate = (val) => {
+  send(val.value, channelItem.value)
+}
+
+// 获取简历
+async function handleSendResume (item) {
+  try {
+    item.loading = true
+    // showResume.value = true
+    // 获取简历列表
+    const result = await getPersonResumeCv()
+    if (result.length === 0) {
+      Snackbar.error(t('resume.resumeYetSubmit'))
+      return
+    }
+    resumeList.value = result
+    showResume.value = true
+  } finally {
+    item.loading = false
+  }
+}
+
+/**
+ * 发送简历
+ * text param
+ * {
+ *  remark: 备注
+ *  query: {} 自定义参数 access -1 未确定 0 拒绝 1 同意
+ *  type: 1 => 发送简历
+ *        2 => 索要简历
+ *        3 => 信息描述
+ * }
+ */
+function handleSubmitResume () {
+  if (!selectResume.value) {
+    Snackbar.error(t('resume.selectResumeToSubmit'))
+    return
+  }
+  const _info = resumeList.value.find((item) => item.id === selectResume.value)
+  const text = {
+    remark: '发送简历',
+    query: {
+      src: _info.url,
+      title: _info.title,
+      id: _info.id,
+    },
+    type: 1
+  }
+  send (JSON.stringify(text), channelItem.value, 105)
+  showResume.value = false
+}
+// 求简历
+function handleRequest () {
+  const text = {
+    remark: '求简历',
+    query: {
+      src: '',
+      title: '',
+      id: '',
+    },
+    type: 2
+  }
+  send (JSON.stringify(text), channelItem.value, 105)
+}
+
+// 简历预览
+const handlePreview = (val) => {
+  previewFile(val.content.query.src)
+}
+
 const handleGetMore = async () => {
   try {
     chatRef.value.changeLoading(true)