這邊題目給出的指示需要摸擬一個影廳的座位狀況,然後使用者可以點選座位來訂票,所以會需要一些建置前端頁面的工作;
這邊會先由前端頁面使用ajax來傳送電影id,日期,場次等資訊到api,然後在api程式中使用php來取出已訂位的資料,建置完座位區後,再以js來完成前端劃位的操作,最後再把訂單資料送到後端去儲存,完成整個訂票的功能。
頁面切換機制
- 在劃位的功能的處理上,我們不使用表單跳頁的方式,而是使用js來控制畫面區塊的切換,這樣就能保留表單的選擇狀態,回上一步時只要切換區塊即可。
- 我們也同時使用ajax的方式把選單的內容傳送到後端去產生一份劃位的頁面,並放在
#booking
區塊中1
2
3
4
5<div class="ct">
<!--點擊選單的確定時,讓兩個div的顯示狀態切換,同時也向後端取得劃位畫面-->
<button onclick="$('#orderForm,#booking').toggle();getBooking()">確定</button>
<button onclick="reset()">重置</button>
</div>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//建立一個空的全域物件變數
let order={};
//用來向後端取得劃位頁面的ajax函式
function getBooking(){
//取得各個下拉選單的資料,並設定進order物件中
order.movie=$("#movie option:selected").text()
order.date=$("#date").val()
order.session=$("#session").val()
//將訂票資訊傳至後端get_booking.php,並取回劃位頁面html內容
$.get("./api/get_booking.php",order,(booking)=>{
//將劃位頁面的html放至#booking區塊中
$("#booking").html(booking)
})
}
劃位頁面製作
劃位頁面的產生及劃位行為應該是本題組最複雜的一部份了,這邊要注意的細節比較多,同時也有很多的技巧用來簡化程式碼的撰寫。
首先我們先在類別
Order
中增加一個方法,這個方法會接收表單傳過來的電影,日期及場次資料,然後回傳剩餘的座位資訊
/controller/Order.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function seats($request){
//將傳入的表單陣列解開為$movie,$date,$session三個變數
extract($request);
//根據電影名稱,日期及場次,取出所有的訂單
$orders=$this->all(['movie'=>$movie,'date'=>$date,'session'=>$session]);
//建立一個用來存放已訂位的座位空陣列
$seats=[];
//迴圈逐筆取出訂單
foreach ($orders as $key => $order) {
//還原訂位為陣列
$tmp=unserialize($order['seats']);
//使用array_merge()函式將訂位資料放在seats陣列中
$seats=array_merge($seats,$tmp);
}
return $seats;
}接著我們建立劃位頁面的架構,並建立必要的class name
api/booking.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<div class="theater">
<!--建立一個容器來存放所有的座位-->
<div class="seats">
<!--seat是座位的基本樣式設定,
null是空座位的css設定,
booked是已被訂位的css設定-->
<div class='seat null'></div>
</div>
</div>
<div class="order-info">
<div>您選擇的電影是:</div>
<div>您選擇的時刻是:</div>
<div>您已經勾選<span id="qt"></span>張票,最多可以購買四張票</div>
<div class="ct">
<button onclick="$('#order,#booking').toggle()">上一步</button>
<button>訂購</button>
</div>
</div>建立劃位頁面的css設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48#booking *{
box-sizing: border-box;
}
.theater{
width:540px;
height:370px;
background-image: url(./icon/03D04.png);
background-repeat: no-repeat;
background-position: center;
margin:auto;
padding-top:18px;
}
.seats{
width:320px;
height:340px;
margin:auto;
display:flex;
flex-wrap: wrap;
}
.seat{
width:64px;
height:85px;
text-align: center;
position:relative;
}
.seat input{
position:absolute;
bottom:5px;
right:5px;
}
.null,.booked{
background-position: center;
background-repeat: no-repeat;
}
.null{
background-image: url("../icon/03D02.png");
}
.booked{
background-image: url("../icon/03D03.png");
}
.order-info{
width:540px;
margin:auto;
padding:0px 100px;
}
.order-info div{
margin:5px;
}根據前端ajax傳來的資料取得劃位頁面需要的內容
1
2
3
4include_once "../base.php";
//使用seats()方法來取得該場次的已訂位資訊
$seats=$Order->seats($_GET);使用迴圈來產生20個座位,包含座位資訊及選票框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<div class="theater">
<div class="seats">
<?php
for($i=0;$i<20;$i++){
//取得座位資訊字串
$position=(floor($i/5)+1)."排".($i%5+1)."號";
<!--判斷目前的座位值是否在陣列$seats中,決定要使用那個class-->
<div class="seat <?=in_array($i,$seats)?'booked':'null';?>">
<?=$position;?>
<?php
if(!in_array($i,$seats)){
echo "<input type='checkbox' name='seat' value='{$i}'>";
}
</div>
}
</div>
</div>根據ajax傳來的資訊,將訂位資訊顯示在下方訂票資訊區
1
2
3
4
5
6
7
8
9<div class="order-info">
<div>您選擇的電影是:<?=$_GET['movie'];?></div>
<div>您選擇的時刻是:<?=$_GET['date'];?> <?=$_GET['session'];?></div>
<div>您已經勾選<span id="qt"></span>張票,最多可以購買四張票</div>
<div class="ct">
<button onclick="$('#order,#booking').toggle()">上一步</button>
<button>訂購</button>
</div>
</div>撰寫訂位行為的js程式碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36//建立一個js陣列用來儲存使用者選中的座位
let seats=new Array();
//監聽checkbox的改變事件
$(".seat input").on("change",function(){
//根據屬性checked的狀態來決定下一步是選擇位置還是取消位置
if($(this).prop('checked')){
//如果是選中的狀態,
//先判斷目前選中的座位有沒有超過四個
if(seats.length>=4){
//如果選中的座位已經四張了,就會出現警告
alert("最多只能購買四張票");
//接著將選中的座位還原為不選中的狀態
$(this).prop('checked',false)
}else{
//如果選中的座位數還沒有超過四個,
//就把座位號碼放入陣列中
seats.push($(this).val())
}
}else{
//如果是要取消選中的座位,
//則同時也在座位陣列中移除該座位號
seats.splice(seats.indexOf($(this).val()),1)
}
//更新票數的文字
$("#qt").text(seats.length)
})撰寫送出訂單函式
1
2
3
4
5
6
7
8
9
10//確認訂單的函式
function checkout(){
order.seats=seats
//使用ajax向api傳送訂單的資料
$.post("./api/order.php",order,(result)=>{
//取得訂單完成的頁面,並更新到#booking區塊中
$("#booking").html(result)
}
)
}最後是製作訂單結果頁面,我們在劃位的最後按下訂購時,並沒有做頁面導向的動作,這邊一樣是利用ajax的方式把訂購資訊及劃位結果送去後端處理,等後端處理完後,再返回訂單的頁面給前端,然後我們再把訂單結果頁面整個取代掉原本的劃位區塊
#booking
api/order.php
根據訂單資料,處理成可以存入資料表的格式,並存入資料表
1 | include_once "../base.php"; |
建立訂單完成頁面,回傳給前端使用
api/order.php
1 | <h3>感謝您的訂購,您的訂單編號是:$_POST['no']; </h3> |
補充
上述的做法重點只在決定座位的資訊,然後送出訂單完成交易,但在實務上,只有checkbox的勾選在使用者互動上是有點薄弱的,因此我們可以在選中及取消座位時,使用我們設定的兩個class來做切換,讓劃位的視覺互動感受更具體一些:
1 | $(".chk").on("change",function(){ |
最後的檢查
題組三的難點在於前台的預告片轉場動畫及訂票劃位功能上,所以如果做完有空,可以先檢查一下這兩個功能,確認分數有拿到;相較於一,二題以四小時內可以做完為目標,三,四題的目標放在四小時內可以做到及格就好了,因此可以在戰略上分配好,那些功能是可以押後來做,把時間留給有把握的功能上,並加強檢查。