feat: 用户体验优化 — 首页加载/继续记账/登录恢复

## 首页加载优化
- 分级加载:首屏只请求 overview + recentTx(2个请求)
- 数据新鲜度:30秒内不重复请求
- 次要数据异步加载:budget + todayData
- 非关键数据后台加载:userInfo + notifications

## 继续记账功能
- SaveSuccess 组件新增「继续记一笔」按钮
- 新增模式显示继续按钮,编辑模式自动返回
- 继续记账时保留分类和日期,清空金额和备注

## 登录失败恢复
- 登录重试机制:最多3次,间隔1秒
- 失败后显示提示而非静默等待

## 群组账单逻辑修正
- 群组账单 = 所有群组成员的个人账单之和
- 修改查询:WHERE user_id IN (群组成员)
This commit is contained in:
wangxiaogang
2026-06-07 17:49:46 +08:00
parent bd7af8e512
commit 1abc55323d
11 changed files with 183 additions and 87 deletions

View File

@@ -202,23 +202,37 @@ function openLink(url: string) {
// #endif
}
async function loadData(silent = false) {
// 数据新鲜度控制30秒内不重复请求
let lastLoadTime = 0
const CACHE_TTL = 30000
async function loadData(silent = false, force = false) {
await waitForReady()
// 数据新鲜度判断30秒内不重复请求
if (!force && silent && Date.now() - lastLoadTime < CACHE_TTL) {
return
}
try {
if (!silent) loading.value = true
loadError.value = false
const now = new Date()
const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
// 关键数据:任一失败则显示错误
// 第一级首屏关键数据2个请求
await Promise.all([
statsStore.fetchOverview(),
budgetStore.fetchBudget(),
txStore.fetchTransactions({ page: 1 }),
fetchTodayData(today)
txStore.fetchTransactions({ page: 1 })
])
recentTx.value = txStore.transactions.slice(0, 5)
lastLoadTime = Date.now()
// 非关键数据:失败不影响页面显示
// 第二级:次要数据(异步,不阻塞首屏)
Promise.all([
budgetStore.fetchBudget(),
fetchTodayData()
]).catch(() => {})
// 第三级:非关键数据
Promise.allSettled([
userStore.fetchUserInfo(),
notifStore.fetchUnreadCount(),
@@ -232,8 +246,10 @@ async function loadData(silent = false) {
}
}
async function fetchTodayData(today: string) {
async function fetchTodayData() {
try {
const now = new Date()
const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
const data = await getOverview({ startDate: today, endDate: today, group_id: groupStore.currentGroupId })
todayExpense.value = data.expense || 0
todayIncome.value = data.income || 0
@@ -252,11 +268,11 @@ onMounted(() => {
// Refresh data when returning from other pages (e.g., after adding a transaction)
onShow(() => {
if (initialLoaded.value && !loading.value) loadData(true)
if (initialLoaded.value && !loading.value) loadData(true, false)
})
onPullDownRefresh(() => {
loadData().finally(() => uni.stopPullDownRefresh())
loadData(false, true).finally(() => uni.stopPullDownRefresh())
})
function goAdd(type: string) {