美文网首页
简易版文字抽奖系统

简易版文字抽奖系统

作者: 芸芸众生ing | 来源:发表于2021-09-23 11:46 被阅读0次

需要用到 xlsxfile-saver 包,如果有帮助,还请点个赞哟!

css动画
/* css动画效果 */
@keyframes scale {
  0% {
    transform: scale(0);
  }

  100% {
    transform: scale(1)
  }
}

@keyframes flash {
  0% {
    opacity: 0;
    -webkit-transform: scale(1.5);
    transform: scale(1.5);
    color: transparent;
    text-shadow: 0 0 5px rgba(0, 0, 0, 0.5)
  }

  50% {
    opacity: 1
  }

  100% {
    opacity: 0;
    -webkit-transform: scale(0.5);
    transform: scale(0.5)
  }
}

@keyframes flow {
  0% {
    background-position: 50% 0
  }

  100% {
    background-position: 50% -250px
  }
}

@keyframes flash {
  0% {
    opacity: 0;
    -webkit-transform: scale(1.5);
    transform: scale(1.5);
    color: transparent;
    text-shadow: 0 0 5px rgba(0, 0, 0, 0.5)
  }

  50% {
    opacity: 1
  }

  100% {
    opacity: 0;
    -webkit-transform: scale(0.5);
    transform: scale(0.5)
  }
}

@keyframes shake {
  0% {
    -webkit-transform: translateX(5px);
    transform: translateX(5px)
  }

  20% {
    -webkit-transform: translateX(-10px);
    transform: translateX(-10px)
  }

  40% {
    -webkit-transform: translateX(15px);
    transform: translateX(15px)
  }

  60% {
    -webkit-transform: translateX(-20px);
    transform: translateX(-20px)
  }

  80% {
    -webkit-transform: translateX(15px);
    transform: translateX(15px)
  }

  100% {
    -webkit-transform: translateX(-10px);
    transform: translateX(-10px)
  }
}

@keyframes dinnerTip {

  0%,
  100% {
    opacity: 0;
    -webkit-transform: perspective(600px) translate3d(-50%, 7px, 0) scale(0.7) rotateY(180deg);
    transform: perspective(600px) translate3d(-50%, 7px, 0) scale(0.7) rotateY(180deg)
  }

  20%,
  80% {
    opacity: 1;
    -webkit-transform: perspective(600px) translate3d(-50%, 0, 0) rotateY(0deg);
    transform: perspective(600px) translate3d(-50%, 0, 0) rotateY(0deg)
  }
}

@keyframes comment {

  0%,
  100% {
    opacity: 0;
    -webkit-transform: translate3d(-50%, 200%, 0) scale(0.7);
    transform: translate3d(-50%, 200%, 0) scale(0.7)
  }

  20%,
  80% {
    opacity: 1;
    -webkit-transform: translate3d(-50%, 0, 0);
    transform: translate3d(-50%, 0, 0)
  }
}
主体代码
<!--
Name: 抽奖首页
author: xingyuelongchen
QQ    : 237956234
Date  : 2021-09-23
-->
<template>
  <div class="body">
    <el-tooltip effect="dark" content="抽奖设置" placement="right">
      <span class="setting" @click="$router.push('/setting')"></span>
    </el-tooltip>
    <div class="bg"></div>
    <div class="temp_container">
      <div class="temp" v-for="(item,index) in domlist" :key="item.phone+'-'+index" v-bind="item">{{item.phone}}</div>
    </div>
    <div class="box">
      <div class="title">{{tips}}</div>
      <div class="title">{{msg}}</div>
      <div class="btn" @click="start">
        <span class="start">
          <span>{{btn}}</span>
        </span>
      </div>
    </div>
    <div v-show="show" class="dialog">
      <div class="dialog-bg" @click="show=false"> </div>
      <div class="border"></div>
      <div class="dialog-box">{{winning}}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: "index",
  data() {
    return {
      show: false,
      winning: "",
      tips: "",
      msg: "抽奖即将开始!",
      btn: "开始",
      current: null,
      list: [],
      domlist: [],
      status: false,
      width: null,
      height: null
    };
  },
  mounted() {
    this.list = JSON.parse(localStorage.getItem("list") || "[]");
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    window.onresize = () => {
      this.width = window.innerWidth;
      this.height = window.innerHeight;
    };
  },
  methods: {
    async start() {
      if (!this.list.length) {
        if (await this.$confirm("无参与抽奖的人员,是否去添加?", "提示!", { type: "warning" })) {
          this.$router.push("/setting");
        }
        return;
      }
      if (this.status) return this.stop();
      if (this.show) return;
      this.tan();
      this.status = true;
      this.current = null;
      this.tips = "正在抽奖";
      this.btn = "停止";
      this.timer = setInterval(() => {
        let index = this.random(0, this.list.length);
        this.current = index;
        let name = this.list[index]?.name || "";
        let phone = this.list[index]?.phone || "";
        this.msg = this.re(name, 1, 2) + " " + this.re(phone, 3, 7, "****");
      }, 50);
    },
    stop() {
      clearInterval(this.timer);
      clearTimeout(this.tanTimer);
      this.status = false;
      this.btn = "继续";
      let { phone } = this.list[this.current];
      this.winning = `${this.re(phone, 3, 7, "****")}`;
      this.show = true;
      let list = this.list.splice(this.current, 1);
      let arr = JSON.parse(localStorage.getItem("draw") || "[]");
      localStorage.setItem("list", JSON.stringify(this.list));
      localStorage.setItem("draw", JSON.stringify(list.concat(arr)));
    },
    tan() {
      clearTimeout(this.tanTimer);
      let arr = new Array(10).fill().map(() => {
        let index = this.random(0, this.list.length);
        let name = this.re(this.list[index]?.name || "", 1, 2);
        let phone = this.re(this.list[index]?.phone || "", 3, 7, "****");
        let left = this.random(0, this.width) + "px";
        let top = this.random(0, this.height) + "px";
        let fontSize = this.random(10, 30) + "px";
        let color = `rgba(0,0,0,${this.random(3, 8) / 10})`;
        let style = { left, top, fontSize, color };
        return { name, phone: Math.ceil(Math.random() * 1 - 0.5) ? name : phone, style };
      });
      this.domlist.push(...arr);
      this.tanTimer = setTimeout(() => this.tan(), 1000);
    },
    random(s, e) {
      return Math.floor(Math.random() * (e - s) + s);
    },
    re(val = "", s = 0, e = 0, k = "*") {
      val = val + "";
      return val.replace(val.slice(s, e), k);
    }
  }
};
</script>
 
<style scoped>
.setting {
  width: 100px;
  height: 100px;
  cursor: pointer;
  position: absolute;
  top: 0%;
  right: 0;
  z-index: 99;
}
.body {
  background: #e9e9e9;
}
.box {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
  width: 300px;
  height: 61px;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
}
.box .title {
  margin: 0 0 30px;
  min-height: 50px;
  padding: 0;
  font-weight: 400;
  font-size: 32px;
  color: #333;
  white-space: nowrap;
  /* overflow: hidden;
  text-overflow: ellipsis; */
}
.box .title.shake {
  animation: shake 0.4s;
}
.bg {
  background: #e9e9e9 url(~@/assets/images/bg.jpg) 50% 0;
  transform: translate3d(0, 0, 0);
  animation: flow 16s linear infinite;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
}

.playing .bg {
  animation-play-state: paused;
}

.temp_container {
  transform: translate3d(0, 0, 0);
  overflow: hidden;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.temp_container .temp {
  position: absolute;
  color: #777;
  animation: flash 1.6s ease-out both;
  white-space: nowrap;
}
.btn .start {
  background: rgba(0, 0, 0, 0.1);
  border-radius: 40px;
  padding: 5px;
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.07), 0 1px rgba(255, 255, 255, 0.5);
  display: inline-block;
  cursor: pointer;
}

.btn .start span {
  border-radius: 35px;
  width: 180px;
  height: 60px;
  line-height: 60px;
  background: linear-gradient(to bottom, #ffba30, #ff911e);
  color: #fff;
  text-align: center;
  display: block;
  font-size: 32px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  box-shadow: inset 0 1px #ffd17c, 0 2px 3px rgba(0, 0, 0, 0.2);
  border: 1px solid #e88e1d;
}

.btn .start:hover span {
  background: linear-gradient(to bottom, #ffce44, #ffa532);
  box-shadow: inset 0 1px #ffe696, 0 2px 3px rgba(0, 0, 0, 0.2);
}

.btn .start:active span {
  background: linear-gradient(to bottom, #ff911e, #ffbb30);
  box-shadow: inset 0 1px #ffb050, 0 2px 3px rgba(0, 0, 0, 0.2);
}
.dialog {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  /* background: url(~@/assets/images/bg1.jpeg) center center / 100% 100%; */
  background: rgba(214, 71, 65, 1);
  color: #fff;
  width: 800px;
  height: 375px;
  border-radius: 7px;
  box-shadow: 0 0 50px 10px rgba(0, 0, 0, 0.3);
  z-index: 10000;
  animation: scale 1.2s;
}
.dialog .dialog-bg {
  position: absolute;
  top: -125px;
  left: 0;
  right: 0;
  margin: auto;
  background: url(~@/assets/images/top.png) no-repeat center center / 100% 100%;
  width: 300px;
  height: 106px;
  cursor: pointer;
}
.dialog .border {
  margin: 15px;
  border: 5px solid rgba(255, 245, 33, 0.6);
  height: 340px;
  border-radius: 10px;
}
.dialog .dialog-box {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  width: 450px;
  height: 130px;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 7px;
  color: rgba(214, 71, 65, 1);
  font-size: 60px;
  text-align: center;
  line-height: 130px;
}
</style>
配置页
<!--
Name: setting
author: xingyuelongchen
QQ    : 237956234
Date  : 2021-09-15
-->
<template>
  <div>
    <div class="page">
      <el-card style="flex:0 0 400px">
        <div slot="header">
          <span>上传列表</span>
          <el-button @click="down" size="mini" type="success" style="float:right">下载模板</el-button>
        </div>
        <el-upload action="#" :on-change="uploadFile" :accept="accept" :auto-upload="false" :show-file-list="false" drag>
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
          <div class="el-upload__tip">只允许({{accept}})表格文件</div>
        </el-upload>
        <el-form ref="form" :model="formData" :rules="rules">
          <el-form-item v-for="item in formFields" v-bind="item" :key="item.prop">
            <el-input v-model="formData[item.prop]"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button @click="add" type="primary">添加</el-button>
          </el-form-item>
        </el-form>
      </el-card>
      <el-card style="flex:1 1 auto;margin-left:20px">
        <div slot="header">
          <span>参与抽奖人员列表</span>
          <el-button @click="to" size="mini" type="success" style="float:right">去抽奖</el-button>
        </div>
        <el-table :data="tableData" border height="500px" stripe>
          <el-table-column label="姓名" prop="name" />
          <el-table-column label="手机号" prop="phone" />
          <el-table-column>
            <template slot-scope="{row}">
              <el-button type="danger" size="mini" @click="del(row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-card>
      <el-card style="flex:0 0 500px;margin-left:20px">
        <div slot="header">
          <span>中奖名单</span>
          <el-button @click="downTable" size="mini" type="success" style="float:right">下载数据</el-button>
        </div>
        <el-table :data="tableDraw" border height="500px" stripe :show-header="false" ref="table" id="table">
          <el-table-column label="姓名" prop="name" />
          <el-table-column label="手机号" prop="phone" />
        </el-table>
      </el-card>
    </div>

  </div>
</template>
<script>
import XLSX from "xlsx";
import FileSaver from "file-saver";
export default {
  name: "setting",
  data() {
    return {
      accept: ".xlsx,.xls",
      tableData: JSON.parse(localStorage.getItem("list") || "[]"),
      tableDraw: JSON.parse(localStorage.getItem("draw") || "[]"),
      formData: {},
      formFields: [
        { label: "姓名", prop: "name" },
        { label: "手机号", prop: "phone", maxLength: 11 }
      ],
      rules: {
        name: { required: true, pattern: /^[\u4e00-\u9fa5]{2,10}$/, message: "请输入正确的姓名", trigger: ["blur"] },
        phone: { required: true, pattern: /^1[3-9][0-9]{9}$/, message: "请输入正确的11位手机号", trigger: ["blur"] }
      }
    };
  },
  methods: {
    downTable() {
      let wb = XLSX.utils.table_to_book(document.querySelector("#table"), { raw: true });
      let wbout = XLSX.write(wb, {
        type: "array",
        bookSST: true,
        bookType: "xlsx"
      });
      try {
        FileSaver.saveAs(new Blob([wbout], { type: "appliction/octet-stream" }), "中奖名单.xlsx");
      } catch (error) {
        console.log(error, wbout);
      }
      return wbout;
    },
    down() {
      let a = document.createElement("a");
      a.download = "人员信息上传模板.xlsx";
      a.href = "/template.xlsx";
      a.click();
    },
    del(row) {
      this.tableData = [...this.tableData].filter((e) => e.phone !== row.phone);
      this.save();
    },
    async add() {
      await this.$refs.form.validate();
      this.tableData.push({ ...this.formData });
      this.$refs.form.resetFields();
      this.save();
    },
    save() {
      let json = JSON.stringify(this.tableData);
      window.localStorage.setItem("list", json);
    },
    async to() {
      if (this.tableData.length) this.$router.push("/");
      else if (await this.$confirm("添加了0个人,确定离开?", "提示!", { type: "warning" })) {
        this.$router.push("/");
      }
    },
    async uploadFile(file) {
      if (!/(\.xlsx|\.xls)$/g.test(file.name)) {
        this.$message.error("请上传excel表格文件");
        return;
      }
      let { Sheets, SheetNames } = await this.readWorkbookFromLocalFile(file.raw);
      // let obj = [];
      this.tableData = [];
      SheetNames.forEach((name) => {
        let json = XLSX.utils.sheet_to_json(Sheets[name]);
        this.tableData.push(...json);
      });
      this.save();
      return false;
    },
    async readWorkbookFromLocalFile(file, callback) {
      return new Promise((resolve, reject) => {
        try {
          var reader = new FileReader();
          reader.onload = function (e) {
            var data = e.target.result;
            var workbook = XLSX.read(data, { type: "binary" });
            if (callback) callback(workbook);
            resolve(workbook);
          };
          reader.readAsBinaryString(file);
        } catch (error) {
          reject(error);
        }
      });
    }
  }
};
</script>
<style scoped>
.page {
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  margin: 50px;
}
.mix-form {
  margin-top: 20px;
}
</style>

项目地址:文字抽奖 (gitee.com);
请点个赞再走吧~

相关文章

  • 简易版文字抽奖系统

    需要用到 xlsx 和 file-saver 包,如果有帮助,还请点个赞哟! css动画 主体代码 配置页 项目地...

  • 学生管理系统简易版

    学生管理系统简易版 mian function view

  • 抽奖系统

    如下是功能实现的代码:

  • 抽奖系统

    try{ bool flag = true; //用于判断是否继续执行 string name; int key...

  • 抽奖系统

    代码: namespace ConsoleApplication1 { class Program { ...

  • 无限抽奖系统

    夕阳缓缓地从天边落下,叶天孤独地站在车站前等待着,俊气的脸上作出一副苦恼的样子,像平常一样,叶天低头沉思着回家后先...

  • 老婆抽奖系统

    "唔……,这是哪里?"陈炎茫然的看着破烂不堪的小木屋,一道记忆如流光进入陈炎的脑子,顿时晕了过去。醒来的时候,已经...

  • 锦囊21:好玩,手机号码大抽奖PPT

    目的:现在抽奖在公司年会或者是沙龙里面已经变得非常流行了,那如何用PPT制作一个抽奖系统呢? 这个抽奖系统是如果我...

  • 百万级用户抽奖系统,流量削峰架构设计方案分享

    1、抽奖系统的背景引入 本文给大家分享一个之前经历过的抽奖系统的流量削峰架构的设计方案。 抽奖、抢红包、秒杀,这类...

  • 如何设计一个百万级用户的抽奖系统?

    1、抽奖系统的背景引入 本文给大家分享一个之前经历过的抽奖系统的流量削峰架构的设计方案。抽奖、抢红包、秒杀,这类系...

网友评论

      本文标题:简易版文字抽奖系统

      本文链接:https://www.haomeiwen.com/subject/wdongltx.html