岗位发布开发
This commit is contained in:
412
pages/job/companySearch.vue
Normal file
412
pages/job/companySearch.vue
Normal file
@@ -0,0 +1,412 @@
|
||||
<template>
|
||||
<view class="company-search-page">
|
||||
<!-- 头部导航 -->
|
||||
<view class="header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<image src="@/static/icon/back.png" class="back-icon"></image>
|
||||
</view>
|
||||
<view class="header-title">选择企业</view>
|
||||
<view class="header-right"></view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-container">
|
||||
<view class="search-box">
|
||||
<view class="search-icon">🔍</view>
|
||||
<input
|
||||
class="search-input"
|
||||
placeholder="请输入企业名称进行搜索"
|
||||
v-model="searchKeyword"
|
||||
@input="onSearchInput"
|
||||
@confirm="onSearchConfirm"
|
||||
/>
|
||||
<view class="clear-btn" v-if="searchKeyword" @click="clearSearch">
|
||||
<view class="clear-icon">✕</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索结果 -->
|
||||
<scroll-view class="content" scroll-y="true" :style="{ height: scrollViewHeight }">
|
||||
<!-- 加载状态 -->
|
||||
<view class="loading-container" v-if="loading">
|
||||
<view class="loading-text">搜索中...</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索结果列表 -->
|
||||
<view class="result-list" v-else-if="searchResults.length > 0">
|
||||
<view
|
||||
class="result-item"
|
||||
v-for="(company, index) in searchResults"
|
||||
:key="company.id || index"
|
||||
@click="selectCompany(company)"
|
||||
>
|
||||
<view class="company-info">
|
||||
<view class="company-name">{{ company.name }}</view>
|
||||
<view class="company-detail" v-if="company.address">
|
||||
<text class="detail-label">地址:</text>
|
||||
<text class="detail-value">{{ company.address }}</text>
|
||||
</view>
|
||||
<view class="company-detail" v-if="company.contact">
|
||||
<text class="detail-label">联系人:</text>
|
||||
<text class="detail-value">{{ company.contact }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="select-icon">
|
||||
<view class="arrow-icon">></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-container" v-else-if="searchKeyword && !loading">
|
||||
<view class="empty-icon">🔍</view>
|
||||
<view class="empty-text">未找到相关企业</view>
|
||||
<view class="empty-tip">请尝试其他关键词</view>
|
||||
</view>
|
||||
|
||||
<!-- 初始状态 -->
|
||||
<view class="initial-container" v-else-if="!searchKeyword">
|
||||
<view class="initial-icon">🔍</view>
|
||||
<view class="initial-text">请输入企业名称进行搜索</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部安全区域 -->
|
||||
<view class="bottom-safe-area"></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { createRequest } from '@/utils/request';
|
||||
|
||||
// 搜索相关状态
|
||||
const searchKeyword = ref('');
|
||||
const searchResults = ref([]);
|
||||
const loading = ref(false);
|
||||
const scrollViewHeight = ref('calc(100vh - 200rpx)');
|
||||
|
||||
// 防抖定时器
|
||||
let debounceTimer = null;
|
||||
|
||||
// 计算滚动视图高度
|
||||
const calculateScrollViewHeight = () => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const windowHeight = systemInfo.windowHeight;
|
||||
const headerHeight = 100; // 头部高度
|
||||
const searchHeight = 100; // 搜索框高度
|
||||
const scrollHeight = windowHeight - headerHeight - searchHeight;
|
||||
scrollViewHeight.value = `${scrollHeight}px`;
|
||||
};
|
||||
|
||||
// 页面加载时计算高度
|
||||
onMounted(() => {
|
||||
calculateScrollViewHeight();
|
||||
});
|
||||
|
||||
// 搜索输入处理(防抖)
|
||||
const onSearchInput = () => {
|
||||
// 清除之前的定时器
|
||||
if (debounceTimer) {
|
||||
clearTimeout(debounceTimer);
|
||||
}
|
||||
|
||||
// 设置新的定时器,500ms后执行搜索
|
||||
debounceTimer = setTimeout(() => {
|
||||
if (searchKeyword.value.trim()) {
|
||||
searchCompanies();
|
||||
} else {
|
||||
searchResults.value = [];
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
// 搜索确认
|
||||
const onSearchConfirm = () => {
|
||||
if (searchKeyword.value.trim()) {
|
||||
searchCompanies();
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索企业
|
||||
const searchCompanies = async () => {
|
||||
if (!searchKeyword.value.trim()) {
|
||||
searchResults.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
|
||||
const response = await createRequest('/app/company/likeList', {
|
||||
name: searchKeyword.value.trim()
|
||||
}, 'GET', false);
|
||||
|
||||
if (response.code === 200) {
|
||||
searchResults.value = response.data || [];
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: response.msg || '搜索失败',
|
||||
icon: 'none'
|
||||
});
|
||||
searchResults.value = [];
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('搜索企业失败:', error);
|
||||
uni.showToast({
|
||||
title: '搜索失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
searchResults.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 选择企业
|
||||
const selectCompany = (company) => {
|
||||
// 返回上一页并传递选中的企业信息
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
// 通过事件总线或全局数据传递选中的企业信息
|
||||
getApp().globalData = getApp().globalData || {};
|
||||
getApp().globalData.selectedCompany = company;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 清除搜索
|
||||
const clearSearch = () => {
|
||||
searchKeyword.value = '';
|
||||
searchResults.value = [];
|
||||
if (debounceTimer) {
|
||||
clearTimeout(debounceTimer);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.company-search-page {
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 30rpx;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 20rpx 30rpx;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #f8f8f8;
|
||||
border-radius: 12rpx;
|
||||
padding: 0 20rpx;
|
||||
height: 80rpx;
|
||||
|
||||
.search-icon {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 20rpx;
|
||||
|
||||
.clear-icon {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200rpx;
|
||||
|
||||
.loading-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.result-list {
|
||||
background: #fff;
|
||||
|
||||
.result-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.company-info {
|
||||
flex: 1;
|
||||
|
||||
.company-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.company-detail {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-bottom: 5rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.arrow-icon {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 400rpx;
|
||||
|
||||
.empty-icon {
|
||||
font-size: 120rpx;
|
||||
color: #ccc;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.initial-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 400rpx;
|
||||
|
||||
.initial-icon {
|
||||
font-size: 120rpx;
|
||||
color: #ccc;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.initial-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-safe-area {
|
||||
height: 120rpx;
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
@@ -10,12 +10,11 @@
|
||||
</view>
|
||||
|
||||
<!-- 主要内容 -->
|
||||
<view class="content">
|
||||
<!-- 岗位基本信息 -->
|
||||
<view class="section">
|
||||
<view class="section-title">岗位基本信息</view>
|
||||
<scroll-view class="content" scroll-y="true" :style="{ height: scrollViewHeight }" :scroll-with-animation="true">
|
||||
<!-- 基本信息区块 -->
|
||||
<view class="form-block">
|
||||
<view class="form-group">
|
||||
<view class="label">岗位名称 *</view>
|
||||
<view class="label">岗位名称</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入岗位名称"
|
||||
@@ -23,75 +22,41 @@
|
||||
/>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">岗位类型 *</view>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="jobTypes"
|
||||
@change="onJobTypeChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ selectedJobType || '请选择岗位类型' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">工作地点 *</view>
|
||||
<view class="label">招聘会公司</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入工作地点"
|
||||
v-model="formData.workLocation"
|
||||
placeholder="请输入公司名称"
|
||||
v-model="formData.companyName"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 薪资待遇 -->
|
||||
<view class="section">
|
||||
<view class="section-title">薪资待遇</view>
|
||||
<view class="salary-row">
|
||||
<view class="form-group">
|
||||
<view class="label">最低薪资</view>
|
||||
<input
|
||||
class="input salary-input"
|
||||
placeholder="0"
|
||||
type="number"
|
||||
v-model="formData.minSalary"
|
||||
/>
|
||||
</view>
|
||||
<view class="salary-separator">-</view>
|
||||
<view class="form-group">
|
||||
<view class="label">最高薪资</view>
|
||||
<input
|
||||
class="input salary-input"
|
||||
placeholder="0"
|
||||
type="number"
|
||||
v-model="formData.maxSalary"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">最小薪资 (元/月)</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入最小薪资"
|
||||
type="number"
|
||||
v-model="formData.minSalary"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">薪资单位</view>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="salaryUnits"
|
||||
@change="onSalaryUnitChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ selectedSalaryUnit || '请选择薪资单位' }}</view>
|
||||
</picker>
|
||||
<view class="label">最大薪资 (元/月)</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入最大薪资"
|
||||
type="number"
|
||||
v-model="formData.maxSalary"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 任职要求 -->
|
||||
<view class="section">
|
||||
<view class="section-title">任职要求</view>
|
||||
<view class="form-group">
|
||||
<view class="label">学历要求</view>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="educationLevels"
|
||||
range-key="label"
|
||||
@change="onEducationChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ selectedEducation || '请选择学历要求' }}</view>
|
||||
<view class="picker-text" data-placeholder="请选择学历要求">{{ selectedEducation || '请选择学历要求' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
@@ -99,10 +64,23 @@
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="experienceLevels"
|
||||
range-key="label"
|
||||
@change="onExperienceChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ selectedExperience || '请选择工作经验' }}</view>
|
||||
<view class="picker-text" data-placeholder="请选择工作经验">{{ selectedExperience || '请选择工作经验' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">工作区县</view>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="workDistricts"
|
||||
range-key="label"
|
||||
@change="onWorkDistrictChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text" data-placeholder="请选择工作区县">{{ selectedWorkDistrict || '请选择工作区县' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
@@ -114,21 +92,49 @@
|
||||
v-model="formData.recruitCount"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">工作地点</view>
|
||||
<view class="location-input-container">
|
||||
<input
|
||||
class="input location-input"
|
||||
placeholder="请输入具体工作地址"
|
||||
v-model="formData.jobLocation"
|
||||
/>
|
||||
<view class="location-btn" @click="chooseLocation">
|
||||
<text class="location-btn-text">选择位置</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">岗位分类</view>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="jobCategories"
|
||||
range-key="label"
|
||||
@change="onJobCategoryChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text" data-placeholder="请选择岗位分类">{{ selectedJobCategory || '请选择岗位分类' }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 岗位描述 -->
|
||||
<view class="section">
|
||||
<!-- 岗位描述区块 -->
|
||||
<view class="form-block">
|
||||
<view class="section-title">岗位描述</view>
|
||||
<view class="form-group">
|
||||
<view class="label">岗位职责</view>
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="请详细描述岗位职责和工作内容"
|
||||
v-model="formData.jobDescription"
|
||||
v-model="formData.description"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 任职要求区块 -->
|
||||
<view class="form-block">
|
||||
<view class="section-title">任职要求</view>
|
||||
<view class="form-group">
|
||||
<view class="label">任职要求</view>
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="请描述对候选人的具体要求"
|
||||
@@ -137,35 +143,52 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<view class="section">
|
||||
<!-- 联系方式区块 -->
|
||||
<view class="form-block">
|
||||
<view class="section-title">联系方式</view>
|
||||
<view class="form-group">
|
||||
<view class="label">联系人</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入联系人姓名"
|
||||
v-model="formData.contactPerson"
|
||||
/>
|
||||
<view class="contacts-container">
|
||||
<view
|
||||
class="contact-item"
|
||||
v-for="(contact, index) in formData.contacts"
|
||||
:key="index"
|
||||
>
|
||||
<view class="contact-header">
|
||||
<view class="contact-title">联系人 {{ index + 1 }}</view>
|
||||
<view
|
||||
class="delete-btn"
|
||||
v-if="formData.contacts.length > 1"
|
||||
@click="removeContact(index)"
|
||||
>
|
||||
删除
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">联系人姓名</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入联系人姓名"
|
||||
v-model="contact.name"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">联系电话</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入联系电话"
|
||||
v-model="contact.phone"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">联系电话</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入联系电话"
|
||||
v-model="formData.contactPhone"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<view class="label">联系邮箱</view>
|
||||
<input
|
||||
class="input"
|
||||
placeholder="请输入联系邮箱"
|
||||
v-model="formData.contactEmail"
|
||||
/>
|
||||
<view class="add-contact-btn" v-if="formData.contacts.length < 3" @click="addContact">
|
||||
<view class="add-icon">+</view>
|
||||
<view class="add-text">添加联系人</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部安全区域 -->
|
||||
<view class="bottom-safe-area"></view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="footer">
|
||||
@@ -178,49 +201,171 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { createRequest } from '@/utils/request';
|
||||
import useDictStore from '@/stores/useDictStore';
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
jobTitle: '',
|
||||
workLocation: '',
|
||||
companyName: '',
|
||||
minSalary: '',
|
||||
maxSalary: '',
|
||||
recruitCount: '',
|
||||
jobDescription: '',
|
||||
recruitCount: '', // 对应接口字段 idCardPictureBackUrl
|
||||
description: '', // 对应接口字段 description
|
||||
jobRequirements: '',
|
||||
contactPerson: '',
|
||||
contactPhone: '',
|
||||
contactEmail: ''
|
||||
jobCategory: '', // 新增:岗位分类
|
||||
companyId: '', // 新增:企业id
|
||||
latitude: '', // 新增:纬度
|
||||
longitude: '', // 新增:经度
|
||||
jobLocation: '', // 新增:工作地点
|
||||
jobLocationAreaCode: '', // 新增:工作地点区县字典代码
|
||||
education: '', // 新增:学历要求字典值
|
||||
experience: '', // 新增:工作经验字典值
|
||||
contacts: [
|
||||
{
|
||||
name: '',
|
||||
phone: ''
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// 字典存储
|
||||
const dictStore = useDictStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 选择器数据
|
||||
const jobTypes = ['技术类', '销售类', '管理类', '服务类', '其他'];
|
||||
const salaryUnits = ['元/月', '元/年', '元/小时'];
|
||||
const educationLevels = ['不限', '高中', '大专', '本科', '硕士', '博士'];
|
||||
const experienceLevels = ['不限', '应届毕业生', '1-3年', '3-5年', '5-10年', '10年以上'];
|
||||
const educationLevels = ref([]);
|
||||
const experienceLevels = ref([]);
|
||||
const workDistricts = ref([]);
|
||||
const workLocations = ref([]);
|
||||
const jobCategories = ref([]); // 新增:岗位分类选项
|
||||
|
||||
// 选中的值
|
||||
const selectedJobType = ref('');
|
||||
const selectedSalaryUnit = ref('');
|
||||
const selectedEducation = ref('');
|
||||
const selectedExperience = ref('');
|
||||
const selectedWorkDistrict = ref('');
|
||||
const selectedWorkLocation = ref('');
|
||||
const selectedJobCategory = ref('');
|
||||
|
||||
// 滚动视图高度
|
||||
const scrollViewHeight = ref('calc(100vh - 200rpx)');
|
||||
|
||||
// 计算滚动视图高度
|
||||
const calculateScrollViewHeight = () => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const windowHeight = systemInfo.windowHeight;
|
||||
const headerHeight = 100; // 头部高度
|
||||
const footerHeight = 120; // 底部按钮高度
|
||||
const scrollHeight = windowHeight - headerHeight - footerHeight;
|
||||
scrollViewHeight.value = `${scrollHeight}px`;
|
||||
};
|
||||
|
||||
// 页面加载时计算高度和初始化数据
|
||||
onMounted(async () => {
|
||||
calculateScrollViewHeight();
|
||||
await initFormData();
|
||||
});
|
||||
|
||||
// 初始化表单数据
|
||||
const initFormData = async () => {
|
||||
try {
|
||||
// 获取字典数据
|
||||
await dictStore.getDictData();
|
||||
|
||||
// 设置学历选项
|
||||
educationLevels.value = dictStore.state.education;
|
||||
|
||||
// 设置工作经验选项
|
||||
experienceLevels.value = dictStore.state.experience;
|
||||
|
||||
// 设置区县选项(从字典获取)
|
||||
workDistricts.value = dictStore.state.area;
|
||||
|
||||
// 设置岗位分类选项
|
||||
jobCategories.value = [
|
||||
{ label: '普通', value: '1' },
|
||||
{ label: '零工', value: '2' },
|
||||
{ label: '实习实训', value: '3' }
|
||||
];
|
||||
|
||||
// 设置企业ID(从用户信息获取)
|
||||
if (userStore.userInfo && userStore.userInfo.id) {
|
||||
formData.companyId = userStore.userInfo.id;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('初始化表单数据失败:', error);
|
||||
uni.showToast({
|
||||
title: '数据加载失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 选择器事件处理
|
||||
const onJobTypeChange = (e) => {
|
||||
selectedJobType.value = jobTypes[e.detail.value];
|
||||
};
|
||||
|
||||
const onSalaryUnitChange = (e) => {
|
||||
selectedSalaryUnit.value = salaryUnits[e.detail.value];
|
||||
};
|
||||
|
||||
const onEducationChange = (e) => {
|
||||
selectedEducation.value = educationLevels[e.detail.value];
|
||||
const index = e.detail.value;
|
||||
const selectedItem = educationLevels.value[index];
|
||||
selectedEducation.value = selectedItem.label;
|
||||
formData.education = selectedItem.value;
|
||||
};
|
||||
|
||||
const onExperienceChange = (e) => {
|
||||
selectedExperience.value = experienceLevels[e.detail.value];
|
||||
const index = e.detail.value;
|
||||
const selectedItem = experienceLevels.value[index];
|
||||
selectedExperience.value = selectedItem.label;
|
||||
formData.experience = selectedItem.value;
|
||||
};
|
||||
|
||||
const onWorkDistrictChange = (e) => {
|
||||
const index = e.detail.value;
|
||||
const selectedItem = workDistricts.value[index];
|
||||
selectedWorkDistrict.value = selectedItem.label;
|
||||
formData.jobLocationAreaCode = selectedItem.value;
|
||||
};
|
||||
|
||||
const onJobCategoryChange = (e) => {
|
||||
const index = e.detail.value;
|
||||
const selectedItem = jobCategories.value[index];
|
||||
selectedJobCategory.value = selectedItem.label;
|
||||
formData.jobCategory = selectedItem.value;
|
||||
};
|
||||
|
||||
// 选择位置
|
||||
const chooseLocation = () => {
|
||||
uni.chooseLocation({
|
||||
success: (res) => {
|
||||
formData.jobLocation = res.address;
|
||||
formData.latitude = res.latitude.toString();
|
||||
formData.longitude = res.longitude.toString();
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择位置失败:', err);
|
||||
uni.showToast({
|
||||
title: '获取位置失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加联系人
|
||||
const addContact = () => {
|
||||
if (formData.contacts.length < 3) {
|
||||
formData.contacts.push({
|
||||
name: '',
|
||||
phone: ''
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 删除联系人
|
||||
const removeContact = (index) => {
|
||||
if (formData.contacts.length > 1) {
|
||||
formData.contacts.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
@@ -229,49 +374,138 @@ const goBack = () => {
|
||||
};
|
||||
|
||||
// 发布岗位
|
||||
const publishJob = () => {
|
||||
// 简单验证
|
||||
if (!formData.jobTitle) {
|
||||
uni.showToast({
|
||||
title: '请输入岗位名称',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!formData.workLocation) {
|
||||
uni.showToast({
|
||||
title: '请输入工作地点',
|
||||
icon: 'none'
|
||||
});
|
||||
const publishJob = async () => {
|
||||
// 表单验证
|
||||
if (!validateForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 模拟发布成功
|
||||
uni.showLoading({
|
||||
title: '发布中...'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '发布成功',
|
||||
icon: 'success'
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '发布中...'
|
||||
});
|
||||
|
||||
// 构建请求数据
|
||||
const requestData = {
|
||||
jobTitle: formData.jobTitle,
|
||||
minSalary: formData.minSalary,
|
||||
maxSalary: formData.maxSalary,
|
||||
education: formData.education,
|
||||
experience: formData.experience,
|
||||
jobLocation: formData.jobLocation,
|
||||
jobLocationAreaCode: formData.jobLocationAreaCode,
|
||||
idCardPictureBackUrl: formData.recruitCount, // 招聘人数
|
||||
latitude: formData.latitude,
|
||||
longitude: formData.longitude,
|
||||
description: formData.description,
|
||||
jobCategory: formData.jobCategory,
|
||||
companyId: formData.companyId,
|
||||
companyName: formData.companyName,
|
||||
jobContactList: formData.contacts.filter(contact => contact.name.trim() && contact.phone.trim())
|
||||
};
|
||||
|
||||
// 调用发布接口
|
||||
const response = await createRequest('/app/job/publishJob', requestData, 'POST', false);
|
||||
|
||||
// 延迟返回
|
||||
setTimeout(() => {
|
||||
goBack();
|
||||
}, 1500);
|
||||
}, 2000);
|
||||
uni.hideLoading();
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({
|
||||
title: '发布成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 延迟返回
|
||||
setTimeout(() => {
|
||||
goBack();
|
||||
}, 1500);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: response.msg || '发布失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error('发布岗位失败:', error);
|
||||
uni.showToast({
|
||||
title: '发布失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 表单验证
|
||||
const validateForm = () => {
|
||||
// 必填字段验证
|
||||
const requiredFields = [
|
||||
{ field: 'jobTitle', message: '请输入岗位名称' },
|
||||
{ field: 'companyName', message: '请输入公司名称' },
|
||||
{ field: 'minSalary', message: '请输入最小薪资' },
|
||||
{ field: 'maxSalary', message: '请输入最大薪资' },
|
||||
{ field: 'education', message: '请选择学历要求' },
|
||||
{ field: 'experience', message: '请选择工作经验' },
|
||||
{ field: 'jobLocation', message: '请选择工作地点' },
|
||||
{ field: 'jobLocationAreaCode', message: '请选择工作区县' },
|
||||
{ field: 'recruitCount', message: '请输入招聘人数' },
|
||||
{ field: 'description', message: '请输入岗位描述' },
|
||||
{ field: 'jobCategory', message: '请选择岗位分类' }
|
||||
];
|
||||
|
||||
for (const { field, message } of requiredFields) {
|
||||
if (!formData[field] || formData[field].toString().trim() === '') {
|
||||
uni.showToast({
|
||||
title: message,
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 薪资验证
|
||||
const minSalary = parseFloat(formData.minSalary);
|
||||
const maxSalary = parseFloat(formData.maxSalary);
|
||||
|
||||
if (minSalary >= maxSalary) {
|
||||
uni.showToast({
|
||||
title: '最大薪资必须大于最小薪资',
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证联系人信息
|
||||
for (let i = 0; i < formData.contacts.length; i++) {
|
||||
const contact = formData.contacts[i];
|
||||
if (!contact.name.trim()) {
|
||||
uni.showToast({
|
||||
title: `请输入第${i + 1}个联系人姓名`,
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!contact.phone.trim()) {
|
||||
uni.showToast({
|
||||
title: `请输入第${i + 1}个联系人电话`,
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.publish-job-page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 120rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -307,16 +541,17 @@ const publishJob = () => {
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section {
|
||||
.form-block {
|
||||
background: #fff;
|
||||
border-radius: 0;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
width: 100%;
|
||||
|
||||
position: relative;
|
||||
padding-bottom: 10rpx;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@@ -326,23 +561,27 @@ const publishJob = () => {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 20rpx;
|
||||
padding: 30rpx 30rpx 20rpx 30rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 30rpx;
|
||||
margin-bottom: 0;
|
||||
padding: 0 30rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
border-bottom: none;
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
color: #000;
|
||||
margin-bottom: 15rpx;
|
||||
font-weight: 500;
|
||||
font-weight: 400;
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
@@ -350,15 +589,23 @@ const publishJob = () => {
|
||||
height: 80rpx;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-bottom: 2rpx solid #e0e0e0;
|
||||
border-radius: 0;
|
||||
padding: 0 0 10rpx 0;
|
||||
padding: 0 0 20rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-bottom-color: #256BFA;
|
||||
background: #fff;
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,15 +614,23 @@ const publishJob = () => {
|
||||
min-height: 120rpx;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-bottom: 2rpx solid #e0e0e0;
|
||||
border-radius: 0;
|
||||
padding: 20rpx 0 10rpx 0;
|
||||
padding: 0 0 20rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-bottom-color: #256BFA;
|
||||
background: #fff;
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,38 +639,132 @@ const publishJob = () => {
|
||||
height: 80rpx;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-bottom: 2rpx solid #e0e0e0;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 0 10rpx 0;
|
||||
justify-content: space-between;
|
||||
padding: 0 0 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.picker-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
|
||||
&:empty::before {
|
||||
content: attr(data-placeholder);
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 8rpx solid transparent;
|
||||
border-right: 8rpx solid transparent;
|
||||
border-top: 8rpx solid #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.salary-row {
|
||||
// 联系人管理样式
|
||||
.contacts-container {
|
||||
.contact-item {
|
||||
margin-bottom: 30rpx;
|
||||
padding: 0 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.contact-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0 10rpx 0;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.contact-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
font-size: 24rpx;
|
||||
color: #ff4757;
|
||||
padding: 8rpx 16rpx;
|
||||
background: #fff;
|
||||
border: 1rpx solid #ff4757;
|
||||
border-radius: 6rpx;
|
||||
|
||||
&:active {
|
||||
background: #ff4757;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
background: transparent;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
margin-bottom: 0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 10rpx;
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-size: 26rpx;
|
||||
padding-bottom: 15rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-contact-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
justify-content: center;
|
||||
margin: 20rpx 30rpx 30rpx 30rpx;
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
border: 2rpx dashed #ddd;
|
||||
border-radius: 12rpx;
|
||||
|
||||
.form-group {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.salary-separator {
|
||||
.add-icon {
|
||||
font-size: 32rpx;
|
||||
color: #666;
|
||||
margin-top: 40rpx;
|
||||
color: #256BFA;
|
||||
margin-right: 10rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.salary-input {
|
||||
text-align: center;
|
||||
.add-text {
|
||||
font-size: 28rpx;
|
||||
color: #256BFA;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #e3f2fd;
|
||||
border-color: #256BFA;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-safe-area {
|
||||
height: 120rpx;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.footer {
|
||||
@@ -426,6 +775,7 @@ const publishJob = () => {
|
||||
background: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
z-index: 100;
|
||||
|
||||
.btn-group {
|
||||
display: flex;
|
||||
@@ -451,4 +801,28 @@ const publishJob = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 防止键盘弹出时页面偏移 */
|
||||
/* #ifdef H5 */
|
||||
.publish-job-page {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
-webkit-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
.publish-job-page * {
|
||||
-webkit-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.publish-job-page {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user