diff --git a/.DS_Store b/.DS_Store index c7e173b..b1b4307 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/deploy-prod-nobuild.sh b/deploy-prod-nobuild.sh index e2d4340..eddf32a 100755 --- a/deploy-prod-nobuild.sh +++ b/deploy-prod-nobuild.sh @@ -15,20 +15,20 @@ mkdir -p logs # 停止并删除现有容器 echo "📦 停止现有容器..." -docker-compose -f docker-compose.prod.yml down +docker compose -f docker-compose.prod.yml down # 构建新镜像 echo "🔨 构建Docker镜像..." -docker-compose -f docker-compose.prod.yml build --no-cache +docker compose --progress=plain -f docker-compose.prod.yml build --no-cache # 启动服务 echo "▶️ 启动PM2服务..." -docker-compose -f docker-compose.prod.yml up -d +docker compose -f docker-compose.prod.yml up -d # 检查服务状态 echo "🔍 检查服务状态..." sleep 15 -docker-compose -f docker-compose.prod.yml ps +docker compose -f docker-compose.prod.yml ps # 检查PM2进程状态 echo "🔄 检查PM2进程状态..." @@ -51,4 +51,4 @@ echo " ✅ 集群模式(2个实例)" echo " ✅ 自动重启和故障恢复" echo " ✅ 内存限制保护(1GB)" echo " ✅ 详细日志管理" -echo " ✅ 进程监控和健康检查" \ No newline at end of file +echo " ✅ 进程监控和健康检查" diff --git a/dist.zip b/dist.zip index 197e669..44dca17 100644 Binary files a/dist.zip and b/dist.zip differ diff --git a/src/components/MeetingTimeline.css b/src/components/MeetingTimeline.css index c5990ab..012cba9 100644 --- a/src/components/MeetingTimeline.css +++ b/src/components/MeetingTimeline.css @@ -244,6 +244,92 @@ } } +/* Dropdown Menu Styles */ +.meeting-actions { + position: relative; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.dropdown-trigger { + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + color: #64748b; +} + +.dropdown-trigger:hover { + background: #f1f5f9; + color: #334155; +} + +.dropdown-menu { + position: absolute; + top: 100%; + right: 0; + background: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + border: 1px solid #e2e8f0; + padding: 0.5rem; + margin-top: 0.5rem; + min-width: 120px; + z-index: 10; + display: flex; + flex-direction: column; + gap: 2px; +} + +.dropdown-item { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + border: none; + background: none; + cursor: pointer; + border-radius: 4px; + font-size: 0.875rem; + font-weight: 500; + color: #374151; + text-decoration: none; + transition: all 0.2s ease; + width: 100%; + text-align: left; +} + +/* 确保Link组件内的dropdown-item正确显示 */ +.dropdown-menu a { + text-decoration: none; + display: block; + width: 100%; +} + +.dropdown-menu a .dropdown-item { + width: 100%; +} + +.dropdown-item:hover { + background: #f3f4f6; + color: #111827; +} + +.dropdown-item.delete-item { + color: #dc2626; +} + +.dropdown-item.delete-item:hover { + background: #fef2f2; + color: #b91c1c; +} + .meeting-content { background: white; border-radius: 12px; diff --git a/src/components/MeetingTimeline.jsx b/src/components/MeetingTimeline.jsx index b3f9bb8..e9e6e5b 100644 --- a/src/components/MeetingTimeline.jsx +++ b/src/components/MeetingTimeline.jsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import { Link } from 'react-router-dom'; -import { Clock, Users, FileText, Calendar, User, Edit, Trash2, MoreVertical } from 'lucide-react'; +import { Link, useNavigate } from 'react-router-dom'; +import { Clock, Users, FileText, User, Edit, Calendar , Trash2, MoreVertical } from 'lucide-react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import rehypeRaw from 'rehype-raw'; @@ -11,7 +11,7 @@ import './MeetingTimeline.css'; const MeetingTimeline = ({ meetingsByDate, currentUser, onDeleteMeeting }) => { const [showDeleteConfirm, setShowDeleteConfirm] = useState(null); const [showDropdown, setShowDropdown] = useState(null); - + const navigate = useNavigate(); // Close dropdown when clicking outside React.useEffect(() => { const handleClickOutside = () => { @@ -66,6 +66,12 @@ const MeetingTimeline = ({ meetingsByDate, currentUser, onDeleteMeeting }) => { return lines.length > maxLines || summary.length > maxLength; }; + const handleEditClick = (meetingId, e) => { + e.preventDefault(); + navigate(`/meetings/edit/${meetingId}`) + setShowDropdown(null); + }; + const handleDeleteClick = (meetingId, e) => { e.preventDefault(); setShowDeleteConfirm(meetingId); @@ -141,15 +147,12 @@ const MeetingTimeline = ({ meetingsByDate, currentUser, onDeleteMeeting }) => { {showDropdown === meeting.meeting_id && (
e.stopPropagation()}> - e.stopPropagation()} +