1028 lines
23 KiB
Vue
1028 lines
23 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="job-detail">
|
|||
|
|
<view class="company-header">
|
|||
|
|
<view class="company-img">
|
|||
|
|
<image :src="`${imgBaseUrl}/jobfair/company.png`" mode=""></image>
|
|||
|
|
</view>
|
|||
|
|
<view>
|
|||
|
|
<view class="company-name">
|
|||
|
|
{{ fair.jobFairTitle }}
|
|||
|
|
<view class="job-type">
|
|||
|
|
{{ fair.jobFairType == 1 ? "线上" : "线下" }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="company-Address">
|
|||
|
|
{{ fair.jobFairAddress }}
|
|||
|
|
<view class="activity-status">
|
|||
|
|
{{
|
|||
|
|
getActivityStatus(fair.jobFairStartTime, fair.jobFairEndTime).text
|
|||
|
|
}}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<template v-if="isExpanded">
|
|||
|
|
<view class="jobfair-title"> 招聘会单位: </view>
|
|||
|
|
<view class="jobfair-content">
|
|||
|
|
<view> 1、招聘会协办单位:{{ fair.jobFairHelpUnit }} </view>
|
|||
|
|
<view> 2、招聘会主办单位:{{ fair.jobFairHostUnit }} </view>
|
|||
|
|
<view> 3、招聘会承办单位:{{ fair.jobFairOrganizeUnit }} </view>
|
|||
|
|
</view>
|
|||
|
|
<view class="jobfair-title"> 内容描述: </view>
|
|||
|
|
<view class="jobfair-content">
|
|||
|
|
{{ fair.jobFairIntroduction }}
|
|||
|
|
</view>
|
|||
|
|
<view class="jobfair-title"> 联系电话: </view>
|
|||
|
|
<view class="jobfair-content">
|
|||
|
|
{{ fair.jobFairPhone }}
|
|||
|
|
</view>
|
|||
|
|
<view class="jobfair-title"> 招聘会备注: </view>
|
|||
|
|
<view class="jobfair-content">
|
|||
|
|
{{ fair.jobFairRemark }}
|
|||
|
|
</view>
|
|||
|
|
<view class="jobfair-content">
|
|||
|
|
<view class="card-times">
|
|||
|
|
<view class="time-left">
|
|||
|
|
<view class="left-date">{{
|
|||
|
|
parseDateTime(fair.jobFairStartTime).time
|
|||
|
|
}}</view>
|
|||
|
|
<view class="left-dateDay">{{
|
|||
|
|
parseDateTime(fair.jobFairStartTime).date
|
|||
|
|
}}</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="line"></view>
|
|||
|
|
<view class="time-center">
|
|||
|
|
<view class="center-date">
|
|||
|
|
{{
|
|||
|
|
getTimeStatus(fair.jobFairStartTime, fair.jobFairEndTime)
|
|||
|
|
.statusText
|
|||
|
|
}}
|
|||
|
|
</view>
|
|||
|
|
<view class="center-dateDay">
|
|||
|
|
{{
|
|||
|
|
getHoursBetween(fair.jobFairStartTime, fair.jobFairEndTime)
|
|||
|
|
}}小时
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="line"></view>
|
|||
|
|
<view class="time-right">
|
|||
|
|
<view class="left-date">{{
|
|||
|
|
parseDateTime(fair.jobFairEndTime).time
|
|||
|
|
}}</view>
|
|||
|
|
<view class="left-dateDay">{{
|
|||
|
|
parseDateTime(fair.jobFairEndTime).date
|
|||
|
|
}}</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="jobfair-title"> 招聘会照片: </view>
|
|||
|
|
<view class="jobfair-content">
|
|||
|
|
<image :src="publicUrl + '/file/file/minio' + fair.jobFairImage" alt="" v-if="fair.jobFairImage" />
|
|||
|
|
<text v-else>暂无照片</text>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
<view class="expand" @click="expand">
|
|||
|
|
<text>{{ isExpanded ? "收起" : "展开" }}</text>
|
|||
|
|
<image class="expand-img" :class="{ 'expand-img-active': !isExpanded }" src="@/static/icon/downs.png">
|
|||
|
|
</image>
|
|||
|
|
</view>
|
|||
|
|
<view class="num-box">
|
|||
|
|
<view class="num-item">
|
|||
|
|
<view class="num">
|
|||
|
|
{{ fair.myJobNum?fair.myJobNum : 0 }}
|
|||
|
|
</view>
|
|||
|
|
<view class="num-desc">
|
|||
|
|
企业招聘岗位
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="num-item">
|
|||
|
|
<view class="num">
|
|||
|
|
{{fair.resumeCount?fair.resumeCount : 0}}
|
|||
|
|
</view>
|
|||
|
|
<view class="num-desc">
|
|||
|
|
收到简历
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 使用scroll-view实现分页加载 -->
|
|||
|
|
<scroll-view scroll-y class="detail-box" @scrolltolower="onReachBottom" lower-threshold="50">
|
|||
|
|
<view class="detail-item" v-for="(item, index) in detail.list" :key="index">
|
|||
|
|
<view class="gw">
|
|||
|
|
岗位名称:<text>{{ item.jobInfo.jobTitle }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="name">
|
|||
|
|
{{ item.personInfo.name }}
|
|||
|
|
<!-- 应聘状态(1已投递、2已邀请面试、3已录用、4不录用) -->
|
|||
|
|
<view class="status" :style="getItemBackgroundStyle('wcl.png')">
|
|||
|
|
{{ getStatusText(item.status) }}
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="bottom">
|
|||
|
|
<view class="tag">
|
|||
|
|
<view class="tag-item">性别:{{ item.personInfo.sex == 0 ? "男" : "女" }}</view>
|
|||
|
|
<view class="tag-item success">年龄:{{ item.personInfo.age }}</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<view class="btn">
|
|||
|
|
<button type="primary" plain>查看</button>
|
|||
|
|
<button type="primary" @click="interviewBtn(item)" v-if="item.status == 1">
|
|||
|
|
面试邀请
|
|||
|
|
</button>
|
|||
|
|
<button type="primary" @click="acceptBtn(item, 0)" v-if="item.status != 3 && item.status != 4">
|
|||
|
|
录用
|
|||
|
|
</button>
|
|||
|
|
<button type="primary" @click="acceptBtn(item, 2)" v-if="item.status != 3 && item.status != 4">
|
|||
|
|
不录用
|
|||
|
|
</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<!-- 加载状态 -->
|
|||
|
|
<view v-if="loading" class="loading">加载中...</view>
|
|||
|
|
<view v-if="!loading && detail.list.length >= detail.total" class="no-more">没有更多数据了</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 面试邀请弹窗 -->
|
|||
|
|
<uni-popup ref="interviewPopup" type="center" :maskClick="false">
|
|||
|
|
<view class="popup-content job-dialog" :style="getItemBackgroundStyle('zphbm-k.png')">
|
|||
|
|
<view class="title">
|
|||
|
|
<image :src="`${imgBaseUrl}/jobfair/xb.png`" mode="aspectFit"></image>
|
|||
|
|
面试邀请
|
|||
|
|
</view>
|
|||
|
|
<view class="dialog-content">
|
|||
|
|
<view class="detail-item1">
|
|||
|
|
<view class="label">面试时间:</view>
|
|||
|
|
<view class="value">
|
|||
|
|
<picker mode="date" fields="day" :value="interviewForm.date"
|
|||
|
|
@change="(e) => (interviewForm.date = e.detail.value)">
|
|||
|
|
<view class="picker">
|
|||
|
|
{{ interviewForm.date || "选择日期" }}
|
|||
|
|
</view>
|
|||
|
|
</picker>
|
|||
|
|
<picker mode="time" :value="interviewForm.time"
|
|||
|
|
@change="(e) => (interviewForm.time = e.detail.value)">
|
|||
|
|
<view class="picker">
|
|||
|
|
{{ interviewForm.time || "选择时间" }}
|
|||
|
|
</view>
|
|||
|
|
</picker>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="detail-item1">
|
|||
|
|
<view class="label">面试地点:</view>
|
|||
|
|
<view class="value">
|
|||
|
|
<radio-group @change="changeAddress">
|
|||
|
|
<!-- v-model="interviewForm.radio" -->
|
|||
|
|
<radio :value="'1'" style="transform: scale(0.7)" />企业地址
|
|||
|
|
<radio :value="'2'" style="transform: scale(0.7)" />定义地址
|
|||
|
|
</radio-group>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="detail-item1" v-if="interviewForm.radio == '2'">
|
|||
|
|
<view class="label">定义地址:</view>
|
|||
|
|
<view class="value">
|
|||
|
|
<input v-model="interviewForm.address" placeholder="请输入地址" />
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
<view class="btn-box">
|
|||
|
|
<button type="primary" @click="submitInterview">提交</button>
|
|||
|
|
<button type="default" @click="closeInterviewPopup">关闭</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</uni-popup>
|
|||
|
|
|
|||
|
|
<!-- 企业录用反馈弹窗 -->
|
|||
|
|
<uni-popup ref="feedBackPopup" type="center" :maskClick="false">
|
|||
|
|
<view class="popup-content job-dialog" :style="getItemBackgroundStyle('zphbm-k.png')">
|
|||
|
|
<view class="title">
|
|||
|
|
<image :src="`${imgBaseUrl}/jobfair/xb.png`" mode="aspectFit"></image>
|
|||
|
|
企业录用反馈
|
|||
|
|
</view>
|
|||
|
|
<view class="dialog-content">
|
|||
|
|
<textarea :rows="7" placeholder="请输入内容(必填)" v-model="feedBack"></textarea>
|
|||
|
|
</view>
|
|||
|
|
<view class="btn-box">
|
|||
|
|
<button type="primary" @click="submitFeedBack">提交</button>
|
|||
|
|
<button type="default" @click="closeFeedBackPopup">关闭</button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</uni-popup>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import config from "@/config.js";
|
|||
|
|
import {
|
|||
|
|
ref,
|
|||
|
|
reactive,
|
|||
|
|
onMounted,
|
|||
|
|
nextTick,
|
|||
|
|
watch,
|
|||
|
|
inject
|
|||
|
|
} from "vue";
|
|||
|
|
import {
|
|||
|
|
onLoad
|
|||
|
|
} from "@dcloudio/uni-app";
|
|||
|
|
import {
|
|||
|
|
useRouter,
|
|||
|
|
useRoute
|
|||
|
|
} from "vue-router";
|
|||
|
|
|
|||
|
|
const {
|
|||
|
|
$api
|
|||
|
|
} = inject("globalFunction");
|
|||
|
|
const imgBaseUrl = config.imgBaseUrl;
|
|||
|
|
const router = useRouter();
|
|||
|
|
const route = useRoute();
|
|||
|
|
const interviewPopup = ref(null);
|
|||
|
|
const feedBackPopup = ref(null);
|
|||
|
|
const loading = ref(false);
|
|||
|
|
const hasMore = ref(true);
|
|||
|
|
const jobFairId = ref("");
|
|||
|
|
const userInfo = ref({});
|
|||
|
|
const isExpanded = ref(false);
|
|||
|
|
|
|||
|
|
const publicUrl = config.LCBaseUrl;
|
|||
|
|
onLoad((option) => {
|
|||
|
|
jobFairId.value = option.jobFairId;
|
|||
|
|
getUser();
|
|||
|
|
});
|
|||
|
|
// 响应式数据
|
|||
|
|
const interviewForm = reactive({
|
|||
|
|
date: "",
|
|||
|
|
time: "",
|
|||
|
|
address: "",
|
|||
|
|
radio: "1",
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const feedBack = ref("");
|
|||
|
|
const pages = reactive({
|
|||
|
|
pageNum: 1,
|
|||
|
|
pageSize: 10,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const detail = reactive({
|
|||
|
|
list: [],
|
|||
|
|
total: 0,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const fair = reactive({});
|
|||
|
|
const openGw = reactive({});
|
|||
|
|
const isAccept = ref(true);
|
|||
|
|
|
|||
|
|
function expand() {
|
|||
|
|
isExpanded.value = !isExpanded.value;
|
|||
|
|
}
|
|||
|
|
// 获取状态文本
|
|||
|
|
const getStatusText = (status) => {
|
|||
|
|
switch (status) {
|
|||
|
|
case "1":
|
|||
|
|
return "已投递";
|
|||
|
|
case "2":
|
|||
|
|
return "已邀请面试";
|
|||
|
|
case "3":
|
|||
|
|
return "已录用";
|
|||
|
|
case "4":
|
|||
|
|
return "不录用";
|
|||
|
|
default:
|
|||
|
|
return "未知状态";
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const baseUrl = config.imgBaseUrl;
|
|||
|
|
const getItemBackgroundStyle = (imageName) => ({
|
|||
|
|
backgroundImage: `url(${baseUrl}/jobfair/${imageName})`,
|
|||
|
|
backgroundSize: "100% 100%", // 覆盖整个容器
|
|||
|
|
backgroundPosition: "center", // 居中
|
|||
|
|
backgroundRepeat: "no-repeat",
|
|||
|
|
});
|
|||
|
|
const getDetail = () => {
|
|||
|
|
const data = {
|
|||
|
|
jobFairId: jobFairId.value,
|
|||
|
|
enterpriseId: userInfo.value.info.userId,
|
|||
|
|
};
|
|||
|
|
$api.myRequest("/jobfair/public/jobfair/detail", data).then((resData) => {
|
|||
|
|
// 直接将数据合并到fair对象
|
|||
|
|
Object.assign(fair, resData.data);
|
|||
|
|
console.log(fair, "fair data");
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function changeAddress(e) {
|
|||
|
|
interviewForm.radio = e.detail.value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const getUser = () => {
|
|||
|
|
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("/system/user/login/user/info", {}, "GET", 10100, headers)
|
|||
|
|
.then((resData) => {
|
|||
|
|
userInfo.value = resData;
|
|||
|
|
getDetail();
|
|||
|
|
getList(false);
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
// 获取收到的简历列表
|
|||
|
|
const getList = (isLoadMore = false) => {
|
|||
|
|
if (loading.value) return;
|
|||
|
|
|
|||
|
|
loading.value = true;
|
|||
|
|
try {
|
|||
|
|
$api
|
|||
|
|
.myRequest(
|
|||
|
|
"/jobfair/public/job-fair-person-job/enterprise/my-received-resume", {
|
|||
|
|
enterpriseId: userInfo.value.info.userId,
|
|||
|
|
jobFairId: jobFairId.value,
|
|||
|
|
...pages,
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
.then((data) => {
|
|||
|
|
if (data.code === 200) {
|
|||
|
|
if (isLoadMore) {
|
|||
|
|
detail.list = [...detail.list, ...data.data.list];
|
|||
|
|
} else {
|
|||
|
|
detail.list = data.data.list || [];
|
|||
|
|
}
|
|||
|
|
detail.total = data.data.total || 0;
|
|||
|
|
hasMore.value = detail.list.length < detail.total;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.log(error, "error");
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "获取数据失败",
|
|||
|
|
icon: "none",
|
|||
|
|
});
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 面试邀请
|
|||
|
|
const interviewBtn = (item) => {
|
|||
|
|
Object.assign(openGw, item);
|
|||
|
|
interviewPopup.value.open();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 关闭面试弹窗
|
|||
|
|
const closeInterviewPopup = () => {
|
|||
|
|
interviewPopup.value.close();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 关闭反馈弹窗
|
|||
|
|
const closeFeedBackPopup = () => {
|
|||
|
|
feedBackPopup.value.close();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 提交面试邀请
|
|||
|
|
const submitInterview = () => {
|
|||
|
|
if (!interviewForm.date) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "请选择面试日期",
|
|||
|
|
icon: "none",
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!interviewForm.time) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "请选择面试时间",
|
|||
|
|
icon: "none",
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (interviewForm.radio == "2" && !interviewForm.address) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "请输入面试地址",
|
|||
|
|
icon: "none",
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const data = {
|
|||
|
|
jobFairPersonJobId: openGw.jobFairPersonJobId,
|
|||
|
|
status: "2",
|
|||
|
|
interviewTime: `${interviewForm.date} ${interviewForm.time}`,
|
|||
|
|
interviewAddress: interviewForm.radio == "2" ? interviewForm.address : fair.jobFairAddress,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
update(data, "面试邀请成功");
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
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 update = (data, msg) => {
|
|||
|
|
$api
|
|||
|
|
.myRequest(
|
|||
|
|
"/jobfair/public/job-fair-person-job/update",
|
|||
|
|
data,
|
|||
|
|
"POST",
|
|||
|
|
9100, {
|
|||
|
|
"Content-Type": "application/json",
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
.then((resData) => {
|
|||
|
|
if (resData.code == 200) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: msg,
|
|||
|
|
icon: "success",
|
|||
|
|
});
|
|||
|
|
closeInterviewPopup();
|
|||
|
|
closeFeedBackPopup();
|
|||
|
|
// 重新加载列表
|
|||
|
|
pages.pageNum = 1;
|
|||
|
|
getList(false);
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "操作失败",
|
|||
|
|
icon: "none",
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 提交反馈
|
|||
|
|
const submitFeedBack = () => {
|
|||
|
|
if (!feedBack.value) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: "请输入内容",
|
|||
|
|
icon: "none",
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const data = {
|
|||
|
|
jobFairPersonJobId: openGw.jobFairPersonJobId,
|
|||
|
|
status: isAccept.value ? "3" : "4",
|
|||
|
|
feedback: feedBack.value,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
update(data, "操作成功");
|
|||
|
|
feedBack.value = "";
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 录用/不录用按钮
|
|||
|
|
const acceptBtn = (item, num) => {
|
|||
|
|
isAccept.value = num == 0;
|
|||
|
|
Object.assign(openGw, item);
|
|||
|
|
feedBackPopup.value.open();
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 返回
|
|||
|
|
const goBack = () => {
|
|||
|
|
router.go(-1);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 获取活动状态
|
|||
|
|
const getActivityStatus = (startTime, endTime) => {
|
|||
|
|
// 获取当前时间戳(毫秒)
|
|||
|
|
const now = Date.now();
|
|||
|
|
|
|||
|
|
// 将开始时间和结束时间转换为时间戳
|
|||
|
|
const start =
|
|||
|
|
typeof startTime === "string" ? new Date(startTime).getTime() : startTime;
|
|||
|
|
const end =
|
|||
|
|
typeof endTime === "string" ? new Date(endTime).getTime() : endTime;
|
|||
|
|
|
|||
|
|
// 处理无效时间
|
|||
|
|
if (isNaN(start) || isNaN(end)) {
|
|||
|
|
return {
|
|||
|
|
text: "未知状态",
|
|||
|
|
style: {},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 判断状态
|
|||
|
|
if (now < start) {
|
|||
|
|
return {
|
|||
|
|
status: 0,
|
|||
|
|
text: "未开始",
|
|||
|
|
style: {},
|
|||
|
|
};
|
|||
|
|
} else if (now > end) {
|
|||
|
|
return {
|
|||
|
|
status: 1,
|
|||
|
|
text: "已结束",
|
|||
|
|
style: {},
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
return {
|
|||
|
|
status: 2,
|
|||
|
|
text: "进行中",
|
|||
|
|
style: {},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 滚动到底部加载更多
|
|||
|
|
const onReachBottom = () => {
|
|||
|
|
if (!loading.value && hasMore.value) {
|
|||
|
|
pages.pageNum++;
|
|||
|
|
getList(true);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.jobfair-content {
|
|||
|
|
color: #656565;
|
|||
|
|
margin-bottom: 20rpx;
|
|||
|
|
line-height: 44rpx;
|
|||
|
|
|
|||
|
|
image {
|
|||
|
|
width: 300rpx;
|
|||
|
|
height: 300rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.jobfair-title {
|
|||
|
|
width: max-content;
|
|||
|
|
color: #404040;
|
|||
|
|
font-weight: 600;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
margin-bottom: 25rpx;
|
|||
|
|
position: relative;
|
|||
|
|
|
|||
|
|
&::after {
|
|||
|
|
bottom: -8px;
|
|||
|
|
position: absolute;
|
|||
|
|
left: 31%;
|
|||
|
|
content: "";
|
|||
|
|
display: block;
|
|||
|
|
width: 37rpx;
|
|||
|
|
height: 9rpx;
|
|||
|
|
background: linear-gradient(to right, #ffad58 0%, #ff7a5b 100%);
|
|||
|
|
border-radius: 10rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.job-detail {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100vh;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
padding: 20rpx;
|
|||
|
|
background: #e9f2ff;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
|
|||
|
|
.detail-box {
|
|||
|
|
min-height: max-content;
|
|||
|
|
max-height: calc(100vh - 375rpx);
|
|||
|
|
padding-top: 20rpx;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
|
|||
|
|
.detail-item {
|
|||
|
|
margin-top: 30rpx;
|
|||
|
|
background: linear-gradient(to bottom, #deecff 0%, #ffffff 100%);
|
|||
|
|
box-shadow: 0 0 10rpx rgba(0, 95, 169, 0.19);
|
|||
|
|
border-radius: 12rpx;
|
|||
|
|
border: 2rpx solid #ffffff;
|
|||
|
|
padding: 30rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.name {
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin: 18rpx 0;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
|
|||
|
|
.status {
|
|||
|
|
width: 160rpx;
|
|||
|
|
text-align: center;
|
|||
|
|
margin-left: 24rpx;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: #fff;
|
|||
|
|
background-size: 100% 100%;
|
|||
|
|
font-weight: normal;
|
|||
|
|
padding: 6rpx 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bottom {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
|
|||
|
|
.tag {
|
|||
|
|
width: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 16rpx;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
|
|||
|
|
.tag-item {
|
|||
|
|
padding: 6rpx 30rpx;
|
|||
|
|
border-radius: 6rpx;
|
|||
|
|
background-color: #E5F1FF;
|
|||
|
|
color: #589BFF;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
|
|||
|
|
&.success {
|
|||
|
|
background-color: #E6F8EB;
|
|||
|
|
color: #21AA5B;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.btn {
|
|||
|
|
width: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: flex-end;
|
|||
|
|
|
|||
|
|
button {
|
|||
|
|
margin: 10rpx;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.gw {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
color: #1477f1;
|
|||
|
|
font-weight: 600;
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.company-header {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 20rpx;
|
|||
|
|
margin-bottom: 26rpx;
|
|||
|
|
|
|||
|
|
.company-img {
|
|||
|
|
width: 110rpx;
|
|||
|
|
height: 107rpx;
|
|||
|
|
border-radius: 20rpx;
|
|||
|
|
|
|||
|
|
image {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.company-Address {
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #404040;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 10rpx;
|
|||
|
|
|
|||
|
|
.activity-status {
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: #0088ff;
|
|||
|
|
font-weight: 600;
|
|||
|
|
position: relative;
|
|||
|
|
margin-left: 10rpx;
|
|||
|
|
|
|||
|
|
&::before {
|
|||
|
|
content: "";
|
|||
|
|
display: inline-block;
|
|||
|
|
width: 10rpx;
|
|||
|
|
height: 10rpx;
|
|||
|
|
background: #0088ff;
|
|||
|
|
border-radius: 50rpx;
|
|||
|
|
margin-right: 6rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.company-name {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
font-size: 38rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #4d4d4d;
|
|||
|
|
position: relative;
|
|||
|
|
margin-bottom: 10rpx;
|
|||
|
|
gap: 10rpx;
|
|||
|
|
|
|||
|
|
.job-type {
|
|||
|
|
padding: 0 20rpx;
|
|||
|
|
color: #fff;
|
|||
|
|
background: #fd9a33;
|
|||
|
|
border-radius: 20rpx;
|
|||
|
|
font-weight: normal;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.loading,
|
|||
|
|
.no-more {
|
|||
|
|
text-align: center;
|
|||
|
|
padding: 20rpx 0;
|
|||
|
|
color: #909399;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 弹窗样式
|
|||
|
|
.popup-content {
|
|||
|
|
width: 90vw;
|
|||
|
|
height: 70vh;
|
|||
|
|
// max-width: 600rpx;
|
|||
|
|
// background: #fff;
|
|||
|
|
border-radius: 20rpx;
|
|||
|
|
padding: 10rpx 20rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.btn-box {
|
|||
|
|
width: 100%;
|
|||
|
|
padding: 15rpx 0 20rpx;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 50rpx;
|
|||
|
|
|
|||
|
|
button {
|
|||
|
|
padding: 0 80rpx;
|
|||
|
|
height: 80rpx;
|
|||
|
|
line-height: 80rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.job-dialog {
|
|||
|
|
// background: url("../../../assets/images/job/company/module/") no-repeat 100% 100%;
|
|||
|
|
|
|||
|
|
.dialog-content {
|
|||
|
|
padding: 10rpx;
|
|||
|
|
height: 80%;
|
|||
|
|
|
|||
|
|
.detail-item1 {
|
|||
|
|
// display: flex;
|
|||
|
|
// align-items: center;
|
|||
|
|
margin: 30rpx 0;
|
|||
|
|
|
|||
|
|
.label {
|
|||
|
|
width: 200rpx;
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
color: #303133;
|
|||
|
|
margin-bottom: 15rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.value {
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
gap: 20rpx;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.picker {
|
|||
|
|
width: 275rpx;
|
|||
|
|
border: 1px solid #dcdfe6;
|
|||
|
|
border-radius: 8rpx;
|
|||
|
|
padding: 16rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.title {
|
|||
|
|
font-size: 38rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
padding: 20rpx;
|
|||
|
|
padding-bottom: 0;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
position: sticky;
|
|||
|
|
top: 0;
|
|||
|
|
|
|||
|
|
image {
|
|||
|
|
width: 14rpx;
|
|||
|
|
height: 33rpx;
|
|||
|
|
margin-right: 14rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
textarea {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 300rpx;
|
|||
|
|
border: 1px solid #dcdfe6;
|
|||
|
|
border-radius: 8rpx;
|
|||
|
|
padding: 20rpx;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
input {
|
|||
|
|
width: 100%;
|
|||
|
|
border: 1px solid #dcdfe6;
|
|||
|
|
border-radius: 8rpx;
|
|||
|
|
height: 75rpx;
|
|||
|
|
line-height: 75rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-times {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-top: 24rpx;
|
|||
|
|
|
|||
|
|
.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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.left-dateDay {
|
|||
|
|
font-weight: 400;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
margin-top: 12rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.line {
|
|||
|
|
width: 40rpx;
|
|||
|
|
height: 2rpx;
|
|||
|
|
background: #7bb6ff;
|
|||
|
|
margin-top: 7rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.time-center {
|
|||
|
|
text-align: center;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-times .time-left,
|
|||
|
|
.card-times .time-right {
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand {
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: nowrap;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
justify-content: center;
|
|||
|
|
margin-bottom: 12rpx;
|
|||
|
|
font-weight: 400;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #256bfa;
|
|||
|
|
|
|||
|
|
.expand-img {
|
|||
|
|
width: 40rpx;
|
|||
|
|
height: 40rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-img-active {
|
|||
|
|
transform: rotate(180deg);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.num-box {
|
|||
|
|
width: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
.num-item {
|
|||
|
|
width: 50%;
|
|||
|
|
text-align: center;
|
|||
|
|
|
|||
|
|
.num {
|
|||
|
|
font-size: 40rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
background: linear-gradient(184deg, #0BBAFB 0%, #4285EC 100%);
|
|||
|
|
-webkit-background-clip: text;
|
|||
|
|
-webkit-text-fill-color: transparent;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.num-desc {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #0C458A;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|