hookehuyr

feat(日历组件): 添加作业筛选功能并优化交互

- 在日历组件中新增作业筛选功能,支持按课程类型筛选
- 调整日历折叠状态的点击区域和布局
- 移除部分未使用的样式代码
- 添加作业选择弹窗及相关事件处理
1 <!-- 1 <!--
2 * @Date: 2025-01-25 15:34:17 2 * @Date: 2025-01-25 15:34:17
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-11-13 20:03:33 4 + * @LastEditTime: 2025-12-11 09:31:06
5 * @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue 5 * @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue
6 * @Description: 可折叠日历组件 6 * @Description: 可折叠日历组件
7 --> 7 -->
8 <template> 8 <template>
9 <div class="collapsible-calendar "> 9 <div class="collapsible-calendar ">
10 <!-- 折叠状态显示 --> 10 <!-- 折叠状态显示 -->
11 - <div v-if="!isExpanded" class="calendar-collapsed" @click="expandCalendar"> 11 + <div v-if="!isExpanded" class="calendar-collapsed">
12 <div class="calendar-header"> 12 <div class="calendar-header">
13 <div class="calendar-icon"> 13 <div class="calendar-icon">
14 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 14 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
...@@ -16,9 +16,13 @@ ...@@ -16,9 +16,13 @@
16 <path d="M7 10H9V12H7V10ZM11 10H13V12H11V10ZM15 10H17V12H15V10Z" fill="#4caf50"/> 16 <path d="M7 10H9V12H7V10ZM11 10H13V12H11V10ZM15 10H17V12H15V10Z" fill="#4caf50"/>
17 </svg> 17 </svg>
18 </div> 18 </div>
19 - <div class="calendar-title-wrapper"> 19 + <!-- <div class="calendar-date-display">
20 + <div class="calendar-date-main">{{ formattedCurrentDate }}</div>
21 + <div class="calendar-weekday">{{ formattedWeekday }}</div>
22 + </div> -->
23 + <div class="calendar-title-wrapper" @click="expandCalendar">
20 <div class="calendar-title">{{ title }}</div> 24 <div class="calendar-title">{{ title }}</div>
21 - <div class="calendar-subtitle">点击选择日期</div> 25 + <div class="calendar-subtitle">点击切换日期</div>
22 </div> 26 </div>
23 </div> 27 </div>
24 <div class="calendar-content"> 28 <div class="calendar-content">
...@@ -26,13 +30,24 @@ ...@@ -26,13 +30,24 @@
26 <div class="calendar-date-main">{{ formattedCurrentDate }}</div> 30 <div class="calendar-date-main">{{ formattedCurrentDate }}</div>
27 <div class="calendar-weekday">{{ formattedWeekday }}</div> 31 <div class="calendar-weekday">{{ formattedWeekday }}</div>
28 </div> 32 </div>
29 - <div class="calendar-action"> 33 + <!-- <div class="calendar-action">
30 <div class="calendar-action-text">指定日期</div> 34 <div class="calendar-action-text">指定日期</div>
31 <div class="calendar-arrow"> 35 <div class="calendar-arrow">
32 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 36 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
33 <path d="M7 10L12 15L17 10H7Z" fill="#4caf50"/> 37 <path d="M7 10L12 15L17 10H7Z" fill="#4caf50"/>
34 </svg> 38 </svg>
35 </div> 39 </div>
40 + </div> -->
41 + <div class="calendar-actions-wrapper">
42 + <!-- 作业筛选 -->
43 + <div class="calendar-action course-filter" @click.stop="openCoursePicker">
44 + <div class="calendar-action-text">{{ selectedCourseText }}</div>
45 + <div class="calendar-arrow">
46 + <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
47 + <path d="M7 10L12 15L17 10H7Z" fill="#4caf50"/>
48 + </svg>
49 + </div>
50 + </div>
36 </div> 51 </div>
37 </div> 52 </div>
38 </div> 53 </div>
...@@ -61,6 +76,23 @@ ...@@ -61,6 +76,23 @@
61 </van-calendar> 76 </van-calendar>
62 </div> 77 </div>
63 </van-popup> 78 </van-popup>
79 +
80 + <!-- 作业选择弹窗 -->
81 + <van-popup
82 + v-model:show="showCoursePicker"
83 +
84 + round
85 + position="bottom"
86 + :style="{ minHeight: '30%', maxHeight: '80%', width: '100%' }"
87 + >
88 + <van-picker
89 + title="作业选择"
90 + :columns="courseColumns"
91 + @confirm="onConfirmCourse"
92 + @cancel="showCoursePicker = false"
93 + :default-index="0"
94 + />
95 + </van-popup>
64 </div> 96 </div>
65 </template> 97 </template>
66 98
...@@ -85,13 +117,37 @@ const props = defineProps({ ...@@ -85,13 +117,37 @@ const props = defineProps({
85 }) 117 })
86 118
87 // Emits定义 119 // Emits定义
88 -const emit = defineEmits(['update:modelValue', 'select', 'click-subtitle', 'panel-change']) 120 +const emit = defineEmits(['update:modelValue', 'select', 'click-subtitle', 'panel-change', 'select-course'])
89 121
90 // 响应式数据 122 // 响应式数据
91 const isExpanded = ref(false) 123 const isExpanded = ref(false)
92 const calendarRef = ref(null) 124 const calendarRef = ref(null)
93 const currentDate = ref(props.modelValue || new Date()) 125 const currentDate = ref(props.modelValue || new Date())
94 126
127 +// 作业筛选相关
128 +const showCoursePicker = ref(false)
129 +const selectedCourseText = ref('全部作业')
130 +const courseColumns = [
131 + { text: '全部作业', value: '' },
132 + { text: '语文语文语文语文语文语文', value: 'chinese' },
133 + { text: '数学', value: 'math' },
134 + { text: '英语', value: 'english' },
135 + { text: '物理', value: 'physics' },
136 + { text: '化学', value: 'chemistry' }
137 +]
138 +
139 +const openCoursePicker = () => {
140 + showCoursePicker.value = true
141 +}
142 +
143 +const onConfirmCourse = (result) => {
144 + // 兼容 Vant 3/4
145 + const option = result.selectedOptions ? result.selectedOptions[0] : result
146 + selectedCourseText.value = option.text
147 + showCoursePicker.value = false
148 + emit('select-course', option.value)
149 +}
150 +
95 // 计算属性:格式化当前日期显示 151 // 计算属性:格式化当前日期显示
96 const formattedCurrentDate = computed(() => { 152 const formattedCurrentDate = computed(() => {
97 return dayjs(currentDate.value).format('YYYY年MM月DD日') 153 return dayjs(currentDate.value).format('YYYY年MM月DD日')
...@@ -195,11 +251,11 @@ defineExpose({ ...@@ -195,11 +251,11 @@ defineExpose({
195 border-radius: 16px 16px 0 0; 251 border-radius: 16px 16px 0 0;
196 } 252 }
197 253
198 - &:hover { 254 + // &:hover {
199 - transform: translateY(-2px); 255 + // transform: translateY(-2px);
200 - box-shadow: 0 8px 30px rgba(76, 175, 80, 0.12), 0 4px 16px rgba(0, 0, 0, 0.08); 256 + // box-shadow: 0 8px 30px rgba(76, 175, 80, 0.12), 0 4px 16px rgba(0, 0, 0, 0.08);
201 - border-color: rgba(76, 175, 80, 0.2); 257 + // border-color: rgba(76, 175, 80, 0.2);
202 - } 258 + // }
203 259
204 &:active { 260 &:active {
205 transform: translateY(-1px); 261 transform: translateY(-1px);
...@@ -233,9 +289,9 @@ defineExpose({ ...@@ -233,9 +289,9 @@ defineExpose({
233 color: #2c3e50; 289 color: #2c3e50;
234 margin-bottom: 2px; 290 margin-bottom: 2px;
235 line-height: 1.3; 291 line-height: 1.3;
236 - overflow: hidden; 292 + // overflow: hidden;
237 - text-overflow: ellipsis; 293 + // text-overflow: ellipsis;
238 - white-space: nowrap; 294 + // white-space: nowrap;
239 } 295 }
240 296
241 .calendar-subtitle { 297 .calendar-subtitle {
...@@ -244,12 +300,30 @@ defineExpose({ ...@@ -244,12 +300,30 @@ defineExpose({
244 font-weight: 400; 300 font-weight: 400;
245 } 301 }
246 } 302 }
303 +
304 + .calendar-date-display {
305 + flex: 0.8;
306 +
307 + .calendar-date-main {
308 + font-size: 16px;
309 + font-weight: 600;
310 + color: #34495e;
311 + margin-bottom: 4px;
312 + line-height: 1.2;
313 + }
314 +
315 + .calendar-weekday {
316 + font-size: 13px;
317 + color: #4caf50;
318 + font-weight: 500;
319 + }
320 + }
247 } 321 }
248 322
249 .calendar-content { 323 .calendar-content {
250 display: flex; 324 display: flex;
251 align-items: center; 325 align-items: center;
252 - justify-content: space-between; 326 + justify-content: end;
253 gap: 16px; 327 gap: 16px;
254 328
255 .calendar-date-display { 329 .calendar-date-display {
...@@ -270,6 +344,14 @@ defineExpose({ ...@@ -270,6 +344,14 @@ defineExpose({
270 } 344 }
271 } 345 }
272 346
347 + .calendar-actions-wrapper {
348 + display: flex;
349 + flex-direction: column;
350 + align-items: flex-end;
351 + gap: 8px;
352 + flex-shrink: 0;
353 + }
354 +
273 .calendar-action { 355 .calendar-action {
274 display: flex; 356 display: flex;
275 align-items: center; 357 align-items: center;
...@@ -321,6 +403,6 @@ defineExpose({ ...@@ -321,6 +403,6 @@ defineExpose({
321 403
322 // 自定义日历样式 404 // 自定义日历样式
323 :deep(.van-popup) { 405 :deep(.van-popup) {
324 - border-radius: 0 0 12px 12px; 406 + // border-radius: 0 0 12px 12px;
325 } 407 }
326 </style> 408 </style>
......
1 <!-- 1 <!--
2 * @Date: 2025-05-29 15:34:17 2 * @Date: 2025-05-29 15:34:17
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-12-10 14:08:51 4 + * @LastEditTime: 2025-12-10 21:32:42
5 * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue 5 * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
18 @select="onSelectDay" 18 @select="onSelectDay"
19 @click-subtitle="onClickSubtitle" 19 @click-subtitle="onClickSubtitle"
20 @panel-change="onPanelChange" 20 @panel-change="onPanelChange"
21 + @select-course="onSelectCourse"
21 /> 22 />
22 </div> 23 </div>
23 24
...@@ -532,6 +533,17 @@ const onPanelChange = ({ date }) => { ...@@ -532,6 +533,17 @@ const onPanelChange = ({ date }) => {
532 getTaskDetail(dayjs(date).format('YYYY-MM')); 533 getTaskDetail(dayjs(date).format('YYYY-MM'));
533 } 534 }
534 535
536 +const selectedCourseText = ref('')
537 +
538 +/**
539 + * 处理作业选择事件
540 + * @param {string} course - 选中的作业
541 + */
542 +const onSelectCourse = (course) => {
543 + selectedCourseText.value = course.text;
544 + console.warn('选中的作业:', course);
545 +}
546 +
535 /** 547 /**
536 * 根据打卡类型获取对应的图标名称 548 * 根据打卡类型获取对应的图标名称
537 * @param {string} type - 打卡类型 549 * @param {string} type - 打卡类型
......