<template>
<div class="punch">
<section class="goTip" :class="{'radar': punched || syncTimeLoading}" @click="confirmPunch">
<div class="circle">
<p v-text="text"></p>
<p>{{currentTimeText}}</p>
</div>
</section>
<section class="position">
<van-icon size=".48rem" color="#c4c7cc" name="location"/>
<p v-text="gps.address?gps.address:$t('lang.noGps')"></p>
<div v-show="!gps.address" @click="getAndLocation">{{$t('lang.getGps')}}</div>
</section>
</div>
</template>
<script>
export default {
name: 'Punch',
data() {
return {
gps: {
address: '',
longitude: '',
latitude: ''
},
syncTimeLoading:true,//同步时间中
gpsLoading: false,//获取GPS中
currentTimeText: ''
}
},
props: {
text: {// 上班 下班
type: String,
default: '出乘'
},
punched: { //是否打过卡
type: Boolean,
default: false
},
currentTime: {//当前时间
type: String,
default: () => {
return '00:00:00'
}
}
},
watch: {
'currentTime': function (value) {
if (!this.punched) {
this.currentTimeText = value;
}
}
},
methods: {
getPosition() {
//TODO
},
getAndLocation() { //从android 获取 地理位置
if (!this.gpsLoading) {
this.gpsLoading = true;
}
//TODO
},
openGPSSetting() { //打开GPS
//TODO
},
confirmPunch() {
if(this.punched || this.syncTimeLoading ){//已打卡,时间获取中 均不能打卡
return;
}
if(this.gpsLoading){//gps定位中
this.$toast('定位中,请稍后重试');
return;
}
if(!this.gps.address){ //定位失败
this.$toast('定位失败,请先获取定位');
return;
}
let message = this.text === '出乘' ? `是否确定出乘?` : '退乘打卡后不可继续编辑报告\n是否确定?';
this.$dialog.confirm({
title: '提示',
className: 'punch-dialog',
message: message,
confirmButtonText: '确定'
})
.then(() => {
if (this.text === '出乘') {
this.$emit('handleClick', '出乘');
} else {
this.$emit('handleClick', '退乘');
}
// on confirm
})
.catch(() => {
// on cancel
});
}
},
mounted() {
}
}
</script>
<style scoped lang="less">
.punch {
display: inline-block;
padding: .2rem 0 .1rem;
}
.goTip {
width: 3.9rem;
height: 3.9rem;
background-color: #CFE1F7;
border: 1px solid #529AEF;
border-radius: 50%;
position: relative;
margin: 0 auto .53rem;
}
.circle {
width: 3.54rem;
height: 3.54rem;
background-color: #4A96F4;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
p {
color: #FFFEFB;
text-align: center;
position: absolute;
width: 100%;
&:first-of-type {
top: 1rem;
font-size: .46rem;
}
&:last-of-type {
font-size: .46rem;
bottom: 1rem;
}
}
}
.position {
display: flex;
align-items: center;
color: #525252;
font-size: .42rem;
p {
margin: 0 .25rem 0 .17rem;
max-width: 5rem;
word-break: break-all;
}
div {
color: #4696F5;
}
}
.radar::before {
content: '';
position: absolute;
width:50%;
height:50%;
background: linear-gradient(45deg, rgba(0, 0, 0, 0) 50%, #8abff6 100%);
border-radius: 100% 0 0 0;
top: 0;
left: 0;
animation: scanning 5s linear infinite;
transform-origin: 100% 100%;
z-index: 1;
}
@keyframes scanning {
to {
transform: rotate(360deg);
}
}
</style>
父组件同步时间
// methods
getServerTime() {
if(this.$refs.punch){
this.$refs.punch.syncTimeLoading = true;
}
setTimeout(()=>{
//this.serveTime
let localTime = this.$moment().valueOf();
let diffTime = localTime - this.formatNow;
if (this.timer) {
clearInterval(this.timer);
}
this.timer = setInterval(() => {
this.getTime(diffTime);
}, 1000)
},3000);
},
getTime(diffTime) {
let localTime = this.$moment().valueOf();
let serveTime = localTime - diffTime;
if (this.lastTime && serveTime - this.lastTime > 5000) {
//服务端获取时间重新init,停止计时器,并禁止打卡
this.getServerTime();
} else {
this.lastTime = serveTime;
this.dateText = this.$moment(serveTime).format('YYYY-MM-DD');
this.weekText = this.$moment(serveTime).format('dddd');
this.currentTime = this.$moment(serveTime).format('HH:mm:ss');
if(this.$refs.punch){
this.$refs.punch.syncTimeLoading = false;
}
}
}
//computed
formatNow() {
return this.$moment(this.serveTime).valueOf() + 1000
},
网友评论