Files
VolunteerManage-for-byw/.trae/documents/volunteer_system_plan.md
T
Trae Assistant 25b2b8f381 feat: 初始化义工时长管理系统
- 管理台:活动设置、时长登记、用户管理、数据导出(Excel/PNG)
- 用户端:姓名查询个人义工时长与活动记录
- 技术栈:React + Vite + TailwindCSS / Node.js + Express + sql.js (SQLite)
- 支持 Docker 部署,附带 Gitea Actions 自动部署工作流
- 响应式界面,兼容移动端与 PC 端
- 默认管理员账号:admin / admin123
2026-10-04 18:06:24 +08:00

12 KiB
Raw Blame History

义工时长管理系统实施计划

仓库研究结论

  • Gitea 仓库:Henry_Du/VolunteerManage-for-byw(空仓库,无任何提交)
  • 本地工作目录:d:\义工时长系统(空目录)
  • 部署目标:Docker 容器运行于服务器,域名 volunteer.bzw-hheb.top(反向代理)
  • CI/CD:Gitea Actions 自动构建并部署

技术选型

层级 技术方案 选型理由
前端框架 React 18 + Vite 5 + TypeScript 开发效率高,响应式生态成熟
UI 样式 TailwindCSS 3 快速构建硬边/极简响应式界面,契合用户 UI 偏好
组件库 shadcn/ui(按需引入) 轻量无样式组件,易定制硬边风格
后端框架 Node.js + Express + TypeScript 与前端同语言,部署简单
数据库 SQLite 3(better-sqlite3) 单文件数据库,无需额外容器;中小规模数据完全够用
认证 管理台:账号密码 + JWT;用户端:仅按姓名查询(无鉴权) 简单实用
导出 xlsx(Excel 表格)、html2canvas(图片 PNG) 表格+图片两种导出需求全覆盖
容器化 多阶段 Dockerfile(构建前端 → 打包后端 + 静态资源) 单容器部署,简单可靠
CI/CD Gitea Actions 推送 main 分支自动构建镜像,通过 SSH 部署到服务器

文件与模块结构

VolunteerManage-for-byw/
├── client/                          # 前端 React 项目
│   ├── src/
│   │   ├── components/              # 通用组件
│   │   ├── pages/
│   │   │   ├── admin/               # 管理台页面
│   │   │   │   ├── Login.tsx        # 管理员登录
│   │   │   │   ├── Layout.tsx       # 管理台布局 + 侧边栏
│   │   │   │   ├── Activities.tsx   # ① 活动设置
│   │   │   │   ├── Hours.tsx        # ② 义工时长登记 + 单次活动导出
│   │   │   │   ├── Users.tsx        # ③ 用户管理(含个人详情)
│   │   │   │   └── Export.tsx       # ④ 数据导出(多选导出项)
│   │   │   └── user/
│   │   │       ├── Index.tsx        # 姓名输入页
│   │   │       └── Dashboard.tsx    # 个人义工时长总览
│   │   ├── api/                     # axios 封装与接口定义
│   │   ├── types/                   # 共享类型
│   │   ├── App.tsx / main.tsx
│   │   └── index.css
│   ├── index.html
│   ├── vite.config.ts
│   ├── tailwind.config.ts
│   ├── tsconfig.json
│   └── package.json
├── server/                          # 后端 Express 项目
│   ├── src/
│   │   ├── index.ts                 # 入口:挂载静态资源 + API 路由
│   │   ├── db/
│   │   │   ├── index.ts             # SQLite 初始化 + 建表
│   │   │   └── schema.sql           # 建表 SQL(users, groups, activities, hours)
│   │   ├── middleware/
│   │   │   └── auth.ts              # JWT 鉴权中间件
│   │   ├── routes/
│   │   │   ├── auth.ts              # POST /api/admin/login
│   │   │   ├── activities.ts        # 活动 CRUD
│   │   │   ├── hours.ts             # 时长登记 + 按活动查询
│   │   │   ├── users.ts             # 部员 CRUD + 个人活动/累计时长
│   │   │   ├── groups.ts            # 工作组 CRUD
│   │   │   └── export.ts            # 各种导出接口(JSON 数据)
│   │   └── config.ts
│   ├── data/                        # SQLite db 文件存放目录(Docker volume 挂载)
│   ├── tsconfig.json
│   └── package.json
├── .gitea/
│   └── workflows/
│       └── deploy.yml               # Actions:构建镜像 → SSH 部署
├── Dockerfile                       # 多阶段构建
├── docker-compose.yml               # 本地快速调试用
├── .dockerignore
├── .gitignore
├── .npmrc                           # 配置 npmmirror 镜像源
└── README.md

数据库表设计(SQLite)

表名 关键字段 说明
work_groups id, name (唯一) 工作组(如"策划部"、"宣传部")
users id, class, name, volunteer_no, group_id (FK) 部员信息;班级+姓名组合唯一
activities id, title, content, start_time, end_time, created_at 活动
activity_groups activity_id, group_id 活动 ↔ 工作组 多对多关联
hours id, activity_id, user_id, hours(decimal), remark, created_at 义工时长登记(一人一次活动一条)
admins id, username, password_hash 管理员账号(初始化一条默认:admin / admin123)

实施步骤(按依赖顺序)

阶段 1:项目脚手架 & 基础配置

  1. 创建根目录结构:client/、server/、.gitea/workflows/
  2. 配置 .npmrc 使用 npmmirror 国内镜像
  3. 初始化前端 Vite + React + TS + TailwindCSS + shadcn 基础依赖
  4. 初始化后端 Express + TS + SQLite 基础依赖
  5. 编写 .gitignore、.dockerignore

阶段 2:后端 API 实现

  1. 编写 SQLite 初始化脚本(建表 + 插入默认管理员)
  2. 实现认证路由:管理员登录(返回 JWT) + 鉴权中间件
  3. 实现工作组 CRUD
  4. 实现部员 CRUD(含所属工作组;查询个人参与活动及累计时长)
  5. 实现活动 CRUD(含设置关联工作组)
  6. 实现时长登记 CRUD(为某活动某部员设置时长+备注;按活动查询所有人的登记)
  7. 实现导出路由:
    • 所有成员 / 所有活动 / 所有时长明细(可多选)
    • 按活动导出时长明细
    • 所有部员累计总时长
    • 所有部员参加的活动列表

阶段 3:前端页面实现

  1. 前端基础:axios 封装、API 类型、路由(react-router-dom)
  2. 用户端:
    • 姓名输入首页(无鉴权,输入姓名查询匹配部员)
    • 个人总览(总时长、参与活动列表)
  3. 管理台:
    • 登录页 + JWT 持久化(localStorage)+ 路由守卫
    • 侧边栏布局(活动/时长/用户/导出四大模块)
    • 活动设置页(列表、新建/编辑弹窗,设置工作组复选框)
    • 时长登记页(选择活动 → 显示参与工作组所有成员 → 填写每人时长/备注 → 保存;提供导出为 Excel / 导出为图片按钮)
    • 用户管理页(部员列表、新建/编辑弹窗、查看详情(累计时长+参与活动))
    • 数据导出页(勾选要导出的内容:全部表格 / 总时长 / 活动记录 → 导出 Excel 或 图片)

阶段 4:容器化与部署

  1. 编写 Dockerfile 多阶段构建:
    • Stage 1:构建 client 生成静态资源
    • Stage 2:构建 server TS → JS,复制 client/dist 作为静态资源
    • Stage 3:node:20-alpine 运行,EXPOSE 3000,挂载 /app/server/data 卷
  2. 编写 docker-compose.yml(本地调试)
  3. 编写 Gitea Actions 工作流 .gitea/workflows/deploy.yml:
    • 触发:push 到 main
    • 步骤:checkout → 登录 Docker Registry(或直接本机构建后导出)→ 构建镜像 → 通过 SSH 连接服务器 → scp 复制 docker-compose(或 docker run)启动新容器 → 健康检查

阶段 5:本地验证 & 推送

  1. 本地 docker compose up 验证系统各功能模块正常
  2. 所有代码首次提交并推送到 Gitea main 分支,触发 Action 自动部署
  3. 线上 volunteer.bzw-hheb.top 访问验证

依赖与注意事项

  1. npm 强制:所有安装命令使用 npm install,不使用 pnpm。.npmrc 写入 registry=https://registry.npmmirror.com。
  2. 管理员初始账号:首次启动自动创建 admin / admin123,需在 README 提醒首次登录后修改(后端提供修改密码接口)。
  3. 数据持久化:SQLite 数据库文件位于容器内 /app/server/data/volunteer.db,部署时必须挂载为 Docker volume 或 bind mount,否则容器重建数据丢失。
  4. 用户端查询:按"姓名"匹配若有重名,展示列表让用户选择(班级+义工号辅助辨别)。
  5. 图片导出:前端将表格渲染成 HTML 后用 html2canvas 生成 PNG 下载;Excel 导出由前端拿到 JSON 数据后用 xlsx 生成。
  6. UI 风格:TailwindCSS 默认禁用圆角(配置 borderRadius: { DEFAULT: '0px' } 或组件级手动零圆角),浅色/黑白专业风。
  7. 响应式:TailwindCSS 断点 md: 适配移动端(菜单变为汉堡按钮、表格水平滚动)。
  8. 反向代理:服务器上由 nginx/caddy 将 volunteer.bzw-hheb.top 反代到容器端口(Action 部署后由用户在服务器上已配置好反向代理)。
  9. Gitea Actions 机密(Secrets):用户需要在 Gitea 仓库设置中配置以下 Secrets:
    • SSH_HOST:服务器 IP/域名
    • SSH_PORT:SSH 端口(默认 22)
    • SSH_USER:SSH 用户名
    • SSH_PRIVATE_KEY:服务器 SSH 私钥

验证清单

  • 管理台登录/退出
  • 工作组增删改查
  • 部员增删改查;查看个人累计时长与活动明细
  • 活动发布(设置工作组);活动编辑/删除
  • 活动时长登记(批量设置);修改/删除登记
  • 单次活动导出:Excel 文件包含姓名、班级、义工号、工作组、时长、备注
  • 单次活动导出:图片样式美观、中文不乱码
  • 总数据导出:支持多选导出项;Excel 多 Sheet 或分文件
  • 所有部员总时长导出(按时长降序)
  • 所有部员参加的活动列表导出
  • 用户端:输入姓名→选择部员→展示总时长与活动列表
  • 移动端:关键页面无横滚(除表格内滚动),点击区域适合手指
  • Docker 构建成功并运行;/app/server/data 持久化正常
  • Gitea Actions push main 后自动部署成功
  • https://volunteer.bzw-hheb.top 可访问各页面

风险与处理

风险 处理方案
html2canvas 在中文/表格复杂时截图截断或样式偏差 对导出区域设置固定宽高、关闭动画、使用 useCORS:true;提供 Excel 导出作为可靠主力
重名部员导致用户端查询混乱 列出所有匹配项,展示班级+义工号让用户二次确认
SQLite 并发写入性能 义工系统写入量低(仅管理员操作),无并发瓶颈;使用 WAL 模式(better-sqlite3 默认支持)
Action SSH 部署失败 先本地手动部署验证一次后再启用 Action;提供备用手动部署步骤(README)
服务器反向代理未配置 WebSocket(如有需要) 本系统无 WebSocket 实时推送,纯 HTTP 即可