Files
salaryAccounting/pages/attendanceManagement/attendanceManagement.vue
T
2025-04-18 18:01:03 +08:00

470 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="attendance-page">
<!-- 月份选择 -->
<view class="month-selector" @click="showDatePicker">
<view class="combination">
<text class="current-month"
>{{ selectedYear }}{{
selectedMonth < 10 ? "0" + selectedMonth : selectedMonth
}}</text
>
<image class="arrow" src="/static/arr.png" mode="aspectFit"></image>
</view>
<text class="month-text">月度</text>
</view>
<!-- 打卡统计 -->
<view class="stat-section">
<view class="section-title">打卡统计</view>
<view class="stat-grid">
<view class="stat-item">
<text class="label">迟到</text>
<text class="value red-text">4</text>
</view>
<view class="stat-item">
<text class="label">严重迟到</text>
<text class="value red-text">3</text>
</view>
<view class="stat-item">
<text class="label">旷工迟到</text>
<text class="value">0</text>
</view>
<view class="stat-item">
<text class="label">早退</text>
<text class="value red-text">1</text>
</view>
<view class="stat-item">
<text class="label">未打卡</text>
<text class="value red-text">2</text>
</view>
</view>
</view>
<!-- 请假统计 -->
<view class="stat-section">
<view class="section-title">请假统计</view>
<view class="stat-grid">
<view class="stat-item">
<text class="label">事假</text>
<text class="value red-text">4</text>
</view>
<view class="stat-item">
<text class="label">病假</text>
<text class="value red-text">3</text>
</view>
<view class="stat-item">
<text class="label">婚假</text>
<text class="value">0</text>
</view>
<view class="stat-item">
<text class="label">产假</text>
<text class="value red-text">1</text>
</view>
<view class="stat-item">
<text class="label">陪产假</text>
<text class="value red-text">2</text>
</view>
<view class="stat-item">
<text class="label">丧假</text>
<text class="value red-text">2</text>
</view>
</view>
</view>
<!-- 加班调休统计 -->
<view class="stat-section">
<view class="section-title">加班调休统计</view>
<view class="stat-grid">
<view class="stat-item">
<text class="label">节假日加班</text>
<text class="value red-text">4</text>
</view>
<view class="stat-item">
<text class="label">休息日加班</text>
<text class="value red-text">3</text>
</view>
<view class="stat-item">
<text class="label">工作日加班</text>
<text class="value">0</text>
</view>
<view class="stat-item">
<text class="label">调休</text>
<text class="value red-text">1</text>
</view>
</view>
</view>
<!-- 底部说明 -->
<view class="bottom-tips">说明请核实当月考勤记录确认无误请签字确认</view>
<!-- 员工签字 -->
<view class="sign">
<view class="sign-tit">
员工签字
<text>/保留员工签字</text>
</view>
<view class="signatureVersion"></view>
</view>
<!-- 签字确认按钮 -->
<view class="confirm-btn" @click="goSignIt"><text>签字确认</text></view>
<!-- 日期选择模态框 -->
<view class="date-picker-modal" v-if="showModal" @click.stop="closeDatePicker">
<view class="modal-content" @click.stop>
<view class="modal-title">{{
currentStep === "year" ? "选择年份" : "选择月份"
}}</view>
<!-- 年份选择 -->
<view class="year-grid" v-if="currentStep === 'year'">
<view
v-for="year in availableYears"
:key="year"
class="year-item"
:class="{ active: tempSelectedYear === year }"
@click="selectYear(year)"
>
<view class="year-circle">
<text>{{ year }}</text>
</view>
</view>
</view>
<!-- 月份选择 -->
<view class="month-grid" v-if="currentStep === 'month'">
<view
v-for="month in months"
:key="month"
class="month-item"
:class="{ active: tempSelectedMonth === month }"
@click="selectMonth(month)"
>
<view class="month-circle">
<text
>{{ tempSelectedYear }}{{ month < 10 ? "0" + month : month }}</text
>
</view>
</view>
</view>
<!-- 底部按钮 -->
<view class="modal-footer" v-if="currentStep === 'month'">
<view class="back-btn" @click="backToYearSelect">返回年份选择</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
return {
showModal: false,
currentYear,
selectedYear: currentYear,
selectedMonth: currentDate.getMonth() + 1,
months: Array.from({ length: 12 }, (_, i) => i + 1),
currentStep: "year", // 'year' 或 'month'
tempSelectedYear: currentYear,
tempSelectedMonth: currentDate.getMonth() + 1,
availableYears: Array.from({ length: 7 }, (_, i) => currentYear - 3 + i),
};
},
created() {
this.$setNavigationBar("考勤管理");
},
methods: {
showDatePicker() {
this.showModal = true;
this.currentStep = "year";
this.tempSelectedYear = this.selectedYear;
this.tempSelectedMonth = this.selectedMonth;
},
closeDatePicker() {
this.showModal = false;
this.currentStep = "year";
},
selectYear(year) {
this.tempSelectedYear = year;
this.currentStep = "month";
},
selectMonth(month) {
this.tempSelectedMonth = month;
this.selectedYear = this.tempSelectedYear;
this.selectedMonth = month;
this.showModal = false;
this.currentStep = "year";
this.$emit("dateSelected", {
year: this.selectedYear,
month: this.selectedMonth,
});
console.log("选择月份触发");
},
backToYearSelect() {
this.currentStep = "year";
},
goSignIt(){
this.$navTo('/pages/sign/sign');
}
},
};
</script>
<style lang="scss" scoped>
.attendance-page {
min-height: 100vh;
background-color: #f8f9fa;
padding: 0 30rpx 0 30rpx;
.month-selector {
padding: 0 28rpx 0 10rpx;
display: flex;
align-items: center;
margin: 40rpx 0;
justify-content: space-between;
.combination {
height: 40rpx;
line-height: 40rpx;
display: flex;
align-content: center;
.current-month {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: #4b5563;
}
.arrow {
transform: rotate(90deg);
width: 40rpx;
height: 40rpx;
}
}
.month-text {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 28rpx;
color: #2b5ce4;
}
}
.stat-section {
background: #fff;
border-radius: 12rpx;
padding: 35rpx 40rpx;
margin-bottom: 20rpx;
.section-title {
font-size: 32rpx;
color: #111827;
}
.stat-grid {
margin-top: 40rpx;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 40rpx 90rpx;
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
.label {
font-size: 28rpx;
color: #4b5563;
margin-bottom: 15rpx;
}
.value {
font-size: 32rpx;
color: #666;
&.red-text {
color: #ff4d4f;
}
}
}
}
}
.bottom-tips {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #b9b9c2;
}
.sign {
margin-top: 32rpx;
margin-bottom: 180rpx;
.sign-tit {
margin-bottom: 32rpx;
margin-left: 8rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 700;
font-size: 28rpx;
color: #000000;
text {
padding-left: 16rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 24rpx;
color: #b9b9c2;
}
}
.signatureVersion {
width: 690rpx;
height: 280rpx;
background: #ffffff;
border-radius: 20rpx;
}
}
.confirm-btn {
position: fixed;
bottom: 45rpx;
left: 20rpx;
right: 20rpx;
height: 78rpx;
background: #ffffff;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 400;
font-size: 30rpx;
color: #0078ff;
font-size: 32rpx;
border: 2rpx solid #0078ff;
}
.date-picker-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
.modal-content {
width: 690rpx;
background: #ffffff;
border-radius: 20rpx;
padding: 40rpx 30rpx;
.modal-title {
font-size: 32rpx;
color: #111827;
text-align: center;
margin-bottom: 40rpx;
font-weight: 500;
}
.year-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
padding: 0 20rpx;
.year-item {
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
.year-circle {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
border: 2rpx solid #e5e7eb;
text {
font-size: 28rpx;
color: #4b5563;
}
}
&.active {
.year-circle {
background: #eef2ff;
border-color: #2b5ce4;
text {
color: #2b5ce4;
}
}
}
}
}
.month-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
padding: 0 20rpx;
.month-item {
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
.month-circle {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
border: 2rpx solid #e5e7eb;
text {
font-size: 28rpx;
color: #4b5563;
}
}
&.active {
.month-circle {
background: #eef2ff;
border-color: #2b5ce4;
text {
color: #2b5ce4;
}
}
}
}
}
.modal-footer {
margin-top: 30rpx;
display: flex;
justify-content: center;
.back-btn {
padding: 20rpx 40rpx;
font-size: 28rpx;
color: #2b5ce4;
background: #eef2ff;
border-radius: 8rpx;
}
}
}
}
}
</style>