2025-07-10 Line 訂單系統-C 階段 建立 Node.js 專案的三個核心檔案config db orderRoutes

2025-07-10 建立 Node.js 專案的三個核心檔案config db orderRoutes

現在我們要正式建立 Node.js 專案的三個核心檔案:

📂 /backend/config.js
📂 /backend/db.js
📂 /backend/routes/orderRoutes.js

這三個檔案的作用如下:

檔案 功能
config.js 載入 .env 並集中管理環境變數
db.js 連線 MySQL(用 mysql2sequelize
orderRoutes.js 提供基本訂單 API(查詢、建立、更新)

🧩 一、config.js

📁 路徑:/backend/config.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
// ===============================
// 📘 config.js
// 讀取 .env 並統一管理系統設定
// ===============================
import dotenv from "dotenv";
dotenv.config();

export const config = {
env: process.env.NODE_ENV || "development",
port: process.env.PORT || 3000,

// Database
db: {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
name: process.env.DB_NAME,
},

// LINE
line: {
channelSecret: process.env.LINE_CHANNEL_SECRET,
channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN,
webhookPath: process.env.LINE_WEBHOOK_PATH,
},

// JWT
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.TOKEN_EXPIRE_DAYS || "7d",
},

// Optional
redis: {
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
},
};

export default config;

🧠 二、db.js

📁 路徑:/backend/db.js

這個檔案會使用 mysql2 套件連線資料庫。
請先在後端專案中執行安裝:

1
npm install mysql2

接著建立檔案內容👇

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
// ===============================
// 🗄️ db.js
// 建立 MySQL 資料庫連線
// ===============================
import mysql from "mysql2/promise";
import config from "./config.js";

let pool;

export async function initDB() {
if (!pool) {
pool = mysql.createPool({
host: config.db.host,
user: config.db.user,
password: config.db.password,
database: config.db.name,
port: config.db.port,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
});
console.log("✅ MySQL connection pool created");
}
return pool;
}

export async function query(sql, params = []) {
const connection = await initDB();
const [rows] = await connection.execute(sql, params);
return rows;
}

// 🔍 測試連線
if (process.env.NODE_ENV === "development") {
initDB()
.then(() => console.log("✅ DB connected successfully"))
.catch((err) => console.error("❌ DB connection error:", err.message));
}

📦 三、routes/orderRoutes.js

📁 路徑:/backend/routes/orderRoutes.js

請先安裝 Express:

1
npm install express

然後建立以下內容:

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
// ===============================
// 🧾 orderRoutes.js
// 訂單相關 API:查詢、建立、更新
// ===============================
import express from "express";
import { query } from "../db.js";

const router = express.Router();

// ✅ GET /api/orders - 取得所有訂單
router.get("/", async (req, res) => {
try {
const orders = await query(
"SELECT o.id, u.display_name AS user_name, o.total_price, o.status, o.created_at FROM orders o JOIN users u ON o.user_id = u.id ORDER BY o.id DESC"
);
res.json(orders);
} catch (err) {
console.error(err);
res.status(500).json({ error: "Server error while fetching orders" });
}
});

// ✅ POST /api/orders - 建立新訂單
router.post("/", async (req, res) => {
try {
const { user_id, items } = req.body;

// 計算總金額
let total = 0;
for (const item of items) {
total += item.price * item.quantity;
}

// 新增訂單
const result = await query(
"INSERT INTO orders (user_id, total_price, status) VALUES (?, ?, 'pending')",
[user_id, total]
);
const orderId = result.insertId;

// 新增訂單明細
for (const item of items) {
await query(
"INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)",
[orderId, item.product_id, item.quantity, item.price]
);
}

res.status(201).json({ message: "Order created successfully", orderId });
} catch (err) {
console.error(err);
res.status(500).json({ error: "Server error while creating order" });
}
});

// ✅ PATCH /api/orders/:id - 更新訂單狀態
router.patch("/:id", async (req, res) => {
try {
const { status } = req.body;
const orderId = req.params.id;

await query("UPDATE orders SET status = ? WHERE id = ?", [status, orderId]);
res.json({ message: "Order status updated" });
} catch (err) {
console.error(err);
res.status(500).json({ error: "Failed to update order" });
}
});

export default router;

🧭 四、整合進主伺服器

你的 server.js(或 index.js) 可以這樣設定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import express from "express";
import cors from "cors";
import orderRoutes from "./routes/orderRoutes.js";
import { initDB } from "./db.js";
import config from "./config.js";

const app = express();
app.use(cors());
app.use(express.json());

// ✅ 註冊路由
app.use("/api/orders", orderRoutes);

// ✅ 啟動伺服器
initDB().then(() => {
app.listen(config.port, () => {
console.log(`🚀 Server running on http://localhost:${config.port}`);
});
});

✅ 測試範例

1️⃣ 查詢所有訂單

1
GET http://localhost:3000/api/orders

2️⃣ 建立訂單

1
2
3
4
5
6
7
8
9
10
POST http://localhost:3000/api/orders
Content-Type: application/json

{
"user_id": 1,
"items": [
{ "product_id": 1, "quantity": 2, "price": 80 },
{ "product_id": 2, "quantity": 1, "price": 60 }
]
}

3️⃣ 更新訂單狀態

1
2
3
4
PATCH http://localhost:3000/api/orders/1
Content-Type: application/json

{ "status": "paid" }

如果你願意,下一步我可以幫你建立:

📘 routes/productRoutes.js
📘 routes/userRoutes.js
📘 routes/lineWebhook.js(讓 LINE Bot 能連接這個訂單 API)

是否要我接下來幫你生成這三個檔案?