Переглянути джерело

app 考勤打卡

黑艺新账号
yxq 1 рік тому
джерело
коміт
ed17c5650d
4 змінених файлів з 378 додано та 285 видалено
  1. +2
    -0
      Learun.Framework.Ultimate V7/LearunApp-2.2.0/App.vue
  2. +1
    -0
      Learun.Framework.Ultimate V7/LearunApp-2.2.0/common/js/weixin-js-sdk.js
  3. +79
    -0
      Learun.Framework.Ultimate V7/LearunApp-2.2.0/common/wxFn.js
  4. +296
    -285
      Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/AttendanceCard/list.vue

+ 2
- 0
Learun.Framework.Ultimate V7/LearunApp-2.2.0/App.vue Переглянути файл

@@ -5,6 +5,8 @@
// 考虑到用户刷新网页时会丢失全局数据、页面栈、页面数据等,因此直接跳回首页即可

async onLaunch(param) {
// 在App.vue文件中获取到页面到URL (初始化WXsdj)
window.localStorage.setItem('scanUrl',location.href.split('#')[0])
//应用的生命周期 应用启动后触发
// #ifdef H5 || APP-VUE
// H5 刷新时获取当前页面路径


+ 1
- 0
Learun.Framework.Ultimate V7/LearunApp-2.2.0/common/js/weixin-js-sdk.js
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 79
- 0
Learun.Framework.Ultimate V7/LearunApp-2.2.0/common/wxFn.js Переглянути файл

@@ -0,0 +1,79 @@
import wx from '@/common/js/weixin-js-sdk.js';
export default {
methods: {
data(){
return {
wxInit:false
}
},
// 初始化wx
initWx(arr = ["getLocation"]) {
const promise = new Promise((resolve, reject) => {
// let url = window.location.href
let url = /(Android)/i.test(navigator.userAgent) ? location.href.split('#')[0] : window
.localStorage
.getItem('scanUrl')
this.HTTP_GET("weixinapi/getweixinwebaccess_token?url=" + encodeURIComponent(url)).then((
success) => {
if (!success) {
resolve(false)
return
}
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: success.appid, // 必填,公众号的唯一标识
timestamp: success.timestamp, // 必填,生成签名的时间戳
nonceStr: success.noncestr, // 必填,生成签名的随机串
signature: success.certificate, // 必填,签名
jsApiList: arr // 必填,需要使用的JS接口列表
});
wx.ready(() => {
this.wxInit = true
this.TOAST("wx初始化成功")
resolve(true)
})
wx.error(() => {
this.TOAST("wx初始化失败")
resolve(false)
})
})
})
return promise
},
// 获取定位
async getLocation() {
return new Promise(async (resolve) => {
if (!this.wxInit) {
let res = await this.initWx(["getLocation"])
if(!res){
resolve(false)
return
}
}
if(!wx.getLocation){
this.TOAST("无效方法")
resolve(false)
}
wx.getLocation({
type: "gcj02", // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: function(res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
console.log(res)
resolve({
lat:latitude,
lng:longitude
})
},
fail: function(error) {
this.TOAST("定位失败")
resolve(false)
}
});
})
}

}
}

+ 296
- 285
Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/AttendanceCard/list.vue Переглянути файл

@@ -1,305 +1,316 @@
<template>
<view class="">
<view v-if="ready" class="contentBox">
<view class="rules">
<view class="">
<template>
<view class="">
<view v-if="ready" class="contentBox">
<view class="rules">
<view class="">
上班 {{info.WorkTime}}
<view class="">
上班 {{info.WorkTime}}
</view>
<view class="">
{{info.UserWorkTime?info.UserWorkTime.substring(8)+' 打卡':'未打卡'}}
</view>
</view>
<view class="">
{{info.UserWorkTime?info.UserWorkTime.substring(8)+' 打卡':'未打卡'}}
<view class="">
下班 {{info.CloseTime}}
</view>
<view class="">
{{info.UserCloseTime?info.UserCloseTime.substring(8)+' 打卡':'未打卡'}}
</view>
</view>
</view>
<view class="">
<view class="">
下班 {{info.CloseTime}}
<view class="content" id="attendContent">
<view id="show">{{now}}</view>
<view class="pen" @click="action('dk')">
<img :class="{gray:info.AttendanceType != 1}" id="attimg" :src="imgsrc" alt="" width="100%">
</view>
<view class="">
{{info.UserCloseTime?info.UserCloseTime.substring(8)+' 打卡':'未打卡'}}
<view class="title">
{{info.AttendanceTypeString}}
</view>
</view>
</view>
<view class="content" id="attendContent">
<view id="show">{{now}}</view>
<view class="pen" @click="action('dk')">
<img :class="{gray:info.AttendanceType != 1}" id="attimg" :src="imgsrc" alt="" width="100%">
</view>
<view class="title">
{{info.AttendanceTypeString}}
<view class="footer">
<img src="../../common/images/2.png" alt="" width="100%">
</view>
</view>
<view class="footer">
<img src="../../common/images/2.png" alt="" width="100%">
</view>
</view>
<view id='container'></view>
</view>
</template>
<script>
/*
* 版 本 Learun-ADMS V7.0.3 力软敏捷开发框架(http://www.learun.cn)
* Copyright (c) 2013-2020 上海力软信息技术有限公司
* 创建人:超级管理员
* 日 期:2022-03-10 15:30
* 描 述:考勤打卡
*/
/**
* 本段代码由移动端代码生成器输出,移动端须 2.2.0 版本及以上可以使用
* 请在移动端 /pages.json 中的 pages 字段中添加一条记录:
* { "path": "pages/AttendanceCard/list", "style": { "navigationBarTitleText": "考勤打卡" } }
*
* (navigationBarTitleText 字段为本页面的标题文本,可以修改)
* (必须自行操作该步骤,力软代码生成器不会自动帮您修改 /pages.json 文件)
*/
import get from 'lodash/get'
import set from 'lodash/set'
import moment from 'moment'
import customPageMixins from '@/common/custompage.js'
//导入图片
import dk from '../../common/images/dk.png'
import dkred from '../../common/images/dkred.png'
import dkyellow from '../../common/images/dkyellow.png'
export default {
mixins: [customPageMixins],
data() {
return {
// 页面相关参数
info:{},
now: null,
imgsrc:dk,
ready: false,
timer:'',
map:null,
}
},
async onLoad() {
await this.init()
},
methods: {
// 页面初始化
async init() {
this.LOADING('加载数据中...')
this.now = this.getCurrentTime()
this.timer = setInterval(this.getCurrentTime,1000)
await this.judgeIsDK()
this.ready = true
this.HIDE_LOADING()
},
// 点击 「打卡」按钮
async action(type) {
switch (type) {
case 'dk':
if(this.imgsrc == dkred){
return
<view id='container'></view>
</view>

</template>


<script>
/*
* 版 本 Learun-ADMS V7.0.3 力软敏捷开发框架(http://www.learun.cn)
* Copyright (c) 2013-2020 上海力软信息技术有限公司
* 创建人:超级管理员
* 日 期:2022-03-10 15:30
* 描 述:考勤打卡
*/

/**
* 本段代码由移动端代码生成器输出,移动端须 2.2.0 版本及以上可以使用
* 请在移动端 /pages.json 中的 pages 字段中添加一条记录:
* { "path": "pages/AttendanceCard/list", "style": { "navigationBarTitleText": "考勤打卡" } }
*
* (navigationBarTitleText 字段为本页面的标题文本,可以修改)
* (必须自行操作该步骤,力软代码生成器不会自动帮您修改 /pages.json 文件)
*/

import get from 'lodash/get'
import set from 'lodash/set'
import moment from 'moment'
import customPageMixins from '@/common/custompage.js'
import wxFn from '@/common/wxFn.js'
//导入图片
import dk from '../../common/images/dk.png'
import dkred from '../../common/images/dkred.png'
import dkyellow from '../../common/images/dkyellow.png'

export default {
mixins: [customPageMixins, wxFn],

data() {
return {
// 页面相关参数
info: {},
now: null,
imgsrc: dk,
ready: false,
timer: '',
map: null,
}
this.LOADING()
this.HTTP_POST('learun/adms/attendance/clockin', {}, '打卡失败').then(success => {
},

async onLoad() {
await this.init()
},

methods: {
// 页面初始化
async init() {
this.LOADING('加载数据中...')

this.now = this.getCurrentTime()
this.timer = setInterval(this.getCurrentTime, 1000)
await this.judgeIsDK()

this.ready = true
this.HIDE_LOADING()
if(!success) {
this.TOAST('打卡失败')
},

// 点击 「打卡」按钮
async action(type) {
switch (type) {
case 'dk':
if (this.imgsrc == dkred) {
return
}
this.LOADING()
this.HTTP_POST('learun/adms/attendance/clockin', {}, '打卡失败').then(success => {
this.HIDE_LOADING()
if (!success) {
this.TOAST('打卡失败')
return
}
this.TOAST('打卡成功', 'success')
setTimeout(this.back, 500)

})
return

default:
break
}
},
//获取打卡信息
async judgeIsDK() {
let success = await this.HTTP_GET('learun/adms/attendance/IsAttendance', {}, '判断当前时间是否可以打卡失败')
if (!success) {
return
}
this.TOAST('打卡成功','success')
setTimeout(this.back,500)
})
return
default: break
}
},
//判断当前时间是否可以打卡
async judgeIsDK(){
let success = await this.HTTP_GET('learun/adms/attendance/IsAttendance',{},'判断当前时间是否可以打卡失败')
if(!success){return}
this.info = success.data
this.imgsrc=dk;
// if ([1].includes(this.info.AttendanceType)) {
// this.imgsrc=dk;
// } else if ([2,3].includes(this.info.AttendanceType)) {
// this.imgsrc=dkyellow;
// }else {
// this.imgsrc=dkred;
// }
if(![5].includes(this.info.AttendanceType)){
if(!window.BMapGL) await this.loadJScript()
this.map = new BMapGL.Map('container');
await this.isFieldPersonnel()
}
},
//返回
back(){
this.NAV_BACK()
},
//获取当前时间
getCurrentTime() {
let nowDate = new Date();
  let hh = nowDate.getHours();
  let mf = nowDate.getMinutes()<10 ? '0'+nowDate.getMinutes() : nowDate.getMinutes();
  let ss = nowDate.getSeconds()<10 ? '0'+nowDate.getSeconds() : nowDate.getSeconds();
  this.now = hh+':'+mf+':'+ss;
},
// 判断是否外勤打卡
async isFieldPersonnel(){
let point = new BMapGL.Point(this.info.GPSLon,this.info.GPSLat)
await this.getDistance(point)
},
//异步加载地图
loadJScript() {
return new Promise((resolve,reject)=>{
window.initMap = function(){
resolve(BMapGL)
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://api.map.baidu.com/api?v=1.0&type=webgl&ak=j1TvNK854LRvVuxuAhNNxdhKVB0KbEZD'+'&callback='+'initMap';
script.onerror = reject
document.head.appendChild(script);
})
},
// 计算距离打卡点的距离
// 签到状态(1正常打卡,2迟到打卡,3早退打卡,4外勤打卡,5不在考勤时间范围)
async getDistance(myP1) {
// new BMapGL.Point(116.404, 39.915)
let myP2 = await this.local();
if(!myP2) {
this.TOAST('获取定位失败!')
return
}
let distance = this.map.getDistance(myP1, myP2).toFixed(2)
console.log('距离',distance,'打卡坐标:',myP1,'当前坐标:',myP2)
if(Number(distance) > Number(this.info.GPSRange)){
this.$set(this.info,'AttendanceType',4)
this.$set(this.info,'AttendanceTypeString','外勤打卡')
}
},
// 获取当前位置
local() {
return new Promise((resolve) => {
let that = this
uni.getLocation({
type: 'gcj02',
isHighAccuracy:true,
success(res) {
// let point = new BMapGL.Point(res.longitude,res.latitude)
// console.log(point)
new BMapGL.Convertor().translate([{lng: res.longitude, lat: res.latitude}], 3, 5, data => {
resolve(data.points[0])
}
this.info = success.data
this.imgsrc = dk;
// if ([1].includes(this.info.AttendanceType)) {
// this.imgsrc=dk;
// } else if ([2,3].includes(this.info.AttendanceType)) {
// this.imgsrc=dkyellow;
// }else {
// this.imgsrc=dkred;
// }
if (![5].includes(this.info.AttendanceType)) {
if (!window.BMapGL) await this.loadJScript()
this.map = new BMapGL.Map('container');
await this.isFieldPersonnel()
}
},
//返回
back() {
this.NAV_BACK()
},
//获取当前时间
getCurrentTime() {
let nowDate = new Date();
let hh = nowDate.getHours();
let mf = nowDate.getMinutes() < 10 ? '0' + nowDate.getMinutes() : nowDate.getMinutes();
let ss = nowDate.getSeconds() < 10 ? '0' + nowDate.getSeconds() : nowDate.getSeconds();
this.now = hh + ':' + mf + ':' + ss;
},
// 判断是否外勤打卡
async isFieldPersonnel() {
let point = new BMapGL.Point(this.info.GPSLon, this.info.GPSLat)
await this.getDistance(point)
},
//异步加载地图
loadJScript() {
return new Promise((resolve, reject) => {
window.initMap = function() {
resolve(BMapGL)
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src =
'https://api.map.baidu.com/api?v=1.0&type=webgl&ak=j1TvNK854LRvVuxuAhNNxdhKVB0KbEZD' +
'&callback=' + 'initMap';
script.onerror = reject
document.head.appendChild(script);
})
},
fail(){
resolve(false)
}
});
});
},
},
destroyed() {
clearInterval(this.timer)
}
}
</script>
},
// 计算距离打卡点的距离
// 签到状态(1正常打卡,2迟到打卡,3早退打卡,4外勤打卡,5不在考勤时间范围)
async getDistance(myP1) {
// new BMapGL.Point(116.404, 39.915)
let myP2 = await this.local();
if (!myP2) {
this.TOAST('获取定位失败!')
return
}
let distance = this.map.getDistance(myP1, myP2).toFixed(2)
console.log('距离', distance, '打卡坐标:', myP1, '当前坐标:', myP2)
if (Number(distance) > Number(this.info.GPSRange)) {
this.$set(this.info, 'AttendanceType', 4)
this.$set(this.info, 'AttendanceTypeString', '外勤打卡')
}
},
// 获取当前位置
local() {
return new Promise(async (resolve) => {
let res = await this.getLocation()
if (!res) {
resolve(false)
}
new BMapGL.Convertor().translate([res], 3, 5, data => {
if(res.status = 0){
alert(res.points[0].lng)
resolve(res.points[0])
}else{
resolve(false)
}
})
});
},
},
destroyed() {
clearInterval(this.timer)
}
}
</script>

<style lang="less">
uni-page-body {
height: 100%;
width: 100%;
background-color: #fff;
}

.content {
width: 48%;
height: 50%;
position: absolute;
top: 15%;
left: 50%;
transform: translate(-50%, 10%);
}

.title {
font-size: 14px;
text-align: center;
color: #333;
margin-top: 8px;
}

.rules {
display: flex;
justify-content: space-between;
color: #666;
padding: 15px;
line-height: 24px;
}

.rules>* {
width: 49%;
background-color: #BDE4FF;
padding: 8px;
border-radius: 8px 12px;
}

.rules>*>*:first-child {
color: #333;
}

#show {
text-align: center;
height: 200rpx;
font-size: 56rpx;
}

<style lang="less">
uni-page-body{
height: 100%;
width: 100%;
background-color: #fff;
}
.content {
width: 48%;
height: 50%;
position: absolute;
top: 15%;
left: 50%;
transform: translate(-50%, 10%);
}
.title{
font-size: 14px;
text-align: center;
color: #333;
margin-top: 8px;
}
.rules{
display: flex;
justify-content: space-between;
color: #666;
padding: 15px;
line-height: 24px;
}
.rules>*{
width: 49%;
background-color: #BDE4FF;
padding: 8px;
border-radius: 8px 12px;
}
.rules>*>*:first-child{
color: #333;
}
#show {
text-align: center;
height: 200rpx;
font-size: 56rpx;
}
.pen {
// height: 48%;
border-radius: 50%;
background-color: #e7f5ff;
display: flex;
align-items: center;
justify-content: center;
}

.pen {
// height: 48%;
border-radius: 50%;
background-color: #e7f5ff;
display: flex;
align-items: center;
justify-content: center;
}
.pen2 {
width: 91%;
height: 91%;
border-radius: 50%;
background-color: #bde4ff;
display: flex;
align-items: center;
justify-content: center;
}

.pen2 {
width: 91%;
height: 91%;
border-radius: 50%;
background-color: #bde4ff;
display: flex;
align-items: center;
justify-content: center;
}
.pen3 {
width: 84%;
height: 84%;
border-radius: 50%;
background-color: #0c86d8;
text-align: center;
font-size: 68rpx;
display: flex;
align-items: center;
justify-content: center;
color: #ffff;
}

.pen3 {
width: 84%;
height: 84%;
border-radius: 50%;
background-color: #0c86d8;
text-align: center;
font-size: 68rpx;
display: flex;
align-items: center;
justify-content: center;
color: #ffff;
}
.footer {
width: 100%;
position: fixed;
left: 0;
bottom: 0;
overflow: hidden;
}

.footer {
width: 100%;
position: fixed;
left: 0;
bottom: 0;
overflow: hidden;
}
.gray{
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
filter: gray;
}
.gray {
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
filter: gray;
}
</style>

Завантаження…
Відмінити
Зберегти