fix: keep today habits visible while refreshing
ci / docker (push) Successful in 5m48s

This commit is contained in:
2026-09-07 17:27:24 +08:00
parent 3772b56617
commit 5d564b0269
4 changed files with 41 additions and 8 deletions
+16 -7
View File
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
import { Activity, ArchiveRestore, Check, Download, FileJson, LogOut, RefreshCw, Trash2, Upload, X } from 'lucide-vue-next'
import { dateKey, habitButtonValue, isHabitComplete, isHabitScheduledToday, mergePage, nextHabitSwipeValue, previousHabitSwipeValue, shouldToggleRowSwipe } from './lib/mvp-utils'
import { dateKey, habitButtonValue, isHabitComplete, isHabitScheduledToday, mergePage, nextHabitSwipeValue, previousHabitSwipeValue, readHabitGridCache, shouldToggleRowSwipe, writeHabitGridCache } from './lib/mvp-utils'
import { csrfHeader } from './lib/csrf'
type View = 'habits' | 'today-habits' | 'settings'
@@ -233,10 +233,20 @@ function refreshHabitDay() {
}
}
async function loadHabits() {
await safe(async () => {
const data = await request(`/habits/grid?week=${dateKey(new Date())}`) as { habits?: Habit[] }
const week = dateKey(new Date())
const cached = readHabitGridCache<Habit>(week)
if (cached) habits.value = cached
if (!cached) busy.value = true
error.value = ''
try {
const data = await request(`/habits/grid?week=${week}`) as { habits?: Habit[] }
habits.value = data.habits ?? []
})
writeHabitGridCache(week, habits.value)
} catch (e) {
error.value = e instanceof Error ? e.message : '请求失败'
} finally {
if (!cached) busy.value = false
}
}
async function loadSettings() {
await safe(async () => {
@@ -302,7 +312,7 @@ onBeforeUnmount(() => {
</header>
<!-- 今日习惯只展示今天该做的习惯复用正式习惯行样式 -->
<div v-if="view === 'today-habits' && !busy" class="habit-list today-habit-list">
<div v-if="view === 'today-habits' && (habits.length || !busy)" class="habit-list today-habit-list">
<div class="habit-toolbar habit-toolbar-today"><label><input v-model="hideCompletedHabits" type="checkbox"> 隐藏已完成</label></div>
<article v-for="h in visibleTodayHabits" :key="h.id" class="habit-row swipeable" :class="{ done: isDone(h, todayKey), ready: Math.abs(habitSwipeOffsets[h.id] ?? 0) >= 64 }" :style="{ '--swipe-x': `${habitSwipeOffsets[h.id] ?? 0}px` }" @pointerdown="startHabitPointer(h, $event)" @pointermove="moveHabitPointer(h, $event)" @pointerup="finishHabitPointer(h, $event)" @pointercancel="cancelHabitPointer(h)" @touchstart.passive="startHabitSwipe(h, $event)" @touchmove.passive="moveHabitSwipe(h, $event)" @touchend="finishHabitSwipe(h, $event)" @touchcancel="cancelHabitSwipe(h)">
<button class="task-check habit-check" :aria-label="isDone(h, todayKey) ? `减少${h.name}一次` : `完成${h.name}一次`" :aria-pressed="isDone(h, todayKey)" @click.stop="toggleHabitFromButton(h)"><span class="task-check-mark"><Check v-if="isDone(h, todayKey)" /></span></button>
@@ -310,9 +320,8 @@ onBeforeUnmount(() => {
<span><span class="habit-name">{{ h.name }}</span><small v-if="habitProgressText(h)">{{ habitProgressText(h) }}</small></span>
</div>
</article>
<div v-if="!visibleTodayHabits.length" class="empty-panel today-empty-panel"><span>{{ hideCompletedHabits && todayHabits.length ? '已完成的习惯已隐藏。' : '今天没有安排习惯,轻松一下吧。' }}</span><button v-if="!hideCompletedHabits || !todayHabits.length" class="soft-button empty-action" @click="openHabitComposer"><Check/>添加习惯</button></div>
<div v-if="!visibleTodayHabits.length && !busy" class="empty-panel today-empty-panel"><span>{{ hideCompletedHabits && todayHabits.length ? '已完成的习惯已隐藏。' : '今天没有安排习惯,轻松一下吧。' }}</span><button v-if="!hideCompletedHabits || !todayHabits.length" class="soft-button empty-action" @click="openHabitComposer"><Check/>添加习惯</button></div>
</div>
<div v-else-if="view === 'today-habits' && busy" class="empty-panel">加载中</div>
<!-- 完整习惯列表 -->
<Transition name="task-compose">