diff --git a/apps/api/src/routes/account.ts b/apps/api/src/routes/account.ts index 74cc556..6423708 100644 --- a/apps/api/src/routes/account.ts +++ b/apps/api/src/routes/account.ts @@ -46,7 +46,7 @@ import { failure, success } from "../http" import { JudgeStatus } from "../judge/status" import { getBooleanOption } from "../services/options" import { getUserProfileById } from "../services/profile" -import { weekStart } from "../time" +import { localTime, weekStart } from "../time" import { isTeacherOrAbove, objectValue, @@ -196,25 +196,29 @@ accountRoutes.post("/me/avatar", requireAuth, async (c) => { accountRoutes.get("/users/:id/metrics", async (c) => { const userId = queryInteger(c.req.param("id"), 0, { min: 1 }) + // 学习天数连比赛提交一起算;首末提交时间照旧只看比赛外的提交 + const outsideContest = sql`filter (where ${schema.submission.contestId} is null)` const [row] = await db .select({ - total: count(), - first: min(schema.submission.createTime), - latest: sql`max(${schema.submission.createTime})`, + first: sql< + string | null + >`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) - .where( - and( - eq(schema.submission.userId, userId), - isNull(schema.submission.contestId), - ), - ) - if (!row?.total || !row.first || !row.latest) + .where(eq(schema.submission.userId, userId)) + if (!row?.first || !row.latest) return failure(c, 404, "no-submissions", "暂无提交") return success(c, { now: new Date().toISOString(), first: row.first, latest: row.latest, + activeDays: row.activeDays, } satisfies Metrics) }) diff --git a/apps/web/src/oj/user/index.vue b/apps/web/src/oj/user/index.vue index 37c0186..746f656 100644 --- a/apps/web/src/oj/user/index.vue +++ b/apps/web/src/oj/user/index.vue @@ -81,7 +81,7 @@ async function init() { firstSubmissionAt.value = parseTime(metricsRes.first) latestSubmissionAt.value = parseTime(metricsRes.latest) toLatestAt.value = durationToDays(metricsRes.latest, metricsRes.now) - learnDuration.value = durationToDays(metricsRes.first, metricsRes.latest) + learnDuration.value = `${metricsRes.activeDays} 天` } } finally { toggle(false) diff --git a/packages/contract/src/account.ts b/packages/contract/src/account.ts index 04ef278..8abd4d0 100644 --- a/packages/contract/src/account.ts +++ b/packages/contract/src/account.ts @@ -19,6 +19,8 @@ export const metricsSchema = z.object({ now: z.string(), latest: z.string(), first: z.string(), + /** 有提交的日历天数(东八区),不是首末提交之间跨了多少天 */ + activeDays: z.number().int(), }) export const rankProfileSchema = z.object({