This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<view class="calendar-container">
|
||||
<!-- 展开/收起按钮,可以外部隐藏 -->
|
||||
<view class="calendar-header">
|
||||
<!-- <view class="calendar-header">
|
||||
<button size="mini" @click="toggleMode">
|
||||
{{ mode === 'month' ? '收起为周' : '展开为月' }}
|
||||
</button>
|
||||
<text>{{ displayTitle }}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view
|
||||
class="calendar-content"
|
||||
@@ -46,7 +46,7 @@ export default {
|
||||
props: {
|
||||
initialMode: { type: String, default: 'month' }, // 'month' or 'week'
|
||||
initialDate: { type: String, default: '' },
|
||||
allowWeekSwitch: { type: Boolean, default: true } // 控制是否允许上下滑切换
|
||||
allowWeekSwitch: { type: Boolean, default: false } // 控制是否允许上下滑切换
|
||||
},
|
||||
data() {
|
||||
const today = new Date()
|
||||
@@ -68,8 +68,10 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
mode() {
|
||||
mode(newMode, oldMode) {
|
||||
this.generateRenderDays()
|
||||
// 通知父组件mode已改变
|
||||
this.$emit('modeChange', newMode);
|
||||
},
|
||||
selected() {
|
||||
this.generateRenderDays()
|
||||
@@ -224,22 +226,34 @@ export default {
|
||||
else this.slide(-1)
|
||||
}
|
||||
},
|
||||
slide(direction) {
|
||||
if (this.mode === 'month') {
|
||||
const y = this.anchorDate.getFullYear()
|
||||
let m = this.anchorDate.getMonth() + 1 + direction
|
||||
let year = y
|
||||
if (m > 12) { m = 1; year++ }
|
||||
if (m < 1) { m = 12; year-- }
|
||||
this.anchorDate = new Date(year, m - 1, 1)
|
||||
} else {
|
||||
const d = this.safeDate(this.selected)
|
||||
d.setDate(d.getDate() + direction * 7)
|
||||
this.selected = this.formatDate(d)
|
||||
this.anchorDate = this.startOfWeek(d)
|
||||
}
|
||||
this.generateRenderDays()
|
||||
}
|
||||
slide(direction) {
|
||||
if (this.mode === 'month') {
|
||||
const y = this.anchorDate.getFullYear()
|
||||
let m = this.anchorDate.getMonth() + 1 + direction
|
||||
let year = y
|
||||
if (m > 12) { m = 1; year++ }
|
||||
if (m < 1) { m = 12; year-- }
|
||||
|
||||
// 切换后的基准日期设为该月1号
|
||||
this.anchorDate = new Date(year, m - 1, 1)
|
||||
this.selected = this.formatDate(this.anchorDate) // ✅ 选中当月1号
|
||||
this.$emit('dateChange', this.selected)
|
||||
|
||||
} else {
|
||||
// 以当前 anchorDate 为基准移动周
|
||||
const d = this.safeDate(this.anchorDate)
|
||||
d.setDate(d.getDate() + direction * 7)
|
||||
|
||||
// 更新基准周
|
||||
this.anchorDate = this.startOfWeek(d)
|
||||
|
||||
// ✅ 选中该周周日(startOfWeek返回的就是周日)
|
||||
this.selected = this.formatDate(this.anchorDate)
|
||||
this.$emit('dateChange', this.selected)
|
||||
}
|
||||
this.generateRenderDays()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -249,7 +263,7 @@ export default {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
box-shadow: 0 2rpx 16rpx #eee;
|
||||
/* box-shadow: 0 2rpx 16rpx #eee; */
|
||||
padding: 12rpx;
|
||||
}
|
||||
.calendar-header {
|
||||
|
140
components/SelectCalendarDialog.vue
Normal file
140
components/SelectCalendarDialog.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="visible" class="mask" @click="close"></view>
|
||||
<!-- 底部弹窗 -->
|
||||
<view class="popup" v-if="visible">
|
||||
<!-- 弹窗标题 -->
|
||||
<view class="dialog-title">选择时间</view>
|
||||
|
||||
<!-- 日期显示区域 -->
|
||||
<view class="date-display">
|
||||
{{ selectedDate }}
|
||||
</view>
|
||||
|
||||
<!-- 日历组件 -->
|
||||
<view class="calendar-wrapper">
|
||||
<CommonCalendar :initial-date="selectedDate" @dateChange="handleDateSelected" />
|
||||
</view>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<view class="confirm-btn" @click="confirmSelection">
|
||||
确认
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonCalendar from '@/components/CommonCalendar.vue'
|
||||
export default {
|
||||
components: {
|
||||
CommonCalendar
|
||||
},
|
||||
name: "SelectCalendarDialog",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedDate: this.getCurrentDate(), // 默认选中的日期
|
||||
showCalendar: true // 控制日历是否显示
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('update:visible', false);
|
||||
},
|
||||
// 获取当前日期
|
||||
getCurrentDate() {
|
||||
const today = new Date();
|
||||
const year = today.getFullYear();
|
||||
const month = String(today.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(today.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
|
||||
// 处理日期选择
|
||||
handleDateSelected(date) {
|
||||
this.selectedDate = date;
|
||||
// 不再需要手动关闭日历,因为日历会一直显示在弹窗中
|
||||
},
|
||||
|
||||
// 确认选择
|
||||
confirmSelection() {
|
||||
this.$emit('confirm', this.selectedDate);
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
.popup {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: 80%;
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 999;
|
||||
animation: slideUp 0.3s ease;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-size: 36rpx;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
margin-top: 45rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.date-display {
|
||||
width: 100%;
|
||||
height: 73rpx;
|
||||
line-height: 73rpx;
|
||||
text-align: start;
|
||||
background: #EBF5FF;
|
||||
border-radius: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #0B0B0B;
|
||||
margin-bottom: 6rpx;
|
||||
margin-left: 35rpx;
|
||||
margin-right: 35rpx;
|
||||
padding-left: 35rpx;
|
||||
}
|
||||
|
||||
.calendar-wrapper {
|
||||
width: 100%;
|
||||
margin-bottom: 89rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
background-color: #0090FF;
|
||||
color: white;
|
||||
border-radius: 44rpx;
|
||||
font-size: 36rpx;
|
||||
margin-left: 65rpx;
|
||||
margin-right: 65rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
</style>
|
115
components/punchInfo.vue
Normal file
115
components/punchInfo.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<!-- 上班 -->
|
||||
<view class="timeline-item">
|
||||
<view class="timeline-dot"></view>
|
||||
<view class="timeline-content">
|
||||
<text class="timeline-label">应上班 09:00</text>
|
||||
<view class="clock-card late">
|
||||
<text class="clock-text">已打卡 08:48:32</text>
|
||||
<text class="status orange">迟到</text>
|
||||
<text class="buka" @click="goBuka">申请补卡</text>
|
||||
<view class="location">
|
||||
<text class="icon">📍</text>
|
||||
<text class="loc-text">某综合服务中心1栋</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
props:{
|
||||
info:{}
|
||||
},
|
||||
methods:{
|
||||
goBuka(){
|
||||
uni.navigateTo({
|
||||
url: '/pages/sys/user/myRecord/cardReplacement'
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
padding-left: 20rpx;
|
||||
margin-left: 60rpx;
|
||||
margin-right: 90rpx;
|
||||
margin-bottom: 40rpx;
|
||||
border-left: 2rpx solid #e0e0e0; /* 竖线 */
|
||||
}
|
||||
|
||||
.timeline-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.timeline-dot {
|
||||
position: absolute;
|
||||
left: -10rpx;
|
||||
top: -10rpx;
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
background-color: #666;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.timeline-label {
|
||||
font-size: 28rpx;
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
/* 打卡卡片 */
|
||||
.clock-card {
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
margin-top: 23rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.clock-text {
|
||||
font-size: 34rpx;
|
||||
color: #000000;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.status {
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.status.orange {
|
||||
color: #ff6b35;
|
||||
}
|
||||
|
||||
.buka {
|
||||
margin-left: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #3370FF;
|
||||
}
|
||||
|
||||
/* 地点 */
|
||||
.location {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.loc-text {
|
||||
font-size: 28rpx;
|
||||
color: #1C9BFF;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user