This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { Activity, ArchiveRestore, Download, FileJson, LogOut, Plus, RefreshCw, Trash2, Upload } from 'lucide-vue-next'
|
||||
import { dateKey, isHabitComplete, mergePage, numericHabitInputValue, shouldToggleRowSwipe } from './lib/mvp-utils'
|
||||
import { csrfHeader } from './lib/csrf'
|
||||
@@ -30,6 +30,7 @@ const numericValues = ref<Record<string, number | string>>({})
|
||||
const todayKey = ref(dateKey(new Date()))
|
||||
const habitSwipeStart = ref<{ id: string; x: number; y: number } | null>(null)
|
||||
const habitSwipeOffsets = ref<Record<string, number>>({})
|
||||
const todayHabits = computed(() => habits.value.filter((item) => item.kind === 'boolean' || (item.cells ?? []).some((cell) => cell.day === todayKey.value && cell.scheduled)))
|
||||
let dayRolloverTimer: ReturnType<typeof setInterval> | undefined
|
||||
|
||||
function formatErrorMessage(detail: unknown): string {
|
||||
@@ -264,17 +265,28 @@ onBeforeUnmount(() => {
|
||||
|
||||
<!-- 习惯(TickTick 风格:一次只操作一个习惯,不再逐格小按钮误触) -->
|
||||
<template v-if="view === 'habits' || view === 'today-habits'">
|
||||
<header class="view-intro">
|
||||
<div><small>{{ view === 'today-habits' ? '今天习惯单独看,一眼就知道还差什么' : '把想坚持的事,变成每天的日常' }}</small><h2>{{ view === 'today-habits' ? '今天的习惯' : '习惯' }}</h2></div>
|
||||
<header v-if="view === 'habits'" class="view-intro">
|
||||
<div><small>把想坚持的事,变成每天的日常</small><h2>习惯</h2></div>
|
||||
<button class="soft-button" @click="loadHabits"><RefreshCw />刷新</button>
|
||||
</header>
|
||||
|
||||
<!-- 今日习惯:只展示“今天该做”的习惯 -->
|
||||
<div v-if="view === 'today-habits' && !busy" class="today-strip">
|
||||
<template v-for="h in habits.filter((item) => item.kind === 'boolean' ? !isDone(item, todayKey) : (item.cells ?? []).find((cell) => cell.day === todayKey && cell.scheduled) !== undefined)" :key="h.id">
|
||||
<button class="today-chip" :class="{ done: isDone(h, todayKey) }" :aria-label="isDone(h, todayKey) ? `完成${h.name}打卡` : `打卡${h.name}`" @click="toggleHabitFromButton(h)"><Repeat2 />{{ h.name }}</button>
|
||||
</template>
|
||||
<div v-if="!habits.some((item) => item.kind === 'boolean' ? !isDone(item, todayKey) : (item.cells ?? []).find((cell) => cell.day === todayKey && cell.scheduled) !== undefined)" class="empty-panel">今天的习惯都完成了 🎉</div>
|
||||
<!-- 今日习惯:只展示“今天该做”的习惯,复用正式习惯行样式 -->
|
||||
<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" :class="{ done: isDone(h, todayKey), swipeable: h.kind !== 'numeric', 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` }" @touchstart.passive="startHabitSwipe(h, $event)" @touchmove.passive="moveHabitSwipe(h, $event)" @touchend="finishHabitSwipe(h, $event)" @touchcancel="cancelHabitSwipe(h)">
|
||||
<span v-if="h.kind !== 'numeric'" class="swipe-bg" :class="{ cancel: isDone(h, todayKey) }">{{ isDone(h, todayKey) ? '↩ 未完成' : '✓ 打卡' }}</span>
|
||||
<div v-if="h.kind !== 'numeric'" class="habit-main">
|
||||
<span><span class="habit-name">{{ h.name }}</span><small>{{ isDone(h, todayKey) ? '今天已完成 · 左滑取消' : '右滑整行打卡' }}</small></span>
|
||||
<button class="habit-swipe-hint" :aria-label="isDone(h, todayKey) ? `取消${h.name}今天的打卡` : `完成${h.name}今天的打卡`" :aria-pressed="isDone(h, todayKey)" @click.stop="toggleHabitFromButton(h)">{{ isDone(h, todayKey) ? '已完成' : '打卡' }}</button>
|
||||
</div>
|
||||
<div v-else class="habit-main numeric-habit">
|
||||
<span><span class="habit-name">{{ h.name }}</span><small>今天 {{ logFor(h, todayKey)?.value || 0 }} / {{ h.target || 1 }}{{ h.unit || '' }}</small></span>
|
||||
<span class="numeric-action">
|
||||
<input v-model.number="numericValues[h.id]" type="number" min="0" :max="h.max_value ?? undefined" step="any" :placeholder="String(h.target || 1)" :aria-label="`${h.name}今日数值`">
|
||||
<button class="soft-button" @click="recordNumeric(h, todayKey)">记录</button>
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
<div v-if="!todayHabits.length" class="empty-panel">今天没有安排习惯,轻松一下吧。</div>
|
||||
</div>
|
||||
<div v-else-if="view === 'today-habits' && busy" class="empty-panel">加载中…</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user