当前位置: 首页 > news >正文

【vue3+vant】移动端 - 部门树下拉选择组件 DeptTreeSelect 开发

目录

  • 效果展示
  • 代码
    • 父组件
    • 子组件 DeptTreeSelect

效果展示

在这里插入图片描述

代码

父组件

父组件使用子组件

<template><div class="supervision-report"><van-fieldv-model="infoView.ssbm"name="ssbm"label="督察对象部门"placeholder="请选择督查对象部门"readonlyright-icon="arrow-down"required:rules="[{ required: true, message: '请选择督察对象部门' }]"@click="showPickerHandle('ssbm')"/><!-- 省略无关代码 --><van-popupv-model:show="isShowPicker"position="bottom":close-on-click-overlay="curColumnsKey !== 'ssbm'"><DetpTreeSelect:init-dept-tree="columnsObj.ssbm"@close="isShowPicker = false"@setValue="setSsbm"/></van-popup></div>
</template><script>
import { ref, onMounted } from 'vue'import { getDeptTree } from '@/api/global-dict-service'export default {setup() {const info = reactive({ssbm: ''})const infoView = reactive({ssbm: ''})const isShowPicker = ref(false)const curColumnsKey = ref('')const columnsObj = reactive({ssbm: []})onMounted(() => {getDept()})const getDept = () => {getDeptTree({}).then(res => {columnsObj.ssbm = res.data || [] // 数据格式在子组件中有})}const showPickerHandle = key => {curColumnsKey.value = keyif (['fssj'].includes(key)) {const curTime = info.fssjcurTime ? (currentDate.value = new Date(curTime)) : new Date()}isShowPicker.value = true}const setSsbm = val => {console.log('val----打印', val)info.ssbm = val.dwdminfoView.ssbm = val.dwjc}return {info,infoView,showPickerHandle,columnsObj,isShowPicker,curColumnsKey,setSsbm}}
}
</script><style lang="less" scoped>
@bgc: #f3f4f6;.supervision-report {height: 100vh;background-color: #fff;.van-form {overflow: auto;}:deep(.van-cell) {@lineHeight: 40px;padding: 10px;&:nth-child(-n + 8) {label {line-height: @lineHeight;}}input {height: @lineHeight;}}:deep(.van-field__body) {background-color: @bgc;border-radius: 5px;padding: 0 10px;}.iconfont,:deep(.van-field__right-icon .van-icon) {font-size: 14px;}.field_block {display: block;}:deep(.van-uploader) {width: 100%;.van-uploader__input-wrapper {width: 100%;border-top: 1px dashed #ccc;.upload_btn {height: 100px;width: 100%;border-radius: 5px;display: flex;flex-direction: column;align-items: center;justify-content: center;color: #9ca3af;font-size: 14px;}}}.upload_tips {margin: 0 20px 10px;color: #9ca3af;word-break: break-all;font-size: 14px;}.btns {display: flex;justify-content: space-between;margin: 0 20px 20px;.van-button {flex: 1;border-radius: 5px;&:first-child {margin-right: 10px;}}}.dialog_father {width: 100%;height: 100vh;position: fixed;top: 0;left: 0;background-color: #423e3e39;display: flex;align-items: center;justify-content: center;.dialog {background-color: #fff;width: 95%;padding: 10px;border-radius: 10px;box-sizing: border-box;&_header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;font-size: 18px;.title {}.close {padding: 5px;font-size: 22px;color: #9ca3af;}}&_body {.TMap {width: 100%;height: 70vh;}}&_footer {display: flex;gap: 10px;margin-top: 10px;.van-button {flex: 1;}}}}
}
</style>

子组件 DeptTreeSelect

@/components/DeptTreeSelect.vue

<!-- 部门树下拉选择组件 -->
<template><div class="area-picker"><div class="btns"><span @click="reset">取消</span><span class="blue" @click="handleConfirm">确定</span></div><!-- 已选择的部门数据 --><div class="header"><spanv-for="(selectedArea, index) in selectedAreas":key="selectedArea.data.dwdm"@click="toggleArea(selectedArea, index)">{{ selectedArea.data?.dwjc }}<i v-if="index < selectedAreas.length - 1" class="arrow"> > </i></span></div><!-- 当前可选择的部门数据 --><div class="body"><divv-for="area in renderAreaList":key="area.data.dwdm"class="body_item"@click="selectDeptFun(area)">{{ area.data?.dwjc }}<span v-if="selectedAreas.includes(area)" class="blue font_weight"></span></div></div></div>
</template><script setup name="DeptTreeSelect">
import { ref } from 'vue'
import { Toast } from 'vant'// initDeptTree 为父组件传的部门树数据
const { initDeptTree } = defineProps({initDeptTree: {type: Array,default: () => [{data: {dwdm: '330000000000',dwmc: '台州市公安局',dwjc: '台州市局',sjdwdm: null},childrenNode: [{data: {dwdm: '33100000011X',dwmc: '仙居县局',dwjc: '台州市局-仙居县局',sjdwdm: '330000000000'},childrenNode: []},{data: {dwdm: '33100000012X',dwmc: '天台县局',dwjc: '台州市局-天台县局',sjdwdm: '330000000000'},childrenNode: []},{data: {dwdm: '33100000013X',dwmc: '三门县局',dwjc: '台州市局-三门县局',sjdwdm: '330000000000'},childrenNode: []},{data: {dwdm: '331000290000',dwmc: '市局各部门',dwjc: '台州市局-市局各部门',sjdwdm: '330000000000'},childrenNode: []}]},{data: {dwdm: '335401000010',dwmc: '高一大队',dwjc: '高一大队',sjdwdm: null},childrenNode: [{data: {dwdm: '33540100001A',dwmc: '一中队',dwjc: '高一大队-一中队',sjdwdm: '335401000010'},childrenNode: []},{data: {dwdm: '33540100001B',dwmc: ' 二中队',dwjc: '高一大队- 二中队',sjdwdm: '335401000010'},childrenNode: []},{data: {dwdm: '33540100001C',dwmc: '三中队',dwjc: '高一大队-三中队',sjdwdm: '335401000010'},childrenNode: []},{data: {dwdm: '33540100001D',dwmc: '四中队',dwjc: '高一大队-四中队',sjdwdm: '335401000010'},childrenNode: []}]}]}
})
const emit = defineEmits(['setValue', 'close'])const renderAreaList = ref([...initDeptTree]) // 存储渲染的区域数据
const selectedAreas = ref([]) // 已选择的部门数据 -- header 部分渲染的数据// 点击 header 部分切换已选择部门
const toggleArea = (area, toggleClickIndex) => {renderAreaList.value =toggleClickIndex === 0? [...initDeptTree]: selectedAreas.value[toggleClickIndex - 1].childrenNodeselectedAreas.value = selectedAreas.value.slice(0, toggleClickIndex)
}// 选中部门时处理
const selectDeptFun = area => {if (area.childrenNode.length > 0) {renderAreaList.value = area.childrenNode} else {const index = selectedAreas.value.findIndex(item => item.data.sjdwdm === area.data.sjdwdm)if (index !== -1) {selectedAreas.value.splice(index, 1)}}selectedAreas.value.push(area)
}// 重置部门数据
const reset = () => {selectedAreas.value = []renderAreaList.value = [...initDeptTree]emit('close')
}// 确定选择部门
const handleConfirm = () => {if (!selectedAreas.value.length) {Toast('请选择部门')return}const value = selectedAreas.value[selectedAreas.value.length - 1].dataemit('setValue', value)reset()
}
</script><style scoped lang="less">
.area-picker {background-color: #e8e7ea;max-height: 50vh;min-height: 30vh;// overflow: auto;display: flex;flex-direction: column;.blue {color: #3970e3;}.font_weight {font-weight: bold;}.btns {display: flex;justify-content: space-between;padding: 10px;background-color: #fff;border-bottom: 1px solid #ccc;font-size: 18px;}.header {background-color: #fff;margin-bottom: 10px;padding: 5px 10px;font-size: 16px;.arrow {margin: 0 5px;}}.body {flex: 1;overflow: auto;padding: 0 8px;background-color: #fff;font-size: 16px;&_item {display: flex;padding: 8px;justify-content: space-between;border-bottom: 1px solid #eee;}}
}
</style>

http://www.mrgr.cn/news/95138.html

相关文章:

  • ASP3605抗辐照加固同步降压调节器——商业航天电源芯片解决方案新选择
  • [蓝桥杯 2023 省 B] 飞机降落(不会dfs的看过来)
  • 使用Streamlit快速构建数据应用程序
  • C#基于MVC模式实现TCP三次握手,附带简易日志管理模块
  • 【QT】】qcustomplot的初步使用二
  • 工具层handle_excel
  • WebSocket 中的条件竞争漏洞 -- UTCTF Chat
  • 如何编译鲁班猫(LubanCat 1N)固件
  • FOC——Butterworth (巴特沃斯)数字滤波器(2025.03.18)
  • 关于Docker是否被淘汰虚拟机实现连接虚拟专用网络Ubuntu 22.04 LTS部署Harbor仓库全流程
  • VSCode扩展工具Copilot MCP使用教程【MCP】
  • 【GNN】0.环境配置
  • 虚幻基础:ue自定义类
  • ASP3605同步降压调节器——高可靠工业电源芯片解决方案
  • Debezium + Kafka-connect 实现Postgres实时同步Hologres
  • golang中的接口
  • ASP3605同步降压调节器——满足汽车电子严苛要求的电源芯片方案
  • numpy学习笔记14:模拟随机游走过程(一次实验)
  • std::expected
  • [入门]NUC13配置Ubuntu20.04详细步骤