fix(个人主页): 总共学习天数改为有提交的天数
Some checks failed
Deploy / deploy (push) Has been cancelled

原来是首末提交之间跨了多久,现在按东八区日期对提交去重计数,比赛提交也算。
首末提交时间仍只看比赛外的提交,口径不变。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-19 07:07:57 -06:00
parent 06ad6745b7
commit b4c0f89291
3 changed files with 18 additions and 12 deletions

View File

@@ -46,7 +46,7 @@ import { failure, success } from "../http"
import { JudgeStatus } from "../judge/status" import { JudgeStatus } from "../judge/status"
import { getBooleanOption } from "../services/options" import { getBooleanOption } from "../services/options"
import { getUserProfileById } from "../services/profile" import { getUserProfileById } from "../services/profile"
import { weekStart } from "../time" import { localTime, weekStart } from "../time"
import { import {
isTeacherOrAbove, isTeacherOrAbove,
objectValue, objectValue,
@@ -196,25 +196,29 @@ accountRoutes.post("/me/avatar", requireAuth, async (c) => {
accountRoutes.get("/users/:id/metrics", async (c) => { accountRoutes.get("/users/:id/metrics", async (c) => {
const userId = queryInteger(c.req.param("id"), 0, { min: 1 }) const userId = queryInteger(c.req.param("id"), 0, { min: 1 })
// 学习天数连比赛提交一起算;首末提交时间照旧只看比赛外的提交
const outsideContest = sql`filter (where ${schema.submission.contestId} is null)`
const [row] = await db const [row] = await db
.select({ .select({
total: count(), first: sql<
first: min(schema.submission.createTime), string | null
latest: sql<string>`max(${schema.submission.createTime})`, >`min(${schema.submission.createTime}) ${outsideContest}`,
latest: sql<
string | null
>`max(${schema.submission.createTime}) ${outsideContest}`,
activeDays: countDistinct(
sql`date(${localTime(schema.submission.createTime)})`,
),
}) })
.from(schema.submission) .from(schema.submission)
.where( .where(eq(schema.submission.userId, userId))
and( if (!row?.first || !row.latest)
eq(schema.submission.userId, userId),
isNull(schema.submission.contestId),
),
)
if (!row?.total || !row.first || !row.latest)
return failure(c, 404, "no-submissions", "暂无提交") return failure(c, 404, "no-submissions", "暂无提交")
return success(c, { return success(c, {
now: new Date().toISOString(), now: new Date().toISOString(),
first: row.first, first: row.first,
latest: row.latest, latest: row.latest,
activeDays: row.activeDays,
} satisfies Metrics) } satisfies Metrics)
}) })

View File

@@ -81,7 +81,7 @@ async function init() {
firstSubmissionAt.value = parseTime(metricsRes.first) firstSubmissionAt.value = parseTime(metricsRes.first)
latestSubmissionAt.value = parseTime(metricsRes.latest) latestSubmissionAt.value = parseTime(metricsRes.latest)
toLatestAt.value = durationToDays(metricsRes.latest, metricsRes.now) toLatestAt.value = durationToDays(metricsRes.latest, metricsRes.now)
learnDuration.value = durationToDays(metricsRes.first, metricsRes.latest) learnDuration.value = `${metricsRes.activeDays}`
} }
} finally { } finally {
toggle(false) toggle(false)

View File

@@ -19,6 +19,8 @@ export const metricsSchema = z.object({
now: z.string(), now: z.string(),
latest: z.string(), latest: z.string(),
first: z.string(), first: z.string(),
/** 有提交的日历天数(东八区),不是首末提交之间跨了多少天 */
activeDays: z.number().int(),
}) })
export const rankProfileSchema = z.object({ export const rankProfileSchema = z.object({