From 306cb41516c91ca7957332c08785c1b03411dde4 Mon Sep 17 00:00:00 2001 From: ddshi <8811906+ddshi@user.noreply.gitee.com> Date: Fri, 6 Feb 2026 13:44:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E7=AA=97=E5=8F=A3UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化日期时间选择器为组合布局(同一行按钮) - 优先级改名为颜色 - 提醒类型移除农历选项 - 使用Popover优化选择器交互 --- src/components/reminder/ReminderCard.tsx | 33 ++++-- src/pages/ArchivePage.tsx | 8 +- src/pages/HomePage.tsx | 135 +++++++++++++++-------- src/stores/contextMenu.ts | 22 +++- 4 files changed, 132 insertions(+), 66 deletions(-) diff --git a/src/components/reminder/ReminderCard.tsx b/src/components/reminder/ReminderCard.tsx index 7eb9d0b..5021e16 100644 --- a/src/components/reminder/ReminderCard.tsx +++ b/src/components/reminder/ReminderCard.tsx @@ -73,6 +73,7 @@ export function ReminderCard({ // 使用全局状态管理右键菜单 const openEventId = useContextMenuStore((state) => state.openEventId); + const menuPosition = useContextMenuStore((state) => state.menuPosition); const { openMenu, closeMenu } = useContextMenuStore(); const isMenuOpen = openEventId === event.id; @@ -84,10 +85,10 @@ export function ReminderCard({ // 右键点击处理 const handleContextMenu = useCallback((e: React.MouseEvent) => { e.preventDefault(); - console.log('[ContextMenu] 右键点击事件, eventId:', event.id); + console.log('[ContextMenu] 右键点击事件, eventId:', event.id, 'x:', e.clientX, 'y:', e.clientY); - // 打开菜单 - openMenu(event.id); + // 打开菜单,传入鼠标位置 + openMenu(event.id, { x: e.clientX, y: e.clientY }); }, [event.id, openMenu]); // 点击外部关闭菜单 @@ -120,25 +121,35 @@ export function ReminderCard({ // 计算菜单位置(带边缘保护) const getMenuPosition = () => { - if (!cardRef.current) return { left: 0, top: 0 }; - - const cardRect = cardRef.current.getBoundingClientRect(); const menuWidth = 180; // 菜单宽度 const menuHeight = 150; // 估算菜单高度 const padding = 8; // 边缘padding - // 计算左侧位置 - let left = cardRect.left; + // 如果有鼠标位置,使用鼠标位置 + let left = padding; + let top = padding; + + if (menuPosition) { + // 水平位置跟随鼠标,添加偏移避免遮挡 + left = menuPosition.x + 4; + // 垂直位置优先显示在鼠标下方 + top = menuPosition.y + 4; + } else if (cardRef.current) { + // 回退到卡片位置 + const cardRect = cardRef.current.getBoundingClientRect(); + left = cardRect.left; + top = cardRect.bottom + 4; + } + + // 边缘保护:确保不超出视口 if (left + menuWidth > window.innerWidth - padding) { left = window.innerWidth - menuWidth - padding; } if (left < padding) left = padding; - // 计算顶部位置(优先显示在下方) - let top = cardRect.bottom + 4; if (top + menuHeight > window.innerHeight - padding) { // 如果下方空间不足,显示在上方 - top = cardRect.top - menuHeight - 4; + top = menuPosition ? menuPosition.y - menuHeight - 4 : top; } if (top < padding) top = padding; diff --git a/src/pages/ArchivePage.tsx b/src/pages/ArchivePage.tsx index 4b71c1c..02543fc 100644 --- a/src/pages/ArchivePage.tsx +++ b/src/pages/ArchivePage.tsx @@ -62,8 +62,12 @@ export function ArchivePage() { if (e.type !== 'reminder' || !e.is_completed) return false; if (!e.date) return false; // 跳过无日期的 const eventDate = new Date(e.date); - const now = new Date(); - return eventDate < now; // 仅已过期的 + // 获取今天的开始时间(只比较日期部分) + const today = new Date(); + today.setHours(0, 0, 0, 0); + const eventDateOnly = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()); + // 仅显示已过期的(日期早于今天) + return eventDateOnly < today; }).sort((a, b) => { if (!a.date || !b.date) return 0; return new Date(b.date).getTime() - new Date(a.date).getTime(); diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 2c2ca48..7f4d86f 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useRef } from 'react'; import { Container, Title, @@ -12,9 +12,10 @@ import { Select, Stack, Box, + Popover, } from '@mantine/core'; import { DatePickerInput, TimeInput } from '@mantine/dates'; -import { IconLogout, IconSettings } from '@tabler/icons-react'; +import { IconCalendar, IconClock, IconSettings, IconLogout } from '@tabler/icons-react'; import { useDisclosure } from '@mantine/hooks'; import { useNavigate } from 'react-router-dom'; import { useAppStore } from '../stores'; @@ -460,56 +461,96 @@ export function HomePage() { /> )} - {/* Date */} - - 日期 - - } - placeholder="选择日期" - value={formDate} - onChange={(value) => setFormDate(value as Date | null)} - required - styles={{ - input: { - borderRadius: 2, - background: '#faf9f7', - }, - }} - /> + {/* Date & Time - Combined selector */} + + + 日期 + + + {/* Date selector */} + + + + + + setFormDate(value as Date | null)} + styles={{ + input: { + borderRadius: 2, + }, + }} + /> + + - {/* Time (only for reminders) */} - {formType === 'reminder' && ( - + + + + + setFormTime(e.target.value)} + styles={{ + input: { + borderRadius: 2, + }, + }} + /> + + + )} + + + + {/* Lunar switch (only for anniversaries) */} + {formType === 'anniversary' && ( + - 时间 + + 农历日期 } - placeholder="选择时间" - value={formTime} - onChange={(e) => setFormTime(e.target.value)} - styles={{ - input: { - borderRadius: 2, - background: '#faf9f7', - }, - }} + checked={formIsLunar} + onChange={(e) => setFormIsLunar(e.currentTarget.checked)} /> )} - {/* Lunar switch */} - - 农历日期 - - } - checked={formIsLunar} - onChange={(e) => setFormIsLunar(e.currentTarget.checked)} - /> - {/* Repeat type */}