步骤0:确定访问路径

步骤二:复制 ~/static/goods.html 内容,导入第三方资源(css、js)
- head: {
- title: '列表页面',
- link: [
- {rel:'stylesheet',href: '/style/goods.css'},
- {rel:'stylesheet',href: '/style/common.css'},
- {rel:'stylesheet',href: '/style/bottomnav.css'},
- {rel:'stylesheet',href: '/style/jqzoom.css'},
- ],
- script: [
- { type: 'text/javascript', src: '/js/header.js' },
- { type: 'text/javascript', src: '/js/goods.js' },
- { type: 'text/javascript', src: '/js/jqzoom-core.js' },
- ]
- },
步骤三:导入公共资源
- import TopNav from '@/components/TopNav'
- import HeaderSearch from '@/components/HeaderSearch'
- import BottomNav from '@/components/BottomNav'
- import Footer from '@/components/Footer'
-
- export default {
- components: {
- TopNav,
- HeaderSearch,
- BottomNav,
- Footer,
- },
- }


步骤四:添加原页面js特效


GET http://localhost:10010/web-service/sku/goods/2600242
返回值
- {
- skuid:"商品ID,skuid",
- spuid:"商品ID,skuid",
- goods_name:"商品名称",
- price:"价格",
- on_sale_date:"上架时间",
- comment_count:"评论数量",
- comment_level:"评论级别(1-5)",
- cat1_info:{
- id:"分类ID",
- cat_name:"分类名称"
- },
- cat2_info:{
- id:"分类ID",
- cat_name:"分类名称"
- },
- cat3_info:{
- id:"分类ID",
- cat_name:"分类名称"
- },
- logo:{
- smlogo:"小LOGO(50x50)",
- biglogo:"大LOGO(350x350)",
- xbiglogo:"超大LOGO(800x800)"
- },
- photos:[
- {
- smimg:"商品图片(50x50)",
- bigimg:"商品图片(350x350)",
- xbigimg:"商品图片(800x800)"
- },
- ...
- ],
- description:"商品描述",
- aftersale:"售后",
- stock:"库存量",
- spec_list:[
- {
- id:"规格ID",
- spec_name:"规格名称",
- options:[
- {
- id:"选项ID",
- option_name:"选项名称"
- }
- ...
- ]
- }
- ...
- ],
- spec_info:{
- id_list:"规格ID:选项ID|规格ID:选项ID|...",
- id_txt:"规格名称:规格选项|规格名称:规格选项|..."
- },
- sku_list:[
- {
- skuid:"SKUID",
- id_list:"规格ID:选项ID|规格ID:选项ID|..."
- },
- ...
- ]
- }


- insert into tb_sku_photo(sku_id,url) values(2600242,'http://img12.360buyimg.com/n1/s450x450_jfs/t1/100605/24/7603/222062/5dfc6d30Ec375bf0a/e29b6690731acb24.jpg');
- insert into tb_sku_photo(sku_id,url) values(2600242,'http://img12.360buyimg.com/n1/s450x450_jfs/t1/110371/2/1323/189888/5dfc6d30E073c3495/cb256ec2d3cf9ae2.jpg');
- insert into tb_sku_photo(sku_id,url) values(2600242,'http://img12.360buyimg.com/n1/s450x450_jfs/t1/95005/38/7465/139593/5dfc6d2fEd2317126/63b5253237353618.jpg');

SkuPhoto : sku对应的所有图片
OneSkuResult:用于封装sku详情
步骤一:创建SkuPhoto,根据tb_sku_photo表编写内容
- 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;
-
- }
步骤二:创建OneSkuResult,根据接口返回结果编写内容
- package com.czxy.changgou4.vo;
-
- import com.czxy.changgou4.pojo.Category;
- import com.czxy.changgou4.pojo.Specification;
- import com.fasterxml.jackson.annotation.JsonProperty;
- import lombok.Data;
-
- import java.util.Date;
- import java.util.List;
- import java.util.Map;
-
- /**
- * @author 桐叔
- * @email liangtong@itcast.cn
- */
- @Data
- public class OneSkuResult {
-
- private Integer skuid;
- private Integer spuid;
- @JsonProperty("goods_name")
- private String goodsName;
- private Double price;
- @JsonProperty("on_sale_date")
- private Date onSaleDate;
- @JsonProperty("comment_count")
- private Integer commentCount;
- @JsonProperty("comment_level")
- private Integer commentLevel;
- @JsonProperty("cat1_info")
- private Category cat1Info;
- @JsonProperty("cat2_info")
- private Category cat2Info;
- @JsonProperty("cat3_info")
- private Category cat3Info;
- private Map
logo; - private List
- private String description;
- private String aftersale;
- private Integer stock;
- @JsonProperty("spec_list")
- private List
specList; - // id_list:'规格ID:选项ID|规格ID:选项ID|...',
- // id_txt:'规格名称:选项名称|规格名称:选项名称|...'
- @JsonProperty("spec_info")
- private Map
specInfo; - @JsonProperty("sku_list")
- private List
-
- }

步骤一:修改skuCommentMapper,完成“评论级别”功能
- /**
- * 通过spu查询评论打分(星星)的平均数
- * @param spuId
- * @return
- */
- @Select("SELECT AVG(star) FROM tb_sku_comment WHERE spu_id = #{spuId}")
- public Integer findAvgStarBySpuId(@Param("spuId") Integer spuId);
步骤二:创建SkuPhotoMapper,完成“通过skuId查询对应的所有的图片”功能
- 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
{ -
- /**
- * 通过skuId查询对应的所有的图片
- * @param spuId
- * @return
- */
- @Select("select * from tb_sku_photo where sku_id = #{spuId}")
- @Results({
- @Result(property="id", column="id"),
- @Result(property="skuId", column="sku_id"),
- @Result(property="url", column="url")
- })
- public List
findSkuPhotoBySkuId(Integer spuId); -
- }
步骤三:修改SkuMapper,添加“查询指定spuId的所有sku”功能

- /**
- * 查询指定spuId的所有sku
- * @param spuId
- * @return
- */
- @Select("select * from tb_sku where spu_id = #{spuId}")
- @ResultMap("skuResult")
- public List
findSkuBySpuId(Integer spuId);

步骤一:修改SkuService,添加findSkuById 方法

- /**
- * 查询详情
- * @param skuid
- * @return
- */
- public OneSkuResult findSkuById(Integer skuid);
步骤二:修改SkuServiceImpl,完成“查询详情”功能
- package com.czxy.changgou4.service.impl;
-
- import com.alibaba.fastjson.JSON;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.czxy.changgou4.mapper.*;
- import com.czxy.changgou4.pojo.Sku;
- import com.czxy.changgou4.pojo.SkuPhoto;
- import com.czxy.changgou4.pojo.Specification;
- import com.czxy.changgou4.pojo.Spu;
- import com.czxy.changgou4.service.SkuService;
- import com.czxy.changgou4.vo.ESData;
- import com.czxy.changgou4.vo.OneSkuResult;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
- import javax.annotation.Resource;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- /**
- * @author 桐叔
- * @email liangtong@itcast.cn
- */
- @Service
- @Transactional
- public class SkuServiceImpl extends ServiceImpl
implements SkuService { -
- @Resource
- private SkuCommentMapper skuCommentMapper;
-
- @Resource
- private SpuMapper spuMapper;
-
- @Resource
- private CategoryMapper categoryMapper;
-
- @Resource
- private SkuPhotoMapper skuPhotoMapper;
-
- @Resource
- private SpecificationMapper specificationMapper;
-
- @Override
- public List
findESData() { - //1 查询所有详情sku
- List
skulist = baseMapper.findAllSkus(); -
- //2 将SKU 转换成 ESData
- List
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
specs;// 可搜索的规格参数,key是参数名,值是参数值 - Map
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;
-
- }
-
- @Override
- public OneSkuResult findSkuById(Integer skuid) {
- OneSkuResult skuResult = new OneSkuResult();
- // 1 查找sku基本信息
- Sku sku = baseMapper.selectById(skuid);
- // 2 根据sku查找spu信息
- Spu spu = spuMapper.findSpuById(sku.getSpuId());
-
- // 3 赋值
- // skuid;
- skuResult.setSkuid(sku.getId());
- // spuid;
- skuResult.setSpuid(sku.getSpuId());
- // 商品名称
- skuResult.setGoodsName(sku.getSkuName());
- // 价格
- skuResult.setPrice(sku.getPrice());
- // 上架时间
- skuResult.setOnSaleDate(spu.getOnSaleTime());
- // 评价数
- Integer comment_count = skuCommentMapper.findNumBySpuId(spu.getId());
- skuResult.setCommentCount(comment_count);
- // 评论级别
- skuResult.setCommentLevel(skuCommentMapper.findAvgStarBySkuId(sku.getId()));
- // 一级分类
- skuResult.setCat1Info(categoryMapper.selectById(spu.getCat1Id()));
- // 二级分类
- skuResult.setCat2Info(categoryMapper.selectById(spu.getCat2Id()));
- // 三级分类
- skuResult.setCat3Info(categoryMapper.selectById(spu.getCat3Id()));
- // 第一张图片
- Map
logo = new HashMap(); - logo.put("smlogo",spu.getLogo());
- logo.put("biglogo",spu.getLogo());
- logo.put("xbiglogo",spu.getLogo());
- skuResult.setLogo(logo);
- // 通过skuId查询对应的所有的图片
- List
skuPhotoList = skuPhotoMapper.findSkuPhotoBySkuId(sku.getId()); - List
- for(SkuPhoto sp:skuPhotoList){
- Map
map = new HashMap(); - map.put("smimg",sp.getUrl());
- map.put("bigimg",sp.getUrl());
- map.put("xbigimg",sp.getUrl());
- photos.add(map);
- }
- skuResult.setPhotos(photos);
-
- // 商品描述
- skuResult.setDescription(spu.getDescription());
- // 售后
- skuResult.setAftersale(spu.getAftersale());
- // 库存量
- skuResult.setStock(sku.getStock());
- // List
spec_list; 根据分类查找规格和规格选项 - List
spec_list = specificationMapper.findSpecificationByCategoryId(spu.getCat3Id()); - skuResult.setSpecList(spec_list);
- // //id_list:'规格ID:选项ID|规格ID:选项ID|...',
- // //id_txt:'规格名称:选项名称|规格名称:选项名称|...'
- // Map
spec_info; - Map
spec_info = new HashMap<>(); - spec_info.put("id_list",sku.getSpecInfoIdList());
- spec_info.put("id_txt",sku.getSpecInfoIdTxt());
- skuResult.setSpecInfo(spec_info);
- // List
- List
skuBySpuIdList = baseMapper.findSkuBySpuId(spu.getId()); - List
- for(Sku s : skuBySpuIdList){
- Map
map = new HashMap<>(); - map.put("skuid",s.getId().toString());
- map.put("id_list",s.getSpecInfoIdList());
- sku_list.add(map);
- }
- skuResult.setSkuList(sku_list);
- // 返回结果
- return skuResult;
- }
-
- }

- /**
- * 查询详情
- * @param skuid
- * @return
- */
- @GetMapping("/goods/{skuid}")
- public BaseResult
findSkuById(@PathVariable("skuid") Integer skuid){ - OneSkuResult sku = skuService.findSkuById(skuid);
-
- return BaseResult.ok("查询成功", sku);
- }
详情页面需要进行SSR
步骤一:修改 “apiserver.js”,查询详情

步骤二:修改 Goods.vue 页面,使用asyncData进行查询

步骤三:修改 Goods.vue 页面,显示当前位置

步骤四:修改 Goods.vue 页面,处理放大镜图片


步骤五:修改 Goods.vue 页面,商品详情

编写specOptionSelect方法
- methods: {
- specOptionSelect(spec,option) {
- // 拼接标记符,规格id:选项id
- let flag = spec.id + ':' + option.id
- // 判断id_list中是否有‘标记符’,如果没有返回-1
- return this.goodsInfo.spec_info.id_list.indexOf(flag) != -1
- }
- },
步骤六:修复bug,图片大小的原因,导致“放大镜”中等图太大,遮盖小图
问题图示

解决
- .midpic img {
- width: 100%;
- }
点击“规格”时,切换SKU的id
步骤一:修改 Goods.vue 页面,给每一个规格选项绑定点击事件
步骤二:修改 Goods.vue 页面,完成 selectSpec 函数