运用vant写一个仿钉钉打卡的功能
我写的是有打卡和记录的功能一共三个页面
现目前是将数据存储到本地,但是这样的方法会导致用户手机清除缓存或者换一个手机登陆就会查询不到打卡的记录信息,所以最好的改为调用接口存取数据最好!
index
<template>
<div>
<van-tabbar v-model="active">
<van-tabbar-item :active="0">打卡</van-tabbar-item>
<van-tabbar-item :active="1">统计</van-tabbar-item>
</van-tabbar>
<check v-if="active == 0"></check>
<record v-if="active == 1"></record>
</div>
</template>
<script>
import { Tabbar, TabbarItem } from 'vant';
import check from './check.vue';
import record from './record.vue';
export default {
name: 'clock',
components: {
[Tabbar.name]: Tabbar,
[TabbarItem.name]: TabbarItem,
check,
record
},
data() {
return {
active: 0
};
},
mounted() {},
methods: {}
};
</script>
<style></style>
打卡页面 check
<template>
<div class="main">
<div class="maintop">
<div class="user">
<img class="user-icon" :src="loginInfo.userIcon" alt="" />
<div>{{ loginInfo.userNickName }}</div>
</div>
<div>{{ today }}</div>
</div>
<div class="tip">打卡记录时间和位置</div>
<!-- 打卡时间 -->
<div class="checktime">
<van-steps direction="vertical" :active="active" active-color="#3791F9">
<van-step class="clock-in" :active="0">
<h3>上班时间{{ clockin.clockintime }}</h3>
<p>打卡地址</p>
</van-step>
<van-step class="clock-out" :active="1" v-if="active == 1">
<h3>下班时间{{ clockout.clockouttime }}</h3>
<p>打卡地址</p>
</van-step>
</van-steps>
</div>
<!-- 打卡按钮 -->
<div v-show="this.btnshow">
<div class="check-container">
<div class="checkbtn">
<div class="btn-content" @click="clockIn">
<div>{{ active == 0 ? '上班打卡' : '下班打卡' }}</div>
<div>{{ showTime }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Step, Steps } from 'vant';
export default {
components: {
[Step.name]: Step,
[Steps.name]: Steps
},
data() {
return {
loginInfo: {
userIcon: '', // 用户头像路径
userNickName: '' // 用户昵称
},
today: '',
t: null,
showTime: '',
active: 0,
clockin: {},
clockout: {},
btnshow: true
};
},
methods: {
getCurrentDate() {
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth() + 1;
let day = now.getDate();
return year + '-' + month + '-' + day;
},
time() {
clearTimeout(this.t); //清除定时器
var dt = new Date();
var h = dt.getHours(); //获取时
var m = dt.getMinutes(); //获取分
var s = dt.getSeconds(); //获取秒
this.showTime = +h + ':' + m + ':' + s;
this.t = setTimeout(this.time, 1000); //设定定时器,循环运行
},
clockIn() {
const dt = new Date();
const clockInTime = dt.getHours() + ':' + dt.getMinutes() + ':' + dt.getSeconds();
let clockInRecord = {};
console.log(clockInTime, 'clockInTime');
if (this.active === 0) {
this.clockin = {
type: '上班',
clockintime: clockInTime
};
this.active = 1;
clockInRecord.clockin = this.clockin;
} else if (this.active === 1) {
this.clockout = {
type: '下班',
clockouttime: clockInTime
};
clockInRecord.clockout = this.clockout;
this.btnshow = false;
}
const clockInRecords = JSON.parse(localStorage.getItem('clockInRecords')) || [];
clockInRecords.push(clockInRecord);
localStorage.setItem('clockInRecords', JSON.stringify(clockInRecords));
}
},
mounted() {
this.loginInfo = this.getLoginInfo();
console.log(this.loginInfo, 'loginInfo');
this.today = this.getCurrentDate();
},
created() {
this.t = setTimeout(this.time, 1000);
}
};
</script>
<style lang="scss" scoped>
.main {
background-color: #f3f4f6;
height: 100vh;
}
.user-icon {
width: 35px;
height: 35px;
border-radius: 35px;
}
.maintop {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
font-size: 16px;
color: #333;
background-color: #fff;
.user {
display: flex;
justify-content: space-between;
align-items: center;
}
}
.tip {
color: #999;
text-align: center;
margin-top: 10px;
}
.check-container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px; /* Adjust margin as needed */
}
.checkbtn {
width: 100px;
height: 100px;
border-radius: 50%; /* Use 50% to make a perfect circle */
color: #fff;
text-align: center;
background: linear-gradient(135deg, #97c6fd, #73b2fb, #54a1fa, #4297fa);
}
.btn-content {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
.checktime {
padding: 20px;
}
.van-steps {
background-color: #f3f4f6;
}
</style>
记录页面 record
<template>
<div class="main">
<div class="maintop">
<div class="user">
<img class="user-icon" :src="loginInfo.userIcon" alt="" />
<div>{{ loginInfo.userNickName }}</div>
</div>
<div>
<span style="color: #3791F9;">{{ today }}</span
><van-icon name="arrow-down" />
</div>
</div>
<!-- 日历 -->
<div>
<van-calendar
:poppable="false"
:show-confirm="false"
:show-mark="false"
:show-title="false"
:show-subtitle="false"
:min-date="minDate"
:max-date="maxDate"
:style="{ height: '390px' }"
/>
<div class="checktime" v-if="this.records">
<van-steps direction="vertical">
<van-step>
<h3>上班时间{{this.records[0]?this.records[0].clockin.clockintime:'上班未打卡' }}</h3>
<p>打卡地址</p>
</van-step>
<van-step>
<h3>下班时间{{ this.records[1]?this.records[1].clockout.clockouttime:'下班未打卡' }}</h3>
<p>打卡地址</p>
</van-step>
</van-steps>
</div>
<div class="unavailable" v-else>暂无打卡信息</div>
</div>
</div>
</template>
<script>
import { Icon, Calendar, Step, Steps } from 'vant';
export default {
components: {
[Icon.name]: Icon,
[Calendar.name]: Calendar,
[Step.name]: Step,
[Steps.name]: Steps
},
data() {
const startDate = new Date('2024-01-01');
const nowday = new Date();
nowday.setDate(nowday.getDate()); // 今天的日期
return {
loginInfo: '',
today: '',
minDate: startDate, // 固定的起始日期
maxDate: nowday // 昨天的日期
};
},
methods: {
getCurrentDate() {
let now = new Date();
let year = now.getFullYear();
let month = now.getMonth() + 1;
let day = now.getDate();
return year + '-' + month + '-' + day;
}
},
mounted() {
this.loginInfo = this.getLoginInfo();
this.today = this.getCurrentDate();
this.records = JSON.parse(localStorage.getItem('clockInRecords'));
console.log(this.records, 'tttttime');
}
};
</script>
<style lang="scss" scoped>
.main {
background-color: #f3f4f6;
height: 100vh;
}
.maintop {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
font-size: 16px;
color: #333;
background-color: #fff;
.user-icon {
width: 35px;
height: 35px;
border-radius: 35px;
}
.user {
display: flex;
justify-content: space-between;
align-items: center;
}
}
::v-deep .van-calendar__selected-day {
background-color: #4297fa !important;
border-radius: 50% !important;
width: 40px;
height: 40px;
}
.checktime {
padding: 20px;
.van-steps {
background-color: #f3f4f6;
}
}
.unavailable {
margin-top: 20px;
color: #999;
text-align: center;
}
</style>
效果图