抽奖应用vue3-ts-LocalStorage

本文档介绍了如何使用Vue3和TypeScript构建一个抽奖应用。涵盖了显示页面(lottery.vue)的设计,操作页面(option.vue)的功能实现,以及在lottery.ts中定义的方法和数据处理。
摘要由CSDN通过智能技术生成

显示页面(lottery.vue):

<template>
    <img id="bg" src="@/assets/bg.png" alt="">
    <div class="card-container one">        
        <div :class="per_class" v-for="(item,index) in show_num" :key="item">
            <!-- <video class="loop-animate" :ref="el=>{loopFlashes.value.push(el)}" muted custom-cache="{
  {false}}" :src="'/src/assets/video/' + show_video_src_arr.value[index]"></video> -->
            <video class="loop-animate" :ref="el=>{loopFlashes.value.push(el)}" muted custom-cache="{
  {false}}" :src="webmsrc_dic[show_video_src_arr.value[index]]"></video>
            <h1>{
  {show_video_src_arr.value[index]}}</h1>
            <p :class="seat_num_class('area')">{
  { cur_lottery_arr.value[index].area }}</p>
            <p :class="seat_num_class('row')">{
  { cur_lottery_arr.value[index].row }}</p>
            <p :class="seat_num_class('seat')">{
  { cur_lottery_arr.value[index].seat }}</p>
        </div>
    </div>
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, reactive, ref } from 'vue'
import Lottery from './lottery'
import car from '../assets/video/car.webm'
import account from '../assets/video/account.webm'
import diamond from '../assets/video/diamond.webm'
import mobilephone from '../assets/video/mobilephone.webm'
import earphone from '../assets/video/earphone.webm'

export default defineComponent({
    name: 'QQSpeedLottery',
    setup(){
        const { max_area,
                max_row,
                max_seat,
                getRandomByRange } = Lottery();

        let show_num = ref(0);
        let show_video_src_arr = reactive({value: [] as any[]});

        let per_class = computed(() => {
            return {
                'per-card': true,
                'card3-margin': show_num.value == 3,
                'card4-margin': show_num.value == 4,
                'card5-margin': show_num.value == 5,
            }
        })

        const loopFlashes = reactive({value: [] as any[]});

        // 1. 翻转动画
        function reverse(){
            for (let i = 0; i < loopFlashes.value.length; i++) {
                if (loopFlashes.value[i] != null) {
                    loopFlashes.value[i].play();
                }
            }
            let t1 = setTimeout(() => {
                lottery_state.value = -1;
                clearTimeout(t1);
            }, 1100);
        }
        
        let lottery_state = ref(-1);
        let seat_num_class = computed(() => {
            return function(type: string){
                return {
                    'seat-num': true,
                    area: type == 'area',
                    row: type == 'row',
                    seat: type == 'seat',
                    end: lottery_state.value == -1
                }
            }
        })

        let cur_lottery_arr = reactive({value: [
            {area: '00', row: '00', seat: '00'}
            ,{area: '00', row: '00', seat: '00'}
            ,{area: '00', row: '00', seat: '00'}
            ,{area: '00', row: '00', seat: '00'}
            ,{area: '00', row: '00', seat: '00'}
        ]});
        
        // 2. 滚动数字
        function lottery(){
            let area = getRandomByRange(1,max_area);
            let row = getRandomByRange(1,max_row);
            let seat = getRandomByRange(1,max_seat);
            cur_lottery_arr.value = [];
            for (let i = 0; i < show_num.value; i++) {
                cur_lottery_arr.value.push({
                    area: area < 10 ? '0'+area.toString() : area.toString(),
                    row: row < 10 ? '0'+row.toString() : row.toString(),
                    seat: seat < 10 ? '0'+seat.toString() : seat.toString()
                })
            }
        }
        // 3. 暂停
        function stop(){
            clearInterval(lottery_interval);
        }

        let lottery_interval: any;
        window.addEventListener("storage", (e) => {
            let newValue = e.newValue;
            let data_json;
            if (newValue != null) {
                data_json = JSON.parse(newValue);    
            }
            // 奖品类型及个数
            if (e.key == "awardTypeAndNum"){
                show_num.value = data_json.award_num;
                show_video_src_arr.value = [];
                for (let i = 0; i < show_num.value; i++) {
                    show_video_src_arr.value.push(data_json.award_type_src);
                }
                // 隐藏座位号,重置动画素材
                lottery_state.value = 1;
                for (let i = 0; i < loopFlashes.value.length; i++) {
                    if (loopFlashes.value[i] != null) {
                        loopFlashes.value[i].load();
                    }
                }
                cur_lottery_arr.value = [
                    {area: '00', row: '00', seat: '00'}
                    ,{area: '00', row: '00', seat: '00'}
                    ,{area: '00', row: '00', seat: '00'}
                    ,{area: '00', row: '00', seat: '00'}
                    ,{area: '00', row: '00', seat: '00'}
                ];
            } else if (e.key == "reverseState"){
                reverse();
            } else if (e.key == "lotteryState") {
                if (data_json.state == 1) {
                    lottery_interval = setInterval(() => {
                        lottery();
                    }, 50);
                } else {
                    stop();
                    cur_lottery_arr.value = data_json.cur_luckyer_list;
                }
            }
        });

        onMounted(() => {
            localStorage.clear();
        })

        let webmsrc_dic: any = {
            'car': car,
            'account': account,
            'diamond': diamond,
            'mobilephone': mobilephone,
            'earphone':earphone
        }
        return {
            per_class,
            reverse,
            show_num,
            loopFlashes,
            show_video_src_arr,
            seat_num_class,
            cur_lottery_arr,
            webmsrc_dic
        }
    }
})
</script>

<style scoped>
#bg{
    position: absolute;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
}
.card-container{
    position: absolute;
    top: 380px;
    left: 0;
    display: flex;
    width: 1920px;
    height: 378px;
    justify-content: center;
}

.per-card{
    position: relative;
    width: 272px;
    height: inherit;
    border-radius: 10px;
    transition: transform 1s; 
}
.per-card:nth-child(1){
    margin-left: 0;
}

.card3-margin{
    margin-left: 106px;
}
.card4-margin{
    margin-left: 118px;
}
.card5-margin{
    margin-left: 118px;
}
.card5-margin{
    margin-left: 59px;
}

.loop-animate{
    position: absolute;
    left: -356px;
    top: -360px;
    width: 990px;
    height: auto;
    -webkit-transform: translate3d(0, 0, 0);
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}

.face{
    transform: rotateY(0deg) scale(1);
}

.back{
    transform: rotateY(180deg) scale(1.2);
}

@font-face{
    font-family: num;
    src: url(../assets/FZRuiZHK_Zhong.TTF);
}
.seat-num{
    position: absolute;
    color: #fff;
    font-size: 34px;
    font-family: num;
    font-style: italic;
    transform: rotateY(90deg);
    opacity: .9;
}
.area{top: 278px;right: 154px;}
.row{top: 320px;right: 190px;}
.seat{top: 322px;right: 101px;}

.end{
    transform: rotateY(0deg);
    transition: transform .3s;
}
</style>

操作页面(option.vue):

<template>
    <div id="option-container">
        <el-select v-model="award_type" placeholder="请选择奖品类型" filterable>
            <el-option
                v-for="(type, award_type_index) in award_type_list"
                :key="'award-type-'+award_type_index"
                :label="type.name"
                :value="award_type_index">
            </el-option>
        </el-select>

        <el-select v-model="award_num" placeholder="请选择奖品个数" filterable style="margin: 0 10px">
            <el-option
                v-for="(num, award_num_index) in award_num_list"
                :key="'award-'+award_num_index"
                :label="num.name"
                :value="award_num_index">
            </el-option>
        </el-select>

        <el-button size="small" @click="certainAwardTypeNum">确认奖品类型及个数</el-button>

        <el-button @click="reverseEvent" :disabled="reverse_is_able">翻转</el-button>
        <el-button @click="startEvent" :disabled="start_is_able">开始</el-button>
        <el-button @click="pauseEvent" :disabled="stop_is_able">暂停</el-button>
        <el-button @click="clearAll">清空已抽奖的纪录</el-button>
    </div>
    <h4 id="tip">当前H5展示奖品为:<span>{
  { cur_show_award_name }}</span>,奖品个数:<span>{
  { cur_show_award_num }}</span>。</h4>
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, ref } from 'vue'
import GHttp from '@/composables/GHttp'
import Lottery from './lottery'
import { ElMessage } from 'element-plus';

export default defineComponent({
    name: 'LotteryOption',
    setup(){
        const { seats_list,
                getRandomByRange } = Lottery();//解构导入的方法

        // 设置按钮可点击状态
        let reverse_is_able = ref(true);
        let start_is_able = ref(true);
        let stop_is_able = ref(true);

        const award_type_list = [
            {name: '钻石', type: 1, src: 'diamond'}
            ,{name: 'S-天行者', type: 2, src: 'car'}
            ,{name: '真我Buds Air2耳机', type: 3, src: 'earphone'}
            ,{name: '真我GT手机', type: 4, src: 'mobilephone'}
            ,{name: '全A车账号', type: 5, src: 'account'}
        ];
        let award_type = ref();

        const award_num_list = [
            {name: '1个', val: 1}
            ,{name: '3个', val: 3}
            ,{name: '4个', val: 4}
            ,{name: '5个', val: 5}
        ];
        let award_num = ref();

        // 设置奖品类型及个数
        let cur_show_award_name = ref('暂无');
        let cur_show_award_num = ref('暂无');
        let award_type_num_state = ref(-1);
        function certainAwardTypeNum(){
            if (award_type.value > -1 && award_num.value > -1) {
                cur_show_award_name.value = award_type.value > -1 ? award_type_list[award_type.value].name : '暂无';
                cur_show_award_num.value = award_num.value > -1 ? award_num_list[award_num.value].name : '暂无';
                let award_type_num_data = {
                    state: award_type_num_state.value,
                    award_type_src: award_type_list[award_type.value].src,
                    award_num: award_num_list[award_num.value].val
                };
                setLocalStorage('awardTypeAndNum', award_type_num_data);
                award_type_num_state.value = -award_type_num_state.value;

                reverse_is_able.value = false;
            } else {
                ElMessage({
                    showClose: true,
                    message: '请选择奖品类型、个数',
                    type: 'error'
                });
            }
        }

        // 翻转
        let reverse_state = ref(-1);
        function reverseEvent(){
            setLocalStorage('reverseState', reverse_state.value);
            reverse_state.value = -reverse_state.value;
            start_is_able.value = false;
        }

        // 开始
        function startEvent(){
            let start_data = {
                state: 1
            };
            setLocalStorage('lotteryState', start_data);
            stop_is_able.value = false;
        }

        // 暂停
        function pauseEvent(){
            lottery_count = 0;
            cur_all_seats_arr = [];
            getLottery();
            stop_is_able.value = true;
        }

        interface resData{
            errcode: number,
            errmsg: string,
            [key: string]: any
        }
        
        let lottery_count = 0;
        let cur_all_seats_arr = [] as any[];
        function getLottery(){
            let final_seat_index = getRandomByRange(0, seats_list.length - 1);
            let final_seat = seats_list[final_seat_index];
            let final_seat_str = final_seat.area + '区' + final_seat.row + '排'  + final_seat.seat + '座';
            let final_seat_obj = {area: final_seat.area, row: final_seat.row, seat: final_seat.seat};
            let add_luckyer_param = {
                luckyerlist: final_seat_str
            };

            if (lottery_count < award_num_list[award_num.value].val) {
                GHttp.post('/addLuckyer', add_luckyer_param).then((res: resData) => {
                    if (res.errcode == 0) {
                        cur_all_seats_arr.push(final_seat_obj);
                        lottery_count ++;
                    }
                    getLottery();
                })
            } else {
                let stop_data = {
                    state: -1,
                    cur_luckyer_list: cur_all_seats_arr
                };
                setLocalStorage('lotteryState', stop_data);
            }
        }

        onMounted(() => {
            localStorage.clear();
            // /auth/getToken {user_id:10086}
            // /getLuckyer
            // /initLuckyer
            // /addLuckyer {luckyerlist: "1,2,3,4"}
            let token_param = {
                "user_id": 10086
            };
            GHttp.post('/auth/getToken', token_param).then((res: resData) => {
                // console.log(res)
            })
        })

        function setLocalStorage(method: string, data: any){
            let data_str = JSON.stringify(data);
            localStorage.setItem(method, data_str);
        }

        // 清空
        function clearAll(){
            GHttp.get('/initLuckyer').then((res: resData) => {
       
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值