[{"content":"嗨，我是 Latte 🐈\n一個熱愛探索新奇事物與直覺設計的全端初學者！(｡･ω･｡)ﾉ♡\n當我不在寫程式時 你會發現我在打電動 🎮、陪貓咪玩耍 🐾、或者偷懶睡大覺 💤\n💼 探索我的專案 📜 閱讀技術文章 也歡迎探索我的 GitHub 取得原始碼或是聯繫我喔！(≧∀≦)ゞ 🚀\n","date":"3 February 2025","externalUrl":null,"permalink":"/Logic-Loom/","section":"","summary":"","title":"","type":"page"},{"content":" 一個充滿神秘與奇幻色彩的 D\u0026amp;D 魔法道具黑市，販售來自異世界的珍稀奇物！\n📌 專案連結：🔗 Shadow Market 🌑 📌 GitHub Repo：🔗 Shadow Market GitHub\n🌟 介紹 # Shadow Market（暗影市集）🌑 是一個專為 Dungeons \u0026amp; Dragons（D\u0026amp;D） 玩家打造的魔法道具商城，讓冒險者可以輕鬆瀏覽、讓管理者管理異世界的珍奇魔法物品。\n本專案採用 Vue 3 + Tailwind CSS + DaisyUI 打造出簡潔美觀的 UI，後端則透過 Express.js + Prisma + MySQL 來管理商品，確保整體體驗穩定順暢。\n\u0026ldquo;在黑暗中低聲耳語，稀世寶物將與有緣人相遇。\u0026rdquo; 🖤✨\n🕶 關於 Shadow Market # Shadow Market 的誕生源於對 D\u0026amp;D 桌遊與奇幻冒險世界的熱愛。在遊戲中，魔法道具不僅能改變戰局，還能塑造角色的成長與故事。\n因此，這個商城不只是販售道具，更是一個充滿神秘色彩的 黑市，玩家可以在這裡尋找來自異界的珍奇異寶，甚至發掘隱藏在黑暗中的交易秘辛……\n「黑暗中總有交易，代價只取決於你的誠意與籌碼。」\n📌 功能特色 # 🏪 商品展示與搜尋 # ✅ 魔法道具展示：首頁列出各式 魔法裝備、卷軸、藥水、詛咒物品 等，並提供詳細描述。\n🔍 強大搜尋功能：透過 名稱、道具類型、稀有度 進行篩選，快速找到需要的物品！\n🔑 編輯與管理系統 # ✅ 快速編輯商品：管理者可以透過彈窗 新增、修改、刪除道具，方便維護商品庫存。\n🔒 管理者驗證機制：進入管理頁面時，需輸入靜態密碼來獲取 暫時性 token，確保商城安全性。\n📊 即時資料更新：後端 API 自動處理數據變更，讓商品資訊能夠即時同步！\n密碼彈窗 新增彈窗 編輯彈窗 🗣️ AI 聊天小精靈 - 愛吹牛的小精靈店員 # ✅ 內建 AI 助手，僅回答 D\u0026amp;D 相關問題，營造沉浸式冒險氛圍！\n📖 角色扮演模式：AI 會根據 NPC 設定 回應對話，不會回答 D\u0026amp;D 以外的內容！\n🔮 與 AI 討論魔法道具：詢問 AI 關於 詛咒物品、神器背景、冒險建議，它都會給予回應！\n🚫 拒絕無關話題：如果玩家提問與 D\u0026amp;D 無關，AI 會打哈哈帶過，確保遊戲氛圍不被破壞！\n示例對話：\n🏰 玩家：「這把詛咒劍有什麼效果？」 🧙 AI：「這把詛咒劍？哦哦，據說挥舞時會讓你感到無比強大，同時讓你的對手感到無比倒楣！(⊙ω⊙) 不過，使用前最好先試試運氣，誰知道會不會有點小意外呢？(¬‿¬)」 🚀 玩家：「你可以幫我查天氣嗎？」 ⚔️ AI：「抱歉，這裡是魔法道具商店，我們只負責預測冒險者穿越龍穴的天氣，其他地方的天氣就交給精通氣象的德魯伊了！(⊙_⊙)」 🚀 Tech Stack # 前端：Vue 3 + Tailwind CSS + DaisyUI 後端：Express.js + Prisma + MySQL 身份驗證：Token-based Admin 認證 部署：Railway 📬 聯絡方式 # 如果你對 Shadow Market（暗影市集）🌑 有興趣，或者有任何建議，歡迎聯絡我！\n📩 Email：latte.0975582420@gmail.com\n來吧，進入黑暗，探索未知的魔法市場…… 🖤🌑✨\n","date":"3 February 2025","externalUrl":null,"permalink":"/Logic-Loom/projects/shadowmarket/","section":"Project 💼","summary":"","title":"🌑 Shadow Market - 黑暗中的魔法交易市集","type":"projects"},{"content":"🚀 這裡是我的開發專區！\n每個專案都是我在學習與實踐中的心血結晶，從前端互動體驗到後端架構設計，這裡記錄了我的技術成長與挑戰歷程。\n不論是工具應用、創意專案，還是小型系統開發，我都希望能透過這些作品展現技術的可能性。快來看看吧！(๑•̀ㅂ•́)و✧\n💡 還有更多精彩專案正在開發中\u0026hellip;\n如果你對某個專案感興趣，歡迎點擊進入詳細介紹，或到 GitHub 查看原始碼，讓我們一起探索更多技術的可能性吧！🚀✨\n","date":"3 February 2025","externalUrl":null,"permalink":"/Logic-Loom/projects/","section":"Project 💼","summary":"","title":"Project 💼","type":"projects"},{"content":" 📜 Post # 💡 歡迎來到我的技術文章專區！\n這裡有開發技巧分享、實用教學與探索筆記，讓你的技術之路充滿靈感與啟發！✨\n快來看看吧～ (｡･ω･｡)ﾉ♡\n","date":"23 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/","section":"","summary":"","title":"","type":"posts"},{"content":" Ｑueue 的概念 # 什麼是 Queue？ # Queue（佇列）是一種先進先出（FIFO, First In First Out）的資料結構。這表示最早被放入佇列的元素，會最先被移除，就像排隊買飲料一樣，先來的人先買到飲料，後來的人要排在後面～ 🍹\nQueue 的基本操作 # Enqueue（入列） ➡️ 將元素加入佇列尾端。 Dequeue（出列） ⬅️ 移除佇列前端的元素。 Peek（查看） 👀 查看佇列最前端的元素，但不移除它。 isEmpty（是否為空） ❓ 判斷佇列是否為空。 視覺化示意圖 # 假設現在有一個空佇列：\n[ ] Enqueue（加入元素）\n我們依序加入 1️⃣、2️⃣、3️⃣：\n[1, 2, 3] → 1 是最先加入的，排在最前面 Dequeue（移除元素）\n現在執行一次出列操作：\nDequeue ➡️ 1 被移除 ➡️ [2, 3] 是不是很像排隊買飲料，前面的人先買完離開，後面的人往前移呢？（*´∀`）~♥\nQueue 的常見應用 # 排隊系統（銀行、超商、遊戲配對）：誰先來就先服務！🏦 資源管理（印表機佇列）：文件按順序列印🖨️ 廣度優先搜尋（BFS）：用於圖論與迷宮解法🗺️ 異步任務處理（如伺服器請求）：排隊處理任務🛠️ Queue 的實作範例：遊戲攻擊隊列 🎮 # 接下來，我們來看一個在遊戲場景中應用 Queue 的例子，展示如何使用 JavaScript 建立一個攻擊順序的佇列系統。\n範例 ⚔️ # 以下是一段模擬角色戰鬥的程式碼，展示如何使用 Queue 實現回合制攻擊邏輯：\nconst queue = []; // 建立一個空的攻擊佇列 // 動態生成按鈕，對應玩家的攻擊 emby.attacks.forEach((attack) =\u0026gt; { const button = document.createElement(\u0026#34;button\u0026#34;); button.innerHTML = attack.name; document.querySelector(\u0026#34;#attackBox\u0026#34;).append(button); }); // 綁定攻擊按鈕事件 document.querySelectorAll(\u0026#34;button\u0026#34;).forEach((button) =\u0026gt; { button.addEventListener(\u0026#34;click\u0026#34;, (e) =\u0026gt; { const selectedAttack = attacks[e.currentTarget.innerHTML]; // 玩家攻擊 emby.attack({ attack: selectedAttack, recipient: draggle, renderedSprites, }); // 若敵人血量歸零，觸發勝利邏輯 if (draggle.health \u0026lt;= 0) { queue.push(() =\u0026gt; draggle.faint()); queue.push(() =\u0026gt; endBattle()); } else { // 若敵人未死亡，隨機選擇攻擊並加入隊列 const randomAttack = draggle.attacks[Math.floor(Math.random() * draggle.attacks.length)]; queue.push(() =\u0026gt; { draggle.attack({ attack: randomAttack, recipient: emby, renderedSprites, }); // 若玩家血量歸零，觸發失敗邏輯 if (emby.health \u0026lt;= 0) { queue.push(() =\u0026gt; emby.faint()); queue.push(() =\u0026gt; endBattle()); } }); } }); }); // 點擊對話框，執行佇列中的攻擊 document.querySelector(\u0026#34;#dialogueBox\u0026#34;).addEventListener(\u0026#34;click\u0026#34;, () =\u0026gt; { if (queue.length \u0026gt; 0) { queue.shift()(); // 執行佇列中的第一個動作 } else { document.querySelector(\u0026#34;#dialogueBox\u0026#34;).style.display = \u0026#34;none\u0026#34;; // 若佇列為空，隱藏對話框 } }); // 遊戲結束邏輯 function endBattle() { gsap.to(\u0026#34;#overlappingDiv\u0026#34;, { opacity: 1, onComplete: () =\u0026gt; { cancelAnimationFrame(battleAnimationId); battle.initiated = false; animate(); document.querySelector(\u0026#34;#userInterface\u0026#34;).style.display = \u0026#34;none\u0026#34;; gsap.to(\u0026#34;#overlappingDiv\u0026#34;, { opacity: 0 }); }, }); } 解析 📖 # 按鈕生成： 根據玩家角色的攻擊列表，動態生成按鈕，讓玩家選擇攻擊。 攻擊佇列： 玩家攻擊後，將敵人的攻擊動作加入 queue，確保動作按照順序執行。 死亡處理： 玩家或敵人血量歸零時，將其死亡動畫與結束邏輯加入 queue，確保事件按順序執行。 點擊觸發佇列： 透過對話框的點擊事件，依序執行 queue 中的動作，模擬回合制的戰鬥流程。 應用場景與優勢 # 順序控制： Queue 的先進先出特性，使遊戲攻擊的執行邏輯清晰且可預測。 擴展性強： 如果需要新增更多攻擊、動畫或特效，只需將對應函式推入 queue，無需改動核心邏輯。 邏輯分離： 將遊戲邏輯與動畫執行分離，便於維護與調試。 結語 # Queue 是處理回合制遊戲動作的利器，讓攻擊、特效、遊戲結束邏輯依序執行，既清晰又靈活。 透過這個實作範例，你可以看到 Queue 如何將複雜的遊戲邏輯簡化為一個易於維護的流程。\n希望這篇文章能幫助你更好地理解 Queue 的應用！ 🎉 快試試將它應用到你的專案中吧！ヾ(≧▽≦*)o\n","date":"23 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/queue/","section":"","summary":"","title":"深入了解 Queue（佇列）：概念與應用實作 ✨","type":"posts"},{"content":" 🎤 前言 # 嗨～今天我們來聊聊如何用 Firebase Admin SDK 打造一個能保護後端 API 的身份驗證中間件！🎉 不用擔心，這篇教學絕對超簡單，只要跟著步驟操作，保證你可以順利完成！( •̀ ω •́ )✧\n🍀 前置作業 # Node.js：確保安裝了最新版本！ Firebase 專案：前往 Firebase 控制台 創建專案，並下載服務帳戶密鑰 JSON 文件～ 安裝依賴：先用以下指令安裝需要的 npm 包： npm install dotenv firebase-admin 準備完成了嗎？那我們開始吧！ヾ(≧▽≦*)o\n🔑 實際操作 # 🌟 步驟一：配置 Firebase Admin SDK # 在 firebase.js 文件中配置 Firebase Admin SDK，用於初始化身份驗證服務。\n// src/config/firebase.js import { initializeApp, cert } from \u0026#34;firebase-admin/app\u0026#34;; import { getAuth } from \u0026#34;firebase-admin/auth\u0026#34;; import * as dotenv from \u0026#34;dotenv\u0026#34;; // 載入環境變數 dotenv.config(); // 初始化 Firebase Admin SDK initializeApp({ credential: cert({ projectId: process.env.FIREBASE_PROJECT_ID, clientEmail: process.env.FIREBASE_CLIENT_EMAIL, privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\\\n/g, \u0026#34;\\n\u0026#34;), // 處理多行密鑰整合為一行 }), }); export const auth = getAuth(); 🌟 小提醒： # 使用 dotenv 管理環境變數，可以更安全地保存敏感信息！ replace(/\\\\n/g, \u0026quot;\\n\u0026quot;) 是為了解決 JSON 格式中多行私鑰的問題，千萬別忘了這步喔！( ˘▽˘)っ 📂 步驟二：自動生成 .env 文件 # 接下來，我們寫個小工具，實現自動生成 .env 文件，超方便！✨\n建立生成腳本 # 新增 generate-env.js，內容如下：\nimport fs from \u0026#34;fs\u0026#34;; import path from \u0026#34;path\u0026#34;; // 指定 Firebase JSON 檔案的路徑 const filePath = path.resolve(\u0026#34;./src/config/你的-firebase-key.json\u0026#34;); const keyFile = fs.readFileSync(filePath, \u0026#34;utf8\u0026#34;); const keyData = JSON.parse(keyFile); // 格式化 private_key const formattedPrivateKey = keyData.private_key.replace(/\\n/g, \u0026#34;\\\\n\u0026#34;); // 生成 .env 文件內容 const envFilePath = path.resolve(\u0026#34;./.env\u0026#34;); const envContent = `FIREBASE_PROJECT_ID=${keyData.project_id}\\nFIREBASE_CLIENT_EMAIL=${keyData.client_email}\\nFIREBASE_PRIVATE_KEY=\u0026#34;${formattedPrivateKey}\u0026#34;\\n`; // 寫入 .env 文件 fs.writeFileSync(envFilePath, envContent, \u0026#34;utf8\u0026#34;); console.log(\u0026#34;.env 文件生成完成！🎉\u0026#34;); 執行腳本 # node generate-env.js 這樣就會在專案目錄中生成一個 .env 文件，裡面會包含 Firebase 的必要配置喔！٩(ˊᗜˋ*)و\n🛡️ 步驟三：建立身份驗證中間件 # 在 authMiddleware.js 中新增以下代碼，來實現身份驗證：\n// middlewares/authMiddleware.js import { auth } from \u0026#34;../config/firebase.js\u0026#34;; export const authMiddleware = async (req, res, next) =\u0026gt; { const authHeader = req.headers.authorization; if (!authHeader) { return res.status(403).json({ status: 403, message: \u0026#34;沒有提供 Authorization header\u0026#34;, }); } const idToken = authHeader.split(\u0026#34; \u0026#34;)[1]; if (!idToken) { return res.status(403).json({ status: 403, message: \u0026#34;沒有提供 id token\u0026#34;, }); } try { const decodedToken = await auth.verifyIdToken(idToken); req.user = decodedToken; // 保存用戶信息 next(); } catch (err) { res.status(403).json({ status: 403, message: \u0026#34;無效的憑證\u0026#34;, error: err.message, }); } }; 這樣的中間件會幫你驗證每個請求的 Token，確保只有有效用戶可以訪問受保護的路由～( •̀ ω •́ )✧\n🚀 步驟四：在 Express 中使用中間件 # 在主伺服器檔案中（例如 index.js），加上中間件來保護路由：\nimport express from \u0026#34;express\u0026#34;; import { authMiddleware } from \u0026#34;./middlewares/authMiddleware.js\u0026#34;; const app = express(); app.use(express.json()); // 受保護的路由 app.get(\u0026#34;/protected\u0026#34;, authMiddleware, (req, res) =\u0026gt; { res.status(200).json({ status: 200, message: \u0026#34;成功訪問受保護的路由！\u0026#34;, user: req.user, // 用戶信息 }); }); // 啟動伺服器 app.listen(3000, () =\u0026gt; { console.log(\u0026#34;伺服器已啟動！請訪問 http://localhost:3000 🚀\u0026#34;); }); 試試看吧！🎉 用 Postman 或其他工具，向 /protected 發送帶有 Firebase Token 的請求，應該會看到回傳的用戶信息！(≧∀≦)ゞ\n🎉 結語 # 現在我們已經成功學會如何：\n初始化 Firebase Admin SDK 自動生成 .env 文件 實現身份驗證中間件 在 Express 中保護路由 是不是很簡單呢？(｡･∀･)ﾉﾞ 如果你覺得這篇教學對你有幫助，別忘了分享給更多需要的人喔！🚀\n一起打造更安全、更強大的後端吧～！ヾ(≧▽≦*)o\n","date":"8 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/set_firebase_authmiddleware/","section":"","summary":"","title":"使用 Firebase Admin SDK 實現身份驗證中間件教學 🔐✨","type":"posts"},{"content":" 🎤 前言 # 使用者體驗（User Experience, UX）是應用程式設計中不可或缺的一環，而一個即時、直觀的反饋能夠讓使用者更安心、更愉快地操作✨。在這篇文章中，我們將介紹如何使用 Naive UI 提供的 useMessage，為操作增加提示彈窗，讓你的專案從「好用」變成「超好用」！(ゝ∀･)\n💡 搭配 useMessage 的優勢 # 傳送門 🌀 Naive UI Message\n即時反饋：讓使用者在操作後即刻獲得成功或失敗的回應。 更友好的提示：以視覺化的彈窗代替冷冰冰的 console.log。 簡單易用：只需一行程式碼，即可實現漂亮的提示彈窗。 🖥️ 使用步驟 # 1. 安裝 Naive UI # 如果你的專案還沒有安裝 Naive UI，請先執行以下指令：\nnpm install naive-ui 2. 基本使用 useMessage # Naive UI 提供的 useMessage 是一個簡單的訊息提示工具，可以用於成功、失敗或警告等提示。使用前，請務必在 App.vue 或其他全域組件中掛載 NMessageProvider：\n```vue \u0026lt;script setup\u0026gt; import { NMessageProvider } from \u0026#39;naive-ui\u0026#39;; \u0026lt;/script\u0026gt; \u0026lt;template\u0026gt; \u0026lt;n-message-provider\u0026gt; \u0026lt;router-view /\u0026gt; \u0026lt;/n-message-provider\u0026gt; \u0026lt;/template\u0026gt; ･*･:≡(　ε:) 以下是基本範例\n\u0026lt;template\u0026gt; \u0026lt;n-button @click=\u0026#34;showMessage\u0026#34;\u0026gt;點我顯示訊息\u0026lt;/n-button\u0026gt; \u0026lt;/template\u0026gt; \u0026lt;script setup\u0026gt; import { useMessage } from \u0026#34;naive-ui\u0026#34;; const message = useMessage() const showMessage = () =\u0026gt; { message.info(\u0026#39;我是一般訊息\u0026#39;) message.success(\u0026#39;我是成功訊息\u0026#39;) message.error(\u0026#39;我是失敗訊息\u0026#39;) message.warning(\u0026#39;我是警告訊息\u0026#39;) } \u0026lt;/script\u0026gt; 3. 搭配 Firebase 功能提升使用者體驗 # 以下是如何在使用者驗證中加入彈窗提示的範例：\n邏輯檔案 # (1) 註冊功能 # // Login/service/registerService.js import { getAuth, createUserWithEmailAndPassword } from \u0026#34;firebase/auth\u0026#34;; const auth = getAuth(); export const registerUser = async (email, password) =\u0026gt; { try { const userCredential = await createUserWithEmailAndPassword(auth, email, password); return { success: true, user: userCredential.user }; } catch (error) { return { success: false, message: error.message }; } }; (2) 登入功能 # // Login/service/loginService.js import { getAuth, signInWithEmailAndPassword } from \u0026#34;firebase/auth\u0026#34;; const auth = getAuth(); export const loginUser = async (email, password) =\u0026gt; { try { const userCredential = await signInWithEmailAndPassword(auth, email, password); return { success: true, user: userCredential.user }; } catch (error) { return { success: false, message: error.message }; } }; (3) Google 登入 # // Login/service/authService.js import { getAuth, GoogleAuthProvider, signInWithPopup } from \u0026#34;firebase/auth\u0026#34;; const auth = getAuth(); export const loginWithGoogle = async () =\u0026gt; { try { const provider = new GoogleAuthProvider(); const userCredential = await signInWithPopup(auth, provider); return { success: true, user: userCredential.user }; } catch (error) { return { success: false, message: error.message }; } }; (4) 忘記密碼功能 # // Login/service/resetPasswordService.js import { getAuth, sendPasswordResetEmail } from \u0026#34;firebase/auth\u0026#34;; const auth = getAuth(); export const resetPassword = async (email) =\u0026gt; { try { await sendPasswordResetEmail(auth, email); return { success: true }; } catch (error) { return { success: false, message: error.message }; } }; (5) 登出功能 # // Login/service/logoutService.js import { getAuth, signOut } from \u0026#34;firebase/auth\u0026#34;; const auth = getAuth(); export const logoutUser = async () =\u0026gt; { try { await signOut(auth); return { success: true }; } catch (error) { return { success: false, message: error.message }; } }; 集中彈窗邏輯在 LoginPage.vue # 在 LoginPage.vue 中，統一處理所有彈窗邏輯，根據 Service 的回傳結果，使用 useMessage 顯示提示。\n\u0026lt;template\u0026gt; \u0026lt;n-input v-model=\u0026#34;email\u0026#34; placeholder=\u0026#34;輸入 Email\u0026#34; /\u0026gt; \u0026lt;n-input v-model=\u0026#34;password\u0026#34; type=\u0026#34;password\u0026#34; placeholder=\u0026#34;輸入密碼\u0026#34; /\u0026gt; \u0026lt;n-button @click=\u0026#34;handleRegister\u0026#34;\u0026gt;註冊\u0026lt;/n-button\u0026gt; \u0026lt;n-button @click=\u0026#34;handleLogin\u0026#34;\u0026gt;登入\u0026lt;/n-button\u0026gt; \u0026lt;n-button @click=\u0026#34;handleGoogleLogin\u0026#34;\u0026gt;Google 登入\u0026lt;/n-button\u0026gt; \u0026lt;n-button @click=\u0026#34;handleResetPassword\u0026#34;\u0026gt;忘記密碼\u0026lt;/n-button\u0026gt; \u0026lt;n-button @click=\u0026#34;handleLogout\u0026#34;\u0026gt;登出\u0026lt;/n-button\u0026gt; \u0026lt;/template\u0026gt; \u0026lt;script setup\u0026gt; import { ref } from \u0026#34;vue\u0026#34;; import { useMessage } from \u0026#34;naive-ui\u0026#34;; import { registerUser } from \u0026#34;./service/registerService.js\u0026#34;; import { loginUser } from \u0026#34;./service/loginService.js\u0026#34;; import { loginWithGoogle } from \u0026#34;./service/authService.js\u0026#34;; import { resetPassword } from \u0026#34;./service/resetPasswordService.js\u0026#34;; import { logoutUser } from \u0026#34;./service/logoutService.js\u0026#34;; const email = ref(\u0026#34;\u0026#34;); const password = ref(\u0026#34;\u0026#34;); const message = useMessage(); const handleRegister = async () =\u0026gt; { const result = await registerUser(email.value, password.value); if (result.success) { message.success(\u0026#39;註冊成功 🎉\u0026#39;); } else { message.error(\u0026#39;註冊失敗 💔\u0026#39;); console.error(result.message); } }; const handleLogin = async () =\u0026gt; { const result = await loginUser(email.value, password.value); if (result.success) { message.success(\u0026#39;登入成功 🎉\u0026#39;); } else { message.error(\u0026#39;登入失敗 💔\u0026#39;); console.error(result.message); } }; const handleGoogleLogin = async () =\u0026gt; { const result = await loginWithGoogle(); if (result.success) { message.success(\u0026#39;Google 登入成功 🎉\u0026#39;); } else { message.error(\u0026#39;Google 登入失敗 💔\u0026#39;); console.error(result.message); } }; const handleResetPassword = async () =\u0026gt; { const result = await resetPassword(email.value); if (result.success) { message.success(\u0026#39;密碼重設郵件已寄出 📩，請檢查你的信箱！\u0026#39;); } else { message.error(\u0026#39;密碼重設失敗 💔\u0026#39;); console.error(result.message); } }; const handleLogout = async () =\u0026gt; { const result = await logoutUser(); if (result.success) { message.success(\u0026#39;登出成功 👋\u0026#39;); } else { message.error(\u0026#39;登出失敗 💔\u0026#39;); console.error(result.message); } }; \u0026lt;/script\u0026gt; 🎉 結語 # 透過 Naive UI 的 useMessage，你可以輕鬆為使用者操作提供即時反饋，提升整體操作體驗。結合 Firebase Authentication，讓你的專案更友好、更專業！快來試試看吧！🚀\n","date":"7 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/set_naive_usemessage/","section":"","summary":"","title":"用 Naive UI 的 useMessage 打造更友好的使用者操作體驗 🎉","type":"posts"},{"content":" 🎤 前言 # 在應用程式中，使用者驗證是不可缺的一環，而 Firebase Authentication 就像是開發者的魔法工具箱🪄！不僅可以快速實現 Email/密碼登入，還支援第三方登入（Google、Facebook 等），更貼心的是，它還內建了 忘記密碼 功能💡！\n今天就帶大家一步步實現這些功能，並在下一篇文章搭配 Naive UI 信息彈窗 提升使用者體驗，讓操作更加直覺、友好！✨（¯▿¯）\n📌 前置作業 # 1. 準備 Firebase 專案 # 登入 Firebase 官方網站，按下建立專案! 輸入你的酷酷名稱建立新專案(ﾉ\u0026gt;ω\u0026lt;)ﾉ 在「專案設定」中選擇平台建立應用程式 新增 Firebase SDK 將 Firebase 產生的 apiKey 複製起來！ 2. 安裝 Firebase 套件 # 在本地專案中安裝 Firebase 套件 npm install firebase 3. 設定 Firebase 環境 # 在專案中新增一個 firebase-config.js 檔案，將 Firebase 配置加入：\n// firebase-config.js import { initializeApp } from \u0026#34;firebase/app\u0026#34;; const firebaseConfig = { apiKey: \u0026#34;你的 API 金鑰\u0026#34;, authDomain: \u0026#34;你的專案域名\u0026#34;, projectId: \u0026#34;你的專案 ID\u0026#34;, storageBucket: \u0026#34;你的儲存空間\u0026#34;, messagingSenderId: \u0026#34;你的訊息傳送者 ID\u0026#34;, appId: \u0026#34;你的 App ID\u0026#34;, }; const app = initializeApp(firebaseConfig); export default app; 🖥️ 實際操作 # 1. 實現 Email/密碼註冊功能 # 建立 registerService.js，實現註冊功能：\n// Login/service/registerService.js import { getAuth, createUserWithEmailAndPassword } from \u0026#34;firebase/auth\u0026#34;; const auth = getAuth(); export const registerUser = async (email, password) =\u0026gt; { try { const userCredential = await createUserWithEmailAndPassword(auth, email, password); console.log(\u0026#34;使用者註冊成功:\u0026#34;, userCredential.user); } catch (error) { console.error(\u0026#34;註冊失敗:\u0026#34;, error.message); } }; 在前端 LoginPage.vue 前端呼叫 registerUser()\n// Login/LoginPage.vue import { registerUser } from \u0026#34;./service/registerService.js\u0026#34;; const email = \u0026#34;test@example.com\u0026#34;; const password = \u0026#34;password123\u0026#34;; registerUser(email, password); 2. 實現 Email/密碼登入功能 # 在 loginService.js 中增加登入功能：\n// Login/service/loginService.js import { signInWithEmailAndPassword } from \u0026#34;firebase/auth\u0026#34;; export const loginUser = async (email, password) =\u0026gt; { try { const userCredential = await signInWithEmailAndPassword(auth, email, password); console.log(\u0026#34;使用者登入成功:\u0026#34;, userCredential.user); } catch (error) { console.error(\u0026#34;登入失敗:\u0026#34;, error.message); } }; 在前端 LoginPage.vue 前端呼叫 loginUser()\n// Login/LoginPage.vue import { loginUser } from \u0026#34;./service/loginService.js\u0026#34;; const email = \u0026#34;test@example.com\u0026#34;; const password = \u0026#34;password123\u0026#34;; loginUser(email, password); 3. 實現 Google 第三方登入 # 啟用 Firebase Google 登入後建立 authService.js，加入以下程式碼：\n// Login/service/authService.js import { GoogleAuthProvider, signInWithPopup } from \u0026#34;firebase/auth\u0026#34;; export const loginWithGoogle = async () =\u0026gt; { try { const provider = new GoogleAuthProvider(); const userCredential = await signInWithPopup(auth, provider); console.log(\u0026#34;Google 登入成功:\u0026#34;, userCredential.user); } catch (error) { console.error(\u0026#34;Google 登入失敗:\u0026#34;, error.message); } }; 在前端 LoginPage.vue 前端呼叫 loginWithGoogle()\n// Login/LoginPage.vue import { loginWithGoogle } from \u0026#34;./service/authService.js\u0026#34;; loginWithGoogle(); 4. 實現忘記密碼功能 # 新建 resetPasswordService.js 新增忘記密碼功能：\n// Login/service/resetPasswordService.js import { getAuth, sendPasswordResetEmail } from \u0026#34;firebase/auth\u0026#34;; export const resetPassword = async (email) =\u0026gt; { try { await sendPasswordResetEmail(auth, email); console.log(\u0026#34;重設密碼郵件已寄出\u0026#34;); } catch (error) { console.error(\u0026#34;密碼重設失敗:\u0026#34;, error.message); } }; 在前端 LoginPage.vue 前端呼叫 resetPassword()\nimport { resetPassword } from \u0026#34;./service/resetPasswordService.js\u0026#34;; resetPassword(\u0026#34;test@example.com\u0026#34;); 5. 實現登出功能 # 最後，實現登出功能：\nimport { signOut } from \u0026#34;firebase/auth\u0026#34;; export const logoutUser = async () =\u0026gt; { try { await signOut(auth); console.log(\u0026#34;使用者已登出\u0026#34;); } catch (error) { console.error(\u0026#34;登出失敗:\u0026#34;, error.message); } }; 🔄 測試與驗證 # 完成功能後，可以依以下步驟進行測試：\n註冊新使用者：檢查 Firebase 控制台是否新增使用者。 登入測試：使用 Email/密碼或 Google 登入，確認控制台有登入紀錄。 忘記密碼測試：輸入已註冊的 Email，檢查是否收到重設密碼郵件📩。 登出測試：確認會話已結束。 ⚠️ 注意事項 # Facebook 第三方登入 由於 Facebook 最近的政策調整，對於個人商家變得不太友善，所以這次教學沒有包含串接 Facebook 登入的部分。如果你還是希望使用 Facebook 第三方登入，建議先仔細評估需求，並多多留意相關政策變更喔！💡\nFirebase 驗證限制 Firebase 的驗證目前僅支援 同裝置間的操作，也就是：\n如果在手機上接收驗證信，就必須在同一台手機上完成驗證。 如果在電腦上接收驗證信，也必須在同一台電腦上完成。 雖然 Firebase 曾推出過 跨裝置驗證 的功能，但很可惜現在已經被棄用😢。這點在設計應用流程時，務必要特別留意喔！✨\n結語 🎉 # 透過 Firebase Authentication，我們不僅可以輕鬆實現多種登入功能，還能提供安全的密碼重設服務，讓使用者體驗大幅提升！🔥 快來試試吧，讓你的專案更加完美！ε٩(๑\u0026gt; ₃ \u0026lt;)۶з\n","date":"6 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/set_firebase_authentication/","section":"","summary":"","title":"Firebase Authentication 教學：讓使用者登入變得輕而易舉 🔐","type":"posts"},{"content":" 前言 🎤 # 在做我的第一個專案時，我們最初用 Notion 當 API 文件，剛開始寫 API 時還會乖乖更新文檔📄，但隨著 API 越寫越多，更新文檔的事情就逐漸被拋諸腦後😅。\n而且在前後端分離的情況下，負責前端的組員常常對測試 API 一頭霧水🤔。這時，我靈光一閃，想起老師課堂上提到的超好用圖形化工具✨——Swagger！於是，我開始鑽研如何把 Swagger 引入專案，讓 API 文件和測試一舉搞定🎯！\n📌 前置作業 # 需要用到兩個套件 swagger-ui-express \u0026amp; swagger-autogen\n1. swagger-ui-express # 傳送門 🌀 swagger-ui-express\n什麼是 swagger-ui-express？🖥️\nswagger-ui-express 是一個方便易用的 Express 中介軟體，讓你輕鬆整合 Swagger UI 到你的 Express 應用程式中！✨ 它可以將你的 Swagger 文件以一個互動式的圖形介面展示出來，供開發者進行查閱和測試，徹底解決 API 文件難管理、難測試的痛點💡。\n為什麼選它？\n快速整合：幾行程式碼就能把 Swagger UI 加入專案🔧。 互動式測試：支援直接從瀏覽器發送請求測試 API 功能🚀。 開發者友好：讓團隊中的每個人（不只後端開發者！）都能方便理解和使用 API📖。 2. swagger-autogen # 傳送門 🌀 swagger-autogen 官方文檔 📄 Quick Start\n什麼是 swagger-autogen？✨\nswagger-autogen 是一個專為開發者設計的工具包，可以自動生成符合 Swagger 規範的 API 文件📄！只需撰寫簡單的註解，它就能快速掃描你的程式碼，幫助你生成完整的 Swagger 文件，還能直接與 Swagger UI 整合，讓 API 文件不僅即時更新，還可以用於互動式測試🚀。\n為什麼選擇它？\n省時省力：免手動撰寫 JSON 格式的 API 文件。 高度自動化：從程式碼註解中自動提取路由資訊📌。 即時測試：結合 Swagger UI，讓 API 測試變得超方便🔧。 🖥️ 實際操作 # 1. 安裝套件至你的 express 專案 # npm install swagger-ui-express npm install swagger-autogen 2. 設定 Swagger 自動生成檔案 # 在專案根目錄中，建立一個 swagger.js 檔案，設定 swagger-autogen 來生成 Swagger 文件。\nimport swaggerAutogen from \u0026#34;swagger-autogen\u0026#34;; const doc = { info: { title: \u0026#34;我的 API 寶庫\u0026#34;, description: \u0026#34;我把所有的 API 都放在 localhost:3030 了，去尋找吧！\u0026#34;, }, host: \u0026#34;localhost:3030\u0026#34;, }; const outputFile = \u0026#34;./swagger-output.json\u0026#34;; const routes = [\u0026#34;./app.js\u0026#34;]; swaggerAutogen()(outputFile, routes, doc); require 的寫法只要把 import 換掉就好，剩下相同\nconst swaggerAutogen = require(\u0026#39;swagger-autogen\u0026#39;)(); 執行它，一鍵生成 swagger-output.json！✨\nnode swagger.js 3. 整合 Swagger UI 到 Express 專案 # 在 app.js 中加入以下程式碼：\nimport express from \u0026#34;express\u0026#34;; const app = express(); // swagger import swaggerUi from \u0026#34;swagger-ui-express\u0026#34;; import fs from \u0026#34;fs\u0026#34;; const swaggerDocument = JSON.parse( fs.readFileSync(new URL(\u0026#34;./swagger-output.json\u0026#34;, import.meta.url), \u0026#34;utf-8\u0026#34;) ); app.use(\u0026#34;/api-docs\u0026#34;, swaggerUi.serve, swaggerUi.setup(swaggerDocument)); 如果不是使用 ES6 則是加入：\nconst express = require(\u0026#39;express\u0026#39;); const app = express(); // swagger const swaggerUi = require(\u0026#39;swagger-ui-express\u0026#39;); const swaggerFile = require(\u0026#39;./swagger-output.json\u0026#39;); // 引入剛生成的 JSON 文件 app.use(\u0026#39;/api-docs\u0026#39;, swaggerUi.serve, swaggerUi.setup(swaggerFile)); // 路徑可自訂，例如 /docs 伺服器啟動後，打開瀏覽器，輸入 http://localhost:3000/api-docs 你的互動式 API 文件就此誕生啦！🎉\n4. 在路由中加入註解 📜 # 為了讓 swagger-autogen 能正確提取 API 資訊，會需要在路由檔案中撰寫註解，例如：\nGET router.get( \u0026#34;/:userId\u0026#34;, /* #swagger.tags = [\u0026#39;Cart\u0026#39;] */ /* #swagger.description = \u0026#34;取得購物車所有商品資料\u0026#34; */ /* #swagger.responses[200] = { schema: { \u0026#34;status\u0026#34;: 200, \u0026#34;message\u0026#34;: \u0026#34;購物車成功取得資料\u0026#34;, \u0026#34;data\u0026#34;: { \u0026#34;cartItems\u0026#34;: [ { \u0026#34;id\u0026#34;: 115, \u0026#34;cart_id\u0026#34;: 5, \u0026#34;created_at\u0026#34;: \u0026#34;2025-01-01T04:57:32.661Z\u0026#34;, \u0026#34;is_selected\u0026#34;: false, }, description: \u0026#34;成功取得資料\u0026#34; } */ CartController.fetchCartByUserId ); POST router.post( \u0026#34;/:userId\u0026#34;, /* #swagger.tags = [\u0026#39;Cart\u0026#39;] */ /* #swagger.description = \u0026#34;新增商品至購物車\u0026#34; */ /*\t#swagger.parameters[\u0026#39;obj\u0026#39;] = { in: \u0026#39;body\u0026#39;, description: \u0026#39;新增商品\u0026#39;, required: true, schema: { \u0026#34;activityId\u0026#34;: 34 } } */ /* #swagger.responses[201] = { schema: { \u0026#34;status\u0026#34;: 201, \u0026#34;message\u0026#34;: \u0026#34;成功新增至購物車\u0026#34;, \u0026#34;data\u0026#34;: { \u0026#34;id\u0026#34;: 115, \u0026#34;cart_id\u0026#34;: 5, \u0026#34;activity_id\u0026#34;: 34, \u0026#34;created_at\u0026#34;: \u0026#34;2025-01-01T04:57:32.661Z\u0026#34;, \u0026#34;is_selected\u0026#34;: false } }, description: \u0026#34;成功新增至購物車\u0026#34; } */ CartController.addActivityToCart ); 註釋規範與格式可以前往作者的 GitHub 上參閱範例\n範例 📚 Advanced Example\n5. 更新文件並測試 🔄 # 每次更新 API 或新增路由時，只需重新執行 node swagger.js，就能生成最新的 Swagger 文件！接著在 /api-docs 路徑中進行互動式測試，快速驗證 API 功能是否正常運作🚀。\n","date":"5 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/set_swagger/","section":"","summary":"","title":"為 Express 專案打造互動式 Swagger API 文檔 🌐","type":"posts"},{"content":" 一個專為社交聚會與團隊協作打造的群組邀請與管理平台。\n📌 專案連結：🔗 Joitogther 🤝🌟 📌 GitHub Repo：🔗 Joitogether GitHub\n🌟 介紹 # Joitogether 是一款專門為活動愛好者設計的平台，讓用戶能夠輕鬆建立聚會、管理邀請與參加聚會。\n這個專案採用 Vue 3 + Naive UI 打造直覺化的使用介面，並搭配 Express.js + Prisma 進行後端數據管理，確保流暢的體驗與穩定的資料存儲。\n無論是私人聚餐、讀書會，還是線上協作，Joitogether 幫助你簡化繁瑣的邀請流程，確保活動順利進行！ 🚀\n🪄 關於 Joitogether # 創作者是一群喜歡大家一起出去玩的人。\n因為現代人出社會久了，學生時代的朋友也都有各自的事業，\n因而無法隨時揪團就出發，所以開發者們寫出了可以 隨揪隨行 的網站，\n讓每一位喜歡 一群人一起做一件事情 的朋友們，可以建立自己的小天地。\n揪愛 Together！❤️\n📌 功能特色 # 🏠 活動首頁 # ✅ 最新文章與熱門文章：首頁顯示最新發表的活動資訊，並可瀏覽近期最受歡迎的活動。\n🔎 活動瀏覽與搜尋：用戶可透過關鍵字搜尋、分類篩選，快速找到符合需求的活動。\n📅 快速活動總覽：清楚列出即將舉辦的活動，包括時間、地點與參與狀況，方便用戶快速決策。\n🪧 登入/註冊 # ✅ 多元登入方式：支援 一般信箱註冊 與 Google 第三方登入，提供便利的登入體驗。\n🔒 安全驗證機制：透過 Firebase Auth 驗證用戶身份，確保帳號安全。\n📂 個人化資料管理：用戶可上傳大頭貼，個人資訊同步儲存至 MySQL 資料庫，確保資料完整性。\n📅 建立活動 # ✅ 活動資訊輸入：用戶可建立活動，填寫詳細資訊，並將數據存入 後端資料庫。\n📍 Google Map 整合：直接串接 Google Maps API，讓活動地點輸入更直覺、精確。\n⚙️ 活動條件設定：團主可自訂 審核條件，並決定活動是否需 先付款 才能參加。\n📜 活動報名與留言互動 # ✅ 活動詳細資訊：提供 地點、時間、參加條件 等重要資訊，讓用戶一目了然。\n📝 報名機制：用戶可直接報名活動，系統將自動判斷是否符合條件。\n💬 留言與評價：用戶可在活動頁面留言互動，查看團主的 過往評價，決定是否參加。\n🔄 即時渲染：動態顯示後端活動數據，根據不同的報名條件提供相應的 彈窗提示。\n🔔 即時通知與提醒 # ✅ 活動與文章通知：當用戶關注的 團主建立活動或發布文章，將即時收到通知。\n📩 更新即時推播：文章被留言或有人報名活動時，用戶將收到即時推播。\n📝 活動審核系統 # ✅ 報名者篩選：團主可瀏覽報名者的資料，並決定是否批准其加入活動。\n💰 付款審核機制：在需要 先付款 的活動中，報名者須完成付款才能進入審核階段。若團主拒絕報名，系統將 自動退費。\n⭐ 活動評價系統 # ✅ 活動結束後評價：參與者可對團主與活動進行評價，留下評論，幫助其他用戶參考。\n🔎 評價顯示：用戶可查看過去其他人對團主的評價，並顯示最多四則評論。\n📡 RESTful API 數據管理：透過 API 進行評價的發送、儲存與更新，確保評價數據的完整性。\n💰 儲值系統 # ✅ 一鍵儲值：用戶可透過儲值金支付活動費用，確保交易便捷。\n💳 藍新金流整合：提供 安全、快速 的金流交易，確保支付安全性。\n🛒 購物車金流 # ✅ 活動付款與退款：所有交易均透過 儲值金 處理，確保交易透明且流暢。\n⚡ 快速儲值：當儲值金不足時，可直接跳轉儲值頁面，並透過 藍新金流 完成支付。\n👤 個人頁面 # ✅ 個人資料總覽：用戶可查看 個人專長、興趣、過去活動評價、發起的活動與文章、追蹤的用戶。\n🔄 數據即時渲染：透過 API 撈取資料，確保頁面顯示最新資訊。\n🚀 Tech Stack # 前端：Vue 3 + Naive UI 後端：Express.js + Prisma + MySQL 身份驗證：Firebase Auth 部署：Railway 📬 聯絡方式 # 如果你對 Joitogether 有興趣，或者有任何建議，歡迎聯絡我！\n📩 Email：latte.0975582420@gmail.com\n","date":"5 January 2025","externalUrl":null,"permalink":"/Logic-Loom/projects/joitother/","section":"Project 💼","summary":"","title":"🤝 Joitogether - 就愛揪團，一起相聚！","type":"projects"},{"content":" 一個專為藝術創作者打造的個人畫廊與委託平台。\n📌 專案連結：🔗 Pyramid of DeadLines 🎨🖌️ 📌 GitHub Repo：🔗 Piramid GitHub\n🌟 介紹 # Piramid 是一個專為繪師打造的個人接案與作品展示網站，採用 Vue 3 + Tailwind CSS 打造簡潔美觀的介面，提供直觀的作品呈現與委託須知，方便潛在客戶快速了解接案流程。\n🪄 命名的小故事 # 為什麼叫 Piramid 呢？🤔 這其實是繪師對自己創作生活的一種幽默調侃。繪師每天都像被靈感與死線活埋在「創作的金字塔」裡，左手靈感、右手壓力，但最後還是能創造出讓人驚嘆的作品。✨\n所以我們戲稱這座網站為 Piramid of DeadLines，象徵繪師在無數次趕稿與創意爆發中堆砌的藝術殿堂！一句話總結： “Buried under deadlines and ideas, but still making art happen.” 🎨🖌️\n📌 功能特色 # ✅ 智能導航設計：首頁隱藏 Navbar，離開首頁後自動顯示固定導航，提升瀏覽體驗。\n🖼 作品展示與彈窗預覽：根據資料動態渲染畫作，點擊作品開啟彈窗檢視細節。\n📜 委託須知與價格展示：清晰標示可接案類型、價格範圍與規則，簡化溝通流程。\n🔗 社群與聯絡整合：內建社群連結與快速聯絡按鈕，提高客戶互動便利性。\n⚡ 效能優化與 SEO：使用 Vite 打包，提升載入速度並優化搜尋引擎曝光度。\n🚀 Tech Stack # 🔹 前端：Vue3 + Vite\n🔹 樣式：Tailwind CSS + DaisyUI 🔹 部署：Vercel\n🔹 圖片管理：本地存儲\n📷 頁面展示 # 以下是 Piramid of DeadLines 的頁面截圖：\n🏠 首頁 # 🖼️ 圖庫 # 🔍 圖庫彈窗 # 📖 關於我 # 💰 委託須知 # 📬 聯絡方式 # 如果你對 Piramid 有興趣，或者有任何建議，歡迎聯絡我！\n📩 Email：latte.0975582420@gmail.com\n","date":"4 January 2025","externalUrl":null,"permalink":"/Logic-Loom/projects/piramid/","section":"Project 💼","summary":"","title":"🎨 Piramid of DeadLines - 藝術家的專屬畫廊","type":"projects"},{"content":" 🎤 前言 # 嗨嗨～歡迎來到 Hugo 的主題魔法世界！✨ Hugo 是一個超靈活又快速的靜態網站生成器，而主題就是讓網站瞬間「變身」的祕密武器！(๑•̀ㅂ•́)و✧\n今天，我將帶你一步步完成 Hugo 主題的安裝與管理～我們會以 Blowfish 主題（🐡） 為例，一起來試試用 Git 子模組 的方法吧！ヾ(≧▽≦*)o\n還在找主題嗎？沒關係！快去 Blowfish 主題官方網站 或 Hugo Themes 官方網站 探索更多驚喜吧！💖\n🎨 為什麼用 Git 安裝主題？ # 管理超方便！💾 主題可以獨立存在，輕鬆更新、切換，完全不影響你的專案！(￣▽￣)b 協作超輕鬆！🤝 跟朋友或團隊合作時，直接同步子模組就搞定，大家都用同一個版本，超貼心！ 穩定又可靠！🔒 從官方倉庫拉取主題，完全不怕下載壞掉的檔案～安心又放心！(๑•̀ㅂ•́)و✧ 🛠️ 如何用 Git 安裝主題 # 步驟一：準備好你的 Hugo 專案 # 在開始之前，請確認你已完成以下幾件事：\n建立 Hugo 專案：如果還沒開始，可以參考 如何搭建 Hugo 網站。ヽ(✿ﾟ▽ﾟ)ノ 推送到 Git 倉庫：檢查你的專案是否已初始化 Git，並做好初始提交喔 步驟二：安裝 Blowfish 主題 🐡 # 進入網站目錄 先進入你的 Hugo 專案目錄～\ncd mywebsite 添加 Blowfish 主題 用以下指令將 Blowfish 主題 加入專案：\ngit submodule add -b main https://github.com/nunocoracao/blowfish.git themes/blowfish 刪掉預設的配置檔 hugo.toml 因為 Blowfish 主題自帶配置檔，我們需要刪除原本的 hugo.toml，以免衝突！✂️\nrm hugo.toml ヽ(*´∀`)ﾉ 搞定了！接下來我們來測試主題是不是正常運行吧～\n步驟三：測試主題是否正常運行 🖥️ # 啟動本地伺服器 用以下指令啟動 Hugo 的本地伺服器～📡 hugo server -t blowfish 預覽你的網站 打開瀏覽器，進入 http://localhost:1313。 是不是超美的主題！🎉 🎉 恭喜你，成功安裝 Blowfish 主題啦！(≧∇≦)ﾉ✨ 🔄 如何更新主題 # 只需一條指令，就能讓你的主題煥然一新～\ngit submodule update --remote --merge 💡 小提醒：\n更新後記得檢查網站是否正常運行，必要時調整一下配置檔！( ˘▽˘)っ 如果遇到問題，可以查看主題的官方文檔幫助排查喔～ (｀・ω・´)b 進階操作：切換或管理多主題 🎨 # 如果你有多個主題想嘗試，或者想切換主題，完全沒問題！✨\n添加另一個主題 git submodule add https://github.com/other-theme-repo.git themes/other-theme 切換主題進行測試 hugo server -t other-theme 刪除不需要的主題 git submodule deinit -f themes/other-theme rm -rf .git/modules/themes/other-theme 這樣就能輕鬆管理多個主題啦～( ੭˙ᗜ˙)੭、\n✨ 結語 # 恭喜你！現在已經學會用 Git 安裝並管理 Hugo 主題啦！(๑\u0026gt;ᴗ\u0026lt;๑)🎉 不管是初學者還是進階用戶，這種方式都能讓你的主題管理變得簡單又高效！快去試試看更多有趣的主題吧！🌈\n如果你還沒有逛過 Hugo Themes 官方網站，千萬不要錯過！那裡有上百個主題等你挑選～(´▽`)ﾉﾞ✨\n🚀 讓我們一起打造出屬於自己的靜態網站王國吧！ ヾ(≧▽≦*)o\n","date":"3 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/set_theme/","section":"","summary":"","title":"使用 Git 安裝並設置 Hugo 主題 🛠️","type":"posts"},{"content":" 🎤 前言 # Hugo 是一款快速、靈活又簡單的靜態網站生成器，適合用來搭建個人部落格、作品展示頁甚至是公司官網！✨ 在這篇文章中，我們將從基礎開始，一步步帶你完成 Hugo 網站的搭建過程。快準備好開啟靜態網站的大門吧！(ง •_•)ง\n🌟 為什麼選擇 Hugo？ # 極速生成：Hugo 的靜態網站生成速度超快，數秒內即可完成網站構建！⚡ 靈活易用：支持多種模板與主題，讓設計網站變得輕鬆簡單。ヾ(•ω•`)o 開放源碼：完全免費，且擁有活躍的社群支持，資源豐富。 🖥️ 實際操作 # 🛠️ 步驟一：安裝 Hugo # 現在，Hugo 不再需要依賴 Go 語言，只需直接下載 Hugo 即可！✨ 以下是安裝 Hugo 的方法：\n使用 Homebrew 安裝（適用於 macOS） # 在 macOS 上，您可以透過 Homebrew 安裝 Hugo，指令如下：\nbrew install hugo 🖋️ 步驟二：初始化 Hugo 網站 # 1. 創建新網站 # 使用以下指令創建您的 Hugo 網站專案，記得將 mywebsite 替換為您想要的專案名稱：\nhugo new site mywebsite 2.進入專案目錄 # cd mywebsite 3. 新增一篇文章 # hugo new posts/my-first-post.md 這將在 content/posts 資料夾中生成名為 my-first-post.md 的 Markdown 文件，可以使用任何文字編輯器打開並編輯內容。\n🖥️ 步驟三：本地測試網站 # 1. 啟動本地伺服器 # 輸入以下指令啟動 Hugo 本地伺服器，並測試網站是否正常運行：\nhugo server 2. 預覽網站 # 打開瀏覽器，進入 http://localhost:1313，就能看到您的 Hugo 網站啦！o(≧▽≦)o\n3. 編輯內容並即時預覽 # 在本地伺服器運行的情況下，您可以直接修改 content/posts/my-first-post.md 文件的內容，Hugo 將自動重新生成網站並即時更新預覽頁面，非常方便！✨\n🎉 結語 # 恭喜～現在已經成功建立了一個基礎的 Hugo 網站！🎊 Hugo 的安裝與初始化非常簡單快速，讓你輕鬆踏入靜態網站的世界。在接下來的文章中，我們將深入探討如何為 Hugo 添加主題並進行個性化配置，讓你的網站更符合你的風格和需求！(ฅ´ω`ฅ)\n快來繼續學習，打造屬於自己的精美 Hugo 網站吧！🚀ヾ(≧▽≦*)o\n","date":"1 January 2025","externalUrl":null,"permalink":"/Logic-Loom/posts/set_hogo/","section":"","summary":"","title":"如何從零開始搭建 Hugo 網站！ヾ(≧▽≦)o*","type":"posts"},{"content":"","externalUrl":null,"permalink":"/Logic-Loom/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/Logic-Loom/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","externalUrl":null,"permalink":"/Logic-Loom/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"}]