Commit Graph
11 Commits
Author SHA1 Message Date
xuyueandClaude Opus 5.5 1b703d13ae style(专题): 「题单」改名「专题」,顶栏、列表、详情、后台、成就说法统一
Deploy / deploy (push) Canceled after 0s
只改界面文字和注释:网址 /problemset、接口、表名、字段名都不动,老链接照常能打开。
设计稿页名「题单重设计」和已执行的迁移文件保留原样。
线上 3 个成就(题单收藏家 / 入门 / 通关)已同步改名。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:12:18 +08:00
xuyueandClaude Opus 5.5 195069450f style(格式化): 改成单引号、一行最长 160,全仓重新格式化
Deploy / deploy (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:52:24 +08:00
xuyueandClaude Opus 5.5 734f4aed05 fix(成就): 成就线的进度线不再从徽章中间透出来
Deploy / deploy (push) Canceled after 0s
徽章底色是半透明的稀有度色,压在线上面挡不住;底下垫一层卡片底色

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:32:37 +08:00
xuyueandClaude Opus 5.5 36f2a45c5e fix(成就): 题单奖章名字不再被截成「物联网专业…」;没有班级时「快拿到了」横排占满整宽
- 奖章名最长 9 个字,竖排格子只放得下 4 个,改成图标 + 全名横排、放不下就换行
- 老师、自己注册的号没有班级就没有「本班」,原来「快拿到了」只占左半边、右边空着

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:31:03 +08:00
xuyueandClaude Opus 5.5 cbeb0737ef feat(成就): 成就页改成「快拿到了 + 本班」加一条条成就线,不再是一墙灰卡
Deploy / deploy (push) Canceled after 0s
- 顶上「快拿到了」三个只说还差什么,旁边「本班」:最近谁拿到了什么、成就最多前五(自己不在就钉在底下)
- 38 个成就按指标收成一条条线、分五组,同一串几档排在一根进度线上,下一档标「差几」;
  悬停看说明、哪天拿到、本班几人有、全站几人有
- 还没找到的隐藏成就只露问号;本班动态里也只说「彩蛋」,不漏名字
- 题单奖章并进「题单和比赛」那组;看别人的成就只有成就线
- 去掉「仅 X% 的人获得」(分母是全站历届账号)和完成度圆环

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:26:37 +08:00
xuyueandClaude Opus 5.5 85108df9d8 feat(成就): 下架三个拿不到的成就、理顺稀有度和图标;接口多给本班几人有和「本班」卡片
- 0032:下架六边形战士(判题机只剩 3 种语言)、坚持三天/一周(按天算基本拿不到);
  不撞南墙改白银、屡败屡战改黄金;百发百中换 💯、屡败屡战换 💪,不再和别的撞图标;
  代码行数只算做对的、空行不算,并按新口径重算所有人;已经拿到的一个不收回
- 奖杯收藏家只数上架的成就(判题结算、补发重算、0032 存量一起改)
- GET /achievements:每个成就带全站几人有、本班几人有;看自己时带「本班」(最近拿到、成就最多前五、自己第几);
  隐藏成就同一串拿到一档就整串亮出来;连续几周给「现在连着几周」而不是历史最长
- 删掉只有旧成就页在用的 /achievements/summary

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:26:37 +08:00
xuyueandClaude Opus 5.5 1e441411a5 style(前台): 页面整体放大一档,列表不再挤成一团;宽屏上内容居中,不再铺满到两边
Deploy / deploy (push) Canceled after 0s
- index.css 加一张 --oj-* 尺寸表和 .oj-page 外壳,二十几个前台页面改成引用它:
  正文 14→15、页标题 20→24、题目/提交列表行高 40→48、比赛/公告 56、筛选控件 28→34
- 阅读型页面限宽 1200 居中;题目/提交列表 1600、比赛详情 1400、排名 1280、班级 PK 1440
- 1280 宽的筛选条放大后放不下,题目/提交列表在 1366 以下退回 13px 的字
- 班级 PK 五个班起格子里不写「一次 x%」(只剩「一次 8…」);赛跑图线尾的数字不再被截掉
- 手机上比赛列表的「没参加」挪到比赛名下面;题单里「以前做对过 · 旧代码先藏着」缩成「做对过」
- 题目详情页(编辑器)和后台不在这一轮

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:43:12 +08:00
xuyue d25b5dbe6d update
Deploy / deploy (push) Canceled after 0s
2026-09-27 19:36:28 +08:00
xuyueandClaude Opus 5 4c0c38445c fix(时区): 日历口径收回东八区,读出的时刻统一成 ISO 并保留微秒
旧栈 Django 按 Asia/Shanghai 算日历,OJ2 重写时这个锚点丢了:容器和数据库会话
都是 UTC,于是「今日提交」在北京时间 0–8 点是空的,「凌晨/早起提交次数」整体偏
8 小时,热力图、AC 趋势年份、近两年活跃人数也各按进程时区切。

- 新增 apps/api/src/time.ts 作为唯一锚点(固定 +8 偏移,不依赖进程 TZ / tzdata),
  todayStart、成就小时/日期键、热力图、月份平移、年份夹逼全部改走它;
  SQL 里按日历切的一律显式 at time zone。
- db/index.ts:连接会话时区设为东八区(兜底);给 timestamptz(1184) 挂 parser,
  读出统一成 ISO 8601 UTC,撤掉为拿 PG 文本形状写的 ::text。parser 保留微秒 ——
  生产库 12.3 万条提交几乎全带微秒,截成毫秒会让翻页分界行和班级 AC 排名的
  <= min(create_time) 把自己排除(翻页每页丢一条、排名少 1)。
- 前端 parseTime/zonedParts/zonedYear 按 Asia/Shanghai 渲染,n-date-picker 做
  toPickerValue/fromPickerValue 平移,站内不再按浏览器时区取时间部件。
- Dockerfile 设 TZ=Asia/Shanghai 作为第二道兜底。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K1d8B3f4SXJwDvUY625eQd
2026-09-14 05:55:17 -06:00
xuyueandClaude Opus 5 c2a81209d7 refactor(前端): 拆掉 camelCase→snake_case 转换层,契约成为唯一真相
utils/legacy.ts 是迁移期的临时层:新后端一律 camelCase,而组件读的还是
旧 Django 的 snake_case,于是在 api 层做一次递归键名重写。它自己的注释就
写了「迁移完成后这一层应当整体拆掉」。现在拆了。

代价不只是那 96 处包装:每个响应都要递归遍历整个对象重写一遍键名,而且
utils/types.ts 和 packages/contract 是两份真相 —— 手抄的那份还抄歪了好几处。

做法是按域推进,每域都用 vue-tsc 相对基线做差,确认零新增错误后再往下走。
前端的类型现在一律以契约为准,只在必要处窄化(比如 languages/template 的键
窄化成 LANGUAGE),删掉的重复定义包括 WebsiteConfig、LoginSummary、
AchievementSummary、ProblemSet、Contest、User、Profile、AdminTag、
StuckProblem 等等,其中 ClassComparison 有两个组件各手抄了一份。

## 顺带修掉的真 bug

- 管理端公告列表的「可见」开关每次都 400:列表响应被契约 omit 掉了 content,
  而更新接口要求 content 必填,toggleVisible 把列表行原样回传。而且是乐观
  翻转、不 await 不 catch,管理员看到开关动了、实际没存也没有提示。
  改成先 GET 整条再 PUT,加失败提示。

- 删有提交的题时只显示笼统的「删除失败」:前端还在 match 旧 Django 的英文
  文案,而后端返回的是 problem-has-submissions + 中文。连同另外 8 处同类
  匹配一起改成判错误码 —— 文案是后端随时能改的,match 文案改一个字就静默失效。

- SubmissionStatus.time_limit_exceeded 写成 `1 | 2`,TS 按位或算成 3,和
  memory_limit_exceeded 撞了同一个值。后端 judge/status.ts 里这是分开的
  两个码,按后端拆成 cpu_/real_ 两项。当前没有代码读这两个成员,但
  CLAUDE.md 明确要求判题状态码三处同步。

- 流程图历史翻到没有提交的那一页会直接抛:契约里 submission 是 nullable,
  被 any 掩盖成看起来非空。补了 null 分支。

## 契约里被逼出来的三处不诚实

- grade 写成 z.string(),但 averageGrade() 在没有可用数据时返回空串,
  前端三张图表拿它查 Record<Grade,...> 会查出 undefined。按实际收紧成
  z.enum([...,""]),四个查表点都补了「无评级」分支。

- difficulty 写成 z.string()。核对过生产库 dump:956 道题只有
  Low/Mid/High 三个值(761/149/46)。收紧成枚举。

- topReaction 写成 z.string(),既对不上前端渲染的 {type,count},也对不上
  旧后端 get_top_reactions 下发的形状。改成正确形状并注明当前恒传 null。

## 明确保留 snake_case 的 54 处

判题沙箱原始输出(cpu_time/exit_code/output_md5/compile_output)、
statistic_info 内容(err_info/time_cost/ast_results)、submission_info
JSONB(is_ac/ac_time/error_number,回滚时旧后端还要读)、SQL 判题引擎的
total_rows/order_sensitive/changed_tables、WebSocket 的 submission_id、
以及数据库选项键 enable_maxkb。每一处都在类型定义旁写了为什么不能改。

language 没有跟着收紧契约 —— 它是配置项、随时可能加语言,收紧会让新语言
在后端 parse 时直接抛。改在 api 边界一处窄化。

## 另外

- utils/http.ts 整个模块已是死代码(四处引用全是 import type),删除。
- profile 的 blog/github/school/major/language 五个字段全链路空转,没有
  任何组件读,从契约到类型一并摘除(数据库列不动)。
- admin/account.ts 往 user_profile 塞的 totalScore 是 OI 模式遗留,表里
  没这一列。Drizzle 按表定义拼列名会把它静默丢弃,所以没出过错,是死代码。

验证:vue-tsc 143 → 54 条且无新增,apps/api tsc、check:routes、web build
全通过;各域响应形状逐条打接口核对过。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 13:44:24 -06:00
xuyue ae1fb329b5 feat(阶段1): 搬入 ojnext 为 apps/web,未改业务代码 2026-08-06 21:18:16 -06:00