88 lines
3.9 KiB
Vue
88 lines
3.9 KiB
Vue
<template>
|
|
<view class="page">
|
|
<view class="filters">
|
|
<picker mode="date" :value="startDate" @change="e=>{startDate=e.detail.value;load()}">
|
|
<view class="field"><text class="label">开始</text><text class="value">{{ startDate || '—' }}</text></view>
|
|
</picker>
|
|
<picker mode="date" :value="endDate" @change="e=>{endDate=e.detail.value;load()}">
|
|
<view class="field"><text class="label">结束</text><text class="value">{{ endDate || '—' }}</text></view>
|
|
</picker>
|
|
</view>
|
|
<view class="summary">
|
|
<view class="sum-item"><text class="k">收入</text><text class="v">{{ fmt(income) }}</text></view>
|
|
<view class="sum-item"><text class="k">支出</text><text class="v">{{ fmt(expense) }}</text></view>
|
|
<view class="sum-item"><text class="k">期初</text><text class="v">{{ fmt(opening) }}</text></view>
|
|
<view class="sum-item"><text class="k">期末</text><text class="v">{{ fmt(ending) }}</text></view>
|
|
</view>
|
|
<scroll-view scroll-y class="list">
|
|
<view class="item" v-for="it in list" :key="it.id">
|
|
<view class="row">
|
|
<text class="title">{{ it.src==='other' ? (it.category || '其他') : (it.remark || '收付款') }}</text>
|
|
<text class="amount" :class="{ in: it.direction==='in', out: it.direction==='out' }">{{ it.direction==='in' ? '+' : '-' }}{{ fmt(it.amount) }}</text>
|
|
</view>
|
|
<view class="meta">{{ formatDate(it.tx_time || it.txTime) }} · {{ it.remark || '-' }}</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { get } from '../../common/http.js'
|
|
export default {
|
|
data() {
|
|
return { accountId: null, startDate: '', endDate: '', list: [], opening: 0, income: 0, expense: 0, ending: 0 }
|
|
},
|
|
onLoad(query) {
|
|
this.accountId = Number(query && query.id)
|
|
this.quickInit()
|
|
this.load()
|
|
},
|
|
methods: {
|
|
quickInit() {
|
|
// 默认本月
|
|
const now = new Date()
|
|
const y = now.getFullYear(), m = now.getMonth()+1
|
|
this.startDate = `${y}-${String(m).padStart(2,'0')}-01`
|
|
const lastDay = new Date(y, m, 0).getDate()
|
|
this.endDate = `${y}-${String(m).padStart(2,'0')}-${String(lastDay).padStart(2,'0')}`
|
|
},
|
|
async load(page=1, size=50) {
|
|
try {
|
|
const res = await get(`/api/accounts/${this.accountId}/ledger`, { startDate: this.startDate, endDate: this.endDate, page, size })
|
|
this.list = (res && res.list) || []
|
|
this.opening = Number(res && res.opening || 0)
|
|
this.income = Number(res && res.income || 0)
|
|
this.expense = Number(res && res.expense || 0)
|
|
this.ending = Number(res && res.ending || 0)
|
|
} catch (e) {
|
|
uni.showToast({ title: '加载失败', icon: 'none' })
|
|
}
|
|
},
|
|
fmt(v) { return (typeof v === 'number' ? v : Number(v||0)).toFixed(2) },
|
|
formatDate(s) { if (!s) return '-'; try { const d=new Date(s); const pad=n=>String(n).padStart(2,'0'); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}` } catch(e){ return s } }
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.page { display:flex; flex-direction: column; height: 100vh; }
|
|
.filters { display:flex; gap: 16rpx; padding: 16rpx; background:#fff; }
|
|
.field { display:flex; justify-content: space-between; align-items:center; padding: 16rpx; border:1rpx solid #eee; border-radius: 12rpx; min-width: 300rpx; }
|
|
.label { color:#666; }
|
|
.value { color:#333; }
|
|
.summary { display:grid; grid-template-columns: repeat(4,1fr); gap: 12rpx; padding: 12rpx 16rpx; background:#fff; border-top:1rpx solid #f1f1f1; border-bottom:1rpx solid #f1f1f1; }
|
|
.sum-item { padding: 12rpx; text-align:center; }
|
|
.k { display:block; color:#888; font-size: 24rpx; }
|
|
.v { display:block; margin-top:6rpx; font-weight:700; color:#333; }
|
|
.list { flex:1; }
|
|
.item { padding: 18rpx 16rpx; border-bottom:1rpx solid #f4f4f4; background:#fff; }
|
|
.row { display:flex; align-items:center; justify-content: space-between; margin-bottom: 6rpx; }
|
|
.title { color:#333; }
|
|
.amount { font-weight:700; }
|
|
.amount.in { color:#2a9d8f; }
|
|
.amount.out { color:#d35b5b; }
|
|
.meta { color:#999; font-size: 24rpx; }
|
|
</style>
|
|
|
|
|