1.1功能模塊實現
1.1.1整體結構
界面由兩部分組成:左側導航欄、右側內容展示區。使用了 Bootstrap 5 的樣式庫,并結合了 ASP.NET MVC 的 @Html.ActionLink 和 Razor 條件判斷語句來動態生成菜單項。
1.1.2導航欄功能模塊
導航欄基礎結構
導航欄基礎結構使用 Bootstrap 的 navbar 類構建響應式導航欄。flex-column align-items-start 表示導航欄是垂直方向排列的。
響應式按鈕
展示區顯示折疊菜單按鈕使用data-bs-toggle="collapse" 控制展開/收起。
動態菜單
根據用戶登錄狀態和角色不同,顯示不同的菜單項。
登錄前:顯示“登錄”選項
登錄后:設計用戶角色:
店主功能用戶管理、花卉管理、訂單管理;普通用戶功能購物車、訂單界面、客服界面;管理員功能用戶管理、花卉管理、花店訂單管理。
商品搜索框
使用Ajax.BeginForm 實現異步搜索鮮花的功能,無需刷新頁面即可更新商品列表。
3.1.2右側內容展示區
主體內容容器使用 flex-grow-1 確保內容區域自動擴展以填滿剩余空間。
@RenderBody() 是 MVC 布局頁中的占位符,表示子頁面的內容會在此處插入。
3.1.3主要功能模塊
模塊 | 功能說明 |
導航欄 | 實現響應式菜單,支持不同用戶角色(管理員、店主、顧客)的不同菜單項。 |
權限控制 | 根據 Session 中的角色信息動態渲染菜單內容。 |
搜索功能 | 使用 AJAX 實現無刷新搜索,提升用戶體驗。 |
內容展示區 | 支持子頁面內容動態加載,保持統一風格。 |
腳本管理 | 集中式引入常用腳本庫,允許子頁面添加自定義腳本。 |
?
3.2控制器介紹
3.2.1購物車控制器
通過多個Action 方法來實現添加、修改、刪除購物車內容以及顯示購物車信息等操作。
(1)?Index()
獲取當前登錄用戶的 ID。查詢該用戶的所有購物車條目,并包含關聯的 Flowers 和 Users 數據。計算購物車中所有商品的總價(單價 × 數量),傳遞給視圖。返回視圖并展示購物車列表。依賴 Session["UserID"] 來判斷當前用戶。
(2)?InsertCart(int flowerID)
判斷用戶是否登錄(Session 是否存在 UserID)。判斷用戶身份是否是管理員或店主,如果是,則不允許購買。檢查該用戶是否已將此商品加入過購物車:若沒有,新增一條記錄;若有,將數量加一。保存更改后返回提示信息。使用了 JavaScript 提示框 (<script>alert(...)</script>) 并返回上一頁。
(3)?AddOne(int id)
根據 CartID 查找購物車條目。將商品數量加一。更新數據庫狀態并保存。
(4)?MinusOne(int id)
同樣根據 CartID 查找購物車條目。商品數量減一:若數量變為 0,則直接刪除該條目;
否則更新數量。
(5)?Delete(int id)
刪除指定 ID 的購物車條目。保存更改后跳轉回購物車首頁。
3.2.2購物車控制器
用于處理與訂單(Order)相關的操作。它使用了 ASP.NET MVC 框架,并結合 Entity Framework 實現對數據庫中訂單數據的訪問和管理。
(1)Index()
功能:展示訂單列表。權限控制:如果未登錄(Session["RoleName"]為空),跳轉到登錄頁。如果是“管理員”或“店主”,顯示全部訂單。如果是普通用戶,則只顯示當前用戶的訂單。
(2)UpdateOrderState(int id, int state)
功能:根據傳入的狀態值更新訂單狀態。參數說明:id: 訂單IDstate: 狀態碼(應映射為枚舉 OrderState)表示訂單的狀態。
3.3 技術介紹
3.3.1購買的倒計時功能
獲取DOM元素:通過document.querySelector('.btn-gradient') 和 document.getElementById('countdown') 分別獲取按鈕和倒計時提示框的引用。禁用按鈕:當函數開始執行時,首先禁用了按鈕防止重復點擊,并且改變了按鈕的文字內容為帶有旋轉圖標的“處理中…”以給用戶視覺反饋。初始化倒計時:將倒計時設定為3秒,并將這個數值顯示在倒計時框內。定時器邏輯:使用setInterval()方法每秒更新一次倒計時:減少剩余時間,并更新倒計時框中的數字。應用了一個名為countdown-pulse的CSS類,用于實現數字的跳動效果。根據剩余時間動態調整背景顏色,提供更豐富的視覺體驗。當倒計時結束(即seconds小于等于0),清除定時器,恢復按鈕的狀態,并導航到購物車頁面。
JS代碼解釋
function addToCart(flowerId) { ????// 獲取按鈕和倒計時元素 ????var button = document.querySelector('.btn-gradient'); ????var countdown = document.getElementById('countdown'); ? ????// 禁用按鈕并改變按鈕文本為加載狀態 ????button.disabled = true; ????button.innerHTML = '<i class="fa fa-spinner fa-spin"></i> 處理中...'; ? ????// 顯示倒計時框并應用動畫效果 ????countdown.style.display = 'inline-block'; ????countdown.classList.add('countdown-show'); ? ????let seconds = 3; // 設置倒計時秒數 ????const numberElement = countdown.querySelector('.countdown-number'); // 獲取倒計時數字元素 ????numberElement.textContent = seconds; // 初始化倒計時數字 ? ????// 開始定時器,每秒更新一次 ????const timer = setInterval(() => { ????????seconds--; // 每次循環減少一秒 ????????numberElement.textContent = seconds; // 更新倒計時數字 ????????numberElement.classList.add('countdown-pulse'); // 添加跳動動畫類 ? ????????// 動態修改背景顏色以增加視覺效果 ????????countdown.style.background = `linear-gradient(145deg, ????????????hsl(${seconds * 40}, 70%, 60%), ????????????#a363d9)`; ? ????????// 在每次添加跳動動畫類之后短暫延遲移除它,創建脈沖效果 ????????setTimeout(() => { ????????????numberElement.classList.remove('countdown-pulse'); ????????}, 200); ? ????????// 如果倒計時結束 ????????if (seconds <= 0) { ????????????clearInterval(timer); // 清除定時器 ????????????countdown.classList.remove('countdown-show'); // 移除動畫效果 ????????????setTimeout(() => { ????????????????countdown.style.display = 'none'; // 隱藏倒計時框 ????????????????button.disabled = false; // 啟用按鈕 ????????????????button.innerHTML = '立即購買'; // 恢復按鈕文本 ????????????????window.location.href = '@Url.Action("InsertCart","Cart",new { flowerID=Model.FlowerId})'; // 跳轉至購物車頁面 ????????????}, 500); ????????} ????}, 1000); // 每隔一秒鐘調用一次回調函數 } |
3.3.2花卉類別選擇功能介紹
視圖模型綁定
當前頁面綁定了一個 Flowers 類型的集合數據,用于展示默認或篩選后的花卉列表。
@model IEnumerable<FlowerShop.Models.Flowers> |
HTML結構的下拉菜單
使用了 ViewBag.flowerType 提供所有花卉類型的選項。每個 <option> 的 value 是花卉類型的 ID,提交后作為參數傳給后臺搜索方法。
<select id="flowerTypeSelect" name="flowertype" onchange="this.form.submit();"> ????<option value="" disabled selected>選擇花卉類型</option> ????@foreach (var flowertype in ViewBag.flowerType as List<FlowerShop.Models.FlowerTypes>) ????{ ????????<option value="@flowertype.FlowerTypeId">@flowertype.FlowerTypeName</option> ????} </select> |
Ajax 異步請求
表單使用了 Ajax.BeginForm 實現無刷新提交。提交時調用控制器 FlowersController 中的 SearchFlowerList(int? flowertype) 方法。返回結果更新到 #GoodShow 容器中,不會重新加載整個頁面。
@using (Ajax.BeginForm("SearchFlowerList", "Flowers", new AjaxOptions { ... })) |
?