VUE+Vant实现H5组织架构选人选公司组件

提醒自己:
这是之前的逻辑,或许你重新写会有更好的方法,可以参考逻辑!!!

功能介绍

1.有面包屑点击切换
2.有公司、部门、人员
3.单选、多选实现
4.编辑/回显
5.使用随意切换层级和跳转到指定层级回显等功能

效果图:

在这里插入图片描述
点击跳转到组件主要内容区域:
在这里插入图片描述
在这里插入图片描述

数据结构

{
"children":[{}],//子级数据
"type" : 0,  // type:0-主企业,2-子企业,1-部门
"comNo" : "1543782809XXXXX",
"teamNo" : null,
"name" : "XXXXXXXX有限公司",
"id" : "1",
"count" : 0,
"parentId" : "",
"contacts": [ {"name" : "刘XXX","icon" : "", // 头像"memberNo" : "111111111111111111","phone" : "17XXXXXXXXX","departmentId": [ "1", "62d6591fa965ea000xxxxx"],"department" : "[["1"],["1","62d6591fa965ea00012xxxxxxx"]"departmentName" : ""}
] //人员数据
}

第一级父级:调用UI组件

<basicCompanyInfo @applySubjectData="getApplySubjectData" class="basic-company-info">js:
// 获取申请公司部门数据
getApplySubjectData(val) {let { aCompany, aCompanyName, aDepartment, aDepartmentName, name, memberNo } = valthis.dataDTO = {companyId:aCompany,companyName:aCompanyName,departmentName:aDepartmentName,departmentNo:aDepartment,userName: name,userId: memberNo}
},

第二级需求UI组件:实现交互

<!-- 组织架构选单位/部门/经办人 -->
<template><div class="basic-company-info"><van-cell @click="goOrgChoose" :value="applySubjectData.aCompanyName"><template #title><div class="required-label">申请单位</div></template><template #right-icon><img src="@/assets/img/icon_right.png" alt="" class="icon_right ml10"></template></van-cell><van-cell title="申请部门":value="!dataState && !applySubjectData.aCompanyName ? '' : (applySubjectData.aDepartmentName ? applySubjectData.aDepartmentName : '该人员未分配部门')" @click="(event) => goOrgChoose(event,2)"><template #right-icon><img src="@/assets/img/icon_right.png" alt="" class="icon_right ml10"></template></van-cell><van-cell :value="applySubjectData.name" @click="(event)=> goOrgChoose(event,3)"><template #title><div class="required-label">经办人</div></template><template #right-icon><img src="@/assets/img/icon_right.png" alt="" class="icon_right ml10"></template></van-cell><van-cell title="" value="" v-show="$router.path=='/reapply'" /></div>
</template><script>
import eventBus from "@/utils/eventBus";
import apiOrder from "@/api/apiOrder";export default {name: "basicCompanyInfo",data(){return{dataState:false,keyName:1,checkData:[],applySubjectData:{},}},props:{applypropsData:{ // 申请单位/部门/经办人的数据type:Object,default:()=>({})}},computed:{userBaseData(){ // 用户信息return this.$store.state.user.userInfo;}},watch:{applypropsData:{handler(val){if(val&&this.$route.query.type==1){this.initapply()}},deep:true}},created() {eventBus.$off(`corporateDepartment${this.keyName}`)eventBus.$on(`corporateDepartment${this.keyName}`, function(data){ // 接收组织架构的数据this.setOrderBaseData(data);}.bind(this));},mounted() {if (this.$route.query.type==1) {this.initapply()}else{this.getCheckData()}},methods:{initapply(){this.applySubjectData=this.applypropsDatathis.applySubjectData.name=this.applypropsData.aPersonNamethis.applySubjectData.managerId=this.applypropsData.aPerson},// 赋值选中的数据async getCheckData(){if(this.applySubjectData.aCompany){ // 有选中公司部门的情况回显this.checkData = [this.applySubjectData];}else {// 第一次进来默认登录信息let userInfo;let res = await apiOrder.findDefaultDept(); // 获取默认部门if (res.code == 200) {let defaultDept = res.data;userInfo = {companyId: defaultDept.id,departmentName: defaultDept.departmentName,departmentNo: defaultDept.departmentNo}}let userBaseData = {...this.userBaseData, ...userInfo};this.initBase(userBaseData)}},// 初始化数据-取自state用户信息async initBase(data){// console.log("初始化数据-取自state用户信息",data)let list = {aCompany:data.companyInfo?.no, // 用户信息的公司id与组织架构的公司id不一致,所以按组织架构为准:一级公司id:1aCompanyName:data.companyInfo?.name,aDepartment:data.departmentNo,aDepartmentName:data.departmentName,memberNo:data.personNo,icon:data.icon,name:data.realName,phone:data.telPhone,};this.setOrderBaseData([list])this.checkData = [list];},// 去选择组织架构goOrgChoose(ev,type){ // 1-企业,2-部门,3-人员this.$emit('changeData')// returnthis.$store.commit('common/updateOrgStructureSelection', this.checkData); // 改变默认勾选数据this.$router.push({ path:'/organizationalStructure', query:{ key:this.keyName,levelType:type }})},// 公司部门数据获取setOrderBaseData(data){let val = data && data[0];this.dataState = false;if(val){this.dataState = true;this.applySubjectData = {...this.applySubjectData,...val};this.$emit('applySubjectData',this.applySubjectData)}}}
}
</script><style scoped lang="scss">
// css根据需求自定义
</style>

组件主要全部代码:

<!-- 组织架构选人/选公司/选部门-->
<template><div class="org-structure"><div class="org-structure-content topNavPt"><!-- 导航部分 --><topNavigation v-if="isShow" :title="breadCrumbsData.length > 0 ? breadCrumbsData[0].name : navTitle"></topNavigation><!-- 面包屑 --><div class="bread-crumbs bag-fff" v-if="breadCrumbsData.length > 0"><div class="bread-crumbs-content" v-for="(item,index) in breadCrumbsData" :key="item.id" @click="goBack(item,index)"><span :class="index == breadCrumbsData.length - 1 ? 'bread-crumbs-content-company cl969696' : 'bread-crumbs-content-company'">{{ item.name }}</span><img src="../../assets/img/icon_right.png" alt="" class="icon_right"></div></div><!-- 公司级别/部门级别 --><div class="pl15 bag-fff"><!-- 一级公司 --><div v-if="!chooseFirstOrder" class="company-cell-content" @click="chooseOrgOrDepartment(orgList)"><van-checkbox v-model="checkByDefaultData">{{ orgList.name }}</van-checkbox><img src="../../assets/img/icon_right.png" alt="" class="icon_right mr15"></div><!-- 二级及以下公司部门 --><div v-else><div v-for="item in chooseOrgList" :key="item.id" @click="chooseOrgOrDepartment(item)" class="company-cell-content"><van-checkbox :class="item.children.length === 0 && item.contacts.length === 0 && item.parentId != 1 ? 'disable-orderBaseCss.scss' : ''" v-model="item.checked">{{ item.name }}<span>{{ `(${item.count})` }}</span></van-checkbox><img src="../../assets/img/icon_right.png" alt="" class="icon_right mr15"></div></div></div><!--  人员级别 --><div v-if="contactsList" class="pl15 bag-fff mt10"><!-- 单选/多选 --><div class="company-cell-content company-personnel" v-for="list in contactsList"><van-checkbox-group v-model="checkedData" ref="checkboxGroup"><van-checkbox :name="list.memberNo" checked-color="#5792FD" @click="(event) => handleChecked(event,list,multipleState)">{{ list.name }}</van-checkbox></van-checkbox-group></div></div></div><!-- 底部按钮 --><div class="bottom-btn-box flex-ai-jc" :style="checkedFinallyData.length > 0 ? '' : 'background: #f9a39c;'" @click="submit"><span>提交{{ multipleState && checkedData.length ? `(已选${checkedData.length}人)` : ''}}</span></div></div>
</template><script>
import apiOrder from '@/api/apiOrder'
import eventBus from "@/utils/eventBus";
export default {name: "organizationalStructure",components:{topNavigation:() => import('@/views/shopBus/components/topNavigation')},props:{multipleSelection:{ // 多选/单选type: Boolean,default: false},navName:{type: String,default: "请选择经办人"},isShow:{type: Boolean,default: true},returnState:{ // 标记是否父子级反参-true父子type: Boolean,default: false},chooseData:{type:Array,default:()=>[]},levelType:{type:String,default:''}},data(){return{orgList: [],chooseOrgList:[],// 组织相关架构chooseFirstOrder:false, // 是否有一级breadCrumbsData:[], // 面包屑数据contactsList:[],// 人员相关数据checkedData:[], // 勾选数据checkedFinallyData:[],// 最终传参数据existData:[],// 之前已存在的值-备份一份keyName:null,submitState:false}},computed:{// 以下数据都是为了区分路由跳转还是父子组件使用navTitle(){return this.$route.query && this.$route.query.navName ? this.$route.query.navName : this.navName;},multipleState(){return this.$route.query && this.$route.query.multipleSelection ? this.$route.query.multipleSelection : this.multipleSelection;},checkByDefaultData(){return this.returnState ? this.chooseData : this.$store.state.common.orgStructureSelection && JSON.parse(JSON.stringify(this.$store.state.common.orgStructureSelection))},levelState(){ // 1-企业,2-部门,3-人员 --自己定义的return this.$route.query && this.$route.query.levelType || this.levelType}},created() {this.keyName = this.$route.query && this.$route.query.key; // 得到唯一key值,便于反参到上一个页面this.getOrgList();},mounted() {if(this.checkByDefaultData.length > 0){ // 有勾选值的话需要初始化已有的数据this.checkedData = this.checkByDefaultData.map(item => item.memberNo);this.existData = this.checkByDefaultData;}},methods:{// 组织架构数据async getOrgList(){let res = await apiOrder.getOrganization();if(res.code == 200 ){this.orgList = res.data;if(this.levelState > 0){ // 有需要跳转到指定层级的情况this.levelInitShow(this.levelState)}}},// 点击公司或者部门chooseOrgOrDepartment(val){if(val.id == 1){this.chooseFirstOrder = true;}if(!this.breadCrumbsData.find(i => i.id === val.id) && (val.children && val.children.length > 0 || val.contacts && val.contacts.length > 0)){ // 不是重复点击 && 有部门或者有人员this.breadCrumbsData.push({ id:val.id,name:val.name,type:val.type }); // 面包屑数据 type:0-主企业,2-子企业,1-部门this.chooseOrgList = [];// 下一级有数据情况if(val.children.length > 0){this.chooseOrgList = val.children; // 组织数据if(this.checkByDefaultData && this.checkByDefaultData.length > 0){ // 如果有选中的数据,勾选上this.chooseOrgList = this.chooseOrgList.map(item =>{let state = this.checkByDefaultData.some(i => (item.type == 2 ? i.aCompany : i.aDepartment) === item.id);return state ? {...item,checked:true} : {...item,checked:false}  // 判断是否需要勾选})}}// 有人员数据if(val.contacts.length > 0){this.contactsList = [...val.contacts]; // 人员数据if(this.checkByDefaultData && this.checkByDefaultData.length > 0) {  // 如果有选中的数据,勾选上this.contactsList.forEach(per => {let state = this.checkByDefaultData.some(i => i.memberNo === per.memberNo);let perState = this.checkedData.some(id => id === per.memberNo); // 判断是否有此人员if(state && !perState){this.multipleState ? this.checkedData.push(per.memberNo) : this.checkedData = [per.memberNo];}})}}}},// 点击面包屑回退goBack(val,inx){if(val.id !== this.breadCrumbsData[this.breadCrumbsData.length - 1].id){ // 当前级时不执行筛选this.breadCrumbsData.splice(inx); // 首先清除面包屑后面的数据let treeData = this.getItemByIdInTree(this.orgList,val.id);this.chooseOrgOrDepartment(treeData);}},// 通过某个节点的id,获取该节点的完整信息getItemByIdInTree(tree,value){if(tree.id === value){return tree;} else {if(tree.children && tree.children.length > 0){for(let i = 0; i < tree.children.length; i++){let resultD = this.getItemByIdInTree(tree.children[i],value);if(resultD){return {...resultD};}}}}},// 通过人员id查找相应节点getMemberNoInTree(tree,id){if(tree.memberNo === id){return tree;} else {if (tree.contacts && tree.contacts.length > 0) {for (let i = 0; i < tree.contacts.length; i++) {let resultD = this.getMemberNoInTree(tree.contacts[i], id);if (resultD) {return resultD;}}}if (tree.children && tree.children.length > 0) {for (let i = 0; i < tree.children.length; i++) {let resultD = this.getMemberNoInTree(tree.children[i],id);if(resultD){return {...resultD};}}}}},// 根据树子节点ID查找所有父节点 - data:要遍历的数据, target:查找目标, result用于装查找结果的数组findParent(node, target, result) {if(node.id === target.id){if( this.levelState == 3 ){ // 到人员的级别result.unshift(node);}return true;}if (node.children && node.children.length > 0) { // 如果当前节点有子节点,则继续遍历子节点for (const childNode of node.children) {if (this.findParent(childNode, target, result)) { // 如果在子节点中找到了子节点的父节点,则将当前节点的ID添加到父节点ID数组中,并返回true表示已经找到了子节点result.unshift(node);return true;}}}// for (let i in node) { // 方法二//   let item = node[i]//   if (item.id === target.id) {//     //将查找到的目标数据加入结果数组中//     result.unshift(item)//     return true//   }//   if (item.children && item.children.length > 0) {//     let ok = this.findParent(item.children, target, result)//     if (ok) {//       result.unshift(item)//       return true//     }//   }// }//走到这说明没找到目标return false},// 根据type来指定展示到某个级别-例如部门跳转过来就指定到部门级别levelInitShow(type){ // 1-企业,2-部门,3-人员let arr = this.checkByDefaultData[0];if(arr){let target = { // 企业使用公司id,部门使用部门id(如果没有部门默认打开公司)id:type == 1 ? arr.aCompany : (arr.aDepartment ? arr.aDepartment : arr.aCompany),name:type == 1 ? arr.aCompanyName : (arr.aDepartmentName && arr.aDepartmentName ? arr.aDepartmentName : arr.aCompanyName)}let result = [];this.findParent(this.orgList, target, result,arr);result.forEach(item =>{this.chooseOrgOrDepartment(item)})console.log('指定层级展开:',arr,result,target)}},// 选择人员handleChecked(ev,val,moreChoose){let aDepartment,company,per;if(!moreChoose){ // 单选this.checkedData = [val.memberNo];}this.checkedFinallyData = []; // 初始化this.checkedData.forEach(user => {// 通过面包屑数据确定公司和部门company = this.breadCrumbsData.find(item => item.type == 2); // 0 是主企业 2 是子企业 1 部门aDepartment = this.breadCrumbsData[this.breadCrumbsData.length - 1];if(!company){ // 没有查到子公司则使用主企业company = this.breadCrumbsData.find(item => item.type == 0);}// 人员数据per = this.getMemberNoInTree(this.orgList,user);let data = {aCompany:company.id, // 申请单位NOaCompanyName:company.name, // 申请单位名称aDepartment:!this.breadCrumbsData.find(item => item.type == 1) ? '' : aDepartment.id,  // 申请部门NO - 多级取最后一个部门/排除第一级公司;都没有部门则为空aDepartmentName:!this.breadCrumbsData.find(item => item.type == 1) ? '' : aDepartment.name, // 申请部门名称memberNo:per.memberNo,icon:per.icon,name:per.name,phone:per.phone,per:per,}this.checkedFinallyData.push(data);})},// 提交submit(){if(this.checkedFinallyData.length > 0){this.submitState = true; // 是否点击提交this.$router.back();if(this.returnState){ // 直接父子组件反参this.$emit('corporateDepartment',this.checkedFinallyData)}}}},beforeDestroy(){if(!this.returnState && this.submitState){ // 不是父子级反参的情况eventBus.$emit(`corporateDepartment${this.keyName}`,this.checkedFinallyData,true)}else if(!this.returnState && !this.submitState){ // 不是父子级反参 && 不是点的提交-反参之前的数据eventBus.$emit(`corporateDepartment${this.keyName}`,this.existData,false)}}
}
</script><style scoped lang="scss">
// css自定义
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计编程网站集:生活部分:饮食+农业,植物(暂记)

这里写目录标题 植物相关综合教程**大型植物&#xff1a;****高大乔木&#xff08;Trees&#xff09;&#xff1a;** 具有坚硬的木质茎&#xff0c;通常高度超过6米。例如&#xff0c;橡树、松树、榉树等。松树梧桐 **灌木&#xff08;Shrubs&#xff09;&#xff1a;** 比乔木…

html5cssjs代码 032 边框属性示例

html5&css&js代码 032 边框属性示例 一、代码二、解释 该HTML文件定义了一个网页页面&#xff0c;主要介绍了HTML5中CSS边框属性的用法。 一、代码 <!DOCTYPE html> <html lang"zh-cn"><head><title>编程笔记 html5&css&j…

mybatis-flex入门体验(一)

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 趁着下午的空闲时间&#xff0c;研究了一下mybatis-flex&#xff0c;看着对我还…

权限提升-Web权限提升篇划分获取资产服务后台系统数据库管理相互转移

知识点 1、权限提升转移-分类&高低&场景 2、Web权限提升及转移-后台&数据库 3、后台权限及转移-转移对象&后台分类 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移 4、域控权限提升及转移 基础点 0、为什么我们要学…

excel所有知识点

1要加双引号 工作表&#xff08;.xlsx) 单击右键→插入&#xff0c;删除&#xff0c;移动、重命名、复制、设置标签颜色&#xff0c;选定全部工作表 工作表的移动&#xff1a;两个表打开→右键→移动&#xff08;如果右键是灰色的&#xff0c;可能是保护工作表了&#xff09…

YOLOv9有效改进|使用iRMB与RepNCSPELAN4融合

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 一、改进点介绍 iRMB是CVPR2023即插即用的到残差注意力机制。 本文使用iRMB与RepNCSPELAN4进行融合 二、iRMB-RepNCSPELAN4模块详解 2.1 模块简介 这…

Flutter 运行 flutter doctor 命令长时间未响应

由于 Flutter 运行 flutter doctor 命令&#xff0c;会从 pub(https://pub.dev/ 类似于 Node.js 的 npm) 上进行资源的下载&#xff0c;如果没有配置国内镜像&#xff0c;可能会由于其服务器在国外导致资源下载慢或者下载不下来&#xff0c;所以出现了运行 flutter doctor 命令…

【C语言基础】:字符串函数(二)

文章目录 一、strncpy函数的使用二、strncat函数的使用三、strncmp函数的使用四、strstr函数的使用和模拟实现4.1 strstr函数的使用4.2 strstr函数的模拟实现 五、strtok函数的使用六、strerror函数的使用 上节回顾&#xff1a;【C语言基础】&#xff1a;字符函数和字符串函数 …

软考高级:软件架构评估-质量属性-安全性概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

精确率(召回率)的权衡(Machine Learning研习十六)

精确率&#xff08;召回率&#xff09;的权衡 为了理解这种权衡&#xff0c;让我们看看 SGDClassifier如何做出分类决策。 对于每个实例&#xff0c;它根据决策函数计算分数。 如果该分数大于阈值&#xff0c;则将该实例分配给正类&#xff1b; 否则它会将其分配给负类。 图 3…

软考高级:软件架构评估:质量属性 - 易用性 和可测试性概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

基于Springboot+vue的在线试题题库管理系统+数据库+报告+免费远程调试

项目介绍: Springbootvue的在线试题题库管理系统&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的在线试题题库管理系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#x…

git tag标签使用

创建标签 git checkout test git tag -a v1.0.0 -m v1.0.0里程碑版本 git push origin v1.0.0 删除标签 git tag -d v1.0.0 git push origin :refs/tags/v1.0.0远程分支可以直接在页面删除

【MySQL】3.1MySQL索引的介绍

目录 一、索引的概念 数据库索引 索引的作用 索引的副作用 索引创建的原则&#xff08;应用场景&#xff09; 适合建立索引 二、索引的分类和创建 1.普通索引 创建普通索引 1.1直接创建 1.2修改表结构的方式创建普通索引 1.3创建表时创建普通索引 2.唯一索引 2.1…

[python]bar_chart_race绘制动态条形图

最近在 B 站上看到了一个宝藏 up 主&#xff0c;名叫 "Jannchie见齐"&#xff0c;专门做动态条形图相关的数据可视化。 可以看到做出的效果还是很不错的&#xff0c;但工具使用的是 JS&#xff0c;不是 Python&#xff0c;于是尝试搜索了一下&#xff0c;看看 Python…

100个openharmony开源demo:1.日历

准备用开发者手机写100个开源的demo不知道能不能实现&#xff0c;日拱一卒&#xff0c;期待蜕变。 第一个demo&#xff1a;日历&#xff0c;借鉴了网上的日历算法&#xff0c;自己用arkts写了界面和点击事件&#xff0c;各位可根据此demo写自己的日历选择器等组件。 1.目录结…

ISO 8601:日期和时间的国际标准

ISO 8601 介绍 ISO 8601&#xff0c;介绍一下 ISO 8601 是由国际标准化组织&#xff08;International Organization for Standardization&#xff0c;ISO&#xff09;发布的国际标准&#xff0c;其全称为《数据存储和交换形式信息交换日期和时间的表示方法》。 这一标准提供了…

【网站项目】293学生用品采购系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

供应链投毒预警 | 恶意Py组件tohoku-tus-iot-automation开展窃密木马投毒攻击

概述 上周&#xff08;2024年3月6号&#xff09;&#xff0c;悬镜供应链安全情报中心在Pypi官方仓库&#xff08;https://pypi.org/&#xff09;中捕获1起新的Py包投毒事件&#xff0c;Python组件tohoku-tus-iot-automation 从3月6号开始连续发布6个不同版本恶意包&#xff0c…

sentinel系统负载自适应流控

系统负载自适应流控 规则配置 规则创建 public class SystemRule extends AbstractRule {private double highestSystemLoad -1;private double highestCpuUsage -1;private double qps -1;private long avgRt -1;private long maxThread -1; }SystemRule类包含了以下几…