× LINELINE系統文件
正式資料截圖

Eagle AI × LINE 頻道 · 開發交接 · 2026-07-07

LINE 頻道全景:從選單到每一頁 LIFF

工地主任 × 監工 · 群組 × 1:1 · 截圖 + 流程圖 + 路由與 API 對照,全部與 line-worker/ 原始碼核實。

關鍵座標 Worker eagle-line.jaredsong.workers.dev · LIFF 2010491601-uK7jHMCT(Full)
程式 = GitLab JaredSong1/eagle-line(本機 eagle-ai-qms/line-worker/)· D1 eagle-line · R2 eagle-line-evidence · cron 每天 08:00。

截圖說明 — 全部是正式環境真實資料(remote D1:真實群組、真實請款單掃描、真實現場照片),身分 = 真實 userId。主任視角拍自 Testing 群組、監工視角拍自另一個真實專案群。手機 430×932、深色主題(淺色是同一套 token 自動切換,畫面右上有手動切換鈕)。

01系統全景圖

一個 Cloudflare Worker 做三件事:bot webhook(聊天訊息與卡片)、/api/*(資料)、靜態 LIFFpublic/index.html,單頁 app)。LINE 上有三個場景,全部通到同一個 LIFF,用 URL 參數決定情境:

flowchart LR
  G["💬 群組聊天
bot 選單 + Flex 卡片
連結都帶 ?g=群組id"] L["🖥️ LIFF 工作台
指派·審核·日報·證據·總覽·我的工項"] P["👤 1:1 聊天
Rich Menu 底欄·跨專案·指揮中心"] G <--> L L <--> P
三個場景通到同一個 LIFF · 角色與情境由 URL 參數決定

核心迴圈,五步:

flowchart LR
  A["1 · 上傳請款單"] --> B["2 · 畫框指派
框 + 監工 + 張數 + 截止"] B --> C["3 · 群組通知
你被指派 N 項"] C --> D["4 · 監工拍照
LIFF 或直接丟照片"] D --> E["5 · 主任審核
採認 / 退回"] E -->|退回| D E -->|採認| F(["完成"])
聊天面(訊息 / 卡片 / postback) LIFF 頁面 推播(push,計費)

設計鎖定:沒有 OCR — 系統不讀掃描上的字。「框 + 人 + 張數」就是資料模型,照片證據掛在框上,任何格式的請款單都能用。標註後的掃描圖是指派 → 拍照 → 審核三步共享的物件。

02選單與 Rich Menu

群組選單 = bot 發的 imagemap 圖片(不是 Rich Menu)

LINE 的 Rich Menu 不會出現在群組,所以群組入口是一張 bot 發的橫幅圖片訊息(imagemap,menuImagemap())。bot 被加進群組時、或有人打喚起詞時發出(見第 3 章)。

群組 imagemap 選單1040×219 · 服務路徑 /menu/12/寬度12 是換圖用的 cache-bust 序號,LINE 會快取舊圖 — 換美術必 bump + 重發選單)。每個 tap zone 的連結都帶 ?g=群組id — bot 從 webhook 事件知道群組並烙進 URL;LIFF 絕不依賴 liff.getContext 拿群組。
Tap zone(x 範圍,實測像素)標籤動作目的地
0–208指派工項開 LIFF?g=(主任 → 上傳/指派;監工 → 我的工項 + 提示)
208–399我的工項開 LIFF?v=mine&g=
399–589出工日報開 LIFF?v=daily&g=
589–795問 Eagle送文字「問 Eagle」bot 在聊天內回答,不開 LIFF
802–1040eagle-ai logo無(純品牌)

1:1 Rich Menu(在 OA Manager 手動設定)

1:1 Rich Menu 底欄2500×843 · 在 OA Manager 上傳與設定 tap 區,程式不管這張圖。四個 tile:問 Eagle(送文字)· 我的工項 ?v=mine · 我的照片 ?v=photos · 我的儀表板 ?v=dash。只有加 OA 好友的人才有 1:1。美術源檔在 line-channel-design/menu-art/

歡迎訊息(兩種)

時機內容(程式)
bot 進群(join 事件)groupWelcome():「⚒️ Eagle AI 已加入這個工地群組!點下方選單開始,第一次會先請你選身分:🏗️ 工地主任(上傳請款單、指派工項、看出工日報與總覽)· 👷 監工(查看我的工項、拍照回報)。選單不見了?隨時打『選單』、『Eagle』或『AI』就能叫出來。」+ imagemap 選單
加好友(follow 事件,1:1)welcomeText(暱稱):「👋 歡迎使用 Eagle AI!我是你的工地小幫手 ⚒️:📋 我的工項(你負責的工項、拍照回報)· 📷 我的照片(你上傳的證據)· 📊 我的儀表板(完成統計與排行)· 💬 問 Eagle(隨時問我)。點下方選單開始 👇」+ 問 Eagle 按鈕卡

03喚起詞完整對照 程式核對

「怎麼叫出選單 / Eagle / AI」在群組裡其實有 多層規則,不是單一關鍵字。以下逐條對照 src/index.jssrc/parse.js 的實際判斷(這是最容易被文件寫漏的地方)。

六層規則

層級觸發(實際 regex / 條件)結果程式
選單關鍵字選單 · 單獨 menu · 單獨 ai
/選單|^\s*(?:menu|ai)\s*$/i
發 imagemap 選單index.js(menuReq)
打招呼 / 求助問eagle · 單獨 hi/hello/help/start/menu · 你好 哈囉 嗨 幫助 怎麼用 可以問 功能 選項 開始狀態列一句 + 問 Eagle 按鈕卡(askMenuFlex:什麼時候到期?/ 有沒有被退回?;管理者再加 待我採認 / 誰還沒交)isGreeting()
@提及 OA群組訊息 tag 到本 OA(LINE 標記 isSelf一定回應:純 tag → 按鈕卡;帶問題 → 回答mentioned
智慧回答
wantsEagle()
主題詞(進度/逾期/退回/採認/待採認/還沒交/請款/照片/幾項…)+疑問意圖(? /嗎 呢 幾 多少 有沒有 哪 什麼 何時…),或整句 ≤6 字。
語尾助詞的陳述句(…了/啦/喔)=閒聊 → 安靜
回答(文字或 Flex 卡)parse.js
EAGLE_TOPIC / QWORD / STMT
Fallback 關鍵字句中任意位置含 menu · eagle · ai(字界)· 指派 · 工項發選單index.js 尾段
提醒全部(主任限定)群組裡打 提醒全部@提及所有今明到期/逾期未回報的監工 + 1:1 推卡;非主任 → 「只有工地主任可以提醒全部」remindAllPending()
🔑 群組歡迎文已明講三個字 groupWelcome() 的最後一句就是:「選單不見了?隨時打『選單』、『Eagle』或『AI』就能叫出來。」 所以正式對外的喚起詞是 選單 / Eagle / AI 三個 —— 文件若只寫「選單 / menu / ai」會漏掉 Eagle,也沒交代 @提及與智慧回答兩層。

群組收到一句文字,bot 怎麼判斷

webhook 依這個優先順序逐層判斷(第一個命中就回,後面不看):

flowchart TD
  M["群組收到文字"] --> Q1{"選單關鍵字?
選單 · menu · ai"} Q1 -->|是| MENU["發 imagemap 選單"] Q1 -->|否| Q2{"主任打「提醒全部」?"} Q2 -->|是| REMIND["@提及未交監工 + 1:1 推卡"] Q2 -->|否| Q3{"@提及 OA,或 wantsEagle?"} Q3 -->|"打招呼 / 純 @提及"| GREET["狀態列 + 問 Eagle 按鈕卡"] Q3 -->|"真的問句"| ANS["回答(文字 / Flex 卡)"] Q3 -->|否| Q4{"像出工日報?"} Q4 -->|是| DAILY["整理成日報卡(確認 / 修改)"] Q4 -->|否| Q5{"句中含
menu·eagle·ai·指派·工項?"} Q5 -->|是| MENU2["發選單"] Q5 -->|否| SILENT(["安靜 — 不打擾群組"])
1:1 聊天不走這棵樹:任何文字 bot 都會答(不需要喚起詞)

為什麼要這麼多層:群組是工班聊天的地方,bot 不能話多。所以只有「明確喚起(選單/@提及)」或「明顯在問 Eagle(主題詞+問句)」才出聲;一般閒聊(「油漆好了啦」)保持安靜。分類器 wantsEagle() 有單元測試護著(parse.test.js 內 3 個 wantsEagle 案例)。

04加入與身分

  • 身分是每群一份:同一人可以在 A 群當主任、B 群當監工(跨群雙身分在 1:1 有檢視切換,見第 8 章)。
  • 第一次在某群開 LIFF → 角色選擇頁。一群只有一位工地主任/api/members 伺服器端擋),被佔走會鎖卡並顯示「已由 X 擔任」。
  • 加入或變更角色時,bot 在群組廣播:「{名字} 加入工項 · 身分:工地主任 / 監工」
第一次進來:選身分非成員開任何 LIFF 連結都先落到這頁(route() 判斷 MY_ROLE 為空)。工地主任卡若已被佔 → 鎖定。
已加入頁 ?v=join再點加入不會重問,直接給前往按鈕(主任 → 指派工項;監工 → 查看工項)。
🔑 身分模型(smart-URL)群組範圍一律來自 bot 烙在連結裡的 ?g=群組idliff.getContext() 只做備援(從 imagemap / Flex 卡開啟時它不可靠 — 曾造成「角色存不住、不能指派」)。1:1 沒有 g → 進個人模式(solo-使用者id)。

05工地主任(群組)

底部導覽五個 tab(NAV_SUPER):指派工項 · 審核 · 出工日報 · 證據 · 總覽。點左上 logo = 回角色首頁(主任 → 指派工項)。

指派:上傳 → 畫框 → 指派 → 通知

1 上傳請款單(主任首頁)拍照(相機)或從相簿/檔案。選完直接進編輯器,不設預覽頁;「更換」在編輯器 header。
2 編輯器:工具箱展開右上 ⊕ 展開:框選(預設)· 移動 · 復原 · 刪除全部 · 收起。旋轉獨立在左下、縮放 pill 右下(pinch / 滾輪 / ±)、⤢ 全螢幕、「看工項」跳到清單。
3 畫框(未指派)拖一個框 → 自動彈指派抽屜。框上的標籤與把手反向縮放(旋轉/縮放後維持恆定大小與正向)。點已指派的框=重開抽屜編輯(tap 與拖曳以 6px 區分)。
4 指派抽屜真實工班名單(本群成員)。需要照片 N(預設 2,拍滿=完成,無手動「標記完成」)· 截止日(預設 +7 天)· 樓層/位置(樓層=綠色 F、區域=中性圖標;填了樓層=一層一任務,逐層分別拍照與審核)。
5 已送出POST /api/assign:存 D1 + 掃描圖進 R2 + 群組推播「你被指派 N 項」。「再上傳一張」=開新掃描(多掃描模型,一掃描一卡);「完成」=liff.closeWindow()

審核:採認 / 退回(逐樓層)

sequenceDiagram
  participant C as 監工
  participant G as 群組
  participant S as 主任
  participant L as LIFF 審核頁
  C->>G: 拍滿張數
  G-->>S: 完成卡「審核 ›」
  S->>L: 深連 ?rev=請款單_框
  S->>L: 逐樓層 採認 / 退回
  L-->>G: 結果(採認✅ / 退回↩️@監工)
    
6 審核清單(tab「審核」)主任預設落「待採認」。一掃描一卡(圖上編號 pin),每列一人 + 狀態 pill。已採認的人灰在原位(不消失);整卡全採認才沉到「已完成」摺疊區。
7 審核詳情 ?rev=請款單_框聊天卡「審核 ›」深連到這頁(可帶樓層直接選定)。點清單列或圖上的框選取;逐樓層 → 底欄「採認 1F|退回」;已採認的樓層變灰不可再選;全部樓層完成或已採認才開放「全部採認」。
8 證據燈箱審核情境的燈箱直接帶「退回|採認」(監工看自己照片時是「刪除這張 / 再拍一張」)。滑動換張 + 頁點。
  • 退回要填理由(quick-reply)→ 該樓層回到待處理;監工重拍新照片會自動清掉退回狀態。退回一定推播群組並 @提及監工。
  • 採認單項時安靜(不洗版);某人整組工項全數採認才發「已採認 {名字} 的全部工項 ✅」。
鎖定:審核 = model A聊天卡上沒有行內採認/退回按鈕 — 核可需要證據與上下文,一律深連進 LIFF 看著照片做(裝置實測後反轉定案)。動詞鎖「採認 / 退回」。

出工日報:聊天自動解析 → LIFF 檢視與修改

flowchart LR
  T["群組貼派工訊息
(任意格式)"] --> P["bot 錨點解析
parseDailyLog()"] P --> K["「已整理」卡
樓層/區域 chips + 人數"] K -->|"確認(主任限定)"| C["✅ 已確認 → 進日報頁"] K -->|"修改"| E["LIFF 編輯器
?v=daily&edit=1"] E --> C C --> R["出工 vs 照片落差
→ 請工班補拍 推播"]

解析器(src/parse.jsparse.test.js 共 22 個案例涵蓋解析器與 wantsEagle)吃工地實際會貼的格式:

  • 日期:民國(115.7.1)、西元、M.D 都認得;同日期重貼=覆蓋舊版並提醒重新確認。
  • 樓層 / 位置:單層、範圍(23F 28F)、以上/以下;區域詞自動判別(車道、前中庭、北側… 台灣工地詞庫)→ 樓層綠 chip、區域中性 chip。
  • 人數:前置或後置、含不含「人」都可;0 人照列不丟
  • 看不懂的行不會默默消失 → 卡上 ⚠ 未整理提示,編輯器裡可「加入」(轉成正式列)或「移除」。
9 出工日報 ?v=daily今日 / 7日 / 月 + ‹› 日期導航(可帶 &d=日期 落到特定日)。已確認徽章、出工合計與較上次差異、⚠ 建議 banner(已派 26 人但收到 0 張照片 → 請工班補拍)。只顯示已確認的日報。
10 日報修改 &edit=1(主任限定,確認也是)逐列展開編輯(樓層可留空、人數可 0)、新增一項、合計自動重算 → 儲存並確認,重發修正卡到群組。

證據 · 總覽 · 說明

11 證據 ?v=evidence上:待採認工作清單 — 逐樓層浮出(1F 拍完就出現,不等 2F),點列深連審核詳情該樓層。下:全專案照片流(全部 / 已採認 / 待採認 / 被退回 + 日期分組)。
12 總覽 ?v=overview完成率環 + 已完成/進行中/待處理 + 待採認/逾期計數 + 工班排行(全部 / 本週 / 今日)。排行的綠色 podium 只給真實達成,0/N 顯示素色條。
13 使用說明 ?v=help走 LIFF 白色 chrome — 不外開瀏覽器,因為 LINE 內建瀏覽器會忽略 theme-color。主任 / 監工兩段步驟教學。

06監工(群組)

底部導覽四個 tab(NAV_CREW):我的工項 · 我的照片 · 排行 · 問 Eagle。點 logo → 我的工項。

14 我的工項 ?v=mine「我的|全部」tab(監工預設我的)、頂部進度條、最新在上排序、一掃描一卡(accordion)+ 編號 pin 找自己的框、「你」tag、待處理 / 逾期 chip。
15 工項詳情:拍照回報進度 X/N、聚焦綠框(其他變暗)。逐項「拍照」→ 原生相機 → 未拍滿自動續拍、拍滿 N 張自動完成 → 群組完成卡 + 主任 1:1 審核卡。縮圖點開燈箱(刪除這張 / 再拍一張;掉到 N 以下會退回待處理)。主任開別人的=代為拍照。
16 我的照片 ?v=photos自己的證據流 + 已採認 / 待採認 / 被退回篩選 + 日期分組。
17 排行同一支 ?v=overview,角色決定內容:監工只看工班排行,主任看完整儀表板。
18 問 Eagle ?v=ask即時狀態(完成 / 待處理 / 逾期)+ 常見問題 accordion。群組情境只回本專案。
19 守門監工點「指派工項」→ 不硬擋,落到我的工項 + 提示「只有工地主任可以指派工項」。審核 deep-link 同理被擋(modal「只有工地主任可以審核工項」)。

07聊天拍照回報(不開 LIFF 也能交)

監工不一定會開 LIFF 拍照 —— 直接把照片丟進群組(或 1:1)也算回報。Worker 收到照片 → 下載進 R2 → 進待歸檔佇列(pending_capture),約 2 秒 debounce 把一波連發照片收成一張卡(LINE 每張照片是獨立 webhook)。

flowchart LR
  P["照片進群組 / 1:1
每張是獨立 webhook"] --> C["2 秒收批
「這是哪一項?」卡"] C --> K["點一下歸檔
(cap: postback)"] K --> D{"拍滿張數?"} D -->|是| F["完成卡 → 審核流"] D -->|否| W["繼續等照片"] C -.->|"混批 / >13 張 / 1:1"| S["整理照片頁
?v=capture&b=批次"]

「這是哪一項?」卡(captureAskCard())回顯照片 + 該監工未完成的工項/樓層按鈕(標籤唯一:「工項N · 第M張 · 樓層」);主任會看到全工班的代傳選項(名字前綴)。沒待辦且不是主任 → bot 安靜(不打擾閒聊丟圖)。

20 整理照片 ?v=capture&b=批次未歸檔照片托盤(可全選)→ 點一個工項歸進去(選取優先 + 確認抽屜)。每列=工項 · 第 M 張 + 進度 / 逾期 chip。1:1 丟照片一律走這頁(跨專案)。
情境規則行為
同人約 2 分鐘內又丟照片先確認再入帳:「延續上一項 — 這張也記到【工項N】嗎?」[是的][換一項·整理照片 ›][略過]。會寫資料的自動行為一律先確認(上次選擇存 capture_pick
點到舊卡片的按鈕每波照片有 batch id,postback 全帶 batch、處理範圍鎖 WHERE batch=?。舊卡 → 「這批照片已處理」,不會誤刪 / 誤歸新照片
沒待辦且不是主任bot 保持安靜(不發卡)
逾時待歸檔托盤 15 分鐘過期;提問卡以約 15 秒連發窗口去重

081:1 個人(指揮中心)

模型:群組=工班佈告欄;主任的 1:1=指揮中心。1:1 導覽四個 tab(NAV_PERSONAL):儀表板 · 我的工項 · 我的照片 · 問 Eagle(Rich Menu 是入口,LIFF 底欄同構)。所有頁面跨專案彙整,多群以專案分組。

21 我的儀表板 ?v=dash主任視角:頂部「N 項待採認」CTA、完成率環、總工項/照片/平均、採認/退回/接受率、本週/今日/逾期、近 7 日長條、各請款單進度。Rich Menu 的主要落點。
22 雙身分切換(lens)有的群當主任、有的當監工 → 右上「檢視:… ▾」下拉切視角(以工地主任檢視 / 以監工檢視)。純 UI 視角,不改伺服器授權;單一身分的人看不到這顆。
23 我的工項(跨專案) ?v=mine「我的工項|待採認」tab;每卡帶所屬群組的角色 badge。在 1:1 拍照會寫回原專案群組(完成推播落在原群)。
24 待採認佇列 ?v=mine&tab=review主任視角才有:所有專案待審一字排開。聊天卡「前往待採認 ›」落這。
25 我的照片(跨專案) ?v=photos跨 N 個專案 · 共 M 張 + 篩選;其餘同群組版。
26 問 Eagle(1:1) ?v=ask跨專案彙總(含「待你採認 N 項」管理者列)。1:1 打任何字 bot 都會答,不用喚起詞。
主任的 1:1 會收到什麼(固定 pattern:1:1 操作 → 效果回到群組)
  • 監工完成 → 「待你審核」卡,按鈕「前往待採認 ›」=跨專案佇列(不是單群審核頁)。監工沒加 OA 好友時退回發群組。
  • 問 Eagle「誰還沒交」→ 還沒交卡上每個專案一顆「催 {專案} 工班 →」(nudge postback)→ 該群組收到「待回報提醒」卡。
另一個入口?v=progress=我的進度純數字儀表板(完成率環 + 週/今日/逾期,沒有清單;showMine(false,true))。與 ?v=dash 相鄰但不同頁,Rich Menu 舊版曾指這裡。

09聊天卡片總表

所有卡片共用一個殼(flexCard()):tone 色條頂欄 + 內文 + 綠色主 CTAprimaryBtn,次要動作灰色)。瀏覽器渲染不出 Flex — 改動要在手機上用「新觸發的訊息」驗(舊卡片永遠凍結在發送當下)。

四種代表卡片的長相(示意,非實際渲染 — 聊天卡片只在 LINE 對話裡呈現,無法截圖):

✅ 工項完成工項完成
江肇偉-Wesley · 工項 1 · 1F
照片 2/2
審核 ›
📸 收到照片收到 3 張照片
(回顯照片)這是哪一項?
工項1 · 第10張 · 1F工項2 · 第10張🗂️ 從清單選工項 ›
⏳ 待你採認3 項
1. HaGima2 項2. LeePan1 項
逐項審核 ›
出工日報 · 已整理7/1(三)· 26 人
23F 28F 室內細清4 人車道 磚抹縫3 人
確認修改
卡片 / 訊息色調發到哪什麼時候發按鈕 → 落點
群組歡迎 + imagemap 選單群組bot 被加入群組四個 tap zone(見第 2 章
1:1 歡迎 + 問 Eagle 按鈕卡1:1加 OA 好友常見問題按鈕(送文字)
加入廣播「X 加入工項 · 身分:…」文字群組LIFF 選擇 / 變更角色
指派通知(每位監工:工項 N · 樓層 · 截止)群組主任送出指派開啟我的工項 › ?v=mine&g=
收到照片「這是哪一項?」群組 / 1:1照片進聊天(2 秒收批)工項/樓層按鈕(cap:)· 從清單選工項 › ?v=capture&b= · 略過(capskip:
延續上一項?(連拍確認)群組 / 1:1同人 2 分鐘內再丟照片是的 · 換一項·整理照片 › · 略過
工項完成 / 已回報群組 + 主任 1:1 副本拍滿需要張數群組卡:審核 › ?rev=;1:1 卡(kick「待你審核」):前往待採認 › ?tab=review
採認 / 退回結果(退回附理由 + @提及監工) / 群組主任在審核頁操作—(單項採認安靜;整組完成才發全部採認通知)
出工日報「已整理」→ 確認後「✅ 已確認」版中性群組群組貼派工文字(重貼=覆蓋 + 提醒)確認(dl_confirm:,主任限定)· 修改(?v=daily&edit=1
請工班補拍群組主任在日報頁按「請工班補拍」開啟我的工項 ›
每日提醒 digest「N 項今明到期/逾期」 / 群組每天 08:00,有今明到期或逾期才發🔔 提醒全部 ›(remindall:,主任限定)· 查看工項 ›
提醒全部(textV2 @提及未交監工 + 各自 1:1「🔔 主任提醒」卡) / 群組 + 監工 1:1digest 按鈕,或主任打「提醒全部」1:1 卡:開啟我的工項 拍照回報 ›
待回報提醒(催工班)指定群組主任在 1:1 按「催 {專案} 工班 →」(nudge:開啟我的工項 拍照回報 ›
問 Eagle 答案卡:待你採認 ⏳ / 還沒交 ❌ / 逾期·到期 🚨⏳ / 需要注意 👀 / 純文字依內容群組 / 1:1@提及、問句、智慧判斷(見第 3 章逐項審核 › / 查看工項 › / 催工班 →
問 Eagle 按鈕選單(綠 header)群組 / 1:1打招呼、純 @提及、「問 Eagle」單詞什麼時候到期? / 有沒有被退回?(管理者+待我採認 / 誰還沒交)
異動通知:重新指派(工項 N 從舊→新)/ 刪除 / 截止日修改精簡群組主任在 LIFF 操作重新指派帶「開啟我的工項 ›」
出站 @提及的格式bot 發出的 @mention 必須用 textV2 + substitution{key}{type:"mention", mentionee:{type:"user", userId}})。text + mention.mentioneesinbound webhook 的格式,發送時被 LINE 靜默忽略、變純文字。Flex 卡本身不能帶 mention → 需要 @提及時另發一則伴隨文字。

計費(reply 免費 / push 計額度)見第 11 章

10LIFF 路由 / Deep-link

單一入口 liff.line.me/2010491601-uK7jHMCT(= worker 根路徑)。route() 分流順序:help / photos / capture(不需成員身分)→ 1:1 個人模式(沒有 g)→ 載入成員 → 非成員一律先落角色選擇rev= 審核深連 → 各 v= 畫面。

參數表

參數畫面備註
?g=群組id群組情境bot 烙進所有群組連結;沒帶 v 時主任 → 上傳/指派、監工 → 我的工項 + 提示
(沒有 g)1:1 個人模式跨專案;雙身分先解析檢視身分
?v=mine我的工項 / 審核清單群組:監工「我的|全部」、主任落「待採認」;1:1:「我的工項|待採認」
?v=mine&tab=review1:1 跨專案待採認佇列聊天卡「前往待採認 ›」用
?v=progress我的進度純數字儀表板完成率環 + 週/今日/逾期,無清單(showMine(false,true)
?rev=請款單_框(配 g)審核詳情 deep-link可帶樓層;聊天完成卡「審核 ›」用;非主任被擋
?v=daily出工日報&d=YYYY-MM-DD 落日、&edit=1 修改模式(主任)
?v=evidence證據(照片流 + 待審清單)群組限定
?v=overview總覽 / 排行主任全量、監工只排行
?v=photos · ?v=ask我的照片 · 問 Eagle群組=本專案;1:1=跨專案
?v=dash我的儀表板(1:1)Rich Menu 主要落點
?v=capture&b=批次整理照片聊天卡「整理照片 ›」用;1:1 丟照片一律走這
?v=join · ?v=help已加入頁 · 使用說明help 不需成員身分(白色 LIFF chrome)

開發輔助參數

參數作用
?as=userId | super | crew只在 localhost 生效(hostname 硬性 gate,正式站無效)。模擬身分渲染(唯讀 — 寫入仍需真 token,匿名 403)。配 ?g= 且不帶 as =自動帶該群主任
?name=顯示名只在 localhost 生效。mock 的顯示名稱(預設 Dev)
?p=1強制 1:1 個人模式。正式站也生效(不受 hostname gate)
?dev=1顯示群組 ↔ 1:1 跳轉 chip。正式站也生效

只有 ?as / ?name(身分 mock)被 hostname 鎖在 localhost;?p=1 / ?dev=1 在線上 workers.dev 也會作用。跑法:cd line-worker && npx wrangler dev --remote(接真實 remote D1)→ http://localhost:8787/?g=…&as=…

11Worker API · 資料層 · 排程

Routes

Route用途
POST /line/webhookbot 事件(訊息 / 照片 / postback / 進群 / 加好友)。X-Line-Signature HMAC 驗簽只在有設 LINE_CHANNEL_SECRET 時執行 — 沒設就全部放行不驗
/api/members名冊查詢(?group=)+ 選角色(一群一主任在這擋)+ 加入廣播
/api/assign送出指派:存 payapp + boxes、掃描圖進 R2、群組推播。欄位不齊 → 400,save-first 不假 ok
/api/payapp · /api/payapp/edit讀掃描(?group=)/ 改框(拍照、採認退回、改派、刪除、改截止 — 逐框 patch,防多人互相覆蓋)
/api/mine · /api/review1:1 跨專案工項(?user=)· 跨專案待採認 + 是否主任
/api/dailylog(+ /save /remind日報讀取 / 主任限定儲存(重發修正卡)/ 補拍提醒
/api/capture(+ /file整理照片:批次讀取 / 歸檔寫入(batch 範圍內)
/api/ask · /api/events問 Eagle 資料(&g= 定範圍)· 群組稽核 log(最近 200 筆)
POST /api/img上傳一張照片到 R2(回傳 line/ key)— LIFF 拍照回報的寫入面
GET /img/<key>提供 R2 照片(只允許 line/ 前綴,長效 immutable cache)
/menu/<序號>/<寬>選單圖(menu-寬.png;換圖要 bump 序號 + 重發選單)
/privacy · /terms平台審核用頁面

寫入授權

  • LIFF 寫入帶 liff.getAccessToken() → worker 打 LINE /v2/profile 驗人 → 依 members 角色授權(主任 / 本人)。
  • 匿名請求 → 403。localhost dev-mock 也因此唯讀。
  • 聊天 postback(採認 / 確認 / 提醒全部…)在 webhook 端用 roleOf() 再驗一次主任身分。

資料層(D1 + R2)

表 / 桶內容
members每群一份的角色(super / foreman)+ 名字頭像
payapps一張掃描一列。boxes=內嵌 JSON:% 座標 + 指派人 + 需要張數 req + photos + 截止 due + 樓層 floors + 逐樓層照片/審核(fp / fpReview / fpReturned)+ 採認 review / 退回 returned
assignments指派彙總(人 × 數量)
daily_log出工日報(解析後的列 + 確認狀態;未整理行以 {unsorted:true} 標記混存,無 schema 變更)
pending_capture · capture_pick聊天照片待歸檔佇列(含 batch 欄)·「延續上一項」的上次選擇
line_groups群組 → 專案名對照(ensureGroupName() 首次看到群組時經 getGroupSummary 學起來)
events稽核 log(誰在何時對哪個框做了什麼)
R2 eagle-line-evidence所有照片與掃描(line/ 開頭 key,經 /img/ 提供)

wa_evidence / wa_sessionWhatsApp 頻道的表(同一個 worker 的另一條線),不屬於 LINE。

測試 · 排程 · 計費

  • 測試:npm test34 個案例(parse.test.js 22:日報解析 + wantsEagle 分類;boxpatch.test.js 12:逐框 patch 防覆蓋)。
  • 排程:cron 0 0 * * *(UTC 00:00 = 台灣 08:00)掃所有群組:今明到期或逾期的未回報工項 → 發 digest 卡(帶「提醒全部」按鈕);沒有到期項就不發
  • 計費:reply(回應使用者動作)免費不限量;push 計入 OA 月額度(台灣 Light 200 / Standard 3,000 / Premium 6,000 則)— digest、指派通知、完成卡、催工班都是 push。

12檔案與交接

帳號與環境

項目值 / 備註
LINE Provider「Eagle AI」(台灣)· OA 未驗證(驗證解鎖群組自動名冊,非關鍵路徑)
LINE Login channel2010491601 — 掛 LIFF 2010491601-uK7jHMCT(size Full,scope profile+openid)。必須維持 Published:Developing 狀態下非開發者開啟會 400
Messaging API channel2010491594 — bot;webhook ON → …/line/webhook
Secrets(wrangler secret)LINE_CHANNEL_ACCESS_TOKEN(push / reply 必需)· LINE_CHANNEL_SECRET(webhook 驗簽,選配)
CloudflareWorker eagle-line · D1 eagle-line · R2 eagle-line-evidence(Jared 的 CF 帳號)

檔案地圖

去哪看位置(重點函式)
程式(唯一交付 repo,禁 AI 署名GitLab JaredSong1/eagle-line=本機 eagle-ai-qms/line-worker/(獨立 git,母 repo 已解除追蹤)
Bot / 卡片 / cron / 喚起詞判斷src/index.js — 卡片殼 flexCard() · 選單 menuImagemap() · 拍照收件 captureAskCard() · 完成 fireCompletion() · 提醒 remindAllPending() · 打招呼 isGreeting() · 排程 scheduled()
LIFF 全部畫面public/index.htmlroute() 開始讀 · 三組導覽 NAV_SUPER / NAV_CREW / NAV_PERSONAL · 審核深連 openReviewDeep() · 日報 showDaily()
解析器 + 智慧回覆 + 測試src/parse.jsparseDailyLog() · wantsEagle())+ tests/
資料層schema.sql(⚠ DROP+CREATE)+ migrate-*.sql(增量,remote 用這些)
選單 / Rich Menu 美術源檔母 repo line-channel-design/menu-art/;輸出品 public/menu-*.png
決策史 / 60 條教訓母 repo docs/specs/eagle-line-channel.md

部署流程

  • 部署:cd line-worker && npm run deploy(wrangler 是本地 devDependency — 一次性指令用 npx wrangler …)。
  • 部署後必驗 live:curl + ?cb=隨機值 抓 LIFF 首頁、grep 本次改動的標記字串 — 「No updated asset files」訊息可能伴隨舊資產,眼見為憑。
  • 換選單美術:重出 menu-*.png → bump /menu/序號 → 部署 → 在群組重發選單(打「選單」)。
  • 資料庫異動:只跑增量 migrate-*.sqlnpx wrangler d1 execute eagle-line --remote --file=…)。
四個地雷
  • Flex 卡瀏覽器看不到,只能手機驗新觸發的訊息;舊卡片凍結在發送當下。
  • src/wa.js / wa_* 表是 WhatsApp 頻道,不是 LINE。
  • 群組選單=imagemap 訊息,1:1 才是 Rich Menu,機制完全不同。
  • schema.sql 是 DROP+CREATE,絕不能重跑在 remote

Eagle AI · LINE 頻道系統文件 · 2026-07-07 · 截圖 28 張 + 選單素材 2 張(shots/)· 喚起詞、路由、API、資料層均已對照 line-worker/ 原始碼核實 · 僅供內部交接。