红包雨项目前端部分

创建项目

pnpm i -g @vue/cli
vue create red_pakage 
pnpm i sass sass-locader -D   
pnpm i --save normalize.css
pnpm i --save-dev postcss-px-to-viewport

pnpm i vant@latest-v2 -S
pnpm i babel-plugin-import -D

https://vant.pro/vant/v2/#/zh-CN/
 

 <van-button @click="test" type="info" size="large">信息按钮</van-button>

<script>
import { Toast } from "vant";
export default {
  name: "RedPackageApp",

  data() {
    return {};
  },

  mounted() {},

  methods: {
    test: function () {
      Toast.success("成功文案");
    },
  },
};
</script>

封装Axios
pnpm i axios
import axios from "axios";
import { Toast } from "vant";
import   getToken   from "./getToken";

const request = axios.create({
    baseURL: "/api",
    timeout: 10000,
});

request.interceptors.request.use(
    (config) => {
        config.headers.token = getToken();
        return config;
    },
    (error) => {
        Toast.fail("请求发送失败" + error);
        return Promise.reject(error);
    }
);

request.interceptors.response.use(
    (response) => {
        console.log(response);
        
        if (response.data.code === 200) {
            return response.data;
        } else {
            Toast.fail("请求失败");
            return Promise.reject(response);
        }
    },
    (error) => {
        Toast.fail("请求失败" + error);
        return Promise.reject(error);
    }
);

export default request;

倒计时遮罩
<template>
  <van-overlay :show="isShow">
    <div class="wrapper">
      <van-count-down v-if="isShow" :time="time" v-slot="{ seconds }" @finish="finish">
        <span class="seconds">{
  
  { seconds }}</span>
      </van-count-down>
    </div>
  </van-overlay>
</template>

<script>
export default {
  name: "CountdownMask",
  props: ["onFinish"],

  data() {
    return {
      isShow: false,
      time: 3500,
    };
  },

  mounted() {},

  methods: {
    show(time = 3500) {
      this.isShow = true;
      this.time = time;
    },
    finish() {
      this.isShow = false;
      this.onFinish();
      //   this.$emit("finish");
    },
  },
};
</script>

<style lang="scss" scoped>
.wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.seconds {
  font-size: 40px;
  color: #f00;
}
</style>
<template>
  <div>
    <CountdownMask ref="countdownMast" :onFinish="onCountFinish" />
  </div>
</template>

<script>
import request from "@/utils/request";
import CountdownMask from "./components/CountdownMask";
export default {
  name: "RedPackageApp",
  components: {
    CountdownMask,
  },

  data() {
    return {};
  },

  mounted() {
    setTimeout(() => {
      this.$refs.countdownMast.show(5000);
    }, 2000);
  },

  methods: {
    onCountFinish() {
      console.log("onFinish in RedPackageApp");
    },
  },
};
</script>

<style lang="scss" scoped></style>
记录页遮罩
<template>
  <van-overlay :show="isShow">
    <div class="wrapper">
      <div class="content">
        <span class="title">恭喜获得</span>
        <span class="amount">{
  
  { amount }}</span>
        <span class="unit">元</span>
      </div>
      <van-icon name="close" class="close_icon" @click="close" />
    </div>
  </van-overlay>
</template>

<script>
export default {
  name: "RecordMask",
  props: ["onClose"],
  data() {
    return {
      isShow: false,
      amount: 0,
    };
  },

  mounted() {},

  methods: {
    show(amount = 0) {
      this.isShow = true;
      this.amount = amount;
    },
    close() {
      this.isShow = false;
      this.onClose();
    },
  },
};
</script>

<style lang="scss" scoped>
.wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  background-image: url("../assets/reward.jpg");
  background-repeat: no-repeat;
  background-size: 300px;
  background-position: center;
  .content {
    transform: translateY(15%);
    display: flex;

    align-items: center;
    justify-content: center;
    background-color: rgba(255, 255, 255, 0.8);
    padding: 20px;
    border-radius: 10px;
  }
  .close_icon {
    position: absolute;
    top: 10px;
    right: 10px;
    color: rgb(255, 255, 255);
    font-size: 40px;
  }
}
</style>
<template>
  <div>
    <CountdownMask ref="countdownMast" :onFinish="onCountFinish" />
    <RecordMask ref="recordMask" :onClose="onRecordClose" />
  </div>
</template>

//
<script>
// import request from "@/utils/request";
import CountdownMask from "./components/CountdownMask";
import RecordMask from "./components/RecordMask.vue";
export default {
  name: "RedPackageApp",
  components: {
    CountdownMask,
    RecordMask,
  },

  data() {
    return {};
  },

  mounted() {
    setTimeout(() => {
      this.$refs.recordMask.show(5000);
    }, 2000);
  },

  methods: {
    onCountFinish() {
      console.log("onFinish in RedPackageApp");
    },
    onRecordClose() {
      console.log("onRecordClose in RedPackageApp");
    },
  },
};
</script>

<style lang="scss" scoped></style>
下红包雨

import defaultUrl from './../assets/red.jpg';

export default class RedPacket {
    constructor(options) {
        this.url = options.url || defaultUrl;
        this.width = options.width || '20vw';
        this.height = options.height || 'auto';
        this.callback = options.callback || function () { };
        this.parent = options.parent || document.body;
        this.create();
    }
    create( ) {
        const img = document.createElement('img');
        img.src = this.url;
        img.style.width = this.width;
        img.style.height = this.height;
        // border-radius: 10px;
        img.style.borderRadius = '10px';
        img.ontouchstart = this.destroy.bind(this, img);
        this.parent.appendChild(img);
    }
    destroy (currentImg) {
        currentImg.remove();
        this.callback();
    }
}
<template>
  <div>
    <CountdownMask ref="countdownMast" :onFinish="onCountFinish" />
    <div class="rain-container" ref="rainContainer"></div>
    <RecordMask ref="recordMask" :onClose="onRecordClose" />
  </div>
</template>

//
<script>
// import request from "@/utils/request";
import CountdownMask from "./components/CountdownMask";
import RecordMask from "./components/RecordMask.vue";
import RedPacket from "./class/RedPacket.js";
export default {
  name: "RedPackageApp",
  components: {
    CountdownMask,
    RecordMask,
  },

  data() {
    return {};
  },

  mounted() {
    setTimeout(() => {
      // this.$refs.countdownMast.show(5000);
    }, 2000);
    new RedPacket({
      parent: this.$refs.rainContainer,
    });
    new RedPacket({
      parent: this.$refs.rainContainer,
    });
    new RedPacket({
      parent: this.$refs.rainContainer,
    });
    new RedPacket({
      parent: this.$refs.rainContainer,
    });
    new RedPacket({
      parent: this.$refs.rainContainer,
    });
    new RedPacket({
      parent: this.$refs.rainContainer,
    });
  },

  methods: {
    onCountFinish() {
      console.log("onFinish in RedPackageApp");
    },
    onRecordClose() {
      console.log("onRecordClose in RedPackageApp");
    },
  },
};
</script>

<style lang="scss" scoped>
.rain-container {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background-image: linear-gradient(180deg, orange, red);
  overflow: hidden;
}
</style>
动画逻辑-随机位置

import defaultUrl from './../assets/red.jpg';

export default class RedPacket {
    constructor(options) {
      
        // 生成一个0-4的随机整数.
        const random = Math.floor(Math.random() * 5);
        this.track = options.track ||  random * 20;
        
        
    }
    create( ) { 
        // position: absolute;
        img.style.position = 'absolute'; 
        // left: 80vw;
        img.style.left = this.track + 'vw'; 
    }
    
}
动画逻辑-下落动画
import defaultUrl from './../assets/red.jpg';

export default class RedPacket {
    constructor(options) {
        this.url = options.url || defaultUrl;
        this.width = options.width || '20vw';
        this.height = options.height || 'auto';
        // 生成一个0-4的随机整数.
        const random = Math.floor(Math.random() * 5);
        this.track = options.track ||  random * 20; 
        // 生成一个-360-360的随机整数. // 生成一个3-8的随机整数. 
        const random1 = Math.floor(Math.random() * 721) - 360;
        const random2 = Math.floor(Math.random() * 6) + 3;
        this.rotate = options.rotate || random1;
        this.duration = options.duration || random2;  

        this.callback = options.callback || function () { };
        this.parent = options.parent || document.body;
        this.create();
    }
    create( ) {
        const img = document.createElement('img');
        img.src = this.url;
        img.style.width = this.width;
        img.style.height = this.height;
        // border-radius: 10px;
        img.style.borderRadius = '10px';
        // position: absolute;
        img.style.position = 'absolute'; 
        // left: 80vw;
        img.style.left = this.track + 'vw';


        img.animate([
            { transform: 'translateY(0)' },
            { transform: `translateY(120vh) rotate(${this.rotate}deg)` }
        ], {
            duration: this.duration * 1000,
            iterations: 1,
            fill: 'forwards'
        });


        img.ontouchstart = this.destroy.bind(this, img);
        this.parent.appendChild(img);
        setTimeout(() => {
            img.remove();
        }, this.duration * 1000);
    }
    destroy (currentImg) {
        currentImg.remove();
        this.callback();
    }
}
红包雨基本逻辑
<template>
  <div>
    <CountdownMask ref="countdownMast" :onFinish="onCountFinish" />
    <div v-show="rainContainerShow" class="rain-container" ref="rainContainer"></div>
    <RecordMask ref="recordMask" :onClose="onRecordClose" />
  </div>
</template>

//
<script>
// import request from "@/utils/request";
import CountdownMask from "./components/CountdownMask";
import RecordMask from "./components/RecordMask.vue";
import RedPacket from "./class/RedPacket.js";
export default {
  name: "RedPackageApp",
  components: {
    CountdownMask,
    RecordMask,
  },

  data() {
    return {
      rainContainerShow: false,
      timer: null,
    };
  },

  mounted() {
    this.$refs.countdownMast.show();
  },

  methods: {
    onCountFinish() {
      console.log("倒计时结束");
      this.createRain(5000, 200);
    },
    onRecordClose() {
      console.log("点了关闭");
    },
    onRainEnd() {
      console.log("下完雨了");
      this.$refs.recordMask.show(888);
    },
    onPacketClick() {
      console.log(" PacketClick  ");
    },
    createRain(duration, speed) {
      console.log("开始下红包雨");
      this.rainContainerShow = true;
      this.timer = setInterval(() => {
        new RedPacket({
          parent: this.$refs.rainContainer,
          callback: this.onPacketClick,
        });
      }, speed);
      setTimeout(() => {
        clearInterval(this.timer);
        this.onRainEnd();
      }, duration);
    },
  },
};
</script>

<style lang="scss" scoped>
.rain-container {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background-image: linear-gradient(180deg, orange, red);
  overflow: hidden;
}
</style>
部署详解

部署Redis

负载均衡

压测

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

源路由 | 源路由网桥 / 生成树网桥

注&#xff1a;本文为 “源路由” 相关文章合辑。 未整理去重。 什么是源路由&#xff08;source routing&#xff09;&#xff1f; yzx99 于 2021-02-23 09:45:51 发布 考虑到一个网络节点 A 从路由器 R1 出发&#xff0c;可以经过两台路由器 R2、R3&#xff0c;到达相同的…

【React】合成事件语法

React 合成事件是 React 为了处理浏览器之间的事件差异而提供的一种跨浏览器的事件系统。它封装了原生的 DOM 事件&#xff0c;提供了一致的事件处理机制。 合成事件与原生事件的区别&#xff1a; 合成事件是 React 自己实现的&#xff0c;封装了原生事件。合成事件依然可以通…

一文解释nn、nn.Module与nn.functional的用法与区别

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;零基础入门PyTorch框架_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 …

TongSearch3.0.4.0安装和使用指引(by lqw)

文章目录 安装准备手册说明支持的数据类型安装控制台安装单节点(如需集群请跳过这一节)解压和启动开启X-Pack Security和生成p12证书&#xff08;之后配置内置密码和ssl要用到&#xff09;配置内置用户密码配置ssl&#xff08;先配置内置用户密码再配ssl&#xff09;配置控制台…

2025年Android NDK超全版本下载地址

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

CSS outline详解:轮廓属性的详细介绍

什么是outline&#xff1f; outline&#xff08;轮廓&#xff09;是CSS中一个有趣的属性&#xff0c;它在元素边框&#xff08;border&#xff09;的外围绘制一条线。与border不同的是&#xff0c;outline不占用空间&#xff0c;不会影响元素的尺寸和位置。这个特性使它在某些…

蓝桥杯之c++入门(六)【string(practice)】

目录 练习1&#xff1a;标题统计方法1&#xff1a;一次性读取整行字符&#xff0c;然后统计方法2&#xff1a;按照单词读取小提示&#xff1a; 练习2&#xff1a;石头剪子布练习3&#xff1a;密码翻译练习4&#xff1a;文字处理软件练习5&#xff1a;单词的长度练习6&#xff1…

Windows编程:下载与安装 Visual Studio 2010

本节前言 在写作本节的时候&#xff0c;本来呢&#xff0c;我正在写的专栏&#xff0c;是 MFC 专栏。而 VS2010 和 VS2019&#xff0c;正是 MFC 学习与开发中&#xff0c;可以使用的两款软件。然而呢&#xff0c;如果你去学习 Windows API 知识的话&#xff0c;那么&#xff0…

基于ansible部署elk集群

ansible部署 ELK部署 ELK常见架构 &#xff08;1&#xff09;ElasticsearchLogstashKibana&#xff1a;这种架构是最常见的一种&#xff0c;也是最简单的一种架构&#xff0c;这种架构通过Logstash收集日志&#xff0c;运用Elasticsearch分析日志&#xff0c;最后通过Kibana中…

(苍穹外卖)项目结构

苍穹外卖项目结构 后端工程基于 maven 进行项目构建&#xff0c;并且进行分模块开发。 1). 用 IDEA 打开初始工程&#xff0c;了解项目的整体结构&#xff1a; 对工程的每个模块作用说明&#xff1a; 序号名称说明1sky-take-outmaven父工程&#xff0c;统一管理依赖版本&…

达梦数据库从单主模式转换为主备模式

目录标题 达梦数据库单主转主备配置笔记前期准备服务器环境数据库安装磁盘空间 流程流程图说明基于脱机备份方式的单实例转主备流程图详细步骤说明 详细步骤1. 检查主库归档模式2. 配置主库配置文件dm.ini 文件dmmal.ini 文件dmarch.ini 文件 3. 备份主库数据库4. 备库配置新建…

计算机毕业设计hadoop+spark+hive民宿推荐系统 酒店推荐系统 民宿价格预测 酒店价预测 机器学习 深度学习 Python爬虫 HDFS集群

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

接口对象封装思想及实现-笔记

目录 接口对象封装代码分层思想 封装案例封装Tpshop商城登录Tpshop商城登录参数化 接口自动化测试框架 接口对象封装 代码分层思想 分层思想&#xff1a;将普通思想分为两层&#xff0c;分为接口对象层和测试脚本层 接口对象层&#xff1a; 对接口进行封装&#xff0c;封装好之…

【LeetCode】5. 贪心算法:买卖股票时机

太久没更了&#xff0c;抽空学习下。 看一道简单题。 class Solution:def maxProfit(self, prices: List[int]) -> int:cost -1profit 0for i in prices:if cost -1:cost icontinueprofit_ i - costif profit_ > profit:profit profit_if cost > i:cost iret…

微信小程序调用企业微信客户服务插件联通企业微信客服

需求背景:用户在小程序页面点击按钮添加企业微信的客服 相关技术:基于uniapp开发的微信小程序 插件名称:企业微信客户服务插件「联系我」插件 - 文档 - 企业微信开发者中心 仔细阅读文档「联系我」插件 - 文档 - 企业微信开发者中心 以下是我的实例代码 1.首先先小程序管…

大数据数仓实战项目(离线数仓+实时数仓)2

目录 1.课程目标和课程内容介绍 2.数仓维度建模设计 3.数仓为什么要分层 4.数仓分层思想和作用 5.数仓中表的种类和同步策略 6.数仓中表字段介绍以及表关系梳理 订单表itcast_orders 订单明细表 itcast_order_goods 商品信息表 itcast_goods 店铺表 itcast_shops 商…

【Android】jni开发之导入opencv和libyuv来进行图像处理

做视频图像处理时需要对其进行水印的添加&#xff0c;放在应用层调用工具性能方面不太满意&#xff0c;于是当下采用opencvlibyuv方法进行处理。 对于Android的jni开发不是很懂&#xff0c;我的需求是导入opencv方便在cpp中调用&#xff0c;但目前找到的教程都是把opencv作为模…

理解 C 与 C++ 中的 const 常量与数组大小的关系

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;数组大小的常量要求&#x1f4af;C 语言中的数组大小要求&#x1f4af;C 中的数组大小要求&#x1f4af;为什么 C 中 const 变量可以作为数组大小&#x1f4af;进一步的…

小菜鸟系统学习Python第六天

1.函数: 2.全局变量加global(这里博主记混了,global使用的时候不能赋值,然后就错了两回) 3.内嵌函数 4.闭包 存在嵌套函数&#xff1a;在一个函数内部定义另一个函数。内部函数引用外部函数的变量&#xff1a;内部函数使用了外部函数作用域中的变量。外部函数返回内部函数&…

【STM32系列】利用MATLAB配合ARM-DSP库设计IIR数字滤波器(保姆级教程)

ps.源码放在最后面 设计FIR数字滤波器可以看这里&#xff1a;利用MATLAB配合ARM-DSP库设计FIR数字滤波器&#xff08;保姆级教程&#xff09; 设计IIR滤波器 MATLAB配置 设计步骤 首先在命令行窗口输入"filterDesigner"&#xff0c;接着就会跳出以下界面&#xf…