03秒杀商品-首页

3.秒杀商品-首页

在这里插入图片描述

秒杀商品首页会显示处于秒杀中以及未开始秒杀的商品。

3.1 秒杀首页实现分析

在这里插入图片描述

秒杀首页需要显示不同时间段的秒杀商品信息,然后当用户选择不同的时间段,查询该时间段下的秒杀商品,实现过程分为两大过程:

1) 加载时间菜单
2)加载时间菜单下秒杀商品信息

3.1.1 加载时间菜单分析

每2个小时就会切换一次抢购活动,所以商品发布的时候,我们将时间定格在2小时内抢购,每次发布商品的时候,商品抢购开始时间和结束时间是这2小时的边界。
每2小时会有一批商品参与抢购,所以我们可以将24小时切分为12个菜单,每个菜单都是个2小时的时间段,当前选中的时间菜单需要根据当前时间判断,判断当前时间属于哪个秒杀时间段,然后将该时间段作为选中的第1个时间菜单。

3.1.2 加载对应秒杀商品分析

进入首页时,到后台查询时间菜单信息,然后将第1个菜单的时间段作为key,在Redis中查询秒杀商品集合,并显示到页面,页面每次点击切换不同时间段菜单的时候,都将时间段传入到后台,后台根据时间段获取对应的秒杀商品集合。

3.2 秒杀渲染服务 - 渲染秒杀首页

3.2.1 新建秒杀渲染服务

1)创建工程changgou_web_seckill,用于秒杀页面渲染
2) 添加依赖

<dependencies>
        <dependency>
            <groupId>com.changgou</groupId>
            <artifactId>changgou_service_seckill_api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>
  1. 添加启动类
package com.changgou.seckill.web;

import com.changgou.interceptor.FeignInterceptor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.changgou.seckill.feign"})
public class SecKillWebApplication {

    public static void main(String[] args) {
        SpringApplication.run(SecKillWebApplication.class,args);
    }

    @Bean
    public FeignInterceptor feignInterceptor(){
        return  new FeignInterceptor();
    }

    /**
     * 设置 redisTemplate 的序列化设置
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 1.创建 redisTemplate 模版
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        // 2.关联 redisConnectionFactory
        template.setConnectionFactory(redisConnectionFactory);
        // 3.创建 序列化类
        GenericToStringSerializer genericToStringSerializer = new GenericToStringSerializer(Object.class);
        // 6.序列化类,对象映射设置
        // 7.设置 value 的转化格式和 key 的转化格式
        template.setValueSerializer(genericToStringSerializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

  1. 添加application.yml
server:
  port: 9104
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
spring:
  jackson:
    time-zone: GMT+8
  thymeleaf:
    cache: false
  application:
    name: seckill-web
  main:
    allow-bean-definition-overriding: true
  redis:
    host: 192.168.200.128
#hystrix 配置
hystrix:
  command:
    default:
      execution:
        timeout:
          #如果enabled设置为false,则请求超时交给ribbon控制
          enabled: true
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 60000
#请求处理的超时时间
ribbon:
  ReadTimeout: 4000
  #请求连接的超时时间
  ConnectTimeout: 3000
  1. 添加静态化资源 (联系我qq1712841217)
    在这里插入图片描述

6)对接网关 (gateway服务)

#秒杀渲染微服务
- id: changgou_seckill_web_route
  uri: lb://seckill-web
  predicates:
    - Path=/api/wseckillgoods/**
  filters:
    - StripPrefix=1

3.3 时间菜单实现

时间菜单显示,先运算出每2小时一个抢购,就需要实现12个菜单,可以先计算出每个时间的临界值,然后根据当前时间判断需要显示12个时间段菜单中的哪个菜单,再在该时间菜单的基础之上往后挪4个菜单,一直显示5个时间菜单。

3.3.1 时间菜单获取

changgou_web_seckill新增控制类SecKillGoodsController

package com.changgou.seckill.web.controller;

import com.changgou.entity.Result;
import com.changgou.seckill.feign.SecKillGoodsFeign;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/wseckillgoods")
public class SecKillGoodsController {

    //获取秒杀时间段集合信息
    @RequestMapping("/timeMenus")
    @ResponseBody
    public List<String> dateMenus(){

        //获取当前时间段相关的信息集合
        List<Date> dateMenus = DateUtil.getDateMenus();
        List<String> result = new ArrayList<>();

        SimpleDateFormat simpleDateFormat  = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (Date dateMenu : dateMenus) {
            String format = simpleDateFormat.format(dateMenu);
            result.add(format);
        }

        return  result;

    }

}

3.3.2 页面加载时间菜单

修改seckill-index.html

在这里插入图片描述

var app = new Vue({
	el: '#app',
	data() {
		return {
			goodslist: [],
			dateMenus:[]
			}
	},
	methods:{
		loadMenus:function () {
			axios.get("/api/wseckill/timeMenus").then(function(response) {
app.dateMenus=response.data;
		//查询当前时间段对应的秒杀商品
			})
		}
	},
created:function () {
	this.loadMenus();
	}
})
</script>

效果如下:

在这里插入图片描述

3.3.3 时间格式化

上面菜单循环输出后,会出现如上图效果,时间格式全部不对,我们需要引入一个moment.min.js来格式化时间。
1)引入moment.min.js
2)添加过滤器 (html-index 336行)

Vue.filter("dateFilter", function(date, formatPattern){
return moment(date).format(formatPattern || "YYYY-MM-DD HH:mm:ss");
});
  1. 取值格式化
<div class="time-clock">{{item | dateFilter('HH:mm')}}</div>

重新访问:http://localhost:9104/wseckill/toIndex 。时间菜单效果如下

在这里插入图片描述

3.3.4 选中实现

3.3.4.1 思路分析

在这里插入图片描述

根据原型图,是让当前第一个时间菜单为选中状态,并且加载第一个菜单对应的数据。
我们可以先定义一个ctime=0,用来记录当前选中的菜单下标,因为默认第一个选中,第一个下标为0,所以初始值为0,每次点击对应菜单的时候,将被点击的菜单的下标值赋值给ctime,然后在每个菜单上判断,下标=ctime则让该菜单选中。

3.3.4.2 代码实现

1)定义ctime=0

var app = new Vue({
			el: '#app',
			data() {
				return {
					goodslist: [],
					dateMenus:[],
					ctime:0,     //当前时间菜单选中的下标,
				}
			}
})

2)页面样式控制:

在这里插入图片描述

在这里插入图片描述

3.3.5 倒计时实现

3.3.5.1 倒计时实现
3.3.5.1.1 基础数据显示

定义一个集合,用于存放五个时间段的倒计时时间差,集合中每一个角标都对应一个倒计时时间差,比如:集合角标为0,对应第一个倒计时时间差。集合角标为1,对应第二个倒计时时间差,依次类推。

因为要有倒计时的效果,所以后续会遍历该时间集合,并让集合中的每一个时间循环递减即可。
在这里插入图片描述

从该集合中获取内容,并更新倒计时时间

在这里插入图片描述

3.3.5.1.2 每个时间差倒计时实现

周期执行函数用法如下:

window.setInterval(function(){//要做的事},1000);

结束执行周期函数用法如下:

window.clearInterval(timers);

具体代码如下:

在这里插入图片描述

//时间差递减实现
						let timers = window.setInterval(function () {
							for(var i=0;i<app.alltimes.length;i++){
								//时间递减
								app.$set(app.alltimes,i,app.alltimes[i]-1000);
								if (app.alltimes[i]<=0){
									//停止倒计时并重新刷新秒杀时间段
									window.clearInterval(timers);
									app.loadMenus();
								}
							}
						},1000);

测试访问:http://localhost:9104/wseckill/toIndex 。可以发现每一个时间段的时间都在每秒递减。

3.3.5.1.3 倒计时时间格式化
//将毫秒转换成时分秒
				timedown:function(num) {
					var oneSecond = 1000;
					var oneMinute=oneSecond*60;
					var oneHour=oneMinute*60
					//小时
					var hours =Math.floor(num/oneHour);
					//分钟
					var minutes=Math.floor((num%oneHour)/oneMinute);
					//秒
					var seconds=Math.floor((num%oneMinute)/oneSecond);
					//拼接时间格式
					var str = hours+':'+minutes+':'+seconds;
					return str;
				},

修改时间差显示设置

在这里插入图片描述

重新访问进行测试。效果如下:

在这里插入图片描述

3.3.5.1.4 正确倒计时时间显示

现在页面中,对于倒计时时间集合内的数据,暂时写的为假数据,现在需要让集合内容的数据是经过计算得出的。第一个是距离结束时间倒计时,后面的4个都是距离开始倒计时,每个倒计时其实就是2个时差,计算方式如下:

第1个时差:第2个抢购开始时间-当前时间,距离结束时间
第2个时差:第2个抢购开始时间-当前时间,距离开始时间
第3个时差:第3个抢购开始时间-当前时间,距离开始时间
第4个时差:第4个抢购开始时间-当前时间,距离开始时间
第5个时差:第5个抢购开始时间-当前时间,距离开始时间

在这里插入图片描述

loadMenus:function () {
					axios.get("/api/wseckillgoods/timeMenus").then(function (response) {
						app.dateMenus = response.data;

						//查询当前秒杀时间段下的秒杀商品列表
						app.searchList(app.dateMenus[0]);

						//计算正确的倒计时时间差
						for(var i=0;i<app.dateMenus.length;i++){
							if (i==0){
								var x =i+1;
								app.$set(app.alltimes,i,new Date(app.dateMenus[x]).getTime() - new Date().getTime());
							} else{
								app.$set(app.alltimes,i,new Date(app.dateMenus[i]).getTime() - new Date().getTime());
							}
						}

						//时间差递减实现
						let timers = window.setInterval(function () {
							for(var i=0;i<app.alltimes.length;i++){
								//时间递减
								app.$set(app.alltimes,i,app.alltimes[i]-1000);
								if (app.alltimes[i]<=0){
									//停止倒计时并重新刷新秒杀时间段
									window.clearInterval(timers);
									app.loadMenus();
								}
							}
						},1000);
					})
发布了211 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u014736082/article/details/104869384
今日推荐