This commit is contained in:
2025-11-05 21:16:09 +08:00
12 changed files with 3842 additions and 1882 deletions

View File

@@ -0,0 +1,639 @@
<template>
<view class="job-dialog">
<view class="header-title">
<image :src="`${imgBaseUrl}/jobfair/xb.png`" mode=""></image>
<text>招聘会报名</text>
</view>
<view class="dialog-content">
<view class="detail-item" v-if="type == 2">
<view class="gw-label">选择展区展位</view>
<!-- 展位状态说明 -->
<view class="status-description">
<view class="status-title">
<text>展位状态说明</text>
</view>
<view class="status-item">
<view class="status-color available"></view>
<text class="status-text">未被占用</text>
</view>
<view class="status-item">
<view class="status-color occupied"></view>
<text class="status-text">已被占用</text>
</view>
<view class="status-item">
<view class="status-color pending"></view>
<text class="status-text">待审核占用</text>
</view>
<view class="status-item">
<view class="status-color selected"></view>
<text class="status-text">当前选中</text>
</view>
</view>
<view class="gw-value">
<view class="cd-detail" v-for="(item, index) in areaAndBoothList" :key="index">
<view class="cd-name">{{ item.jobFairAreaName }}</view>
<view class="cd-con">
<view class="cd-con-item" :class="getBoothStatusClass(booth)"
v-for="(booth, boothIndex) in item.boothList" :key="boothIndex"
@click="selectBooth(booth, item.jobFairAreaId)">
<text>{{ booth.jobFairBoothName }}</text>
</view>
</view>
</view>
</view>
</view>
<view class="detail-item">
<view class="gw-label">请选择招聘岗位</view>
<view class="gw-value">
<view class="checkbox-group">
<view class="checkbox-item job-item" v-for="(item, index) in jobList" :key="index"
:class="{ 'checked': checkList.includes(item) }" @click="toggleJobSelection(item)">
<view class="item-checkbox">
<view class="checkbox-icon" :class="{ 'checked': checkList.includes(item) }">
<text v-if="checkList.includes(item)"></text>
</view>
<view class="job-info">
<view class="job-name">{{ item.jobTitle }}</view>
<view class="salary">{{ item.salaryRange }}/</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="detail-item">
<view class="gw-label">请上传招聘海报</view>
<view class="gw-value">
<view v-if="imageUrl">
<image v-if="imageUrl" :src="publicUrl + '/file/file/minio' + imageUrl" class="avatar"
mode="aspectFit" />
<button type="warn" class="del-icon" @click="imageUrl = ''" size="mini">删除</button>
</view>
<view v-else>
<button @click="chooseImage" class="avatar-uploader transparent-btn" type="default">
<view class="avatar-uploader-icon">+</view>
</button>
</view>
</view>
</view>
</view>
<view class="btn-box">
<button style="background: #409EFF;color: #fff;" @click="submitForm">提交</button>
<button type="default" @click="closeDialog">取消</button>
</view>
</view>
</template>
<script setup>
import config from "@/config.js"
import {
ref,
reactive,
onMounted,
nextTick,
watch,
inject
} from 'vue';
const emit = defineEmits(['closePopup']);
import {
createRequest
} from '@/utils/request.js';
const {
$api
} = inject('globalFunction');
// 定义props
const props = defineProps({
// 招聘会类型1线上 2线下
signType: {
type: Number,
default: 1
},
// 报名角色 ent企业 person个人
signRole: {
type: String,
default: 'ent'
},
// 招聘会id
jobFairId: {
type: String,
default: ''
}
});
// 监听props变化
watch(() => props.signType, (newVal) => {
type.value = newVal;
});
// 响应式数据
const checkList = ref([]);
const imageUrl = ref('');
const type = ref('');
const id = ref('');
const jobList = ref([]);
const userId = ref('');
const areaAndBoothList = ref([]);
const jobFairAreaId = ref(null);
const jobFairBoothId = ref(null);
const avatarUploader = ref(null);
// 配置
const publicUrl = config.LCBaseUrl;
const imgBaseUrl = config.imgBaseUrl
const uploadUrl = config.LCBaseUrl + "/file/file/upload";
// 方法
const selectBooth = (booth, jobFairAreaIdVal) => {
if (booth.status == 0) {
jobFairBoothId.value = booth.jobFairBoothId;
jobFairAreaId.value = jobFairAreaIdVal;
}
};
const submitForm = async () => {
if (type.value == "2") {
if (!jobFairBoothId.value || !jobFairAreaId.value) {
uni.showToast({
title: '请选择展区展位',
icon: 'none'
});
return;
}
}
if (checkList.value.length === 0) {
uni.showToast({
title: '请选择招聘岗位',
icon: 'none'
});
return;
}
if (!imageUrl.value) {
uni.showToast({
title: '请上传招聘海报',
icon: 'none'
});
return;
}
$api.myRequest("/system/user/login/user/info", {}, "GET", 10100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((userInfo) => {
let data = {}
if (type.value == "2") {
data = {
jobFairId: id.value,
enterpriseId: userInfo.info.userId,
jobInfoList: checkList.value,
poster: imageUrl.value,
jobFairAreaId: jobFairAreaId.value,
jobFairBoothId: jobFairBoothId.value,
code: userInfo.info.entCreditCode
};
} else {
data = {
jobFairId: id.value,
enterpriseId: userInfo.info.userId,
jobInfoList: checkList.value,
poster: imageUrl.value,
code: userInfo.info.entCreditCode
};
}
$api.myRequest("/jobfair/public/job-fair-sign-up-enterprise/sign-up", data, "post", 9100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((res) => {
if (res.code === 200) {
uni.showToast({
title: '报名成功',
icon: 'success'
});
closeDialog();
} else {
uni.showToast({
title: res.msg || '报名失败',
icon: 'none'
});
}
});
})
};
const closeDialog = () => {
checkList.value = [];
imageUrl.value = '';
jobFairBoothId.value = null;
jobFairAreaId.value = null;
emit('closePopup')
};
const handleAvatarSuccess = (response) => {
imageUrl.value = response.data.url;
uni.showToast({
title: '海报上传成功',
icon: 'success'
});
};
const showDialog = (dialogType, dialogId) => {
type.value = dialogType;
id.value = dialogId;
nextTick(() => {
getJobList();
if (type.value === "2") {
getAreaAndBoothInfo();
}
});
};
// 展区展位列表
const getAreaAndBoothInfo = () => {
const data = {
jobFairId: props.jobFairId,
}
$api.myRequest("/jobfair/public/jobfair/area-and-booth-info-by-job-fair-id", data, "GET", 9100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((resData) => {
areaAndBoothList.value = resData.data || [];
});
};
// 岗位列表
const getJobList = () => {
$api.myRequest("/system/user/login/user/info", {}, "GET", 10100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((userInfo) => {
const data = {
jobFairId: id.value,
enterpriseId: userInfo.info.userId,
pageNum: 1,
pageSize: 1000,
code: userInfo.info.entCreditCode
}
$api.myRequest("/jobfair/public/job-info/list", data, "GET", 9100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((resData) => {
jobList.value = resData.data.list || [];
});
});
};
const getBoothStatusClass = (booth) => {
const s = booth.status || 0;
if (s == 1) return "cd-con-item-checked";
if (s == 2) return "cd-con-item-review";
if (jobFairBoothId.value && jobFairBoothId.value == booth.jobFairBoothId)
return "cd-con-item-mychecked";
return "";
};
// 选择图片
const chooseImage = () => {
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePath = res.tempFilePaths[0];
uploadImage(tempFilePath);
}
});
};
// 上传图片
const uploadImage = (tempFilePath) => {
uni.uploadFile({
url: uploadUrl,
filePath: tempFilePath,
name: 'file',
success: (uploadFileRes) => {
try {
const response = JSON.parse(uploadFileRes.data);
handleAvatarSuccess(response);
} catch (e) {
uni.showToast({
title: '上传失败,请重试',
icon: 'none'
});
}
},
fail: (err) => {
console.error('上传失败:', err);
uni.showToast({
title: '上传失败,请重试',
icon: 'none'
});
}
});
};
// 切换岗位选择
const toggleJobSelection = (item) => {
const index = checkList.value.indexOf(item);
if (index > -1) {
checkList.value.splice(index, 1);
} else {
checkList.value.push(item);
}
};
// 暴露方法给父组件
defineExpose({
showDialog
});
onMounted(() => {
setTimeout(() => {
type.value = props.signType;
if (props.jobFairId) {
id.value = props.jobFairId;
getJobList();
if (props.signType == 2) {
getAreaAndBoothInfo();
}
}
}, 100);
});
// 监听jobFairId变化
watch(() => props.jobFairId, (newVal) => {
if (newVal) {
id.value = newVal;
getJobList();
if (type.value === 2) {
getAreaAndBoothInfo();
}
}
});
</script>
<style lang="scss" scoped>
.del-icon {
margin-left: 30rpx;
}
.btn-box {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-top: 30rpx;
}
.btn-box button {
padding: 0 80rpx;
height: 80rpx;
line-height: 80rpx;
}
.avatar-uploader {
border: 2rpx solid #0983ff;
border-radius: 12rpx;
cursor: pointer;
position: relative;
overflow: hidden;
width: 400rpx;
height: 200rpx;
}
.avatar-uploader-icon {
font-size: 56rpx;
color: #007AFF;
line-height: 200rpx;
text-align: center;
}
.job-dialog {
width: 100%;
height: 100%;
}
.dialog-content {
padding: 0 20rpx;
height: calc(100% - 17vh);
overflow-y: auto;
box-sizing: border-box;
}
.checkbox-group {
width: 100%;
}
.checkbox-item {
display: flex;
align-items: center;
border-bottom: 2rpx solid #b5d3ff;
padding: 30rpx 0;
}
.job-item {
width: 97%;
}
.checkbox-icon {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #ddd;
border-radius: 8rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.checkbox-icon.checked {
background-color: #409eff;
border-color: #409eff;
color: white;
}
.job-info {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
}
.detail-item {
margin-bottom: 40rpx;
}
.detail-item .gw-label {
font-size: 32rpx;
color: #333333;
margin-bottom: 20rpx;
}
.detail-item .gw-value {
display: flex;
flex-wrap: wrap;
overflow-y: auto;
}
.detail-item .gw-value .cd-detail {
width: 100%;
background: #fff;
border-radius: 20rpx;
margin-bottom: 28rpx;
margin-top: 28rpx;
}
.detail-item .gw-value .cd-detail .cd-name {
background: #d3e8ff;
color: #0076d9;
font-size: 40rpx;
height: 80rpx;
line-height: 80rpx;
padding: 0 40rpx;
border-radius: 16rpx;
overflow: hidden;
position: relative;
}
.detail-item .gw-value .cd-detail .cd-name::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 10rpx;
height: 100%;
background: #349cfc;
}
.detail-item .gw-value .cd-detail .cd-con {
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 30rpx 40rpx;
gap: 20rpx;
}
.detail-item .gw-value .cd-detail .cd-con .cd-con-item {
width: 80rpx;
height: 80rpx;
background: #67CFA7;
line-height: 80rpx;
text-align: center;
color: #fff;
border: 2rpx solid #ddd;
border-radius: 20rpx;
cursor: pointer;
font-weight: 600;
font-size: 32rpx;
}
.detail-item .gw-value .cd-detail .cd-con .cd-con-item-review {
background-color: #F8BB92;
}
.detail-item .gw-value .cd-detail .cd-con .cd-con-item-checked {
background: #F6A1A1;
}
.detail-item .gw-value .cd-detail .cd-con .cd-con-item-mychecked {
background: #79BEFE;
}
.item-checkbox {
width: 100%;
padding: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
.job-name {
font-size: 32rpx;
color: #409eff;
}
.salary {
font-size: 32rpx;
color: #ff6e27;
font-weight: 600;
}
.header-title {
font-size: 38rpx;
font-weight: 600;
color: #303133;
padding: 20rpx;
padding-bottom: 40rpx;
background: #fff;
display: flex;
align-items: center;
position: sticky;
top: 0;
}
.header-title image {
width: 14rpx;
height: 33rpx;
margin-right: 14rpx;
}
.avatar {
width: 400rpx;
height: 200rpx;
border-radius: 12rpx;
}
/* 展位状态说明样式 */
.status-description {
margin-top: 30rpx;
padding: 20rpx;
background-color: #f5f7fa;
border-radius: 8rpx;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.status-title {
font-weight: bold;
margin-bottom: 16rpx;
width: 100%;
}
.status-item {
width: 43%;
display: flex;
align-items: center;
margin-right: 30rpx;
margin-bottom: 10rpx;
}
.status-color {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
.status-color.available {
background-color: #67CFA7;
border: 2rpx solid #ddd;
}
.status-color.occupied {
background-color: #F6A1A1;
}
.status-color.pending {
background-color: #F8BB92;
}
.status-color.selected {
background-color: #79BEFE;
}
.status-text {
margin-right: 16rpx;
}
/* 透明按钮样式 */
.transparent-btn {
background: transparent !important;
border: 2rpx dashed #0983ff !important;
}
</style>

View File

@@ -1,572 +1,417 @@
<template>
<AppLayout title="" :use-scroll-view="false">
<template #headerleft>
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
</template>
<template #headerright>
<view class="btn mar_ri10">
<image
src="@/static/icon/collect3.png"
v-if="!companyInfo.isCollection"
></image>
<image src="@/static/icon/collect2.png" v-else></image>
</view>
</template>
<view class="content">
<view class="content-top">
<view class="companyinfo-left">
<image src="@/static/icon/companyIcon.png" mode=""></image>
</view>
<view class="companyinfo-right">
<view class="row1">{{ companyInfo?.companyName }}</view>
<view class="row2" v-if="companyInfo?.industry || companyInfo?.scale">
<dict-tree-Label
v-if="companyInfo?.industry"
dictType="industry"
:value="companyInfo?.industry"
></dict-tree-Label>
<span v-if="companyInfo?.industry && companyInfo?.scale">&nbsp;·&nbsp;</span>
<dict-Label
v-if="companyInfo?.scale"
dictType="scale"
:value="companyInfo?.scale"
></dict-Label>
</view>
</view>
</view>
<view class="conetent-info" :class="{ expanded: isExpanded }">
<view class="info-title">公司介绍</view>
<view class="info-desirption">{{
companyInfo.description
<AppLayout title="" :use-scroll-view="false">
<template #headerleft>
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
</template>
<template #headerright>
<view class="btn mar_ri10">
<image src="@/static/icon/collect3.png" v-if="!companyInfo.isCollection"></image>
<image src="@/static/icon/collect2.png" v-else></image>
</view>
</template>
<view class="content">
<view class="content-top">
<view class="companyinfo-left">
<image src="@/static/icon/companyIcon.png" mode=""></image>
</view>
<view class="companyinfo-right">
<view class="row1">{{ companyInfo?.companyName }}</view>
<view class="row2">
{{ companyInfo?.scale }}
</view>
</view>
</view>
<view class="conetent-info" :class="{ expanded: isExpanded }">
<view class="info-title">公司介绍</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>
<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">在招职位</text></view>
<template v-if="companyInfo.jobInfoList.length != 0">
<view v-for="job in companyInfo.jobInfoList" :key="job.jobId" class="job-card-wrapper">
<view class="cards" @click="navTo(`/packageA/pages/post/post?jobId=${job.jobId}`)">
<view class="card-header">
<view class="card-title-row">
<text class="job-title">{{ job.jobTitle }}</text>
<view class="card-pay">
<view class="pay-text">
<text class="salary-amount">{{ formatSalary(job.minSalary, job.maxSalary) }}</text>
<text class="salary-unit">/</text>
</view>
</view>
</view>
</view>
<view class="card-tags" v-if="job.experience || job.education">
<view class="tag tag-experience" v-if="job.experience">
<image class="tag-icon" :src="`${baseUrl}/jobfair/jy.png`" mode="aspectFit"></image>
<view class="tag-text">
<dict-Label dictType="experience" :value="job.experience"></dict-Label>
</view>
</view>
<view class="tag tag-education" v-if="job.education">
<image class="tag-icon" :src="`${baseUrl}/jobfair/xx.png`" mode="aspectFit"></image>
<view class="tag-text">
<dict-Label dictType="education" :value="job.education"></dict-Label>
</view>
</view>
</view>
<view class="card-location" v-if="job.jobLocation">
<image class="location-icon" src="/static/icon/point3.png" mode="aspectFit"></image>
<text class="location-text">{{ job.jobLocation }}</text>
</view>
</view>
</view>
</template>
<empty v-else pdTop="200"></empty>
</view>
</scroll-view>
</view>
</AppLayout>
</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">在招职位</text></view>
<template v-if="companyInfo.jobInfoList.length != 0">
<view v-for="job in companyInfo.jobInfoList" :key="job.id">
<!-- @click="navTo(`/packageA/pages/post/post?jobId=${JSON.stringify(job)}`)" -->
<!-- :style="getItemBackgroundStyle('bj2.png')" -->
<view class="cards">
<view class="card-company">
<text class="company">{{ job.jobTitle }}</text>
<view class="salary"> {{ job.salaryRange }}/ </view>
</view>
<view class="card-tags">
<view class="tag jy">
<image :src="`${baseUrl}/jobfair/jy.png`" mode=""></image>
{{ job.experienceRequirement }}
</view>
<view class="tag xl">
<image :src="`${baseUrl}/jobfair/xx.png`" mode=""></image>
{{ job.educationRequirement }}
</view>
<view class="tag yd" v-if="job.jobRequirement">
<image :src="`${baseUrl}/jobfair/lx-1.png`" mode=""></image>
{{ job.jobRequirement }}
</view>
</view>
<view class="card-companyName">
{{ job.jobDescription }}
</view>
<view class="deliver-box">
<view class="deliver-btn" @click="deliverResume">
简历投递
</view>
</view>
</view>
</view>
</template>
<empty v-else pdTop="200"></empty>
</view>
</scroll-view>
</view>
</AppLayout>
</template>
<script setup>
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 config from "@/config.js";
import { storeToRefs } from "pinia";
import useLocationStore from "@/stores/useLocationStore";
const { longitudeVal, latitudeVal } = storeToRefs(useLocationStore());
const { $api, navTo, vacanciesTo, navBack, parseQueryParams } = inject("globalFunction");
const isExpanded = ref(false);
const pageState = reactive({
page: 0,
list: [],
total: 0,
maxPage: 1,
pageSize: 10,
});
const companyInfo = ref({
jobInfoList: [],
companyName: '',
scale: '',
industry: '',
description: '',
isCollection: false
});
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 config from "@/config.js";
import {
storeToRefs
} from "pinia";
import useLocationStore from "@/stores/useLocationStore";
const {
longitudeVal,
latitudeVal
} = storeToRefs(useLocationStore());
const {
$api,
navTo,
vacanciesTo,
navBack
} = inject("globalFunction");
const isExpanded = ref(false);
const pageState = reactive({
page: 0,
list: [],
total: 0,
maxPage: 1,
pageSize: 10,
});
const companyInfo = ref({
jobInfoList: [],
});
const baseUrl = config.imgBaseUrl;
const companyIdRef = ref(null);
const baseUrl = config.imgBaseUrl;
const getItemBackgroundStyle = (imageName) => ({
backgroundImage: `url(${baseUrl}/jobfair/${imageName})`,
backgroundSize: "100% 100%", // 覆盖整个容器
backgroundPosition: "center", // 居中
backgroundRepeat: "no-repeat",
});
const getItemBackgroundStyle = (imageName) => ({
backgroundImage: `url(${baseUrl}/jobfair/${imageName})`,
backgroundSize: "100% 100%", // 覆盖整个容器
backgroundPosition: "center", // 居中
backgroundRepeat: "no-repeat",
});
onLoad((options) => {
companyInfo.value = JSON.parse(options.job);
});
// 获取公司详情
function getCompanyDetail(companyId) {
if (!companyId) {
console.error('companyId 不能为空');
return;
}
function expand() {
isExpanded.value = !isExpanded.value;
}
// 尝试获取公司详情,如果接口不存在,可能公司详情会包含在职位数据中
$api.createRequest(`/app/company/${companyId}`).then((resData) => {
if (resData && resData.data) {
const data = resData.data;
companyInfo.value = {
...companyInfo.value,
...data,
companyName: data.name || data.companyName || data.company?.name || '',
scale: data.scale || data.company?.scale || '',
industry: data.industry || data.company?.industry || '',
description: data.description || data.companyIntroduction || data.introduction || data.company?.introduction || '',
isCollection: data.isCollection || false,
// 如果接口直接返回了职位列表,也设置进去
jobInfoList: data.jobInfoList || data.jobs || data.list || companyInfo.value.jobInfoList || []
};
console.log('companyInfo',companyInfo.value);
}
// 获取在招职位列表
getCompanyJobs(companyId);
}).catch((error) => {
console.error('获取公司详情失败:', error);
// 如果获取公司详情失败,尝试通过职位列表接口获取公司信息
// 或者直接获取职位列表
getCompanyJobs(companyId);
});
}
function deliverResume() {
const raw = uni.getStorageSync("Padmin-Token");
const token = typeof raw === "string" ? raw.trim() : "";
const headers = token ? {
Authorization: raw.startsWith("Bearer ") ? raw : `Bearer ${token}`
} : {};
// 获取公司在招职位列表
function getCompanyJobs(companyId) {
if (!companyId) {
return;
}
$api.myRequest("/dashboard/auth/heart", {}, "POST", 10100, headers).then((resData1) => {
if (resData1.code == 200) {
$api.myRequest("/system/user/login/user/info", {}, "GET", 10100, headers).then((resData) => {
$api.myRequest("/jobfair/public/job-fair-person-job/insert", {}, "GET", 9100, {
"Content-Type": "application/json"
}).then((data) => {
if (data && data.code === 200) {
$api.msg("简历投递成功");
} else {
$api.msg((data && data.msg) || "简历投递失败");
}
});
});
} else {
$api.msg('请先登录')
}
});
// 使用正确的 API 路径:/app/company/job/{companyId}
$api.createRequest(`/app/company/job/${companyId}`, {}, 'GET').then((resData) => {
console.log('获取职位列表返回数据:', resData);
if (resData) {
// 优先检查 rows 字段(根据实际返回的数据结构)
if (resData.rows && Array.isArray(resData.rows)) {
companyInfo.value.jobInfoList = resData.rows;
}
// 如果返回的是数组
else if (Array.isArray(resData)) {
companyInfo.value.jobInfoList = resData;
}
// 如果返回的是对象,包含列表字段
else if (resData.data) {
if (Array.isArray(resData.data)) {
companyInfo.value.jobInfoList = resData.data;
} else if (resData.data.rows && Array.isArray(resData.data.rows)) {
companyInfo.value.jobInfoList = resData.data.rows;
} else if (resData.data.list && Array.isArray(resData.data.list)) {
companyInfo.value.jobInfoList = resData.data.list;
} else if (resData.data.jobInfoList && Array.isArray(resData.data.jobInfoList)) {
companyInfo.value.jobInfoList = resData.data.jobInfoList;
} else {
companyInfo.value.jobInfoList = [];
}
} else {
companyInfo.value.jobInfoList = [];
}
} else {
companyInfo.value.jobInfoList = [];
}
}).catch((error) => {
console.error('获取在招职位列表失败:', error);
companyInfo.value.jobInfoList = [];
});
}
onLoad((options) => {
console.log('options',options);
let companyId = null;
// 优先从 options 中获取 companyId小程序和 H5 都支持)
if (options && options.companyId) {
companyId = decodeURIComponent(options.companyId);
}
// 如果 options 中没有,尝试从 URL 解析(仅 H5 环境)
else {
// 使用 try-catch 包裹,避免在小程序环境中访问 window.location 报错
try {
// #ifdef H5
const params = parseQueryParams();
companyId = params.companyId;
// #endif
} catch (e) {
console.warn('解析 URL 参数失败:', e);
}
}
console.log('companyId', companyId);
if (companyId) {
companyIdRef.value = companyId;
getCompanyDetail(companyId);
} else {
console.error('未获取到 companyId 参数');
// 如果参数名是 job尝试兼容旧的方式
if (options && options.job) {
try {
const parsedData = JSON.parse(options.job);
if (parsedData.companyId) {
companyIdRef.value = parsedData.companyId;
getCompanyDetail(parsedData.companyId);
} else {
companyInfo.value = { ...companyInfo.value, ...parsedData };
}
} catch (e) {
console.error('解析 job 参数失败:', e);
}
}
}
});
onShow(() => {
// 仅在 H5 环境中从 URL 获取参数(小程序环境中 onShow 不会传递 URL 参数)
// #ifdef H5
try {
const params = parseQueryParams();
const companyId = params.companyId;
if (companyId && companyId !== companyIdRef.value) {
companyIdRef.value = companyId;
getCompanyDetail(companyId);
}
} catch (e) {
console.warn('onShow 中解析 URL 参数失败:', e);
}
// #endif
});
function expand() {
isExpanded.value = !isExpanded.value;
}
// 格式化薪资范围
function formatSalary(minSalary, maxSalary) {
if (minSalary && maxSalary) {
return `${minSalary}-${maxSalary}`;
} else if (minSalary) {
return `${minSalary}`;
} else if (maxSalary) {
return `最高${maxSalary}`;
}
return '面议';
}
// 截断文本,超过指定长度显示省略号
function truncateText(text, maxLength) {
if (!text) return '';
if (text.length <= maxLength) return text;
return text.substring(0, maxLength) + '...';
}
}
</script>
<style lang="stylus" scoped>
.btnback {
width: 64rpx;
height: 64rpx;
}
.btnback {
width: 64rpx;
height: 64rpx;
}
.btn {
display: flex;
justify-content: space-between;
align-items: center;
width: 52rpx;
height: 52rpx;
}
.btn {
display: flex;
justify-content: space-between;
align-items: center;
width: 52rpx;
height: 52rpx;
}
image {
height: 100%;
width: 100%;
}
image {
height: 100%;
width: 100%;
}
.content {
height: 100%;
display: flex;
flex-direction: column;
.content {
height: 100%;
display: flex;
flex-direction: column;
.content-top {
padding: 28rpx;
padding-top: 50rpx;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
.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-left {
width: 96rpx;
height: 96rpx;
margin-right: 24rpx;
}
.companyinfo-right {
.row1 {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.companyinfo-right {
.row1 {
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.row2 {
font-weight: 400;
font-size: 28rpx;
color: #6C7282;
line-height: 45rpx;
}
}
}
.row2 {
font-weight: 400;
font-size: 28rpx;
color: #6C7282;
line-height: 45rpx;
}
}
}
.conetent-info {
padding: 0 28rpx;
overflow: hidden;
max-height: 0rpx;
transition: max-height 0.3s ease;
.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-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;
}
.info-desirption {
margin-top: 12rpx;
font-weight: 400;
font-size: 28rpx;
color: #495265;
text-align: justified;
}
.title2 {
margin-top: 48rpx;
}
}
.title2 {
margin-top: 48rpx;
}
}
.expanded {
max-height: 1000rpx; // 足够显示完整内容
}
.expanded {
max-height: 1000rpx; // 足够显示完整内容
}
.expand {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
justify-content: center;
margin-top: 20rpx;
margin-bottom: 28rpx;
font-weight: 400;
font-size: 28rpx;
color: #256BFA;
.expand {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
justify-content: center;
margin-top: 20rpx;
margin-bottom: 28rpx;
font-weight: 400;
font-size: 28rpx;
color: #256BFA;
.expand-img {
width: 40rpx;
height: 40rpx;
}
.expand-img {
width: 40rpx;
height: 40rpx;
}
.expand-img-active {
transform: rotate(180deg);
}
}
}
.expand-img-active {
transform: rotate(180deg);
}
}
}
.Detailscroll-view {
flex: 1;
overflow: hidden;
background: #F4F4F4;
.Detailscroll-view {
flex: 1;
overflow: hidden;
background: #F4F4F4;
.views {
padding: 28rpx;
.views {
padding: 28rpx;
.Detail-title {
font-weight: 600;
font-size: 32rpx;
color: #000000;
position: relative;
display: flex;
justify-content: space-between;
.Detail-title {
font-weight: 600;
font-size: 32rpx;
color: #000000;
position: relative;
display: flex;
justify-content: space-between;
.title {
position: relative;
z-index: 2;
}
}
.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;
}
.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;
}
.job-card-wrapper {
margin-top: 22rpx;
.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;
padding-bottom: 18rpx;
background: #f2f8fc;
&:first-child {
margin-top: 0;
}
}
.card-company {
display: flex;
justify-content: space-between;
align-items: flex-start;
border-bottom: 1rpx solid #c2d7ea;
.cards {
padding: 30rpx;
background: #FFFFFF;
box-shadow: 0rpx 2rpx 12rpx 0rpx rgba(0, 0, 0, 0.08);
border-radius: 24rpx;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
.company {
font-weight: 600;
font-size: 32rpx;
color: #207AC7;
}
&:active {
transform: scale(0.98);
box-shadow: 0rpx 1rpx 8rpx 0rpx rgba(0, 0, 0, 0.12);
}
.salary {
font-weight: 600;
font-size: 28rpx;
color: #F83A3C;
white-space: nowrap;
line-height: 48rpx;
}
}
.card-header {
margin-bottom: 0;
.deliver-box {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 5rpx;
.card-title-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20rpx;
.deliver-btn {
padding: 10rpx 25rpx;
background: #53ACFF;
width: max-content;
color: #fff;
}
}
.job-title {
flex: 1;
font-family: 'PingFangSC-Medium', 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Microsoft YaHei', sans-serif;
text-align: left;
word-break: break-all;
font-weight: 500;
font-size: 32rpx;
color: #333333;
}
.card-companyName {
font-weight: 400;
font-size: 28rpx;
margin-top: 23rpx;
display: flex;
align-items: center;
.card-pay {
flex-shrink: 0;
display: flex;
align-items: center;
image {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
}
}
.pay-text {
font-family: DIN-Medium;
font-weight: 500;
font-size: 28rpx;
color: #4C6EFB;
line-height: 45rpx;
white-space: nowrap;
.card-tags {
display: flex;
flex-wrap: wrap;
margin: 25rpx 0 35rpx;
.salary-amount {
font-family: DIN-Medium;
font-weight: 500;
font-size: 28rpx;
color: #4C6EFB;
line-height: 45rpx;
}
image {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
}
.salary-unit {
font-weight: 400;
font-size: 20rpx;
color: #4C6EFB;
margin-left: 4rpx;
}
}
}
}
}
.jy {
background: #D9EDFF;
color: #0086FF;
}
.card-tags {
display: flex;
flex-wrap: wrap;
gap: 10rpx;
margin-top: 20rpx;
margin-bottom: 20rpx;
.xl {
background: #FFF1D5;
color: #FF7F01;
}
.tag {
display: flex;
align-items: center;
width: fit-content;
height: 30rpx;
padding: 6rpx 20rpx;
border-radius: 4rpx;
background: #F4F4F4;
font-weight: 400;
font-size: 24rpx;
color: #6C7282;
white-space: nowrap;
line-height: 30rpx;
text-align: center;
.yd {
background: #FFD8D8;
color: #F83A3C;
}
.tag-icon {
width: 24rpx;
height: 24rpx;
margin-right: 8rpx;
flex-shrink: 0;
}
.tag {
width: fit-content;
height: 30rpx;
border-radius: 4rpx;
padding: 6rpx 20rpx;
line-height: 30rpx;
font-weight: 400;
font-size: 24rpx;
text-align: center;
white-space: nowrap;
margin-right: 20rpx;
display: flex;
align-items: center;
}
}
.tag-text {
line-height: 1;
}
}
}
.card-location {
display: flex;
align-items: flex-start;
margin-top: 20rpx;
.location-icon {
width: 28rpx;
height: 28rpx;
margin-right: 4rpx;
margin-top: 0;
flex-shrink: 0;
}
.location-text {
flex: 1;
font-weight: 400;
font-size: 24rpx;
color: #999999;
line-height: 25rpx;
word-break: break-all;
}
}
}
}
}
.card-bottom {
margin-top: 32rpx;
display: flex;
justify-content: space-between;
font-size: 28rpx;
color: #6C7282;
}
}
}
}
</style>

View File

@@ -105,16 +105,23 @@
</view>
<template #footer>
<view class="footer" v-if="hasnext">
<view class="btn-wq button-click" :class="{ 'btn-desbel': fairInfo.isCollection }"
<view class="btn-wq button-click" :class="{ 'btn-desbel': fairInfo.isSignUp==1 }"
@click="applyExhibitors">
{{ fairInfo.isCollection ? '预约招聘会' : '预约招聘会' }}
{{ fairInfo.isSignUp==1 ? '报名' : '报名招聘会' }}
</view>
</view>
</template>
<uni-popup ref="CompanySignPopup" background-color="#fff" :mask-click="false">
<view class="popup-content">
<signDialog v-if="signDialogisshow" :signType="signType" :signRole="signRole"
:jobFairId="fairInfo.jobFairId" @closePopup="closePopup"></signDialog>
</view>
</uni-popup>
</AppLayout>
</template>
<script setup>
import signDialog from '@/components/jobfair/signDialog.vue';
import config from "@/config.js"
import {
reactive,
@@ -128,7 +135,6 @@
onLoad,
onShow
} from '@dcloudio/uni-app';
import dictLabel from '@/components/dict-Label/dict-Label.vue';
import useLocationStore from '@/stores/useLocationStore';
const {
$api,
@@ -148,6 +154,15 @@
const fairInfo = ref({});
const companyList = ref([]);
const hasnext = ref(true);
const userInfo = ref({});
const signDialogisshow = ref(false)
// 弹窗
const signType = ref(1);
// person个人 ent企业
const signRole = ref('ent');
const CompanySignPopup = ref(null)
const jobFairId = ref(null)
const baseUrl = config.imgBaseUrl
const getItemBackgroundStyle = (imageName) => ({
@@ -157,28 +172,59 @@
backgroundRepeat: 'no-repeat'
});
onLoad((options) => {
getCompanyInfo(options.jobFairId);
jobFairId.value=options.jobFairId
const raw = uni.getStorageSync("Padmin-Token");
const token = typeof raw === "string" ? raw.trim() : "";
const headers = token ? {
Authorization: raw.startsWith("Bearer ") ? raw : `Bearer ${token}`
} : {};
$api.myRequest("/dashboard/auth/heart", {}, "POST", 10100, headers).then((resData) => {
if (resData.code == 200) {
$api.myRequest("/system/user/login/user/info", {}, "GET", 10100, {
Authorization: `Bearer ${uni.getStorageSync("Padmin-Token")}`
}).then((userinfo) => {
userInfo.value = userinfo
getCompanyInfo(userInfo.value.info.userId, options.jobFairId);
});
} else {
getCompanyInfo('', options.jobFairId);
}
});
});
function 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');
function closePopup() {
CompanySignPopup.value.close()
getCompanyInfo(userInfo.value.info.userId, jobFairId.value)
}
function getCompanyInfo(userId, id) {
let data={}
if (userInfo.value&&userInfo.value.userType == 'ent') {
data={
jobFairId: id,
enterpriseId: userId,
code:userInfo.value.info.entCreditCode
}
}else if(userInfo.value&&userInfo.value.userType == 'ent'){
data={
jobFairId: id,
personId: userId,
idCard:userInfo.value.info.personCardNo
}
}else{
data={
jobFairId: id,
personId: userId
}
}
$api.myRequest('/jobfair/public/jobfair/detail', data).then((resData) => {
fairInfo.value = resData.data;
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()
});
};
@@ -205,21 +251,56 @@
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('预约成功');
});
if (fairInfo.value.isSignUp == 1) {
$api.msg('请勿重复报名');
return
}
const raw = uni.getStorageSync("Padmin-Token");
const token = typeof raw === "string" ? raw.trim() : "";
const headers = token ? {
Authorization: raw.startsWith("Bearer ") ? raw : `Bearer ${token}`
} : {};
$api.myRequest("/dashboard/auth/heart", {}, "POST", 10100, headers).then((resData) => {
if (resData.code == 200) {
if (userInfo.value.userType == 'ent') {
// 企业
signType.value = fairInfo.value.jobFairType;
signRole.value = userInfo.userType;
signDialogisshow.value = true
CompanySignPopup.value.open()
}else{
$api.myRequest("/jobfair/public/job-fair-sign-up-person/sign-up", {
personId: userInfo.value.info.userId,
jobFairId: jobFairId.value,
idCard:userInfo.value.info.personCardNo
}, "POST", 9100, { "Content-Type": "application/json",...headers }).then((res) => {
if (res.code === 200) {
uni.showToast({
title: '报名成功',
icon: 'success'
});
getCompanyInfo(userInfo.value.info.userId, jobFairId.value)
} else {
uni.showToast({
title: res.msg || '报名失败',
icon: 'none'
});
}
})
}
} else {
$api.msg('请先登录');
setTimeout(() => {
uni.redirectTo({
url: '/packageB/login'
})
}, 1000)
}
});
}
function parseDateTime(datetimeStr) {
@@ -288,6 +369,12 @@
</script>
<style lang="stylus" scoped>
.popup-content {
width: 90vw;
height: 80vh;
position: relative;
}
.btnback {
width: 64rpx;
height: 64rpx;
@@ -528,6 +615,7 @@
color: #333333;
display: flex;
align-items: center;
image {
width: 30rpx;
height: 30rpx;
@@ -577,7 +665,8 @@
display: flex;
align-items: center;
margin-right: 20rpx;
image{
image {
width: 22rpx;
height: 22rpx;
margin-right: 8rpx;

View File

@@ -253,6 +253,7 @@ const applicants = ref([
]);
onLoad((option) => {
console.log(option, 'option');
if (option.jobId) {
initLoad(option);
}

View File

@@ -1,559 +0,0 @@
<template>
<AppLayout title="" :use-scroll-view="false">
<template #headerleft>
<view class="btnback">
<image src="@/static/icon/back.png" @click="navBack"></image>
</view>
</template>
<view class="content">
<view class="content-top">
<view class="companyinfo-left">
<image src="@/static/icon/companyIcon.png" mode=""></image>
</view>
<view class="companyinfo-right">
<view class="row1 line_2">{{ fairInfo?.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>
<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>
<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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,497 @@
<template>
<view class="help-filter-page">
<view class="header">
<view class="back-btn" @click="goBack">
<uni-icons type="arrowleft" size="24" color="#fff" />
</view>
<view class="title">筛选和帮扶</view>
</view>
<!-- 筛选条件区域 -->
<view class="filter-section">
<view class="filter-item">
<view class="filter-label">人员姓名</view>
<input class="filter-input" v-model="filters.personName" placeholder="请输入人员姓名" />
</view>
<view class="filter-item">
<view class="filter-label">身份证号</view>
<input class="filter-input" v-model="filters.idCard" placeholder="请输入身份证号" />
</view>
<view class="filter-item">
<view class="filter-label">帮扶类型</view>
<picker class="filter-picker" mode="selector" range="{{helpTypes}}" bindchange="onHelpTypeChange">
<view class="picker-text">{{filters.helpType || '请选择帮扶类型'}}</view>
</picker>
</view>
<view class="filter-item">
<view class="filter-label">帮扶人员</view>
<input class="filter-input" v-model="filters.helperName" placeholder="请输入帮扶人员姓名" />
</view>
<view class="filter-item">
<view class="filter-label">所属区域</view>
<picker class="filter-picker" mode="selector" range="{{regions}}" bindchange="onRegionChange">
<view class="picker-text">{{filters.region || '请选择所属区域'}}</view>
</picker>
</view>
<view class="date-range">
<view class="filter-label">帮扶时间</view>
<view class="date-inputs">
<input class="date-input" v-model="filters.startDate" type="date" placeholder="开始日期" />
<view class="date-separator"></view>
<input class="date-input" v-model="filters.endDate" type="date" placeholder="结束日期" />
</view>
</view>
<view class="filter-buttons">
<button class="query-btn" type="primary" @click="queryData">查询</button>
<button class="reset-btn" @click="resetFilters">重置</button>
</view>
</view>
<!-- 帮扶记录列表 -->
<view class="list-section">
<view class="list-header">
<view class="list-title">帮扶记录列表</view>
<view class="list-count">{{helpRecords.length}}条记录</view>
</view>
<view class="records-list">
<view class="record-item" v-for="record in helpRecords" :key="record.id">
<view class="record-header">
<view class="person-name">{{record.personName}}</view>
<view class="job-tag" @click="showJobRecommend(record)">{{record.jobTag}}</view>
</view>
<view class="record-info">
<view class="info-row">
<uni-icons type="call" size="14" color="#999" />
<span class="info-label">联系电话</span>
<span class="info-value">{{record.phone}}</span>
</view>
<view class="info-row">
<uni-icons type="card" size="14" color="#999" />
<span class="info-label">身份证号</span>
<span class="info-value">{{record.idCard}}</span>
</view>
<view class="info-row">
<uni-icons type="location" size="14" color="#999" />
<span class="info-label">所属区域</span>
<span class="info-value">{{record.region}}</span>
</view>
<view class="info-row">
<uni-icons type="person" size="14" color="#999" />
<span class="info-label">帮扶人员</span>
<span class="info-value">{{record.helperName}}</span>
</view>
<view class="info-row">
<uni-icons type="briefcase" size="14" color="#999" />
<span class="info-label">帮扶单位</span>
<span class="info-value">{{record.helperUnit}}</span>
</view>
<view class="info-row">
<uni-icons type="calendar" size="14" color="#999" />
<span class="info-label">帮扶日期</span>
<span class="info-value">{{record.helpDate}}</span>
</view>
<view class="info-row">
<uni-icons type="time" size="14" color="#999" />
<span class="info-label">下次联系</span>
<span class="info-value">{{record.nextContactDate}}</span>
</view>
</view>
<view class="record-actions">
<button class="detail-btn" @click="showDetail(record)">详情</button>
<button class="follow-btn" @click="followUp(record)">跟进</button>
<button class="recommend-btn" @click="showJobRecommend(record)">智能推荐</button>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'uni-app'
export default {
name: 'HelpFilter',
setup() {
const router = useRouter()
// 筛选条件
const filters = reactive({
personName: '',
idCard: '',
helpType: '',
helperName: '',
region: '',
startDate: '',
endDate: ''
})
// 帮扶类型选项
const helpTypes = ref(['就业帮扶', '技能培训', '创业支持', '政策咨询'])
// 区域选项
const regions = ref(['喀什地区/疏勒县', '喀什地区/疏附县', '喀什地区/伽师县', '喀什地区/岳普湖县'])
// 帮扶记录数据
const helpRecords = ref([
{
id: 1,
personName: '王小明',
jobTag: '招聘岗位推荐',
phone: '13912345678',
idCard: '371302198801112024',
region: '喀什地区/疏勒县',
helperName: '新兴社区管理员',
helperUnit: '新兴社区',
helpDate: '2023-11-05',
nextContactDate: '2023-11-06'
},
{
id: 2,
personName: '赵小美',
jobTag: '招聘岗位推荐',
phone: '15912345678',
idCard: '371302198801112024',
region: '喀什地区/疏勒县',
helperName: '新兴社区管理员',
helperUnit: '新兴社区',
helpDate: '2023-11-05',
nextContactDate: '2023-11-06'
},
{
id: 3,
personName: '赵小美',
jobTag: '招聘岗位推荐',
phone: '15912345678',
idCard: '371302198801112024',
region: '喀什地区/疏勒县',
helperName: '新兴社区管理员',
helperUnit: '新兴社区',
helpDate: '2023-11-05',
nextContactDate: '2023-11-06'
}
])
// 返回上一页
const goBack = () => {
router.back()
}
// 重置筛选条件
const resetFilters = () => {
Object.keys(filters).forEach(key => {
filters[key] = ''
})
}
// 查询数据
const queryData = () => {
// 这里是模拟查询实际项目中应该调用API
console.log('查询条件:', filters)
// 实际开发中这里应该调用接口获取数据
// fetchHelpRecords(filters)
}
// 显示详情
const showDetail = (record) => {
console.log('查看详情:', record)
// 跳转到详情页面
// router.push({ path: '/detail', query: { id: record.id } })
}
// 跟进
const followUp = (record) => {
console.log('跟进记录:', record)
// 跳转到跟进页面
router.push({ path: '/packageB/priority/helpFollow', query: { personId: record.id, personName: record.personName } })
}
// 智能推荐
const showJobRecommend = (record) => {
console.log('智能推荐:', record)
// 跳转到推荐页面
// router.push({ path: '/recommend', query: { id: record.id } })
}
// 帮扶类型选择变化
const onHelpTypeChange = (e) => {
filters.helpType = helpTypes.value[e.detail.value]
}
// 区域选择变化
const onRegionChange = (e) => {
filters.region = regions.value[e.detail.value]
}
onMounted(() => {
// 组件挂载时的初始化逻辑
})
return {
filters,
helpTypes,
regions,
helpRecords,
goBack,
resetFilters,
queryData,
showDetail,
followUp,
showJobRecommend,
onHelpTypeChange,
onRegionChange
}
}
}
</script>
<style scoped>
.help-filter-page {
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
background-color: #1989fa;
display: flex;
align-items: center;
padding: 20rpx 30rpx;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
.back-btn {
padding: 10rpx;
}
.title {
color: #fff;
font-size: 36rpx;
font-weight: bold;
flex: 1;
text-align: center;
margin-right: 60rpx;
}
.filter-section {
background-color: #fff;
margin-top: 100rpx;
padding: 30rpx;
border-radius: 10rpx;
margin-bottom: 20rpx;
}
.filter-item {
display: flex;
align-items: center;
margin-bottom: 30rpx;
}
.filter-label {
font-size: 28rpx;
color: #333;
width: 200rpx;
}
.filter-input {
flex: 1;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
.filter-picker {
flex: 1;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
display: flex;
align-items: center;
padding: 0 20rpx;
}
.picker-text {
font-size: 28rpx;
color: #999;
}
.date-range {
display: flex;
align-items: flex-start;
margin-bottom: 30rpx;
}
.date-inputs {
flex: 1;
display: flex;
align-items: center;
}
.date-input {
flex: 1;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
.date-separator {
margin: 0 20rpx;
color: #999;
}
.filter-buttons {
display: flex;
gap: 20rpx;
}
.query-btn {
flex: 1;
background-color: #1989fa;
color: #fff;
font-size: 32rpx;
border: none;
height: 88rpx;
line-height: 88rpx;
}
.reset-btn {
flex: 1;
background-color: #fff;
color: #333;
font-size: 32rpx;
border: 1rpx solid #e0e0e0;
height: 88rpx;
line-height: 88rpx;
}
.list-section {
background-color: #fff;
padding: 30rpx;
border-radius: 10rpx;
}
.list-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
}
.list-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.list-count {
font-size: 28rpx;
color: #999;
}
.record-item {
border: 1rpx solid #e0e0e0;
border-radius: 10rpx;
padding: 30rpx;
margin-bottom: 30rpx;
}
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.person-name {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.job-tag {
font-size: 24rpx;
color: #ff6600;
padding: 5rpx 15rpx;
border: 1rpx solid #ff6600;
border-radius: 15rpx;
}
.record-info {
margin-bottom: 30rpx;
}
.info-row {
display: flex;
align-items: center;
margin-bottom: 15rpx;
font-size: 28rpx;
}
.info-label {
color: #666;
margin-left: 10rpx;
}
.info-value {
color: #333;
margin-left: 10rpx;
}
.record-actions {
display: flex;
gap: 20rpx;
}
.detail-btn {
flex: 1;
background-color: #e8f3ff;
color: #1989fa;
font-size: 28rpx;
border: none;
height: 70rpx;
line-height: 70rpx;
}
.follow-btn {
flex: 1;
background-color: #e6f7ff;
color: #1890ff;
font-size: 28rpx;
border: none;
height: 70rpx;
line-height: 70rpx;
}
.recommend-btn {
flex: 1;
background-color: #f6ffed;
color: #52c41a;
font-size: 28rpx;
border: none;
height: 70rpx;
line-height: 70rpx;
}
</style>

View File

@@ -0,0 +1,442 @@
<template>
<view class="help-follow-page">
<view class="header">
<view class="back-btn" @click="goBack">
<uni-icons type="arrowleft" size="24" color="#fff" />
</view>
<view class="title">跟进</view>
</view>
<!-- 人员信息卡片 -->
<view class="person-info-card">
<view class="info-item">
<uni-icons type="person" size="20" color="#1989fa" />
<span class="info-label">人员姓名</span>
<span class="info-value">{{personInfo.personName}}</span>
</view>
<view class="info-item">
<uni-icons type="briefcase" size="20" color="#1989fa" />
<span class="info-label">帮扶类型</span>
<span class="info-value">{{personInfo.helpType}}</span>
</view>
</view>
<!-- 新增跟进记录 -->
<view class="follow-form-section">
<view class="section-title">新增跟进记录</view>
<view class="form-item">
<view class="form-label required">跟进日期</view>
<input class="form-input date-input" v-model="followData.followDate" type="date" placeholder="请选择跟进日期" />
</view>
<view class="form-item">
<view class="form-label required">跟进方式</view>
<picker class="form-picker" mode="selector" range="{{followMethods}}" @change="onFollowMethodChange">
<view class="picker-text">{{followData.followMethod || '请选择跟进方式'}}</view>
</picker>
</view>
<view class="form-item">
<view class="form-label required">跟进内容</view>
<textarea class="form-textarea" v-model="followData.followContent" placeholder="请输入跟进内容" rows="4"></textarea>
</view>
<view class="form-item">
<view class="form-label required">跟进结果</view>
<textarea class="form-textarea" v-model="followData.followResult" placeholder="请输入跟进结果" rows="3"></textarea>
</view>
<view class="form-item">
<view class="form-label">下一步计划</view>
<textarea class="form-textarea" v-model="followData.nextPlan" placeholder="请输入下一步计划" rows="3"></textarea>
</view>
<view class="form-item">
<view class="form-label">下次联系</view>
<input class="form-input date-input" v-model="followData.nextContactDate" type="date" placeholder="请选择下次联系日期" />
</view>
<view class="form-buttons">
<button class="save-btn" type="primary" @click="saveFollowRecord">保存跟进</button>
<button class="reset-btn" @click="resetForm">重置</button>
</view>
</view>
<!-- 跟进历史记录 -->
<view class="history-section">
<view class="section-header">
<view class="section-title">跟进历史记录</view>
<view class="record-count">{{historyRecords.length}}条记录</view>
</view>
<view class="history-list">
<view class="history-item" v-for="record in historyRecords" :key="record.id">
<view class="history-header">
<uni-icons type="time" size="16" color="#1989fa" />
<span class="history-date">{{record.date}}</span>
</view>
<view class="history-content">
<view class="history-row">
<span class="history-label">跟进方式</span>
<span class="history-value">{{record.method}}</span>
</view>
<view class="history-row">
<span class="history-label">跟进人</span>
<span class="history-value">{{record.follower}}</span>
</view>
<view class="history-row">
<span class="history-label">跟进内容</span>
<span class="history-value">{{record.content}}</span>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { ref, reactive, onMounted } from 'vue'
import { useRouter, useRoute } from 'uni-app'
export default {
name: 'HelpFollow',
setup() {
const router = useRouter()
const route = useRoute()
// 人员信息
const personInfo = reactive({
personName: '王小美',
helpType: '招聘岗位推荐'
})
// 跟进方式选项
const followMethods = ref(['电话', '微信', '邮件', '上门拜访', '视频会议', '其他'])
// 跟进表单数据
const followData = reactive({
followDate: '',
followMethod: '',
followContent: '',
followResult: '',
nextPlan: '',
nextContactDate: ''
})
// 历史记录数据
const historyRecords = ref([
{
id: 1,
date: '2025-11-05',
method: '电话',
follower: '新兴社区管理员',
content: '内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容。'
},
{
id: 2,
date: '2025-11-05',
method: '电话',
follower: '新兴社区管理员',
content: '内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容。'
}
])
// 返回上一页
const goBack = () => {
router.back()
}
// 重置表单
const resetForm = () => {
Object.keys(followData).forEach(key => {
followData[key] = ''
})
}
// 保存跟进记录
const saveFollowRecord = () => {
// 表单验证
if (!followData.followDate) {
uni.showToast({ title: '请选择跟进日期', icon: 'none' })
return
}
if (!followData.followMethod) {
uni.showToast({ title: '请选择跟进方式', icon: 'none' })
return
}
if (!followData.followContent) {
uni.showToast({ title: '请输入跟进内容', icon: 'none' })
return
}
if (!followData.followResult) {
uni.showToast({ title: '请输入跟进结果', icon: 'none' })
return
}
// 这里是模拟保存实际项目中应该调用API
console.log('保存跟进记录:', followData)
// 保存成功后添加到历史记录列表
const newRecord = {
id: historyRecords.value.length + 1,
date: followData.followDate,
method: followData.followMethod,
follower: '当前登录用户', // 实际应该从登录信息中获取
content: followData.followContent
}
historyRecords.value.unshift(newRecord)
// 清空表单
resetForm()
uni.showToast({ title: '保存成功', icon: 'success' })
}
// 跟进方式选择变化
const onFollowMethodChange = (e) => {
followData.followMethod = followMethods.value[e.detail.value]
}
onMounted(() => {
// 组件挂载时的初始化逻辑
// 可以从路由参数中获取人员ID等信息
console.log('路由参数:', route.query)
// 实际项目中应该根据ID加载人员信息和历史记录
// loadPersonInfo(route.query.personId)
// loadHistoryRecords(route.query.personId)
})
return {
personInfo,
followMethods,
followData,
historyRecords,
goBack,
resetForm,
saveFollowRecord,
onFollowMethodChange
}
}
}
</script>
<style scoped>
.help-follow-page {
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
background-color: #1989fa;
display: flex;
align-items: center;
padding: 20rpx 30rpx;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
}
.back-btn {
padding: 10rpx;
}
.title {
color: #fff;
font-size: 36rpx;
font-weight: bold;
flex: 1;
text-align: center;
margin-right: 60rpx;
}
.person-info-card {
background-color: #fff;
margin-top: 100rpx;
padding: 30rpx;
display: flex;
justify-content: space-around;
border-radius: 10rpx;
margin-bottom: 20rpx;
}
.info-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 10rpx;
}
.info-label {
font-size: 26rpx;
color: #666;
}
.info-value {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.follow-form-section {
background-color: #fff;
padding: 30rpx;
border-radius: 10rpx;
margin-bottom: 20rpx;
}
.history-section {
background-color: #fff;
padding: 30rpx;
border-radius: 10rpx;
margin-bottom: 30rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
}
.record-count {
font-size: 28rpx;
color: #999;
}
.form-item {
margin-bottom: 30rpx;
}
.form-label {
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
display: inline-block;
}
.required::before {
content: '*';
color: #ff4d4f;
margin-right: 5rpx;
}
.form-input {
width: 100%;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
}
.date-input {
background-color: #fafafa;
}
.form-picker {
width: 100%;
height: 80rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
display: flex;
align-items: center;
padding: 0 20rpx;
background-color: #fafafa;
}
.picker-text {
font-size: 28rpx;
color: #999;
}
.form-textarea {
width: 100%;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
padding: 20rpx;
font-size: 28rpx;
min-height: 150rpx;
resize: none;
}
.form-buttons {
display: flex;
gap: 20rpx;
margin-top: 40rpx;
}
.save-btn {
flex: 1;
background-color: #1989fa;
color: #fff;
font-size: 32rpx;
border: none;
height: 88rpx;
line-height: 88rpx;
}
.reset-btn {
flex: 1;
background-color: #fff;
color: #333;
font-size: 32rpx;
border: 1rpx solid #e0e0e0;
height: 88rpx;
line-height: 88rpx;
}
.history-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.history-item {
border: 1rpx solid #e0e0e0;
border-radius: 10rpx;
padding: 20rpx;
}
.history-header {
display: flex;
align-items: center;
margin-bottom: 15rpx;
gap: 10rpx;
}
.history-date {
font-size: 28rpx;
color: #1989fa;
font-weight: 500;
}
.history-content {
padding-left: 30rpx;
}
.history-row {
margin-bottom: 10rpx;
font-size: 28rpx;
}
.history-label {
color: #666;
margin-right: 10rpx;
}
.history-value {
color: #333;
}
</style>

View File

@@ -144,6 +144,7 @@
"navigationBarTitleTextSize": "30rpx"
}
}
],
"subpackages": [
{
@@ -314,7 +315,7 @@
"root": "packageB",
"pages": [
{
"path": "jobFair/detail",
"path": "jobFair/detailCom",
"style": {
"navigationBarTitleText": "招聘会详情",
"navigationBarTitleTextSize": "30rpx"

File diff suppressed because it is too large Load Diff

View File

@@ -593,8 +593,6 @@ const { columnCount, columnSpace } = useColumnCount(() => {
const getCompanyInfo = () => {
try {
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
console.log('缓存中的userInfo:', cachedUserInfo);
// 重置企业信息
companyInfo.name = '';
companyInfo.avatar = '';

View File

@@ -1,7 +1,8 @@
{
"description": "项目配置文件。",
"packOptions": {
"ignore": []
"ignore": [],
"include": []
},
"setting": {
"urlCheck": false,
@@ -9,28 +10,21 @@
"postcss": true,
"minified": true,
"newFeature": true,
"bigPackageSizeSupport": true
"bigPackageSizeSupport": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"condition": false
},
"compileType": "miniprogram",
"libVersion": "3.5.7",
"libVersion": "3.10.3",
"appid": "wx9d1cbc11c8c40ba7",
"projectname": "qingdao-employment-service",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"game": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": []
}
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}