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

uniapp使用uview UI,自定义级联选择组件

一、需求:

1.省市区级联选择,可多选
2.可以一键选择某个区域下的所有数据
3.点击省展开市,点击市展开区,以此类推(可返回上一层或多层)
4.只获取选择的人

效果视频

二、注意事项以及源码

1.需要安装uView UI组件库,安装地址uView UI官网

2.源码,复制即用

<template><view class="container"><!-- 层级导航 --><view class="breadcrumb"><text class="breadcrumb-item" v-for="(item, index) in breadcrumbList" :key="index" @click="goBackToLevel(index)":class="{ 'breadcrumb-item-active': index === breadcrumbList.length - 1 }">{{ item }}<text v-if="index !== breadcrumbList.length - 1" class="breadcrumb-separator"> ></text></text></view><!-- 层级内容 --><view class="level-content"><view class="level-item" v-for="(item, index) in currentLevelData" :key="item.id"><!-- 将点击事件移到内部元素,避免与复选框冲突 --><view class="level-item-left" @click="handleLevelItemClick(item)"><view class="level-icon" :style="{ backgroundColor: getLevelColor(item) }"><text class="level-icon-text">{{ getLevelCode(item) }}</text></view><view class="level-info"><text class="level-title">{{ item.name }}</text><text class="level-desc">{{ item.leaf ? item.emergencyPersonnel.phone : `${getAllLeafCount(item)} 个人员` }}</text></view></view><view class="select-checkbox"><u-checkbox :checked="isNodeSelected(item)" :indeterminate="isNodeIndeterminate(item)"@change="(value) => handleNodeSelect(item, value)" shape="circle" active-color="#4F46E5"></u-checkbox></view></view></view><!-- 底部操作栏 --><view class="footer-bar"><view class="selected-info"><u-icon name="account-fill" size="30" color="#4F46E5"></u-icon><text class="selected-count">已选择 {{ selectedPersons.length }}</text></view><u-button type="primary" @click="toFormPage" :disabled="selectedPersons.length === 0"class="next-button">下一步</u-button></view></view>
</template><script>
export default {data() {return {// 人员数据结构(修改后:新增省份、简化字段、常见姓名)personnelData: [{"id": "510000","name": "四川省","children": [{"id": "511400","name": "眉山市","children": [{"id": "市管理员","name": "市管理员","children": [{"id": "10","name": "赵六","children": [],"emergencyPersonnel": {"unitName": "市管理员","unitAddress": "眉山市政务服务中心","personName": "赵六","phone": "19162984018","provinceName": "四川省","cityName": "眉山市","countyName": ""},"leaf": true},{"id": "11","name": "孙七","children": [],"emergencyPersonnel": {"unitName": "市管理员","unitAddress": "眉山市政务服务中心","personName": "孙七","phone": "18180809001","provinceName": "四川省","cityName": "眉山市","countyName": ""},"leaf": true}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false},{"id": "440000","name": "广东省","children": [{"id": "440100","name": "广州市","children": [{"id": "天河区管理员","name": "天河区管理员","children": [{"id": "12","name": "周八","children": [],"emergencyPersonnel": {"unitName": "天河区管理员","unitAddress": "广州市天河区政务中心","personName": "周八","phone": "18228880309","provinceName": "广东省","cityName": "广州市","countyName": "天河区"},"leaf": true},{"id": "13","name": "吴九","children": [],"emergencyPersonnel": {"unitName": "天河区管理员","unitAddress": "广州市天河区政务中心","personName": "吴九","phone": "18990370720","provinceName": "广东省","cityName": "广州市","countyName": "天河区"},"leaf": true}],"emergencyPersonnel": null,"leaf": false},{"id": "海珠区管理员","name": "海珠区管理员","children": [{"id": "14","name": "郑十","children": [],"emergencyPersonnel": {"unitName": "海珠区管理员","unitAddress": "广州市海珠区政务中心","personName": "郑十","phone": "15508337779","provinceName": "广东省","cityName": "广州市","countyName": "海珠区"},"leaf": true}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false},{"id": "440300","name": "深圳市","children": [{"id": "南山区管理员","name": "南山区管理员","children": [{"id": "15","name": "钱十一","children": [],"emergencyPersonnel": {"unitName": "南山区管理员","unitAddress": "深圳市南山区政务中心","personName": "钱十一","phone": "15983336111","provinceName": "广东省","cityName": "深圳市","countyName": "南山区"},"leaf": true}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false},{"id": "330000","name": "浙江省","children": [{"id": "330100","name": "杭州市","children": [{"id": "西湖区管理员","name": "西湖区管理员","children": [{"id": "16","name": "冯十二","children": [],"emergencyPersonnel": {"unitName": "西湖区管理员","unitAddress": "杭州市西湖区政务中心","personName": "冯十二","phone": "18783398823","provinceName": "浙江省","cityName": "杭州市","countyName": "西湖区"},"leaf": true},{"id": "17","name": "陈十三","children": [],"emergencyPersonnel": {"unitName": "西湖区管理员","unitAddress": "杭州市西湖区政务中心","personName": "陈十三","phone": "13547674447","provinceName": "浙江省","cityName": "杭州市","countyName": "西湖区"},"leaf": true}],"emergencyPersonnel": null,"leaf": false},{"id": "余杭区管理员","name": "余杭区管理员","children": [{"id": "18","name": "褚十四","children": [],"emergencyPersonnel": {"unitName": "余杭区管理员","unitAddress": "杭州市余杭区政务中心","personName": "褚十四","phone": "18160172259","provinceName": "浙江省","cityName": "杭州市","countyName": "余杭区"},"leaf": true}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false}],"emergencyPersonnel": null,"leaf": false}],// 当前层级数据currentLevelData: [],// 层级导航路径breadcrumbList: [],// 已选择的人员selectedPersons: [],// 层级历史记录,用于返回levelHistory: []};},onLoad() {// 初始化层级数据(因personnelData改为数组,此处调整为加载所有省份)this.currentLevelData = this.personnelData;this.breadcrumbList = ["全国"];this.levelHistory = [this.currentLevelData];},methods: {// 获取层级颜色getLevelColor(item) {if (item.leaf) {return '#E0E7FF';}const colors = ['#E0F2FE', '#DBEAFE', '#EFF6FF', '#F0FDF4', '#FEF3C7'];let hash = 0;for (let i = 0; i < item.name.length; i++) {hash = item.name.charCodeAt(i) + ((hash << 5) - hash);}return colors[Math.abs(hash) % colors.length];},// 获取层级代码getLevelCode(item) {if (item.leaf) {return item.name.charAt(0);}return item.name.substring(0, 2);},// 递归获取某个节点下的所有叶子节点getAllLeafNodes(node) {let leafNodes = [];if (node.leaf) {leafNodes.push(node);} else if (node.children && node.children.length > 0) {node.children.forEach(child => {leafNodes = leafNodes.concat(this.getAllLeafNodes(child));});}return leafNodes;},// 计算某个节点下的叶子节点总数getAllLeafCount(node) {return this.getAllLeafNodes(node).length;},// 判断某个节点的选中状态isNodeSelected(node) {const leafNodes = this.getAllLeafNodes(node);if (node.leaf) {return this.selectedPersons.some(p => p.id === node.id);}return leafNodes.every(leaf =>this.selectedPersons.some(p => p.id === leaf.id));},// 判断某个非叶子节点是否半选isNodeIndeterminate(node) {if (node.leaf) return false;const leafNodes = this.getAllLeafNodes(node);const selectedLeafCount = leafNodes.filter(leaf =>this.selectedPersons.some(p => p.id === leaf.id)).length;return selectedLeafCount > 0 && selectedLeafCount < leafNodes.length;},// 将叶子节点转换为selectedPersons格式convertLeafToSelected(leafNode) {return {id: leafNode.id,name: leafNode.name,phone: leafNode.emergencyPersonnel.phone,unitName: leafNode.emergencyPersonnel.unitName,unitAddress: leafNode.emergencyPersonnel.unitAddress,provinceName: leafNode.emergencyPersonnel.provinceName,cityName: leafNode.emergencyPersonnel.cityName,countyName: leafNode.emergencyPersonnel.countyName};},// 处理节点选择 - 修正事件参数问题handleNodeSelect(node, checked) {const leafNodes = this.getAllLeafNodes(node);if (checked) {// 选中操作:添加所有未选中的叶子节点leafNodes.forEach(leaf => {const isExist = this.selectedPersons.some(p => p.id === leaf.id);if (!isExist) {this.selectedPersons.push(this.convertLeafToSelected(leaf));}});} else {// 取消选中:移除所有相关叶子节点this.selectedPersons = this.selectedPersons.filter(p =>!leafNodes.some(leaf => leaf.id === p.id));}},// 处理层级项点击handleLevelItemClick(item) {if (!item.leaf && item.children && item.children.length > 0) {// 判断当前层级是否是最外层(全国层级)const isRootLevel = this.breadcrumbList.length === 1 && this.breadcrumbList[0] === "全国";if (!isRootLevel) {this.breadcrumbList.push(item.name);} else {// 从全国进入省份时,更新导航路径this.breadcrumbList = ["全国", item.name];}this.currentLevelData = item.children;this.levelHistory.push(this.currentLevelData);}},// 返回上一级goBackToLevel(index) {if (index >= this.breadcrumbList.length - 1) return;// 调整导航路径this.breadcrumbList = this.breadcrumbList.slice(0, index + 1);// 调整层级历史this.levelHistory = this.levelHistory.slice(0, index + 1);// 更新当前层级数据this.currentLevelData = this.levelHistory[index];},// 前往表单页面toFormPage() {console.log(this.selectedPersons);if (this.selectedPersons.length === 0) {this.$u.toast('请至少选择一个人员');return;}}}
};
</script><style scoped>
/* 样式保持不变 */
.container {background-color: #F8F8F8;min-height: 100vh;padding-bottom: 60px;
}.breadcrumb {padding: 12px 15px;background-color: white;display: flex;align-items: center;font-size: 14px;overflow-x: auto;white-space: nowrap;
}.breadcrumb-item {color: #6B7280;padding: 0 2px;
}.breadcrumb-item-active {color: #4F46E5;font-weight: 500;
}.breadcrumb-separator {margin: 0 4px;color: #D1D5DB;
}.level-content {background-color: white;padding-top: 10px;
}.level-item {display: flex;align-items: center;justify-content: space-between;padding: 12px 15px;border-bottom: 1px solid #F3F4F6;
}.level-item-left {display: flex;align-items: center;width: 80%;
}.level-icon {width: 36px;height: 36px;border-radius: 50%;display: flex;align-items: center;justify-content: center;
}.level-icon-text {font-size: 14px;font-weight: 500;color: #4F46E5;
}.level-info {margin-left: 12px;
}.level-title {font-size: 16px;color: #1F2937;
}.level-desc {font-size: 12px;color: #6B7280;margin-top: 2px;display: block;
}.select-checkbox {width: 20px;height: 20px;display: flex;align-items: center;justify-content: center;
}.footer-bar {position: fixed;bottom: 0;left: 0;right: 0;background-color: white;display: flex;align-items: center;justify-content: space-between;padding: 10px 15px;border-top: 1px solid #F3F4F6;}.selected-info {display: flex;align-items: center;color: #1F2937;font-size: 14px;
}.selected-count {margin-left: 5px;
}.next-button {width: 120px;border-radius: 20px;
}
</style>
http://www.dtcms.com/a/361706.html

相关文章:

  • 正则表达式与grep文本过滤详解
  • 盲盒抽谷机小程序开发:如何用3D技术重构沉浸式体验?
  • 【Proteus仿真】8*8LED点阵控制系列仿真——循环显示数字/按键控制显示图案
  • 虚拟机- + linux
  • UFUNCTION C++ 的再次理解
  • 凸集与优化
  • Python OpenCV图像处理与深度学习:Python OpenCV视频处理入门
  • C++实时视频抽帧抓图功能(附源码)
  • DeepSeek-V3.1 模型 API 新特性拆解:逆向 + 火山双渠道适配与推理模式智能切换指南
  • 基于FPGA的红外与可见光图像融合算法
  • Day42 Grad-CAM与Hook函数
  • 进程与线程 - 并发的基石
  • SQL执行过程及原理详解
  • [SWPUCTF 2018]SimplePHP
  • 实现自己的AI视频监控系统-第三章-信息的推送与共享2
  • 刘洋洋《一笔相思绘红妆》上线,献给当代痴心人的一封情书
  • 互斥量(Mutex,全称 Mutual Exclusion)用于保证同一时间只有一个线程(或进程)访问共享资源,从而避免并发操作导致的数据不一致问题
  • RAG-文本到SQL
  • SOME/IP-SD中IPv4端点选项与IPv4 SD端点选项
  • 突破超强回归模型,高斯过程回归!
  • 使用 BayesFlow 神经网络简化贝叶斯推断的案例分享(二)
  • 无重复字符的最长子串,leetCode热题100,C++实现
  • 【FireCrawl】:本地部署AI爬虫+DIFY集成+V2新特性
  • FFmpeg 不同编码的压缩命令详解
  • 速卖通自养号测评系统开发指南:环境隔离与行为模拟实战
  • 测试-用例篇
  • FFMPEG AAC
  • 【LeetCode每日一题】19. 删除链表的倒数第 N 个结点 24. 两两交换链表中的节点
  • Java内存模型下的高性能锁优化与无锁编程实践指南
  • 几种特殊的数字滤波器---原理及设计