style(格式化): 改成单引号、一行最长 160,全仓重新格式化
Deploy / deploy (push) Canceled after 0s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-26 13:52:24 +08:00
1 parent 530e1a3d5d
commit 195069450f
480 files changed
+15507 -24650

No files matched your search

@@ -1,9 +1,9 @@
<script setup lang="ts">
import { useThemeVars } from "naive-ui"
import UserName from "shared/components/UserName.vue"
import { parseTime } from "utils/functions"
import type { Achievement, AchievementClassBoard } from "utils/types"
import Medal from "./Medal.vue"
import { useThemeVars } from 'naive-ui'
import UserName from 'shared/components/UserName.vue'
import { parseTime } from 'utils/functions'
import type { Achievement, AchievementClassBoard } from 'utils/types'
import Medal from './Medal.vue'
/**
* 「本班」:最近谁拿到了什么、成就最多的前五名(自己不在里面就钉在底下)。
@@ -26,8 +26,7 @@ const recent = computed(() => {
const item = byId.value.get(row.achievementId)
if (!item) continue
const last = rows.at(-1)
if (last && last.username === row.username && last.time === row.unlockTime)
last.items.push(item)
if (last && last.username === row.username && last.time === row.unlockTime) last.items.push(item)
else
rows.push({
key: `${row.username}-${row.unlockTime}-${row.achievementId}`,
@@ -42,8 +41,8 @@ const recent = computed(() => {
function what(items: Achievement[]) {
const known = items.filter((item) => item.metric !== null).map((item) => item.name)
const eggs = items.length - known.length
if (eggs) known.push(eggs === 1 ? "一个彩蛋" : `${eggs} 个彩蛋`)
return known.join("、")
if (eggs) known.push(eggs === 1 ? '一个彩蛋' : `${eggs} 个彩蛋`)
return known.join('、')
}
</script>
@@ -54,29 +53,19 @@ function what(items: Achievement[]) {
<div class="col">
<span class="sub">最近拿到</span>
<div v-for="row in recent" :key="row.key" class="line">
<Medal
:icon="row.items[0]!.icon"
:rarity="row.items[0]!.rarity"
:size="28"
:state="row.items[0]!.metric === null ? 'unknown' : 'on'"
/>
<Medal :icon="row.items[0]!.icon" :rarity="row.items[0]!.rarity" :size="28" :state="row.items[0]!.metric === null ? 'unknown' : 'on'" />
<span class="what">
<UserName :username="row.username" />
<span class="muted">拿到</span>
{{ what(row.items) }}
</span>
<span class="date">{{ parseTime(row.time, "M月D日") }}</span>
<span class="date">{{ parseTime(row.time, 'M月D日') }}</span>
</div>
<span v-if="!recent.length" class="empty">这学期还没人拿到</span>
</div>
<div class="col">
<span class="sub">成就最多</span>
<div
v-for="row in board.most"
:key="row.username"
class="line rank"
:class="{ mine: row.username === me }"
>
<div v-for="row in board.most" :key="row.username" class="line rank" :class="{ mine: row.username === me }">
<span class="no">{{ row.rank }}</span>
<UserName :username="row.username" />
<b>{{ row.count }}</b>
@@ -94,9 +83,9 @@ function what(items: Achievement[]) {
<style scoped>
.card {
padding: 14px 20px 12px;
border: 1px solid v-bind("theme.borderColor");
border: 1px solid v-bind('theme.borderColor');
border-radius: var(--oj-radius);
background: v-bind("theme.cardColor");
background: v-bind('theme.cardColor');
}
h3 {
@@ -120,7 +109,7 @@ h3 {
.sub {
margin-bottom: 4px;
font-size: var(--oj-fs-meta);
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
}
.line {
@@ -143,7 +132,7 @@ h3 {
.date,
.no,
.empty {
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
}
.muted {
@@ -178,7 +167,7 @@ h3 {
}
.pinned {
border-top: 1px dashed v-bind("theme.borderColor");
border-top: 1px dashed v-bind('theme.borderColor');
}
.compact {
@@ -1,16 +1,16 @@
<script setup lang="ts">
import { useThemeVars } from "naive-ui"
import AchievementIcon from "shared/components/AchievementIcon.vue"
import type { UserBadge } from "utils/types"
import type { Group } from "../series"
import Medal from "./Medal.vue"
import SeriesRow from "./SeriesRow.vue"
import { useThemeVars } from 'naive-ui'
import AchievementIcon from 'shared/components/AchievementIcon.vue'
import type { UserBadge } from 'utils/types'
import type { Group } from '../series'
import Medal from './Medal.vue'
import SeriesRow from './SeriesRow.vue'
/** 一组成就线(做题 / 坚持 / …),「彩蛋」组末尾是还没找到的问号,「题单和比赛」组末尾是拿到的题单奖章 */
const props = defineProps<{ group: Group; badges?: UserBadge[]; compact?: boolean }>()
const theme = useThemeVars()
const showBadges = computed(() => props.group.name === "题单和比赛" && !!props.badges?.length)
const showBadges = computed(() => props.group.name === '题单和比赛' && !!props.badges?.length)
</script>
<template>
@@ -31,10 +31,7 @@ const showBadges = computed(() => props.group.name === "题单和比赛" && !!pr
<div class="badge-list">
<n-tooltip v-for="b in badges" :key="b.id" :delay="150">
<template #trigger>
<router-link
:to="{ name: 'problemset', params: { problemSetId: b.problemSet.id } }"
class="badge"
>
<router-link :to="{ name: 'problemset', params: { problemSetId: b.problemSet.id } }" class="badge">
<AchievementIcon :icon="b.badge.icon" :size="24" />
<span>{{ b.badge.name }}</span>
</router-link>
@@ -49,9 +46,9 @@ const showBadges = computed(() => props.group.name === "题单和比赛" && !!pr
<style scoped>
.card {
padding: 14px 20px 20px;
border: 1px solid v-bind("theme.borderColor");
border: 1px solid v-bind('theme.borderColor');
border-radius: var(--oj-radius);
background: v-bind("theme.cardColor");
background: v-bind('theme.cardColor');
}
h3 {
@@ -65,7 +62,7 @@ h3 {
h3 small {
font-size: var(--oj-fs-meta);
font-weight: 400;
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
font-variant-numeric: tabular-nums;
}
@@ -79,7 +76,7 @@ h3 small {
.masked-title {
font-size: 13px;
color: v-bind("theme.textColor2");
color: v-bind('theme.textColor2');
}
.masked-list,
@@ -99,8 +96,8 @@ h3 small {
border-radius: 6px;
font-size: var(--oj-fs-sec);
white-space: nowrap;
color: v-bind("theme.textColor1");
background: v-bind("theme.actionColor");
color: v-bind('theme.textColor1');
background: v-bind('theme.actionColor');
text-decoration: none;
}
@@ -1,8 +1,8 @@
<script setup lang="ts">
import { useThemeVars } from "naive-ui"
import AchievementIcon from "shared/components/AchievementIcon.vue"
import { RARITY_COLOR } from "utils/constants"
import type { AchievementRarity } from "utils/types"
import { useThemeVars } from 'naive-ui'
import AchievementIcon from 'shared/components/AchievementIcon.vue'
import { RARITY_COLOR } from 'utils/constants'
import type { AchievementRarity } from 'utils/types'
/**
* 一枚徽章:拿到的是稀有度色的圈,没拿到的灰掉,还没找到的隐藏成就是虚线问号。
@@ -13,10 +13,10 @@ const props = withDefaults(
icon?: string
rarity?: AchievementRarity
size?: number
state?: "on" | "off" | "unknown"
state?: 'on' | 'off' | 'unknown'
ring?: number | null
}>(),
{ icon: "", rarity: "bronze", size: 40, state: "on", ring: null },
{ icon: '', rarity: 'bronze', size: 40, state: 'on', ring: null },
)
const theme = useThemeVars()
@@ -25,25 +25,13 @@ const r = computed(() => props.size / 2 + 3)
const box = computed(() => props.size + 8)
const circumference = computed(() => 2 * Math.PI * r.value)
// 底色都是半透明的,下面垫一层卡片底色 —— 不然成就线的进度线会从徽章中间透出来
const onBg = computed(
() => `linear-gradient(${color.value}26, ${color.value}26), ${theme.value.cardColor}`,
)
const offBg = computed(
() =>
`linear-gradient(${theme.value.actionColor}, ${theme.value.actionColor}), ${theme.value.cardColor}`,
)
const onBg = computed(() => `linear-gradient(${color.value}26, ${color.value}26), ${theme.value.cardColor}`)
const offBg = computed(() => `linear-gradient(${theme.value.actionColor}, ${theme.value.actionColor}), ${theme.value.cardColor}`)
</script>
<template>
<span class="medal" :style="{ width: `${size}px`, height: `${size}px` }">
<svg
v-if="ring !== null && state !== 'unknown'"
class="arc"
:width="box"
:height="box"
:viewBox="`0 0 ${box} ${box}`"
aria-hidden="true"
>
<svg v-if="ring !== null && state !== 'unknown'" class="arc" :width="box" :height="box" :viewBox="`0 0 ${box} ${box}`" aria-hidden="true">
<circle :cx="box / 2" :cy="box / 2" :r="r" fill="none" class="arc-track" stroke-width="3" />
<circle
:cx="box / 2"
@@ -56,15 +44,8 @@ const offBg = computed(
:stroke-dasharray="`${circumference * Math.min(1, ring)} ${circumference}`"
/>
</svg>
<span v-if="state === 'unknown'" class="disc unknown" :style="{ fontSize: `${size * 0.42}px` }">
?
</span>
<span
v-else
class="disc"
:class="state"
:style="state === 'on' ? { borderColor: color, background: onBg } : undefined"
>
<span v-if="state === 'unknown'" class="disc unknown" :style="{ fontSize: `${size * 0.42}px` }"> ? </span>
<span v-else class="disc" :class="state" :style="state === 'on' ? { borderColor: color, background: onBg } : undefined">
<AchievementIcon :icon="icon" :size="Math.round(size * 0.56)" />
</span>
</span>
@@ -85,11 +66,11 @@ const offBg = computed(
}
.arc-track {
stroke: v-bind("theme.dividerColor");
stroke: v-bind('theme.dividerColor');
}
.arc-fill {
stroke: v-bind("theme.primaryColor");
stroke: v-bind('theme.primaryColor');
}
.disc {
@@ -105,7 +86,7 @@ const offBg = computed(
}
.disc.off {
border-color: v-bind("theme.borderColor");
border-color: v-bind('theme.borderColor');
background: v-bind(offBg);
}
@@ -117,9 +98,9 @@ const offBg = computed(
}
.disc.unknown {
border: 1.5px dashed v-bind("theme.borderColor");
border: 1.5px dashed v-bind('theme.borderColor');
background: v-bind(offBg);
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
font-weight: 700;
}
</style>
@@ -1,9 +1,9 @@
<script setup lang="ts">
import { useThemeVars } from "naive-ui"
import { RARITY_LABEL } from "utils/constants"
import { useRarityColor } from "shared/composables/rarity"
import type { Near } from "../series"
import Medal from "./Medal.vue"
import { useThemeVars } from 'naive-ui'
import { RARITY_LABEL } from 'utils/constants'
import { useRarityColor } from 'shared/composables/rarity'
import type { Near } from '../series'
import Medal from './Medal.vue'
/**
* 「快拿到了」:每个只说还差什么,进度条底下是现在几 / 要几、本班几人有。
@@ -16,9 +16,7 @@ const rarityText = useRarityColor()
function now(item: Near) {
const { series, achievement } = item
return series.streak
? `现在连着 ${series.value} ${series.unit}`
: `${series.value} / ${achievement.threshold} ${series.unit}`
return series.streak ? `现在连着 ${series.value} ${series.unit}` : `${series.value} / ${achievement.threshold} ${series.unit}`
}
const percent = (item: Near) => Math.round((item.series.value / item.achievement.threshold!) * 100)
@@ -55,9 +53,7 @@ const percent = (item: Near) => Math.round((item.series.value / item.achievement
/>
<div class="foot">
<span>{{ now(item) }}</span>
<span v-if="item.achievement.classHolders !== null">
本班 {{ item.achievement.classHolders }} 人有
</span>
<span v-if="item.achievement.classHolders !== null"> 本班 {{ item.achievement.classHolders }} 人有 </span>
</div>
</div>
</div>
@@ -68,9 +64,9 @@ const percent = (item: Near) => Math.round((item.series.value / item.achievement
<style scoped>
.card {
padding: 14px 20px 6px;
border: 1px solid v-bind("theme.borderColor");
border: 1px solid v-bind('theme.borderColor');
border-radius: var(--oj-radius);
background: v-bind("theme.cardColor");
background: v-bind('theme.cardColor');
}
h3 {
@@ -83,7 +79,7 @@ h3 {
align-items: center;
gap: 14px;
padding: 11px 0;
border-top: 1px solid v-bind("theme.dividerColor");
border-top: 1px solid v-bind('theme.dividerColor');
}
.body {
@@ -109,7 +105,7 @@ h3 {
margin-left: auto;
font-size: var(--oj-fs-sec);
font-weight: 600;
color: v-bind("theme.primaryColorPressed");
color: v-bind('theme.primaryColorPressed');
white-space: nowrap;
}
@@ -117,7 +113,7 @@ h3 {
display: flex;
justify-content: space-between;
font-size: 12px;
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
font-variant-numeric: tabular-nums;
}
@@ -132,7 +128,7 @@ h3 {
}
.wide .item {
border-top: 1px solid v-bind("theme.dividerColor");
border-top: 1px solid v-bind('theme.dividerColor');
}
/* 手机:「还差什么」换到名字下面一行 */
@@ -1,10 +1,10 @@
<script setup lang="ts">
import { useThemeVars } from "naive-ui"
import { RARITY_LABEL } from "utils/constants"
import { parseTime } from "utils/functions"
import type { Achievement } from "utils/types"
import type { Series } from "../series"
import Medal from "./Medal.vue"
import { useThemeVars } from 'naive-ui'
import { RARITY_LABEL } from 'utils/constants'
import { parseTime } from 'utils/functions'
import type { Achievement } from 'utils/types'
import type { Series } from '../series'
import Medal from './Medal.vue'
/**
* 一条成就线:左边线名和现在的数,右边几档按门槛排在一根进度线上,下一档头上标「差几」。
@@ -53,8 +53,8 @@ function gap(item: Achievement) {
function when(item: Achievement) {
if (!item.unlocked) return `现在 ${props.series.value} ${props.series.unit}`
// 补发的不写日期:一次补发会给几百人盖上同一个时间戳
if (item.backfilled || !item.unlockTime) return "已拿到"
return `${parseTime(item.unlockTime, "M月D日")}拿到`
if (item.backfilled || !item.unlockTime) return '已拿到'
return `${parseTime(item.unlockTime, 'M月D日')}拿到`
}
function holders(item: Achievement) {
@@ -68,35 +68,19 @@ function holders(item: Achievement) {
<div class="label">
<span class="name">{{ series.label }}</span>
<span class="value">
<b>{{ series.streak ? "现在 " : "" }}{{ series.value }}</b>
<b>{{ series.streak ? '现在 ' : '' }}{{ series.value }}</b>
<small>{{ series.unit }}</small>
</span>
</div>
<div class="track" :style="{ height: `${size + 36}px` }">
<span
class="line"
:style="{ top: `${size / 2 - 2}px`, width: `${center(series.items.length - 1)}%` }"
></span>
<span class="line" :style="{ top: `${size / 2 - 2}px`, width: `${center(series.items.length - 1)}%` }"></span>
<span class="line done" :style="{ top: `${size / 2 - 2}px`, width: `${fill}%` }"></span>
<div
v-for="(item, i) in series.items"
:key="item.id"
class="tier"
:class="{ on: item.unlocked }"
:style="{ left: `${center(i)}%` }"
>
<div v-for="(item, i) in series.items" :key="item.id" class="tier" :class="{ on: item.unlocked }" :style="{ left: `${center(i)}%` }">
<n-tooltip :delay="150">
<template #trigger>
<span class="trigger">
<span v-if="gap(item)" class="gap" :style="{ bottom: `${size + 4}px` }">
差 {{ gap(item) }}
</span>
<Medal
:icon="item.icon"
:rarity="item.rarity"
:size="size"
:state="item.unlocked ? 'on' : 'off'"
/>
<span v-if="gap(item)" class="gap" :style="{ bottom: `${size + 4}px` }"> 差 {{ gap(item) }} </span>
<Medal :icon="item.icon" :rarity="item.rarity" :size="size" :state="item.unlocked ? 'on' : 'off'" />
</span>
</template>
<div class="tip">
@@ -129,7 +113,7 @@ function holders(item: Achievement) {
.name {
font-size: 13px;
color: v-bind("theme.textColor2");
color: v-bind('theme.textColor2');
white-space: nowrap;
}
@@ -142,7 +126,7 @@ function holders(item: Achievement) {
.value small {
margin-left: 3px;
font-size: 12px;
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
}
.track {
@@ -154,11 +138,11 @@ function holders(item: Achievement) {
left: 0;
height: 4px;
border-radius: 2px;
background: v-bind("theme.dividerColor");
background: v-bind('theme.dividerColor');
}
.line.done {
background: v-bind("theme.primaryColor");
background: v-bind('theme.primaryColor');
}
.tier {
@@ -188,7 +172,7 @@ function holders(item: Achievement) {
line-height: 16px;
font-weight: 600;
white-space: nowrap;
color: v-bind("theme.primaryColorPressed");
color: v-bind('theme.primaryColorPressed');
background: v-bind(gapBg);
}
@@ -197,18 +181,18 @@ function holders(item: Achievement) {
line-height: 15px;
text-align: center;
white-space: nowrap;
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
}
.tier.on .tier-name {
color: v-bind("theme.textColor1");
color: v-bind('theme.textColor1');
font-weight: 600;
}
.tier-at {
font-size: 11px;
line-height: 14px;
color: v-bind("theme.textColor3");
color: v-bind('theme.textColor3');
font-variant-numeric: tabular-nums;
}