| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 | <template>	<view style="padding: 15px 15px 70px 15px;">		<baseInfo v-if="cvData?.person" :data="cvData?.person" />		<view v-if="skillExp?.length">			<view class="gap-line"></view>			<view class="title-line">职业技能</view>			<view class="tags">        <view          v-for="skill in skillExp"          :key="skill.title"          class="tag"        >          {{ skill.title }}        </view>      </view>		</view>		<view v-if="cvData?.person?.advantage">			<view class="gap-line"></view>			<view class="title-line">个人优势</view>			<advantage :data="cvData?.person?.advantage" />		</view>		<view v-if="cvData?.interestedList?.length">			<view class="gap-line"></view>			<view class="title-line">求职意向</view>			<jobIntention :data="dealJobData(cvData?.interestedList || [])" />		</view>		<view v-if="cvData?.eduList?.length">			<view class="gap-line"></view>			<view class="title-line">教育经历</view>			<eduExp :data="cvData?.eduList" />		</view>		<view v-if="cvData?.workList?.length">			<view class="gap-line"></view>			<view class="title-line">工作经历</view>			<workExp :data="cvData?.workList" />		</view>		<view v-if="cvData?.trainList?.length">			<view class="gap-line"></view>			<view class="title-line">培训经历</view>			<trainingExperience :data="cvData?.trainList" />		</view>		<view class="bottom-sticky">			<view class="bottom-content">        <!-- <button class="bottom-content-tool shareButtonCss" open-type="share">          <uni-icons type="redo-filled" size="24" color="#00B760" style="line-height: 24px;"/>          <span style="color:#00B760;font-weight:bold;line-height: 22px;">分享</span>        </button> -->				<button class="btnStyle bgButtons ss-m-l-15" type="primary" plain="true" @tap="handleSend">立即沟通</button>        <button class="buttons btnStyle" type="primary" @click="handleInvite">邀请面试</button>      </view>		</view>	</view></template><script setup>import { ref } from 'vue'import { onLoad } from '@dcloudio/uni-app'import { dealJobData } from '@/utils/dict'import { getDict } from '@/hooks/useDictionaries'import { getText } from '@/utils/getText'import { dealDictObjData } from '@/utils/position'import { getPersonCvDetail } from '@/api/enterprise.js'import baseInfo from './components/baseInfo.vue'import advantage from './components/advantage.vue'import jobIntention from './components/jobIntention.vue'import workExp from './components/workExp.vue'import eduExp from './components/eduExp.vue'import trainingExperience from './components/trainingExperience.vue'import { getJobAdvertisedList } from '@/api/new/position'import { defaultText, talkToUser } from '@/hooks/useIM'import { getAccessToken } from '@/utils/request'import { showAuthModal } from '@/hooks/useModal'const cvData = ref({})const skillExp = ref([])const getSkillExp = async (data) => {	if (!data || !data.length) {    return  }	const { data: _skillList} = await getDict('skillList', {}, 'skillList')  const skillList = _skillList?.data  if (!skillList || !skillList.length) {    return  }	const { data: _skillLevelArr } = await getDict('menduner_skill_level')  const skillLevelArr = _skillLevelArr?.data  if (!skillLevelArr || !skillLevelArr.length) {    return  }	skillExp.value = data.map(e => {    return {      ...e,      title: `${getText(e.skillId, skillList, 'nameCn', 'id')} / ${getText(e.level, skillLevelArr)}`    }  })}const getDetail = async (id) => {	uni.showLoading({ title: '加载中' })	try {		const { data } = await getPersonCvDetail(id)		if (!data) return		data.person = dealDictObjData({}, data.person)		cvData.value = data || {}		getSkillExp(data?.skillList || [])		uni.hideLoading()	} catch {		uni.hideLoading()	}}// 职位列表const jobNum = ref(0)const getJobList = async () => {  const { data } = await getJobAdvertisedList({ pageNo: 1, pageSize: 10, hasExpiredData: false, status: 0 })  jobNum.value = data?.total || 0}const btnType = ref('') // 1: 人才详情 2:简历投递onLoad(async (options) => {	const { id, type } = options	if (!id) {		uni.showToast({			title: '缺少人员id',			icon: 'none'		})		setTimeout(() => {			uni.navigateBack({ delta: 1 })		}, 1000)		return	}	btnType.value = type	await getDetail(id)	getJobList()})// 邀请面试const handleInvite = async () => {	if (!getAccessToken()) {    showAuthModal()    return  }  // 企业必须有招聘中的职位才能发起面试邀请  if (jobNum.value === 0) {		uni.showToast({			title: '请先发布招聘职位',			icon: 'none',			duration: 2000		})		return	}	uni.navigateTo({	  url: `/pagesB/InviteInterview/index?id=${cvData.value.person.userId}`	})}// 立即沟通const handleSend = async () => {	if (!getAccessToken()) {    showAuthModal()    return  }  // 企业必须有招聘中的职位才能发起沟通  if (jobNum.value === 0) {		uni.showToast({			title: '请先发布招聘职位',			icon: 'none',			duration: 2000		})		return	}  const userId = cvData.value.person.userId  if (!userId) return  const channel = await talkToUser({ userId, text: defaultText })	const query = {		id: userId,		name: cvData.value?.person?.name || cvData.value?.person?.phone,		channelID: channel.channelID,		channelType: channel.channelType,		avatar: cvData.value.person?.avatar,		sex: cvData.value.person?.sex,	}	const queryStr = Object.keys(query).reduce((r, v) => {		if (!query[v]) {			return r		}		return r += `${v}=${encodeURIComponent(query[v])}&`	}, '?')	uni.navigateTo({    url: `/pagesA/chart/index${queryStr.slice(0, -1)}`  })}</script><style scoped lang="scss">.gap-line {	border-bottom: 1px solid #eee;	margin: 30px 0;}.title-line {	font-size: 20px;	position: relative;	line-height: 20px;	margin-left: 12px;	margin-bottom: 20px;	padding-left: 10px;	&::before {		content: '';		position: absolute;		width: 6px;		height: 20px;		background: #00B760;		left: -10px;		border-radius: 6px;	}}.tags {  display: flex;  flex-wrap: wrap;  .tag {    margin: 0 10rpx 10rpx 0;    border: 2rpx solid #00B760;    color: #00B760;    white-space: nowrap;    padding: 4rpx 10rpx;    border-radius: 10rpx;    font-size: 24rpx;  }}.bottom-content {  display: flex;  justify-content: space-evenly;  align-items: center;  width: 100%;  margin: 20rpx 0;  .btnStyle {    flex: 1;    margin-right: 20rpx;		border-radius: 50rpx;  }  .bgButtons {    border: 2rpx solid #00B760;    color: #00B760;  }  .shareButtonCss {    font-size: 16px;    background: unset;    &::after{      border:none !important;    }  }  &-tool {    width: 160rpx;    display: flex;    justify-content: center;    flex-direction: column;    align-items: center;  }}</style>
 |