{“content”:”---\nname: hs-design-landing\ndescription: HS Design 网页项目维护 — 部署、Git push、Cloudflare Pages、D1 数据库\n---\n\n# HS Design Landing 项目维护手册\n\n## 项目信息(已更新 2026-04-22)\n\n- 本地路径: D:\\OpenClaw_Home\\.openclaw\\workspace\\projects\\hs-design-landing\n- GitHub 仓库: JakeBilu/Landing-Page(private)\n- Cloudflare Account ID: f6b7326e471bbe3d1b0a0e2ba770f47d\n- Cloudflare Global API Key (cfk_…): cfk_r8ECCUq8K0nZjyuJGkbWEelbYX4r3NxyBnuqK5zj38f26a11(存 ~/.hermes/auth.json)\n- wrangler scope token (cfut_…): cfut_12ghB5p8RCyV44tggQebkEVUwOIWKAkuItxQuc0814c82082(Workers Scripts Read/Write)\n- Production URL: https://hsdesign.biz/HS_Design_Quotation(报价工具,无 .html 后缀,308 重定向自 /HS_Design_Quotation.html)\n- 注意: hsdesign.biz 本身是另一个项目(Health Space Interior),报价系统在子路径\n- GitHub SSH: id_ed25519 key 对 GitHub push 无效,必须通过 PC 的 git -C \"D:\\OpenClaw_Home\\.openclaw\\workspace\\projects\\hs-design-landing\" push 方式 push\n- D1 Database: hsdesign-quotes(UUID: 8d776216-e135-4c9f-b1bb-9669cb10bd85)\n- wrangler.toml 绑定: [[d1_databases]] name=“DB”, database_id=“8d776216-e135-4c9f-b1bb-9669cb10bd85”\n\n## 架构(Workers with Assets,2026-04-22 确认)\n\n\nGitHub (JakeBilu/Landing-Page main)\n ↓ git push\nCloudflare Workers with Assets (hsdesign worker)\n ↓ 自动部署 ~30s\nhttps://hsdesign.biz/\n├── index.html # 主网站(极简奢华升级 2026-04-22)\n├── HS_Design_Quotation.html # 报价工具(D1 后端)\n├── quote-app.js # 报价工具前端逻辑\n└── _worker.js # Cloudflare Worker(所有路由在此)\n\n\n重要:这是 Workers with Assets 架构,不是 Pages Functions!Worker 文件是 _worker.js(根目录),部署后 Cloudflare 自动将其作为 Worker 处理,同时 env.ASSETS.fetch(request) 服务静态文件。functions/ 目录不会被自动识别。\n\n所有路由都在 _worker.js 内:\n- /notion-proxy/* → 转发到 Notion API\n- /d1-api/* → D1 REST API(fetch 到 api.cloudflare.com/.../d1/database/{id}/query)\n- 其他 → env.ASSETS.fetch(request)(静态文件)\n\n**⚠️ Workers with Assets + D1 binding 限制**:\n- wrangler.toml 的 [[d1_databases]] binding 无法自动注入到 Workers with Assets Worker\n- env.DB 在 Worker 中是 undefined\n- 解法:Worker 用 Cloudflare Global API Key 调用 D1 REST API(fetch,无需 D1 binding)\n- D1 REST API 端点:POST https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}/query\n- 注意路径是 d1/database/(不是 d1/databases/)\n\n## 文件上传到远程 PC(已验证流程)\n\nSCP 路径格式(SSH 命令中用双反斜杠):\n\nsozo@100.83.112.84:C:\\\\Users\\\\sozo\\\\AppData\\\\Local\\\\Temp\\\\filename\n\n\n上传本地文件到远程 temp:\nbash\nscp -i ~/.ssh/id_ed25519_hermes -o StrictHostKeyChecking=no \\\n /path/to/local/file \\\n \"sozo@100.83.112.84:C:\\\\Users\\\\sozo\\\\AppData\\\\Local\\\\Temp\\\\filename\"\n\n\n远程执行 PowerShell 脚本:\nbash\nssh -i ~/.ssh/id_ed25519_hermes -o StrictHostKeyChecking=no sozo@100.83.112.84 \\\n 'powershell -ExecutionPolicy Bypass -File C:/Users/sozo/AppData/Local/Temp/script.ps1'\n\n\n## Git Commit + Push(正确方式)\n\n**⚠️ SSH key 注意**:~/.ssh/id_ed25519 对 GitHub 无效(Permission denied)。必须通过 PC 的 PowerShell 执行 git 命令。\n\nSCP 上传修改文件到远程 PC:\nbash\nscp -i ~/.ssh/id_ed25519_hermes -o StrictHostKeyChecking=no \\\n /path/to/local/file \\\n \"sozo@100.83.112.84:C:\\\\\\\\Users\\\\\\\\sozo\\\\\\\\AppData\\\\\\\\Local\\\\\\\\Temp\\\\\\\\filename\"\n\n\n在远程 PC 上 commit + push:\nbash\nssh -i ~/.ssh/id_ed25519_hermes sozo@100.83.112.84 \\\n 'powershell -Command \" \\\n Copy-Item C:\\\\Users\\\\sozo\\\\AppData\\\\Local\\\\Temp\\\\quote-app.js D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing\\\\quote-app.js -Force; \\\n git -C D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing add quote-app.js; \\\n git -C D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing commit -m '\\''Add adjustable markup rate'\\''; \\\n git -C D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing push \\\n \"'\n\n\n完整工作流(本地修改 → 上传到 PC → push):\n1. 本地编辑文件\n2. scp 上传到 PC temp:scp -i ~/.ssh/id_ed25519_hermes local.js sozo@100.83.112.84:'C:\\\\Users\\\\sozo\\\\AppData\\\\Local\\\\Temp\\\\local.js'\n3. SSH 到 PC 执行 copy + commit + push(如上)\nbash\nssh ... sozo@100.83.112.84 \\\n 'git -C \"D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing\" add -A && \\\n git -C \"D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing\" commit -m \"描述\" && \\\n git -C \"D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing\" push origin main'\n\n\n### Git Push 后 Pages 没更新\n\n项目名是 hsdesign,不是 hs-design-landing:\nbash\ncurl -s \"https://api.cloudflare.com/client/v4/accounts/f6b7326e471bbe3d1b0a0e2ba770f47d/pages/projects\" \\\n -H \"X-Auth-Email: ida.czia@gmail.com\" \\\n -H \"X-Auth-Key: $CF_KEY\"\n\n\n## D1 API Worker(独立 Worker,非 Workers with Assets)\n\n部署目录: D:\\OpenClaw_Home\\.openclaw\\workspace\\projects\\hs-design-test\\\n\n**⚠️ 关键:必须使用 ES Module 格式**:\n- 文件后缀 .mjs,使用 export default { fetch(request, env) {...} }\n- ❌ addEventListener('fetch', event => {...}) 旧格式会导致 error 1101(Worker 内部未捕获异常),原因未知\n- wrangler.toml 必须指定 main = \"d1-api-worker.mjs\"\n\nwrangler.toml:\ntoml\nname = \"hsdesign-d1-api\"\nmain = \"d1-api-worker.mjs\"\naccount_id = \"f6b7326e471bbe3d1b0a0e2ba770f47d\"\ncompatibility_date = \"2024-01-01\"\n\n\n部署命令:\nbash\ncd D:\\OpenClaw_Home\\.openclaw\\workspace\\projects\\hs-design-test\nset CLOUDFLARE_EMAIL=ida.czia@gmail.com\nset CLOUDFLARE_API_TOKEN=cfut_12ghB5p8RCyV44tggQebkEVUwOIWKAkuItxQuc0814c82082\nnpx wrangler deploy --name hsdesign-d1-api\n\n\nSecret 上传(部署后必须执行):\nbash\necho cfk_r8ECCUq8K0nZjyuJGkbWEelbYX4r3NxyBnuqK5zj38f26a11 | npx wrangler secret put CF_API_KEY --name hsdesign-d1-api\n\n\nWorker URL: https://hsdesign-d1-api.ida-czia.workers.dev\n\n端点(只有这些,Worker 把 /d1-api 去掉后剩余部分当 SQL 查 D1):\n- GET /d1-api/test → 检查 env 状态,返回 {cf_api_key_set, env_keys}\n- POST /d1-api body: {\"sql\": \"SELECT ...\"} → D1 查询\n\n**⚠️ 重要:前端调用 URL 必须是 Worker 根地址,不能带任何路径!\njavascript\n// ✅ 正确:直接 POST 到 /d1-api,SQL 在 body\nfetch('https://hsdesign-d1-api.ida-czia.workers.dev/d1-api', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sql: 'SELECT * FROM quotes LIMIT 50' })\n})\n\n// ❌ 错误:带 /v1/databases/... 路径(这是 Notion API 格式,Worker 不认)\nfetch('https://hsdesign-d1-api.ida-czia.workers.dev/d1-api/v1/databases/xxx/query', ...)\n\n\n调试技巧**:\n1. 先用 curl 确认 Worker 正常:curl https://hsdesign-d1-api.ida-czia.workers.dev/d1-api/test\n2. 再用 curl 测实际查询:curl -X POST https://hsdesign-d1-api.ida-czia.workers.dev/d1-api -H 'Content-Type: application/json' -d '{\"sql\":\"SELECT 1\"}'\n3. 如果 curl 成功但浏览器失败 → 检查前端 JS 的 URL 路径是否正确\n\n已知错误码:\n| 错误码 | 原因 | 解决 |\n|--------|------|------|\n| 1101 | addEventListener 旧格式 | 改 ES Module 格式 |\n| 1042 | compatibility_flags nodejs_compat | 去掉该 flag |\n| 1104 | Workers 平台暂时性错误 | 等几秒重试 |\n| 10000/9109 | Token 权限不足 | 用 wrangler-full scope token |\n| 400 | SQL 语法错误或路径错误 | 检查 URL 路径是否正确,Worker 收到的是无效 SQL |\n\n**⚠️ [vars] 陷阱**:绝对不要在 wrangler.toml 写 [vars] CF_API_KEY=\"***\",这会覆盖 secret\n\n## Workers with Assets + D1 binding 限制\n\nwrangler.toml 的 [[d1_databases]] binding 无法自动注入到 Workers with Assets Worker。解法:Worker 用 Cloudflare Global API Key 调用 D1 REST API。\n\nDatabase: hsdesign-quotes,UUID: 8d776216-e135-4c9f-b1bb-9669cb10bd85\n\n## D1 REST API(备用信息)\n\n注意:2026-04-23 已改用独立 D1 Worker(见上方章节)。以下信息仅作参考。\n\nDatabase: hsdesign-quotes,UUID: 8d776216-e135-4c9f-b1bb-9669cb10bd85\n\nD1 REST API 端点(Worker 内通过 fetch 调用):\n\nPOST https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}/query\nAuthorization: Bearer {CF_GLOBAL_API_KEY}\nContent-Type: application/json\nBody: {\"sql\":\"SELECT * FROM quotes LIMIT 10\"}\n\n注意路径是 d1/database/(不是 d1/databases/)\n\nWorker 内 D1 调用方式(必须用 REST API,不能用 env.DB):\njavascript\nconst CF_ACCOUNT_ID = 'f6b7326e471bbe3d1b0a0e2ba770f47d';\nconst CF_API_KEY = env.CF_API_KEY; // 从 secret 或 env 变量获取\n\nasync function d1Query(sql) {\n const res = await fetch(\n `https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/d1/database/8d776216-e135-4c9f-b1bb-9669cb10bd85/query`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${CF_API_KEY}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ sql })\n }\n );\n return res.json();\n}\n\n\n## 报价工具(HS_Design_Quotation.html)\n\n前端路由:quote-app.js 使用 PROXY = 'https://hsdesign-d1-api.ida-czia.workers.dev/d1-api'\n\n### ⚠️ Cache Busting(重要!防止用户加载旧版本 JS)\n\nHTML 入口 HS_Design_Quotation.html 包含以下 cache control meta tag,确保每次打开都拉最新代码:\nhtml\n<meta http-equiv=\"Cache-Control\" content=\"no-cache, no-store, must-revalidate\">\n<meta http-equiv=\"Pragma\" content=\"no-cache\">\n<meta http-equiv=\"Expires\" content=\"0\">\n\n\n同时 quote-app.js 带有版本号:\nhtml\n<script src=\"quote-app.js?v=20260425\"></script>\n\n\n每次更新 quote-app.js 后,必须同时更新 HTML 里的 v= 值! 这样即使用户浏览器缓存了旧 JS,加载 HTML 时也会拉取新版 JS 文件。更新 version 的流程:\n1. 修改 quote-app.js\n2. 更新 HS_Design_Quotation.html 里的 v= 为当天日期(如 v=20260426)\n3. git add → commit → push\n\n### Playwright 浏览器测试\n\n测试脚本(PC 上运行):C:\\Users\\sozo\\AppData\\Local\\Temp\\test_login_hsdesign2.py\n\n执行方式(从 Termux SSH 到 PC):\nbash\nscp -i ~/.ssh/id_ed25519_hermes test_script.py sozo@100.83.112.84:'C:\\Users\\sozo\\AppData\\Local\\Temp\\'\nssh ... 'cmd /c set PYTHONIOENCODING=utf-8 && set PYTHONLEGACYWINDOWSSTDIO=utf-8 && python C:/Users/sozo/AppData/Local/Temp/test_script.py'\n\n\n测试重点检查:\n- chkGate type(应为 function,不是 undefined)\n- Page errors(应为 0)\n- Console errors(应为 0)\n- Gate display after login(应为 none)\n\n## 报价工具已知 Bug(2026-04-24)\n\n**⚠️ 关键:前端必须直接 POST 到 Worker 根地址 /d1-api,SQL 在 JSON body 里**\njavascript\n// ✅ 正确:SQL 在 body,路径只有 /d1-api\nconst PROXY = 'https://hsdesign-d1-api.ida-czia.workers.dev/d1-api';\nfetch(PROXY, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ sql: 'SELECT * FROM quotes LIMIT 50' })\n})\n\n// ❌ 错误:Notion API 格式 /v1/databases/...(Worker 不认这个路径)\nfetch(PROXY + '/v1/databases/' + DB + '/query', ...) // → D1 400 Bad Request\n\n\n实际发生的 Bug(2026-04-23):前端 quote-app.js 里所有 D1 调用都用了 Notion API 格式 /v1/databases/{DB}/query,Worker 把这段当 SQL 查 D1 导致 400。修复:把所有 PROXY + '/v1/databases/' + DB + '/query' 改成 PROXY,SQL 放 body。症状:sidebar 加载失败,localStorage fallback 生效时才能看到旧数据。\n\n调试:curl 测试 Worker 是否正常:\nbash\n# 测试端点\ncurl https://hsdesign-d1-api.ida-czia.workers.dev/d1-api/test\n# 测试实际查询\ncurl -X POST https://hsdesign-d1-api.ida-czia.workers.dev/d1-api \\\n -H 'Content-Type: application/json' \\\n -d '{\"sql\":\"SELECT id, name, status FROM quotes LIMIT 3\"}'\n\n\nWorker 端点(只有这些,Worker 把 /d1-api 去掉后剩余部分当 SQL 查 D1):\n- GET /d1-api/test → 检查 env 状态,返回 {cf_api_key_set, env_keys}\n- POST /d1-api body: {\"sql\": \"SELECT ...\"} → D1 查询\n\nquote-app.js SQL 操作(都 POST 到 PROXY,不要带路径):\n- loadQuotes: SELECT id, name, project, date, status, qno, addr, data, created_at FROM quotes ORDER BY date DESC LIMIT 50\n- saveQuote UPDATE: UPDATE quotes SET name='...', project='...', ... WHERE id='...'\n- saveQuote INSERT: INSERT INTO quotes (id, name, project, date, status, qno, addr, data) VALUES (...)\n- delQuote: DELETE FROM quotes WHERE id='...'\n\nlocalStorage 缓存:hsdesign_quotes_cache key 保存 quotes 数组,HTTP 错误时自动 fallback 显示缓存数据\n\nD1 quotes 表结构:\nsql\nCREATE TABLE IF NOT EXISTS quotes (\n id TEXT PRIMARY KEY,\n name TEXT,\n project TEXT,\n date TEXT,\n status TEXT DEFAULT 'Draft',\n qno TEXT DEFAULT '',\n addr TEXT DEFAULT '',\n data TEXT DEFAULT '{}', -- JSON: items, terms, notes2, qno, addr, notes\n created_at TEXT DEFAULT (datetime('now'))\n);\n\n\n### 报价工具缓存导致用户看到旧版本(2026-04-25)\n\n问题:代码更新后,即使用户 Ctrl+Shift+R 强制刷新,仍然看到旧版本。这是因为 Cloudflare Workers with Assets 会缓存静态文件(quote-app.js 等)。\n\n解决方案:Cache-Busting 双保险\n\n1. Cache-Control meta(入口页面)\nhtml\n<meta http-equiv=\"Cache-Control\" content=\"no-cache, no-store, must-revalidate\">\n<meta http-equiv=\"Pragma\" content=\"no-cache\">\n<meta http-equiv=\"Expires\" content=\"0\">\n\n放在 <head> 最前面(viewport meta 之后),确保每次打开页面都重新验证。\n\n2. JS 版本号(script 引用)\nhtml\n<script src=\"quote-app.js?v=20260425\"></script>\n\n每次 push 更新时更新 v= 值为当天日期,浏览器认为是新文件,自动拉取最新版本。\n\n建议:每次发布前用当天日期更新版本号,对用户完全透明,无需手动清理缓存。\n\n### quote-app.js Unicode 字符损坏导致登录失败(2026-04-24)\n- 根因:buildItemRow 中 .f-sell 是 type=\"number\" input,但 value 用 fmt(it.sell)(返回 “10,540.00” 带逗号),浏览器把逗号字符串 coerce 成空值\n- 修复:第 347 行,<input type=\"number\" class=\"f-sell\" ... value=\"${it.sell||it.sell===0?fmt(it.sell):''}\" ...> 改为 value=\"${it.sell||it.sell===0?it.sell:''}\"\n- 修复 commit:644f961\n\n#### Bug 2:PDF section total 重复显示\n- 症状:PDF 导出时 section total 行显示两遍(一次在合并单元格,一次在金额列)\n- 修复:line 604 colspan=\"6\"(原来 colspan=“5” + 单独一列)\n- 状态:已修复(commit cbb071c),如仍出现请强制刷新 Ctrl+Shift+R\n\n#### Bug 3:25% markup 硬编码\n- 状态:已修复(commit 4e98779)\n- 实现:\n - MARKUP_RATE 全局变量(默认 0.25)\n - Toolbar 有 Markup 输入框(#mk-input),5-200% 可调\n - 所有 +25% 按钮有 .mk-btn class,动态显示当前 markup 百分比\n - autoSell() 用 ct * (1 + MARKUP_RATE) 计算\n\n### quote-app.js Unicode 字符损坏导致登录失败(2026-04-24)\n\n症状:密码 HSHSHS 输入后按 Enter 没反应,页面不跳转。\n\n诊断流程:\n1. Playwright on PC 诊断:chkGate type: undefined → chkGate is not defined\n2. 页面 console 有 PAGEERROR: Invalid or unexpected token\n3. PC 上用 Node.js 做 JS 语法检查:\n python\n subprocess.run([\"node\", \"--check\", path]) # 发现 SyntaxError at line 170\n \n4. 第 170 行:${escHtml(q.project)||'??} → 非 ASCII 字符('—' em-dash, '▾' 箭头)变成了 '??\n\n根因:文件中的中文字符/特殊符号在某个 commit 过程中被损坏为 ??,导致 JS 语法错误,浏览器无法执行脚本,所有函数(chkGate, PASS 等)都未定义。\n\n修复:\n1. 从 GitHub 逐个 commit 排查,找最后一个干净的 commit:43183af(quote-app.js 742 行)\n2. dfd8169 到 4e98779 之间的所有 commit 都已经损坏(字符在 GitHub 线上就已经坏)\n3. 从 43183af 下载干净版本,重新加上 markup 改动:\n - 加 let MARKUP_RATE = 0.25; 在 state 区\n - autoSell() 里 ct * 1.25 → ct * (1 + MARKUP_RATE)\n4. Commit f77bf27:fix: restore corrupted Unicode chars and re-add MARKUP_RATE\n\n经验教训:\n- 不要手动修复损坏的字符——从最后一个干净 commit 重建 + 重加改动,比逐字符修复更可靠\n- GitHub Raw 页面显示的也是损坏内容,说明问题在 commit 层面,不在本地\n- Node.js --check 模式可以在不上线的情况下快速定位 JS 语法错误\n\n### 报价工具 Unicode 损坏恢复流程(2026-04-25)\n\n症状:线上报价页面无法登录,DevTools 显示 SyntaxError: Invalid or unexpected token,chkGate is not defined\n\n诊断:\nbash\n# 线上文件语法检查\ncurl -s \"https://hsdesign.biz/quote-app.js\" | node --check\n\n# 查看损坏位置\ncurl -s \"https://hsdesign.biz/quote-app.js\" | grep -n \"??\" | head\n\n\n根本原因:Termux 本地 quote-app.js 文件中的中文字符(— em-dash、▾ 箭头等)在 SCP 上传/PS1 decode 过程中被破坏成 ??,导致 JS 语法错误。推送到 GitHub 后线上版本也损坏。\n\n**⚠️ 关键原则:永远不要信任 Termux 本地文件作为 source of truth!\n- Termux 文件系统偶尔会损坏非 ASCII 字符(中文、特殊符号变 ??)\n- 任何修改前,先用 curl 验证 GitHub Raw 文件是干净的\n- node --check 应该在 push 前强制执行\n- 如果 GitHub 文件已损坏,从最后一个干净 commit 恢复,而不是尝试在损坏的文件上继续编辑\n\n恢复流程(已验证):\n1. 在 PC 上找到最后一个干净 commit:\n bash\n # 用 GitHub commit history 找干净版本(通常 commit message 有 \"fix: restore\" 或 markup 改动)\n # 例如 f77bf27 = \"fix: restore corrupted Unicode chars and re-add MARKUP_RATE\"\n \n2. 在 PC 上 checkout 干净版本:\n bash\n git -C \"D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing\" checkout f77bf27 -- quote-app.js\n \n3. 验证文件干净(用 Python 读文件,不用 PowerShell Get-Content):\n bash\n ssh PC 'python -c \"f=open(r'\"'\"'D:\\\\path\\\\quote-app.js'\"'\"','\"'\"'r'\"'\"',encoding='\"'\"'utf-8'\"'\"'); print(f.readlines()[169][:100]); f.close()\"'\n \n4. 应用 fix(用 Python SSH 执行字符串替换):上传 Python patch 脚本到 PC 执行,不要在 heredoc 中拼接复杂字符串\n5. commit + push:\n bash\n git add quote-app.js && git commit -m \"fix: ...\" && git push origin main\n \n\n关键原则**:\n- Termux 本地文件损坏后不要直接用——从 GitHub 干净 commit 恢复比修复更快更可靠\n- 用 node --check 在本地和网络层面同时验证语法\n- Windows 上读 JS 文件用 Python,不要用 PowerShell Get-Content(会报 FileStream 错误)或 type(会显示遮蔽)\n\n\n## 常见问题\n\n### hsdesign.biz 显示旧内容\n1. 检查 Cloudflare Pages 部署状态 — 登录 Cloudflare Dashboard 看 Workers & Pages → hsdesign\n2. 清除浏览器缓存或用隐身模式\n3. 确认 DNS CNAME 指向 hsdesign.pages.dev\n\n### Git push 后 Pages 没更新\n- Cloudflare Workers with Assets 自动部署通常 30s-1min\n- 检查 Cloudflare Dashboard → Workers & Pages → hsdesign → Deployments\n\n### wrangler deploy 报 static files 错误\n- 原因:项目有 functions/ 目录(Pages 约定),wrangler 误判为 Pages 项目\n- 解决:把 functions 改名为 _functions_backup\n\n### 报价工具显示 offline\n- 打开浏览器 DevTools → Network → 检查 /d1-api/* 请求是否返回 200\n- 检查 D1 Worker (hsdesign-d1-api.ida-czia.workers.dev) 是否在线\n- 确认 CF API Key 是有效的(有 D1 权限)\n\n### D1 Worker 返回 1101\n- 原因:使用了 addEventListener 旧格式代码\n- 解决:改用 ES Module 格式(export default { fetch(request, env) {...} })\n\n## 关键文件路径(远程 PC)\n\n| 文件 | 路径 |\n|------|------|\n| 项目根目录 | D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-landing |\n| Worker 脚本 | D:\\\\...\\\\hs-design-landing\\\\hs-design-landing\\\\d1-api-worker.mjs |\n| 主网站 | D:\\\\...\\\\hs-design-landing\\\\index.html |\n| 报价工具 | D:\\\\...\\\\hs-design-landing\\\\HS_Design_Quotation.html |\n| 报价前端 JS | D:\\\\...\\\\hs-design-landing\\\\quote-app.js |\n| wrangler 配置 | D:\\\\...\\\\hs-design-landing\\\\wrangler.toml |\n| D1 Worker 测试目录 | D:\\\\OpenClaw_Home\\\\.openclaw\\\\workspace\\\\projects\\\\hs-design-test |\n”}