[題目解析] 第 50 屆全國技能競賽青少年組網頁設計考題分析
本篇為 (Moudle 2) 提供競賽選手使用,作為題目作答之技巧研究解析練習,不代表考場之實際考題之內容準確性。相關連結資源如下:
版型設計
題目沒有提供網頁版型,需由選手自行完成並列入視覺美術評分作業,請依序自行開發完成版型設計(妥善利用考場素材包發揮),同時本節將使用 Bootstrap 技術快速完成開發作業。
本節將先完成以下三筆檔案動作:
- index.html: 作為一般前台使用
- admin.html: 做為後台使用,提供管理者(與玩家)能對留言板修改刪除之後台管理。
- plugin/style.css: 提供此兩項網頁之 css 外觀設計。
小技巧:我們先使用 *.html
為副檔名,這樣使用 VSCode 進行編寫時能得到 Emmet 輔助提示與編寫,最後進行 PHP 設計時再改回*.php
副檔名即可。
此外前置作業需使用 bootstrap 2.2.2 相關檔案,請自行準備放入指定位置,並記得網頁 header 內宣告
- plugin/bootstrap.min.css: bootstrap 樣式表
- plugin/bootstrap.min.js: bootstrap 動態模組
- plugin/jquery.min.js: bootstrap 驅動工具
- img/glyphicons-halflings-white.png: 樣式表圖片
宣告方式如下(放入需使用 bootstrap 之網頁):
<head> |
前台設計
- 根據題目基本要求:具備選單區、留言區主題(含增加留言)、競賽分配主題(含玩家參賽導引)、後台登入
- 本解析視覺設計部分:採用 one page 設計並將相關題目要求列入選單,並規劃頁首與廣告區,使體驗完整提高。
初始化外觀
進行以下 CSS 優化:
- 漸層的背景,建議電競風格為主(螢光與暗黑色)
- 統一將文字調整為黑體,採 1rem 為基準大小、加粗統一、文字置中(另需要則個別調整)、灰黑文字色
- 使用 border-box 減少空間計算問題
- 另外由於 BS 2.2 預設窄版為 940px(但部分 BS Component 不支援),因此使用
!important
強制覆蓋且能自由調整寬度。
/*環境調整*/ |
標題
作為網站名稱文字標題,保留部分區域空間作為其他擴充位置。
小技巧:
- 使用 BS Grid System 功能方便裁切成 4+8 或 4+4+4。
- 這裡使用 header 標籤當主容器(不用 div),這樣就省寫 class 或其他名稱綁定。
<!--網站標題--> |
需要自訂 CSS 調整,主區塊 CSS 部分重點:
- 將背景刷白,並固定整體為 100px 高。
- 利用文字高度跟區塊同高,使標題文字有垂直至中的單行效果。
/* 網站標題 */ |
選單
提供網站選單作用,依題目要求規劃選單項目。
小技巧:
- 使用 BS Navbar 快速搞定選單,並使用
.navbar-inverse
做為我們的黑色風格。 - 使用 BS Layouts 觀念設計窄版
<div class="container">
,窄版定義對ul.nav
有效(做為該新外層)。
- 範例的部分 HTML 屬性以及 LOGO 連結可以移除,且
.active
部分也不使用,剩餘之整體 HTML 結構請加強默背。 - 超連結之目標位置可以提早或晚寫,這裡注意有 錨點連結 跟 model 呼叫(事後說明)兩種寫法。
<!-- 選單區 --> |
選單 CSS 重點:
- 選單列整體浮點靠右
- 設計整體選單區能根據滾動 沾黏至頂端 ,並消除原有的
margin-bottom
,另外拉至 99 層,避免被其他層級吃掉。
/* 選單區 */ |
廣告
為了讓網站有視覺效果,這裡用簡單的圖片背景跟文字描述(可從試題 PDF 進行文字複製)。這裡使用 section 為標籤,因為差異需求就必須有 class 名稱為 .ad
。
<!-- 廣告主題 --> |
廣告 CSS 重點:
- 背景圖由當天素材提供,自行挑選適合圖片放置在指定位置處,並注意 background 特性做中心不重複。
- 背景圖高度應該跟你的廣告區塊高度一致,譬如兩者高度都是 400px(用 Adobe 裁切圖片)。
- 為了讓 p 元素能在整個
.ad
中心,使用 flex 進行主軸與交軸皆為中心點。 - p 元素寬度應該跟
.container
窄版同寬,這樣窄版效果會一致。另外做內距跟半透明黑底之白字效果。
/* 廣告主題 */ |
留言
這裡會使用 section 標籤為 HTML 區域。比起前面來說相對複雜,有以下設計要點。
關於主題區域部分:
- 使用窄版
section.container
,並內含一個 h2 為標題。 - 我們需要一個 a 超連結來呼叫 modal,model 的原理稍晚進行說明,只需注意
a[data-toggle="modal"]
為必寫。 a[data-toggle="modal"]
為了好看,在行內樣式做 float:right 效果,但為了消除後面的 float 溢位需補充<div style="clear: both;"></div>
強制消除後續的浮動機制。- 我們需要提供給選單做錨點連結至該主題,為了錨點效果良好,改為在
section
之前增加div#
做為替代品。
- 使用窄版
關於留言部分:
- 會有一個以上(資料庫比數)的
div.row-fluid
為每則留言區塊;分為一般跟已刪除兩種留言版型可能,各做一組方便之後 PHP 套用。 - 每一個留言區塊會使用 BS grid system 做設計 span2+sapn10;span2 會提供人像、人名、編號,span10 會提供內容、電話、信箱、時間與修改和刪除鍵(提供管理員)。
- 修改與刪除鍵只有後台需要,你可以先設計在前台 index.html,之後快速複製成 admin.html 後,再移除原本 index.html 的這個多餘部分。
- 修改導向到 modal 且為
#msgmdy
;刪除的導向目標為api.php?do=msgdel&id=0
,這裡的 id 是指資料表內的索引編號也要一併告知 PHP 做處理。 - 人像題目雖然沒有要求,為了版面好看建議自行到 AI 設計 user.jpg(100*100),並注意使用 HTML 綁定 100*100 寬高。
- 流水號編號請額外用 span.sn 包覆,方便之後 PHP 操作。
- 這裡會使用不少 BS 的 CSS 外觀優化。
- 會有一個以上(資料庫比數)的
小技巧:
- 使用 .btn .btn-{color} 為按鈕美化。
- 使用 .thumbnail 能提供白底與圓角化的卡片效果。
- 使用 .img-circle 能幫我們把圖片圓形化。
- 使用 .badge .badge-{color} 能產生圓角化背景色。
- 除了電話 icon 可用
<span>☎</span>
,其他 icon 我們能用 Icons by Glyphicons 來美化。
<!-- 留言板 --> |
留言 CSS 重點:
關於主題區域部分:
- section 到時候一共有 2+1 大格,唯獨
section.ad
外觀不同需要排除指定。 - section 上邊緣處使用 margin-top 撐開與前者的距離,並本身黑底背景色。
- 讓版面至少有一個畫面高,section 最小高度大約為 800px,或用 cals 去計算 100vh -200px 更精準(螢幕高 100%減去上下 margin 的 80*2px 與 padding 20*2px)。
- 標題
h2
白色、每個留言部分div.row-fluid
為白底並修正padding:0
使版面切齊且用margin-top
讓留言板塊之間有間格。
- section 到時候一共有 2+1 大格,唯獨
留言部分:
- 留言內容
p
最少需要 100px 高(跟圖片高度 100px 切齊),且文字靠左。 - 留言下方的
div.bottom
區域為文字靠右、內距上下為 10px、且上緣有個虛線效果。 - 若是刪除留言的版本
div.del
,我們做半透效果並帶明顯紅字,添加 padding 上下內距 10px 可以更好看些。
- 留言內容
/* 留言板 */ |
參賽匹配
使用跟前者相同的 section 標籤結構與 CSS 外觀效果,可以省下一些工作,有以下設計要點。
關於主題區域部分:
- 跟前一項主題(留言板)相同,只是主內容變 table,結構為
section.container>h2+table
。 - table 有完整的結構
table>thead+tbody
,利於之後的 PHP 資料載入。 - 注意題目描述,這裡的主題名稱為 最新消息與賽制公告區塊。
- 也有 a 超連結來呼叫 modal 做我要參賽,但這部分已做在 Navbar 內。
- 同樣需要提供給選單做錨點連結至該主題增加
div#
做為替代品。
- 跟前一項主題(留言板)相同,只是主內容變 table,結構為
關於表格部分:
- 將會依賴 Bootstrap 來完成表格設計。須注意在 thead 這裡先分配好 100%空間(對
th
指定寬度),能讓表格整齊好看。 - 這裡的列顯示可能有兩種版面(單或雙),先設計成單數結束,後續 PHP 設計階段會再說明如何處理。
- 將會依賴 Bootstrap 來完成表格設計。須注意在 thead 這裡先分配好 100%空間(對
小技巧:
- 使用 .table .table-striped 能對表格美化且有單雙背景差異化。
<!-- 賽事版 --> |
賽事 CSS 重點:
關於主題區域部分:
- 與前者相同,這裡不用處理(只要你 css 的選擇器是正常發揮)。
表格部分:
- 表格所有子元素(對應文字)為白色與水平置中、所有文字欄位做垂直中心
- 為了單雙列好看,這裡使用偽類操作,做紅藍半透背景操作。
- 對表格內的圖片做圓角化處理,且限定寬高 50px。
/* 賽事版 */ |
Modal
Modal 是 Bootstrap Javascript 功能,能對應超連結(屬性 data-toggle=”modal” 且 href=#id)進行呼叫燈箱。因此我們集中放到 footer 且共有新增留言、編輯留言、我要參賽、帳號登入(四種 modal)需設計,可善用複製貼上修改局部代碼幫助減少工作量。
<footer> |
CSS 只需要設計與前者相同的外距離(上方)即可。
footer { |
小技巧:
- 使用 Bootstrap Modal 能以燈箱效果呼叫一個指定的 div 進行 pop 效果。
- 同上,需注意它需要超連結 a:link 方式且指定 [data-toggle=”modal”] 與 [href=”#id”],才能做對象燈箱呼應行為。
- 使用 form.form-horizontal>div.control-group>(label.control+input) 能幫助表單排版美化。
新增留言 (msgadd)
- 使用 form[method=”post”],且 action 到
api.php?do=msgadd
之後由 PHP 處理作業。 - 善用 modal 本身
.modal-header+.modal-body+.modal-footer
的三個區域使用。 - 所以表單輸入欄位都應該持有獨有的 name 名稱以及必填驗證功能 (required 與 pattern)。
<!-- Modal for msg add--> |
修改留言 (msgmdy)
- 使用 form[method=”post”],且 action 到
api.php?do=msgmdy
之後由 PHP 處理作業。 - 與前者 form#msgadd 相同類似,差別於修改部分多了 value 提供為預設舊值。
- 修改需要另提供 PHP 欲修改資料之指定編號,這裡需要多做一個
input:hidden
偷偷帶資料編號。 - 修改功能只有後台會提供,這裡先一併處理掉。之後設計 admin.html 時進行保留,反之 index.html 可移除(不移除也不會怎樣)。
<!-- for admin to msgmdy--> |
我要參賽 (pkadd)
- 與前者 form#msgadd 相同類似,使用 form[method=”post”],且 action 到
api.php?do=pkadd
之後由 PHP 處理作業。 - 由於需要檔案上傳,這裡需增加屬性
form['enctype="multipart/form-data"]
方能成功傳遞檔案給 PHP。
<!-- for pkadd --> |
後台登入 (login)
- 與前者 form#msgadd 相同類似,使用 form[method=”post”],且 action 到
api.php?do=login
之後由 PHP 處理作業。 - 雖題目未表達明確,我們將管理員登入與玩家登入做合併處理,因此 PHP 端需要額外判斷兩種身分可能。
- 驗證碼部分請使用 svg(約 250*50)進行設計,注意保留
1234 作為驗證值變化使用。
<!-- for login --> |
後台設計
- 大致結構相同一致,可從 index.html 複製為 admin.html。再將不必要的元素進行移除。
- 留言區:標題為玩家留言版後台管理請留意。
- 選單區:調整內容為回前台與登出(導向到
api.php?do=logout
)。 - 留言區:移除新增留言功能,這是前台的功能,後台不需要。
- Modal 區:後台需移除廣告區、賽事列表,另外 footer 部分僅保留 修改用 modal 即可;前台移除 footer 之修改用 modal(非必要不影響)、以及移除修改刪除按鈕。
<body> |
資料庫規劃 (MySQL)
使用 XAMPP 的 MySQL 服務之一,你需要自行建立資料庫 db00(00 為你的應考座號)並提供 2 個資料表 (pk,msg),並適時的塞入一些數據方便測試與驗收作業。各項資料表如下:
msg
- 資料表建立
msg
,資料 5 筆
# | 名稱 | 型態 | 編碼與排序 | 屬性 | 空值 | 預設值 | 備註 | 額外資訊 |
---|---|---|---|---|---|---|---|---|
1 | id | int(10) | UNSIGNED | 否 | 無 | AUTO_INCREMENT | ||
3 | user | text | utf8mb4_unicode_ci | 否 | 無 | |||
3 | info | text | utf8mb4_unicode_ci | 否 | 無 | |||
3 | text | utf8mb4_unicode_ci | 否 | 無 | ||||
3 | tel | text | utf8mb4_unicode_ci | 否 | 無 | |||
3 | date | datetime | 否 | 無 | ||||
2 | del | int(11) | 否 | 無 |
id | user | info | tel | date | del | |
---|---|---|---|---|---|---|
1 | User A | 留言內容A | aa@gmail.com | 02-02345678 | 2020-07-20 10:23:04 | 0 |
2 | User B | 留言內容B | bb@gmail.com | 02-12345678 | 2020-07-20 11:28:02 | 1 |
3 | User C | 留言內容C | cc@gmail.com | 02-22345678 | 2020-07-20 12:51:02 | 0 |
4 | User D | 留言內容D | dd@gmail.com | 02-32345678 | 2020-07-20 13:55:54 | 0 |
5 | User E | 留言內容E | ee@gmail.com | 02-42345678 | 2020-07-20 14:51:25 | 0 |
pk
- 資料表建立
pk
(與前者相同你可以用複製節省時間),資料 5 筆
# | 名稱 | 型態 | 編碼與排序 | 屬性 | 空值 | 預設值 | 備註 | 額外資訊 |
---|---|---|---|---|---|---|---|---|
1 | id | int(10) | UNSIGNED | 否 | 無 | AUTO_INCREMENT | ||
3 | user | text | utf8mb4_unicode_ci | 否 | 無 | |||
3 | info | text | utf8mb4_unicode_ci | 否 | 無 | |||
3 | text | utf8mb4_unicode_ci | 否 | 無 | ||||
3 | tel | text | utf8mb4_unicode_ci | 否 | 無 | |||
3 | date | datetime | 否 | 無 | ||||
2 | del | int(11) | 否 | 無 |
id | user | info | tel | date | del | |
---|---|---|---|---|---|---|
1 | User A | user.jpg | aa@gmail.com | 02-02345678 | 2020-07-20 10:23:04 | 0 |
2 | User B | user.jpg | bb@gmail.com | 02-12345678 | 2020-07-20 11:28:02 | 1 |
3 | User C | user.jpg | cc@gmail.com | 02-22345678 | 2020-07-20 12:51:02 | 0 |
4 | User D | user.jpg | dd@gmail.com | 02-32345678 | 2020-07-20 13:55:54 | 0 |
5 | User E | user.jpg | ee@gmail.com | 02-42345678 | 2020-07-20 14:51:25 | 0 |
小技巧:你應該具備且熟悉 SQL 指令 (INSERT、SELECT、UPDATE),若不熟悉請多利用 phpmyadmin 來取得範例指令。之後的 PDO 連線會連續使用到 SQL 指令。
後端處理 (PHP)
大致可分為五個檔案進行設計:
- index.php:將前面的 index.html 更改為 index.php,才能塞入 PHP 代碼提供前台之畫面處理。
- admin.php:將前面的 admin.html 更改為 admin.php,才能塞入 PHP 代碼提供後台之畫面處理。
- api.php:核心的 PHP 資料處理兩大功能,負責基礎設定以及所有的資料提交處理 (api.php?do=…)
- msg.php:前後台都有的留言板(差異於能否修改刪除),這裡獨立出來再匯入能兩份工作一次完成。
- pk.php:前獨有的賽事板,為了方便也一起獨立出來另匯入做開發。
新增 api.php 並進行已下基礎設定。
|
接下來我們會根據功能設計,不斷的添加代碼到這四筆檔案做進行編修。
站台登入
修改好副檔名後,我們開始對 index.php 提供登入功能,這裡還需要驗證碼。
前台的登入引導會有兩種可能,分別為未登入者引導到
api.php
,以及成功登入者直接到admin.php
。這機制需要session
來操作判斷。假定有個變數為
$_SESSION['user']
能代表登入狀態,如果未登入者為 guest,登入者可能是 admin 或用戶信箱號碼。先處理登入按鈕的顯示,在那之前需要先引用
session_start()
進來,最快是 include api.php 這個檔案。
增添到 index.php 到頁首處:index.php
include("api.php");接著於加入 $_SESSION[‘user’] 判斷處理:
api.php if (empty($_SESSION['user'])) $_SESSION['user'] = "guest";
接著判斷$_SESSION 是否為 guest 來決定登入的導向連結
修改:index.php <li><a href="#pkadd" data-toggle="modal">玩家參賽</a></li>
<li><a href="#login" data-toggle="modal">網站管理</a></li>為
index.php <li><a href="#pkadd" data-toggle="modal">玩家參賽</a></li>
需要驗證碼所以我們頁首處需要產生隨機數 1000~9999,注意此代碼必須於 include 之後
index.php include("api.php");
$_SESSION['rand']=rand(1000, 9999);接著調整 svg 的文字部分,找到
footer svg text
之數字進行替換,像是以下代碼index.php <text transform="matrix(1 0 0 1 12.505 23.5904)" style="font-size:24px;letter-spacing:7"><?= $_SESSION['rand'] ?></text>
可測試一下登入功能,並查看是否轉到 api.php?do=login 之畫面為何,並停留到此畫面勿離開。
增添代碼如下:api.php if (!empty($_GET['do'])) switch ($_GET['do']) {
case 'login':
print_r($_SESSION);
print_r($_GET);
print_r($_POST);
break;
}你可以這樣 print_r() 這些超全域變數做判斷。
接著我們要做驗證碼處理與後續處理,這裡會有三種狀況分別為:驗證碼錯誤、管理者登入、用戶登入(採 user Name 與 Mail),同時利用 JS 指令提供資訊並轉向到適合的頁面去。
調整case 'login'
內容為:api.php case 'login':
if ($_SESSION['rand'] != $_POST['ans'])
echo '<script>alert("驗證碼錯誤,請重新登入");location.href="index.php";</script>';
else if ($_POST['user'] == "admin" && $_POST['pwd'] == "1234") {
$_SESSION['user'] = "admin";
echo '<script>alert("歡迎管理員");location.href="admin.php";</script>';
} else {
$sql = "SELECT * FROM msg WHERE user='{$_POST['user']}' AND mail='{$_POST['pwd']}'";
$msglist = $db->query($sql)->fetchAll();
if ($msglist) {
$_SESSION['user'] = $_POST['user'];
$_SESSION['mail'] = $_POST['pwd'];
echo '<script>alert("歡迎,' . $_SESSION['user'] . '");location.href="admin.php";</script>';
} else echo '<script>alert("帳密錯誤,請重新登入");location.href="index.php";</script>';
}
break;此外我們需要對後台做個驗證機制,凡是沒有經過 api.php?do=login 索取得到$_SESSION[‘user’] 新值的人都給他踢回前台去。
admin.php
include("api.php");
if ($_SESSION['user'] == 'guest' || empty($_SESSION['user']))
echo "<script>alert('你沒有訪問權限,請回前台登入');location.href='index.php';</script>";
站台登出
這裡做個站台登出功能,方便我們前後台測試多種帳戶。
case 'logout': |
留言列表
這部分是共用在前後台的,唯一差別在於如果管理者或訪客都是全部顯示,如果是用戶管理則是限定個人顯示。如果是後者,巧的是驗證登入時我們已經 SELECT 過 DB 了,所以可以省下 SELECT 工作
將留言板挖空另存為
msg.php
。
修改index.php & admin.php <!-- each ok -->
<div class="thumbnail row-fluid">
<div class="span2">
<img src="img/user.jpg" class="img-circle" width="100" height="100">
<h4>User Name</h4>
<h5>#<span class="sn">1</span></h5>
</div>
<div class="span10">
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Possimus eligendi autem accusantium nam illo
commodi voluptates vero consectetur eum beatae?</p>
<div class="bottom">
<span class="badge badge-info">
☎ <span class="tel">0988-100200</span>
</span>
<span class="badge badge-info">
<i class="icon-envelope icon-white"></i> <span class="mail">sss@gmail.com</span>
</span>
<span class="badge badge-info">
<i class="icon-time icon-white"></i> 2020/02/02 12:00:00
</span>
<!-- for admin use -->
<!--
<span class="control">
<a href="#msgmdy" class="btn btn-warning" data-toggle="modal">編輯</a>
<a href="api.php?do=msgdel&id=0" class="btn btn-danger">刪除</a>
</span>
-->
</div>
</div>
</div>
<!-- each del -->
<div class="thumbnail row-fluid del">
<div class="span2">#2</div>
<div class="span10">此樓留言已被刪除</div>
</div>為
index.php & admin.php include("msg.php")
msg.php 需要一些判斷何種顯示,包含了:
- 是否為管理員(後台)或前台則要完整 SELECT,如果不是就拿之前登入時的驗證資料。
- 如果資料中有發現 del 成立,畫面上我們要調整為已刪除,否則正常顯示
- 如果頁面是前台,我們不能顯示 control(即使是管理員),這需要另一個判斷目前是 index.php 還是 admin.php。
- 之後還要使用 JS 處理加載數據,因此修改按鈕需加入 onclick 並觸發 JS 名為 setval 之函式操作。因此電話信箱也添加了
span.class
名稱
|
|
|
目前為止已經能正常顯示來自資料庫的留言資訊,接著是進行增加修改刪除作業。
新增留言
前面 modal 已完成表單設計,這裡只要檢查表單過來的資料為何,組合成 INSERT 指令輸出並轉回首頁即可。
case 'msgadd': |
修改留言
這裡的修改留言是後台功能,按下修改時我們必須幫使用者設定 value(舊值)。透過 JavaScript 來完成 DOM 的讀取與寫入。同時還要處理提交出去的表單修改。於該頁最後添加:
<script> |
case 'msgmdy': |
刪除留言
相對來說簡單些,只要提供 id 編號就能轉為 UPDATE 指令要求 del=1,我們不希望真的刪除掉資料。
case 'msgdel': |
比賽列表
雖然沒有共用前後台頁面,但避免程式碼過混亂我們也另抽取為 pk.php。
修改:index.php <tbody>
<tr>
<td>1</td>
<!--img's size=50*50-->
<td><img src="img/user.jpg"></td>
<td>User Name</td>
<td>VS</td>
<td>User Name</td>
<!--img's size=50*50-->
<td><img src="img/user.jpg"></td>
</tr>
<tr>
<td>2</td>
<!--img's size=50*50-->
<td><img src="img/user.jpg"></td>
<td>User Name</td>
<td>VS</td>
<td>等待匹配中。..</td>
<td></td>
</tr>
</tbody>為
index.php <tbody>
include("pk.php")
</tbody>我們需要判斷如果資料數是基數的要添加匹配中的資訊,反之不用。只是為了版面好看我們要用陣列來處理排序問題。
pk.php
<tr>
</tr>
比賽報名
也都是表單提交轉 INSERT 指令。比較特別的是這裡需要做圖片上傳,我們需要透過 PHP 將表單的$_FILE 進行複製到 img 資料夾內,接著抽取路徑之新檔案名稱一併 INSERT 上去。
case 'pkadd': |