iT邦幫忙

2026 iThome 鐵人賽

DAY 22
0
Vibe Coding

從零打造 AI 全端應用:Vibe Coding 結合 n8n 視覺化工作流實戰系列 第 22 篇

Day 22:進階商業場景 (二):Vibe Coding 實作歷史紀錄頁面與第二支 Webhook

  • 分享至 

  • xImage
  •  

Day 22:進階商業場景 (二):Vibe Coding 實作歷史紀錄頁面與第二支 Webhook

嗨,大家今天過得好嗎?歡迎來到鐵人賽 Day 22。

昨天我們成功在 n8n 中把 AI 產出的菜單「回寫」到 PostgreSQL 資料庫中。現在你的資料庫裡,應該已經躺著幾筆帶有 session_id 的歷史配單紀錄了。

一個完整的 App 不可能只有單向的輸入。今天,我們要在 n8n 建立我們的第二支 API(讀取歷史紀錄),並再次請出 Vibe Coding 幫我們在 SwiftUI 快速刻出一個「歷史訂單列表」,完成 App 的雙向資料流!

第一步:在 n8n 打造 GET Webhook

我們要開一支全新的 API 給前端拉取歷史資料。請在 n8n 開啟一個新的 Workflow(或者在原本的畫布空白處拉新的節點)。

  1. 新增 Webhook 節點:

    • 這次 HTTP Method 請務必改為 GET(因為我們只是要「獲取」資料,不包含複雜的 JSON Body)。
    • Path 設為 history(網址會變成 /webhook-test/history)。
    • Respond 維持預設的 When Last Node Finishes 即可。
  2. 新增 PostgreSQL 節點:

    • 接在 Webhook 後面,Operation 選擇 Execute Query。
    • 輸入撈取歷史紀錄的 SQL 語法:
      SELECT cpu, gpu, total_price, purpose 
      FROM hardware_history 
      WHERE session_id = $1 
      ORDER BY id DESC;
      
    • 設定 Query Parameter $1 來防止 SQL Injection。

經典踩坑:GET 請求的變數在哪裡?

這裡有一個全端新手超容易卡關的雷點。
在 Day 11 我們做 POST 請求時,前端傳來的變數藏在 HTTP Body 裡,所以我們在 n8n 是用 {{ $json.body.budget }} 來抓取。

但是,GET 請求是沒有 Body 的! 它的變數會跟在網址後面(例如 ?sessionId=12345)。
所以在設定 PostgreSQL 的參數時,請你務必要改成從 query 中抓取:
{{ $json.query.sessionId }}

如果這裡寫錯,你的 SQL 就會永遠撈不到東西,回傳一片空白。

第二步:在前端擴充 APIService

後端的 API 準備好了,現在把視角切回 Xcode。
我們要在 APIService.swift 裡面,加入第二個發送 GET 請求的 Function。你可以手動加,或是用這個 Prompt 請 AI 幫你寫:

請幫我在 APIService 中新增一個 `fetchHistory(sessionId: String)` 的非同步函數。
1. 目標 URL 為:`[http://192.168.](http://192.168.)X.X:5678/webhook-test/history?sessionId=\(sessionId)`
2. 使用 GET 請求。
3. 預期回傳的是一個陣列 (Array),請將它解析為 `[HardwareMenu]` 並回傳。

AI 會產出類似這樣的 Code:

func fetchHistory(sessionId: String) async throws -> [HardwareMenu] {
    // 注意這裡的參數是直接拼在網址後面的 (Query String)
    let urlString = "[http://192.168.](http://192.168.)X.X:5678/webhook-test/history?sessionId=\(sessionId)"
    guard let url = URL(string: urlString) else { throw URLError(.badURL) }
    
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    
    let (data, response) = try await session.data(for: request)
    
    guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
        throw URLError(.badServerResponse)
    }
    
    // 注意!因為回傳的是多筆紀錄,這裡的型別必須加中括號 [HardwareMenu].self
    return try JSONDecoder().decode([HardwareMenu].self, from: data)
}

第三步:Vibe Coding 極速產出歷史列表頁

資料層搞定了,最後就是畫面的呈現。為了維持 MVC 架構,我們同樣需要一個 Controller 跟一個 View。

請對 AI 下這段結構化 Prompt:

我需要一個用來顯示歷史紀錄的 SwiftUI 頁面。
請嚴格遵守 MVC 架構,幫我生成 `HistoryController` 與 `HistoryListView`。

【任務要求】
1. HistoryController:包含一個 `[HardwareMenu]` 陣列來存放資料,一個 `isLoading` 狀態,以及一個呼叫 `APIService.shared.fetchHistory` 的函數。
2. HistoryListView:使用 `List` 或 `ScrollView` 來展示陣列資料。每一筆資料請設計成一個精美的卡片 (顯示 CPU、GPU 與總價)。
3. 當畫面出現 (onAppear) 時,自動觸發 Controller 去拉取資料。

幾秒鐘後,你就會得到一個乾淨的 HistoryListView 和對應的 Controller。

為了讓這個頁面能被看見,你可以回到最外層的 App 進入點,或是做一個 TabView 把「首頁」跟「歷史紀錄」兩個 View 包起來。這部分因為是純 SwiftUI 的基礎導覽機制,我就不佔用篇幅了,你可以直接叫 AI 幫你加上底部的 Tab 導航列。

來測試一下雙向資料流吧!

  1. 確保你的 n8n history Webhook 正在監聽中(按下 Execute Workflow)。
  2. 在 Xcode 跑起模擬器,切換到你剛做好的「歷史紀錄」Tab。
  3. 畫面上會先出現短暫的轉圈圈,接著...
    Boom!你過去幾天測試時,拜託 AI 配出來的那些菜單,全部化身為精美的卡片列表,一字排開呈現在你眼前!

小結

今天我們完成了全端開發的另一個重要里程碑:打通了 GET 請求的資料流,並透過 Vibe Coding 毫不費力地完成了列表畫面的刻版與資料綁定。

到這裡,我們的「AI 硬體推薦 App」已經具備了完整的 CRUD(讀寫)能力,在商業場景上已經是個合格的 MVP(最小可行性產品)了。

但,軟體開發不可能永遠一帆風順。如果今天 n8n 的某個節點當機了,或是外部的匯率 API 突然掛掉,整個工作流就會中斷,前端也會永遠等不到回應。
明天,我們要把視角切回 n8n,實作後端極度重要的**「Error Trigger (錯誤捕捉) 與 Fallback 機制」**,打造一個不會輕易當機的強韌工作流!

我們 Day 23 見!


上一篇
# Day 21:進階商業場景 (一):讓 AI 寫入資料庫!實作 n8n 的回寫與歷史紀錄
下一篇
Day 23:打造不死的後端:n8n 錯誤捕捉 (Error Trigger) 與 Fallback 備援機制
系列文
從零打造 AI 全端應用:Vibe Coding 結合 n8n 視覺化工作流實戰 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言