seat.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. <template name="dever-seat">
  2. <view class="w-100 grace-body">
  3. <view class="bg-f1">
  4. <movable-area :style="'height:'+(seatRow*40+350)+'rpx;width: 100vw;tops:'+(rpxNum*132)+'px'" class="pt-f left-0">
  5. <movable-view :style="'width: 100vw;height:'+(seatRow*40+350)+'rpx;'" :inertia="true" :scale="true" :scale-min="0.95"
  6. :scale-max="2" direction="all" @change="onMove" @scale="onScale">
  7. <picker @change="openHall" :value="hall_index" :range="hall_data" v-if="hall_state">
  8. <view class="Stage dp-f jc-c ai-c fz-22 color-333" style="margin-top:10rpx">
  9. {{hall_data[hall_index]}}
  10. </view>
  11. </picker>
  12. <view style="height: 30rpx;margin-top: 30rpx;margin-bottom: 30rpx;" class="m-0-a mt-48 dp-f jc-c ai-c fz-22 color-999 br-5">{{item.name}}</view>
  13. <view v-for="(item,index) in seatArray" :key="index" class="dp-f jc-c mt-20" :style="'width:'+boxWidth+'px;height:'+seatSize+'px'">
  14. <view v-for="(seat,col) in item" :key="col" class="dp-ib" :style="'width:'+seatSize+'px;height:'+seatSize+'px'"
  15. @click="handleChooseSeat(index,col)">
  16. <image v-if="seat.type===0" class="w-100 h-100" src="@/static/seat/unselected.png" mode="aspectFit"></image>
  17. <image v-else-if="seat.type===1" class="w-100 h-100" src="@/static/seat/selected.png" mode="aspectFit" style="width:40rpx;height:40rpx;"></image>
  18. <image v-else-if="seat.type===2" class="w-100 h-100" :id="seat.TipsId" src="@/static/seat/bought.png" mode="aspectFit" style="width:40rpx;height:40rpx;border-radius:50%;margin-top: -1px;" :src="seat.User.avatar" @click="showTips(seat.TipsId, seat.Id, seat.Tips, seat.SeatCode, seat.User)"></image>
  19. </view>
  20. </view>
  21. <view class="pt-f bg-line br-15 over-h" :style="'left: '+(20-moveX/scale)+'px;top:112rpx;width:30rpx;'">
  22. <view class="w-100 dp-f ai-c jc-c fz-22 color-fff" :style="'height:'+seatSize+'px;margin-top:20rpx;'" v-for="(m,mindex) in mArr"
  23. :key="mindex">{{m}}</view>
  24. <view :style="'height: 20rpx;'"></view>
  25. </view>
  26. </movable-view>
  27. </movable-area>
  28. <view class="pt-f bottom-bar left-0 dp-f fd-cr z1000">
  29. <view class="bg-white p-all-32" style="width: 750rpx;">
  30. <view class="dp-f ai-c jc-c fz-28 color-333 mb-20" v-if="SelectNum===0">
  31. 推荐选座
  32. <view style="width: 106rpx;height: 60rpx;" class="b-1 br-5 dp-f ai-c jc-c fz-28 ml-20" v-for="(n,numindex) in 4"
  33. :key="n" @click="smartChoose(numindex+1)">
  34. {{numindex+1}}人
  35. </view>
  36. </view>
  37. <view class="dp-f ai-c fw-w fz-28 color-333 mb-20" v-if="SelectNum>0">
  38. <text>已选</text>
  39. <view class="p-all-10 b-1 br-5 dp-f ai-c jc-c fz-28 ml-20" v-for="(optItem,optindex) in optArr" :key="optindex">
  40. {{optItem.RowNum+'排'+optItem.ColumnNum+'座'}}
  41. </view>
  42. </view>
  43. <view style="width: 566rpx;height: 90rpx;" class="dp-f jc-c ai-c br-10 fz-34 color-fff" :class="SelectNum>0?'bg-red-1':'bg-unbtn'"
  44. @click="buySeat">
  45. <text>{{SelectNum>0?('¥ '+aPrice+' 确认座位'):'选择座位后才能观看'}}</text>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. <view v-if="show">
  51. <dever-publish :title="title" :is_upload="false" @hideModal="hideTips" @getRefresh="getRefresh" :type="seat_table" :type_id="seat_table_id" :api="api" :playtime="playtime"></dever-publish>
  52. </view>
  53. </view>
  54. </template>
  55. <script>
  56. import deverPublish from '@/lib/dever/components/publish.vue';
  57. export default {
  58. props: {
  59. type : {
  60. type : String,
  61. value : null
  62. },
  63. type_id : {
  64. type : String,
  65. value : null
  66. },
  67. item : {
  68. type : Object,
  69. value : null
  70. },
  71. index : 0
  72. },
  73. components:{
  74. deverPublish
  75. },
  76. data() {
  77. return {
  78. cycle : false,
  79. scaleMin:1,//h5端为解决1无法缩小问题,设为0.95
  80. boxWidth: 400, //屏幕宽度px
  81. space: ' ', //空格
  82. seatArray: [], //影院座位的二维数组,-1为非座位,0为未购座位,1为已选座位(绿色),2为已购座位(红色),一维行,二维列
  83. seatRow: 0, //影院座位行数
  84. seatCol: 0, //影院座位列数
  85. seatSize: 0, //座位尺寸
  86. SelectNum: 0, //选择座位数
  87. moveX: 0, //水平移动偏移量
  88. scale: 1, //放大倍数
  89. minRow: 0, //从第几行开始排座位
  90. minCol: 0, //从第几列开始排座位
  91. showTis: true, //显示选座提示
  92. seatList: [], //接口获取的原始位置
  93. mArr: [], //排数提示
  94. optArr: [], //选中的座位数组。
  95. isWXAPP:false,
  96. price : 1,
  97. fetch : {
  98. user : {},
  99. hall : 1,
  100. disabled : true,
  101. },
  102. show : false,
  103. api : 'app/community/?l=api.addTips',
  104. title : '发布聊天泡泡',
  105. seat_table : '',
  106. seat_table_id : 0,
  107. tipsData : {},
  108. page : 1,
  109. play : false,
  110. playtime : 0,
  111. tipsTimeData : {},
  112. hall_state : false,
  113. hall_data : [],
  114. hall_index : 0,
  115. //手动停止播放
  116. setStop : false,
  117. source : false,
  118. };
  119. },
  120. computed: {
  121. aPrice() {
  122. if (this.fetch.disabled) {
  123. return (this.SelectNum - 1) * this.price
  124. } else {
  125. return (this.SelectNum) * this.price
  126. }
  127. },
  128. rpxNum() {
  129. return this.boxWidth / 750
  130. },
  131. pxNum() {
  132. return 750 / this.boxWidth
  133. },
  134. },
  135. mounted() {
  136. if (this.item.title) {
  137. this.title = this.item.title;
  138. }
  139. this.price = parseFloat(this.item.seat_price);
  140. this.setHall();
  141. //获取宽度
  142. uni.getSystemInfo({
  143. success: function(e) {
  144. this.boxWidth = e.screenWidth
  145. //#ifdef H5
  146. this.scaleMin = 0.95
  147. //#endif
  148. }
  149. })
  150. this.page = 1;
  151. this.initData(this.hall)
  152. },
  153. methods: {
  154. setHall : function() {
  155. var default_hall = this.Dever.data('hall_' + this.type_id);
  156. if (!default_hall) {
  157. default_hall = 1;
  158. } else {
  159. default_hall = parseInt(default_hall);
  160. }
  161. var hall = parseInt(this.item.hall_num);
  162. this.hall_index = default_hall - 1;
  163. this.hall = default_hall;
  164. var hall_state = false;
  165. for (var i=0; i<hall ; i++) {
  166. this.hall_data[i] = (i+1) + '号厅';
  167. if (this.hall_index == i) {
  168. hall_state = true;
  169. }
  170. }
  171. if (!hall_state) {
  172. this.hall_index = 0;
  173. this.hall = 1;
  174. }
  175. this.hall_state = true;
  176. },
  177. openHall : function(e) {
  178. this.hall_index = e.detail.value;
  179. this.hall = parseInt(this.hall_index+1);
  180. this.Dever.data('hall_' + this.type_id, this.hall);
  181. this.page = 1;
  182. this.initData(this.hall);
  183. },
  184. showTips : function(tipsid, id, tips, code, user) {
  185. if (!this.play && this.playtime == 0) {
  186. this.Dever.alert('播放时才能发送消息');
  187. return;
  188. }
  189. this.seat_table = tips;
  190. this.seat_table_id = id;
  191. this.show = true;
  192. if (this.play) {
  193. this.setStop = true;
  194. this.$emit('stop');
  195. }
  196. },
  197. hideTips : function() {
  198. this.show = false;
  199. if (this.setStop == true) {
  200. this.$emit('start');
  201. this.setStop = false;
  202. }
  203. },
  204. setDisabled : function() {
  205. this.$emit('setDisabled', this.fetch.disabled);
  206. },
  207. tips : function(id, content, curtime) {
  208. var id = '#tips_' + this.type_id + '_' + id;
  209. if (this.tipsData[id]) {
  210. this.Dever.layer.close(this.tipsData[id]);
  211. }
  212. var self = this;
  213. this.tipsData[id] = this.Dever.layer.tips(content, id, {
  214. tips: [1, '#0FA6D8'],
  215. tipsMore: true,
  216. end : function() {
  217. if (self.source && curtime) {
  218. self.source.time[curtime] = false;
  219. }
  220. }
  221. //time : 100000,
  222. });
  223. },
  224. getRefresh : function(cate_id, type, type_id, content) {
  225. this.tips(type_id, content, this.playtime);
  226. if (!this.tipsTimeData[this.playtime]) {
  227. this.tipsTimeData[this.playtime] = [];
  228. }
  229. this.tipsTimeData[this.playtime].push({type_id:type_id,content:content});
  230. this.hideTips();
  231. },
  232. initData: function(hall) {
  233. var self = this;
  234. this.cycle && (clearInterval(this.cycle));
  235. this.Dever.get(this, 'app/user/?l=api.seat', {code:this.Dever.config.code,noloading:1, content_id : this.type_id, hall : hall}, function(t) {
  236. self.setDisabled();
  237. let arr = t.seat
  238. //数据说明:SeatCode座位编号,RowNum-行号,ColumnNum-纵号,YCoord-Y坐标,XCoord-X坐标,Status-状态
  239. let row = 0
  240. let col = 0
  241. let minCol = parseInt(arr[0].XCoord)
  242. let minRow = parseInt(arr[0].YCoord)
  243. for (let i of arr) {
  244. minRow = parseInt(i.YCoord) < minRow ? parseInt(i.YCoord) : minRow
  245. minCol = parseInt(i.XCoord) < minCol ? parseInt(i.XCoord) : minCol
  246. row = parseInt(i.YCoord) > row ? parseInt(i.YCoord) : row
  247. col = parseInt(i.XCoord) > col ? parseInt(i.XCoord) : col
  248. self.seat_table = i.Tips
  249. }
  250. self.seatList = arr
  251. self.seatRow = row - minRow + 1
  252. self.seatCol = col - minCol + 3
  253. self.minRow = minRow
  254. self.minCol = minCol - 1
  255. self.initSeatArray()
  256. self.tipsTimeData = {};
  257. self.getData();
  258. });
  259. },
  260. start : function() {
  261. this.play = true;
  262. },
  263. stop : function() {
  264. this.play = false;
  265. this.Dever.layer.closeAll();
  266. },
  267. time : function(data) {
  268. var time = data[1];
  269. this.source = data[0];
  270. this.playtime = time;
  271. //console.info(time);
  272. if (this.tipsTimeData[time]) {
  273. this.handle(this.tipsTimeData[time], time);
  274. }
  275. },
  276. // 获取聊天历史数据
  277. getData : function() {
  278. var self = this;
  279. this.Dever.get(this, 'app/community/?l=api.tips', {code:this.Dever.config.code,noloading:1, type:this.seat_table, pg:this.page}, function(t) {
  280. var arr = Object.keys(t.info);
  281. if (arr.length > 0) {
  282. self.save(t.info);
  283. }
  284. });
  285. },
  286. save : function(data) {
  287. this.tipsTimeData = Object.assign(this.tipsTimeData, data);
  288. this.page++;
  289. this.getData();
  290. },
  291. //执行聊天泡泡
  292. handle : function(items, curtime) {
  293. if (!this.play) {
  294. return;
  295. }
  296. this.cycle && (clearInterval(this.cycle));
  297. var i = 0;
  298. var len = items.length;
  299. this.tips(items[i]['type_id'], items[i]['content'], curtime);
  300. i++;
  301. this.cycle = setInterval(() => {
  302. var time = 5;
  303. // #ifndef H5
  304. time = Math.ceil(Math.floor(Math.random() * (this.maxTime - this.minTime + 1) + this.minTime));
  305. // #endif
  306. if (!this.play) {
  307. clearInterval(this.cycle);
  308. } else if (i < len) {
  309. this.tips(items[i]['type_id'], items[i]['content'], curtime);
  310. i++;
  311. } else {
  312. clearInterval(this.cycle);
  313. }
  314. }, 1000)
  315. },
  316. //初始座位数组
  317. initSeatArray: function() {
  318. let seatArray = Array(this.seatRow).fill(0).map(() => Array(this.seatCol).fill({
  319. type: -1,
  320. SeatCode: '',
  321. RowNum: '',
  322. ColumnNum: ''
  323. }));
  324. this.seatArray = seatArray
  325. this.seatSize = this.boxWidth > 0 ?
  326. parseInt(parseInt(this.boxWidth, 10) / (this.seatCol + 1), 10) :
  327. parseInt(parseInt(414, 10) / (this.seatCol + 1), 10)
  328. this.initNonSeatPlace();
  329. },
  330. //初始化是座位的地方
  331. initNonSeatPlace: function() {
  332. let seat = this.seatList.slice()
  333. let arr = this.seatArray.slice()
  334. for (let num in seat) {
  335. let status = 2 //-1为非座位,0为未购座位,1为已选座位(绿色),2为已购座位(红色)
  336. if (seat[num].Status === 0) {
  337. status = 0
  338. } else if (seat[num].Status === -1) {
  339. status = -1
  340. }
  341. arr[parseInt(seat[num].YCoord) - this.minRow][parseInt(seat[num].XCoord) - this.minCol] = {
  342. type: status,
  343. SeatCode: seat[num].SeatCode,
  344. RowNum: seat[num].RowNum,
  345. ColumnNum: seat[num].ColumnNum,
  346. User: seat[num].User,
  347. Id : seat[num].Id,
  348. Tips : seat[num].Tips,
  349. TipsId : 'tips_' + this.type_id + '_' + seat[num].Id
  350. }
  351. }
  352. this.seatArray = arr.slice()
  353. let mArr = []
  354. for (let i in arr) {
  355. let m = ''
  356. for (let n of arr[i]) {
  357. if (n.SeatCode) {
  358. m = n.RowNum
  359. }
  360. }
  361. if (m) {
  362. mArr.push(m)
  363. } else {
  364. mArr.push('')
  365. }
  366. }
  367. this.mArr = mArr
  368. },
  369. //放大缩小事件
  370. onScale: function(e) {
  371. this.showTis = false
  372. // this.moveX=-e.detail.x
  373. let w = this.boxWidth * 0.5
  374. let s = 1 - e.detail.scale
  375. this.moveX = w * s
  376. this.scale = e.detail.scale
  377. if (s > 0 || s === 0) {
  378. this.showTis = true
  379. }
  380. },
  381. //移动事件
  382. onMove: function(e) {
  383. this.showTis = false
  384. this.moveX = e.detail.x
  385. },
  386. //重置座位
  387. resetSeat: function() {
  388. this.SelectNum = 0
  389. this.optArr = []
  390. //将所有已选座位的值变为0
  391. let oldArray = this.seatArray.slice();
  392. for (let i = 0; i < this.seatRow; i++) {
  393. for (let j = 0; j < this.seatCol; j++) {
  394. if (oldArray[i][j].type === 1) {
  395. oldArray[i][j].type = 0
  396. }
  397. }
  398. }
  399. this.seatArray = oldArray;
  400. },
  401. //选定且购买座位
  402. buySeat: function() {
  403. if (this.SelectNum === 0) {
  404. return
  405. }
  406. let oldArray = [];
  407. for (let i = 0; i < this.seatRow; i++) {
  408. for (let j = 0; j < this.seatCol; j++) {
  409. if (this.seatArray[i][j].type === 1) {
  410. oldArray.push(this.seatArray[i][j].SeatCode)
  411. }
  412. }
  413. }
  414. this.buy(oldArray);
  415. },
  416. buy : function(seat) {
  417. seat = seat.join(',');
  418. var self = this;
  419. this.Dever.confirm('确定购买座位吗?第一个座位免费哦~有了座位就有观看权了~还有内容发布权~', function() {
  420. var data = {};
  421. data.code = self.Dever.config.code;
  422. data.seat = seat;
  423. data.content_id = self.type_id;
  424. data.type = self.type;
  425. data.index = self.index;
  426. var location = 'dream/view?code={code}&name=' + self.Dever.config.name;
  427. data.location = location;
  428. data.refer = self.Dever.host + '/' + location;
  429. self.Dever.post('app/user/?l=pay.seat', data, function(t) {
  430. if (t.type && t.type == 'free') {
  431. self.Dever.alert('选座成功,您可以点击头像发布内容~');
  432. self.resetSeat();
  433. self.initData(self.hall);
  434. } else {
  435. self.Dever.pay(t, t.location, '支付失败');
  436. }
  437. });
  438. /*
  439. self.Dever.post('app/user/?l=api.seatSave', {code:self.Dever.config.code, seat:seat, content_id : self.type_id}, function(t) {
  440. self.Dever.alert('选座成功,您可以点击头像发布内容~');
  441. self.resetSeat();
  442. self.initData(self.hall);
  443. });
  444. */
  445. })
  446. },
  447. //处理座位选择逻辑
  448. handleChooseSeat: function(row, col) {
  449. let seatValue = this.seatArray[row][col].type;
  450. let newArray = this.seatArray;
  451. //如果是已购座位,直接返回
  452. if (seatValue === 2 || seatValue === -1) return
  453. //如果是已选座位点击后变未选
  454. if (seatValue === 1) {
  455. newArray[row][col].type = 0
  456. this.SelectNum--
  457. this.getOptArr(newArray[row][col], 0)
  458. } else if (seatValue === 0) {
  459. if (this.SelectNum >= 4) {
  460. this.Dever.alert('一次最多只能购买4个座位');
  461. return;
  462. }
  463. newArray[row][col].type = 1
  464. this.SelectNum++
  465. this.getOptArr(newArray[row][col], 1)
  466. }
  467. //必须整体更新二维数组,Vue无法检测到数组某一项更新,必须slice复制一个数组才行
  468. this.seatArray = newArray.slice();
  469. },
  470. //处理已选座位数组
  471. getOptArr: function(item, type) {
  472. let optArr = this.optArr
  473. if (type === 1) {
  474. optArr.push(item)
  475. } else if (type === 0) {
  476. let arr = []
  477. optArr.forEach(v => {
  478. if (v.SeatCode !== item.SeatCode) {
  479. arr.push(v)
  480. }
  481. })
  482. optArr = arr
  483. }
  484. this.optArr = optArr.slice()
  485. },
  486. //推荐选座,参数是推荐座位数目,
  487. smartChoose: function(num) {
  488. //console.log('num===', num)
  489. // 先重置
  490. this.resetSeat()
  491. //找到影院座位水平垂直中间位置的后一排
  492. let rowStart = parseInt((this.seatRow - 1) / 2, 10) + 1;
  493. //先从中间排往后排搜索
  494. let backResult = this.searchSeatByDirection(rowStart, this.seatRow - 1, num);
  495. if (backResult.length > 0) {
  496. this.chooseSeat(backResult);
  497. this.SelectNum += num
  498. return
  499. }
  500. //再从中间排往前排搜索
  501. let forwardResult = this.searchSeatByDirection(rowStart - 1, 0, num);
  502. if (forwardResult.length > 0) {
  503. this.chooseSeat(forwardResult);
  504. this.SelectNum += num
  505. return
  506. }
  507. //提示用户无合法位置可选
  508. alert('无合法位置可选!')
  509. },
  510. //搜索函数,参数:fromRow起始行,toRow终止行,num推荐座位数
  511. searchSeatByDirection: function(fromRow, toRow, num) {
  512. /*
  513. * 推荐座位规则
  514. * (1)初始状态从座位行数的一半处的后一排的中间开始向左右分别搜索,取离中间最近的,如果满足条件,
  515. * 记录下该结果离座位中轴线的距离,后排搜索完成后取距离最小的那个结果座位最终结果,优先向后排进行搜索,
  516. * 后排都没有才往前排搜,前排逻辑同上
  517. *
  518. * (2)只考虑并排且连续的座位,不能不在一排或者一排中间有分隔
  519. *
  520. * */
  521. /*
  522. * 保存当前方向搜索结果的数组,元素是对象,result是结果数组,offset代表与中轴线的偏移距离
  523. * {
  524. * result:Array([x,y])
  525. * offset:Number
  526. * }
  527. *
  528. */
  529. let currentDirectionSearchResult = [];
  530. let largeRow = fromRow > toRow ? fromRow : toRow,
  531. smallRow = fromRow > toRow ? toRow : fromRow;
  532. for (let i = smallRow; i <= largeRow; i++) {
  533. //每一排的搜索,找出该排里中轴线最近的一组座位
  534. let tempRowResult = [],
  535. minDistanceToMidLine = Infinity;
  536. for (let j = 0; j <= this.seatCol - num; j++) {
  537. //如果有合法位置
  538. if (this.checkRowSeatContinusAndEmpty(i, j, j + num - 1)) {
  539. //计算该组位置距离中轴线的距离:该组位置的中间位置到中轴线的距离
  540. let resultMidPos = parseInt((j + num / 2), 10);
  541. let distance = Math.abs(parseInt(this.seatCol / 2) - resultMidPos);
  542. //如果距离较短则更新
  543. if (distance < minDistanceToMidLine) {
  544. minDistanceToMidLine = distance;
  545. //该行的最终结果
  546. tempRowResult = this.generateRowResult(i, j, j + num - 1)
  547. }
  548. }
  549. }
  550. //保存该行的最终结果
  551. currentDirectionSearchResult.push({
  552. result: tempRowResult,
  553. offset: minDistanceToMidLine
  554. })
  555. }
  556. //处理后排的搜索结果:找到距离中轴线最短的一个
  557. //注意这里的逻辑需要区分前后排,对于后排是从前往后,前排则是从后往前找
  558. let isBackDir = fromRow < toRow;
  559. let finalReuslt = [],
  560. minDistanceToMid = Infinity;
  561. if (isBackDir) {
  562. //后排情况,从前往后
  563. currentDirectionSearchResult.forEach((item) => {
  564. if (item.offset < minDistanceToMid) {
  565. finalReuslt = item.result;
  566. minDistanceToMid = item.offset;
  567. }
  568. });
  569. } else {
  570. //前排情况,从后往前找
  571. currentDirectionSearchResult.reverse().forEach((item) => {
  572. if (item.offset < minDistanceToMid) {
  573. finalReuslt = item.result;
  574. minDistanceToMid = item.offset;
  575. }
  576. })
  577. }
  578. //直接返回结果
  579. return finalReuslt
  580. },
  581. /*辅助函数,判断每一行座位从i列到j列是否全部空余且连续
  582. *
  583. */
  584. checkRowSeatContinusAndEmpty: function(rowNum, startPos, endPos) {
  585. let isValid = true;
  586. for (let i = startPos; i <= endPos; i++) {
  587. if (this.seatArray[rowNum][i].type !== 0) {
  588. isValid = false;
  589. break;
  590. }
  591. }
  592. return isValid
  593. },
  594. //辅助函数:返回每一行的某个合理位置的座位数组
  595. generateRowResult: function(row, startPos, endPos) {
  596. let result = [];
  597. for (let i = startPos; i <= endPos; i++) {
  598. result.push([row, i])
  599. }
  600. return result
  601. },
  602. //辅助函数:智能推荐的选座操作
  603. chooseSeat: function(result) {
  604. let opt = this.optArr
  605. let oldArray = this.seatArray.slice();
  606. for (let i = 0; i < result.length; i++) {
  607. //选定座位
  608. oldArray[result[i][0]][result[i][1]].type = 1
  609. this.optArr.push(oldArray[result[i][0]][result[i][1]])
  610. }
  611. this.seatArray = oldArray;
  612. },
  613. }
  614. }
  615. </script>
  616. <style lang="scss" scoped>
  617. @import '@/static/layer/theme/default/layer.css';
  618. .main {
  619. position: relative;
  620. }
  621. .p-all-10{
  622. padding: 10rpx;
  623. }
  624. .ml-10 {
  625. margin-left: 10rpx;
  626. }
  627. .m-0-10 {
  628. margin: 0 10rpx;
  629. }
  630. .bg-unbtn {
  631. background-color: #f9abb3;
  632. }
  633. .bg-red-1 {
  634. background-color: #F45664;
  635. }
  636. .br-10 {
  637. border-radius: 10rpx;
  638. }
  639. .ml-20 {
  640. margin-left: 20rpx;
  641. }
  642. .mb-20 {
  643. margin-bottom: 20rpx;
  644. }
  645. .p-all-32 {
  646. padding: 32rpx;
  647. }
  648. .fd-cr {
  649. flex-direction: column-reverse;
  650. /* 主轴方向从下到上,默认从左到右 */
  651. }
  652. .bottom-bar {
  653. bottom: var(--window-bottom);
  654. }
  655. .color-fff {
  656. color: #fff
  657. }
  658. .br-15 {
  659. border-radius: 15rpx;
  660. }
  661. .over-h {
  662. overflow: hidden;
  663. }
  664. .dp-ib {
  665. display: inline-block;
  666. }
  667. .mt-20 {
  668. margin-top: 20rpx;
  669. margin-left: 30rpx;
  670. }
  671. .pa-v-2 {
  672. /* 定位垂直对齐 */
  673. left: 50%;
  674. transform: translateX(-50%)
  675. }
  676. .b-d-1 {
  677. border: 1px dashed #e5e5e5;
  678. }
  679. .w-100 {
  680. width: 100%;
  681. }
  682. .h-100 {
  683. height: 100%;
  684. }
  685. .bg-f1 {
  686. background-color: #f1f1f1;
  687. }
  688. .h-100vh {
  689. height: 100vh;
  690. }
  691. .pt-f {
  692. position: fixed;
  693. }
  694. .left-0 {
  695. left: 0;
  696. }
  697. .p-0-32 {
  698. padding: 0 32rpx;
  699. }
  700. .pt-20 {
  701. padding-top: 20rpx;
  702. }
  703. .bg-white {
  704. background-color: #fff;
  705. }
  706. .z1000 {
  707. z-index: 1000;
  708. }
  709. .fz-34 {
  710. font-size: 34rpx;
  711. }
  712. .fw-b {
  713. font-weight: bold;
  714. }
  715. .mt-10 {
  716. margin-top: 10rpx;
  717. }
  718. .fz-28 {
  719. font-size: 28rpx;
  720. }
  721. .color-666 {
  722. color: #666666
  723. }
  724. .dp-f {
  725. display: flex;
  726. }
  727. .jc-c {
  728. justify-content: center;
  729. }
  730. .ai-c {
  731. align-items: center;
  732. }
  733. .fz-22 {
  734. font-size: 22rpx;
  735. }
  736. .color-333 {
  737. color: #333333
  738. }
  739. .m-0-a {
  740. margin: 0 auto;
  741. }
  742. .mt-48 {
  743. margin-top: 48rpx;
  744. }
  745. .fz-20 {
  746. font-size: 20rpx;
  747. }
  748. .color-999 {
  749. color: #999999
  750. }
  751. .b-1 {
  752. border: 1px solid #CCCCCC;
  753. }
  754. .br-5 {
  755. border-radius: 5rpx;
  756. }
  757. .Stage {
  758. background-color: #dddddd;
  759. width: 380rpx;
  760. height: 34rpx;
  761. transform: perspective(34rpx) rotateX(-10deg);
  762. margin: 0 auto;
  763. }
  764. .bg-line {
  765. background-color: rgba(0, 0, 0, 0.3);
  766. }
  767. .sel-seat {
  768. background: url('@/static/seat/selected.png') center center no-repeat;
  769. background-size: 100% 100%;
  770. }
  771. .unsel-seat {
  772. background: url('@/static/seat/unselected.png') center center no-repeat;
  773. background-size: 100% 100%;
  774. }
  775. .bought-seat {
  776. background: url('@/static/seat/bought.png') center center no-repeat;
  777. background-size: 100% 100%;
  778. }
  779. </style>