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

简介: 【畅购商城】详情页详情之商品详情

1.构建详情页

步骤0:确定访问路径

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

7ea16401d9d9412fbd10ce5e807dc824.png

6949d0fd089049279bdb82435a5dab70.png

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

e8614301f8f543cdb65dbafa05217e25.png

9443b1bde55741ee891f6fbda2220d2b.png

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

8b95511f87c14b3aa0bd46774c5f0cb3.png

2.详情

2.1分析

e9c5079638334638b8021df2755489ca.png

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|..."
        },
        ...
    ]
}

5266552e6a564027b4c5bab1ea2b5de6.png


01ea49b5bed24fab8510e12da5ecac5c.png


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


5891b5e0c5984b4fa3a96bdfb7126c1d.png

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


dd909cdbf4984602bb6f6bb92f220206.png

步骤一:修改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”功能


a6cace3debe74966bc90d0e6e630249f.png

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

6493bc548ab9415db571065cf9ef8d7a.png

2.6后端实现

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


image.png

/**
 * 查询详情
 * @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;
    }
}

4aa5308222414952b2024bed68a72355.png

/**
 * 查询详情
 * @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”,查询详情

13076b19eb7f423fae46ad66a5416f02.png


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


b9fcb7556ea64bd1945b1c01460cba82.png

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

720a833ebd814ce8a51438b5726a630b.png

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

27aca095e73f42e9a3009999ba731ea5.png

35bef280a58f49adb003aaa613eefb9d.png


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

9a8da57916a04b79822c7dac807e0b3a.png

编写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,图片大小的原因,导致“放大镜”中等图太大,遮盖小图

问题图示


d2d2151141494160818cfbfe9d2d9e48.png



解决

1. <style>
2.   .midpic img {
3.     width: 100%;
4.   }
5. </style>


3.规格操作

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



28064b36bc5d4ceb9402e7a9de739a6f.png


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


820378e028e747c58d100b8b6f550547.png

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


20acd009286e46be9ca33686ba1991b3.png



相关文章
|
2月前
|
缓存 数据挖掘 API
商品详情API接口的应用实践
本文探讨了商品详情API接口在电商领域的应用实践,介绍了其作为高效数据交互方式的重要性,包括实时获取商品信息、提升用户体验和运营效率。文章详细描述了API接口的特点、应用场景如商品展示、SEO优化、数据分析及跨平台整合,并提出了缓存机制、分页加载、异步加载和错误处理等优化策略,旨在全面提升电商运营效果。
|
3月前
|
JSON 搜索推荐 API
抖音商品详情API接口:获取商品信息的指南
抖音商品详情API接口由抖音开放平台提供,允许第三方应用访问抖音小店的商品数据,包括基本信息、价格、库存及用户评价等。其优势在于数据实时性、自动化处理、市场分析及个性化推荐。通过注册账号、获取API密钥、阅读文档和构建请求,用户可高效获取商品信息,提升运营效率。未来,该接口将在电商领域发挥更大作用。
|
6天前
|
负载均衡 安全 API
小红书商品详情API接口获取步骤
获取小红书商品详情API接口需先注册账号并实名认证,阅读API文档后,通过编程语言调用API,构建请求参数,处理返回数据。确保应用支持高并发,遵守安全规范,申请API权限,查阅接口文档,进行开发调试。
|
11天前
|
JSON API 开发者
微店(Weidian)商品详情API接口解析实战
微店(Weidian)是一个基于社交关系的电商平台,为商家提供了一整套的电商解决方案。微店API接口允许开发者通过编程方式访问和操作微店平台上的数据,从而可以创建自动化的工具、应用或集成服务。
|
2月前
|
供应链 监控 搜索推荐
商品详情API接口的多场景应用总结
商品详情API接口在电商、零售、物流及供应链管理等领域广泛应用,提供精准商品信息,优化用户体验,提升运营效率,支持数据驱动决策,并在移动应用和社交媒体等新兴领域展现出巨大潜力。
|
3月前
|
XML JSON API
淘宝商品详情API接口:获取商品信息的指南
淘宝详情API接口是淘宝开放平台提供的一种API接口,它允许开发者通过编程方式获取淘宝商品的详细信息。这些信息包括商品的基本属性、价格、库存状态、销售策略、卖家信息等,对于电商分析、市场研究或者商品信息管理等场景非常有用。
133 1
|
2月前
|
安全 NoSQL 测试技术
商品详情API接口的技术实现
本文介绍了电商平台上商品详情API接口的设计与实现过程,涵盖需求分析、接口定义、数据模型设计及技术选型等方面。通过合理的后端框架、数据库设计和安全措施,确保接口高效、稳定和安全。最后,通过详尽的测试与部署步骤,实现优质购物体验。旨在为技术人员提供实用参考。
|
5月前
|
API 开发者 Python
淘宝商品详情API接口开发实战
在电商领域,获取淘宝商品详情是关键需求。需先注册淘宝开放平台账号并创建应用,获取AppKey与AppSecret;随后申请商品服务API权限。利用Python,通过AppKey和AppSecret获取Access Token,进而调用商品详情API,需替换示例代码中的`your_app_key`, `your_app_secret`, `your_access_token`, 和`item_id`。注意遵守平台限制,处理可能的错误及合理规划调用策略以避免违规。[示例代码](https://)展示了从获取Access Token到调用商品详情API的全过程。
|
SQL 前端开发
显示商品详情【项目 商城】
显示商品详情【项目 商城】
94 0
|
前端开发 JavaScript
商城业务:商品详情
商城业务:商品详情