实现效果如下图,写了定时器。
这是可以进行一些设置,基础版本,都是正常班,没有考虑夜班。如果有需要的话可以自行实现。
样式也可以自行调整,内容样式有参考小程序 加油摸鱼侠。
小程序体验
代码如下,我使用的是uniapp,技术有限,没有思考太多,觉得代码冗余的可以自行在加以封装,样式可自行修改。可能会有bug,如果遇到的话可以私信,看到的话会进行修复和完善。
显示页面
<template>
<view class="pageHome">
<view class="offDuty">
<p>距离{{text}}还剩 </p>
<text class="offDutyTime">{{offDutyTime}}</text>
</view>
<view class="todayPay">
<p>今日生活费到账</p>
<span class="pay animate__animated animate__flash">{{ salary.toFixed(2) }}</span>
<button @click="goEdit" class="edit">设置</button>
</view>
</view>
</template>
<script>
import {
getTimestamp,
formatTime
} from "@/utils/pay.js"
export default {
data() {
return {
salary: 10.2175,
increase: 0,
settledWages: 0,
dataFrom: null,
remainSeconds: 0,
offDutyTime: 0,
text:'下班',
timer:null
};
},
onLoad(options) {
// this.toDayPay()
if (uni.getStorageSync('pay')) {
this.dataFrom = uni.getStorageSync('pay')
}
},
onShow() {
this.dataFrom = uni.getStorageSync('pay')
this.initData()
},
mounted() {
this.initData()
},
methods: {
// 倒计时函数
updateCountdown(endTime) {
// 获取当前时间
const now = new Date();
// 构造指定时间点
const [hour, minute] = endTime.split(':'); // 将时间字符串按冒号分隔成时和分两个数字
const targetTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0);
// 计算剩余时间(单位:毫秒)
let timeDiff = targetTime.getTime() - now.getTime();
this.remainSeconds = Math.floor(timeDiff / 1000); // 将剩余时间转换为秒数
this.offDutyTime = formatTime(this.remainSeconds)
},
goEdit() {
uni.navigateTo({
url: '/pages/luckydraw/index'
})
},
// 当前时间到开始上班时间过了多少秒
getSecondsByTime(hour, minute, second) {
// 获取当前时间戳
const now = new Date();
const timestamp = now.getTime();
// 获取今天的指定时间的时间戳
const year = now.getFullYear();
const month = now.getMonth() + 1;
const day = now.getDate();
const target = new Date(year, month - 1, day, hour, minute, second);
const targetTimestamp = target.getTime();
// 计算已经过了多少秒
const seconds = Math.floor((timestamp - targetTimestamp) / 1000);
return seconds;
},
initData(){
this.timer = setInterval(()=>{
this.toDayPay()
},1000)
},
toDayPay() {
if (this.dataFrom) {
const timestamp = Date.now() / 1000; // 当前时间秒
const [hour, minute] = this.dataFrom.startTime.split(':')
const seconds = this.getSecondsByTime(hour, minute, 0)
// 上班时间(秒)
let startTime = getTimestamp(this.dataFrom.startTime)
let endTime = getTimestamp(this.dataFrom.endTime)
// 午休时间(秒)
let restStartTime = getTimestamp(this.dataFrom.restStartTime)
let restEndTime = getTimestamp(this.dataFrom.restEndTime)
// 每天上班总时长(秒)
let workTime = endTime - startTime
// 每天休息时长(秒)
let restTime = restEndTime - restStartTime
// 每秒所得工资
this.increase = this.dataFrom.monthlyPay / this.dataFrom.monthlyWork / (workTime - restTime)
let settledWages = 0;
if(timestamp<startTime){
this.text = '上班'
this.updateCountdown(this.dataFrom.startTime)
return
}else if(timestamp>endTime){
this.text = '下班'
this.offDutyTime = 0
return
}else{
if(timestamp>restStartTime && timestamp<restEndTime){
this.text = '午休结束'
this.updateCountdown(this.dataFrom.restEndTime)
}else if(timestamp<restStartTime){
settledWages = this.increase * seconds
this.text = '午休'
this.updateCountdown(this.dataFrom.restStartTime)
this.salary = settledWages
this.salary += this.increase;
}else{
settledWages = this.increase * seconds - restTime * this.increase
this.updateCountdown(this.dataFrom.endTime)
this.salary = settledWages
this.salary += this.increase;
}
}
}
},
},
destroyed() {
clearInterval(this.timer)
}
}
</script>
<style lang="less">
.pageHome {
text-align: center;
.todayPay {
position: relative;
margin: 0 auto;
width: 90vw;
height: 26vh;
background-color: #ff0000;
text-align: center;
border-radius: 1rem;
font-size: 32rpx;
color: orange;
.pay {
color: white;
font-size: 60rpx
}
.edit {
position: absolute;
left: 1rem;
bottom: 1rem;
width: 20vw;
}
}
.offDuty {
width: 100vw;
height: 10vh;
background-color: red;
border-radius: 0 0 5rem 5rem;
color: white;
font-size: 24rpx;
.offDutyTime {
font-size: 48rpx
}
}
}
</style>
抽取出来封装的方法 getTimestamp是传入一个时间,然后将其转换成秒。
formatTime是传入秒,返回的是一个时间格式的字符串
export function getTimestamp(timeStr) {
const today = new Date()
const timestamp = Date.now(); // 当前时间戳
const time = timeStr.split(':')
const targetTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), time[0], time[1])
return Math.floor(targetTime.getTime() / 1000)
}
export function formatTime(seconds) {
const hours = Math.floor(seconds / 3600); // 计算小时数
const minutes = Math.floor((seconds % 3600) / 60); // 计算分钟数
const secondsLeft = seconds % 60; // 计算剩余秒数
const paddedHours = String(hours).padStart(2, '0'); // 将小时数补0为两位数
const paddedMinutes = String(minutes).padStart(2, '0'); // 将分钟数补0为两位数
const paddedSeconds = String(secondsLeft).padStart(2, '0'); // 将剩余秒数补0为两位数
return `${paddedHours}:${paddedMinutes}:${paddedSeconds}`; // 返回时间格式字符串
}
设置页面内容
<template>
<view class="luckyDraw">
<view class="edit">
<form @submit="formSubmit">
<text class="title">设置薪资</text>
<view class="editContent">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
上下班时间
</view>
<view class="uni-list-cell-db">
<picker mode="time" :value="dataFrom.startTime" @change="bindStartTimeChange"
name="startTime">
<view class="uni-input">{{dataFrom.startTime}}</view>
</picker>
<p class="timeStyle">~</p>
<picker mode="time" :value="dataFrom.endTime" @change="bindEndTimeChange" name="endTime">
<view class="uni-input">{{dataFrom.endTime}}</view>
</picker>
</view>
</view>
</view>
<view class="editContent">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
午休时间
</view>
<view class="uni-list-cell-db">
<picker mode="time" :value="dataFrom.restStartTime" @change="restStartTimeChange"
name="restStartTime">
<view class="uni-input">{{dataFrom.restStartTime}}</view>
</picker>
<p class="timeStyle">~</p>
<picker mode="time" :value="dataFrom.restEndTime" @change="restEndTimeChange"
name="restEndTime">
<view class="uni-input">{{dataFrom.restEndTime}}</view>
</picker>
</view>
</view>
</view>
<view class="editContent">
<p>平均月薪</p> <input type="default" :value="dataFrom.monthlyPay" name="monthlyPay">
</view>
<view class="editContent">
<p>月工作天数</p><input type="default" :value="dataFrom.monthlyWork" name="monthlyWork">
</view>
<p class="attention">注:秒薪=平均月薪/月工作天数/(上班时长-午休时长)</p>
<view class="editContent">
<button @click="cancel">取消</button>
<button form-type="submit">确定</button>
</view>
</form>
</view>
</view>
</template>
<script>
export default {
data() {
return {
dataFrom: {
monthlyPay: 3000,
monthlyWork: 22,
startTime: '08:30',
endTime: '18:30',
restStartTime: '12:00',
restEndTime: '13:30'
},
};
},
onLoad() {
if (uni.getStorageSync('pay')) {
this.dataFrom = uni.getStorageSync('pay')
}
},
methods: {
bindStartTimeChange: function(e) {
this.dataFrom.startTime = e.detail.value
},
bindEndTimeChange: function(e) {
this.dataFrom.endTime = e.detail.value
},
restStartTimeChange: function(e) {
this.dataFrom.restStartTime = e.detail.value
},
restEndTimeChange: function(e) {
this.dataFrom.restEndTime = e.detail.value
},
cancel(){
uni.navigateBack()
},
formSubmit(e) {
this.dataFrom = e.detail.value
uni.setStorageSync('pay', this.dataFrom)
uni.navigateBack()
},
},
};
</script>
<style lang="less">
.edit {
margin: 1rem auto;
width: 90vw;
height: 44vh;
background-color: rgb(250, 213, 86);
border-radius: 1rem;
color: black;
text-align: center;
.title {
font-weight: bold;
font-size: 48rpx;
}
.uni-list-cell {
width: 100%;
display: flex;
justify-content: space-between;
.uni-list-cell-db {
display: flex;
.timeStyle {
padding: 0 .2rem;
}
.uni-input {
width: 20vw;
height: 5vh;
line-height: 5vh;
background-color: white;
border-radius: .5rem;
}
}
}
.editContent {
display: flex;
justify-content: space-between;
margin: 1rem;
input {
width: 30vw;
height: 5vh;
background-color: white;
border-radius: .5rem;
}
}
}
.attention {
font-size: 24rpx
}
</style>