Files
ks-app-employment-service/pages/careerfair/careerfair.vue

804 lines
19 KiB
Vue
Raw Permalink 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>
<view class="app-custom-root">
<view class="app-container">
<!-- 顶部头部区域 -->
<view class="container-header">
<view class="header-top">
<view class="header-btnLf button-click" @click="seemsg(1)" :class="{ active: state.current === 1 }">
线上招聘会
</view>
<view class="header-btnLf button-click" @click="seemsg(2)" :class="{ active: state.current === 2 }">
线下招聘会
</view>
<view class="header-btnLf button-click" @click="seemsg(3)" :class="{ active: state.current === 3 }">
我参与的
</view>
<!-- <view class="header-btnLf button-click" @click="navTo('/packageB/login')">
登录
</view> -->
</view>
<view class="header-input btn-feel">
<uni-icons class="iconsearch" color="#666666" type="search" size="18"
@click="getFair('refresh')"></uni-icons>
<input class="input" placeholder="招聘会" placeholder-class="inputplace"
v-model="pageState.jobFairTitle" />
</view>
</view>
<!-- 主体内容区域 -->
<view class="container-main">
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower">
<view class="cards" v-if="fairList.length">
<view class="card press-button" v-for="(item, index) in fairList" :key="index"
@click="goDetail(item.jobFairId)">
<view class="card-title">
{{ item.jobFairTitle }}
<view class="center-date"
:style="{ color: getTimeStatus(item.jobFairStartTime, item.jobFairEndTime).color,borderColor: getTimeStatus(item.jobFairStartTime, item.jobFairEndTime).color }">
{{ getTimeStatus(item.jobFairStartTime, item.jobFairEndTime).statusText }}
</view>
</view>
<view class="card-row">
<text class="">{{ item.jobFairAddress }}</text>
</view>
<view class="card-times">
<view class="time-left">
<view class="left-date">
{{parseDateTime(item.jobFairStartTime).time}}
</view>
<view class="left-dateDay">
{{parseDateTime(item.jobFairStartTime).date}}
</view>
</view>
<view class="line"></view>
<view class="time-center">
<view class="center-dateDay">
{{getHoursBetween(item.jobFairStartTime,item.jobFairEndTime)}}小时
</view>
</view>
<view class="line"></view>
<view class="time-right">
<view class="left-date">
{{parseDateTime(item.jobFairEndTime).time}}
</view>
<view class="left-dateDay">
{{parseDateTime(item.jobFairEndTime).date}}
</view>
</view>
</view>
<view class="recommend-card-line"></view>
<view class="card-footer">内容简介{{ item.jobFairIntroduction || "暂无" }}</view>
</view>
</view>
<empty v-else pdTop="200"></empty>
</scroll-view>
</view>
<!-- 自定义tabbar -->
<CustomTabBar :currentPage="1" />
<!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess"></WxAuthLogin>
</view>
</view>
</template>
<script setup>
import {
reactive,
inject,
watch,
ref,
onMounted,
onUnmounted
} from "vue";
import {
onLoad,
onShow
} from "@dcloudio/uni-app";
import useLocationStore from "@/stores/useLocationStore";
import {
storeToRefs
} from "pinia";
import {
tabbarManager
} from "@/utils/tabbarManager";
import WxAuthLogin from "@/components/WxAuthLogin/WxAuthLogin.vue";
import config from "@/config.js";
const {
longitudeVal,
latitudeVal
} = storeToRefs(useLocationStore());
const wxAuthLoginRef = ref(null);
const {
$api,
navTo,
cloneDeep
} = inject("globalFunction");
const isLogin = ref(false);
const weekList = ref([]);
const fairList = ref([]);
const currentDay = ref({});
const userInfo = ref({});
const state = reactive({
current: 1,
all: [{}],
});
const pageState = reactive({
pageNum: 0,
total: 0,
maxPage: 2,
pageSize: 10,
jobFairTitle: "",
});
const baseUrl = config.imgBaseUrl;
onLoad(() => {
// const today = new Date();
// const year = today.getFullYear();
// const month = String(today.getMonth() + 1).padStart(2, '0');
// const day = String(today.getDate()).padStart(2, '0');
// const currentDate = `${year}-${month}-${day}`;
// const result = getNextDates({
// startDate: currentDate,
// });
// weekList.value = result;
getHeart();
});
onShow(() => {
// 更新自定义tabbar选中状态
tabbarManager.updateSelected(1);
});
onMounted(() => {
// 监听退出登录事件,显示微信登录弹窗
uni.$on("showLoginModal", () => {
wxAuthLoginRef.value?.open();
});
});
onUnmounted(() => {
uni.$off("showLoginModal");
});
// 登录成功回调
const handleLoginSuccess = () => {
console.log("登录成功");
// 可以在这里添加登录成功后的处理逻辑
};
function goDetail(jobFairId){
if(state.current != 3){
navTo('/packageA/pages/exhibitors/exhibitors?jobFairId=' + jobFairId)
}else{
console.log(userInfo.value, 'userInfo');
if(userInfo.value){
if(userInfo.value.userType=='ent'){
navTo('/packageB/jobFair/detailCom?jobFairId=' + jobFairId)
}else{
navTo('/packageB/jobFair/detailPerson?jobFairId=' + jobFairId)
}
}
}
}
function toSelectDate() {
navTo("/packageA/pages/selectDate/selectDate", {
query: {
date: currentDay.value.fullDate,
},
onBack: (res) => {
const result = getNextDates({
startDate: res.date,
});
const formattedDate = res.date.slice(5); // MM-DD
const dateFull = {
date: res.date.slice(5),
day: "周" + res.week,
fullDate: res.date,
};
currentDay.value = dateFull;
weekList.value = result;
getFair("refresh");
},
});
}
// 查看消息类型
function changeSwiperMsgType(e) {
const currented = e.detail.current;
state.current = currented;
}
function seemsg(index) {
state.current = index;
if (index != 3) {
getFair("refresh");
} else {
if (!isLogin.value) {
getHeart();
return;
}
// 确保获取到用户信息后再请求“我参与的”列表
if (!userInfo.value?.info?.userId) {
getUser().then(() => {
getMyFair("refresh");
});
} else {
getMyFair("refresh");
}
}
}
const handleScrollToLower = () => {
if (pageState.pageNum >= pageState.maxPage) {
return;
} else {
if (state.current != 3) {
getFair();
} else {
this.$nextTick(() => {
getMyFair();
});
}
}
};
function getHeart() {
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) {
isLogin.value = true;
getUser();
} else {
isLogin.value = false;
$api.msg('请先登录')
getFair("refresh");
}
});
}
function getUser() {
const raw = uni.getStorageSync("Padmin-Token");
const token = typeof raw === "string" ? raw.trim() : "";
const headers = token ? {
Authorization: raw.startsWith("Bearer ") ? raw : `Bearer ${token}`
} : {};
return $api.myRequest("/system/user/login/user/info", {}, "GET", 10100, headers).then((resData) => {
// 正确映射响应为用户信息(优先使用 data 字段)
const data = resData?.data ?? resData;
userInfo.value = data || {};
getFair("refresh");
return userInfo.value;
});
}
function getMyFair(type = "add") {
if (type === "refresh") {
pageState.pageNum = 1;
pageState.maxPage = 1;
}
if (type === "add" && pageState.pageNum < pageState.maxPage) {
pageState.pageNum += 1;
}
let params = {
pageNum: pageState.pageNum,
pageSize: pageState.pageSize,
jobFairTitle: pageState.jobFairTitle,
};
if (isLogin.value) {
console.log(userInfo, 'userInfo');
if (userInfo.value.userType == "ent") {
params.enterpriseId = userInfo.value.info.userId;
$api.myRequest("/jobfair/public/jobfair/enterprise/my-sign-up-job-fair", params).then((resData) => {
if (type === "add") {
const reslist = resData.data.list;
fairList.value = fairList.value.concat(reslist);
} else {
fairList.value = resData.data.list;
}
pageState.total = resData.data.total;
pageState.maxPage = resData.data.pages;
});
} else {
params.personId = userInfo.value.info.userId;
$api.myRequest("/jobfair/public/jobfair/person/my-sign-up-job-fair", params).then((resData) => {
if (type === "add") {
const reslist = resData.data.list;
fairList.value = fairList.value.concat(reslist);
} else {
fairList.value = resData.data.list;
}
pageState.total = resData.data.total;
pageState.maxPage = resData.data.pages;
});
}
console.log(params, 'params');
} else {
$api.msg('请先登录');
}
}
function getFair(type = "add") {
if (type === "refresh") {
pageState.pageNum = 1;
pageState.maxPage = 1;
}
if (type === "add" && pageState.pageNum < pageState.maxPage) {
pageState.pageNum += 1;
}
let params = {
pageNum: pageState.pageNum,
pageSize: pageState.pageSize,
jobFairTitle: pageState.jobFairTitle,
jobFairType: state.current,
};
if (isLogin.value) {
if (userInfo.value.userType == "ent") {
params.enterpriseId = userInfo.value.info.userId;
} else {
params.personId = userInfo.value.info.userId;
}
}
$api.myRequest("/jobfair/public/jobfair/page", params).then((resData) => {
if (type === "add") {
const reslist = resData.data.list;
fairList.value = fairList.value.concat(reslist);
} else {
fairList.value = resData.data.list;
}
pageState.total = resData.data.total;
pageState.maxPage = resData.data.pages;
});
}
function toIOSDate(input) {
if (!input) return null;
if (input instanceof Date) return isNaN(input.getTime()) ? null : input;
if (typeof input === "number") {
const d = new Date(input);
return isNaN(d.getTime()) ? null : d;
}
if (typeof input !== "string") return null;
let s = input.trim();
// "YYYY-MM-DD HH:mm[:ss]" -> "YYYY-MM-DDTHH:mm[:ss]"
if (/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}(:\d{2})?$/.test(s)) {
s = s.replace(" ", "T");
// 仅到分钟则补秒
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(s)) {
s = s + ":00";
}
}
// 其余已是 iOS 可解析格式:"YYYY/MM/DD[ HH:mm:ss]"、"YYYY-MM-DD"、ISO 8601 等
const d = new Date(s);
return isNaN(d.getTime()) ? null : d;
}
function parseDateTime(datetimeStr) {
if (!datetimeStr)
return {
time: "",
date: "",
};
const dateObj = toIOSDate(datetimeStr);
if (!dateObj)
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 = toIOSDate(startTimeStr);
const endTime = toIOSDate(endTimeStr);
if (!startTime || !endTime) {
return {
status: 1,
statusText: "时间异常",
color: "#999999"
};
}
// 判断状态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 = toIOSDate(startTimeStr);
const end = toIOSDate(endTimeStr);
if (!start || !end) return 0;
const diffMs = end - start;
const diffHours = diffMs / (1000 * 60 * 60);
return +diffHours.toFixed(2); // 保留 2 位小数
}
const selectDate = (item) => {
if (currentDay.value?.fullDate === item.fullDate) {
currentDay.value = {};
getFair("refresh");
return;
}
currentDay.value = item;
getFair("refresh");
};
function getNextDates({
startDate = "",
count = 6
}) {
const baseDate = startDate ? toIOSDate(startDate) || new Date() : new Date(); // 指定起点或今天
const dates = [];
const dayNames = ["日", "一", "二", "三", "四", "五", "六"];
for (let i = 0; i < count; i++) {
const date = new Date(baseDate);
date.setDate(baseDate.getDate() + i);
const fullDate = date.toISOString().slice(0, 10); // YYYY-MM-DD
const formattedDate = fullDate.slice(5); // MM-DD
const dayOfWeek = dayNames[date.getDay()];
dates.push({
date: formattedDate,
fullDate,
day: "周" + dayOfWeek,
});
}
// 可选设置默认选中项
// currentDay.value = dates[0];
return dates;
}
</script>
<style scoped lang="stylus">
.app-custom-root {
position: fixed;
z-index: 10;
width: 100vw;
height: calc(100% - var(--window-bottom));
overflow: hidden;
}
.app-container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
.app-container .container-header {
background: url("@/static/icon/background2.png") 0 0 no-repeat;
background-size: 100% 400rpx;
}
.app-container .container-header .header-top {
display: flex;
line-height: calc(88rpx - 14rpx);
padding: 16rpx 44rpx 14rpx 44rpx;
}
.app-container .container-header .header-top .header-btnLf {
display: flex;
white-space: nowrap;
justify-content: flex-start;
align-items: center;
width: calc(60rpx * 3);
font-weight: 500;
font-size: 40rpx;
color: #696969;
margin-right: 44rpx;
position: relative;
}
.app-container .container-header .header-top .header-btnLf .btns-wd {
position: absolute;
top: 2rpx;
right: 2rpx;
width: 16rpx;
height: 16rpx;
background: #f73636;
border-radius: 50%;
border: 4rpx solid #eeeeff;
}
.app-container .container-header .header-top .active {
font-weight: 600;
font-size: 40rpx;
color: #000000;
}
.app-container .container-header .header-input {
padding: 0 24rpx;
width: calc(100% - 48rpx);
position: relative;
}
.app-container .container-header .header-input .iconsearch {
position: absolute;
left: 50rpx;
top: 50%;
transform: translate(0, -50%);
}
.app-container .container-header .header-input .input {
padding: 0 30rpx 0 80rpx;
height: 80rpx;
background: #ffffff;
border-radius: 75rpx;
font-size: 28rpx;
}
.app-container .container-header .header-input .inputplace {
font-weight: 400;
font-size: 28rpx;
color: #b5b5b5;
}
.app-container .container-header .header-date {
padding: 28rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.app-container .container-header .header-date .data-week {
flex: 1;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
overflow: hidden;
}
.app-container .container-header .header-date .data-week .weel-days {
font-family: "PingFangSC-Medium", "PingFang SC", "Helvetica Neue", Helvetica,
Arial, "Microsoft YaHei", sans-serif;
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
font-weight: 400;
font-size: 24rpx;
color: #333333;
width: 96rpx;
height: 88rpx;
}
.app-container .container-header .header-date .data-week .weel-days .day {
font-weight: 500;
}
.app-container .container-header .header-date .data-week .active {
background: rgba(37, 107, 250, 0.1);
border-radius: 12rpx;
color: #256bfa;
}
.app-container .container-header .header-date .data-all {
width: 66rpx;
height: 66rpx;
margin-left: 18rpx;
}
.app-container .container-header .header-date .data-all .allimg {
width: 100%;
height: 100%;
}
.container-main {
flex: 1;
overflow: hidden;
background-color: #f4f4f4;
}
.main-scroll {
width: 100%;
height: calc(100% - 150rpx);
}
.cards {
padding: 28rpx;
}
.cards .card {
margin-top: 28rpx;
padding: 32rpx;
background: linear-gradient(to bottom, #e3efff 0%, #fbfdff 100%);
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.04);
border-radius: 20rpx;
}
.cards .card-title {
font-family: "PingFangSC-Medium", "PingFang SC", "Helvetica Neue", Helvetica,
Arial, "Microsoft YaHei", sans-serif;
font-weight: 600;
font-size: 34rpx;
color: #005eb6;
text-align: center;
position relative;
display: flex;
align-items: center;
justify-content: center;
&::after {
content: "";
width: 120rpx;
height: 4rpx;
background: linear-gradient(to right, #015EEA 0%, #00C0FA 100%);
position: absolute;
left: 50%;
bottom: -14rpx;
transform: translate(-50%, -50%);
}
.center-date {
font-weight: 400;
font-size: 24rpx;
// position: absolute;
// right: 0;
// top: 0;
border: 1rpx solid;
padding: 5rpx 10rpx;
margin-left: 10rpx;
}
}
.cards .card-row {
display: flex;
justify-content: center;
font-size: 26rpx;
color: #3e8ff3;
margin-top: 23rpx;
}
.cards .card-times {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 24rpx;
}
.cards .card-times .time-left,
.cards .card-times .time-right {
text-align: center;
}
.cards .card-times .left-date {
font-weight: 600;
font-size: 48rpx;
font-family: "PingFangSC-Medium", "PingFang SC", "Helvetica Neue", Helvetica,
Arial, "Microsoft YaHei", sans-serif;
background: linear-gradient(180deg, #015EEA 0%, #00C0FA 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.cards .card-times .left-dateDay {
font-weight: 400;
font-size: 24rpx;
color: #333333;
margin-top: 12rpx;
}
.cards .card-times .line {
width: 40rpx;
height: 2rpx;
background: #7BB6FF;
margin-top: 7rpx;
}
.cards .card-times .time-center {
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.cards .card-times .time-center .center-dateDay {
font-weight: 400;
font-size: 24rpx;
color: #fff;
margin-top: 6rpx;
line-height: 48rpx;
width: max-content;
height: 48rpx;
background: #71B1FF;
border-radius: 8rpx;
padding: 0 30rpx;
}
.cards .recommend-card-line {
width: 100%;
height: 0;
border-radius: 0;
border-bottom: 2rpx dashed rgba(0, 0, 0, 0.14);
margin-top: 32rpx;
position: relative;
}
.cards .recommend-card-line::before {
content: "";
position: absolute;
left: 0;
top: 0;
transform: translate(-50%, -50%);
width: 28rpx;
height: 28rpx;
background: #f4f4f4;
border-radius: 50%;
}
.cards .recommend-card-line::after {
content: "";
position: absolute;
right: 0;
top: 0;
transform: translate(50%, -50%);
width: 28rpx;
height: 28rpx;
background: #f4f4f4;
border-radius: 50%;
}
.cards .card-footer {
margin-top: 32rpx;
min-height: 50rpx;
font-weight: 400;
font-size: 28rpx;
color: #6c7282;
text-align: center;
}
.cards .card:first-child {
margin-top: 0;
}
</style>