diff --git a/CLAUDE.md b/CLAUDE.md index 3cd582f..5658df5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -77,8 +77,7 @@ cd apps/web && bun run build # 前端构建(不在 verify 里 - 任务名不能和根 `package.json` 的脚本重名(Vite+ 直接报错),所以 `verify` 没有对应的 `bun run` 脚本,用 `bunx vp run verify`。 - 缓存在 `node_modules/.vite/task-cache`,按读到的文件内容做指纹;怀疑缓存不对时删掉它。 -- 2026-09-16 用 Prettier 全量格式化过一次,2026-09-27 换成 Oxfmt,差异只有 5 个文件 - (长联合类型的换行)。之后**改完代码顺手跑一下 `bun run fmt`**。 +- **改完代码顺手跑一下 `bun run fmt`**。 ⚠️ **前端类型检查只能走 `bun run type-check` 这个脚本。** 两条看起来等价的路子都会**静默 通过**:`vue-tsc --noEmit -p tsconfig.json` 检查 0 个文件(那个 tsconfig 是 `files: []` + @@ -88,6 +87,15 @@ references 的壳,真正的配置在 `tsconfig.app.json`),而 `vite build` **不要写测试** —— 沿用上一代的项目约定。验证靠实跑:起服务、打接口、看结果。 本机 Docker 全套都能起,实跑的成本比想象中低。 +## 提交 + +**直接在 `main` 上干活,不开特性分支。** 注意 push 到 `github` 这个 remote 的 `main` +会触发 CI 部署(平时 push 的 `origin` 不会),见 `docs/deploy.md`。 + +提交信息用中文,格式 `type(范围): 从用户视角描述现象`,例如 +`fix(流程图): 「重新判题」从来没成功过,而且会把原来的评分清掉`。 +常用 type:`fix` / `feat` / `refactor` / `perf` / `chore` / `style`。 + ## 几件必须知道的事 ### 单二进制是有代价的 @@ -182,7 +190,7 @@ bun run --filter '@oj2/api' check:ast # 升级 tree-sitter-* 之后一定要 没有 OI。上一代残留的 OI 分支在阶段 0 已经砍掉,不要「顺手补回来」。 -### 前端基线是 Chrome 105(2026-09-16 从 < 94 上调) +### 前端基线是 Chrome 105 机房**部分**电脑是 Chrome 105,其余更新 —— 按最低那档定基线。 @@ -191,8 +199,6 @@ bun run --filter '@oj2/api' check:ast # 升级 tree-sitter-* 之后一定要 (`toSorted` / `Set` 运算 / 迭代器辅助那批是 Chrome 110+ 才有的)。`modernTargets` 不写, 用插件自带的基线(`chrome>=105`),正好是这一档。polyfill 清单写死在 `vite.config.ts`, **升级前端依赖后重新审计**:`DEBUG=vite:legacy bun run build` 会打印探测到的全集。 -- **Chrome < 94 那套删掉了**:`mermaid-legacy`(mermaid@9)、cytoscape 的 UMD→ESM 别名、 - `useMermaid.ts` 里按 UA 分叉的 v9 回调式 render —— 105 用得上 mermaid 11。 - **View Transitions 要 111,105 没有**,`darkTransition.ts` 的降级分支是真在用的。 ### 时间只有一个锚点:`apps/api/src/time.ts` @@ -213,9 +219,7 @@ SQL 里要按日历切,用 `localTime(列)`(生成 `列 at time zone 'Asia/S (见 `apps/web/CLAUDE.md`)。 时区常量 `TIME_ZONE` / `TIME_ZONE_OFFSET_MINUTES` 在 `packages/contract/src/time.ts`, -前后端共用一份,按**固定偏移**算(大陆 1991 年起没有夏令时)。旧栈的口径本来就是东八区, -重写时丢过一次、2026-09 才收回来 —— 期间「今日提交」在北京时间 0:00–8:00 是空的, -两个小时口径的成就整体偏 8 小时,事后已用一次性脚本对账订正(账平了,脚本已删)。 +前后端共用一份,按**固定偏移**算(大陆 1991 年起没有夏令时),与旧栈的东八区口径一致。 **再动日历口径之前先读 `docs/timezone.md`**,那里有实测数据和核实方法; Dockerfile 的 `TZ` 和数据库连接的 `TimeZone` 是**刻意不设**的,别「顺手补上」。 diff --git a/apps/web/CLAUDE.md b/apps/web/CLAUDE.md index fe619b0..4b6d29d 100644 --- a/apps/web/CLAUDE.md +++ b/apps/web/CLAUDE.md @@ -8,10 +8,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co (`ojnext` 与 `../OnlineJudge` 都已下线且**完全冻结,一行都不改**)。Vue 3 + TypeScript, Vite(Rolldown 内核)、Naive UI、Pinia、Vue Router。 -**浏览器基线是 Chrome 105**(机房部分电脑那一档,2026-09-16 从 < 94 上调): +**浏览器基线是 Chrome 105**(机房部分电脑那一档): `vite.config.ts` 的 `@vitejs/plugin-legacy` 和写死的 polyfill 清单不能删 —— vite 8 -默认 target 是 chrome111,比机房高。`mermaid-legacy` 那条 < 94 的 fallback 已删除。 -理由写在该文件的注释里,详见 `../CLAUDE.md`。 +默认 target 是 chrome111,比机房高。 +理由写在该文件的注释里,详见 `../../CLAUDE.md`。 ## Commands @@ -59,7 +59,7 @@ API 调用不按模块分:学生端全在 `oj/api.ts`、后台全在 `admin/ap Shared logic lives in `shared/`: - `store/` — Pinia stores: `user` (auth/roles), `config` (site-wide settings), `authModal` (login/signup form state), `screenMode` (problem split-screen layout), `loginSummary` (AI activity summary), `collab` (help-request queue + collab room), `achievement` (解锁弹窗队列), `myFlowchart` (流程图弹窗的 mermaid 源码) -- `composables/` — `pagination` (URL-synced), `websocket` (reconnect + heartbeat), `collabDoc` (Yjs binding for the collab channel), `configUpdate` (WS-pushed config sync), `useMermaid` (lazy Mermaid render), `darkTransition` (View Transitions,111 以下走降级分支), `hiddenStudents` (统计面板的「请假隐藏」), `chartTheme`, `breakpoints`, `maxkb`, `learnProgress`, `rarity` +- `composables/` — `aiStream`, `pagination` (URL-synced), `websocket` (reconnect + heartbeat), `collabDoc` (Yjs binding for the collab channel), `configUpdate` (WS-pushed config sync), `useMermaid` (lazy Mermaid render), `darkTransition` (View Transitions,111 以下走降级分支), `hiddenStudents` (统计面板的「请假隐藏」), `chartTheme`, `breakpoints`, `maxkb`, `learnProgress`, `rarity` - `layout/` — `default.vue` and `admin.vue` layout wrappers - `api.ts` — shared API calls (auth, profile, tags, captcha) @@ -127,7 +127,7 @@ return contract("GET /problems/:id", problemDetailSchema, value) 一道闸,一行脏数据能让整条练习列表 500。 **后端出参已经不 `parse` 了**(原来 136 处,全部改成 `satisfies`;撤的时候炸出两个 -一直存在的线上 500,见 `../CLAUDE.md` 的「出参不 `parse`,用 `satisfies`」)。 +一直存在的线上 500,见 `../../CLAUDE.md` 的「出参不 `parse`,用 `satisfies`」)。 所以现在收紧一个字段的直接后果落在 **`tsc` 编译期**,而不再是运行时 500 —— 这是好事, 但别因此就放心大胆收:契约里的形状仍然要对得上库里的存量数据,前端拿到对不上的值 一样会渲染错。收紧任何字段之前,拿根目录那份生产备份把全量数据跑一遍, @@ -174,7 +174,7 @@ Env files: `.env`(本机)、`.env.production`(服务器)、`.env.staging | `PUBLIC_ICONIFY_URL` | 自建 Iconify 图标源,不设则走公共 CDN | 后端地址**不在这里**:`utils/api.ts` 写死 `baseURL: "/api"`,dev 由 `vite.config.ts` 的 -proxy 转给 3000,线上由 Caddy 同源伺服。(原来的 `PUBLIC_OJ_URL` / `PUBLIC_WS_URL` 早已不存在。) +proxy 转给 3000,线上由 Caddy 同源伺服。 ### Routing @@ -195,4 +195,4 @@ Routes are defined in `src/routes.ts` with two root routes: `ojs` (user-facing) 后端就在同一个仓库的 `../api`(Bun + Hono + Drizzle,编译成单二进制), 契约在 `../../packages/contract`。**不要再去看 `OnlineJudge/`** —— 那是已下线的 -Django 后端,只作参照、完全冻结。详见 `../CLAUDE.md`。 +Django 后端,只作参照、完全冻结。详见 `../../CLAUDE.md`。