Files
senmesh-zc/AGENTS.md

6.6 KiB
Raw Blame History

AGENTS.md

森睿智传(senmesh-zc-legacy)——内网/外网文件传输与网盘管理 Web 端(React SPA)。后端为 s-file(alita-bjy-uygur 仓库),本项目为其前端。

常用命令

bun install        # 安装依赖(使用 bun.lock;Node >= 20,本机经 nvm 提供)
bun run dev        # 启动开发服务器(Vite)
bun run build      # tsc -b && vite build(类型检查 + 构建,构建目标 chrome86)
bun run build:inside   # 内网包(VITE_IS_INSIDE=true)→ dist/inside
bun run build:outside  # 外网包(VITE_IS_INSIDE=false)→ dist/outside
bun run lint       # ESLint(存在大量存量告警,见「代码约定」)
bun run preview    # 预览构建产物

内外网发布包构建后打 tar(解压后 index.html 在顶层,可直接作为 nginx 站点根):

tar -czf release/senmesh-zc-inside.tar.gz --exclude='.DS_Store' -C dist/inside .
tar -czf release/senmesh-zc-outside.tar.gz --exclude='.DS_Store' -C dist/outside .

没有测试框架,验证手段为 build(含 tsc 严格检查)+ 浏览器冒烟。

关键注意事项

  • 路由树是生成的:src/routeTree.gen.ts 由 @tanstack/router-plugin 在 dev/build 时生成。新增路由文件后直接跑 tsc -b 会报路由不存在 —— 先跑 bunx vite build(或启动 dev)再跑 bunx tsc -b。
  • Hash 路由:createHashHistory,页面地址形如 /#/admin/user,直接访问不带 # 的路径会落到首页。
  • ESLint 基线:存量代码大量 no-explicit-any、useColumns 在回调中调用等告警属既有风格;新代码与周围风格保持一致即可,tsc 严格检查(strict、noUnusedLocals、noUnusedParameters)才是硬门禁。

技术栈

React 19 · TypeScript(strict) · Vite(rolldown-vite) · TanStack Router(文件路由 + autoCodeSplitting)· TanStack Query v5(全局 retry: false、refetchOnWindowFocus: false,见 src/main.tsx)· TanStack Table · zustand(persist + derive-zustand)· axios · Tailwind 3 + shadcn/ui(Radix)· lucide-react · sonner · react-dropzone · react-hook-form + zod

目录结构

src/
  apis/            # 接口函数,按域分文件(user/org/file/upload-config)
  lib/http/        # axios 实例与拦截器(index.ts 导出 http 与常量)
  routes/
    (user)/        # 用户端网盘页面(my/outside/inside/share/recycle)
    admin/         # 管理后台;route.tsx 定义侧边菜单
    extract/       # 抽取
  components/      # 共享业务组件;ui/ 为 shadcn 基础组件
  hooks/           # 共享 hooks(kebab-case 文件名,如 use-upload-config.ts)
  stores/user.ts   # 登录态 store(persist,key 为 `${VITE_STORE_PREFIX}_user`)

路由/页面组织约定

  • 功能目录 = index.tsx(路由 + useColumns + 页面组件)+ -hooks/ + -components/;- 前缀目录不参与路由。
  • 列表页统一走 useFetchList 模式:useState 分页 {pageIndex, pageSize} + useQuery(queryKey 含 [名称, pagination, params])+ useReactTable(getCoreRowModel、手动分页)+ 共享 <DataTable>/<Pagination>。
  • 筛选条件采用「点击查询后生效」:草稿 state 与提交 params 分离,提交时过滤空值并重置到第一页(参考 admin/org-account、admin/file-record)。
  • 管理后台菜单在 admin/route.tsx 的 menus 中维护;仅平台机构(超管)可见的菜单加入 platformOnlyUrls(由 useIsPlatformOrg 即 org.id === 1 判断),机构级菜单(用户管理、上传配置)不加入。

HTTP 层与后端约定(重要)

  • 响应拦截器(src/lib/http/interceptors.ts)resolve 的值是 AlitaResult 本体:{ requestId, code, success, msg, data }。因此 queryFn 里 .then(res => res.data) 拿到的才是业务数据(如分页 Page:{ entityList, totalCount, pageCount })。
  • 分页参数走 query:pageNo(从 1 开始)/pageSize。
  • code "200" 成功;555/666/999/401/402/700 拦截器统一 toast.error(msg) 后 reject;401/402 清 token 并跳转 /login?redirect=...;603 换 token;非 JSON 响应按文件下载处理。
  • 错误提示只依赖拦截器:mutation 用 toast.promise(mutateAsync(...), { loading, success }),不要加 error 回调(会与拦截器重复弹错)。
  • 请求自动携带 Authorization: Bearer <token>(取自 user store)与 X-XSRF-TOKEN。

代码约定

  • API 函数放 src/apis/,形如 export const xxx = (data: any) => http.post("/path", data),参数类型沿用 any(存量风格)。
  • mutation hooks 放页面 -hooks/ 下,仿照 useCancelUser/useUserStatusActions:useMutation + toast.promise 包装,暴露 xxx 与 xxxIsPending。
  • 表单弹窗优先 react-hook-form + zod(参考 EditUserDialog);简单确认弹窗仿 CancelUserConfirmDialog(Dialog + Spinner + onSuccess 里 refetch + setOpen(false))。
  • 页面骨架:外层 p-4 box-border min-h-full space-y-4 → 标题区(text-lg + text-xs text-black/50 副标题)→ 白卡片 p-4 rounded-lg border bg-white space-y-2 → 工具行 → <DataTable> + sticky <Pagination>。
  • 图标用 lucide-react;文案为中文;时间格式 yyyy-MM-dd HH:mm:ss;文件大小用 formatFileSize(src/lib/utils.ts)。

环境变量(.env.development / .env.production)

VITE_API_URL(dev 为 /api,由 vite server.proxy 转发到后端)、VITE_STORE_PREFIX、VITE_BASEPATH、VITE_APP_TITLE、VITE_IS_INSIDE(内网部署标识,影响菜单文案与路由行为)、VITE_DOMAIN、VITE_INIT_PASSWORD。

后端联调

  • 接口文档在后端仓库 alita-bjy-uygur/docs/ 下的 接口文档-*.md,动手前先读对应文档(含字段表、错误文案、权限说明)。
  • 管理端接口普遍要求「平台管理员/机构管理员」身份,前端仅做菜单/入口级控制,权限由后端兜底;错误文案以文档「校验失败提示」为准,前端校验提示需与后端 msg 保持一致。
  • 后端不可达时的冒烟技巧:登录态持久化在 localStorage senmeshzc_user,注入 {"state":{"token":"...","user":{...},"org":{...}},"version":0} 后刷新即可进入受限页面验证 UI(org.id = 1 即平台机构)。

验证清单

  1. bunx vite build && bunx tsc -b 通过(新增路由时先 build 再 tsc)。
  2. bun run dev + 浏览器过一遍改动页面:菜单显隐、空态/加载/错误重试态、弹窗交互、toast 文案。
  3. 涉及上传/记录等平台差异逻辑时,分别验证内网(VITE_IS_INSIDE=true)口径。