This commit is contained in:
@@ -117,16 +117,29 @@ function habitProgressText(h: Habit) {
|
||||
return `${Number(logFor(h, todayKey.value)?.value ?? 0)} / ${h.target ?? 1}`
|
||||
}
|
||||
|
||||
function setLocalHabitValue(h: Habit, next: number | boolean) {
|
||||
habits.value = habits.value.map((item) => item.id !== h.id
|
||||
? item
|
||||
: {
|
||||
...item,
|
||||
cells: (item.cells ?? []).map((cell) => cell.day === todayKey.value ? { ...cell, value: next } : cell),
|
||||
})
|
||||
}
|
||||
|
||||
async function applyHabitSwipe(h: Habit, deltaX: number) {
|
||||
const current = logFor(h, todayKey.value)?.value
|
||||
const next = deltaX > 0
|
||||
? nextHabitSwipeValue(h.kind, current, h.target ?? 1)
|
||||
: previousHabitSwipeValue(h.kind, current)
|
||||
await safe(async () => {
|
||||
const previous = current ?? 0
|
||||
setLocalHabitValue(h, next)
|
||||
try {
|
||||
await request(`/habits/${h.id}/logs/${todayKey.value}`, { method: 'PUT', body: JSON.stringify({ value: next }) })
|
||||
await loadHabits()
|
||||
emit('notice', next > Number(current ?? 0) ? '已记录一次 🎉' : '已减少一次')
|
||||
})
|
||||
emit('notice', next > Number(previous) ? '已记录一次 🎉' : '已减少一次')
|
||||
} catch (e) {
|
||||
setLocalHabitValue(h, previous)
|
||||
error.value = e instanceof Error ? e.message : '请求失败'
|
||||
}
|
||||
}
|
||||
|
||||
async function finishHabitSwipe(h: Habit, event: TouchEvent) {
|
||||
@@ -285,8 +298,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<!-- 今日习惯:只展示“今天该做”的习惯,复用正式习惯行样式 -->
|
||||
<div v-if="view === 'today-habits' && !busy" class="habit-list today-habit-list">
|
||||
<article v-for="h in todayHabits" :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`, '--swipe-width': `${Math.abs(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)">
|
||||
<span class="swipe-bg" :class="{ cancel: isDone(h, todayKey) }">{{ isDone(h, todayKey) ? (h.kind === 'numeric' ? '− 一次' : '↩ 未完成') : (h.kind === 'numeric' ? '+ 一次' : '✓ 打卡') }}</span>
|
||||
<article v-for="h in todayHabits" :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)">
|
||||
<div class="habit-main">
|
||||
<span><span class="habit-name">{{ h.name }}</span><small v-if="habitProgressText(h)">{{ habitProgressText(h) }}</small></span>
|
||||
<button class="sr-only" :aria-label="isDone(h, todayKey) ? `减少${h.name}一次` : `完成${h.name}一次`" @click.stop="toggleHabitFromButton(h)">切换习惯状态</button>
|
||||
@@ -311,8 +323,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<!-- 习惯列表支持整行滑动记录。 -->
|
||||
<div v-if="view === 'habits'" class="habit-list">
|
||||
<article v-for="h in habits" :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`, '--swipe-width': `${Math.abs(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)">
|
||||
<span class="swipe-bg" :class="{ cancel: isDone(h, todayKey) }">{{ isDone(h, todayKey) ? (h.kind === 'numeric' ? '− 一次' : '↩ 未完成') : (h.kind === 'numeric' ? '+ 一次' : '✓ 打卡') }}</span>
|
||||
<article v-for="h in habits" :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)">
|
||||
<div class="habit-main">
|
||||
<span><span class="habit-name">{{ h.name }}</span><small v-if="habitProgressText(h)">{{ habitProgressText(h) }}</small></span>
|
||||
<button class="sr-only" :aria-label="isDone(h, todayKey) ? `减少${h.name}一次` : `完成${h.name}一次`" :aria-pressed="isDone(h, todayKey)" @click.stop="toggleHabitFromButton(h)">切换习惯状态</button>
|
||||
|
||||
Reference in New Issue
Block a user