商品详情页面静态化thymeleaf

每一个商品都有cid 每一个spu 都作为一个 spuId.html 静态化,以减少服务器压力和访问速率、前端转发路径如下:
1、通过nginx 代理,代理静态化微服务端口8084以及路径 /item
商品详情页面静态化thymeleaf_第1张图片

商品详情页面静态化thymeleaf_第2张图片

商品详情的数据,需要封装在model 中,通过thymeleaf和vue 来动态展示在item.html 上,需要对spu 、skus 、skuDetails 、以及商品对应的specs(通用规格参数、特殊规格参数)等一系列数据进行封装;
一般封装成map 这样进行取值展示;

商品详情页面静态化thymeleaf_第3张图片

1、创建接口client,在 item-service商品微服务中GoodsController,创建querySpuById 查询spu 的方法、item-interface微服务对外提供api接口、

 /**
     * 通过spuid  查询
     * @param id spuid
     * @return
     */
    @GetMapping("spu/{spuId}")
    public ResponseEntity<Spu> querySpuById(@PathVariable("spuId") Long id){
        Spu spu=this.goodsService.querySpuById(id);
        if (spu != null) {
            return ResponseEntity.ok(spu);
        }
        return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
    }

2、model中封装数据

/**
 * @auther SyntacticSugar
 * @data 2018/12/23 0023上午 11:26
 */
@Service
public class GoodsService {
    @Autowired
    private BrandClient brandClient;
    @Autowired
    private CategoryClient categoryClient;
    @Autowired
    private GoodsClient goodsClient;
    @Autowired
    private SpecClient specClient;

    //日志
    private static final Logger logger = LoggerFactory.getLogger(GoodsService.class);

    public Map<String, Object> loadModel(Long goodsId) {
        try {
            Map<String, Object> map = new HashMap<>();

            List<Sku> skus = this.goodsClient.querySkuBySpuId(goodsId);
            SpuDetail spuDetail = this.goodsClient.querySpuDetailById(goodsId);
            Spu spu = this.goodsClient.querySpuById(goodsId);
            // 对查询的goods 封装
            map.put("skus", skus);
            map.put("spuDetail", spuDetail);
            map.put("spu", spu);
                 return map;
        } catch (Exception e) {
            //    public void error(String format, Object arg1, Object arg2);
            logger.error("spuId:{}", goodsId,e);
            e.printStackTrace();
        }
        return null;
    }
@Controller
@RequestMapping("item")
public class GoodsController {

   @Autowired
    private GoodsService goodsService;

    @GetMapping("{id}.html")
    public String get(Model model, @PathVariable("id") Long spuId) {
        model.addAllAttributes(goodsService.loadModel(spuId));
        return "item";
    }
}

在item.html中

<script th:inline="javascript">
	const skus=/*[[${skus}]]*/{};
	const spuDetail=/*[[${spuDetail}]]*/{};
	const spu=/*[[${spu}]]*/{};
	console.log(skus);
	console.log(spuDetail);
	console.log(spu);
script>

前端页面console ,可以看到skus、spuDetail、spu 对象,在spuDetail中取值通用规范参数genericSpec,特殊规格参数specialSpec、
商品详情页面静态化thymeleaf_第4张图片

通用规范参数genericSpec,特殊规格参数specialSpec、

      String genericSpec = spuDetail.getGenericSpec();
            String specialSpec = spuDetail.getSpecialSpec();
            Map<Long, Object> genericMap = JsonUtils.parseMap(genericSpec, Long.class, Object.class);
            Map<Long, List<String>> specMap = JsonUtils.nativeRead(specialSpec, new TypeReference<Map<Long, List<String>>>() {
            });
               map.put("genericMap", genericMap);
            map.put("specMap", specMap);

商品详情页面静态化thymeleaf_第5张图片
处理规格参数为 k :v 展示在页面,

   // 查询特有规格参数、普通规格参数
            List<SpecParam> params = this.specClient.querySpecParam(null, spu.getCid3(), null, false);

            // 处理成 kv
            HashMap<Long, String> paramMap = new HashMap<>();
            params.forEach(param->{
                paramMap.put(param.getId(),param.getName());
            });
     		map.put("paramMap", paramMap);

商品详情页面静态化thymeleaf_第6张图片

//value为每一个sku的规格参数数组
//key 是param.getId()
				<dl v-for="(value,key,index) in specMap " :key="index">
								<dt>
									<div class="fl title">
									<i>{{key}}i>
								div>
								dt>
								<dd v-for="v in value">
									<a href="javascript:;" class="selected">
										{{v}}<span title="点击取消选择"> span>
									a>
								dd>
							dl>

商品详情页面静态化thymeleaf_第7张图片

{{key}}
更改为{{paramMap[key]}}

商品详情页面静态化thymeleaf_第8张图片

商品详情页面静态化thymeleaf_第9张图片
通过计算,计算skus的每一个sku的indexes中的index 等于值的index的话,给其赋值;

	computed:{

			sku(){
				const index = Object.values(this.indexes).join("_");
				return this.skus.find(s => s.indexes == index);
			}

		},

商品详情页面静态化thymeleaf_第10张图片


展示图片,在skus数组中的对象中有images
计算属性中存在每一个sku 、sku中的images 是字符串,转化为数组展示。
1、需要判断图片是否存在
2、需要绑定选择的规格参数 和数组中图片的下标 一致,即
商品详情页面静态化thymeleaf_第11张图片

这样就能够选择什么机身颜色,对应哪一个图片,默认选择第一张即images[0];

			<div class="zoom">
						
						<div id="preview" class="spec-preview">
							<span class="jqzoom">
								<img :jqimg="images[0]" :src="images[0]" width="400px" height="400px"/>
							span>
						div>
						
						<div class="spec-scroll">
							<a class="prev"><a>
							
							<div class="items">
								<ul>
									
  • <img :src="image" :bimg="image" onmousemove="preview(this)" /> li> ul> div> <a class="next">>a> div> div>
  • 查询规格参数,当然这处没有什么问题,但是vue显示规格参数组specGroups:null 然后断点debug发现是有值的,放行以后值展示出来了,有时候代码没错,思路没错,刷新就不出来,就debug跟着走一走;

    商品详情页面静态化thymeleaf_第12张图片

        /**
         * 查规格参数组
         * @param cid  分类id
         * @return
         */
        @GetMapping("/groups/{cid}")
        public ResponseEntity<List<SpecGroup>> querySpecGroups(@PathVariable("cid")Long cid){
            List<SpecGroup> specGroups = this.specService.querySpecGroups(cid);
            if (specGroups != null && 0!=specGroups.size()) {
                return ResponseEntity.ok(specGroups);
            }
            return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        }
    

    在service 中封装规格参数组数据进去
    在pojo中SpecGroup,添加业务字段 List< SpecParam>

    @Table(name = "tb_spec_group")
    public class SpecGroup {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        private Long cid;
    
        private String name;
    
        //改组下所有的规格参数
        @Transient
        private List<SpecParam> params;
        // getter setter
        }
    
    @Service
    public class SpecService {
    
        @Autowired
        private SpecGroupMapper specGroupMapper;
        @Autowired
        private SpecParamMapper specParamMapper;
        public List<SpecGroup> querySpecGroups(Long cid) {
            SpecGroup specGroup = new SpecGroup();
            specGroup.setCid(cid);
            List<SpecGroup> specGroups = this.specGroupMapper.select(specGroup);
            // 把specParams参数规格设置到speGroup中
            specGroups.forEach(speGroup -> {
                SpecParam specParam = new SpecParam();
                specParam.setGroupId(speGroup.getId());
                specParam.setCid(cid);
                speGroup.setParams(this.specParamMapper.select(specParam));
    
            });
            return specGroups;
        }
        }
    
    	const specGroups=/*[[${specGroups}]]*/{}
    	console.log(specGroups)
    
    data中声明属性、
    specGroups
    

    商品详情页面静态化thymeleaf_第13张图片
    展示在页面

    	
    		<div class="intro-detail" v-html="spuDetail.description">
    		div>
    

    商品详情页面静态化thymeleaf_第14张图片

    处理规格预包装、

             <div class="Ptable" v-for="group in specGroups">
               <div class="Ptable-item">
                  <h3>主体h3>
                  <dl v-for="param in group.params">
                         <dt>{{param.name}}dt>
                    <dd>{{param.generic?genericMap[param.id]:specMap[param.id]}}dd>
                   dl>
                div>
          div>
    

    参数组下params中对通用规格做判断,true就在通用规格参数map中取值,false就在特殊规格参数map中取值、
    商品详情页面静态化thymeleaf_第15张图片
    通用规格参数、
    商品详情页面静态化thymeleaf_第16张图片
    特有规格参数、
    商品详情页面静态化thymeleaf_第17张图片
    显然不合适,当展示当前sku的规格属性,在计算属性中存在sku 的特有规格参数、
    商品详情页面静态化thymeleaf_第18张图片

    <dd>
    {{param.generic?genericMap[param.id]:JSON.parse(sku.ownSpec)[param.id]}}
    dd>
    

    商品详情页面静态化thymeleaf_第19张图片

    处理组名字,使用插值表达式取出组名

    <h3>{{group.name}}h3>
    

    商品详情页面静态化thymeleaf_第20张图片
    刷新如下:
    商品详情页面静态化thymeleaf_第21张图片
    处理剩下的售后保障、商品评价等、
    商品详情页面静态化thymeleaf_第22张图片

    你可能感兴趣的:(项目)