6.搜索模块
6.1构建列表页
- 步骤一:创建 ~/pages/list/_cid.vue 页面
- 步骤二:复制静态list.html页面到 list/_cid.vue中,并修改js和css引用方式
- 1)修改页面,完善标签
- 2)替换图片路径
<template>
<div>
<!-- 顶部导航 start -->
<!--
省略 html原有内容
-->
<!-- 底部版权 end -->
</div>
</template>
<script>
export default {
head: {
title: '列表页面',
link: [
{rel:'stylesheet',href: '/style/list.css'},
{rel:'stylesheet',href: '/style/common.css'},
{rel:'stylesheet',href: '/style/bottomnav.css'},
],
script: [
{ type: 'text/javascript', src: '/js/header.js' },
{ type: 'text/javascript', src: '/js/list.js' },
]
},
}
</script>
<style>
</style>
- 步骤三:添加已有组件
<template>
<div>
<!-- 顶部导航 start -->
<TopNav></TopNav>
<!-- 顶部导航 end -->
<div style="clear:both;"></div>
<!-- 头部 start -->
<HeaderSearch></HeaderSearch>
<!-- 头部 end-->
<div style="clear:both;"></div>
<!-- 列表主体 start -->
<!-- 省略 html原有内容 -->
<!-- 列表主体 end-->
<div style="clear:both;"></div>
<!-- 底部导航 start -->
<BottomNav></BottomNav>
<!-- 底部导航 end -->
<div style="clear:both;"></div>
<!-- 底部版权 start -->
<Footer></Footer>
<!-- 底部版权 end -->
</div>
</template>
<script>
import TopNav from '../../components/TopNav'
import HeaderSearch from '../../components/HeaderSearch'
import BottomNav from '../../components/BottomNav'
import Footer from '../../components/Footer'
export default {
head: {
title: '列表页面',
link: [
{rel:'stylesheet',href: '/style/list.css'},
{rel:'stylesheet',href: '/style/common.css'},
{rel:'stylesheet',href: '/style/bottomnav.css'},
],
script: [
{ type: 'text/javascript', src: '/js/header.js' },
{ type: 'text/javascript', src: '/js/list.js' },
]
},
components: {
TopNav,
HeaderSearch,
BottomNav,
Footer
},
}
</script>
<style>
</style>
6.2优化组件HeaderSearch组件
- 非首页“HeaderSearch”组件,不能隐藏分类
- 步骤一:修改HeaderSearch组件,添加props
export default {
props: {
isFirst: { //是否是首页
type: Boolean,
default: true
}
}
}
- 步骤二:如果不在首页时,在指定的3处添加样式
- 步骤三:修改 ~/pages/list/_id.vue ,将HeaderSearch组件的isFirst属性修改成false
- 步骤四:显示分类数据
<!-- 头部 start -->
<HeaderSearch :isFirst="false" :list="categorysList"></HeaderSearch>
<!-- 头部 end-->
async asyncData( { app } ) {
// 查询快报 + 查询分类
let [{data: categoryData}] = await Promise.all([
app.$requestServer.findCategorys()
])
return {
categorysList : categoryData.data
}
}
- 步骤五:修改logo访问路径
6.3指定分类的所有品牌
- 6.3.1接口
GET http://localhost:10010/web-service/brands/category/76
6.3.2后端实现:JavaBean
- 表结构分析:
- 分类表:tb_category
- 品牌表:tb_brand
关系:多对多(不同的分类,拥有不同的品牌)tb_category_bran
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Data
@TableName("tb_brand")
public class Brand {
@TableId(type = IdType.AUTO)
private Integer id; //品牌id
@TableField(value = "brand_name")
private String brandName; //品牌名称
@TableField(value = "logo")
private String logo; //品牌图片地址
}
6.3.3后端实现:查询
- 步骤一:创建BrandMapper接口,根据分类查询所有的品牌
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Brand;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Mapper
public interface BrandMapper extends BaseMapper<Brand> {
/**
* 根据分类查询所有的品牌
* @param categoryId
* @return
*/
@Select("select b.* from tb_brand b ,tb_category_brand cb " +
" where b.id = cb.brand_id and cb.category_id = #{categoryId}")
public List<Brand> findAll(@Param("categoryId") Integer categoryId);
}
- 步骤二:创建BrandService接口
package com.czxy.changgou4.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Brand;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
public interface BrandService extends IService<Brand> {
/**
* 根据分类查询所有的品牌
* @param categoryId
* @return
*/
public List<Brand> findAll(Integer categoryId);
}
- 步骤三:编写BrandService实现类
package com.czxy.changgou4.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.BrandMapper;
import com.czxy.changgou4.pojo.Brand;
import com.czxy.changgou4.service.BrandService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Service
@Transactional
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements BrandService {
@Override
public List<Brand> findAll(Integer categoryId) {
return baseMapper.findAll(categoryId);
}
}
- 步骤四:创建BrandController,符合接口规范
package com.czxy.changgou4.controller;
import com.czxy.changgou4.pojo.Brand;
import com.czxy.changgou4.service.BrandService;
import com.czxy.changgou4.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@RestController
@RequestMapping("/brands")
public class BrandController {
@Resource
private BrandService brandService;
/**
* //GET /brands/category/76
* @param categoryId
* @return
*/
@GetMapping("/category/{categoryId}")
public BaseResult findAll(@PathVariable("categoryId") Integer categoryId){
//1 查询
List<Brand> list = this.brandService.findAll( categoryId );
//2 封装
return BaseResult.ok("查询成功", list );
}
}
6.3.4前端实现
- 步骤一:修改apiclient.js,编写ajax
//指定分类的品牌
findBrand : (categoryId) => {
return axios.get('/web-service/brands/category/' + categoryId)
}
- 步骤二:修改 ~/pages/list/_cid 页面,页面加载成功后,获得分类id
data() {
return {
searchMap: { //搜索条件对象
catId: '' //分类id
}
}
},
async mounted() {
//设置id
this.searchMap.catId = this.$route.params.cid
},
- 步骤三:修改 ~/pages/list/_cid.vue 页面,查询品牌
data() {
return {
searchMap: { //搜索条件对象
catId: '' //分类id
},
brandList : [], //所有品牌
}
},
methods: {
async findAllBrandFn() {
let { data : brandData } = await this.$request.findBrand( this.searchMap.catId )
this.brandList = brandData.data
}
},
async mounted() {
//设置id
this.searchMap.catId = this.$route.params.cid
// 查询所有的品牌
this.findAllBrandFn()
},
- 步骤四:修改 ~/pages/list/_id 页面,显示分类数据
<dl>
<dt>品牌:</dt>
<dd :class="{'cur' : searchMap.brandId == '' }"><a href="" @click.prevent="brandSearch('')">不限</a></dd>
<dd :class="{'cur' : searchMap.brandId == bl.id}" v-for="(bl,bli) in brandList" :key="bli">
<a :href="bl.link" @click.prevent="brandSearch(bl.id)">{{bl.brandName}}</a>
</dd>
</dl>
- 步骤五:修改 ~/pages/list/_id 页面,回显选中数据
methods: {
brandSearch (bid){
//记录品牌id
this.searchMap.brandId = bid;
//查询
this.searchList();
},
searchList () {
console.info(this.searchMap)
}
},
6.4指定分类的所有规格
- 6.4.1接口
GET http://localhost:10010/web-service/specifications/category/76
6.4.2后端实现:JavaBean
- 表结构分析:
- 规格表:tb_specification
- 规格选项表:tb_specification_option
- 关系:一对多(一个规格,拥有多个规格选项)
- 规格选项
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@TableName("tb_specification_option")
@Data
public class SpecificationOption {
/*
CREATE TABLE `tb_specification_option` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`spec_id` int(10) unsigned NOT NULL COMMENT '规格ID',
`option_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '选项名称',
PRIMARY KEY (`id`),
KEY `specification_options_spec_id_index` (`spec_id`)
)
*/
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value="spec_id")
@JsonProperty("spec_id")
private Integer specId; //外键,规格ID
private Specification specification; //外键对应对象
@TableField(value="option_name")
@JsonProperty("option_name")
private String optionName; //选项名称
}
- 规格
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@TableName("tb_specification")
@Data
public class Specification {
/*
CREATE TABLE `tb_specification` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`spec_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '规格名称',
`category_id` int(10) unsigned NOT NULL COMMENT '分类ID',
PRIMARY KEY (`id`)
)
*/
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value = "spec_name")
@JsonProperty("spec_name")
private String specName; //规格名称
@TableField(value = "category_id")
private Integer categoryId; //分类外键
private Category category; //分类外键对应对象
private List<SpecificationOption> options; //一个规格,具有多个规格选项
}
6.4.3后端实现:查询
- 查询规格的同时,查询对应的规格选项
- 步骤一:创建 SpecificationOptionMapper,用于查询指定“规格”的所有“规格选项”
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.SpecificationOption;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Mapper
public interface SpecificationOptionMapper extends BaseMapper<SpecificationOption> {
/**
* 查询指定规格的所有规格选项
* @param spceId
* @return
*/
@Select("select * from tb_specification_option where spec_id = #{specId}")
@Results({
@Result(property = "id",column = "id"),
@Result(property = "specId",column = "spec_id"),
@Result(property = "optionName",column = "option_name"),
})
public List<SpecificationOption> findSpecOptionBySpecId(@Param("specId") Integer spceId);
}
- 步骤二:创建SpecificationMapper,查询指定分类的所有规格,含规格选项信息
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Specification;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Mapper
public interface SpecificationMapper extends BaseMapper<Specification> {
/**
* 查询指定分类的所有规格
* @param categoryId
* @return
*/
@Select("select * from tb_specification where category_id = #{categoryId}")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "specName", column = "spec_name"),
@Result(property = "categoryId", column = "category_id"),
@Result(property = "options", many=@Many(select="com.czxy.changgou4.mapper.SpecificationOptionMapper.findSpecOptionBySpecId"), column = "id"),
})
public List<Specification> findSpecificationByCategoryId(@Param("categoryId") Integer categoryId);
}
- 步骤三:创建SpecificationService接口
package com.czxy.changgou4.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Specification;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
public interface SpecificationService extends IService<Specification> {
/**
* 查询指定分类的所有规格
* @param categoryId
* @return
*/
public List<Specification> findSpecificationByCategoryId(Integer categoryId);
}
- 步骤四:创建SpecificationService实现类
package com.czxy.changgou4.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.SpecificationMapper;
import com.czxy.changgou4.pojo.Specification;
import com.czxy.changgou4.service.SpecificationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Service
@Transactional
public class SpecificationServiceImpl extends ServiceImpl<SpecificationMapper, Specification> implements SpecificationService {
@Override
public List<Specification> findSpecificationByCategoryId(Integer categoryId) {
return baseMapper.findSpecificationByCategoryId(categoryId);
}
}
- 步骤五:创建 SpecificationController
package com.czxy.changgou4.controller;
import com.czxy.changgou4.pojo.Specification;
import com.czxy.changgou4.service.SpecificationService;
import com.czxy.changgou4.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@RestController
@RequestMapping("/specifications")
public class SpecificationController {
@Resource
private SpecificationService specificationService;
/**
* GET /specifications/category/:catid
* @param categoryId
* @return
*/
@GetMapping("/category/{catId}")
public BaseResult findSpecificationByCategoryId(@PathVariable("catId") Integer categoryId){
//1 查询
List<Specification> list = this.specificationService.findSpecificationByCategoryId(categoryId);
//2 封装
return BaseResult.ok("查询成功", list);
}
}
6.4.4前端实现
- 步骤一:修改 api.js ,查询规格
//指定分类的规格
findSpec : (categoryId) => {
return axios.get('/web-service/specifications/category/' + categoryId)
},
- 步骤二:修改 pages/list/_id ,页面加载成功,查询规格
data() {
return {
searchMap: { //搜索条件对象
catId: '', //分类id
brandId: '', // 品牌id
},
brandList : [], //所有品牌
specList : [], //所有规格
}
},
methods: {
async findAllBrandFn() {
let { data : brandData } = await this.$request.findBrand( this.searchMap.catId )
this.brandList = brandData.data
},
async findAllSpecFn() {
let { data : specData } = await this.$request.findSpec( this.searchMap.catId )
this.specList = specData.data
},
brandSearch(bid) {
//记录品牌id
this.searchMap.brandId = bid;
//查询
this.searchList();
},
searchList () {
console.info(this.searchMap)
}
},
async mounted() {
//设置id
this.searchMap.catId = this.$route.params.cid
// 查询所有的品牌
this.findAllBrandFn()
// 查询所有的规格
this.findAllSpecFn()
},
- 步骤三:显示数据
<!--显示规格数据-->
<dl v-for="(sl,sli) in specList" :key="sli">
<dt>{{sl.spec_name}}:</dt>
<dd :class="{'cur': sl.selectId == ''}"><a href="" @click.prevent="specSearch(sl ,'' , )">不限</a></dd>
<dd :class="{'cur' : sl.selectId == op.id }" v-for="(op,opi) in sl.options" :key="opi">
<a href="" @click.prevent="specSearch(sl ,op , )">{{op.option_name}}</a>
</dd>
</dl>
- 步骤四:选中规格,整体内容回显
specSearch (spec , option ) {
//记录选中的id
this.$set(spec,'selectId', option ? option.id : '' )
}
6.5前置技术:ElasticSearch
参考《elasticsearch入门.doc》
6.6电商概念:SKU和SPU
-
SPU = Standard Product Unit (标准产品单位)
-
SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
通俗点讲,属性值、特性相同的商品就可以称为一个SPU。 -
例如:
iphone X就是一个SPU,与颜色、款式、套餐都无关。 -
SKU=stock keeping unit(库存量单位)
-
SKU即库存进出计量的单位, 可以是以件、盒、托盘等为单位。
SKU是物理上不可分割的最小存货单元。 -
例如:
iPhone X 128G 黑色,就是一个SKU -
总结
SPU:可以理解为一类商品的总称(一组产品特性的集合)
SKU:可以称之为最小库存单位,也就是所能唯一确定一件商品的唯一标识。
6.7流程分析
- sku查询功能:从数据库查询sku相关的所有信息
- 数据同步:将数据库中的数据,同步到es中。()
- 数据库查询搜索慢、es查询速度快
- 同步时机:1. 定时器(理论)、2. 测试程序(实施)
- 搜索服务:从elasticsearch中搜索数据,默认情况下es中没有数据,通过“数据同步”操作后,es有数据
6.8表结构分析
- 商品相关表总览
- 表间关系
6.9查询所有SKU
- 接口
GET http://localhost:10010/web-service/sku/esData
6.9.2后端实现:JavaBean
- 数据库相关JavaBean
- Spu类似分类
- Sku 商品详情
- SkuComment sku的评论
- ES相关JavaBean
- ESData 准备存放到es中的数据,是以上三种数据的组合数据。
SPU
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* Created by liangtong.
*/
@TableName("tb_spu")
@Data
public class Spu {
@TableId(type = IdType.AUTO)
private Integer id;
//spu名字
@TableField(value="spu_name")
private String spuName;
//spu副名称
@TableField(value="spu_subname")
private String spuSubname;
//商品logo
@TableField(value="logo")
private String logo;
//分类1Id
@TableField(value="cat1_id")
private Integer cat1Id;
//分类2ID
@TableField(value="cat2_id")
private Integer cat2Id;
//分类3Id
@TableField(value="cat3_id")
private Integer cat3Id;
@TableField(value="brand_id")
private Integer brandId;
@TableField(exist = false)
private Brand brand;
//审核时间
@TableField(value="check_time")
private String checkTime;
//审核状态 审核状态,0:未审核,1:已通过,2:未通过
@TableField(value="check_status")
private String checkStatus;
//价格
@TableField(value="price")
private String price;
//是否上架
@TableField(value="is_on_sale")
private Integer isOnSale;
//上架时间
@TableField(value="on_sale_time")
private Date onSaleTime;
//删除时间
@TableField(value="deleted_at")
private String deletedAt;
@TableField(value="weight")
private String weight;
//商品描述
@TableField(value="description")
private String description;
//规格与包装
@TableField(value="packages")
private String packages;
//售后保障
@TableField(value="aftersale")
private String aftersale;
//规格列表,json串
@TableField(value="spec_list")
private String specList;
@TableField(value="created_at")
private String createdAt;
@TableField(value="updated_at")
private String updatedAt;
}
- Sku
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created by liangtong.
*/
@TableName("tb_sku")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Sku {
@TableId(type = IdType.AUTO)
private Integer id;
//库存量
@TableField(value="stock")
private Integer stock;
@TableField(value="spu_id")
private Integer spuId;
@TableField(exist = false)
private Spu spu;
//sku名字
@TableField(value="sku_name")
private String skuName;
@TableField(value="images")
private String images;
@TableField(value="price")
private Double price;
//1:1|2:6|6:22
@TableField(value="spec_info_id_list")
private String specInfoIdList;
//规格列表码,格式:{"机身颜色":"白色","内存":"3GB","机身存储":"16GB"}
@TableField(value="spec_info_id_txt")
private String specInfoIdTxt;
}
- SkuComment
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* Created by liangtong.
*/
@TableName("tb_sku_comment")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SkuComment {
@TableId(type = IdType.AUTO)
private Integer id;
@TableField(value="created_at")
private Date createdAt;
@TableField(value="updated_at")
private Date updatedAt;
@TableField(value="user_id")
private Integer userId;
@TableField(exist = false)
private User user;
@TableField(value="spu_id")
private Integer spuId;
@TableField(exist = false)
private Spu spu;
@TableField(value="sku_id")
private Integer skuId;
@TableField(exist = false)
private Sku sku;
@TableField(value="ratio")
private String ratio;
@TableField(value="spec_list")
private String specList;
@TableField(value="content")
private String content;
@TableField(value="star")
private Integer star;
@TableField(value="isshow")
private String isShow;
@TableField(value="sn")
private String sn;
}
- SkuPhoto
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* Created by liangtong.
*/
@TableName("tb_sku_photo")
@Data
public class SkuPhoto {
@TableId(type = IdType.AUTO)
private Integer id;
//外键
@TableField(value="sku_id")
@JsonProperty("sku_id")
private Integer skuId;
@TableField(exist = false)
private Sku sku;
@TableField(value="url")
private String url;
}
- ESData
package com.czxy.changgou4.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.Map;
/**
* Created by liangtong.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ESData {
private Integer id; // skuId
private String logo;//图片地址
private String skuName;//sku名字
private String all; // 所有需要被搜索的信息,包含标题,分类,甚至品牌
private Date onSaleTime;//上架时间
//品牌编号
private Integer brandId;
//分类id
private Integer catId;
//规格列表
private Map<String, Object> specs;// 可搜索的规格参数,key是参数名,值是参数值
private Double price;// 价格
private String spuName;
private Integer stock;
private String description;
private String packages;//规格与包装
private String aftersale;//售后保障
private String midlogo;
//评价数
private Integer commentCount;
// 销量
private Integer sellerCount;
}
6.9.3后端实现:搭建环境
- 步骤一:修改父项目的pom.xml,锁定fastjson的依赖
<fastjson.version>1.2.9</fastjson.version>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
- 步骤二:修改web服务,添加fastjson依赖
<!--json转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
- 步骤三:修改网关,确定 ESData路径
6.9.4后端实现:查询
- SpuMapper:通过SpuId查询详情,含品牌信息
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Spu;
import org.apache.ibatis.annotations.*;
/**
* Created by liangtong.
*/
@Mapper
public interface SpuMapper extends BaseMapper<Spu> {
@Select("select * from tb_spu where id = #{spuId}")
@Results({
@Result(property = "spuName" , column = "spu_name"),
@Result(property = "spuSubname" , column = "spu_subname"),
@Result(property = "cat1Id" , column = "cat1_id"),
@Result(property = "cat2Id" , column = "cat2_id"),
@Result(property = "cat3Id" , column = "cat3_id"),
@Result(property = "brandId" , column = "brand_id"),
@Result(property = "checkTime" , column = "check_time"),
@Result(property = "checkStatus" , column = "check_status"),
@Result(property = "isOnSale" , column = "is_on_sale"),
@Result(property = "onSaleTime" , column = "on_sale_time"),
@Result(property = "deletedAt" , column = "deleted_at"),
@Result(property = "specList" , column = "spec_list"),
@Result(property = "onSaleTime" , column = "on_sale_time"),
@Result(property = "createdAt" , column = "created_at"),
@Result(property = "updatedAt" , column = "updated_at"),
@Result(property="brand", column="brand_id",
one=@One(
select="com.czxy.changgou4.mapper.BrandMapper.selectById"
))
})
public Spu findSpuById(@Param("spuId") Integer spuId);
}
- SkuCommentMapper:查询评论数
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.SkuComment;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* Created by liangtong.
*/
@Mapper
public interface SkuCommentMapper extends BaseMapper<SkuComment> {
/**
* 查询评论数
* @param spu_id
* @return
*/
@Select("select count(*) from tb_sku_comment where spu_id = #{spu_id}")
public Integer findNumBySpuId(@Param("spu_id") Integer spu_id);
}
- SkuMapper:查询所有sku,含对应的spu信息
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Sku;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* Created by liangtong.
*/
@Mapper
public interface SkuMapper extends BaseMapper<Sku> {
@Select("select * from tb_sku")
@Results(id="skuResult" , value={
@Result(id=true,column="id",property="id"),
@Result(column="stock",property="stock"),
@Result(column="spu_id",property="spuId"),
@Result(column="sku_name",property="skuName"),
@Result(column="spec_info_id_list",property="specInfoIdList"),
@Result(column="spec_info_id_txt",property="specInfoIdTxt"),
@Result(column="spu_id",property="spu",
one=@One(
select="com.czxy.changgou4.mapper.SpuMapper.findSpuById"
))
})
public List<Sku> findAllSkus();
}
SkuPhotoMapper
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.SkuPhoto;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* Created by liangtong.
*/
@Mapper
public interface SkuPhotoMapper extends BaseMapper<SkuPhoto> {
}
package com.czxy.changgou4.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Sku;
import com.czxy.changgou4.vo.ESData;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
public interface SkuService extends IService<Sku> {
/**
*
* @return
*/
public List<ESData> findESData();
}
package com.czxy.changgou4.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.SkuCommentMapper;
import com.czxy.changgou4.mapper.SkuMapper;
import com.czxy.changgou4.pojo.Sku;
import com.czxy.changgou4.service.SkuService;
import com.czxy.changgou4.vo.ESData;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Service
@Transactional
public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements SkuService {
@Resource
private SkuCommentMapper skuCommentMapper;
@Override
public List<ESData> findESData() {
//1 查询所有详情sku
List<Sku> skulist = baseMapper.findAllSkus();
//2 将SKU 转换成 ESData
List<ESData> esDataList = new ArrayList<>();
for (Sku sku:skulist){
ESData esData = new ESData();
// id
esData.setId(sku.getId());
// 图片地址
esData.setLogo(sku.getSpu().getLogo());
// 商品名称
esData.setSkuName(sku.getSkuName());
// all “华为xx {"机身颜色":"白色","内存":"3GB","机身存储":"16GB"} 荣耀 ”
esData.setAll(sku.getSkuName()+" " + sku.getSpecInfoIdTxt() + " " +sku.getSpu().getBrand().getBrandName());
// on_sale_time
esData.setOnSaleTime(sku.getSpu().getOnSaleTime());
// brand_id
esData.setBrandId(sku.getSpu().getBrandId());
// cat_id
esData.setCatId(sku.getSpu().getCat3Id());
// Map<String, Object> specs;// 可搜索的规格参数,key是参数名,值是参数值
Map<String,Object> specs = JSON.parseObject(sku.getSpecInfoIdTxt(), Map.class);
// Map newSpecs = new HashMap();
// for(String key : specs.keySet()){
// newSpecs.put("spec" + key , specs.get(key));
// }
esData.setSpecs(specs);
// price 价格
esData.setPrice(sku.getPrice());
// spu_name
esData.setSpuName(sku.getSpu().getSpuName());
// stock 库存
esData.setStock(sku.getStock());
// description
esData.setDescription(sku.getSpu().getDescription());
// packages;//规格与包装
esData.setPackages(sku.getSpu().getPackages());
// aftersale;//售后保障
esData.setAftersale(sku.getSpu().getAftersale());
// midlogo;
esData.setMidlogo(sku.getSpu().getLogo());
// comment_count; 评价数
Integer comment_count = skuCommentMapper.findNumBySpuId(sku.getSpu().getId());
esData.setCommentCount(comment_count);
//销售量
esData.setSellerCount(10);
esDataList.add(esData);
}
return esDataList;
}
}
package com.czxy.changgou4.controller;
import com.czxy.changgou4.service.SkuService;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.ESData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@RestController
@RequestMapping("/sku")
public class SkuController {
@Autowired
private SkuService skuService;
@GetMapping("/esData")
public BaseResult<List<ESData>> findESData(){
List<ESData> esData = skuService.findESData();
return BaseResult.ok("查询成功", esData);
}
}