From b822d21eaeb5eaa55ab8b2b6eee3005160611204 Mon Sep 17 00:00:00 2001 From: ljy Date: Wed, 26 Aug 2026 00:44:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=8F=90=E4=BA=A4=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 3 + .env.example | 19 + .env.production | 3 + .gitignore | 3 + deploy/BAIDU_SEO.md | 40 ++ deploy/nginx-cache.conf | 37 ++ index.html | 67 ++- package-lock.json | 1017 ++++++++++++++++++++++++++++++++ package.json | 7 +- public/_headers | 24 + public/robots.txt | 4 + public/sitemap.xml | 58 ++ scripts/prerender-routes.mjs | 37 ++ scripts/sync-assets-to-oss.mjs | 94 +++ src/content/deep/assets.ts | 40 +- src/content/site.ts | 34 +- src/lib/assetUrl.ts | 19 + src/stage/StageShell.tsx | 18 +- src/stage/stageAssets.ts | 31 +- src/vite-env.d.ts | 8 + 20 files changed, 1491 insertions(+), 72 deletions(-) create mode 100644 .env.development create mode 100644 .env.example create mode 100644 .env.production create mode 100644 deploy/BAIDU_SEO.md create mode 100644 deploy/nginx-cache.conf create mode 100644 public/_headers create mode 100644 public/robots.txt create mode 100644 public/sitemap.xml create mode 100644 scripts/prerender-routes.mjs create mode 100644 scripts/sync-assets-to-oss.mjs create mode 100644 src/lib/assetUrl.ts diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..a2cfb07 --- /dev/null +++ b/.env.development @@ -0,0 +1,3 @@ +# Dev: load images/audio from OSS (same prefix as production). +# Layout: {VITE_OSS_BASE}/assets/... → oss://dukang-prod/dukang_office/assets/... +VITE_OSS_BASE=https://dukang-prod.oss-cn-hangzhou.aliyuncs.com/dukang_office diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d937270 --- /dev/null +++ b/.env.example @@ -0,0 +1,19 @@ +# Public CDN/OSS base for static images & audio (no trailing slash). +# Object layout: {VITE_OSS_BASE}/assets/... → oss://dukang-prod/dukang_office/assets/... +# +# Used by: +# .env.development → npm run dev +# .env.production → npm run build +# +# Examples: +# VITE_OSS_BASE=https://dukang-prod.oss-cn-hangzhou.aliyuncs.com/dukang_office +# VITE_OSS_BASE=https://cdn.dukanghaoke.com/dukang_office +# Leave empty only if you intentionally want local /assets during that mode. +VITE_OSS_BASE= + +# --- For npm run oss:sync only (do not commit secrets) --- +# OSS_REGION=oss-cn-hangzhou +# OSS_BUCKET=dukang-prod +# OSS_PREFIX=dukang_office +# OSS_ACCESS_KEY_ID= +# OSS_ACCESS_KEY_SECRET= diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..f8d6ffb --- /dev/null +++ b/.env.production @@ -0,0 +1,3 @@ +# Production OSS public prefix (no trailing slash). +# Layout: {VITE_OSS_BASE}/assets/... → oss://dukang-prod/dukang_office/assets/... +VITE_OSS_BASE=https://dukang-prod.oss-cn-hangzhou.aliyuncs.com/dukang_office diff --git a/.gitignore b/.gitignore index b2af1db..ccfe9e7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,8 @@ node_modules dist .DS_Store *.local +.env +.env.local +.env.*.local _tmp_*.txt .vite diff --git a/deploy/BAIDU_SEO.md b/deploy/BAIDU_SEO.md new file mode 100644 index 0000000..04a7a18 --- /dev/null +++ b/deploy/BAIDU_SEO.md @@ -0,0 +1,40 @@ +# 百度搜索资源平台操作清单(部署后执行) + +目标站点:https://www.dukanghaoke.com + +## 1. 验证站点 + +1. 打开 https://ziyuan.baidu.com/ 登录 +2. 添加站点:`https://www.dukanghaoke.com`(若裸域跳转到 www,可一并添加) +3. 验证归属(二选一): + - **HTML 文件**:把平台下发的 `baidu_verify_xxxx.html` 放到 `public/` 后重新部署 + - **Meta 标签**:把验证码填入 `index.html` 中 `baidu-site-verification` 的 content(替换 REPLACE_WITH_BAIDU_CODE)后重新部署 + +## 2. 提交资源 + +1. Sitemap:提交 `https://www.dukanghaoke.com/sitemap.xml` +2. 普通收录:优先推送 + - https://www.dukanghaoke.com/ + - https://www.dukanghaoke.com/brand + - https://www.dukanghaoke.com/qingxiang + - https://www.dukanghaoke.com/haoke + - https://www.dukanghaoke.com/contact +3. 有 API Token 时可用普通收录 API 每日推送核心 URL + +## 3. 自检 + +- 浏览器打开 `https://www.dukanghaoke.com/robots.txt`、`/sitemap.xml` +- 百度搜索:`site:www.dukanghaoke.com` +- 品牌词「杜康好客」通常需数天到数周才稳定展示新站 + +## 4. OSS 图片(与收录并行) + +1. 将 `public/assets`(及如有 `public/audio`)上传到 `oss://dukang-prod/dukang_office/assets/`(音频到 `.../audio/`) +2. 确认 `.env.production` 中 `VITE_OSS_BASE` 与公网前缀一致后 `npm run build` 再部署 +3. 抽查:`{VITE_OSS_BASE}/assets/logo.png` 可公网打开 + +## 5. 缓存 + +- 站点 HTML:短校验(见 `deploy/nginx-cache.conf` / `public/_headers`) +- Vite 带 hash 的 JS/CSS:长缓存 +- OSS 图片:建议 30 天 Cache-Control;发版后一般只需 purge 首页 HTML diff --git a/deploy/nginx-cache.conf b/deploy/nginx-cache.conf new file mode 100644 index 0000000..2ccd637 --- /dev/null +++ b/deploy/nginx-cache.conf @@ -0,0 +1,37 @@ +# Nginx / 宝塔:分层缓存片段(并入 server {} 后 reload) +# Vite 构建产物在 /assets/ 下且文件名含 content hash → 长缓存 +# 注意:若 public 静态图也挂在 /assets/,与构建产物同前缀时用扩展名区分 + +location = /index.html { + add_header Cache-Control "public, max-age=0, must-revalidate"; +} + +location ~* \.html$ { + add_header Cache-Control "public, max-age=0, must-revalidate"; +} + +# Vite 打出的带 hash 的 JS/CSS(部署后路径通常为 /assets/index-xxxxx.js) +location ~* ^/assets/.*\.(?:js|css)$ { + add_header Cache-Control "public, max-age=31536000, immutable"; + try_files $uri =404; +} + +# 同域兜底图片(生产主图应走 OSS;若仍有本地图则 7 天) +location ~* ^/assets/.*\.(?:png|jpe?g|gif|webp|svg|ico)$ { + add_header Cache-Control "public, max-age=604800"; + try_files $uri =404; +} + +location = /robots.txt { + add_header Cache-Control "public, max-age=0, must-revalidate"; +} + +location = /sitemap.xml { + add_header Cache-Control "public, max-age=0, must-revalidate"; + default_type application/xml; +} + +# SPA 路由回退(按实际根目录调整) +# location / { +# try_files $uri $uri/ /index.html; +# } diff --git a/index.html b/index.html index 89fd800..c9f948c 100644 --- a/index.html +++ b/index.html @@ -4,18 +4,77 @@ - + + + + + + - - - 杜康好客 · 酒祖杜康 + + + + 杜康好客官网|酒祖杜康清香 · 你请客我买单 + + +
+ diff --git a/package-lock.json b/package-lock.json index 74d14a0..a120abf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", "@vitejs/plugin-react": "^4.4.1", + "ali-oss": "^6.23.0", "sharp": "^0.34.2", "typescript": "~5.8.3", "vite": "^6.3.5" @@ -1774,6 +1775,73 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "3.5.3", + "resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-3.5.3.tgz", + "integrity": "sha512-yqXL+k5rr8+ZRpOAntkaaRgWgE5o8ESAj5DyRmVTCSoZxXmqemb9Dd7T4i5UzwuERdLAJUy6XzR9zFVuf0kzkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/ali-oss": { + "version": "6.23.0", + "resolved": "https://registry.npmmirror.com/ali-oss/-/ali-oss-6.23.0.tgz", + "integrity": "sha512-FipRmyd16Pr/tEey/YaaQ/24Pc3HEpLM9S1DRakEuXlSLXNIJnu1oJtHM53eVYpvW3dXapSjrip3xylZUTIZVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "address": "^1.2.2", + "agentkeepalive": "^3.4.1", + "bowser": "^1.6.0", + "copy-to": "^2.0.1", + "dateformat": "^2.0.0", + "debug": "^4.3.4", + "destroy": "^1.0.4", + "end-or-error": "^1.0.1", + "get-ready": "^1.0.0", + "humanize-ms": "^1.2.0", + "is-type-of": "^1.4.0", + "js-base64": "^2.5.2", + "jstoxml": "^2.0.0", + "lodash": "^4.17.21", + "merge-descriptors": "^1.0.1", + "mime": "^2.4.5", + "platform": "^1.3.1", + "pump": "^3.0.0", + "qs": "^6.4.0", + "sdk-base": "^2.0.1", + "stream-http": "2.8.2", + "stream-wormhole": "^1.0.4", + "urllib": "^2.44.0", + "utility": "^1.18.0", + "xml2js": "^0.6.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.11.13", "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz", @@ -1787,6 +1855,13 @@ "node": ">=6.0.0" } }, + "node_modules/bowser": { + "version": "1.9.4", + "resolved": "https://registry.npmmirror.com/bowser/-/bowser-1.9.4.tgz", + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==", + "dev": true, + "license": "MIT" + }, "node_modules/browserslist": { "version": "4.28.8", "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.8.tgz", @@ -1821,6 +1896,44 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001809", "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", @@ -1842,6 +1955,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1862,6 +1985,20 @@ "url": "https://opencollective.com/express" } }, + "node_modules/copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", @@ -1869,6 +2006,16 @@ "dev": true, "license": "MIT" }, + "node_modules/dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", @@ -1887,6 +2034,30 @@ } } }, + "node_modules/default-user-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/default-user-agent/-/default-user-agent-1.0.0.tgz", + "integrity": "sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-name": "~1.0.3" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", @@ -1897,6 +2068,38 @@ "node": ">=8" } }, + "node_modules/digest-header": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/digest-header/-/digest-header-1.1.0.tgz", + "integrity": "sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.403", "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.403.tgz", @@ -1904,6 +2107,59 @@ "dev": true, "license": "ISC" }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/end-or-error": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/end-or-error/-/end-or-error-1.0.1.tgz", + "integrity": "sha512-OclLMSug+k2A0JKuf494im25ANRBVW8qsjmwbgX7lQ8P82H21PQ1PWkoYwb9y5yMBS69BPlwtzdIFClo3+7kOQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.11.14" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", @@ -1956,12 +2212,32 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", @@ -1980,6 +2256,19 @@ } } }, + "node_modules/formstream": { + "version": "1.5.2", + "resolved": "https://registry.npmmirror.com/formstream/-/formstream-1.5.2.tgz", + "integrity": "sha512-NASf0lgxC1AyKNXQIrXTEYkiX99LhCEXTkiGObXAkpBui86a4u8FjH1o2bGb3PpqI3kafC+yw4zWeK6l6VHTgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "destroy": "^1.0.4", + "mime": "^2.5.2", + "node-hex": "^1.0.1", + "pause-stream": "~0.0.11" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", @@ -1995,6 +2284,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2005,6 +2304,171 @@ "node": ">=6.9.0" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-ready": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/get-ready/-/get-ready-1.0.0.tgz", + "integrity": "sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==", + "dev": true, + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-class-hotfix": { + "version": "0.0.6", + "resolved": "https://registry.npmmirror.com/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", + "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-type-of": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/is-type-of/-/is-type-of-1.4.0.tgz", + "integrity": "sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "^1.0.2", + "is-class-hotfix": "~0.0.6", + "isstream": "~0.1.2" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2038,6 +2502,20 @@ "node": ">=6" } }, + "node_modules/jstoxml": { + "version": "2.2.9", + "resolved": "https://registry.npmmirror.com/jstoxml/-/jstoxml-2.2.9.tgz", + "integrity": "sha512-OYWlK0j+roh+eyaMROlNbS5cd5R25Y+IUpdl7cNdB8HNrkgwQzIS7L9MegxOiWNBj9dQhA/yAxiMwCC5mwNoBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", @@ -2048,6 +2526,62 @@ "yallist": "^3.0.2" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", @@ -2055,6 +2589,18 @@ "dev": true, "license": "MIT" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.18", "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.18.tgz", @@ -2074,6 +2620,16 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-hex": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/node-hex/-/node-hex-1.0.1.tgz", + "integrity": "sha512-iwpZdvW6Umz12ICmu9IYPRxg0tOLGmU3Tq2tKetejCj3oZd7b2nUXwP3a7QA5M9glWy8wlPS1G3RwM/CdsUbdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/node-releases": { "version": "2.0.53", "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.53.tgz", @@ -2084,6 +2640,85 @@ "node": ">=18" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/os-name": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==", + "dev": true, + "license": "MIT", + "dependencies": { + "osx-release": "^1.0.0", + "win-release": "^1.0.0" + }, + "bin": { + "os-name": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osx-release": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.1.0" + }, + "bin": { + "osx-release": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmmirror.com/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", + "dev": true, + "license": [ + "MIT", + "Apache2" + ], + "dependencies": { + "through": "~2.3" + } + }, "node_modules/peerjs": { "version": "1.5.5", "resolved": "https://registry.npmmirror.com/peerjs/-/peerjs-1.5.5.tgz", @@ -2136,6 +2771,13 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/platform": { + "version": "1.3.6", + "resolved": "https://registry.npmmirror.com/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "dev": true, + "license": "MIT" + }, "node_modules/postcss": { "version": "8.5.26", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.26.tgz", @@ -2165,6 +2807,24 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/qrcode.react": { "version": "4.2.0", "resolved": "https://registry.npmmirror.com/qrcode.react/-/qrcode.react-4.2.0.tgz", @@ -2174,6 +2834,23 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/react": { "version": "19.2.8", "resolved": "https://registry.npmmirror.com/react/-/react-19.2.8.tgz", @@ -2243,6 +2920,22 @@ "react-dom": ">=18" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/rollup": { "version": "4.62.4", "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.62.4.tgz", @@ -2289,12 +2982,46 @@ "fsevents": "~2.3.2" } }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, + "node_modules/sdk-base": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/sdk-base/-/sdk-base-2.0.1.tgz", + "integrity": "sha512-eeG26wRwhtwYuKGCDM3LixCaxY27Pa/5lK4rLKhQa7HBjJ3U3Y+f81MMZQRsDw/8SC2Dao/83yJTXJ8aULuN8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-ready": "~1.0.0" + } + }, "node_modules/sdp": { "version": "3.2.2", "resolved": "https://registry.npmmirror.com/sdp/-/sdp-3.2.2.tgz", @@ -2375,6 +3102,82 @@ "node": ">=10" } }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2385,6 +3188,80 @@ "node": ">=0.10.0" } }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-http": { + "version": "2.8.2", + "resolved": "https://registry.npmmirror.com/stream-http/-/stream-http-2.8.2.tgz", + "integrity": "sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-wormhole": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/stream-wormhole/-/stream-wormhole-1.1.0.tgz", + "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", @@ -2402,6 +3279,13 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", + "dev": true, + "license": "MIT" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", @@ -2424,6 +3308,19 @@ "node": ">=14.17" } }, + "node_modules/unescape": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.3.1", "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", @@ -2455,6 +3352,62 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/urllib": { + "version": "2.44.1", + "resolved": "https://registry.npmmirror.com/urllib/-/urllib-2.44.1.tgz", + "integrity": "sha512-vreOVvFizoiIz5NK9IYMgUknkriHHBVccn2VFfJhgKz6O2qwm0SgjFk4OpXFRDXpdrTx8EzM1DB0/pejrqXwPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.3.0", + "content-type": "^1.0.2", + "default-user-agent": "^1.0.0", + "digest-header": "^1.0.0", + "ee-first": "~1.1.1", + "formstream": "^1.1.0", + "humanize-ms": "^1.2.0", + "iconv-lite": "^0.6.3", + "pump": "^3.0.0", + "qs": "^6.4.0", + "statuses": "^1.3.1", + "utility": "^1.16.1" + }, + "engines": { + "node": ">= 0.10.0" + }, + "peerDependencies": { + "proxy-agent": "^5.0.0" + }, + "peerDependenciesMeta": { + "proxy-agent": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utility": { + "version": "1.18.0", + "resolved": "https://registry.npmmirror.com/utility/-/utility-1.18.0.tgz", + "integrity": "sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-to": "^2.0.1", + "escape-html": "^1.0.3", + "mkdirp": "^0.5.1", + "mz": "^2.7.0", + "unescape": "^1.0.1" + }, + "engines": { + "node": ">= 0.12.0" + } + }, "node_modules/vite": { "version": "6.4.3", "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.3.tgz", @@ -2543,6 +3496,70 @@ "npm": ">=3.10.0" } }, + "node_modules/win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/win-release/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index 008f65c..a88ccc6 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,11 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc -b && vite build", + "build": "tsc -b && vite build && node scripts/prerender-routes.mjs", "preview": "vite preview", - "optimize:stage": "node scripts/optimize-stage-images.mjs" + "optimize:stage": "node scripts/optimize-stage-images.mjs", + "oss:sync": "node scripts/sync-assets-to-oss.mjs", + "prerender": "node scripts/prerender-routes.mjs" }, "dependencies": { "peerjs": "^1.5.5", @@ -20,6 +22,7 @@ "@types/react": "^19.1.2", "@types/react-dom": "^19.1.2", "@vitejs/plugin-react": "^4.4.1", + "ali-oss": "^6.23.0", "sharp": "^0.34.2", "typescript": "~5.8.3", "vite": "^6.3.5" diff --git a/public/_headers b/public/_headers new file mode 100644 index 0000000..11ca144 --- /dev/null +++ b/public/_headers @@ -0,0 +1,24 @@ +/* + X-Frame-Options: DENY + X-Content-Type-Options: nosniff + +/ + Cache-Control: public, max-age=0, must-revalidate + +/*.html + Cache-Control: public, max-age=0, must-revalidate + +/assets/*.js + Cache-Control: public, max-age=31536000, immutable + +/assets/*.css + Cache-Control: public, max-age=31536000, immutable + +/assets/* + Cache-Control: public, max-age=604800 + +/robots.txt + Cache-Control: public, max-age=0, must-revalidate + +/sitemap.xml + Cache-Control: public, max-age=0, must-revalidate diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..ecaa8b5 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://www.dukanghaoke.com/sitemap.xml diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..e4e766f --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,58 @@ + + + + https://www.dukanghaoke.com/ + weekly + 1.0 + + + https://www.dukanghaoke.com/brand + weekly + 0.8 + + + https://www.dukanghaoke.com/poetry + weekly + 0.8 + + + https://www.dukanghaoke.com/qingxiang + weekly + 0.8 + + + https://www.dukanghaoke.com/haoke + weekly + 0.8 + + + https://www.dukanghaoke.com/system + monthly + 0.8 + + + https://www.dukanghaoke.com/tech + monthly + 0.8 + + + https://www.dukanghaoke.com/subsidy + monthly + 0.8 + + + https://www.dukanghaoke.com/partner + weekly + 0.7 + + + https://www.dukanghaoke.com/tech-detail + monthly + 0.7 + + + https://www.dukanghaoke.com/contact + monthly + 0.7 + + diff --git a/scripts/prerender-routes.mjs b/scripts/prerender-routes.mjs new file mode 100644 index 0000000..734db88 --- /dev/null +++ b/scripts/prerender-routes.mjs @@ -0,0 +1,37 @@ +/** + * After vite build: copy dist/index.html to each main route folder for crawler/static hosting. + */ +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const outDir = path.resolve(__dirname, '../dist') + +const ROUTES = [ + '/brand', + '/poetry', + '/qingxiang', + '/haoke', + '/system', + '/tech', + '/subsidy', + '/partner', + '/tech-detail', + '/contact', +] + +const indexHtml = path.join(outDir, 'index.html') +if (!fs.existsSync(indexHtml)) { + console.error('dist/index.html not found; run vite build first') + process.exit(1) +} + +const html = fs.readFileSync(indexHtml, 'utf8') +for (const route of ROUTES) { + const dir = path.join(outDir, route.replace(/^\//, '')) + fs.mkdirSync(dir, { recursive: true }) + fs.writeFileSync(path.join(dir, 'index.html'), html) + console.log(`prerender ${route}/index.html`) +} +console.log('Done.') diff --git a/scripts/sync-assets-to-oss.mjs b/scripts/sync-assets-to-oss.mjs new file mode 100644 index 0000000..c9b5ea2 --- /dev/null +++ b/scripts/sync-assets-to-oss.mjs @@ -0,0 +1,94 @@ +/** + * Upload public/assets (and optional public/audio) to Aliyun OSS. + * + * Target layout (matches VITE_OSS_BASE + /assets/...): + * oss://{bucket}/dukang_office/assets/... + * oss://{bucket}/dukang_office/audio/... + * + * Required env: + * OSS_REGION e.g. oss-cn-hangzhou + * OSS_BUCKET e.g. dukang-prod + * OSS_ACCESS_KEY_ID + * OSS_ACCESS_KEY_SECRET + * Optional: + * OSS_PREFIX default dukang_office + * OSS_ENDPOINT custom endpoint if needed + */ +import fs from 'node:fs/promises' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import OSS from 'ali-oss' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const root = path.resolve(__dirname, '..') + +const region = process.env.OSS_REGION +const bucket = process.env.OSS_BUCKET +const accessKeyId = process.env.OSS_ACCESS_KEY_ID +const accessKeySecret = process.env.OSS_ACCESS_KEY_SECRET +const prefix = (process.env.OSS_PREFIX || 'dukang_office').replace(/^\/|\/$/g, '') +const endpoint = process.env.OSS_ENDPOINT + +if (!region || !bucket || !accessKeyId || !accessKeySecret) { + console.error( + 'Missing OSS env. Set OSS_REGION, OSS_BUCKET, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET', + ) + process.exit(1) +} + +const client = new OSS({ + region, + bucket, + accessKeyId, + accessKeySecret, + ...(endpoint ? { endpoint } : {}), +}) + +async function walk(dir) { + const entries = await fs.readdir(dir, { withFileTypes: true }) + const files = [] + for (const entry of entries) { + const full = path.join(dir, entry.name) + if (entry.isDirectory()) { + files.push(...(await walk(full))) + } else { + files.push(full) + } + } + return files +} + +async function uploadDir(localDir, remoteSubdir) { + try { + await fs.access(localDir) + } catch { + console.warn(`skip (missing): ${localDir}`) + return 0 + } + + const files = await walk(localDir) + let count = 0 + for (const file of files) { + const rel = path.relative(localDir, file).split(path.sep).join('/') + const key = `${prefix}/${remoteSubdir}/${rel}` + await client.put(key, file, { + headers: { + 'Cache-Control': 'public, max-age=2592000', + }, + }) + count += 1 + console.log(`put ${key}`) + } + return count +} + +async function main() { + const n1 = await uploadDir(path.join(root, 'public/assets'), 'assets') + const n2 = await uploadDir(path.join(root, 'public/audio'), 'audio') + console.log(`\nDone. uploaded ${n1 + n2} files under oss://${bucket}/${prefix}/`) +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/src/content/deep/assets.ts b/src/content/deep/assets.ts index 4a6319b..c4b2c33 100644 --- a/src/content/deep/assets.ts +++ b/src/content/deep/assets.ts @@ -1,28 +1,30 @@ +import { assetUrl } from '../../lib/assetUrl' + export const deepImages = { brand: [ - '/assets/brand/emb_p6_5.png', - '/assets/brand/emb_p31_1.png', - '/assets/brand/emb_p15_3.png', - '/assets/brand/emb_p33_1.png', - '/assets/brand/photo_p11_1.jpg', - '/assets/brand/photo_p8_4.jpg', + assetUrl('/assets/brand/emb_p6_5.png'), + assetUrl('/assets/brand/emb_p31_1.png'), + assetUrl('/assets/brand/emb_p15_3.png'), + assetUrl('/assets/brand/emb_p33_1.png'), + assetUrl('/assets/brand/photo_p11_1.jpg'), + assetUrl('/assets/brand/photo_p8_4.jpg'), ], poetry: [ - '/assets/poetry/emb_p33_4.png', - '/assets/poetry/emb_p49_4.png', - '/assets/poetry/emb_p59_4.png', - '/assets/poetry/emb_p67_4.png', - '/assets/poetry/emb_p25_4.png', - '/assets/poetry/emb_p66_4.png', + assetUrl('/assets/poetry/emb_p33_4.png'), + assetUrl('/assets/poetry/emb_p49_4.png'), + assetUrl('/assets/poetry/emb_p59_4.png'), + assetUrl('/assets/poetry/emb_p67_4.png'), + assetUrl('/assets/poetry/emb_p25_4.png'), + assetUrl('/assets/poetry/emb_p66_4.png'), ], qingxiang: [ - '/assets/qingxiang/emb_p7_5.png', - '/assets/qingxiang/emb_p6_8.png', - '/assets/qingxiang/emb_p7_4.png', - '/assets/qingxiang/emb_p12_2.png', - '/assets/qingxiang/emb_p7_6.png', - '/assets/qingxiang/emb_p6_2.png', - '/assets/t30-bottle.png', + assetUrl('/assets/qingxiang/emb_p7_5.png'), + assetUrl('/assets/qingxiang/emb_p6_8.png'), + assetUrl('/assets/qingxiang/emb_p7_4.png'), + assetUrl('/assets/qingxiang/emb_p12_2.png'), + assetUrl('/assets/qingxiang/emb_p7_6.png'), + assetUrl('/assets/qingxiang/emb_p6_2.png'), + assetUrl('/assets/t30-bottle.png'), ], } diff --git a/src/content/site.ts b/src/content/site.ts index 276f084..d132b74 100644 --- a/src/content/site.ts +++ b/src/content/site.ts @@ -302,27 +302,29 @@ export const moduleEntries = [ { to: '/contact', label: '联系我们', desc: '扫码对接负责人' }, ] as const -/** Pure visuals only (no PDF page screenshots with baked-in text) */ +import { assetUrl } from '../lib/assetUrl' + +/** Pure visuals only (no PDF page screenshots with baked-in text). Paths resolve via VITE_OSS_BASE. */ export const images = { - logo: '/assets/logo.png', - qr: '/assets/qr-contact.png', - t30: '/assets/t30-bottle.png', + logo: assetUrl('/assets/logo.png'), + qr: assetUrl('/assets/qr-contact.png'), + t30: assetUrl('/assets/t30-bottle.png'), brand: { - manor: '/assets/brand/emb_p6_5.png', - monument: '/assets/brand/emb_p31_1.png', - landscape: '/assets/brand/emb_p15_3.png', - relic: '/assets/brand/emb_p33_1.png', + manor: assetUrl('/assets/brand/emb_p6_5.png'), + monument: assetUrl('/assets/brand/emb_p31_1.png'), + landscape: assetUrl('/assets/brand/emb_p15_3.png'), + relic: assetUrl('/assets/brand/emb_p33_1.png'), }, poetry: { - inkA: '/assets/poetry/emb_p33_4.png', - inkB: '/assets/poetry/emb_p49_4.png', - inkC: '/assets/poetry/emb_p59_4.png', - inkD: '/assets/poetry/emb_p67_4.png', + inkA: assetUrl('/assets/poetry/emb_p33_4.png'), + inkB: assetUrl('/assets/poetry/emb_p49_4.png'), + inkC: assetUrl('/assets/poetry/emb_p59_4.png'), + inkD: assetUrl('/assets/poetry/emb_p67_4.png'), }, qingxiang: { - hall: '/assets/qingxiang/emb_p7_4.png', - interior: '/assets/qingxiang/emb_p6_2.png', - storefront: '/assets/qingxiang/emb_p7_6.png', - scene: '/assets/qingxiang/emb_p12_2.png', + hall: assetUrl('/assets/qingxiang/emb_p7_4.png'), + interior: assetUrl('/assets/qingxiang/emb_p6_2.png'), + storefront: assetUrl('/assets/qingxiang/emb_p7_6.png'), + scene: assetUrl('/assets/qingxiang/emb_p12_2.png'), }, } diff --git a/src/lib/assetUrl.ts b/src/lib/assetUrl.ts new file mode 100644 index 0000000..fba7ba5 --- /dev/null +++ b/src/lib/assetUrl.ts @@ -0,0 +1,19 @@ +/** + * Prefix local static paths with OSS/CDN base when VITE_OSS_BASE is set. + * Example: VITE_OSS_BASE=https://dukang-prod.oss-cn-hangzhou.aliyuncs.com/dukang_office + * /assets/logo.png → https://.../dukang_office/assets/logo.png + * Leave unset in local dev to keep serving from /assets on the Vite host. + */ +const OSS_BASE = (import.meta.env.VITE_OSS_BASE as string | undefined)?.replace(/\/$/, '') ?? '' + +export function assetUrl(path: string): string { + const p = path.startsWith('/') ? path : `/${path}` + return OSS_BASE ? `${OSS_BASE}${p}` : p +} + +export function assetPair(pair: { thumb: string; full: string }): { thumb: string; full: string } { + return { + thumb: assetUrl(pair.thumb), + full: assetUrl(pair.full), + } +} diff --git a/src/stage/StageShell.tsx b/src/stage/StageShell.tsx index d208d25..e03ff78 100644 --- a/src/stage/StageShell.tsx +++ b/src/stage/StageShell.tsx @@ -13,9 +13,10 @@ import { defaultIntervals, type RemoteToHost, } from './remote/protocol' +import { assetUrl } from '../lib/assetUrl' import './StageShell.css' -const BGM_SRC = '/assets/stage/bgm.wav' +const BGM_SRC = assetUrl('/assets/stage/bgm.wav') const BGM_START = 4 const BGM_END = 35 @@ -32,7 +33,7 @@ export function StageShell() { const bgmRef = useRef(null) const audioWantedRef = useRef(true) const [isAutoPlay, setIsAutoPlay] = useState(true) - const [audioPlaying, setAudioPlaying] = useState(true) + const [audioPlaying, setAudioPlaying] = useState(false) const [remoteOpen, setRemoteOpen] = useState(false) const [intervals, setIntervals] = useState(() => defaultIntervals(stageNavItems.length)) @@ -89,20 +90,12 @@ export function StageShell() { audio.currentTime = BGM_START void audio.play().catch(() => setAudioPlaying(false)) } - // Retry after user gesture when autoplay policy blocked start (not after intentional pause) - const onGesture = () => { - if (audioWantedRef.current && audio.paused) void playBgm() - } audio.addEventListener('timeupdate', onTimeUpdate) audio.addEventListener('ended', onEnded) - window.addEventListener('pointerdown', onGesture) - window.addEventListener('keydown', onGesture) void playBgm() return () => { audio.removeEventListener('timeupdate', onTimeUpdate) audio.removeEventListener('ended', onEnded) - window.removeEventListener('pointerdown', onGesture) - window.removeEventListener('keydown', onGesture) audio.pause() bgmRef.current = null } @@ -274,7 +267,10 @@ export function StageShell() {