【畅购商城】详情页详情之商品详情

我心飞翔 分类:vue

1.构建详情页

步骤0:确定访问路径

http://localhost:3000/Goods?id=1

【畅购商城】详情页详情之商品详情
【畅购商城】详情页详情之商品详情

步骤二:复制 ~/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' },
    ]
  },

步骤三:导入公共资源

<script>
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,
  },
}
</script>
【畅购商城】详情页详情之商品详情
【畅购商城】详情页详情之商品详情

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

【畅购商城】详情页详情之商品详情

2.详情

2.1分析

【畅购商城】详情页详情之商品详情

2.2接口

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|..."
        },
        ...
    ]
}
【畅购商城】详情页详情之商品详情
【畅购商城】详情页详情之商品详情

​​​​​​2.3​初始化数据

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');

​​​​​​2.4​后端实现:JavaBean

【畅购商城】详情页详情之商品详情

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<String, String> logo;
    private List<Map> photos;
    private String description;
    private String aftersale;
    private Integer stock;
    @JsonProperty("spec_list")
    private List<Specification> specList;
    // id_list:'规格ID:选项ID|规格ID:选项ID|...',
    // id_txt:'规格名称:选项名称|规格名称:选项名称|...'
    @JsonProperty("spec_info")
    private Map<String, String> specInfo;
    @JsonProperty("sku_list")
    private List<Map<String, String>> skuList;

}

​​​​​​​2.5后端实现:Mapper

【畅购商城】详情页详情之商品详情

步骤一:修改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<SkuPhoto> {

    /**
     * 通过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<SkuPhoto> findSkuPhotoBySkuId(Integer spuId);

}

步骤三:修改SkuMapper,添加“查询指定spuId的所有sku”功能

【畅购商城】详情页详情之商品详情
/**
 * 查询指定spuId的所有sku
 * @param spuId
 * @return
 */
@Select("select * from tb_sku where spu_id = #{spuId}")
@ResultMap("skuResult")
public  List<Sku> findSkuBySpuId(Integer spuId);
【畅购商城】详情页详情之商品详情

2.6后端实现

步骤一:修改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<SkuMapper, Sku> 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<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;

    }

    @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<String,String> logo = new HashMap();
        logo.put("smlogo",spu.getLogo());
        logo.put("biglogo",spu.getLogo());
        logo.put("xbiglogo",spu.getLogo());
        skuResult.setLogo(logo);
        // 通过skuId查询对应的所有的图片
        List<SkuPhoto> skuPhotoList = skuPhotoMapper.findSkuPhotoBySkuId(sku.getId());
        List<Map> photos = new ArrayList<>();
        for(SkuPhoto sp:skuPhotoList){
            Map<String,String> 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<SpecResult> spec_list; 根据分类查找规格和规格选项
        List<Specification> spec_list = specificationMapper.findSpecificationByCategoryId(spu.getCat3Id());
        skuResult.setSpecList(spec_list);
        // //id_list:'规格ID:选项ID|规格ID:选项ID|...',
        //  //id_txt:'规格名称:选项名称|规格名称:选项名称|...'
        // Map<String, String> spec_info;
        Map<String,String> spec_info = new HashMap<>();
        spec_info.put("id_list",sku.getSpecInfoIdList());
        spec_info.put("id_txt",sku.getSpecInfoIdTxt());
        skuResult.setSpecInfo(spec_info);
        // List<Map<String, String>> sku_list;
        List<Sku> skuBySpuIdList = baseMapper.findSkuBySpuId(spu.getId());
        List<Map<String, String>> sku_list = new ArrayList<>();
        for(Sku s : skuBySpuIdList){
            Map<String,String> 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<OneSkuResult> findSkuById(@PathVariable("skuid") Integer skuid){
    OneSkuResult sku = skuService.findSkuById(skuid);

    return BaseResult.ok("查询成功", sku);
}

2.7前端实现

详情页面需要进行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,图片大小的原因,导致“放大镜”中等图太大,遮盖小图

问题图示

【畅购商城】详情页详情之商品详情

解决

<style>
  .midpic img {
    width: 100%;
  }
</style>

3.规格操作

点击“规格”时,切换SKU的id

【畅购商城】详情页详情之商品详情

步骤一:修改 Goods.vue 页面,给每一个规格选项绑定点击事件

【畅购商城】详情页详情之商品详情

步骤二:修改 Goods.vue 页面,完成 selectSpec 函数

【畅购商城】详情页详情之商品详情

​​​

回复

我来回复
  • 暂无回复内容