123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- <template>
- <div>
- <div v-if="showLogin" class="login-content" :style="{'background-image': 'url(' + webContent.loginBgUrl + ')'}">
- <div class="login-content-box pa-10">
- <div class="login-content-box-title text-center mt-4">请先登录您的企业账号</div>
- <passwordFrom class="mt-10" ref="passRef" placeholder="请输入企业邮箱" :validEmail="true"></passwordFrom>
- <v-btn :loading="loading" color="primary" class="white--text mt-5" min-width="340" @click="handleLogin">登录</v-btn>
- </div>
- </div>
- <div v-else class="content py-3" @scroll="handleScroll">
- <v-card class="py-3 px-5" :style="{'width': isMobile ? '100%' : '750px'}" style="min-height: calc(100vh - 24px); box-sizing: border-box; margin: 0 auto;">
- <div class="d-flex align-center" style="width: 340px; margin: auto;">
- <TextInput v-model="textItem.value" :item="textItem" @click="openDrawer" @appendInnerClick="openDrawer"></TextInput>
- </div>
- <!-- 已发布职位 -->
- <div class="text-end mb-1">
- <v-menu transition="slide-y-transition">
- <template v-slot:activator="{ props, isActive }">
- <v-btn color="primary" v-bind="props" variant="tonal" :append-icon="isActive ? 'mdi mdi-menu-up' : 'mdi mdi-menu-down'">
- {{ query?.jobId ? select : '选择已发布职位推荐' }}
- </v-btn>
- </template>
- <v-list>
- <v-list-item v-for="k in selectItems.items" :key="k.value" color="primary" :active="k.value === query?.jobId">
- <v-list-item-title @click="handleActive(k)">{{ k.label }}</v-list-item-title>
- </v-list-item>
- </v-list>
- </v-menu>
- <v-icon v-if="query?.jobId" color="primary" size="30" class="ml-3" @click="handleClearJob">mdi-close-circle-outline</v-icon>
- </div>
- <v-divider></v-divider>
- <div v-if="items.length">
- <div v-for="(val, index) in items" :key="val.id" @click="handleDetail(val)">
- <div class="py-3 d-flex align-center">
- <v-avatar size="large">
- <v-img :src="getUserAvatar(val.avatar, val.sex)" width="50" height="50"></v-img>
- </v-avatar>
- <div class="ml-3 d-flex flex-column">
- <p class="font-size-20">{{ val.name }}</p>
- <p class="color-999 font-size-16">
- {{ val.jobStatusName }}
- <span v-if="val.jobStatusName && val.expName" class="septal-line"></span>
- {{ val.expName }}
- <span v-if="val.eduName" class="septal-line"></span>
- {{ val.eduName }}
- </p>
- </div>
- </div>
- <div class="bg-box" v-if="index !== items.length - 1"></div>
- </div>
- </div>
- <Empty v-else :elevation="false" message="暂无数据"></Empty>
- </v-card>
- </div>
- <Loading :visible="loading"></Loading>
- <v-navigation-drawer v-model="screen" location="top" temporary class="px-5" style="border-radius: 0 0 10px 10px;">
- <FilterPage ref="filterRef" @close="screen = false" @search="handleSearch"></FilterPage>
- </v-navigation-drawer>
- </div>
- </template>
- <script setup>
- defineOptions({ name: 'talentRecommendation'})
- import { ref, onMounted } from 'vue'
- import passwordFrom from '@/views/login/components/passwordPage.vue'
- import Snackbar from '@/plugins/snackbar'
- import { useUserStore } from '@/store/user'
- import { passwordLogin } from '@/api/common'
- import { getJobAdvertised, getPersonSearchPage, getPersonRecommendPage } from '@/api/enterprise'
- import { dealDictArrayData } from '@/utils/position'
- import { getUserAvatar } from '@/utils/avatar'
- import { useRouter } from 'vue-router'
- import FilterPage from './components/filter.vue'
- import { webContentStore } from '@/store/webContent'
- const webContent = webContentStore()
- const router = useRouter()
- const loading = ref(false)
- const passRef = ref(null)
- const items = ref([])
- const total = ref(0)
- const query = ref({
- pageNo: 1,
- pageSize: 20
- })
- const select = ref('')
- const screen1 = ref(false)
- const token = ref(localStorage.getItem('ENT_ACCESS_TOKEN'))
- const showLogin = ref(token.value ? false : true)
- const selectItems = ref({
- label: '已发布职位',
- placeholder: '请选择要进行推荐的职位',
- clearable: true,
- width: 600,
- items: []
- })
- const textItem = ref({
- type: 'text',
- width: 600,
- value: '',
- label: '输入关键词搜索',
- clearable: false,
- readonly: true,
- appendInnerIcon: 'mdi-magnify'
- })
- // 已发布职位列表
- const getJobList = async () => {
- const data = await getJobAdvertised({ status: 0 })
- if (data.length) {
- const list = dealDictArrayData([], data)
- selectItems.value.items = list.map(e => {
- return { label: `${e.name}${e.areaName ? '_' + e.areaName : ''} ${e.payFrom ? e.payFrom + '-' : ''}${e.payTo}${e.payName ? '/' + e.payName : ''}`, value: e.id }
- })
- }
- }
- const handleActive = (k) => {
- select.value = k.label
- query.value.jobId = k.value
- query.value.pageNo = 1
- screen1.value = false
- getData(true)
- }
- const handleClearJob = () => {
- select.value = ''
- delete query.value.jobId
- query.value.pageNo = 1
- items.value = []
- total.value = 0
- screen1.value = false
- }
- // 组件挂载后添加事件监听器
- const isMobile = ref(false)
- onMounted(async () => {
- await webContent.getSystemWebContent()
- if (!token.value) {
- Snackbar.warning('请先登录')
- showLogin.value = true
- }
- else getJobList()
- const userAgent = navigator.userAgent
- isMobile.value = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(userAgent)
- })
- // 列表
- const getData = async (isEmpty) => {
- // isEmpty:是否清空列表
- loading.value = true
- try {
- const res = query.value?.jobId ? await getPersonRecommendPage(query.value) : await getPersonSearchPage(query.value)
- const list = res.list || []
- items.value = list.length ? !isEmpty ? [...items.value, ...dealDictArrayData([], list)] : dealDictArrayData([], list) : []
- total.value = res.total
- } catch (err) {
- loading.value = false
- if (err.code === 401) {
- items.value = []
- total.value = 0
- token.value = null
- query.value = {
- pageNo: 1,
- pageSize: 20
- }
- Snackbar.warning('请先登录')
- showLogin.value = true
- }
- } finally {
- loading.value = false
- }
- }
- // 底部加载
- const handleScroll = (e) => {
- if (!token.value) {
- showLogin.value = true
- Snackbar.warning('请先登录')
- return
- }
- if (e.srcElement.scrollTop + e.srcElement.clientHeight > e.srcElement.scrollHeight - 10) {
- if (items.value.length < total.value) {
- query.value.pageNo++
- getData()
- }
- }
- }
- // 登录
- const handleLogin = async () => {
- const { valid } = await passRef.value.passwordForm.validate()
- if (!valid) return
- loading.value = true
- try {
- const data = await passwordLogin({ ...passRef.value.loginData, account: passRef.value.loginData.phone })
- await useUserStore().changeRole({ ...data, type: 'emailLogin', noJump: true })
- await getJobList()
- if (data?.accessToken) {
- token.value = data?.accessToken
- showLogin.value = false
- }
- } catch (err) {
- Snackbar.warning(err)
- } finally {
- loading.value = false
- }
- }
- // 人才详情
- const handleDetail = ({ userId, id }) => {
- if (!token.value) {
- showLogin.value = true
- Snackbar.warning('请先登录')
- return
- }
- if (!userId || !id) return
- router.push(`/recruit/enterprise/talentRecommendation/details/${userId}?id=${id}`)
- }
- // 筛选
- const filterRef = ref()
- const screen = ref(false)
- const openDrawer = () => {
- if (!token.value) {
- showLogin.value = true
- Snackbar.warning('请先登录')
- return
- }
- screen.value = true
- }
- const handleSearch = (val) => {
- if (!token.value) {
- showLogin.value = true
- Snackbar.warning('请先登录')
- return
- }
- screen.value = false
- textItem.value.value = val.content
- query.value.pageNo = 1
- query.value = Object.assign(query.value, val)
- getData(true)
- }
- </script>
- <style scoped lang="scss">
- .content {
- background-color: #f2f4f7;
- height: 100vh;
- overflow-y: auto;
- }
- .login-content {
- position: relative;
- width: 100%;
- height: 100vh;
- background-size: cover;
- &-box {
- position: absolute;
- top: 50%;
- left: 50%;
- translate: -50% -50%;
- width: 420px;
- height: 380px;
- background-color: #fff;
- border-radius: 10px;
- &-title {
- color: #4c4c4c;
- font-size: 24px;
- }
- }
- }
- .bg-box {
- height: 10px;
- background-color: #f2f4f7;
- }
- .active {
- color: var(--v-primary-base);
- border: 2px solid var(--v-primary-base);
- }
- </style>
|