包含 s-file 后端、React 前端、MeshSafe 安全检测对接,以及内外网两套 compose/nginx/配置(仅前端 28180/28280 对外发布,其余端口不暴露)。 说明:deploy/config/application-iw.yml 与 application-ow.yml 按维护者 明确要求原样入库,其中含本机 Docker 用的库口令、RabbitMQ 口令与 JWT 密钥;上生产前需替换。
6.6 KiB
6.6 KiB
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即平台机构)。
验证清单
bunx vite build && bunx tsc -b通过(新增路由时先 build 再 tsc)。bun run dev+ 浏览器过一遍改动页面:菜单显隐、空态/加载/错误重试态、弹窗交互、toast 文案。- 涉及上传/记录等平台差异逻辑时,分别验证内网(
VITE_IS_INSIDE=true)口径。