从0到1实现单机记账APP原理与细节uniApp内含源码 (一)

单机记账APP演示及源码

具体演示如下面视频所示。免费下载地址:点击进入
预览APP(内含开屏广告)下载地址:http://8.142.10.182:8888/down/aWHWeGaEQE2W.apk
服务器买的便宜,带宽很小所以下载速度慢,主要还是囊中羞涩,哈哈。
内容有点长,将结构、样式、方法都写进去了,可以复制粘贴直接用,资源就去下载地址直接全部下载下来吧。


单机记账APP

  • 单机记账APP演示及源码
  • 一、本章详细讲解记账功能页面的实现
      • 1.基本搭建
      • 2.记账页面实现
          • (1)收支类型
          • (2)金额输入
          • (3)时间选择、备注
          • (4)记账
  • 小结

一、本章详细讲解记账功能页面的实现

1.基本搭建

首先使用HBuilder新建项目(文件>>新建>>项目>>选择默认模板),然后引入uView2.0的UI框架(官网有详细的指引地址连接)。


总共5个页面结构图所示,别的是之前连接自己的服务器,写的登录设置密码的功能,现在改成单机的另外的页面就不需要了。
从0到1实现单机记账APP原理与细节uniApp内含源码 (一)_第1张图片


2.记账页面实现

先看页面,然后我们分别要实现的是收支类型、金额输入、时间选择、备注以及记账

从0到1实现单机记账APP原理与细节uniApp内含源码 (一)_第2张图片


(1)收支类型

先行铺写收支类型部分的结构和样式,具体的代码如下:



<view class="headNav">
	<text @click.stop="setType(0)" :class="{'navActive':statusPay == 0}">支出text>
	<text @click.stop="setType(1)" :class="{'navActive':statusPay == 1}">收入text>
	<view class="navLine" :style="{'left':lineLeft}">view>
view>


<view class="inputBox">
	<view class="alignItems">
		<u-icon name="rmb-circle-fill" size="26" color="#ffd607">u-icon>
		<u-icon name="arrow-right" size="20" color="#ffd607">u-icon>
	view>
	<text @click.stop="showkey = true" style="min-width: 200rpx;text-align: right;flex: 1;">¥{{money?money:'0.00'}}text>
view>



<view>
	
	<view v-show="statusPay == 0" class="typeTitle">
		<text @click="setKind(0)" :class="{'typeActive':kindNav == 0}">食品饮料text>
		<text @click="setKind(1)" :class="{'typeActive':kindNav == 1}">衣裤鞋帽text>
		<text @click="setKind(2)" :class="{'typeActive':kindNav == 2}">居家生活text>
		<text @click="setKind(3)" :class="{'typeActive':kindNav == 3}">交通游玩text>
	view>
	
	<view v-show="statusPay == 1" class="typeTitle">
		<text @click="setKind(4)" :class="{'typeActive':kindNav == 4}">收入text>
	view>
	
	<view v-show="statusPay != 2" class="typeBox">
		<view class="selectKind" :style="selKindClass">
			<view class="fillUp">view>
		view>
		<view @click="setKindBox(index)" v-for="(item,index) in list[kindNav]" :key="index" class="kindBox">
			<image :src="item.img" class="kindImg" mode="">image>
			<text>{{item.name}}text>
		view>
	view>
view>




<style>
.headNav {
	position: relative;
	display: flex;
	color: #999999;
	justify-content: center;
}

.navLine {
	position: absolute;
	bottom: 0;
	width: 100rpx;
	height: 10rpx;
	background: #ffd607;
	border-radius: 10rpx;
	transition: ease-out 0.4s;
}

.headNav text {
	font-weight: bold;
	text-align: center;
	width: 220rpx;
	line-height: 80rpx;
	transition: ease-out 0.4s;
}

.navActive {
	color: #333;
}

/* 金额 */
.inputBox {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0 30rpx;
	font-weight: bold;
	line-height: 120rpx;
}

.alignItems {
	display: flex;
	align-items: center;
}

/* 分类选择 */
.typeTitle {
	display: flex;
	line-height: 60rpx;
	color: #999999;
	border-top: 20rpx #F4F4F4 solid;
}

.typeTitle text {
	width: 25%;
	line-height: 80rpx;
	text-align: center;
}

.typeActive {
	color: #333;
	font-weight: bold;
}

.typeBox {
	position: relative;
	font-size: 24rpx;
	color: #999999;
	display: flex;
	flex-wrap: wrap;
	padding: 0 30rpx 30rpx 30rpx;
	border-bottom: 20rpx #F4F4F4 solid;
}

.kindBox {
	width: 172rpx;
	padding: 20rpx 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	z-index: 1;
}

.kindImg {
	width: 80rpx;
	height: 80rpx;
	margin-bottom: 8rpx;
}

/* 类型选择框 */
.fillUp {
	width: 156rpx;
	height: 144rpx;
	border-radius: 0 10rpx 0 10rpx;
	background: #FFFFFF;
}

.selectKind {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 172rpx;
	height: 160rpx;
	background: linear-gradient(45deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4, #f441a5);
	background-size: 400%;
	border-radius: 0 10rpx 0 10rpx;
	filter: blur(2px);
	animation: animate 8s linear infinite;
	transition: ease-out 0.4s;
}
/* 让颜色动起来的动画 */
@keyframes animate {
	0% {
		background-position: 0%;
	}

	100% {
		background-position: 400%;
	}
}
style>


具体实现切换的方法思想:
为了实现收支下面小横条的移动所以通过“lineLeft”变量来实现控制,在css样式中 写有transition: ease-out 0.4s;动画属性。
同理选择类别的也是通过“selKindClass”来控制选择框的移动,中间选择框颜色会想弥红灯一样的改变颜色也是通过css中控制的。
具体方法和需要的变量如下所示:

// data() {return { 存放的值如下 }}
selKindClass: "left:-100px;top:0;", // 选择框
statusPay: 0, // 0支出、1收入、2转账
lineLeft: '216rpx', // 收支下的小黄条
showkey: true, // 数字键盘
money: '', // 金额
kindNav: 0, // 分类
//img中资源找不到可以自行下载修改名字
list: [
	// 食品分类
	[{
		"img": "/static/icon/food01.png",
		"name": "早中晚餐",
		"id": 1
	}, {
		"img": "/static/icon/food02.png",
		"name": "饮料",
		"id": 2
	}, {
		"img": "/static/icon/food03.png",
		"name": "蔬菜",
		"id": 3
	}, {
		"img": "/static/icon/food04.png",
		"name": "零食",
		"id": 4
	}, {
		"img": "/static/icon/other.png",
		"name": "其他",
		"id": 5
	}],
	// 衣物分类
	[{
		"img": "/static/icon/dress01.png",
		"name": "衣服",
		"id": 6
	}, {
		"img": "/static/icon/dress02.png",
		"name": "鞋子",
		"id": 7
	}, {
		"img": "/static/icon/dress03.png",
		"name": "帽子",
		"id": 8
	}, {
		"img": "/static/icon/dress04.png",
		"name": "首饰",
		"id": 9
	}, {
		"img": "/static/icon/other.png",
		"name": "其他",
		"id": 10
	}],
	// 居家分类
	[{
		"img": "/static/icon/home01.png",
		"name": "日常用品",
		"id": 11
	}, {
		"img": "/static/icon/home02.png",
		"name": "厨房用品",
		"id": 12
	}, {
		"img": "/static/icon/home03.png",
		"name": "床上用品",
		"id": 13
	}, {
		"img": "/static/icon/home04.png",
		"name": "电器用品",
		"id": 14
	}, {
		"img": "/static/icon/other.png",
		"name": "其他",
		"id": 15
	}],
	// 游玩分类
	[{
		"img": "/static/icon/play01.png",
		"name": "交通费",
		"id": 16
	}, {
		"img": "/static/icon/play02.png",
		"name": "油费",
		"id": 17
	}, {
		"img": "/static/icon/play03.png",
		"name": "娱乐",
		"id": 18
	}, {
		"img": "/static/icon/other.png",
		"name": "其他",
		"id": 19
	}],
	// 支出分类
	[{
		"img": "/static/icon/outlay01.png",
		"name": "工资",
		"id": 20
	}, {
		"img": "/static/icon/outlay02.png",
		"name": "兼职",
		"id": 21
	}, {
		"img": "/static/icon/outlay03.png",
		"name": "福利",
		"id": 22
	}, {
		"img": "/static/icon/other.png",
		"name": "其他",
		"id": 23
	}]
],



// 	methods: {方法如下}
// 收支下方横条
setType(stu) {
	// 下面是后面金额输入时控制自定义数字键盘的显示和隐藏。
	// this.showkey = true
	this.statusPay = stu
	this.lineLeft = stu * 220 + 216 + 'rpx'
	this.statusPay == 0 ? this.setKind(0) : this.setKind(4)
},
// 类别选择
setKind(index) {
	this.selKindClass = "left:-100px;top:0;"
	this.kindNav = index
},
// 类别选择框
setKindBox(index) {
	this.typeStatu = this.list[this.kindNav][index].id
	this.showkey = false
	var topSum = parseInt(index / 4)
	var leftSum = parseInt(index % 4)
	this.selKindClass = "left:" + (leftSum * 172 + 30) + "rpx;top:" + (topSum * 160) + "rpx;"
},

(2)金额输入

金额输入可以将哪个金额的地方设置为input的输入框,为了尝试一下自己能否写一个数字键盘,最终发现还是比较简单的。
具体结构和样式如下:



<view v-show="showkey" class="keyboardBox">
	<view v-for="(item,index) in keyboardList" :key="index" class="flexColumn">
		<view @click.stop="countMoney(itemTwo)" v-for="itemTwo in item" :key="itemTwo">{{itemTwo}}view>
	view>
	<view class="flexColumn">
		<view @click.stop="delMoney(1)" style="height: 100rpx;">
			<u-icon name="backspace" color="#FFFFFF" size="28">u-icon>
		view>
		<view @click.stop="delMoney(2)">Cview>
		<view @click="readyBtn()" class="keyBtn">确定view>
	view>
view>



<style>
/* 键盘样式 */
.keyboardBox {
	position: absolute;
	bottom: 0;
	width: 100%;
	display: flex;
	background: #474669;
	color: #FFFFFF;
	font-weight: bold;
	padding: 10rpx 0 60rpx 0;
}

.flexColumn {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	line-height: 100rpx;
}

.flexColumn view {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
}

.flexColumn view:hover {
	background: #656496;
}

.keyBtn {
	width: 100%;
	text-align: center;
	background: #616593;
	line-height: 200rpx;
}
style>

具体方法和变量如下:

// data() {return { 存放的值如下 }}
// 键盘
keyboardList: [
	['1', '4', '7', '.'],
	['2', '5', '8', '0'],
	['3', '6', '9', '00']
],


// 	methods: {方法如下}
// 输入数字
countMoney(sum) {
	// 小数点
	this.money += sum
},
// 删除
delMoney(stu) {
	if (stu == 2) {
		this.money = ''
	} else {
		var newMoney = this.money.substr(0, this.money.length - 1)
		this.money = newMoney
	}
},
// 确定
readyBtn() {
	this.showkey = false
},
(3)时间选择、备注

时间选择使用了uView中的“u-datetime-picker”组件,正常使用是可以的,我这里使用了formatter过滤器实现一下每个数字后面跟着对应的文字。备注没啥说的。具体结构和样式如下:



<view class="footBox">
	<view @click="showPicker = true" class="footBoxleft">
		<u-icon name="calendar" size="28">u-icon>
		<text class="timeTitle">{{addBillTime}}text>
	view>
	<input type="text" v-model="remark" placeholder="输入备注内容...">
view>


<u-datetime-picker ref="datetimePicker" :show="showPicker" v-model="datetime" :formatter="formatter"
	mode="datetime" @cancel="showPicker = false" @confirm="setAddTime">u-datetime-picker>


<style>
/* 时间以及备注 */
.footBox {
	display: flex;
	padding: 0 30rpx;
	line-height: 80rpx;
}

.footBoxleft {
	display: flex;
	align-items: center;
}

.footBox input {
	display: block;
	flex: 1;
	height: 80rpx;
}
.timeTitle {
	font-weight: bold;
	width: 160rpx;
	text-align: center;
	font-size: 30rpx;
}
style>

添加完时间和备注在部分小机型上,会出现数字键盘遮挡的现象存在,所有要给整个屏幕注册一个隐藏键盘的事件
具体方法和变量如下:

// data() {return { 存放的值如下 }}
showPicker: false, // 时间选择器
datetime: Number(new Date()), // 时间
addBillTime: '现在', // 用于显示的文字
remark:'', // 备注
yearTime: '', // 年
monthTime: '', // 月


// 	methods: {方法如下}
//点击空白处隐藏键盘(这个事件 需要放在