微信小程序Demo: 微信小程序考勤打卡示例

您所在的位置:网站首页 个人记录上班考勤的app 微信小程序Demo: 微信小程序考勤打卡示例

微信小程序Demo: 微信小程序考勤打卡示例

2023-11-24 19:08| 来源: 网络整理| 查看: 265

页面效果展示

集成腾讯地图SDK

腾讯位置服务为微信小程序提供了基础的标点能力、线和圆的绘制接口等地图组件和位置展示、地图选点等地图API位置服务能力支持,使得开发者可以自由地实现自己的微信小程序产品。 在此基础上,腾讯位置服务微信小程序JavaScript SDK是专为小程序开发者提供的LBS数据服务工具包,可以在小程序中调用腾讯位置服务的POI检索、关键词输入提示、地址解析、逆地址解析、行政区划和距离计算等数据服务,让您的小程序更强大!

文档地址:微信小程序JavaScript SDK

使用步骤说明:

1.申请开发者密钥(key):申请密钥 2.开通webserviceAPI服务

控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebServiceAPI -> 保存

(小程序SDK需要用到webserviceAPI的部分服务,所以使用该功能的KEY需要具备相应的权限)

3.下载微信小程序JavaScriptSDK

微信小程序JavaScriptSDK v1.1 JavaScriptSDK v1.2 ,这里推荐下载1.2版本,将下载好的SDK放在对应文件夹中,去引用它(即 qqmap-wx-jssdk.min.js 文件)引用到你小程序项目中。

4.安全域名设置

在小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加https://apis.map.qq.com

这个操作需要小程序管理员进到后台去配置 本地环境开发只需设置 勾上 不校验合法域名 即可

5.小程序核心代码示例 // 引入SDK核心类,js文件根据自己业务,位置可自行放置 var QQMapWX = require('../../libs/qqmap-wx-jssdk.js'); var qqmapsdk; Page({ onLoad: function () { // 实例化API核心类 qqmapsdk = new QQMapWX({ key: '申请的key' }); }, onShow: function () { // 调用接口 qqmapsdk.search({ keyword: 'DreamCoders', success: function (res) { console.log(res); }, fail: function (res) { console.log(res); }, complete: function (res) { console.log(res); } }); } }) 微信小程序代码

wx.getLocation(Object object)

功能描述 获取当前的地理位置、速度。当用户离开小程序后,此接口无法调用。开启高精度定位,接口耗时会增加,可指定 highAccuracyExpireTime 作为超时时间。地图相关使用的坐标格式应为 gcj02。 高频率调用会导致耗电,如有需要可使用持续定位接口 wx.onLocationChange。 基础库 2.17.0 版本起 wx.getLocation 增加调用频率限制,相关公告。

使用方法 自 2022 年 7 月 14 日后发布的小程序,若使用该接口,需要在 app.json 中进行声明,否则将无法正常使用该接口,2022年7月14日前发布的小程序不受影响。具体规则见公告

申请开通 暂只针对如下类目的小程序开放,需要先通过类目审核,再在小程序管理后台,「开发」-「开发管理」-「接口设置」中自助开通该接口权限。 接口权限申请入口将于2022年3月11日开始内测,于3月31日全量上线。并从4月18日开始,在代码审核环节将检测该接口是否已完成开通,如未开通,将在代码提审环节进行拦截。

微信小程序获取定位关键方法 getLocation。因此需要在 app.json 中进行声明,后期小程序上线还需要单独申请getLocation 接口权限。

app.json 部分关键代码 { "pages": [ "pages/index/index", "pages/sign/sign" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "Weixin", "navigationBarTextStyle": "black" }, "tabBar": { "custom": false, "backgroundColor": "#fefefe", "color": "#999999", "selectedColor": "#1C9D9D", "list": [{ "pagePath": "pages/index/index", "text": "首页", "iconPath": "/images/home.png", "selectedIconPath": "/images/home_cur.png" }, { "pagePath": "pages/sign/sign", "text": "打卡", "iconPath": "/images/day.png", "selectedIconPath": "/images/day_cur.png" }, { "pagePath": "pages/index/index", "text": "我的", "iconPath": "/images/my.png", "selectedIconPath": "/images/my_cur.png" } ] }, "permission": { "scope.userLocation": { "desc": "您的位置信息将用于小程序考勤签到功能" } }, "requiredPrivateInfos":[ "getLocation" ], "style": "v2", "sitemapLocation": "sitemap.json", "lazyCodeLoading": "requiredComponents" } sign.wxml代码 DreamCoders {{tip}} 新的一天开始了,加油哦~ {{is_meal==2 ? '已订':'订餐'}} 上班打卡 {{record[0].times ? record[0].times : '未打卡'}} {{record[0].address ? record[0].address : '暂无打卡地址'}} 下班打卡 {{record[1].times ? record[1].times : '未打卡'}} {{record[1].address ? record[1].address : '暂无打卡地址'}} {{nowDate}} {{nowDay}} {{signType>0 ? "下班打卡" : "上班打卡"}} {{now_time}} 已打卡 {{now_time_stop}} {{current_address}} 刷新位置 sign.js代码 let qqMapSdk= require("../../utils/qqmap.js"); let util = require('../../utils/util.js') Page({ /** * 页面的初始数据 */ data: { signType:0,//0上班打卡 1下班打卡 is_out:2,//1办公地点打卡 2外勤打卡 is_meal:1,//1未定餐 2已订餐 now_time: '',//当前时间 nowDate:'',//当前年月日 nowDay:'',//星期几 tip:'',//提示 上午好、下午好 current_address: '',//当前定位地址 status: 0, //0未打卡 1已打卡 latlng:[],//经纬度 now_time_stop: '', //已打卡时间 area:{},//考勤点多个 record:[],//打卡记录 }, onLoad: function (options) { this.getCurrentTime(); this.setData({ now_time: this.getTime(), nowDate: util.formatTime(new Date()), nowDay: util.formatDay(new Date()), tip: util.formatSole(), }) }, onShow: function () { this.getLocation(); this.setData({ status:0, current_address:'', }) }, signTap() { var that = this; if (!that.data.current_address) { return wx.showToast({ title: '未获取当前定位', icon: 'error' }) } var list = that.data.record.concat({'times':that.data.now_time,'address':that.data.current_address}); wx.vibrateLong();//手机震动提示 that.getSignRecord(); that.setData({ status: 1, //已打卡 record:list, now_time_stop: that.data.now_time, }) console.log(list); console.log(that.data.record); wx.showToast({ title: '打卡成功', icon: 'none' }) }, getCurrentTime: function () { var time = setInterval(() => { this.setData({ now_time: this.getTime() }) }, 1000) }, getTime() { let dateTime = ''; let hh = new Date().getHours() let mf = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes() let ss = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds() dateTime = hh + ':' + mf + ':' + ss; return dateTime; }, // 请求获取定位授权 getUserAuth: function () { return new Promise((resolve, reject) => { wx.authorize({ scope: 'scope.userLocation' }).then(() => { resolve() }).catch(() => { let that = this; wx.getSetting({ success: (res) => { if (res.authSetting['scope.userLocation'] != undefined && res.authSetting['scope.userLocation'] != true) { wx.showModal({ title: '请求授权当前位置', content: '需要获取您的地理位置,请确认授权', success: function (res) { if (res.cancel) { wx.showToast({ title: '拒绝授权', icon: 'none', duration: 1000 }) } else if (res.confirm) { wx.openSetting({ success: function (dataAu) { if (dataAu.authSetting["scope.userLocation"] == true) { //再次授权,调用wx.getLocation的API that.getLocation(); } else { wx.showToast({ title: '授权失败', icon: 'none', duration: 1000 }) } } }) } } }) } else if (res.authSetting['scope.userLocation'] == undefined) { that.getLocation(); } else { that.getLocation(); } } }) }) }) }, getLocation: function () { const that = this // 实例化腾讯地图API核心类 const QQMapWX = new qqMapSdk({ key: '你申请的KEY'// KEY必填 }); //获取当前位置 wx.getLocation({ type: 'gcj02', success: function(res) { that.latitude = res.latitude that.longitude = res.longitude QQMapWX.reverseGeocoder({ location: { latitude: res.latitude, longitude: res.longitude }, success: function(res) { let address = res.result.address + res.result.formatted_addresses.recommend; that.getSignRecord(); that.setData({ current_address:address, latlng:[res.result.location.lat,res.result.location.lng] }) }, fail: function(res) { this.getUserAuth() wx.showToast({ title: '获取定位失败,请打开手机定位,重新进入!', icon: 'none' }); } }) }, }) }, // 刷新定位 refreshAdd() { this.getLocation(), this.getSignRecord() }, //处理打卡记录及判断打卡位置是否办公地点打卡 getSignRecord: function () { var that = this; console.log(that.data.latlng); var distance = that.getDistance(that.data.latlng[0],that.data.latlng[1],31.370450,121.228252); if(distance < 200000000000000){ that.setData({ is_out:1, }) } }, //经纬度距离计算 getDistance:function (lat1, lng1, lat2, lng2, unit = false) { var radLat1 = lat1 * Math.PI / 180.0 var radLat2 = lat2 * Math.PI / 180.0 var a = radLat1 - radLat2 var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0 var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))) s = s * 6378.137 // EARTH_RADIUS; s = Math.round(s * 10000) / 10000 //输出为公里 if (0) { //是否返回带单位 if (s < 1) { //如果距离小于1km返回m s = s.toFixed(3) s = s * 1000 + "m" } else { s = s.toFixed(2) s = s + "km" } } else { s = s.toFixed(3) s = s * 1000 } return s }, //订餐操作 ToMealTap:function (e) { wx.showToast({ title: '订餐成功', icon: 'none' }) this.setData({ is_meal: 2, }) } })

sign.json 代码

{ "usingComponents": {}, "navigationBarTitleText": "考勤打卡" } sign.wxss 代码 page { height: calc(100% - 10px) } .index { margin-top: 10px; background: #fff; min-height: 100%; } .head { padding-bottom: 10rpx; border-bottom: 2rpx solid #E5E5E5; } .head_box { padding: 26rpx 28rpx 8px; width: 750rpx; box-sizing: border-box; } .user_ava { width: 116rpx; height: 116rpx; overflow: hidden; border-radius: 25%; margin-right: 32rpx; } .user_name { font-size: 32rpx; font-weight: 600; color: #333333; margin-bottom: 18rpx; } .user_name text { font-size: 24rpx; color: #999999; font-weight: 400; margin-left: 40rpx; } .user_add { font-size: 28rpx; color: #3380F3; } .contentBox { padding: 44rpx 28rpx; } .signRecord{ display: flex; flex-flow: row nowrap; justify-content: space-between; margin-top: 15px; } .dateInfo{ text-align: center; position: relative; top: 50px; font-size: 35rpx; } .c_title { font-size: 28rpx; color: #666666; margin-bottom: 26rpx; } .c_section .c_item { position: relative; font-size: 30rpx; font-weight: 600; color: #333333; padding-left: 40rpx; margin-bottom: 110rpx; } .c_section text { color: #307CED; text-overflow: ellipsis; overflow: hidden; width: 80%; white-space: nowrap; } .c_section .c_item::before { content: ''; position: absolute; width: 18rpx; height: 18rpx; border: 2rpx solid #999999; left: 0; top: 50%; margin-top: -9rpx; border-radius: 50%; } .c_section { position: relative; } .c_section .c_item::after { content: ''; position: absolute; width: 2rpx; height: 178rpx; background: #E6E6E6; left: 10rpx; top: 34rpx; } .c_section view:last-child::after { display: none; } .start_lo { position: absolute; top: 30px; left: -5px; } .start_end { position: absolute; bottom: -108px; left: 20px; } .c_clock { margin: 180rpx auto 0; width: 350rpx; height: 380rpx; perspective: 1500; -webkit-perspective: 1500; -moz-perspective: 1500; } .clock_time { width: 350rpx; height: 350rpx; margin-bottom: 30rpx; position: absolute; transition: all 1s; backface-visibility: hidden; } .clock_time::after { content: ''; top: 0; left: 0; width: 350rpx; height: 350rpx; border-radius: 50%; position: absolute; z-index: 9; background: rgba(48, 124, 237, 0.08); animation: scale 1s infinite alternate-reverse; } /* 已打卡 */ .clock_time_over { width: 350rpx; height: 350rpx; margin-bottom: 30rpx; border-radius: 50%; background: rgba(48, 124, 237, 0.08); position: absolute; transition: all 1s; backface-visibility: hidden; transform: rotateY(-180deg); } .clock_time_over::after { position: absolute; z-index: 11; content: ''; width: 320rpx; height: 320rpx; background: #C6CED9; border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); } .clock_time_over text { position: relative; z-index: 13; color: #FFFFFF; } .clock_time_over text:first-child { font-size: 36rpx; margin-bottom: 14rpx; } .clock_time_over text:last-child { font-size: 28rpx; } @keyframes scale { 0% { transform: scale(1.1); } 100% { transform: scale(1); } } .clock_time::before { position: absolute; z-index: 11; content: ''; width: 320rpx; height: 320rpx; background: rgb(48, 124, 237, 0.79); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); } .clock_time text { position: relative; z-index: 13; color: #FFFFFF; } .clock_time text:first-child { font-size: 36rpx; margin-bottom: 14rpx; } .clock_time text:last-child { font-size: 45rpx; } .clock_address { text-align: center; font-size: 30rpx; color: #333333; width: 80%; margin: 20px auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .clock_address text { vertical-align: middle; } .add_icon { width: 28rpx; height: 36rpx; margin-right: 16rpx; vertical-align: middle; } .refresh { margin-top: 25px; color: #307CED; display: flex; align-items: center; justify-content: center; } .now_location { font-size: 24rpx; color: #333333 !important; } .upload_box { width: 260rpx; height: 180rpx; background: #F5F5F8; border-radius: 5rpx; } .upload_box text { font-size: 20rpx; color: #999 !important; font-weight: 100; } .camera_icon { width: 42rpx; height: 44rpx; margin-bottom: 10rpx; } .clock_img { width: 100%; height: 100%; } .del_icon { width: 32rpx; height: 32rpx; position: absolute; right: -4px; top: -11rpx; } .ative::before { background: #307cedc9; border: 2rpx solid #307cedc9 !important; } .c1 { transform: rotateY(180deg) } .c1::after { animation: none !important; } .c2 { transform: rotateY(0deg) } .mealBtn{ position: absolute; right: 15px; } .mealBtn image{ width: 27px; height: 27px; } .mealText{ font-size: 12px; color: #999999; } .outArea::before{ background: #f44336 !important; } .signInfo{ width: 48%; height: 65px; background: #f1f1f1; padding: 10px; border-radius: 5px; } .signInfo text{ float: inline-end; } .sign_address{ display: flex; margin-top: 5px; } .sign_address view{ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; font-size: 14px; margin-top: 1px !important; color: #5f5a5a; } .text-green{ color: green; } util.js 代码 function formatTime(date) { var year = date.getFullYear() var month = date.getMonth() + 1 var day = date.getDate() return year + "年" + month + "月" + day + "日"; } const formatDay = dates => { let _day = new Array('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'); let date = new Date(dates); date.setDate(date.getDate()); let day = date.getDay(); return _day[day]; } const formatSole = () => { let timeNow = new Date(); let hours = timeNow.getHours(); let text = ``; if (hours >= 0 && hours 6 && hours 8 && hours 10 && hours 13 && hours 17 && hours


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3