做网站推广需要多少费用,陕西营销型网站制作,免费查公司的网站,e4a做网站app简单分析一下商品分类表的结构 先来说一下分类表与品牌表之间的关系 再来说一下分类表和品牌表与商品表之间的关系 面我们要开始就要创建sql语句了嘛#xff0c;这里我们分析一下字段
用到的数据库是heima-tb_category这个表 现在去数据库里面创建好这张表 下面我们再去编… 简单分析一下商品分类表的结构 先来说一下分类表与品牌表之间的关系 再来说一下分类表和品牌表与商品表之间的关系 面我们要开始就要创建sql语句了嘛这里我们分析一下字段
用到的数据库是heima-tb_category这个表 现在去数据库里面创建好这张表 下面我们再去编写一个实体类之前我们去看一下这个类的请求方式请求路径请求参数返回数据都是什么 下面再去编写实体类
实体都是放到 出现了一个小插曲开始的时候我maven项目右边的模块有些是灰色的导致我导入依赖之后所有的注解什么都不能用解决方案如下 然后把依赖重新导入一下
我们先去完成我们商品分类表的一个实体类 Category.java
package com.leyou.item.pojo;import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;import javax.persistence.Id;
import javax.persistence.Table;/*** Created by Administrator on 2023/8/28.*/
Table(nametb_category)
Data
public class Category {IdKeySql(useGeneratedKeys true)private Long id;private String name;private Long parentId;private Boolean isParent;private Integer sort;
}然后去到ly-item-service去写具体的业务逻辑比如mapper,service,web都在这里面
这里来说一个依赖问题 引入了spring-boot-starter-web这个依赖也包含了spring的核心依赖
说一下在写这个controller类的时候我们的路径是什么路径就是我们访问每一个接口传递过来的url ResponseEntity这个类是干嘛的 格式用法有两种 CollectionUtils工具类 这个是Spring给我们提供的一个工具类
我们可以来做如下检测 下面我们贴上这个CategoryController的代码
package com.leyou.item.web;import com.leyou.item.pojo.Category;
import com.leyou.item.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** Created by Administrator on 2023/8/29.*/
RestController
RequestMapping(/category)
public class CategoryController {Autowiredprivate CategoryService categoryService;/*** 根据父节点的id查询商品分类* param pid* return*/GetMapping(/list)public ResponseEntityListCategory queryCategoryListByPid(RequestParam(pid)Long pid) {try {if(pid null || pid.longValue() 0) {//会返回带着状态码的对象400 参数不合法// return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();//可以做一格优化下面的类似return ResponseEntity.badRequest().build();}//开始利用service执行查询操作ListCategory categoryList categoryService.queryCategoryListByParentId(pid);if(CollectionUtils.isEmpty(categoryList)) {//如果结果集为空响应404return ResponseEntity.notFound().build();}//查询成功响应200return ResponseEntity.ok(categoryList);//这里才真正放了数据} catch (Exception e) {e.printStackTrace();}//自定义状态码然后返回//500返回一个服务器内部的错误//这里也可以不返回程序出错本身就会返回500return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build()}}下面我们去Service创建queryCategoryListByParentId这个方法
看一下完整代码
package com.leyou.item.service;import com.leyou.item.mapper.CategoryMapper;
import com.leyou.item.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/*** Created by Administrator on 2023/8/29.*/
Service
public class CategoryService {Autowiredprivate CategoryMapper categoryMapper;/*** 根据父节点的id来查询子结点* param pid* return*/public ListCategory queryCategoryListByParentId(Long pid) {Category category new Category();category.setParentId(pid);return categoryMapper.select(category);}}上面都做完了现在去数据库操作把分类中的数据给插入一下类似于如下这些数据 下面就是在数据中存在的数据 下面我开始去启动
我们的数据肯定是去走网关的
网关很明显我们是可以看到数据的 但是在项目里面点击就出不来 上面明显就是出现了跨域的问题 跨域我们就是在服务端进行一个配置 说的简单点服务器就给给我们配置如下信息 我们这里在服务器搭配一个类来配置这些信息就可以了
我们这里用SpringMVC帮我们写的一个cors跨域过滤器来做CrosFilter
具体代码如下
package com.leyou.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;/*** Created by Administrator on 2023/8/31.*/
Configuration
public class LeyouCorsConfiguration {Beanpublic CorsFilter corsFilter() {//1.添加CORS配置信息CorsConfiguration config new CorsConfiguration();//1) 允许的域,不要写*否则cookie就无法使用了config.addAllowedOrigin(http://manage.leyou.com);config.addAllowedOrigin(http://www.leyou.com);//2) 是否发送Cookie信息config.setAllowCredentials(true);//3) 允许的请求方式config.addAllowedMethod(OPTIONS);config.addAllowedMethod(HEAD);config.addAllowedMethod(GET);config.addAllowedMethod(PUT);config.addAllowedMethod(POST);config.addAllowedMethod(DELETE);config.addAllowedMethod(PATCH);// 4允许的头信息config.addAllowedHeader(*);//2.添加映射路径我们拦截一切请求UrlBasedCorsConfigurationSource configSource new UrlBasedCorsConfigurationSource();configSource.registerCorsConfiguration(/**, config);//3.返回新的CorsFilter.return new CorsFilter(configSource);}
}
重新启动一下网关服务器 下面来讲品牌查询 我们现在要做的就是查询出上面的品牌 我们必须弄明白请求方式请求路径请求参数响应数据决定返回值
一般来说如果页面要展示一个列表的话就要返回一个List集合对象或者返回一个分页对象
我们就必须定义一个分页对象
分页对象后面大家都要用我们就放到common里面去
先来把这个分页对象给做了
package com.leyou.common.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/*** Created by Administrator on 2023/9/2.*/
Data
NoArgsConstructor
AllArgsConstructor
public class PageResultT {private Long total;//总条数private Integer totalPage;//总页数private ListT items;//当前页面数据对象public PageResult(Long total,ListT items) {this.total total;this.items items;}
}下面我们来做一下前端页面 先去找这个页面在menu.js里面去查看商品的路径在什么位置 上面就是品牌的路径/item/brand下面我们看组件在哪里
去到下面这个位置 这个位置去找我们的路由页面 所有的页面组件全部都在pages里面放着
我们这里自己来写一下组件
我们自己定义一个MyBrand1.vue组件 我们这个页面主要还是去做一个分页的表格
可以去Vuetify里面查找
我们这里应该去找从服务端就已经分页与排序好的数据 下面我们可以去看到这里面的模板代码 上面就是我们要用的模板代码
数据脚本当然是你在script里面可以查看一下
scriptconst desserts [{name: Frozen Yogurt,calories: 159,fat: 6.0,carbs: 24,protein: 4.0,iron: 1,},{name: Jelly bean,calories: 375,fat: 0.0,carbs: 94,protein: 0.0,iron: 0,},{name: KitKat,calories: 518,fat: 26.0,carbs: 65,protein: 7,iron: 6,},{name: Eclair,calories: 262,fat: 16.0,carbs: 23,protein: 6.0,iron: 7,},{name: Gingerbread,calories: 356,fat: 16.0,carbs: 49,protein: 3.9,iron: 16,},{name: Ice cream sandwich,calories: 237,fat: 9.0,carbs: 37,protein: 4.3,iron: 1,},{name: Lollipop,calories: 392,fat: 0.2,carbs: 98,protein: 0,iron: 2,},{name: Cupcake,calories: 305,fat: 3.7,carbs: 67,protein: 4.3,iron: 8,},{name: Honeycomb,calories: 408,fat: 3.2,carbs: 87,protein: 6.5,iron: 45,},{name: Donut,calories: 452,fat: 25.0,carbs: 51,protein: 4.9,iron: 22,},]const FakeAPI {async fetch ({ page, itemsPerPage, sortBy }) {return new Promise(resolve {setTimeout(() {const start (page - 1) * itemsPerPageconst end start itemsPerPageconst items desserts.slice()if (sortBy.length) {const sortKey sortBy[0].keyconst sortOrder sortBy[0].orderitems.sort((a, b) {const aValue a[sortKey]const bValue b[sortKey]return sortOrder desc ? bValue - aValue : aValue - bValue})}const paginated items.slice(start, end)resolve({ items: paginated, total: items.length })}, 500)})},}export default {data: () ({itemsPerPage: 5,headers: [{title: Dessert (100g serving),align: start,sortable: false,key: name,},{ title: Calories, key: calories, align: end },{ title: Fat (g), key: fat, align: end },{ title: Carbs (g), key: carbs, align: end },{ title: Protein (g), key: protein, align: end },{ title: Iron (%), key: iron, align: end },],serverItems: [],loading: true,totalItems: 0,}),methods: {loadItems ({ page, itemsPerPage, sortBy }) {this.loading trueFakeAPI.fetch({ page, itemsPerPage, sortBy }).then(({ items, total }) {this.serverItems itemsthis.totalItems totalthis.loading false})},},}
/script
下面我们去看一下品牌表展示什么样的内容我们看一下数据库里面的字段先来创建一张产品表然后把数据也给插入进去 下面我们把数据给插进去类似于插入下面这些数据 看一下很明显这个表的数据就已经存在了 我们表头我们直接可以从下面的位置修改 下面直接展示品牌页面前端所有代码
templatev-cardv-card-titlev-btn colorprimary clickaddBrand新增品牌/v-btn!--搜索框与search属性关联--v-spacer/v-flex xs3v-text-field label输入关键字搜索 v-model.lazysearch append-iconsearch hide-details//v-flex/v-card-titlev-divider/v-data-table:headersheaders:itemsbrands:pagination.syncpagination:total-itemstotalBrands:loadingloadingclasselevation-1template slotitems slot-scopepropstd classtext-xs-center{{ props.item.id }}/tdtd classtext-xs-center{{ props.item.name }}/tdtd classtext-xs-centerimg v-ifprops.item.image :srcprops.item.image width130 height40span v-else无/span/tdtd classtext-xs-center{{ props.item.letter }}/tdtd classjustify-center layout px-0v-btn flat icon clickeditBrand(props.item) colorinfoi classel-icon-edit//v-btnv-btn flat icon clickdeleteBrand(props.item) colorpurplei classel-icon-delete//v-btn/td/template/v-data-table!--弹出的对话框--v-dialog max-width500 v-modelshow persistent scrollablev-card!--对话框的标题--v-toolbar dense dark colorprimaryv-toolbar-title{{isEdit ? 修改 : 新增}}品牌/v-toolbar-titlev-spacer/!--关闭窗口的按钮--v-btn icon clickcloseWindowv-iconclose/v-icon/v-btn/v-toolbar!--对话框的内容表单 这里是要把获得的brand 数据传递给子组件使用自定义标签:oldBrand 而父组件值为oldBrand--v-card-text classpx-5 styleheight:400pxbrand-form closecloseWindow :oldBrandoldBrand :isEditisEdit//v-card-text/v-card/v-dialog/v-card
/templatescript// 导入自定义的表单组件引入子组件 brandformimport BrandForm from ./BrandFormexport default {name: brand,data() {return {search: , // 搜索过滤字段totalBrands: 0, // 总条数brands: [], // 当前页品牌数据loading: true, // 是否在加载中pagination: {}, // 分页信息headers: [{text: id, align: center, value: id},{text: 名称, align: center, sortable: false, value: name},{text: LOGO, align: center, sortable: false, value: image},{text: 首字母, align: center, value: letter, sortable: true,},{text: 操作, align: center, value: id, sortable: false}],show: false,// 控制对话框的显示oldBrand: {}, // 即将被编辑的品牌数据isEdit: false, // 是否是编辑}},mounted() { // 渲染后执行// 查询数据--搜索后页面还处在第几页只要搜索页面渲染后重新查询this.getDataFromServer();},watch: {pagination: { // 监视pagination属性的变化deep: true, // deep为true会监视pagination的属性及属性中的对象属性变化handler() {// 变化后的回调函数这里我们再次调用getDataFromServer即可this.getDataFromServer();}},search: { // 监视搜索字段handler() {this.pagination.page 1;this.getDataFromServer();}}},methods: {getDataFromServer() { // 从服务的加载数的方法。// 发起请求this.$http.get(/item/brand/page, {params: {key: this.search, // 搜索条件page: this.pagination.page,// 当前页rows: this.pagination.rowsPerPage,// 每页大小sortBy: this.pagination.sortBy,// 排序字段desc: this.pagination.descending// 是否降序}}).then(resp { // 这里使用箭头函数this.brands resp.data.items;this.totalBrands resp.data.total;// 完成赋值后把加载状态赋值为falsethis.loading false;//})},addBrand() {// 修改标记新增前修改为falsethis.isEdit false;// 控制弹窗可见this.show true;// 把oldBrand变为null因为之前打开过修改窗口oldBrand数据被带过来了导致新增this.oldBrand null;},editBrand(oldBrand){//test 使用//this.show true;//获取要编辑的brand//this.oldBrand oldBrand;//requestParam,相当于把http,url ?namezhangsanage21 传给方法//pathvarable 相当与把url www.emporium.com/1/2 传给方法//如果不需要url上的参数controller不需要绑定数据// 根据品牌信息查询商品分类, 因为前台页面请求是拼接的 data 类似于jquery 里面回显的数据this.$http.get(/item/category/bid/ oldBrand.id).then(({data}) {// 修改标记this.isEdit true;// 控制弹窗可见this.show true;// 获取要编辑的brandthis.oldBrand oldBrand// 回显商品分类this.oldBrand.categories data;})},closeWindow(){// 重新加载数据this.getDataFromServer();// 关闭窗口this.show false;}},components:{BrandForm}}
/scriptstyle scoped/style下面开始写后台逻辑 开始写后台先写一个产品类 Brand.java
package com.leyou.item.pojo;import lombok.Data;import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;/*** Created by Administrator on 2023/9/2.*/
Data
Table(nametb_brand)
public class Brand {IdGeneratedValue(strategy GenerationType.IDENTITY)private Long id;private String name;//品牌名称private String image;//品牌图片private Character letter;
}接下来我们写上我们的通用Mapper类 下面我们去写service接口 下面去写Controller类
分析一下 返回的是什么当前页的数据list集合和总条数
也就是上面返回的是如下一个分页对象在ly-common模块里面如果需要用到这个模块的对象那么我们就需要把这个模块当成依赖引入到另外一个模块里面
这里是ly-item下面的模块ly-item-service需要用到PageResult对象 下面就是Controller中的代码 下面去完成Service中的方法
package com.leyou.item.service;import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.common.pojo.PageResult;
import com.leyou.item.mapper.BrandMapper;
import com.leyou.item.pojo.Brand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;/*** Created by Administrator on 2023/9/2.*/
Service
public class BrandService {//内部需要一个mapper调用Autowiredprivate BrandMapper brandMapper;/**** param page 当前页* param rows 每页大小* param sortBy 排序字段* param desc 是否降序* param key 搜索关键字* return*/public PageResultBrand queryBrandByPageAndSort(Integer page,Integer rows, String sortBy, Boolean desc, String key) {//开启分页//这个会自动拼接到后面的sql语句上面PageHelper.startPage(page,rows);//传进来一个页码和展示多少行的数据,//过滤Example example new Example(Brand.class);if(key ! null !.equals(key)) {//进来有一模糊查询//把这个语句拼接上example.createCriteria().andLike(name,% key %).orEqualTo(letter,key);}if(sortBy ! null !.equals(sortBy)) {//根据sortBy字段进行排序String orderByClause sortBy (desc ? DESC : ASC );example.setOrderByClause(orderByClause);}//利用通用mapper进行查询PageBrand pageInfo (PageBrand) brandMapper.selectByExample(example);//返回结果//这里面传递总条数和页面信息return new PageResult(pageInfo.getTotal(),pageInfo);}
}说一下用Autowired注入Mapper的时候提示注入不了爆红