Quellcode durchsuchen

求职者同意、拒绝面试邀请

Xiao_123 vor 10 Monaten
Ursprung
Commit
b275d133d3

+ 47 - 6
src/views/recruit/personal/PersonalCenter/components/interview/index.vue

@@ -1,13 +1,23 @@
 <template>
 <template>
   <div>
   <div>
     <v-divider></v-divider>
     <v-divider></v-divider>
-      <v-tabs v-model="tabVal" align-tabs="start" color="primary" bg-color="#fff">
+      <v-tabs class="mb-3" v-model="query.status" align-tabs="start" color="primary" bg-color="#fff" @update:model-value="handleUpdate">
         <v-tab :value="0">待接受</v-tab>
         <v-tab :value="0">待接受</v-tab>
         <v-tab :value="1">待面试</v-tab>
         <v-tab :value="1">待面试</v-tab>
-        <v-tab :value="2">已完成</v-tab>
-        <v-tab :value="3">已取消</v-tab>
+        <v-tab :value="3">已完成</v-tab>
+        <v-tab :value="98">已拒绝</v-tab>
       </v-tabs>
       </v-tabs>
-      <Empty class="mt-3"></Empty>
+      <div v-if="items.length">
+        <ItemPage :items="items" :tab="query.status" @refresh="getData"></ItemPage>
+        <CtPagination
+          v-if="total > 0"
+          :total="total"
+          :page="query.pageNo"
+          :limit="query.pageSize"
+          @handleChange="handleChangePage"
+        ></CtPagination>
+      </div>
+      <Empty v-else class="mt-3"></Empty>
   </div>
   </div>
 </template>
 </template>
 
 
@@ -15,9 +25,40 @@
 // 面试
 // 面试
 defineOptions({ name: 'interview-index'})
 defineOptions({ name: 'interview-index'})
 import { ref } from 'vue'
 import { ref } from 'vue'
-// import { getUserInterviewInvitePage } from '@/api/recruit/personal/personalCenter'
+import { getUserInterviewInvitePage } from '@/api/recruit/personal/personalCenter'
+import { dealDictObjData } from '@/utils/position'
+import ItemPage from './item.vue'
+
+const query = ref({
+  pageNo: 1,
+  pageSize: 10,
+  status: 0
+})
+const total = ref(0)
+const items = ref([])
+
+const getData = async () => {
+  const { list, total: number } = await getUserInterviewInvitePage(query.value)
+  items.value = list.map(e => {
+    e.job = { ...e.job, ...dealDictObjData({}, e.job) }
+    e.enterprise = { ...e.enterprise, ...dealDictObjData({}, e.enterprise)}
+    e.active = false
+    return e
+  })
+  total.value = number
+}
+getData()
+
+const handleUpdate = () => {
+  query.value.pageNo = 1
+  getData()
+}
+
+const handleChangePage = (e) => {
+  query.value.pageNo = e
+  getData()
+}
 
 
-const tabVal = ref(0)
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">

+ 188 - 0
src/views/recruit/personal/PersonalCenter/components/interview/item.vue

@@ -0,0 +1,188 @@
+<template>
+  <div class="position-item mb-3 job-closed" v-for="(val, i) in props.items" :key="i" @mouseenter="val.active = true" @mouseleave="val.active = false">
+      <div class="info-header">
+        <div v-if="val.active && val.status === '0'" class="header-btn">
+          <v-btn color="primary" size="small" @click="handleAgree(val)">同意</v-btn>
+          <v-btn class="ml-3" color="error" size="small" @click="handleRefuse(val)">拒绝</v-btn>
+        </div>
+        <div class="img-box">
+          <v-avatar :image="val.contact.avatar || 'https://minio.citupro.com/dev/menduner/7.png'" size="x-small"></v-avatar>
+          <span class="name">
+            <span class="mx-3">{{ val.contact.name }}</span>
+            <span class="gray">{{ val.contact.postNameCn }}</span>
+            <span v-if="val.invitePhone" class="septal-line"></span>
+            <span class="gray">{{ val.invitePhone }}</span>
+          </span>
+        </div>
+      </div>
+      <div class="info-content">
+        <div class="job-info">
+          <div class="job-name ellipsis" style="max-width: 410px;">
+            <span class="mr-3">{{ val.job.name }}</span>
+            <span>{{ val.job.payFrom }}-{{ val.job.payTo }}/{{ val.job.payName }}</span>
+          </div>
+          <div class="job-other d-flex align-center">
+            <div style="width: 30px;height: 30px;">
+              <v-img width="30" height="30" :src="val.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/7.png'"></v-img>
+            </div>
+            <div class="ellipsis" style="max-width: 400px;">
+              <span class="mx-2 enterprise-name" @click="handleToEnterprise(val)">{{ val.enterprise.name }}</span>
+            [
+              <span>{{ val.enterprise.industryName }}</span>
+              <span>&nbsp;·&nbsp;{{ val.enterprise.financingName }}</span>
+              <span>&nbsp;·&nbsp;{{ val.enterprise.scaleName }}</span>
+            ]
+            </div>
+          </div>
+        </div>
+        <div class="font-size-14 color-666" style="width: 322px;">
+          <div>面试时间:{{ timesTampChange(val.time).slice(0, 16) }}</div>
+          <div class="mt-3 ellipsis" style="max-width: 322px;">面试地点:{{ val.address }}</div>
+        </div>
+      </div>
+  </div>
+
+  <CtDialog :visible="show" title="同意面试邀请" :footer="true" widthType="2" @close="handleClose" @submit="handleSubmit">
+    <TextInput v-model="query.phone" :item="textItem"></TextInput>
+  </CtDialog>
+</template>
+
+<script setup>
+defineOptions({ name: 'interview-item'})
+import { ref } from 'vue'
+import { useI18n } from '@/hooks/web/useI18n'
+import { timesTampChange } from '@/utils/date'
+import { userInterviewInviteReject, userInterviewInviteConsent } from '@/api/recruit/personal/personalCenter'
+import Snackbar from '@/plugins/snackbar'
+import Confirm from '@/plugins/confirm'
+
+const { t } = useI18n()
+const emits = defineEmits(['refresh'])
+const props = defineProps({
+  items: {
+    type: Array,
+    default: () => []
+  },
+  tab: {
+    type: Number,
+    default: 0
+  }
+})
+const show = ref(false)
+const query = ref({
+  id: null,
+  phone: null
+})
+const textItem = ref({
+  type: 'text',
+  clearable: true,
+  label: '联系号码 *'
+})
+
+// 企业详情
+const handleToEnterprise = (item) => {
+  const id = item.enterprise.id
+  if (!id) return
+  window.open(`/recruit/personal/company/details/${id}?key=briefIntroduction`)
+}
+
+// 同意
+const handleAgree = (val) => {
+  if (!val.id) return
+  query.value = {
+    id: val.id,
+    phone: val.phone
+  }
+  show.value = true
+}
+
+const handleClose = () => {
+  show.value = false
+  query.value = {
+    id: null,
+    phone: null
+  }
+}
+
+const handleSubmit = async () => {
+  if (!query.value.phone) return Snackbar.warning('请填写您的联系号码')
+  await userInterviewInviteConsent(query.value)
+  Snackbar.success(t('common.operationSuccessful'))
+  handleClose()
+  emits('refresh')
+}
+
+// 拒绝
+const handleRefuse = (val) => {
+  if (!val.id) return
+  Confirm(t('common.confirmTitle'), '您是否确定要拒绝此面试邀请?').then(async () => {
+    await userInterviewInviteReject(val.id)
+    Snackbar.success(t('common.operationSuccessful'))
+    emits('refresh')
+  })
+}
+</script>
+
+<style scoped lang="scss">
+.position-item {
+  height: 144px;
+  background-color: #fff;
+  border-radius: 12px;
+  &:hover {
+    box-shadow: 0 16px 40px 0 rgba(153, 153, 153, .3);
+  }
+  .info-header {
+    height: 48px;
+    background: linear-gradient(90deg,#f5fcfc,#fcfbfa);
+    border-radius: 12px;
+    .img-box {
+      padding: 12px 24px;
+      .name {
+        color: var(--color-222);
+        font-weight: 400;
+        font-size: 13px;
+        .gray {
+          color: var(--color-666);
+        }
+      }
+    }
+    .header-btn {
+      padding: 10px 10px 0 0;
+      float: right;
+      .v-btn {
+        z-index: 1;
+      }
+    }
+  }
+  .info-content {
+    display: flex;
+    padding: 16px 24px;
+    justify-content: space-between;
+    .job-info {
+      width: 430px;
+      max-width: 430px;
+      font-weight: 500;
+      font-size: 16px;
+      margin-right: 12px;
+      .job-name {
+        height: 22px;
+        line-height: 22px;
+        color: var(--color-222);
+        margin-bottom: 12px;
+      }
+      .job-other {
+        color: var(--color-666);
+        height: 22px;
+        line-height: 22px;
+        font-size: 14px;
+        .enterprise-name {
+          cursor: pointer;
+          &:hover {
+            color: var(--v-primary-base)
+          }
+        }
+      }
+    }
+  }
+}
+</style>