Browse Source

docs: add comprehensive AR recognition and backend API documentation

- Created AR quick start guide with testing instructions, troubleshooting, and deployment steps
- Added detailed AR recognition feature documentation covering TensorFlow.js integration, waste classification mapping, and performance optimization
- Included backend README with Spring Boot project structure, API endpoints, database schema, and deployment configuration
- Documented complete technical specifications for AR scanning
徐福静0235668 3 days ago
parent
commit
e6e0bfde95
100 changed files with 3526 additions and 0 deletions
  1. 152 0
      AR功能快速开始.md
  2. 306 0
      AR智能识别功能说明.md
  3. 164 0
      backend/README.md
  4. 126 0
      backend/pom.xml
  5. 14 0
      backend/src/main/java/com/recycle/RecycleAppApplication.java
  6. 27 0
      backend/src/main/java/com/recycle/common/PageResult.java
  7. 57 0
      backend/src/main/java/com/recycle/common/Result.java
  8. 38 0
      backend/src/main/java/com/recycle/config/MybatisPlusConfig.java
  9. 99 0
      backend/src/main/java/com/recycle/config/SwaggerConfig.java
  10. 43 0
      backend/src/main/java/com/recycle/config/WebConfig.java
  11. 24 0
      backend/src/main/java/com/recycle/controller/business/BusinessAuthController.java
  12. 64 0
      backend/src/main/java/com/recycle/controller/business/BusinessOrderController.java
  13. 52 0
      backend/src/main/java/com/recycle/controller/client/AuthController.java
  14. 34 0
      backend/src/main/java/com/recycle/controller/client/CategoryController.java
  15. 44 0
      backend/src/main/java/com/recycle/controller/client/CollectorController.java
  16. 65 0
      backend/src/main/java/com/recycle/controller/client/OrderController.java
  17. 43 0
      backend/src/main/java/com/recycle/controller/client/ProductController.java
  18. 76 0
      backend/src/main/java/com/recycle/controller/client/UserController.java
  19. 24 0
      backend/src/main/java/com/recycle/controller/government/GovernmentAuthController.java
  20. 45 0
      backend/src/main/java/com/recycle/controller/government/StatisticsController.java
  21. 21 0
      backend/src/main/java/com/recycle/dto/LoginDTO.java
  22. 26 0
      backend/src/main/java/com/recycle/dto/RegisterDTO.java
  23. 28 0
      backend/src/main/java/com/recycle/entity/Activity.java
  24. 31 0
      backend/src/main/java/com/recycle/entity/AdministrativeRegion.java
  25. 21 0
      backend/src/main/java/com/recycle/entity/AiChatHistory.java
  26. 24 0
      backend/src/main/java/com/recycle/entity/AiGeneratedReport.java
  27. 22 0
      backend/src/main/java/com/recycle/entity/AiInsight.java
  28. 22 0
      backend/src/main/java/com/recycle/entity/Badge.java
  29. 22 0
      backend/src/main/java/com/recycle/entity/BusinessAlert.java
  30. 32 0
      backend/src/main/java/com/recycle/entity/BusinessOrder.java
  31. 24 0
      backend/src/main/java/com/recycle/entity/BusinessTodo.java
  32. 28 0
      backend/src/main/java/com/recycle/entity/CategoryStatistics.java
  33. 20 0
      backend/src/main/java/com/recycle/entity/CheckinRecord.java
  34. 59 0
      backend/src/main/java/com/recycle/entity/Collector.java
  35. 30 0
      backend/src/main/java/com/recycle/entity/ComplianceCheck.java
  36. 24 0
      backend/src/main/java/com/recycle/entity/Contract.java
  37. 20 0
      backend/src/main/java/com/recycle/entity/CustomerServiceMessage.java
  38. 18 0
      backend/src/main/java/com/recycle/entity/CustomerServiceSession.java
  39. 31 0
      backend/src/main/java/com/recycle/entity/Device.java
  40. 22 0
      backend/src/main/java/com/recycle/entity/DeviceAlert.java
  41. 26 0
      backend/src/main/java/com/recycle/entity/DeviceMaintenance.java
  42. 23 0
      backend/src/main/java/com/recycle/entity/DonationProject.java
  43. 23 0
      backend/src/main/java/com/recycle/entity/DonationRecord.java
  44. 45 0
      backend/src/main/java/com/recycle/entity/DropPoint.java
  45. 36 0
      backend/src/main/java/com/recycle/entity/Earning.java
  46. 47 0
      backend/src/main/java/com/recycle/entity/Enterprise.java
  47. 22 0
      backend/src/main/java/com/recycle/entity/EnterpriseEmployee.java
  48. 26 0
      backend/src/main/java/com/recycle/entity/EnterpriseSubscription.java
  49. 24 0
      backend/src/main/java/com/recycle/entity/ExchangeRecord.java
  50. 18 0
      backend/src/main/java/com/recycle/entity/Favorite.java
  51. 27 0
      backend/src/main/java/com/recycle/entity/GovernmentNotice.java
  52. 24 0
      backend/src/main/java/com/recycle/entity/GovernmentOperationLog.java
  53. 45 0
      backend/src/main/java/com/recycle/entity/GovernmentUser.java
  54. 31 0
      backend/src/main/java/com/recycle/entity/GovernmentWarning.java
  55. 26 0
      backend/src/main/java/com/recycle/entity/IndustryChainData.java
  56. 23 0
      backend/src/main/java/com/recycle/entity/InviteRecord.java
  57. 23 0
      backend/src/main/java/com/recycle/entity/LoginLog.java
  58. 28 0
      backend/src/main/java/com/recycle/entity/MonitoringLocation.java
  59. 33 0
      backend/src/main/java/com/recycle/entity/Notification.java
  60. 23 0
      backend/src/main/java/com/recycle/entity/NotificationSetting.java
  61. 25 0
      backend/src/main/java/com/recycle/entity/OrderReview.java
  62. 22 0
      backend/src/main/java/com/recycle/entity/PointsRecord.java
  63. 23 0
      backend/src/main/java/com/recycle/entity/Policy.java
  64. 23 0
      backend/src/main/java/com/recycle/entity/PolicyApplication.java
  65. 29 0
      backend/src/main/java/com/recycle/entity/PolicyEvaluation.java
  66. 26 0
      backend/src/main/java/com/recycle/entity/PolicySimulation.java
  67. 47 0
      backend/src/main/java/com/recycle/entity/Product.java
  68. 78 0
      backend/src/main/java/com/recycle/entity/RecycleOrder.java
  69. 35 0
      backend/src/main/java/com/recycle/entity/RecycleStation.java
  70. 29 0
      backend/src/main/java/com/recycle/entity/RegionStatistics.java
  71. 24 0
      backend/src/main/java/com/recycle/entity/RiskAssessment.java
  72. 23 0
      backend/src/main/java/com/recycle/entity/ScanHistory.java
  73. 28 0
      backend/src/main/java/com/recycle/entity/StatisticsReport.java
  74. 23 0
      backend/src/main/java/com/recycle/entity/SubscriptionPlan.java
  75. 33 0
      backend/src/main/java/com/recycle/entity/SubsidyApplication.java
  76. 28 0
      backend/src/main/java/com/recycle/entity/SubsidyPayment.java
  77. 24 0
      backend/src/main/java/com/recycle/entity/Task.java
  78. 59 0
      backend/src/main/java/com/recycle/entity/User.java
  79. 47 0
      backend/src/main/java/com/recycle/entity/UserAddress.java
  80. 17 0
      backend/src/main/java/com/recycle/entity/UserBadge.java
  81. 24 0
      backend/src/main/java/com/recycle/entity/UserTask.java
  82. 44 0
      backend/src/main/java/com/recycle/entity/WasteCategory.java
  83. 23 0
      backend/src/main/java/com/recycle/entity/WithdrawRecord.java
  84. 41 0
      backend/src/main/java/com/recycle/exception/GlobalExceptionHandler.java
  85. 49 0
      backend/src/main/java/com/recycle/interceptor/AuthInterceptor.java
  86. 7 0
      backend/src/main/java/com/recycle/mapper/ActivityMapper.java
  87. 7 0
      backend/src/main/java/com/recycle/mapper/AdministrativeRegionMapper.java
  88. 7 0
      backend/src/main/java/com/recycle/mapper/AiChatHistoryMapper.java
  89. 7 0
      backend/src/main/java/com/recycle/mapper/AiGeneratedReportMapper.java
  90. 7 0
      backend/src/main/java/com/recycle/mapper/AiInsightMapper.java
  91. 7 0
      backend/src/main/java/com/recycle/mapper/BadgeMapper.java
  92. 7 0
      backend/src/main/java/com/recycle/mapper/BusinessAlertMapper.java
  93. 7 0
      backend/src/main/java/com/recycle/mapper/BusinessOrderMapper.java
  94. 7 0
      backend/src/main/java/com/recycle/mapper/BusinessTodoMapper.java
  95. 7 0
      backend/src/main/java/com/recycle/mapper/CategoryStatisticsMapper.java
  96. 7 0
      backend/src/main/java/com/recycle/mapper/CheckinRecordMapper.java
  97. 9 0
      backend/src/main/java/com/recycle/mapper/CollectorMapper.java
  98. 7 0
      backend/src/main/java/com/recycle/mapper/ComplianceCheckMapper.java
  99. 7 0
      backend/src/main/java/com/recycle/mapper/ContractMapper.java
  100. 7 0
      backend/src/main/java/com/recycle/mapper/CustomerServiceMessageMapper.java

+ 152 - 0
AR功能快速开始.md

@@ -0,0 +1,152 @@
+# AR智能识别 - 快速开始
+
+## 立即测试
+
+### 1. 启动开发服务器
+
+```bash
+npm start
+```
+
+### 2. 访问AR识别页面
+
+浏览器打开: `http://localhost:4200/consumer/ar-recognition`
+
+**重要**: 摄像头访问需要 HTTPS 或 localhost
+
+### 3. 使用流程
+
+1. **等待模型加载** (首次约 3-5 秒)
+2. **点击"开始扫描"按钮**
+3. **允许摄像头权限**
+4. **对准任意物品**:
+   - 塑料瓶
+   - 手机/电脑
+   - 书籍/纸张
+   - 水果
+   - 餐具
+   - 电子产品
+
+5. **查看识别结果**:
+   - 废品类别
+   - 可获得积分
+   - 回收建议
+
+## 测试建议
+
+### 推荐测试物品
+
+| 物品 | 预期类别 | 积分 |
+|------|----------|------|
+| 塑料瓶 | 可回收垃圾 | 5 |
+| 手机 | 可回收垃圾 | 50 |
+| 笔记本电脑 | 可回收垃圾 | 100 |
+| 苹果/橙子 | 厨余垃圾 | 2 |
+| 书籍 | 可回收垃圾 | 3 |
+| 剪刀 | 可回收垃圾 | 5 |
+
+### 最佳识别效果
+
+- ✅ 光线充足
+- ✅ 物品清晰对焦
+- ✅ 物品占据画面 1/3 以上
+- ✅ 背景简洁
+
+## 核心文件
+
+```
+src/app/
+├── core/services/
+│   └── ar-scanner.service.ts       # AI识别服务
+└── consumer/home/ar-recognition/
+    ├── ar-recognition.ts           # 组件逻辑
+    ├── ar-recognition.html         # 界面模板
+    └── ar-recognition.scss         # 样式
+```
+
+## 调整参数
+
+### 识别灵敏度
+
+`ar-recognition.ts:109`
+```typescript
+if (result && result.confidence > 60) { // 调整阈值 (0-100)
+```
+
+### 检测频率
+
+`ar-recognition.ts:97`
+```typescript
+setInterval(async () => {
+  // ...
+}, 500); // 调整间隔 (毫秒)
+```
+
+### 视频质量
+
+`ar-scanner.service.ts:54`
+```typescript
+video: {
+  facingMode: 'environment',
+  width: { ideal: 1280 },  // 分辨率
+  height: { ideal: 720 }
+}
+```
+
+## 故障排除
+
+### 摄像头无法访问
+```bash
+# 确保使用 localhost 或 HTTPS
+# 检查浏览器权限设置
+```
+
+### 模型加载失败
+```bash
+# 清除缓存重试
+# 检查网络连接
+```
+
+### 识别不准确
+```bash
+# 改善光线条件
+# 降低置信度阈值
+# 靠近物品拍摄
+```
+
+## 生产部署
+
+### GitHub Pages
+```bash
+npm run build
+# 将 dist/ 推送到 gh-pages 分支
+```
+
+### Vercel (推荐)
+```bash
+npm install -g vercel
+vercel
+```
+
+## 成本
+
+- **开发**: $0
+- **部署**: $0 (GitHub Pages/Vercel 免费层)
+- **AI模型**: $0 (TensorFlow.js 本地运行)
+- **总计**: **$0**
+
+## 技术特点
+
+✅ 完全离线运行 (模型下载后)
+✅ 实时检测 (500ms 延迟)
+✅ 30+ 种物品识别
+✅ AR 检测框叠加
+✅ 移动端优化
+✅ PWA 支持
+
+---
+
+**快速链接**:
+- 详细文档: `AR智能识别功能说明.md`
+- 源码: `src/app/consumer/home/ar-recognition/`
+- 服务: `src/app/core/services/ar-scanner.service.ts`

+ 306 - 0
AR智能识别功能说明.md

@@ -0,0 +1,306 @@
+# AR智能识别功能实现说明
+
+## 功能概述
+
+通过手机摄像头实时扫描废品垃圾,使用 TensorFlow.js + MobileNet 进行 AI 识别,显示废品类别、积分奖励和回收建议。
+
+## 技术栈
+
+- **前端框架**: Angular 20.3
+- **AI模型**: TensorFlow.js + COCO-SSD (MobileNet v2)
+- **相机访问**: WebRTC (getUserMedia API)
+- **实时检测**: Canvas API 绘制检测框
+- **部署**: GitHub Pages (前端) + Vercel (后端API可选)
+- **总成本**: $0
+
+## 已实现功能
+
+### 1. 核心服务 (`ar-scanner.service.ts`)
+
+**位置**: `src/app/core/services/ar-scanner.service.ts`
+
+**功能**:
+- ✅ TensorFlow.js 模型初始化和加载
+- ✅ 摄像头权限请求和视频流管理
+- ✅ 实时物体检测 (500ms 间隔)
+- ✅ 废品分类映射 (30+ 种常见物品)
+- ✅ 检测结果转换为回收信息
+
+**支持的废品类别**:
+- **可回收垃圾**: 塑料瓶、纸张、书籍、手机、电脑、键盘、鼠标、金属制品等
+- **厨余垃圾**: 水果 (苹果、橙子、香蕉等)
+- **其他垃圾**: 陶瓷、牙刷等
+
+### 2. AR识别组件 (`ar-recognition.component.ts`)
+
+**位置**: `src/app/consumer/home/ar-recognition/`
+
+**核心功能**:
+- ✅ 模型加载状态显示
+- ✅ 实时摄像头预览
+- ✅ Canvas 绘制检测框和标签
+- ✅ 识别结果展示 (类别、置信度、积分、回收建议)
+- ✅ 扫描历史记录 (localStorage 持久化)
+- ✅ 错误处理和用户提示
+
+### 3. 用户界面
+
+**主要界面**:
+1. **加载状态**: AI模型加载中的提示
+2. **待机状态**: 摄像头预览和扫描框
+3. **扫描中**: 实时视频流 + AR检测框 + 物品标签
+4. **结果展示**: 废品信息、分类、积分、回收建议
+5. **历史记录**: 最近扫描的物品列表
+
+## 使用流程
+
+### 用户操作流程
+
+1. **进入页面**
+   - 等待 AI 模型加载 (首次约 3-5 秒)
+   - 显示加载进度和提示
+
+2. **开始扫描**
+   - 点击 "开始扫描" 按钮
+   - 浏览器请求摄像头权限
+   - 允许权限后显示实时视频流
+
+3. **物品识别**
+   - 将废品对准摄像头
+   - AI 每 500ms 自动检测一次
+   - 实时绘制检测框和物品名称
+   - 置信度 > 60% 时自动停止并展示结果
+
+4. **查看结果**
+   - 废品名称和类别
+   - 置信度百分比
+   - 可获得的积分
+   - 材质信息
+   - 回收建议
+
+5. **确认或重试**
+   - 确认回收: 保存到历史记录,获得积分
+   - 重新识别: 重新开始扫描
+
+## 配置说明
+
+### 1. 检测参数调整
+
+在 `ar-recognition.ts` 中可调整:
+
+```typescript
+// 检测间隔 (毫秒)
+this.detectionInterval = setInterval(async () => {
+  // ...
+}, 500); // 调整此值控制检测频率
+
+// 置信度阈值
+if (result && result.confidence > 60) { // 调整此值控制识别灵敏度
+  // ...
+}
+```
+
+### 2. 添加新的废品类别
+
+在 `ar-scanner.service.ts` 的 `getWasteMapping()` 方法中添加:
+
+```typescript
+'item-name': {
+  item: '物品名称',
+  category: '可回收垃圾', // 可回收垃圾/有害垃圾/厨余垃圾/其他垃圾
+  points: 10,
+  tips: [
+    '回收提示1',
+    '回收提示2',
+    '可获得 X 积分奖励'
+  ],
+  recyclingInfo: {
+    material: '材质',
+    recyclable: true,
+    process: '处理方式'
+  }
+}
+```
+
+### 3. 摄像头配置
+
+在 `ar-scanner.service.ts` 中调整视频质量:
+
+```typescript
+const constraints = {
+  video: {
+    facingMode: 'environment', // 后置摄像头
+    width: { ideal: 1280 },    // 视频宽度
+    height: { ideal: 720 }     // 视频高度
+  },
+  audio: false
+};
+```
+
+## 依赖包
+
+### 已安装的包
+
+```json
+{
+  "@tensorflow/tfjs": "latest",
+  "@tensorflow-models/coco-ssd": "latest",
+  "@tensorflow/tfjs-backend-webgl": "latest"
+}
+```
+
+### 安装命令
+
+```bash
+npm install @tensorflow/tfjs @tensorflow-models/coco-ssd @tensorflow/tfjs-backend-webgl --legacy-peer-deps
+```
+
+## 部署说明
+
+### 本地测试
+
+```bash
+# 启动开发服务器
+npm start
+
+# 访问 (需要 HTTPS 或 localhost)
+http://localhost:4200/consumer/ar-recognition
+```
+
+**注意**: 摄像头访问需要 HTTPS 或 localhost 环境
+
+### 生产部署
+
+#### GitHub Pages 部署
+
+```bash
+# 构建生产版本
+npm run build
+
+# 部署到 GitHub Pages
+# 将 dist/ 目录内容推送到 gh-pages 分支
+```
+
+#### Vercel 部署
+
+```bash
+# 安装 Vercel CLI
+npm install -g vercel
+
+# 部署
+vercel
+```
+
+**配置文件** (`vercel.json`):
+```json
+{
+  "buildCommand": "npm run build",
+  "outputDirectory": "dist/recycle-app",
+  "framework": "angular",
+  "headers": [
+    {
+      "source": "/(.*)",
+      "headers": [
+        {
+          "key": "Permissions-Policy",
+          "value": "camera=*"
+        }
+      ]
+    }
+  ]
+}
+```
+
+## 性能优化
+
+### 1. 模型加载优化
+
+- 使用 `mobilenet_v2` 版本 (轻量级)
+- 首次加载后缓存模型
+- 使用 WebGL 后端加速
+
+### 2. 检测性能
+
+- 检测间隔 500ms (避免过于频繁)
+- 自动停止检测当找到高置信度结果
+- Canvas 重用避免频繁创建
+
+### 3. 内存管理
+
+- 组件销毁时释放资源
+- 停止摄像头流
+- 清理定时器
+
+## 浏览器兼容性
+
+| 浏览器 | 支持版本 | 说明 |
+|--------|----------|------|
+| Chrome | 90+ | ✅ 完全支持 |
+| Safari | 14+ | ✅ 支持 (iOS 需 14.5+) |
+| Firefox | 88+ | ✅ 支持 |
+| Edge | 90+ | ✅ 支持 |
+
+## 常见问题
+
+### 1. 摄像头权限被拒绝
+
+**解决方案**:
+- 检查浏览器设置
+- 确保使用 HTTPS 或 localhost
+- 清除网站权限并重新授权
+
+### 2. 模型加载失败
+
+**解决方案**:
+- 检查网络连接
+- 清除浏览器缓存
+- 确认 TensorFlow.js CDN 可访问
+
+### 3. 检测不准确
+
+**解决方案**:
+- 确保光线充足
+- 物品清晰对焦
+- 调整置信度阈值
+- 添加更多训练数据 (进阶)
+
+### 4. 性能问题
+
+**解决方案**:
+- 降低视频分辨率
+- 增加检测间隔
+- 使用更轻量的模型
+
+## 未来增强
+
+### 短期计划
+
+- [ ] 添加更多废品分类
+- [ ] 支持批量识别
+- [ ] 识别历史统计图表
+- [ ] 分享识别结果
+
+### 长期计划
+
+- [ ] 自定义模型训练 (Google Colab)
+- [ ] 迁移学习优化识别准确度
+- [ ] AR 3D 效果展示
+- [ ] 社区共享识别数据
+
+## 技术支持
+
+- **文档**: 查看项目 README.md
+- **Issues**: GitHub Issues
+- **讨论**: GitHub Discussions
+
+## 开发者信息
+
+- **开发框架**: Angular 20.3
+- **AI 框架**: TensorFlow.js 4.x
+- **模型**: COCO-SSD (MobileNet v2)
+- **许可证**: MIT
+
+---
+
+**更新时间**: 2024-12-16
+**版本**: v1.0.0

+ 164 - 0
backend/README.md

@@ -0,0 +1,164 @@
+# 废品回收APP后端服务
+
+基于 Spring Boot 3.2 + MyBatis-Plus 的后端 API 服务。
+
+## 技术栈
+
+- **框架**: Spring Boot 3.2.0
+- **ORM**: MyBatis-Plus 3.5.5
+- **数据库**: MySQL 8.x
+- **文档**: Knife4j (Swagger)
+- **工具**: Hutool, Lombok
+- **认证**: JWT
+
+## 项目结构
+
+```
+backend/
+├── src/main/java/com/recycle/
+│   ├── common/          # 通用类(Result, PageResult)
+│   ├── config/          # 配置类
+│   ├── controller/      # 控制器
+│   │   ├── client/      # C端接口
+│   │   ├── business/    # B端接口
+│   │   └── government/  # G端接口
+│   ├── dto/             # 数据传输对象
+│   ├── entity/          # 实体类
+│   ├── exception/       # 异常处理
+│   ├── interceptor/     # 拦截器
+│   ├── mapper/          # MyBatis Mapper
+│   ├── service/         # 服务层
+│   └── util/            # 工具类
+└── src/main/resources/
+    ├── application.yml  # 配置文件
+    └── mapper/          # XML映射文件
+```
+
+## 快速开始
+
+### 1. 环境要求
+
+- JDK 17+
+- Maven 3.8+
+- MySQL 8.x
+
+### 2. 配置数据库
+
+编辑 `src/main/resources/application.yml`,修改数据库连接信息:
+
+```yaml
+spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/recycle_app?...
+    username: root
+    password: your_password  # 修改为你的密码
+```
+
+### 3. 启动项目
+
+```bash
+# 方式一:Maven命令
+mvn spring-boot:run
+
+# 方式二:打包后运行
+mvn clean package -DskipTests
+java -jar target/recycle-app-backend-1.0.0.jar
+
+# 方式三:IDE中运行
+# 直接运行 RecycleAppApplication.java 的 main 方法
+```
+
+### 4. 访问API文档
+
+启动后访问:http://localhost:8080/doc.html
+
+## API接口概览
+
+### C端接口 `/api/c/`
+
+| 模块 | 路径 | 说明 |
+|------|------|------|
+| 认证 | `/api/c/auth/*` | 登录、注册 |
+| 用户 | `/api/c/user/*` | 用户信息、地址管理 |
+| 订单 | `/api/c/orders/*` | 回收订单 |
+| 分类 | `/api/c/categories/*` | 废品分类 |
+| 回收员 | `/api/c/collectors/*` | 回收员列表 |
+| 商品 | `/api/c/products/*` | 积分商城 |
+
+### B端接口 `/api/b/`
+
+| 模块 | 路径 | 说明 |
+|------|------|------|
+| 认证 | `/api/b/auth/*` | 企业登录 |
+| 订单 | `/api/b/orders/*` | 订单管理 |
+
+### G端接口 `/api/g/`
+
+| 模块 | 路径 | 说明 |
+|------|------|------|
+| 认证 | `/api/g/auth/*` | 政府用户登录 |
+| 统计 | `/api/g/statistics/*` | 数据统计 |
+
+## 请求示例
+
+### 用户注册
+
+```bash
+POST /api/c/auth/register
+Content-Type: application/json
+
+{
+  "phone": "13800138000",
+  "password": "123456"
+}
+```
+
+### 用户登录
+
+```bash
+POST /api/c/auth/login
+Content-Type: application/json
+
+{
+  "phone": "13800138000",
+  "password": "123456"
+}
+```
+
+响应:
+
+```json
+{
+  "code": 200,
+  "message": "操作成功",
+  "data": {
+    "token": "eyJhbGciOiJIUzI1NiJ9...",
+    "user": { ... }
+  }
+}
+```
+
+### 创建回收订单
+
+```bash
+POST /api/c/orders
+Authorization: Bearer <token>
+Content-Type: application/json
+
+{
+  "categoryId": 1,
+  "categoryName": "纸类",
+  "estimatedWeight": 5.0,
+  "contactName": "张三",
+  "contactPhone": "13800138000",
+  "address": "北京市朝阳区xxx",
+  "recycleMethod": "pickup",
+  "timeOption": "immediate"
+}
+```
+
+## 注意事项
+
+1. 需要先执行 `database/` 目录下的 SQL 文件创建数据库
+2. 默认端口 8080,可在 application.yml 中修改
+3. Redis 配置可选,如不使用请移除相关依赖

+ 126 - 0
backend/pom.xml

@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.recycle</groupId>
+    <artifactId>recycle-app-backend</artifactId>
+    <version>1.0.0</version>
+    <packaging>jar</packaging>
+    <name>recycle-app-backend</name>
+    <description>废品回收APP后端服务</description>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.7.18</version>
+        <relativePath/>
+    </parent>
+
+    <properties>
+        <java.version>11</java.version>
+        <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
+        <knife4j.version>3.0.3</knife4j.version>
+        <hutool.version>5.8.23</hutool.version>
+        <jwt.version>0.12.3</jwt.version>
+    </properties>
+
+    <dependencies>
+        <!-- Spring Boot Web -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- Spring Boot Validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <!-- MySQL Driver -->
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- MyBatis-Plus -->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <!-- Lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- Knife4j (Swagger) -->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-spring-boot-starter</artifactId>
+            <version>${knife4j.version}</version>
+        </dependency>
+
+        <!-- Hutool 工具类 -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>${hutool.version}</version>
+        </dependency>
+
+        <!-- JWT -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-api</artifactId>
+            <version>${jwt.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>${jwt.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-jackson</artifactId>
+            <version>${jwt.version}</version>
+            <scope>runtime</scope>
+        </dependency>
+
+        <!-- Redis (可选) -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!-- Test -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 14 - 0
backend/src/main/java/com/recycle/RecycleAppApplication.java

@@ -0,0 +1,14 @@
+package com.recycle;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@MapperScan("com.recycle.mapper")
+public class RecycleAppApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(RecycleAppApplication.class, args);
+    }
+}

+ 27 - 0
backend/src/main/java/com/recycle/common/PageResult.java

@@ -0,0 +1,27 @@
+package com.recycle.common;
+
+import lombok.Data;
+import java.util.List;
+
+/**
+ * 分页结果类
+ */
+@Data
+public class PageResult<T> {
+
+    private List<T> records;
+    private Long total;
+    private Long size;
+    private Long current;
+    private Long pages;
+
+    public PageResult() {}
+
+    public PageResult(List<T> records, Long total, Long size, Long current) {
+        this.records = records;
+        this.total = total;
+        this.size = size;
+        this.current = current;
+        this.pages = (total + size - 1) / size;
+    }
+}

+ 57 - 0
backend/src/main/java/com/recycle/common/Result.java

@@ -0,0 +1,57 @@
+package com.recycle.common;
+
+import lombok.Data;
+import java.io.Serializable;
+
+/**
+ * 统一返回结果类
+ */
+@Data
+public class Result<T> implements Serializable {
+
+    private Integer code;
+    private String message;
+    private T data;
+    private Long timestamp;
+
+    public Result() {
+        this.timestamp = System.currentTimeMillis();
+    }
+
+    public static <T> Result<T> success() {
+        Result<T> result = new Result<>();
+        result.setCode(200);
+        result.setMessage("操作成功");
+        return result;
+    }
+
+    public static <T> Result<T> success(T data) {
+        Result<T> result = new Result<>();
+        result.setCode(200);
+        result.setMessage("操作成功");
+        result.setData(data);
+        return result;
+    }
+
+    public static <T> Result<T> success(String message, T data) {
+        Result<T> result = new Result<>();
+        result.setCode(200);
+        result.setMessage(message);
+        result.setData(data);
+        return result;
+    }
+
+    public static <T> Result<T> error(String message) {
+        Result<T> result = new Result<>();
+        result.setCode(500);
+        result.setMessage(message);
+        return result;
+    }
+
+    public static <T> Result<T> error(Integer code, String message) {
+        Result<T> result = new Result<>();
+        result.setCode(code);
+        result.setMessage(message);
+        return result;
+    }
+}

+ 38 - 0
backend/src/main/java/com/recycle/config/MybatisPlusConfig.java

@@ -0,0 +1,38 @@
+package com.recycle.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.LocalDateTime;
+
+@Configuration
+public class MybatisPlusConfig {
+
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        return interceptor;
+    }
+
+    @Bean
+    public MetaObjectHandler metaObjectHandler() {
+        return new MetaObjectHandler() {
+            @Override
+            public void insertFill(MetaObject metaObject) {
+                this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now());
+                this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now());
+            }
+
+            @Override
+            public void updateFill(MetaObject metaObject) {
+                this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now());
+            }
+        };
+    }
+}

+ 99 - 0
backend/src/main/java/com/recycle/config/SwaggerConfig.java

@@ -0,0 +1,99 @@
+package com.recycle.config;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ReflectionUtils;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
+import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Configuration
+public class SwaggerConfig {
+
+    @Bean
+    public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
+        return new BeanPostProcessor() {
+            @Override
+            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+                if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
+                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
+                }
+                return bean;
+            }
+
+            private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
+                List<T> copy = mappings.stream()
+                        .filter(mapping -> mapping.getPatternParser() == null)
+                        .collect(Collectors.toList());
+                mappings.clear();
+                mappings.addAll(copy);
+            }
+
+            @SuppressWarnings("unchecked")
+            private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
+                try {
+                    Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
+                    field.setAccessible(true);
+                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
+                } catch (IllegalArgumentException | IllegalAccessException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        };
+    }
+
+    @Bean
+    public Docket clientApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("C端API")
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.recycle.controller.client"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    @Bean
+    public Docket businessApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("B端API")
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.recycle.controller.business"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    @Bean
+    public Docket governmentApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("G端API")
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.recycle.controller.government"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("废品回收APP后端API")
+                .description("废品回收APP C端/B端/G端接口文档")
+                .version("1.0.0")
+                .contact(new Contact("Recycle Team", "", ""))
+                .build();
+    }
+}

+ 43 - 0
backend/src/main/java/com/recycle/config/WebConfig.java

@@ -0,0 +1,43 @@
+package com.recycle.config;
+
+import com.recycle.interceptor.AuthInterceptor;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@RequiredArgsConstructor
+public class WebConfig implements WebMvcConfigurer {
+
+    private final AuthInterceptor authInterceptor;
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOriginPatterns("*")
+                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+                .allowedHeaders("*")
+                .allowCredentials(true)
+                .maxAge(3600);
+    }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(authInterceptor)
+                .addPathPatterns("/api/**")
+                .excludePathPatterns(
+                        "/api/c/auth/login",
+                        "/api/c/auth/register",
+                        "/api/c/categories/**",
+                        "/api/c/collectors/nearby",
+                        "/api/c/collectors/online",
+                        "/api/b/auth/**",
+                        "/api/g/auth/**",
+                        "/doc.html",
+                        "/swagger-ui/**",
+                        "/v3/api-docs/**"
+                );
+    }
+}

+ 24 - 0
backend/src/main/java/com/recycle/controller/business/BusinessAuthController.java

@@ -0,0 +1,24 @@
+package com.recycle.controller.business;
+
+import com.recycle.common.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Api(tags = "B端认证接口")
+@RestController
+@RequestMapping("/api/b/auth")
+public class BusinessAuthController {
+
+    @ApiOperation("企业用户登录")
+    @PostMapping("/login")
+    public Result<Map<String, Object>> login(@RequestBody Map<String, String> params) {
+        // TODO: 实现企业用户登录逻辑
+        Map<String, Object> data = new HashMap<>();
+        data.put("token", "business_token_placeholder");
+        return Result.success(data);
+    }
+}

+ 64 - 0
backend/src/main/java/com/recycle/controller/business/BusinessOrderController.java

@@ -0,0 +1,64 @@
+package com.recycle.controller.business;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.recycle.common.PageResult;
+import com.recycle.common.Result;
+import com.recycle.entity.RecycleOrder;
+import com.recycle.service.RecycleOrderService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@Api(tags = "B端订单接口")
+@RestController
+@RequestMapping("/api/b/orders")
+@RequiredArgsConstructor
+public class BusinessOrderController {
+
+    private final RecycleOrderService recycleOrderService;
+
+    @ApiOperation("获取订单列表")
+    @GetMapping
+    public Result<PageResult<RecycleOrder>> getOrders(
+            @RequestParam(defaultValue = "1") Integer page,
+            @RequestParam(defaultValue = "10") Integer size,
+            @RequestParam(required = false) String status) {
+        
+        LambdaQueryWrapper<RecycleOrder> wrapper = new LambdaQueryWrapper<>();
+        if (status != null && !"all".equals(status)) {
+            wrapper.eq(RecycleOrder::getStatus, status);
+        }
+        wrapper.orderByDesc(RecycleOrder::getCreatedAt);
+        
+        Page<RecycleOrder> pageResult = recycleOrderService.page(new Page<>(page, size), wrapper);
+        PageResult<RecycleOrder> result = new PageResult<>(
+                pageResult.getRecords(),
+                pageResult.getTotal(),
+                pageResult.getSize(),
+                pageResult.getCurrent()
+        );
+        return Result.success(result);
+    }
+
+    @ApiOperation("接单")
+    @PostMapping("/{id}/accept")
+    public Result<Void> acceptOrder(@PathVariable Long id, @RequestParam Long collectorId) {
+        RecycleOrder order = recycleOrderService.getById(id);
+        if (order == null) {
+            return Result.error("订单不存在");
+        }
+        order.setStatus("accepted");
+        order.setCollectorId(collectorId);
+        recycleOrderService.updateById(order);
+        return Result.success();
+    }
+
+    @ApiOperation("完成订单")
+    @PostMapping("/{id}/complete")
+    public Result<Void> completeOrder(@PathVariable Long id, @RequestParam Long collectorId) {
+        recycleOrderService.completeOrder(id, collectorId);
+        return Result.success();
+    }
+}

+ 52 - 0
backend/src/main/java/com/recycle/controller/client/AuthController.java

@@ -0,0 +1,52 @@
+package com.recycle.controller.client;
+
+import com.recycle.common.Result;
+import com.recycle.dto.LoginDTO;
+import com.recycle.dto.RegisterDTO;
+import com.recycle.entity.User;
+import com.recycle.service.UserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import javax.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Api(tags = "认证接口")
+@RestController
+@RequestMapping("/api/c/auth")
+@RequiredArgsConstructor
+public class AuthController {
+
+    private final UserService userService;
+
+    @ApiOperation("用户注册")
+    @PostMapping("/register")
+    public Result<Void> register(@Valid @RequestBody RegisterDTO dto) {
+        userService.register(dto.getPhone(), dto.getPassword());
+        return Result.success();
+    }
+
+    @ApiOperation("用户登录")
+    @PostMapping("/login")
+    public Result<Map<String, Object>> login(@Valid @RequestBody LoginDTO dto) {
+        String token = userService.login(dto.getPhone(), dto.getPassword());
+        User user = userService.getByPhone(dto.getPhone());
+
+        Map<String, Object> data = new HashMap<>();
+        data.put("token", token);
+        data.put("user", user);
+
+        return Result.success(data);
+    }
+
+    @ApiOperation("获取当前用户信息")
+    @GetMapping("/info")
+    public Result<User> getUserInfo(@RequestAttribute("userId") Long userId) {
+        User user = userService.getById(userId);
+        user.setPassword(null);
+        return Result.success(user);
+    }
+}

+ 34 - 0
backend/src/main/java/com/recycle/controller/client/CategoryController.java

@@ -0,0 +1,34 @@
+package com.recycle.controller.client;
+
+import com.recycle.common.Result;
+import com.recycle.entity.WasteCategory;
+import com.recycle.service.WasteCategoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api(tags = "分类接口")
+@RestController
+@RequestMapping("/api/c/categories")
+@RequiredArgsConstructor
+public class CategoryController {
+
+    private final WasteCategoryService wasteCategoryService;
+
+    @ApiOperation("获取所有分类")
+    @GetMapping
+    public Result<List<WasteCategory>> getCategories() {
+        List<WasteCategory> categories = wasteCategoryService.getActiveCategories();
+        return Result.success(categories);
+    }
+
+    @ApiOperation("获取分类详情")
+    @GetMapping("/{id}")
+    public Result<WasteCategory> getCategoryDetail(@PathVariable Long id) {
+        WasteCategory category = wasteCategoryService.getById(id);
+        return Result.success(category);
+    }
+}

+ 44 - 0
backend/src/main/java/com/recycle/controller/client/CollectorController.java

@@ -0,0 +1,44 @@
+package com.recycle.controller.client;
+
+import com.recycle.common.Result;
+import com.recycle.entity.Collector;
+import com.recycle.service.CollectorService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api(tags = "回收员接口")
+@RestController
+@RequestMapping("/api/c/collectors")
+@RequiredArgsConstructor
+public class CollectorController {
+
+    private final CollectorService collectorService;
+
+    @ApiOperation("获取附近回收员")
+    @GetMapping("/nearby")
+    public Result<List<Collector>> getNearbyCollectors(
+            @RequestParam(required = false) Double longitude,
+            @RequestParam(required = false) Double latitude,
+            @RequestParam(defaultValue = "10") Integer limit) {
+        List<Collector> collectors = collectorService.getNearbyCollectors(longitude, latitude, limit);
+        return Result.success(collectors);
+    }
+
+    @ApiOperation("获取在线回收员列表")
+    @GetMapping("/online")
+    public Result<List<Collector>> getOnlineCollectors() {
+        List<Collector> collectors = collectorService.getOnlineCollectors();
+        return Result.success(collectors);
+    }
+
+    @ApiOperation("获取回收员详情")
+    @GetMapping("/{id}")
+    public Result<Collector> getCollectorDetail(@PathVariable Long id) {
+        Collector collector = collectorService.getById(id);
+        return Result.success(collector);
+    }
+}

+ 65 - 0
backend/src/main/java/com/recycle/controller/client/OrderController.java

@@ -0,0 +1,65 @@
+package com.recycle.controller.client;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.recycle.common.PageResult;
+import com.recycle.common.Result;
+import com.recycle.entity.RecycleOrder;
+import com.recycle.service.RecycleOrderService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@Api(tags = "订单接口")
+@RestController
+@RequestMapping("/api/c/orders")
+@RequiredArgsConstructor
+public class OrderController {
+
+    private final RecycleOrderService recycleOrderService;
+
+    @ApiOperation("创建回收订单")
+    @PostMapping
+    public Result<RecycleOrder> createOrder(@RequestAttribute("userId") Long userId, @RequestBody RecycleOrder order) {
+        order.setUserId(userId);
+        RecycleOrder created = recycleOrderService.createOrder(order);
+        return Result.success(created);
+    }
+
+    @ApiOperation("获取订单列表")
+    @GetMapping
+    public Result<PageResult<RecycleOrder>> getOrders(
+            @RequestAttribute("userId") Long userId,
+            @RequestParam(defaultValue = "all") String status,
+            @RequestParam(defaultValue = "1") Integer page,
+            @RequestParam(defaultValue = "10") Integer size) {
+        Page<RecycleOrder> pageResult = recycleOrderService.getUserOrders(userId, status, page, size);
+        PageResult<RecycleOrder> result = new PageResult<>(
+                pageResult.getRecords(),
+                pageResult.getTotal(),
+                pageResult.getSize(),
+                pageResult.getCurrent()
+        );
+        return Result.success(result);
+    }
+
+    @ApiOperation("获取订单详情")
+    @GetMapping("/{id}")
+    public Result<RecycleOrder> getOrderDetail(@RequestAttribute("userId") Long userId, @PathVariable Long id) {
+        RecycleOrder order = recycleOrderService.getById(id);
+        if (order == null || !order.getUserId().equals(userId)) {
+            return Result.error("订单不存在");
+        }
+        return Result.success(order);
+    }
+
+    @ApiOperation("取消订单")
+    @PostMapping("/{id}/cancel")
+    public Result<Void> cancelOrder(
+            @RequestAttribute("userId") Long userId,
+            @PathVariable Long id,
+            @RequestParam(required = false) String reason) {
+        recycleOrderService.cancelOrder(id, userId, reason);
+        return Result.success();
+    }
+}

+ 43 - 0
backend/src/main/java/com/recycle/controller/client/ProductController.java

@@ -0,0 +1,43 @@
+package com.recycle.controller.client;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.recycle.common.PageResult;
+import com.recycle.common.Result;
+import com.recycle.entity.Product;
+import com.recycle.service.ProductService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@Api(tags = "商品接口")
+@RestController
+@RequestMapping("/api/c/products")
+@RequiredArgsConstructor
+public class ProductController {
+
+    private final ProductService productService;
+
+    @ApiOperation("获取商品列表")
+    @GetMapping
+    public Result<PageResult<Product>> getProducts(
+            @RequestParam(defaultValue = "all") String category,
+            @RequestParam(defaultValue = "1") Integer page,
+            @RequestParam(defaultValue = "10") Integer size) {
+        Page<Product> pageResult = productService.getProductList(category, page, size);
+        PageResult<Product> result = new PageResult<>(
+                pageResult.getRecords(),
+                pageResult.getTotal(),
+                pageResult.getSize(),
+                pageResult.getCurrent()
+        );
+        return Result.success(result);
+    }
+
+    @ApiOperation("获取商品详情")
+    @GetMapping("/{id}")
+    public Result<Product> getProductDetail(@PathVariable Long id) {
+        Product product = productService.getById(id);
+        return Result.success(product);
+    }
+}

+ 76 - 0
backend/src/main/java/com/recycle/controller/client/UserController.java

@@ -0,0 +1,76 @@
+package com.recycle.controller.client;
+
+import com.recycle.common.Result;
+import com.recycle.entity.User;
+import com.recycle.entity.UserAddress;
+import com.recycle.service.UserService;
+import com.recycle.service.UserAddressService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Api(tags = "用户接口")
+@RestController
+@RequestMapping("/api/c/user")
+@RequiredArgsConstructor
+public class UserController {
+
+    private final UserService userService;
+    private final UserAddressService userAddressService;
+
+    @ApiOperation("获取用户信息")
+    @GetMapping("/info")
+    public Result<User> getUserInfo(@RequestAttribute("userId") Long userId) {
+        User user = userService.getById(userId);
+        user.setPassword(null);
+        return Result.success(user);
+    }
+
+    @ApiOperation("更新用户信息")
+    @PutMapping("/info")
+    public Result<Void> updateUserInfo(@RequestAttribute("userId") Long userId, @RequestBody User user) {
+        userService.updateUserInfo(userId, user);
+        return Result.success();
+    }
+
+    @ApiOperation("获取用户地址列表")
+    @GetMapping("/addresses")
+    public Result<List<UserAddress>> getAddresses(@RequestAttribute("userId") Long userId) {
+        List<UserAddress> addresses = userAddressService.getUserAddresses(userId);
+        return Result.success(addresses);
+    }
+
+    @ApiOperation("添加地址")
+    @PostMapping("/addresses")
+    public Result<UserAddress> addAddress(@RequestAttribute("userId") Long userId, @RequestBody UserAddress address) {
+        address.setUserId(userId);
+        UserAddress saved = userAddressService.addAddress(address);
+        return Result.success(saved);
+    }
+
+    @ApiOperation("更新地址")
+    @PutMapping("/addresses/{id}")
+    public Result<Void> updateAddress(@RequestAttribute("userId") Long userId,
+                                       @PathVariable Long id,
+                                       @RequestBody UserAddress address) {
+        userAddressService.updateAddress(userId, id, address);
+        return Result.success();
+    }
+
+    @ApiOperation("删除地址")
+    @DeleteMapping("/addresses/{id}")
+    public Result<Void> deleteAddress(@RequestAttribute("userId") Long userId, @PathVariable Long id) {
+        userAddressService.deleteAddress(userId, id);
+        return Result.success();
+    }
+
+    @ApiOperation("设置默认地址")
+    @PutMapping("/addresses/{id}/default")
+    public Result<Void> setDefaultAddress(@RequestAttribute("userId") Long userId, @PathVariable Long id) {
+        userAddressService.setDefaultAddress(userId, id);
+        return Result.success();
+    }
+}

+ 24 - 0
backend/src/main/java/com/recycle/controller/government/GovernmentAuthController.java

@@ -0,0 +1,24 @@
+package com.recycle.controller.government;
+
+import com.recycle.common.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Api(tags = "G端认证接口")
+@RestController
+@RequestMapping("/api/g/auth")
+public class GovernmentAuthController {
+
+    @ApiOperation("政府用户登录")
+    @PostMapping("/login")
+    public Result<Map<String, Object>> login(@RequestBody Map<String, String> params) {
+        // TODO: 实现政府用户登录逻辑
+        Map<String, Object> data = new HashMap<>();
+        data.put("token", "government_token_placeholder");
+        return Result.success(data);
+    }
+}

+ 45 - 0
backend/src/main/java/com/recycle/controller/government/StatisticsController.java

@@ -0,0 +1,45 @@
+package com.recycle.controller.government;
+
+import com.recycle.common.Result;
+import com.recycle.service.RecycleOrderService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Api(tags = "G端统计接口")
+@RestController
+@RequestMapping("/api/g/statistics")
+@RequiredArgsConstructor
+public class StatisticsController {
+
+    private final RecycleOrderService recycleOrderService;
+
+    @ApiOperation("获取总体统计数据")
+    @GetMapping("/overview")
+    public Result<Map<String, Object>> getOverview() {
+        Map<String, Object> data = new HashMap<>();
+        
+        // 订单总数
+        long totalOrders = recycleOrderService.count();
+        data.put("totalOrders", totalOrders);
+        
+        // TODO: 添加更多统计数据
+        data.put("totalRecycleWeight", 0);
+        data.put("totalCarbonReduction", 0);
+        data.put("totalUsers", 0);
+        
+        return Result.success(data);
+    }
+
+    @ApiOperation("获取区域统计")
+    @GetMapping("/regions")
+    public Result<Map<String, Object>> getRegionStatistics() {
+        Map<String, Object> data = new HashMap<>();
+        // TODO: 实现区域统计
+        return Result.success(data);
+    }
+}

+ 21 - 0
backend/src/main/java/com/recycle/dto/LoginDTO.java

@@ -0,0 +1,21 @@
+package com.recycle.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import lombok.Data;
+
+@Data
+@ApiModel(description = "登录请求")
+public class LoginDTO {
+
+    @ApiModelProperty(value = "手机号", example = "13800138000")
+    @NotBlank(message = "手机号不能为空")
+    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
+    private String phone;
+
+    @ApiModelProperty(value = "密码", example = "123456")
+    @NotBlank(message = "密码不能为空")
+    private String password;
+}

+ 26 - 0
backend/src/main/java/com/recycle/dto/RegisterDTO.java

@@ -0,0 +1,26 @@
+package com.recycle.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import lombok.Data;
+
+@Data
+@ApiModel(description = "注册请求")
+public class RegisterDTO {
+
+    @ApiModelProperty(value = "手机号", example = "13800138000")
+    @NotBlank(message = "手机号不能为空")
+    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
+    private String phone;
+
+    @ApiModelProperty(value = "密码", example = "123456")
+    @NotBlank(message = "密码不能为空")
+    @Size(min = 6, max = 20, message = "密码长度需要在6-20位之间")
+    private String password;
+
+    @ApiModelProperty(value = "邀请码", example = "ABC123")
+    private String inviteCode;
+}

+ 28 - 0
backend/src/main/java/com/recycle/entity/Activity.java

@@ -0,0 +1,28 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("activities")
+public class Activity {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String title;
+    private String description;
+    private String content;
+    private String image;
+    private String tag;
+    private String type;
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private Integer rewardPoints;
+    private BigDecimal rewardCash;
+    private Integer sortOrder;
+    private Integer status;
+    private LocalDateTime createdAt;
+}

+ 31 - 0
backend/src/main/java/com/recycle/entity/AdministrativeRegion.java

@@ -0,0 +1,31 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("administrative_regions")
+public class AdministrativeRegion {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String regionCode;
+    private String name;
+    private Long parentId;
+    private Integer level;
+    private String manager;
+    private String contact;
+    private String address;
+    private Integer population;
+    private BigDecimal areaSize;
+    private Integer recyclePoints;
+    private BigDecimal complianceRate;
+    private BigDecimal monthlyVolume;
+    private BigDecimal longitude;
+    private BigDecimal latitude;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 21 - 0
backend/src/main/java/com/recycle/entity/AiChatHistory.java

@@ -0,0 +1,21 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("ai_chat_history")
+public class AiChatHistory {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private Long userId;
+    private String sessionId;
+    private String role;
+    private String content;
+    private String attachments;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/AiGeneratedReport.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("ai_generated_reports")
+public class AiGeneratedReport {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String reportNo;
+    private String reportType;
+    private String title;
+    private String summary;
+    private String content;
+    private Long regionId;
+    private Long generatorId;
+    private LocalDateTime generateTime;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 22 - 0
backend/src/main/java/com/recycle/entity/AiInsight.java

@@ -0,0 +1,22 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("ai_insights")
+public class AiInsight {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String type;
+    private String title;
+    private String description;
+    private String icon;
+    private String actionUrl;
+    private Integer isRead;
+    private LocalDateTime createdAt;
+}

+ 22 - 0
backend/src/main/java/com/recycle/entity/Badge.java

@@ -0,0 +1,22 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("badges")
+public class Badge {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private String description;
+    private String icon;
+    private String conditionType;
+    private Integer conditionValue;
+    private Integer rewardPoints;
+    private Integer sortOrder;
+    private LocalDateTime createdAt;
+}

+ 22 - 0
backend/src/main/java/com/recycle/entity/BusinessAlert.java

@@ -0,0 +1,22 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("business_alerts")
+public class BusinessAlert {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String type;
+    private String level;
+    private String title;
+    private String content;
+    private String icon;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 32 - 0
backend/src/main/java/com/recycle/entity/BusinessOrder.java

@@ -0,0 +1,32 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("business_orders")
+public class BusinessOrder {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String orderNo;
+    private Long enterpriseId;
+    private Long consumerOrderId;
+    private String customerName;
+    private String customerPhone;
+    private String categoryName;
+    private BigDecimal weight;
+    private BigDecimal estimatedValue;
+    private String area;
+    private String address;
+    private Long collectorId;
+    private String collectorName;
+    private String collectorPhone;
+    private BigDecimal settlementAmount;
+    private String settlementStatus;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/BusinessTodo.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("business_todos")
+public class BusinessTodo {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String title;
+    private String description;
+    private String type;
+    private String icon;
+    private Integer count;
+    private String priority;
+    private String actionUrl;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 28 - 0
backend/src/main/java/com/recycle/entity/CategoryStatistics.java

@@ -0,0 +1,28 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("category_statistics")
+public class CategoryStatistics {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long regionId;
+    private String category;
+    private LocalDate statDate;
+    private String statType;
+    private BigDecimal volume;
+    private BigDecimal value;
+    private BigDecimal recycleRate;
+    private BigDecimal regenerationRate;
+    private Integer companies;
+    private String marketDemand;
+    private String trend;
+    private LocalDateTime createdAt;
+}

+ 20 - 0
backend/src/main/java/com/recycle/entity/CheckinRecord.java

@@ -0,0 +1,20 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("checkin_records")
+public class CheckinRecord {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private LocalDate checkinDate;
+    private Integer continuousDays;
+    private Integer rewardPoints;
+    private LocalDateTime createdAt;
+}

+ 59 - 0
backend/src/main/java/com/recycle/entity/Collector.java

@@ -0,0 +1,59 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 回收员表
+ */
+@Data
+@TableName("collectors")
+public class Collector {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private Long userId;
+
+    private String name;
+
+    private String phone;
+
+    private String avatar;
+
+    private String idCard;
+
+    private BigDecimal rating;
+
+    private Integer reviewCount;
+
+    private Integer completedOrders;
+
+    private String experience;
+
+    private String specialties;
+
+    private String serviceArea;
+
+    private String workingHours;
+
+    private String responseTime;
+
+    private String priceRange;
+
+    private String features;
+
+    private String status;
+
+    private BigDecimal longitude;
+
+    private BigDecimal latitude;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+}

+ 30 - 0
backend/src/main/java/com/recycle/entity/ComplianceCheck.java

@@ -0,0 +1,30 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("compliance_checks")
+public class ComplianceCheck {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String checkNo;
+    private Long enterpriseId;
+    private String enterpriseName;
+    private Long regionId;
+    private String checkType;
+    private LocalDate checkDate;
+    private String riskLevel;
+    private String riskPattern;
+    private String findings;
+    private String suggestions;
+    private Long inspectorId;
+    private String inspectorName;
+    private String status;
+    private LocalDate rectifyDeadline;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/Contract.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("contracts")
+public class Contract {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String contractNo;
+    private String title;
+    private BigDecimal amount;
+    private LocalDate startDate;
+    private LocalDate endDate;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 20 - 0
backend/src/main/java/com/recycle/entity/CustomerServiceMessage.java

@@ -0,0 +1,20 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("customer_service_messages")
+public class CustomerServiceMessage {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long sessionId;
+    private String senderType;
+    private Long senderId;
+    private String content;
+    private String contentType;
+    private LocalDateTime createdAt;
+}

+ 18 - 0
backend/src/main/java/com/recycle/entity/CustomerServiceSession.java

@@ -0,0 +1,18 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("customer_service_sessions")
+public class CustomerServiceSession {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private String status;
+    private LocalDateTime createdAt;
+    private LocalDateTime closedAt;
+}

+ 31 - 0
backend/src/main/java/com/recycle/entity/Device.java

@@ -0,0 +1,31 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("devices")
+public class Device {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String deviceNo;
+    private Long enterpriseId;
+    private String name;
+    private String type;
+    private String model;
+    private String location;
+    private String status;
+    private Integer runningTime;
+    private BigDecimal processedVolume;
+    private BigDecimal efficiency;
+    private BigDecimal temperature;
+    private BigDecimal pressure;
+    private LocalDate lastMaintenance;
+    private LocalDate nextMaintenance;
+    private LocalDateTime createdAt;
+}

+ 22 - 0
backend/src/main/java/com/recycle/entity/DeviceAlert.java

@@ -0,0 +1,22 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("device_alerts")
+public class DeviceAlert {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long deviceId;
+    private Long enterpriseId;
+    private String type;
+    private String level;
+    private String title;
+    private String description;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 26 - 0
backend/src/main/java/com/recycle/entity/DeviceMaintenance.java

@@ -0,0 +1,26 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("device_maintenance")
+public class DeviceMaintenance {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long deviceId;
+    private Long enterpriseId;
+    private String type;
+    private String title;
+    private String description;
+    private BigDecimal cost;
+    private String technician;
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/DonationProject.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("donation_projects")
+public class DonationProject {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private String description;
+    private String image;
+    private BigDecimal targetAmount;
+    private BigDecimal currentAmount;
+    private Integer donorCount;
+    private Integer status;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/DonationRecord.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("donation_records")
+public class DonationRecord {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private Long projectId;
+    private String projectName;
+    private BigDecimal amount;
+    private Integer rewardPoints;
+    private BigDecimal rewardCarbon;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 45 - 0
backend/src/main/java/com/recycle/entity/DropPoint.java

@@ -0,0 +1,45 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 投递点表
+ */
+@Data
+@TableName("drop_points")
+public class DropPoint {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String name;
+
+    private String address;
+
+    private String phone;
+
+    private BigDecimal longitude;
+
+    private BigDecimal latitude;
+
+    private BigDecimal rating;
+
+    private Integer capacity;
+
+    private String supportedTypes;
+
+    private String workingHours;
+
+    private String features;
+
+    private String status;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+}

+ 36 - 0
backend/src/main/java/com/recycle/entity/Earning.java

@@ -0,0 +1,36 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 收益记录表
+ */
+@Data
+@TableName("earnings")
+public class Earning {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private Long userId;
+
+    private Long orderId;
+
+    private String type;
+
+    private BigDecimal cashAmount;
+
+    private Integer pointsAmount;
+
+    private BigDecimal carbonReduction;
+
+    private String category;
+
+    private String description;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+}

+ 47 - 0
backend/src/main/java/com/recycle/entity/Enterprise.java

@@ -0,0 +1,47 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 企业表
+ */
+@Data
+@TableName("enterprises")
+public class Enterprise {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String name;
+
+    private String code;
+
+    private String type;
+
+    private String legalPerson;
+
+    private String phone;
+
+    private String email;
+
+    private String address;
+
+    private String registeredCapital;
+
+    private LocalDate establishDate;
+
+    private String logo;
+
+    private Integer status;
+
+    private Integer verified;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+}

+ 22 - 0
backend/src/main/java/com/recycle/entity/EnterpriseEmployee.java

@@ -0,0 +1,22 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("enterprise_employees")
+public class EnterpriseEmployee {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String employeeNo;
+    private String name;
+    private String phone;
+    private String role;
+    private String department;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 26 - 0
backend/src/main/java/com/recycle/entity/EnterpriseSubscription.java

@@ -0,0 +1,26 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("enterprise_subscriptions")
+public class EnterpriseSubscription {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private Long planId;
+    private String planName;
+    private LocalDate startDate;
+    private LocalDate endDate;
+    private BigDecimal amount;
+    private Integer maxUsers;
+    private Integer usedUsers;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/ExchangeRecord.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("exchange_records")
+public class ExchangeRecord {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private Long productId;
+    private String productName;
+    private Integer pointsCost;
+    private Integer quantity;
+    private String status;
+    private String shippingAddress;
+    private String shippingNo;
+    private LocalDateTime createdAt;
+    private LocalDateTime updatedAt;
+}

+ 18 - 0
backend/src/main/java/com/recycle/entity/Favorite.java

@@ -0,0 +1,18 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("favorites")
+public class Favorite {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private String type;
+    private Long targetId;
+    private LocalDateTime createdAt;
+}

+ 27 - 0
backend/src/main/java/com/recycle/entity/GovernmentNotice.java

@@ -0,0 +1,27 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("government_notices")
+public class GovernmentNotice {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String title;
+    private String content;
+    private String type;
+    private String level;
+    private String targetRegions;
+    private String attachment;
+    private Long publisherId;
+    private String publisherName;
+    private LocalDateTime publishTime;
+    private LocalDateTime expireTime;
+    private String status;
+    private Integer viewCount;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/GovernmentOperationLog.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("government_operation_logs")
+public class GovernmentOperationLog {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private String userName;
+    private String module;
+    private String action;
+    private String targetType;
+    private Long targetId;
+    private String detail;
+    private String ip;
+    private String userAgent;
+    private LocalDateTime createdAt;
+}

+ 45 - 0
backend/src/main/java/com/recycle/entity/GovernmentUser.java

@@ -0,0 +1,45 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+/**
+ * 政府用户表
+ */
+@Data
+@TableName("government_users")
+public class GovernmentUser {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String username;
+
+    private String password;
+
+    private String name;
+
+    private String department;
+
+    private String position;
+
+    private String phone;
+
+    private String email;
+
+    private String avatar;
+
+    private String role;
+
+    private Long regionId;
+
+    private String permissions;
+
+    private Integer status;
+
+    private LocalDateTime lastLoginAt;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+}

+ 31 - 0
backend/src/main/java/com/recycle/entity/GovernmentWarning.java

@@ -0,0 +1,31 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("government_warnings")
+public class GovernmentWarning {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String warningNo;
+    private String type;
+    private String level;
+    private String title;
+    private String content;
+    private Long regionId;
+    private String regionName;
+    private Long enterpriseId;
+    private String enterpriseName;
+    private String source;
+    private String evidence;
+    private String status;
+    private Long handlerId;
+    private String handlerName;
+    private LocalDateTime handleTime;
+    private String handleResult;
+    private LocalDateTime createdAt;
+}

+ 26 - 0
backend/src/main/java/com/recycle/entity/IndustryChainData.java

@@ -0,0 +1,26 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("industry_chain_data")
+public class IndustryChainData {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long regionId;
+    private String stage;
+    private LocalDate reportDate;
+    private BigDecimal volume;
+    private BigDecimal efficiency;
+    private Integer companies;
+    private Integer employees;
+    private BigDecimal revenue;
+    private BigDecimal growthRate;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/InviteRecord.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("invite_records")
+public class InviteRecord {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long inviterId;
+    private Long inviteeId;
+    private String inviteeNickname;
+    private String inviteeAvatar;
+    private String status;
+    private Integer rewardPoints;
+    private Integer completedOrders;
+    private LocalDateTime inviteTime;
+    private LocalDateTime successTime;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/LoginLog.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("login_logs")
+public class LoginLog {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private Long enterpriseId;
+    private LocalDateTime loginTime;
+    private String ip;
+    private String location;
+    private String device;
+    private String browser;
+    private String status;
+    private String failReason;
+}

+ 28 - 0
backend/src/main/java/com/recycle/entity/MonitoringLocation.java

@@ -0,0 +1,28 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("monitoring_locations")
+public class MonitoringLocation {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String locationNo;
+    private String name;
+    private String type;
+    private String address;
+    private BigDecimal longitude;
+    private BigDecimal latitude;
+    private BigDecimal capacity;
+    private BigDecimal currentVolume;
+    private BigDecimal recycleVolume;
+    private String status;
+    private LocalDateTime lastUpdate;
+    private LocalDateTime createdAt;
+}

+ 33 - 0
backend/src/main/java/com/recycle/entity/Notification.java

@@ -0,0 +1,33 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+/**
+ * 通知表
+ */
+@Data
+@TableName("notifications")
+public class Notification {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private Long userId;
+
+    private String type;
+
+    private String title;
+
+    private String message;
+
+    private String icon;
+
+    private Long referenceId;
+
+    private Integer isRead;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/NotificationSetting.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("notification_settings")
+public class NotificationSetting {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private Integer systemAlerts;
+    private Integer dataReports;
+    private Integer policyUpdates;
+    private Integer emailNotifications;
+    private String email;
+    private Integer smsNotifications;
+    private String phone;
+    private LocalDateTime updatedAt;
+}

+ 25 - 0
backend/src/main/java/com/recycle/entity/OrderReview.java

@@ -0,0 +1,25 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("order_reviews")
+public class OrderReview {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long orderId;
+    private Long userId;
+    private Long collectorId;
+    private Integer rating;
+    private String content;
+    private String images;
+    private String tags;
+    private Integer isAnonymous;
+    private String reply;
+    private LocalDateTime replyTime;
+    private LocalDateTime createdAt;
+}

+ 22 - 0
backend/src/main/java/com/recycle/entity/PointsRecord.java

@@ -0,0 +1,22 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("points_records")
+public class PointsRecord {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private String type;
+    private Integer amount;
+    private Integer balance;
+    private String source;
+    private Long referenceId;
+    private String description;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/Policy.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("policies")
+public class Policy {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String title;
+    private String description;
+    private String issuer;
+    private String amountRange;
+    private LocalDate deadline;
+    private String requirements;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/PolicyApplication.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("policy_applications")
+public class PolicyApplication {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private Long policyId;
+    private String policyTitle;
+    private String materials;
+    private String status;
+    private LocalDateTime submitAt;
+    private LocalDateTime resultAt;
+    private String remark;
+    private LocalDateTime createdAt;
+}

+ 29 - 0
backend/src/main/java/com/recycle/entity/PolicyEvaluation.java

@@ -0,0 +1,29 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("policy_evaluations")
+public class PolicyEvaluation {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long policyId;
+    private String policyName;
+    private Long regionId;
+    private LocalDate evalDate;
+    private String evalPeriod;
+    private BigDecimal subsidyAmount;
+    private BigDecimal recycleGrowth;
+    private BigDecimal participationRate;
+    private BigDecimal satisfactionRate;
+    private BigDecimal costBenefitRatio;
+    private String indicators;
+    private String recommendations;
+    private LocalDateTime createdAt;
+}

+ 26 - 0
backend/src/main/java/com/recycle/entity/PolicySimulation.java

@@ -0,0 +1,26 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("policy_simulations")
+public class PolicySimulation {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private String simulationType;
+    private String parameters;
+    private BigDecimal subsidyAmount;
+    private Integer timeRange;
+    private String result;
+    private BigDecimal recycleIncrease;
+    private BigDecimal budgetCost;
+    private BigDecimal carbonReduction;
+    private BigDecimal participation;
+    private LocalDateTime createdAt;
+}

+ 47 - 0
backend/src/main/java/com/recycle/entity/Product.java

@@ -0,0 +1,47 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 商品表
+ */
+@Data
+@TableName("products")
+public class Product {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String name;
+
+    private String category;
+
+    private String image;
+
+    private String description;
+
+    private Integer pointsPrice;
+
+    private BigDecimal cashPrice;
+
+    private BigDecimal marketPrice;
+
+    private Integer stock;
+
+    private Integer sales;
+
+    private String tag;
+
+    private Integer sortOrder;
+
+    private Integer status;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+}

+ 78 - 0
backend/src/main/java/com/recycle/entity/RecycleOrder.java

@@ -0,0 +1,78 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 回收订单表
+ */
+@Data
+@TableName("recycle_orders")
+public class RecycleOrder {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String orderNo;
+
+    private Long userId;
+
+    private Long collectorId;
+
+    private Long dropPointId;
+
+    private Long categoryId;
+
+    private String categoryName;
+
+    private String recycleMethod;
+
+    private BigDecimal weight;
+
+    private BigDecimal estimatedWeight;
+
+    private BigDecimal pricePerKg;
+
+    private BigDecimal cashAmount;
+
+    private Integer pointsAmount;
+
+    private BigDecimal carbonReduction;
+
+    private String contactName;
+
+    private String contactPhone;
+
+    private String address;
+
+    private LocalDate scheduledDate;
+
+    private String scheduledTime;
+
+    private String timeOption;
+
+    private String notes;
+
+    private String photos;
+
+    private String additionalServices;
+
+    private BigDecimal serviceFee;
+
+    private String status;
+
+    private String cancelReason;
+
+    private LocalDateTime completedAt;
+
+    private Integer rated;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+}

+ 35 - 0
backend/src/main/java/com/recycle/entity/RecycleStation.java

@@ -0,0 +1,35 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("recycle_stations")
+public class RecycleStation {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String stationNo;
+    private String name;
+    private String type;
+    private Long regionId;
+    private String address;
+    private BigDecimal longitude;
+    private BigDecimal latitude;
+    private String operatorName;
+    private Long operatorId;
+    private String contactName;
+    private String contactPhone;
+    private String workingHours;
+    private String supportedTypes;
+    private BigDecimal dailyCapacity;
+    private BigDecimal todayVolume;
+    private String complianceStatus;
+    private LocalDate lastInspection;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 29 - 0
backend/src/main/java/com/recycle/entity/RegionStatistics.java

@@ -0,0 +1,29 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("region_statistics")
+public class RegionStatistics {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long regionId;
+    private String regionName;
+    private LocalDate statDate;
+    private String statType;
+    private BigDecimal recycleVolume;
+    private BigDecimal recycleRate;
+    private BigDecimal regenerationRate;
+    private BigDecimal accuracyRate;
+    private BigDecimal marketPrice;
+    private Integer companies;
+    private BigDecimal carbonReduction;
+    private String trend;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/RiskAssessment.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("risk_assessments")
+public class RiskAssessment {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long regionId;
+    private String riskType;
+    private String level;
+    private String title;
+    private String content;
+    private String impact;
+    private Integer probability;
+    private String strategy;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/ScanHistory.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("scan_history")
+public class ScanHistory {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private String detectedClass;
+    private String itemName;
+    private String category;
+    private Integer confidence;
+    private Integer points;
+    private String image;
+    private String bbox;
+    private LocalDateTime createdAt;
+}

+ 28 - 0
backend/src/main/java/com/recycle/entity/StatisticsReport.java

@@ -0,0 +1,28 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("statistics_reports")
+public class StatisticsReport {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long enterpriseId;
+    private String reportType;
+    private LocalDate reportDate;
+    private BigDecimal totalRecycleWeight;
+    private BigDecimal totalRevenue;
+    private Integer totalOrders;
+    private Integer newUsers;
+    private BigDecimal carbonReduction;
+    private BigDecimal waterSaving;
+    private BigDecimal electricitySaving;
+    private String categoryData;
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/SubscriptionPlan.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+
+@Data
+@TableName("subscription_plans")
+public class SubscriptionPlan {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String code;
+    private String name;
+    private BigDecimal price;
+    private String unit;
+    private Integer maxUsers;
+    private String storageLimit;
+    private String features;
+    private Integer isPopular;
+    private Integer status;
+}

+ 33 - 0
backend/src/main/java/com/recycle/entity/SubsidyApplication.java

@@ -0,0 +1,33 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("subsidy_applications")
+public class SubsidyApplication {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String applicationNo;
+    private Long enterpriseId;
+    private String enterpriseName;
+    private String subsidyType;
+    private BigDecimal amount;
+    private String purpose;
+    private String materials;
+    private LocalDate applyDate;
+    private String status;
+    private String blockchainHash;
+    private String blockchainStatus;
+    private Long reviewerId;
+    private String reviewerName;
+    private LocalDateTime reviewTime;
+    private String reviewComment;
+    private String rejectReason;
+    private LocalDateTime createdAt;
+}

+ 28 - 0
backend/src/main/java/com/recycle/entity/SubsidyPayment.java

@@ -0,0 +1,28 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("subsidy_payments")
+public class SubsidyPayment {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String paymentNo;
+    private Long applicationId;
+    private Long enterpriseId;
+    private String enterpriseName;
+    private BigDecimal amount;
+    private String purpose;
+    private LocalDate paymentDate;
+    private String paymentMethod;
+    private String bankAccount;
+    private Integer effectiveness;
+    private String status;
+    private LocalDateTime createdAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/Task.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("tasks")
+public class Task {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private String name;
+    private String description;
+    private String type;
+    private String icon;
+    private Integer rewardPoints;
+    private Integer targetCount;
+    private String action;
+    private Integer sortOrder;
+    private Integer status;
+    private LocalDateTime createdAt;
+}

+ 59 - 0
backend/src/main/java/com/recycle/entity/User.java

@@ -0,0 +1,59 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 用户表
+ */
+@Data
+@TableName("users")
+public class User {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String phone;
+
+    private String password;
+
+    private String nickname;
+
+    private String avatar;
+
+    private Integer avatarIndex;
+
+    private Integer level;
+
+    private String levelName;
+
+    private Integer levelProgress;
+
+    private Integer totalPoints;
+
+    private Integer availablePoints;
+
+    private BigDecimal totalCash;
+
+    private BigDecimal availableCash;
+
+    private BigDecimal totalCarbon;
+
+    private Integer recycleCount;
+
+    private String inviteCode;
+
+    private Long invitedBy;
+
+    private Integer status;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+
+    private LocalDateTime lastLoginAt;
+}

+ 47 - 0
backend/src/main/java/com/recycle/entity/UserAddress.java

@@ -0,0 +1,47 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 用户地址表
+ */
+@Data
+@TableName("user_addresses")
+public class UserAddress {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private Long userId;
+
+    private String contactName;
+
+    private String contactPhone;
+
+    private String province;
+
+    private String city;
+
+    private String district;
+
+    private String detail;
+
+    private String fullAddress;
+
+    private String label;
+
+    private Integer isDefault;
+
+    private BigDecimal longitude;
+
+    private BigDecimal latitude;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updatedAt;
+}

+ 17 - 0
backend/src/main/java/com/recycle/entity/UserBadge.java

@@ -0,0 +1,17 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("user_badges")
+public class UserBadge {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private Long badgeId;
+    private LocalDateTime unlockedAt;
+}

+ 24 - 0
backend/src/main/java/com/recycle/entity/UserTask.java

@@ -0,0 +1,24 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("user_tasks")
+public class UserTask {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private Long taskId;
+    private Integer progress;
+    private Integer completed;
+    private Integer rewardClaimed;
+    private LocalDate resetDate;
+    private LocalDateTime completedAt;
+    private LocalDateTime createdAt;
+    private LocalDateTime updatedAt;
+}

+ 44 - 0
backend/src/main/java/com/recycle/entity/WasteCategory.java

@@ -0,0 +1,44 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 废品分类表
+ */
+@Data
+@TableName("waste_categories")
+public class WasteCategory {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String name;
+
+    private String code;
+
+    private String icon;
+
+    private Long parentId;
+
+    private BigDecimal pricePerKg;
+
+    private Integer pointsPerKg;
+
+    private BigDecimal carbonPerKg;
+
+    private String description;
+
+    private String tips;
+
+    private String recyclingInfo;
+
+    private Integer sortOrder;
+
+    private Integer status;
+
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createdAt;
+}

+ 23 - 0
backend/src/main/java/com/recycle/entity/WithdrawRecord.java

@@ -0,0 +1,23 @@
+package com.recycle.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("withdraw_records")
+public class WithdrawRecord {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    private Long userId;
+    private BigDecimal amount;
+    private String method;
+    private String account;
+    private String status;
+    private String remark;
+    private LocalDateTime processedAt;
+    private LocalDateTime createdAt;
+}

+ 41 - 0
backend/src/main/java/com/recycle/exception/GlobalExceptionHandler.java

@@ -0,0 +1,41 @@
+package com.recycle.exception;
+
+import com.recycle.common.Result;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.BindException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    @ExceptionHandler(RuntimeException.class)
+    public Result<Void> handleRuntimeException(RuntimeException e) {
+        log.error("运行时异常: ", e);
+        return Result.error(e.getMessage());
+    }
+
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public Result<Void> handleValidException(MethodArgumentNotValidException e) {
+        String message = e.getBindingResult().getFieldError() != null
+                ? e.getBindingResult().getFieldError().getDefaultMessage()
+                : "参数校验失败";
+        return Result.error(400, message);
+    }
+
+    @ExceptionHandler(BindException.class)
+    public Result<Void> handleBindException(BindException e) {
+        String message = e.getBindingResult().getFieldError() != null
+                ? e.getBindingResult().getFieldError().getDefaultMessage()
+                : "参数绑定失败";
+        return Result.error(400, message);
+    }
+
+    @ExceptionHandler(Exception.class)
+    public Result<Void> handleException(Exception e) {
+        log.error("系统异常: ", e);
+        return Result.error("系统繁忙,请稍后重试");
+    }
+}

+ 49 - 0
backend/src/main/java/com/recycle/interceptor/AuthInterceptor.java

@@ -0,0 +1,49 @@
+package com.recycle.interceptor;
+
+import com.recycle.util.JwtUtil;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+@Component
+@RequiredArgsConstructor
+public class AuthInterceptor implements HandlerInterceptor {
+
+    private final JwtUtil jwtUtil;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        // OPTIONS请求直接放行
+        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
+            return true;
+        }
+
+        String token = request.getHeader("Authorization");
+        if (StringUtils.hasText(token) && token.startsWith("Bearer ")) {
+            token = token.substring(7);
+        }
+
+        if (!StringUtils.hasText(token)) {
+            response.setStatus(401);
+            response.setContentType("application/json;charset=UTF-8");
+            response.getWriter().write("{\"code\":401,\"message\":\"未登录\"}");
+            return false;
+        }
+
+        if (!jwtUtil.validateToken(token)) {
+            response.setStatus(401);
+            response.setContentType("application/json;charset=UTF-8");
+            response.getWriter().write("{\"code\":401,\"message\":\"登录已过期\"}");
+            return false;
+        }
+
+        // 将用户ID放入request属性中
+        Long userId = jwtUtil.getUserId(token);
+        request.setAttribute("userId", userId);
+
+        return true;
+    }
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/ActivityMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.Activity;
+
+public interface ActivityMapper extends BaseMapper<Activity> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/AdministrativeRegionMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.AdministrativeRegion;
+
+public interface AdministrativeRegionMapper extends BaseMapper<AdministrativeRegion> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/AiChatHistoryMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.AiChatHistory;
+
+public interface AiChatHistoryMapper extends BaseMapper<AiChatHistory> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/AiGeneratedReportMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.AiGeneratedReport;
+
+public interface AiGeneratedReportMapper extends BaseMapper<AiGeneratedReport> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/AiInsightMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.AiInsight;
+
+public interface AiInsightMapper extends BaseMapper<AiInsight> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/BadgeMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.Badge;
+
+public interface BadgeMapper extends BaseMapper<Badge> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/BusinessAlertMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.BusinessAlert;
+
+public interface BusinessAlertMapper extends BaseMapper<BusinessAlert> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/BusinessOrderMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.BusinessOrder;
+
+public interface BusinessOrderMapper extends BaseMapper<BusinessOrder> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/BusinessTodoMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.BusinessTodo;
+
+public interface BusinessTodoMapper extends BaseMapper<BusinessTodo> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/CategoryStatisticsMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.CategoryStatistics;
+
+public interface CategoryStatisticsMapper extends BaseMapper<CategoryStatistics> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/CheckinRecordMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.CheckinRecord;
+
+public interface CheckinRecordMapper extends BaseMapper<CheckinRecord> {
+}

+ 9 - 0
backend/src/main/java/com/recycle/mapper/CollectorMapper.java

@@ -0,0 +1,9 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.Collector;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface CollectorMapper extends BaseMapper<Collector> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/ComplianceCheckMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.ComplianceCheck;
+
+public interface ComplianceCheckMapper extends BaseMapper<ComplianceCheck> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/ContractMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.Contract;
+
+public interface ContractMapper extends BaseMapper<Contract> {
+}

+ 7 - 0
backend/src/main/java/com/recycle/mapper/CustomerServiceMessageMapper.java

@@ -0,0 +1,7 @@
+package com.recycle.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.recycle.entity.CustomerServiceMessage;
+
+public interface CustomerServiceMessageMapper extends BaseMapper<CustomerServiceMessage> {
+}

Some files were not shown because too many files changed in this diff