Files
smt/stores/logs.js
T

292 lines
7.1 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)
// 计算间隔时间:当前记录与上一条记录的间隔(上一条是 index-1,因为已倒序)
let interval = ''
if (index > 0) {
const currentTime = getTime(log)
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 = '刚刚'
}
}
}
// 获取显示日期
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)
displayDate = date.toISOString().split('T')[0]
}
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'
}