fix: TransactionItem小头像+预算页双显+账单静默刷新

TransactionItem:
- meta 区域改为 view+flex 布局,小头像作为独立元素渲染
- creator-tag 容器包裹头像+昵称,小程序端 image 不嵌套在 text 内

预算页:
- 群组模式顶部显示概览行(群组预算 | 我的预算)
- 下方显示「设置我的预算」卡片,编辑作用于个人预算
- 个人模式保持原样

账单页:
- loadTx 添加 silent 参数,静默刷新时不清空列表
- onShow 调用 loadTx(true, true) 避免骨架屏闪烁
This commit is contained in:
2026-06-04 18:10:25 +08:00
parent 8bd4af9b9a
commit 5417821906
3 changed files with 82 additions and 47 deletions

View File

@@ -17,12 +17,14 @@
/>
<view class="info">
<text class="name">{{ item.note || item.category_name || '未分类' }}</text>
<text class="meta">
<image v-if="isOtherCreator && creatorAvatarUrl" :src="creatorAvatarUrl" class="creator-mini-avatar" mode="aspectFill" />
<text v-else-if="isOtherCreator" class="creator-mini-initial">{{ item.creator_nickname?.[0] }}</text>
<text v-if="isOtherCreator" class="creator-name">{{ item.creator_nickname }} · </text>
{{ item.category_name || '未分类' }}{{ hideDate ? '' : ' · ' + formatDate(item.date) }}
</text>
<view class="meta">
<view v-if="isOtherCreator" class="creator-tag">
<image v-if="creatorAvatarUrl" :src="creatorAvatarUrl" class="creator-mini-avatar" mode="aspectFill" />
<text v-else class="creator-mini-initial">{{ item.creator_nickname?.[0] }}</text>
<text class="creator-name">{{ item.creator_nickname }}</text>
</view>
<text>{{ (isOtherCreator ? ' · ' : '') + (item.category_name || '未分类') }}{{ hideDate ? '' : ' · ' + formatDate(item.date) }}</text>
</view>
</view>
<text class="amount" :class="item.type">{{ item.type === 'expense' ? '-' : '+' }}{{ formatAmount(item.amount) }}</text>
</view>
@@ -148,16 +150,22 @@ function onTouchEnd() {
}
}
.creator-tag {
margin-right: 4rpx;
display: inline;
}
.creator-mini-avatar {
width: 28rpx;
height: 28rpx;
border-radius: 50%;
vertical-align: middle;
margin-right: 4rpx;
position: relative;
top: 4rpx;
}
.creator-mini-initial {
display: inline-flex;
display: flex;
width: 28rpx;
height: 28rpx;
border-radius: 50%;
@@ -166,8 +174,7 @@ function onTouchEnd() {
color: #FF8C69;
align-items: center;
justify-content: center;
vertical-align: middle;
margin-right: 4rpx;
flex-shrink: 0;
}
.info {

View File

@@ -122,7 +122,7 @@ onMounted(async () => {
// 静默刷新(切换群组/返回时)
onShow(() => {
if (initialLoaded.value) loadTx(true)
if (initialLoaded.value) loadTx(true, true)
})
function switchFilter(type: string) {
@@ -130,10 +130,10 @@ function switchFilter(type: string) {
loadTx(true)
}
async function loadTx(reset = false) {
async function loadTx(reset = false, silent = false) {
if (reset) {
page.value = 1
txList.value = []
if (!silent) txList.value = []
}
const seq = ++loadSeq
const params: any = { page: page.value, pageSize }

View File

@@ -12,45 +12,40 @@
</view>
<view class="content">
<!-- 群组模式群组总预算只读 -->
<view class="preview-card" v-if="groupStore.isGroupMode && !loading">
<view class="preview-header">
<text class="preview-label">群组预算</text>
<text class="preview-month">{{ currentMonth }}</text>
<!-- 群组模式顶部概览 -->
<view class="overview-row" v-if="groupStore.isGroupMode && !loading">
<view class="overview-item">
<text class="overview-label">群组预算</text>
<text class="overview-value">{{ budget ? formatAmount(budget.amount) : '未设置' }}</text>
</view>
<view class="overview-divider"></view>
<view class="overview-item">
<text class="overview-label">我的预算</text>
<text class="overview-value highlight">{{ budgetAmount > 0 ? formatAmount(budgetAmount) : '未设置' }}</text>
</view>
<text class="preview-amount">
{{ budget ? formatAmount(budget.amount) : '未设置' }}
</text>
<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) : '未设置' }}
{{ budgetAmount > 0 ? formatAmount(budgetAmount) : '未设置' }}
</text>
<view class="preview-skeleton" v-else></view>
<BudgetBar
v-if="myBudgetAmount > 0"
:total="myBudgetAmount"
:used="myExpense"
v-if="budgetAmount > 0"
:total="budgetAmount"
:used="monthExpense"
:showLabel="true"
/>
<text class="preview-hint" v-else>设置预算掌控开支</text>
</view>
<!-- 快捷金额 -->
<view class="section-title">{{ groupStore.isGroupMode ? '设置我的预算' : '快捷金额' }}</view>
<view class="section-title">快捷金额</view>
<view class="preset-grid">
<view
class="preset-item"
@@ -97,9 +92,8 @@ const groupStore = useGroupStore()
const currentMonth = getCurrentMonth()
const budget = ref<any>(null)
const budgetAmount = ref(0)
const monthExpense = ref(0)
const myBudgetAmount = ref(0)
const myExpense = ref(0)
const loading = ref(true)
const initialLoaded = ref(false)
const amountStr = ref('')
@@ -113,17 +107,12 @@ function formatPreset(val: number) {
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()
// 群组模式用 myAmount(个人预算),个人模式用 amount
budgetAmount.value = budget.value
? (groupStore.isGroupMode ? (budget.value.myAmount || 0) : budget.value.amount)
: 0
if (budgetAmount.value > 0) {
amountStr.value = (budgetAmount.value / 100).toString()
}
}
@@ -236,6 +225,45 @@ function goBack() {
padding: 0 40rpx;
}
.overview-row {
display: flex;
align-items: center;
background: #FFFFFF;
border-radius: 28rpx;
padding: 28rpx 32rpx;
margin-bottom: 24rpx;
border: 2rpx solid #F0E0D6;
box-shadow: 4rpx 4rpx 12rpx rgba(45, 27, 27, 0.08);
}
.overview-item {
flex: 1;
text-align: center;
}
.overview-label {
font-size: 24rpx;
color: #8B7E7E;
display: block;
margin-bottom: 8rpx;
}
.overview-value {
font-family: 'Fredoka', sans-serif;
font-size: 32rpx;
font-weight: 600;
color: #2D1B1B;
&.highlight { color: #FF8C69; }
}
.overview-divider {
width: 2rpx;
height: 56rpx;
background: #F0E0D6;
flex-shrink: 0;
}
.preview-card {
background: #FFFFFF;
border-radius: 40rpx;