时段选项的 value 是 `<date-fns 单位>:<数量>`,把它解成 Duration 的那段 `split(":")`
在**五个组件里各写了一遍**(提交统计、流程图统计、AI 分析页、榜单页、班级对比页),
每份的兜底还都不一样;选项列表也抄了好几份:
- 两个统计面板逐字相同地拼「10/20/30 分钟 + DURATION_OPTIONS + 全部时段」;
- rank/list.vue 和 class/pk.vue 各手写了同样的五条长时段,pk.vue 里还留着一句
「与 rank/list.vue 保持一致」的注释 —— 靠注释同步的东西迟早不同步。
现在:`PANEL_DURATION_OPTIONS`(面板用,含分钟级和 all)、`LONG_DURATION_OPTIONS`
(榜单/班级对比用,从 DURATION_OPTIONS 派生)、`durationFromValue()`(唯一解析)。
各站点自己的兜底保留在原处,那部分本来就该各不相同。
## 行为零变化,逐条比对过
把改动前各处手写的列表原样取出来和新的比:面板 12 条、榜单 5 条、班级对比 6 条,
标签与取值逐条一致;11 个时段值的解析结果与旧的内联写法逐个相同。
唯一的差异在 `all`:旧写法产出 `{all: NaN}`,新写法回 null。**两边都到不了** ——
三处用到 subOptions 的地方全在 `query.duration === "all" ? … : …` 的 else 分支里,
三元短路,all 时根本不求值。逐处确认过。
## 实跑
- 榜单页:下拉 5 条顺序正确;切一周内,请求从 start=2026-08-10(months:1)
变成 start=2026-09-03(weeks:1),正好差 7 天;
- 班级对比页:下拉 6 条含「全部时间」;两个班 PK,全部时间和一个月内都正常出结果;
- 提交统计面板:默认 minutes:10,统计请求的 start 正好比 end 早 10 分钟。
另:ChartJS.register 那 15 处**没有动**。逐个列出来看,它们注册的是各自需要的那一套,
不是同一份重复(真正逐字相同的只有 4 个 Bar 图和 2 个 Line 图),而且组件各自声明依赖
正是 chart.js 该用的方式 —— 没用到的控制器不会进包,忘了注册会当场抛
`"bar" is not a registered controller`,是响的不是静默的。集中注册只会把懒加载的图表
代码推进首屏,为省 6 处重复不值得。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012j1vgeDqay8wKCh8dPgPcH
This commit is contained in:
@@ -17,9 +17,9 @@ import {
|
||||
getClassPK,
|
||||
} from "oj/api"
|
||||
import { useBreakpoints } from "shared/composables/breakpoints"
|
||||
import { getACRate } from "utils/functions"
|
||||
import { durationFromValue, getACRate } from "utils/functions"
|
||||
import Pagination from "shared/components/Pagination.vue"
|
||||
import { ChartType } from "utils/constants"
|
||||
import { ChartType, LONG_DURATION_OPTIONS } from "utils/constants"
|
||||
import { renderTableTitle } from "utils/renders"
|
||||
import Chart from "./components/Chart.vue"
|
||||
import Index from "./components/Index.vue"
|
||||
@@ -282,21 +282,12 @@ async function listActivity() {
|
||||
}))
|
||||
}
|
||||
|
||||
const options: SelectOption[] = [
|
||||
{ label: "一周内", value: "weeks:1" },
|
||||
{ label: "一个月内", value: "months:1" },
|
||||
{ label: "两个月内", value: "months:2" },
|
||||
{ label: "半年内", value: "months:6" },
|
||||
{ label: "一年内", value: "years:1" },
|
||||
]
|
||||
const options: SelectOption[] = [...LONG_DURATION_OPTIONS]
|
||||
|
||||
const subOptions = computed<Duration>(() => {
|
||||
let dur = options.find((it) => it.value === duration.value) ?? options[1]
|
||||
const x = dur.value!.toString().split(":")
|
||||
const unit = x[0]
|
||||
const n = x[1]
|
||||
return { [unit]: parseInt(n) }
|
||||
})
|
||||
// 认不出来退回 options[1](一个月内),和 duration 的初值一致
|
||||
const subOptions = computed<Duration>(
|
||||
() => durationFromValue(duration.value) ?? durationFromValue(LONG_DURATION_OPTIONS[1]!.value)!,
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
// 「全服 Top10」就是榜单第一页的前 10 条:挂载时 init() 取的正是 offset=0&limit=10,
|
||||
|
||||
Reference in New Issue
Block a user