文章目录
1. 6.小程序页面布局 - 账单明细
1.1. 竞品
之前已经做好了《5.小程序页面布局 - 记账页面》
现在开始进行编写账单明细的页面,还是一样的套路,我们看看竞品大概是什么样:
![](https://img-blog.csdnimg.cn/img_convert/afa40b27e137424895d5bc9a7bb91a1b.png)
1.2. 布局分析
-
竞品主要是3大块:
头部:显式时间、收入、支出总览
快捷入口:一些按钮,账单、预算、资产管家等
账单明细:按天,当月倒序排列,如果一天有多笔支出,要计算一下当日汇总。(参考上图的“4月27日”效果)
-
我们现在要做什么?
头部需要:一样显式时间,增加一个“切换账簿”,来支持切换到其他的账簿合作记账
快捷入口:暂时取消,待功能需求稳定后增加
账单明细:参考竞品
1.3. 布局demo
直接看结果先:
![](https://img-blog.csdnimg.cn/img_convert/e84dcfc5593cabf44d8ee2ccb4187bed.png)
整体还是一目了然的,已经把各个区域加了边框。
尽量使用了简单的布局方式,没有加样式,因为我们主要使用vView组件来做实现。
布局,主要使用的就是flex布局。
上图的源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
margin: 0;
}
body {
width: 390px;
}
/* 头部区域样式 */
.header {
background-color: aliceblue;
height: 150px;
display: flex;
align-items: center;
}
/* 头部的4个块,flex布局,平分 */
.header .header-date,
.header .header-income,
.header .header-out,
.header .header-switch {
height: 100px;
border: 1px solid black;
/* 每个块,都占总宽度的25% */
width: 25%;
/* 开启flex布局 */
display: flex;
/* 主轴是y轴,这样,可以让里面的内容上下排布 */
flex-direction: column;
/* 主轴y轴居中对齐 */
justify-content: center;
/* 侧轴x轴居中对齐 */
align-items: center;
/* 每个块,都是100%宽度,不然就是靠内容撑开的宽度 */
width: 100%;
}
/* 列表区域布局 */
.content {
background-color: antiquewhite;
height: 644px;
}
/* 当日小计 */
.content .content-day-header {
height: 28px;
display: flex;
justify-content: space-between;
margin: 0 20px;
background-color: #808080;
align-items: center;
}
.content .content-day-list {
/* display: flex; */
}
/* 支出明细 */
.content .content-day-list .content-day-list-line {
width: 90%;
height: 43px;
display: flex;
justify-content: space-between;
margin: 0 auto;
}
/* 支出明细 - 左边的 图+名目 */
.line-left {
width: 100px;
display: flex;
border: 1px solid black;
align-items: center;
}
.line-left img {
width: 24px;
height: 24px;
}
/* 支出明细 - 右边的 金额 */
.line-right {
width: 100px;
display: flex;
justify-content: flex-end;
border: 1px solid black;
align-items: center;
}
</style>
</head>
<body>
<div class="header">
<div class="header-date">
<div>2024</div>
<div>05月 🔽</div>
</div>
<div class="header-income">
<div>收入</div>
<div>9999.99元</div>
</div>
<div class="header-out">
<div>支出</div>
<div>8888.88元</div>
</div>
<div class="header-switch">
<div>切换账单</div>
</div>
</div>
<div class="content">
<!-- 第一天 -->
<div class="content-day-header">
<div>04月27日 星期六</div>
<div>-299</div>
</div>
<div class="content-day-list">
<div class="content-day-list-line">
<div class="line-left">
<div class="line-img">
<img src="礼物.png" />
</div>
<div class="line-text">餐饮</div>
</div>
<div class="line-right">
<div class="line-money">-200</div>
</div>
</div>
<div class="content-day-list-line">
<div class="line-left">
<div class="line-img">
<img src="交通.png" />
</div>
<div class="line-text">交通</div>
</div>
<div class="line-right">
<div class="line-money">-99</div>
</div>
</div>
</div>
<!-- 第二天 -->
<div class="content-day-header">
<div>04月27日 星期六</div>
<div>-299</div>
</div>
<div class="content-day-list">
<div class="content-day-list-line">
<div class="line-left">
<div class="line-img">
<img src="礼物.png" />
</div>
<div class="line-text">餐饮</div>
</div>
<div class="line-right">
<div class="line-money">-200</div>
</div>
</div>
<div class="content-day-list-line">
<div class="line-left">
<div class="line-img">
<img src="交通.png" />
</div>
<div class="line-text">交通</div>
</div>
<div class="line-right">
<div class="line-money">-99</div>
</div>
</div>
</div>
</div>
</body>
</html>
1.4. 页面实现-头部
-
实现的效果:
共4个块,均分。
背景是渐变色。
-
布局代码:
<div class="header">
<div class="header-date">
<div class="line1-text">2024</div>
<div class="line2-text">05<span class="line2-text-small">月</span>
<u-icon style="margin-left: 5px;" name="arrow-down-fill"></u-icon>
</div>
</div>
<div class="header-income">
<div class="line1-text">收入</div>
<div class="line2-text">99999.99<span class="line2-text-small">元</span></div>
</div>
<div class="header-out">
<div class="line1-text">支出</div>
<div class="line2-text">88888.88<span class="line2-text-small">元</span></div>
</div>
<div class="header-switch">
<div>
<image style="width: 60rpx; height: 60rpx;" src="../../static/账簿.png"></image>
</div>
<div style="font-size: 13px;">
切换账簿
</div>
</div>
</div>
-
css代码
/* 头部区域样式 */ .header { /* background-color: aliceblue; */ background-image: linear-gradient(rgba(249, 219, 97, 1), rgba(250, 230, 200, 1)); height: 120px; display: flex; align-items: center; } .header .line1-text { color: #808080; font-size: 12px; } .header .line2-text { color: #000000; font-size: 15px; margin-top: 15rpx; } .header .line2-text-small { font-size: 12px; color: #808080; } /* 头部的4个块,flex布局,平分 */ .header .header-date, .header .header-income, .header .header-out, .header .header-switch { height: 100px; /* border: 1px solid black; */ /* 每个块,都占总宽度的25% */ width: 25%; /* 开启flex布局 */ display: flex; /* 主轴是y轴,这样,可以让里面的内容上下排布 */ flex-direction: column; /* 主轴y轴居中对齐 */ justify-content: center; /* 侧轴x轴居中对齐 */ align-items: center; /* 每个块,都是100%宽度,不然就是靠内容撑开的宽度 */ width: 100%; }
1.5. 账单明细
// 计算scroll-view高度
let _this = this;
uni.getSystemInfo({
success(res) {
_this.phone_height = res.windowHeight
let v = uni.createSelectorQuery().select(".h");
v.boundingClientRect(data => {
_this.scroll_view_height = _this.phone_height - data.height;
}).exec();
}
})
1.5.1. 账单明细-竞品分析
这个跟我们借鉴的布局方式差不多,大概长这个样:
![](https://img-blog.csdnimg.cn/img_convert/8a4339380b691c63b71bf2b4f8afe0e9.png)
分析:
- 账单明细部分,是一个大的块
- 包含了按天倒序展示的内容
- 如果当天有多笔数据,要做一个汇总
- 汇总单独占一行,显式:时间、星期几、当日支出小计、当日收入小计
1.5.2. 账单明细-实现
我们的实现:
- 先使用mock数据来做页面
- 要将每日的数据先进行计算,得到按自然天倒序排序的数组
- 当天数据,还要包含一个数组,这个数组里的数据,才是每天的收支记录明细。
- 我们使用uniapp的scroll-view来做大容器。这样可以做:下拉刷新到上月数据。触底加载下一个月数据。
看看实现的结果,再分步实现:
1.5.2.1. 账单明细-实现-mock数据
这个是好理解的,我们为了能够和后面的api部分解绑,就不在vue文件中写死数据,而是用一个外部导入的js方法来承载mock数据。
在/js
目录创建 api_bill_crud.js
文件,录入以下mock内容(意思是,加载某用于某月收支明细数据):
export function getUserMonthBillList(openid, month_int) {
return new Promise((resolve, reject) => {
let mockMonthBills = [{"_id":"66397bf9f08210b07d2bf163","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"通讯","bill_id":"2024-05-07_1715043320337","收支":"支出","bill_money":-96,"年":"2024","月":"05","日":"07","time":"05月07日","week":"星期二","bill_type":"通讯","desc":"手机话费","icon":"../../static/type/通讯.png","date_str":"20240507","date_int":20240507,"full_date_str":"2024-05-07","update_time":"2024-05-07T00:55:20.336Z","date":"2024-05-07T00:55:21.339Z"},{"_id":"6639af53b9fb2360b051521e","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"学习","bill_id":"2024-05-07_1715056466394","收支":"支出","bill_money":-60,"年":"2024","月":"05","日":"07","time":"05月07日","week":"星期二","bill_type":"学习","desc":"unicloud云一年","icon":"../../static/type/学习.png","date_str":"20240507","date_int":20240507,"full_date_str":"2024-05-07","update_time":"2024-05-07T04:34:26.393Z","date":"2024-05-07T04:34:27.369Z"},{"_id":"663834278a5c7863b10cca32","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"学习","bill_id":"2024-05-06_1714959398647","收支":"支出","bill_money":-30,"年":"2024","月":"05","日":"06","time":"05月06日","week":"星期一","bill_type":"学习","desc":"小程序费用","icon":"../../static/type/学习.png","date_str":"20240506","date_int":20240506,"full_date_str":"2024-05-06","date":"2024-05-06T01:36:39.593Z"},{"_id":"6638579e3d029c65e9ceedc7","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"购物","bill_id":"2024-05-06_1714968477135","收支":"支出","bill_money":-40,"年":"2024","月":"05","日":"06","time":"05月06日","week":"星期一","bill_type":"购物","desc":"口罩","icon":"../../static/type/购物.png","date_str":"20240506","date_int":20240506,"full_date_str":"2024-05-06","date":"2024-05-06T04:07:58.740Z","update_time":"2024-05-06T10:05:54.923Z"},{"_id":"6638afef0d2b315faf286f70","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"孩子","bill_id":"2024-05-06_1714991085662","收支":"支出","bill_money":-252,"年":"2024","月":"05","日":"06","time":"05月06日","week":"星期一","bill_type":"孩子","desc":"5月份餐费","icon":"../../static/type/孩子.png","date_str":"20240506","date_int":20240506,"full_date_str":"2024-05-06","date":"2024-05-06T10:24:47.753Z","update_time":"2024-05-06T13:05:54.923Z"},{"_id":"663437948620667bb4eae083","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"餐饮","bill_id":"2024-05-03_1714698130514","收支":"支出","bill_money":-17.5,"年":"2024","月":"05","日":"03","time":"05月03日","week":"星期五","bill_type":"餐饮","desc":"早餐","icon":"../../static/type/餐饮.png","date_str":"20240503","date_int":20240503,"full_date_str":"2024-05-03","date":"2024-05-03T01:02:12.243Z"},{"_id":"663565d7466d41f585ec6ef8","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"电","bill_id":"2024-05-03_1714775509594","收支":"支出","bill_money":-84,"年":"2024","月":"05","日":"03","time":"05月03日","week":"星期五","bill_type":"电","desc":"","icon":"../../static/type/电.png","date_str":"20240503","date_int":20240503,"full_date_str":"2024-05-03","date":"2024-05-03T22:31:51.116Z"},{"_id":"663784b78a5c7863b1fd7faf","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"旅行","bill_id":"2024-05-03_1714914486668","收支":"支出","bill_money":-200,"年":"2024","月":"05","日":"03","time":"05月03日","week":"星期五","bill_type":"旅行","desc":"宜兴","icon":"../../static/type/旅行.png","date_str":"20240503","date_int":20240503,"full_date_str":"2024-05-03","date":"2024-05-05T13:08:06.713Z"},{"_id":"6632f2d1c3b5c96502a740d1","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"餐饮","bill_id":"2024-05-02_1714614991720","收支":"支出","bill_money":-10,"年":"2024","月":"05","日":"02","time":"05月02日","week":"星期四","bill_type":"餐饮","desc":"串","icon":"../../static/type/餐饮.png","date_str":"20240502","date_int":20240502,"full_date_str":"2024-05-02","date":"2024-05-02T01:56:33.398Z"},{"_id":"6632f61b0d2b315faf862e8b","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"零食","bill_id":"2024-05-02_1714615833865","收支":"支出","bill_money":-7,"年":"2024","月":"05","日":"02","time":"05月02日","week":"星期四","bill_type":"零食","desc":"蜜雪冰城","icon":"../../static/type/零食.png","date_str":"20240502","date_int":20240502,"full_date_str":"2024-05-02","date":"2024-05-02T02:10:35.481Z"},{"_id":"6633207a652341ed5e77f151","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"餐饮","bill_id":"2024-05-02_1714626680512","收支":"支出","bill_money":-127,"年":"2024","月":"05","日":"02","time":"05月02日","week":"星期四","bill_type":"餐饮","desc":"午餐","icon":"../../static/type/餐饮.png","date_str":"20240502","date_int":20240502,"full_date_str":"2024-05-02","date":"2024-05-02T05:11:22.131Z"},{"_id":"663380971c90b65e4337d32e","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"零食","bill_id":"2024-05-02_1714651286335","收支":"支出","bill_money":-30,"年":"2024","月":"05","日":"02","time":"05月02日","week":"星期四","bill_type":"零食","desc":"","icon":"../../static/type/零食.png","date_str":"20240502","date_int":20240502,"full_date_str":"2024-05-02","date":"2024-05-02T12:01:27.867Z"},{"_id":"66338ea29755e328304923bf","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"餐饮","bill_id":"2024-05-02_1714654880413","收支":"支出","bill_money":-8.5,"年":"2024","月":"05","日":"02","time":"05月02日","week":"星期四","bill_type":"餐饮","desc":"紫燕","icon":"../../static/type/餐饮.png","date_str":"20240502","date_int":20240502,"full_date_str":"2024-05-02","date":"2024-05-02T13:01:22.254Z"},{"_id":"6632f786eef9cb63bb41c538","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"餐饮","bill_id":"2024-05-01_1714616197749","收支":"支出","bill_money":-21,"年":"2024","月":"05","日":"01","time":"05月01日","week":"星期三","bill_type":"餐饮","desc":"猪头肉","icon":"../../static/type/餐饮.png","date_str":"20240501","date_int":20240501,"full_date_str":"2024-05-01","date":"2024-05-02T02:16:38.660Z"},{"_id":"6632f79aee97ef5896c1151f","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"水果","bill_id":"2024-05-01_1714616217844","收支":"支出","bill_money":-21,"年":"2024","月":"05","日":"01","time":"05月01日","week":"星期三","bill_type":"水果","desc":"西瓜","icon":"../../static/type/水果.png","date_str":"20240501","date_int":20240501,"full_date_str":"2024-05-01","date":"2024-05-02T02:16:58.130Z"},{"_id":"663108b0ee97ef58968d7957","openid":"oCIe95E0U1WibyRNJ864n-okoRT0","category":"工资","bill_id":"2024-04-30_1714489520278","收支":"收入","bill_money":7000,"年":"2024","月":"04","日":"30","time":"04月30日","week":"星期二","bill_type":"工资","desc":"","icon":"../../static/type/工资.png","date_str":"20240430","date_int":20240430,"full_date_str":"2024-04-30","date":"2024-04-30T15:05:20.363Z"}];
resolve(mockMonthBills);
})
}
这里用到了Promise,其实主要作用了是为了让后面的api接口异步调用操作变为同步等待,减少回调地域问题。
使用时,在使用此方法前加async
即可。
// 测试数据,用以验证页面布局及样式
let result = await getUserMonthBillList('1332', 5);
console.log('获取用户x月份账单成功');
this.month_bills = result;
1.5.2.2. 每日收支数据的聚合整理
按照前面的分析:
2. 要将每日的数据先进行计算,得到按自然天倒序排序的数组
3. 当天数据,还要包含一个数组,这个数组里的数据,才是每天的收支记录明细。
然后我们已经有了mock数据,最好还是也封装一个方法,进行收支数据的处理:
在/js
目录创建 bill_calculate.js
文件,录入以下内容:
/**
* @param {Object} month_bill_list 某月的所有收支明细数据
* @return {number} income_month 此月收入合计
* @@return {number} expenditure_month 此月支出合计
* @@return {Array} user_bill_list 按天为item的数组,每个item是当天发生的收支明细
*/
export function transformBills(month_bill_list) {
// 先按照时间进行排序,然后将数据按天汇总。
let sorted_detail_list = Array.from(month_bill_list).sort((a, b) => b['date_int'] - a[
'date_int']);
// sorted_detail_list = sorted_detail_list.filter(item => item['月'] == this.month);
let user_bill_list = []
let income_month = 0
let expenditure_month = 0
sorted_detail_list.map(function(this_bill) {
let today_summary = user_bill_list.find(item => item['日'] == this_bill['日']);
if (today_summary == undefined) {
let expenditure = this_bill['收支'] == '支出' ? Math.abs(this_bill['bill_money']) : 0;
let income = this_bill['收支'] == '收入' ? this_bill['bill_money'] : 0;
expenditure_month = this_bill['收支'] == '支出' ? expenditure_month+this_bill['bill_money']: expenditure_month;
income_month = this_bill['收支'] == '收入' ? income_month+this_bill['bill_money']: income_month;
today_summary = {
expenditure: parseFloat(expenditure),
income: parseFloat(income),
list: [this_bill],
time: this_bill.time,
week: this_bill.week,
full_date: this_bill.date_str,
'日': this_bill['日']
};
user_bill_list.push(today_summary); // 后来的放后面
} else {
// 计算对应日期的消费、收入汇总
let expenditure = this_bill['收支'] == '支出' ? today_summary.expenditure + Math.abs(this_bill['bill_money']) : today_summary.expenditure;
let income = this_bill['收支'] == '收入' ? today_summary.income + this_bill['bill_money'] :
today_summary.income;
expenditure_month = this_bill['收支'] == '支出' ? expenditure_month+this_bill['bill_money']: expenditure_month;
income_month = this_bill['收支'] == '收入' ? income_month+this_bill['bill_money']: income_month;
today_summary.expenditure = expenditure;
today_summary.income = income;
today_summary.list = [this_bill, ...today_summary.list];
}
});
return [income_month.toFixed(2), expenditure_month.toFixed(2), user_bill_list]
}
1.5.2.3. 页面scroll-view
为什么使用scroll-view,前面已经提到:
4. 我们使用uniapp的scroll-view来做大容器。这样可以做:下拉刷新到上月数据。触底加载下一个月数据。
实现起来,主要就是页面、js、css
-
页面
<view v-if="transfromedBills.length > 0"> <scroll-view scroll-y="true" :style="{height:scroll_view_height+'px'}" refresher-enabled="true" :refresher-triggered="refresherTriggered" @refresherrefresh="refresher()" @scrolltolower="loadMore"> <view> <view v-for="(item, index) in transfromedBills" :key="index"> <view class="u-flex list-box day_summary"> <view class="u-m-r-10 u-flex-1"> <view class="header-text"> {{item.time}} {{item.week}}</view> </view> <view class="u-m-r-10 u-flex-1"> <view class="header-text">{{income_str}} {{item.income}}</view> </view> <view class="u-m-r-10 u-flex-1"> <view class="header-text">{{expenditure_str}} {{item.expenditure}}</view> </view> </view> <view class="list-box-children" v-for="(item1, index1) in item.list" :key="index1" @click="toDetail(item1)"> <view class="u-flex"> <image slot="icon" class="box-icon" :src="item1.icon" mode="" :lazy-load="lazy_load"> </image> </view> <view class="box-left"> {{item1.bill_type}} </view> <view class="box-desc"> {{item1.desc}} </view> <view class="u-flex-1 box-right"> {{item1.bill_money}} </view> </view> </view> </view> </scroll-view> </view>
-
js
<script> import { useStore } from 'vuex'; import { getUserMonthBillList } from '@/js/api_bill_crud.js'; import { transformBills } from '@/js/bill_calculate.js'; export default { data() { return { current_year: new Date().getFullYear(), current_month: new Date().getMonth() + 1, tabbar: [], month_bills: [], transfromedBills: [], income: 0, expenditure: 0, expenditure_str: '', // ?? lazy_load: true, //? refresherTriggered: false, // 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 scroll_view_height: 0, income_str: '', } }, methods: { refresher() { console.log('下拉刷新'); if (this._refresherTriggered) { return; } // 去加载上一个月的数据 if (this.current_month == 1) { this.current_month = 12; this.current_year = this.current_year - 1; } else { this.current_month = this.current_month - 1; } console.log('要去加载上个月的年{}月{}', this.current_year, this.current_month); var that = this; if (!this.refresherTriggered) { //下拉刷新,先变true再变false才能关闭 this.refresherTriggered = true; //关掉圈圈,需要先执行完刷新操作 setTimeout(() => { that.refresherTriggered = false; }, 1000); } }, loadMore() { console.log('加载更多loadMore'); // 去加载下一个月的数据 if (this.current_month == 12) { this.current_month = 1; this.current_year = this.current_year + 1; } else { this.current_month = this.current_month + 1; } console.log('要去加载下个月的年{}月{}', this.current_year, this.current_month); } }, async onShow() { let [income, expenditure, transfromedBills] = transformBills(this.month_bills); this.transfromedBills = transfromedBills; this.income = income; this.expenditure = expenditure; console.log('账单计算成功'); // console.log(income); // console.log(expenditure); // console.log(transfromedBills); }, async onLoad() { const store = useStore(); //获取store对象 /** * 示例中为每个tabbar页面都写了一遍tabbar变量,您可以将tabbar数组写入到vuex中,这样可以全局引用 */ this.tabbar = store.getters.getTabbar; // scroll-view高度,暂不计算。 this.scroll_view_height = 600 // 测试数据,用以验证页面布局及样式 let result = await getUserMonthBillList('1332', 5); console.log('获取用户x月份账单成功'); this.month_bills = result; let [income, expenditure, transfromedBills] = transformBills(this.month_bills); this.transfromedBills = transfromedBills; this.income = income; this.expenditure = expenditure; console.log('账单计算成功'); } } </script>
-
css
<style lang="scss"> .u-flex { display: flex; flex-direction: row; align-items: center; } .day_summary { background-color: #f7f7f7; } .list-box { padding: 18rpx 18rpx 18rpx 40rpx; } .list-box-children { display: -webkit-box; display: -webkit-flex; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -webkit-flex-direction: row; flex-direction: row; -webkit-box-align: center; -webkit-align-items: center; align-items: center; position: relative; box-sizing: border-box; width: 100%; padding: 26rpx 32rpx; font-size: 28rpx; line-height: 50rpx; color: #606266; background-color: #fff; text-align: left; .box-icon { width: 50rpx; height: 50rpx; margin-right: 35rpx; } .box-left { width: auto; font-weight: 500; font-size: 28rpx; } .box-right { overflow: hidden; text-align: right; vertical-align: middle; color: #909399; font-size: 26rpx; } .box-desc { font-weight: 500; width: 300rpx; margin-left: 50rpx; overflow: hidden; text-overflow: ellipsis; -ms-text-overflow: ellipsis; display: -webkit-box; line-clamp: 1; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } } .u-m-r-10 { margin-right: 10rpx !important; } .u-flex-1 { flex: 1; } .header-text { font-size: 25rpx; color: #7a7a7a; } </style>
通过下拉刷新和触底加载更多,页面能正确的处理调用,后面通过api再完善真是数据的处理
1.6. TODO
内容较多,下一节再处理:
- 点击更新或删除明细账单
- 头部数据的联动,不再是固定数据
- 月份可以点击下拉箭头自行快速选择
- 每日的收支汇总,布局要再优化一下。