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
// 当前点击节点的id
this.currentNodeId = id
} else if ($event === 'edit') {
// 编辑部门的场景
this.showDialog = true
// 当前点击节点的id,后面要用他获取数据,获取数据的最终目的就是数据回显
// 下面的代码存在问题:
// 我们点击编辑的时候,会提示我们“找不到对应的部门”,然后我们发现下面传到add-dept组件中的id为null
// 下面这行代码更新了子组件add-dept中的props,然后又直接调用了子组件add-dept中的getDepartmentDetail方法(同步方法)
// 但是我们的更新props是一个异步的方法,所以存在一种可能,先执行了getDepartmentDetail方法又刷新的props
this.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,不存在就返回false
if (result.some(item => item.code === value)) {
// 校验失败时的错误对象
callback(new Error('部门中已经有该编码'))
} else {
// 校验成功时的对象
callback()
}
}
}],
// 部门介绍
introduce: [{ required: true, message: '部门介绍不能为空', trigger: 'blur' },
{ min: 2, max: 10, message: '部门名称的长度1-100个字符' }],
// 部门负责人id
managerId:
[{ 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,不存在就返回false
if (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赋值上currentNodeId
await 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: '', // 部门负责人id
name: '', // 部门名称,
pid: '' // 父级部门的id
}
// resetFields重置表单有一个局限性,只能重置在模板中绑定的数据(假如说没有绑定某个字段,那这个字段肯定不能重置)
this.$refs.addDept.resetFields()
// 修改父组件的值,子传给父亲
// this.$emit可以触发一个自定义事件(父组件需要接收这个时间),然后把false这个值传出去
// this.$emit('',false) 但是我们先不用这个方法
// 这里我们使用了 sync修饰,表示会接受子组件的事件,也就是update:showDialog这个事件,然后会把值赋值给showDialog
this.$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
// 当前点击节点的id
this.currentNodeId = id
} else if ($event === 'edit') {
// 编辑部门的场景
this.showDialog = true
// 当前点击节点的id,后面要用他获取数据,获取数据的最终目的就是数据回显
// 下面的代码存在问题:
// 我们点击编辑的时候,会提示我们“找不到对应的部门”,然后我们发现下面传到add-dept组件中的id为null
// 下面这行代码更新了子组件add-dept中的props,然后又直接调用了子组件add-dept中的getDepartmentDetail方法(同步方法)
// 但是我们的更新props是一个异步的方法,所以存在一种可能,先执行了getDepartmentDetail方法又刷新的props
this.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()
})
}
}