✅P58_三级分类-删除-批量删除
大约 8 分钟
批量删除实现
批量删除按钮
<el-button type="danger" @click="batchDelete">批量删除</el-button>
batchDelete方法
methods: {
batchDelete() {
//....
}
}
勾选状态:半选状态,选中、未选
方法参考
- leafOnly:是否只是叶子节点,默认值为 false
- includeHalfChecked:是否包含半选节点,默认值为 false
用法参考:
**Tree树形控件->节点过滤**
this
:指的是当前vue实例$refs
:指的是当前vue实例中的组件tree
: 指的是当前vue实例中的tree组件filter
:指的是当前vue实例中的tree组件中的方法
点击批量删除按钮就会调用Tree组件中的getCheckedNodes
方法获取选中的节点,将选中的节点catId封装成数组,发送给后台
具体实现
<el-tree
ref="menuTree"
//省略其他代码
>
获取勾选的节点
methods: {
batchDelete() {
//获取选中的节点
let noderArrayList = this.$refs.menuTree.getCheckedNodes();
}
}
遍历选中的节点存放到batchDeleteCatId
中
data() {
//这里存放数据
return {
batchDeleteCatId: [],
}
}
batchDelete() {
//参考:Tree树形组件->树节点的选择
let noderArrayList = this.$refs.menuTree.getCheckedNodes();
console.log("被选中的节点数组:", noderArrayList);
for (let i = 0; i < noderArrayList.length; i++) {
this.batchDeleteCatId.push(noderArrayList[i].catId);
}
在点击批量删除按钮时需要弹出个确认框,再次确认时向后台发送请求
this.$confirm(`是否批量删除【${nodeName}】菜单?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl("/product/category/delete"),
method: "post",
data: this.$http.adornData(this.batchDeleteCatId, false)
}).then(({ data }) => {
this.$message({
type: 'success',
message: '删除成功!'
});
//刷新分类
this.getMenuList();
//删除更新后的菜单依然展开
this.expandKey = parentCid;
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
});
batchDelete()代码
batchDelete() {
//参考:Tree树形组件->树节点的选择
let noderArrayList = this.$refs.menuTree.getCheckedNodes();
let nodeName = [];
let parentCid = [];
console.log("被选中的节点数组:", noderArrayList);
for (let i = 0; i < noderArrayList.length; i++) {
this.batchDeleteCatId.push(noderArrayList[i].catId);
nodeName.push(noderArrayList[i].name);
parentCid.push(noderArrayList[i].parentCid);
}
this.$confirm(`是否批量删除【${nodeName}】菜单?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl("/product/category/delete"),
method: "post",
data: this.$http.adornData(this.batchDeleteCatId, false)
}).then(({ data }) => {
this.$message({
type: 'success',
message: '删除成功!'
});
//刷新分类
this.getMenuList();
//删除更新后的菜单依然展开
this.expandKey = parentCid;
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
});
}
前端代码
src\views\modules\product\category.vue
<!-- 三级分类页面 -->
<template>
<div>
<el-switch v-model="draggable" active-text="开启拖拽" inactive-text="关闭拖拽" active-color="#ff4949"></el-switch>
<el-button v-if="draggable" @click="batchSave">批量保存</el-button>
<el-button type="danger" @click="batchDelete">批量删除</el-button>
<el-tree
:data="menu"
:props="defaultProps"
show-checkbox
:expand-on-click-node="false"
node-key="catId"
:default-expanded-keys="expandKey"
draggable
:allow-drop="allowDrop"
@node-drop="handleDrop"
:draggable="draggable"
ref="menuTree"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<!-- 一级和二级目录才可以添加 -->
<el-button v-if="node.level <= 2" type="text" size="mini" @click="() => append(data)">
Append
</el-button>
<!-- 如果没有子节点才可以进行删除 -->
<el-button v-if="node.childNodes.length == 0" type="text" size="mini" @click="() => remove(node, data)">
Delete
</el-button>
<el-button type="text" size="mini" @click="edit(data)">Edit</el-button>
</span>
</span>
</el-tree>
<el-dialog :title="title" :visible.sync="dialogFormVisible" width="30%" :close-on-click-modal="false">
<el-form :model="category">
<el-form-item label="分类名称">
<el-input v-model="category.name"></el-input>
</el-form-item>
<el-form-item label="显示状态">
<el-input v-model="category.showStatus"></el-input>
</el-form-item>
<el-form-item label="排序">
<el-input v-model="category.sort"></el-input>
</el-form-item>
<el-form-item label="图标">
<el-input v-model="category.icon"></el-input>
</el-form-item>
<el-form-item label="计量单位">
<el-input v-model="category.productUnit"></el-input>
</el-form-item>
<el-form-item label="商品数量">
<el-input v-model="category.productCount"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="choose">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
export default {
data() {
//这里存放数据
return {
pCid: [],
draggable: false,
updateNodes: [],
maxLevel: 0,
title: "",
//区分新增和编辑的类型
dialogType: "",
dialogFormVisible: false,
category: {
name: "",
parentCid: "",
catLevel: "",
showStatus: 1,
sort: 0,
icon: "",
productUnit: "",
productCount: "",
},
menu: [],
expandKey: [],
defaultProps: {
children: "children",
label: "name"
},
batchDeleteCatId: [],
};
},
//监听属性 类似于data概念
computed: {},
//监控data中的数据变化
watch: {},
//方法集合
methods: {
getMenuList() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl('/product/category/list/tree'),
method: 'get',
}).then(({ data }) => { // 1.使用解构即{},将data对象解构出来
console.log("获取三级分类数据:", data);
// 2.将data中的data赋值给menu
this.menu = data.data;
});
},
choose() {
if (this.dialogType == "add") {
this.addCategory();
} else if (this.dialogType == "edit") {
this.editCategory();
}
},
append(data) {
console.log("append", data);
this.title = "添加分类",
this.dialogType = "add";
this.dialogFormVisible = true;
this.category.parentCid = data.catId;
this.category.catLevel = data.cat_level * 1 + 1;
console.log("append this category:", this.category);
},
remove(node, data) {
var ids = [data.catId];
// 反引号是新标准es6的功能,可以用$配合大括号来实现变量拼接
this.$confirm(`是否删除【${data.name}】菜单?`, "提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl("/product/category/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getMenuList();
//默认菜单展示
this.expandKey = [node.parent.data.catId];
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
console.log("remove", node, data);
},
// 添加分类
addCategory() {
this.$http({
url: this.$http.adornUrl("/product/category/save"),
method: "post",
data: this.$http.adornData(this.category, false)
}).then(({ data }) => {
this.dialogFormVisible = false;
this.$message({
type: 'success',
message: '新增成功'
});
//刷新分类数据
this.getMenuList();
this.expandKey = [this.category.parentCid];
}).catch({
type: 'info',
message: '已取消删除'
});
},
//修改分类
edit(data) {
console.log("要修改的分类数据对象为:", data);
this.title = "商品分类修改",
this.dialogFormVisible = true;
this.dialogType = "edit";
this.$http({
url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
method: "get",
params: this.$http.adornParams({})
}).then(({ data }) => {
console.log("编辑分类得数据回显:", data);
// 通过catId进行更新分类数据
this.category.catId = data.category.catId;
this.category.name = data.category.name;
// 扩展默认菜单
this.category.parentCid = data.category.parentCid;
// this.category.catLevel = data.category.catLevel;
this.category.icon = data.category.icon;
// this.category.productUnit = data.category.productUnit;
this.category.productCount = data.category.productCount;
});
},
editCategory() {
let { catId, name, icon, productCount } = this.category;
var data = {
catId: catId,
name: name,
icon: icon,
productCount: productCount
};
console.log("edit-data", data);
//发送修改请求
this.$http({
url: this.$http.adornUrl("/product/category/update"),
method: "post",
data: this.$http.adornData(data, false),
}).then(({ data }) => {
//关闭对话框
this.dialogFormVisible = false;
this.$message({
type: 'success',
message: '修改成功'
});
//刷新分类数据
this.getMenuList();
//操作完成后分类数据展开
this.expandKey = [this.category.parentCid];
// 属性恢复默认值
this.category.catId = null;
this.category.parentCid = 0;
this.category.catLevel = 0;
this.category.name = "";
this.category.icon = "";
this.category.productUnit = "";
this.category.productCount = 0;
});
},
cancel() {
this.dialogFormVisible = false;
this.category.catId = null;
this.category.parentCid = 0;
this.category.catLevel = 0;
this.category.name = "";
this.category.icon = "";
this.category.productUnit = "";
this.category.productCount = 0;
},
// 》》》》》》》》》》》》》》》》》》》》》批量保存》》》》》》》》》》》》》》》》》》》》》》
batchSave() {
this.$http({
url: this.$http.adornUrl("/product/category/update/sort"),
method: "post",
data: this.$http.adornData(this.updateNodes, false)
}).then(({ data }) => {
this.$message({
type: "success",
message: "拖拽成功!"
});
this.getMenuList();
//默认菜单展示
this.expandKey = this.pCid;
//将数据置为原始数据,防止拖拽节点时不断的累加
this.updateNodes = [];
this.maxLevel = 0;
});
},
// 》》》》》》》》》》》》》》》》》》》》》分类拖拽功能》》》》》》》》》》》》》》》》》》》》》》
//是否可以被拖拽判断
allowDrop(draggingNode, dropNode, type) {
console.log("draggingNode:", draggingNode, "dropNode:", dropNode, "type:", type);
//1、获取当前拖拽节点的最大层级
this.countNodeLevel(draggingNode);
//定义拖动节点的深度
let maxDeep = 0;
if (this.maxLevel == 0) {
//节点本身,没有子节点
maxDeep = 1;
} else {
maxDeep = Math.abs(this.maxLevel - draggingNode.level) + 1;
}
//判断是否可拖拽
if (type == "inner") {
return maxDeep + dropNode.level <= 3;
} else {
return maxDeep + dropNode.parent.level <= 3;
}
},
//获取当前节点的最大层级
countNodeLevel(draggingNode) {
if (draggingNode.childNodes != null && draggingNode.childNodes.length > 0) {
for (let i = 0; i < draggingNode.childNodes.length; i++) {
if (draggingNode.childNodes[i].level > this.maxLevel) {
this.maxLevel = draggingNode.childNodes[i].level;
} else {
this.countNodeLevel(draggingNode.childNodes[i])
}
}
}
},
//拖拽后调用方法
handleDrop(draggingNode, dropNode, type, ev) {
console.log("draggingNode:", draggingNode, "dropNode:", dropNode, "type:", type, "ev:", ev);
//定义父节点
let pCid = null;
let subChild = null;
//1、当前节点最新的父节点id
//如果节点被拖拽到了目标节点的前面或者后面,则被拖拽节点的父节点就是目标节点的父节点
if (type == "before" || type == "after") {
pCid = dropNode.data.parentCid == undefined ? 0 : dropNode.parent.data.catId;
subChild = dropNode.parent.childNodes;
}
//如果节点被拖拽到了目标节点里,那么目标节点的catId就是拖拽节点的父id
else if (type == "inner") {
pCid = dropNode.data.catId;
subChild = dropNode.childNodes;
}
this.pCid.push(pCid);
//2、当前拖拽节点的最新顺序
if (subChild != null && subChild.length > 0) {
for (let i = 0; i < subChild.length; i++) {
//如果遍历的是当前正在拖拽的节点
if (subChild[i].data.catId == draggingNode.data.catId) {
let catLevel = draggingNode.level;
if (subChild[i].level != draggingNode.level) {
//当前节点的层级发生变化
catLevel = subChild[i].level;
//修改他子节点的层级
this.updateChildNodesLevel(subChild[i]);
}
this.updateNodes.push({ catId: subChild[i].data.catId, sort: i, parentCid: pCid, catLevel: catLevel });
} else {
this.updateNodes.push({ catId: subChild[i].data.catId, sort: i });
}
}
//3、当前拖拽节点的最新层级
console.log("updateNodes", this.updateNodes);
};
},
//更新子节点层级
updateChildNodesLevel(node) {
if (node.childNodes.length > 0) {
for (let i = 0; i < node.childNodes.length; i++) {
var cNode = node.childNodes[i].data;
this.updateNodes.push({
catId: cNode.catId,
catLevel: node.childNodes[i].level,
});
this.updateChildNodesLevel(node.childNodes[i]);
}
}
},
// 》》》》》》》》》》》》》》》》》》》》》批量删除》》》》》》》》》》》》》》》》》》》》》》
batchDelete() {
//参考:Tree树形组件->树节点的选择
let noderArrayList = this.$refs.menuTree.getCheckedNodes();
let nodeName = [];
let parentCid = [];
console.log("被选中的节点数组:", noderArrayList);
for (let i = 0; i < noderArrayList.length; i++) {
this.batchDeleteCatId.push(noderArrayList[i].catId);
nodeName.push(noderArrayList[i].name);
parentCid.push(noderArrayList[i].parentCid);
}
this.$confirm(`是否批量删除【${nodeName}】菜单?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl("/product/category/delete"),
method: "post",
data: this.$http.adornData(this.batchDeleteCatId, false)
}).then(({ data }) => {
this.$message({
type: 'success',
message: '删除成功!'
});
//刷新分类
this.getMenuList();
//删除更新后的菜单依然展开
this.expandKey = parentCid;
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
});
}
},
//生命周期 - 创建完成(可以访问当前this实例)
created() {
this.getMenuList();
},
//生命周期 - 挂载完成(可以访问 DOM 元素)
mounted() { },
beforeCreate() { }, //生命周期 - 创建之前
beforeMount() { }, //生命周期 - 挂载之前
beforeUpdate() { }, //生命周期 - 更新之前
updated() { }, //生命周期 - 更新之后
beforeDestroy() { }, //生命周期 - 销毁之前
destroyed() { }, //生命周期 - 销毁完成
activated() { }, //如果页面有 keep-alive 缓存功能, 这个函数会触发
};
</script>
<style scoped></style>