招聘会模块

This commit is contained in:
2025-10-31 17:24:07 +08:00
parent 99d932a453
commit 9a6ad76000
9 changed files with 2619 additions and 1436 deletions

View File

@@ -2,7 +2,8 @@ import useUserStore from "../stores/useUserStore";
import { import {
request, request,
createRequest, createRequest,
uploadFile uploadFile,
myRequest
} from "../utils/request"; } from "../utils/request";
import streamRequest, { import streamRequest, {
chatRequest chatRequest
@@ -885,7 +886,8 @@ export const $api = {
uploadFile, uploadFile,
formatFileSize, formatFileSize,
sendingMiniProgramMessage, sendingMiniProgramMessage,
copyText copyText,
myRequest
} }

View File

@@ -1,6 +1,9 @@
export default { export default {
// baseUrl: 'http://39.98.44.136:8080', // 测试 // baseUrl: 'http://39.98.44.136:8080', // 测试
baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks', // 测试 baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks', // 测试
LCBaseUrl:'http://10.110.145.145:9100',//招聘、培训、帮扶
LCBaseUrlInner:'http://10.110.145.145:10100',//内网端口
// sseAI+ // sseAI+
// StreamBaseURl: 'http://39.98.44.136:8000', // StreamBaseURl: 'http://39.98.44.136:8000',
StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai', StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai',

View File

@@ -10,9 +10,8 @@
<image <image
src="@/static/icon/collect3.png" src="@/static/icon/collect3.png"
v-if="!companyInfo.isCollection" v-if="!companyInfo.isCollection"
@click="companyCollection"
></image> ></image>
<image src="@/static/icon/collect2.png" v-else @click="companyCollection"></image> <image src="@/static/icon/collect2.png" v-else></image>
</view> </view>
</template> </template>
<view class="content"> <view class="content">
@@ -21,41 +20,73 @@
<image src="@/static/icon/companyIcon.png" mode=""></image> <image src="@/static/icon/companyIcon.png" mode=""></image>
</view> </view>
<view class="companyinfo-right"> <view class="companyinfo-right">
<view class="row1">{{ companyInfo?.name }}</view> <view class="row1">{{ companyInfo?.companyName }}</view>
<view class="row2"> <view class="row2">
<dict-tree-Label {{ companyInfo?.scale }}
v-if="companyInfo?.industry"
dictType="industry"
:value="companyInfo?.industry"
></dict-tree-Label>
<span v-if="companyInfo?.industry">&nbsp;</span>
<dict-Label dictType="scale" :value="companyInfo?.scale"></dict-Label>
</view> </view>
</view> </view>
</view> </view>
<view class="conetent-info" :class="{ expanded: isExpanded }"> <view class="conetent-info" :class="{ expanded: isExpanded }">
<view class="info-title">公司介绍</view> <view class="info-title">公司介绍</view>
<view class="info-desirption">{{ companyInfo.description }}</view> <view class="info-desirption">{{
companyInfo.companyIntroduction
}}</view>
<!-- <view class="info-title title2">公司地址</view> <!-- <view class="info-title title2">公司地址</view>
<view class="locationCompany"></view> --> <view class="locationCompany"></view> -->
</view> </view>
<view class="expand" @click="expand"> <view class="expand" @click="expand">
<text>{{ isExpanded ? '收起' : '展开' }}</text> <text>{{ isExpanded ? "收起" : "展开" }}</text>
<image <image
class="expand-img" class="expand-img"
:class="{ 'expand-img-active': !isExpanded }" :class="{ 'expand-img-active': !isExpanded }"
src="@/static/icon/downs.png" src="@/static/icon/downs.png"
></image> ></image>
</view> </view>
<scroll-view scroll-y class="Detailscroll-view" @scrolltolower="getJobsList('add')"> <scroll-view scroll-y class="Detailscroll-view">
<view class="views"> <view class="views">
<view class="Detail-title"><text class="title">在招职位</text></view> <view class="Detail-title"><text class="title">在招职位</text></view>
<renderJobs <template v-if="companyInfo.jobInfoList.length != 0">
v-if="pageState.list.length" <view v-for="job in companyInfo.jobInfoList" :key="job.id">
:list="pageState.list" <view class="cards" @click="navTo(`/packageA/pages/post/post?jobId=${JSON.stringify(job)}`)">
:longitude="longitudeVal" <view class="card-company">
:latitude="latitudeVal" <text class="company">{{ job.jobTitle }}</text>
></renderJobs> <view class="salary"> {{ job.salaryRange }} </view>
</view>
<view class="card-companyName">{{ job.companyName }}</view>
<view class="card-companyName">{{ job.jobDescription }}</view>
<view class="card-tags">
<view class="tag">
{{ job.educationRequirement }}
</view>
<view class="tag">
{{ job.experienceRequirement }}
</view>
<!-- <view class="tag">
{{ vacanciesTo(job.vacancies) }}
</view> -->
<view class="tag" v-if="job.jobRequirement">
{{ job.jobRequirement }}
</view>
</view>
<view class="card-bottom">
<view>{{ job.postingDate }}</view>
<view>
<convert-distance
:alat="job.latitude"
:along="job.longitude"
:blat="latitude"
:blong="longitude"
></convert-distance>
<dict-Label
class="mar_le10"
dictType="area"
:value="job.jobLocationAreaCode"
></dict-Label>
</view>
</view>
</view>
</view>
</template>
<empty v-else pdTop="200"></empty> <empty v-else pdTop="200"></empty>
</view> </view>
</scroll-view> </scroll-view>
@@ -64,14 +95,14 @@
</template> </template>
<script setup> <script setup>
import point from '@/static/icon/point.png'; import point from "@/static/icon/point.png";
import { reactive, inject, watch, ref, onMounted, computed } from 'vue'; import { reactive, inject, watch, ref, onMounted, computed } from "vue";
import { onLoad, onShow } from '@dcloudio/uni-app'; import { onLoad, onShow } from "@dcloudio/uni-app";
import dictLabel from '@/components/dict-Label/dict-Label.vue'; import dictLabel from "@/components/dict-Label/dict-Label.vue";
import { storeToRefs } from 'pinia'; import { storeToRefs } from "pinia";
import useLocationStore from '@/stores/useLocationStore'; import useLocationStore from "@/stores/useLocationStore";
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore()); const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const { $api, navTo, vacanciesTo, navBack } = inject('globalFunction'); const { $api, navTo, vacanciesTo, navBack } = inject("globalFunction");
const isExpanded = ref(false); const isExpanded = ref(false);
const pageState = reactive({ const pageState = reactive({
@@ -84,69 +115,21 @@ const pageState = reactive({
const companyInfo = ref({}); const companyInfo = ref({});
onLoad((options) => { onLoad((options) => {
console.log(options); companyInfo.value = JSON.parse(options.job);
getCompanyInfo(options.companyId || options.bussinessId); console.log(companyInfo.value, "companyInfo.value");
}); });
function companyCollection() {
const companyId = companyInfo.value.companyId;
if (companyInfo.value.isCollection) {
$api.createRequest(`/app/company/collection/${companyId}`, {}, 'DELETE').then((resData) => {
getCompanyInfo(companyId);
$api.msg('取消收藏成功');
});
} else {
$api.createRequest(`/app/company/collection/${companyId}`, {}, 'POST').then((resData) => {
getCompanyInfo(companyId);
$api.msg('收藏成功');
});
}
}
function getCompanyInfo(id) {
$api.createRequest(`/app/company/${id}`).then((resData) => {
companyInfo.value = resData.data;
getJobsList();
});
}
function getJobsList(type = 'add') {
if (type === 'refresh') {
pageState.page = 1;
pageState.maxPage = 1;
}
if (type === 'add' && pageState.page < pageState.maxPage) {
pageState.page += 1;
}
let params = {
current: pageState.page,
pageSize: pageState.pageSize,
};
$api.createRequest(`/app/company/job/${companyInfo.value.companyId}`, params).then((resData) => {
const { rows, total } = resData;
if (type === 'add') {
const str = pageState.pageSize * (pageState.page - 1);
const end = pageState.list.length;
const reslist = rows;
pageState.list.splice(str, end, ...reslist);
} else {
pageState.list = rows;
}
pageState.total = resData.total;
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
});
}
function expand() { function expand() {
isExpanded.value = !isExpanded.value; isExpanded.value = !isExpanded.value;
} }
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.btnback{ .btnback {
width: 64rpx; width: 64rpx;
height: 64rpx; height: 64rpx;
} }
.btn { .btn {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@@ -154,33 +137,38 @@ function expand() {
width: 52rpx; width: 52rpx;
height: 52rpx; height: 52rpx;
} }
image { image {
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.content{
height: 100% .content {
height: 100%;
display: flex; display: flex;
flex-direction: column flex-direction: column;
.content-top{
padding: 28rpx .content-top {
padding-top: 50rpx padding: 28rpx;
display: flex padding-top: 50rpx;
flex-direction: row display: flex;
flex-wrap: nowrap flex-direction: row;
.companyinfo-left{ flex-wrap: nowrap;
.companyinfo-left {
width: 96rpx; width: 96rpx;
height: 96rpx; height: 96rpx;
margin-right: 24rpx margin-right: 24rpx;
} }
.companyinfo-right{
.row1{ .companyinfo-right {
.row1 {
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 32rpx;
color: #333333; color: #333333;
} }
.row2{
.row2 {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6C7282;
@@ -188,110 +176,130 @@ image {
} }
} }
} }
.conetent-info{
padding: 0 28rpx .conetent-info {
padding: 0 28rpx;
overflow: hidden; overflow: hidden;
max-height: 0rpx; max-height: 0rpx;
transition: max-height 0.3s ease; transition: max-height 0.3s ease;
.info-title{
.info-title {
font-weight: 600; font-weight: 600;
font-size: 28rpx; font-size: 28rpx;
color: #000000; color: #000000;
} }
.info-desirption{
margin-top: 12rpx .info-desirption {
margin-top: 12rpx;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #495265; color: #495265;
text-align: justified; text-align: justified;
} }
.title2{
margin-top: 48rpx .title2 {
margin-top: 48rpx;
} }
} }
.expanded { .expanded {
max-height: 1000rpx; // 足够显示完整内容 max-height: 1000rpx; // 足够显示完整内容
} }
.expand{
display: flex .expand {
flex-wrap: nowrap display: flex;
white-space: nowrap flex-wrap: nowrap;
justify-content: center white-space: nowrap;
margin-top: 20rpx justify-content: center;
margin-bottom: 28rpx margin-top: 20rpx;
margin-bottom: 28rpx;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #256BFA; color: #256BFA;
.expand-img{
.expand-img {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
} }
.expand-img-active{
transform: rotate(180deg) .expand-img-active {
transform: rotate(180deg);
} }
} }
} }
.Detailscroll-view{
.Detailscroll-view {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
background: #F4F4F4; background: #F4F4F4;
.views{
padding: 28rpx .views {
.Detail-title{ padding: 28rpx;
.Detail-title {
font-weight: 600; font-weight: 600;
font-size: 32rpx; font-size: 32rpx;
color: #000000; color: #000000;
position: relative; position: relative;
display: flex display: flex;
justify-content: space-between justify-content: space-between;
.title{
.title {
position: relative; position: relative;
z-index: 2; z-index: 2;
} }
} }
.Detail-title::before{
position: absolute .Detail-title::before {
position: absolute;
content: ''; content: '';
left: -14rpx left: -14rpx;
bottom: 0 bottom: 0;
height: 16rpx; height: 16rpx;
width: 108rpx; width: 108rpx;
background: linear-gradient(to right, #CBDEFF, #FFFFFF); background: linear-gradient(to right, #CBDEFF, #FFFFFF);
border-radius: 8rpx; border-radius: 8rpx;
z-index: 1; z-index: 1;
} }
.cards{
.cards {
padding: 32rpx; padding: 32rpx;
background: #FFFFFF; background: #FFFFFF;
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0,0,0,0.04); box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.04);
border-radius: 20rpx 20rpx 20rpx 20rpx; border-radius: 20rpx 20rpx 20rpx 20rpx;
margin-top: 22rpx; margin-top: 22rpx;
.card-company{
display: flex .card-company {
justify-content: space-between display: flex;
align-items: flex-start justify-content: space-between;
.company{ align-items: flex-start;
.company {
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 32rpx;
color: #333333; color: #333333;
} }
.salary{
.salary {
font-weight: 500; font-weight: 500;
font-size: 28rpx; font-size: 28rpx;
color: #4C6EFB; color: #4C6EFB;
white-space: nowrap white-space: nowrap;
line-height: 48rpx line-height: 48rpx;
} }
} }
.card-companyName{
.card-companyName {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6C7282;
} }
.card-tags{
display: flex .card-tags {
flex-wrap: wrap display: flex;
.tag{ flex-wrap: wrap;
.tag {
width: fit-content; width: fit-content;
height: 30rpx; height: 30rpx;
background: #F4F4F4; background: #F4F4F4;
@@ -303,14 +311,15 @@ image {
color: #6C7282; color: #6C7282;
text-align: center; text-align: center;
margin-top: 14rpx; margin-top: 14rpx;
white-space: nowrap white-space: nowrap;
margin-right: 20rpx margin-right: 20rpx;
} }
} }
.card-bottom{
margin-top: 32rpx .card-bottom {
display: flex margin-top: 32rpx;
justify-content: space-between display: flex;
justify-content: space-between;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6C7282;
} }

View File

@@ -11,15 +11,11 @@
<image src="@/static/icon/companyIcon.png" mode=""></image> <image src="@/static/icon/companyIcon.png" mode=""></image>
</view> </view>
<view class="companyinfo-right"> <view class="companyinfo-right">
<view class="row1 line_2">{{ fairInfo?.name }}</view> <view class="row1 line_2">{{ fairInfo?.jobFairTitle }}</view>
<view class="row2"> <view class="row2">
<text>{{ fairInfo.location }}</text> <text>{{ fairInfo?.jobFairAddress }}</text>
<convert-distance <convert-distance :alat="fairInfo?.latitude" :along="fairInfo?.longitude" :blat="latitudeVal"
:alat="fairInfo.latitude" :blong="longitudeVal"></convert-distance>
:along="fairInfo.longitude"
:blat="latitudeVal"
:blong="longitudeVal"
></convert-distance>
</view> </view>
</view> </view>
</view> </view>
@@ -27,70 +23,84 @@
<image class="location-img" src="/static/icon/mapLine.png"></image> <image class="location-img" src="/static/icon/mapLine.png"></image>
<view class="location-info"> <view class="location-info">
<view class="info"> <view class="info">
<text class="info-title">{{ fairInfo.address }}</text> <text class="info-title">{{ fairInfo?.jobFairAddress }}</text>
<text class="info-text">位置</text> <text class="info-text">位置</text>
</view> </view>
</view> </view>
</view> </view>
<view class="conetent-info" :class="{ expanded: isExpanded }"> <view class="conetent-info" :class="{ expanded: isExpanded }">
<view class="info-title">内容描述</view> <view class="info-title">内容描述</view>
<view class="info-desirption">{{ fairInfo.description }}</view> <view class="info-desirption">{{ fairInfo?.jobFairIntroduction }}</view>
<!-- <view class="info-title title2">公司地址</view> <!-- <view class="info-title title2">公司地址</view>
<view class="locationCompany"></view> --> <view class="locationCompany"></view> -->
<view class="company-times"> <view class="company-times">
<view class="info-title">内容描述</view> <view class="info-title">内容描述</view>
<view class="card-times"> <view class="card-times">
<view class="time-left"> <view class="time-left">
<view class="left-date">{{ parseDateTime(fairInfo.startTime).time }}</view> <view class="left-date">{{ parseDateTime(fairInfo.jobFairStartTime).time }}</view>
<view class="left-dateDay">{{ parseDateTime(fairInfo.startTime).date }}</view> <view class="left-dateDay">{{ parseDateTime(fairInfo.jobFairStartTime).date }}</view>
</view> </view>
<view class="line"></view> <view class="line"></view>
<view class="time-center"> <view class="time-center">
<view class="center-date"> <view class="center-date">
{{ getTimeStatus(fairInfo.startTime, fairInfo.endTime).statusText }} {{ getTimeStatus(fairInfo.jobFairStartTime, fairInfo.jobFairEndTime).statusText }}
</view> </view>
<view class="center-dateDay"> <view class="center-dateDay">
{{ getHoursBetween(fairInfo.startTime, fairInfo.endTime) }}小时 {{ getHoursBetween(fairInfo.jobFairStartTime, fairInfo.jobFairEndTime) }}小时
</view> </view>
</view> </view>
<view class="line"></view> <view class="line"></view>
<view class="time-right"> <view class="time-right">
<view class="left-date">{{ parseDateTime(fairInfo.endTime).time }}</view> <view class="left-date">{{ parseDateTime(fairInfo.jobFairEndTime).time }}</view>
<view class="left-dateDay">{{ parseDateTime(fairInfo.endTime).date }}</view> <view class="left-dateDay">{{ parseDateTime(fairInfo.jobFairEndTime).date }}</view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view class="expand" @click="expand"> <view class="expand" @click="expand">
<text>{{ isExpanded ? '收起' : '展开' }}</text> <text>{{ isExpanded ? '收起' : '展开' }}</text>
<image <image class="expand-img" :class="{ 'expand-img-active': !isExpanded }" src="@/static/icon/downs.png">
class="expand-img" </image>
:class="{ 'expand-img-active': !isExpanded }"
src="@/static/icon/downs.png"
></image>
</view> </view>
<scroll-view scroll-y class="Detailscroll-view"> <scroll-view scroll-y class="Detailscroll-view">
<view class="views"> <view class="views">
<view class="Detail-title"> <view class="Detail-title">
<text class="title">参会单位{{ companyList.length }}</text> <text class="title">参会单位{{ companyList.length }}</text>
</view> </view>
<renderCompanys <view v-for="job in companyList" :key="job.id">
v-if="companyList.length" <view class="cards" @click="navTo('/packageA/pages/UnitDetails/UnitDetails?job='+JSON.stringify(job))">
:list="companyList" <view class="card-company">
:longitude="longitudeVal" <text class="company line_1">{{ job.companyName }}</text>
:latitude="latitudeVal" </view>
></renderCompanys> <view class="card-bottom">
<empty v-else pdTop="200"></empty> <view class="fl_box fs_14">
{{ job.scale }}
</view>
<view class="ris">
<text class="fs_14">
在招职位·
<text class="color_256BFA">{{ job.jobInfoList.length || '-' }}</text>
</text>
</view>
</view>
<view class="card-tags">
<view class="tag" v-if="job.industry">
{{ job.industry }}
</view>
<view class="tag">
{{ job.companyType }}
</view>
</view>
</view>
</view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<template #footer> <template #footer>
<view class="footer" v-if="hasnext"> <view class="footer" v-if="hasnext">
<view <view class="btn-wq button-click" :class="{ 'btn-desbel': fairInfo.isCollection }"
class="btn-wq button-click" @click="applyExhibitors">
:class="{ 'btn-desbel': fairInfo.isCollection }"
@click="applyExhibitors"
>
{{ fairInfo.isCollection ? '已预约招聘会' : '预约招聘会' }} {{ fairInfo.isCollection ? '已预约招聘会' : '预约招聘会' }}
</view> </view>
</view> </view>
@@ -99,32 +109,66 @@
</template> </template>
<script setup> <script setup>
import point from '@/static/icon/point.png'; import point from '@/static/icon/point.png';
import { reactive, inject, watch, ref, onMounted, computed } from 'vue'; import {
import { onLoad, onShow } from '@dcloudio/uni-app'; reactive,
import dictLabel from '@/components/dict-Label/dict-Label.vue'; inject,
import useLocationStore from '@/stores/useLocationStore'; watch,
const { $api, navTo, vacanciesTo, navBack } = inject('globalFunction'); ref,
import { storeToRefs } from 'pinia'; onMounted,
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore()); computed
} from 'vue';
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import dictLabel from '@/components/dict-Label/dict-Label.vue';
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 isExpanded = ref(false);
const fairInfo = ref({}); const fairInfo = ref({});
const companyList = ref([]); const companyList = ref([]);
const hasnext = ref(true); const hasnext = ref(true);
onLoad((options) => { onLoad((options) => {
getCompanyInfo(options.jobFairId); getCompanyInfo(options.jobFairId);
});
function getCompanyInfo(id) {
$api.createRequest(`/app/fair/${id}`).then((resData) => {
fairInfo.value = resData.data;
companyList.value = resData.data.companyList;
hasAppointment();
}); });
}
const hasAppointment = () => { function getCompanyInfo(id) {
// $api.createRequest(`/app/fair/${id}`).then((resData) => {
// fairInfo.value = resData.data;
// companyList.value = resData.data.companyList;
// hasAppointment();
// });
$api.myRequest('/jobfair/public/jobfair/detail', {
jobFairId: id
}).then((resData) => {
console.log(resData, 'resData');
fairInfo.value = resData.data;
console.log(fairInfo.value, 'fairInfo.value');
// hasAppointment()
});
$api.myRequest('/jobfair/public/jobfair/enterprises-with-jobs-by-job-fair-id', {
jobFairId: id
}).then((resData) => {
companyList.value = resData.data;
// hasAppointment()
});
};
const hasAppointment = () => {
const isTimePassed = (timeStr) => { const isTimePassed = (timeStr) => {
const targetTime = new Date(timeStr.replace(/-/g, '/')).getTime(); // 兼容格式 const targetTime = new Date(timeStr.replace(/-/g, '/')).getTime(); // 兼容格式
const now = Date.now(); const now = Date.now();
@@ -132,23 +176,23 @@ const hasAppointment = () => {
}; };
hasnext.value = isTimePassed(fairInfo.value.startTime); hasnext.value = isTimePassed(fairInfo.value.startTime);
}; };
function openMap(lat, lng, name = '位置') { function openMap(lat, lng, name = '位置') {
const isConfirmed = window.confirm('是否打开地图查看位置?'); const isConfirmed = window.confirm('是否打开地图查看位置?');
if (!isConfirmed) return; if (!isConfirmed) return;
// 使用高德地图或百度地图的 H5 链接打开 // 使用高德地图或百度地图的 H5 链接打开
const url = `https://uri.amap.com/marker?position=${lng},${lat}&name=${encodeURIComponent(name)}`; const url = `https://uri.amap.com/marker?position=${lng},${lat}&name=${encodeURIComponent(name)}`;
window.location.href = url; window.location.href = url;
} }
function expand() { function expand() {
isExpanded.value = !isExpanded.value; isExpanded.value = !isExpanded.value;
} }
// 取消/收藏岗位 // 取消/收藏岗位
function applyExhibitors() { function applyExhibitors() {
const fairId = fairInfo.value.jobFairId; const fairId = fairInfo.value.jobFairId;
if (fairInfo.value.isCollection) { if (fairInfo.value.isCollection) {
// $api.createRequest(`/app/fair/collection/${fairId}`, {}, 'DELETE').then((resData) => { // $api.createRequest(`/app/fair/collection/${fairId}`, {}, 'DELETE').then((resData) => {
@@ -162,14 +206,20 @@ function applyExhibitors() {
$api.msg('预约成功'); $api.msg('预约成功');
}); });
} }
} }
function parseDateTime(datetimeStr) { function parseDateTime(datetimeStr) {
if (!datetimeStr) return { time: '', date: '' }; if (!datetimeStr) return {
time: '',
date: ''
};
const dateObj = new Date(datetimeStr); const dateObj = new Date(datetimeStr);
if (isNaN(dateObj.getTime())) return { time: '', date: '' }; // 无效时间 if (isNaN(dateObj.getTime())) return {
time: '',
date: ''
}; // 无效时间
const year = dateObj.getFullYear(); const year = dateObj.getFullYear();
const month = String(dateObj.getMonth() + 1).padStart(2, '0'); const month = String(dateObj.getMonth() + 1).padStart(2, '0');
@@ -181,9 +231,9 @@ function parseDateTime(datetimeStr) {
time: `${hours}:${minutes}`, time: `${hours}:${minutes}`,
date: `${year}${month}${day}`, date: `${year}${month}${day}`,
}; };
} }
function getTimeStatus(startTimeStr, endTimeStr) { function getTimeStatus(startTimeStr, endTimeStr) {
const now = new Date(); const now = new Date();
const startTime = new Date(startTimeStr); const startTime = new Date(startTimeStr);
const endTime = new Date(endTimeStr); const endTime = new Date(endTimeStr);
@@ -205,9 +255,9 @@ function getTimeStatus(startTimeStr, endTimeStr) {
status, // 0: 进行中1: 已过期2: 待开始 status, // 0: 进行中1: 已过期2: 待开始
statusText, statusText,
}; };
} }
function getHoursBetween(startTimeStr, endTimeStr) { function getHoursBetween(startTimeStr, endTimeStr) {
const start = new Date(startTimeStr); const start = new Date(startTimeStr);
const end = new Date(endTimeStr); const end = new Date(endTimeStr);
@@ -215,103 +265,111 @@ function getHoursBetween(startTimeStr, endTimeStr) {
const diffHours = diffMs / (1000 * 60 * 60); const diffHours = diffMs / (1000 * 60 * 60);
return +diffHours.toFixed(2); // 保留 2 位小数 return +diffHours.toFixed(2); // 保留 2 位小数
} }
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.btnback{ .btnback {
width: 64rpx; width: 64rpx;
height: 64rpx; height: 64rpx;
} }
.btn {
.btn {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
width: 52rpx; width: 52rpx;
height: 52rpx; height: 52rpx;
} }
image {
image {
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.content{
height: 100% .content {
height: 100%;
display: flex; display: flex;
flex-direction: column flex-direction: column;
.content-top{ .content-top {
padding: 28rpx padding: 28rpx;
padding-top: 50rpx padding-top: 50rpx;
display: flex display: flex;
flex-direction: row flex-direction: row;
flex-wrap: nowrap flex-wrap: nowrap;
.companyinfo-left{ .companyinfo-left {
width: 96rpx; width: 96rpx;
height: 96rpx; height: 96rpx;
margin-right: 24rpx margin-right: 24rpx;
} }
.companyinfo-right{ .companyinfo-right {
flex: 1 flex: 1;
.row1{ .row1 {
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 32rpx;
color: #333333; color: #333333;
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif; font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
} }
.row2{ .row2 {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6C7282;
line-height: 45rpx; line-height: 45rpx;
display: flex display: flex;
justify-content: space-between justify-content: space-between;
} }
} }
} }
.locations{
padding: 0 28rpx .locations {
padding: 0 28rpx;
height: 86rpx; height: 86rpx;
position: relative
margin-bottom: 36rpx position: relative;
.location-img{ margin-bottom: 36rpx;
.location-img {
border-radius: 8rpx 8rpx 8rpx 8rpx; border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 2rpx solid #EFEFEF; border: 2rpx solid #EFEFEF;
} }
.location-info{
position: absolute
top: 0
left: 0
width: 100%
height: 100%
.info{ .location-info {
padding: 0 60rpx position: absolute;
height: 100%
display: flex top: 0;
align-items: center left: 0;
justify-content: space-between width: 100%;
white-space: nowrap height: 100%;
padding-top: rpx
.info-title{ .info {
padding: 0 60rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
white-space: nowrap;
.info-title {
font-weight: 600; font-weight: 600;
font-size: 28rpx; font-size: 28rpx;
color: #333333; color: #333333;
} }
.info-text{
.info-text {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #9B9B9B; color: #9B9B9B;
position: relative; position: relative;
padding-right: 20rpx padding-right: 20rpx
} }
.info-text::before{
.info-text::before {
position: absolute; position: absolute;
right: 0; right: 0;
top: 50%; top: 50%;
content: ''; content: '';
width: 4rpx; width: 4rpx;
height: 16rpx; height: 16rpx;
border-radius: 2rpx border-radius: 2rpx;
background: #9B9B9B; background: #9B9B9B;
transform: translate(0, -75%) rotate(-45deg) transform: translate(0, -75%) rotate(-45deg)
} }
@@ -323,7 +381,7 @@ image {
content: ''; content: '';
width: 4rpx; width: 4rpx;
height: 16rpx; height: 16rpx;
border-radius: 2rpx border-radius: 2rpx;
background: #9B9B9B; background: #9B9B9B;
transform: translate(0, -25%) rotate(45deg) transform: translate(0, -25%) rotate(45deg)
} }
@@ -331,117 +389,137 @@ image {
} }
} }
} }
.conetent-info{
padding: 0 28rpx .conetent-info {
padding: 0 28rpx;
overflow: hidden; overflow: hidden;
max-height: 0rpx; max-height: 0rpx;
transition: max-height 0.3s ease; transition: max-height 0.3s ease;
.info-title{
.info-title {
font-weight: 600; font-weight: 600;
font-size: 28rpx; font-size: 28rpx;
color: #000000; color: #000000;
} }
.info-desirption{
margin-top: 12rpx .info-desirption {
margin-top: 12rpx;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #495265; color: #495265;
text-align: justified; text-align: justify;
} }
.title2{
.title2 {
margin-top: 48rpx margin-top: 48rpx
} }
} }
.company-times{
padding-top: 40rpx .company-times {
.info-title{ padding-top: 40rpx;
.info-title {
font-weight: 600; font-weight: 600;
font-size: 28rpx; font-size: 28rpx;
color: #000000; color: #000000;
} }
} }
.expanded { .expanded {
max-height: 1000rpx; // 足够显示完整内容 max-height: 1000rpx; // 足够显示完整内容
} }
.expand{
display: flex .expand {
flex-wrap: nowrap display: flex;
white-space: nowrap flex-wrap: nowrap;
justify-content: center white-space: nowrap;
margin-bottom: 46rpx justify-content: center;
margin-bottom: 46rpx;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #256BFA; color: #256BFA;
.expand-img{
.expand-img {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
} }
.expand-img-active{
.expand-img-active {
transform: rotate(180deg) transform: rotate(180deg)
} }
} }
} }
.Detailscroll-view{
.Detailscroll-view {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
background: #F4F4F4; background: #F4F4F4;
.views{
padding: 28rpx .views {
.Detail-title{ padding: 28rpx;
.Detail-title {
font-weight: 600; font-weight: 600;
font-size: 32rpx; font-size: 32rpx;
color: #000000; color: #000000;
position: relative; position: relative;
display: flex
justify-content: space-between display: flex;
.title{ justify-content: space-between;
.title {
position: relative; position: relative;
z-index: 2; z-index: 2;
} }
} }
.Detail-title::before{
position: absolute .Detail-title::before {
position: absolute;
content: ''; content: '';
left: -14rpx left: -14rpx;
bottom: 0 bottom: 0;
height: 16rpx; height: 16rpx;
width: 108rpx; width: 108rpx;
background: linear-gradient(to right, #CBDEFF, #FFFFFF); background: linear-gradient(to right, #CBDEFF, #FFFFFF);
border-radius: 8rpx; border-radius: 8rpx;
z-index: 1; z-index: 1;
} }
.cards{
.cards {
padding: 32rpx; padding: 32rpx;
background: #FFFFFF; background: #FFFFFF;
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0,0,0,0.04); box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.04);
border-radius: 20rpx 20rpx 20rpx 20rpx; border-radius: 20rpx 20rpx 20rpx 20rpx;
margin-top: 22rpx; margin-top: 22rpx;
.card-company{
display: flex .card-company {
justify-content: space-between display: flex;
align-items: flex-start justify-content: space-between;
.company{ align-items: flex-start;
.company {
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 32rpx;
color: #333333; color: #333333;
} }
.salary{
.salary {
font-weight: 500; font-weight: 500;
font-size: 28rpx; font-size: 28rpx;
color: #4C6EFB; white-space: nowrap;
white-space: nowrap line-height: 48rpx;
line-height: 48rpx
} }
} }
.card-companyName{
.card-companyName {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6C7282;
} }
.card-tags{
display: flex .card-tags {
flex-wrap: wrap display: flex;
.tag{ flex-wrap: wrap;
.tag {
width: fit-content; width: fit-content;
height: 30rpx; height: 30rpx;
background: #F4F4F4; background: #F4F4F4;
@@ -453,63 +531,64 @@ image {
color: #6C7282; color: #6C7282;
text-align: center; text-align: center;
margin-top: 14rpx; margin-top: 14rpx;
white-space: nowrap white-space: nowrap;
margin-right: 20rpx margin-right: 20rpx;
} }
} }
.card-bottom{
margin-top: 32rpx .card-bottom {
display: flex margin-top: 32rpx;
justify-content: space-between display: flex;
justify-content: space-between;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6C7282;
} }
} }
} }
} }
.card-times{
.card-times {
display: flex; display: flex;
justify-content: space-between justify-content: space-between;
align-items: center align-items: center;
padding: 24rpx 30rpx 10rpx 30rpx padding: 24rpx 30rpx 10rpx 30rpx;
.time-left, .time-left,
.time-right{ .time-right {
text-align: center text-align: center;
.left-date{ .left-date {
font-weight: 500; font-weight: 500;
font-size: 48rpx; font-size: 48rpx;
color: #333333; color: #333333;
} }
.left-dateDay{ .left-dateDay {
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #333333; color: #333333;
margin-top: 12rpx margin-top: 12rpx;
} }
} }
.line{ .line {
width: 40rpx; width: 40rpx;
height: 0rpx; height: 0rpx;
border: 2rpx solid #D4D4D4; border: 2rpx solid #D4D4D4;
margin-top: 64rpx margin-top: 64rpx;
} }
.time-center{ .time-center {
text-align: center; text-align: center;
display: flex display: flex;
flex-direction: column flex-direction: column;
justify-content: center justify-content: center;
align-items: center align-items: center;
.center-date{ .center-date {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #FF881A; color: #FF881A;
padding-top: 10rpx
} }
.center-dateDay{ .center-dateDay {
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #333333; color: #333333;
margin-top: 6rpx margin-top: 6rpx;
line-height: 48rpx; line-height: 48rpx;
width: 104rpx; width: 104rpx;
height: 48rpx; height: 48rpx;
@@ -517,13 +596,16 @@ image {
border-radius: 8rpx 8rpx 8rpx 8rpx; border-radius: 8rpx 8rpx 8rpx 8rpx;
} }
} }
} }
.footer{
.footer {
background: #FFFFFF; background: #FFFFFF;
box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11,44,112,0.12); box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11, 44, 112, 0.12);
border-radius: 0rpx 0rpx 0rpx 0rpx; border-radius: 0rpx 0rpx 0rpx 0rpx;
padding: 40rpx 28rpx 20rpx 28rpx
.btn-wq{ padding: 40rpx 28rpx 20rpx 28rpx;
.btn-wq {
height: 90rpx; height: 90rpx;
background: #256BFA; background: #256BFA;
border-radius: 12rpx 12rpx 12rpx 12rpx; border-radius: 12rpx 12rpx 12rpx 12rpx;
@@ -533,9 +615,10 @@ image {
text-align: center; text-align: center;
line-height: 90rpx line-height: 90rpx
} }
.btn-desbel{
.btn-desbel {
background: #6697FB; background: #6697FB;
box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11,44,112,0.12); box-shadow: 0rpx -4rpx 24rpx 0rpx rgba(11, 44, 112, 0.12);
}
} }
}
</style> </style>

View File

@@ -1,11 +1,559 @@
<template> <template>
<view> <AppLayout title="" :use-scroll-view="false">
招聘会详情 <template #headerleft>
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view> </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?.name }}</view>
<view class="row2">
<text>{{ fairInfo.location }}</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.address }}</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.description }}</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.startTime).time }}</view>
<view class="left-dateDay">{{ parseDateTime(fairInfo.startTime).date }}</view>
</view>
<view class="line"></view>
<view class="time-center">
<view class="center-date">
{{ getTimeStatus(fairInfo.startTime, fairInfo.endTime).statusText }}
</view>
<view class="center-dateDay">
{{ getHoursBetween(fairInfo.startTime, fairInfo.endTime) }}小时
</view>
</view>
<view class="line"></view>
<view class="time-right">
<view class="left-date">{{ parseDateTime(fairInfo.endTime).time }}</view>
<view class="left-dateDay">{{ parseDateTime(fairInfo.endTime).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>
<renderCompanys
v-if="companyList.length"
:list="companyList"
:longitude="longitudeVal"
:latitude="latitudeVal"
></renderCompanys>
<empty v-else pdTop="200"></empty>
</view>
</scroll-view>
</view>
<template #footer>
<view class="footer" v-if="hasnext">
<view
class="btn-wq button-click"
:class="{ 'btn-desbel': fairInfo.isCollection }"
@click="applyExhibitors"
>
{{ fairInfo.isCollection ? '已预约招聘会' : '预约招聘会' }}
</view>
</view>
</template>
</AppLayout>
</template> </template>
<script> <script setup>
import point from '@/static/icon/point.png';
import { reactive, inject, watch, ref, onMounted, computed } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import dictLabel from '@/components/dict-Label/dict-Label.vue';
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);
onLoad((options) => {
getCompanyInfo(options.jobFairId);
});
function getCompanyInfo(id) {
$api.createRequest(`/app/fair/${id}`).then((resData) => {
fairInfo.value = resData.data;
companyList.value = resData.data.companyList;
hasAppointment();
});
}
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() {
const fairId = fairInfo.value.jobFairId;
if (fairInfo.value.isCollection) {
// $api.createRequest(`/app/fair/collection/${fairId}`, {}, 'DELETE').then((resData) => {
// getCompanyInfo(fairId);
// $api.msg('取消预约成功');
// });
$api.msg('已预约成功');
} else {
$api.createRequest(`/app/fair/collection/${fairId}`, {}, 'POST').then((resData) => {
getCompanyInfo(fairId);
$api.msg('预约成功');
});
}
}
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();
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';
}
}
const d = new Date(s);
return isNaN(d.getTime()) ? null : d;
}
function parseDateTime(datetimeStr) {
if (!datetimeStr) return { time: '', date: '' };
const dateObj = toIOSDate(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 = toIOSDate(startTimeStr);
const endTime = toIOSDate(endTimeStr);
if (!startTime || !endTime) {
return { status: 1, statusText: '时间异常' };
}
let status = 0;
let statusText = '开始中';
if (now < startTime) {
status = 2;
statusText = '待开始';
} else if (now > endTime) {
status = 1;
statusText = '已过期';
} else {
status = 0;
statusText = '进行中';
}
return { status, statusText };
}
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);
}
</script> </script>
<style> <style lang="stylus" scoped>
.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
padding-top: rpx
.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: justified;
}
.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: 500;
font-size: 32rpx;
color: #333333;
}
.salary{
font-weight: 500;
font-size: 28rpx;
color: #4C6EFB;
white-space: nowrap
line-height: 48rpx
}
}
.card-companyName{
font-weight: 400;
font-size: 28rpx;
color: #6C7282;
}
.card-tags{
display: flex
flex-wrap: wrap
.tag{
width: fit-content;
height: 30rpx;
background: #F4F4F4;
border-radius: 4rpx;
padding: 6rpx 20rpx;
line-height: 30rpx;
font-weight: 400;
font-size: 24rpx;
color: #6C7282;
text-align: center;
margin-top: 14rpx;
white-space: nowrap
margin-right: 20rpx
}
}
.card-bottom{
margin-top: 32rpx
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;
padding-top: 10rpx
}
.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> </style>

237
packageB/login.vue Normal file
View File

@@ -0,0 +1,237 @@
<template>
<AppLayout title="" :use-scroll-view="false">
<view class="wrap">
<view class="login_index">
<input class="input" placeholder="请输入账号" placeholder-class="inputplace" v-model="form.username" />
<view class="login_yzm">
<input class="input" type="password" placeholder="请输入密码" placeholder-class="inputplace"
v-model="form.password" />
</view>
<view class="login_yzm">
<input class="input" placeholder="请输入验证码" placeholder-class="inputplace" v-model="form.code" />
<image class="yzm" :src="codeUrl" @click="getCodeImg"></image>
</view>
<button class="com-btn" @click="register"> </button>
</view>
</view>
</AppLayout>
</template>
<script setup>
import {
reactive,
inject,
watch,
ref,
onMounted,
onUnmounted
} from 'vue'
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
const {
$api,
navTo,
vacanciesTo,
navBack
} = inject("globalFunction");
const placeholderStyle = 'font-size:30rpx'
const checked = ref(true)
const codeUrl = ref('')
const form = reactive({
username: 'langchaojituan',
password: 'Aa123456?',
rememberMe: false,
code: '',
uuid: ''
})
onLoad(() => {
})
onMounted(() => {
getCodeImg()
})
function register() {
if (!form.username) {
uni.showToast({
icon: 'none',
title: '请输入用户名'
})
return
}
if (!form.password) {
uni.showToast({
icon: 'none',
title: '请输入密码'
})
return
}
if (!form.uuid) {
uni.showToast({
icon: 'none',
title: '请输入验证码'
})
return
}
uni.showLoading({
title: '登录中...',
mask: true
})
$api.myRequest('/auth/login',form,'post',10100).then((res) => {
console.log(res, 'res')
uni.setStorageSync('Padmin-Token', res.data.access_token)
uni.reLaunch({
url: '/pages/index/index'
})
codeUrl.value = 'data:image/gif;base64,' + res.img
}).catch(() => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '登录失败,请重试'
})
})
}
function getCodeImg() {
$api.myRequest('/code',{},'get',10100).then((resData) => {
codeUrl.value = 'data:image/gif;base64,' + resData.img
form.uuid = resData.uuid
});
}
</script>
<style scoped lang="stylus">
.wrap {
background-color: #ffffff;
height: 100vh;
position: relative;
.lg-head {
height: 480rpx;
background: #46ca98;
position: relative;
.view_logo {
text-align: center;
.login_logo {
width: 300rpx;
height: 300rpx;
margin-top: 100rpx;
}
}
.bg-cover {
position: absolute;
bottom: -4rpx;
left: 0;
right: 0;
height: 30rpx;
background-size: 100% 100%;
z-index: 1;
}
}
}
.login_index {
font-size: 36rpx;
font-weight: 500;
width: 596rpx;
margin: 0 auto;
::v-deep .is-input-border {
border: 0;
border-bottom: 1px solid #dcdfe6 !important;
border-radius: 0;
}
::v-deep .uni-input-input {
font-size: 32rpx;
padding-left: 10rpx;
}
::v-deep .uniui-contact-filled:before {
color: #46ca98;
font-size: 50rpx;
}
::v-deep .uniui-locked-filled:before {
color: #46ca98;
font-size: 50rpx;
}
.login_yzm {
margin-top: 40rpx;
display: flex;
align-items: center;
.yzm {
width: 200rpx;
height: 80rpx;
}
}
.com-btn {
height: 100rpx;
background: #46ca98;
border-radius: 50rpx;
color: #fff;
margin-top: 100rpx;
}
.login_wt {
margin: 0 auto;
text-align: right;
font-size: 24rpx;
color: rgba(134, 134, 136, 1);
}
}
.lg-bottom {
position: absolute;
bottom: -3px;
left: 0;
width: 100%;
.bottom-svg {
position: absolute;
bottom: -3px;
left: 0;
width: 100%;
}
}
.login_tongyi {
font-size: 26rpx;
color: rgba(196, 196, 196, 1);
width: 620rpx;
margin: 32rpx auto;
text-align: center;
text {
color: rgba(86, 176, 236, 1);
}
}
.input {
padding: 0 30rpx 0 80rpx;
height: 80rpx;
background: #FFFFFF;
border-radius: 75rpx 75rpx 75rpx 75rpx;
font-size: 28rpx;
}
.inputplace {
font-weight: 400;
font-size: 28rpx;
color: #B5B5B5;
}
</style>

View File

@@ -212,9 +212,9 @@
"path": "pages/exhibitors/exhibitors", "path": "pages/exhibitors/exhibitors",
"style": { "style": {
"navigationBarTitleText": "参展单位", "navigationBarTitleText": "参展单位",
"navigationBarBackgroundColor": "#4778EC", "navigationBarBackgroundColor": "#FFFFFF",
"navigationBarTextStyle": "white", "navigationBarTextStyle": "black"
"navigationStyle": "custom" // "navigationStyle": "custom"
} }
}, { }, {
"path": "pages/myResume/myResume", "path": "pages/myResume/myResume",
@@ -357,6 +357,15 @@
"navigationBarTitleTextSize": "30rpx" "navigationBarTitleTextSize": "30rpx"
// "navigationStyle": "custom" // "navigationStyle": "custom"
} }
},
{
"path" : "login",
"style" :
{
"navigationBarTitleText" : "登录",
"navigationBarTitleTextSize": "30rpx"
// "navigationStyle": "custom"
}
}, },
{ {
"path" : "train/index", "path" : "train/index",

View File

@@ -4,18 +4,50 @@
<!-- 顶部头部区域 --> <!-- 顶部头部区域 -->
<view class="container-header"> <view class="container-header">
<view class="header-top"> <view class="header-top">
<view class="header-btnLf button-click" @click="seemsg(0)" :class="{ active: state.current === 0 }"> <view
现场招聘 class="header-btnLf button-click"
@click="seemsg(1)"
:class="{ active: state.current === 1 }"
>
线上招聘会
</view> </view>
<view class="header-btnLf button-click" @click="seemsg(1)" :class="{ active: state.current === 1 }"> <view
VR虚拟招聘会 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> </view>
<view class="header-input btn-feel"> <view class="header-input btn-feel">
<uni-icons class="iconsearch" color="#666666" type="search" size="18"></uni-icons> <uni-icons
<input class="input" placeholder="招聘会" placeholder-class="inputplace" /> 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="header-date"> <!-- <view class="header-date">
<view class="data-week"> <view class="data-week">
<view <view
class="weel-days button-click" class="weel-days button-click"
@@ -31,22 +63,31 @@
<view class="data-all"> <view class="data-all">
<image class="allimg button-click" @click="toSelectDate" src="/static/icon/date1.png"></image> <image class="allimg button-click" @click="toSelectDate" src="/static/icon/date1.png"></image>
</view> </view>
</view> </view> -->
</view> </view>
<!-- 主体内容区域 --> <!-- 主体内容区域 -->
<view class="container-main"> <view class="container-main">
<scroll-view scroll-y class="main-scroll" @scrolltolower="handleScrollToLower"> <scroll-view
scroll-y
class="main-scroll"
@scrolltolower="handleScrollToLower"
>
<view class="cards" v-if="fairList.length"> <view class="cards" v-if="fairList.length">
<view <view
class="card press-button" class="card press-button"
v-for="(item, index) in fairList" v-for="(item, index) in fairList"
:key="index" :key="index"
@click="navTo('/packageA/pages/exhibitors/exhibitors?jobFairId=' + item.jobFairId)" @click="
navTo(
'/packageA/pages/exhibitors/exhibitors?jobFairId=' +
item.jobFairId
)
"
> >
<view class="card-title">{{ item.name }}</view> <view class="card-title">{{ item.jobFairTitle }}</view>
<view class="card-row"> <view class="card-row">
<text class="">{{ item.location }}</text> <text class="">{{ item.jobFairAddress }}</text>
<text class=""> <text class="">
<convert-distance <convert-distance
:alat="item.latitude" :alat="item.latitude"
@@ -58,26 +99,44 @@
</view> </view>
<view class="card-times"> <view class="card-times">
<view class="time-left"> <view class="time-left">
<view class="left-date">{{ parseDateTime(item.startTime).time }}</view> <view class="left-date">{{
<view class="left-dateDay">{{ parseDateTime(item.startTime).date }}</view> parseDateTime(item.jobFairStartTime).time
}}</view>
<view class="left-dateDay">{{
parseDateTime(item.jobFairStartTime).date
}}</view>
</view> </view>
<view class="line"></view> <view class="line"></view>
<view class="time-center"> <view class="time-center">
<view class="center-date"> <view class="center-date">
{{ getTimeStatus(item.startTime, item.endTime).statusText }} {{
getTimeStatus(item.jobFairStartTime, item.jobFairEndTime)
.statusText
}}
</view> </view>
<view class="center-dateDay"> <view class="center-dateDay">
{{ getHoursBetween(item.startTime, item.endTime) }}小时 {{
getHoursBetween(
item.jobFairStartTime,
item.jobFairEndTime
)
}}小时
</view> </view>
</view> </view>
<view class="line"></view> <view class="line"></view>
<view class="time-right"> <view class="time-right">
<view class="left-date">{{ parseDateTime(item.endTime).time }}</view> <view class="left-date">{{
<view class="left-dateDay">{{ parseDateTime(item.endTime).date }}</view> parseDateTime(item.jobFairEndTime).time
}}</view>
<view class="left-dateDay">{{
parseDateTime(item.jobFairEndTime).date
}}</view>
</view> </view>
</view> </view>
<view class="recommend-card-line"></view> <view class="recommend-card-line"></view>
<view class="card-footer">内容简介{{ item.description }}</view> <view class="card-footer"
>内容简介{{ item.jobFairIntroduction || "暂无" }}</view
>
</view> </view>
</view> </view>
<empty v-else pdTop="200"></empty> <empty v-else pdTop="200"></empty>
@@ -87,48 +146,53 @@
<CustomTabBar :currentPage="1" /> <CustomTabBar :currentPage="1" />
<!-- 微信授权登录弹窗 --> <!-- 微信授权登录弹窗 -->
<WxAuthLogin ref="wxAuthLoginRef" @success="handleLoginSuccess"></WxAuthLogin> <WxAuthLogin
ref="wxAuthLoginRef"
@success="handleLoginSuccess"
></WxAuthLogin>
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import { reactive, inject, watch, ref, onMounted, onUnmounted } from 'vue'; import { reactive, inject, watch, ref, onMounted, onUnmounted } from "vue";
import { onLoad, onShow } from '@dcloudio/uni-app'; import { onLoad, onShow } from "@dcloudio/uni-app";
import useLocationStore from '@/stores/useLocationStore'; import useLocationStore from "@/stores/useLocationStore";
import { storeToRefs } from 'pinia'; import { storeToRefs } from "pinia";
import { tabbarManager } from '@/utils/tabbarManager'; import { tabbarManager } from "@/utils/tabbarManager";
import WxAuthLogin from '@/components/WxAuthLogin/WxAuthLogin.vue'; import WxAuthLogin from "@/components/WxAuthLogin/WxAuthLogin.vue";
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore()); const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const wxAuthLoginRef = ref(null); const wxAuthLoginRef = ref(null);
const { $api, navTo, cloneDeep } = inject('globalFunction'); const { $api, navTo, cloneDeep } = inject("globalFunction");
const isLogin = ref(false);
const weekList = ref([]); const weekList = ref([]);
const fairList = ref([]); const fairList = ref([]);
const currentDay = ref({}); const currentDay = ref({});
const userInfo = ref({});
const state = reactive({ const state = reactive({
current: 0, current: 1,
all: [{}], all: [{}],
}); });
const pageState = reactive({ const pageState = reactive({
page: 0, pageNum: 0,
total: 0, total: 0,
maxPage: 2, maxPage: 2,
pageSize: 10, pageSize: 10,
search: {}, jobFairTitle: "",
}); });
onLoad(() => { onLoad(() => {
const today = new Date(); // const today = new Date();
const year = today.getFullYear(); // const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0'); // const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0'); // const day = String(today.getDate()).padStart(2, '0');
const currentDate = `${year}-${month}-${day}`; // const currentDate = `${year}-${month}-${day}`;
const result = getNextDates({ // const result = getNextDates({
startDate: currentDate, // startDate: currentDate,
}); // });
weekList.value = result; // weekList.value = result;
getFair('refresh'); getHeart();
}); });
onShow(() => { onShow(() => {
@@ -138,40 +202,39 @@ onShow(() => {
onMounted(() => { onMounted(() => {
// 监听退出登录事件,显示微信登录弹窗 // 监听退出登录事件,显示微信登录弹窗
uni.$on('showLoginModal', () => { uni.$on("showLoginModal", () => {
wxAuthLoginRef.value?.open(); wxAuthLoginRef.value?.open();
}); });
}); });
onUnmounted(() => { onUnmounted(() => {
uni.$off('showLoginModal'); uni.$off("showLoginModal");
}); });
// 登录成功回调 // 登录成功回调
const handleLoginSuccess = () => { const handleLoginSuccess = () => {
console.log('登录成功'); console.log("登录成功");
// 可以在这里添加登录成功后的处理逻辑 // 可以在这里添加登录成功后的处理逻辑
}; };
function toSelectDate() { function toSelectDate() {
navTo('/packageA/pages/selectDate/selectDate', { navTo("/packageA/pages/selectDate/selectDate", {
query: { query: {
date: currentDay.value.fullDate, date: currentDay.value.fullDate,
}, },
onBack: (res) => { onBack: (res) => {
console.log(res);
const result = getNextDates({ const result = getNextDates({
startDate: res.date, startDate: res.date,
}); });
const formattedDate = res.date.slice(5); // MM-DD const formattedDate = res.date.slice(5); // MM-DD
const dateFull = { const dateFull = {
date: res.date.slice(5), date: res.date.slice(5),
day: '周' + res.week, day: "周" + res.week,
fullDate: res.date, fullDate: res.date,
}; };
currentDay.value = dateFull; currentDay.value = dateFull;
weekList.value = result; weekList.value = result;
getFair('refresh'); getFair("refresh");
}, },
}); });
} }
@@ -182,56 +245,178 @@ function changeSwiperMsgType(e) {
} }
function seemsg(index) { function seemsg(index) {
if (index === 1) {
return $api.msg('功能确定中');
}
state.current = index; state.current = index;
console.log(index, '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 = () => { const handleScrollToLower = () => {
if (pageState.pageNum >= pageState.maxPage) {
return;
} else {
if (state.current != 3) {
getFair(); getFair();
console.log('触底'); } else {
this.$nextTick(() => {
getMyFair();
})
}
}
}; };
function getFair(type = 'add') { function getHeart() {
if (type === 'refresh') { const raw = uni.getStorageSync("Padmin-Token");
pageState.page = 1; 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;
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; pageState.maxPage = 1;
} }
if (type === 'add' && pageState.page < pageState.maxPage) { if (type === "add" && pageState.pageNum < pageState.maxPage) {
pageState.page += 1; pageState.pageNum += 1;
} }
let params = { let params = {
...pageState.search, pageNum: pageState.pageNum,
current: pageState.page,
pageSize: pageState.pageSize, pageSize: pageState.pageSize,
jobFairTitle: pageState.jobFairTitle,
}; };
if (currentDay.value?.fullDate) { if (isLogin.value) {
params.queryDate = currentDay.value.fullDate; if (userInfo.value.userType == "ent") {
} params.enterpriseId = userInfo.value.info.userId;
$api.createRequest('/app/fair', params).then((resData) => {
const { rows, total } = resData;
console.log(rows);
if (type === 'add') {
const str = pageState.pageSize * (pageState.page - 1);
const end = fairList.value.length;
const reslist = rows;
fairList.value.splice(str, end, ...reslist);
} else { } else {
fairList.value = rows; params.personId = userInfo.value.info.userId;
} }
// pageState.list = resData.rows; }
pageState.total = resData.total; $api.myRequest("/jobfair/public/jobfair/enterprise/my-sign-up-job-fair", params).then((resData) => {
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize); 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 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) { function parseDateTime(datetimeStr) {
if (!datetimeStr) return { time: '', date: '' }; if (!datetimeStr)
return {
time: '',
date: '',
};
const dateObj = new Date(datetimeStr); const dateObj = toIOSDate(datetimeStr);
if (isNaN(dateObj.getTime())) return { time: '', date: '' }; // 无效时间 if (!dateObj)
return {
time: '',
date: '',
}; // 无效时间
const year = dateObj.getFullYear(); const year = dateObj.getFullYear();
const month = String(dateObj.getMonth() + 1).padStart(2, '0'); const month = String(dateObj.getMonth() + 1).padStart(2, '0');
@@ -247,8 +432,12 @@ function parseDateTime(datetimeStr) {
function getTimeStatus(startTimeStr, endTimeStr) { function getTimeStatus(startTimeStr, endTimeStr) {
const now = new Date(); const now = new Date();
const startTime = new Date(startTimeStr); const startTime = toIOSDate(startTimeStr);
const endTime = new Date(endTimeStr); const endTime = toIOSDate(endTimeStr);
if (!startTime || !endTime) {
return { status: 1, statusText: '时间异常' };
}
// 判断状态0 开始中1 过期2 待开始 // 判断状态0 开始中1 过期2 待开始
let status = 0; let status = 0;
@@ -270,8 +459,10 @@ function getTimeStatus(startTimeStr, endTimeStr) {
} }
function getHoursBetween(startTimeStr, endTimeStr) { function getHoursBetween(startTimeStr, endTimeStr) {
const start = new Date(startTimeStr); const start = toIOSDate(startTimeStr);
const end = new Date(endTimeStr); const end = toIOSDate(endTimeStr);
if (!start || !end) return 0;
const diffMs = end - start; const diffMs = end - start;
const diffHours = diffMs / (1000 * 60 * 60); const diffHours = diffMs / (1000 * 60 * 60);
@@ -282,17 +473,17 @@ function getHoursBetween(startTimeStr, endTimeStr) {
const selectDate = (item) => { const selectDate = (item) => {
if (currentDay.value?.fullDate === item.fullDate) { if (currentDay.value?.fullDate === item.fullDate) {
currentDay.value = {}; currentDay.value = {};
getFair('refresh'); getFair("refresh");
return; return;
} }
currentDay.value = item; currentDay.value = item;
getFair('refresh'); getFair("refresh");
}; };
function getNextDates({ startDate = '', count = 6 }) { function getNextDates({ startDate = "", count = 6 }) {
const baseDate = startDate ? new Date(startDate) : new Date(); // 指定起点或今天 const baseDate = startDate ? (toIOSDate(startDate) || new Date()) : new Date(); // 指定起点或今天
const dates = []; const dates = [];
const dayNames = ['日', '一', '二', '三', '四', '五', '六']; const dayNames = ["日", "一", "二", "三", "四", "五", "六"];
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const date = new Date(baseDate); const date = new Date(baseDate);
@@ -305,7 +496,7 @@ function getNextDates({ startDate = '', count = 6 }) {
dates.push({ dates.push({
date: formattedDate, date: formattedDate,
fullDate, fullDate,
day: '周' + dayOfWeek, day: "周" + dayOfWeek,
}); });
} }
@@ -316,7 +507,7 @@ function getNextDates({ startDate = '', count = 6 }) {
} }
</script> </script>
<style lang="stylus" scoped> <style scoped>
.app-custom-root { .app-custom-root {
position: fixed; position: fixed;
z-index: 10; z-index: 10;
@@ -324,22 +515,28 @@ function getNextDates({ startDate = '', count = 6 }) {
height: calc(100% - var(--window-bottom)); height: calc(100% - var(--window-bottom));
overflow: hidden; overflow: hidden;
} }
.app-container { .app-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
width: 100%; width: 100%;
.container-header { }
background: url('@/static/icon/background2.png') 0 0 no-repeat;
.app-container .container-header {
background: url("@/static/icon/background2.png") 0 0 no-repeat;
background-size: 100% 400rpx; background-size: 100% 400rpx;
.header-top{ }
.app-container .container-header .header-top {
display: flex; display: flex;
line-height: calc(88rpx - 14rpx); line-height: calc(88rpx - 14rpx);
padding: 16rpx 44rpx 14rpx 44rpx; padding: 16rpx 44rpx 14rpx 44rpx;
.header-btnLf { }
.app-container .container-header .header-top .header-btnLf {
display: flex; display: flex;
width: fit-content; white-space: nowrap;
white-space: nowrap
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
width: calc(60rpx * 3); width: calc(60rpx * 3);
@@ -348,92 +545,100 @@ function getNextDates({ startDate = '', count = 6 }) {
color: #696969; color: #696969;
margin-right: 44rpx; margin-right: 44rpx;
position: relative; position: relative;
.btns-wd{ }
position: absolute
.app-container .container-header .header-top .header-btnLf .btns-wd {
position: absolute;
top: 2rpx; top: 2rpx;
right: 2rpx right: 2rpx;
width: 16rpx; width: 16rpx;
height: 16rpx; height: 16rpx;
background: #F73636; background: #f73636;
border-radius: 50%; border-radius: 50%;
border: 4rpx solid #EEEEFF; border: 4rpx solid #eeeeff;
} }
}
.active { .app-container .container-header .header-top .active {
font-weight: 600; font-weight: 600;
font-size: 40rpx; font-size: 40rpx;
color: #000000; color: #000000;
} }
}
.header-input{ .app-container .container-header .header-input {
padding: 0 24rpx padding: 0 24rpx;
width: calc(100% - 48rpx); width: calc(100% - 48rpx);
position: relative position: relative;
.iconsearch{ }
position: absolute
.app-container .container-header .header-input .iconsearch {
position: absolute;
left: 50rpx; left: 50rpx;
top: 50% top: 50%;
transform: translate(0, -50%) transform: translate(0, -50%);
} }
.input{
padding: 0 30rpx 0 80rpx .app-container .container-header .header-input .input {
padding: 0 30rpx 0 80rpx;
height: 80rpx; height: 80rpx;
background: #FFFFFF; background: #ffffff;
border-radius: 75rpx 75rpx 75rpx 75rpx; border-radius: 75rpx;
font-size: 28rpx; font-size: 28rpx;
} }
.inputplace{
.app-container .container-header .header-input .inputplace {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #B5B5B5; color: #b5b5b5;
} }
} .app-container .container-header .header-date {
.header-date{ padding: 28rpx;
padding: 28rpx display: flex;
display: flex justify-content: space-between;
justify-content: space-between align-items: center;
align-items: center }
.data-week{
flex: 1 .app-container .container-header .header-date .data-week {
display: flex flex: 1;
justify-content: space-between display: flex;
flex-wrap: nowrap justify-content: space-between;
overflow: hidden flex-wrap: nowrap;
.weel-days{ overflow: hidden;
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif; }
display: flex
justify-content: center .app-container .container-header .header-date .data-week .weel-days {
flex-direction: column font-family: "PingFangSC-Medium", "PingFang SC", "Helvetica Neue", Helvetica,
text-align: center Arial, "Microsoft YaHei", sans-serif;
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #333333; color: #333333;
width: 96rpx; width: 96rpx;
height: 88rpx; height: 88rpx;
}
.label{} .app-container .container-header .header-date .data-week .weel-days .day {
.day{
font-weight: 500; font-weight: 500;
} }
}
.active{ .app-container .container-header .header-date .data-week .active {
background: rgba(37,107,250,0.1); background: rgba(37, 107, 250, 0.1);
border-radius: 12rpx 12rpx 12rpx 12rpx; border-radius: 12rpx;
color: #256BFA; color: #256bfa;
} }
}
.data-all{ .app-container .container-header .header-date .data-all {
width: 66rpx; width: 66rpx;
height: 66rpx; height: 66rpx;
margin-left: 18rpx margin-left: 18rpx;
.allimg{ }
.app-container .container-header .header-date .data-all .allimg {
width: 100%; width: 100%;
height: 100% height: 100%;
}
}
}
}
} }
.container-main { .container-main {
@@ -441,127 +646,144 @@ function getNextDates({ startDate = '', count = 6 }) {
overflow: hidden; overflow: hidden;
background-color: #f4f4f4; background-color: #f4f4f4;
} }
.main-scroll { .main-scroll {
width: 100% width: 100%;
height: 100%; height: calc(100% - 150rpx);
} }
.cards{
padding: 28rpx 28rpx 28rpx 28rpx; .cards {
.card{ padding: 28rpx;
margin-top: 28rpx }
.cards .card {
margin-top: 28rpx;
padding: 32rpx; padding: 32rpx;
background: #FFFFFF background: #ffffff;
background: #FFFFFF; box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0, 0, 0, 0.04);
box-shadow: 0rpx 0rpx 8rpx 0rpx rgba(0,0,0,0.04); border-radius: 20rpx;
border-radius: 20rpx 20rpx 20rpx 20rpx; }
.card-title{
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif; .cards .card-title {
font-family: "PingFangSC-Medium", "PingFang SC", "Helvetica Neue", Helvetica,
Arial, "Microsoft YaHei", sans-serif;
font-weight: 500; font-weight: 500;
font-size: 32rpx; font-size: 32rpx;
color: #333333; color: #333333;
} }
.card-row{
display: flex .cards .card-row {
justify-content: space-between display: flex;
justify-content: space-between;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #495265; color: #495265;
margin-top: 4rpx margin-top: 4rpx;
} }
.card-times{
.cards .card-times {
display: flex; display: flex;
justify-content: space-between justify-content: space-between;
align-items: center align-items: center;
margin-top: 24rpx margin-top: 24rpx;
.time-left, }
.time-right{
text-align: center .cards .card-times .time-left,
.left-date{ .cards .card-times .time-right {
text-align: center;
}
.cards .card-times .left-date {
font-weight: 500; font-weight: 500;
font-size: 48rpx; font-size: 48rpx;
color: #333333; color: #333333;
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif; font-family: "PingFangSC-Medium", "PingFang SC", "Helvetica Neue", Helvetica,
} Arial, "Microsoft YaHei", sans-serif;
.left-dateDay{ }
.cards .card-times .left-dateDay {
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #333333; color: #333333;
margin-top: 12rpx margin-top: 12rpx;
} }
}
.line{ .cards .card-times .line {
width: 40rpx; width: 40rpx;
height: 0rpx; height: 0;
border: 2rpx solid #D4D4D4; border: 2rpx solid #d4d4d4;
margin-top: 64rpx margin-top: 64rpx;
} }
.time-center{
.cards .card-times .time-center {
text-align: center; text-align: center;
display: flex display: flex;
flex-direction: column flex-direction: column;
justify-content: center justify-content: center;
align-items: center align-items: center;
.center-date{ }
.cards .card-times .time-center .center-date {
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #FF881A; color: #ff881a;
padding-top: 10rpx padding-top: 10rpx;
} }
.center-dateDay{
.cards .card-times .time-center .center-dateDay {
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #333333; color: #333333;
margin-top: 6rpx margin-top: 6rpx;
line-height: 48rpx; line-height: 48rpx;
width: 104rpx; width: 104rpx;
height: 48rpx; height: 48rpx;
background: #F9F9F9; background: #f9f9f9;
border-radius: 8rpx 8rpx 8rpx 8rpx; border-radius: 8rpx;
} }
}
}
.recommend-card-line{
width: calc(100%);
height: 0rpx;
border-radius: 0rpx 0rpx 0rpx 0rpx;
border: 2rpx dashed rgba(0,0,0,0.14);
margin-top: 32rpx
position: relative
}
.recommend-card-line::before{ .cards .recommend-card-line {
position: absolute width: 100%;
content: '' height: 0;
left: 0 border-radius: 0;
top: 0 border: 2rpx dashed rgba(0, 0, 0, 0.14);
transform: translate(-50% - 110rpx, -50%) margin-top: 32rpx;
position: relative;
}
.cards .recommend-card-line::before {
content: "";
position: absolute;
left: 0;
top: 0;
transform: translate(-50%, -50%);
width: 28rpx; width: 28rpx;
height: 28rpx; height: 28rpx;
background: #F4F4F4; background: #f4f4f4;
border-radius: 50%; border-radius: 50%;
} }
.recommend-card-line::after{ .cards .recommend-card-line::after {
position: absolute content: "";
content: '' position: absolute;
right: 0 right: 0;
top: 0 top: 0;
transform: translate(50% + 100rpx, -50%) transform: translate(50%, -50%);
width: 28rpx; width: 28rpx;
height: 28rpx; height: 28rpx;
background: #F4F4F4; background: #f4f4f4;
border-radius: 50%; border-radius: 50%;
} }
.card-footer{
margin-top: 32rpx .cards .card-footer {
margin-top: 32rpx;
min-height: 50rpx; min-height: 50rpx;
font-weight: 400; font-weight: 400;
font-size: 28rpx; font-size: 28rpx;
color: #6C7282; color: #6c7282;
} }
}
.card:first-child{ .cards .card:first-child {
margin-top: 0 margin-top: 0;
}
} }
</style> </style>

View File

@@ -173,3 +173,73 @@ export function uploadFile(tempFilePaths, loading = false) {
}) })
}) })
} }
export function myRequest(url, data = {}, method = 'GET', port = 9100, headers = {}, loading = false) {
let LCBaseUrl = config.LCBaseUrl
if (port != 9100) {
LCBaseUrl = config.LCBaseUrlInner
}
const header = headers || {};
// 上下文
// /jobfair-api/jobfair/public 招聘会
// /dashboard-api/dashboard 用户登录相关
// /dashboard-api 获取验证码、登录
if (loading) {
uni.showLoading({
title: '请稍后',
mask: true
})
}
return new Promise((resolve, reject) => {
uni.request({
url: LCBaseUrl + url,
method: method,
data: data,
header,
success: resData => {
if(url=='/dashboard/auth/heart'){
resolve(resData.data)
return
}else{
// 响应拦截
if (resData.statusCode === 200) {
const {
code,
msg
} = resData.data
if (code === 200) {
resolve(resData.data)
return
}
// 处理业务错误
if (resData.data?.code === 401 || resData.data?.code === 402) {
useUserStore().logOut()
}
// 显示具体的错误信息
const errorMsg = msg || '请求出现异常,请联系工作人员'
uni.showToast({
title: errorMsg,
icon: 'none'
})
const err = new Error(errorMsg)
err.error = resData
reject(err)
return
}
// HTTP状态码不是200的情况
const err = new Error('网络请求失败,请检查网络连接')
err.error = resData
reject(err)
}
},
fail: (err) => {
reject(err)
},
complete: () => {
if (loading) {
uni.hideLoading();
}
}
})
})
}