3.2 iHRM人力资源 - 组织架构 - 编辑及删除
iHRM人力资源 - 组织架构
文章目录
- iHRM人力资源 - 组织架构
- 一、编辑功能
- 1.1 表单弹层并数据回显
- 1.2 编辑校验
- 1.3 编辑
- 二、删除功能
一、编辑功能
编辑功能和新增功能用的组件其实是一个,结构几乎是一样的,其实是复用了组件,我们也省去了很多的开发过程

在如下所示的位置进行编写

1.1 表单弹层并数据回显
首先在index页面的下拉结构不会改变
当点击下拉菜单中的某个选项的时候,就会执行operateDept方法
<!--下拉菜单组件--><!--@command是下拉菜单的执行方法,当点击下拉菜单中的某一项的时候,就会执行operateDept方法--><!--$event实参表示类型,也就是下面command中的值,表示事件所携带的默认参数,如果不传data.id的话,默认传入的就是$event实参--><el-dropdown @command="operateDept($event,data.id)"><!--显示区域内容--><span class="el-dropdown-link">操作<i class="el-icon-arrow-down el-icon--right"></i>
</span><!--下拉菜单的选项--><el-dropdown-menu slot="dropdown"><el-dropdown-item command="add">添加子部门</el-dropdown-item><el-dropdown-item command="edit">编辑部门</el-dropdown-item><el-dropdown-item command="del">删除</el-dropdown-item></el-dropdown-menu></el-dropdown>

弹层
<!--放置弹层-->
<!--:show-dialog 是我们在add-dept组件中定义的props-->
<!--sync修饰,表示会接受子组件的事件,也就是update:showDialog这个事件,然后会把值赋值给下面的showDialog-->
<!--自定义事件updateDepartment,子组件触发,父组件执行getDepartment方法,刷新组织结构-->
<!--ref可以获取dom的实例对象,也可以获取自定义组件的实例对象-->
<add-dept ref="addDept" @updateDepartment="getDepartment" :current-node-id="currentNodeId":show-dialog.sync="showDialog"
></add-dept>
方法
methods: {operateDept($event, id) {if ($event === 'add') {// 添加子部门// 显示弹层组件this.showDialog = true// 当前点击节点的idthis.currentNodeId = id} else if ($event === 'edit') {// 编辑部门的场景this.showDialog = true// 当前点击节点的id,后面要用他获取数据,获取数据的最终目的就是数据回显// 下面的代码存在问题:// 我们点击编辑的时候,会提示我们“找不到对应的部门”,然后我们发现下面传到add-dept组件中的id为null// 下面这行代码更新了子组件add-dept中的props,然后又直接调用了子组件add-dept中的getDepartmentDetail方法(同步方法)// 但是我们的更新props是一个异步的方法,所以存在一种可能,先执行了getDepartmentDetail方法又刷新的propsthis.currentNodeId = id// 要在子组件获取数据// 父组件调用子组件的方法来获取数据// 此时this.$refs.addDept等同于子组件的this// this.$refs.addDept.getDepartmentDetail() 在这里调用会和props产生同步异步的问题// 有没有办法等到props更新之后再去调用getDepartmentDetail方法呢?// this.$nextTick会等到我们数据更新完毕,执行回调函数this.$nextTick(() => {this.$refs.addDept.getDepartmentDetail()})}}........
}
add-dept组件方法中的方法
methods: {// 获取组织的详情async getDepartmentDetail() {const result = await getDepartmentDetail(this.currentNodeId)// 完成数据回显this.formDara = result}......
}
获取部门详情的api方法
/*** 获取部门详情*/
export function getDepartmentDetail(id) {// 不写请求方式的话,默认为get类型// 这个地方使用了一个模板字符串return request({url: `/company/department/${id}`})
}
1.2 编辑校验
首先说明,修改的表单校验和新增的表单校验是一个样子的,所以说表单校验规则可以复用
- 表单项必填/表单项长度限制
- 部门名称和已有部门不重复
- 部门编码和已有编码不重复

但是目前有下面这个问题,当我们点击“编辑”后,会出现下面的情况,所以我们应该把“编辑”功能和“新增”功能的校验区别开
如果是编辑模式下,我们应该把当前的这条数据排除掉,不要和自己去比

那我们怎么区别新增还是编辑场景呢?
很好判断,当时新增操作的时候,formData中没有id字段

当时编辑操作的时候,formData中有id字段

修改编辑的校验
rules: {// 部门编码code: [{ required: true, message: '部门编码不能为空', trigger: 'blur' },{ min: 2, max: 10, message: '部门编码的长度2-10个字符' },// 自定义业务校验,部门编码不能重复{trigger: 'blur', validator: async(rule, value, callback) => {// value值是输入的编码值let result = await getDepartment()// 判断此时是编辑模式还是新增模式if (this.formDara.id) {// 存在id,说明是编辑状态,我们要将自身排除掉result = result.filter(item => item.id !== this.formDara.id)}// result实际是一个数组,然后查看数组中是否存在用户输入的value值// 我们可以使用some()方法,如果存在就返回true,不存在就返回falseif (result.some(item => item.code === value)) {// 校验失败时的错误对象callback(new Error('部门中已经有该编码'))} else {// 校验成功时的对象callback()}}}],// 部门介绍introduce: [{ required: true, message: '部门介绍不能为空', trigger: 'blur' },{ min: 2, max: 10, message: '部门名称的长度1-100个字符' }],// 部门负责人idmanagerId:[{ required: true, message: '部门负责人id不能为空', trigger: 'blur' }],// 部门名称name:[{ required: true, message: '部门名称不能为空', trigger: 'blur' },{ min: 2, max: 10, message: '部门名称的长度2-10个字符' },{trigger: 'blur', validator: async(rule, value, callback) => {// value值是输入的编码值let result = await getDepartment()// 判断此时是编辑模式还是新增模式if (this.formDara.id) {// 存在id,说明是编辑状态,我们要将自身排除掉result = result.filter(item => item.id !== this.formDara.id)}// result实际是一个数组,然后查看数组中是否存在用户输入的value值// 我们可以使用some()方法,如果存在就返回true,不存在就返回falseif (result.some(item => item.name === value)) {// 校验失败时的错误对象callback(new Error('部门中已经有该名称'))} else {// 校验成功时的对象callback()}}}]// pid: '' // 父级部门的id
}
上面那么多的代码,其实有用的就是下面这个

1.3 编辑
其实“添加”功能的“确认”和“取消”在这里差不多就能复用
因为我们“添加”和“编辑”功能公用的一个组件,所以我们需要区分一下是编辑下的文本框还是增加下的文本框

api接口
/*** 更新部门接口*/
export function updateDepartment(data) {return request(({url: `/company/department/${data.id}`,method: 'PUT',data: data}))
}
方法内容
// 点击确定时调用此方法
btnOK() {this.$refs.addDept.validate(async isOK => {if (isOK) {let msg = '新增'// 通过formData中是否有id来确认是“编辑”环境还是“增加”环境if (this.formDara.id) {// 编辑场景msg = '编辑'await updateDepartment(this.formDara)} else {// 新增场景// ...this.formDara 表示相当于把formDara数据进行了拷贝,考到了一个新对象里面// pid: this.currentNodeId表示将formDara中的pid赋值上currentNodeIdawait addDepartment({ ...this.formDara, pid: this.currentNodeId })}// 校验已经通过// 此时可以通知父组件更新,也就是子传父,可以选择触发一个自定义事件(父组件要监听这个事件)this.$emit('updateDepartment')// 提示消息this.$message.success(+`${msg}部门成功`)// 关闭this.close()}})
},
再写一个计算属性,当我们点击“编辑”的时候,弹层会显示“编辑部门”,同理我们点击“新增”时,弹层会显示“新增部门”
<!--:visible用来控制显示和隐藏,由于我们是一个组件,所以我们需要外部传入一个参数来控制显示还是隐藏-->
<!--@close用于监视关闭弹层(点击右上角×号的时候,就会执行此函数)-->
<el-dialog :title="showTitle" :visible="showDialog" @close="close">
computed: {showTitle() {return this.formData.id ? '编辑部门' : '新增部门'}
}
但是现在还有一个问题,当我们点击“编辑”后,关闭,再点击“新增”,我们发现弹层左上角显示“编辑部门”,而不是“新增部门”,原因就是this.$refs.addDept.resetFields()重置表单时有问题,并没有把id给清空

其实我们可以手动置空
close() {// 重置表单this.formData ={code: '', // 部门编码introduce: '', // 部门介绍managerId: '', // 部门负责人idname: '', // 部门名称,pid: '' // 父级部门的id}// resetFields重置表单有一个局限性,只能重置在模板中绑定的数据(假如说没有绑定某个字段,那这个字段肯定不能重置)this.$refs.addDept.resetFields()// 修改父组件的值,子传给父亲// this.$emit可以触发一个自定义事件(父组件需要接收这个时间),然后把false这个值传出去// this.$emit('',false) 但是我们先不用这个方法// 这里我们使用了 sync修饰,表示会接受子组件的事件,也就是update:showDialog这个事件,然后会把值赋值给showDialogthis.$emit('update:showDialog', false)
},
二、删除功能
流程图

async getDepartment() {// 下面这个方法是import导入的api请求方法const result = await getDepartment()// 但是我们获取到的数据是列表的形式,没有层级结构,我们要使用递归的方式完成树形结构this.depts = transListToTreeData(result, 0)
},
operateDept($event, id) {if ($event === 'add') {// 添加子部门// 显示弹层组件this.showDialog = true// 当前点击节点的idthis.currentNodeId = id} else if ($event === 'edit') {// 编辑部门的场景this.showDialog = true// 当前点击节点的id,后面要用他获取数据,获取数据的最终目的就是数据回显// 下面的代码存在问题:// 我们点击编辑的时候,会提示我们“找不到对应的部门”,然后我们发现下面传到add-dept组件中的id为null// 下面这行代码更新了子组件add-dept中的props,然后又直接调用了子组件add-dept中的getDepartmentDetail方法(同步方法)// 但是我们的更新props是一个异步的方法,所以存在一种可能,先执行了getDepartmentDetail方法又刷新的propsthis.currentNodeId = id// 要在子组件获取数据// 父组件调用子组件的方法来获取数据// 此时this.$refs.addDept等同于子组件的this// this.$refs.addDept.getDepartmentDetail() 在这里调用会和props产生同步异步的问题// 有没有办法等到props更新之后再去调用getDepartmentDetail方法呢?// this.$nextTick会等到我们数据更新完毕,执行回调函数this.$nextTick(() => {this.$refs.addDept.getDepartmentDetail()})} else if ($event === 'del') {// 删除部门// 假如用户点击了“取消”,我们这里是不需要管的this.$confirm('您确定要删除该部门吗?').then(async() => {// 进入到这里,说明用户点击了确认按钮await delDepartment(id)// 提示消息this.$message.success('删除部门成功')// 重新拉取数据getDepartment()})}
}
相关文章:
3.2 iHRM人力资源 - 组织架构 - 编辑及删除
iHRM人力资源 - 组织架构 文章目录 iHRM人力资源 - 组织架构一、编辑功能1.1 表单弹层并数据回显1.2 编辑校验1.3 编辑 二、删除功能 一、编辑功能 编辑功能和新增功能用的组件其实是一个,结构几乎是一样的,其实是复用了组件,我们也省去了很…...
支付系统核心逻辑 — — 状态机(JavaGolang版本)
支付系统核心逻辑 — — 状态机 代码地址:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/state_machine_demo 1 概念:FSM(有限状态机),模式之间转换 状态机,也叫有限状态机(…...
rest_framework_mongoengine实现后端的增删改查
rest_framework_mongoengine实现后端增删改查 一、增删改查 1. 继承ModelViewSet实现增删改查 父urls.py path("api/testapp/", include("apps.testapp.urls")), # 测试子urls.py # -*- coding: utf-8 -*- from django.urls import path from res…...
【精读文献】Scientific data|2017-2021年中国10米玉米农田变化制图
论文名称:Mapping annual 10-m maize cropland changes in China during 2017–2021 第一作者及通讯作者:Xingang Li, Ying Qu 第一作者单位及通讯作者单位:北京师范大学地理学部 文章发表期刊:《Scientific data》(…...
高光谱图像修复笔记
目录 RetinexFormer 也有MST-plus-plus代码,分辨率可以调 MST-plus-plus github地址: WACV2023 DSTrans RetinexFormer GitHub - caiyuanhao1998/Retinexformer: "Retinexformer: One-stage Retinex-based Transformer for Low-light Image E…...
GPS定位原理及应用分析
一.定位原理 1.卫星定位(GPS,北斗导航) ①.硬件构成(24颗卫星,可构建一套导航系统) 为何是24颗卫星? 可以做到全球覆盖,同一地点地球上空可观测到4颗卫星。 …...
Java面试篇9——并发编程
并发编程知识梳理 提示,此仅为面试,若想对线程有跟完整了解,请点击这里 提示:直接翻到最后面看面试真题,上面的为详解 面试考点 文档说明 在文档中对所有的面试题都进行了难易程度和出现频率的等级说明 星数越多代表…...
[RK3399 Linux] 使用busybox 1.36.1制作rootfs
一、 编译、安装、配置 busybox 1.1 下载源码 根文件系统是根据busybox来制作的。 下载地址:https://busybox.net/downloads/。 这里就以1.36.1版本为例进行编译安装介绍: 注意:编译linux内核与文件系统中的所有程序要使用相同的交叉编译器。 下载完成后解压: mkdir …...
JavaScript入门--循环
JavaScript入门--循环 一、for循环二、for in语句三、break语句四、continue语句五、while循环六、do-while语句一、for循环 先来看一个循环案例: for (i = 0; i < 5; i++) {...
【Delphi 爬虫库 1】GET和POST方法
文章目录 1.最简单的Get方法实现2.可自定义请求头、自定义Cookie的Get方法实现3.提取响应协议头4.Post方法实现单词翻译 爬虫的基本原理是根据需求获取信息并返回。就像当我们感到饥饿时,可以选择自己烹饪食物、外出就餐,或者订外卖一样。在编程中&#…...
[leetcode] 快乐数 E
:::details 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。 如果这个过程 结果为 1…...
Lobe UI - 基于 AntDesign 开发的 AIGC Web 应用的开源 UI 组件库
今天推荐一个可以快速开发 ChatGPT UI 界面的组件库,质量很高,拿来就能用。 Lobe UI 是由 lobehub 团队开发的一套 web UI 组件库,和我之前推荐的很多通用型的 UI 组件库不同,Lobe UI 是专门为目前火热的 AIGC 应用开发而打造&am…...
Java常用类 -- Random类
该类实例用于生成伪随机数的流 伪随机数:通过算法算出来的数,是假的随机数 (一)具体使用 public static void main(String[] args) { Random r new Random(); System.out.println("随机出int类型的数据" r.nextIn…...
Docker安装Kong网关
文章目录 一、kong是什么?二、搭建步骤1.搭建PostgreSQL2.搭建Kong网关2.1、制作镜像2.2、数据库初始化2.3、启动Kong网关一、kong是什么? Github地址:https://github.com/Kong/kong Kong是一个可扩展、开源的云原生API网关,可以在分布式环境中管理、监控和安全地发布API…...
spispispi
SPI C.. & C.. logic是SPI的控制逻辑,芯片内部进行地址锁存、数据读写等操作,都是由控制逻辑自动完成。控制逻辑的左边是SPI的通信引脚,这些引脚和主控芯片相连,主控芯片通过SPI协议,把指令和数据发送给控制逻辑&a…...
MySQL——创建和插入
一、插入数据 INSERT 使用建议; 在任何情况下建议列出列名,在 VALUES 中插入值时,注意值和列的意义对应关系 values 指定的值顺序非常重要,决定了值是否被保存到正确的列中 在指定了列名的情况下,你可以仅对需要插入的列给到…...
【BUG】element-ui表格中使用video标签,数据翻页,video中的视频仍然显示第一页的视频,没有重新加载
BUG描述 遇到一个问题,使用element-ui构建的管理端后台,表格里面每一行都有一个video标签,里面有视频,当我翻页了以后,视频不会重新加载,仍然显示的是第一页的视频,代码如下: <e…...
【JavaSE】你真的了解内部类吗?
前言 本篇会详细讲解内部类的四种形式,让你掌握内部类~ 欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 目录 前言 内部类介绍 实例内部类 定义 调用 静态内部类 定义 调用 匿名内部类 定义和调用1 调用方法2 …...
Vue3(二):报错调试,vue3响应式原理、computed和watch,ref,props,接口
一、准备工作调试 跟着张天禹老师看前几集的时候可能会遇到如下问题: 1.下载插件:Vue Language Features (Volar)或者直接下载vue-offical 2.npm run serve时运行时出现错误:Error: vitejs/plugin-vue requires vue (>3.2.13) …...
前端console用法分享
console对于前端人员来讲肯定都不陌生,相信大部分开发者都会使用console来进行调试,但它能做的绝不仅限于调试。 最常见的控制台方法 作为开发者,最常用的 console 方法如下: 控制台打印结果: 今天我分享的是一些 co…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
