谷粒商城-全栈-19 商品服务-三级分类-删除
这一节实现三级分类的删除功能。
一、页面效果
前端页面增加删除按钮,可以参考 Element官方文档
修改文件 src/views/modules/product/category.vue
<!-- 分类 -->
<template>
<el-tree
:data="menus"
:props="defaultProps"
:expand-on-click-node="false"
show-checkbox
node-key="catId"
>
<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>
</span>
</span>
</el-tree>
</template>
<script>
// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
// 例如:import 《组件名称》 from '《组件路径》';
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
props: {},
data() {
return {
menus: [],
defaultProps: {
children: "children",
label: "name",
},
};
},
// 监听属性 类似于data概念
computed: {},
// 监控data中的数据变化
watch: {},
methods: {
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get",
}).then(({ data }) => {
this.menus = data.data;
});
},
append(data) {
console.log("append", data);
},
remove(node, data) {
console.log("remove_data", data);
console.log("remove_node", node);
},
},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
this.getMenus();
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {},
beforeCreate() {}, // 生命周期 - 创建之前
beforeMount() {}, // 生命周期 - 挂载之前
beforeUpdate() {}, // 生命周期 - 更新之前
updated() {}, // 生命周期 - 更新之后
beforeDestroy() {}, // 生命周期 - 销毁之前
destroyed() {}, // 生命周期 - 销毁完成
activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style>
</style>
二、逻辑删除
逆向生成根据分类表已经生成了删除功能,该删除功能是直接从数据库里边删掉数据,即物理删除,但是我们业务只需要逻辑删除,所以,原来的删除操作需要做改动。
product/controller/CategoryController.java
逆向生成的删除代码
/**
* 删除
*
* @RequestBody:获取请求体,必须发送POST请求,也就是只有POST才有请求体@RequestBody
* SpringMVC 自动将请求体的数据(json),转为对应的对象
*/
@RequestMapping("/delete")
//@RequiresPermissions("product:category:delete")
public R delete(@RequestBody Long[] catIds) {
// categoryService.removeByIds(Arrays.asList(catIds));
// 1、检查当前删除的,是否有在其他地方引用
categoryService.removeMenuByIds(Arrays.asList(catIds));
return R.ok();
}
说明:
@RequestBody
:获取请求体,必须发送POST请求,也就是只有POST才有请求体@RequestBody。SpringMVC
自动将请求体的数据(json),转为对应的对象
添加删除方法 product/service/CategoryService.java
public interface CategoryService extends IService<CategoryEntity> {
PageUtils queryPage(Map<String, Object> params);
List<CategoryEntity> listWithTree();
void removeMenuByIds(List<Long> asList);
}
实现删除方法product/service/impl/CategoryServiceImpl.java
@Override
public void removeMenuByIds(List<Long> asList) {
// TODO::1、检查当前删除的,是否有在其他地方引用
baseMapper.deleteBatchIds(asList);
}
mybatis-plus逻辑删除
步骤:
1、配置全局的逻辑删除规则(省略)
2、配置逻辑删除的组件Bean(省略)
3、给bean加上逻辑删除注解@TableLogic
实现:
修改 gulimall-product/src/main/resources/application.yml
,添加逻辑删除配置:
mybatis-plus:
mapper-location: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto # id主键自增
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
修改 product/entity/CategoryEntity.java
,添加逻辑删除注解
/**
* 是否显示[0-不显示,1显示]
*/
@TableLogic(value = "1", delval = "0")
private Integer showStatus;
在PostMan调用该接口进行测试:
http://localhost:8888/api/product/category/delete
查看数据库,show_status 状态改为 0 了,即不显示了
我们可以看下控制台打印的SQL语句,实际上是进行了更新的操作:
2020-08-18 01:39:18.541 DEBUG 46703 --- [nio-6000-exec-1] c.a.g.p.dao.CategoryDao.deleteBatchIds : ==> Preparing: UPDATE pms_category SET show_status=0 WHERE cat_id IN ( ? ) AND show_status=1
2020-08-18 01:39:18.569 DEBUG 46703 --- [nio-6000-exec-1] c.a.g.p.dao.CategoryDao.deleteBatchIds : ==> Parameters: 1000(Long)
2020-08-18 01:39:18.677 DEBUG 46703 --- [nio-6000-exec-1] c.a.g.p.dao.CategoryDao.deleteBatchIds : <== Updates: 1
三、效果细化
后端删除的接口已经写好了,现在做前端页面的接口调用和页面细节处理。
思路:有关删除接口的实现可以参考 role.vue 里边的方法。
新建 http get和post代码片段,方便使用:
vue.json
{
"生成vue模板": {
"prefix": "vue",
"body": [
"<!-- $1 -->",
"<template>",
"<div class='$2'>$5</div>",
"</template>",
"",
"<script>",
"//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)",
"//例如:import 《组件名称》 from '《组件路径》';",
"",
"export default {",
"//import引入的组件需要注入到对象中才能使用",
"components: {},",
"props: {},",
"data() {",
"//这里存放数据",
"return {",
"",
"};",
"},",
"//监听属性 类似于data概念",
"computed: {},",
"//监控data中的数据变化",
"watch: {},",
"//方法集合",
"methods: {",
"",
"},",
"//生命周期 - 创建完成(可以访问当前this实例)",
"created() {",
"",
"},",
"//生命周期 - 挂载完成(可以访问DOM元素)",
"mounted() {",
"",
"},",
"beforeCreate() {}, //生命周期 - 创建之前",
"beforeMount() {}, //生命周期 - 挂载之前",
"beforeUpdate() {}, //生命周期 - 更新之前",
"updated() {}, //生命周期 - 更新之后",
"beforeDestroy() {}, //生命周期 - 销毁之前",
"destroyed() {}, //生命周期 - 销毁完成",
"activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发",
"}",
"</script>",
"<style lang='scss' scoped>",
"//@import url($3); 引入公共css类",
"$4",
"</style>"
],
"description": "生成vue模板(全局用户代码片段)"
},
"http-get请求": {
"prefix": "httpget",
"body": [
"this.\\$http({",
"url: this.\\$http.adornUrl(''),",
"method: 'get',",
"params: this.\\$http.adornParams({})",
"}).then(({ data }) => {",
"})"
],
"description": "httpGET请求"
},
"http-post请求": {
"prefix": "httppost",
"body": [
"this.\\$http({",
"url: this.\\$http.adornUrl(''),",
"method: 'post',",
"data: this.\\$http.adornData(data, false)",
"}).then(({ data }) => { });"
],
"description": "httpPOST请求"
}
}
src/views/modules/product/category.vue
增加删除方法
methods: {
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get",
}).then(({ data }) => {
this.menus = data.data;
});
},
append(data) {
console.log("append", data);
},
remove(node, data) {
var ids = [data.catId];
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({
message: "菜单删除成功", // 菜单删除成功仍然要展示父节点
type: "success",
});
// 重新刷新页面
this.getMenus();
// 设置需要默认展开的菜单
this.expendedKey = [node.parent.data.catId];
});
})
.catch(() => {});
},
},
该页面实现了,删除接口调用,确认删除提示,删除成功提示,删除刷新,删除之后父菜单栏默认展开。
菜单栏默认展开,需要添加该属性:
:default-expanded-keys="expendedKey"
data增加 expendedKey
属性
data() {
return {
menus: [],
expendedKey: [],
defaultProps: {
children: "children",
label: "name",
},
};
},
remove方法里边增加属性赋值
// 设置需要默认展开的菜单
this.expendedKey = [node.parent.data.catId];
前端页面完整代码:
<!-- 分类 -->
<template>
<el-tree
:data="menus"
:props="defaultProps"
:expand-on-click-node="false"
show-checkbox
node-key="catId"
:default-expanded-keys="expendedKey"
>
<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>
</span>
</span>
</el-tree>
</template>
<script>
// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
// 例如:import 《组件名称》 from '《组件路径》';
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
props: {},
data() {
return {
menus: [],
expendedKey: [],
defaultProps: {
children: "children",
label: "name",
},
};
},
// 监听属性 类似于data概念
computed: {},
// 监控data中的数据变化
watch: {},
methods: {
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get",
}).then(({ data }) => {
this.menus = data.data;
});
},
append(data) {
console.log("append", data);
},
remove(node, data) {
var ids = [data.catId];
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({
message: "菜单删除成功", // 菜单删除成功仍然要展示父节点
type: "success",
});
// 重新刷新页面
this.getMenus();
// 设置需要默认展开的菜单
this.expendedKey = [node.parent.data.catId];
});
})
.catch(() => {});
},
},
// 生命周期 - 创建完成(可以访问当前this实例)
created() {
this.getMenus();
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted() {},
beforeCreate() {}, // 生命周期 - 创建之前
beforeMount() {}, // 生命周期 - 挂载之前
beforeUpdate() {}, // 生命周期 - 更新之前
updated() {}, // 生命周期 - 更新之后
beforeDestroy() {}, // 生命周期 - 销毁之前
destroyed() {}, // 生命周期 - 销毁完成
activated() {}, // 如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style>
</style>
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)