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

news2025/7/17 19:02:25

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 函数

​​​​​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/6787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sysweld笔记:利用稳态算法加速算法模拟焊接过程的残余应力

作者&#xff1a;贾亚波博士&#xff0c;仿真秀专栏作者 在进行热力耦合的仿真过程中&#xff0c;如果模型足够的长并且热源速度恒定&#xff0c;通常其热学&#xff0c;相变以及热力耦合都会达到稳态的过程&#xff0c;因此如何直接计算稳态问题成为了大家研究的热点问题。 …

【C++笔试强训】第二十四天

&#x1f387;C笔试强训 博客主页&#xff1a;一起去看日落吗分享博主的C刷题日常&#xff0c;大家一起学习博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a;夜色难免微凉&#xff0c;前方必有曙光 &#x1f31e;。 &#x1f4a6;&a…

【数据结构】栈基本操作的实现(C语言)

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f40c; 个人主页&#xff1a;蜗牛牛啊 &#x1f525; 系列专栏&#xff1a;&#x1f6f9;初出茅庐C语言、&#x1f6f4;数据结构 &#x1f4d5; 学习格言&#xff1a;博…

SpringBoot项目打包时配置文件区分日常、测试、预发、正式环境

前言&#x1f34a; 在我们开发项目的时候&#xff0c;一般有四套环境&#xff1a;日常、测试、预发、正式。日常环境作为我们开发环境&#xff1b;测试环境给测试同学测试功能&#xff1b;预发环境给正式环境发布时提供准备&#xff1b;正式环境则是稳定的生产环境。 这四套环…

面试官问我new Vue阶段做了什么?

前言 本篇录入吊打面试官专栏&#xff0c;希望能祝君拿下Offer一臂之力&#xff0c;各位看官感兴趣可移步&#x1f6b6;。这段时间面了很多家公司&#xff0c;被问到的题我感觉不重复不止100道&#xff0c;将会挑选觉得常见且有意义的题目进行分析及回答。有人说面试造火箭&am…

Redis字符串、hash、列表方法使用以及Redis管道与Django集成Redis

目录标题一、Redis字符串操作二、Redis-hash操作三、Redis列表操作四、Redis管道五、Redis其他操作六、Django中集成Redis七、Celery介绍一、Redis字符串操作 名称属性setex:过期时间&#xff08;秒&#xff09;px:过期时间(毫秒) nx:如果设置为True&#xff0c;则只有name不存…

毕业设计:SpringBoot+Vue+Element的校内跑腿平台

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 文末获取源码 项目编号&#xff1a;BS-XX-…

MySQL基础总结

一.sql数据及语言基本类型: 1.语言的分类 DDL:数据定义语言,用来定义数据库对象:数据库,表,列等。关键字:create,alter,drop等 DML:数据操作语言,用来对数据库中表的记录进行操作。关键字:insert,delete,update等 DQL:数据库查询语言,用来查询数据库中表的记录。关键字:select,…

PIX2SEQ: A LANGUAGE MODELING FRAMEWORK FOR OBJECT DETECTION

文章目录ABSTRACT1 INTRODUCTION2 pix2seq框架2.1SEQUENCE CONSTRUCTION FROM OBJECT DESCRIPTIONS2.2 ARCHITECTURE, OBJECTIVE AND INFERENCE2.3 SEQUENCE AUGMENTATION TO INTEGRATE TASK PRIORS3 EXPERIMENTS3.1 EXPERIMENTAL SETUP3.2 MAIN COMPARISONS3.3 ABLATION ON SE…

2022年都在说软件测试饱和了?都在担心面试不上。

今年开始&#xff0c;小编听到最多的问题就是 软件测试行业是不是饱和了&#xff1f; 软件测试行业还有前景吗&#xff1f; 无非是因为投出去的简历回复的越来越少了 据中华英才网统计&#xff0c;目前软件测试人才的缺口在100万人以上&#xff0c;并以每年20%的速度递增&am…

2.5 自定义srv C++

功能介绍 以自定义数据类型为基础&#xff0c;完成一个节点作为服务器&#xff0c;另一个节点接收传送两个数字到服务端&#xff0c;服务端计算后反馈到客户端进行打印输出 1、工作空间 1.1 创建工作空间lee_ws mkdir -p ~/lee_ws/src cd ~/lee_ws/src/ catkin_init_worksp…

Unity 旋转大总结和项目操作

操作演示 旋转 (online-video-cutter.com)旋转方法都放在了按钮上&#xff0c;第一个是初始化按钮&#xff0c;将cube恢复到&#xff08;0&#xff0c;0&#xff0c;0&#xff09;&#xff0c;但是位置不会变成&#xff08;0&#xff0c;0&#xff0c;0&#xff09; 这个是参…

clickhouse中的sql操作

DDL操作 create操作 create table t_order_mt2(id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime,INDEX a total_amount TYPE minmax GRANULARITY 5 ) engine MergeTree partition by toYYYYMMDD(create_time) order by (id, sku_id) primary key …

【工具】工具小集

Gif录制工具 LICEcap一款轻量级屏幕录制工具&#xff0c;可以导出GIF动画图片格式&#xff0c;支持导出GIF 动画图片格式&#xff0c;可灵活调整录制窗口大小。 https://www.cockos.com/licecap/ 浏览器插件&#xff08;工具箱&#xff09; FeHelper插件支持Chrome、Firefox…

创建个人中心页面(下)

目录 布局规划前端页面 获取头像获取Bot列表 对接获取Bot信息渲染到前端 实现创建一个Bot 前端进行对接插入Bot 实现创建成功关闭和清空 修改时间 实现删除按钮 安装依赖&#xff1a;vue3-ace-editor 布局规划前端页面 使用 bootstrap 的 grids system 进行布局 在 bo…

windows常见的命令操作大全

目录 一、目录文件操作 cd命令 dir命令 md命令 rd命令 move命令 copy命令 del命令 二、文本相关操作 type命令 >命令 findstr命令 |命令 三、网络相关操作 小建议&#xff1a;跟着文章亲手敲一遍是避免忘记的有效方法 一、目录文件操作 cd命令 功能&#xf…

你真的会解决android ANR 问题吗?

前言 ​ 还记得之前写过一篇关于ANR 的介绍&#xff0c;现在看来&#xff0c;那个只是皮毛。现实中遇到应用或系统ANR 的问题&#xff0c;是很难解决的。下面进入正题&#xff0c;来详细了解下如何解决。 一.ANR 关键字 1. event log 中“am_ANR” 关键字&#xff0c;main-l…

27岁Python程序员做独立开发年收入超900万,家中有屋又有田,生活乐无边

他是谁 他叫赖利蔡斯&#xff0c;27岁的Python程序员。现在拥有一家自己的小型软件公司。 他现在的生活 躺赚 每天躺着就可以赚到钱&#xff0c;睡觉时从来不会被闹钟吵醒。 每天干自己的喜欢的事情&#xff0c;读书、编程、讨论公司业务、研究自己感兴趣的事情&#xff0…

Java#4(各类语句和一点小练习)

目录 一.分支语句 1.if语句:和C语言中的没有什么区别 2.switch语句:可以使用C语言的写法,但新增了一种更加简便的写法 二. 循环语句 1.for循环:和C语言没有什么太大区别 2.while循环:和C语言没有什么太大区别 练习:回文数的判断 3.do while(先运行一次再判断):和C语言没…

项目经理如何进行项目汇报才能让项目顺利进行,让领导一看就喜欢?

项目经理如何进行项目工作汇报才能让项目顺利进行&#xff0c;让领导一看就喜欢&#xff1f;领导听工作汇报&#xff0c;就是想知道项目干得怎么样。因此&#xff0c;项目经理事先一定要思考&#xff0c;这次工作汇报应该达到什么目的。 工作汇报要注意这三个问题 简单描述项目…