文章目录
-
- 1.数据库表设计
- 2.renren-generator生成CRUD
- 3.前端显示树形菜单和属性分组信息
- 5.点击家居第三级分类,显示对应商品属性组信息
- 6.通过管理系统来添加属性组
- 7.通过管理系统,修改属性组
1.数据库表设计
1.在sunliving_commodity数据库中创建商品属性表
use sunliving_commodity;
CREATE TABLE `commodity_attrgroup`
(
id BIGINT NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` CHAR(20) COMMENT '组名',
sort INT COMMENT '排序',
description VARCHAR(255) COMMENT '说明',
icon VARCHAR(255) COMMENT '组图标',
category_id BIGINT COMMENT '所属分类 id',
PRIMARY KEY (id)
) CHARSET = utf8mb4 COMMENT ='家居商品属性分组';
2.插入测试数据
INSERT INTO
`commodity_attrgroup` (id,`name`, sort,description,icon,category_id)
VALUES(1, '主体',0,'主体说明','',301);
INSERT INTO
`commodity_attrgroup` (id,`name`, sort,description,icon,category_id)
VALUES(2, '规格',0,'规格说明','',301);
INSERT INTO
`commodity_attrgroup` (id,`name`, sort,description,icon,category_id)
VALUES(3, '功能',0,'功能说明','',301);
SELECT * FROM `commodity_attrgroup`;
2.renren-generator生成CRUD
1.配置renren-generator生成代码
1.application.yml 配置数据库连接
2.generator.properties 配置生成器
3.根据端口访问生成器服务 http://localhost:81/
4.生成代码
5.将main目录覆盖掉本项目的main目录,注意如果冲突立即停止,手动调整
2.检查代码
1.数据表字段
2.application.yml的mybatis-plus配置(默认开启自动驼峰命名)
3.AttrgroupEntity.java
- 检查驼峰命名对应没问题
4.AttrgroupDao.java(@Mapper 注入容器)
5.AttrgroupDao.xml(application.yml 配置扫描)
6.AttrgroupService.java
7.AttrgroupServiceImpl.java(@Service 注入容器)
8.AttrgroupController.java(@RestController 注入容器)
@RequiresPermissions注解全部注销掉
3.测试后端代码
1.测试查询
http://localhost:9091/sunliving-commodity/commodity/attrgroup/list
2.测试修改
http://localhost:9091/sunliving-commodity/commodity/attrgroup/update
4.前端创建页面并完成crud测试
1.创建目录和菜单
2.将代码生成器生成的两个前端页面拷贝到前端对应目录下
1.后端生成页面所在位置
2.粘贴到前端指定位置
3.修改attrgroup.vue的一个url,查看是否能正常访问
4.重启前端项目测试,跨域问题,说明成功访问到了后端资源(直接使用网关解决跨域即可)
3.区分多环境并配置GateWay
1.由于还是访问的 sunliving-commodity 模块,所以之前已经区分过多环境了
dev.env.js
prod.env.js
2.配置GateWay也配置过了
3.修改attrgroup.vue的一个url为使用GateWay的请求
4.再次访问,请求成功!
5.将其使用环境变量替换,并修改attrgroup.vue和attrgroup-add-or-update.vue的所有请求(共四个)
6.如果有时候会出现不好使的情况,就进Nacos把服务影响的服务下线(因为之前已经上线了项目,但是后端没更新)
3.前端显示树形菜单和属性分组信息
1.view层进行布局,将页面分成两列
- 第一列是树形菜单
- 第二列就是表单
<!--
1. el-row 是 elementui 的布局控件 参考 elementui 官网 - Layout 布局 -分栏间隔
2. 我们将其分成两栏, 一栏放置分类树形菜单 一栏放置家居分类属性组的表单-->
<el-row :gutter="20">
<el-col :span="5">
<!--1. 分类树形占 5 个单元宽度, 保留 ref, :data, :props, node-key 基本显示的属性
2. node-click 实际是 el-tree 中规定好的实际,会传递三个参数: 参考 elmentui 官网
elementui-Tree 树形控件-Events -->
<el-tree ref="categoryTree" :data="data" :props="defaultProps" node-key="id">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
</span>
</el-tree>
</el-col>
<el-col :span="19">
<!-- 说明 原家居分类属性组的表单放在这里 带 div. -->
</el-col>
</el-row>
2.数据池绑定两个树形菜单的属性
data: [], // 树形控件的数据
defaultProps: { // 树形控件的默认属性配置
children: 'childrenCategories',
label: 'name'
},
3.方法池编写获取data的方法
// 获取分类列表(带层级)
getCategories() {
this.$http({
url: process.env.COMMODITY_BASEPATH + '/commodity/category/list/tree',
method: 'get'
}).then(({data}) => { // 解构了data
this.data = data.data;
})
}
4.初始化时调用
created() { // 生命周期钩子,初始化时调用
this.getCategories()
}
5.结果展示
5.点击家居第三级分类,显示对应商品属性组信息
1.后端 sunliving-commodity模块
1.com/sun/sunliving/commodity/service/AttrgroupService.java 新增方法
/**
* 条件分页查询属性分组
* @param params
* @param categoryId
* @return
*/
PageUtils queryPage(Map<String, Object> params, Long categoryId);
2.com/sun/sunliving/commodity/service/impl/AttrgroupServiceImpl.java
@Override
public PageUtils queryPage(Map<String, Object> params, Long categoryId) {
//1.获取查询输入框的key
String key = (String) params.get("key");
//2.构造查询条件
QueryWrapper<AttrgroupEntity> wrapper = new QueryWrapper<>();
//如果key不为空
if (StringUtils.isNotBlank(key)) {
System.out.println("key = " + key);
// id等于key或者name like %key%
wrapper.eq("id", key).or().like("name", key);
}
// 如果categoryId不为0
if (categoryId != 0) {
// categoryId等于categoryId
wrapper.eq("category_id", categoryId);
}
// 3.分页查询
IPage<AttrgroupEntity> page = this.page(
new Query<AttrgroupEntity>().getPage(params),
// 查询条件
wrapper
);
return new PageUtils(page);
}
3.com/sun/sunliving/commodity/controller/AttrgroupController.java
/**
* 条件分页查询属性分组
*/
@RequestMapping("/list/{categoryId}")
public R list(@RequestParam Map<String, Object> params, @PathVariable("categoryId") Long categoryId) {
PageUtils page = attrgroupService.queryPage(params, categoryId);
return R.ok().put("page", page);
}
2.前端 attrgroup.vue
1.el-tree添加点击事件,得到节点信息
2.数据池定义catId默认为0
3.方法池实现点击方法,点击后如果为三级节点就进行条件查询
// 点击树形节点,获取数据,如果是第三级就进行条件分页查询
nodeclick(data) {
if (data.catLevel == 3) {
this.catId = data.id
this.getDataList() // 进行条件分页查询
}
}
4.修改getDataList,添加catId的参数条件
3.整体分析
1.后端接口
- 如果传递了参数key,则添加name like key或者id等于key的查询条件
- 如果catId不为0,则添加按照catId进行查询的条件
2.前端逻辑
- 点击节点,获取该节点的信息
- 如果等级是3,则给数据池中的catId赋值,然后调用getDataList查询,携带catId
- 这样,初始化时catId默认为0,key也为空,所以不带条件查询
- 点击了节点则会按照catId查询
- 输入了key则会按照key查询
- 既点击了节点又输入了key,则会进行两个条件的查询
4.后端sunliving-commodity模块引入分页插件完成分页功能
com/sun/sunliving/commodity/config/CorsConfig.java
package com.sun.sunliving.commodity.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Description: 分页插件使用
*
* @Author sun
* @Create 2024/4/18 13:06
* @Version 1.0
*/
@Configuration
@EnableTransactionManagement // 开启事务
@MapperScan("com.sun.sunliving.commodity.dao") // 扫描mapper接口
public class MyBatisConfig {
// 引入分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作,
// true 调回到首页,false 继续请求 默认 false
paginationInterceptor.setOverflow(true);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
paginationInterceptor.setLimit(100);
return paginationInterceptor;
}
}
6.通过管理系统来添加属性组
1.前端引入级联选择器 attrgroup-add-or-update.vue
1.方法池获取分类列表(带层级)
// 获取分类列表(带层级)
getCategories() {
this.$http({
url: process.env.COMMODITY_BASEPATH + '/commodity/category/list/tree',
method: 'get'
}).then(({data}) => { // 解构了data
this.data = data.data;
})
}
2.created方法调用一下
created() {
this.getCategories()
}
3.输出一下data,是可以获取到树形菜单的值的
4.view引入树形菜单
<el-cascader
v-model="cascadedCategoryId"
:options="categories"
:props="props"
></el-cascader>
5.配置数据池
categories: [], // 树形数据
cascadedCategoryId: [], // 级联选择器的值,从 categories 中取,如果是三级就是[1,2,3]的形式
props: {
value: 'id', // 从 categories 中取 id放到 cascadedCategoryId
label: 'name', // 从 categories 中取 name作为级联选择器的显示标签
children: 'childrenCategories', // 从 categories 中取 childrenCategories作为级联选择器的子选项
expandTrigger: 'hover' // 悬停展开
}
6.方法池中将树形数据给categories
7.查看效果
2. 后端 sunliving-commodity模块
1.修改com/sun/sunliving/commodity/entity/CategoryEntity.java,添加注解,使得如果为空就不返回子列表
2.成功解决显示空白的问题
3.前端提交表单
1.修改提交表单逻辑,从级联选择器中取最后一个id值
2.尝试提交,校验失败
3.解决方式:将级联选择器的值赋值给表单,还按照原来方式提交
7.通过管理系统,修改属性组
1.问题分析
1.目前点击修改,所属分类id不会自动显示
2.原因是点击修改按钮的回显策略是之前的回显表单数据,所以失效了
2.解决思路分析
1.找到目前这个view所绑定的model
2.点击修改后的策略是向/info/{id}发送请求获取数据
3.所以解决方式就是:修改后端/info/{id}的逻辑,使其可以返回这个级联菜单的model数据
3.具体实现
1.由于是返回一个AttrgroupEntity.java,所以需要添加级联菜单的属性
2.经过分析,这个级联菜单的属性需要查找category表的所有父ip
1.com/sun/sunliving/commodity/service/CategoryService.java
/**
* 根据id来获取该id对应的所有父id的数组
*
* @return
*/
List<Long> getCascadedCategoryId(Long categoryId);
2.com/sun/sunliving/commodity/service/impl/CategoryServiceImpl.java
@Override
public List<Long> getCascadedCategoryId(Long categoryId) {
ArrayList<Long> res = new ArrayList<>();
// 根据categoryId查询出所有的父id,并放到res中
// 查询一下当前记录
CategoryEntity categoryEntity = categoryDao.selectById(categoryId);
// 只要当前记录不为空,就一直循环
while (categoryEntity != null) {
res.add(categoryEntity.getId());
categoryId = categoryEntity.getParentId();
categoryEntity = categoryDao.selectById(categoryId);
}
// 使用 Collections.reverse 直接反转
Collections.reverse(res);
return res;
}
3.修改com/sun/sunliving/commodity/controller/AttrgroupController.java 通过
/**
* 信息
*/
@RequestMapping("/info/{id}")
// @RequiresPermissions("commodity:attrgroup:info")
public R info(@PathVariable("id") Long id) {
AttrgroupEntity attrgroup = attrgroupService.getById(id);
// 调用categoryService获取所属分类id的所有父id
List<Long> cascadedCategoryId = categoryService.getCascadedCategoryId(attrgroup.getCategoryId());
attrgroup.setCascadedCategoryId(cascadedCategoryId);
return R.ok().put("attrgroup", attrgroup);
}