跳到主要內容

FE Day 31 專案定義:預約系統的前端(設計與路由)



FE Day 31 專案定義:預約系統的前端(設計與路由)

執行需求:CPU 可跑。今天是「前端開發實戰:React 與 Next.js 全套」系列的第三十一天,也是「貫穿專案篇」的第一天。從今天起,連續 14 天(Day 31-44)我們要打造一個完整的「預約管理系統」前端,串接 Web 系列 Day 35-44 完成的 FastAPI 後端。今天不寫任何元件,只做最關鍵的一件事:把整個專案的「設計與路由」講清楚,把後續 13 天的所有決議都先攤出來。今天結束之前,你會拿到一張路由地圖、一份頁面盤點表、一組 API 端點對齊清單,以及一份 Day 32-44 都會沿用的命名與目錄慣例。

引言

很多 side project 失敗不是因為寫得不好,而是因為「寫到一半才發現當初沒想清楚」。今天的目的是把專案的「介面層」與「資料流」先畫清楚,後續每一天只負責實作其中一個區塊,不會再回頭做架構決策。這種「先設計、再實作」的節奏,是專業團隊與新手最大的差別:前者把爭議在白板階段解決,後者在寫程式時才發現「咦,這個頁面要叫 /admin 還是 /dashboard」。

貫穿專案的預約管理系統定位為「小型服務業的線上預約平台」,情境涵蓋攝影棚、健身教練、語言家教、諮詢工作室,所有資料皆為虛構示範。系統有兩種角色:服務提供者(admin)與客戶(customer)。前端要做的事包含「讓客戶可以看服務、看時段、建立預約、收到通知」,以及「讓 admin 可以管理服務品項、調整可預約時段、確認或取消預約、看今日行程」。為了讓沒有 FastAPI 後端的讀者也能跑,今天也會定義「內建 mock 資料」的離線模式,後續章節所有範例預設走 mock,只有在 Day 36 才把真實 API 串起來。

今天的目標有四:第一,定義產品範圍與兩種角色能做什麼;第二,畫出 Next.js App Router 的路由地圖;第三,對齊 Web 系列 Day 35-44 的 API 端點清單;第四,建立 Day 32-44 都會沿用的共用設定(命名、目錄、狀態管理)。讀完之後,你會對「這個專案最終長什麼樣」有一張具體的圖,未來 13 天每一天的實作都會呼應這張圖。

產品範圍與兩種角色

預約管理系統要解決的核心問題是「讓服務提供者不用接電話就能管理時段,讓客戶不用傳訊息就能預約」。為了讓這個系統在小型團隊規模下可完成,我們刻意把範圍縮到三個核心場景:服務展示、預約建立、後台管理。其他像金流、訊息推播、會員制度、評論評分都先不做。

兩種角色的具體權限分得很清楚:admin 可以管理服務品項(新增、編輯、停用)、設定可預約時段、看到所有客戶的預約、確認或取消預約;customer 可以看服務品項、看可預約時段、建立預約、看自己的歷史。一個帳號同一時間只能有一種角色,但 admin 可以把自己降級成 customer 來測試對方視角,這個切換會在 Day 38 登入流程實作。

為了避免「某天突然發現需要多一個角色」的災難,我們現在就把未來可能擴充的角色寫進 enum 預留位:UserRole = "admin" | "customer" | "staff",其中 staff 是 Day 44 之後可能新增的「只能看預約不能改服務」的客服角色。今天先把型別定義好,業務邏輯只實作 admin 與 customer 兩種。

路由地圖:URL 結構與檔案對應

Next.js App Router 的精神是「資料夾即 URL、檔名即特殊用途」。我們把所有路由畫成一張表,後續每一天會照這張表建立對應的 app/ 目錄結構。這是整個專案篇最重要的一張圖,建議複製到你的記事本:

URL 檔案 角色 說明
/ app/page.tsx 公開 首頁,介紹系統並導引登入或開始預約
/services app/services/page.tsx 公開 服務清單,所有人可瀏覽
/services/[id] app/services/[id]/page.tsx 公開 單一服務的詳細頁,含可預約時段
/bookings/new?serviceId=... app/bookings/new/page.tsx customer 建立預約的表單頁
/bookings app/bookings/page.tsx customer 客戶的預約歷史與狀態
/login app/(auth)/login/page.tsx 公開 登入頁
/register app/(auth)/register/page.tsx 公開 註冊頁
/admin app/admin/page.tsx admin 後台首頁,今日預約總覽
/admin/bookings app/admin/bookings/page.tsx admin 所有預約的管理清單
/admin/services app/admin/services/page.tsx admin 服務品項管理(新增、編輯、停用)
/admin/services/[id]/slots app/admin/services/[id]/slots/page.tsx admin 設定該服務的可預約時段

這張表有兩個關鍵設計。第一,把「公開」、「customer」、「admin」三種可見性直接寫在表格裡,後面寫權限檢查時只要對應欄位即可,不會漏掉。第二,用 route group (auth) 把登入與註冊包起來,未來這兩頁共用同一個 layout(不顯示頂部選單),而且 URL 仍然是 /login、/register 而不是 /auth/login,對 SEO 與使用者友善。

巢狀結構的部分,/admin 底下有自己的 layout.tsx,負責驗證 admin 身份、套上後台專用側欄。/admin/services/[id]/slots 是動態路由加巢狀目錄,動態參數 id 是服務 UUID。未來如果要加 /admin/services/[id]/blackouts(特殊休館日),照同樣的目錄慣例即可,不用改路由表。

頁面盤點與資訊密度

設計不能只看 URL,也要看每個頁面要呈現什麼。我們把每個頁面的「核心資訊」與「主要操作」列成盤點表,作為 Day 32 之後實作的依據:

頁面 主要資訊 主要操作
首頁 / 服務介紹、登入與註冊入口 瀏覽服務、開始預約
服務清單 /services 所有啟用中的服務卡片(名稱、時長、價格) 點進單一服務
單一服務 /services/[id] 服務描述、可預約時段(未來 7 天) 選擇時段開始預約
建立預約 /bookings/new 選定的服務、時段、備註欄位 確認建立預約
我的預約 /bookings 預約清單(日期、狀態、服務) 取消預約、查看詳情
後台首頁 /admin 今日預約總數、未確認預約數、最近七天流量 進入各管理頁
後台預約管理 /admin/bookings 所有客戶預約(篩選、搜尋) 確認、取消、改期
後台服務管理 /admin/services 所有服務品項(含停用的) 新增、編輯、停用
後台時段設定 /admin/services/[id]/slots 該服務的週期性時段 新增、刪除時段模板

這張表刻意寫得很簡略:主要資訊只列三項、主要操作只列三項。原因是「寫得越具體、未來越難改」。今天先決定大方向,未來實作時如果發現某個頁面需要更多欄位,就地加上即可;但如果今天把欄位寫得太死,明天就會陷入「為什麼這頁有這個欄位、那頁沒有」的細節辯論。把粒度控在「足夠指導實作、不至於綁死調整空間」,是介面設計的第一守則。

API 端點對齊:與 Web 系列的契約

Web 系列 Day 35-44 已經把後端 API 做完。我們要做的不是「自己決定端點格式」,而是「照著 Web 系列的契約呼叫」。下表列出前端會用到的所有端點,以及對應的 Day 來源(後續章節也會反覆引用這張表):

方法 端點 用途 Web 系列出處
POST /auth/register 註冊新帳號(customer) Day 36
POST /auth/login 登入並取得 token Day 36
POST /auth/refresh 用 refresh token 換新 token Day 36
GET /services 列出啟用中的服務 Day 36
POST /services 新增服務(admin) Day 36
PATCH /services/{id} 編輯服務(admin) Day 36
DELETE /services/{id} 停用服務(admin) Day 36
GET /services/{id}/slots?from=...&to=... 列出可預約時段 Day 37
GET /bookings 客戶自己的預約 Day 37
POST /bookings 建立預約 Day 37
POST /bookings/{id}/cancel 取消預約 Day 37

這張表的關鍵是「前端不會自創端點」。如果某個畫面需要後端資料而端點表裡沒有,那就是要先回頭補 Web 系列的端點、不能前端自己掰一個。我們刻意把「資料來源於哪一天」標在表格最後一欄,這樣之後串接時可以照著 Web 系列的章節順序讀,邊讀邊對應今天寫的前端程式碼。

離線模式:沒有後端時的 mock 資料

為了讓沒有跑 FastAPI 的讀者也能跟著實作,今天定義的內建 mock 資料長這樣:

// lib/mock/types.ts
// 與 Web 系列 Day 35 的 SQLModel 對齊的純型別定義,方便前端、後端共用。

export type UserRole = "admin" | "customer";

export type Service = {
  id: string;
  name: string;
  description: string;
  durationMinutes: number;
  bufferMinutes: number;
  priceCents: number;
  isActive: boolean;
};

export type BookingStatus = "pending" | "confirmed" | "cancelled" | "completed";

export type Booking = {
  id: string;
  reference: string;
  customerId: string;
  customerName: string;
  serviceId: string;
  serviceName: string;
  startAt: string;
  endAt: string;
  status: BookingStatus;
  notes: string;
};

export type Session = {
  userId: string;
  email: string;
  displayName: string;
  role: UserRole;
  accessToken: string;
  refreshToken: string;
};
// lib/mock/data.ts
// 預設提供的虛構資料,全部都是假的,僅供示範。

import type { Booking, Service } from "./types";

export const mockServices: Service[] = [
  {
    id: "svc-001",
    name: "個人攝影 60 分鐘",
    description: "棚拍 + 修圖 5 張",
    durationMinutes: 60,
    bufferMinutes: 15,
    priceCents: 450000,
    isActive: true,
  },
  {
    id: "svc-002",
    name: "一對一健身 90 分鐘",
    description: "器材指導與動作調整",
    durationMinutes: 90,
    bufferMinutes: 30,
    priceCents: 800000,
    isActive: true,
  },
  {
    id: "svc-003",
    name: "語言家教 30 分鐘",
    description: "線上一對一",
    durationMinutes: 30,
    bufferMinutes: 5,
    priceCents: 300000,
    isActive: true,
  },
];

export const mockBookings: Booking[] = [
  {
    id: "bk-0001",
    reference: "BS-20260410-0001",
    customerId: "u-001",
    customerName: "王小明",
    serviceId: "svc-001",
    serviceName: "個人攝影 60 分鐘",
    startAt: "2026-04-10T14:00:00+08:00",
    endAt: "2026-04-10T15:00:00+08:00",
    status: "confirmed",
    notes: "請準備深色背景",
  },
  {
    id: "bk-0002",
    reference: "BS-20260411-0002",
    customerId: "u-002",
    customerName: "李小華",
    serviceId: "svc-002",
    serviceName: "一對一健身 90 分鐘",
    startAt: "2026-04-11T16:00:00+08:00",
    endAt: "2026-04-11T17:30:00+08:00",
    status: "pending",
    notes: "",
  },
];

這份型別定義刻意與 Web 系列 Day 35 的 SQLModel 欄位一一對應,但用 camelCase(前端慣例)而非 snake_case(後端慣例)。Day 36 串接 FastAPI 時會寫一個轉換層把 snake_case 轉成 camelCase,讓 mock 與真實 API 的資料形狀一致,元件程式碼不會因為切換模式而壞掉。所有示範資料都是虛構的:服務名稱、價格、客戶姓名都不是真實的,可以放心放在前端範例裡。

mock 模式切換走環境變數與單一切換點:

// lib/api-mode.ts
// 依環境變數決定走 mock 還是 live;整個專案只允許從這裡讀取模式。

export type ApiMode = "mock" | "live";

export function getApiMode(): ApiMode {
  const raw = process.env.NEXT_PUBLIC_API_MODE ?? "mock";
  return raw === "live" ? "live" : "mock";
}

// 預設為 mock,開發期不需要後端也能跑;部署到正式環境時改 NEXT_PUBLIC_API_MODE=live。
export const API_MODE = getApiMode();
// lib/api/services.ts
// 同一個 useServices(),背後依 API_MODE 決定走 mock 還是 live API。

import { API_MODE } from "@/lib/api-mode";
import { mockServices } from "@/lib/mock/data";
import type { Service } from "@/lib/mock/types";

export async function fetchServices(): Promise<Service[]> {
  if (API_MODE === "mock") {
    // 模擬網路延遲,方便在 UI 上驗證載入狀態
    await new Promise((resolve) => setTimeout(resolve, 150));
    return mockServices.filter((s) => s.isActive);
  }
  const res = await fetch(`${process.env.NEXT_PUBLIC_API_BASE}/services`, {
    cache: "no-store",
  });
  if (!res.ok) throw new Error(`fetchServices failed: ${res.status}`);
  return res.json();
}

把模式切換集中在 API_MODE 常數,所有資料層函式(如 fetchServices)共用同一個分支判斷。日後新增 fetchBookings、createBooking 全部依循這個寫法,不會出現「某個函式忘了判斷模式」的 bug。這個抽象也是 Day 36 串接 FastAPI 時最重要的入口。

命名與目錄慣例

為了避免 Day 32 之後每一天都為「檔案放哪」爭論,我們現在把目錄與命名定下來。這份慣例從今天起每天都會沿用:

booking-frontend/
├── app/                          # Next.js App Router 入口
│   ├── (auth)/                   # 登入、註冊共用 layout
│   ├── admin/                    # 後台區,套用 admin layout
│   ├── bookings/                 # 客戶預約相關
│   ├── services/                 # 服務瀏覽
│   └── layout.tsx                # 根 layout
├── components/                   # 共用元件
│   ├── ui/                       # 按鈕、輸入框、卡片等基礎元件
│   ├── booking/                  # 預約專用元件
│   └── admin/                    # 後台專用元件
├── lib/                          # 共用工具
│   ├── api-mode.ts               # mock/live 切換
│   ├── api/                      # FastAPI 呼叫層
│   ├── mock/                     # 離線模式資料
│   ├── monitor.ts                # Day 30 的監控抽象層
│   └── format.ts                 # 日期、貨幣格式化
├── public/                       # 靜態檔案
├── styles/                       # 全域 CSS
├── tests/                        # 單元與元件測試
└── types/                        # 全域型別定義

這份目錄有三個關鍵原則。第一,app/ 只放路由檔,業務邏輯放 components/ 與 lib/,避免「頁面檔越長越難讀」。第二,components/ 用子資料夾分類:ui/ 是通用元件、booking/ 與 admin/ 是功能專屬元件,這樣搜尋時一眼就知道去哪裡找。第三,lib/ 是「非元件、非路由」的所有東西,包括 API 切換層、API 呼叫、mock 資料、工具函式、Day 30 的監控層。這條規則是 Day 16 的延伸,把「邏輯跟畫面分離」這條原則貫穿到整個專案。

命名部分:元件檔名用 PascalCase(BookingCard.tsx)、工具函式檔名用 camelCase(formatDate.ts)、常數與設定檔用 kebab-case(api-mode.ts)。TypeScript 型別檔統一放 types/ 或就近放元件旁邊(小範圍)。

狀態管理策略

預約管理系統的狀態大致分四類:伺服器狀態(服務清單、預約清單)、UI 狀態(表單輸入、modal 開關)、使用者狀態(目前登入者、token)、全域設定(主題、語言)。每類用不同的工具,避免「什麼都丟 Redux」或「什麼都用 useState」:

// lib/state-strategy.ts
// 預約系統的狀態分類與對應工具(2026 年 3 月主流)

export type StateCategory =
  | { kind: "server"; tool: "TanStack Query 5.x"; example: "useServices()" }
  | { kind: "ui"; tool: "useState / useReducer"; example: "表單欄位、modal 開關" }
  | { kind: "user"; tool: "React Context + httpOnly cookie"; example: "AuthProvider、currentUser" }
  | { kind: "global-config"; tool: "Server Component props 或 env"; example: "API base URL、主題" };

// 對應的套件選擇:
// - 伺服器狀態:TanStack Query 5.x(Day 14 介紹)
// - UI 狀態:原生 useState / useReducer(Day 6 介紹)
// - 使用者狀態:Context + httpOnly cookie(Day 38 實作)
// - 全域設定:環境變數 + Server Component 傳遞

這份決策表有兩個理由。第一,伺服器狀態不該放 Redux 或 Context,因為它的生命週期跟 request 綁定,TQ(TanStack Query)有 cache、staleTime、refetch 等專屬機制,比 Context 強太多。第二,使用者狀態刻意放 httpOnly cookie 而不是 localStorage,因為 XSS 攻擊可以偷 localStorage 但偷不到 httpOnly cookie。Day 38 登入流程會完整實作。

把上面的策略寫成實際的常數檔,方便後續章節直接 import:

// lib/query-keys.ts
// TanStack Query 5.x 的 query key 集中管理,避免散落各處導致快取失效。

export const queryKeys = {
  services: {
    all: ["services"] as const,
    list: () => [...queryKeys.services.all, "list"] as const,
    detail: (id: string) => [...queryKeys.services.all, "detail", id] as const,
  },
  bookings: {
    mine: (customerId: string) => ["bookings", "mine", customerId] as const,
    detail: (id: string) => ["bookings", "detail", id] as const,
  },
} as const;

// 預設的 staleTime:30 秒內不重複打後端
export const DEFAULT_STALE_TIME_MS = 30_000;

設計系統的視覺語彙(簡述)

今天不實作設計系統,但把視覺方向講清楚,Day 32 會正式建立。我們的設計選擇是「專業、克制、暖色」:背景用接近純白的 bg-slate-50、卡片用 bg-white 加 shadow-sm、主色用 indigo-600、強調色用 amber-500(用於「開始預約」這類主要 CTA)、錯誤用 rose-600。字型走 Tailwind 4.x 的 font-sans 預設 stack。

我們刻意不堆四張 KPI 卡、不用漸層、不用過度圓角。對 side project 來說,「看起來像 2026 年的中型 SaaS」比「看起來像設計師個人作品」更重要,這也呼應 Day 1 講過的「讓你能專注在程式邏輯而不是設計美感」。

常見錯誤與踩雷

第一個踩雷是「先寫程式再想路由」。很多新手會在 Day 31 直接開始寫元件,結果寫到一半才發現「預約詳情頁要叫 /bookings/[id] 還是 /my/bookings/[id]」,最後整個目錄要重構。今天就是把這類決策先做掉,未來寫程式時只剩「照著實作」。

第二個踩雷是「路由表跟 API 表分開放在不同檔案」。如果前端有兩份獨立的「端點清單」,半年後一定有一份過期而另一份沒過期,最後除錯時懷疑「到底是前端還是後端錯了」。我們把端點表放在前端專案根目錄的 API-CONTRACT.md,引用 Web 系列的具體 Day,兩邊對齊同一份來源。

第三個踩雷是「mock 資料與真實 API 形狀不同」。如果 mock 的欄位是 start_at(snake_case)而真實 API 回 startAt(camelCase),前端切換模式時就要改一堆存取。今天定義的型別統一用 camelCase,並在 Day 36 寫一層 snake_case 轉 camelCase 的轉換器,確保切換無痛。

第四個踩雷是「離線模式忘記標示」。如果某個畫面用的是 mock 資料、但 UI 上看起來跟真實資料一模一樣,使用者會誤以為「我按按鈕真的建立了預約」。Day 32 會在開發模式下加一個浮動的「Mock Mode」標籤,讓開發者一眼知道目前是離線狀態,這對 demo 與測試都特別重要。

效能與實務提醒

今天設計的路由有 11 個頁面,預估打包後的 First Load JS 約 80 到 120 KB。對一個中型 SaaS 來說這個體積合理,不需特別處理;對追求極致 LCP 的頁面(例如首頁),可以考慮用 Next.js 的 Partial Prerendering(PPR)把首頁靜態化。今天先不展開,Day 25 會深入效能主題。

另一個實務提醒是「動態路由的數量」。我們的 /services/[id] 與 /admin/services/[id]/slots 是動態路由,id 是 UUID。Next.js 對動態路由的處理是「伺服器端在 request 時才決定渲染結果」,所以靜態預先生成(SSG)不適用。如果未來想要預先生成熱門服務頁,可以用 generateStaticParams 把已知的 id 列出來預先渲染,但對小型系統來說 SSR 已經夠快,不必多此一舉。

對無障礙(a11y)的要求,今天雖然不深入實作,但所有頁面的設計原則都遵循:互動元素都要有 aria-label、表單欄位都要有關聯的 label 元素、色彩對比至少 4.5:1。Day 28 的無障礙基礎與 Day 42 的無障礙總檢會再次檢視這些原則,今天先把方向定下來。

另一個實務提醒是「mock 載入時間的處理」。UI 在 mock 模式下應該跟真實 API 有一樣的載入體驗(skeleton、spinner、optimistic update),不能因為是本地資料就立刻顯示出來。下面是一個簡單的 mock 載入 helper,未來所有 mock 函式都會用它:

// lib/mock/with-delay.ts
// 讓 mock 函式模擬網路延遲,方便在 UI 上驗證載入狀態。

export async function withDelay(value, ms = 150) {
  await new Promise((resolve) => setTimeout(resolve, ms));
  return value;
}

// 用法:
// return withDelay(mockServices.filter((s) => s.isActive));
// 之後切到 live 模式時,只要把 withDelay 拿掉、改回 return res.json(),介面不變。

小結

今天把貫穿專案「預約管理系統」的設計與路由定義完成。我們畫了 11 個頁面的路由地圖、寫了 11 個 API 端點的對齊表、定下目錄與命名慣例、確認狀態管理策略,並預留 mock 模式讓沒有後端的讀者也能跟著實作。明天 Day 32 會在這份藍圖上實際建立 Next.js 專案,把路由、目錄、共用元件先建好。今天的決議會被後續 13 天反覆引用,務必把這篇當作整個專案篇的「目錄頁」留存。

結語

貫穿專案從今天正式開工。設計在前、實作在後,這是軟體工程最基本也最容易被忽略的紀律。明天 Day 32 我們會把這張藍圖落實成 Next.js 專案:建立目錄結構、裝好 Tailwind 4.x、寫好設計系統的基礎元件、串好 TanStack Query 的 Provider,並把所有東西放到一個可以 pnpm dev 跑得起來的最小骨架。今天寫的路由表會在明天變成實際的 app/ 資料夾,型別定義會變成 lib/mock/types.ts,目錄慣例會變成實際的檔案結構。Day 33 開始寫第一個真正的畫面(服務清單)。

延伸資源

  • Next.js 15 App Router 路由約定官方文件:https://nextjs.org/docs/app/building-your-application/routing
  • TanStack Query 5.x 官方介紹(伺服器狀態管理):https://tanstack.com/query/latest
  • Web 系列 Day 35 的預約系統資料模型:https://blog.hao-code.com/2025/07/web-day-35.html
  • Web 系列 Day 36 的認證 API 契約:https://blog.hao-code.com/2025/07/web-day-36.html
  • Web 系列 Day 37 的預約流程 API:https://blog.hao-code.com/2025/07/web-day-37.html

留言

這個網誌中的熱門文章

Day 2 變數與資料型別

Day 2 變數與資料型別 引言 寫程式的過程中,變數與資料型別是處理資料的基礎。變數是存放資料的容器,資料型別則決定這筆資料有哪些特性、可以進行哪些操作。學會定義變數、認識各種資料型別,是學好 Python 的關鍵一步。 這篇文章會帶你了解 Python 中變數的觀念、如何定義變數,以及常見的資料型別,包括整數、浮點數、字串、布林值,還有串列、元組、字典與集合等容器型別。我們也會介紹變數的命名規則與撰寫風格建議,以及如何用 type() 檢查資料型別。 什麼是變數?如何在 Python 中定義變數 變數是在程式執行時用來存放資料的名稱。透過定義變數,我們可以給一筆資料一個名字,並在程式的其他地方用這個名字取用該筆資料。在 Python 中,變數不需要事先宣告型別,因為 Python 是動態型別語言,變數的型別由指定給它的值決定。 定義變數的基本語法 在 Python 中定義變數非常簡單,只要用賦值符號 = 把值指定給變數即可。例如: x = 5 # 定義變數 x,並把整數 5 賦值給它 name = "Alice" # 定義變數 name,並把字串 "Alice" 賦值給它 在這裡,x 是一個變數,被賦予整數 5;name 是另一個變數,被賦予字串 "Alice"。 變數的更新與覆寫 變數的值可以修改,也就是說,我們可以在程式的不同地方給同一個變數新的值。例如: x = 10 # x 最初被賦予 10 x = 15 # x 的值現在被更新為 15 這樣就能依照需求,在程式執行過程中靈活調整變數的值。 Python 的動態型別系統 Python 和某些靜態型別語言不同,定義變數時不需要宣告型別。賦值時,Python 會根據值自動判斷變數的型別。例如: x = 5 # x 是整數 x = 3.14 # x 變成浮點數 x = "Hi" # x 變成字串 同一個變數在程式執行過程中可以存放不同型別的值,這是 Python 的彈性之一。 常見資料型別 在 Python 中,資料型別決定我們可以對變數進行哪些操作...

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門

Python 從入門到 PyTorch 深度學習:開啟 AI 世界的大門 隨著人工智慧(AI)與深度學習(Deep Learning)快速發展,越來越多人對這些技術產生興趣。不論你是想踏入 AI 領域的初學者,還是已經有程式基礎的開發者,學好 Python 與深度學習框架(例如 PyTorch),都能為你打開更多可能。 為什麼選擇 Python? Python 已經是資料科學與人工智慧領域的首選語言。它的語法簡潔、容易上手,而且擁有龐大的生態系與大量開源函式庫。無論是資料處理、資料視覺化,還是建立機器學習與深度學習模型,Python 都能勝任。對想進入 AI 或資料科學領域的人來說,它幾乎是必備工具。 PyTorch 是什麼? PyTorch 是由 Meta(原 Facebook)AI 研究團隊開發的開源深度學習框架,以易用、靈活和動態計算圖著稱,是許多 AI 研究人員與開發者的首選。相較於其他框架,PyTorch 的寫法更貼近原生 Python,對初學者相對友善。無論是簡單的實驗,還是複雜的深度學習模型,PyTorch 都能提供強大的支援。 這個系列能帶給你什麼? 這個系列會從 Python 的基礎開始,帶你一步一步學習,最後能自己用 PyTorch 建立深度學習模型。即使你完全沒有寫過程式,也能跟著文章的節奏累積技能,理解 AI 與深度學習的核心觀念。 本系列涵蓋的主題 Python 基礎:從變數、條件判斷到函式與模組。 資料處理工具:用 NumPy 與 Pandas 有效率地操作資料。 資料視覺化:用 Matplotlib 與 Seaborn 把資料畫成圖表。 深度學習的數學基礎:線性代數、微積分與機率。 PyTorch 入門:理解張量、模型建構與 GPU 加速。 基礎深度學習模型:CNN 與 RNN 的實作應用。 深度學習專案實戰:從資料前處理到模型部署的端到端流程。 誰適合這個系列? 程式初學者 :如果你對 AI 充滿好奇,卻還沒寫過程式,系列的第一部分會帶你快速上手 Python,並幫助你理解深度學習的基本觀念。 資料科學愛好者 :如果你已經熟悉一些資料處理方法,進階部分會教你如何用 PyTorch 建構深度學習模型。 開發者與研究人員 :想更深入了...

Day 1 Python 簡介與環境設定

Day 1 Python 簡介與環境設定 引言 在現在的科技環境裡,程式設計已經是一項重要技能。無論你是對資料科學有興趣、想成為開發者,或是想踏入人工智慧(AI)領域,學會寫程式都能明顯提升你的競爭力。在眾多程式語言中,Python 因為語法簡單、功能強大、應用範圍廣泛,成為許多人進入程式世界的第一選擇。這篇文章會帶你認識 Python 的背景與優勢,並一步步教你在不同系統上安裝與設定 Python 開發環境,最後寫出第一支 Python 程式。 為什麼選擇 Python? Python 是一種高階程式語言,由 Guido van Rossum 在 1991 年發布。Python 的設計哲學強調程式碼的可讀性,並用縮排來定義程式區塊,這點和許多使用大括號的語言不同。簡潔的語法讓它成為初學者的理想選擇;就算是經驗豐富的開發者,也能用它完成複雜的專案。 Python 的優勢如下: 簡單易學 :Python 的語法清楚、結構簡潔,初學者很快就能上手。和其他語言相比,學習曲線相對平緩,不需要先弄懂一堆複雜觀念,就能開始寫程式。 應用範圍廣泛 :從資料科學、網頁開發、人工智慧、機器學習、自動化測試到網路爬蟲,Python 都有大量開源函式庫與工具支援,而且在這些領域都扮演關鍵角色。 豐富的函式庫與框架 :Python 的函式庫生態系非常龐大。做資料分析有 NumPy、Pandas;開發網站有 Django、Flask;做深度學習有 TensorFlow、PyTorch。各種需求幾乎都能找到對應的套件,讓開發更有效率。 跨平台支援 :Python 支援 Windows、macOS、Linux 等作業系統,程式通常不需要太多修改就能跨平台執行,讓開發與部署更有彈性。 活躍的社群 :Python 擁有龐大的開發者社群。學習或開發上遇到問題,幾乎都能在社群與論壇(例如 Stack Overflow)找到答案,對初學者來說是很強的後盾,也能減少卡關時的挫折感。 Python 的應用領域 Python 的流行與強大功能,讓許多領域都開始大量使用它。以下是幾個常見的應用方向: 資料科學 :隨著大數據與人工智慧興起,資料科學大量使用 Python。NumPy、Pandas 與 Matplotlib 等工具能處理和分析龐...