Files
ks-app-employment-service/components/jobfair/signDialog.vue

639 lines
13 KiB
Vue
Raw Normal View History

2025-11-05 17:21:01 +08:00
<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>