ZUCC_移动应用交互设计VUE3.0_LAB5影院选座

7 篇文章 0 订阅

功能展示:

1. 默认界面

   2.场次的下拉表单

3.放映影厅的下拉表单

4.选择座位的功能

 5.最多选择十个座位,座位的盒子用flex布局

.box{
        display: flex;
        width: 465px;
        flex-flow: wrap;
    
    }

 6.取消座位

 7.切换场次,显示不同的座位表

 8.切换影厅,显示不同的座位表

9.包场按钮,只有全场都是空座的时候才能选择

10.点击包场按钮 

 实现思路:

如何实现两个下拉表单的改变从而改变座位表:

// 下拉表单设置一个点击事件 改变便利的数组下标 数组下标可以放在data里

//n表示第n天,m是第m厅
    n:1,
    m:1,
seat:[
        [//第一天
            [//一号厅
                0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,2,2,0,0,0,0,
            0,0,0,2,2,0,2,2,0,0,
            -1,0,0,0,0,0,0,0,0,-1,
            -1,-1,0,0,0,0,0,0,-1,-1,
            ],
            [//二号厅
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,2,2,0,0,0,0,
            0,0,0,2,2,0,2,2,0,0,
            -1,0,0,0,0,0,0,0,0,-1,
            -1,-1,0,0,0,0,0,0,-1,-1,
            ]
        ],
        [//第二天
             [//一号厅
                0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,2,2,0,0,0,0,
            0,0,0,2,2,0,2,2,0,0,
            -1,0,0,0,0,0,0,0,0,-1,
            -1,-1,0,0,0,0,0,0,-1,-1,
            ],
            [//二号厅
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,2,2,0,0,0,0,
            0,0,0,2,2,0,2,2,0,0,
            -1,0,0,0,0,0,0,0,0,-1,
            -1,-1,0,0,0,0,0,0,-1,-1,
            ]
        ]
    ]
    
    time:["2020.5.18","2020.5.19","2020.5.20"]
    room:["一号影厅","二号影厅"]
//seat[第n天][第m厅][座位号]

首先用一个三维数组表示不同的场次,影厅,座位 

用n代表场次的下标,m是代表影厅的下表,那么调用不同的座位表就是seat[n][m],选择不同的作为就是seat[n][m][index](n和m是响应式变量,要传到html中进行控制)

然后如何将下拉表单的改变同步座位表的改变呢?首先我想到把select->option中加一个@click的事件,后来发现,option没有点击事件,所以不行,但是section有一个change事件,只要value改变就会触发,所以再声明两个变量timeString和roomString,使用v-model和select绑定,目的是为了选择不同的下拉选项从而改变seat[n][m]的n和m从而该表座位表

        <p>放映影厅:
                <select v-model="roomString" @change="changeM()">
                  <option v-for = "(roomItem,roomIndex) in filmInfo.room"  >{{roomItem}}                    
                  </option>
               </select>
        </p>

如果选择不同的下拉表单,roomString改变,因为改变,出发change事件,再将room数组里存储的信息和roomString比对,从而获得改变之后的下标,再赋值给m。

const changeM = ()=>{            
            state.filmInfo.room.forEach((item,index)=>{
                if(state.roomString === item){
                    state.m = index;
                }
            })

 这里会产生一些问题,比如在第一场选择后座位,切换到第二场选择座位,回来再看第一场发现,那些座位还是被选中的状态,这是不希望出现的,所以需要每次切换影厅或者场次的时候进行初始化操作,把所有被选中的取消。
 

const initSeat = ()=>{
            for(let i = 0;i<state.seat[state.n][state.m].length;i++){
                if(state.seat[state.n][state.m][i]==1)
                    state.seat[state.n][state.m][i]=0;
            }
        }

如何实现包场按钮

        包场按钮如果只是点击之后全选座位的话比较好实现,但是因为增添了要只有空座才能点击,并且要在座位的盒子里添加”包场“所以需要很多初始化的操作。
        包场的具体业务逻辑就是,先检测座位表内可以选择座位的个数,如果等于座位的总数(seat[n][m].length)那么包场按钮的disabled就是false
        需要一个函数判断是否可以包场:

const ifFlag = ()=>{
            state.counter=0;
            for(let i = 0;i<state.seat[state.n][state.m].length;i++){
                if(state.seat[state.n][state.m][i]===0)
                    state.counter++;
            }
            if(state.counter==state.seat[state.n][state.m].length){
                state.btnFlag = false;
            }
            else {
                state.btnFlag = true;
            }
        }//判断能不能包场

        包场按钮的点击事件:

const choseAll = (()=>{
            for(let i = 0;i<state.seat[state.n][state.m].length;i++){
                if(state.seat[state.n][state.m][i]==1||state.seat[state.n][state.m][i]==0)
                    state.seat[state.n][state.m][i]=state.seat[state.n][state.m][i]==1?0:1;
            }
            if(state.flag==1){
                state.curSeat.push("包场");
                state.flag=0;
                state.count = 110;
                totalPrice = 110*38;
            }
            else {
                state.curSeat = [];
                state.flag=1;
                state.count = 0;
                totalPrice = 0;
            }
            
        })

但其实包场按钮还是有一些bug的,还需要完善

总体的代码

<template>
  <div class="film">
      <div class="filmLeft">
          <h3>屏幕</h3>
          <ul>
              <li v-for="(item,index) in seat[n][m]"  class = "seat" 
              :class ="{'noSeat':seat[n][m][index]==-1,
              'seatSpace':seat[n][m][index]==0,
              'seatActive':seat[n][m][index]==1,
              'seatNoUse':seat[n][m][index]==2}"
              @click = "choseSeat(index)">
              </li>
          </ul> 
          <button :disabled = "btnFlag" @click = "choseAll" >包场</button> 
      </div>
      <div class="filmRight">
          <div class="rightTop">
              <div class="rightTopLeft">
                  <a href="#">
                      <img :src="filmInfo.filmImg" width = "200" height="200" >
                    </a>
            </div>
            <div div class="rightTopRight">
              <p>影片中文名:<strong>{{filmInfo.name}}</strong></p>
              <p>影片英文名:{{filmInfo.nameEnglish}}</p>
              <p>影片类型:{{filmInfo.storyType}}</p>
              <p>版本:{{filmInfo.copyRight}}</p>
              <p>{{filmInfo.place}}/{{filmInfo.timeLength}}</p>
              <p>{{filmInfo.timeShow}}</p>
            </div>
          </div>
          <div class="rightBottom">
          <p>电影院:{{filmInfo.cinema}}</p>
          <p>场次:  
              <select v-model="timeString" @change="changeN()">
                  <option v-for = "(timeItem,timeIndex) in filmInfo.time"  >{{timeItem}}</option>
               </select>
          </p>
          <p>放映影厅:
              <select v-model="roomString" @change="changeM()">
                  <option v-for = "(roomItem,roomIndex) in filmInfo.room"  >{{roomItem}}</option>
               </select>
          </p>
          <p>座位:
              <div class="box">
                  <span class="smSeat"  v-for="item in curSeat">{{item}}</span>
              </div>
          </p>
          <p>已选择<strong style="color:red;">{{count}}</strong>个座位,
            <strong style="color:red;">再次点击座位可取消
                <span v-show="maxFlag">你最多选择十个座位</span>
            </strong>
          </p>
          <hr>
          <p>单价:<strong>{{filmInfo.price}}</strong></p>
          <p>总价:<strong>{{totalPrice}}</strong></p>
        </div>
      </div>
  </div>
</template>

<script>
import { reactive, toRefs, computed ,watch,onMounted} from "vue";
export default {
    setup(){
        const state  = new reactive({
            count:0,  //选择座位的数量
            counter:0,//可选座位
            maxFlag:false,
            btnFlag:true,
            flag : 1,
            n:0,
            m:0,
            timeString:"2020.5.18",
            roomString:"一号影厅",
            filmInfo: {
                name:"囧妈",
                nameEnglish: "Lost in Russia",
                copyRight:'中文2D',
                filmImg:require("@/assets/film.jpg"),
                storyType:'喜剧',
                place:"中国内地", 
                timeLength:"126分钟",
                timeShow:"2020-2-2",
                cinema:"万达影城",
                // room:["一号影厅","二号影厅","三号影厅","四号影厅"]
                price:38,
                room:["一号影厅","二号影厅","三号影厅"],
                // time:[],
                time:["2020.5.18","2020.5.19","2020.5.20"]
            },
            seatIndex:[],//按顺序存放座位的在seatFlag的下标
            curSeat:[],//存放对应的座位号 是字符串
            seat:[
                    [//第一天
                        [//一号厅
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,0,0,0,0,0,
                            0,0,0,0,2,0,0,0,0,0,
                            0,0,0,0,2,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                        [//二号厅
                        -1,-1,-1,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,0,0,0,0,0,0,
                        0,0,0,0,2,2,0,0,0,0,
                        0,0,0,2,2,0,2,2,0,0,
                        -1,0,0,0,0,0,0,0,0,-1,
                        -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                        [//三号厅
                            0,0,0,0,0,0,0,0,0,-1,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,2,2,0,0,0,0,0,0,
                            0,0,2,2,2,2,2,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                    ],
                    [//第二天
                        [//一号厅
                            -1,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,2,2,0,0,0,0,0,0,
                            0,0,2,2,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                        [//二号厅
                            2,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,2,2,2,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,2,0,0,
                            0,0,0,0,0,0,0,2,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                        [//三号厅
                            2,2,0,0,0,0,0,0,0,-1,
                            2,2,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,2,2,0,0,0,0,0,0,
                            0,0,2,2,2,2,2,0,0,0,
                            0,0,0,0,0,2,0,0,0,0,
                            0,0,0,0,0,2,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                    ],
                    [//第三天
                        [//一号厅
                            -1,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                        [//二号厅
                            2,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,2,2,0,
                            0,0,0,0,0,0,2,2,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,2,2,0,0,0,0,
                            0,0,0,2,2,0,2,2,0,0,
                            -1,0,0,0,0,0,0,0,0,-1,
                            -1,-1,0,0,0,0,0,0,-1,-1,
                        ],
                        [//三号厅
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,
                        ],
                    ]
                ]
           
        })
        const ifFlag = ()=>{
            state.counter=0;
            for(let i = 0;i<state.seat[state.n][state.m].length;i++){
                if(state.seat[state.n][state.m][i]===0)
                    state.counter++;
            }
            if(state.counter==state.seat[state.n][state.m].length){
                state.btnFlag = false;
            }
            else {
                state.btnFlag = true;
            }
        }//判断能不能包场

        const initSeat = ()=>{
            for(let i = 0;i<state.seat[state.n][state.m].length;i++){
                if(state.seat[state.n][state.m][i]==1)
                    state.seat[state.n][state.m][i]=0;
            }
        }

        const choseSeat = (index)=>{
            // console.log(state.curSeat);
            // console.log(`选择了${state.count}个座位`);
            if(state.seat[state.n][state.m][index]===1){
                state.seat[state.n][state.m][index] = 0;
                state.seatIndex.splice(state.seatIndex.findIndex((item)=>item==index),1);//把当前座位删掉
            }
            else{ 
                if(state.seat[state.n][state.m][index]===0&&state.count<10){
                    state.seat[state.n][state.m][index] =1;
                    state.seatIndex.push(index);
                }
            }
             state.curSeat = []
                for(let data of state.seatIndex){
                    state.curSeat.push((Math.floor(data/10)+1)+'行'+(data%10+1)+'列');
                }
            //计算当前选择了多少个座位
            state.count = state.seatIndex.length;
            if(state.count>=10){
                state.maxFlag = true;
            }
            else {
                state.maxFlag = false;
            }
            ifFlag();
        }

        const choseAll = (()=>{
            for(let i = 0;i<state.seat[state.n][state.m].length;i++){
                if(state.seat[state.n][state.m][i]==1||state.seat[state.n][state.m][i]==0)
                    state.seat[state.n][state.m][i]=state.seat[state.n][state.m][i]==1?0:1;
            }
            if(state.flag==1){
                state.curSeat.push("包场");
                state.flag=0;
                state.count = 110;
                totalPrice = 110*38;
            }
            else {
                state.curSeat = [];
                state.flag=1;
                state.count = 0;
                totalPrice = 0;
            }
            
        })
        
        const changeN = ()=>{
            state.count=0;
            state.seatIndex = [];
            state.curSeat = [];
            console.log(state.roomString);
            state.filmInfo.time.forEach((item,index)=>{
                if(state.timeString == item){
                    state.n = index;
                }
            })
            initSeat();//更换场次就把之前选择的座位复原,不能用数组遍历方法,因为遍历方法不能改变数组的值
            ifFlag();
            console.log(state.counter,state.seat[state.n][state.m].length)
        }

        const changeM = ()=>{
            state.count=0;
            state.seatIndex = [];
             state.curSeat = [];
            // console.log(state.roomString);
            state.filmInfo.room.forEach((item,index)=>{
                if(state.roomString === item){
                    state.m = index;
                }
            })
            initSeat();
            ifFlag();
            console.log(state.counter,state.seat[state.n][state.m].length)
        }

        let totalPrice = computed(()=>{
            
            let total = 0;
            total = state.count*state.filmInfo.price;
            return total
            
        })
        return { 
            ...toRefs(state),
            choseSeat,
            choseAll,
            changeN,
            changeM,
            totalPrice

        }

    }
}
</script>

<style>
    .film{
        margin: 0 auto;
        width: 1050px;
        height: 550px;
        border: 1px solid black;
    }
    .film h3{
        text-align: center;
    }
    .filmLeft ul{
        list-style: none;
    }
    .seat{
        float:left;
        width: 30px;
        height: 30px;
        margin:5px 10px;
        cursor:pointer;
    }
    .noSeat{
        background: url("../assets/空座位.png") no-repeat center center; 
        /* background-color: aquamarine; */
        background-size: contain;
    }
    .seatSpace{
        background: url("../assets/可选座位.png") no-repeat ;
        background-size: contain;
        /* background-color: pink; */
    }  
    .seatActive{
        background: url("../assets/选中座位.png") no-repeat ;
        background-size: contain;
        /* background-color: black; */
    }
    .seatNoUse{
        background: url("../assets/售出座位 .png") center center;
        background-size: contain;
        /* background-color: green; */
    }
    .filmLeft{
        width: 550px;
        height: 500px;
        float: left;
    }
    .filmRight{
        width: 500px;
        height: 550px;
        float: left;
        background-color: bisque;
    }
    .rightTopLeft{
        float: left;
        margin: 20px 15px 5px 10px;
    }
    .rightTopRight{
        float: left;
        margin: 0px 0px 5px 5px ;
    }
    .rightBottom{
        clear:both;
        margin: 0px 10px;
        
    }
    .box{
        display: flex;
        width: 465px;
        flex-flow: wrap;
    
    }
    .smSeat{
        margin-right: 5px;
        border: 1px solid black;

    }

</style>

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值