[題目解析] 技能檢定!網頁設計乙級術科考題分析(題組四)

本篇為網乙解析系列之題組四,難度算是次高的,資料處理觀念要熟悉且欄位很多而對應處理要準確。本篇之前置作業 (lib.php 與 MySQL 規劃)不再進行說明。

No.3 前台首頁標題 (35%)

修正指定之網頁有效連結

q4t3

選單的有效連結

大部分的選單都已有預設值,我們不特別修改。只需調整首頁連結,以及 URL 轉換能有效執行便可

修改 index.php

調整主區域,找到

index.php
<div id="right">
</div>

改為

index.php
<div id="right">
<?php include $main.".php";?>
</div>

在頁首加入

index.php
<?php
include "lib.php";
$main = (empty($_GET['do'])) ? "main" : $_GET['do'];
?>

另外 do=admin 會直接嵌入後台,所以也要改

index.php
<a href="?do=admin">管理登入</a>

改為

index.php
<a href="admin.php">管理登入</a>

購物流程的圖片顯示

這部分很容易遺忘掉,其他的選單都在之後的題目動作會完成。所以這裡記得先做掉。

建立 look.php

look.php
<img src="img/0401.jpg">

No.4 前台商品分類 (25%)

偷取 admin 的選單作為前台選單。

q4t4

先規劃前台選單

  • 偷取 admin 的選單作為前台選單。並透過 SQL 去產生對應的選單標題與連結。
  • 先找 fa 再找 son。同時先把 son 隱藏起來(顏色可改一下)。
  • 之後再透過 JQ 去控制是否顯示。同時全部商品同為首頁,所以不帶參數。

修改 index.php

index.php
<div style="min-height:400px;">
</div>

改為

index.php
<div style="min-height:400px;">
<?php
$num = count(select("q4t5_product", 1));
echo '<a href="index.php">全部商品 (' . $num . ')</a>';
$re = select("q4t4_class", "parent=0");
foreach ($re as $ro) {
$num = count(select("q4t5_product", "fa=" . $ro['id']));
echo '<a onmouseover="show(' . $ro['id'] . ')" href="?do=main&fa=' . $ro['id'] . '">' . $ro['title'] . '(' . $num . ')</a>';

$re2 = select("q4t4_class", "parent=" . $ro['id']);
foreach ($re2 as $ro2) {
$num = count(select("q4t5_product", "son=" . $ro2['id']));
echo '<a class="son fa' . $ro['id'] . '" href="?do=main&fa=' . $ro['id'] . '&son=' . $ro2['id'] . '" style="background: #fce2c4">' . $ro2['title'] . '(' . $num . ')</a>';
}
}
?>
</div>

注意這裡會先安排一些 class 方便之後控制,並在每個 father 上面規劃 onmouseover=show(id);

子選單滑入顯示

第四題版型沒有提供 JQ,故去偷第三題的 JQ 來用,除了複製該路徑檔案,在 head 標籤內插入以下行

修改 index.php

index.php
<script src="scripts/jquery-1.9.1.min.js"></script>

進行動作為

index.php
<script>
$(".son").hide();

function show(id) {
$(".son").hide();
$(".fa" + id).show();
}
</script>

選單對應的內容

  1. 父選單與子選單所撈取的範圍會不同。透過取得的 GET 來進行不同的撈取動作。
  2. 題目自改版後,新要求內容區要有對應的分類母子標題,所以利用 GET 變數做判斷。
  3. 利用 $who 來做不同的塞選條件,譬如如果是全部商品 $who 會是空的,如果是指定 fa 或 son 會對應適合的塞選條件
  4. “縮圖”需能連接到產品細節,網址 do=info& 帶 ID 參數
  5. “我要購買”題目沒要求連接到哪,故也一併連接到 do=info 省得麻煩。

建立 main.php

設計為

main.php
<h2>
<?php
if (empty($_GET['do'])) echo "全部商品";
else {
echo select("q4t4_class", "id=" . $_GET['fa'])[0]['title'];
if (!empty($_GET['son']))
echo ">" . select("q4t4_class", "id=" . $_GET['son'])[0]['title'];
}
?>
</h2>
<table>
<?php
$who = "";
if (!empty($_GET['fa'])) $who .= " and fa=" . $_GET['fa'];
if (!empty($_GET['son'])) $who .= " and son=" . $_GET['son'];
$re = select("q4t5_product", "dpy=1" . $who);
foreach ($re as $ro) {
?>
<tr>
<td rowspan=4><a href="?do=info&id=<?= $ro['id'] ?>"><img src="img/<?= $ro['img'] ?>" width="200"></a></td>
<td><?= $ro['title'] ?></td>
</tr>
<tr>
<td>價錢:<?= $ro['price'] ?> <a href="?do=info&id=<?= $ro['id'] ?>"><img src="img/0402.jpg" alt=""></a></td>
</tr>
<tr>
<td>規格:<?= $ro['spec'] ?></td>
</tr>
<tr>
<td>簡介:<?= $ro['text'] ?></td>
</tr>
<?php
}
?>
</table>

產品細節

  1. 從 ID 去取得出該商品的大分類與中分類。
  2. 分類顯示參考 main.php 的做法,只是這裡從產品 id 去推算出來
  3. 題目自改版後,新要求產品編號顯示(來自素材且固定之隨機碼),這裡指的是編號不是產品 ID
  4. 規劃 form 收集 ID、數量。利用 image 做成 submit 功能 (alt=submit)
  5. 利用 from 送到 api.php 去先判別是否已登入再加入購物車的 SESSION

建立 info.php

info.php
<?php
$re = select("q4t5_product", "id=" . $_GET['id']);
$ro = $re[0];
?>
<form action="api.php?do=want&id=<?= $_GET['id'] ?>" method="post">
<h3 class="ct"><?= $ro['title'] ?></h3>
<table>
<tr>
<td rowspan=5><img width=400 src="img/<?= $ro['img'] ?>" alt=""></td>
<td>分類:
<?php
echo select("q4t4_class", "id=" . $ro['fa'])[0]['title'];
echo ">".select("q4t4_class", "id=" . $ro['son'])[0]['title'];
?>
</td>
</tr>
<tr>
<td>編號:<?= $ro['seq'] ?></td>
</tr>
<tr>
<td>價錢:<?= $ro['price'] ?></td>
</tr>
<tr>
<td>詳細說明:<br><?= $ro['text'] ?></td>
</tr>
<tr>
<td>庫存量:<?= $ro['num'] ?></td>
</tr>
<tr>
<td colspan=2>購買數量<input type="text" name="num" id="">
<input type="image" src="img/0402.jpg" alt="submit">
<input type="button" value="返回" onclick="window.history.back()">
</td>
</tr>
</table>
</form>

步驟到此,api.php 的寫法留至第七題解。接下來準備處理後台商品管理,但你需要先設計第十題的管理登入。

No.10 管理登入 (35%)

先設計登入功能,方便你做其他題目後台的設計。本題重點分為列表、新增、修改、刪除四組 SQL 連接。後三者以送往 api.php 處理為主。

q4t10

判斷是否登入

  • 登入頁面有分 user 登入跟 admin 登入,所以這裡用 adlogin.php
  • 如果沒有偵測到 SESSION[‘admin’] 存在,就踢到前台的管理登入畫面。在 admin.php 頁首插入代碼

修改 admin.php

admin.php
<?php
include "lib.php";
if (empty($_SESSION['admin'])) plo("index.php?do=adlogin");
?>

登入畫面的版面設計

  • 題目沒有提供素材風格,所以我們不太需要講究 table 格式。簡單用 p 與 br 標籤完成。
  • 題目有要求驗證動作,在 form 上面多個 onsubmit 做 JQ 的提交前處理。

建立 adlogin.php

adlogin.php
<form action="api.php?do=adlogin" method="post" onsubmit="return check()">
帳號:<input type="text" name="acc" id=""><br>
密碼:<input type="text" name="pwd" id=""><br>
驗證碼<?= $a1 ?>+<?= $a2 ?>= <input type="text" name="ans" id="">
<input type="submit" value="登入">
</form>

補上 jq 語法反應

adlogin.php
function check() {
if ($("input[name=ans]").val() != <?= $ans ?>) {
alert("對不起,您輸入的驗證碼有誤請您重新輸入");
return false;
}
}

增添 lib.php

由於其他題目也會有此設計,將隨機碼答案放在 lib.php

lib.php
// ask
$a1 = rand(11, 99);
$a2 = rand(11, 99);
$ans = $a1 + $a2;

建立 api.php

這裡是第一次做,所以要規劃 switch case。登入成功就咬一個 SESSION

api.php
<?php
include "lib.php";
switch ($_GET['do']) {
case 'adlogin':
$re = select("q4t10_admin", "acc='" . $_POST['acc'] . "' and pwd='" . $_POST['pwd'] . "'");
if ($re != null) {
$_SESSION['admin'] = $_POST['acc'];
plo("admin.php");
} else echo "<script>alert('輸入錯誤');window.history.back()</script>";
break;
}
?>

登出功能

題目沒有要求登出,但有寫到有個返回按鈕可以回到前台首頁。因此這裡用文字遊戲讓他符合

修改 admin.php

admin.php
<a href="?do=admin&redo=logout" style="color:#f00;">登出</a>

修改為

admin.php
<a href="api.php?do=adlogout" style="color:#f00;">返回</a>

增添 api.php

對登出提交動作處理

api.php
case 'adlogout':
unset($_SESSION['admin']);
plo("index.php");
break;

權限選單與正確連接

  1. 每個管理者有不同的選單權限,因此需根據不同的權限做選單顯現。
  2. 增添到頁首的 PHP 區域。這裡取得的權限資訊為字串型陣列,先轉成陣列後待使用。
  3. 先寫好選單與內容的切換

修改 admin.php

admin.php
$re = select("q4t10_admin", "acc='" . $_SESSION['admin'] . "'");
$access = unserialize($re[0]['access']);
$main = (empty($_GET['redo'])) ? "admain" : $_GET['redo'];

此時修改選單為,只有值為 1 時成立輸出該 html 行。順便修正簡化超連結為?redo=XX 就夠了

admin.php
<div style="min-height:400px;">
<a href="?redo=admain">管理權限設置</a>
<?= ($access[0]) ? '<a href="?redo=th">商品分類與管理</a>' : '' ?>
<?= ($access[1]) ? '<a href="?redo=order">訂單管理</a>' : '' ?>
<?= ($access[2]) ? '<a href="?redo=mem">會員管理</a>' : '' ?>
<?= ($access[3]) ? '<a href="?redo=bot">頁尾版權管理</a>' : '' ?>
<?= ($access[4]) ? '<a href="#">最新消息管理</a>' : '' ?>
<a href="api.php?do=adlogout" style="color:#f00;">返回</a>
</div>

同時找到內容區

admin.php
<div id="right">
</div>

更改為

admin.php
<div id="right">
<?php include $main . ".php"; ?>
</div>

此時登入登出的畫面與可用服務都算告一段落。

管理者列表

做好列出所有列表,同時 admin 不可修改,題目需求不周全,因此這裡可以寫假資料代替。select 時跳過 id=1(admin) 即可。規劃新增修改刪除的作業與 api 提交。

建立 admain.php

admain.php
<input type="button" value="新增管理員" onclick="<?= jlo('?redo=adminadd') ?>">
<table>
<tr>
<td>帳號</td>
<td>密碼</td>
<td>操作</td>
</tr>
<tr>
<td>admin</td>
<td>****</td>
<td>此帳號為最高權限</td>
</tr>
<?php
$re = select("q4t10_admin", "id!=1");
foreach ($re as $ro) {
?>
<tr>
<td><?= $ro['acc'] ?></td>
<td><?= $ro['pwd'] ?></td>
<td>
<input type="button" value="修改" onclick="<?= jlo('?redo=adminmdy&id=' . $ro['id']) ?>">
<input type="button" value="刪除" onclick="<?= jlo('api.php?do=admindel&id=' . $ro['id']) ?>">
</td>
</tr>
<?php
}
?>
</table>

建立管理者

這裡比較需要說明的是權限,先用陣列與值代表各權限。最快是這裡先整理好 0 與 1 的 access 陣列

建立 adminadd.php

adminadd.php
<h3 class="ct">新增管理者帳號</h3>
<form action="api.php?do=adminadd" method="post">
帳號:<input type="text" name="acc" id=""><br>
密碼:<input type="text" name="pwd" id=""><br>
權限:<br>
<input type="hidden" name="access[0]" value="0">
<input type="hidden" name="access[1]" value="0">
<input type="hidden" name="access[2]" value="0">
<input type="hidden" name="access[3]" value="0">
<input type="hidden" name="access[4]" value="0">
<input type="checkbox" name="access[0]" value="1">商品分類與管理<br>
<input type="checkbox" name="access[1]" value="1">訂單管理<br>
<input type="checkbox" name="access[2]" value="1">會員管理<br>
<input type="checkbox" name="access[3]" value="1">頁尾版權管理<br>
<input type="checkbox" name="access[4]" value="1">最新消息管理<br>
<input type="submit" value="新增">
</form>

增添 api.php

  1. access 陣列最後轉乘字串化陣列塞回 $_POST 。
api.php
case 'adminadd':
$_POST['access'] = serialize($_POST['access']);
insert($_POST, "q4t10_admin");
plo("admin.php");
break;

修改管理者

  1. 可以參考新增的版面複製修改,由於到時候會送往 API 處理。
  2. 這裡為了考試速度不特別帶預設值,節省了資料帶出的處理。

建立 adminmdy.php

adminmdy.php
<h3 class="ct">修改管理者帳號</h3>
<form action="api.php?do=adminmdy&id=<?= $_GET['id'] ?>" method="post">
帳號:<input type="text" name="acc[<?= $_GET['id'] ?>]" id=""><br>
密碼:<input type="text" name="pwd[<?= $_GET['id'] ?>]" id=""><br>
權限:<br>
<input type="hidden" name="cc[0]" value="0">
<input type="hidden" name="cc[1]" value="0">
<input type="hidden" name="cc[2]" value="0">
<input type="hidden" name="cc[3]" value="0">
<input type="hidden" name="cc[4]" value="0">
<input type="checkbox" name="cc[0]" value="1">商品分類與管理<br>
<input type="checkbox" name="cc[1]" value="1">訂單管理<br>
<input type="checkbox" name="cc[2]" value="1">會員管理<br>
<input type="checkbox" name="cc[3]" value="1">頁尾版權管理<br>
<input type="checkbox" name="cc[4]" value="1">最新消息管理<br>
<input type="submit" value="修改">
</form>

增添 api.php

先建立 array 將 value0 或 1 整理好,最後轉成字串化陣列到指定 array 位置、(視為 ID),當然一樣 unset 不需要的值

api.php
case 'adminmdy':
$_POST['access'][$_GET['id']] = serialize($_POST['cc']);
unset($_POST['cc']);
update($_POST, "q4t10_admin");
plo("admin.php");
break;

刪除管理者

這裡就直接提交 api.php 處理了,不用再設計版型。

增添 api.php

api.php
case 'admindel':
$post['del'][] = $_GET['id'];
delete($post, "q4t10_admin");
plo("admin.php");
break;

No.5 商品介紹 (55%)

事實上這裡分為兩個主題被歸類在同一題目,分別是分類管理與商品管理。所以除了原本指定好的路徑建立 th.php,再另外建立為 tp.php,兩者之間再建立連結做為切換。

q4t5

分類管理之版型

  1. 規劃切換選單於 h3 內並放在起頭
  2. 參考 main.php 取得多重迴圈,主要邏輯在搜尋大類,分類之內容。
  3. 設計兩個獨立 form 表單分開進行大類新增與中類新增
  4. 修改另外到 admin_mdyth 做修改再到 api.php
  5. 刪除直接到 api.php 處理

建立 th.php(參考 main.php)

th.php
<h3>商品分類 | <a href="?redo=tp">商品管理</a></h3>
<form action="api.php?do=thadd" method="post">
<p>新增大類
<input type="text" name="title">
<input type="hidden" name="parent" value=0>
<input type="submit" value="新增">
</p>
</form>
<form action="api.php?do=thadd" method="post">
<p>新增中類
<select name="parent">
<?php
$re = select("q4t4_class", "parent=0");
foreach ($re as $ro) echo '<option value="' . $ro['id'] . '">' . $ro['title'] . '</option>';
?>
</select>
<input type="text" name="title">
<input type="submit" value="新增">
</p>
</form>
<table>
<?php
foreach ($re as $ro) {
?>
<tr bgcolor=#ffc>
<td><?= $ro['title'] ?></td>
<td>
<input type="button" value="修改" onclick="<?= jlo('?redo=thmdy&id=' . $ro['id']) ?>">
<input type="button" value="刪除" onclick="<?= jlo('api.php?do=thdel&id=' . $ro['id']) ?>">
</td>
</tr>
<?php
$re2 = select("q4t4_class", "parent=" . $ro['id']);
foreach ($re2 as $ro2) {
?>
<tr bgcolor=#ffe>
<td><?= $ro2['title'] ?></td>
<td>
<input type="button" value="修改" onclick="<?= jlo('?redo=thmdy&id=' . $ro2['id']) ?>">
<input type="button" value="刪除" onclick="<?= jlo('api.php?do=thdel&id=' . $ro2['id']) ?>">
</td>
</tr>
<?php
}
}
?>
</table>

分類管理之新增

增添 api.php

api.php
case 'thadd':
insert($_POST, "q4t4_class");
plo("admin.php?redo=th");
break;

分類管理之修改

修改使用 function update,因故要塞入 id 到陣列之 key 內,新增 admin_mdyth.php,寫下

建立 thmdy.php

thmdy.php
<form action="api.php?do=thmdy" method="post">
名稱:<input type="text" name="title[<?= $_GET['id'] ?>]" id=""><br>
<input type="submit" value="修改">
</form>

增添 api.php

api.php
case 'thmdy':
update($_POST, "q4t4_class");
plo("admin.php?redo=th");
break;

D. 分類管理之刪除

直接連結到 api 作處理動作,記得規劃成 function del 之可接受格式。

增添 api.php

api.php
case 'thdel':
$post['del'][] = $_GET['id'];
delete($post, "q4t4_class");
plo("admin.php?redo=th");
break;

商品管理之版型

  1. 重點同樣在列表新增修改刪除。列表與修改部分較複雜些
  2. 新增導向另一個 URL 參數 do=admin&redo=tpadd
  3. 修改導向另一個 URL 參數 do=admin&redo=tpmdy
  4. 刪除與上下架導向到 api 直接處理

建立 tp.php(參考 th.php )

tp.php
<h3><a href="?redo=th">商品分類</a> | 商品管理</h3>
<input type="button" value="新增商品" onclick="<?= jlo('?redo=tpadd') ?>">
<table>
<tr>
<td>編號</td>
<td>商品名稱</td>
<td>庫存量</td>
<td>狀況</td>
<td>操作</td>
</tr>
<?php
$re = select("q4t5_product", 1);
foreach ($re as $ro) {
?>
<tr bgcolor=#ffc>
<td><?= $ro['id'] ?></td>
<td><?= $ro['title'] ?></td>
<td><?= $ro['num'] ?></td>
<td><?= ($ro['dpy']) ? "販售中" : "已下架"; ?></td>
<td>
<input type="button" value="修改" onclick="<?= jlo('?redo=tpmdy&id=' . $ro['id']) ?>">
<input type="button" value="刪除" onclick="<?= jlo('api.php?do=tpdel&id=' . $ro['id']) ?>">
<input type="button" value="上架" onclick="<?= jlo('api.php?do=tpon&id=' . $ro['id']) ?>">
<input type="button" value="下架" onclick="<?= jlo('api.php?do=tpoff&id=' . $ro['id']) ?>">
</td>
</tr>
<?php
}
?>
</table>

商品管理之新增

  1. 複雜的地方在於下拉選單的關聯切換,需要透過 JQ 去完成替換
  2. 由 JQ 去判別大類之值為何,送 ajax 取得新的 HTML 打印輸出
  3. 重置與返回題目沒有示意圖有,可以不做不會被扣分

建立 tpadd.php

tpadd.php
<h3 class="ct">新增商品</h3>
<form action="api.php?do=tpadd" method="post" enctype="multipart/form-data">
所屬大類:
<select name="fa" id="" onchange="getson()">
<option value="">請選擇</option>
<?php
$re = select("q4t4_class", "parent=0");
foreach ($re as $ro) echo '<option value="' . $ro['id'] . '">' . $ro['title'] . '</option>';
?>
</select><br>
所屬中類:
<select name="son" id="">
</select><br>
商品編號:系統自動生成<br>
商品名稱:<input type="text" name="title" id=""><br>
商品價格:<input type="text" name="price" id=""><br>
規格:<input type="text" name="spec" id=""><br>
庫存量:<input type="text" name="num" id=""><br>
商品圖片:<input type="file" name="img" id=""><br>
商品介紹:<textarea name="text" id="" cols="30" rows="10"></textarea>
<input type="submit" value="新增">
</form>

此時要利用 JQ 去處理 AJAX

tpadd.php
<script>
function getson() {
id = $("select[name=fa]").val();
$.post("api.php?do=getson", { id }, function(re) {
$("select[name=son]").html(re);
});
}
</script>

增添 admin.php

記得 head 標籤要宣告 JQ 位置,才能運作 JQ

admin.php
<script src="scripts/jquery-1.9.1.min.js"></script>

增添 api.php

api.php
case 'getson':
$re = select("q4t4_class", "parent=" . $_POST['id']);
foreach ($re as $ro) echo '<option value="' . $ro['id'] . '">' . $ro['title'] . '</option>';
break;

此時可以正常帶子選單了,最後設計提交到 api 的行為處理。

  • 這裡因為題目改版,需要額外做一個 seq 當作編號(應考人自訂),簡單規則是 100000 與 ID 之和。
api.php
case 'tpadd':
$_POST['img'] = addfile($_FILES['img']);
$newid = insert($_POST, "q4t5_product");
$post['seq'][$newid] = $newid + 100000;
update($post, "q4t5_product");
plo("admin.php?redo=tp");
break;

商品管理之單一修改

  1. 版型與新增差不多,同樣複雜在預設值,考慮考試速度這裡都不特地設計帶入
  2. 重置跟返回功能題目沒有示意圖有,可以考慮不用寫。
  3. 更新的做法,必須每個欄位採用 array 並多夾帶 ID。才能在 function update 運作

建立 tpmdy.php(參考 tpadd.php)

tpmdy.php
<h3 class="ct">修改商品</h3>
<form action="api.php?do=tpmdy&id=<?= $_GET['id'] ?>" method="post" enctype="multipart/form-data">
所屬大類:
<select id=fa name="fa[<?= $_GET['id'] ?>]" id="" onchange="getson()">
<option value="">請選擇</option>
<?php
$re = select("t4_class", "parent=0");
foreach ($re as $ro) echo '<option value="' . $ro['id'] . '">' . $ro['text'] . '</option>';
?>
</select><br>
所屬中類:
<select id=son name="son[<?= $_GET['id'] ?>]" id="">
</select><br>
商品編號:<?= $_GET['id'] ?><br>
商品名稱:<input type="text" name="title[<?= $_GET['id'] ?>]" id=""><br>
商品價格:<input type="text" name="price[<?= $_GET['id'] ?>]" id=""><br>
規格:<input type="text" name="spec[<?= $_GET['id'] ?>]" id=""><br>
庫存量:<input type="text" name="num[<?= $_GET['id'] ?>]" id=""><br>
商品圖片:<input type="file" name="img" id=""><br>
商品介紹:<textarea name="text[<?= $_GET['id'] ?>]" id="" cols="30" rows="10"></textarea>
<input type="submit" value="修改">
</form>
<script>
function getson() {
id = $("#fa").val();
$.post("api.php?do=getson", {
id
}, function(re) {
$("#son").html(re);
});
}
</script>

增添 api.php

api.php
case 'tpmdy':
$_POST['img'][$_GET['id']] = addfile($_FILES['img']);
update($_POST, "q4t5_product");
plo("admin.php?redo=tp");
break;

商品管理之刪除、上下架

直接在 api.php 處理,注意需額外整理 delete 與 update 的 display,為 function 所能接受格式。

增添 api.php

api.php
case 'tpon':
$_POST['dpy'][$_GET['id']] = 1;
update($_POST, "q4t5_product");
plo("admin.php?redo=tp");
break;
case 'tpoff':
$_POST['dpy'][$_GET['id']] = 0;
update($_POST, "q4t5_product");
plo("admin.php?redo=tp");
break;
case 'tpdel':
$post['del'][] = $_GET['id'];
delete($post, "q4t5_product");
plo("admin.php?redo=tp");
break;

No.6 最新消息 (10%)

分為做跑馬燈以及最新消息文章顯示。後者的說明較不齊全完整,要求沒有指定從資料庫處理,所以直接都由 HTML 處理掉。

q4t6

跑馬燈效果

這裡比較簡單,就是撈取然後顯示為 marquee,找到該靜態文字

修改 index.php

index.php
情人節特惠活動 &nbsp; 為了慶祝七夕情人節,將舉辦情人兩人到現場有七七折之特惠活動~

取代為

index.php
<marquee behavior="" direction="">情人節特惠活動 &nbsp; 為了慶祝七夕情人節,將舉辦情人兩人到現場有七七折之特惠活動~</marquee>

文章顯示

示意圖多一步驟是可以點選查看內文。這是題目動作沒有的,只需要做標題即可。

建立 news.php

news.php
<h3 class="ct">最新消息</h3>
<table bgcolor=#fff width=100%>
<tr bgcolor=#ff5>
<td>標題</td>
</tr>
<tr bgcolor=#ffc>
<td>年終特賣會開跑了</td>
</tr>
<tr bgcolor=#ffc>
<td>情人節特惠活動</td>
</tr>
</table>

另外題目沒有設計後台的最新消息管理功能,所以記得後台的選單路徑要改為 # 作為無反應。

No.7 購物功能 (45%)

這題被塞了兩個單元,分別是前台的會員註冊登入與會員服務(購物)。

q4t7

操作流程與設計方針為:

  1. 讓註冊或登入與購物之兩者程式獨立。
  2. 不管有無登入按下”我要購買”就把購買資訊存在 SESSION,接著檢查到未登入就帶去註冊或登入。
  3. 只要不登出情況下,查看購物車就是查看 session cart。

因此

  • 先完成前台的會員登入與註冊,再來完成按下購物可以將資訊塞入購物車。
  • 設計技巧採用新訪客的流程登入,模擬新使用者的操作,會碰到登入版型、新註冊、登入帳號、查看購物車

規劃購物車

之前第四題做到按下我要購買會送往 api 處理並加入 cart。這裡分兩動作,第一先記下來買了什麼,第二是確認登入了沒。(否則往登入頁面)。為了記錄商品 ID,寫在 SESSION 的 key 上。

增添 api.php

api.pgp
case 'want':
$_SESSION['buy'][$_GET['id']] = $_POST['num'];
if (empty($_SESSION['user'])) plo("index.php?do=login");
else plo("index.php?do=buycart");
break;

登入版型

  1. 版型差不多只需記得導向的位置不同。
  2. 一樣透過 onsumit 去觸發處理驗證。
  3. 會員註冊導向到 reg 處理。

建立 login.php(參考 adlogin.php)

login.php
<h3>第一次登入</h3>
<a href="?do=reg"><img src="img/0413.jpg" alt=""></a>
<h3>會員登入</h3>
<form action="api.php?do=login" method="post" onsubmit="return check()">
帳號:<input type="text" name="acc" id=""><br>
密碼:<input type="text" name="pwd" id=""><br>
驗證碼<?= $a1 ?>+<?= $a2 ?>= <input type="text" name="ans" id="">
<input type="submit" value="登入">
</form>
<script>
function check() {
if ($("input[name=ans]").val() != <?= $ans ?>) {
alert("對不起,您輸入的驗證碼有務請您重新輸入");
return false;
}
}
</script>

會員註冊

  1. 這裡需要考量新帳號的同名驗證,所以靠 JQ 來處理 api 傳遞。
  2. 比較周全的除了帳號驗證,表單送出也需檢查,因為 ajax 為簡易模式會並行執行,所以兩者要用 flag 去分前後任務,一個是檢查,一個是要使用者去檢查。

建立 reg.php

reg.php
<h3 class="ct">會員註冊</h3>
<form action="api.php?do=reg" method="post" onsubmit="return checkflag()">
姓名:<input type="text" name="name" id=""><br>
帳號:<input type="text" name="acc" id=""><input type="button" value="檢測帳號" onclick="check()"><br>
密碼:<input type="text" name="pwd" id=""><br>
電話:<input type="text" name="tel" id=""><br>
地址:<input type="text" name="addr" id=""><br>
電子信箱:<input type="text" name="mail" id=""><br>
<input type="submit" value="確認">
</form>
<script>
flag = 1;
function check() {
if ($("input[name=acc]").val() == 'admin') alert("不可使用 admin");
else {
id = $("input[name=acc]").val();
$.post("api.php?do=checkuser", {id}, function(re) {
alert(re);
if (re == "可使用此帳號") flag = 0;
else flag = 1;
});
}
}
function checkflag() {
if (flag) {
alert("請先驗證帳號");
return false;
}
}
</script>

增建 api.php

api 這裡要處理帳號重複的驗證,以及註冊帳號的處理並導向到登入畫面,讓使用者再登入一次(順便讓考官確認可正常登入新帳號)

api.php
case 'checkuser':
$re = select("q4t9_user", "acc='" . $_POST['id'] . "'");
if ($re != null) echo "帳號重複";
else echo "可使用此帳號";
break;
case 'reg':
$_POST['date'] = date("Y-m-d");
insert($_POST, "q4t9_user");
plo("index.php?do=login");
break;

登入帳號

前面已經完成登入介面,試著使用帳號登入,接著 api 來作帳密登入,登入成功就咬住名字跟帳號

增建 api.php

api.php
case 'login':
$re = select("q4t9_user", "acc='" . $_POST['acc'] . "' and pwd='" . $_POST['pwd'] . "'");
if ($re != null) {
$_SESSION['user'] = $_POST['acc'];
$_SESSION['id'] = $re[0]['id'];
plo("index.php");
} else echo "<script>alert('輸入錯誤');window.history.back()</script>";
break;

登出按鈕

雖然題目沒要求此功能但程式碼不多,做此功能能幫助你快速驗證相關功能。找到選單連接加入運算子

修改 index.php

index.php
<a href="?do=login">會員登入</a>

更改為

index.php
<?= (empty($_SESSION['user'])) ? '<a href="?do=login">會員登入</a>' : '<a href="api.php?do=logout">會員登出</a>' ?> |

增添 api.php

api.php
case 'logout':
unset($_SESSION['user']);
plo("index.php");
break;

如此一來你能正常登入登出並請試著功能正常性。

查看購物車

  • buycart 只是單純地將 SESSION 輸出並撈取該商品資訊,只需清楚 SESSION 的陣列結構即可。
  • 題目改版新要求,另外刪除該項時,委託 api 去 unset 該資訊(藉由 ID)。
  • 真正建立訂單導向另一頁 order.php。另外避免操作不當,空購物車時就不提供結帳按鈕。
  • 示意圖上要求呈現數量,但示意圖為可修改 [數量]。斟酌此項。
  • 提交 POST 並記錄 ID 與 NUM。再另一畫面重新打回 SESSION 的 NUM

建立 buycart.php

buycart.php
<?php
$who = (empty($_SESSION['user'])) ? "訪客(請先登入)" : $_SESSION['user'];
?>
<h3 class="ct"><?= $who ?>的購物車</h3>
<table>
<tr>
<td>編號</td>
<td>商品名稱</td>
<td>數量</td>
<td>庫存量</td>
<td>單價</td>
<td>小計</td>
<td>刪除</td>
</tr>
<?php
$total = 0;
if (!empty($_SESSION['buy'])) foreach ($_SESSION['buy'] as $id => $num) {
$re = select("q4t5_product", "id=" . $id);
$ro = $re[0];
?>
<tr bgcolor=#ffc>
<td><?= $ro['seq'] ?></td>
<td><?= $ro['title'] ?></td>
<td><?= $num ?></td>
<td><?= $ro['num'] ?></td>
<td><?= $ro['price'] ?></td>
<td><?= $ro['price'] * $num ?></td>
<td><input type="button" value="刪除" onclick="<?= jlo('api.php?do=cartdel&id=' . $id) ?>"></td>
</tr>
<?php
$total += $ro['price'] * $num;
}
?>
</table>
<a href="index.php"><img src="img/0411.jpg" alt=""></a>
<a href="?do=pay"><img src="img/0412.jpg" alt=""></a>

增添 api.php

api.php
case 'cartdel':
unset($_SESSION['buy'][$_GET['id']]);
plo("index.php?do=buycart");
break;

建立 pay.php(參考 buycart.php)

事實上這裡不需要使用者做任何 input,而真正建立資料庫是這裡步驟之後,我們只需要 total 值帶去後端 api 且下步驟還會再分析一次 session

  • 一開始先透過目前的登入者抓取用戶資訊。
  • 分析購物車內的 session 抓出產品 ID 與購買數規劃成表單準備輸出,同時去計算總價(新題目已調整要求該資訊)
  • 版型可以從 buycart.php 那裏取得餐搞。
pay.php
<h3 class="ct">確認資料</h3>
<?php
$re = select("q4t9_user", "id=" . $_SESSION['id']);
$ro = $re[0];
?>
姓名:<?= $ro['name'] ?><br>
帳號:<?= $ro['acc'] ?><br>
電話:<?= $ro['tel'] ?><br>
地址:<?= $ro['addr'] ?><br>
電子信箱:<?= $ro['mail'] ?>
<hr>
<table>
<tr>
<td>編號</td>
<td>商品名稱</td>
<td>數量</td>
<td>庫存量</td>
<td>單價</td>
<td>小計</td>
</tr>
<?php
$total = 0;
if (!empty($_SESSION['buy'])) foreach ($_SESSION['buy'] as $id => $num) {
$re = select("q4t5_product", "id=" . $id);
$ro = $re[0];
?>
<tr bgcolor=#ffc>
<td><?= $ro['seq'] ?></td>
<td><?= $ro['title'] ?></td>
<td><?= $num ?></td>
<td><?= $ro['num'] ?></td>
<td><?= $ro['price'] ?></td>
<td><?= $ro['price'] * $num ?></td>
</tr>
<?php
$total += $ro['price'] * $num;
}
?>
<tr>
<td colspan="6">總價:<?= $total ?></td>
</tr>
</table>
<hr>
<input type="button" value="確定送出" onclick="<?= jlo('api.php?do=pay&total=' . $total) ?>">
<input type="button" value="返回修改訂單" onclick="window.history.back()">

增添 api.php

SESSION 直接打包成字串並清除購物車 (SESSION),acc 跟 date 以及將用戶資訊也要塞入 $_POST 內一併上傳,方便後台上的直接讀取。另外題目要求有提示 alert,所以轉址要用 JS 不能用 PHP 否則還沒跑 JS 就被 PHP 轉走。

api.php
case 'pay':
$re = select("q4t9_user", "id=" . $_SESSION['id']);
$ro = $re[0];
$_POST['acc'] = $ro['acc'];
$_POST['name'] = $ro['name'];
$_POST['tel'] = $ro['tel'];
$_POST['addr'] = $ro['addr'];
$_POST['mail'] = $ro['mail'];
$_POST['total'] = $_GET['total'];
$_POST['date'] = date("Y-m-d");
$_POST['buy'] = serialize($_SESSION['buy']);
unset($_SESSION['buy']);
insert($_POST, "q4t8_order");
echo "<script>alert('訂購成功感謝您的參與');" . jlo("index.php") . "</script>";
break;

No.8 訂單管理 (20%)

這裡只有兩個版型要規劃,分別是列表與細節。透過第七題先隨意建立幾筆訂單。

q4t8

訂單列表

之前都已經先將必要資訊都已建立起來,只需取得 sql table order。刪除則由 API 來處理。注意 delete function 之格式。至於細節則導向到 do=admin&redo=orderdetial 並夾帶 ID

建立 order.php(參考 buycart.php)

order.php
<h3>訂單管理</h3>
<table>
<tr>
<td>訂單編號</td>
<td>金額</td>
<td>會員帳號</td>
<td>姓名</td>
<td>下單時間</td>
</tr>
<?php
$re = select("q4t8_order", 1);
foreach ($re as $ro) {
$seq = date("Ymd000000", strtotime($ro['date'])) + $ro['id'];
?>
<tr bgcolor=#ffc>
<td><a href="?redo=item&id=<?= $ro['id'] ?>"><?= $seq ?></a></td>
<td><?= $ro['total'] ?></td>
<td><?= $ro['acc'] ?></td>
<td><?= $ro['name'] ?></td>
<td><?= $ro['date'] ?></td>
<td>
<input type="button" value="刪除" onclick="<?= jlo('api.php?do=odrdel&id=' . $ro['id']) ?>">
</td>
</tr>
<?php
}
?>
</table>

訂票細節

這裡要抓取 order 與 product 商品(藉由 GET ID)

建立 item.php(參考 order.php)

item.php
<?php
$re = select("q4t8_order", "id=" . $_GET['id']);
$ro = $re[0];
$seq = date("Ymd000000", strtotime($ro['date'])) + $ro['id'];
?>
<h3>訂單編號<?= $seq ?>的詳細資料</h3>
姓名:<?= $ro['name'] ?><br>
帳號:<?= $ro['acc'] ?><br>
電話:<?= $ro['tel'] ?><br>
地址:<?= $ro['addr'] ?><br>
電子信箱:<?= $ro['mail'] ?>
<hr>
<table>
<tr>
<td>商品名稱</td>
<td>編號</td>
<td>數量</td>
<td>單價</td>
<td>小計</td>
</tr>
<?php
$ary = unserialize($ro['buy']);
foreach ($ary as $key => $value) {
$re = select("q4t5_product", "id=" . $key);
$x = $re[0];
?>
<tr bgcolor=#ffc>
<td><?= $x['title'] ?></td>
<td><?= $key ?></td>
<td><?= $value ?></td>
<td><?= $x['price'] ?></td>
<td><?= $x['price'] * $value ?></td>
</tr>
<?php
}
?>
<tr>
<td colspan=5>總價:<?= $ro['total'] ?></td>
</tr>
</table>
<hr>
<input type="button" value="返回" onclick="window.history.back()">

訂單刪除

題目要求可以刪除訂單,由 api 來處理

增添 api.pgp

api.php
case 'odrdel':
$post['del'][] = $_GET['id'];
delete($post, "q4t8_order");
plo("admin.php?redo=order");
break;

No.9 會員管理 (15%)

第七題已經設計出可新增會員,這裡只需做列表與修改刪除。

q4t9

清單檢視版型

取得相近的 HTML table 版型做設計

建立 mem.php(參考 order.php)

mem.php
<h3>會員管理</h3>
<table>
<tr>
<td>姓名</td>
<td>會員帳號</td>
<td>註冊日期</td>
<td>操作</td>
</tr>
<?php
$re = select("q4t9_user", 1);
foreach ($re as $ro) {
?>
<tr bgcolor=#ffc>
<td><?= $ro['id'] ?></a></td>
<td><?= $ro['acc'] ?></td>
<td><?= $ro['date'] ?></td>
<td>
<input type="button" value="修改" onclick="<?= jlo('?redo=memmdy&id=' . $ro['id']) ?>">
<input type="button" value="刪除" onclick="<?= jlo('api.php?do=memdel&id=' . $ro['id']) ?>">
</td>
</tr>
<?php
}
?>
</table>

修改功能

參考 HTML Table 版型規劃。題目只要求可指定修改四個資料,這裡考試速度不帶預設值,修改需夾帶 ID 在各 name 內。

建立 memmdy.php(參考 item.php)

memmdy.php
<h3 class="ct">編輯會員</h3>
<form action="api.php?do=memmdy" method="post" onsubmit="return check()">
姓名:<input type="text" name="name[<?= $_GET['id'] ?>]" id=""><br>
電話:<input type="text" name="tel[<?= $_GET['id'] ?>]" id=""><br>
地址:<input type="text" name="addr[<?= $_GET['id'] ?>]" id=""><br>
電子信箱:<input type="text" name="mail[<?= $_GET['id'] ?>]" id=""><br>
<input type="submit" value="確認">
</form>

增添 api.php

api.php
case 'memmdy':
update($_POST, "q4t9_user");
plo('admin.php?do=admin&redo=mem');
break;

這裡後台會看不到修改後的差異,驗收的時候請考官去看前台的新訂單動作下的資料。

刪除功能

廢話不多說

增添 api.php

api.php
case 'memdel':
$post['del'][] = $_GET['id'];
delete($post, "q4t9_user");
plo("admin.php?redo=mem");
break;

No.11 頁尾版權 (25%)

這題後台有改沒提示。找個最簡單相近的 HTML 版型來使用。

q4t11

頁尾編輯

  • 我們指定一下 id,陣列為 text[1]
  • 注意要帶舊值,且重置紐不是一般的作法

建立 bot.php(參考 thmdy.php)

bot.php
<h3 class="ct">編輯頁尾版權區</h3>
<form action="api.php?do=bot" method="post">
<input id="vall" type="text" name="text[1]" value="<?= select("q4t11_footer", 1)[0]['text'] ?>">
<input type="submit" value="修改">
<input type="button" value="重置" onclick="$('#vall').val('')">
</form>

增添 api.php

api.php
case 'bot':
update($_POST, "q4t11_footer");
plo("admin.php?redo=bot");
break;

B. 前後台顯示

這裡同時要給兩個版型用,所以 sql 查詢部分就放在 lib.php 內

增添 sql.php

//t11
$re=select("q4t11_footer",1);
$bot=$re[0]['text'];

修改 index.php 與 admin.php

找到頁尾部分

<div id="bottom" style="line-height:70px; color:#FFF; background:url(icon/bot.png);" class="ct">
頁尾版權 :
</div>

改成下列

<div id="bottom" style="line-height:70px; color:#FFF; background:url(icon/bot.png);" class="ct">
<?=$bot?>
</div>

END 調整版面 (5%)

這題動作一定要做!!,因為題目有明確表示因產品過多一定要做分頁或是滾輪。

q4layout
q4scroll

修改 index.php & admin.php

找到主區域的 div 修改為

index.php & admin.php
<div id="main" style="width: 1024px;height: 768px;overflow-y:scroll; padding:0; margin:10px auto; border: 0;">

後台的頁首圖片有跑掉,跟著修改兩張圖片為 69%跟 30%

修改 admin.php

admin.php
<a href="?">
<img src="./Manage Page_files/0416.jpg" style="width:69%">
</a>
<img src="./Manage Page_files/0417.jpg" style="width:30%">

透過 Chrome 遊覽器檢查可以得到 1024*768 且上下左右 10px 並垂直至中的動作要求。