SE-第七組
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- # 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,開發流程更單純。

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully