Files
ks-app-employment-service/packageA/pages/exhibitors/exhibitors.vue
2025-11-05 17:21:01 +08:00

769 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<AppLayout title="" :use-scroll-view="false">
<template #headerleft>
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
</template>
<view class="content">
<view class="content-top">
<view class="companyinfo-left">
<image src="@/static/icon/companyIcon.png" mode=""></image>
</view>
<view class="companyinfo-right">
<view class="row1 line_2">{{ fairInfo?.jobFairTitle }}</view>
<view class="row2">
<text>{{ fairInfo?.jobFairAddress }}</text>
<convert-distance :alat="fairInfo?.latitude" :along="fairInfo?.longitude" :blat="latitudeVal"
:blong="longitudeVal"></convert-distance>
</view>
</view>
</view>
<view class="locations">
<image class="location-img" src="/static/icon/mapLine.png"></image>
<view class="location-info">
<view class="info">
<text class="info-title">{{ fairInfo?.jobFairAddress }}</text>
<text class="info-text">位置</text>
</view>
</view>
</view>
<view class="conetent-info" :class="{ expanded: isExpanded }">
<view class="info-title">内容描述</view>
<view class="info-desirption">{{ fairInfo?.jobFairIntroduction }}</view>
<!-- <view class="info-title title2">公司地址</view>
<view class="locationCompany"></view> -->
<view class="company-times">
<view class="info-title">内容描述</view>
<view class="card-times">
<view class="time-left">
<view class="left-date">{{ parseDateTime(fairInfo.jobFairStartTime).time }}</view>
<view class="left-dateDay">{{ parseDateTime(fairInfo.jobFairStartTime).date }}</view>
</view>
<view class="line"></view>
<view class="time-center">
<view class="center-date">
{{ getTimeStatus(fairInfo.jobFairStartTime, fairInfo.jobFairEndTime).statusText }}
</view>
<view class="center-dateDay">
{{ getHoursBetween(fairInfo.jobFairStartTime, fairInfo.jobFairEndTime) }}小时
</view>
</view>
<view class="line"></view>
<view class="time-right">
<view class="left-date">{{ parseDateTime(fairInfo.jobFairEndTime).time }}</view>
<view class="left-dateDay">{{ parseDateTime(fairInfo.jobFairEndTime).date }}</view>
</view>
</view>
</view>
</view>
<view class="expand" @click="expand">
<text>{{ isExpanded ? '收起' : '展开' }}</text>
<image class="expand-img" :class="{ 'expand-img-active': !isExpanded }" src="@/static/icon/downs.png">
</image>
</view>
<scroll-view scroll-y class="Detailscroll-view">
<view class="views">
<view class="Detail-title">
<text class="title">参会单位{{ companyList.length }}</text>
</view>
<view v-for="job in companyList" :key="job.id">
<view class="cards" :style="getItemBackgroundStyle('bj.png')"
@click="navTo('/packageA/pages/UnitDetails/UnitDetails?job='+JSON.stringify(job))">
<view class="card-company">
<view class="company line_1">
<image :src="`${baseUrl}/jobfair/mc.png`" mode=""></image>
{{ job.companyName }}
</view>
<view class="ris">
<text class="fs_14">
在招职位
{{ job.jobInfoList.length || '-' }}
</text>
</view>
</view>
<view class="card-bottom">
<view class="fl_box fs_14">
{{ job.scale }}
</view>
</view>
<view class="card-tags">
<view class="tag" v-if="job.industry">
<image :src="`${baseUrl}/jobfair/hy.png`" mode=""></image>
{{ job.industry }}
</view>
<view class="tag">
<image :src="`${baseUrl}/jobfair/lx.png`" mode=""></image>
{{ job.companyType }}
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
<template #footer>
<view class="footer" v-if="hasnext">
<view class="btn-wq button-click" :class="{ 'btn-desbel': fairInfo.isSignUp==1 }"
@click="applyExhibitors">
{{ fairInfo.isSignUp==1 ? '已报名' : '报名招聘会' }}
</view>
</view>
</template>
<uni-popup ref="CompanySignPopup" background-color="#fff" :mask-click="false">
<view class="popup-content">
<signDialog v-if="signDialogisshow" :signType="signType" :signRole="signRole"
:jobFairId="fairInfo.jobFairId" @closePopup="closePopup"></signDialog>
</view>
</uni-popup>
</AppLayout>
</template>
<script setup>
import signDialog from '@/components/jobfair/signDialog.vue';
import config from "@/config.js"
import {
reactive,
inject,
watch,
ref,
onMounted,
computed
} from 'vue';
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import useLocationStore from '@/stores/useLocationStore';
const {
$api,
navTo,
vacanciesTo,
navBack
} = inject('globalFunction');
import {
storeToRefs
} from 'pinia';
const {
longitudeVal,
latitudeVal
} = storeToRefs(useLocationStore());
const isExpanded = ref(false);
const fairInfo = ref({});
const companyList = ref([]);
const hasnext = ref(true);
const userInfo = ref({});
const signDialogisshow = ref(false)
// 弹窗
const signType = ref(1);
// person个人 ent企业
const signRole = ref('ent');
const CompanySignPopup = ref(null)
const jobFairId = ref(null)
const baseUrl = config.imgBaseUrl
const getItemBackgroundStyle = (imageName) => ({
backgroundImage: `url(${baseUrl}/jobfair/${imageName})`,
backgroundSize: '100% 100%', // 覆盖整个容器
backgroundPosition: 'center', // 居中
backgroundRepeat: 'no-repeat'
});
onLoad((options) => {
jobFairId.value=options.jobFairId
const raw = uni.getStorageSync("Padmin-Token");
const token = typeof raw === "string" ? raw.trim() : "";
const headers = token ? {
Authorization: raw.startsWith("Bearer ") ? raw : `Bearer ${token}`
} : {};
$api.myRequest("/dashboard/auth/heart", {}, "POST", 10100, headers).then((resData) => {
if (resData.code == 200) {
$api.myRequest("/system/user/login/user/info", {}, "GET", 10100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((userinfo) => {
userInfo.value = userinfo
getCompanyInfo(userInfo.value.info.userId, options.jobFairId);
});
} else {
getCompanyInfo('', options.jobFairId);
}
});
});
function closePopup() {
CompanySignPopup.value.close()
getCompanyInfo(userInfo.value.info.userId, jobFairId.value)
}
function getCompanyInfo(userId, id) {
let data={}
if (userInfo.value&&userInfo.value.userType == 'ent') {
data={
jobFairId: id,
enterpriseId: userId,
code:userInfo.value.info.entCreditCode
}
}else if(userInfo.value&&userInfo.value.userType == 'ent'){
data={
jobFairId: id,
personId: userId,
idCard:userInfo.value.info.personCardNo
}
}else{
data={
jobFairId: id,
personId: userId
}
}
$api.myRequest('/jobfair/public/jobfair/detail', data).then((resData) => {
fairInfo.value = resData.data;
});
$api.myRequest('/jobfair/public/jobfair/enterprises-with-jobs-by-job-fair-id', {
jobFairId: id
}).then((resData) => {
companyList.value = resData.data;
});
};
const hasAppointment = () => {
const isTimePassed = (timeStr) => {
const targetTime = new Date(timeStr.replace(/-/g, '/')).getTime(); // 兼容格式
const now = Date.now();
return now < targetTime;
};
hasnext.value = isTimePassed(fairInfo.value.startTime);
};
function openMap(lat, lng, name = '位置') {
const isConfirmed = window.confirm('是否打开地图查看位置?');
if (!isConfirmed) return;
// 使用高德地图或百度地图的 H5 链接打开
const url = `https://uri.amap.com/marker?position=${lng},${lat}&name=${encodeURIComponent(name)}`;
window.location.href = url;
}
function expand() {
isExpanded.value = !isExpanded.value;
}
// 报名招聘会
function applyExhibitors() {
if (fairInfo.value.isSignUp == 1) {
$api.msg('请勿重复报名');
return
}
const raw = uni.getStorageSync("Padmin-Token");
const token = typeof raw === "string" ? raw.trim() : "";
const headers = token ? {
Authorization: raw.startsWith("Bearer ") ? raw : `Bearer ${token}`
} : {};
$api.myRequest("/dashboard/auth/heart", {}, "POST", 10100, headers).then((resData) => {
if (resData.code == 200) {
if (userInfo.value.userType == 'ent') {
// 企业
signType.value = fairInfo.value.jobFairType;
signRole.value = userInfo.userType;
signDialogisshow.value = true
CompanySignPopup.value.open()
}else{
$api.myRequest("/jobfair/public/job-fair-sign-up-person/sign-up", {
personId: userInfo.value.info.userId,
jobFairId: jobFairId.value,
idCard:userInfo.value.info.personCardNo
}, "POST", 9100, { "Content-Type": "application/json",...headers }).then((res) => {
if (res.code === 200) {
uni.showToast({
title: '报名成功',
icon: 'success'
});
getCompanyInfo(userInfo.value.info.userId, jobFairId.value)
} else {
uni.showToast({
title: res.msg || '报名失败',
icon: 'none'
});
}
})
}
} else {
$api.msg('请先登录');
setTimeout(() => {
uni.redirectTo({
url: '/packageB/login'
})
}, 1000)
}
});
}
function parseDateTime(datetimeStr) {
if (!datetimeStr) return {
time: '',
date: ''
};
const dateObj = new Date(datetimeStr);
if (isNaN(dateObj.getTime())) return {
time: '',
date: ''
}; // 无效时间
const year = dateObj.getFullYear();
const month = String(dateObj.getMonth() + 1).padStart(2, '0');
const day = String(dateObj.getDate()).padStart(2, '0');
const hours = String(dateObj.getHours()).padStart(2, '0');
const minutes = String(dateObj.getMinutes()).padStart(2, '0');
return {
time: `${hours}:${minutes}`,
date: `${year}${month}${day}`,
};
}
function getTimeStatus(startTimeStr, endTimeStr) {
const now = new Date();
const startTime = new Date(startTimeStr);
const endTime = new Date(endTimeStr);
// 判断状态0 开始中1 过期2 待开始
let status = 0;
let statusText = '开始中';
let color = '#13C57C'; // 进行中 - 绿色
if (now < startTime) {
status = 2; // 待开始
statusText = '待开始';
color = '#015EEA'; // 未开始 - 蓝色
} else if (now > endTime) {
status = 1; // 已过期
statusText = '已过期';
color = '#999999'; // 已过期 - 灰色
} else {
status = 0; // 进行中
statusText = '进行中';
color = '#13C57C'; // 进行中 - 绿色
}
return {
status, // 0: 进行中1: 已过期2: 待开始
statusText,
color
};
}
function getHoursBetween(startTimeStr, endTimeStr) {
const start = new Date(startTimeStr);
const end = new Date(endTimeStr);
const diffMs = end - start;
const diffHours = diffMs / (1000 * 60 * 60);
return +diffHours.toFixed(2); // 保留 2 位小数
}
</script>
<style lang="stylus" scoped>
.popup-content {
width: 90vw;
height: 80vh;
position: relative;
}
.btnback {
width: 64rpx;
height: 64rpx;
}
.btn {
display: flex;
justify-content: space-between;
align-items: center;
width: 52rpx;
height: 52rpx;
}
image {
height: 100%;
width: 100%;
}
.content {
height: 100%;
display: flex;
flex-direction: column;
.content-top {
padding: 28rpx;
padding-top: 50rpx;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
.companyinfo-left {
width: 96rpx;
height: 96rpx;
margin-right: 24rpx;
}
.companyinfo-right {
flex: 1;
.row1 {
font-weight: 500;
font-size: 32rpx;
color: #333333;
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
}
.row2 {
font-weight: 400;
font-size: 28rpx;
color: #6C7282;
line-height: 45rpx;
display: flex;
justify-content: space-between;
}
}
}
.locations {
padding: 0 28rpx;
height: 86rpx;
position: relative;
margin-bottom: 36rpx;
.location-img {
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 2rpx solid #EFEFEF;
}
.location-info {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.info {
padding: 0 60rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
white-space: nowrap;
.info-title {
font-weight: 600;
font-size: 28rpx;
color: #333333;
}
.info-text {
font-weight: 400;
font-size: 28rpx;
color: #9B9B9B;
position: relative;
padding-right: 20rpx
}
.info-text::before {
position: absolute;
right: 0;
top: 50%;
content: '';
width: 4rpx;
height: 16rpx;
border-radius: 2rpx;
background: #9B9B9B;
transform: translate(0, -75%) rotate(-45deg)
}
.info-text::after {
position: absolute;
right: 0;
top: 50%;
content: '';
width: 4rpx;
height: 16rpx;
border-radius: 2rpx;
background: #9B9B9B;
transform: translate(0, -25%) rotate(45deg)
}
}
}
}
.conetent-info {
padding: 0 28rpx;
overflow: hidden;
max-height: 0rpx;
transition: max-height 0.3s ease;
.info-title {
font-weight: 600;
font-size: 28rpx;
color: #000000;
}
.info-desirption {
margin-top: 12rpx;
font-weight: 400;
font-size: 28rpx;
color: #495265;
text-align: justify;
}
.title2 {
margin-top: 48rpx
}
}
.company-times {
padding-top: 40rpx;
.info-title {
font-weight: 600;
font-size: 28rpx;
color: #000000;
}
}
.expanded {
max-height: 1000rpx; // 足够显示完整内容
}
.expand {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
justify-content: center;
margin-bottom: 46rpx;
font-weight: 400;
font-size: 28rpx;
color: #256BFA;
.expand-img {
width: 40rpx;
height: 40rpx;
}
.expand-img-active {
transform: rotate(180deg)
}
}
}
.Detailscroll-view {
flex: 1;
overflow: hidden;
background: #F4F4F4;
.views {
padding: 28rpx;
.Detail-title {
font-weight: 600;
font-size: 32rpx;
color: #000000;
position: relative;
display: flex;
justify-content: space-between;
.title {
position: relative;
z-index: 2;
}
}
.Detail-title::before {
position: absolute;
content: '';
left: -14rpx;
bottom: 0;
height: 16rpx;
width: 108rpx;
background: linear-gradient(to right, #CBDEFF, #FFFFFF);
border-radius: 8rpx;
z-index: 1;
}
.cards {
padding: 32rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.04);
border-radius: 20rpx 20rpx 20rpx 20rpx;
margin-top: 22rpx;
.card-company {
display: flex;
justify-content: space-between;
align-items: flex-start;
.company {
font-weight: 600;
font-size: 32rpx;
color: #333333;
display: flex;
align-items: center;
image {
width: 30rpx;
height: 30rpx;
margin-right: 10rpx;
}
}
.salary {
font-weight: 500;
font-size: 28rpx;
white-space: nowrap;
line-height: 48rpx;
}
.ris {
background: #53ACFF;
color: #fff;
padding: 7rpx 20rpx;
border-radius: 8rpx;
}
}
.card-companyName {
font-weight: 400;
font-size: 28rpx;
color: #6C7282;
}
.card-tags {
display: flex;
flex-wrap: wrap;
.tag {
width: fit-content;
height: 30rpx;
background: #E0F0FF;
border-radius: 4rpx;
padding: 6rpx 26rpx;
line-height: 30rpx;
font-weight: 400;
font-size: 24rpx;
color: #595959;
text-align: center;
margin-top: 14rpx;
white-space: nowrap;
display: flex;
align-items: center;
margin-right: 20rpx;
image {
width: 22rpx;
height: 22rpx;
margin-right: 8rpx;
}
}
}
.card-bottom {
margin-top: 15rpx;
display: flex;
justify-content: space-between;
font-size: 28rpx;
color: #6C7282;
}
}
}
}
.card-times {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 30rpx 10rpx 30rpx;
.time-left,
.time-right {
text-align: center;
.left-date {
font-weight: 500;
font-size: 48rpx;
color: #333333;
}
.left-dateDay {
font-weight: 400;
font-size: 24rpx;
color: #333333;
margin-top: 12rpx;
}
}
.line {
width: 40rpx;
height: 0rpx;
border: 2rpx solid #D4D4D4;
margin-top: 64rpx;
}
.time-center {
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.center-date {
font-weight: 400;
font-size: 28rpx;
color: #FF881A;
}
.center-dateDay {
font-weight: 400;
font-size: 24rpx;
color: #333333;
margin-top: 6rpx;
line-height: 48rpx;
width: 104rpx;
height: 48rpx;
background: #F9F9F9;
border-radius: 8rpx 8rpx 8rpx 8rpx;
}
}
}
.footer {
background: #FFFFFF;
box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11, 44, 112, 0.12);
border-radius: 0rpx 0rpx 0rpx 0rpx;
padding: 40rpx 28rpx 20rpx 28rpx;
.btn-wq {
height: 90rpx;
background: #256BFA;
border-radius: 12rpx 12rpx 12rpx 12rpx;
font-weight: 500;
font-size: 32rpx;
color: #FFFFFF;
text-align: center;
line-height: 90rpx
}
.btn-desbel {
background: #6697FB;
box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11, 44, 112, 0.12);
}
}
</style>