Update DOX docs for R2 image upload

This commit is contained in:
2026-09-12 10:10:21 +08:00
parent df330ffd70
commit 00502e5e52
3 changed files with 9 additions and 5 deletions
+5 -3
View File
@@ -15,6 +15,7 @@
- `env.d.ts``App.Locals.isAdmin` 型別宣告。
- `schemas/` — Zod 驗證層:admin 表單輸入(post / content / case / settings / ai / keyword)同 AI 輸出格式;配合 `lib/form.ts``parseForm``lib/ai.ts` 的生成流程使用(`lib/` 細節由 `lib/AGENTS.md` 擁有)。
- `pages/` — 路由層同 `/admin` 後台(詳見下面 Routes & SSR / Admin,因 Astro 限制冇獨立 child doc)。
- `components/admin/ImageField.astro` — 後台圖片欄位(URL text input + 揀檔上傳/預覽);client 端縮圖同 fetch `/admin/upload` 嘅 script 喺 `layouts/AdminLayout.astro`
## Local Contracts
@@ -32,7 +33,8 @@
- **環境變數**:只用 `getEnv()`,且只可喺 `prerender = false` 的頁面/endpoint 用。
- **前台動態頁**:讀 D1 → 傳 props 畀單一 React island`client:load`),並設邊緣快取 `Cache-Control: public, s-maxage=60, stale-while-revalidate=300`
- **404**`blog/[slug].astro` 找唔到文章 → 設 `Astro.response.status = 404` 並 render noindex 頁。
- **Endpoint**:用 `APIRoute``sitemap.xml.ts` 由 D1 讀已發布文章並設 `s-maxage=3600``media/[...key].ts` 由 R2 讀圖並回 `public, max-age=31536000, immutable`+ ETag / 304
- **Endpoint**:用 `APIRoute``sitemap.xml.ts` 由 D1 讀已發布文章並設 `s-maxage=3600`
- **圖片 endpoints**`/admin/upload`POST,受 middleware 保護,寫入 R2 `MEDIA`);`/media/[...key]`GET,公開讀 R2 出圖,設 `Cache-Control: public, max-age=31536000, immutable` 同 ETag304)。
- **AI 生成(同步)**`/admin/ai` 的生成喺 admin POST 內同步 `await` 完成先 redirect。如日後要改做背景處理,可用 `Astro.locals.cfContext`Cloudflare `ExecutionContext`)嘅 `waitUntil`,唔使改現有流程。
- **SEO**:用 `Base.astro`canonical / OG / sitemap 全部靠 `astro.config.mjs``site`(現為佔位 `https://example.com`,上線前要改)。
@@ -48,7 +50,7 @@
- **網站設定**`settings.astro``data/settings-fields.ts``SETTINGS_GROUPS` / `ALL_SETTING_KEYS` 產生表單,逐 key upsert。
- **文章**`index.astro` 列表、`post/[id].astro` 新增/編輯(`id === "new"` 為新增);slug 自動 `slugify` 並用 `uniqueSlug` 去重。
- **AI 生成**`ai.astro``/admin/ai`)管 AI 設定 + 關鍵字佇列,同步呼叫 `generateBlogPost`;成功會 redirect 去新草稿 `/admin/post/<id>`。生成按鈕用 inline `onsubmit` 顯示「生成中…」。
- **圖片**一律以 URL 字串處理。上傳經 `admin/upload.ts``POST``scope ∈ settings | cases | posts`JPG/PNG/WebP/GIF、上限 8MB,存 R2 `MEDIA`,回 `{ ok, url }`);對外由公開 `media/[...key].ts` 服務
- **圖片**圖片欄位(settings 的 `hero_image` / `og_image``cases.imageUrl``posts.coverImage`)用 `components/admin/ImageField.astro`,可揀檔即時上傳去 R2(binding `MEDIA`),亦可貼 URLclient 端縮到最大寬 1600px 並轉 WebP 先上傳。上傳 endpoint `/admin/upload`(受 middleware 保護`scope ∈ settings | cases | posts`JPG/PNG/WebP/GIF、上限 8MB),出圖 endpoint `/media/[...key]`(公開、`immutable` cache)。換圖/刪除時由 `lib/media.ts``deleteMedia` 清舊 R2 檔
- 前台可見性靠 `status``published` / `draft`);列表頁顯示全部,前台只顯示 published。
## Work Guidance
@@ -70,4 +72,4 @@
| `components/site/AGENTS.md` | 前台 React island 與 Chakra UI 元件 |
| `data/AGENTS.md` | D1 讀取查詢層與後台設定欄位定義 |
| `db/AGENTS.md` | Drizzle schemamigration 的唯一來源) |
| `lib/AGENTS.md` | auth / env / db / form / ai / markdown 基礎工具 |
| `lib/AGENTS.md` | auth / env / db / form / media / ai / markdown 基礎工具 |