This commit is contained in:
@@ -16,3 +16,5 @@ client/dist/
|
|||||||
client/node_modules/
|
client/node_modules/
|
||||||
server/node_modules/
|
server/node_modules/
|
||||||
server/dist/
|
server/dist/
|
||||||
|
**/tsconfig.tsbuildinfo
|
||||||
|
.trae/
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
# 义工时长管理系统实施计划
|
|
||||||
|
|
||||||
## 仓库研究结论
|
|
||||||
|
|
||||||
- **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 即可 |
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"root":["./src/app.tsx","./src/main.tsx","./src/api/index.ts","./src/components/button.tsx","./src/components/datatable.tsx","./src/components/input.tsx","./src/components/modal.tsx","./src/components/select.tsx","./src/components/textarea.tsx","./src/pages/admin/activities.tsx","./src/pages/admin/export.tsx","./src/pages/admin/hours.tsx","./src/pages/admin/layout.tsx","./src/pages/admin/login.tsx","./src/pages/admin/users.tsx","./src/pages/user/dashboard.tsx","./src/pages/user/index.tsx","./src/types/index.ts","./src/utils/export.ts"],"version":"5.9.3"}
|
|
||||||
Reference in New Issue
Block a user