2025-07-15 Line 訂單系統-D 階段 — Redis 快取與訂單狀態通知設計與實作

2025-07-15 Line 訂單系統-D 階段 — Redis 快取與訂單狀態通知設計與實作

現在正式進入:

📒 D 階段 — Redis 快取與訂單狀態通知設計與實作

這是整個 LINE 訂單系統的「智慧化」階段,
讓你的系統不僅能收單,還能即時更新訂單狀態減少資料庫負擔推播通知使用者


🧭 D 階段目標總覽

目標 功能說明
⚡ 引入 Redis 作為訂單快取,減少頻繁的 MySQL 查詢
🔔 即時通知機制 當訂單狀態改變時(例如「已接單」、「配送中」),LINE 即時通知使用者
🧩 API 整合 提供 /api/orders/:id/status 更新訂單狀態的後端端點
🖥️ Vue3 後台 管理者可在後台點擊按鈕更新狀態(並觸發推播)

⚙️ 系統架構概念圖(D 階段)

1
2
3
4
5
6
7
8
9
LINE 使用者

LINE Messaging API

Node.js (Webhook)

Redis ←→ MySQL

Vue3 後台 (管理者更新訂單狀態)
  • Redis:快速暫存訂單狀態,避免重查 MySQL。
  • MySQL:正式持久儲存。
  • Vue 後台更新狀態 → Redis + MySQL 更新 → LINE 即時通知。

🧱 實作步驟


🔹 D1 — 安裝 Redis 與設定連線

✅ 在本機或雲端安裝 Redis

Lenovo(Windows)Mac Air 上都可用 Docker:

1
docker run --name redis -p 6379:6379 -d redis

✅ 安裝 Node.js 套件

在你的 backend 專案中:

1
npm install redis

✅ 新增 .env 變數

1
2
REDIS_HOST=127.0.0.1
REDIS_PORT=6379

🔹 D2 — 建立 Redis 連線工具

📁 backend/utils/redisClient.js

1
2
3
4
5
6
7
8
9
10
11
12
13
import { createClient } from "redis";

const client = createClient({
socket: {
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
},
});

client.on("error", (err) => console.error("❌ Redis 錯誤:", err));
client.connect();

export default client;

🔹 D3 — 修改 orders.js 支援 Redis 快取

當查詢訂單列表時,會先查 Redis,沒有才查 MySQL。
更新訂單時,Redis 與 MySQL 會同步更新。

📁 backend/routes/orders.js(更新後版本):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import express from "express";
import mysql from "mysql2/promise";
import redisClient from "../utils/redisClient.js";
import axios from "axios";

const router = express.Router();

const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
});

// ✅ 查詢所有訂單(含 Redis 快取)
router.get("/orders", async (req, res) => {
try {
// 嘗試從 Redis 取得快取
const cachedOrders = await redisClient.get("orders");
if (cachedOrders) {
console.log("📦 從 Redis 取得訂單資料");
return res.json(JSON.parse(cachedOrders));
}

// 查詢 MySQL
const [rows] = await pool.query(
`SELECT o.id, o.user_name, p.name AS product_name, o.quantity, o.status, o.created_at
FROM orders o
LEFT JOIN products p ON o.product_id = p.id
ORDER BY o.created_at DESC`
);

// 寫入 Redis 快取(存活 60 秒)
await redisClient.setEx("orders", 60, JSON.stringify(rows));

res.json(rows);
} catch (err) {
console.error("查詢訂單錯誤:", err);
res.status(500).json({ error: "伺服器錯誤" });
}
});

// ✅ 更新訂單狀態(並推播 LINE)
router.put("/orders/:id/status", async (req, res) => {
const orderId = req.params.id;
const { newStatus, userName } = req.body;

try {
// 更新 MySQL
await pool.query(`UPDATE orders SET status = ? WHERE id = ?`, [
newStatus,
orderId,
]);

// 更新 Redis 快取
await redisClient.del("orders"); // 清掉舊快取

// 查找 LINE 使用者(假設 userName 對應 LINE userId)
const lineUserId = userName;

// 傳送 LINE 通知
if (lineUserId) {
await axios.post(
"https://api.line.me/v2/bot/message/push",
{
to: lineUserId,
messages: [
{
type: "text",
text: `📢 您的訂單(#${orderId})狀態已更新為:「${newStatus}」`,
},
],
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.LINE_CHANNEL_ACCESS_TOKEN}`,
},
}
);
}

res.json({ success: true });
} catch (err) {
console.error("更新訂單狀態錯誤:", err);
res.status(500).json({ error: "伺服器錯誤" });
}
});

export default router;

🔹 D4 — Vue3 後台按鈕觸發更新

📁 frontend/src/views/LineOrders.vue(部分新增內容):

1
2
3
4
5
6
7
8
<td>
<select v-model="order.status" @change="updateStatus(order)">
<option>新訂單</option>
<option>已接單</option>
<option>配送中</option>
<option>已完成</option>
</select>
</td>
1
2
3
4
5
6
7
8
9
10
11
const updateStatus = async (order) => {
try {
await axios.put(`http://localhost:3000/api/orders/${order.id}/status`, {
newStatus: order.status,
userName: order.user_name, // 對應 LINE userId
});
alert(`訂單 #${order.id} 狀態已更新為「${order.status}」`);
} catch (err) {
console.error("更新狀態錯誤:", err);
}
};

🧪 測試流程

步驟 動作 結果
1️⃣ 啟動 Redis + Node.js Redis 客戶端連線成功
2️⃣ Vue3 後台載入訂單清單 第一次從 MySQL 查詢,之後從 Redis 快取
3️⃣ 改變訂單狀態(例如改為「已接單」) Redis 清快取、MySQL 更新、LINE 推播通知
4️⃣ 回到 LINE App 檢查訊息 收到「您的訂單已更新」通知 ✅

✅ D 階段完成成果

模組 狀態
Redis 快取導入 ✅ 已完成
訂單狀態即時更新 ✅ 已完成
LINE 推播通知 ✅ 已完成
前端管理介面 ✅ 已整合

🚀 下一步(📕 E 階段預告)

接下來的 E 階段 將會進入:

「前端介面優化(RWD + UI/UX)」

內容包括:

  • 美化 LineOrders.vue(RWD、自動更新、進度條)
  • 新增「即時刷新」或「Socket 實時訂單」
  • 強化前端的「使用者體驗」

是否要我接下來幫你進入 📕 E 階段 — Vue3 前端優化(RWD+UI/UX 改版與即時刷新設計)