feat: 更新 README 和版本管理脚本,优化 PageLayout 组件布局,添加 .eslintignore 文件

This commit is contained in:
katelya
2025-09-01 21:57:20 +08:00
parent 4d4f2ab665
commit ab4e58dc4c
5 changed files with 207 additions and 52 deletions
+53
View File
@@ -0,0 +1,53 @@
# Dependencies
node_modules/
.pnpm-store/
# Build outputs
.next/
out/
dist/
build/
# Cache directories
.cache/
.parcel-cache/
# Environment files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Log files
*.log
logs/
# Editor directories and files
.vscode/
.idea/
*.swp
*.swo
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# PWA Service Worker files (auto-generated)
public/sw.js
public/workbox-*.js
# Generated files
src/lib/runtime.ts
manifest.json
# Test coverage
coverage/
# Storybook build outputs
storybook-static/
+108 -5
View File
@@ -188,12 +188,17 @@
1. **Fork** 本仓库到你的 GitHub 账户。
2. 登陆 [Cloudflare](https://cloudflare.com),点击 **计算(Workers-> Workers 和 Pages**,点击创建
3. 选择 Pages,导入现有的 Git 存储库,选择 Fork 后的仓库
4. 构建命令填写 **pnpm install --frozen-lockfile && pnpm run pages:build**,预设框架为无,构建输出目录为 `.vercel/output/static`
4. 构建命令填写 **npm install && npm run pages:build**,预设框架为无,构建输出目录为 `.vercel/output/static`
5. 保持默认设置完成首次部署。进入设置,将兼容性标志设置为 `nodejs_compat`
6. 首次部署完成后进入设置,新增 PASSWORD 密钥(变量和机密下),而后重试部署。
7. 如需自定义 `config.json`,请直接修改 Fork 后仓库中该文件。
8. 每次 Push 到 `main` 分支将自动触发重新构建。
**⚠️ 重要提示:**
- 确保您的仓库中有 `pnpm-lock.yaml` 文件
- 如果构建失败,可以尝试使用 **pnpm install --frozen-lockfile && pnpm run pages:build**
- Cloudflare Pages 环境变量建议设置为"加密"类型以提高安全性
#### D1 支持
0. 完成普通部署并成功访问
@@ -226,6 +231,20 @@ docker run -d \
访问 `http://服务器IP:3000` 即可使用。(需要在服务器控制台开放 3000 端口)
**⚠️ Windows 用户注意事项:**
```bash
# 如果在 Windows 上使用 Docker Desktop,建议先创建配置目录
mkdir katelyatv-config
# 然后使用绝对路径挂载(避免路径问题)
docker run -d \
--name katelyatv \
-p 3000:3000 \
--env PASSWORD=your_secure_password \
--restart unless-stopped \
ghcr.io/katelya77/katelyatv:latest
```
#### 2. 带自定义配置的部署
```bash
@@ -434,20 +453,42 @@ mkdir katelyatv && cd katelyatv
# 2. 创建 docker-compose.yml 文件(复制上面的内容)
nano docker-compose.yml
# 3. 启动所有服务
# 3. 检查配置文件语法
docker compose config
# 4. 启动所有服务
docker compose up -d
# 4. 查看服务状态
# 5. 查看服务状态
docker compose ps
# 5. 查看启动日志
# 6. 查看启动日志
docker compose logs -f
# 6. 首次访问 http://your-server:3000
# 7. 等待服务完全启动(通常需要 30-60 秒)
# 检查健康状态
docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
# 8. 首次访问 http://your-server:3000
# 使用管理员账号 admin / admin_super_secure_password 登录
# 然后访问 /admin 进行管理员配置
```
**🔍 部署验证步骤:**
```bash
# 验证 Redis 连接
docker compose exec katelyatv-redis redis-cli ping
# 应该返回 "PONG"
# 验证 KatelyaTV 服务
curl -I http://localhost:3000
# 应该返回 HTTP 200 状态码
# 查看服务启动顺序
docker compose logs --timestamps | grep "Ready in"
```
### 🔄 管理与维护
```bash
@@ -482,6 +523,51 @@ docker compose down -v --remove-orphans
4. **资源监控**:定期检查容器资源使用情况,必要时调整配置
5. **日志管理**:配置日志轮转,避免日志文件过大
### 🛠️ 常见部署问题排查
**问题 1:容器启动失败**
```bash
# 检查容器状态
docker compose ps
# 查看详细错误日志
docker compose logs katelyatv
# 常见原因:端口被占用、环境变量配置错误、镜像拉取失败
```
**问题 2Redis 连接失败**
```bash
# 检查 Redis 容器状态
docker compose exec katelyatv-redis redis-cli ping
# 检查网络连通性
docker compose exec katelyatv ping katelyatv-redis
# 验证环境变量
docker compose exec katelyatv env | grep REDIS
```
**问题 3Upstash Redis 连接问题**
```bash
# 验证 Upstash 配置
curl -H "Authorization: Bearer YOUR_TOKEN" YOUR_UPSTASH_URL/ping
# 检查环境变量格式
echo $UPSTASH_URL # 应该是 https://xxx.upstash.io
echo $UPSTASH_TOKEN # 应该是长字符串令牌
```
**问题 4Cloudflare D1 初始化失败**
- 确保在 D1 控制台中正确执行了所有 SQL 语句
- 检查数据库绑定名称是否为 `DB`
- 验证环境变量 `NEXT_PUBLIC_STORAGE_TYPE=d1`
**问题 5Vercel 部署问题**
- 检查环境变量是否正确设置
- 确保 `config.json` 文件格式正确
- 查看 Vercel 部署日志中的错误信息
## 🔄 自动同步最近更改
建议在 fork 的仓库中启用本仓库自带的 GitHub Actions 自动同步功能(见 `.github/workflows/sync.yml`)。
@@ -490,6 +576,8 @@ docker compose down -v --remove-orphans
## ⚙️ 环境变量
### 📋 变量说明表
| 变量 | 说明 | 可选值 | 默认值 |
| --------------------------- | ----------------------------------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| USERNAME | redis 部署时的管理员账号 | 任意字符串 | (空) |
@@ -505,6 +593,21 @@ docker compose down -v --remove-orphans
| NEXT_PUBLIC_IMAGE_PROXY | 默认的浏览器端图片代理 | url prefix | (空) |
| NEXT_PUBLIC_DOUBAN_PROXY | 默认的浏览器端豆瓣数据代理 | url prefix | (空) |
### 🔧 配置验证
**部署后可通过以下方式验证环境变量是否生效:**
1. **访问服务状态页**`http://your-domain/api/server-config`
2. **检查管理员面板**:使用管理员账号登录后访问 `/admin`
3. **查看容器日志**
```bash
# Docker 单容器
docker logs katelyatv
# Docker Compose
docker compose logs katelyatv
```
## 📋 配置说明
所有可自定义项集中在根目录的 `config.json` 中:
+1 -1
View File
@@ -1 +1 @@
if(!self.define){let e,s={};const c=(c,n)=>(c=new URL(c+".js",n).href,s[c]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=c,e.onload=s,document.head.appendChild(e)}else e=c,importScripts(c),s()}).then(()=>{let e=s[c];if(!e)throw new Error(`Module ${c} didnt register its module`);return e}));self.define=(n,a)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let t={};const o=e=>c(e,i),u={module:{uri:i},exports:t,require:o};s[i]=Promise.all(n.map(e=>u[e]||o(e))).then(e=>(a(...e),t))}}define(["./workbox-e9849328"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"720e1c5b3ccb46ee5b17b83529c6c9ce"},{url:"/_next/static/chunks/110-242994b03aacf58a.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/154-de4a84fd5b2e0100.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/29-0844689411ca7d55.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/459-e3682af48de73c26.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/51b697cb-f464f3017ac1ea30.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/63-87ec1ced0bf21584.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/682-28f3765b3c021599.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/900-fb094d8873768e88.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/967-217cdcb80ae3beeb.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/_not-found/page-ac328df06cf68f14.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/admin/page-d0def26e413c060d.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/douban/page-2d0023184aa37aff.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/layout-bd0bfbfdb401e15f.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/login/page-fcbddca77bc41b81.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/page-1c3dfeac6b19d4e5.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/play/page-7cd4f72b453741ca.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/search/page-2e4f55fe3c431d81.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/app/warning/page-11cba4cf9332a238.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/c72274ce-06682d6fc8197e6d.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/da9543df-bf6da1a431d8604f.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/framework-6e06c675866dc992.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/main-2fabec0df3918ea4.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/main-app-dbd320e104e1a5dc.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/pages/_app-792b631a362c29e1.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/pages/_error-9fde6601392a2a99.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-17170f1d90853b2d.js",revision:"owcChvMBPcqUgysujuf1h"},{url:"/_next/static/css/23100062f5d4aac0.css",revision:"23100062f5d4aac0"},{url:"/_next/static/css/275ed64cc4367444.css",revision:"275ed64cc4367444"},{url:"/_next/static/css/992fe66234716999.css",revision:"992fe66234716999"},{url:"/_next/static/media/26a46d62cd723877-s.woff2",revision:"befd9c0fdfa3d8a645d5f95717ed6420"},{url:"/_next/static/media/55c55f0601d81cf3-s.woff2",revision:"43828e14271c77b87e3ed582dbff9f74"},{url:"/_next/static/media/581909926a08bbc8-s.woff2",revision:"f0b86e7c24f455280b8df606b89af891"},{url:"/_next/static/media/8e9860b6e62d6359-s.woff2",revision:"01ba6c2a184b8cba08b0d57167664d75"},{url:"/_next/static/media/97e0cb1ae144a2a9-s.woff2",revision:"e360c61c5bd8d90639fd4503c829c2dc"},{url:"/_next/static/media/df0a9ae256c0569c-s.woff2",revision:"d54db44de5ccb18886ece2fda72bdfe0"},{url:"/_next/static/media/e4af272ccee01ff0-s.p.woff2",revision:"65850a373e258f1c897a2b3d75eb74de"},{url:"/_next/static/owcChvMBPcqUgysujuf1h/_buildManifest.js",revision:"046380ae5bc74b46b6d5eac3eed65355"},{url:"/_next/static/owcChvMBPcqUgysujuf1h/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/favicon.ico",revision:"c5de6e56c5664adda146825f75ea6ecf"},{url:"/icons/icon-192x192.png",revision:"4a56c090828a1ad254c903c7aec0389d"},{url:"/icons/icon-256x256.png",revision:"f6409eb1a001f754121e3a8281c0319c"},{url:"/icons/icon-384x384.png",revision:"f6efc3e357b9ffdf4e0d8c14b2ed0ac1"},{url:"/icons/icon-512x512.png",revision:"9c008cbbeb6a576fe07bb1284a83f4d2"},{url:"/logo.png",revision:"40de611b143c47c6291c7bdad2c959ca"},{url:"/manifest.json",revision:"7bd3dabc1cfbfe40f09577efca223d31"},{url:"/robots.txt",revision:"e2b2cd8514443456bc6fb9d77b3b1f3e"},{url:"/screenshot1.png",revision:"10572bfcea54dc93ac4c5f7c9057fc98"},{url:"/screenshot2.png",revision:"f815a8990973a221899976867365c239"},{url:"/screenshot3.png",revision:"49709e96345dfeeab1d8083821d4b44e"},{url:"/screenshot4.png",revision:"a76c751e41e37556048a487e4f8b8b1c"},{url:"/wechat.jpg",revision:"d0f601311802667cd6ca5a37dc69bfa7"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:c,state:n})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;const s=e.pathname;return!s.startsWith("/api/auth/")&&!!s.startsWith("/api/")},new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")},new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>!(self.origin===e.origin),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")});
if(!self.define){let e,s={};const a=(a,n)=>(a=new URL(a+".js",n).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didnt register its module`);return e}));self.define=(n,c)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let t={};const r=e=>a(e,i),o={module:{uri:i},exports:t,require:r};s[i]=Promise.all(n.map(e=>o[e]||r(e))).then(e=>(c(...e),t))}}define(["./workbox-e9849328"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/app-build-manifest.json",revision:"95803b57e88eef065d7509dd2a83fba2"},{url:"/_next/static/J7ayQg7mNrFOgKQuAh0h0/_buildManifest.js",revision:"046380ae5bc74b46b6d5eac3eed65355"},{url:"/_next/static/J7ayQg7mNrFOgKQuAh0h0/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/110-1617e84e1c4bea87.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/154-de4a84fd5b2e0100.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/29-0844689411ca7d55.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/459-e3682af48de73c26.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/51b697cb-f464f3017ac1ea30.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/63-87ec1ced0bf21584.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/682-28f3765b3c021599.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/900-fb094d8873768e88.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/967-217cdcb80ae3beeb.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/_not-found/page-ac328df06cf68f14.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/admin/page-d0def26e413c060d.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/douban/page-2d0023184aa37aff.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/layout-bd0bfbfdb401e15f.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/login/page-fcbddca77bc41b81.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/page-1c3dfeac6b19d4e5.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/play/page-7cd4f72b453741ca.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/search/page-2e4f55fe3c431d81.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/app/warning/page-11cba4cf9332a238.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/c72274ce-06682d6fc8197e6d.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/da9543df-bf6da1a431d8604f.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/framework-6e06c675866dc992.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/main-2fabec0df3918ea4.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/main-app-dbd320e104e1a5dc.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/pages/_app-792b631a362c29e1.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/pages/_error-9fde6601392a2a99.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-17170f1d90853b2d.js",revision:"J7ayQg7mNrFOgKQuAh0h0"},{url:"/_next/static/css/0578cc219b4d0116.css",revision:"0578cc219b4d0116"},{url:"/_next/static/css/23100062f5d4aac0.css",revision:"23100062f5d4aac0"},{url:"/_next/static/css/275ed64cc4367444.css",revision:"275ed64cc4367444"},{url:"/_next/static/media/26a46d62cd723877-s.woff2",revision:"befd9c0fdfa3d8a645d5f95717ed6420"},{url:"/_next/static/media/55c55f0601d81cf3-s.woff2",revision:"43828e14271c77b87e3ed582dbff9f74"},{url:"/_next/static/media/581909926a08bbc8-s.woff2",revision:"f0b86e7c24f455280b8df606b89af891"},{url:"/_next/static/media/8e9860b6e62d6359-s.woff2",revision:"01ba6c2a184b8cba08b0d57167664d75"},{url:"/_next/static/media/97e0cb1ae144a2a9-s.woff2",revision:"e360c61c5bd8d90639fd4503c829c2dc"},{url:"/_next/static/media/df0a9ae256c0569c-s.woff2",revision:"d54db44de5ccb18886ece2fda72bdfe0"},{url:"/_next/static/media/e4af272ccee01ff0-s.p.woff2",revision:"65850a373e258f1c897a2b3d75eb74de"},{url:"/favicon.ico",revision:"c5de6e56c5664adda146825f75ea6ecf"},{url:"/icons/icon-192x192.png",revision:"4a56c090828a1ad254c903c7aec0389d"},{url:"/icons/icon-256x256.png",revision:"f6409eb1a001f754121e3a8281c0319c"},{url:"/icons/icon-384x384.png",revision:"f6efc3e357b9ffdf4e0d8c14b2ed0ac1"},{url:"/icons/icon-512x512.png",revision:"9c008cbbeb6a576fe07bb1284a83f4d2"},{url:"/logo.png",revision:"40de611b143c47c6291c7bdad2c959ca"},{url:"/manifest.json",revision:"7bd3dabc1cfbfe40f09577efca223d31"},{url:"/robots.txt",revision:"e2b2cd8514443456bc6fb9d77b3b1f3e"},{url:"/screenshot1.png",revision:"10572bfcea54dc93ac4c5f7c9057fc98"},{url:"/screenshot2.png",revision:"f815a8990973a221899976867365c239"},{url:"/screenshot3.png",revision:"49709e96345dfeeab1d8083821d4b44e"},{url:"/screenshot4.png",revision:"a76c751e41e37556048a487e4f8b8b1c"},{url:"/wechat.jpg",revision:"d0f601311802667cd6ca5a37dc69bfa7"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({request:e,response:s,event:a,state:n})=>s&&"opaqueredirect"===s.type?new Response(s.body,{status:200,statusText:"OK",headers:s.headers}):s}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;const s=e.pathname;return!s.startsWith("/api/auth/")&&!!s.startsWith("/api/")},new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>{if(!(self.origin===e.origin))return!1;return!e.pathname.startsWith("/api/")},new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:e})=>!(self.origin===e.origin),new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")});
+3 -1
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env node
/* eslint-disable @typescript-eslint/no-var-requires, no-console, unused-imports/no-unused-vars */
/**
* MoonTV 版本管理脚本
* 用于自动化版本号更新、CHANGELOG 生成和发布管理
@@ -13,7 +15,7 @@ const { execSync } = require('child_process');
const PACKAGE_JSON = path.join(__dirname, '../package.json');
const VERSION_TXT = path.join(__dirname, '../VERSION.txt');
const CHANGELOG_MD = path.join(__dirname, '../CHANGELOG.md');
const README_MD = path.join(__dirname, '../README.md');
const _README_MD = path.join(__dirname, '../README.md');
// 版本类型
const VERSION_TYPES = {
+42 -45
View File
@@ -163,65 +163,62 @@ const TopNavbar = ({ activePath = '/' }: { activePath?: string }) => {
const PageLayout = ({ children, activePath = '/' }: PageLayoutProps) => {
return (
<div className='w-full min-h-screen flex flex-col'>
<div className='w-full min-h-screen'>
{/* 移动端头部 */}
<MobileHeader showBackButton={['/play'].includes(activePath)} />
{/* 桌面端顶部导航栏 - 保持固定在顶部 */}
{/* 桌面端顶部导航栏 - 直接放在最外层,确保 sticky 生效 */}
<div className='hidden md:block'>
<TopNavbar activePath={activePath} />
</div>
{/* 主要布局容器 - 确保可滚动 */}
<div className='flex-1 w-full overflow-auto'>
{/* 主内容区域 */}
<div className='relative min-w-0 transition-all duration-300'>
{/* 桌面端左上角返回按钮 */}
{['/play'].includes(activePath) && (
<div className='absolute top-3 left-1 z-20 hidden md:flex'>
<BackButton />
</div>
)}
{/* 主内容区域 - 移除 overflow-auto,让整个页面可滚动 */}
<div className='relative min-w-0 transition-all duration-300'>
{/* 桌面端左上角返回按钮 */}
{['/play'].includes(activePath) && (
<div className='absolute top-3 left-1 z-20 hidden md:flex'>
<BackButton />
</div>
)}
{/* 主内容容器 - 为播放页面使用特殊布局(83.33%宽度),其他页面使用默认布局(66.67%宽度) */}
<main className='mb-14 md:mb-0 md:p-6 lg:p-8'>
{/* 使用flex布局实现宽度控制 */}
<div className='flex w-full min-h-[calc(100vh-4rem)]'>
{/* 左侧留白区域 - 播放页面占8.33%,其他页面占16.67% */}
<div
className='hidden md:block flex-shrink-0'
style={{
width: ['/play'].includes(activePath) ? '8.33%' : '16.67%'
}}
></div>
{/* 主内容容器 - 为播放页面使用特殊布局(83.33%宽度),其他页面使用默认布局(66.67%宽度) */}
<main className='mb-14 md:mb-0 md:p-6 lg:p-8'>
{/* 使用flex布局实现宽度控制 */}
<div className='flex w-full min-h-[calc(100vh-4rem)]'>
{/* 左侧留白区域 - 播放页面占8.33%,其他页面占16.67% */}
<div
className='hidden md:block flex-shrink-0'
style={{
width: ['/play'].includes(activePath) ? '8.33%' : '16.67%'
}}
></div>
{/* 主内容区 - 播放页面占83.33%,其他页面占66.67% */}
{/* 主内容区 - 播放页面占83.33%,其他页面占66.67% */}
<div
className='flex-1 md:flex-none rounded-container w-full'
style={{
width: ['/play'].includes(activePath) ? '83.33%' : '66.67%'
}}
>
<div
className='flex-1 md:flex-none rounded-container w-full'
style={{
width: ['/play'].includes(activePath) ? '83.33%' : '66.67%'
className='p-4 md:p-8 lg:p-10'
style={{
paddingBottom: 'calc(3.5rem + env(safe-area-inset-bottom))',
}}
>
<div
className='p-4 md:p-8 lg:p-10'
style={{
paddingBottom: 'calc(3.5rem + env(safe-area-inset-bottom))',
}}
>
{children}
</div>
{children}
</div>
{/* 右侧留白区域 - 播放页面占8.33%,其他页面占16.67% */}
<div
className='hidden md:block flex-shrink-0'
style={{
width: ['/play'].includes(activePath) ? '8.33%' : '16.67%'
}}
></div>
</div>
</main>
</div>
{/* 右侧留白区域 - 播放页面占8.33%,其他页面占16.67% */}
<div
className='hidden md:block flex-shrink-0'
style={{
width: ['/play'].includes(activePath) ? '8.33%' : '16.67%'
}}
></div>
</div>
</main>
</div>
{/* 移动端底部导航 */}