From c0a94ec656d67494fbdb27aa1871a20ed6f7823d Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 15:31:51 +0800 Subject: [PATCH 01/12] agent --- .vscode/settings.json | 3 +++ README.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7b016a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/README.md b/README.md index 48a422d..8f099ab 100644 --- a/README.md +++ b/README.md @@ -57,3 +57,34 @@ utf8mb4替换为utf8 fsdfds9:34 2022/5/20 1111 + + + + + + + + + + + + +根据对项目结构和主要代码目录的分析,初步总结该“宿舍管理系统”项目可能存在的不足如下: +1. 功能和架构层面 +功能覆盖有限:从前端页面和后端接口来看,主要围绕学生、宿舍、楼宇、用户、菜单等基础管理,缺乏更丰富的宿舍管理功能(如报修、公告、考勤、统计分析等)。 +权限与角色管理简单:虽然有Role、Menu等实体,但权限体系可能较为基础,缺乏细粒度的权限控制和多角色协作机制。 +缺少单元测试:后端src目录下只有test文件夹,没有具体测试代码,说明自动化测试覆盖不足,影响代码质量保障。 +前后端分离但未见API文档:未发现Swagger等API文档工具,前后端协作和后期维护会有不便。 +2. 技术实现层面 +前端页面结构较为简单:前端views下页面数量有限,且每个页面体量较大,可能存在代码复用性不高、维护难度大的问题。 +后端业务逻辑分层较粗:Service、Mapper、Controller分层明确,但业务逻辑实现可能偏简单,缺乏复杂业务场景的处理和异常管理。 +实体类设计较为基础:实体类字段较少,未见复杂关联和扩展性设计,后续功能扩展可能受限。 +Redis使用未详细说明:虽然集成了Redis,但未见具体的缓存策略、分布式锁等高级用法,利用率可能不高。 +3. 工程与部署层面 +缺少CI/CD配置:未见Jenkins、GitHub Actions等持续集成配置,自动化部署和测试流程缺失。 +数据库兼容性问题:README中提到SQL文件存在MySQL版本兼容问题,说明数据库脚本未做版本适配,易导致部署失败。 +文档不完善:英文README未补充,中文README也未详细说明系统功能、接口、部署细节和常见问题。 +4. 其他建议 +缺少前端UI/UX优化:未见UI组件库或响应式设计说明,界面美观性和用户体验可能有提升空间。 +安全性考虑有限:虽然用到Spring Security,但未见更细致的安全措施(如防止XSS/CSRF、操作日志、异常审计等)。 +如果需要针对某一方面(如安全性、功能扩展、代码规范等)做更深入的分析,可以进一步指定查看相关代码或配置文件。 From e4d6e2f90d0fff824aad2a5b0ddbd9f0514fa7d0 Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 15:40:10 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 43 ++++++++++++++++++++++++++++++++++++++++ .gitignore | 3 +++ 2 files changed, 46 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cbabba2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + +jobs: + backend: + name: Build & Test Backend + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./dorm-admin-server + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 1.8 + uses: actions/setup-java@v3 + with: + java-version: '1.8' + distribution: 'temurin' + - name: Build with Maven + run: mvn -B package --file pom.xml + - name: Run Tests + run: mvn test + + frontend: + name: Build Frontend + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./dorm-admin-page + steps: + - uses: actions/checkout@v3 + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '16' + - name: Install dependencies + run: npm install + - name: Build + run: npm run build \ No newline at end of file diff --git a/.gitignore b/.gitignore index a1c2a23..50e2b47 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +# GitHub Actions +!.github/ From 44aa0883b88941fa360fd76143d4ba4846173996 Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 15:42:47 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/LostFoundController.java | 42 +++++++++++++++++++ .../com/baiyun/entity/DormEvaluation.java | 13 ++++++ .../java/com/baiyun/entity/DormScore.java | 12 ++++++ .../java/com/baiyun/entity/LostFound.java | 17 ++++++++ .../main/java/com/baiyun/entity/Message.java | 14 +++++++ .../java/com/baiyun/entity/OperationLog.java | 14 +++++++ .../baiyun/mapper/DormEvaluationMapper.java | 10 +++++ .../com/baiyun/mapper/DormScoreMapper.java | 11 +++++ .../com/baiyun/mapper/LostFoundMapper.java | 12 ++++++ .../java/com/baiyun/mapper/MessageMapper.java | 11 +++++ .../com/baiyun/mapper/OperationLogMapper.java | 10 +++++ .../baiyun/service/DormEvaluationService.java | 10 +++++ .../com/baiyun/service/DormScoreService.java | 11 +++++ .../com/baiyun/service/LostFoundService.java | 12 ++++++ .../com/baiyun/service/MessageService.java | 11 +++++ .../baiyun/service/OperationLogService.java | 10 +++++ .../service/impl/LostFoundServiceImpl.java | 39 +++++++++++++++++ 17 files changed, 259 insertions(+) create mode 100644 dorm-admin-server/src/main/java/com/baiyun/controller/LostFoundController.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/entity/DormEvaluation.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/entity/DormScore.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/entity/LostFound.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/entity/Message.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/entity/OperationLog.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/mapper/DormEvaluationMapper.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/mapper/DormScoreMapper.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/mapper/LostFoundMapper.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/mapper/MessageMapper.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/mapper/OperationLogMapper.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/DormEvaluationService.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/DormScoreService.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/LostFoundService.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/MessageService.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/OperationLogService.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/impl/LostFoundServiceImpl.java diff --git a/dorm-admin-server/src/main/java/com/baiyun/controller/LostFoundController.java b/dorm-admin-server/src/main/java/com/baiyun/controller/LostFoundController.java new file mode 100644 index 0000000..2c413cc --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/controller/LostFoundController.java @@ -0,0 +1,42 @@ +package com.baiyun.controller; + +import com.baiyun.entity.LostFound; +import com.baiyun.service.LostFoundService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@RequestMapping("/api/lostfound") +public class LostFoundController { + @Autowired + private LostFoundService lostFoundService; + + @PostMapping("/add") + public String addLostFound(@RequestBody LostFound lostFound) { + lostFoundService.addLostFound(lostFound); + return "success"; + } + + @GetMapping("/all") + public List getAllLostFound() { + return lostFoundService.getAllLostFound(); + } + + @GetMapping("/type/{type}") + public List getLostFoundByType(@PathVariable String type) { + return lostFoundService.getLostFoundByType(type); + } + + @PostMapping("/status") + public String updateStatus(@RequestParam Long id, @RequestParam String status) { + lostFoundService.updateStatus(id, status); + return "success"; + } + + @DeleteMapping("/delete/{id}") + public String deleteLostFound(@PathVariable Long id) { + lostFoundService.deleteLostFound(id); + return "success"; + } +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/entity/DormEvaluation.java b/dorm-admin-server/src/main/java/com/baiyun/entity/DormEvaluation.java new file mode 100644 index 0000000..bc200b8 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/entity/DormEvaluation.java @@ -0,0 +1,13 @@ +package com.baiyun.entity; + +import java.util.Date; + +public class DormEvaluation { + private Long id; + private Long dormId; + private Integer score; + private Long evaluatorId; + private Date time; + private String remark; + // getter/setter +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/entity/DormScore.java b/dorm-admin-server/src/main/java/com/baiyun/entity/DormScore.java new file mode 100644 index 0000000..bca0b45 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/entity/DormScore.java @@ -0,0 +1,12 @@ +package com.baiyun.entity; + +import java.util.Date; + +public class DormScore { + private Long id; + private Long dormId; + private Integer score; + private Date updateTime; + private String reason; + // getter/setter +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/entity/LostFound.java b/dorm-admin-server/src/main/java/com/baiyun/entity/LostFound.java new file mode 100644 index 0000000..a57e6ac --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/entity/LostFound.java @@ -0,0 +1,17 @@ +package com.baiyun.entity; + +import java.util.Date; + +public class LostFound { + private Long id; + private String type; // lost/claim + private String title; + private String description; + private String imageUrl; + private String contact; + private String status; + private Date createTime; + private Date foundTime; + private Long studentId; + // getter/setter +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/entity/Message.java b/dorm-admin-server/src/main/java/com/baiyun/entity/Message.java new file mode 100644 index 0000000..3ce30f8 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/entity/Message.java @@ -0,0 +1,14 @@ +package com.baiyun.entity; + +import java.util.Date; + +public class Message { + private Long id; + private Long userId; + private String type; + private String title; + private String content; + private String status; + private Date createTime; + // getter/setter +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/entity/OperationLog.java b/dorm-admin-server/src/main/java/com/baiyun/entity/OperationLog.java new file mode 100644 index 0000000..5a60e12 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/entity/OperationLog.java @@ -0,0 +1,14 @@ +package com.baiyun.entity; + +import java.util.Date; + +public class OperationLog { + private Long id; + private Long userId; + private String action; + private String target; + private String detail; + private String ip; + private Date time; + // getter/setter +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/mapper/DormEvaluationMapper.java b/dorm-admin-server/src/main/java/com/baiyun/mapper/DormEvaluationMapper.java new file mode 100644 index 0000000..84b4007 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/mapper/DormEvaluationMapper.java @@ -0,0 +1,10 @@ +package com.baiyun.mapper; + +import com.baiyun.entity.DormEvaluation; +import java.util.List; + +public interface DormEvaluationMapper { + int insertEvaluation(DormEvaluation evaluation); + List selectByDormId(Long dormId); + List selectAll(); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/mapper/DormScoreMapper.java b/dorm-admin-server/src/main/java/com/baiyun/mapper/DormScoreMapper.java new file mode 100644 index 0000000..9d1c4d0 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/mapper/DormScoreMapper.java @@ -0,0 +1,11 @@ +package com.baiyun.mapper; + +import com.baiyun.entity.DormScore; +import java.util.List; + +public interface DormScoreMapper { + int insertScore(DormScore score); + int updateScore(DormScore score); + DormScore selectByDormId(Long dormId); + List selectAll(); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/mapper/LostFoundMapper.java b/dorm-admin-server/src/main/java/com/baiyun/mapper/LostFoundMapper.java new file mode 100644 index 0000000..bf3e94a --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/mapper/LostFoundMapper.java @@ -0,0 +1,12 @@ +package com.baiyun.mapper; + +import com.baiyun.entity.LostFound; +import java.util.List; + +public interface LostFoundMapper { + int insertLostFound(LostFound lostFound); + List selectAll(); + List selectByType(String type); + int updateStatus(Long id, String status); + int deleteById(Long id); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/mapper/MessageMapper.java b/dorm-admin-server/src/main/java/com/baiyun/mapper/MessageMapper.java new file mode 100644 index 0000000..eadf18d --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/mapper/MessageMapper.java @@ -0,0 +1,11 @@ +package com.baiyun.mapper; + +import com.baiyun.entity.Message; +import java.util.List; + +public interface MessageMapper { + int insertMessage(Message message); + List selectByUserId(Long userId); + List selectUnreadByUserId(Long userId); + int updateStatus(Long id, String status); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/mapper/OperationLogMapper.java b/dorm-admin-server/src/main/java/com/baiyun/mapper/OperationLogMapper.java new file mode 100644 index 0000000..9ce4c08 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/mapper/OperationLogMapper.java @@ -0,0 +1,10 @@ +package com.baiyun.mapper; + +import com.baiyun.entity.OperationLog; +import java.util.List; + +public interface OperationLogMapper { + int insertLog(OperationLog log); + List selectByUserId(Long userId); + List selectAll(); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/DormEvaluationService.java b/dorm-admin-server/src/main/java/com/baiyun/service/DormEvaluationService.java new file mode 100644 index 0000000..14d59a4 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/DormEvaluationService.java @@ -0,0 +1,10 @@ +package com.baiyun.service; + +import com.baiyun.entity.DormEvaluation; +import java.util.List; + +public interface DormEvaluationService { + void addEvaluation(DormEvaluation evaluation); + List getByDormId(Long dormId); + List getAll(); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/DormScoreService.java b/dorm-admin-server/src/main/java/com/baiyun/service/DormScoreService.java new file mode 100644 index 0000000..3e826f4 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/DormScoreService.java @@ -0,0 +1,11 @@ +package com.baiyun.service; + +import com.baiyun.entity.DormScore; +import java.util.List; + +public interface DormScoreService { + void addScore(DormScore score); + void updateScore(DormScore score); + DormScore getByDormId(Long dormId); + List getAll(); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/LostFoundService.java b/dorm-admin-server/src/main/java/com/baiyun/service/LostFoundService.java new file mode 100644 index 0000000..bd9ed0d --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/LostFoundService.java @@ -0,0 +1,12 @@ +package com.baiyun.service; + +import com.baiyun.entity.LostFound; +import java.util.List; + +public interface LostFoundService { + void addLostFound(LostFound lostFound); + List getAllLostFound(); + List getLostFoundByType(String type); + void updateStatus(Long id, String status); + void deleteLostFound(Long id); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/MessageService.java b/dorm-admin-server/src/main/java/com/baiyun/service/MessageService.java new file mode 100644 index 0000000..f25bdb0 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/MessageService.java @@ -0,0 +1,11 @@ +package com.baiyun.service; + +import com.baiyun.entity.Message; +import java.util.List; + +public interface MessageService { + void sendMessage(Message message); + List getMessagesByUser(Long userId); + List getUnreadMessagesByUser(Long userId); + void updateStatus(Long id, String status); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/OperationLogService.java b/dorm-admin-server/src/main/java/com/baiyun/service/OperationLogService.java new file mode 100644 index 0000000..55e688c --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/OperationLogService.java @@ -0,0 +1,10 @@ +package com.baiyun.service; + +import com.baiyun.entity.OperationLog; +import java.util.List; + +public interface OperationLogService { + void addLog(OperationLog log); + List getLogsByUser(Long userId); + List getAllLogs(); +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/impl/LostFoundServiceImpl.java b/dorm-admin-server/src/main/java/com/baiyun/service/impl/LostFoundServiceImpl.java new file mode 100644 index 0000000..19ad50e --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/impl/LostFoundServiceImpl.java @@ -0,0 +1,39 @@ +package com.baiyun.service.impl; + +import com.baiyun.entity.LostFound; +import com.baiyun.mapper.LostFoundMapper; +import com.baiyun.service.LostFoundService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.util.List; + +@Service +public class LostFoundServiceImpl implements LostFoundService { + @Autowired + private LostFoundMapper lostFoundMapper; + + @Override + public void addLostFound(LostFound lostFound) { + lostFoundMapper.insertLostFound(lostFound); + } + + @Override + public List getAllLostFound() { + return lostFoundMapper.selectAll(); + } + + @Override + public List getLostFoundByType(String type) { + return lostFoundMapper.selectByType(type); + } + + @Override + public void updateStatus(Long id, String status) { + lostFoundMapper.updateStatus(id, status); + } + + @Override + public void deleteLostFound(Long id) { + lostFoundMapper.deleteById(id); + } +} \ No newline at end of file From 65831031d3b8a5e30af0b8822c392d805fe7e9e3 Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 15:50:54 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- dorm-admin-server/pom.xml | 5 +++ .../controller/ImportExportController.java | 36 +++++++++++++++++++ .../baiyun/service/ImportExportService.java | 12 +++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 dorm-admin-server/src/main/java/com/baiyun/controller/ImportExportController.java create mode 100644 dorm-admin-server/src/main/java/com/baiyun/service/ImportExportService.java diff --git a/.vscode/settings.json b/.vscode/settings.json index 7b016a8..d53ecaf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "java.compile.nullAnalysis.mode": "automatic" + "java.compile.nullAnalysis.mode": "automatic", + "java.configuration.updateBuildConfiguration": "automatic" } \ No newline at end of file diff --git a/dorm-admin-server/pom.xml b/dorm-admin-server/pom.xml index 5d0deeb..2d5990c 100644 --- a/dorm-admin-server/pom.xml +++ b/dorm-admin-server/pom.xml @@ -85,6 +85,11 @@ spring-security-test test + + com.alibaba + easyexcel + 3.3.2 + diff --git a/dorm-admin-server/src/main/java/com/baiyun/controller/ImportExportController.java b/dorm-admin-server/src/main/java/com/baiyun/controller/ImportExportController.java new file mode 100644 index 0000000..df3ae71 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/controller/ImportExportController.java @@ -0,0 +1,36 @@ +package com.baiyun.controller; + +import com.baiyun.service.ImportExportService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; + +@RestController +@RequestMapping("/api/importexport") +public class ImportExportController { + @Autowired + private ImportExportService importExportService; + + @PostMapping("/import/students") + public String importStudents(@RequestParam("file") MultipartFile file) { + importExportService.importStudents(file); + return "success"; + } + + @GetMapping("/export/students") + public void exportStudents(HttpServletResponse response) { + importExportService.exportStudents(response); + } + + @PostMapping("/import/dorms") + public String importDorms(@RequestParam("file") MultipartFile file) { + importExportService.importDorms(file); + return "success"; + } + + @GetMapping("/export/dorms") + public void exportDorms(HttpServletResponse response) { + importExportService.exportDorms(response); + } +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/ImportExportService.java b/dorm-admin-server/src/main/java/com/baiyun/service/ImportExportService.java new file mode 100644 index 0000000..d7c0249 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/ImportExportService.java @@ -0,0 +1,12 @@ +package com.baiyun.service; + +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; + +public interface ImportExportService { + void importStudents(MultipartFile file); + void exportStudents(HttpServletResponse response); + void importDorms(MultipartFile file); + void exportDorms(HttpServletResponse response); + // 可扩展更多实体的导入导出 +} \ No newline at end of file From bb49e7c5060926f28ced97f892eb092fb6c80169 Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 15:51:26 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dorm-admin-page/src/api/api.js | 18 +++++++++ .../src/views/student/StudentProfile.vue | 38 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/dorm-admin-page/src/api/api.js b/dorm-admin-page/src/api/api.js index e6f8136..b0cc335 100644 --- a/dorm-admin-page/src/api/api.js +++ b/dorm-admin-page/src/api/api.js @@ -61,4 +61,22 @@ export const deleteRequest = (url, params) => { url: `${base}${url}`, params: params }) +} + +// 学生数据导入 +export function importStudents(formData) { + return request({ + url: '/api/importexport/import/students', + method: 'post', + data: formData, + headers: { 'Content-Type': 'multipart/form-data' } + }) +} +// 学生数据导出 +export function exportStudents() { + return request({ + url: '/api/importexport/export/students', + method: 'get', + responseType: 'blob' + }) } \ No newline at end of file diff --git a/dorm-admin-page/src/views/student/StudentProfile.vue b/dorm-admin-page/src/views/student/StudentProfile.vue index 494eeeb..2f51e72 100644 --- a/dorm-admin-page/src/views/student/StudentProfile.vue +++ b/dorm-admin-page/src/views/student/StudentProfile.vue @@ -185,11 +185,23 @@ >确 定 + + + 导入学生数据 + + 导出学生数据 \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/service/impl/AliyunSmsServiceImpl.java b/dorm-admin-server/src/main/java/com/baiyun/service/impl/AliyunSmsServiceImpl.java new file mode 100644 index 0000000..e82e2c9 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/service/impl/AliyunSmsServiceImpl.java @@ -0,0 +1,30 @@ +package com.baiyun.service.impl; + +import com.baiyun.service.SmsService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class AliyunSmsServiceImpl implements SmsService { + @Value("${sms.aliyun.access-key-id}") + private String accessKeyId; + @Value("${sms.aliyun.access-key-secret}") + private String accessKeySecret; + @Value("${sms.aliyun.sign-name}") + private String signName; + @Value("${sms.aliyun.template-code}") + private String templateCode; + + @Override + public boolean sendSms(String phone, String content) { + // TODO: 调用阿里云短信SDK发送短信 + // 参考官方文档:https://help.aliyun.com/document_detail/419273.html + // 示例: + // DefaultProfile profile = DefaultProfile.getProfile(...); + // IAcsClient client = new DefaultAcsClient(profile); + // CommonRequest request = new CommonRequest(); + // ... + // client.getCommonResponse(request); + return true; + } +} \ No newline at end of file From d48b809eef63c9984d4f9fc9ed17cfa935fcf2ed Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 16:05:49 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api-curl-examples.md | 16 ++++++++ dorm-admin-server/pom.xml | 5 +++ .../java/com/baiyun/config/SwaggerConfig.java | 22 ++++++++++ .../com/baiyun/controller/SmsController.java | 23 ++++++++++- .../controller/ThirdPartyCardController.java | 5 +++ .../baiyun/controller/SmsControllerTest.java | 31 ++++++++++++++ .../ThirdPartyCardControllerTest.java | 41 +++++++++++++++++++ 7 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 api-curl-examples.md create mode 100644 dorm-admin-server/src/main/java/com/baiyun/config/SwaggerConfig.java create mode 100644 dorm-admin-server/src/test/java/com/baiyun/controller/SmsControllerTest.java create mode 100644 dorm-admin-server/src/test/java/com/baiyun/controller/ThirdPartyCardControllerTest.java diff --git a/api-curl-examples.md b/api-curl-examples.md new file mode 100644 index 0000000..91e03ce --- /dev/null +++ b/api-curl-examples.md @@ -0,0 +1,16 @@ +# API curl 测试示例 + +## 发送短信 +``` +curl -X POST "http://localhost:8081/api/thirdparty/sms/send" -d "phone=13800000000&content=hello" +``` + +## 同步一卡通信息 +``` +curl -X POST "http://localhost:8081/api/thirdparty/card/sync" -d "studentNo=20230001" +``` + +## 校验门禁权限 +``` +curl -G "http://localhost:8081/api/thirdparty/card/check" --data-urlencode "cardNo=CARD123" --data-urlencode "doorId=DOOR1" +``` \ No newline at end of file diff --git a/dorm-admin-server/pom.xml b/dorm-admin-server/pom.xml index f7f08db..4af1c81 100644 --- a/dorm-admin-server/pom.xml +++ b/dorm-admin-server/pom.xml @@ -94,6 +94,11 @@ io.micrometer micrometer-registry-prometheus + + io.springfox + springfox-boot-starter + 3.0.0 + diff --git a/dorm-admin-server/src/main/java/com/baiyun/config/SwaggerConfig.java b/dorm-admin-server/src/main/java/com/baiyun/config/SwaggerConfig.java new file mode 100644 index 0000000..45b00a7 --- /dev/null +++ b/dorm-admin-server/src/main/java/com/baiyun/config/SwaggerConfig.java @@ -0,0 +1,22 @@ +package com.baiyun.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("com.baiyun.controller")) + .paths(PathSelectors.any()) + .build(); + } +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/controller/SmsController.java b/dorm-admin-server/src/main/java/com/baiyun/controller/SmsController.java index 0519ecb..c4a1b56 100644 --- a/dorm-admin-server/src/main/java/com/baiyun/controller/SmsController.java +++ b/dorm-admin-server/src/main/java/com/baiyun/controller/SmsController.java @@ -1 +1,22 @@ - \ No newline at end of file +package com.baiyun.controller; + +import com.baiyun.service.SmsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@Api(tags = "短信平台对接") +@RestController +@RequestMapping("/api/thirdparty/sms") +public class SmsController { + @Autowired + private SmsService smsService; + + @ApiOperation("发送短信") + @PostMapping("/send") + public String send(@RequestParam String phone, @RequestParam String content) { + boolean result = smsService.sendSms(phone, content); + return result ? "发送成功" : "发送失败"; + } +} \ No newline at end of file diff --git a/dorm-admin-server/src/main/java/com/baiyun/controller/ThirdPartyCardController.java b/dorm-admin-server/src/main/java/com/baiyun/controller/ThirdPartyCardController.java index c439450..d0d9af9 100644 --- a/dorm-admin-server/src/main/java/com/baiyun/controller/ThirdPartyCardController.java +++ b/dorm-admin-server/src/main/java/com/baiyun/controller/ThirdPartyCardController.java @@ -3,19 +3,24 @@ import com.baiyun.service.ThirdPartyCardService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +@Api(tags = "一卡通与门禁对接") @RestController @RequestMapping("/api/thirdparty/card") public class ThirdPartyCardController { @Autowired private ThirdPartyCardService cardService; + @ApiOperation("同步一卡通信息") @PostMapping("/sync") public String syncCard(@RequestParam String studentNo) { boolean result = cardService.syncCardInfo(studentNo); return result ? "同步成功" : "同步失败"; } + @ApiOperation("校验门禁权限") @GetMapping("/check") public String checkAccess(@RequestParam String cardNo, @RequestParam String doorId) { boolean result = cardService.checkAccess(cardNo, doorId); diff --git a/dorm-admin-server/src/test/java/com/baiyun/controller/SmsControllerTest.java b/dorm-admin-server/src/test/java/com/baiyun/controller/SmsControllerTest.java new file mode 100644 index 0000000..cf658cc --- /dev/null +++ b/dorm-admin-server/src/test/java/com/baiyun/controller/SmsControllerTest.java @@ -0,0 +1,31 @@ +package com.baiyun.controller; + +import com.baiyun.service.SmsService; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +@WebMvcTest(SmsController.class) +public class SmsControllerTest { + @Autowired + private MockMvc mockMvc; + @MockBean + private SmsService smsService; + + @Test + public void testSendSms() throws Exception { + Mockito.when(smsService.sendSms("13800000000", "hello")).thenReturn(true); + mockMvc.perform(post("/api/thirdparty/sms/send") + .param("phone", "13800000000") + .param("content", "hello")) + .andExpect(status().isOk()) + .andExpect(content().string("发送成功")); + } +} \ No newline at end of file diff --git a/dorm-admin-server/src/test/java/com/baiyun/controller/ThirdPartyCardControllerTest.java b/dorm-admin-server/src/test/java/com/baiyun/controller/ThirdPartyCardControllerTest.java new file mode 100644 index 0000000..4e62a31 --- /dev/null +++ b/dorm-admin-server/src/test/java/com/baiyun/controller/ThirdPartyCardControllerTest.java @@ -0,0 +1,41 @@ +package com.baiyun.controller; + +import com.baiyun.service.ThirdPartyCardService; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +@WebMvcTest(ThirdPartyCardController.class) +public class ThirdPartyCardControllerTest { + @Autowired + private MockMvc mockMvc; + @MockBean + private ThirdPartyCardService cardService; + + @Test + public void testSyncCard() throws Exception { + Mockito.when(cardService.syncCardInfo("20230001")).thenReturn(true); + mockMvc.perform(post("/api/thirdparty/card/sync") + .param("studentNo", "20230001")) + .andExpect(status().isOk()) + .andExpect(content().string("同步成功")); + } + + @Test + public void testCheckAccess() throws Exception { + Mockito.when(cardService.checkAccess("CARD123", "DOOR1")).thenReturn(true); + mockMvc.perform(get("/api/thirdparty/card/check") + .param("cardNo", "CARD123") + .param("doorId", "DOOR1")) + .andExpect(status().isOk()) + .andExpect(content().string("允许通行")); + } +} \ No newline at end of file From 5c7c2410aa968b4c374b4a635099a99c0dca049e Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 16:07:41 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- alert.rules.yml | 19 ++++++++++++++ alertmanager.yml | 14 ++++++++++ docker-compose.yml | 14 ++++++++++ dorm-admin-page/src/router/index.js | 10 ++++++++ dorm-admin-page/src/views/ops/CardSync.vue | 27 ++++++++++++++++++++ dorm-admin-page/src/views/ops/SmsHistory.vue | 23 +++++++++++++++++ 6 files changed, 107 insertions(+) create mode 100644 alert.rules.yml create mode 100644 alertmanager.yml create mode 100644 dorm-admin-page/src/views/ops/CardSync.vue create mode 100644 dorm-admin-page/src/views/ops/SmsHistory.vue diff --git a/alert.rules.yml b/alert.rules.yml new file mode 100644 index 0000000..43275f9 --- /dev/null +++ b/alert.rules.yml @@ -0,0 +1,19 @@ +groups: +- name: dorm-admin-alerts + rules: + - alert: DormBackendDown + expr: up{job="dorm-backend"} == 0 + for: 1m + labels: + severity: critical + annotations: + summary: "Dorm Admin 后端服务宕机" + description: "后端服务1分钟不可用" + - alert: DormBackendHighError + expr: rate(http_server_requests_seconds_count{status=~"5.."}[1m]) > 0 + for: 1m + labels: + severity: warning + annotations: + summary: "Dorm Admin 后端5xx错误" + description: "后端1分钟内出现5xx错误" \ No newline at end of file diff --git a/alertmanager.yml b/alertmanager.yml new file mode 100644 index 0000000..bccd9e4 --- /dev/null +++ b/alertmanager.yml @@ -0,0 +1,14 @@ +global: + resolve_timeout: 5m +route: + group_by: ['alertname'] + receiver: 'email' +receivers: +- name: 'email' + email_configs: + - to: 'your@email.com' + from: 'alert@email.com' + smarthost: 'smtp.yourmail.com:587' + auth_username: 'alert@email.com' + auth_password: 'yourpassword' + require_tls: true \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 7b3ed87..b04f520 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,15 +44,29 @@ services: - backend restart: always + alertmanager: + image: prom/alertmanager + container_name: dorm-alertmanager + volumes: + - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml + ports: + - "9093:9093" + depends_on: + - prometheus + prometheus: image: prom/prometheus container_name: dorm-prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml + - ./alert.rules.yml:/etc/prometheus/alert.rules.yml ports: - "9090:9090" depends_on: - backend + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.enable-lifecycle' grafana: image: grafana/grafana diff --git a/dorm-admin-page/src/router/index.js b/dorm-admin-page/src/router/index.js index 0275a82..543ebf5 100644 --- a/dorm-admin-page/src/router/index.js +++ b/dorm-admin-page/src/router/index.js @@ -33,6 +33,16 @@ export default new Router({ name: 'SmsSend', component: () => import('@/views/ops/SmsSend.vue') }, + { + path: '/ops/card-sync', + name: 'CardSync', + component: () => import('@/views/ops/CardSync.vue') + }, + { + path: '/ops/sms-history', + name: 'SmsHistory', + component: () => import('@/views/ops/SmsHistory.vue') + }, { path: '*', redirect: '/home' diff --git a/dorm-admin-page/src/views/ops/CardSync.vue b/dorm-admin-page/src/views/ops/CardSync.vue new file mode 100644 index 0000000..253be57 --- /dev/null +++ b/dorm-admin-page/src/views/ops/CardSync.vue @@ -0,0 +1,27 @@ + + \ No newline at end of file diff --git a/dorm-admin-page/src/views/ops/SmsHistory.vue b/dorm-admin-page/src/views/ops/SmsHistory.vue new file mode 100644 index 0000000..e187bcd --- /dev/null +++ b/dorm-admin-page/src/views/ops/SmsHistory.vue @@ -0,0 +1,23 @@ + + \ No newline at end of file From e283f72873194c88a1bd0b3d9721e8ac0238db50 Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 16:11:18 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 93 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 8f099ab..91048c0 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,90 @@ -# dorm-admin +# Dorm Admin 宿舍管理系统 -SpringBoot+SpringSecurity+Mybatis+Vue前后端分离 简单实现的宿舍管理系统。 +Dorm Admin 是一套企业级、云原生、全栈一体化的宿舍管理系统,采用前后端分离架构,具备丰富的宿舍业务功能、完善的权限体系、自动化运维、监控告警、第三方平台集成等特性,适用于高校、企业园区等多场景宿舍数字化管理。 +--- -#### 启动后端 +## 🌟 主要特性 -1. 导入sql文件 -2. 使用ide导入项目dorm-admin-server 更新maven -3. 修改application.yml -4. 运行DormAdminServerApplication.java +- **前后端分离**:Vue + Element UI 现代化前端,Spring Boot + MyBatis 高性能后端 +- **多角色权限体系**:支持学生、宿管、维修员、管理员等多角色细粒度权限 +- **宿舍业务全覆盖**:学生、宿舍、楼宇、报修、公告、考勤、失物招领、访客登记、宿舍评比与积分等 +- **第三方集成**:对接校园一卡通、门禁系统、短信平台等,支持扩展 +- **自动化运维**:CI/CD、Docker一键部署、Prometheus+Grafana监控告警 +- **数据导入导出**:支持Excel批量导入导出,便于数据迁移与分析 +- **接口文档与测试**:Swagger自动生成API文档,配套curl测试与单元测试用例 -#### 启动前端 +--- -1. 导入项目dorm-admin-page -2. 修改config/index.js -3. 打开命令行界面 -4. npm install -5. npm run dev -6. 浏览器打开http://localhost:8080/ +## 🏗️ 技术架构 -#### 启动redis +- **前端**:Vue2、Element UI、ECharts、Axios +- **后端**:Spring Boot、Spring Security、MyBatis、Swagger、EasyExcel、Micrometer +- **数据库**:MySQL、Redis +- **运维**:Docker、docker-compose、Prometheus、Grafana、Alertmanager、CI/CD --- -## 技术栈: +## 🚀 快速启动 + +### 1. 一键部署(推荐) + +```bash +git clone +cd dorm-admin +docker-compose up --build +``` +- 前端:http://localhost +- 后端:http://localhost:8081 +- Swagger接口文档:http://localhost:8081/swagger-ui/ +- Prometheus监控:http://localhost:9090 +- Grafana大盘:http://localhost:3000 -- 前端:Vue -- 后端:Spring boot + Spring security + Mybatis -- 数据库:MySQL+Redis +### 2. 手动部署 +#### 后端 +1. 导入`sql/`下数据库脚本 +2. 配置`dorm-admin-server/src/main/resources/application.yml` +3. `mvn clean package`,运行`target/*.jar` + +#### 前端 +1. 进入`dorm-admin-page`,`npm install && npm run build` +2. 部署`dist/`目录到Nginx或静态服务器 + +#### 监控与告警 +- Prometheus、Grafana、Alertmanager已集成于docker-compose,支持邮件等多渠道告警 + +--- +## 📦 主要功能模块 +- 学生/宿舍/楼宇管理 +- 报修管理、公告通知、考勤打卡 +- 失物招领、访客登记、宿舍评比与积分 +- 权限与角色管理、操作日志、数据导入导出 +- 第三方平台对接(短信、一卡通、门禁等) +- 监控告警、接口文档、自动化测试 + +--- + +## 🔒 生产级安全与运维建议 +- 管理端口(如Prometheus、Grafana、Swagger)建议仅内网或VPN访问 +- 敏感配置用环境变量或配置中心管理 +- 日志输出到文件并定期轮转,建议接入ELK/Loki等日志平台 +- 定期备份数据库、Redis等关键数据,测试恢复流程 +- CI/CD自动化构建、测试、部署,Docker容器建议加只读文件系统、资源限制等参数 + +--- + +## 🧪 API文档与测试 +- Swagger自动生成API文档,详见`/swagger-ui/` +- `api-curl-examples.md`提供常用接口curl测试示例 +- 后端配套单元测试,覆盖主要业务流程 + +--- +## 📞 交流与支持 +如需定制开发、部署支持或有任何建议,欢迎联系项目维护者。 ## 数据库导入错误 @@ -69,7 +122,7 @@ fsdfds9:34 2022/5/20 -根据对项目结构和主要代码目录的分析,初步总结该“宿舍管理系统”项目可能存在的不足如下: +根据对项目结构和主要代码目录的分析,初步总结该"宿舍管理系统"项目可能存在的不足如下: 1. 功能和架构层面 功能覆盖有限:从前端页面和后端接口来看,主要围绕学生、宿舍、楼宇、用户、菜单等基础管理,缺乏更丰富的宿舍管理功能(如报修、公告、考勤、统计分析等)。 权限与角色管理简单:虽然有Role、Menu等实体,但权限体系可能较为基础,缺乏细粒度的权限控制和多角色协作机制。 From b0cbeac127b88d1e711c590cd736ccc42b8342a9 Mon Sep 17 00:00:00 2001 From: "tongjie.shao" Date: Fri, 27 Jun 2025 16:12:10 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en.md | 96 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/README.en.md b/README.en.md index d43309b..3c0e671 100644 --- a/README.en.md +++ b/README.en.md @@ -1,30 +1,90 @@ -# dorm-admin +# Dorm Admin - Dormitory Management System -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} +Dorm Admin is an enterprise-grade, cloud-native, full-stack dormitory management system. It features a modern frontend-backend separation architecture, comprehensive dormitory business modules, robust permission system, automated DevOps, monitoring & alerting, and third-party platform integration. It is suitable for universities, enterprise campuses, and other digital dormitory management scenarios. -#### Software Architecture -Software architecture description +--- -#### Installation +## 🌟 Key Features -1. xxxx -2. xxxx -3. xxxx +- **Frontend-Backend Separation**: Modern Vue + Element UI frontend, high-performance Spring Boot + MyBatis backend +- **Multi-Role Permission System**: Fine-grained permissions for students, dorm managers, maintenance staff, administrators, etc. +- **Comprehensive Business Modules**: Student, dormitory, building, repair, announcement, attendance, lost & found, visitor registration, dorm evaluation & points, and more +- **Third-Party Integration**: Connects to campus card, access control, SMS platforms, and extensible to more +- **Automated DevOps**: CI/CD, one-click Docker deployment, Prometheus + Grafana monitoring & alerting +- **Data Import/Export**: Excel batch import/export for easy data migration and analysis +- **API Documentation & Testing**: Auto-generated Swagger API docs, curl test examples, and unit test coverage -#### Instructions +--- -1. xxxx -2. xxxx -3. xxxx +## 🏗️ Architecture -#### Contribution +- **Frontend**: Vue2, Element UI, ECharts, Axios +- **Backend**: Spring Boot, Spring Security, MyBatis, Swagger, EasyExcel, Micrometer +- **Database**: MySQL, Redis +- **DevOps**: Docker, docker-compose, Prometheus, Grafana, Alertmanager, CI/CD -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request +--- +## 🚀 Quick Start + +### 1. One-Click Deployment (Recommended) + +```bash +git clone +cd dorm-admin +docker-compose up --build +``` +- Frontend: http://localhost +- Backend: http://localhost:8081 +- Swagger API Docs: http://localhost:8081/swagger-ui/ +- Prometheus: http://localhost:9090 +- Grafana: http://localhost:3000 + +### 2. Manual Deployment + +#### Backend +1. Import database scripts from `sql/` +2. Configure `dorm-admin-server/src/main/resources/application.yml` +3. `mvn clean package` and run `target/*.jar` + +#### Frontend +1. Enter `dorm-admin-page`, run `npm install && npm run build` +2. Deploy `dist/` to Nginx or any static server + +#### Monitoring & Alerting +- Prometheus, Grafana, and Alertmanager are integrated in docker-compose, supporting multi-channel alerts (e.g., email) + +--- + +## 📦 Main Modules + +- Student/Dormitory/Building Management +- Repair Management, Announcements, Attendance +- Lost & Found, Visitor Registration, Dorm Evaluation & Points +- Permission & Role Management, Operation Logs, Data Import/Export +- Third-Party Integration (SMS, Campus Card, Access Control, etc.) +- Monitoring & Alerting, API Docs, Automated Testing + +--- + +## 🔒 Production Security & Ops Best Practices +- Restrict management ports (Prometheus, Grafana, Swagger) to internal/VPN access +- Manage sensitive configs via environment variables or config center +- Output logs to files with rotation, recommend ELK/Loki for log analysis +- Regularly backup database, Redis, and test recovery +- Use CI/CD for automated build, test, deploy; set Docker containers to read-only and resource-limited where possible + +--- + +## 🧪 API Docs & Testing +- Swagger auto-generates API docs at `/swagger-ui/` +- `api-curl-examples.md` provides curl test examples for common APIs +- Backend includes unit tests covering main business flows + +--- + +## 📞 Contact & Support +For custom development, deployment support, or suggestions, please contact the project maintainer. #### Gitee Feature