行业知识
day07
文章目录
- 1 分类管理
- 1.1 菜单添加
- 1.2 表结构介绍
- 1.3 页面制作
- 1.4 列表查询
- 1.4.1 需求分析
- 1.4.2 后端接口
- Category
- CategoryController
- CategoryService
- CategoryMapper
- CategoryMapper.xml
- 1.4.3 前端对接
- category.js
- category.vue
- 2 EasyExcel
- 2.1 数据导入导出意义
- 2.2 EasyExcel简介
- 2.3 入门案例
- 2.3.1 解析Excel数据
- 2.3.2 存储数据到Excel
- 2.4 导出功能
- 2.4.1 需求说明
- 2.4.2 后端接口
- CategoryController
- CategoryService
- CategoryMapper
- CategoryMapper.xml
- 2.4.3 前端对接
- category.js
- category.vue
- 2.5 导入功能
- 2.5.1 需求说明
- 2.5.2 后端接口
- CategoryController
- CategoryService
- CategoryMapper
- CategoryMapper.xml
- 2.5.3 前端对接
- 3 品牌管理
- 3.1 菜单添加
- 3.2 表结构介绍
- 3.3 页面制作
- 3.4 列表查询
- 3.4.1 后端接口
- Brand
- BrandController
- BrandService
- BrandMapper
- BrandMapper.xml
- 3.4.2 前端对接
- brand.js
- brand.vue
- 3.5 品牌添加
- 3.5.1 需求说明
- 3.5.2 页面制作
- 3.5.3 后端接口
- BrandController
- BrandService
- BrandMapper
- BrandMapper.xml
- 3.5.4 前端对接
- brand.js
- brand.vue
- 3.6 修改品牌
- 3.6.1 需求说明
- 3.6.2 数据回显
- 3.6.3 提交修改
- 后端接口
- BrandController
- BrandService
- BrandMapper
- BrandMapper.xml
- 前端对接
- brand.js
- brand.vue
- 3.7 删除品牌
- 3.7.1 需求说明
- 3.7.2 后端接口
- BrandController
- BrandService
- BrandMapper
- BrandMapper.xml
- 3.7.3 前端对接
- brand.js
- brand.vue
1 分类管理
分类管理就是对商品的分类数据进行维护。常见的分类数据:电脑办公、手机、家居家装、汽车用品…
1.1 菜单添加
首先在系统中添加分类管理的菜单,具体步骤如下所示:
1、在后台管理系统中通过系统管理的菜单管理添加分类管理的相关菜单,如下所示:
2、给系统管理员角色分配分类管理菜单访问权限:
3、在前端项目中创建对应的页面,以及配置对应的异步路由
在src/views/product的文件夹,在该文件夹中加入分类管理页面文件,如下所示
在src/router/modules文件夹下创建product.js路由文件,文件内容如下所示:
const Layout = () => import('@/layout/index.vue')const category = () => import('@/views/product/category.vue')export default [ { path: '/product', component: Layout, name: 'product', meta: { title: '商品管理', }, icon: 'Histogram', children: [ { path: '/category', name: 'category', component: category, meta: { title: '分类管理', }, }, ], },]在src/router/index.js中添加异步路由,如下所示:
import product from './modules/product' // 动态菜单export const asyncRoutes = [...system,...base,...product]
1.2 表结构介绍
分类数据所对应的表结构如下所示:
CREATE TABLE `category` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类id', `name` varchar(50) DEFAULT NULL COMMENT '分类名称', `image_url` varchar(200) DEFAULT NULL, `parent_id` bigint DEFAULT NULL COMMENT '父分类id', `status` tinyint DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]', `order_num` int DEFAULT NULL COMMENT '排序', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '删除标记(0:不可用 1:可用)', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=704 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品分类';
注意:分类数据是具有层级结构的,因此在进行数据展示的时候可以考虑使用树形表格进行展示。在咱们的尚品甄选项目中关于分类的数据只支持三级。
1.3 页面制作
对比如下页面结构,使用Element Plus制作出对应的页面,数据可以暂时使用假数据。
该页面可以将其分为2部分:
1、导入导出按钮
2、分类列表展示【树形表格】
代码实现如下所示:
导出 导入 {{ scope.row.status == 1 ? '正常' : '停用' }} import { ref } from 'vue';// 定义list属性模型const list = ref([ {"id":1 , "name":"数码" , "orderNum":"1" , "status":1 , "createTime":"2023-05-22" , "hasChildren": true}, {"id":2 , "name":"手机" , "orderNum":"1", "status":1, "createTime":"2023-05-22"},])// 加载数据的方法const fetchData = (row, treeNode, resolve) => { // 向后端发送请求获取数据 const data = [ {"id":3 , "name":"智能设备" , "orderNum":"1" , "status":1 , "createTime":"2023-05-22" }, {"id":4 , "name":"电子教育" , "orderNum":"2" , "status":1 , "createTime":"2023-05-22" }, ] // 返回数据 resolve(data)}.search-p { margin-bottom: 10px; padding: 10px; border: 1px solid #ebeef5; border-radius: 3px; background-color: #fff;}.tools-p { margin: 10px 0; padding: 10px; border: 1px solid #ebeef5; border-radius: 3px; background-color: #fff;}1.4 列表查询
1.4.1 需求分析
当页面初始化完毕以后,此时就需要从请求后端接口查询所有的一级分类数据,一级分类数据的parent_id为0。当用户点击某一个分类前的小箭头,那么此时就需要查询该分类下所对应的所有的子分类数据。对应的sql语句如下所示:
select * from category where parent_id = 0 ;
1.4.2 后端接口
Category
定义一个与数据库表相对应的实体类:
// com.atguigu.spzx.model.entity.product@Datapublic class Category extends BaseEntity {private String name;private String imageUrl;private Long parentId;private Integer status;private Integer orderNum;private Boolean hasChildren;private List children;}CategoryController
表现层代码实现:
// com.atguigu.spzx.manager.controller@RestController@RequestMapping(value="/admin/product/category")public class CategoryController { @Autowired private CategoryService categoryService; @Operation(summary = "根据parentId获取下级节点") @GetMapping(value = "/findByParentId/{parentId}") public Result findByParentId(@PathVariable Long parentId) { List list = categoryService.findByParentId(parentId); return Result.build(list , ResultCodeEnum.SUCCESS) ; }}CategoryService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl@Servicepublic class CategoryServiceImpl implements CategoryService { @Autowired private CategoryMapper categoryMapper ; @Override public List findByParentId(Long parentId) { // 根据分类id查询它下面的所有的子分类数据 List categoryList = categoryMapper.selectByParentId(parentId); if(!CollectionUtils.isEmpty(categoryList)) { // 遍历分类的集合,获取每一个分类数据 categoryList.forEach(item -> { // 查询该分类下子分类的数量 int count = categoryMapper.countByParentId(item.getId()); if(count > 0) { item.setHasChildren(true); } else { item.setHasChildren(false); } }); } return categoryList; }}CategoryMapper
持久层代码实现:
@Mapperpublic interface CategoryMapper { public abstract List selectByParentId(Long parentId); public abstract int countByParentId(Long id);}CategoryMapper.xml
映射文件中添加如下的sql语句:
id,name,image_url,parent_id,status,order_num,create_time,update_time,is_deleted select from categorywhere parent_id = #{parentId}and is_deleted = 0order by id desc select count(id)from categorywhere parent_id = #{parentId}and is_deleted = 01.4.3 前端对接
category.js
在src/api文件夹下创建一个category.js文件,文件的内容如下所示:
import request from '@/utils/request'const api_name = '/admin/product/category'// 根据parentId获取下级节点export const FindCategoryByParentId = parentId => { return request({ url: `${api_name}/findByParentId/${parentId}`, method: 'get', })}category.vue
修改category.vue文件,内容如下所示:
import { ref , onMounted} from 'vue';import { FindCategoryByParentId } from '@/api/category.js'// 定义list属性模型const list = ref([])// 页面初始化完毕以后请求后端接口查询数据onMounted(async () => { const {code , data , message} = await FindCategoryByParentId(0) list.value = data ; })// 加载数据的方法const fetchData = async (row, treeNode, resolve) => { // 向后端发送请求获取数据 const {code , data , message} = await FindCategoryByParentId(row.id) // 返回数据 resolve(data)}2 EasyExcel
2.1 数据导入导出意义
后台管理系统是管理、处理企业业务数据的重要工具,在这样的系统中,数据的导入和导出功能是非常重要的,其主要意义包括以下几个方面:
1、提高数据操作效率:手动逐条添加或修改数据不仅费时费力,而且容易出错,此时就可以将大量数据从Excel等表格软件中导入到系统中时,通过数据导入功能,可以直接将表格中的数据批量导入到系统中,提高了数据操作的效率。
2、实现数据备份与迁移:通过数据导出功能,管理员可以将系统中的数据导出为 Excel 或其他格式的文件,以实现数据备份,避免数据丢失。同时,也可以将导出的数据文件用于数据迁移或其他用途。
3、方便企业内部协作:不同部门可能会使用不同的系统或工具进行数据处理,在这种情况下,通过数据导入和导出功能,可以方便地转换和共享数据,促进企业内部协作。
2.2 EasyExcel简介
官网地址:https://easyexcel.opensource.alibaba.com/
EasyExcel 的主要特点如下:
1、高性能:EasyExcel 采用了异步导入导出的方式,并且底层使用 NIO 技术实现,使得其在导入导出大数据量时的性能非常高效。
2、易于使用:EasyExcel 提供了简单易用的 API,用户可以通过少量的代码即可实现复杂的 Excel 导入导出操作。
3、增强的功能“EasyExcel 支持多种格式的 Excel 文件导入导出,同时还提供了诸如合并单元格、数据校验、自定义样式等增强的功能。
4、可扩展性好:EasyExcel 具有良好的扩展性,用户可以通过自定义 Converter 对自定义类型进行转换,或者通过继承 EasyExcelListener 来自定义监听器实现更加灵活的需求。
2.3 入门案例
2.3.1 解析Excel数据
需求:对资料中的excel数据进行解析,将其存储到对应的List集合中,并遍历List集合
步骤:
1、在spzx-model的pom.xml文件中添加如下依赖:
com.alibaba easyexcel ch.qos.logback logback-classic
2、定义一个实体类来封装每一行的数据,如下所示:
// com.atguigu.spzx.model.vo.product@Datapublic class CategoryExcelVo {@ExcelProperty(value = "id" ,index = 0)private Long id;@ExcelProperty(value = "名称" ,index = 1)private String name;@ExcelProperty(value = "图片url" ,index = 2)private String imageUrl ;@ExcelProperty(value = "上级id" ,index = 3)private Long parentId;@ExcelProperty(value = "状态" ,index = 4)private Integer status;@ExcelProperty(value = "排序" ,index = 5)private Integer orderNum;}3、定义一个监听器,监听解析到的数据,如下所示:
public class ExcelListener extends AnalysisEventListener { //可以通过实例获取该值 private List datas = new ArrayList(); @Override public void invoke(T o, AnalysisContext analysisContext) { // 每解析一行数据就会调用一次该方法 datas.add(o);//数据存储到list,供批量处理,或后续自己业务逻辑处理。 } public List getDatas() { return datas; } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { // excel解析完毕以后需要执行的代码 } }4、编写测试方法
public class EasyExcelTest { @Test public void easyExcelReadTest() { String fileName = "E://分类数据.xlsx" ; ExcelListener excelListener = new ExcelListener(); // 创建一个监听器对象 EasyExcel.read(fileName, CategoryExcelVo.class, excelListener).sheet().doRead(); // 解析excel表格 List excelVoList = excelListener.getDatas(); // 获取解析到的数据 excelVoList.forEach(s -> System.out.println(s) ); // 进行遍历操作 }}2.3.2 存储数据到Excel
需求:将如下的集合数据存储到Excel中文件中
List list = new ArrayList() ;list.add(new CategoryExcelVo(1L , 0L , "数码办公" , 1 , 1)) ;list.add(new CategoryExcelVo(2L , 1L , "手机通讯" , 1 , 1)) ;list.add(new CategoryExcelVo(3L , 2L , "手机" , 1 , 0)) ;
代码实现:
@Testpublic void saveDataToExcel() { List list = new ArrayList() ; list.add(new CategoryExcelVo(1L , 0L , "数码办公" , 1 , 1)) ; list.add(new CategoryExcelVo(2L , 1L , "手机通讯" , 1 , 1)) ; list.add(new CategoryExcelVo(3L , 2L , "手机" , 1 , 0)) ; EasyExcel.write("D://分类数据.xlsx" , CategoryExcelVo.class).sheet("分类数据").doWrite(list);}2.4 导出功能
2.4.1 需求说明
当用户点击导出按钮的时候,此时将数据库中的所有的分类的数据导出到一个excel文件中,如下所示:
2.4.2 后端接口
CategoryController
表现层代码实现:
// com.atguigu.spzx.manager.controller#CategoryController@GetMapping(value = "/exportData")public void exportData(HttpServletResponse response) { categoryService.exportData(response);}CategoryService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl#CategoryServiceImpl@Overridepublic void exportData(HttpServletResponse response) { try { // 设置响应结果类型 response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("分类数据", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 查询数据库中的数据 List categoryList = categoryMapper.selectAll(); List categoryExcelVoList = new ArrayList(categoryList.size()); // 将从数据库中查询到的Category对象转换成CategoryExcelVo对象 for(Category category : categoryList) { CategoryExcelVo categoryExcelVo = new CategoryExcelVo(); BeanUtils.copyProperties(category, categoryExcelVo, CategoryExcelVo.class); categoryExcelVoList.add(categoryExcelVo); } // 写出数据到浏览器端 EasyExcel.write(response.getOutputStream(), CategoryExcelVo.class).sheet("分类数据").doWrite(categoryExcelVoList); } catch (IOException e) { e.printStackTrace(); }}CategoryMapper
持久层代码实现:
@Mapperpublic interface CategoryMapper { public abstract List selectAll();}CategoryMapper.xml
在映射文件中添加如下sql语句:
select from category where is_deleted = 0 order by id
2.4.3 前端对接
category.js
在src/api文件夹下创建一个category.js文件,文件的内容如下所示:
// 导出方法export const ExportCategoryData = () => { return request({ url: `${api_name}/exportData`, method: 'get', responseType: 'blob' // 这里指定响应类型为blob类型,二进制数据类型,用于表示大量的二进制数据 })}category.vue
修改category.vue文件,内容如下所示:
导出import { ExportCategoryData } from '@/api/category.js'const exportData = () => { // 调用 ExportCategoryData() 方法获取导出数据 ExportCategoryData().then(res => { // 创建 Blob 对象,用于包含二进制数据 const blob = new Blob([res]); // 创建 a 标签元素,并将 Blob 对象转换成 URL const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); // 设置下载文件的名称 link.download = '分类数据.xlsx'; // 模拟点击下载链接 link.click(); }) }2.5 导入功能
2.5.1 需求说明
当用户点击导入按钮的时候,此时会弹出一个对话框,让用户选择要导入的excel文件,选择完毕以后将文件上传到服务端,服务端通过easyExcel解析文件的内容,然后将解析的结果存储到category表中。如下所示:
2.5.2 后端接口
CategoryController
表现层代码实现:
// com.atguigu.spzx.manager.controller#CategoryController@PostMapping("importData")public Result importData(MultipartFile file) { categoryService.importData(file); return Result.ok();}CategoryService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl#CategoryServiceImpl@Overridepublic void importData(MultipartFile file) { // 使用EasyExcel解析数据 List categoryExcelVoList = ExcelHelper.importExcel(file, CategoryExcelVo.class); List categoryList = new ArrayList(); // 如果解析到的数据不为空,那么此时将解析到的对象转换成Category对象 if(!CollectionUtils.isEmpty(categoryExcelVoList)) { for(CategoryExcelVo categoryExcelVo : categoryExcelVoList) { Category category = new Category(); BeanUtils.copyProperties(categoryExcelVo, category, Category.class); categoryList.add(category); } // 进行数据的批量保存 categoryMapper.batchInsert(categoryList); }}CategoryMapper
持久层代码实现:
@Mapperpublic interface CategoryMapper { public abstract void batchInsert(List categoryList);}CategoryMapper.xml
映射文件中添加如下sql语句:
insert into category ( id, name, image_url, parent_id, status, order_num, create_time , update_time , is_deleted ) values ( #{item.id}, #{item.name}, #{item.imageUrl}, #{item.parentId}, #{item.status}, #{item.orderNum}, now(), now(), 0 )2.5.3 前端对接
修改category.vue文件,内容如下所示:
导入 上传 import { useApp } from '@/pinia/modules/app' // 文件上传相关变量以及方法定义const dialogImportVisible = ref(false)const headers = { token: useApp().authorization.token // 从pinia中获取token,在进行文件上传的时候将token设置到请求头中}const importData = () => { dialogImportVisible.value = true}// 上传文件成功以后要执行方法const onUploadSuccess = async (response, file) => { ElMessage.success('操作成功') dialogImportVisible.value = false const { data } = await FindCategoryByParentId(0) list.value = data ; }3 品牌管理
品牌管理就是对商品的所涉及到的品牌数据进行维护。常见的品牌数据:小米、华为、海尔…
3.1 菜单添加
首先在系统中添加品牌管理的菜单,具体步骤如下所示:
1、在后台管理系统中通过系统管理的菜单管理添加品牌管理的菜单,如下所示:
2、给系统管理员角色分配品牌管理菜单访问权限:
3、在前端项目中创建对应的页面,以及配置对应的异步路由
在src/views/product的文件夹,在该文件夹中加入品牌管理页面文件,如下所示:
在src/router/modules文件夹下创建product.js路由文件,文件内容如下所示:
const Layout = () => import('@/layout/index.vue')const category = () => import('@/views/product/category.vue')const brand = () => import('@/views/product/brand.vue')export default [ { path: '/product', component: Layout, name: 'product', meta: { title: '商品管理', }, icon: 'Histogram', children: [ { path: '/category', name: 'category', component: category, meta: { title: '分类管理', }, }, { path: '/brand', name: 'brand', component: brand, meta: { title: '品牌管理', }, }, ], },]3.2 表结构介绍
品牌数据所对应的表结构如下所示:
CREATE TABLE `brand` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL COMMENT '品牌名称', `logo` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL COMMENT '品牌图标', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '删除标记(0:不可用 1:可用)', PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='分类品牌'
3.3 页面制作
对比如下页面结构,使用Element Plus制作出对应的页面,数据可以暂时使用假数据。
该页面可以将其分为3部分:
1、添加按钮
2、数据表格
3、分页组件
代码实现如下所示:
添 加 修改 删除 import { ref } from 'vue'// 定义表格数据模型const list = ref([ {"id":1 , "name":"华为" , "logo":"http://139.198.127.41:9000/sph/20230506/华为.png"} , {"id":2 , "name":"小米" , "logo":"http://139.198.127.41:9000/sph/20230506/小米.png"} , ])// 分页条数据模型const total = ref(0).tools-p { margin: 10px 0; padding: 10px; border: 1px solid #ebeef5; border-radius: 3px; background-color: #fff;}3.4 列表查询
需求说明:当品牌管理页面加载完毕以后就向后端发送分页查询请求,后端进行分页查询,返回分页结果数据。
3.4.1 后端接口
Brand
创建一个与数据库表相对应的实体类,如下所示:
@Datapublic class Brand extends BaseEntity {private String name;private String logo;}BrandController
表现层代码实现:
// com.atguigu.spzx.manager.controller@RestController@RequestMapping(value="/admin/product/brand")public class BrandController { @Autowired private BrandService brandService ; @GetMapping("/{page}/{limit}") public Result findByPage(@PathVariable Integer page, @PathVariable Integer limit) { PageInfo pageInfo = brandService.findByPage(page, limit); return Result.build(pageInfo , ResultCodeEnum.SUCCESS) ; }}BrandService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl;@Servicepublic class BrandServiceImpl implements BrandService { @Autowired private BrandMapper brandMapper ; @Override public PageInfo findByPage(Integer page, Integer limit) { PageHelper.startPage(page, limit); List brandList = brandMapper.findByPage() ; return new PageInfo(brandList); }}BrandMapper
持久层代码实现:
// com.atguigu.spzx.manager.mapper@Mapperpublic interface BrandMapper { public abstract List findByPage(); }BrandMapper.xml
在BrandMapper.xml映射文件中添加如下的sql语句:
id,name,logo,create_time,update_time,is_deleted select from brand where is_deleted = 0 order by id desc
3.4.2 前端对接
brand.js
在src/api目录下添加brand.js文件,内容如下所示:
import request from '@/utils/request'const api_name = '/admin/product/brand'// 分页列表export const GetBrandPageList = (page, limit) => { return request({ url: `${api_name}/${page}/${limit}`, method: 'get' })}brand.vue
修改brand.vue文件,内容如下所示:
import { ref , onMounted } from 'vue'import { GetBrandPageList } from '@/api/brand.js'// 定义表格数据模型const list = ref([])// 分页条数据模型const total = ref(0)//分页条数据模型const pageParamsForm = { page: 1, // 页码 limit: 10, // 每页记录数}const pageParams = ref(pageParamsForm)// 钩子函数onMounted(()=> { fetchData()})//页面变化const handleSizeChange = size => { pageParams.value.limit = size fetchData()}const handleCurrentChange = number => { pageParams.value.page = number fetchData()}// 分页查询const fetchData = async () => { const {code , message , data} = await GetBrandPageList(pageParams.value.page , pageParams.value.limit) list.value = data.list total.value = data.total}3.5 品牌添加
3.5.1 需求说明
用户点击添加按钮,此时需要展示一个添加数据的表单对话框,用户填写表单数据,点击提交按钮,请求后端接口完成数据的保存操作。效果如下所示:
3.5.2 页面制作
页面代码如下所示:
添 加 提交 取消 // 定义提交表单数据模型const defaultForm = { logo: ""}const brand = ref(defaultForm)const dialogVisible = ref(false) // 显示添加品牌表单const addShow = () => { dialogVisible.value = true }.avatar-uploader .el-upload { border: 1px dashed var(--el-border-color); border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; transition: var(--el-transition-duration-fast);}.avatar-uploader .el-upload:hover { border-color: var(--el-color-primary);}.el-icon.avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 178px; height: 178px; text-align: center;}3.5.3 后端接口
BrandController
表现层代码实现:
// com.atguigu.spzx.manager.controller@PostMapping("save")public Result save(@RequestBody Brand brand) { brandService.save(brand); return Result.build(null , ResultCodeEnum.SUCCESS) ;}BrandService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl;public void save(Brand brand) { brandMapper.save(brand) ;}BrandMapper
持久层代码实现:
// com.atguigu.spzx.manager.mapper@Mapperpublic interface BrandMapper { public abstract void save(Brand brand);}BrandMapper.xml
在BrandMapper.xml映射文件中添加如下的sql语句:
insert into brand ( id, name, logo, create_time , update_time , is_deleted ) values ( #{id}, #{name}, #{logo}, now(), now(), 0 )3.5.4 前端对接
brand.js
在src/api目录下添加brand.js文件,内容如下所示:
// 保存品牌export const SaveBrand = brand => { return request({ url: `${api_name}/save`, method: 'post', data: brand, })}brand.vue
修改brand.vue文件,内容如下所示:
提交 取消 import { SaveBrand } from '@/api/brand.js'import { ElMessage, ElMessageBox } from 'element-plus' // 定义提交表单数据模型const defaultForm = { id: '', name: '', logo: ""}const brand = ref(defaultForm)const dialogVisible = ref(false) // 显示添加品牌表单const addShow = () => { brand.value = {} dialogVisible.value = true }//上传const handleAvatarSuccess = (response) => { brand.value.logo = response.data}// 保存数据const saveOrUpdate = () => { if (!brand.value.id) { saveData() } }// 新增const saveData = async () => { await SaveBrand(brand.value) dialogVisible.value = false ElMessage.success('操作成功') fetchData()}3.6 修改品牌
3.6.1 需求说明
当用户点击修改按钮的时候,那么此时就弹出对话框,在该对话框中需要将当前行所对应的品牌数据在该表单页面进行展示。当用户在该表单中点击提交按钮的时候那么此时就需要将表单进行提交,在后端需要提交过来的表单数据修改数据库中的即可。
效果如下所示:
3.6.2 数据回显
分析:
1、使用添加数据的表单即可
2、要将当前操作行的数据展示在表单中,那么此时需要用到插槽
代码如下所示:
修改 //进入修改const editShow = row => { brand.value = row dialogVisible.value = true}3.6.3 提交修改
后端接口
BrandController
表现层代码实现:
// com.atguigu.spzx.manager.controller@PutMapping("updateById")public Result updateById(@RequestBody Brand brand) { brandService.updateById(brand); return Result.build(null , ResultCodeEnum.SUCCESS) ;}BrandService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl;@Overridepublic void updateById(Brand brand) { brandMapper.updateById(brand) ;}BrandMapper
持久层代码实现:
// com.atguigu.spzx.manager.mapper@Mapperpublic interface BrandMapper { public abstract void updateById(Brand brand);}BrandMapper.xml
在BrandMapper.xml映射文件中添加如下的sql语句:
update brand set name = #{name}, logo = #{logo}, update_time = now() where id = #{id}前端对接
brand.js
在src/api目录下添加brand.js文件,内容如下所示:
// 修改信息export const UpdateBrandById = brand => { return request({ url: `${api_name}/updateById`, method: 'put', data: brand, })}brand.vue
修改brand.vue文件,内容如下所示:
import { UpdateBrandById } from '@/api/brand.js' // 保存数据const saveOrUpdate = () => { if (!brand.value.id) { saveData() } else { updateData() }}// 修改const updateData = async () => { await UpdateBrandById(brand.value) dialogVisible.value = false ElMessage.success('操作成功') fetchData()}3.7 删除品牌
3.7.1 需求说明
当点击删除按钮的时候此时需要弹出一个提示框,询问是否需要删除数据?如果用户点击是,那么此时向后端发送请求传递id参数,后端接收id参数进行逻辑删除。
效果如下所示:
3.7.2 后端接口
BrandController
表现层代码实现:
// com.atguigu.spzx.manager.controller@DeleteMapping("/deleteById/{id}")public Result deleteById(@PathVariable Long id) { brandService.deleteById(id); return Result.build(null , ResultCodeEnum.SUCCESS) ;}BrandService
业务层代码实现:
// com.atguigu.spzx.manager.service.impl;@Overridepublic void deleteById(Long id) { brandMapper.deleteById(id) ;}BrandMapper
持久层代码实现:
// com.atguigu.spzx.manager.mapper@Mapperpublic interface BrandMapper { public abstract void deleteById(Long id);}BrandMapper.xml
在BrandMapper.xml映射文件中添加如下的sql语句:
update brand set update_time = now() , is_deleted = 1 where id = #{id}3.7.3 前端对接
brand.js
在src/api目录下添加brand.js文件,内容如下所示:
// 根据id删除品牌export const DeleteBrandById = id => { return request({ url: `${api_name}/deleteById/${id}`, method: 'delete', })}brand.vue
修改brand.vue文件,内容如下所示:
删除 import { DeleteBrandById } from '@/api/brand.js' //删除const remove = async id => { ElMessageBox.confirm('此操作将永久删除该记录, 是否继续?', 'Warning', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }) .then(async () => { await DeleteBrandById(id) ElMessage.success('删除成功') fetchData() }) .catch(() => { ElMessage.info('取消删除') })}
上一篇:腾讯云服务器怎么租用的?
下一篇:台服服务器怎么打开网络?