|
@@ -0,0 +1,741 @@
|
|
|
+<template>
|
|
|
+ <view class="sel-seat" :style="{height}">
|
|
|
+ <!-- top -->
|
|
|
+ <view class="seat-head">
|
|
|
+ <text class="sh-title">{{ title }}</text>
|
|
|
+ <text class="sh-info">{{ info }}</text>
|
|
|
+ </view>
|
|
|
+ <!-- main -->
|
|
|
+ <view class="seat-main">
|
|
|
+ <movable-area class="vm-area">
|
|
|
+ <movable-view :style="'width: 750rpx;height:'+(seatRow*40+350)+'rpx;'" :inertia="true" :scale="true" :scale-min="0.95"
|
|
|
+ :scale-max="2" direction="all" @change="onMove" @scale="onScale">
|
|
|
+ <view class="sm-title">
|
|
|
+ <text class="text">{{ roomName }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="sm-screen">
|
|
|
+ <text class="text">银幕中央</text>
|
|
|
+ </view>
|
|
|
+ <view class="sm-line-center"></view>
|
|
|
+ <!-- seat content -->
|
|
|
+ <view v-for="(item,index) in seatArray" :key="index"
|
|
|
+ class="sm-cell" :style="'width:'+boxWidth+'px;height:'+seatSize+'px'">
|
|
|
+ <view v-for="(seat,col) in item" :key="col" class="dp-ib" :style="'width:'+seatSize+'px;height:'+seatSize+'px'"
|
|
|
+ @click="handleChooseSeat(index,col)">
|
|
|
+ <!-- // 情侣左座 -->
|
|
|
+ <template v-if="seat.flag === 1">
|
|
|
+ <image v-if="seat.type===0" class="sm-icon" src="/uni_modules/anil-seat/static/unselected-l.png" mode="aspectFit"></image>
|
|
|
+ <image v-else-if="seat.type===1" class="sm-icon" src="/uni_modules/anil-seat/static/selected-l.png" mode="aspectFit"></image>
|
|
|
+ <image v-else-if="seat.type===2" class="sm-icon" src="/uni_modules/anil-seat/static/bought.png" mode="aspectFit"></image>
|
|
|
+ </template>
|
|
|
+ <!-- // 情侣右座 -->
|
|
|
+ <template v-else-if="seat.flag === 2">
|
|
|
+ <image v-if="seat.type===0" class="sm-icon" src="/uni_modules/anil-seat/static/unselected-r.png" mode="aspectFit"></image>
|
|
|
+ <image v-else-if="seat.type===1" class="sm-icon" src="/uni_modules/anil-seat/static/selected-r.png" mode="aspectFit"></image>
|
|
|
+ <image v-else-if="seat.type===2" class="sm-icon" src="/uni_modules/anil-seat/static/bought.png" mode="aspectFit"></image>
|
|
|
+ </template>
|
|
|
+ <!-- // 普通座位 其他座位 -->
|
|
|
+ <template v-else>
|
|
|
+ <image v-if="seat.type===0" class="sm-icon" src="/uni_modules/anil-seat/static/unselected.png" mode="aspectFit"></image>
|
|
|
+ <image v-else-if="seat.type===1" class="sm-icon" src="/uni_modules/anil-seat/static/selected.png" mode="aspectFit"></image>
|
|
|
+ <image v-else-if="seat.type===2" class="sm-icon" src="/uni_modules/anil-seat/static/bought.png" mode="aspectFit"></image>
|
|
|
+ </template>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="sm-line-index" :style="'left: '+(10-moveX/scale)+'px;'">
|
|
|
+ <text class="text" :style="'height:'+seatSize+'px;'" v-for="(m,mindex) in mArr"
|
|
|
+ :key="mindex">{{m}}</text>
|
|
|
+ </view>
|
|
|
+ </movable-view>
|
|
|
+ </movable-area>
|
|
|
+ <view class="fix-tips">
|
|
|
+ <view class="v-tips">
|
|
|
+ <image :style="'width:'+seatSize+'px;height:'+seatSize+'px'" src="/uni_modules/anil-seat/static/unselected.png" mode="aspectFit"></image>
|
|
|
+ <text class="text">可选</text>
|
|
|
+ </view>
|
|
|
+ <view class="v-tips">
|
|
|
+ <image :style="'width:'+seatSize+'px;height:'+seatSize+'px'" src="/uni_modules/anil-seat/static/bought.png" mode="aspectFit"></image>
|
|
|
+ <text class="text">不可选</text>
|
|
|
+ </view>
|
|
|
+ <view class="v-tips">
|
|
|
+ <image :style="'width:'+seatSize+'px;height:'+seatSize+'px'" src="/uni_modules/anil-seat/static/selected.png" mode="aspectFit"></image>
|
|
|
+ <text class="text">选中</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <!-- foot -->
|
|
|
+ <view class="seat-foot">
|
|
|
+ <view class="sf-recommend" v-if="SelectNum === 0">
|
|
|
+ <text class="text">推荐选座</text>
|
|
|
+ <view class="sfr-tag" v-for="num in Math.min(max, 6)" :key="num"
|
|
|
+ @click="smartChoose(num+1)">
|
|
|
+ <text class="text">{{ num+1 }}人</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="sf-arselect" v-else>
|
|
|
+ <text class="text">已选</text>
|
|
|
+ <scroll-view scroll-x="true">
|
|
|
+ <view class="scr-wrap">
|
|
|
+ <view class="sfr-selt" v-for="(optItem,optindex) in optArr" :key="optItem.SeatCode"
|
|
|
+ @click="handleChooseSeat(optItem.rowIndex, optItem.colIndex)">
|
|
|
+ <!-- <image src="static/close.png" class="sfr-close"></image> -->
|
|
|
+ <text class="text">{{ optItem.SeatName }}</text>
|
|
|
+ <text class="price">¥{{ optItem.Price || '' }}</text>
|
|
|
+ <view class="sfr-close">X</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+ <view class="f-btn" :class="{disabled: SelectNum === 0 }" @click="buySeat">
|
|
|
+ <text class="text">{{SelectNum === 0 ? '请选座位' : `¥ ${aPrice} 确认座位`}}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ export default {
|
|
|
+ name:"anil-seat",
|
|
|
+ props: {
|
|
|
+ seatData: {
|
|
|
+ type: Array
|
|
|
+ },
|
|
|
+ max: {
|
|
|
+ type: Number,
|
|
|
+ default: 4
|
|
|
+ },
|
|
|
+ title: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ info: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ roomName: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ height: {
|
|
|
+ type: String,
|
|
|
+ // #ifndef MP-WEIXIN
|
|
|
+ default: 'calc(100vh - 44px)',
|
|
|
+ // #endif
|
|
|
+ // #ifdef MP-WEIXIN
|
|
|
+ default: '100vh',
|
|
|
+ // #endif
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ scaleMin:1,//h5端为解决1无法缩小问题,设为0.95
|
|
|
+ boxWidth: 400, //屏幕宽度px
|
|
|
+ space: ' ', //空格
|
|
|
+ seatArray: [], //影院座位的二维数组,-1为非座位,0为未购座位,1为已选座位(绿色),2为已购座位(红色),一维行,二维列
|
|
|
+ seatRow: 0, //影院座位行数
|
|
|
+ seatCol: 0, //影院座位列数
|
|
|
+ seatSize: 0, //座位尺寸
|
|
|
+ SelectNum: 0, //选择座位数
|
|
|
+ moveX: 0, //水平移动偏移量
|
|
|
+ scale: 1, //放大倍数
|
|
|
+ minRow: 0, //从第几行开始排座位
|
|
|
+ minCol: 0, //从第几列开始排座位
|
|
|
+ showTis: true, //显示选座提示
|
|
|
+ seatList: [], //接口获取的原始位置
|
|
|
+ mArr: [], //排数提示
|
|
|
+ optArr: [], //选中的座位数组。
|
|
|
+ isWXAPP:false,
|
|
|
+ areaHeight: 0
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ aPrice() {
|
|
|
+ let totalAmount = ''
|
|
|
+ if (this.optArr && this.optArr.length) {
|
|
|
+ totalAmount = this.optArr.map(item => Number(item.Price)).reduce((prev, curr) => prev + curr)
|
|
|
+ }
|
|
|
+ return Number(totalAmount).toFixed(2)
|
|
|
+ },
|
|
|
+ rpxNum() {
|
|
|
+ return this.boxWidth / 750
|
|
|
+ },
|
|
|
+ pxNum() {
|
|
|
+ return 750 / this.boxWidth
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ //获取宽度
|
|
|
+ uni.getSystemInfo({
|
|
|
+ success: (e) => {
|
|
|
+ this.boxWidth = e.screenWidth
|
|
|
+ //#ifdef H5
|
|
|
+ this.scaleMin = 0.95
|
|
|
+ //#endif
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // this.initData()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ initData: function(data) {
|
|
|
+ let arr = data || this.seatData
|
|
|
+ //假数据说明:SeatCode座位编号,RowNum-行号,ColumnNum-纵号,YCoord-Y坐标,XCoord-X坐标,Status-状态
|
|
|
+ let row = 0
|
|
|
+ let col = 0
|
|
|
+ let minCol = parseInt(arr[0].XCoord)
|
|
|
+ let minRow = parseInt(arr[0].YCoord)
|
|
|
+ for (let i of arr) {
|
|
|
+ minRow = parseInt(i.YCoord) < minRow ? parseInt(i.YCoord) : minRow
|
|
|
+ minCol = parseInt(i.XCoord) < minCol ? parseInt(i.XCoord) : minCol
|
|
|
+ row = parseInt(i.YCoord) > row ? parseInt(i.YCoord) : row
|
|
|
+ col = parseInt(i.XCoord) > col ? parseInt(i.XCoord) : col
|
|
|
+ }
|
|
|
+ this.seatList = arr
|
|
|
+ this.seatRow = row - minRow + 1
|
|
|
+ this.seatCol = col - minCol + 3
|
|
|
+ this.minRow = minRow
|
|
|
+ this.minCol = minCol - 1
|
|
|
+ this.initSeatArray()
|
|
|
+ },
|
|
|
+ //初始座位数组
|
|
|
+ initSeatArray: function() {
|
|
|
+ let seatArray = Array(this.seatRow).fill(0).map(() => Array(this.seatCol).fill({
|
|
|
+ type: -1,
|
|
|
+ SeatCode: '',
|
|
|
+ RowNum: '',
|
|
|
+ ColumnNum: ''
|
|
|
+ }));
|
|
|
+ this.seatArray = seatArray
|
|
|
+ this.seatSize = this.boxWidth > 0 ?
|
|
|
+ parseInt(parseInt(this.boxWidth, 10) / (this.seatCol + 1), 10) :
|
|
|
+ parseInt(parseInt(414, 10) / (this.seatCol + 1), 10)
|
|
|
+ this.initNonSeatPlace();
|
|
|
+ },
|
|
|
+ //初始化是座位的地方
|
|
|
+ initNonSeatPlace: function() {
|
|
|
+ let seat = this.seatList.slice()
|
|
|
+ let arr = this.seatArray.slice()
|
|
|
+ for (let num in seat) {
|
|
|
+ let status = 2 //-1为非座位,0为未购座位,1为已选座位(绿色),2为已购座位(红色)
|
|
|
+ switch (seat[num].Status) {
|
|
|
+ case -2:
|
|
|
+ status = 2
|
|
|
+ break;
|
|
|
+ case -1:
|
|
|
+ status = -1
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ status = 2
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ status = 0
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // if (seat[num].Status === 1) {
|
|
|
+ // status = 0
|
|
|
+ // } else if (seat[num].Status === -1) {
|
|
|
+ // status = -1
|
|
|
+ // }
|
|
|
+ arr[parseInt(seat[num].YCoord) - this.minRow][parseInt(seat[num].XCoord) - this.minCol] = {
|
|
|
+ type: status,
|
|
|
+ SeatCode: seat[num].SeatCode,
|
|
|
+ RowNum: seat[num].RowNum,
|
|
|
+ ColumnNum: seat[num].ColumnNum,
|
|
|
+ Price: seat[num].Price,
|
|
|
+ SeatName: seat[num].SeatName,
|
|
|
+ flag: seat[num].flag,
|
|
|
+ area: seat[num].area
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.seatArray = arr.slice()
|
|
|
+ let mArr = []
|
|
|
+ for (let i in arr) {
|
|
|
+ let m = ''
|
|
|
+ for (let n of arr[i]) {
|
|
|
+ if (n.SeatCode) {
|
|
|
+ m = n.RowNum
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (m) {
|
|
|
+ mArr.push(m)
|
|
|
+ } else {
|
|
|
+ mArr.push('')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.mArr = mArr
|
|
|
+ },
|
|
|
+ //放大缩小事件
|
|
|
+ onScale: function(e) {
|
|
|
+ this.showTis = false
|
|
|
+ // this.moveX=-e.detail.x
|
|
|
+ let w = this.boxWidth * 0.5
|
|
|
+ let s = 1 - e.detail.scale
|
|
|
+ this.moveX = w * s
|
|
|
+ this.scale = e.detail.scale
|
|
|
+ if (s > 0 || s === 0) {
|
|
|
+ this.showTis = true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //移动事件
|
|
|
+ onMove: function(e) {
|
|
|
+ this.showTis = false
|
|
|
+ this.moveX = e.detail.x
|
|
|
+ },
|
|
|
+ //重置座位
|
|
|
+ resetSeat: function() {
|
|
|
+ this.SelectNum = 0
|
|
|
+ this.optArr = []
|
|
|
+ //将所有已选座位的值变为0
|
|
|
+ let oldArray = this.seatArray.slice();
|
|
|
+ for (let i = 0; i < this.seatRow; i++) {
|
|
|
+ for (let j = 0; j < this.seatCol; j++) {
|
|
|
+ if (oldArray[i][j].type === 1) {
|
|
|
+ oldArray[i][j].type = 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.seatArray = oldArray;
|
|
|
+ },
|
|
|
+ //选定且购买座位
|
|
|
+ buySeat: function() {
|
|
|
+ if (this.SelectNum === 0) return;
|
|
|
+ // let oldArray = [];
|
|
|
+ // for (let i = 0; i < this.seatRow; i++) {
|
|
|
+ // for (let j = 0; j < this.seatCol; j++) {
|
|
|
+ // if (this.seatArray[i][j].type === 1) {
|
|
|
+ // oldArray.push(this.seatArray[i][j])
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ this.$emit('confirm', this.optArr)
|
|
|
+ },
|
|
|
+ //处理座位选择逻辑
|
|
|
+ handleChooseSeat: function(row, col, isbreak) {
|
|
|
+ let newArray = this.seatArray;
|
|
|
+ let seatValue = newArray[row][col].type;
|
|
|
+ let flag = newArray[row][col].flag
|
|
|
+ //如果是已购座位,直接返回
|
|
|
+ if (seatValue === 2 || seatValue === -1) return
|
|
|
+ //如果是已选座位点击后变未选
|
|
|
+ if (seatValue === 1) {
|
|
|
+ newArray[row][col].type = 0
|
|
|
+ this.SelectNum--
|
|
|
+ this.getOptArr(newArray[row][col], 0)
|
|
|
+ } else if (seatValue === 0) {
|
|
|
+ if (this.SelectNum >= this.max) {
|
|
|
+ return uni.showToast({
|
|
|
+ title: '一次最多选择' + this.max + '张',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ newArray[row][col].rowIndex = row
|
|
|
+ newArray[row][col].colIndex = col
|
|
|
+ newArray[row][col].type = 1
|
|
|
+ this.SelectNum++
|
|
|
+ this.getOptArr(newArray[row][col], 1)
|
|
|
+ }
|
|
|
+ switch (flag) {
|
|
|
+ case 1: // 情侣左座
|
|
|
+ !isbreak && this.handleChooseSeat(row, col+1, true)
|
|
|
+ break;
|
|
|
+ case 2: // 情侣右座
|
|
|
+ !isbreak && this.handleChooseSeat(row, col-1, true)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ //必须整体更新二维数组,Vue无法检测到数组某一项更新,必须slice复制一个数组才行
|
|
|
+ // this.seatArray = newArray.slice();
|
|
|
+ // this.$forceUpdate()
|
|
|
+ },
|
|
|
+ //处理已选座位数组
|
|
|
+ getOptArr: function(item, type) {
|
|
|
+ let optArr = this.optArr
|
|
|
+ if (type === 1) {
|
|
|
+ optArr.push(item)
|
|
|
+ } else if (type === 0) {
|
|
|
+ let arr = []
|
|
|
+ optArr.forEach(v => {
|
|
|
+ if (v.SeatCode !== item.SeatCode) {
|
|
|
+ arr.push(v)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ optArr = arr
|
|
|
+ }
|
|
|
+ this.optArr = optArr.slice()
|
|
|
+ },
|
|
|
+ //推荐选座,参数是推荐座位数目,
|
|
|
+ smartChoose: function(num) {
|
|
|
+ // console.log('num===', num)
|
|
|
+ // 先重置
|
|
|
+ this.resetSeat()
|
|
|
+ //找到影院座位水平垂直中间位置的后一排
|
|
|
+ let rowStart = parseInt((this.seatRow - 1) / 2, 10) + 1;
|
|
|
+ //先从中间排往后排搜索
|
|
|
+ let backResult = this.searchSeatByDirection(rowStart, this.seatRow - 1, num);
|
|
|
+ if (backResult.length > 0) {
|
|
|
+ this.chooseSeat(backResult);
|
|
|
+ this.SelectNum += num
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //再从中间排往前排搜索
|
|
|
+ let forwardResult = this.searchSeatByDirection(rowStart - 1, 0, num);
|
|
|
+ if (forwardResult.length > 0) {
|
|
|
+ this.chooseSeat(forwardResult);
|
|
|
+ this.SelectNum += num
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //提示用户无合法位置可选
|
|
|
+ uni.showToast({
|
|
|
+ title: '无合法位置可选!',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ //搜索函数,参数:fromRow起始行,toRow终止行,num推荐座位数
|
|
|
+ searchSeatByDirection: function(fromRow, toRow, num) {
|
|
|
+ /*
|
|
|
+ * 推荐座位规则
|
|
|
+ * (1)初始状态从座位行数的一半处的后一排的中间开始向左右分别搜索,取离中间最近的,如果满足条件,
|
|
|
+ * 记录下该结果离座位中轴线的距离,后排搜索完成后取距离最小的那个结果座位最终结果,优先向后排进行搜索,
|
|
|
+ * 后排都没有才往前排搜,前排逻辑同上
|
|
|
+ *
|
|
|
+ * (2)只考虑并排且连续的座位,不能不在一排或者一排中间有分隔
|
|
|
+ *
|
|
|
+ * */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 保存当前方向搜索结果的数组,元素是对象,result是结果数组,offset代表与中轴线的偏移距离
|
|
|
+ * {
|
|
|
+ * result:Array([x,y])
|
|
|
+ * offset:Number
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ */
|
|
|
+ let currentDirectionSearchResult = [];
|
|
|
+
|
|
|
+ let largeRow = fromRow > toRow ? fromRow : toRow,
|
|
|
+ smallRow = fromRow > toRow ? toRow : fromRow;
|
|
|
+
|
|
|
+ for (let i = smallRow; i <= largeRow; i++) {
|
|
|
+ //每一排的搜索,找出该排里中轴线最近的一组座位
|
|
|
+ let tempRowResult = [],
|
|
|
+ minDistanceToMidLine = Infinity;
|
|
|
+ try{
|
|
|
+ for (let j = 0; j <= this.seatCol - num; j++) {
|
|
|
+ //如果有合法位置
|
|
|
+ if (this.checkRowSeatContinusAndEmpty(i, j, j + num - 1, num)) {
|
|
|
+ //计算该组位置距离中轴线的距离:该组位置的中间位置到中轴线的距离
|
|
|
+ let resultMidPos = parseInt((j + num / 2), 10);
|
|
|
+ let distance = Math.abs(parseInt(this.seatCol / 2) - resultMidPos);
|
|
|
+ //如果距离较短则更新
|
|
|
+ if (distance < minDistanceToMidLine) {
|
|
|
+ minDistanceToMidLine = distance;
|
|
|
+ //该行的最终结果
|
|
|
+ tempRowResult = this.generateRowResult(i, j, j + num - 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch(e){
|
|
|
+ //TODO handle the exception
|
|
|
+ uni.showToast({
|
|
|
+ title: '暂无推荐选座',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ //保存该行的最终结果
|
|
|
+ currentDirectionSearchResult.push({
|
|
|
+ result: tempRowResult,
|
|
|
+ offset: minDistanceToMidLine
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ //处理后排的搜索结果:找到距离中轴线最短的一个
|
|
|
+ //注意这里的逻辑需要区分前后排,对于后排是从前往后,前排则是从后往前找
|
|
|
+ let isBackDir = fromRow < toRow;
|
|
|
+ let finalReuslt = [],
|
|
|
+ minDistanceToMid = Infinity;
|
|
|
+ if (isBackDir) {
|
|
|
+ //后排情况,从前往后
|
|
|
+ currentDirectionSearchResult.forEach((item) => {
|
|
|
+ if (item.offset < minDistanceToMid) {
|
|
|
+ finalReuslt = item.result;
|
|
|
+ minDistanceToMid = item.offset;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ //前排情况,从后往前找
|
|
|
+ currentDirectionSearchResult.reverse().forEach((item) => {
|
|
|
+ if (item.offset < minDistanceToMid) {
|
|
|
+ finalReuslt = item.result;
|
|
|
+ minDistanceToMid = item.offset;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ //直接返回结果
|
|
|
+ return finalReuslt
|
|
|
+ },
|
|
|
+
|
|
|
+ /*辅助函数,判断每一行座位从i列到j列是否全部空余且连续
|
|
|
+ *
|
|
|
+ */
|
|
|
+ checkRowSeatContinusAndEmpty: function(rowNum, startPos, endPos, num) {
|
|
|
+ let isValid = true;
|
|
|
+ for (let i = startPos; i <= endPos; i++) {
|
|
|
+ if (this.seatArray[rowNum][i].type !== 0) {
|
|
|
+ isValid = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 忽略情侣座
|
|
|
+ if ([1, 2].includes(this.seatArray[rowNum][i].flag)) {
|
|
|
+ isValid = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return isValid
|
|
|
+ },
|
|
|
+ //辅助函数:返回每一行的某个合理位置的座位数组
|
|
|
+ generateRowResult: function(row, startPos, endPos) {
|
|
|
+ let result = [];
|
|
|
+ for (let i = startPos; i <= endPos; i++) {
|
|
|
+ result.push([row, i])
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ },
|
|
|
+ //辅助函数:智能推荐的选座操作
|
|
|
+ chooseSeat: function(result) {
|
|
|
+ let opt = this.optArr
|
|
|
+ let oldArray = this.seatArray.slice();
|
|
|
+ for (let i = 0; i < result.length; i++) {
|
|
|
+ //选定座位
|
|
|
+ oldArray[result[i][0]][result[i][1]].rowIndex = result[i][0]
|
|
|
+ oldArray[result[i][0]][result[i][1]].colIndex = result[i][1]
|
|
|
+ oldArray[result[i][0]][result[i][1]].type = 1
|
|
|
+ this.optArr.push(oldArray[result[i][0]][result[i][1]])
|
|
|
+ }
|
|
|
+ this.seatArray = oldArray;
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.sel-seat {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 100%;
|
|
|
+ height: 100vh;
|
|
|
+ .seat-head {
|
|
|
+ background-color: #ffffff;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
+ position: relative;
|
|
|
+ z-index: 5;
|
|
|
+ .sh-title {
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ .sh-info {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999999;
|
|
|
+ margin-top: 10rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .seat-main {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ position: relative;
|
|
|
+ padding: 10rpx;
|
|
|
+ .vm-area {
|
|
|
+ width: 750rpx;
|
|
|
+ overflow: hidden;
|
|
|
+ height: calc(100% - 40rpx);
|
|
|
+ }
|
|
|
+ .sm-title {
|
|
|
+ background-color: #dddddd;
|
|
|
+ width: 380rpx;
|
|
|
+ height: 34rpx;
|
|
|
+ transform: perspective(34rpx) rotateX(-10deg);
|
|
|
+ margin: 0 auto;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ position: relative;
|
|
|
+ z-index: 2;
|
|
|
+ .text {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .sm-screen {
|
|
|
+ width: 100rpx;
|
|
|
+ height: 30rpx;
|
|
|
+ border: 1rpx solid #cccccc;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin: 48rpx auto 0;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ position: relative;
|
|
|
+ z-index: 1;
|
|
|
+ .text {
|
|
|
+ font-size: 20rpx;
|
|
|
+ color: #999999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .sm-line-center {
|
|
|
+ height: 610rpx;
|
|
|
+ width: 0;
|
|
|
+ border: 1rpx dashed #e5e5e5;
|
|
|
+ position: fixed;
|
|
|
+ left: 50%;
|
|
|
+ top: 0;
|
|
|
+ display: block;
|
|
|
+ z-index: 0;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ }
|
|
|
+ .fix-tips {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 24rpx;
|
|
|
+ position: fixed;
|
|
|
+ bottom: 198rpx;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ z-index: 1;
|
|
|
+ padding: 20rpx;
|
|
|
+ .v-tips {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ color: #999;
|
|
|
+ margin: 0 10rpx;
|
|
|
+ .text {
|
|
|
+ margin-left: 10rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // seat style
|
|
|
+ .sm-cell {
|
|
|
+ display: flex;
|
|
|
+ margin-top: 20rpx;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ position: relative;
|
|
|
+ z-index: 2;
|
|
|
+ .sm-icon {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .sm-line-index {
|
|
|
+ position: fixed;
|
|
|
+ top: 114rpx;
|
|
|
+ left: 20rpx;
|
|
|
+ border-radius: 14rpx;
|
|
|
+ overflow: hidden;
|
|
|
+ background-color: rgba($color: #000000, $alpha: 0.3);
|
|
|
+ z-index: 3;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding-bottom: 20rpx;
|
|
|
+ width: 30rpx;
|
|
|
+ .text {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #ffffff;
|
|
|
+ width: 100%;
|
|
|
+ text-align: center;
|
|
|
+ margin-top: 20rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .seat-foot {
|
|
|
+ margin-top: auto;
|
|
|
+ background-color: #ffffff;
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
+ position: relative;
|
|
|
+ z-index: 5;
|
|
|
+ .sf-recommend {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding-bottom: 20rpx;
|
|
|
+ .text {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666666;
|
|
|
+ }
|
|
|
+ .sfr-tag {
|
|
|
+ width: 110rpx;
|
|
|
+ height: 60rpx;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ border: 1rpx solid #ccc;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-left: 20rpx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .sf-arselect {
|
|
|
+ @extend .sf-recommend;
|
|
|
+ .text {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666666;
|
|
|
+ }
|
|
|
+ .price {
|
|
|
+ font-size: 20rpx;
|
|
|
+ color: red;
|
|
|
+ }
|
|
|
+ .scr-wrap {
|
|
|
+ display: flex;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ .sfr-selt {
|
|
|
+ min-width: 130rpx;
|
|
|
+ height: 60rpx;
|
|
|
+ border-radius: 4rpx;
|
|
|
+ border: 1rpx solid #ccc;
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ justify-content: center;
|
|
|
+ flex-direction: column;
|
|
|
+ margin-left: 20rpx;
|
|
|
+ position: relative;
|
|
|
+ margin-left: 20rpx;
|
|
|
+ padding-left: 10rpx;
|
|
|
+ .text {
|
|
|
+ font-size: 20rpx;
|
|
|
+ }
|
|
|
+ .sfr-close {
|
|
|
+ position: absolute;
|
|
|
+ right: 6rpx;
|
|
|
+ top: 10rpx;
|
|
|
+ font-size: 20rpx;
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .f-btn {
|
|
|
+ background-color: #F45664;
|
|
|
+ width: 100%;
|
|
|
+ height: 90rpx;
|
|
|
+ line-height: 90rpx;
|
|
|
+ text-align: center;
|
|
|
+ border-radius: 10rpx;
|
|
|
+ .text {
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 36rpx;
|
|
|
+ }
|
|
|
+ &.disabled {
|
|
|
+ opacity: .8;
|
|
|
+ &:active {
|
|
|
+ background-color: #F45664;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &:active {
|
|
|
+ background-color: #de4e5d;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|