Files
smt/stores/logs.js
T
root 50109b3a96 fix: 修复抽烟记录第一条不显示距离上次时间的问题
- 第一条记录现在显示距离当前时间的间隔
- 后续记录显示距离上一条记录的间隔

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:24:57 +08:00

314 lines
7.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineStore } from 'pinia'
import * as api from '@/api'
export const useLogsStore = defineStore('logs', {
state: () => ({
logs: [], // 记录列表
total: 0, // 总条数
page: 1, // 当前页
pageSize: 20, // 每页数量
hasMore: true, // 是否有更多
loading: false, // 加载状态
refreshing: false, // 刷新状态
queryType: 'all' // 当前筛选类型
}),
getters: {
// 按日期分组
groupedByDate: (state) => {
const groups = {}
state.logs.forEach(log => {
const date = log.smoke_time?.split('T')[0] || ''
if (!groups[date]) {
groups[date] = []
}
groups[date].push(log)
})
return groups
},
// 抽烟记录数量
smokeCount: (state) => {
return state.logs.filter(log => normalizeLogType(log) === 'smoke').length
},
// 忍住记录数量
resistedCount: (state) => {
return state.logs.filter(log => normalizeLogType(log) === 'resisted').length
},
// 格式化记录列表(按时间倒序,最新的在前)
formattedLogs: (state) => {
if (!state.logs || state.logs.length === 0) {
return []
}
// 获取时间戳的辅助函数
const getTime = (log) => {
if (log.smoke_at) {
return new Date(log.smoke_at).getTime()
}
if (log.smoke_time) {
return new Date(log.smoke_time).getTime()
}
if (log.createtime) {
return typeof log.createtime === 'number' ? log.createtime * 1000 : new Date(log.createtime).getTime()
}
return 0
}
// 先按时间倒序排序
const sortedLogs = [...state.logs].sort((a, b) => {
const timeA = getTime(a)
const timeB = getTime(b)
return timeB - timeA // 倒序:最新的在前
})
return sortedLogs.map((log, index) => {
const type = normalizeLogType(log)
// 计算间隔时间
let interval = ''
const currentTime = getTime(log)
if (index === 0) {
// 第一条记录:显示距离当前时间的间隔
const now = Date.now()
const diff = now - currentTime
if (diff > 0) {
const hours = Math.floor(diff / (1000 * 60 * 60))
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
if (hours > 0) {
interval = `${hours}小时${minutes}`
} else if (minutes > 0) {
interval = `${minutes}分钟`
} else {
interval = '刚刚'
}
}
} else {
// 后续记录:显示距离上一条记录的间隔
const prevTime = getTime(sortedLogs[index - 1])
const diff = prevTime - currentTime
if (diff > 0) {
const hours = Math.floor(diff / (1000 * 60 * 60))
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
if (hours > 0) {
interval = `${hours}小时${minutes}`
} else if (minutes > 0) {
interval = `${minutes}分钟`
} else {
interval = '刚刚'
}
}
}
// 获取显示日期(用本地日期,避免 UTC 导致差一天)
let displayDate = ''
if (log.smoke_time) {
displayDate = log.smoke_time.split('T')[0]
} else if (log.createtime) {
const date = typeof log.createtime === 'number'
? new Date(log.createtime * 1000)
: new Date(log.createtime)
const y = date.getFullYear()
const m = String(date.getMonth() + 1).padStart(2, '0')
const d = String(date.getDate()).padStart(2, '0')
displayDate = `${y}-${m}-${d}`
}
return {
...log,
type,
interval,
displayTime: formatLogTime(log.smoke_at || log.smoke_time || log.createtime),
displayDate
}
})
}
},
actions: {
// 获取记录列表
async fetchLogs(refresh = false, type) {
if (this.loading) return
this.loading = true
if (refresh) {
this.refreshing = true
this.page = 1
this.logs = []
this.queryType = type || 'all'
}
try {
const res = await api.getLogs({
page: this.page,
page_size: this.pageSize,
type: this.queryType
})
if (res.data) {
let newLogs = res.data.items || []
// 按时间倒序排序(最新的在前)
newLogs = newLogs.sort((a, b) => {
const timeA = new Date(a.smoke_at || a.smoke_time || (a.createtime ? a.createtime * 1000 : 0)).getTime()
const timeB = new Date(b.smoke_at || b.smoke_time || (b.createtime ? b.createtime * 1000 : 0)).getTime()
return timeB - timeA
})
if (refresh) {
this.logs = newLogs
} else {
// 合并并去重(按 id
const existingIds = new Set(this.logs.map(log => log.id))
const uniqueNewLogs = newLogs.filter(log => !existingIds.has(log.id))
this.logs = [...this.logs, ...uniqueNewLogs]
// 再次排序确保顺序
this.logs.sort((a, b) => {
const timeA = new Date(a.smoke_at || a.smoke_time || (a.createtime ? a.createtime * 1000 : 0)).getTime()
const timeB = new Date(b.smoke_at || b.smoke_time || (b.createtime ? b.createtime * 1000 : 0)).getTime()
return timeB - timeA
})
}
this.total = res.data.total || 0
this.hasMore = newLogs.length >= this.pageSize
}
} catch (e) {
console.error('fetchLogs error:', e)
uni.showToast({
title: '加载失败',
icon: 'none'
})
} finally {
this.loading = false
this.refreshing = false
}
},
// 加载更多
async loadMore() {
if (!this.hasMore || this.loading) return
this.page++
await this.fetchLogs(false)
},
// 删除记录
async deleteLog(id) {
try {
await api.deleteLog(id)
// 乐观更新:先从列表中移除
const index = this.logs.findIndex(log => log.id === id)
if (index > -1) {
this.logs.splice(index, 1)
this.total--
}
uni.showToast({
title: '删除成功',
icon: 'success'
})
return true
} catch (e) {
console.error('deleteLog error:', e)
uni.showToast({
title: '删除失败',
icon: 'none'
})
// 失败时刷新列表恢复数据
await this.fetchLogs(true)
return false
}
},
// 更新记录
async updateLog(id, data) {
try {
await api.updateLog(id, data)
// 更新本地数据
const index = this.logs.findIndex(log => log.id === id)
if (index > -1) {
this.logs[index] = {
...this.logs[index],
...data
}
}
uni.showToast({
title: '更新成功',
icon: 'success'
})
return true
} catch (e) {
console.error('updateLog error:', e)
uni.showToast({
title: '更新失败',
icon: 'none'
})
return false
}
},
// 清空列表
clearLogs() {
this.logs = []
this.total = 0
this.page = 1
this.hasMore = true
this.queryType = 'all'
}
}
})
// 辅助函数:格式化时间
function formatLogTime(timeStr) {
if (!timeStr) return '--:--'
let date
if (typeof timeStr === 'number') {
// 如果是时间戳(秒)
date = new Date(timeStr * 1000)
} else if (typeof timeStr === 'string') {
// 如果是字符串
date = new Date(timeStr)
} else {
return '--:--'
}
// 检查日期是否有效
if (isNaN(date.getTime())) {
return '--:--'
}
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
return `${hours}:${minutes}`
}
function normalizeLogType(log) {
const rawType = log?.type
if (typeof rawType === 'string') {
const value = rawType.toLowerCase()
if (value === 'resisted' || value === 'resist') return 'resisted'
if (value === 'smoke' || value === 'log_smoke') return 'smoke'
}
if (typeof rawType === 'number') {
if (rawType === 0) return 'resisted'
if (rawType === 1) return 'smoke'
}
if (log?.num === 0) return 'resisted'
return 'smoke'
}