--- # System prepended metadata title:海大餐飲外送系統-設計文件(SDD) --- # 軟體設計文件(SDD) - 專案名稱:海大餐飲外送系統(Bing2Go) - 撰寫日期:2025/11/25 - 發展者:林津瑄、郭浩、劉俊麟、宋辰星、黃俊源 --- ## 版次變更記錄 | 版次 | 變更項目 | 變更日期 | | --- | -------- | -------- | | 0.1 | 初版 | 2025/11/25 | | 0.2 | 更新類別圖與部屬環境 | 2025/12/21 | | 0.3 | 更新介面需求設計 | 2025/12/22 | | 0.4 | 更新使用者畫面設計 | 2025/12/24 | | 0.5 | | | | 1.0 | | | --- ## 目錄 1. [系統模型與架構 (System Model / System Architecture)](#1.-系統模型與架構-System-Model-/-System-Architecture) 2. [介面需求與設計 (Interface Requirement and Design)](#2.-介面需求與設計-Interface-Requirement-and-Design) 3. [流程設計 (Process Design)](#3.-流程設計-Process-Design) 4. [使用者畫面設計 (User Interface Design)](#4.-使用者畫面設計-User-Interface-Design) 5. [資料設計 (Data Design)](#5.-資料設計-Data-Design) 6. [類別圖設計 (Class Diagram)](#6-類別圖設計-Class-Diagram) 7. [實作方案 (Implementation Languages and Platforms)](#7.-實作方案-Implementation-Languages-and-Platforms) 8. [設計議題 (Design Issue)](#8.-設計議題-Design-Issue) --- ## 1. 系統模型與架構 (System Model / System Architecture) #### Contex diagram ![軟體工程(第七組)-C4 model.drawio (1)](https://hackmd.io/_uploads/BJOKX0Im-e.png) #### Container diagram ![軟體工程(第七組)-C4 model.drawio (3)](https://hackmd.io/_uploads/ByKyICUQ-l.png) --- #### 系統架構圖 web application展開: ```mermaid flowchart TD subgraph WebApplication["Web App (Nuxt 3 client)"] pages["Pages & Routes<br>(Nuxt Pages)"]:::component layout["Layout & UI Kit<br>(Vuetify Components)"]:::component store["Global State<br>(Pinia Stores)"]:::component auth["Auth Client<br>(JWT / Local Auth)"]:::component apiClient["API Client<br>($fetch / useFetch)"]:::component map["Map Widgets<br>(Leaflet)"]:::component notifications["User Feedback<br>(Snackbars)"]:::component i18n["Internationalization<br>(@nuxtjs/i18n)"]:::component wsClient["WebSocket Client<br>(Chat)"]:::component end subgraph ServerSide["Server Side (Nuxt 3 Nitro)"] Nitro["API Routes & Services<br>(server/api)"]:::server Mongoose["ODM<br>(Mongoose)"]:::server end actorCustomer([顧客]):::actor --> pages actorExternal([外送員]):::actor --> pages actorAdmin([管理員]):::actor --> pages pages --> layout pages --> store pages --> auth pages --> apiClient pages --> map pages --> notifications pages --> i18n pages --> wsClient auth --> apiClient store --> apiClient apiClient -->|"REST / JSON"| Nitro wsClient <-->|"WebSocket"| Nitro Nitro --> Mongoose Mongoose -->|"Query"| DB[(MongoDB)]:::database map -->|"Map Tiles"| OSM[(OpenStreetMap)]:::external classDef component fill:#cce5ff,stroke:#1f2937,stroke-width:1px; classDef actor fill:#fff,stroke:#1f2937,stroke-width:1px; classDef external fill:#f8f0ff,stroke:#6b21a8,stroke-width:1 ``` Api application (Server Side)展開: ```mermaid flowchart TD subgraph ServerSide["Server Side (Nuxt 3 Nitro)"] controllers["API Routes<br>(server/api)"]:::component wsHandler["WebSocket Handler<br>(server/routes/ws)"]:::component authService["Auth Service<br>(JWT / Local Auth)"]:::component restService["Restaurant Service<br>(CRUD / Search)"]:::component geoUtil["Geocoding Utility<br>(Nominatim + Cache)"]:::utility imageUtil["Image Utility<br>(ImgBB Upload)"]:::utility models["Mongoose Models<br>(User/Restaurant/Order/GeoCache)"]:::component end WebUI[(Web Application)]:::external <-->|"REST / JSON"| controllers WebUI <-->|"WebSocket"| wsHandler controllers --> authService controllers --> restService controllers --> imageUtil %% Services using Models authService --> models restService --> models wsHandler --> models %% Services using Utilities restService --> geoUtil %% Utilities using Models (for caching) geoUtil --> models %% External Connections geoUtil -->|"Forward Geocoding"| Nominatim[(Nominatim OSM)]:::external imageUtil -->|"Upload API"| ImgBB[(ImgBB)]:::external models -->|"Query / Save"| Mongo[(MongoDB)]:::external classDef component fill:#e0f2f1,stroke:#004d40,stroke-width:1px; classDef utility fill:#fff9c4,stroke:#fbc02d,stroke-width:1px; classDef external fill:#f8f0ff,stroke:#6b21a8 ``` --- #### 部署環境 系統採用 Nuxt 全站部署架構,以 ZEABUR 作為前端與後端的整合執行平台。前端頁面由 Nuxt 透過 ZEABUR 靜態輸出與 SSR 生成,API 端點則以 /api/** 自動映射為 Nitro Serverless Functions,經由 JWT 驗證後存取 MongoDB Atlas。地理座標解析需時則透過 Serverless 呼叫 Nominatim API。整體架構以單站式整併部署降低維運成本,同時保有完整服務邏輯與資料隔離。 另外配置備援節點於俊源的 Ubuntu 伺服器,並透過 Docker 容器化應用程式,以便在開發或維護過程中進行測試與驗證,確保部署環境一致、易於維護與管理。 ```mermaid flowchart TD User["使用者瀏覽器<br/>客戶 / 外送員 / 管理員"] --> |HTTPS + JWT| ZEABUR["ZEABUR<br>Fullstack Deployment (NUXT)"] subgraph ZEABUR Frontend["Nuxt 前端<br/>Vue3 SPA / SSR"] API["Serverless API<br/>/api/** (Nitro)"] end Frontend --> |"fetch('/api/**')"|API API -->|MongoDB Driver| DB["(MongoDB Atlas<br/>Cluster)"] API -->|HTTP GET + JSON| Nominatim["(Nominatim<br/>Geocoding API)"] ``` --- ## 2. 介面需求與設計 (Interface Requirement and Design) ### Auth | 介面名稱 | 提供者 | 使用者(前端模組) | Method / URL | Input | Output | 描述 | | ------- | ----- | --------------------- | ----------------------------- | ---------------------------------------------- | ----------------- | ----------- | | 使用者登入 | Auth | `/login` | POST `/api/auth/login` | email, password | token, userPublic | 驗證帳密並登入 | | 使用者註冊 | Auth | `/register` | POST `/api/auth/register` | name, email, password | token, userPublic | 建立帳號 | | 查詢登入者資料 | Auth | `UserStore` | GET `/api/auth/me` | JWT | userPublic | 用於自動登入與權限判斷 | | 更新我的資料 | Users | `/profile` | PATCH `/api/auth/me` | multipart form-data: name, address, phone, img | userPublic | 更新個資 | | 變更我的密碼 | Users | `/profile` | PATCH `/api/auth/me/password` | currentPassword, newPassword | success | 變更密碼 | ### Restaurants | 介面名稱 | 提供者 | 使用者(前端模組) | Method / URL | Input | Output | 描述 | | ------ | ----------- | -------------------------------------------- | --------------------------- | --------------------------- | ---------------------- | ----------- | | 搜尋餐廳 | Restaurants | `/customer/stores` | GET `/api/restaurants` | search, limit, skip | restaurants[] | 關鍵字搜尋 | | 取得餐廳詳細 | Restaurants | `/customer/stores/[id]` | GET `/api/restaurants/{id}` | id | restaurant | 顯示餐廳內容 & 菜單 | | 搜尋附近餐廳 | Restaurants | `/customer/stores` | GET `/api/restaurants/near` | address / search / distance | restaurants[]+distance | 依距離排序回傳餐廳 | ### Cart | 介面名稱 | 提供者 | 使用者(前端模組) | Method / URL | Input | Output | 描述 | | ------- | ---- | --------------------- | ---------------------- | ------- | ------------ | ---------- | | 取得購物車 | Cart | `/customer/cart` | GET `/api/cart` | JWT | cart | 查看購物車內容 | | 更新購物車商品 | Cart | `/customer/stores/[id]、/customer/cart` | POST `/api/cart/items` | items[] | cart | 新增或替換購物車商品 | | 計算外送費用 | Cart | `/customer/payment` | GET `/api/cart/delivery-fee` | customerLatitude, customerLongitude, restaurants | distance, deliveryFee | 根據顧客與餐廳距離估算外送費 | | 清空購物車 | Cart | `/customer/cart` | DELETE `/api/cart` | JWT | cart (empty) | 移除全部商品 | ### Order(顧客側) | 介面名稱 | 提供者 | 使用者(前端模組) | Method / URL | Input | Output | 描述 | | ---------- | ----- | ------------------------------------- | ------------------------------- | ------------------------------------- | -------- | -------- | | 建立訂單 | Order | `/customer/payment` | POST `/api/orders` | deliveryInfo, deliveryFee, arriveTime | order | 結帳並生成訂單 | | 查詢我的訂單 | Order | `/customer/orders` | GET `/api/orders?role=customer` | JWT | orders[] | 顧客查訂單列表 | | 查詢訂單細節 | Order | `/customer/order-state/[id]、customer/orders/[id]` | GET `/api/orders/{id}` | id | order | 顯示訂單資訊 | | 訂單聊天紀錄 | Order | `/customer/order-state/[id]/chat` | GET `/api/orders/{id}/chats` | id | messages | 顧客與外送員聊天 | | 發送聊天訊息 | Order | `/customer/order-state/[id]/chat` | POST `/api/orders/{id}/chats` | role=customer, content | message | 顧客傳送訊息 | | 更新訂單狀態(收貨) | Order | `/customer/order-state/[id]` | PATCH `/api/orders/{id}/status` | customerStatus | order | 顧客更新訂單階段 | ### Order(外送員側) | 介面名稱 | 提供者 | 使用者(前端模組) | Method / URL | Input | Output | 描述 | | ---------- | ----- | --------------------------------------- | ----------------------------------- | ------------------------ | -------- | ----------- | | 查詢可接單列表 | Order | `/delivery/customer-orders` | GET `/api/orders/available` | keyword, sortBy, lat/lon | orders[] | 查詢可接的訂單 | | 接單 | Order | `/delivery/customer-orders/[id]` | PATCH `/api/orders/{id}/accept` | id | order | 外送員接單 | | 查詢我接的訂單 | Order | `/delivery/orders` | GET `/api/orders?role=delivery` | JWT | orders[] | 外送員查詢自己接的訂單 | | 更新訂單狀態(送餐) | Order | `/delivery/customer-orders/[id]` | PATCH `/api/orders/{id}/status` | deliveryStatus | order | 外送員更新狀態 | | 聊天(外送員) | Order | `/delivery/customer-order-state/[id]/chat` | GET & POST `/api/orders/{id}/chats` | content / role=delivery | messages | 與顧客聊天 | ### Reviews | 介面名稱 | 提供者 | 使用者(前端模組) | Method / URL | Input | Output | 描述 | | ------- | ---- | --------------------- | ---------------------- | ------- | ------------ | ---------- | | 取得餐廳評論 | Reviews | `/customer/stores/[id]/reviews` | GET `/api/reviews` | restaurantId, sort, skip, limit | reviews[] | 取得特定一家餐廳的所有評論 | | 建立新評論 | Reviews | `/customer/stores/[id]/reviews` | POST `/api/reviews` | restaurantId, rating, content | review | 顧客對餐廳做出評價 | ### Admin | 介面名稱 | 提供者 | Method / URL | 使用者(前端模組) | Input | Output | 描述 | | ------------------ | ------------------- | -------------------------------------------------- | -------------------------------------- | ------------------------------ | ------------- | -------------------------- | | 搜尋餐廳(含下架) | Admin → Restaurants | GET `/api/admin/restaurants` | `/admin/stores` | search, geocode | restaurants[] | 後台餐廳清單 | | 新增餐廳 | Admin → Restaurants | POST `/api/admin/restaurants` | `/admin/stores/new` | multipart form | restaurant | 建立餐廳 | | 更新餐廳 | Admin → Restaurants | PATCH `/api/admin/restaurants/{id}` | `/admin/stores/[id]` | multipart form | restaurant | 修改餐廳資訊 | | 刪除餐廳 | Admin → Restaurants | DELETE `/api/admin/restaurants/{id}` | `/admin/stores/[id]` | id | success | **永久刪除(需二次確認)** | | 新增菜單項目 | Admin → Menu | POST `/api/admin/restaurants/{id}/menu` | `/admin/stores/new、admin/stores/[id]` | multipart form | menuItem | 新增商品 | | 修改菜單項目 | Admin → Menu | PATCH `/api/admin/restaurants/{id}/menu/{menuId}` | `/admin/stores/[id]` | multipart form | menuItem | 修改商品內容 | | 刪除菜單項目 | Admin → Menu | DELETE `/api/admin/restaurants/{id}/menu/{menuId}` | `/admin/stores/[id]` | id, menuId | success | 移除商品 | | 查詢所有訂單 | Admin → Orders | GET `/api/admin/orders` | `/admin/orders` | completed / from / to / sortBy | orders[] | 監看訂單 | | 停用會員 | Admin → Users | PATCH `/api/admin/users/{id}/ban` | `/admin/users/[id]` | id | success | 封鎖帳號 | | 解停用會員 | Admin → Users | PATCH `/api/admin/users/{id}/unban` | `/admin/users/[id]` | id | success | 解除封鎖 | | 刪除評論 | Admin → Reviews | DELETE `/api/admin/reviews/{id}` | `/admin/stores/[id]/reviews` | id | success | 刪除評論 | 本系統前後端以 RESTful API 為介接方式。 介面提供者(後端模組)依功能分為 Auth、Users、Restaurants、Cart、Order、Reviews、Admin 六大模組;介面使用者為前端各獨立頁面/模組。 所有跨模組溝通均透過 HTTP + JSON 進行,不直接共享資料庫,並以 JWT 控制授權與角色權限。 因此系統具備清楚的責任劃分、低耦合與高延展性,利於後續擴充(如通知、支付、店家後台)。 --- ## 3. 流程設計 (Process Design) ![截圖 2025-11-20 上午11.46.40](https://hackmd.io/_uploads/BJRQJf2xWx.png) ![截圖 2025-11-20 上午11.48.31](https://hackmd.io/_uploads/SJpq1G3eWl.png) ![截圖 2025-11-20 上午11.49.22](https://hackmd.io/_uploads/S1GA1z2xWl.png) ![截圖 2025-11-20 上午11.51.17](https://hackmd.io/_uploads/HJMrlzng-e.png) ![image](https://hackmd.io/_uploads/SkGqklM-We.png) ![截圖 2025-11-20 上午11.50.40](https://hackmd.io/_uploads/B1pflM3xZg.png) ![截圖 2025-11-20 上午11.52.46](https://hackmd.io/_uploads/By55xG3lZg.png) ![截圖 2025-11-20 上午11.53.29](https://hackmd.io/_uploads/ByLaxzhebl.png) ![image](https://hackmd.io/_uploads/HJ341ezZZg.png) ![image](https://hackmd.io/_uploads/HyW1lxzbZx.png) ![截圖 2025-11-20 上午11.54.57](https://hackmd.io/_uploads/HJlmWzngWx.png) --- ## 4. 使用者畫面設計 (User Interface Design) #### 登入 ![image](https://hackmd.io/_uploads/rJkv9uu7be.png) ![image](https://hackmd.io/_uploads/H1UPqudmbe.png) 尚未登入的使用者進入系統所看到的畫面,使用者可在此頁面透過輸入電子郵件、密碼及選擇身分並按下「登入」登入帳號。若帳號與密碼輸入錯誤,系統會顯示錯誤訊息並要求重新輸入。若使用者還沒註冊帳號可以按下「建立帳號」註冊帳號。若使用者忘記密碼,可以按下「忘記密碼?」。按下右下角的"A/文"按鈕可以切換中/英文。 #### 註冊 ![image](https://hackmd.io/_uploads/BJLY9_d7-g.png) ![image](https://hackmd.io/_uploads/SkVpq_OQWe.png) 尚未註冊帳號的使用者可以在這個頁面填寫必要資訊(暱稱、email、密碼)後並按下「立即註冊」即可註冊帳號,註冊成功會自動跳轉到登入頁面。也可以先填寫預設外送地址、聯絡電話,作為將來下單或接單時的預設資料。預設會隨機產生一張頭像,按下建立帳戶下方的圓圈也可以上傳頭像。想回到登入頁面可以按「已有帳號?前往登入」。按下右下角的"A/文"按鈕可以切換中/英文。 --- ### 顧客 #### 瀏覽餐廳 ![image](https://hackmd.io/_uploads/r1hGjuuX-x.png) 顧客登入後會跳轉到此頁面。按下頂部 navbar 左上方「瀏覽店家」也能跳轉到此頁面。按下「電資暨綜合教學大樓」可以選擇預設地點或編輯外送地址,如果一開始沒有填寫地址預設為電資暨綜合教學大樓。按下「搜尋餐廳、美食」可以輸入想查詢的餐廳名稱或關鍵字,會根據搜尋內容顯示下方的餐廳列表。也可以按下「咖哩」或「中式」等篩選條件來篩選餐廳。按下下方餐廳列表中的餐廳卡片會跳轉到餐廳詳細資料頁面。 #### 餐廳詳細資訊 ![image](https://hackmd.io/_uploads/HyQEjOOmWe.png) 該頁面會顯示餐廳的名稱、星數、簡介、地址、電話、菜單。在下方的菜單中,按下餐點右邊的「+」可以進入「餐點詳細資訊」頁面。按下「查看評論/撰寫評論」可以進入「餐廳評價」頁面。 #### 餐廳評價 ![image](https://hackmd.io/_uploads/rJsDbtOQbl.png) 該頁面顯示所有此餐廳的評價,包含評價顧客暱稱、頭像、時間、內容、星數。顧客也可以填寫評價,選擇星數、填寫內容,並按下「送出評價」。可使用排序方式來排序顯示的評價卡片。 #### 餐點詳細資訊 ![image](https://hackmd.io/_uploads/B1wP-0llWl.png) 該頁面會顯示餐點的簡介、價格。在下方透過「+」「-」選擇餐點數量,並按下「馬上冰!」,即可將餐點加入購物冰箱。按下頂部 navbar 右上角的購物冰箱 icon 可以跳轉到購物冰箱頁面。 #### 購物冰箱 ![image](https://hackmd.io/_uploads/SkvdoduQbl.png) 該頁面會顯示所有被加入購物冰箱的餐點,可以點餐點右邊的「+」和左邊的「-」來修改餐點數量。可以在頁面右邊瀏覽訂單的小計、總金額和預估的外送費。可以按下「前往結帳」跳轉到結帳頁面。 #### 結帳 ![image](https://hackmd.io/_uploads/HyBlnO_7Zl.png) 在「外送詳細資訊」區域可以讓顧客確認並修改成立訂單必要的資訊,包含外送地址、聯絡人暱稱、連絡電話和備註。下方的「付款方式」區域可以選擇付款方式,目前系統只支援「現場付款」。在右方的「訂單摘要」區域確認餐點的數量、價格、預估時間後,按下「確認送出訂單」即可下單,接著會跳轉到訂單狀態頁面。 #### 訂單狀態 ![image](https://hackmd.io/_uploads/ByEwau_X-g.png) ![image](https://hackmd.io/_uploads/SkaDaOdm-g.png) 可以在頁面上方的進度條中確認訂單的狀態,有沒人接QAQ、在路上、已接收、已完成四種狀態。外送員接單後,可以確認外送員的暱稱、頭像和電話。可以在下方確認訂單和餐廳的詳細資訊。可以在下方的地圖看到外送員、顧客、餐廳的位置和路徑。按下頂部 navbar 左上角的「我的訂單」可以跳轉到訂單列表頁面。按下「我已收到餐點」按鈕後可以將訂單狀態設定為已接收。當顧客按下「已接收」以及外送員按下「已送達」系統會將訂單狀態設定為完成。按下「聯絡外送員」可以開啟此訂單的即時通訊。 #### 訂單列表 ![image](https://hackmd.io/_uploads/Hy-bAuOXbx.png) ![image](https://hackmd.io/_uploads/SkFlA_d7Wg.png) 按下「未完成」或「已完成」可以瀏覽正在處理的訂單和歷史訂單。可以按下「查看詳情」跳轉到訂單狀態頁面。 #### 帳號資訊 ![image](https://hackmd.io/_uploads/BkX_A_uQ-e.png) 按下頂部 navbar 右上角的使用者 icon 可以跳轉到我的帳戶頁面。可以在這個頁面修改暱稱、預設外送地址、連絡電話、密碼,按下「儲存變更」完成修改。按下頭像可以更換頭像。下方的身分管理欄位會有一個按鈕,使用者可以透過此按鈕切換現在的身分。按下「登出」可以登出帳號。 --- ### 外送員 #### 顧客訂單 ![image](https://hackmd.io/_uploads/B1K-Dpegbl.png) 按下頂部 navbar 左上角的「顧客訂單」,該頁面可以看到所有待處理的訂單,可以瀏覽訂單要取、送的地點、地址、預計送達時間及報酬。可以根據排序和搜尋快速找到符合要求的訂單。點擊「查看並接單」可以跳轉到訂單資訊頁面。 #### 訂單資訊 ![image](https://hackmd.io/_uploads/S1kYOaxxbl.png) 該頁面可以看到取餐餐廳、取餐地址、外送地點、預計送達時間、顧客暱稱、顧客電話、訂單內容、外送費。按下「立即接單」可以接訂單,並跳轉到訂單狀態頁面。 #### 訂單狀態 ![image](https://hackmd.io/_uploads/ryghR_d7be.png) ![image](https://hackmd.io/_uploads/rk_3COOQbx.png) ![image](https://hackmd.io/_uploads/BkK0RuuQWg.png) 該頁面可以看到取餐餐廳、餐廳地址、餐廳電話、取餐品項、外送地址、顧客暱稱、顧客電話和顧客備註。可以在下方的地圖看到外送員、顧客、餐廳的位置和路徑。當外送員已送達餐點時,按下「已送達」可以將訂單狀態改為已送達。當顧客按下「我已收到餐點」以及外送員按下「已送達」系統會將訂單狀態設定為完成。按下「聯絡顧客」可以開啟此訂單的即時通訊。 #### 訂單列表 ![image](https://hackmd.io/_uploads/H1nKyY_Xbx.png) ![image](https://hackmd.io/_uploads/H1rqkKOX-l.png) 按下頂部 navbar 左上角的「我的訂單」,可以跳轉到訂單列表頁面。按下「當前任務」和「歷史訂單」可以瀏覽正在處理的訂單和歷史訂單。按下當前任務列表中的「查看詳情」,可以跳轉到訂單狀態頁面。 --- ### 管理員 #### 管理店家 ![image](https://hackmd.io/_uploads/S1t6yYd7-x.png) 身份為管理員的用戶在登入後會進到管理店家頁面,該頁面會有所有餐廳列表,按下餐廳卡片或右邊的「編輯」會跳轉到餐廳詳細資訊頁面,按下「查看評論」會跳轉到餐廳評價管理頁面。按下「新增餐廳」可以跳轉到新增餐廳頁面。在搜尋欄輸入餐廳名稱可以搜尋餐廳。按下頂部 navbar 右上角的登出 icon 可以登出系統。 #### 餐廳評價頁面 ![image](https://hackmd.io/_uploads/HyitMYd7be.png) 管理員可以在這個頁面看到所有此餐廳的評價,包含顧客暱稱、頭像、評論時間、內容、星數。並可使用排序來快速找到符合條件的評價。按下評論右邊的「刪除評論」,可以刪掉對應評論,用來避免顧客惡意評價。 #### 餐廳詳細資訊頁面 ![image](https://hackmd.io/_uploads/BJ-kMAIXWx.png) 管理員可以在這個頁面編輯餐廳的資訊,包括名稱、介紹、地址、電話;可以編輯菜單的資訊,包含餐點照片、餐點名稱、價格、介紹,按下餐點右邊的垃圾桶 icon 可以刪除餐點,按下「儲存所有變更」完成修改。按下下方的「新增菜單項目」可以新增餐點。按下上方的「查看評論」會跳轉到餐廳評價頁面。 #### 新增餐廳 ![image](https://hackmd.io/_uploads/S19bGR8Q-l.png) 在填寫必要的資訊(名稱、介紹、地址、電話、封面圖片)後按下「建立餐廳」可以新增餐廳到列表中。按下下方的「新增菜單項目」可以新增餐點,包含餐點照片、餐點名稱、價格、介紹,按下餐點右邊的垃圾桶 icon 可以刪除餐點。 #### 查看訂單 ![image](https://hackmd.io/_uploads/B1UlxY_QZx.png) ![image](https://hackmd.io/_uploads/rkhGeYOQ-e.png) 按下頂部 navbar 左上方的「查看訂單」可以跳轉到此頁面。按下「未完成」和「已完成」可以瀏覽所有現在正在處理和已經完成的訂單。會顯示訂單的編號、狀態、顧客資訊、外送員資訊、訂單價格。按下訂單可以跳轉到訂單詳細資訊頁面。按下日曆 icon 可以篩選指定日期範圍的訂單。也可依條件選擇排序方式。 #### 訂單詳細資訊 ![image](https://hackmd.io/_uploads/BkeNlF_m-e.png) ![image](https://hackmd.io/_uploads/rkPHlKuXZx.png) ![image](https://hackmd.io/_uploads/S1FLxYdmbl.png) 該頁面可以看到訂單的編號、狀態、顧客暱稱、收件人資訊、餐廳資訊、外送地址、外送員、外送員電話、訂單內容與金額、外送費。可以在下方的地圖看到外送員、顧客、餐廳的位置和路徑。 #### 管理會員 ![image](https://hackmd.io/_uploads/BJ7KxKO7Wg.png) 按下頂部 navbar 左上方的「管理會員」可以跳轉到此頁面。此頁面會顯示所有使用者的列表。會顯示使用者的暱稱、頭像、email、身份及建立時間。按下使用者會跳轉到會員詳細資訊頁面。在搜尋欄輸入使用者暱稱或 email 可以查詢使用者,也可依排序依據、排序方式做篩選。 #### 會員詳細資訊 ![image](https://hackmd.io/_uploads/HyyixYdQ-g.png) ![image](https://hackmd.io/_uploads/rkRilF_XZx.png) 此頁面會顯示使用者的 ID、暱稱、頭像、email、外送地址、電話、身份、建立時間。按下「停用此帳號」可以使該使用者無法再使用本系統(管理員無法被停用)。 --- ## 5. 資料設計 (Data Design) {%hackmd H1aWnvrQ-e %} --- ## 6. 類別圖設計 (Class Diagram) {%hackmd BJ_sdPr7-e %} --- ## 7. 實作方案 (Implementation Languages and Platforms) ### 開發架構與技術 - 採用 Responsive Web Design,確保各種裝置皆有良好使用體驗。 - 前後端整合使用 Nuxt.js 進行開發 - 介面採用 Vuetify 作為 UI Framework - 資料儲存採 MongoDB Atlas - 利用 GitHub Actions 進行持續整合與自動部署: - 系統主要部署於 ZEABUR 雲端平台 - 使用俊源的 Ubuntu 伺服器作為備援節點 ### 部署環境 系統採用 Nuxt 全站部署架構,前端與後端整合於 ZEABUR 執行。 - 前端頁面由 Nuxt 透過 靜態輸出與 SSR 生成,提升載入速度與 SEO。 - API 端點以 `/api/**` 映射為 Nitro Serverless Functions, 經 JWT 驗證後存取 MongoDB Atlas。 - 地理座標解析透過 Serverless 呼叫 Nominatim API,處理需時的地理資訊需求。 - 整體架構以單站式整合部署,降低維運成本,並保有完整服務邏輯與資料隔離。 為提升開發及維護效率,系統另配置備援節點於俊源的 Ubuntu 伺服器,並透過 Docker 容器化 Nuxt 前端與 API 服務,以便在開發或維護過程中進行測試與驗證。 --- ## 8. 設計議題 (Design Issue) ### 議題 1:大量資料載入與渲染效能優化 - 議題內容:資料庫中的餐廳資訊、歷史訂單記錄及使用者資料會累積成龐大的數據量,若在前端頁面嘗試一次性透過API獲取所有資料,將導致API回應延遲、前端渲染負擔和伺服器資源耗盡等問題。 - 可能解決方案: - 維持一次性載入 - 傳統頁碼分頁 - 滾動載入 - 最後解決方案與理由:最後決定採用"滾動載入",因為可提升使用者體驗,無限捲動能提供不中斷的沉浸式瀏覽體驗,也能降低首次載入時間。 ### 議題 2 如何在系統中添加創意又獨特的內容 - 議題內容:原本的系統在外觀及功能上過於死板,缺乏有趣或令人驚豔的設計。且系統和"軟體工程"的關聯性較弱,僅作為一個單純的餐飲外送系統,缺乏和此課程的連結。 - 可能解決方案: - 在系統介紹頁面添加軟體工程課程介紹 - 改變常用介面元素命名,並將教授的名字融入系統中 - 最後解決方案與理由:最後決定採用方案二,將常見的購物車改為購物冰箱,加入購物車改為馬上冰,因為購物冰箱的意象比購物車更貼合餐飲,且能有效增加使用者的操作樂趣,並形成系統的記憶點。 ### 議題 3 在不干擾主要操作流程的前提下加入額外資訊展示 - 議題內容:系統需展示課程介紹、平台活動等額外資訊,但若直接放入主介面,可能造成資訊過度堆疊,使畫面雜亂,降低使用者的操作效率。因此需要選擇合適的介面呈現方式,在保持頁面整潔的前提下,提升資訊可見性。 - 可能解決方案: - 將所有活動或介紹整合至主頁固定區塊 - 另開獨立導覽頁顯示 - 採用彈窗式廣告於適當時機顯示 - 最後解決方案與理由:採用「彈窗式廣告」。此方式可維持主畫面整潔,避免大量資訊佔據主要視覺空間,同時能於使用者有空閒或關鍵時點顯示必要資訊,提升資訊曝光度與使用者體驗。 ### 議題 4 品項尺寸(M / L / XL)規格設計疏漏 - 議題內容:系統在一開始設計資料表與前端畫面時,只將「品項」視為單一規格,沒有預留 M、L、XL 等不同尺寸的欄位與選項。後期導入實際餐點資料及外送平台菜單時才發現,多數飲品與餐點都有不同容量或大小,若硬套用原本的單一規格設計,會導致價格、熱量、庫存等資訊無法正確對應,也不利於未來功能擴充。 - 可能解決方案: - 重新設計資料模型,完整支援多尺寸 - 以不同尺寸視為不同品項 - 暫時統一為單一尺寸(例如 L) - 最後解決方案與理由:先統一使用外送平台資料中的 L 尺寸作為標準尺寸,目前系統功能的核心在「訂餐流程」與「資料串接」,對「多尺寸選擇」的依賴度較低,因此先固定為 L 不會影響主要流程。 ### 議題 5 圖片儲存方式與資料庫空間管理 - 議題內容:系統需要在頁面中顯示餐點或店家的圖片,一開始直覺是「把圖片直接存進資料庫」,但實作時發現: - 圖片檔案體積較大,若直接存成 BLOB 會讓資料庫變得肥大、備份與還原速度變慢。 - 前端要顯示圖片時,需要透過後端再轉檔或串流,流程較複雜。 - 資料庫本身並不是為大量檔案儲存設計,長期擴充會遇到效能與空間問題。 因此必須重新思考圖片的儲存策略。 - 可能解決方案: - 圖片直接存入資料庫(BLOB / Base64) - 圖片存放在本機伺服器檔案系統,只在資料庫存檔案路徑 - 使用第三方圖床服務(例如 imgbb),資料庫只存圖片 URL - 最後解決方案與理由:最後決定 採用第三方圖床服務 imgbb,圖片先上傳到 imgbb,取得 URL 後再將該 URL 存入資料庫。前端顯示圖片時,只要將 URL 綁定到 `<img>` 的 src 即可,不需要額外寫圖片串流或檔案下載的 API,開發流程更單純。