feat: 恭学教育基地管理系统初始提交

- 后端: NestJS 11 + TypeORM + JWT认证 + SQLite/MySQL
- 前端: React 19 + Ant Design 6 + Vite 8 + ECharts
- 功能模块: 数据面板、学生管理、宿舍管理、入住管理、费用录入、账单管理、教室管理、押金管理、操作日志、账号管理
- 支持Docker一键部署
This commit is contained in:
陈浩
2026-06-06 17:26:10 +08:00
commit 78676a124a
123 changed files with 26403 additions and 0 deletions

286
技术文档.md Normal file
View File

@@ -0,0 +1,286 @@
# 宿舍水电费精准计费系统 - 技术文档
## 一、系统概述
教培公司集训基地宿舍水电费精准计费系统,采用「人天数加权分摊」算法,按每位学生的实际入住天数公平分摊宿舍公共费用。
### 核心功能
| 模块 | 功能说明 |
|------|---------|
| 数据面板 | 统计卡片、费用趋势图、宿舍排行、甘特图 |
| 宿舍总览 | 房态可视化网格,空置/在住/满员颜色区分 |
| 学生管理 | 增删改查 |
| 宿舍管理 | 增删改查,删除前检查在住人员 |
| 入住管理 | 入住登记、退宿、换房、删除已退宿记录 |
| 费用录入 | 宿舍公共费用(水/电/保洁等)+ 个人附加费,支持编辑 |
| 账单管理 | 自动生成、确认、标记已付、删除、批量操作 |
| 账单导出 | Excel汇总+明细双Sheet、单条PDF账单 |
| 操作日志 | 所有涉及钱的操作自动审计留痕 |
| 账号管理 | 用户增删改查、角色区分、启用/禁用、重置密码仅admin可见 |
| 移动端适配 | 手机端Drawer导航、响应式表格和弹窗 |
---
## 二、技术架构
```
前端 (React + Vite) 后端 (NestJS) 数据库
┌─────────────────┐ ┌──────────────────┐ ┌──────────┐
│ React 19 │ │ NestJS 11 │ │ SQLite │
│ Ant Design 6 │────▶│ TypeORM 0.3 │────▶│ (开发) │
│ ECharts │ │ JWT + Passport │ │ MySQL 8 │
│ Vite 8 │ │ ExcelJS + PDFKit │ │ (生产) │
└─────────────────┘ └──────────────────┘ └──────────┘
```
### 前端技术栈
- React 19 + TypeScript
- Vite 8构建打包
- Ant Design 6UI 组件库)
- ECharts图表可视化
- react-router-dom v7路由
- axiosHTTP 客户端)
- dayjs日期处理
- Apple 设计语言:主色 #007AFF,背景 #f5f5f7
### 后端技术栈
- NestJS 11 + TypeScript
- TypeORM 0.3ORM 框架)
- passport-jwtJWT 认证)
- bcryptjs密码加密
- class-validator参数校验
- ExcelJSExcel 导出)
- PDFKitPDF 导出)
- SQLite / MySQL双数据库支持
---
## 三、项目目录结构
```
宿舍水电费/
├── backend/ # 后端NestJS
│ ├── src/
│ │ ├── entities/ # 数据库实体
│ │ │ ├── student.entity.ts
│ │ │ ├── room.entity.ts
│ │ │ ├── occupancy.entity.ts
│ │ │ ├── room-expense.entity.ts
│ │ │ ├── personal-expense.entity.ts
│ │ │ ├── bill.entity.ts
│ │ │ ├── bill-item.entity.ts
│ │ │ ├── user.entity.ts
│ │ │ ├── operation-log.entity.ts
│ │ │ └── index.ts
│ │ ├── auth/ # 认证 & 账号管理
│ │ │ ├── auth.module.ts
│ │ │ ├── auth.service.ts
│ │ │ ├── auth.controller.ts
│ │ │ ├── dto/auth.dto.ts
│ │ │ ├── guards/jwt-auth.guard.ts
│ │ │ └── strategies/jwt.strategy.ts
│ │ ├── students/ # 学生模块
│ │ ├── rooms/ # 宿舍模块
│ │ ├── occupancies/ # 入住模块
│ │ ├── expenses/ # 费用模块
│ │ ├── bills/ # 账单模块
│ │ │ ├── bills.module.ts
│ │ │ ├── bills.service.ts # 核心计费引擎
│ │ │ ├── bills-export.service.ts # Excel/PDF导出
│ │ │ ├── bills.controller.ts
│ │ │ └── dto/bill.dto.ts
│ │ ├── dashboard/ # 数据面板
│ │ ├── operation-logs/ # 操作日志(@Global
│ │ ├── app.module.ts # 根模块
│ │ └── main.ts # 入口
│ ├── .env.example # 环境变量模板
│ ├── package.json
│ └── tsconfig.json
├── frontend/ # 前端React + Vite
│ ├── src/
│ │ ├── api/index.ts # axios 实例自动携带JWT
│ │ ├── layouts/MainLayout.tsx # 主布局(桌面侧边栏/移动端Drawer
│ │ ├── pages/
│ │ │ ├── Login/ # 登录页
│ │ │ ├── Dashboard/ # 数据面板
│ │ │ ├── RoomVisual/ # 宿舍可视化
│ │ │ ├── Students/ # 学生管理
│ │ │ ├── Rooms/ # 宿舍管理
│ │ │ ├── Occupancies/ # 入住管理
│ │ │ ├── Expenses/ # 费用录入
│ │ │ ├── Bills/ # 账单管理(含导出)
│ │ │ ├── OperationLogs/ # 操作日志
│ │ │ └── Users/ # 账号管理
│ │ ├── App.tsx # 路由配置
│ │ ├── index.css # 全局样式 + 移动端媒体查询
│ │ └── main.tsx
│ ├── package.json
│ └── vite.config.ts
└── .gitignore
```
---
## 四、核心算法 —— 人天数加权分摊
```
学生应付 = (该学生计费天数 / 宿舍所有学生计费天数之和) × 宿舍该项总费用
```
**计费天数计算规则:**
- 起始日 = max(学生计费起始日, 账单周期开始日)
- 结束日 = min(学生退宿日 或 周期结束日, 账单周期结束日)
- 天数 = ceil(结束日 - 起始日) + 1不足一天按一天算
**设计亮点:**
- `billing_start_date``check_in_date` 分离,允许灵活调整计费起始日
- 个人附加费独立处理,不参与分摊
- 一次生成所有学生账单,包含分摊明细
---
## 五、数据库表结构
| 表名 | 说明 | 关键字段 |
|------|------|---------|
| students | 学生 | id, name, phone, id_card, status |
| rooms | 宿舍 | id, building, room_number, capacity |
| occupancies | 入住记录 | student_id, room_id, check_in_date, billing_start_date, check_out_date |
| room_expenses | 宿舍费用 | room_id, expense_type, amount, period_start, period_end |
| personal_expenses | 个人费用 | student_id, room_id, expense_type, amount, expense_date |
| bills | 账单 | student_id, period_start, period_end, shared_amount, personal_amount, total_amount, status |
| bill_items | 账单明细 | bill_id, expense_type, days, total_room_days, room_total_amount, student_amount |
| users | 系统用户 | username, password_hash, role(admin/operator), is_active, last_login_at |
| operation_logs | 操作日志 | user_id, username, module, action, target_id, detail, created_at |
---
## 六、API 接口列表
### 认证
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/auth/login | 登录 |
| POST | /api/auth/register | 创建账号需JWT |
| GET | /api/auth/profile | 当前用户信息 |
| GET | /api/auth/users | 用户列表 |
| PUT | /api/auth/users/:id | 编辑用户 |
| PUT | /api/auth/users/:id/password | 重置密码 |
| DELETE | /api/auth/users/:id | 删除用户 |
### 业务模块
| 方法 | 路径 | 说明 |
|------|------|------|
| CRUD | /api/students | 学生管理 |
| CRUD | /api/rooms | 宿舍管理 |
| GET | /api/rooms/visual | 宿舍可视化数据 |
| POST | /api/occupancies/check-in | 入住登记 |
| PUT | /api/occupancies/:id/check-out | 退宿 |
| PUT | /api/occupancies/:id/transfer | 换房 |
| CRUD | /api/expenses/room | 宿舍费用 |
| CRUD | /api/expenses/personal | 个人费用 |
| POST | /api/bills/generate | 生成账单 |
| GET | /api/bills | 账单列表 |
| GET | /api/bills/export/excel | 导出Excel |
| GET | /api/bills/export/pdf/:id | 导出单条PDF |
| PUT | /api/bills/:id/status | 更新状态 |
| GET | /api/operation-logs | 操作日志 |
| GET | /api/dashboard/stats | 统计数据 |
---
## 七、环境变量配置
参见 `backend/.env.example`
| 变量 | 说明 | 默认值 |
|------|------|--------|
| DB_TYPE | 数据库类型 | sqlite |
| DB_HOST | MySQL 主机 | localhost |
| DB_PORT | MySQL 端口 | 3306 |
| DB_USERNAME | 数据库用户 | root |
| DB_PASSWORD | 数据库密码 | (空) |
| DB_DATABASE | 数据库名 | dorm_billing |
| JWT_SECRET | JWT 签名密钥 | dorm-billing-jwt-secret-key-2024 |
| JWT_EXPIRES_IN | JWT 过期时间 | 24h |
| ADMIN_PASSWORD | 初始管理员密码 | admin123 |
---
## 八、生产部署(宝塔面板)
### 前置条件
- 宝塔面板已安装 Node.js v18+、MySQL 8.0
- 已创建数据库 `dorm_billing`
### 部署步骤
```bash
# 1. 上传代码到服务器
# 2. 配置后端环境变量
cd /www/wwwroot/dorm-billing/backend
cp .env.example .env
vi .env # 填入真实的数据库密码、JWT密钥、管理员密码
# 3. 安装依赖 & 构建
cd backend && npm install && npm run build
cd ../frontend && npm install && npm run build
# 4. PM2 启动后端
cd ../backend
pm2 start dist/main.js --name dorm-billing
pm2 save && pm2 startup
```
### Nginx 配置
```nginx
server {
listen 80;
server_name your-domain.com;
root /www/wwwroot/dorm-billing/frontend/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:3000/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
### 首次登录
-`admin` + `.env` 中设置的 `ADMIN_PASSWORD` 登录
- 进入「账号管理」为老师创建操作员账号
---
## 九、角色权限
| 角色 | 权限 |
|------|------|
| admin管理员 | 所有功能 + 账号管理 |
| operator操作员 | 除账号管理外的所有功能 |
---
## 十、常见运维操作
```bash
# 查看后端日志
pm2 logs dorm-billing
# 重启后端
pm2 restart dorm-billing
# 更新代码后重新部署
cd backend && npm install && npm run build && pm2 restart dorm-billing
cd ../frontend && npm install && npm run build
```