Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 22 minutes and 11 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (32)
Walkthrough前端应用框架从 Next.js 迁移至 Vite + React Router,包括移除 Next.js 配置、添加 Vite 构建和 React Router 路由管理。后端和基础设施层面分离了 Dockerfile,更新了 Docker Compose 配置,并调整了 ESLint 规则及项目文档。 Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Dependency ReviewThe following issues were found:
Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. License Issuesapps/backend/package.json
apps/frontend/package.json
OpenSSF ScorecardScorecard details
Scanned Files
|
There was a problem hiding this comment.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/frontend/src/components/video/VodPalyer/index.tsx (1)
19-52:⚠️ Potential issue | 🟠 Major播放器实例缺少绑定与清理,存在泄漏风险
创建的
Player实例未赋给xgInstanceRef.current,且useDeepCompareEffect缺少清理函数。当url或showType变化时,旧实例无法被销毁,导致内存泄漏。修复方案
const player = new Player({ id: 'xgplayer', url, height: '100%', width: '100%', autoplay: true, playsinline: true, plugins: [HlsPlugin], hls: { retryCount: 3, retryDelay: 1000, loadTimeout: 10000, fetchOptions: { mode: 'cors' } } }); + xgInstanceRef.current = player; player.on('error', (e: any) => { onError?.(e.message); }); + return () => { + player.destroy(); + if (xgInstanceRef.current === player) { + xgInstanceRef.current = null; + } + }; }, [url, showType]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/components/video/VodPalyer/index.tsx` around lines 19 - 52, The VodPalyer effect currently constructs a Player but never assigns it to xgInstanceRef.current or cleans it up; update the useDeepCompareEffect in VodPalyer to set xgInstanceRef.current = player after creation, attach the error handler to that instance, and return a cleanup function that removes the 'error' listener and calls the player's destroy method (or equivalent) to dispose the instance when url or showType changes or the component unmounts; ensure you also skip creation when showType === 'iframe' as before.apps/frontend/src/pages/detail/index.tsx (1)
117-131:⚠️ Potential issue | 🟠 Major改为受控组件,使 Select 在播放线路数据变化时同步更新。
defaultValue只在组件初次挂载时生效。当用户在同一路由切换id/site时,handleDetail()会重新获取影片数据并调用setActivePlayList()更新状态,但 Select 仍会显示前一部影片的选中项,导致 UI 与状态不同步。💡 改法
- defaultValue={activePlayList?.name} + value={activePlayList?.name}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/pages/detail/index.tsx` around lines 117 - 131, The Select is using defaultValue so it doesn't update when movieDetail or activePlayList changes; change Select to be a controlled component by replacing defaultValue with value={activePlayList?.name} (use the same unique symbols: Select, activePlayList, setActivePlayList, movieDetail?.vod_play_list) and keep the onChange handler to find and set the active playlist so the UI stays in sync when handleDetail() updates state; ensure options still map from movieDetail?.vod_play_list to provide matching value strings.apps/frontend/src/pages/category/index.tsx (1)
52-62:⚠️ Potential issue | 🟠 Major修复
useEffect中site依赖缺失导致的竞态条件。第二个
useEffect调用getCategory()时未检查site是否存在,且缺少site依赖。当 URL 中有id但site为空时,getCategory会以空site参数发起 API 请求,然后第一个useEffect才执行重定向。同时,当id不变但site改变时,第二个useEffect不会重新执行,导致页面继续显示前一个站点的过期数据。💡 建议改法
useEffect(() => { if (typeof id === 'string' && id) { - getCategory(id, filters); + if (site) { + getCategory(id, filters); + } } - }, [filters, id]); + }, [filters, id, site]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/pages/category/index.tsx` around lines 52 - 62, 第二个 useEffect 在调用 getCategory(id, filters) 前应先确认 site 存在并把 site 加入依赖以避免竞态:在包含 getCategory 调用的 effect(当前以 [filters, id] 为依赖的那个)中先检查 typeof site === 'string' && site,然后才调用 getCategory;同时将 site 写入该 effect 的依赖数组(即 [filters, id, site]),确保当 site 变化时会重新触发并避免用空 site 发起请求;保留第一个 effect 用于基于 site 为空时的 navigate('/home') 重定向逻辑。
🧹 Nitpick comments (11)
.prettierignore (1)
6-6: 避免全局忽略 JSON,当前会让 JSON 的格式化链路失效Line 6 的
**/*.json会使.lintstagedrc里*.{md,json}的 JSON 格式化基本被跳过。建议只忽略构建产物中的 JSON,而不是全局忽略。可选修复示例
-**/*.json +dist/**/*.json🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.prettierignore at line 6, 当前 .prettierignore 中的全局模式 `**/*.json` 导致所有 JSON 文件(包括 .lintstagedrc 中的 *.{md,json})被跳过,破坏了 JSON 的格式化链路。请在 .prettierignore 中删除或替换 `**/*.json` 为仅匹配构建产物的具体路径(例如 `dist/**/*.json`、`build/**/*.json`、或其它产物目录),确保不再全局忽略 JSON,从而恢复对项目根目录和源文件(如 .lintstagedrc 指定的 *.json)的格式化。tsconfig.base.json (1)
1-13: 考虑为前端添加isolatedModules以提高 Vite 兼容性当前前端已采用 Vite + esbuild 构建(package.json 确认),建议在
apps/frontend/tsconfig.json中添加isolatedModules: true以确保类型检查与 esbuild 单文件转译模式兼容:{ "compilerOptions": { "isolatedModules": true } }虽然构建脚本显式执行了
tsc && vite build(完整类型检查在转译前进行),但isolatedModules仍是 Vite 项目的最佳实践。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tsconfig.base.json` around lines 1 - 13, Add "isolatedModules": true to the compilerOptions of the frontend tsconfig to ensure compatibility with Vite/esbuild single-file transpilation; locate the apps/frontend/tsconfig.json (the file that defines compilerOptions for the frontend build) and add the isolatedModules flag under compilerOptions so it reads compilerOptions { ..., "isolatedModules": true }.docker-compose.prod.yml (1)
34-37: 考虑添加 Redis 持久化和重启策略Redis 服务当前没有配置数据持久化,容器重启后缓存数据会丢失。如果这是预期行为(仅用于缓存)则可以接受,否则建议添加持久化配置。同时建议为所有服务添加重启策略以提高可靠性。
♻️ 可选的增强配置
redis: image: redis:alpine ports: - '127.0.0.1:6379:6379' + restart: unless-stopped + volumes: + - redis_data:/data + command: redis-server --appendonly yes + +volumes: + redis_data:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docker-compose.prod.yml` around lines 34 - 37, 当前 docker-compose 中的 redis 服务定义 (redis, image: redis:alpine, ports: '127.0.0.1:6379:6379') 未配置持久化和重启策略;如果需要保留数据,请为服务添加持久化卷绑定或命名卷并配置 RDB/AOF 持久化相关设置以及合适的 restart 策略(例如 always 或 unless-stopped)以提升可靠性;定位并修改服务块 redis,加入 volumes 条目指向主机目录或命名卷并在 docker-compose 中添加 restart: 条目,同时如需持久化请在 Redis 配置(或指定命令/配置文件)中启用 RDB/AOF 参数。apps/frontend/Dockerfile (1)
23-28: 可选:考虑使用非 root 用户运行 NginxTrivy 标记了容器以 root 用户运行的安全风险。对于 Nginx 容器,实现非 root 运行需要额外配置(修改监听端口或使用
nginx-unprivileged镜像)。鉴于这是服务静态文件的简单场景,此优化可作为后续改进项。♻️ 可选方案:使用 nginx-unprivileged 镜像
-FROM nginx:alpine AS runner +FROM nginxinc/nginx-unprivileged:alpine AS runner RUN rm -f /etc/nginx/conf.d/default.conf COPY --from=builder /app/apps/frontend/dist /usr/share/nginx/html COPY --from=builder /app/apps/frontend/conf/nginx.conf /etc/nginx/conf.d/default.conf -EXPOSE 80 +EXPOSE 8080 CMD ["nginx", "-g", "daemon off;"]注意:使用此方案需要同步更新
nginx.conf中的监听端口和docker-compose.prod.yml中的端口映射。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/Dockerfile` around lines 23 - 28, The Dockerfile currently runs Nginx as root; change the base/runtime image to a non-root variant (e.g., use an nginx unprivileged image) to remove the root-user risk and then update related configs: switch the FROM in apps/frontend/Dockerfile to the non-root nginx image and ensure the nginx.conf referenced by COPY (apps/frontend/conf/nginx.conf) uses a non-privileged listen port, and adjust docker-compose.prod.yml port mappings accordingly so host→container port mapping matches the new unprivileged port..cursor/rules/frontend/workflow.mdc (1)
69-69:dynamic是 Next.js 特有的 API
dynamic导入是 Next.js 的next/dynamicAPI。在 Vite + React 架构下,应使用React.lazy()配合Suspense实现动态导入。📝 建议更新文档
-- Use `dynamic` imports for heavy components (e.g., video player) +- Use `React.lazy()` with `Suspense` for heavy components (e.g., video player)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.cursor/rules/frontend/workflow.mdc at line 69, 本条规则当前建议使用 Next.js 的 `dynamic`,但在 Vite + React 项目里应改为说明使用 React.lazy 和 Suspense 实现动态导入;请在 workflow.mdc 中把 “Use `dynamic` imports for heavy components (e.g., video player)” 文本改为推荐使用 `React.lazy()` + `Suspense`(针对重组件如 VideoPlayer 或 video player),并补充短说明如何在组件加载失败或加载中显示占位器(fallback),以便读者在 Vite 环境下正确实现按需加载。apps/backend/Dockerfile (1)
15-28: 建议使用非 root 用户运行容器静态分析工具 Trivy 标记了容器以 root 用户运行的安全风险。Node.js Alpine 镜像已内置
node用户,建议在 runner 阶段切换到该用户以提高安全性。🔒️ 建议添加 USER 指令
FROM node:24-alpine AS runner WORKDIR /app RUN corepack enable COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/apps/backend/node_modules ./apps/backend/node_modules COPY --from=builder /app/apps/backend/dist ./apps/backend/dist COPY --from=builder /app/apps/backend/package.json ./apps/backend/ COPY --from=builder /app/apps/backend/logs ./apps/backend/logs COPY package.json pnpm-workspace.yaml ./ +RUN chown -R node:node /app +USER node + ENV NODE_ENV=production EXPOSE 8888 CMD ["node", "apps/backend/dist/index.js"]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/backend/Dockerfile` around lines 15 - 28, 当前 runner 阶段容器以 root 身份运行(见 FROM node:24-alpine AS runner、WORKDIR /app、CMD ["node", "apps/backend/dist/index.js"]),需要切换到非 root 用户以消除 Trivy 报告的风险;在 runner 阶段在确保 /app 及其子目录(由 COPY 复制的文件)归属非 root 用户后切换到内置 node 用户(或创建/使用特定非特权用户),即在复制文件后执行对 /app 目录的所有权调整(chown 到 node)并添加 USER node,这样运行 CMD 时不会以 root 启动并能访问必要文件。apps/frontend/src/App.tsx (1)
22-28: 考虑添加 404 路由处理当前路由配置没有处理未知路径的情况。用户访问不存在的路由时会看到空白页面。
♻️ 建议添加通配符路由
<Routes> <Route path="/" element={<Navigate to="/home" replace />} /> <Route path="/home" element={<HomePage />} /> <Route path="/category" element={<CategoryPage />} /> <Route path="/detail" element={<DetailPage />} /> <Route path="/setting" element={<SettingPage />} /> + <Route path="*" element={<Navigate to="/home" replace />} /> </Routes>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/App.tsx` around lines 22 - 28, Routes lacks a catch-all for unknown paths which causes blank pages; add a wildcard Route (path="*") to the existing Routes block so unknown URLs render a 404/NotFound view (or redirect) — create or use a NotFoundPage component and add Route with element={<NotFoundPage />} (or element={<Navigate to="/home" replace />} if you prefer redirect) alongside the other Route entries (Routes, Route, Navigate, HomePage, CategoryPage, DetailPage, SettingPage).apps/backend/package.json (1)
19-20: ESLint 配置不必要地将 React 规则应用于后端代码根据
eslint.config.mjs,React 和 React Hooks 插件的规则应用到**/*.{ts,tsx,js,jsx}全局范围,而后端代码中无 React 依赖且不使用任何 React Hooks。建议在 ESLint 配置中限制 React 相关规则仅应用于前端目录(如apps/frontend/**),避免不必要的规则污染。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/backend/package.json` around lines 19 - 20, The ESLint config currently applies React and React Hooks rules globally via the file glob pattern "**/*.{ts,tsx,js,jsx}"; update eslint.config.mjs to restrict React-related plugins/rules so they only target the front-end (e.g., use an override or change the files pattern to "apps/frontend/**" or "apps/frontend/**/*.{ts,tsx,js,jsx}") and remove React/react-hooks rules from backend-targeted patterns; ensure backend files continue to use appropriate Node/TypeScript rules and that React/react-hooks rules remain applied only to the frontend (identify the plugin names "plugin:react" / "react-hooks" and the global files/glob pattern in eslint.config.mjs when making the change).eslint.config.mjs (1)
44-54: 导入排序配置与项目约定不一致。当前配置
'newlines-between': 'never'不允许导入组之间有空行,但根据项目编码规范,导入顺序应在 builtins → externals → internals 组之间保留空行。如果这是有意的配置变更,请确认更新相关文档;否则建议调整为
'always'。♻️ 如需保持空行分隔
'import-x/order': [ 'warn', { groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], - 'newlines-between': 'never', + 'newlines-between': 'always', alphabetize: { order: 'asc', caseInsensitive: true } } ]Based on learnings: "Import order must follow: builtins → externals → internals, with blank lines between groups"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@eslint.config.mjs` around lines 44 - 54, The import order rule 'import-x/order' currently sets 'newlines-between': 'never', which contradicts the project convention requiring blank lines between builtins, externals and internals; update the rule configuration for 'import-x/order' to use 'newlines-between': 'always' so builtins → externals → internals are separated by blank lines (or, if the change was intentional, ensure the project docs are updated to reflect the new convention).apps/frontend/conf/nginx.conf (1)
1-34: Nginx 配置结构良好。配置正确设置了:
- Gzip 压缩
- 静态资源长期缓存
- API 代理到
backend:8888(与后端配置一致)- SPA 路由回退
可选改进:考虑添加基础安全响应头以增强安全性。
🛡️ 可选:添加安全响应头
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; + # 安全响应头 + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + # Gzip 压缩🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/conf/nginx.conf` around lines 1 - 34, Add common security response headers in the nginx server block to harden responses: insert add_header directives (e.g., X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and a conservative Content-Security-Policy) inside the main server { } (or inside location / to apply to SPA responses) and ensure Strict-Transport-Security is added only when TLS is enabled; also make sure add_header uses the always flag where appropriate and that headers are not overridden by the /api proxy (add them in both server block and proxy_set_header contexts if needed).apps/frontend/src/pages/detail/index.tsx (1)
104-111: 给懒加载播放器补一个局部Suspense边界。
PlayerComponent已经改成React.lazy(),但本文件里已经没有对应的Suspense包裹了。若路由上层没有统一边界,播放器首次渲染会直接挂起;即便上层有全局边界,播放器 chunk 的加载也会把整页一起切到 fallback。💡 建议改法
-import React, { useEffect, useMemo, useState } from 'react'; +import React, { Suspense, useEffect, useMemo, useState } from 'react'; @@ - <PlayerComponent - url={playerUrl} - onError={(msg: string) => { - message.error(msg); - }} - showType={playerShowType} - style={{ width: '100%' }} - /> + <Suspense fallback={<Loading />}> + <PlayerComponent + url={playerUrl} + onError={(msg: string) => { + message.error(msg); + }} + showType={playerShowType} + style={{ width: '100%' }} + /> + </Suspense>Also applies to: 177-177
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/pages/detail/index.tsx` around lines 104 - 111, PlayerComponent is now lazy-loaded (React.lazy) but this file no longer wraps it in a local Suspense boundary, so its initial load can suspend the whole page; wrap each usage of PlayerComponent in a React.Suspense with a small local fallback (e.g., spinner or skeleton) to limit suspension to the player only, ensure React.Suspense is imported where missing, and apply the same local Suspense wrapper to the other PlayerComponent instance referenced later in the file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/backend/src/routes/registry.ts`:
- Around line 25-29: The production branch uses require('./registry.gen') inside
an ESM module which throws "require is not defined"; change that to use dynamic
import: await import('./registry.gen') and assign mod.namespaces to namespaces
and mod.default to app. Make the enclosing function that contains the
isProduction check async (or convert its caller to await it) so you can use
await import, and keep references to the symbols namespaces and app and the
module name './registry.gen' when updating the code.
In `@apps/frontend/index.html`:
- Line 2: The page currently sets the HTML root element's language to lang="en"
which conflicts with the Chinese content; update the <html> element's lang
attribute from "en" to "zh-CN" (i.e., change lang="en" → lang="zh-CN") so screen
readers and input methods match the page language, and re-run any HTML
accessibility/lint checks to validate the change.
- Line 5: 移除 viewport 元标签中阻止缩放的属性:删除 user-scalable=no 和
maximum-scale=1.0(以及任何类似阻止缩放的属性),保留响应设置例如 width=device-width 和
initial-scale=1.0,以恢复用户缩放能力并改善可访问性;在 apps/frontend 的 index.html 中定位包含 <meta
name="viewport"> 的标签并更新其属性即可。
In `@apps/frontend/src/components/InitProvider.tsx`:
- Around line 14-18: The redirect in InitProvider's useEffect uses
navigate('/setting') which pushes a history entry and can create a back-button
redirect loop; update the navigate call inside the useEffect to perform a
replace navigation (use navigate('/setting', { replace: true })) so the settings
redirect replaces the current history entry instead of adding one; ensure you
update the call site in the InitProvider component (the useEffect containing
vod_hub_api, hasError and navigate) and keep the effect dependencies unchanged.
In `@apps/frontend/src/components/video/VodSearch/index.tsx`:
- Around line 192-193: The route build in the VodSearch component currently
encodes vod.vod_id but not the site parameter (see the navigate call that
constructs `/detail?id=${encodeURIComponent(vod.vod_id as
string)}&site=${site}`), which can break when site contains special characters;
update that navigate invocation (and the duplicate occurrence later) to encode
the site value as well (e.g., use encodeURIComponent(site)) so both id and site
are safely URL-encoded before navigating.
In `@apps/frontend/src/components/video/VodTypes/index.tsx`:
- Around line 92-99: The URL construction in handleTabClick uses raw values
(name, key, site) which can break when they contain special characters; update
handleTabClick to encode query parameters before calling navigate (e.g., use
encodeURIComponent or build the query via URLSearchParams) so the name derived
from items.find(...)? .label and other params are safely encoded when navigating
to `/category?id=...&name=...&site=...`; ensure both the 'name' and other
dynamic values (key, site) are encoded consistently.
In `@CLAUDE.MD`:
- Around line 49-50: Update the custom provider guidance to explicitly require
these individual route files—namespace.ts, home.ts, homeVod.ts, category.ts,
detail.ts, play.ts, and search.ts—and state that each file must export a route
object that implements the Route interface (i.e., export const route: Route =
...); also clarify that CMS Providers only need namespace.ts and index.ts using
the createCMSRoutes() factory; ensure the wording replaces the vague "home.ts,
category.ts, etc." with this exact list and the export requirement so generated
routes follow the expected structure.
- Around line 144-153: The markdown table starting with the header "| Item |
Convention | Example |" lacks blank lines before and after it (causing
markdownlint MD058); add one empty line immediately before that table header and
one empty line immediately before the following "### Git Workflow" heading so
the table is separated from surrounding content and the lint warning is
resolved.
In `@docker-compose.prod.yml`:
- Line 27: The CACHE_TTL environment value is currently set to 60000 but the
config code multiplies process.env.CACHE_TTL by 1000 when computing ttl (ttl:
process.env.CACHE_TTL ? parseInt(process.env.CACHE_TTL, 10) * 1000 : 1000 * 60),
so change the env value to seconds (e.g., set CACHE_TTL=60) in the
docker-compose file to produce a 60s TTL; ensure the updated value is applied
where CACHE_TTL is read (process.env.CACHE_TTL) and adjust any related docs if
necessary.
In `@package.json`:
- Line 27: 从 package.json 中移除未使用的依赖 "eslint-plugin-compat":在 package.json 中删除
"eslint-plugin-compat": "^7.0.1" 条目,确认 eslint.config.mjs
没有引用或导入该插件(若存在引用一并移除),然后更新锁文件并重新安装依赖(运行 npm install 或 yarn install / pnpm
install)以使 package-lock.json / yarn.lock 与 package.json 同步。
In `@README.md`:
- Around line 172-184: Update the two Docker Compose commands in the README:
replace the legacy "docker-compose up -d" invocation with "docker compose up -d"
and replace "docker-compose -f docker-compose.prod.yml up -d" with "docker
compose -f docker-compose.prod.yml up -d"; edit the section that references
docker-compose.yml and docker-compose.prod.yml so the examples use the modern
"docker compose" syntax.
---
Outside diff comments:
In `@apps/frontend/src/components/video/VodPalyer/index.tsx`:
- Around line 19-52: The VodPalyer effect currently constructs a Player but
never assigns it to xgInstanceRef.current or cleans it up; update the
useDeepCompareEffect in VodPalyer to set xgInstanceRef.current = player after
creation, attach the error handler to that instance, and return a cleanup
function that removes the 'error' listener and calls the player's destroy method
(or equivalent) to dispose the instance when url or showType changes or the
component unmounts; ensure you also skip creation when showType === 'iframe' as
before.
In `@apps/frontend/src/pages/category/index.tsx`:
- Around line 52-62: 第二个 useEffect 在调用 getCategory(id, filters) 前应先确认 site 存在并把
site 加入依赖以避免竞态:在包含 getCategory 调用的 effect(当前以 [filters, id] 为依赖的那个)中先检查 typeof
site === 'string' && site,然后才调用 getCategory;同时将 site 写入该 effect 的依赖数组(即
[filters, id, site]),确保当 site 变化时会重新触发并避免用空 site 发起请求;保留第一个 effect 用于基于 site
为空时的 navigate('/home') 重定向逻辑。
In `@apps/frontend/src/pages/detail/index.tsx`:
- Around line 117-131: The Select is using defaultValue so it doesn't update
when movieDetail or activePlayList changes; change Select to be a controlled
component by replacing defaultValue with value={activePlayList?.name} (use the
same unique symbols: Select, activePlayList, setActivePlayList,
movieDetail?.vod_play_list) and keep the onChange handler to find and set the
active playlist so the UI stays in sync when handleDetail() updates state;
ensure options still map from movieDetail?.vod_play_list to provide matching
value strings.
---
Nitpick comments:
In @.cursor/rules/frontend/workflow.mdc:
- Line 69: 本条规则当前建议使用 Next.js 的 `dynamic`,但在 Vite + React 项目里应改为说明使用 React.lazy
和 Suspense 实现动态导入;请在 workflow.mdc 中把 “Use `dynamic` imports for heavy components
(e.g., video player)” 文本改为推荐使用 `React.lazy()` + `Suspense`(针对重组件如 VideoPlayer 或
video player),并补充短说明如何在组件加载失败或加载中显示占位器(fallback),以便读者在 Vite 环境下正确实现按需加载。
In @.prettierignore:
- Line 6: 当前 .prettierignore 中的全局模式 `**/*.json` 导致所有 JSON 文件(包括 .lintstagedrc 中的
*.{md,json})被跳过,破坏了 JSON 的格式化链路。请在 .prettierignore 中删除或替换 `**/*.json`
为仅匹配构建产物的具体路径(例如 `dist/**/*.json`、`build/**/*.json`、或其它产物目录),确保不再全局忽略
JSON,从而恢复对项目根目录和源文件(如 .lintstagedrc 指定的 *.json)的格式化。
In `@apps/backend/Dockerfile`:
- Around line 15-28: 当前 runner 阶段容器以 root 身份运行(见 FROM node:24-alpine AS
runner、WORKDIR /app、CMD ["node", "apps/backend/dist/index.js"]),需要切换到非 root
用户以消除 Trivy 报告的风险;在 runner 阶段在确保 /app 及其子目录(由 COPY 复制的文件)归属非 root 用户后切换到内置 node
用户(或创建/使用特定非特权用户),即在复制文件后执行对 /app 目录的所有权调整(chown 到 node)并添加 USER node,这样运行 CMD
时不会以 root 启动并能访问必要文件。
In `@apps/backend/package.json`:
- Around line 19-20: The ESLint config currently applies React and React Hooks
rules globally via the file glob pattern "**/*.{ts,tsx,js,jsx}"; update
eslint.config.mjs to restrict React-related plugins/rules so they only target
the front-end (e.g., use an override or change the files pattern to
"apps/frontend/**" or "apps/frontend/**/*.{ts,tsx,js,jsx}") and remove
React/react-hooks rules from backend-targeted patterns; ensure backend files
continue to use appropriate Node/TypeScript rules and that React/react-hooks
rules remain applied only to the frontend (identify the plugin names
"plugin:react" / "react-hooks" and the global files/glob pattern in
eslint.config.mjs when making the change).
In `@apps/frontend/conf/nginx.conf`:
- Around line 1-34: Add common security response headers in the nginx server
block to harden responses: insert add_header directives (e.g., X-Frame-Options,
X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and a conservative
Content-Security-Policy) inside the main server { } (or inside location / to
apply to SPA responses) and ensure Strict-Transport-Security is added only when
TLS is enabled; also make sure add_header uses the always flag where appropriate
and that headers are not overridden by the /api proxy (add them in both server
block and proxy_set_header contexts if needed).
In `@apps/frontend/Dockerfile`:
- Around line 23-28: The Dockerfile currently runs Nginx as root; change the
base/runtime image to a non-root variant (e.g., use an nginx unprivileged image)
to remove the root-user risk and then update related configs: switch the FROM in
apps/frontend/Dockerfile to the non-root nginx image and ensure the nginx.conf
referenced by COPY (apps/frontend/conf/nginx.conf) uses a non-privileged listen
port, and adjust docker-compose.prod.yml port mappings accordingly so
host→container port mapping matches the new unprivileged port.
In `@apps/frontend/src/App.tsx`:
- Around line 22-28: Routes lacks a catch-all for unknown paths which causes
blank pages; add a wildcard Route (path="*") to the existing Routes block so
unknown URLs render a 404/NotFound view (or redirect) — create or use a
NotFoundPage component and add Route with element={<NotFoundPage />} (or
element={<Navigate to="/home" replace />} if you prefer redirect) alongside the
other Route entries (Routes, Route, Navigate, HomePage, CategoryPage,
DetailPage, SettingPage).
In `@apps/frontend/src/pages/detail/index.tsx`:
- Around line 104-111: PlayerComponent is now lazy-loaded (React.lazy) but this
file no longer wraps it in a local Suspense boundary, so its initial load can
suspend the whole page; wrap each usage of PlayerComponent in a React.Suspense
with a small local fallback (e.g., spinner or skeleton) to limit suspension to
the player only, ensure React.Suspense is imported where missing, and apply the
same local Suspense wrapper to the other PlayerComponent instance referenced
later in the file.
In `@docker-compose.prod.yml`:
- Around line 34-37: 当前 docker-compose 中的 redis 服务定义 (redis, image:
redis:alpine, ports: '127.0.0.1:6379:6379')
未配置持久化和重启策略;如果需要保留数据,请为服务添加持久化卷绑定或命名卷并配置 RDB/AOF 持久化相关设置以及合适的 restart 策略(例如
always 或 unless-stopped)以提升可靠性;定位并修改服务块 redis,加入 volumes 条目指向主机目录或命名卷并在
docker-compose 中添加 restart: 条目,同时如需持久化请在 Redis 配置(或指定命令/配置文件)中启用 RDB/AOF 参数。
In `@eslint.config.mjs`:
- Around line 44-54: The import order rule 'import-x/order' currently sets
'newlines-between': 'never', which contradicts the project convention requiring
blank lines between builtins, externals and internals; update the rule
configuration for 'import-x/order' to use 'newlines-between': 'always' so
builtins → externals → internals are separated by blank lines (or, if the change
was intentional, ensure the project docs are updated to reflect the new
convention).
In `@tsconfig.base.json`:
- Around line 1-13: Add "isolatedModules": true to the compilerOptions of the
frontend tsconfig to ensure compatibility with Vite/esbuild single-file
transpilation; locate the apps/frontend/tsconfig.json (the file that defines
compilerOptions for the frontend build) and add the isolatedModules flag under
compilerOptions so it reads compilerOptions { ..., "isolatedModules": true }.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1449fa5d-eb6d-40a0-9c38-93c09c192df5
⛔ Files ignored due to path filters (2)
apps/frontend/app/favicon.icois excluded by!**/*.icopnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (115)
.cursor/rules/frontend/code-style.mdc.cursor/rules/frontend/project.mdc.cursor/rules/frontend/structure.mdc.cursor/rules/frontend/workflow.mdc.github/workflows/docker-image.yml.lintstagedrc.prettierignore.prettierrcAGENTS.mdAGENTS.mdCLAUDE.MDDockerfileREADME.mdapps/backend/Dockerfileapps/backend/package.jsonapps/backend/src/api/index.tsapps/backend/src/api/namespace/index.tsapps/backend/src/app.tsxapps/backend/src/index.tsapps/backend/src/middleware/cache.tsapps/backend/src/routes/360kan/category.tsapps/backend/src/routes/360kan/detail.tsapps/backend/src/routes/360kan/home.tsapps/backend/src/routes/360kan/homeVod.tsapps/backend/src/routes/360kan/play.tsapps/backend/src/routes/360kan/request.tsapps/backend/src/routes/360kan/search.tsapps/backend/src/routes/360zy/index.tsapps/backend/src/routes/bdzy/index.tsapps/backend/src/routes/bfzy/index.tsapps/backend/src/routes/feifan/index.tsapps/backend/src/routes/guangsuzy/index.tsapps/backend/src/routes/hongniuzy/index.tsapps/backend/src/routes/huyazy/index.tsapps/backend/src/routes/ikunzy/index.tsapps/backend/src/routes/lzzy/index.tsapps/backend/src/routes/mdzy/index.tsapps/backend/src/routes/proxy.tsapps/backend/src/routes/registry.tsapps/backend/src/routes/sdzy/index.tsapps/backend/src/routes/subozy/index.tsapps/backend/src/utils/cache/index.tsapps/backend/src/utils/cms/category/index.tsapps/backend/src/utils/cms/detail/index.tsapps/backend/src/utils/cms/factory.tsapps/backend/src/utils/cms/home/index.tsapps/backend/src/utils/cms/homeVod/index.tsapps/backend/src/utils/cms/play/index.tsapps/backend/src/utils/cms/search/index.tsapps/backend/src/utils/logger/index.tsapps/frontend/Dockerfileapps/frontend/app/home/components/HomeCarousel/index.tsxapps/frontend/app/layout.tsxapps/frontend/conf/nginx.confapps/frontend/index.htmlapps/frontend/lib/types/index.tsapps/frontend/next.config.tsapps/frontend/package.jsonapps/frontend/postcss.config.mjsapps/frontend/src/App.tsxapps/frontend/src/components/BasicLayout.module.scssapps/frontend/src/components/BasicLayout.tsxapps/frontend/src/components/Disclaimer.tsxapps/frontend/src/components/InitProvider.tsxapps/frontend/src/components/SiteHeader.tsxapps/frontend/src/components/ThemeProvider.tsxapps/frontend/src/components/icons/AtomIcon.tsxapps/frontend/src/components/icons/SearchIcon.tsxapps/frontend/src/components/index.module.scssapps/frontend/src/components/ui/Loading/Loading.tsxapps/frontend/src/components/ui/Loading/index.module.scssapps/frontend/src/components/ui/Loading/index.tsapps/frontend/src/components/ui/ThemeSelector.module.scssapps/frontend/src/components/ui/ThemeSelector.tsxapps/frontend/src/components/video/VodList/index.module.scssapps/frontend/src/components/video/VodList/index.tsxapps/frontend/src/components/video/VodPalyer/index.module.scssapps/frontend/src/components/video/VodPalyer/index.tsxapps/frontend/src/components/video/VodSearch/index.tsxapps/frontend/src/components/video/VodSites/index.module.scssapps/frontend/src/components/video/VodSites/index.tsxapps/frontend/src/components/video/VodTypes/index.module.scssapps/frontend/src/components/video/VodTypes/index.tsxapps/frontend/src/globals.scssapps/frontend/src/lib/constant/llm.tsapps/frontend/src/lib/constant/prompt.tsapps/frontend/src/lib/constant/site.tsapps/frontend/src/lib/hooks/useIsMobile/index.tsapps/frontend/src/lib/store/useSettingStore.tsapps/frontend/src/lib/store/useThemeStore.tsapps/frontend/src/lib/store/useVodSitesStore.tsapps/frontend/src/lib/themes/index.tsapps/frontend/src/lib/types/index.tsapps/frontend/src/lib/utils/index.tsapps/frontend/src/lib/utils/request/index.tsapps/frontend/src/main.tsxapps/frontend/src/pages/category/index.module.scssapps/frontend/src/pages/category/index.tsxapps/frontend/src/pages/detail/index.module.scssapps/frontend/src/pages/detail/index.tsxapps/frontend/src/pages/home/index.module.scssapps/frontend/src/pages/home/index.tsxapps/frontend/src/pages/setting/index.module.scssapps/frontend/src/pages/setting/index.tsxapps/frontend/src/services/index.tsapps/frontend/src/services/vodhub/index.tsapps/frontend/tsconfig.jsonapps/frontend/vite.config.tscommitlint.config.jsdocker-compose.prod.ymldocker-compose.ymleslint.config.jseslint.config.mjspackage.jsontsconfig.base.json
💤 Files with no reviewable changes (48)
- apps/backend/src/api/index.ts
- apps/backend/src/app.tsx
- apps/backend/src/middleware/cache.ts
- apps/backend/src/routes/360zy/index.ts
- apps/backend/src/routes/bfzy/index.ts
- apps/backend/src/routes/hongniuzy/index.ts
- apps/backend/src/routes/proxy.ts
- apps/backend/src/routes/bdzy/index.ts
- apps/backend/src/routes/360kan/category.ts
- apps/backend/src/routes/360kan/detail.ts
- apps/backend/src/routes/360kan/home.ts
- apps/backend/src/routes/360kan/request.ts
- apps/backend/src/routes/feifan/index.ts
- apps/backend/src/routes/huyazy/index.ts
- apps/backend/src/routes/ikunzy/index.ts
- apps/backend/src/routes/mdzy/index.ts
- apps/backend/src/routes/sdzy/index.ts
- apps/backend/src/routes/guangsuzy/index.ts
- apps/backend/src/routes/360kan/play.ts
- apps/backend/src/api/namespace/index.ts
- apps/backend/src/utils/cms/detail/index.ts
- apps/backend/src/routes/subozy/index.ts
- apps/backend/src/utils/cache/index.ts
- apps/backend/src/routes/lzzy/index.ts
- apps/backend/src/routes/360kan/homeVod.ts
- apps/backend/src/routes/360kan/search.ts
- apps/backend/src/utils/cms/category/index.ts
- apps/backend/src/utils/cms/homeVod/index.ts
- apps/backend/src/utils/cms/home/index.ts
- apps/frontend/src/components/ui/Loading/Loading.tsx
- apps/frontend/src/lib/store/useThemeStore.ts
- apps/backend/src/utils/cms/play/index.ts
- apps/backend/src/utils/cms/factory.ts
- apps/frontend/src/lib/constant/llm.ts
- apps/frontend/src/lib/store/useVodSitesStore.ts
- apps/backend/src/utils/logger/index.ts
- apps/backend/src/utils/cms/search/index.ts
- apps/frontend/src/components/ThemeProvider.tsx
- apps/frontend/src/components/ui/ThemeSelector.tsx
- Dockerfile
- apps/frontend/src/components/video/VodSites/index.tsx
- apps/frontend/src/components/video/VodList/index.tsx
- apps/frontend/lib/types/index.ts
- apps/frontend/next.config.ts
- apps/frontend/postcss.config.mjs
- apps/frontend/app/layout.tsx
- apps/frontend/app/home/components/HomeCarousel/index.tsx
- eslint.config.js
| if (isProduction) { | ||
| const mod = (await import('./registry.gen')) as { namespaces: typeof namespaces; default: Hono }; | ||
| // eslint-disable-next-line | ||
| const mod = require('./registry.gen') as { namespaces: typeof namespaces; default: Hono }; | ||
| namespaces = mod.namespaces; | ||
| app = mod.default; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Verify module system settings =="
fd -HI '^package\.json$' apps/backend | while read -r f; do
echo "--- $f"
jq -r '.name, (.type // "<no type field>")' "$f"
done
echo
echo "== Verify TS module target =="
fd -HI 'tsconfig.*\.json' apps/backend | while read -r f; do
echo "--- $f"
jq -r '.compilerOptions.module // "<unset>", .compilerOptions.moduleResolution // "<unset>"' "$f"
done
echo
echo "== Check current require() usage in registry.ts =="
rg -n -C2 '\brequire\s*\(' apps/backend/src/routes/registry.ts
echo
echo "== Locate generated registry artifact (if present) =="
fd -HI 'registry\.gen\.(js|mjs|cjs|ts)$' apps/backend/src/routes || trueRepository: consistent-k/VodHub
Length of output: 1790
生产分支在 ESM 环境下使用 require() 会导致启动失败
第 27 行在 ESM 文件中直接使用 require('./registry.gen')。根据项目配置(type: module 在 package.json),此代码会抛出 require is not defined 错误,导致生产环境启动失败。建议改用 await import('./registry.gen'):
修复建议
if (isProduction) {
- // eslint-disable-next-line
- const mod = require('./registry.gen') as { namespaces: typeof namespaces; default: Hono };
+ const mod = (await import('./registry.gen')) as {
+ namespaces: typeof namespaces;
+ default: Hono;
+ };
namespaces = mod.namespaces;
app = mod.default;
}需要将包含此代码的函数改为 async。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/backend/src/routes/registry.ts` around lines 25 - 29, The production
branch uses require('./registry.gen') inside an ESM module which throws "require
is not defined"; change that to use dynamic import: await
import('./registry.gen') and assign mod.namespaces to namespaces and mod.default
to app. Make the enclosing function that contains the isProduction check async
(or convert its caller to await it) so you can use await import, and keep
references to the symbols namespaces and app and the module name
'./registry.gen' when updating the code.
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
There was a problem hiding this comment.
请移除禁止缩放配置,这会造成可访问性阻断
Line 5 使用 user-scalable=no 与 maximum-scale=1.0 会阻止用户缩放页面,低视力用户无法完成基本阅读操作。
修复示例
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/index.html` at line 5, 移除 viewport 元标签中阻止缩放的属性:删除
user-scalable=no 和 maximum-scale=1.0(以及任何类似阻止缩放的属性),保留响应设置例如 width=device-width
和 initial-scale=1.0,以恢复用户缩放能力并改善可访问性;在 apps/frontend 的 index.html 中定位包含 <meta
name="viewport"> 的标签并更新其属性即可。
| navigate(`/detail?id=${encodeURIComponent(vod.vod_id as string)}&site=${site}`); | ||
| }} |
There was a problem hiding this comment.
请同时编码 site 查询参数,避免特殊字符导致路由参数损坏
目前只编码了 vod_id。当 site 含中文或 & 时,详情页参数可能被截断或解析错误。
修复示例
- navigate(`/detail?id=${encodeURIComponent(vod.vod_id as string)}&site=${site}`);
+ navigate(`/detail?id=${encodeURIComponent(String(vod.vod_id ?? ''))}&site=${encodeURIComponent(site)}`);Also applies to: 226-227
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/components/video/VodSearch/index.tsx` around lines 192 -
193, The route build in the VodSearch component currently encodes vod.vod_id but
not the site parameter (see the navigate call that constructs
`/detail?id=${encodeURIComponent(vod.vod_id as string)}&site=${site}`), which
can break when site contains special characters; update that navigate invocation
(and the duplicate occurrence later) to encode the site value as well (e.g., use
encodeURIComponent(site)) so both id and site are safely URL-encoded before
navigating.
| 1. **CMS Providers** (Recommended): Only need `namespace.ts` and `index.ts` using `createCMSRoutes()` factory | ||
| 2. **Custom Providers**: Individual route files (`home.ts`, `category.ts`, etc.) with custom logic |
There was a problem hiding this comment.
自定义 Provider 约束描述不完整,可能导致生成错误路由结构。
这里用“home.ts, category.ts, etc.”过于宽泛,缺少 namespace.ts、homeVod.ts、detail.ts、play.ts、search.ts,也未强调“每个文件都要导出符合 Route 接口的 route 对象”。建议写成明确清单,避免后续实现偏差。
建议修订(示例)
-2. **Custom Providers**: Individual route files (`home.ts`, `category.ts`, etc.) with custom logic
+2. **Custom Providers**: Must define individual route files:
+ `namespace.ts`, `home.ts`, `homeVod.ts`, `category.ts`, `detail.ts`, `play.ts`, `search.ts`.
+ Each file must export a `route` object that conforms to the `Route` interface.Based on learnings: Applies to apps/backend/src/routes/**/*.{ts,tsx} : Custom backend providers must create individual route files (namespace.ts, home.ts, homeVod.ts, category.ts, detail.ts, play.ts, search.ts), each exporting a route object conforming to the Route interface.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 1. **CMS Providers** (Recommended): Only need `namespace.ts` and `index.ts` using `createCMSRoutes()` factory | |
| 2. **Custom Providers**: Individual route files (`home.ts`, `category.ts`, etc.) with custom logic | |
| 1. **CMS Providers** (Recommended): Only need `namespace.ts` and `index.ts` using `createCMSRoutes()` factory | |
| 2. **Custom Providers**: Must define individual route files: | |
| `namespace.ts`, `home.ts`, `homeVod.ts`, `category.ts`, `detail.ts`, `play.ts`, `search.ts`. | |
| Each file must export a `route` object that conforms to the `Route` interface. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@CLAUDE.MD` around lines 49 - 50, Update the custom provider guidance to
explicitly require these individual route files—namespace.ts, home.ts,
homeVod.ts, category.ts, detail.ts, play.ts, and search.ts—and state that each
file must export a route object that implements the Route interface (i.e.,
export const route: Route = ...); also clarify that CMS Providers only need
namespace.ts and index.ts using the createCMSRoutes() factory; ensure the
wording replaces the vague "home.ts, category.ts, etc." with this exact list and
the export requirement so generated routes follow the expected structure.
| | Item | Convention | Example | | ||
| |---|---|---| | ||
| | Variables/functions | `camelCase` | `getLocalhostAddress` | | ||
| | Types/interfaces | `PascalCase` | `HomeData`, `RouteItem` | | ||
| | Constants | `UPPER_SNAKE_CASE` | `SUCCESS_CODE` | | ||
| | Frontend components | `PascalCase` | `VodList` | | ||
| | Frontend hooks | `use` prefix | `useIsMobile` | | ||
| | Frontend stores | `use` + `Store` suffix | `useSettingStore` | | ||
|
|
||
| ### Git Workflow |
There was a problem hiding this comment.
表格前后缺少空行,会触发 markdownlint MD058。
建议在表格前(Line 144 前)和表格后(Line 153 前)各补一个空行,消除当前 lint warning。
建议修订(示例)
### Naming Conventions
+
| Item | Convention | Example |
|---|---|---|
| Variables/functions | `camelCase` | `getLocalhostAddress` |
| Types/interfaces | `PascalCase` | `HomeData`, `RouteItem` |
| Constants | `UPPER_SNAKE_CASE` | `SUCCESS_CODE` |
| Frontend components | `PascalCase` | `VodList` |
| Frontend hooks | `use` prefix | `useIsMobile` |
| Frontend stores | `use` + `Store` suffix | `useSettingStore` |
+
### Git Workflow📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | Item | Convention | Example | | |
| |---|---|---| | |
| | Variables/functions | `camelCase` | `getLocalhostAddress` | | |
| | Types/interfaces | `PascalCase` | `HomeData`, `RouteItem` | | |
| | Constants | `UPPER_SNAKE_CASE` | `SUCCESS_CODE` | | |
| | Frontend components | `PascalCase` | `VodList` | | |
| | Frontend hooks | `use` prefix | `useIsMobile` | | |
| | Frontend stores | `use` + `Store` suffix | `useSettingStore` | | |
| ### Git Workflow | |
| ### Naming Conventions | |
| | Item | Convention | Example | | |
| |---|---|---| | |
| | Variables/functions | `camelCase` | `getLocalhostAddress` | | |
| | Types/interfaces | `PascalCase` | `HomeData`, `RouteItem` | | |
| | Constants | `UPPER_SNAKE_CASE` | `SUCCESS_CODE` | | |
| | Frontend components | `PascalCase` | `VodList` | | |
| | Frontend hooks | `use` prefix | `useIsMobile` | | |
| | Frontend stores | `use` + `Store` suffix | `useSettingStore` | | |
| ### Git Workflow |
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 144-144: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@CLAUDE.MD` around lines 144 - 153, The markdown table starting with the
header "| Item | Convention | Example |" lacks blank lines before and after it
(causing markdownlint MD058); add one empty line immediately before that table
header and one empty line immediately before the following "### Git Workflow"
heading so the table is separated from surrounding content and the lint warning
is resolved.
Summary by CodeRabbit
发布说明
新特性
改进
Chores