vue3实现一个抽奖小项目

news2024/11/15 18:26:05

前言

  • 在公司年会期间我做了个抽奖小项目,我把它分享出来,有用得着的可以看下。
  • 浏览链接:http://xisite.top/original/luck-draw/index.html
  • 项目链接:https://gitee.com/xi1213/luck-draw (欢迎star!)
  • 项目截图:

实现目标

  • 数据保存:无后端,纯前端实现,浏览器刷新或者关闭数据不能丢失。
  • 姓名切换:点击中部开始按钮姓名快速切换。
  • 奖项切换:奖项为操作人员手动切换设置。
  • 历史记录:抽奖完成后需要有历史记录。
  • 数据导入:允许参与人员的表格导入。

数据保存

无后台,纯前端实现而且需要刷新关闭浏览器数据不丢失,很容易便会想到使用localStorage,localStorage存入的数据具有持久性,不会因为刷新或关闭浏览器而变化(除非手动刻意的清除),有别于sessionstorage,localStorage的生命周期是永久,sessionstorage是浏览器或者标签页关闭。

因为存入的数据不是单纯的字符串,而是具有结构性的对象数组,所以需要配合JSON.stringify与JSON.parse来使用。这是存入数据的方法:

localStorage.setItem("luckDrawHis", JSON.stringify(luckDrawHis));//JSON.stringify将json转换为字符串

这是读取数据的方法:

JSON.parse(localStorage.getItem("luckDrawHis"))//JSON.parse将字符串转换为json

姓名切换

抽奖的方式是数据导入后,点击中间的圆形开始按钮,姓名便开始快速切换,再次点击按钮便停止姓名切换,弹出对话框显示当前姓名以及设置的奖项。

切换姓名利用了vue的数据响应式原理。先获取到所有的参与人员数据,然后乱序处理,最后循环展示,我这里每个姓名展示的时间为50毫秒,你也可以自己设置。这里的数组乱序我使用了洗牌算法,其实就是利用Math.random获取数组的随机下标,然后与最后一个元素进行位置交换。

//洗牌算法(乱序数组)
function shuffle(arr) {
  let l = arr.length
  let index, temp
  while (l > 0) {
    index = Math.floor(Math.random() * l)
    temp = arr[l - 1]
    arr[l - 1] = arr[index]
    arr[index] = temp
    l--
  }
  return arr;
}

//循环列表
function forNameList(list) {
  list = shuffle(list);
  for (let i = 0; i < list.length; i++) {
    setTimeout(() => {
      if (!isStop.value) {
        curName.value = list[i].name;
        (i == list.length - 1) && (forNameList(nameList.value));//数组耗尽循环
      }
    }, 50 * i);
  }
}

奖项切换

奖项切换直接使用elementPlus的单选框即可。

历史记录

每次点击抽奖出现结果时,将之前的抽奖结果取出来,然后把当前的结果添加到末尾。

点击抽奖历史按钮时再将所有历史数据取出来。

数据导入

由于需要导入人员表格数据,这里我使用了xlsx插件与file-saver插件来实现。

首先是下载模板。
在这里插入图片描述

将事先准备好的表格模板放在项目的public目录下。

点击下载模板按钮时直接调用以下方法即可,其中的saveAs是file-saver插件中的方法,传入路径与文件名即可。

import { saveAs } from 'file-saver';
//下载模板
function downTemp() {
    let fileName = "人员模板.xlsx";//文件名
    let fileUrl = "./template/";//文件路径(路径相对index.html)
    saveAs(fileUrl + fileName, fileName);
}

表格处理好,

点击导入按钮读取表格数据时使用的是xlsx插件,下面是读取数据的方法。

import * as XLSX from "xlsx";
//导入数据
function importData(e) {
    isLoading.value = true;
    let file = e.target.files[0]; //获取事件中的file对象
    let fileReader = new FileReader(); //创建文件读取器
    fileReader.onload = (event) => {
        let result = event.target.result; //获取读取的结果
        let workBook = XLSX.read(result, { type: "binary" }); //XLSX读取返回的结果
        let jsonData = XLSX.utils.sheet_to_json(
            workBook.Sheets[workBook.SheetNames[0]]
        ); //将读取结果转换为json
        tabData.value = [];
        jsonData.forEach((j) => {
            tabData.value.push({
                name: j.姓名,
                age: j.性别,
                department: j.部门,
            });
        }); //处理成需要的数据格式
        localStorage.setItem("tabData", JSON.stringify(tabData.value));//数据存入本地
        tabDataS.value = JSON.parse(localStorage.getItem("tabData"));//取出数据
        emits("getNameList", tabData);
        isLoading.value = false;
    };
    fileReader.readAsBinaryString(file); //开始读取文件
    ((document.getElementsByClassName("inp-xlsx")[0]).value = ""); //置空选中的文件
};

结语

  • 项目很简单,但给我的时间很少,很多优化的地方都没做好,后面有时间了再优化下,顺便适配下移动端。
  • 原文地址:https://xiblogs.top/?id=53

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

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

相关文章

UNIAPP学习点滴记录

一、事件处理 1&#xff09;tap和click的区别 在HbuilderX中&#xff0c;两者都是点击时触发事件;不同的是: 1.click是组件被点击时触发&#xff0c;会有约300ms的延迟(内置处理优化了) 2.tap是手指触摸离开时触发&#xff0c;没有300ms的延迟&#xff0c;但是会员事件穿透…

两种分类方法的比较

一个物体既可以按照元素分类法去分类&#xff0c;也可以按照形态分类法去分类。但似乎很难用元素去分类形态&#xff0c;也很难用形态去分类元素。 想用元素分类形态就得加入位置变量。而所谓的位置变量显然是一种空间变量。是粒子在空间中&#xff0c;所以所谓的空间变量似乎…

SpringBoot学习笔记【part14】Spring Cache + Redis 集成缓存数据

Spring Cache 是一个非常优秀的缓存组件&#xff0c;方便切换各种底层Cache&#xff08;如&#xff1a;redis&#xff09; 使用Spring Cache的好处&#xff1a; 提供基本的Cache抽象&#xff0c;方便切换各种底层Cache&#xff1b;通过注解Cache可以实现类似于事务一样&#x…

基于MMdet的Cascade MASKRCNN 原理及源码解读

目录 一、原理 二、源码解读 1、总参数文件configs/cascade_rcnn/cascade_mask_rcnn_r50_fpn_1x_coco.py 2、模型配置字典../_base_/models/cascade_mask_rcnn_r50_fpn.py 3、基于检测器类搭建模型 CascadeRCNN 4、backbone&#xff08;ResNet&#xff09; 5、neck&am…

深度学习数据标注_Lableme

图像标注工具Lable labelme 是一款图像标注工具&#xff0c;主要用于神经网络构建前的数据集准备工作&#xff0c;因为是用 Python 写的&#xff0c;所以使用前需要先安装 Python 集成环境 anaconda。 anaconda 安装 anaconda下载地址如下&#xff1a; https://www.anaconda…

数据结构:循环链表、双向链表和有序表

1、循环链表 循环链表(circular linked list)是线性表的另一种形式的链式存储表示。它的特点是表中最后一个结点的指针域指向第一个结点,整个链表成为一个由链指针相链接的环。对于循环链表,通常还在表中第一个结点之前“附加”一个“头结点”,并令“头指针”指向最后一个结点…

【算法基础】基础算法之排序

&#x1f63d;PREFACE&#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐ 评论&#x1f4dd;&#x1f4e2;系列专栏&#xff1a;https://blog.csdn.net/weixin_59954106/category_12108349.html&#x1f4aa;种一棵树最好是十年前其次是现在目录 1.快排 步骤 思路方法 题目…

ABB机器人仿真软件robotstudio v6.08安装教程

ABB机器人仿真软件robotstudio v6.08安装教程 具体步骤可参考以下内容: 注意:安装之前,最好将电脑的名称改为英文,否则可能会安装不成功, 第1步:将下载的安装包解压缩, 第2步:找到解压后的文件中的RobotStudio6.08, 第3步:找到“setup.exe”, 第4步:软件正在…

Open3D 深度图像转点云数据(Python版本)

文章目录 一、简介二、代码实现三、实现效果测试数据参考文献一、简介 深度图像的获取有很多方式,如激光雷达、结构光以及深度相机等,网上很多教程都是在讲解通过深度相机所获取的深度图像转换为三维点云数据(相机内参、外参),但是通过激光雷达所生成的深度相机通常与相机…

数据分析-决策树

我们生活中遇到很多问题其实把他们抽象成一个数学模型&#xff0c;都可以抽象为一个决策树。&#xff08;比如打篮球&#xff09; 我们总是会经历两个阶段&#xff1a;构造、剪枝 构造 什么是构造呢&#xff1f;构造就是生成一棵完整的决策树。简单来说&#xff0c;构造的过程…

【MySQL基础】MySQL多表操作详解

序号系列文章4【MySQL基础】MySQL表的七大约束5【MySQL基础】字符集与校对集详解6【MySQL基础】MySQL单表操作详解7【MySQL基础】运算符及相关函数详解文章目录前言MySQL多表操作1&#xff0c;多表关系1.1&#xff0c;一对一1.2&#xff0c;一对多1.3&#xff0c;多对多2&#…

Prometheus 配置身份认证

Prometheus 版本 2.41.0 平台统一监控的介绍和调研直观感受PromQL及其数据类型PromQL之选择器和运算符PromQL之函数Prometheus 配置身份认证 Prometheus 使用默认方式安装是不带有身份证认证和TLS&#xff0c;需要单独配置开启。 Prometheus 配置文件为yaml格式&#xff0c;并…

【自然语言处理】文本表示(一):One-Hot、BOW、TF-IDF、N-Gram

文本表示&#xff08;一&#xff09;&#xff1a;One-Hot、BOW、TF-IDF、N-Gram1.One-Hot 编码 One-Hot 编码&#xff0c;又称 “独热编码”&#xff0c;是比较常用的文本特征提取方法。这种方法把每个词表示为一个很长的向量。这个向量的维度是词表大小&#xff0c;只有一个维…

4. 基础语法

1. 标识符 a. 第一个字符必须是字母表中字母或下划线 _&#xff1b; b. 标识符的其他的部分由字母、数字和下划线组成&#xff1b; c. 标识符对大小写敏感&#xff1b; 在 Python 3 中&#xff0c;可以用中文作为变量名&#xff0c;非 ASCII 标识符也是允许的&#xff1b; 2.…

【JavaGuide面试总结】计算机网络·中

【JavaGuide面试总结】计算机网络中1.说说断开连接 - TCP 四次挥手2.为什么要四次挥手&#xff1f;3.为什么不能把服务器发送的 ACK 和 FIN 合并起来&#xff0c;变成三次挥手&#xff1f;4.如果第二次挥手时服务器的 ACK 没有送达客户端&#xff0c;会怎样&#xff1f;5.为什么…

第五届字节跳动青训营 前端进阶学习笔记(五)CSS进阶

文章目录前言CSS的重要特性1.选择器特指度&#xff08;1&#xff09;选择器优先级&#xff08;2&#xff09;选择器特指度2.继承&#xff08;1&#xff09;默认继承&#xff08;2&#xff09;显式继承3.初始值4.CSS属性值的计算过程布局&#xff08;Layout&#xff09;1.布局相…

搜索?——P3956 [NOIP2017 普及组] 棋盘

传送门: [NOIP2017 普及组] 棋盘 - 洛谷 思路: 将棋盘的每一个格子看做一个点&#xff0c;建一个无向图用来跑最短路. 这道题本应用搜索来做&#xff0c;但是转换成最短路好像简单点 建图: 1.对于已经有颜色的格子&#xff0c;在扫描四个方向的格子对相同颜色的建条长度为0…

【目标检测】目标检测究竟发展到了什么程度?聊聊这22年!

目录&#xff1a;目标检测的发展历程一、引言二、背景三、目标检测发展脉络3.1 传统目标检测算法3.1.1 Viola Jones Detector3.1.2 HOG Detector3.1.3 DPM Detector3.1.4 局限性3.2 Anchor-Based中的Two-stage目标检测算法3.2.1 RCNN3.2.2 SPPNet3.2.3 Fast RCNN3.2.4 Faster R…

Allegro如何设置Net Group操作指导

Allegro如何设置Net Group操作指导 Allegro除了可以对一组网络设置Bus以外,同样支持创建Net Group,如下图 功能和Bus的功能类似,并且同一个Net Group里面的网络可以形成一个shape形式的Group,方便查看 具体创建方法操作如下 打开规则管理器选择Electrical

MySQL窗口函教-开窗聚合函数(SUM()、AVG()、MAX()、MIN()、COUNT())

MySQL窗口函教-开窗聚合函数&#xff08;SUM()、AVG()、MAX()、MIN()、COUNT()&#xff09;和传统的聚合函数区别&#xff1f;最大的区别在于&#xff0c;一个操作列&#xff0c;一个是依次操作行&#xff0c;最终显示出每一行&#xff0c;最后的效果就是呈现叠加的效果-- 开窗…