<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>
|