feat: onShow静默刷新 + 群组预算双显 + TransactionItem优化
onShow 静默刷新(首次有loading,后续静默): - budget: 添加 initialLoaded 守卫,避免首次双重请求 - profile: 添加 onShow 刷新概览/预算/账单/群组 - group-manage: 添加 onShow 刷新群组列表 - category-manage: 添加 onShow 刷新分类列表 - add: 添加 onShow 刷新分类(可能新增了分类) 群组模式预算双显: - 服务端 GET /budget 群组模式额外返回 myAmount(本人预算) - 客户端 Budget 类型添加 myAmount 字段 - 预算页群组模式:群组总预算卡片(只读)+ 我的预算卡片(可编辑) - 个人模式保持原样 TransactionItem 群组模式优化: - 主图标始终显示分类图标(不再显示创建者头像) - 他人记录在昵称旁显示小头像(28rpx圆形)
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useCategoryStore } from '@/stores/category'
|
||||
import { useTransactionStore } from '@/stores/transaction'
|
||||
import { waitForReady } from '@/utils/app-ready'
|
||||
@@ -150,6 +151,11 @@ onMounted(async () => {
|
||||
}
|
||||
})
|
||||
|
||||
// 返回页面时刷新分类(可能新增了分类)
|
||||
onShow(() => {
|
||||
catStore.fetchCategories()
|
||||
})
|
||||
|
||||
function onDateChange(e: any) {
|
||||
selectedDate.value = e.detail.value
|
||||
}
|
||||
|
||||
@@ -12,27 +12,45 @@
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<!-- 当前预算预览 -->
|
||||
<view class="preview-card">
|
||||
<!-- 群组模式:群组总预算(只读) -->
|
||||
<view class="preview-card" v-if="groupStore.isGroupMode && !loading">
|
||||
<view class="preview-header">
|
||||
<text class="preview-label">本月预算</text>
|
||||
<text class="preview-label">群组预算</text>
|
||||
<text class="preview-month">{{ currentMonth }}</text>
|
||||
</view>
|
||||
<text class="preview-amount" v-if="!loading">
|
||||
<text class="preview-amount">
|
||||
{{ budget ? formatAmount(budget.amount) : '未设置' }}
|
||||
</text>
|
||||
<view class="preview-skeleton" v-else></view>
|
||||
<BudgetBar
|
||||
v-if="budget"
|
||||
:total="budget.amount"
|
||||
:used="monthExpense"
|
||||
:showLabel="true"
|
||||
/>
|
||||
<text class="preview-hint" v-else>群组成员均未设置预算</text>
|
||||
</view>
|
||||
|
||||
<!-- 我的预算 / 个人模式预算 -->
|
||||
<view class="preview-card">
|
||||
<view class="preview-header">
|
||||
<text class="preview-label">{{ groupStore.isGroupMode ? '我的预算' : '本月预算' }}</text>
|
||||
<text class="preview-month">{{ currentMonth }}</text>
|
||||
</view>
|
||||
<text class="preview-amount" v-if="!loading">
|
||||
{{ myBudgetAmount > 0 ? formatAmount(myBudgetAmount) : '未设置' }}
|
||||
</text>
|
||||
<view class="preview-skeleton" v-else></view>
|
||||
<BudgetBar
|
||||
v-if="myBudgetAmount > 0"
|
||||
:total="myBudgetAmount"
|
||||
:used="myExpense"
|
||||
:showLabel="true"
|
||||
/>
|
||||
<text class="preview-hint" v-else>设置预算,掌控开支</text>
|
||||
</view>
|
||||
|
||||
<!-- 快捷金额 -->
|
||||
<view class="section-title">快捷金额</view>
|
||||
<view class="section-title">{{ groupStore.isGroupMode ? '设置我的预算' : '快捷金额' }}</view>
|
||||
<view class="preset-grid">
|
||||
<view
|
||||
class="preset-item"
|
||||
@@ -65,6 +83,7 @@ import { ref, onMounted } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useBudgetStore } from '@/stores/budget'
|
||||
import { useStatsStore } from '@/stores/stats'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { waitForReady } from '@/utils/app-ready'
|
||||
import { formatAmount, getCurrentMonth } from '@/utils/format'
|
||||
import { statusBarHeight } from '@/utils/system'
|
||||
@@ -74,11 +93,15 @@ import Icon from '@/components/Icon/Icon.vue'
|
||||
|
||||
const budgetStore = useBudgetStore()
|
||||
const statsStore = useStatsStore()
|
||||
const groupStore = useGroupStore()
|
||||
|
||||
const currentMonth = getCurrentMonth()
|
||||
const budget = ref<any>(null)
|
||||
const monthExpense = ref(0)
|
||||
const myBudgetAmount = ref(0)
|
||||
const myExpense = ref(0)
|
||||
const loading = ref(true)
|
||||
const initialLoaded = ref(false)
|
||||
const amountStr = ref('')
|
||||
|
||||
const presets = [1000, 2000, 3000, 5000, 10000]
|
||||
@@ -87,6 +110,23 @@ function formatPreset(val: number) {
|
||||
return val >= 10000 ? (val / 10000) + '万' : val.toLocaleString()
|
||||
}
|
||||
|
||||
function syncBudgetData() {
|
||||
budget.value = budgetStore.budget
|
||||
monthExpense.value = statsStore.overview.expense
|
||||
// 群组模式用 myAmount,个人模式用 amount
|
||||
if (budget.value) {
|
||||
myBudgetAmount.value = groupStore.isGroupMode ? (budget.value.myAmount || 0) : budget.value.amount
|
||||
myExpense.value = groupStore.isGroupMode ? statsStore.overview.expense : statsStore.overview.expense
|
||||
} else {
|
||||
myBudgetAmount.value = 0
|
||||
myExpense.value = 0
|
||||
}
|
||||
// 预填输入框(个人预算)
|
||||
if (myBudgetAmount.value > 0) {
|
||||
amountStr.value = (myBudgetAmount.value / 100).toString()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await waitForReady()
|
||||
loading.value = true
|
||||
@@ -95,27 +135,24 @@ onMounted(async () => {
|
||||
budgetStore.fetchBudget(currentMonth),
|
||||
statsStore.fetchOverview(currentMonth)
|
||||
])
|
||||
budget.value = budgetStore.budget
|
||||
monthExpense.value = statsStore.overview.expense
|
||||
if (budget.value) {
|
||||
amountStr.value = (budget.value.amount / 100).toString()
|
||||
}
|
||||
syncBudgetData()
|
||||
} catch (e) {
|
||||
console.error('Budget page load error:', e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
initialLoaded.value = true
|
||||
}
|
||||
})
|
||||
|
||||
// 返回页面时刷新预算数据
|
||||
// 返回页面时静默刷新
|
||||
onShow(async () => {
|
||||
if (!initialLoaded.value) return
|
||||
try {
|
||||
await Promise.all([
|
||||
budgetStore.fetchBudget(currentMonth),
|
||||
statsStore.fetchOverview(currentMonth)
|
||||
])
|
||||
budget.value = budgetStore.budget
|
||||
monthExpense.value = statsStore.overview.expense
|
||||
syncBudgetData()
|
||||
} catch {}
|
||||
})
|
||||
|
||||
@@ -135,7 +172,7 @@ async function onConfirm() {
|
||||
}
|
||||
try {
|
||||
await budgetStore.setBudget(amount, currentMonth)
|
||||
budget.value = budgetStore.budget
|
||||
syncBudgetData()
|
||||
uni.showToast({ title: '预算已设置', icon: 'success' })
|
||||
setTimeout(() => uni.navigateBack(), 1500)
|
||||
} catch {
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useCategoryStore, type Category } from '@/stores/category'
|
||||
import { waitForReady } from '@/utils/app-ready'
|
||||
import { getCategoryTransactionCount } from '@/api/category'
|
||||
@@ -144,9 +145,17 @@ const migrateTargets = computed(() => {
|
||||
return currentCategories.value.filter(c => c.id !== deletingCat.value?.id)
|
||||
})
|
||||
|
||||
const initialLoaded = ref(false)
|
||||
|
||||
onMounted(async () => {
|
||||
await waitForReady()
|
||||
catStore.fetchCategories()
|
||||
await catStore.fetchCategories()
|
||||
initialLoaded.value = true
|
||||
})
|
||||
|
||||
// 返回页面时静默刷新
|
||||
onShow(() => {
|
||||
if (initialLoaded.value) catStore.fetchCategories()
|
||||
})
|
||||
|
||||
function goBack() {
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { waitForReady } from '@/utils/app-ready'
|
||||
import { statusBarHeight, capsuleRight } from '@/utils/system'
|
||||
@@ -86,10 +87,17 @@ const groupStore = useGroupStore()
|
||||
const newGroupName = ref('')
|
||||
const inviteCode = ref('')
|
||||
const saving = ref(false)
|
||||
const initialLoaded = ref(false)
|
||||
|
||||
onMounted(async () => {
|
||||
await waitForReady()
|
||||
groupStore.fetchGroups()
|
||||
await groupStore.fetchGroups()
|
||||
initialLoaded.value = true
|
||||
})
|
||||
|
||||
// 返回页面时静默刷新
|
||||
onShow(() => {
|
||||
if (initialLoaded.value) groupStore.fetchGroups()
|
||||
})
|
||||
|
||||
function goBack() {
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useTransactionStore } from '@/stores/transaction'
|
||||
import { useStatsStore } from '@/stores/stats'
|
||||
import { useBudgetStore } from '@/stores/budget'
|
||||
@@ -140,6 +141,7 @@ const budget = computed(() => budgetStore.budget)
|
||||
const loading = ref(true)
|
||||
const showAbout = ref(false)
|
||||
const showIdentity = ref(false)
|
||||
const initialLoaded = ref(false)
|
||||
|
||||
onMounted(async () => {
|
||||
await waitForReady()
|
||||
@@ -156,9 +158,23 @@ onMounted(async () => {
|
||||
console.error('Profile load error:', e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
initialLoaded.value = true
|
||||
}
|
||||
})
|
||||
|
||||
// 返回页面时静默刷新
|
||||
onShow(async () => {
|
||||
if (!initialLoaded.value) return
|
||||
try {
|
||||
await Promise.all([
|
||||
statsStore.fetchOverview(),
|
||||
budgetStore.fetchBudget(),
|
||||
txStore.fetchTransactions({ page: 1, pageSize: 1 }),
|
||||
groupStore.fetchGroups()
|
||||
])
|
||||
} catch {}
|
||||
})
|
||||
|
||||
function goBudget() {
|
||||
uni.navigateTo({ url: '/pages/budget/index' })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user