refactor(logs): update date filtering logic and improve UI for log entries
This commit is contained in:
+51
-57
@@ -1,18 +1,16 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<view class="status-bar" :style="{ height: navBarHeight + 'px' }"></view>
|
||||
|
||||
<view class="filters-sticky">
|
||||
<view class="filters" :style="{ top: navBarHeight + 'px' }">
|
||||
<view class="tabs">
|
||||
<view class="filters">
|
||||
<view class="date-filters">
|
||||
<view
|
||||
v-for="tab in tabs"
|
||||
:key="tab.value"
|
||||
class="tab"
|
||||
:class="{ 'tab-active': currentTab === tab.value }"
|
||||
@tap="currentTab = tab.value"
|
||||
v-for="option in dateFilters"
|
||||
:key="option.value"
|
||||
class="date-filter"
|
||||
:class="{ 'date-filter-active': currentDateFilter === option.value }"
|
||||
@tap="currentDateFilter = option.value"
|
||||
>
|
||||
{{ tab.label }}
|
||||
{{ option.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -45,7 +43,7 @@
|
||||
|
||||
<view class="section-head">
|
||||
<text class="section-label">时间记录</text>
|
||||
<text class="section-note">{{ currentTab === 'smoke' ? '仅看抽烟记录' : '按日期倒序' }}</text>
|
||||
<text class="section-note">{{ currentDateFilterLabel }} · 按日期倒序</text>
|
||||
</view>
|
||||
|
||||
<view v-if="logsStore.loading && logsStore.logs.length === 0" class="skeleton">
|
||||
@@ -162,14 +160,15 @@ import { useLogin } from '@/hooks/useLogin'
|
||||
|
||||
const { waitForLogin } = useLogin()
|
||||
const logsStore = useLogsStore()
|
||||
const navBarHeight = ref(0)
|
||||
|
||||
const tabs = [
|
||||
const dateFilters = [
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '抽烟记录', value: 'smoke' }
|
||||
{ label: '今天', value: 'today' },
|
||||
{ label: '近7天', value: 'week' },
|
||||
{ label: '本月', value: 'month' }
|
||||
]
|
||||
|
||||
const currentTab = ref('all')
|
||||
const currentDateFilter = ref('all')
|
||||
const showEditDialog = ref(false)
|
||||
const editType = ref('smoke')
|
||||
const editData = ref(null)
|
||||
@@ -177,11 +176,12 @@ const editingLogId = ref(null)
|
||||
|
||||
// 筛选后的记录
|
||||
const filteredLogs = computed(() => {
|
||||
const logs = logsStore.formattedLogs
|
||||
if (currentTab.value === 'all') {
|
||||
return logs
|
||||
}
|
||||
return logs.filter(log => log.type === currentTab.value)
|
||||
const logs = logsStore.formattedLogs.filter(log => log.type === 'smoke')
|
||||
return logs.filter(log => isInDateFilter(log.displayDate, currentDateFilter.value))
|
||||
})
|
||||
|
||||
const currentDateFilterLabel = computed(() => {
|
||||
return dateFilters.find(item => item.value === currentDateFilter.value)?.label || '全部'
|
||||
})
|
||||
|
||||
// 按日期分组
|
||||
@@ -218,6 +218,25 @@ function localDateStr(d) {
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
function isInDateFilter(dateStr, filter) {
|
||||
if (!dateStr || filter === 'all') return true
|
||||
const today = new Date()
|
||||
const target = new Date(`${dateStr}T00:00:00`)
|
||||
if (Number.isNaN(target.getTime())) return false
|
||||
const todayText = localDateStr(today)
|
||||
if (filter === 'today') return dateStr === todayText
|
||||
if (filter === 'week') {
|
||||
const start = new Date(today)
|
||||
start.setDate(today.getDate() - 6)
|
||||
start.setHours(0, 0, 0, 0)
|
||||
return target >= start && dateStr <= todayText
|
||||
}
|
||||
if (filter === 'month') {
|
||||
return target.getFullYear() === today.getFullYear() && target.getMonth() === today.getMonth()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 格式化分组标题
|
||||
function formatGroupTitle(dateStr) {
|
||||
if (!dateStr) return ''
|
||||
@@ -241,7 +260,7 @@ function formatGroupTitle(dateStr) {
|
||||
|
||||
// 下拉刷新
|
||||
async function onRefresh() {
|
||||
await logsStore.fetchLogs(true, currentTab.value)
|
||||
await logsStore.fetchLogs(true, 'smoke')
|
||||
}
|
||||
|
||||
// 上拉加载
|
||||
@@ -300,25 +319,13 @@ function handleDelete(log) {
|
||||
async function initPage() {
|
||||
try {
|
||||
await waitForLogin()
|
||||
await logsStore.fetchLogs(true, currentTab.value)
|
||||
await logsStore.fetchLogs(true, 'smoke')
|
||||
} catch (e) {
|
||||
console.error('initPage error:', e)
|
||||
}
|
||||
}
|
||||
|
||||
function setupNavBar() {
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
const statusBarH = systemInfo.statusBarHeight || 0
|
||||
try {
|
||||
const menuBtn = uni.getMenuButtonBoundingClientRect()
|
||||
navBarHeight.value = menuBtn.bottom + (menuBtn.top - statusBarH)
|
||||
} catch (e) {
|
||||
navBarHeight.value = statusBarH + 44
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setupNavBar()
|
||||
initPage()
|
||||
})
|
||||
|
||||
@@ -342,10 +349,6 @@ function levelLabel(level) {
|
||||
return '极强'
|
||||
}
|
||||
|
||||
watch(currentTab, async (value) => {
|
||||
await logsStore.fetchLogs(true, value)
|
||||
})
|
||||
|
||||
onShareAppMessage(() => {
|
||||
return {
|
||||
title: '戒烟助手 - 我的戒烟记录',
|
||||
@@ -365,32 +368,23 @@ onShareAppMessage(() => {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.filters-sticky {
|
||||
position: relative;
|
||||
height: 96rpx;
|
||||
height: 88rpx;
|
||||
flex-shrink: 0;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.filters {
|
||||
position: fixed;
|
||||
left: 32rpx;
|
||||
right: 32rpx;
|
||||
z-index: 50;
|
||||
padding-top: 8rpx;
|
||||
padding-bottom: 14rpx;
|
||||
background: rgba(246, 248, 246, 0.9);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 10rpx 0 12rpx;
|
||||
box-sizing: border-box;
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
backdrop-filter: blur(14px);
|
||||
}
|
||||
|
||||
.tabs {
|
||||
.date-filters {
|
||||
display: flex;
|
||||
gap: 8rpx;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
border: 1rpx solid rgba(226, 232, 240, 0.82);
|
||||
border-radius: 22rpx;
|
||||
@@ -399,17 +393,17 @@ onShareAppMessage(() => {
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.tab {
|
||||
.date-filter {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 15rpx 0;
|
||||
padding: 14rpx 0;
|
||||
border-radius: 18rpx;
|
||||
font-size: 25rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 900;
|
||||
color: #64748B;
|
||||
}
|
||||
|
||||
.tab-active {
|
||||
.date-filter-active {
|
||||
background: linear-gradient(135deg, #10B981, #06B6D4);
|
||||
color: #FFFFFF;
|
||||
box-shadow: 0 8rpx 18rpx rgba(16, 185, 129, 0.16);
|
||||
|
||||
@@ -142,6 +142,7 @@ const profileStore = useProfileStore()
|
||||
const userStore = useUserStore()
|
||||
const { waitForLogin } = useLogin()
|
||||
const { proxy } = getCurrentInstance()
|
||||
const MEDALLION_IMAGE = '../../static/achievements/theme-medallion.png'
|
||||
|
||||
const navBarHeight = ref(0)
|
||||
const latestNSTIResult = ref(null)
|
||||
@@ -529,7 +530,7 @@ async function handleSaveAchievementPoster() {
|
||||
await fetchPosterData()
|
||||
const [qrPath, medallionInfo] = await Promise.all([
|
||||
downloadMiniProgramTestCode({ path: 'pages/index/index', width: 240 }).catch(() => ''),
|
||||
getImageInfo('/static/achievements/theme-medallion.png')
|
||||
getImageInfo(MEDALLION_IMAGE)
|
||||
])
|
||||
const posterPath = await drawAchievementPoster(qrPath, medallionInfo)
|
||||
await savePosterToAlbum(posterPath)
|
||||
|
||||
Reference in New Issue
Block a user