特易招,招聘小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

504 lines
13 KiB

<template>
<uv-popup ref="popup" mode="bottom" :round="30"
:safeAreaInsetBottom="false" @close="handleClose">
<view class="job-type-picker">
<view class="header">
<view class="title">选择工种</view>
<view class="close-btn" @click="close">
<uv-icon name="close" size="40rpx"></uv-icon>
</view>
</view>
<view class="content">
<!-- 左侧一级工种列表 -->
<view class="left-panel">
<scroll-view scroll-y class="scroll-view">
<!-- 插槽自定义内容 -->
<slot name="custom-options"></slot>
<view
class="job-type-item"
:class="{ active: selectedParentType && selectedParentType.id === item.id }"
v-for="item in jobTypeList"
:key="item.id"
@click="selectParentType(item)">
{{ item.name }}
</view>
</scroll-view>
</view>
<!-- 右侧二三级工种列表 -->
<view class="right-panel">
<scroll-view scroll-y class="scroll-view">
<!-- 二级工种 -->
<template v-if="selectedParentType && !selectedSubType">
<!-- 选择整个工种选项 -->
<view
v-if="showSelectWholeType"
class="job-type-item whole-type-item"
@click="selectWholeParentType">
<uv-icon name="checkmark-circle" size="30rpx" color="#3796F8"></uv-icon>
选择整个{{ selectedParentType.name }}
</view>
<view
class="job-type-item"
:class="{
'selected': multiple && isSubTypeSelected(item),
'active': !multiple && selectedSubType && selectedSubType.id === item.id
}"
v-for="item in subTypeList"
:key="item.id"
@click="selectSubType(item)">
{{ item.name }}
<uv-icon v-if="multiple && isSubTypeSelected(item)"
name="checkmark-circle" size="30rpx" color="#3796F8"></uv-icon>
</view>
<!-- 多选时的确认按钮 -->
<view v-if="multiple && selectedSubTypes.length > 0"
class="confirm-btn" @click="confirmMultipleSubTypeSelection">
<button class="confirm-button">确认选择工种 ({{ selectedSubTypes.length }})</button>
</view>
</template>
<!-- 三级工种 -->
<template v-if="selectedSubType">
<view
class="job-type-item back-item"
@click="backToSubType">
<uv-icon name="arrow-left" size="30rpx"></uv-icon>
返回{{ selectedParentType.name }}
</view>
<!-- 选择整个子工种选项 -->
<view
v-if="showSelectWholeType"
class="job-type-item whole-type-item"
@click="selectWholeSubType">
<uv-icon name="checkmark-circle" size="30rpx" color="#3796F8"></uv-icon>
选择整个{{ selectedSubType.name }}
</view>
<view
class="job-type-item"
:class="{
'selected': multiple && isDetailTypeSelected(item),
'active': !multiple && selectedDetailType && selectedDetailType.id === item.id
}"
v-for="item in detailTypeList"
:key="item.id"
@click="selectDetailType(item)">
{{ item.name }}
<uv-icon v-if="multiple && isDetailTypeSelected(item)"
name="checkmark-circle" size="30rpx" color="#3796F8"></uv-icon>
</view>
<!-- 多选时的确认按钮 -->
<view v-if="multiple && selectedDetailTypes.length > 0"
class="confirm-btn" @click="confirmMultipleSelection">
<button class="confirm-button">确认选择 ({{ selectedDetailTypes.length }})</button>
</view>
</template>
</scroll-view>
</view>
</view>
</view>
</uv-popup>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'JobTypePicker',
props: {
// 是否只选择到二级工种,不选择三级
onlySubType: {
type: Boolean,
default: false
},
// 是否支持多选
multiple: {
type: Boolean,
default: false
},
// 是否显示"选择整个工种"选项
showSelectWholeType: {
type: Boolean,
default: true
}
},
data() {
return {
selectedParentType: null, // 选中的一级工种
selectedSubType: null, // 选中的二级工种
selectedDetailType: null, // 选中的三级工种
selectedSubTypes: [], // 多选时选中的二级工种列表
selectedDetailTypes: [], // 多选时选中的三级工种列表
subTypeList: [], // 二级工种列表
detailTypeList: [], // 三级工种列表
}
},
computed: {
...mapState(['jobTypeList'])
},
methods: {
// 打开弹窗
open() {
this.$refs.popup.open()
},
// 关闭弹窗
close() {
this.$refs.popup.close()
},
// 弹窗关闭时重置状态
handleClose() {
this.selectedParentType = null
this.selectedSubType = null
this.selectedDetailType = null
this.selectedSubTypes = []
this.selectedDetailTypes = []
this.subTypeList = []
this.detailTypeList = []
},
// 选择一级工种
async selectParentType(parentType) {
this.selectedParentType = parentType
this.selectedSubType = null
this.selectedDetailType = null
this.detailTypeList = []
// 获取二级工种列表
try {
this.subTypeList = await this.$store.dispatch('getChildJobTypeList', parentType.id)
// 如果没有下级工种,直接确认选择
if (this.subTypeList.length === 0) {
this.confirm()
}
} catch (error) {
console.error('获取二级工种列表失败:', error)
this.subTypeList = []
// 获取失败时也直接确认
this.confirm()
}
},
// 选择二级工种
async selectSubType(subType) {
if (this.multiple) {
// 多选模式
const index = this.selectedSubTypes.findIndex(item => item.id === subType.id)
if (index > -1) {
// 取消选择
this.selectedSubTypes.splice(index, 1)
} else {
// 添加选择
this.selectedSubTypes.push(subType)
}
} else {
// 单选模式
this.selectedSubType = subType
this.selectedDetailType = null
// 如果只选择到二级工种,直接确认
if (this.onlySubType) {
this.confirm()
return
}
// 获取三级工种列表
try {
this.detailTypeList = await this.$store.dispatch('getChildJobTypeList', subType.id)
// 如果没有下级工种,直接确认
if (this.detailTypeList.length === 0) {
this.confirm()
}
} catch (error) {
console.error('获取三级工种列表失败:', error)
this.detailTypeList = []
// 获取失败时也直接确认
this.confirm()
}
}
},
// 选择三级工种
selectDetailType(detailType) {
if (this.multiple) {
// 多选模式
const index = this.selectedDetailTypes.findIndex(item => item.id === detailType.id)
if (index > -1) {
// 取消选择
this.selectedDetailTypes.splice(index, 1)
} else {
// 添加选择
this.selectedDetailTypes.push(detailType)
}
} else {
// 单选模式
this.selectedDetailType = detailType
this.confirm()
}
},
// 检查二级工种是否被选中(多选模式)
isSubTypeSelected(subType) {
return this.selectedSubTypes.some(item => item.id === subType.id)
},
// 检查三级工种是否被选中(多选模式)
isDetailTypeSelected(detailType) {
return this.selectedDetailTypes.some(item => item.id === detailType.id)
},
// 选择整个一级工种
selectWholeParentType() {
this.selectedSubType = null
this.selectedSubTypes = []
this.selectedDetailType = null
this.selectedDetailTypes = []
this.confirm()
},
// 选择整个二级工种
selectWholeSubType() {
this.selectedDetailType = null
this.selectedDetailTypes = []
this.confirm()
},
// 确认多选二级工种选择
confirmMultipleSubTypeSelection() {
// 直接返回多选二级工种的数据
this.confirm()
},
// 确认多选选择
confirmMultipleSelection() {
this.confirm()
},
// 返回二级工种选择
backToSubType() {
this.selectedSubType = null
this.selectedDetailType = null
this.detailTypeList = []
},
// 确认选择
confirm() {
const result = {
parentType: this.selectedParentType,
subType: this.selectedSubType,
detailType: this.selectedDetailType,
subTypes: this.selectedSubTypes,
detailTypes: this.selectedDetailTypes
}
// 生成完整工种文本
let fullJobType = ''
let selectedId = '' // 用于传给后端的ID
let selectedIds = [] // 多选时的ID数组
if (this.selectedParentType) {
fullJobType += this.selectedParentType.name
}
// 多选二级工种模式
if (this.multiple && this.selectedSubTypes.length > 0) {
const subTypeNames = this.selectedSubTypes.map(item => item.name).join(',')
fullJobType = subTypeNames
result.selectedJobType = this.selectedParentType // 多选二级工种时返回一级工种作为选中工种
result.selectedSubTypes = this.selectedSubTypes
// 返回多选二级工种的ID数组
selectedIds = this.selectedSubTypes.map(item => item.id)
result.selectedIds = selectedIds
} else if (this.selectedSubType) {
fullJobType += this.selectedSubType.name
// 多选三级工种模式
if (this.multiple && this.selectedDetailTypes.length > 0) {
const detailTypeNames = this.selectedDetailTypes.map(item => item.name).join(',')
fullJobType += detailTypeNames
result.selectedJobType = this.selectedSubType // 多选时返回二级工种作为选中工种
result.selectedDetailTypes = this.selectedDetailTypes
// 返回多选三级工种的ID数组
selectedIds = this.selectedDetailTypes.map(item => item.id)
result.selectedIds = selectedIds
} else if (this.selectedDetailType) {
// 单选三级工种模式
fullJobType += this.selectedDetailType.name
result.selectedJobType = this.selectedDetailType
selectedId = this.selectedDetailType.id
} else {
// 选择整个二级工种
result.selectedJobType = this.selectedSubType
selectedId = this.selectedSubType.id
}
} else {
// 选择整个一级工种
result.selectedJobType = this.selectedParentType
selectedId = this.selectedParentType.id
}
result.fullJobType = fullJobType
result.selectedId = selectedId // 单选时的ID
result.selectedIds = selectedIds // 多选时的ID数组
this.$emit('confirm', result)
this.close()
}
}
}
</script>
<style scoped lang="scss">
.job-type-picker {
height: 70vh;
background: #fff;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #eee;
.title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.close-btn {
padding: 10rpx;
}
}
.content {
display: flex;
height: calc(70vh - 160rpx);
.left-panel {
width: 240rpx;
border-right: 1px solid #eee;
background: #f8f8f8;
}
.right-panel {
flex: 1;
}
.scroll-view {
height: 100%;
}
.job-type-item {
padding: 30rpx 20rpx;
font-size: 28rpx;
color: #333;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
&.active {
background: #fff;
color: $uni-color;
font-weight: bold;
position: relative;
&::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 6rpx;
background: $uni-color;
}
}
&.back-item {
display: flex;
align-items: center;
color: $uni-color;
background: #f8f8f8;
uv-icon {
margin-right: 10rpx;
}
}
&.whole-type-item {
display: flex;
align-items: center;
color: #3796F8;
background: rgba(#3796F8, 0.1);
font-weight: bold;
uv-icon {
margin-right: 10rpx;
}
}
&.selected {
background: rgba($uni-color, 0.1);
color: $uni-color;
font-weight: bold;
position: relative;
&::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 6rpx;
background: $uni-color;
}
}
}
.left-panel {
.select-all-item {
display: flex;
align-items: center;
color: #3796F8;
background: rgba(#3796F8, 0.1);
font-weight: bold;
padding: 30rpx 20rpx;
font-size: 28rpx;
border-bottom: 1px solid #f0f0f0;
uv-icon {
margin-right: 10rpx;
}
}
}
.confirm-btn {
position: sticky;
bottom: 0;
background: #fff;
padding: 20rpx;
border-top: 1px solid #eee;
.confirm-button {
width: 100%;
background: $uni-color;
color: #fff;
border: none;
border-radius: 10rpx;
padding: 20rpx;
font-size: 28rpx;
}
}
}
}
</style>