Note “university attendance system” small procedures (1) note “university attendance system” small procedures (2) note “university attendance system” small procedures (3)

The introduction



I. Sorting out functional requirements and planning ideas

  • 1. The user registers and logs in.
  • 2. Teacher and student curriculum information association, curriculum information viewing.
  • 3. Campus information release, check-in task release, leave management, user management.
  • 4. Add the weather and poster generation function.

Get the demand to think about in addition to registration and login, mainly divided into two blocks, one for the ordinary student user function, the second for the administrator teacher function. Because to display all in a small program, so consider adding ‘status’ field in user registration as a follow-up user permission judgment basis to display corresponding pages and functions. (also do not know this to do right 😢, big head)

Draw flow chart according to understanding


Ii. Building the overall layout of the project

The applets are divided into four parts, so first we create the corresponding tabbar in app.json.

  • The materials used in the Alibaba icon library (www.iconfont.cn)

Effect:


3. User registration and login

  • Before that, we need to open cloud development and create a collection of user information in the database.
  • Youzan.github. IO/vant-appellate/appellate /… www.color-ui.com/

Here, I created three new pages, namely the start animation transition page, the login page and the registration page.

Start the animation transition page:

  • The judgment as shown in the flow chart is made here: When the user opens a small program first entered the page transition, this page will get the user openid first, and then in the collection of database users to find whether there is a lot of, if the existing jump small program home page, if there is no jump to the login page, user registration authorization. (first time contact, wanted to think can only use this stupid method, If there is a good method please recommend to me 😘😘😘) before the method has a Bug, in this judge whether the user exists the code has been modified

Click to see the JS code
Page({data: {openID: ", // obtain user _openID panduan: ", // check whether arr: []}, onLoad: Function(options) {wx.cloud.callFunction({openid name: 'login', data: {}, }).then(res => { this.openid = res.result.openid }).then(res => { const db = wx.cloud.database({ env: 'env-urae8' // database environment name}) db.collection('users'). Where ({_openID: this. Openid, // check whether there is openID in database}). Function (res) {if (res.data.length == 0) {// Wx. redirectTo({url: '/pages/login/login'})} else if (res.data.length > 0) {wx.relaunch ({url: '/pages/index/index', }) } // console.log(res.data.length) } }) }) } })Copy the code


User login page:

  • User login, the first need to enter the registered student id and user authorization success, in this will determine whether the database input student ID openID is consistent with the current OpenID, meet the above three points to successfully log in, originally intended to do more verification to improve security, but did not expect to later audit to dig a big hole for yourself. Therefore, I set up an account to facilitate wechat audit (that is, there is no need to verify OpenID, the OpenID that wechat auditor logs in is inconsistent with the OpenID entered into the database during registration, so I was called back several times because of the wrong account number!! 😕 😒 😑)

Click to see the JS code
Page({ data: { userid:'', haveuserid:'no', openid: '', errMsg:'' }, onGotUserInfo(e){ this.data.errMsg = e.detail.errMsg if (e.detail.errMsg == 'getUserInfo:ok'){ this.setData({ userBtn: true, trueBtn:false }) } }, useridInput(e){ this.userid = e.detail.value }, LoginBtn (){this.data.haveuserId = 'no' const db = wx.cloud.database({// new user registration information for database env: 'env-urae8' }) db.collection('users').get().then(res => { for (let i = 0; i < res.data.length; i++) { if (res.data[i].userid === this.userid && res.data[i]._openid == this.openid) { this.data.haveuserid = 'yes' } } Var pattern = /^\d{6,12}$/ if(this.userid == '***'){switchTab({url: '/pages/index/index' }) }else if (pattern.test(this.userid) && this.data.haveuserid == 'yes' && this.data.errMsg == 'getUserInfo:ok'){ wx.switchTab({ url: '/pages/index/index' }) }else if (this.data.errMsg == 'getUserInfo:fail auth deny' || this.data.errMsg == '') { Wx. showToast({title: 'please authorize login again ', icon:' None ', duration: 2000})}else if (! Pattern. Test (this.userid)) {// Check if user name wx.showtoast ({title: 'please enter 6-12 digits ', icon:' None ', duration: 1500})}else if (this.data.haveUserId == 'no') {wx.showtoast ({title: 'error ', icon: 'none', duration: 2000 }) } }) }, registerBtn(){ wx.redirectTo({ url: '/pages/register/register' }) }, onLoad: Function(options) {this.setData({trueBtn:true}) wx.cloud.callFunction({// Get openID name: 'login', data: {}, success: res => { this.openid = res.result.openid }, fail: err => { wx.showToast({ icon: 'none', title: 'User info failed to get, please check network ',})}})Copy the code
<view> <view> <view class="input"> <image SRC =".. /.. /images/userimg. PNG "></image> <input class="inputBtn" bindinput="useridInput" placeholder=" <view class="userBtn"> <button hidden="{{ userBtn }}" open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="onGotUserInfo" class="onGotUserInfo"></button> <image hidden="{{ trueBtn }}" class="true" src=".. /.. /images/true. PNG "></image> <text class="userTit"> </text> </view> <button class="loginBtn shadow bG-blue" </button> <button class="registerBtn shadow bg-blue" bindtap="registerBtn"> </button> </view>Copy the code
Click to see the WXSS code
page {
    position: relative;
    background-color: white;
}
.title {
    margin-top: 200rpx;
    text-align: center;
    font-size: 40rpx;
}
.input{
    width: 60%;
    margin: 0 auto;
    margin-top: 120rpx;
    padding: 20rpx;
    border-radius: 10rpx;
    background-color: #f6f6f6;
    display: flex;
    justify-content: start;
}
.input image{
    width: 30rpx;
    height: 30rpx;
    margin-top: 6rpx;
    display: block;
}
.inputBtn {
    width: 100%;
    height: 40rpx;
    margin-left: 20rpx;
}
.loginBtn, .registerBtn {
    width: 400rpx;
    margin: 0 auto;
    background-color: #07c160;
    color: white;
    font-weight: 600;
}
.loginBtn {
    margin-bottom: 60rpx;
    margin-top: 60rpx;
}
.userBtn {
    margin-top: 160rpx;
    margin-left: 190rpx;
    display: flex;
    justify-content: flex-start;
}
.onGotUserInfo {
    width: 44rpx;
    height: 44rpx;
    border-radius: 20rpx;
    padding: 0;
    margin: 0;
    border: 6rpx solid #07c160;
}
.true{
    width: 44rpx;
    height: 44rpx;
}
.userTit{
    margin-left: 12rpx;
}
Copy the code


User registration page:

  • Youzan.github. IO/vtant-appellate/appellate/appellate/appellate/appellate/appellate/appellate… Here and login page similar logic, first determine input account registration will be in the database if there is a consistent student id and openid, if there is a prompt login directly, does not exist, it validate input account whether meet your requirements (I set of conditions is 6 to 12 digits), if meet all the conditions above, can be registered. Successful registration redirects to home page.

Click to see the JS code
const app = getApp() wx.cloud.init(); Page ({data: {steps: [{text: 'the first step, desc:' authorization login '}, {text: 'the second step, desc:' input '}, {text: 'the third step, desc: }], active: 0, nextOne: true, // first step hiddenName: false, // first step hiddenName: false, ", // user name avatarUrl: ", // user profile picture userStatus: "0", // user registration status step: 1, openID: ', haveUserId :'no', nextOne() {this.setData({active: 1, // the status is step 2 firstBoxHide: })}, onGotUserInfo(e) {this.setData({nickName: E.d etail. The userInfo. NickName, / / get the user name avatarUrl: e.d etail. The userInfo. AvatarUrl, / / to get head nextOne: False, // Next button shows hiddenName: true, // Authorize button to hide firstHide: False}) / / display user information. This nickName = e.d etail. The userInfo. NickName enclosing avatarUrl = e.d etail. The userInfo. AvatarUrl}, useridInput(e) { this.userid = e.detail.value }, SecondBtn () {this.data.haveuserId = 'no' const db = wx.cloud.database({// new user registration information for database env: 'env-urae8' }) db.collection('users').get().then(res => { for(var i = 0; i < res.data.length ; i++){ if (res.data[i].userid === this.userid || res.data[i]._openid == this.openid){ this.data.haveuserid = 'yes' } } Var pattern = /^\d{6,12}$/ if (! Pattern. Test (this.userid)) {// Check if user name wx.showtoast ({title: 'please enter 6-12 digits ', icon:' None ', duration: 1500})} else if (this.data.haveuserId == 'yes') {if (this.data.haveUserId == 'yes') { 'None ', duration: 1500}) this.setData({backBtn: false, // display return login button})} else {this.setdata ({secondBtn: True, // hide nextTwo: false // display the next button of the second frame})}})}, backBtn(){// return to the login page wx.redirectto ({url: '/pages/login/login' }) }, nextTwo() { this.setData({ userid: this.userid, nickName: this.nickName, avatarUrl: This. avatarUrl, secondBoxHide: true, // Hide second box thirdBoxHide: false, // Display third box nextTwo: true, // Hide next 2 button active: })}, thirdBtn() {// Complete registration button const db = wx.cloud.database({// add new user registration information to database env: 'env-urae8' }) db.collection('users').add({ data: { userid: this.userid, nickName: this.nickName, userStatus: this.data.userStatus }, success: res => { wx.switchTab({ url: '/pages/index/index' }) } }) }, onLoad: Function (options) {this.setData({active: 0, // Initial state is step 1 nextOne: true, // Hide next button firstHide: FirstBoxHide: false, // secondBoxHide: true, // secondBoxHide: true, // nextTwo: true, // secondBoxHide: thirdBoxHide: Openid if (this.data.step === 1 &&! this.data.openid) { wx.cloud.callFunction({ name: 'login', data: {}, success: res => { app.globalData.openid = res.result.openid this.step = 2, this.openid = res.result.openid }, fail: Err => {wx.showtoast ({icon: 'none', title: 'Failed to get user info, please check network ',})}})Copy the code
<view class="cont"> <view class="title"> Register </view> <view class="cont_box"> <van-steps class="van-steps" steps="{{steps }}" active="{{ active }}" active-color="#07c160" inactive-icon=".. /.. /images/true.png" /> </view> <view class="first" hidden="{{ firstBoxHide }}"> <view class="user_box" hidden="{{ firstHide }}"> <image class="avatarUrl" src="{{ avatarUrl }}"></image> </view> <view class="nickName" hidden="{{ firstHide }}">{{ nickName }}</view> <button hidden="{{hiddenName}}" open-type="getUserInfo" lang="zh_CN" Bindgetuserinfo ="onGotUserInfo" class="loginBtn shadow bg-blue"> <button > <button class="nextOne shadow bg-blue" </button> </view> <view class="second" hidden="{{secondBoxHide}}"> <input Class ="useridInput" bindinput="useridInput" placeholder=" placeholder "></input> <button class="secondBtn shadow bg-blue" Bindtap ="secondBtn" hidden="{{secondBtn}}"> </button> <button class="nextTwo shadow bg-blue" bindtap="nextTwo" Hidden ="{{nextTwo}}"> Next </button> <button class="backBtn shadow bG-blue "bindTap ="backBtn" hidden="{{backBtn" hidden="{{backBtn </button> <view class="third" hidden="{{thirdBoxHide}}"> <view class="user_box" > <image Class ="avatarUrl" SRC ="{{avatarUrl}}" </image> </view> <view class="nickName"> {{nickName}}</view> <view class="userid"> {{userid}}</view> <button class="thirdBtn shadow bg-blue" bindtap="thirdBtn">Copy the code
Click to see the WXSS code
page { width: 100%; height: 100%; position: relative; background-color: white; } .register_bg { position: absolute; width: 100%; height: 100%; top: 0; left: 0; } .cont { width: 100%; margin-top: 200rpx; color: black; z-index: 1; display: flex; justify-content: start; flex-direction: column; } .cont .title { font-size: 46rpx; text-align: center; margin-bottom: 60rpx; } .van-steps { width: 82%; margin: 0 auto; } .first, .second, .third { width: 100%; height: 500rpx; position: relative; text-align: center; } .first .user_box, .third .user_box { width: 160rpx; height: 160rpx; border-radius: 80rpx; margin: 0 auto; margin-top: 50rpx; position: relative; overflow: hidden; box-shadow:0 2rpx 4rpx rgba(0, 0, 0, .3); } .nickName{ height: 40rpx; line-height: 40rpx; margin-top: 26rpx; font-size: 30rpx; } .first .avatarUrl, .third .avatarUrl { width: 160rpx; height: 160rpx; position: absolute; top: 0; left: 0; } .first .success { margin-top: 20rpx; } .loginBtn, .nextOne, .nextTwo, .backBtn,.secondBtn,.thirdBtn { width: 240rpx; height: 80rpx; background-color: #07c160; color: white; line-height: 80rpx; text-align: center; font-size: 30rpx; font-weight: 600; border: none; position: absolute; bottom: 0; left: calc(50% - 120rpx); } .secondBtn{ bottom: 260rpx; } .backBtn { bottom: 130rpx; Background-color: RGB (255,255,255); background-color: RGB (255,255); background-color: RGB (255,255); background-color: RGB (255,255); background-color: transparent; border: none; padding: 0; margin: 0; line-height: 1; } button::after { border: none; background-color: transparent; }. Button-hover {color: rgba(0, 0, 0, 0.8); background-color: transparent; } .second .useridInput { width: 60%; height: 40rpx; padding: 20rpx; border-radius: 12rpx; margin: 50rpx auto; text-align: left; background-color: #f6f6f6; } .third .userid { margin-top: 30rpx; }Copy the code



Iv. Home page construction

  • Weather data from Avatar data, also compared with many interfaces, this relatively return data is considerable and the charge is affordable within the range www.avatardata.cn/.
  • The UI style references many other applets (Inkweather, Microweather, etc.); Weather mini module refer to juejin.cn/post/684490… ; Tencent Map API lbs.qq.com/qqmap_wx_js… ; Thanks for their help and refer to 👍👍👍

Let’s take a look at the finished renderings

  • 1. Obtain the information about the current location city.
    • In the early stage, Tencent Map registration and certification are required, key is obtained, and wechat small program JavaScript SDK is introduced into the project. For specific steps, please refer to Tencent Map API 👆 (see link above).
getUserLocation() { var qqmapsdk; var _this = this; Wx.getsetting ({// determine whether to authorize success(res) {wx.getLocation({type: 'gcj02', // return latitude and latitude available for wx.openLocation success(res) {// console.log(' authorized ') qqmapsdk = new QQMapWX({key: }) qqmapsdk.reverseGeocoder({location: {latitude: res.latitude, longitude: res.longitude }, AddressRes = addressres.result.ad_info.city; addressRes = addressres.result.ad_info. / / get the current city})}, fail (res) {the console. The log (res)}})}, fail (res) {/ / the console. The log (' unauthorized ')}}}}})),Copy the code
  • 2. Invoke the weather interface to obtain the current city weather data based on the obtained city information.
  • Wx. Request ({url: "https://api.avatardata.cn/Weather/Query?key= after you register the key value & cityname = '+ positioning for the city name, the header: {'content-type': 'application '// default value}, success(res) {// Return city weather data}})Copy the code
  • 3. Determine whether the display of the weather module is hidden based on the current weather status. Such as:
  • If (res.data.result.weather[I].info.day[1].indexof (' clear ') >= 0) {else if (res.data.result.weather[I].info.day[1].indexof (' clear ') >= 0) {if (res.data.result.weather[I].info.day[1].indexof (' clear ') >= 0) (res) data. The result. The weather [I] the info. The day [1]. The indexOf (' Yin ') > = 0 | | res. Data. The result. The weather [I] the info. The day [1]. The indexOf (' cloud ') > = 0) { Day [1].indexof (' light rain ') >= 0) {// Light rain gas module shows other hidden} else if (res.data.result.weather[I].info.day[1].indexof (' light rain ') >= 0) {// Light rain gas module shows other hidden} else if (res.data.result.weather[I].info.day[1].indexof (' rain ') >= 0) {// Rain gas module shows other hide} else if (res.data.result.weather[I].info.day[1].indexof (' snow ') >= 0) {Copy the code
  • 4. Because some of the returned interface data is unwanted, or I want to add some new pictures and text, so I rewrite the data into the form of object array, and finally render it. Take the following module for example
  • Let weather = [] weather.push({date: date, week: res.data.result.weather[I]. Week, // daywea: Daytemp: res.data.result.weather[I].info.day[1], // DayTemp: res.data.result.weather[I].info.day[2], // Daytemp: daywind: Daywind, // Daywind li: res.data.result.weather[I].info.day[4], // Daywind nightwea: Res.data.result.weather [I].info.night[1], // Night weather nighttemp: Res. Data. The result. The weather [I] info. Night [2], / / night temperature}) consloe. Log (weather) / / / / print results (5) [{...}, {...}, {...}, {...}, {...}] / / 0: {Date: "11-27", week: "3 ", DayWEa:" light rain ", DayTemp: "10", Daywind: "west wind ", DayWindli: "4-5 ", NightTemp: "8", NightWEa: "8", Daywea: "10", DayWind:" West wind ", DayWindli: "4-5" "Rain" week, "three"} / / 1: {date: 11-28, week: "four", daywea: "cloudy", daytemp: "ten," daywind: "west wind",... } / / 2: {date: 11-29, week: "five," daywea: "Yin", daytemp: "11", daywind: "northeaster,"... } / / 3: {date: "11-30", the week: "six," daywea: "rain," daytemp: "13", daywind: "calm",... } / / 4: {date: 12-01, week: "day", daywea: "Yin", daytemp: "11", daywind: "west wind",... }Copy the code


    First write here, if there is any bad place, please point out and discuss, we will continue to share the following content. You can also scan the code in advance to view the small program, welcome to point out the shortcomings, thank you 🌞😃😃😃