|
|
@ -105,6 +105,12 @@ onMounted(() => { |
|
|
loadMissions() |
|
|
loadMissions() |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const todayProgressPercent = computed(() => { |
|
|
|
|
|
const { claimed, total } = todayStats.value |
|
|
|
|
|
if (!total || total <= 0) return 0 |
|
|
|
|
|
return Math.min(100, Math.round((claimed / total) * 100)) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
const activeMissions = computed(() => missions.value.filter(m => !m.isFromYesterday)) |
|
|
const activeMissions = computed(() => missions.value.filter(m => !m.isFromYesterday)) |
|
|
const hasAnyMissions = computed(() => activeMissions.value.length > 0) |
|
|
const hasAnyMissions = computed(() => activeMissions.value.length > 0) |
|
|
|
|
|
|
|
|
@ -321,6 +327,16 @@ const MissionCardContent = defineComponent({ |
|
|
<div v-else class="missions-content"> |
|
|
<div v-else class="missions-content"> |
|
|
<div v-if="activeMissions.length > 0" class="stats-bar"> |
|
|
<div v-if="activeMissions.length > 0" class="stats-bar"> |
|
|
<span class="stats-text">今日进度: {{ todayStats.claimed }}/{{ todayStats.total }}</span> |
|
|
<span class="stats-text">今日进度: {{ todayStats.claimed }}/{{ todayStats.total }}</span> |
|
|
|
|
|
<div |
|
|
|
|
|
class="stats-progress-track" |
|
|
|
|
|
role="progressbar" |
|
|
|
|
|
:aria-valuenow="todayStats.claimed" |
|
|
|
|
|
:aria-valuemin="0" |
|
|
|
|
|
:aria-valuemax="todayStats.total" |
|
|
|
|
|
:aria-label="`今日已领取 ${todayStats.claimed} / ${todayStats.total}`" |
|
|
|
|
|
> |
|
|
|
|
|
<div class="stats-progress-fill" :style="{ width: `${todayProgressPercent}%` }" /> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div v-if="hasAnyMissions" class="mission-list"> |
|
|
<div v-if="hasAnyMissions" class="mission-list"> |
|
|
@ -442,6 +458,9 @@ const MissionCardContent = defineComponent({ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.stats-bar { |
|
|
.stats-bar { |
|
|
|
|
|
display: flex; |
|
|
|
|
|
flex-direction: column; |
|
|
|
|
|
gap: 10px; |
|
|
background: rgba(255, 255, 255, 0.05); |
|
|
background: rgba(255, 255, 255, 0.05); |
|
|
border: 1px solid rgba(255, 255, 255, 0.1); |
|
|
border: 1px solid rgba(255, 255, 255, 0.1); |
|
|
border-radius: 8px; |
|
|
border-radius: 8px; |
|
|
@ -450,10 +469,27 @@ const MissionCardContent = defineComponent({ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.stats-text { |
|
|
.stats-text { |
|
|
color: #888888; |
|
|
color: #aaaaaa; |
|
|
font-size: 0.9rem; |
|
|
font-size: 0.9rem; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.stats-progress-track { |
|
|
|
|
|
width: 100%; |
|
|
|
|
|
height: 10px; |
|
|
|
|
|
border-radius: 999px; |
|
|
|
|
|
background: rgba(0, 0, 0, 0.35); |
|
|
|
|
|
overflow: hidden; |
|
|
|
|
|
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.stats-progress-fill { |
|
|
|
|
|
height: 100%; |
|
|
|
|
|
min-width: 0; |
|
|
|
|
|
border-radius: 999px; |
|
|
|
|
|
background: linear-gradient(90deg, #16a34a, #22c55e 45%, #4ade80); |
|
|
|
|
|
transition: width 0.4s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.mission-list { |
|
|
.mission-list { |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
flex-direction: column; |
|
|
|