callmeyan b01ce4d2c9 fix(file-upload): 优化文件上传逻辑并防止重复添加
- 更新服务器端文件上传处理逻辑,避免重复发送事件
- 客户端优化文件上传组件,防止重复添加文件
- 调整文件列表更新策略,支持文件更新
- 优化上传区域样式,提升用户体验
2025-08-01 18:13:16 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00
2025-08-01 15:41:44 +08:00

My Live Photos - 实时文件共享系统

一个轻量级的实时文件共享系统,支持图片和视频文件的上传与实时分享。

🚀 功能特性

核心功能

  • 实时文件上传: 支持图片和视频文件的拖拽上传和点击上传
  • WebSocket 实时推送: 文件上传后立即推送给所有在线用户
  • 响应式现代UI设计: 基于Tailwind CSS的现代化界面支持移动端和桌面端
  • 管理员面板: 提供文件管理功能,包括文件状态控制
  • SQLite 数据存储: 轻量级数据库存储文件元数据
  • 文件隐藏/显示控制: 管理员可以控制文件的可见性
  • 文件删除功能: 支持安全删除文件及其记录

技术亮点

  • 实时双向通信,低延迟
  • 文件上传进度显示
  • 图片预览和视频播放
  • 文件分类和筛选
  • 响应式网格布局
  • 暗色/亮色主题切换

🛠 技术栈

前端

  • Next.js 14+: React全栈框架支持SSR和静态生成
  • TypeScript: 类型安全的JavaScript
  • Tailwind CSS: 实用优先的CSS框架
  • Socket.io Client: 实时通信客户端
  • React Hook Form: 高性能表单处理
  • Lucide React: 现代化图标库

后端

  • Next.js API Routes: 内置API路由
  • Socket.io Server: WebSocket服务器
  • SQLite: 轻量级关系型数据库
  • Prisma: 数据库ORM和迁移工具
  • Multer: 文件上传中间件
  • Sharp: 图片处理库

开发工具

  • ESLint: 代码质量检查
  • Prettier: 代码格式化
  • Husky: Git hooks管理
  • Commitlint: 提交信息规范

📁 项目结构

my-live-photos/
├── README.md
├── package.json
├── next.config.js
├── tailwind.config.js
├── tsconfig.json
├── .env.local
├── .env.example
├── prisma/
│   ├── schema.prisma
│   ├── migrations/
│   └── seed.ts
├── public/
│   ├── uploads/
│   │   ├── images/
│   │   └── videos/
│   ├── favicon.ico
│   └── robots.txt
├── src/
│   ├── app/
│   │   ├── globals.css
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   └── admin/
│   │       ├── layout.tsx
│   │       └── page.tsx
│   ├── components/
│   │   ├── ui/
│   │   │   ├── button.tsx
│   │   │   ├── card.tsx
│   │   │   ├── dialog.tsx
│   │   │   ├── dropdown-menu.tsx
│   │   │   ├── input.tsx
│   │   │   ├── toast.tsx
│   │   │   └── tooltip.tsx
│   │   ├── FileCard.tsx
│   │   ├── FileGrid.tsx
│   │   ├── FileUpload.tsx
│   │   ├── Header.tsx
│   │   ├── AdminPanel.tsx
│   │   ├── ThemeToggle.tsx
│   │   └── SocketProvider.tsx
│   ├── lib/
│   │   ├── db.ts
│   │   ├── socket.ts
│   │   ├── utils.ts
│   │   └── validations.ts
│   ├── types/
│   │   ├── file.ts
│   │   └── api.ts
│   ├── hooks/
│   │   ├── useFiles.ts
│   │   ├── useUpload.ts
│   │   └── useTheme.ts
│   └── api/
│       ├── files/
│       │   ├── route.ts
│       │   └── [id]/route.ts
│       └── upload/
│           └── route.ts
└── .gitignore

🗄 数据库设计

文件表 (files)

CREATE TABLE files (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  filename VARCHAR(255) NOT NULL,
  original_name VARCHAR(255) NOT NULL,
  file_type VARCHAR(50) NOT NULL,
  file_size INTEGER NOT NULL,
  file_path VARCHAR(500) NOT NULL,
  mime_type VARCHAR(100) NOT NULL,
  is_visible BOOLEAN DEFAULT true,
  is_deleted BOOLEAN DEFAULT false,
  uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

索引设计

CREATE INDEX idx_files_type ON files(file_type);
CREATE INDEX idx_files_visible ON files(is_visible);
CREATE INDEX idx_files_uploaded_at ON files(uploaded_at DESC);

🔌 API 设计

文件上传 API

POST /api/upload
Content-Type: multipart/form-data

请求体:
- file: 文件对象
- metadata: JSON字符串可选

响应:
{
  "success": true,
  "file": {
    "id": 1,
    "filename": "uuid_filename.jpg",
    "originalName": "photo.jpg",
    "fileType": "image",
    "fileSize": 1024000,
    "filePath": "/uploads/images/uuid_filename.jpg",
    "mimeType": "image/jpeg",
    "isVisible": true,
    "uploadedAt": "2024-01-01T00:00:00Z"
  }
}

获取文件列表 API

GET /api/files?type=image&page=1&limit=20

响应:
{
  "success": true,
  "files": [...],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 100,
    "totalPages": 5
  }
}

文件管理 API

PUT /api/files/[id]
{
  "isVisible": false
}

DELETE /api/files/[id]

📡 WebSocket 事件

客户端事件

  • file:upload: 文件上传
  • file:delete: 文件删除
  • file:toggle:visibility: 切换文件可见性

服务器事件

  • file:uploaded: 新文件上传通知
  • file:deleted: 文件删除通知
  • file:visibility:changed: 文件可见性变更通知
  • user:connected: 用户连接通知
  • user:disconnected: 用户断开连接通知

🎨 UI/UX 设计

颜色主题

:root {
  --primary: #3b82f6;
  --primary-dark: #2563eb;
  --secondary: #64748b;
  --background: #ffffff;
  --surface: #f8fafc;
  --text: #1e293b;
  --text-secondary: #64748b;
  --border: #e2e8f0;
  --success: #10b981;
  --warning: #f59e0b;
  --error: #ef4444;
}

.dark {
  --background: #0f172a;
  --surface: #1e293b;
  --text: #f1f5f9;
  --text-secondary: #94a3b8;
  --border: #334155;
}

组件设计

  1. 文件卡片: 显示文件预览、基本信息和操作按钮
  2. 上传区域: 拖拽上传区域,支持点击选择文件
  3. 文件网格: 响应式网格布局,自适应不同屏幕尺寸
  4. 管理面板: 文件列表管理界面,支持批量操作
  5. 实时通知: Toast通知系统显示实时更新

🚀 快速开始

环境要求

  • Node.js 18+
  • npm 或 yarn

安装依赖

npm install

环境配置

cp .env.example .env.local
# 编辑 .env.local 文件,配置数据库连接等

数据库初始化

npx prisma generate
npx prisma db push
npx prisma db seed

启动开发服务器

npm run dev

访问 http://localhost:3000 查看应用

构建生产版本

npm run build
npm start

🔧 开发指南

添加新功能

  1. src/types/ 中定义类型
  2. src/lib/validations.ts 中添加验证规则
  3. src/api/ 中创建API路由
  4. src/components/ 中创建UI组件
  5. src/hooks/ 中创建自定义Hook

代码规范

  • 使用 TypeScript 严格模式
  • 遵循 ESLint 和 Prettier 规则
  • 使用 Conventional Commits 提交规范
  • 编写组件和函数的 JSDoc 注释

测试策略

  • 单元测试: Jest + React Testing Library
  • 集成测试: Playwright
  • API测试: Supertest

📈 性能优化

前端优化

  • 图片懒加载和压缩
  • 虚拟滚动处理大量文件
  • 代码分割和懒加载
  • 缓存策略优化

后端优化

  • 文件上传大小限制和类型验证
  • 数据库查询优化和索引
  • WebSocket连接管理
  • CDN集成静态资源

🔒 安全考虑

文件上传安全

  • 文件类型白名单验证
  • 文件大小限制
  • 文件名消毒处理
  • 病毒扫描集成

数据安全

  • SQL注入防护
  • XSS攻击防护
  • CSRF保护
  • 认证和授权

📄 许可证

MIT License

🤝 贡献指南

  1. Fork 项目
  2. 创建功能分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 创建 Pull Request

📞 联系方式

如有问题或建议,请通过以下方式联系:

  • 创建 Issue
  • 发送邮件
  • 提交 Pull Request

My Live Photos - 让分享更简单,让回忆更鲜活。

Description
No description provided
Readme 160 KiB
Languages
TypeScript 91.4%
JavaScript 6.6%
CSS 2%