Shock! ! Fifteen days to develop an Android punch card app, and successfully released!

Summary

Staying at home on vacation, now in his junior year, facing two options for finding a job and postgraduate. But there was not much interest in finding a job, so he prepared for the postgraduate examination. Then I want to start to record a little bit of the life of the postgraduate, as a later memory. After all, the postgraduate entrance examination is the last opportunity that can be changed through hard work. Then search for various punching apps or applets in the application market and applets. But none of them meet their own requirements. So it was born to develop a small punching program of its own. I just started a small program and successfully released it. It is called " 21-day habit card ", and its function is simplified. But after the development of the applet was not satisfied, so the idea of ​​developing Android emerged. This Android is not an ordinary Android, but Android developed through uniapp is equivalent to a web Android application.

Function display, page display

Homepage Show
Join a circle
Scan code
Circle details page
Daily punch content
calendar
Share QR code
Discovery page
Insert picture description here
My page

function display

Watch the video

Item view

Android app download:

Android experience

A simplified version of WeChat applet

Check-in applet QR code

development process

Never contacted uniapp, this winter vacation is the first contact with uniapp, but looking at the vue used by uniapp. It's more convenient to get started.

interface design

The dcloud community provides many plugins and templates, and has also learned the front end before adding it. So he drew the design draft himself. Pure hand-painted, so I will not show it here. First think about the function, then draw a style, specify a certain part and click to jump to a certain page. In fact, it is simple, it is really not easy to draw. Because the logic should be considered clearly, including page transfer parameters, parameters can not be wrong, the parameters required for each page jump are also different.

feature design

The functions expected to be envisaged:
1. Punching rings: There are two types: public punching rings and private punching rings. The private punching circle can be set whether it can be accessed by the public
. 2. Daily punching: At first, I only thought about the punching content, and did not consider the function of punching pictures. Later, it was found that it was not perfect to upload pictures, so I added the punch card upload function.
3. Punching calendar: View daily punching
4. Punching chart: viewing punching data
5. Graphic circle: You can publish your content publicly and it can be recommended to everyone to view.
Newly added function in the later period:
Credit function: prepare for future resource sharing app.
Member function: automatic evaluation based on the number of points, no charge, but also for the preparation of resource app.
Anonymous venting: When we insist on getting used to, there will always be a lot of trivial things to disturb us, and we have no way to vent, so we developed the function of anonymous venting, where the avatar and nickname are randomly generated. Who vents, but it is always good to say it.
(The vent comment function is still under development)

Background development

The back-end uses Java language, and the database uses mysql, which is mounted on the Alibaba Cloud server.

Front-end development

I used some of the content of the two big brothers' component libraries, and also developed some pages myself. At the same time, according to his own needs, he has developed the component library of the big brother

Realization of some functions of Android app

Android login status saving

To introduce store,
first add the following sentence to main.js, introduce store

import store from './store'

Then create the store directory, create the index.js file, write in it

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
	state: {
		/**
		 * 是否需要强制登录
		 */
		forcedLogin: false,
		hasLogin: false,
		userinfo:{}
	},
	mutations: {
		login(state, userinfo) {//登录方法
			state.userinfo = userinfo;
			state.hasLogin = true;
			uni.setStorage({
				key: 'userinfo',//登录用户的信息
				data: userinfo
			})
			uni.setStorage({
				key:'hasLogin',//登录状态
				data:true
			})
		},
		logout(state) {//注销登录方法
			state.userinfo = {};
			state.hasLogin = false;
			uni.removeStorage({
				key: 'userinfo'//抹除登录用户信息
			});
			uni.removeStorage({
				key:'hasLogin'//抹除登录状态
			})
		}
	}
})

export default store

After completion, you need to join on the page using this method

import {
		mapState,
		mapMutations
	} from 'vuex';
	...mapMutations(['login']) //登录页面引入
	...mapMutations(['logout']) //注销页面引入

Page to get the information of the logged in user

uni.getStorage({
		key: 'userinfo',//获取缓存中的用户信息
		success(e) {
			that.openid=e.data.openid//用户的唯一标志
			console.log(e.data)
			if (e.data) {
			     uni.request({
					url: 'url',//获取数据的url
					data: {
					},
					method: 'POST',
					header: {
						"Content-Type": "application/x-www-form-urlencoded"
					},
					success: (res) => {},
					fail: () => {
						uni.showModal({
							title:'您好,系统正在维护中'
						})
					}
				})
			}else {
				uni.navigateTo({//获取失败返回登录界面
					url: '../login/login'
				})
			}
})

Pull-down refresh function

Uniapp is the same as the applet, you need to enable onpulldownrefresh
and add it to the style of the corresponding page in pages.json

"enablePullDownRefresh": true, // 开启下拉
"backgroundTextStyle": "dark"

Then add the request interface that needs to refresh the data in the onPullDownRefresh method on the page

onPullDownRefresh() {
			var that=this
			uni.request({
				url: 'url',
				data: {
				},
				method: 'POST',
				header: {
					"Content-Type": "application/x-www-form-urlencoded"
				},
				success: (res) => {
					uni.stopPullDownRefresh()
				}
			})
		},

Punch card

As a punch card app, the generation of punch cards is crucial, although not everyone will save this punch card.
But the punch card is the only evidence that we have completed the punch card.

Draw card

var now = new Date();
var year = now.getFullYear();       //年
var month = now.getMonth() + 1;     //月
var day = now.getDate();
var hour=now.getHours();
var minute=now.getMinutes();
var reallywight=uni.getSystemInfoSync().windowWidth
var reallyhight=uni.getSystemInfoSync().windowHeight
var wigth=uni.getSystemInfoSync().windowWidth-50
var hight=uni.getSystemInfoSync().windowHeight-90
var height=uni.getSystemInfoSync().windowHeight-190
const ctx =uni.createCanvasContext('myCanvas');
ctx.drawImage( "../../static/cards/card19.png" , 25 ,25 ,wigth,wigth*1.77 );		//绘制图
ctx.save() 
ctx.setFillStyle("#FFFFFF")
ctx.font = 'normal 16px sans-serif';
ctx.fillText("每/",wigth-80,70)
ctx.fillText("日/",wigth-56,70)
ctx.fillText("一/",wigth-32,70)
ctx.fillText("签",wigth-8,70)
var nowtime=hour+":"+minute
ctx.fillText(nowtime,wigth-56,100)
ctx.setFillStyle("#FFFFFF")
ctx.setFontSize(50)//设置字体大小,默认10
ctx.textAlign = 'center'	// 设置位置
ctx.font = 'normal 40px sans-serif';	// 字体样式
ctx.fillText(day , 60, 80);
ctx.font = 'normal 15px sans-serif';
ctx.fillText("⛪枣庄市",70,120)
ctx.font = 'normal 10px sans-serif';
ctx.fillText("21天习惯打卡",60, wigth*1.70-45)
ctx.save()
ctx.font = 'normal 12px sans-serif';
var dayy=year+"."+month
ctx.fillText(dayy,60,100)
ctx.save()
var text="所有的习惯以,不可见的程度积聚起来,如百溪汇于川,百川流于海!"
ctx.font = '30px FZShuTi';
var str= new Array();   
str=text.split(","); 
// ctx.textAlign="center";
var uphight=0
for (var i=0;i<str.length;i++){
	ctx.font = '30px shuti';
	ctx.fillText(str[i], reallywight/2, height/2+uphight)
	uphight+=40
}
ctx.font = 'normal 20px FZYaoti';
ctx.fillText("考研记录生活圈子",wigth-80,wigth*1.70-25)
ctx.font = 'normal 20px FZYaoti';
ctx.fillText("已打卡10天",wigth-50,wigth*1.77-15)
ctx.draw()

Card adaptation issues

Screen problem

The development of punch cards requires the use of canvas to draw punch cards. And the screens of mobile phones are different, so we have to consider the layout of cards on different mobile phones.
In this place, I used the method to get the width and height of the user's mobile phone screen. Although some special mobile phones will also have some formatting errors, they are only slightly shifted. Not a big problem

Text wrapping issues

Two implementation methods.

First, it is applicable to the problem that the length of the text is not known or the specific output is
divided. Split the text to get the length of the string first, and then split it by split.
By cyclically concatenating character strings, it automatically draws when the set width is reached, then the character string is emptied, and the concatenation continues
until the last line is drawn.

Second, we have known the content of the text in advance.
When we develop some punching apps, we output the content as specified, and randomly generate the strings in our array. At this time, we can specify the split symbol in the string.

In my development, I randomly generated a sentence in 20 famous quotes, the content is already known, so I adopted the second development method

var text="所有的习惯以,不可见的程度积聚起来,如百溪汇于川,百川流于海!"//假设是随机生成的橘子
ctx.font = '30px FZShuTi';
var str= new Array();   
str=text.split(","); //拆分句子
// ctx.textAlign="center";
var uphight=0
for (var i=0;i<str.length;i++){
	ctx.font = '30px shuti';
	ctx.fillText(str[i], reallywight/2, height/2+uphight)
	uphight+=40
}

to sum up

Through the development and design of the punch card app, we thoroughly understand the working mechanism of uniapp. At the same time, I also have some new ideas. It is like the points mentioned above to prepare for the resource app.
The next step is to develop a resource app. We earn points by punching cards, and then get the resources we need. Then we learn the punching resources step by step, and improve our ability by punching cards and acquiring resources. I hope that the app developed in the future can help everyone.

Published 71 original articles · 291 praises · 40,000+ views

Guess you like

Origin blog.csdn.net/lk888666/article/details/105681548