| | |
| | | size="16"></u-icon> |
| | | <text class="shift-text">白班: 09:00-18:00</text> |
| | | </view> |
| | | <!-- <view v-if="todayRecord?.checkInTime" |
| | | class="shift-item"> |
| | | <u-icon name="checkmark-circle" |
| | | color="#4cd964" |
| | | size="16"></u-icon> |
| | | <text class="shift-text">{{ todayRecord.checkInTime }}已打卡</text> |
| | | </view> --> |
| | | </view> |
| | | <!-- 打卡按钮 --> |
| | | <view class="checkin-button-container"> |
| | |
| | | return "下班打卡"; |
| | | } |
| | | return "已打卡"; |
| | | }); |
| | | |
| | | // 生成最近日期 |
| | | const recentDates = computed(() => { |
| | | const dates = []; |
| | | const today = new Date(); |
| | | |
| | | // 获取最近7天的日期 |
| | | for (let i = 6; i >= 0; i--) { |
| | | const date = new Date(today); |
| | | date.setDate(today.getDate() - i); |
| | | |
| | | const dateStr = `${date.getFullYear()}-${String( |
| | | date.getMonth() + 1 |
| | | ).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`; |
| | | const hasRecord = rawAttendance.value.some(item => item.date === dateStr); |
| | | |
| | | dates.push({ |
| | | date: dateStr, |
| | | day: date.getDate(), |
| | | isToday: i === 0, |
| | | hasRecord, |
| | | }); |
| | | } |
| | | |
| | | return dates; |
| | | }); |
| | | |
| | | // 导航到详细报告页面 |
| | |
| | | flex: 1; |
| | | } |
| | | |
| | | /* 日期选择器 */ |
| | | .date-picker { |
| | | margin-bottom: 24rpx; |
| | | } |
| | | |
| | | .weekday { |
| | | display: inline-block; |
| | | width: 44rpx; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | color: $text-tertiary; |
| | | margin-bottom: 12rpx; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .date-items { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .date-item { |
| | | width: 44rpx; |
| | | height: 44rpx; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 14px; |
| | | color: $text-secondary; |
| | | background-color: rgba($primary-color, 0.05); |
| | | transition: all 0.3s ease; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .date-item:hover { |
| | | background-color: rgba($primary-color, 0.1); |
| | | transform: scale(1.1); |
| | | } |
| | | |
| | | .date-item.active { |
| | | background-color: $primary-color; |
| | | color: #ffffff; |
| | | font-weight: 600; |
| | | box-shadow: 0 2rpx 8rpx rgba($primary-color, 0.3); |
| | | } |
| | | |
| | | .date-item.has-record { |
| | | position: relative; |
| | | } |
| | | |
| | | .date-item.has-record::after { |
| | | content: ""; |
| | | position: absolute; |
| | | bottom: 4rpx; |
| | | width: 8rpx; |
| | | height: 8rpx; |
| | | border-radius: 50%; |
| | | background-color: $success-color; |
| | | box-shadow: 0 1rpx 2rpx rgba($success-color, 0.3); |
| | | } |
| | | |
| | | /* 今日考勤状态 */ |
| | | .today-status { |
| | | display: flex; |
| | |
| | | |
| | | .checkin-time { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .weekday { |
| | | width: 38rpx; |
| | | } |
| | | |
| | | .date-item { |
| | | width: 38rpx; |
| | | height: 38rpx; |
| | | } |
| | | } |
| | | |
| | |
| | | dept: "生产一部", |
| | | }); |
| | | |
| | | // 部门选项 |
| | | const deptOptions = [ |
| | | { label: "生产一部", value: "生产一部" }, |
| | | { label: "生产二部", value: "生产二部" }, |
| | | { label: "设备维护部", value: "设备维护部" }, |
| | | { label: "质检部", value: "质检部" }, |
| | | ]; |
| | | |
| | | // 模拟考勤原始数据 |
| | | const rawAttendance = ref([ |
| | | { |
| | |
| | | |
| | | // 查询表单 |
| | | const searchForm = reactive({ |
| | | dept: "", |
| | | date: "", |
| | | }); |
| | | |
| | |
| | | // 查询 |
| | | const recomputeTable = () => { |
| | | const list = rawAttendance.value.filter(item => { |
| | | if (searchForm.dept && item.dept !== searchForm.dept) { |
| | | return false; |
| | | } |
| | | if (searchForm.date && item.date !== searchForm.date) { |
| | | return false; |
| | | } |
| | |
| | | recomputeTable(); |
| | | }; |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.dept = ""; |
| | | searchForm.date = ""; |
| | | recomputeTable(); |
| | | }; |
| | | |
| | | // 导出(演示) |
| | | const handleExport = () => { |
| | | uni.showToast({ |
| | | title: "当前为演示页面,导出功能未对接实际接口", |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // 默认展示当天数据 |
| | | // const today = new Date(); |
| | | // const Y = today.getFullYear(); |
| | | // const M = String(today.getMonth() + 1).padStart(2, "0"); |
| | | // const D = String(today.getDate()).padStart(2, "0"); |
| | | // searchForm.date = `${Y}-${M}-${D}`; |
| | | recomputeTable(); |
| | | }); |
| | | </script> |
| | |
| | | font-weight: 500; |
| | | } |
| | | |
| | | /* 导出按钮 */ |
| | | .export-section { |
| | | text-align: center; |
| | | margin: 0 20rpx 30rpx; |
| | | } |
| | | |
| | | .export-btn { |
| | | width: 100%; |
| | | border-radius: 8rpx; |
| | | border: 1rpx solid $primary-color; |
| | | color: $primary-color; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .export-btn:hover { |
| | | background-color: $primary-color; |
| | | color: #ffffff; |
| | | box-shadow: 0 4rpx 12rpx rgba($primary-color, 0.3); |
| | | transform: translateY(-2rpx); |
| | | } |
| | | |
| | | /* 响应式调整 */ |
| | | @media (max-width: 375px) { |
| | | .search-section, |
| | | .record-list, |
| | | .empty-state, |
| | | .export-section { |
| | | .empty-state { |
| | | margin: 12rpx; |
| | | } |
| | | |
| | |
| | | |
| | | .search-section, |
| | | .record-item-card, |
| | | .empty-state, |
| | | .export-section { |
| | | .empty-state { |
| | | animation: fadeInUp 0.5s ease-out; |
| | | } |
| | | |
| | |
| | | |
| | | .empty-state { |
| | | animation-delay: 0.2s; |
| | | } |
| | | |
| | | .export-section { |
| | | animation-delay: 0.3s; |
| | | } |
| | | </style> |