谷粒商城第十一天-品牌管理中关联分类

目录

一、总述

二、前端部分

1. 调整查询调用

2. 关联分类

三、后端部分

四、总结


一、总述

之前是在商品的分类管理中直接使用的若依的逆向代码

有下面的几个问题:

1. 表格上面的参数填写之后,都是按照完全匹配进行搜索,没有模糊匹配

2. 分页有问题

上面的这两个问题只要是你不做任何的修改,就是这个样子

下面是这里品牌管理特殊的:

1. 每个品牌需要关联分类


总的来说

前端:

在前端上面,将api啊,请求参数啊配好,因为其实这里是为了规范,原本的话,这个若依逆向生成的,的表单数据除了本身的填写的那些信息,还有分页参数也填上去了。这样的话就一个参数,当然后端可以只用一个参数接收,但是这个参数类除了含品牌的信息还额外的需要分页信息,就不合理了,因此得拆分,所以前端需要修改一下

另外因为每个品牌需要关联分类,因此还得添加上关联分类的这个按钮

后端:

这里的话,还是发生了一些改变的,相比之前直接无脑用。

首先:

1. 查询要分页并且模糊查询

2. 其次删除接口不能只删品牌本身,其品牌分类的关联也要将其删除(要有这种意识,其实这种意识是最基本的,我之前还傻傻的没有意识到,写博文的时候重看才发现问题的

然后对于品牌本身接口就这些修改。然后这里涉及到品牌-分类关联,因此

这里的话,这个关联的相关接口,要考虑是否需要对逆向生成的接口作修改

1. 通过需求,显示的时候需要显示分类名和品牌名

还好这个在关系表中都做了冗余存储,所以查的话正常查,不需要多次查啥的

2. 但是新增的时候,就需要查出品牌名和分类名,然后存入到关联表中

二、前端部分

两点:

1. 调整查询调用

现在需要分页(其实本来就可以分页的,只是这里规范一下子,其实也不知道是不是真的规范,但是我现在就这样弄吧!

api:

// 查询品牌列表
export function listBrand(brandParams,pageParams) {return request({url: '/product/brand/list',method: 'get',params: {brand: JSON.stringify(brandParams),pageParams: JSON.stringify(pageParams)}})
}

这里的话其实如果要想两个参数还是get请求的话,就必须得这样写,就是先将其转为字符串,

直接对象的话,我测试了后端接收不到。除非换成post请求,后端使用@RequestBody进行接收

调用: 

 

/** 查询品牌列表 */getList() {this.loading = true;const {name,descript,firstLetter,sort} = this.queryParams;const {pageNum,pageSize} = this.queryParams;let brandParams = {name,descript,firstLetter,sort};let pageParams = {pageNum,pageSize};listBrand(brandParams,pageParams).then((response) => {this.brandList = response.rows;this.total = response.total;this.loading = false;});},

2. 关联分类

1. 从老师给的代码中选取相关构件(有基本样子)

1. 1 将其”关联分类“按钮放好

<el-button type="text" size="mini" @click="updateCatelogHandle(scope.row.brandId)">关联分类</el-button>

1.2 弹窗代码放置好

 <el-dialog title="关联分类" :visible.sync="cateRelationDialogVisible" width="30%"><el-popover placement="right-end" v-model="popCatelogSelectVisible"><category-cascader :catelogPath.sync="catelogPath"></category-cascader><div style="text-align: right; margin: 0"><el-button size="mini" type="text" @click="popCatelogSelectVisible = false">取消</el-button><el-button type="primary" size="mini" @click="addCatelogSelect">确定</el-button></div><el-button slot="reference">新增关联</el-button></el-popover><el-table :data="cateRelationTableData" style="width: 100%"><el-table-column prop="id" label="#"></el-table-column><el-table-column prop="brandName" label="品牌名"></el-table-column><el-table-column prop="catelogName" label="分类名"></el-table-column><el-table-column fixed="right" header-align="center" align="center" label="操作"><template slot-scope="scope"><el-buttontype="text"size="small"@click="deleteCateRelationHandle(scope.row.id,scope.row.brandId)">移除</el-button></template></el-table-column></el-table><span slot="footer" class="dialog-footer"><el-button @click="cateRelationDialogVisible = false">取 消</el-button><el-button type="primary" @click="cateRelationDialogVisible = false">确 定</el-button></span></el-dialog>

 注意到,它这里用了一个popover标签,这其实就是弹出窗

还是嵌套弹出窗。我把最后的效果拿出来:

至于这个分类怎么出来的,就是下面这一句:

<category-cascader :catelogPath.sync="catelogPath"></category-cascader>

这里的sync的作用是当选择的分类发生变化的时候,父组件中的catelogPath也将动态的变化

所以得在父组件也就是引用这个组件的组件,也就是在品牌的这个组件中,在数据域中声明好:catelogPath这个属性 

 这里就是一个分类组件,自己封装的,因为很多地方需要使用

要正确使用还是那三步:

1. 抽取组件

这里之前第十天的时候添加属性分组的时候,已经抽取出来了:

但是我那个比较简单,没有涉及到categoryPath的动态感应

没什么好说的,直接用老师的:

<template>
<!-- 
使用说明:
1)、引入category-cascader.vue
2)、语法:<category-cascader :catelogPath.sync="catelogPath"></category-cascader>解释:catelogPath:指定的值是cascader初始化需要显示的值,应该和父组件的catelogPath绑定;由于有sync修饰符,所以cascader路径变化以后自动会修改父的catelogPath,这是结合子组件this.$emit("update:catelogPath",v);做的--><div><el-cascaderfilterableclearable placeholder="试试搜索:手机"v-model="paths":options="categorys":props="setting"></el-cascader></div>
</template><script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
import {treeListCategory} from "@/api/product/category"
export default {//import引入的组件需要注入到对象中才能使用components: {},//接受父组件传来的值props: {catelogPath: {type: Array,default(){return [];}}},data() {//这里存放数据return {setting: {value: "catId",label: "name",children: "children",expandTrigger: 'hover'},categorys: [],paths: this.catelogPath};},watch:{catelogPath(v){this.paths = this.catelogPath;},paths(v){this.$emit("update:catelogPath",v);//还可以使用pubsub-js进行传值this.PubSub.publish("catPath",v);}},//方法集合methods: {getCategorys() {treeListCategory().then((response)=>{this.categorys = response.data;})}},//生命周期 - 创建完成(可以访问当前this实例)created() {this.getCategorys();}
};
</script>
<style scoped>
</style>

2. 导入组件

3. 使用组件

2. 从模板中提取好数据,绑定到数据域中

无非就是一些 弹窗的标志值还有数据

3. 修改方法

就是对老师给的方法看是不是要修改一下,无非就是修改一下数据格式,逻辑基本上不需要修改,无非就是请求那里使用自己的,导入一下自己的api,调用自己的请求对象

1. 

 这个没什么好说的,不要修改,就是打开一下弹窗,并且记录当前那一行的品牌id,为以后查关联作铺垫

 2. 获取关联列表

到这里,直接把查曾删都全部导入进来

 这个没什么好说的,主要是记得若依框架的查询接口,最终是以TableDataInfo对象返回的,所以得拿到里面的row才是真正的数据,这里的话不涉及到分页,所以拿到这个row真正的数据就行了。

//查询关联列表getCateRelation() {listRelation({brandId: this.brandId}).then((response)=>{this.cateRelationTableData = response.rows;})},

3. 新增关联

没什么好说的,传上品牌id和分类id即可

//新增品牌分类关联addCatelogSelect() {this.popCatelogSelectVisible =false;addRelation({brandId: this.brandId,catelogId: this.catelogPath[this.catelogPath.length-1]}).then((response)=>{if(response.code == 200){this.$modal.msgSuccess("新增品牌分类关系成功");this.getCateRelation();}else{this.$modal.confirm("新增品牌分类关系失败");}})}

4. 删除关联

也没什么好说的,直接传入关联id也就是当前这条记录的id即可

//删除关联deleteCateRelationHandle(id) {delRelation(id).then((response)=>{if(response.code == 200){this.$modal.msgSuccess("删除品牌分类关系成功");this.getCateRelation();}else{this.$modal.confirm("删除品牌分类关系失败");}})}

三、后端部分

1. 首先品牌本身

1.1 分页模糊查询

这个得话使用MP带的分页功能,因为若依自带的我还没弄明白。

需要注意的是要使用MP带的分页,就得配置一下,不然不起作用:

@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();paginationInnerInterceptor.setOptimizeJoin(true);paginationInnerInterceptor.setDbType(DbType.MYSQL);paginationInnerInterceptor.setOverflow(true);interceptor.addInnerInterceptor(paginationInnerInterceptor);OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);return interceptor;}
}

反正我用的3.4.3版本的MP是需要这个的:

 接口:

/*** 查询品牌列表*/
@ApiOperation("查询品牌列表")
//@PreAuthorize("@ss.hasPermi('product:brand:list')")
@GetMapping("/list")public TableDataInfo list(@RequestParam("brand") String brandJson,@RequestParam("pageParams") String pageParamsJson) {Brand brand = new Gson().fromJson(brandJson, Brand.class);PageParamsDto pageParamsDto = new Gson().fromJson(pageParamsJson, PageParamsDto.class);TableDataInfo tableDataInfo = brandService.pageList(brand,pageParamsDto);return tableDataInfo;}

当前端需要传递两个参数还需要是get请求的时候,后端参数就是用字符串接收,然后使用Gson类进行解析 

前端部分接口:

// 查询品牌列表
export function listBrand(brandParams,pageParams) {return request({url: '/product/brand/list',method: 'get',params: {brand: JSON.stringify(brandParams),pageParams: JSON.stringify(pageParams)}})
}

后端接口实现:

/*** 分页并且模糊查询获取品牌列表** @param brand* @param pageParamsDto* @return*/@Overridepublic TableDataInfo pageList(Brand brand, PageParamsDto pageParamsDto) {LambdaQueryWrapper<Brand> wrapper = new LambdaQueryWrapper<>();wrapper.like(StringUtils.hasText(brand.getName()),Brand::getName,brand.getName());wrapper.eq(brand.getFirstLetter()!=null,Brand::getFirstLetter,brand.getFirstLetter());wrapper.eq(brand.getSort()!=null,Brand::getSort,brand.getSort());wrapper.eq(Brand::getShowStatus,1);wrapper.like(StringUtils.hasText(brand.getDescript()),Brand::getDescript,brand.getDescript());Page<Brand> page = new Page<>(pageParamsDto.getPageNum(),pageParamsDto.getPageSize());page(page,wrapper);return new TableDataInfo(page.getRecords(),page.getTotal());}

1.2 删除需要注意关系也要删除

接口:

/*** 删除品牌*/@ApiOperation("删除品牌")//@PreAuthorize("@ss.hasPermi('product:brand:remove')")@Log(title = "品牌", businessType = BusinessType.DELETE)@DeleteMapping("/{brandIds}")public AjaxResult remove(@PathVariable Long[] brandIds) {return toAjax(brandService.removeMore(Arrays.asList(brandIds)));}

实现:

@Override@Transactionalpublic boolean removeMore(List<Long> list) {boolean remove = removeByIds(list);AtomicBoolean flag = new AtomicBoolean(true);list.stream().forEach(item->{LambdaQueryWrapper<CategoryBrandRelation> wrapper = new LambdaQueryWrapper<CategoryBrandRelation>().eq(CategoryBrandRelation::getBrandId, item);if(categoryBrandRelationService.list(wrapper).size()!=0){boolean remove1 = categoryBrandRelationService.remove(wrapper);if (!remove1) {flag.set(false);}}});return remove&& flag.get();}

这里操作了多张表,加上@Transactional注解

注意这里是存在关系再去进行删除,而非对每个都去删除,当不存在的时候去删除就是false,最终就会返回false了,就出错了。

2. 关联那边的

2.1 查询列表

很简单,直接逆向的,因为不涉及分页模糊

/*** 查询品牌分类关联列表*/
@ApiOperation("查询品牌分类关联列表")
//@PreAuthorize("@ss.hasPermi('product:relation:list')")
@GetMapping("/list")public TableDataInfo list(CategoryBrandRelation categoryBrandRelation) {startPage();List<CategoryBrandRelation> list = categoryBrandRelationService.list(new QueryWrapper<CategoryBrandRelation>(categoryBrandRelation));return getDataTable(list);}

2.2 新增

接口:

/*** 新增品牌分类关联*/@ApiOperation("新增品牌分类关联")//@PreAuthorize("@ss.hasPermi('product:relation:add')")@Log(title = "品牌分类关联", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(@RequestBody CategoryBrandRelation categoryBrandRelation) {return categoryBrandRelationService.saveDetails(categoryBrandRelation);}

实现:

@Overridepublic AjaxResult saveDetails(CategoryBrandRelation categoryBrandRelation) {//先判断当前的关联关系是否已存在LambdaQueryWrapper<CategoryBrandRelation> wrapper = new LambdaQueryWrapper<>(categoryBrandRelation);CategoryBrandRelation relation = getOne(wrapper);if (relation != null) {return AjaxResult.error("当前分类关联已存在");}Brand brand = brandService.getById(categoryBrandRelation.getBrandId());Category category = categoryService.getById(categoryBrandRelation.getCatelogId());categoryBrandRelation.setBrandName(brand.getName());categoryBrandRelation.setCatelogName(category.getName());boolean save = save(categoryBrandRelation);if (save) {return AjaxResult.success();}else{return AjaxResult.error();}}

这里要为两个冗余字段附上值,以便查询的时候不要多表去查,提高效率 

2.3 删除

没什么好说的,利用传来的关联id集合,直接使用MP的批量删除就行了

/*** 删除品牌分类关联*/@ApiOperation("删除品牌分类关联")//@PreAuthorize("@ss.hasPermi('product:relation:remove')")@Log(title = "品牌分类关联", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids) {return toAjax(categoryBrandRelationService.removeByIds(Arrays.asList(ids)));}

四、总结

前端就是引入那个分类关联相关的东西,该导入的组件导好,该导入的方法导好,把数据域配好,方法修改好就行了

总结前端开发步骤:

1. 导入好组件相关的基本构件,就是那三部分

别的组件、方法等

2. 看数据域是否要增添

3. 看方法是否要修改

这里后端的话:

1. 要知道分页模糊查询,这是最基本的,知道配合若依开发

2. 要对增删改接口有全局的意识,这点很重要,比如说增加的话,是不是需要额外的添加属性

删除的话,是不是还要删其他表,修改的话是不是也要动其他表

3. 了解若依的返回逻辑,对于增删改,若依是以toAjax()这种顶级封装的方式进行返回的,按照布尔值,选择是success还是error。而对于查询,是以TableDataInfo对象返回的,我们可以根据自己的需要,也可以改变这种方式,在service实现中来返回request对象,这样可以增加异常信息返回给前端。

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

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

相关文章

计算机网络—HTTP

这里写目录标题 HTTP是什么HTTP常见状态码HTTP常见字段GET与POST的区别Get和Post是安全和幂等吗PUT幂等&#xff0c;不安全DELETE幂等&#xff0c;不是安全 HTTP缓存技术HTTP缓存实现技术 HTTP1.0优缺点和性能HTTP1.1优缺点和性能HTTP2优缺点和性能HTTP3优缺点和性能HTTP和HTTP…

vuex学习总结

一、vuex工作原理 工作流程&#xff1a;需求&#xff1a;改变组件count的sun变量的值&#xff0c;先调用dispatch函数传入jia函数和要改变的值给actions&#xff08;这个actions里面必须有jia这个函数&#xff09;&#xff1b;actions收到后调用commit函数将jia方法和值传给mut…

做BI领域的ChatGPT,思迈特升级一站式ABI平台

8月8日&#xff0c;以「指标驱动 智能决策」为主题&#xff0c;2023 Smartbi V11系列新品发布会在广州丽思卡尔顿酒店开幕。 ​ 后疫情时代&#xff0c;BI发展趋势的观察与应对 在发布会上&#xff0c;思迈特CEO吴华夫在开场致辞中表示&#xff0c;当前大环境背景下&#xf…

Stable Diffusion教程(9) - AI视频转动漫

配套抖音视频教程&#xff1a;https://v.douyin.com/UfTcrcJ/ 安装mov2mov插件 打开webui点击扩展->从网址安装输入地址&#xff0c;然后点击安装 https://github.com/Scholar01/sd-webui-mov2mov 最后重启webui 下载模型 从国内liblib AI 模型站下载模型 LiblibAI哩…

已有公司将ChatGPT集成到客服中心以增强用户体验

Ozonetel正在利用ChatGPT来改善客户体验。该公司表示&#xff0c;他们通过使用ChatGPT收集与客户互动过程收集的“语料”能够更有针对性地提高服务效率&#xff0c;提供个性化的用户体验&#xff0c;并实现更高的客户满意度。[1] 通过这套解决方案&#xff0c;客服中心将拥有一…

办理流量卡也是有条件的,这五种情况就不能办理流量卡!

流量卡资费虽然便宜&#xff0c;但也不是谁都可以办得&#xff0c;以下这几种情况是办不了的&#xff01; 看到网上的流量卡资费便宜&#xff0c;也想随手申请一张&#xff0c;别想得太简单了&#xff0c;流量卡也不是那么好办理的&#xff0c;换句话来讲&#xff0c;办理流量…

【量化课程】07_量化回测

文章目录 7.1 pandas计算策略评估指标数据准备净值曲线年化收益率波动率最大回撤Alpha系数和Beta系数夏普比率信息比率 7.2 聚宽平台量化回测实践平台介绍策略实现 7.3 Backtrader平台量化回测实践Backtrader简介Backtrader量化回测框架实践 7.4 BigQuant量化框架实战BigQuant简…

特语云用Linux和MCSM面板搭建 我的世界基岩版插件服 教程

Linux系统 用MCSM和DockerWine 搭建 我的世界 LiteLoaderBDS 服务器 Minecraft Bedrock Edition 也就是我的世界基岩版&#xff0c;这是 Minecraft 的另一个版本。Minecraft 基岩版可以运行在 Win10、Android、iOS、XBox、switch。基岩版不能使用 Java 版的服务器&#xff0c;…

Spring BeanPostProcessor 接口的作用和使用

BeanPostProcessor 接口是 Spring 框架中的一个扩展接口&#xff0c;用于在 Spring 容器实例化、配置和初始化 bean 的过程中提供自定义的扩展点。通过实现这个接口&#xff0c;您可以在 bean 实例创建的不同生命周期阶段插入自己的逻辑&#xff0c;从而实现对 bean 行为的定制…

Springboot-Retrofit HTTP工具框架快速使用

在SpringBoot项目直接使用okhttp、httpClient或者RestTemplate发起HTTP请求&#xff0c;既繁琐又不方便统一管理。 因此&#xff0c;在这里推荐一个适用于SpringBoot项目的轻量级HTTP客户端框架retrofit-spring-boot-starter&#xff0c;使用非常简单方便&#xff0c;同时又提供…

【第二阶段】kotlin的函数类型作为返回类型

fun main() {//调用,返回的是一个匿名类型&#xff0c;所以info就是一个匿名函数val infoshow("",0)//info接受的返回值为匿名类型&#xff0c;此时info就是一个匿名函数println(info("kotlin",20)) }//返回类型为一个匿名函数的返回类型fun show(name:Str…

maven如何建立JavaWeb项目并连接数据库,验证登录

这里是建立建立web项目&#xff1a;Maven如何创建Java web项目&#xff08;纯干货版&#xff09;&#xff01;&#xff01;&#xff01;_明天更新的博客-CSDN博客 我们主要演示如何连接数据库验证登录。 1.在webapp目录下创建我们的登录页面&#xff1a;index.jsp 还需要再…

Stable Diffusion+Temporal-kit 半虚半实应用

1.先下载temporal-kit,重启webui 2.下载好ffmpeg,配置好环境,下载Ebsynth 3.准备好你需要的视频,拖到预处理视频位置 4.填写参数,点解保存设置,然后并点击生成,会生成到目标文件夹的input位置 5.然后拉出input文件夹里面你想切换成处理的帧图片,然后填写prompt查看效…

excel操作之向下填充快速操作(序号1->100)

开始-》填充-》序列-》列 步长值为1&#xff0c;终止值为100 如果是日期操作

Linux系统下安装Git软件

环境说明 Linux系统&#xff1a;CentOS 7.9 安装GCC等 JDK版本&#xff1a;jdk-8u202-linux-x64.tar.gz Maven版本&#xff1a;apache-maven-3.8.8-bin.tar.gz 在以上环境下安装Git&#xff08;git-2.41.0.tar.gz&#xff09;软件。 查看是否安装Git软件 查看Git版本&#…

STM32 F103C8T6学习笔记7:双机无线串口通信

今日尝试配通俩个C8T6单片机之间的无线串口通信&#xff0c;文章提供原理&#xff0c;源码&#xff0c;测试效果图&#xff0c;测试工程下载&#xff1a; 目录 传输不规范问题&#xff1a; 串口通信资源&#xff1a; 单个串口资源理解&#xff1a; 单片机串口资源&#xf…

Linux命名管道进程通信

文章目录 前言一、什么是命名管道通信二、创建方式三、代码示例四、文件进程通信总结 前言 命名管道 是实现进程间通信的强大工具&#xff0c;它提供了一种简单而有效的方式&#xff0c;允许不同进程之间进行可靠的数据交换。不仅可以在同一主机上的不相关进程间进行通信&…

Springboot集成ip2region离线IP地名映射-修订版

title: Springboot集成ip2region离线IP地名映射 date: 2020-12-16 11:15:34 categories: springboot description: Springboot集成ip2region离线IP地名映射 1. 背景2. 集成 2.1. 步骤2.2. 样例2.3. 响应实例DataBlock2.4. 响应实例RegionAddress 3. 打开浏览器4. 源码地址&…

04.利用Redis国逻辑过期实现缓存功能---解决缓存击穿

学习目标&#xff1a; 提示&#xff1a;学习如何利用Redis逻辑过期实现添加缓存功能解决缓存击穿 学习产出&#xff1a; 缓存击穿讲解图&#xff1a; 解决方案&#xff1a; 采用互斥锁采用逻辑过期 1. 准备pom环境 <dependency><groupId>org.springframework…

nodejs+vue+elementui学生档案信息管理系统_06bg9

利用计算机网络的便利&#xff0c;开发一套基于nodejs的大学生信息管理系统&#xff0c;将会给人们的生活带来更多的便利&#xff0c;而且在经济效益上&#xff0c;也会有很大的便利!这可以节省大量的时间和金钱。学生信息管理系统是学校不可缺少的一个环节&#xff0c;其内容直…