From 5f9bcfc9b2a1765d775dafa990e23f0f8c964747 Mon Sep 17 00:00:00 2001 From: tangweijie <877588133@qq.com> Date: Thu, 15 Jan 2026 12:16:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(prison):=20=E5=AE=8C=E5=96=84=E7=9B=91?= =?UTF-8?q?=E5=AE=A4=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E5=8F=8A=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复监室状态枚举显示问题,使用标准字典类型 - 优化监区树形选择组件,改用 el-tree-select - 修复 PrisonerDO.subAreaId 字段相关编译错误 - 优化 CellServiceImpl 关联查询监区名称 - 修复 lambda 表达式变量引用问题 - 配置 Redis 密码 redis_Dbdb2F --- sql/prison_dict_data.sql | 64 +++--- sql/prison_init.sql | 33 +++ .../admin/area/PrisonAreaController.java | 38 ++++ .../controller/admin/area/vo/AreaRespVO.java | 15 +- .../admin/area/vo/AreaSaveReqVO.java | 8 +- .../admin/cell/PrisonCellController.java | 27 ++- .../controller/admin/cell/vo/CellRespVO.java | 4 + .../dashboard/PrisonDashboardController.java | 33 +++ .../admin/dashboard/vo/ChartDataVO.java | 25 +++ .../dashboard/vo/DashboardStatisticsVO.java | 49 +++++ .../admin/dashboard/vo/ProvinceChartVO.java | 25 +++ .../admin/prisoner/PrisonerController.java | 139 +++++++++++- .../arealog/PrisonerAreaLogController.java | 93 ++++++++ .../arealog/vo/PrisonerAreaLogPageReqVO.java | 41 ++++ .../arealog/vo/PrisonerAreaLogRespVO.java | 92 ++++++++ .../arealog/vo/PrisonerAreaLogSaveReqVO.java | 66 ++++++ .../admin/prisoner/vo/PrisonerExcelVO.java | 3 - .../admin/prisoner/vo/PrisonerRespVO.java | 27 +++ .../admin/prisoner/vo/PrisonerSaveReqVO.java | 42 +++- .../admin/prisoner/vo/TransferReqVO.java | 29 +++ .../admin/release/ReleaseController.java | 134 +++++++++++ .../admin/release/vo/ReleasePageReqVO.java | 38 ++++ .../admin/release/vo/ReleaseRespVO.java | 80 +++++++ .../admin/release/vo/ReleaseSaveReqVO.java | 59 +++++ .../scorerecord/ScoreDetailController.java | 85 +++++++ .../scorerecord/vo/ScoreDetailPageReqVO.java | 40 ++++ .../scorerecord/vo/ScoreDetailRespVO.java | 65 ++++++ .../scorerecord/vo/ScoreDetailSaveReqVO.java | 46 ++++ .../admin/scorerule/ScoreRuleController.java | 96 ++++++++ .../scorerule/vo/ScoreRulePageReqVO.java | 30 +++ .../admin/scorerule/vo/ScoreRuleRespVO.java | 58 +++++ .../scorerule/vo/ScoreRuleSaveReqVO.java | 53 +++++ .../prison/convert/area/AreaConvert.java | 29 +++ .../convert/prisoner/PrisonerConvert.java | 72 ++++++ .../PrisonerAreaLogConvert.java | 29 +++ .../dal/dataobject/PrisonerAreaLogDO.java | 99 +++++++++ .../prison/dal/dataobject/PrisonerDO.java | 50 +++++ .../prison/dal/dataobject/area/AreaDO.java | 17 +- .../dal/dataobject/release/ReleaseDO.java | 95 ++++++++ .../dataobject/scorerecord/ScoreDetailDO.java | 71 ++++++ .../dal/dataobject/scorerule/ScoreRuleDO.java | 66 ++++++ .../dal/mysql/PrisonerAreaLogMapper.java | 15 ++ .../prison/dal/mysql/PrisonerMapper.java | 17 ++ .../dashboard/PrisonDashboardMapper.java | 170 ++++++++++++++ .../dal/mysql/release/ReleaseMapper.java | 15 ++ .../mysql/scorerecord/ScoreDetailMapper.java | 15 ++ .../dal/mysql/scorerule/ScoreRuleMapper.java | 15 ++ .../prison/enums/AreaChangeTypeEnum.java | 28 +++ .../module/prison/enums/AreaTypeEnum.java | 38 ++++ .../module/prison/enums/CellStatusEnum.java | 37 ++++ .../prison/enums/DictTypeConstants.java | 14 ++ .../module/prison/enums/EducationEnum.java | 2 + .../prison/enums/ErrorCodeConstants.java | 4 + .../yudao/module/prison/enums/GenderEnum.java | 11 + .../prison/enums/PrisonerStatusEnum.java | 11 + .../module/prison/enums/ReleaseTypeEnum.java | 31 +++ .../module/prison/enums/RiskLevelEnum.java | 11 + .../prison/enums/SupervisionLevelEnum.java | 11 + .../prison/service/PrisonerService.java | 19 +- .../prison/service/area/AreaService.java | 34 +++ .../prison/service/area/AreaServiceImpl.java | 153 ++++++++++++- .../prison/service/cell/CellService.java | 2 +- .../prison/service/cell/CellServiceImpl.java | 57 ++++- .../dashboard/PrisonDashboardService.java | 19 ++ .../impl/PrisonDashboardServiceImpl.java | 137 ++++++++++++ .../service/impl/PrisonerServiceImpl.java | 208 +++++++++++++++++- .../PrisonerAreaLogServiceImpl.java | 107 +++++++++ .../PrisonerAreaLogService.java | 69 ++++++ .../service/release/ReleaseService.java | 78 +++++++ .../release/impl/ReleaseServiceImpl.java | 194 ++++++++++++++++ .../service/reminder/NotifyService.java | 37 ++++ .../service/reminder/ReminderService.java | 74 +++++++ .../scorerecord/ScoreDetailService.java | 62 ++++++ .../impl/ScoreDetailServiceImpl.java | 94 ++++++++ .../service/scorerule/ScoreRuleService.java | 70 ++++++ .../scorerule/impl/ScoreRuleServiceImpl.java | 105 +++++++++ .../service/transfer/TransferService.java | 27 +++ .../transfer/impl/TransferServiceImpl.java | 114 ++++++++++ .../module/prison/util/DataMaskUtils.java | 93 ++++++++ .../main/resources/mapper/PrisonerMapper.xml | 34 ++- .../main/resources/sql/preset_area_data.sql | 149 +++++++++++++ .../src/main/resources/sql/prison_module.sql | 38 +++- .../prison/enums/EducationEnumTest.java | 82 +++++++ .../module/prison/enums/GenderEnumTest.java | 42 ++++ .../prison/enums/PrisonerStatusEnumTest.java | 75 +++++++ .../prison/enums/RiskLevelEnumTest.java | 50 +++++ .../enums/SupervisionLevelEnumTest.java | 50 +++++ .../src/main/resources/application-local.yaml | 26 +-- .../src/main/resources/application.yaml | 4 +- 89 files changed, 4824 insertions(+), 89 deletions(-) create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/PrisonDashboardController.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ChartDataVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/DashboardStatisticsVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ProvinceChartVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/PrisonerAreaLogController.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogPageReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogRespVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogSaveReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/TransferReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/ReleaseController.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleasePageReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseRespVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseSaveReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/ScoreDetailController.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailPageReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailRespVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailSaveReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/ScoreRuleController.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRulePageReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleRespVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleSaveReqVO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/area/AreaConvert.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisonerarealog/PrisonerAreaLogConvert.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerAreaLogDO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/release/ReleaseDO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerecord/ScoreDetailDO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerule/ScoreRuleDO.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerAreaLogMapper.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/dashboard/PrisonDashboardMapper.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/release/ReleaseMapper.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerecord/ScoreDetailMapper.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerule/ScoreRuleMapper.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaChangeTypeEnum.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaTypeEnum.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/CellStatusEnum.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ReleaseTypeEnum.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/PrisonDashboardService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/impl/PrisonDashboardServiceImpl.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/prisonerarealog/PrisonerAreaLogServiceImpl.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/prisonerarealog/PrisonerAreaLogService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/ReleaseService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/impl/ReleaseServiceImpl.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/NotifyService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/ReminderService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/ScoreDetailService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/impl/ScoreDetailServiceImpl.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/ScoreRuleService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/impl/ScoreRuleServiceImpl.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/TransferService.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/impl/TransferServiceImpl.java create mode 100644 yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/util/DataMaskUtils.java create mode 100644 yudao-module-prison/src/main/resources/sql/preset_area_data.sql create mode 100644 yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/EducationEnumTest.java create mode 100644 yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/GenderEnumTest.java create mode 100644 yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnumTest.java create mode 100644 yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnumTest.java create mode 100644 yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnumTest.java diff --git a/sql/prison_dict_data.sql b/sql/prison_dict_data.sql index 3ce4900289..d784b715d9 100644 --- a/sql/prison_dict_data.sql +++ b/sql/prison_dict_data.sql @@ -3,20 +3,20 @@ -- ============================================ -- 1. 监管等级 (prison_supervision_level) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2008, '监管等级', 'prison_supervision_level', '0', '服刑人员监管等级', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (200801, 1, '严管级', '1', 'danger', '', 'prison_supervision_level', '0', '需要重点监控', 'admin', NOW(), 'admin', NOW(), 0), (200802, 2, '普管级', '2', 'warning', '', 'prison_supervision_level', '0', '常规管理', 'admin', NOW(), 'admin', NOW(), 0), (200803, 3, '宽管级', '3', 'success', '', 'prison_supervision_level', '0', '表现良好,给予更多自主权', 'admin', NOW(), 'admin', NOW(), 0); -- 2. 风险等级 (prison_risk_level) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2009, '风险等级', 'prison_risk_level', '0', '服刑人员风险等级', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (200901, 1, '低风险', '1', 'success', '', 'prison_risk_level', '0', '低风险,表现稳定', 'admin', NOW(), 'admin', NOW(), 0), (200902, 2, '中风险', '2', 'warning', '', 'prison_risk_level', '0', '中风险,需要定期关注', 'admin', NOW(), 'admin', NOW(), 0), @@ -24,10 +24,10 @@ VALUES (200904, 4, '极高风险', '4', 'danger', '', 'prison_risk_level', '0', '极高风险,需要重点监控', 'admin', NOW(), 'admin', NOW(), 0); -- 3. 服刑人员状态 (prisoner_status) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2010, '服刑人员状态', 'prisoner_status', '0', '服刑人员状态', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201001, 1, '在押', '1', 'primary', '', 'prisoner_status', '0', '正在服刑', 'admin', NOW(), 'admin', NOW(), 0), (201002, 2, '假释', '2', 'warning', '', 'prisoner_status', '0', '假释期间', 'admin', NOW(), 'admin', NOW(), 0), @@ -36,10 +36,10 @@ VALUES (201005, 5, '已死亡', '5', 'danger', '', 'prisoner_status', '0', '已死亡', 'admin', NOW(), 'admin', NOW(), 0); -- 4. 文化程度 (prison_education) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2011, '文化程度', 'prison_education', '0', '服刑人员文化程度', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201101, 1, '文盲', '1', 'info', '', 'prison_education', '0', '未接受过教育', 'admin', NOW(), 'admin', NOW(), 0), (201102, 2, '小学', '2', 'info', '', 'prison_education', '0', '小学毕业', 'admin', NOW(), 'admin', NOW(), 0), @@ -50,10 +50,10 @@ VALUES (201107, 7, '本科及以上', '7', 'success', '', 'prison_education', '0', '本科及以上学历', 'admin', NOW(), 'admin', NOW(), 0); -- 5. 问卷问题类型 (prison_question_type) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2012, '问卷问题类型', 'prison_question_type', '0', '问卷问题类型', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201201, 1, '单选', '1', 'primary', '', 'prison_question_type', '0', '单选题', 'admin', NOW(), 'admin', NOW(), 0), (201202, 2, '多选', '2', 'success', '', 'prison_question_type', '0', '多选题', 'admin', NOW(), 'admin', NOW(), 0), @@ -61,59 +61,59 @@ VALUES (201204, 4, '评分', '4', 'info', '', 'prison_question_type', '0', '评分题', 'admin', NOW(), 'admin', NOW(), 0); -- 6. 问卷状态 (prison_questionnaire_status) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2013, '问卷状态', 'prison_questionnaire_status', '0', '问卷状态', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201301, 1, '草稿', '1', 'info', '', 'prison_questionnaire_status', '0', '问卷草稿', 'admin', NOW(), 'admin', NOW(), 0), (201302, 2, '已发布', '2', 'success', '', 'prison_questionnaire_status', '0', '问卷已发布', 'admin', NOW(), 'admin', NOW(), 0), (201303, 3, '已禁用', '3', 'danger', '', 'prison_questionnaire_status', '0', '问卷已禁用', 'admin', NOW(), 'admin', NOW(), 0); -- 6.1 问卷类型 (prison_questionnaire_type) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2021, '问卷类型', 'prison_questionnaire_type', '0', '问卷类型', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (202101, 1, '心理测评', '1', 'primary', '', 'prison_questionnaire_type', '0', '心理测评问卷', 'admin', NOW(), 'admin', NOW(), 0), (202102, 2, '行为评估', '2', 'warning', '', 'prison_questionnaire_type', '0', '行为评估问卷', 'admin', NOW(), 'admin', NOW(), 0), (202103, 3, '满意度调查', '3', 'success', '', 'prison_questionnaire_type', '0', '满意度调查问卷', 'admin', NOW(), 'admin', NOW(), 0); -- 7. 消费类型 (prison_consumption_type) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2014, '消费类型', 'prison_consumption_type', '0', '消费记录类型', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201401, 1, '存款', '1', 'success', '', 'prison_consumption_type', '0', '存款', 'admin', NOW(), 'admin', NOW(), 0), (201402, 2, '消费', '2', 'primary', '', 'prison_consumption_type', '0', '消费', 'admin', NOW(), 'admin', NOW(), 0), (201403, 3, '转账', '3', 'warning', '', 'prison_consumption_type', '0', '转账', 'admin', NOW(), 'admin', NOW(), 0); -- 8. 消费状态 (prison_consumption_status) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2015, '消费状态', 'prison_consumption_status', '0', '消费记录状态', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201501, 1, '成功', '1', 'success', '', 'prison_consumption_status', '0', '交易成功', 'admin', NOW(), 'admin', NOW(), 0), (201502, 2, '失败', '2', 'danger', '', 'prison_consumption_status', '0', '交易失败', 'admin', NOW(), 'admin', NOW(), 0); -- 9. 评估类型 (prison_assessment_type) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2016, '评估类型', 'prison_assessment_type', '0', '危险评估类型', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201601, 1, '入狱评估', '1', 'primary', '', 'prison_assessment_type', '0', '入狱时评估', 'admin', NOW(), 'admin', NOW(), 0), (201602, 2, '定期评估', '2', 'success', '', 'prison_assessment_type', '0', '定期评估', 'admin', NOW(), 'admin', NOW(), 0), (201603, 3, '专项评估', '3', 'warning', '', 'prison_assessment_type', '0', '专项评估', 'admin', NOW(), 'admin', NOW(), 0); -- 10. 考核等级 (prison_score_level) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2017, '考核等级', 'prison_score_level', '0', '计分考核等级', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201701, 1, '优秀', '1', 'success', '', 'prison_score_level', '0', '表现优秀', 'admin', NOW(), 'admin', NOW(), 0), (201702, 2, '良好', '2', 'primary', '', 'prison_score_level', '0', '表现良好', 'admin', NOW(), 'admin', NOW(), 0), @@ -121,31 +121,37 @@ VALUES (201704, 4, '不合格', '4', 'danger', '', 'prison_score_level', '0', '表现不合格', 'admin', NOW(), 'admin', NOW(), 0); -- 11. 考核状态 (prison_score_status) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2018, '考核状态', 'prison_score_status', '0', '计分考核状态', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201801, 1, '待审核', '1', 'info', '', 'prison_score_status', '0', '待审核', 'admin', NOW(), 'admin', NOW(), 0), (201802, 2, '已通过', '2', 'success', '', 'prison_score_status', '0', '已通过审核', 'admin', NOW(), 'admin', NOW(), 0), (201803, 3, '已驳回', '3', 'danger', '', 'prison_score_status', '0', '已驳回', 'admin', NOW(), 'admin', NOW(), 0); -- 12. 监区类型 (prison_area_type) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2019, '监区类型', 'prison_area_type', '0', '监区类型', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (201901, 1, '普通监区', '1', 'primary', '', 'prison_area_type', '0', '普通管理监区', 'admin', NOW(), 'admin', NOW(), 0), (201902, 2, '严管监区', '2', 'danger', '', 'prison_area_type', '0', '严格管理监区', 'admin', NOW(), 'admin', NOW(), 0), (201903, 3, '医院', '3', 'success', '', 'prison_area_type', '0', '监狱医院', 'admin', NOW(), 'admin', NOW(), 0), -(201904, 4, '禁闭室', '4', 'warning', '', 'prison_area_type', '0', '禁闭室', 'admin', NOW(), 'admin', NOW(), 0); +(201904, 4, '禁闭室', '4', 'warning', '', 'prison_area_type', '0', '禁闭室', 'admin', NOW(), 'admin', NOW(), 0), +(201905, 5, '老残监区', '5', 'info', '', 'prison_area_type', '0', '老弱病残监区', 'admin', NOW(), 'admin', NOW(), 0), +(201906, 6, '女犯监区', '6', 'primary', '', 'prison_area_type', '0', '女性罪犯监区', 'admin', NOW(), 'admin', NOW(), 0), +(201907, 7, '未成年犯监区', '7', 'success', '', 'prison_area_type', '0', '未成年罪犯监区', 'admin', NOW(), 'admin', NOW(), 0), +(201908, 8, '出入监区', '8', 'warning', '', 'prison_area_type', '0', '新收押/释放监区', 'admin', NOW(), 'admin', NOW(), 0), +(201909, 9, '劳动监区', '9', 'primary', '', 'prison_area_type', '0', '劳动改造监区', 'admin', NOW(), 'admin', NOW(), 0), +(201910, 10, '教育监区', '10', 'success', '', 'prison_area_type', '0', '教育改造监区', 'admin', NOW(), 'admin', NOW(), 0); -- 13. 监室状态 (prison_cell_status) -INSERT INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_type (id, name, type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (2020, '监室状态', 'prison_cell_status', '0', '监室状态', 'admin', NOW(), 'admin', NOW(), 0); -INSERT INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) +INSERT IGNORE INTO system_dict_data (id, sort, label, value, color_type, css_class, dict_type, status, remark, creator, create_time, updater, update_time, deleted) VALUES (202001, 1, '启用', '1', 'success', '', 'prison_cell_status', '0', '监室启用', 'admin', NOW(), 'admin', NOW(), 0), (202002, 2, '禁用', '2', 'danger', '', 'prison_cell_status', '0', '监室禁用', 'admin', NOW(), 'admin', NOW(), 0); diff --git a/sql/prison_init.sql b/sql/prison_init.sql index bbb9f57cb2..6c8e4d0e19 100644 --- a/sql/prison_init.sql +++ b/sql/prison_init.sql @@ -19,6 +19,12 @@ CREATE TABLE IF NOT EXISTS `prison_prisoner` ( `crime` varchar(200) NOT NULL COMMENT '罪名', `sentence_years` int DEFAULT 0 COMMENT '刑期(年)', `sentence_months` int DEFAULT 0 COMMENT '刑期(月)', + `life_imprisonment` tinyint DEFAULT 0 COMMENT '是否无期:0-否 1-是', + `death_sentence_reprieve` tinyint DEFAULT 0 COMMENT '是否死缓:0-否 1-是', + `court_name` varchar(100) DEFAULT NULL COMMENT '判决法院', + `judgment_date` date DEFAULT NULL COMMENT '判决日期', + `judgment_no` varchar(50) DEFAULT NULL COMMENT '判决书编号', + `original_sentence` varchar(100) DEFAULT NULL COMMENT '原判刑期', `imprisonment_date` date DEFAULT NULL COMMENT '入狱日期', `release_date` date DEFAULT NULL COMMENT '释放日期', `supervision_level` tinyint DEFAULT 2 COMMENT '监管等级:1-严管 2-普管 3-宽管', @@ -226,3 +232,30 @@ CREATE TABLE IF NOT EXISTS `prison_questionnaire_record` ( KEY `idx_questionnaire_id` (`questionnaire_id`), KEY `idx_prisoner_id` (`prisoner_id`) ) ENGINE=InnoDB COMMENT='问卷答题记录表'; + +-- 罪犯监区变动记录表 +CREATE TABLE IF NOT EXISTS `prison_prisoner_area_log` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + `prisoner_id` bigint NOT NULL COMMENT '罪犯ID', + `from_area_id` bigint DEFAULT NULL COMMENT '原监区ID', + `from_cell_id` bigint DEFAULT NULL COMMENT '原监室ID', + `to_area_id` bigint NOT NULL COMMENT '新监区ID', + `to_cell_id` bigint NOT NULL COMMENT '新监室ID', + `change_type` varchar(20) NOT NULL COMMENT '变动类型:调监区、调监室、入监、出监', + `reason` varchar(500) DEFAULT NULL COMMENT '变动原因', + `approve_no` varchar(50) DEFAULT NULL COMMENT '批准文号', + `operate_by` bigint NOT NULL COMMENT '操作人ID', + `operate_name` varchar(50) DEFAULT NULL COMMENT '操作人姓名', + `operate_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`), + KEY `idx_prisoner_id` (`prisoner_id`), + KEY `idx_operate_time` (`operate_time`) +) ENGINE=InnoDB COMMENT='罪犯监区变动记录表'; + + diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/PrisonAreaController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/PrisonAreaController.java index 736b93546b..ed12e49940 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/PrisonAreaController.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/PrisonAreaController.java @@ -101,4 +101,42 @@ public class PrisonAreaController { BeanUtils.toBean(list, AreaRespVO.class)); } + @GetMapping("/tree") + @Operation(summary = "获得监区树形结构") + @PreAuthorize("@ss.hasPermission('prison:area:query')") + public CommonResult> getAreaTree( + @RequestParam(value = "name", required = false) String name, + @RequestParam(value = "type", required = false) Integer type, + @RequestParam(value = "level", required = false) Integer level, + @RequestParam(value = "status", required = false) Integer status) { + List tree = areaService.getAreaTree(name, type, level, status); + return success(BeanUtils.toBean(tree, AreaRespVO.class)); + } + + @GetMapping("/children") + @Operation(summary = "获得子监区列表") + @Parameter(name = "parentId", description = "父级ID", required = true) + @PreAuthorize("@ss.hasPermission('prison:area:query')") + public CommonResult> getChildAreas(@RequestParam("parentId") Long parentId) { + List children = areaService.getChildAreas(parentId); + return success(BeanUtils.toBean(children, AreaRespVO.class)); + } + + @GetMapping("/parent-list") + @Operation(summary = "获得父级监区列表") + @Parameter(name = "level", description = "监区级别", required = false) + @PreAuthorize("@ss.hasPermission('prison:area:query')") + public CommonResult> getParentAreas(@RequestParam(value = "level", required = false) Integer level) { + List parentAreas = areaService.getParentAreas(level); + return success(BeanUtils.toBean(parentAreas, AreaRespVO.class)); + } + + @PostMapping("/sync-current-count") + @Operation(summary = "同步监区当前人数") + @PreAuthorize("@ss.hasPermission('prison:area:update')") + public CommonResult syncCurrentCount(@RequestParam("areaId") Long areaId) { + areaService.syncCurrentCount(areaId); + return success(true); + } + } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaRespVO.java index 24da832f09..bf68ccd666 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaRespVO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaRespVO.java @@ -24,8 +24,16 @@ public class AreaRespVO { @ExcelProperty("监区编码") private String code; - @Schema(description = "监区类型:1-普通监区 2-严管监区 3-医院 4-禁闭室", example = "1") - @ExcelProperty("监区类型:1-普通监区 2-严管监区 3-医院 4-禁闭室") + @Schema(description = "父级ID,0表示顶级监区") + @ExcelProperty("父级ID") + private Long parentId; + + @Schema(description = "级别:1-监区(大队) 2-分监区(中队)") + @ExcelProperty("级别") + private Integer level; + + @Schema(description = "监区类型:1-普通监区 2-严管监区 3-集训监区 4-出监监区 5-医院 6-禁闭室", example = "1") + @ExcelProperty("监区类型") private Integer type; @Schema(description = "容纳人数") @@ -52,4 +60,7 @@ public class AreaRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "子监区列表,仅一级监区返回") + private List children; + } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaSaveReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaSaveReqVO.java index bbd2a2fe57..95909e5eb2 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaSaveReqVO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/area/vo/AreaSaveReqVO.java @@ -20,7 +20,13 @@ public class AreaSaveReqVO { @NotEmpty(message = "监区编码不能为空") private String code; - @Schema(description = "监区类型:1-普通监区 2-严管监区 3-医院 4-禁闭室", example = "1") + @Schema(description = "父级ID,0表示顶级监区") + private Long parentId; + + @Schema(description = "级别:1-监区(大队) 2-分监区(中队)") + private Integer level; + + @Schema(description = "监区类型:1-普通监区 2-严管监区 3-集训监区 4-出监监区 5-医院 6-禁闭室", example = "1") private Integer type; @Schema(description = "容纳人数") diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/PrisonCellController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/PrisonCellController.java index e6d6b83455..97c88f0c5d 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/PrisonCellController.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/PrisonCellController.java @@ -8,12 +8,13 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; -import jakarta.validation.constraints.*; import jakarta.validation.*; import jakarta.servlet.http.*; import java.util.*; import java.io.IOException; +import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; +import cn.iocoder.yudao.module.prison.dal.mysql.area.AreaMapper; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -38,6 +39,9 @@ public class PrisonCellController { @Resource private CellService cellService; + @Resource + private AreaMapper areaMapper; + @PostMapping("/create") @Operation(summary = "创建监室信息") @PreAuthorize("@ss.hasPermission('prison:cell:create')") @@ -77,15 +81,25 @@ public class PrisonCellController { @PreAuthorize("@ss.hasPermission('prison:cell:query')") public CommonResult getCell(@RequestParam("id") Long id) { CellDO cell = cellService.getCell(id); - return success(BeanUtils.toBean(cell, CellRespVO.class)); + if (cell == null) { + return success(null); + } + CellRespVO respVO = BeanUtils.toBean(cell, CellRespVO.class); + // 填充监区名称 + if (cell.getAreaId() != null) { + AreaDO area = areaMapper.selectById(cell.getAreaId()); + if (area != null) { + respVO.setAreaName(area.getName()); + } + } + return success(respVO); } @GetMapping("/page") @Operation(summary = "获得监室信息分页") @PreAuthorize("@ss.hasPermission('prison:cell:query')") public CommonResult> getCellPage(@Valid CellPageReqVO pageReqVO) { - PageResult pageResult = cellService.getCellPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, CellRespVO.class)); + return success(cellService.getCellPage(pageReqVO)); } @GetMapping("/export-excel") @@ -95,10 +109,9 @@ public class PrisonCellController { public void exportCellExcel(@Valid CellPageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = cellService.getCellPage(pageReqVO).getList(); + List list = cellService.getCellPage(pageReqVO).getList(); // 导出 Excel - ExcelUtils.write(response, "监室信息.xls", "数据", CellRespVO.class, - BeanUtils.toBean(list, CellRespVO.class)); + ExcelUtils.write(response, "监室信息.xls", "数据", CellRespVO.class, list); } } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/vo/CellRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/vo/CellRespVO.java index 07b5fe9aff..50d1d82757 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/vo/CellRespVO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/cell/vo/CellRespVO.java @@ -20,6 +20,10 @@ public class CellRespVO { @ExcelProperty("所属监区ID") private Long areaId; + @Schema(description = "所属监区名称", example = "一监区") + @ExcelProperty("所属监区") + private String areaName; + @Schema(description = "监室名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") @ExcelProperty("监室名称") private String name; diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/PrisonDashboardController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/PrisonDashboardController.java new file mode 100644 index 0000000000..07a0d52885 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/PrisonDashboardController.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.prison.controller.admin.dashboard; + +import cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo.DashboardStatisticsVO; +import cn.iocoder.yudao.module.prison.service.dashboard.PrisonDashboardService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 管理后台 - 监管看板 + * + * @author xlcp + */ +@RestController +@RequestMapping("/prison/dashboard") +@Tag(name = "管理后台 - 监管看板") +@RequiredArgsConstructor +public class PrisonDashboardController { + + private final PrisonDashboardService dashboardService; + + @GetMapping("/statistics") + @Operation(summary = "获取看板统计数据") + @PreAuthorize("@ss.hasPermission('prison:dashboard:query')") + public DashboardStatisticsVO getStatistics() { + return dashboardService.getDashboardStatistics(); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ChartDataVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ChartDataVO.java new file mode 100644 index 0000000000..eb6de82ac8 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ChartDataVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "图表数据项") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ChartDataVO { + + @Schema(description = "分组名称", example = "青年(18-30)") + private String name; + + @Schema(description = "数量", example = "100") + private Integer value; + + @Schema(description = "占比", example = "28.5") + private Double percentage; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/DashboardStatisticsVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/DashboardStatisticsVO.java new file mode 100644 index 0000000000..10b84cd78b --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/DashboardStatisticsVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Schema(description = "管理后台 - 监管看板统计 Response VO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DashboardStatisticsVO { + + // ==================== 核心指标卡片 ==================== + + @Schema(description = "在册罪犯总数") + private Integer totalPrisoners; + + @Schema(description = "本月已释放人数") + private Integer monthlyReleased; + + @Schema(description = "本月已移交人数") + private Integer monthlyTransferred; + + @Schema(description = "当前就医人数") + private Integer hospitalCount; + + @Schema(description = "当前禁闭人数") + private Integer solitaryCount; + + // ==================== 图表数据 ==================== + + @Schema(description = "年龄分布") + private List ageDistribution; + + @Schema(description = "刑期分布") + private List sentenceDistribution; + + @Schema(description = "文化程度分布") + private List educationDistribution; + + @Schema(description = "省份分布") + private List provinceDistribution; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ProvinceChartVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ProvinceChartVO.java new file mode 100644 index 0000000000..c3d22bff93 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/dashboard/vo/ProvinceChartVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "省份图表数据") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProvinceChartVO { + + @Schema(description = "省份名称", example = "河南省") + private String province; + + @Schema(description = "省份编码", example = "41") + private Integer provinceCode; + + @Schema(description = "人数", example = "156") + private Integer count; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/PrisonerController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/PrisonerController.java index 34ad70838e..849447044b 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/PrisonerController.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/PrisonerController.java @@ -4,9 +4,16 @@ import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.PrisonerAreaLogRespVO; import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.*; import cn.iocoder.yudao.module.prison.convert.prisoner.PrisonerConvert; +import cn.iocoder.yudao.module.prison.convert.prisonerarealog.PrisonerAreaLogConvert; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.cell.CellDO; +import cn.iocoder.yudao.module.prison.dal.mysql.area.AreaMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.cell.CellMapper; import cn.iocoder.yudao.module.prison.service.PrisonerService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -24,6 +31,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** * 服刑人员信息管理 Controller @@ -39,6 +47,12 @@ public class PrisonerController { @Resource private PrisonerService prisonerService; + @Resource + private AreaMapper areaMapper; + + @Resource + private CellMapper cellMapper; + @PostMapping("/create") @Operation(summary = "新增服刑人员") @PreAuthorize("@ss.hasPermission('prison:prisoner:create')") @@ -76,21 +90,108 @@ public class PrisonerController { @GetMapping("/get") @Operation(summary = "获取服刑人员详情") @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('prison:prisoner:read')") public CommonResult getPrisoner(@RequestParam("id") Long id) { PrisonerDO prisoner = prisonerService.getPrisoner(id); - return success(PrisonerConvert.INSTANCE.convert(prisoner)); + if (prisoner == null) { + return success(null); + } + PrisonerRespVO vo = convertToRespVO(prisoner); + // 设置监区名称 + if (prisoner.getPrisonAreaId() != null) { + cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO area = areaMapper.selectById(prisoner.getPrisonAreaId()); + if (area != null) { + vo.setPrisonAreaName(area.getName()); + } + } + // 设置监室名称 + if (prisoner.getPrisonCellId() != null) { + cn.iocoder.yudao.module.prison.dal.dataobject.cell.CellDO cell = cellMapper.selectById(prisoner.getPrisonCellId()); + if (cell != null) { + vo.setPrisonCellName(cell.getName()); + } + } + return success(vo); + } + + /** + * 将 PrisonerDO 转换为 PrisonerRespVO + */ + private PrisonerRespVO convertToRespVO(PrisonerDO prisoner) { + PrisonerRespVO vo = new PrisonerRespVO(); + vo.setId(prisoner.getId()); + vo.setPrisonerNo(prisoner.getPrisonerNo()); + vo.setName(prisoner.getName()); + vo.setBirthday(prisoner.getBirthday()); + vo.setIdCard(prisoner.getIdCard()); + vo.setEthnicity(prisoner.getEthnicity()); + vo.setNativePlace(prisoner.getNativePlace()); + if (prisoner.getEducation() != null) { + vo.setEducation(prisoner.getEducation().getValue()); + } + vo.setOccupation(prisoner.getOccupation()); + vo.setAddress(prisoner.getAddress()); + vo.setCrime(prisoner.getCrime()); + vo.setSentenceYears(prisoner.getSentenceYears()); + vo.setSentenceMonths(prisoner.getSentenceMonths()); + vo.setLifeImprisonment(prisoner.getLifeImprisonment()); + vo.setDeathSentenceReprieve(prisoner.getDeathSentenceReprieve()); + vo.setCourtName(prisoner.getCourtName()); + vo.setJudgmentDate(prisoner.getJudgmentDate()); + vo.setJudgmentNo(prisoner.getJudgmentNo()); + vo.setOriginalSentence(prisoner.getOriginalSentence()); + vo.setImprisonmentDate(prisoner.getImprisonmentDate()); + vo.setReleaseDate(prisoner.getReleaseDate()); + vo.setReleaseType(prisoner.getReleaseType()); + vo.setReleaseReason(prisoner.getReleaseReason()); + vo.setPhoto(prisoner.getPhoto()); + vo.setPrisonAreaId(prisoner.getPrisonAreaId()); + vo.setPrisonCellId(prisoner.getPrisonCellId()); + if (prisoner.getStatus() != null) { + vo.setStatus(prisoner.getStatus().getValue()); + vo.setStatusName(prisoner.getStatus().getName()); + } + vo.setRemark(prisoner.getRemark()); + vo.setCreateTime(prisoner.getCreateTime() != null ? prisoner.getCreateTime().toString() : null); + + // 设置性别 + if (prisoner.getGender() != null) { + vo.setGender(prisoner.getGender().getValue()); + vo.setGenderName(prisoner.getGender().getName()); + } + + // 设置监管等级 + if (prisoner.getSupervisionLevel() != null) { + vo.setSupervisionLevel(prisoner.getSupervisionLevel().getValue()); + vo.setSupervisionLevelName(prisoner.getSupervisionLevel().getName()); + } + + // 设置风险等级 + if (prisoner.getRiskLevel() != null) { + vo.setRiskLevel(prisoner.getRiskLevel().getValue()); + String[] riskLabels = {"", "低风险", "中风险", "高风险", "极高风险"}; + Integer value = prisoner.getRiskLevel().getValue(); + if (value >= 1 && value <= 4) { + vo.setRiskLevelName(riskLabels[value]); + } else { + vo.setRiskLevelName(prisoner.getRiskLevel().getName()); + } + } + + return vo; } @GetMapping("/page") @Operation(summary = "获取服刑人员分页列表") + @PreAuthorize("@ss.hasPermission('prison:prisoner:read')") public CommonResult> getPrisonerPage(@Valid PrisonerPageReqVO reqVO) { - PageResult pageResult = prisonerService.getPrisonerPage(reqVO); - return success(PrisonerConvert.INSTANCE.convertPage(pageResult)); + return success(prisonerService.getPrisonerPage(reqVO)); } @GetMapping("/get-by-no") @Operation(summary = "根据服刑人员编号获取服刑人员") @Parameter(name = "prisonerNo", description = "服刑人员编号", required = true) + @PreAuthorize("@ss.hasPermission('prison:prisoner:read')") public CommonResult getPrisonerByNo(@RequestParam("prisonerNo") String prisonerNo) { PrisonerDO prisoner = prisonerService.getPrisonerByNo(prisonerNo); return success(PrisonerConvert.INSTANCE.convert(prisoner)); @@ -101,9 +202,37 @@ public class PrisonerController { @ApiAccessLog(operateType = EXPORT) @PreAuthorize("@ss.hasPermission('prison:prisoner:export')") public void exportExcel(HttpServletResponse response, @Valid PrisonerPageReqVO reqVO) throws IOException { - PageResult pageResult = prisonerService.getPrisonerPage(reqVO); - List excelVOs = PrisonerConvert.INSTANCE.convertExcelList(pageResult.getList()); + PageResult pageResult = prisonerService.getPrisonerPage(reqVO); + List excelVOs = PrisonerConvert.INSTANCE.convertExcelListFromRespVO(pageResult.getList()); ExcelUtils.write(response, "服刑人员数据.xls", "服刑人员列表", PrisonerExcelVO.class, excelVOs); } + @PostMapping("/transfer") + @Operation(summary = "调监") + @Parameter(name = "prisonerId", description = "罪犯ID", required = true) + @Parameter(name = "targetCellId", description = "目标监室ID", required = true) + @Parameter(name = "reason", description = "调监原因") + @PreAuthorize("@ss.hasPermission('prison:prisoner:transfer')") + public CommonResult transfer( + @RequestParam("prisonerId") Long prisonerId, + @RequestParam("targetCellId") Long targetCellId, + @RequestParam(value = "reason", required = false) String reason) { + cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.TransferReqVO reqVO = + new cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.TransferReqVO(); + reqVO.setPrisonerId(prisonerId); + reqVO.setTargetCellId(targetCellId); + reqVO.setReason(reason); + prisonerService.doTransfer(reqVO, getLoginUserId()); + return success(true); + } + + @GetMapping("/get-area-history") + @Operation(summary = "获取罪犯位置历史轨迹") + @Parameter(name = "id", description = "罪犯ID", required = true) + @PreAuthorize("@ss.hasPermission('prison:prisoner:query')") + public CommonResult> getAreaHistory(@RequestParam("id") Long id) { + List list = prisonerService.getAreaHistory(id); + return success(PrisonerAreaLogConvert.INSTANCE.convertList(list)); + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/PrisonerAreaLogController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/PrisonerAreaLogController.java new file mode 100644 index 0000000000..800cedd05f --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/PrisonerAreaLogController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.*; +import cn.iocoder.yudao.module.prison.convert.prisonerarealog.PrisonerAreaLogConvert; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; +import cn.iocoder.yudao.module.prison.service.prisonerarealog.PrisonerAreaLogService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 罪犯监区变动记录 Controller + * + * @author xlcp + */ +@Tag(name = "罪犯监区变动记录") +@RestController +@RequestMapping("/prison/prisoner-area-log") +public class PrisonerAreaLogController { + + @Resource + private PrisonerAreaLogService prisonerAreaLogService; + + @PostMapping("/create") + @Operation(summary = "创建罪犯监区变动记录") + @PreAuthorize("@ss.hasPermission('prison:prisoner-area-log:create')") + public CommonResult createPrisonerAreaLog(@Valid @RequestBody PrisonerAreaLogSaveReqVO reqVO) { + return success(prisonerAreaLogService.createPrisonerAreaLog(reqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新罪犯监区变动记录") + @PreAuthorize("@ss.hasPermission('prison:prisoner-area-log:update')") + public CommonResult updatePrisonerAreaLog(@Valid @RequestBody PrisonerAreaLogSaveReqVO reqVO) { + prisonerAreaLogService.updatePrisonerAreaLog(reqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除罪犯监区变动记录") + @Parameter(name = "id", description = "记录ID", required = true) + @PreAuthorize("@ss.hasPermission('prison:prisoner-area-log:delete')") + public CommonResult deletePrisonerAreaLog(@RequestParam("id") Long id) { + prisonerAreaLogService.deletePrisonerAreaLog(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Operation(summary = "批量删除罪犯监区变动记录") + @PreAuthorize("@ss.hasPermission('prison:prisoner-area-log:delete')") + public CommonResult deletePrisonerAreaLogList(@RequestParam("ids") List ids) { + prisonerAreaLogService.deletePrisonerAreaLogList(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获取罪犯监区变动记录") + @Parameter(name = "id", description = "记录ID", required = true) + public CommonResult getPrisonerAreaLog(@RequestParam("id") Long id) { + PrisonerAreaLogDO areaLog = prisonerAreaLogService.getPrisonerAreaLog(id); + if (areaLog == null) { + return success(null); + } + return success(PrisonerAreaLogConvert.INSTANCE.convert(areaLog)); + } + + @GetMapping("/page") + @Operation(summary = "获取罪犯监区变动记录分页列表") + public CommonResult> getPrisonerAreaLogPage(@Valid PrisonerAreaLogPageReqVO reqVO) { + PageResult page = prisonerAreaLogService.getPrisonerAreaLogPage(reqVO); + return success(PrisonerAreaLogConvert.INSTANCE.convertPage(page)); + } + + @GetMapping("/list-by-prisoner-id") + @Operation(summary = "获取罪犯的监区变动记录列表") + @Parameter(name = "prisonerId", description = "罪犯ID", required = true) + public CommonResult> getPrisonerAreaLogListByPrisonerId( + @RequestParam("prisonerId") Long prisonerId) { + List list = prisonerAreaLogService.getPrisonerAreaLogListByPrisonerId(prisonerId); + return success(PrisonerAreaLogConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogPageReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogPageReqVO.java new file mode 100644 index 0000000000..6238c0e5a3 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogPageReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 罪犯监区变动记录分页查询 Request VO + * + * @author xlcp + */ +@Schema(description = "罪犯监区变动记录分页查询") +@Data +@EqualsAndHashCode(callSuper = true) +public class PrisonerAreaLogPageReqVO extends PageParam { + + @Schema(description = "罪犯ID", example = "1") + private Long prisonerId; + + @Schema(description = "罪犯编号", example = "ZF2024001") + private String prisonerNo; + + @Schema(description = "变动类型:1-调入 2-调出 3-临时安置 4-医疗回监 5-初始分配", example = "1") + private Integer changeType; + + @Schema(description = "原监区ID", example = "1") + private Long fromAreaId; + + @Schema(description = "新监区ID", example = "2") + private Long toAreaId; + + @Schema(description = "操作开始时间", example = "2024-01-01") + private LocalDateTime operateTimeStart; + + @Schema(description = "操作结束时间", example = "2024-12-31") + private LocalDateTime operateTimeEnd; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogRespVO.java new file mode 100644 index 0000000000..d433c0778c --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogRespVO.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 罪犯监区变动记录 Response VO + * + * @author xlcp + */ +@Schema(description = "罪犯监区变动记录") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrisonerAreaLogRespVO { + + @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "19443") + private Long id; + + @Schema(description = "罪犯ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long prisonerId; + + @Schema(description = "罪犯编号", example = "ZF2024001") + private String prisonerNo; + + @Schema(description = "罪犯姓名", example = "张三") + private String prisonerName; + + @Schema(description = "原监区ID", example = "1") + private Long fromAreaId; + + @Schema(description = "原监区名称", example = "一监区") + private String fromAreaName; + + @Schema(description = "原分监区ID", example = "1") + private Long fromSubAreaId; + + @Schema(description = "原分监区名称", example = "一分监区") + private String fromSubAreaName; + + @Schema(description = "原监室ID", example = "1") + private Long fromCellId; + + @Schema(description = "原监室名称", example = "101监室") + private String fromCellName; + + @Schema(description = "新监区ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long toAreaId; + + @Schema(description = "新监区名称", example = "二监区") + private String toAreaName; + + @Schema(description = "新分监区ID", example = "2") + private Long toSubAreaId; + + @Schema(description = "新分监区名称", example = "二分监区") + private String toSubAreaName; + + @Schema(description = "新监室ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long toCellId; + + @Schema(description = "新监室名称", example = "201监室") + private String toCellName; + + @Schema(description = "变动类型:1-调入 2-调出 3-临时安置 4-医疗回监 5-初始分配", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer changeType; + + @Schema(description = "变动类型名称", example = "调监") + private String transferTypeName; + + @Schema(description = "变动原因", example = "因表现良好,调换监区") + private String reason; + + @Schema(description = "批准文号", example = "沪狱刑调〔2024〕001号") + private String approveNo; + + @Schema(description = "操作人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long operateBy; + + @Schema(description = "操作人姓名", example = "张警官") + private String operateName; + + @Schema(description = "操作时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-15 10:00:00") + private LocalDateTime operateTime; + + @Schema(description = "创建时间", example = "2024-01-15 10:00:00") + private String createTime; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogSaveReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogSaveReqVO.java new file mode 100644 index 0000000000..07757fb10e --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/arealog/vo/PrisonerAreaLogSaveReqVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * 罪犯监区变动记录创建/更新 Request VO + * + * @author xlcp + */ +@Schema(description = "罪犯监区变动记录创建/更新") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrisonerAreaLogSaveReqVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "罪犯ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "罪犯ID不能为空") + private Long prisonerId; + + @Schema(description = "罪犯编号", example = "ZF2024001") + private String prisonerNo; + + @Schema(description = "原监区ID", example = "1") + private Long fromAreaId; + + @Schema(description = "原监室ID", example = "1") + private Long fromCellId; + + @Schema(description = "新监区ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "新监区ID不能为空") + private Long toAreaId; + + @Schema(description = "新监室ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "新监室ID不能为空") + private Long toCellId; + + @Schema(description = "变动类型:1-调入 2-调出 3-临时安置 4-医疗回监 5-初始分配", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "变动类型不能为空") + private Integer changeType; + + @Schema(description = "变动原因", example = "因表现良好,调换监区") + private String reason; + + @Schema(description = "批准文号", example = "沪狱刑调〔2024〕001号") + private String approveNo; + + @Schema(description = "操作人ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "操作人ID不能为空") + private Long operateBy; + + @Schema(description = "操作人姓名", example = "张警官") + private String operateName; + + @Schema(description = "操作时间", example = "2024-01-15 10:00:00") + private LocalDateTime operateTime; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerExcelVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerExcelVO.java index 8a60f7e6b1..e7b9a37a04 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerExcelVO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerExcelVO.java @@ -28,9 +28,6 @@ public class PrisonerExcelVO { @ExcelProperty("出生日期") private LocalDate birthday; - @ExcelProperty("身份证号") - private String idCard; - @ExcelProperty("民族") private String ethnicity; diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerRespVO.java index d877ccda3b..47c04c8611 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerRespVO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerRespVO.java @@ -61,12 +61,39 @@ public class PrisonerRespVO { @Schema(description = "刑期(月)", example = "6") private Integer sentenceMonths; + @Schema(description = "是否无期:0-否 1-是", example = "0") + private Integer lifeImprisonment; + + @Schema(description = "是否死缓:0-否 1-是", example = "0") + private Integer deathSentenceReprieve; + + @Schema(description = "判决法院", example = "上海市第一中级人民法院") + private String courtName; + + @Schema(description = "判决日期", example = "2023-01-15") + private LocalDate judgmentDate; + + @Schema(description = "判决书编号", example = "(2023)沪01刑初123号") + private String judgmentNo; + + @Schema(description = "原判刑期", example = "有期徒刑10年") + private String originalSentence; + @Schema(description = "入狱日期", example = "2024-01-01") private LocalDate imprisonmentDate; @Schema(description = "释放日期", example = "2027-07-01") private LocalDate releaseDate; + @Schema(description = "释放类型", example = "1") + private Integer releaseType; + + @Schema(description = "释放原因", example = "刑满释放") + private String releaseReason; + + @Schema(description = "照片URL", example = "http://xxx.com/photo.jpg") + private String photo; + @Schema(description = "监管等级", example = "2") private Integer supervisionLevel; diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerSaveReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerSaveReqVO.java index 4fc9c924b7..99dcdbdb19 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerSaveReqVO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/PrisonerSaveReqVO.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.*; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -21,10 +20,12 @@ public class PrisonerSaveReqVO { @Schema(description = "服刑人员编号", example = "ZF2024001") @NotBlank(message = "服刑人员编号不能为空") + @Size(max = 50, message = "服刑人员编号长度不能超过50") private String prisonerNo; @Schema(description = "姓名", example = "张三") @NotBlank(message = "姓名不能为空") + @Size(max = 50, message = "姓名长度不能超过50") private String name; @Schema(description = "性别", example = "1", required = true) @@ -36,33 +37,69 @@ public class PrisonerSaveReqVO { private LocalDate birthday; @Schema(description = "身份证号", example = "310101199001011234") + @Pattern(regexp = "^[0-9]{17}[0-9Xx]$", message = "身份证号格式不正确") private String idCard; @Schema(description = "民族", example = "汉族") + @Size(max = 50, message = "民族长度不能超过50") private String ethnicity; @Schema(description = "籍贯", example = "上海") + @Size(max = 100, message = "籍贯长度不能超过100") private String nativePlace; @Schema(description = "文化程度", example = "3") private Integer education; @Schema(description = "职业", example = "无业") + @Size(max = 100, message = "职业长度不能超过100") private String occupation; @Schema(description = "家庭住址", example = "上海市浦东新区xxx") + @Size(max = 500, message = "家庭住址长度不能超过500") private String address; @Schema(description = "罪名", example = "盗窃罪", required = true) @NotBlank(message = "罪名不能为空") + @Size(max = 100, message = "罪名长度不能超过100") private String crime; @Schema(description = "刑期(年)", example = "3") + @Min(value = 0, message = "刑期(年)不能为负数") + @Max(value = 150, message = "刑期(年)不能超过150") private Integer sentenceYears; @Schema(description = "刑期(月)", example = "6") + @Min(value = 0, message = "刑期(月)不能为负数") + @Max(value = 11, message = "刑期(月)不能超过11") private Integer sentenceMonths; + @Schema(description = "是否无期:0-否 1-是", example = "0") + @Min(value = 0, message = "是否无期值不正确") + @Max(value = 1, message = "是否无期值不正确") + private Integer lifeImprisonment; + + @Schema(description = "是否死缓:0-否 1-是", example = "0") + @Min(value = 0, message = "是否死缓值不正确") + @Max(value = 1, message = "是否死缓值不正确") + private Integer deathSentenceReprieve; + + @Schema(description = "判决法院", example = "上海市第一中级人民法院") + @Size(max = 100, message = "判决法院长度不能超过100") + private String courtName; + + @Schema(description = "判决日期", example = "2023-01-15") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate judgmentDate; + + @Schema(description = "判决书编号", example = "(2023)沪01刑初123号") + @Size(max = 50, message = "判决书编号长度不能超过50") + private String judgmentNo; + + @Schema(description = "原判刑期", example = "有期徒刑10年") + @Size(max = 100, message = "原判刑期长度不能超过100") + private String originalSentence; + @Schema(description = "入狱日期", example = "2024-01-01", required = true) @NotNull(message = "入狱日期不能为空") @DateTimeFormat(pattern = "yyyy-MM-dd") @@ -88,6 +125,7 @@ public class PrisonerSaveReqVO { private Integer status; @Schema(description = "备注", example = "无") + @Size(max = 500, message = "备注长度不能超过500") private String remark; } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/TransferReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/TransferReqVO.java new file mode 100644 index 0000000000..4fcea41ea1 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/prisoner/vo/TransferReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import jakarta.validation.constraints.NotNull; + +/** + * 调监请求 VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TransferReqVO { + + @Schema(description = "罪犯ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "罪犯ID不能为空") + private Long prisonerId; + + @Schema(description = "目标监室ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "目标监室ID不能为空") + private Long targetCellId; + + @Schema(description = "调监原因") + private String reason; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/ReleaseController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/ReleaseController.java new file mode 100644 index 0000000000..2cae686ede --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/ReleaseController.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.prison.controller.admin.release; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.release.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.release.ReleaseDO; +import cn.iocoder.yudao.module.prison.service.release.ReleaseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +/** + * 释放登记 Controller + * + * @author xlcp + */ +@Tag(name = "管理后台 - 释放登记管理") +@RestController +@RequestMapping("/prison/release") +public class ReleaseController { + + @Resource + private ReleaseService releaseService; + + @PostMapping("/create") + @Operation(summary = "创建释放登记") + @PreAuthorize("@ss.hasPermission('prison:release:create')") + public CommonResult createRelease(@Valid @RequestBody ReleaseSaveReqVO createReqVO) { + return success(releaseService.createRelease(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新释放登记") + @PreAuthorize("@ss.hasPermission('prison:release:update')") + public CommonResult updateRelease(@Valid @RequestBody ReleaseSaveReqVO updateReqVO) { + releaseService.updateRelease(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除释放登记") + @PreAuthorize("@ss.hasPermission('prison:release:delete')") + public CommonResult deleteRelease(@RequestParam("id") Long id) { + releaseService.deleteRelease(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Operation(summary = "批量删除释放登记") + @PreAuthorize("@ss.hasPermission('prison:release:delete')") + public CommonResult deleteReleaseList(@RequestParam("ids") List ids) { + releaseService.deleteReleaseListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得释放登记") + @PreAuthorize("@ss.hasPermission('prison:release:query')") + public CommonResult getRelease(@RequestParam("id") Long id) { + ReleaseDO release = releaseService.getRelease(id); + return success(BeanUtils.toBean(release, ReleaseRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得释放登记分页") + @PreAuthorize("@ss.hasPermission('prison:release:query')") + public CommonResult> getReleasePage(@Valid ReleasePageReqVO pageReqVO) { + PageResult pageResult = releaseService.getReleasePage(pageReqVO); + List voList = pageResult.getList().stream() + .map(this::convertToRespVO) + .collect(Collectors.toList()); + return success(new PageResult<>(voList, pageResult.getTotal())); + } + + @PostMapping("/do-release") + @Operation(summary = "执行释放") + @PreAuthorize("@ss.hasPermission('prison:release:update')") + public CommonResult doRelease(@RequestParam("id") Long id) { + releaseService.doRelease(id, getLoginUserId()); + return success(true); + } + + @PostMapping("/cancel-release") + @Operation(summary = "取消释放") + @PreAuthorize("@ss.hasPermission('prison:release:update')") + public CommonResult cancelRelease(@RequestParam("id") Long id) { + releaseService.cancelRelease(id, getLoginUserId()); + return success(true); + } + + private ReleaseRespVO convertToRespVO(ReleaseDO release) { + ReleaseRespVO respVO = BeanUtils.toBean(release, ReleaseRespVO.class); + // 设置释放类型名称 + respVO.setReleaseTypeName(getReleaseTypeName(release.getReleaseType())); + // 设置状态名称 + respVO.setStatusName(getStatusName(release.getStatus())); + return respVO; + } + + private String getReleaseTypeName(Integer releaseType) { + if (releaseType == null) return ""; + return switch (releaseType) { + case 1 -> "刑满释放"; + case 2 -> "假释"; + case 3 -> "暂予监外执行"; + case 4 -> "减刑"; + case 5 -> "法院裁定释放"; + case 6 -> "死亡"; + case 7 -> "其他"; + default -> ""; + }; + } + + private String getStatusName(Integer status) { + if (status == null) return ""; + return switch (status) { + case 1 -> "待释放"; + case 2 -> "已释放"; + case 3 -> "已取消"; + default -> ""; + }; + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleasePageReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleasePageReqVO.java new file mode 100644 index 0000000000..001d7d7879 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleasePageReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.prison.controller.admin.release.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDate; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 释放登记分页查询 Request VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReleasePageReqVO extends PageParam { + + @Schema(description = "罪犯编号") + private String prisonerNo; + + @Schema(description = "罪犯姓名") + private String prisonerName; + + @Schema(description = "释放类型:1-刑满释放 2-假释 3-暂予监外执行 4-减刑 5-法院裁定释放 6-死亡 7-其他") + private Integer releaseType; + + @Schema(description = "状态:1-待释放 2-已释放 3-已取消") + private Integer status; + + @Schema(description = "实际释放日期起") + private LocalDate actualReleaseDateStart; + + @Schema(description = "实际释放日期止") + private LocalDate actualReleaseDateEnd; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseRespVO.java new file mode 100644 index 0000000000..d1505c26fb --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseRespVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.prison.controller.admin.release.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 释放登记 Response VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReleaseRespVO { + + @Schema(description = "记录ID") + private Long id; + + @Schema(description = "罪犯ID") + private Long prisonerId; + + @Schema(description = "罪犯编号") + private String prisonerNo; + + @Schema(description = "罪犯姓名") + private String prisonerName; + + @Schema(description = "释放类型:1-刑满释放 2-假释 3-暂予监外执行 4-减刑 5-法院裁定释放 6-死亡 7-其他") + private Integer releaseType; + + @Schema(description = "释放类型名称") + private String releaseTypeName; + + @Schema(description = "释放原因") + private String releaseReason; + + @Schema(description = "裁定法院(假释/减刑时)") + private String courtName; + + @Schema(description = "裁定书编号") + private String judgmentNo; + + @Schema(description = "实际释放日期") + private LocalDate actualReleaseDate; + + @Schema(description = "交接人") + private String handoverPerson; + + @Schema(description = "交接单位(移交时)") + private String handoverUnit; + + @Schema(description = "证件类型:1-身份证 2-户口簿 3-其他") + private Integer certificateType; + + @Schema(description = "证件号码") + private String certificateNo; + + @Schema(description = "状态:1-待释放 2-已释放 3-已取消") + private Integer status; + + @Schema(description = "状态名称") + private String statusName; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "操作人ID") + private Long operatorId; + + @Schema(description = "操作人姓名") + private String operatorName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseSaveReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseSaveReqVO.java new file mode 100644 index 0000000000..e8871efe87 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/release/vo/ReleaseSaveReqVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.prison.controller.admin.release.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDate; +import jakarta.validation.constraints.NotNull; + +/** + * 释放登记 Save Request VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReleaseSaveReqVO { + + @Schema(description = "记录ID") + private Long id; + + @Schema(description = "罪犯ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "罪犯ID不能为空") + private Long prisonerId; + + @Schema(description = "释放类型:1-刑满释放 2-假释 3-暂予监外执行 4-减刑 5-法院裁定释放 6-死亡 7-其他", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "释放类型不能为空") + private Integer releaseType; + + @Schema(description = "释放原因") + private String releaseReason; + + @Schema(description = "裁定法院(假释/减刑时)") + private String courtName; + + @Schema(description = "裁定书编号") + private String judgmentNo; + + @Schema(description = "实际释放日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "实际释放日期不能为空") + private LocalDate actualReleaseDate; + + @Schema(description = "交接人") + private String handoverPerson; + + @Schema(description = "交接单位(移交时)") + private String handoverUnit; + + @Schema(description = "证件类型:1-身份证 2-户口簿 3-其他") + private Integer certificateType; + + @Schema(description = "证件号码") + private String certificateNo; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/ScoreDetailController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/ScoreDetailController.java new file mode 100644 index 0000000000..3e8cbda573 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/ScoreDetailController.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerecord; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.scorerecord.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerecord.ScoreDetailDO; +import cn.iocoder.yudao.module.prison.service.scorerecord.ScoreDetailService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 考核记录明细 Controller + * + * @author xlcp + */ +@Tag(name = "管理后台 - 考核记录明细") +@RestController +@RequestMapping("/prison/score-detail") +public class ScoreDetailController { + + @Resource + private ScoreDetailService scoreDetailService; + + @PostMapping("/create") + @Operation(summary = "创建考核记录") + @PreAuthorize("@ss.hasPermission('prison:score-detail:create')") + public CommonResult createScoreDetail(@Valid @RequestBody ScoreDetailSaveReqVO createReqVO) { + return success(scoreDetailService.createScoreDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新考核记录") + @PreAuthorize("@ss.hasPermission('prison:score-detail:update')") + public CommonResult updateScoreDetail(@Valid @RequestBody ScoreDetailSaveReqVO updateReqVO) { + scoreDetailService.updateScoreDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除考核记录") + @PreAuthorize("@ss.hasPermission('prison:score-detail:delete')") + public CommonResult deleteScoreDetail(@RequestParam("id") Long id) { + scoreDetailService.deleteScoreDetail(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Operation(summary = "批量删除考核记录") + @PreAuthorize("@ss.hasPermission('prison:score-detail:delete')") + public CommonResult deleteScoreDetailList(@RequestParam("ids") List ids) { + scoreDetailService.deleteScoreDetailListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得考核记录") + @PreAuthorize("@ss.hasPermission('prison:score-detail:query')") + public CommonResult getScoreDetail(@RequestParam("id") Long id) { + ScoreDetailDO scoreDetail = scoreDetailService.getScoreDetail(id); + return success(BeanUtils.toBean(scoreDetail, ScoreDetailRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得考核记录分页") + @PreAuthorize("@ss.hasPermission('prison:score-detail:query')") + public CommonResult> getScoreDetailPage(@Valid ScoreDetailPageReqVO pageReqVO) { + PageResult pageResult = scoreDetailService.getScoreDetailPage(pageReqVO); + List list = pageResult.getList().stream() + .map(item -> BeanUtils.toBean(item, ScoreDetailRespVO.class)) + .collect(Collectors.toList()); + return success(new PageResult<>(list, pageResult.getTotal())); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailPageReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailPageReqVO.java new file mode 100644 index 0000000000..cf7a32b4db --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailPageReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.time.LocalDate; + +/** + * 考核记录明细分页查询 Request VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreDetailPageReqVO extends PageParam { + + @Schema(description = "罪犯编号") + private String prisonerNo; + + @Schema(description = "罪犯ID") + private Long prisonerId; + + @Schema(description = "记录日期起") + private LocalDate recordDateStart; + + @Schema(description = "记录日期止") + private LocalDate recordDateEnd; + + @Schema(description = "类型:1-加分 2-扣分") + private Integer scoreType; + + @Schema(description = "规则ID") + private Long ruleId; + + @Schema(description = "状态:1-有效 2-作废") + private Integer status; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailRespVO.java new file mode 100644 index 0000000000..c8779735b1 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailRespVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 考核记录明细 Response VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreDetailRespVO { + + @Schema(description = "记录ID") + private Long id; + + @Schema(description = "罪犯ID") + private Long prisonerId; + + @Schema(description = "罪犯编号") + private String prisonerNo; + + @Schema(description = "记录日期") + private LocalDate recordDate; + + @Schema(description = "规则ID") + private Long ruleId; + + @Schema(description = "规则名称") + private String ruleName; + + @Schema(description = "得分") + private BigDecimal score; + + @Schema(description = "类型:1-加分 2-扣分") + private Integer scoreType; + + @Schema(description = "类型名称") + private String scoreTypeName; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "记录人ID") + private Long recorderId; + + @Schema(description = "记录人姓名") + private String recorderName; + + @Schema(description = "状态:1-有效 2-作废") + private Integer status; + + @Schema(description = "状态名称") + private String statusName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailSaveReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailSaveReqVO.java new file mode 100644 index 0000000000..4396d8c40b --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerecord/vo/ScoreDetailSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * 考核记录明细 Save Request VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreDetailSaveReqVO { + + @Schema(description = "记录ID") + private Long id; + + @Schema(description = "罪犯ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "罪犯ID不能为空") + private Long prisonerId; + + @Schema(description = "记录日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "记录日期不能为空") + private LocalDate recordDate; + + @Schema(description = "规则ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "规则ID不能为空") + private Long ruleId; + + @Schema(description = "得分", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "得分不能为空") + private BigDecimal score; + + @Schema(description = "类型:1-加分 2-扣分", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "类型不能为空") + private Integer scoreType; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/ScoreRuleController.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/ScoreRuleController.java new file mode 100644 index 0000000000..b29c391e2e --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/ScoreRuleController.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerule; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.scorerule.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerule.ScoreRuleDO; +import cn.iocoder.yudao.module.prison.service.scorerule.ScoreRuleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * 考核规则配置 Controller + * + * @author xlcp + */ +@Tag(name = "管理后台 - 考核规则配置") +@RestController +@RequestMapping("/prison/score-rule") +public class ScoreRuleController { + + @Resource + private ScoreRuleService scoreRuleService; + + @PostMapping("/create") + @Operation(summary = "创建考核规则") + @PreAuthorize("@ss.hasPermission('prison:score-rule:create')") + public CommonResult createScoreRule(@Valid @RequestBody ScoreRuleSaveReqVO createReqVO) { + return success(scoreRuleService.createScoreRule(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新考核规则") + @PreAuthorize("@ss.hasPermission('prison:score-rule:update')") + public CommonResult updateScoreRule(@Valid @RequestBody ScoreRuleSaveReqVO updateReqVO) { + scoreRuleService.updateScoreRule(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除考核规则") + @PreAuthorize("@ss.hasPermission('prison:score-rule:delete')") + public CommonResult deleteScoreRule(@RequestParam("id") Long id) { + scoreRuleService.deleteScoreRule(id); + return success(true); + } + + @DeleteMapping("/delete-list") + @Operation(summary = "批量删除考核规则") + @PreAuthorize("@ss.hasPermission('prison:score-rule:delete')") + public CommonResult deleteScoreRuleList(@RequestParam("ids") List ids) { + scoreRuleService.deleteScoreRuleListByIds(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得考核规则") + @PreAuthorize("@ss.hasPermission('prison:score-rule:query')") + public CommonResult getScoreRule(@RequestParam("id") Long id) { + ScoreRuleDO scoreRule = scoreRuleService.getScoreRule(id); + return success(BeanUtils.toBean(scoreRule, ScoreRuleRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得考核规则分页") + @PreAuthorize("@ss.hasPermission('prison:score-rule:query')") + public CommonResult> getScoreRulePage(@Valid ScoreRulePageReqVO pageReqVO) { + PageResult pageResult = scoreRuleService.getScoreRulePage(pageReqVO); + List list = pageResult.getList().stream() + .map(item -> BeanUtils.toBean(item, ScoreRuleRespVO.class)) + .collect(Collectors.toList()); + return success(new PageResult<>(list, pageResult.getTotal())); + } + + @GetMapping("/list-by-category") + @Operation(summary = "根据类别获取考核规则列表") + @PreAuthorize("@ss.hasPermission('prison:score-rule:query')") + public CommonResult> getScoreRuleListByCategory( + @RequestParam("category") Integer category) { + List list = scoreRuleService.getScoreRuleListByCategory(category); + return success(list.stream() + .map(item -> BeanUtils.toBean(item, ScoreRuleRespVO.class)) + .collect(Collectors.toList())); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRulePageReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRulePageReqVO.java new file mode 100644 index 0000000000..1c0fd70aed --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRulePageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerule.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 考核规则配置分页查询 Request VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreRulePageReqVO extends PageParam { + + @Schema(description = "类别:1-劳动改造 2-教育改造 3-日常行为 4-卫生纪律 5-加分项 6-扣分项") + private Integer category; + + @Schema(description = "项目名称") + private String itemName; + + @Schema(description = "项目编码") + private String itemCode; + + @Schema(description = "状态:1-启用 2-禁用") + private Integer status; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleRespVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleRespVO.java new file mode 100644 index 0000000000..bfd7034183 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleRespVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerule.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 考核规则配置 Response VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreRuleRespVO { + + @Schema(description = "规则ID") + private Long id; + + @Schema(description = "类别:1-劳动改造 2-教育改造 3-日常行为 4-卫生纪律 5-加分项 6-扣分项") + private Integer category; + + @Schema(description = "类别名称") + private String categoryName; + + @Schema(description = "项目名称") + private String itemName; + + @Schema(description = "项目编码") + private String itemCode; + + @Schema(description = "分值") + private BigDecimal score; + + @Schema(description = "日最高分限制") + private BigDecimal maxDailyScore; + + @Schema(description = "月最高分限制") + private BigDecimal maxMonthlyScore; + + @Schema(description = "规则说明") + private String description; + + @Schema(description = "状态:1-启用 2-禁用") + private Integer status; + + @Schema(description = "状态名称") + private String statusName; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleSaveReqVO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleSaveReqVO.java new file mode 100644 index 0000000000..0115ae6ae9 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/controller/admin/scorerule/vo/ScoreRuleSaveReqVO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.prison.controller.admin.scorerule.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import jakarta.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * 考核规则配置 Save Request VO + * + * @author xlcp + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreRuleSaveReqVO { + + @Schema(description = "规则ID") + private Long id; + + @Schema(description = "类别:1-劳动改造 2-教育改造 3-日常行为 4-卫生纪律 5-加分项 6-扣分项", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "类别不能为空") + private Integer category; + + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "项目名称不能为空") + private String itemName; + + @Schema(description = "项目编码(唯一)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "项目编码不能为空") + private String itemCode; + + @Schema(description = "分值(加分正数,扣分负数)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "分值不能为空") + private BigDecimal score; + + @Schema(description = "日最高分限制") + private BigDecimal maxDailyScore; + + @Schema(description = "月最高分限制") + private BigDecimal maxMonthlyScore; + + @Schema(description = "规则说明") + private String description; + + @Schema(description = "状态:1-启用 2-禁用") + private Integer status; + + @Schema(description = "排序") + private Integer sort; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/area/AreaConvert.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/area/AreaConvert.java new file mode 100644 index 0000000000..397290bfdf --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/area/AreaConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.prison.convert.area; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.prison.controller.admin.area.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 监区信息 Convert + * + * @author xlcp + */ +@Mapper +public interface AreaConvert { + + AreaConvert INSTANCE = Mappers.getMapper(AreaConvert.class); + + AreaDO convert(AreaSaveReqVO bean); + + AreaRespVO convert(AreaDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisoner/PrisonerConvert.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisoner/PrisonerConvert.java index 3283f87166..6e36752a5e 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisoner/PrisonerConvert.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisoner/PrisonerConvert.java @@ -3,7 +3,14 @@ package cn.iocoder.yudao.module.prison.convert.prisoner; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.*; import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.enums.GenderEnum; +import cn.iocoder.yudao.module.prison.enums.SupervisionLevelEnum; +import cn.iocoder.yudao.module.prison.enums.PrisonerStatusEnum; +import cn.iocoder.yudao.module.prison.enums.RiskLevelEnum; +import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; import org.mapstruct.factory.Mappers; import java.util.List; @@ -18,8 +25,33 @@ public interface PrisonerConvert { PrisonerConvert INSTANCE = Mappers.getMapper(PrisonerConvert.class); + @Mapping(target = "gender", source = "gender", qualifiedByName = "IntegerToGenderEnum") + @Mapping(target = "supervisionLevel", source = "supervisionLevel", qualifiedByName = "IntegerToSupervisionLevelEnum") + @Mapping(target = "riskLevel", source = "riskLevel", qualifiedByName = "IntegerToRiskLevelEnum") + @Mapping(target = "status", source = "status", qualifiedByName = "IntegerToPrisonerStatusEnum") PrisonerDO convert(PrisonerSaveReqVO bean); + // 自定义映射方法:将 Integer 转换为枚举类型 + @Named("IntegerToGenderEnum") + default GenderEnum intToGender(Integer value) { + return value != null ? GenderEnum.fromValue(value) : null; + } + + @Named("IntegerToSupervisionLevelEnum") + default SupervisionLevelEnum intToSupervisionLevel(Integer value) { + return value != null ? SupervisionLevelEnum.fromValue(value) : null; + } + + @Named("IntegerToRiskLevelEnum") + default RiskLevelEnum intToRiskLevel(Integer value) { + return value != null ? RiskLevelEnum.fromValue(value) : null; + } + + @Named("IntegerToPrisonerStatusEnum") + default PrisonerStatusEnum intToStatus(Integer value) { + return value != null ? PrisonerStatusEnum.fromValue(value) : null; + } + PrisonerRespVO convert(PrisonerDO bean); List convertList(List list); @@ -28,4 +60,44 @@ public interface PrisonerConvert { List convertExcelList(List list); + List convertExcelListFromRespVO(List list); + + @AfterMapping + default void afterConvert(PrisonerDO source, PrisonerRespVO target) { + // 设置性别 + if (source.getGender() != null) { + target.setGender(source.getGender().getValue()); + target.setGenderName(source.getGender().getName()); + } + // 设置监管等级 + if (source.getSupervisionLevel() != null) { + target.setSupervisionLevel(source.getSupervisionLevel().getValue()); + target.setSupervisionLevelName(source.getSupervisionLevel().getName()); + } + // 设置风险等级 + if (source.getRiskLevel() != null) { + target.setRiskLevel(source.getRiskLevel().getValue()); + // 风险等级标签 + String[] riskLabels = {"", "低风险", "中风险", "高风险", "极高风险"}; + Integer value = source.getRiskLevel().getValue(); + if (value >= 1 && value <= 4) { + target.setRiskLevelName(riskLabels[value]); + } + } + // 设置状态 + if (source.getStatus() != null) { + target.setStatus(source.getStatus().getValue()); + target.setStatusName(source.getStatus().getName()); + } + } + + @AfterMapping + default void afterConvertPage(PageResult page, PageResult result) { + if (page.getList() != null) { + for (int i = 0; i < page.getList().size(); i++) { + afterConvert(page.getList().get(i), result.getList().get(i)); + } + } + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisonerarealog/PrisonerAreaLogConvert.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisonerarealog/PrisonerAreaLogConvert.java new file mode 100644 index 0000000000..e68ab0791d --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/convert/prisonerarealog/PrisonerAreaLogConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.prison.convert.prisonerarealog; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 罪犯监区变动记录 Convert + * + * @author xlcp + */ +@Mapper +public interface PrisonerAreaLogConvert { + + PrisonerAreaLogConvert INSTANCE = Mappers.getMapper(PrisonerAreaLogConvert.class); + + PrisonerAreaLogDO convert(PrisonerAreaLogSaveReqVO bean); + + PrisonerAreaLogRespVO convert(PrisonerAreaLogDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerAreaLogDO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerAreaLogDO.java new file mode 100644 index 0000000000..746a1f1d92 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerAreaLogDO.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.prison.dal.dataobject; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 罪犯监区变动记录 DO + * + * @author xlcp + */ +@TableName("prison_prisoner_area_log") +@KeySequence("prison_prisoner_area_log_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrisonerAreaLogDO extends BaseDO { + + /** + * 主键ID + */ + private Long id; + + /** + * 罪犯ID + */ + private Long prisonerId; + + /** + * 罪犯编号 + */ + private String prisonerNo; + + /** + * 原监区ID + */ + private Long fromAreaId; + + /** + * 原分监区ID + */ + private Long fromSubAreaId; + + /** + * 原监室ID + */ + private Long fromCellId; + + /** + * 新监区ID + */ + private Long toAreaId; + + /** + * 新分监区ID + */ + private Long toSubAreaId; + + /** + * 新监室ID + */ + private Long toCellId; + + /** + * 变动类型:1-调入 2-调出 3-临时安置 4-医疗回监 5-初始分配 + */ + private Integer changeType; + + /** + * 变动原因 + */ + private String reason; + + /** + * 批准文号 + */ + private String approveNo; + + /** + * 操作人ID + */ + private Long operateBy; + + /** + * 操作人姓名 + */ + private String operateName; + + /** + * 操作时间 + */ + private LocalDateTime operateTime; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerDO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerDO.java index a174237a60..b07c597ee7 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerDO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/PrisonerDO.java @@ -92,6 +92,36 @@ public class PrisonerDO extends BaseDO { */ private Integer sentenceMonths; + /** + * 是否无期:0-否 1-是 + */ + private Integer lifeImprisonment; + + /** + * 是否死缓:0-否 1-是 + */ + private Integer deathSentenceReprieve; + + /** + * 判决法院 + */ + private String courtName; + + /** + * 判决日期 + */ + private LocalDate judgmentDate; + + /** + * 判决书编号 + */ + private String judgmentNo; + + /** + * 原判刑期 + */ + private String originalSentence; + /** * 入狱日期 */ @@ -102,6 +132,21 @@ public class PrisonerDO extends BaseDO { */ private LocalDate releaseDate; + /** + * 释放类型:1-刑满 2-假释 3-暂予监外执行 4-减刑 5-移交 6-死亡 + */ + private Integer releaseType; + + /** + * 释放原因 + */ + private String releaseReason; + + /** + * 照片URL + */ + private String photo; + /** * 当前监管等级 */ @@ -117,6 +162,11 @@ public class PrisonerDO extends BaseDO { */ private Long prisonAreaId; + /** + * 当前分区ID + */ + private Long subAreaId; + /** * 当前监室ID */ diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/area/AreaDO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/area/AreaDO.java index 509ec76bfc..d98837fac9 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/area/AreaDO.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/area/AreaDO.java @@ -6,6 +6,7 @@ import java.time.LocalDateTime; import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.*; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableField; /** * 监区信息 DO @@ -36,9 +37,17 @@ public class AreaDO extends BaseDO { */ private String code; /** - * 监区类型:1-普通监区 2-严管监区 3-医院 4-禁闭室 + * 监区类型:1-普通监区 2-严管监区 3-集训监区 4-出监监区 5-医院 6-禁闭室 */ private Integer type; + /** + * 父级ID,0表示顶级监区 + */ + private Long parentId; + /** + * 级别:1-监区(大队) 2-分监区(中队) + */ + private Integer level; /** * 容纳人数 */ @@ -60,5 +69,11 @@ public class AreaDO extends BaseDO { */ private String remark; + /** + * 子监区列表(非数据库字段) + */ + @TableField(exist = false) + private List children; + } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/release/ReleaseDO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/release/ReleaseDO.java new file mode 100644 index 0000000000..3411a8ab0c --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/release/ReleaseDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.prison.dal.dataobject.release; + +import lombok.*; +import java.util.*; +import java.time.LocalDate; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 释放登记记录 DO + * + * @author xlcp + */ +@TableName("prison_prisoner_release") +@KeySequence("prison_prisoner_release_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReleaseDO extends BaseDO { + + /** + * 记录ID + */ + @TableId + private Long id; + /** + * 罪犯ID + */ + private Long prisonerId; + /** + * 罪犯编号 + */ + private String prisonerNo; + /** + * 罪犯姓名 + */ + private String prisonerName; + /** + * 释放类型:1-刑满释放 2-假释 3-暂予监外执行 4-减刑 5-法院裁定释放 6-死亡 7-其他 + */ + private Integer releaseType; + /** + * 释放原因 + */ + private String releaseReason; + /** + * 裁定法院(假释/减刑时) + */ + private String courtName; + /** + * 裁定书编号 + */ + private String judgmentNo; + /** + * 实际释放日期 + */ + private LocalDate actualReleaseDate; + /** + * 交接人 + */ + private String handoverPerson; + /** + * 交接单位(移交时) + */ + private String handoverUnit; + /** + * 证件类型:1-身份证 2-户口簿 3-其他 + */ + private Integer certificateType; + /** + * 证件号码 + */ + private String certificateNo; + /** + * 状态:1-待释放 2-已释放 3-已取消 + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 操作人ID + */ + private Long operatorId; + /** + * 操作人姓名 + */ + private String operatorName; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerecord/ScoreDetailDO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerecord/ScoreDetailDO.java new file mode 100644 index 0000000000..6990d6a0da --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerecord/ScoreDetailDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.prison.dal.dataobject.scorerecord; + +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import java.time.LocalDate; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 考核记录明细 DO + * + * @author xlcp + */ +@TableName("prison_score_detail") +@KeySequence("prison_score_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreDetailDO extends BaseDO { + + /** + * 记录ID + */ + @TableId + private Long id; + /** + * 罪犯ID + */ + private Long prisonerId; + /** + * 罪犯编号 + */ + private String prisonerNo; + /** + * 记录日期 + */ + private LocalDate recordDate; + /** + * 规则ID + */ + private Long ruleId; + /** + * 得分 + */ + private BigDecimal score; + /** + * 类型:1-加分 2-扣分 + */ + private Integer scoreType; + /** + * 备注 + */ + private String remark; + /** + * 记录人ID + */ + private Long recorderId; + /** + * 记录人姓名 + */ + private String recorderName; + /** + * 状态:1-有效 2-作废 + */ + private Integer status; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerule/ScoreRuleDO.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerule/ScoreRuleDO.java new file mode 100644 index 0000000000..8d7e02ff5b --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/dataobject/scorerule/ScoreRuleDO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.prison.dal.dataobject.scorerule; + +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 考核规则配置 DO + * + * @author xlcp + */ +@TableName("prison_score_rule") +@KeySequence("prison_score_rule_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ScoreRuleDO extends BaseDO { + + /** + * 规则ID + */ + @TableId + private Long id; + /** + * 类别:1-劳动改造 2-教育改造 3-日常行为 4-卫生纪律 5-加分项 6-扣分项 + */ + private Integer category; + /** + * 项目名称 + */ + private String itemName; + /** + * 项目编码(唯一) + */ + private String itemCode; + /** + * 分值(加分正数,扣分负数) + */ + private BigDecimal score; + /** + * 日最高分限制 + */ + private BigDecimal maxDailyScore; + /** + * 月最高分限制 + */ + private BigDecimal maxMonthlyScore; + /** + * 规则说明 + */ + private String description; + /** + * 状态:1-启用 2-禁用 + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerAreaLogMapper.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerAreaLogMapper.java new file mode 100644 index 0000000000..7263ddc556 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerAreaLogMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.prison.dal.mysql; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 罪犯监区变动记录 Mapper + * + * @author xlcp + */ +@Mapper +public interface PrisonerAreaLogMapper extends BaseMapperX { + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerMapper.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerMapper.java index 17b1cca3a5..20b8239f2d 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerMapper.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/PrisonerMapper.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.prison.dal.mysql; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; /** * 服刑人员信息 Mapper @@ -12,4 +13,20 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface PrisonerMapper extends BaseMapperX { + /** + * 统计某监区(含子监区)下的罪犯数量 + * + * @param areaId 监区ID + * @return 罪犯数量 + */ + Integer countByAreaIdOrChildren(@Param("areaId") Long areaId); + + /** + * 统计直接属于某监区的罪犯数量(不含子监区) + * + * @param areaId 监区ID + * @return 罪犯数量 + */ + Integer countByDirectAreaId(@Param("areaId") Long areaId); + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/dashboard/PrisonDashboardMapper.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/dashboard/PrisonDashboardMapper.java new file mode 100644 index 0000000000..66d215f911 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/dashboard/PrisonDashboardMapper.java @@ -0,0 +1,170 @@ +package cn.iocoder.yudao.module.prison.dal.mysql.dashboard; + +import cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo.ChartDataVO; +import cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo.ProvinceChartVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 监管看板 Mapper + * + * @author xlcp + */ +@Mapper +public interface PrisonDashboardMapper { + + /** + * 查询核心指标卡片数据 + * + * @return 包含 totalPrisoners, hospitalCount, solitaryCount 的对象 + */ + @Select(""" + SELECT + COALESCE(SUM(CASE WHEN p.status = 1 THEN 1 ELSE 0 END), 0) AS total_prisoners, + COALESCE(SUM(CASE WHEN pa.type = 5 THEN 1 ELSE 0 END), 0) AS hospital_count, + COALESCE(SUM(CASE WHEN pa.type = 6 THEN 1 ELSE 0 END), 0) AS solitary_count + FROM prison_prisoner p + LEFT JOIN prison_area pa ON p.prison_area_id = pa.id + WHERE p.deleted = 0 + """) + DashboardCardVO selectDashboardCards(); + + /** + * 查询本月释放人数 + * status=1 表示已释放 + */ + @Select(""" + SELECT COUNT(*) FROM prison_prisoner_release + WHERE deleted = 0 + AND DATE_FORMAT(actual_release_date, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') + AND status = 1 + """) + Integer selectMonthlyReleased(); + + /** + * 查询本月移交人数 + * change_type: 1-调入 2-调出 + */ + @Select(""" + SELECT COUNT(*) FROM prison_prisoner_area_log + WHERE deleted = 0 + AND change_type IN (1, 2) + AND DATE_FORMAT(operate_time, '%Y-%m') = DATE_FORMAT(CURDATE(), '%Y-%m') + """) + Integer selectMonthlyTransferred(); + + /** + * 查询年龄分布 + */ + @Select(""" + SELECT name, COUNT(*) AS value + FROM ( + SELECT + CASE + WHEN TIMESTAMPDIFF(YEAR, p.birthday, CURDATE()) < 18 THEN '未成年(≤17)' + WHEN TIMESTAMPDIFF(YEAR, p.birthday, CURDATE()) BETWEEN 18 AND 30 THEN '青年(18-30)' + WHEN TIMESTAMPDIFF(YEAR, p.birthday, CURDATE()) BETWEEN 31 AND 50 THEN '中年(31-50)' + WHEN TIMESTAMPDIFF(YEAR, p.birthday, CURDATE()) BETWEEN 51 AND 60 THEN '中老年(51-60)' + ELSE '老龄(60+)' + END AS name + FROM prison_prisoner p + WHERE p.status = 1 AND p.deleted = 0 AND p.birthday IS NOT NULL + ) AS age_data + GROUP BY name + """) + List selectAgeDistribution(); + + /** + * 查询刑期分布 + */ + @Select(""" + SELECT name, COUNT(*) AS value + FROM ( + SELECT + CASE + WHEN p.death_sentence_reprieve = 1 THEN '死缓' + WHEN p.life_imprisonment = 1 THEN '无期' + WHEN (COALESCE(p.sentence_years, 0) * 12 + COALESCE(p.sentence_months, 0)) <= 36 THEN '短刑(≤3年)' + WHEN (COALESCE(p.sentence_years, 0) * 12 + COALESCE(p.sentence_months, 0)) BETWEEN 37 AND 120 THEN '中刑(3-10年)' + ELSE '长刑(10年以上)' + END AS name + FROM prison_prisoner p + WHERE p.status = 1 AND p.deleted = 0 + ) AS sentence_data + GROUP BY name + """) + List selectSentenceDistribution(); + + /** + * 查询文化程度分布 + */ + @Select(""" + SELECT + CASE p.education + WHEN 1 THEN '文盲' + WHEN 2 THEN '小学' + WHEN 3 THEN '初中' + WHEN 4 THEN '高中' + WHEN 5 THEN '中专' + WHEN 6 THEN '大专' + WHEN 7 THEN '本科' + WHEN 8 THEN '研究生及以上' + ELSE '未知' + END AS name, + COUNT(*) AS value + FROM prison_prisoner p + WHERE p.status = 1 AND p.deleted = 0 + GROUP BY p.education + """) + List selectEducationDistribution(); + + /** + * 查询省份分布(原始数据,包含编码) + */ + @Select(""" + SELECT + LEFT(p.native_place, 2) AS province_code, + COUNT(*) AS count + FROM prison_prisoner p + WHERE p.status = 1 AND p.deleted = 0 AND p.native_place IS NOT NULL + GROUP BY LEFT(p.native_place, 2) + """) + List selectProvinceDistributionRaw(); + + /** + * 内部类:核心卡片数据 + */ + class DashboardCardVO { + private Integer totalPrisoners; + private Integer hospitalCount; + private Integer solitaryCount; + + public Integer getTotalPrisoners() { + return totalPrisoners; + } + + public void setTotalPrisoners(Integer totalPrisoners) { + this.totalPrisoners = totalPrisoners; + } + + public Integer getHospitalCount() { + return hospitalCount; + } + + public void setHospitalCount(Integer hospitalCount) { + this.hospitalCount = hospitalCount; + } + + public Integer getSolitaryCount() { + return solitaryCount; + } + + public void setSolitaryCount(Integer solitaryCount) { + this.solitaryCount = solitaryCount; + } + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/release/ReleaseMapper.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/release/ReleaseMapper.java new file mode 100644 index 0000000000..5889ed9800 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/release/ReleaseMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.prison.dal.mysql.release; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.prison.dal.dataobject.release.ReleaseDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 释放登记记录 Mapper + * + * @author xlcp + */ +@Mapper +public interface ReleaseMapper extends BaseMapperX { + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerecord/ScoreDetailMapper.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerecord/ScoreDetailMapper.java new file mode 100644 index 0000000000..e557a3cb00 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerecord/ScoreDetailMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.prison.dal.mysql.scorerecord; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerecord.ScoreDetailDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 考核记录明细 Mapper + * + * @author xlcp + */ +@Mapper +public interface ScoreDetailMapper extends BaseMapperX { + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerule/ScoreRuleMapper.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerule/ScoreRuleMapper.java new file mode 100644 index 0000000000..75066028d5 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/dal/mysql/scorerule/ScoreRuleMapper.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.prison.dal.mysql.scorerule; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerule.ScoreRuleDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 考核规则配置 Mapper + * + * @author xlcp + */ +@Mapper +public interface ScoreRuleMapper extends BaseMapperX { + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaChangeTypeEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaChangeTypeEnum.java new file mode 100644 index 0000000000..eb125bdd35 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaChangeTypeEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.prison.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 监区变动类型枚举 + * + * @author xlcp + */ +@Getter +@AllArgsConstructor +public enum AreaChangeTypeEnum { + + TRANSFER_IN(1, "调入"), + TRANSFER_OUT(2, "调出"), + TEMPORARY_PLACEMENT(3, "临时安置"), + RETURN_FROM_MEDICAL(4, "医疗回监"), + INITIAL_ALLOCATION(5, "初始分配"); + + @EnumValue + @JsonValue + private final Integer value; + private final String name; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaTypeEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaTypeEnum.java new file mode 100644 index 0000000000..09d20c1996 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/AreaTypeEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.prison.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 监区类型枚举 + * + * @author xlcp + */ +@Getter +@AllArgsConstructor +public enum AreaTypeEnum { + + NORMAL(1, "普通监区"), + STRICT(2, "严管监区"), + TRAINING(3, "集训监区"), + RELEASE(4, "出监监区"), + HOSPITAL(5, "医院"), + SOLITARY(6, "禁闭室"); + + @EnumValue + @JsonValue + private final Integer value; + private final String name; + + public static AreaTypeEnum fromValue(Integer value) { + return Arrays.stream(values()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/CellStatusEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/CellStatusEnum.java new file mode 100644 index 0000000000..15c01f1758 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/CellStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.prison.enums; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 监室状态枚举 + * + * @author xlcp + */ +@Getter +@AllArgsConstructor +public enum CellStatusEnum implements ArrayValuable { + + ENABLE(1, "启用"), + DISABLE(2, "禁用"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(CellStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/DictTypeConstants.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/DictTypeConstants.java index 3a55c38494..ec4f9db6b6 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/DictTypeConstants.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/DictTypeConstants.java @@ -12,4 +12,18 @@ public interface DictTypeConstants { String PRISONER_STATUS = "prisoner_status"; // 服刑人员状态 String PRISON_EDUCATION = "prison_education"; // 文化程度 + // 监区相关 + String PRISON_AREA_LEVEL = "prison_area_level"; // 监区级别 + String PRISON_AREA_TYPE = "prison_area_type"; // 监区类型 + + // 监室相关 + String PRISON_CELL_STATUS = "prison_cell_status"; // 监室状态 + + // 释放相关 + String PRISON_RELEASE_TYPE = "prison_release_type"; // 释放类型 + String PRISON_AREA_CHANGE_TYPE = "prison_area_change_type"; // 变动类型 + + // 考核相关 + String PRISON_SCORE_CATEGORY = "prison_score_category"; // 考核类别 + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/EducationEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/EducationEnum.java index aa3265b65b..2a140d2d98 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/EducationEnum.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/EducationEnum.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.prison.enums; import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; @@ -22,6 +23,7 @@ public enum EducationEnum { BACHELOR_OR_ABOVE(7, "本科及以上"); @EnumValue + @JsonValue private final Integer value; private final String name; diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ErrorCodeConstants.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ErrorCodeConstants.java index a3b5e14868..10d4db8ba5 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ErrorCodeConstants.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ErrorCodeConstants.java @@ -12,6 +12,7 @@ public class ErrorCodeConstants { // ========== 服刑人员信息 1xxxx ========== public static final ErrorCode PRISONER_NOT_EXISTS = new ErrorCode(1_000_001, "服刑人员信息不存在"); public static final ErrorCode PRISONER_NO_EXISTS = new ErrorCode(1_000_002, "服刑人员编号【{0}】已存在"); + public static final ErrorCode PRISONER_DATE_INVALID = new ErrorCode(1_000_003, "释放日期必须晚于入狱日期"); // ========== 监区管理 2xxxx ========== public static final ErrorCode PRISON_AREA_NOT_EXISTS = new ErrorCode(2_000_001, "监区信息不存在"); @@ -35,6 +36,9 @@ public class ErrorCodeConstants { // ========== 消费记录 7xxxx ========== public static final ErrorCode PRISON_CONSUMPTION_NOT_EXISTS = new ErrorCode(7_000_001, "消费记录不存在"); + // ========== 罪犯监区变动记录 8xxxx ========== + public static final ErrorCode PRISONER_AREA_LOG_NOT_EXISTS = new ErrorCode(8_000_001, "罪犯监区变动记录不存在"); + // ========== 别名 (兼容codegen生成的代码) ========== public static final ErrorCode AREA_NOT_EXISTS = PRISON_AREA_NOT_EXISTS; public static final ErrorCode CELL_NOT_EXISTS = PRISON_CELL_NOT_EXISTS; diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/GenderEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/GenderEnum.java index 20d9b2324f..64691d670f 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/GenderEnum.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/GenderEnum.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.prison.enums; import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; + /** * 性别枚举 * @@ -17,7 +20,15 @@ public enum GenderEnum { FEMALE(2, "女"); @EnumValue + @JsonValue private final Integer value; private final String name; + public static GenderEnum fromValue(Integer value) { + return Arrays.stream(values()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnum.java index 35559b12e1..9e8dd12b67 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnum.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnum.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.prison.enums; import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; + /** * 服刑人员状态枚举 * @@ -20,7 +23,15 @@ public enum PrisonerStatusEnum { DECEASED(5, "已死亡"); @EnumValue + @JsonValue private final Integer value; private final String name; + public static PrisonerStatusEnum fromValue(Integer value) { + return Arrays.stream(values()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ReleaseTypeEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ReleaseTypeEnum.java new file mode 100644 index 0000000000..c73416f02f --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/ReleaseTypeEnum.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.prison.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 释放类型枚举 + * + * @author xlcp + */ +@Getter +@AllArgsConstructor +public enum ReleaseTypeEnum { + + COMPLETED(1, "刑满释放"), + PAROLED(2, "假释"), + MEDICAL_RELEASE(3, "保外就医"), + COMMUTATION(4, "减刑"), + OUTSIDE_EXECUTION(5, "暂予监外执行"), + SPECIAL_AMNESTY(6, "特赦"), + DECEASED(7, "死亡"), + OTHER(8, "其他"); + + @EnumValue + @JsonValue + private final Integer value; + private final String name; + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnum.java index be21498e99..6df613ecfd 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnum.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnum.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.prison.enums; import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; + /** * 风险等级枚举 * @@ -18,7 +21,15 @@ public enum RiskLevelEnum { LOW(3, "低风险"); @EnumValue + @JsonValue private final Integer value; private final String name; + public static RiskLevelEnum fromValue(Integer value) { + return Arrays.stream(values()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnum.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnum.java index a0e27a428d..1944034b9b 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnum.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnum.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.prison.enums; import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; + /** * 监管等级枚举 * @@ -18,7 +21,15 @@ public enum SupervisionLevelEnum { RELAXED(3, "宽管级"); @EnumValue + @JsonValue private final Integer value; private final String name; + public static SupervisionLevelEnum fromValue(Integer value) { + return Arrays.stream(values()) + .filter(e -> e.getValue().equals(value)) + .findFirst() + .orElse(null); + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/PrisonerService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/PrisonerService.java index e78e16d68b..565d4313b1 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/PrisonerService.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/PrisonerService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.prison.service; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; import java.util.List; @@ -56,7 +57,7 @@ public interface PrisonerService { * @param reqVO 查询条件 * @return 服刑人员分页列表 */ - PageResult getPrisonerPage(PrisonerPageReqVO reqVO); + PageResult getPrisonerPage(PrisonerPageReqVO reqVO); /** * 根据服刑人员编号获取服刑人员 @@ -66,4 +67,20 @@ public interface PrisonerService { */ PrisonerDO getPrisonerByNo(String prisonerNo); + /** + * 执行调监 + * + * @param reqVO 调监请求 + * @param operatorId 操作人ID + */ + void doTransfer(TransferReqVO reqVO, Long operatorId); + + /** + * 获取罪犯位置历史轨迹 + * + * @param prisonerId 罪犯ID + * @return 位置历史记录列表 + */ + List getAreaHistory(Long prisonerId); + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaService.java index 7906ab9f7c..f5f7180bb7 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaService.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaService.java @@ -14,6 +14,40 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; */ public interface AreaService { + /** + * 获取监区树形结构 + * + * @param name 监区名称(可选) + * @param type 监区类型(可选) + * @param level 监区级别(可选) + * @param status 状态(可选) + * @return 树形结构列表 + */ + List getAreaTree(String name, Integer type, Integer level, Integer status); + + /** + * 获取子监区列表 + * + * @param parentId 父级ID + * @return 子监区列表 + */ + List getChildAreas(Long parentId); + + /** + * 获取父级监区列表(用于新增/编辑时选择) + * + * @param level 监区级别,可选 + * @return 父级监区列表 + */ + List getParentAreas(Integer level); + + /** + * 同步监区人数 + * + * @param areaId 监区ID + */ + void syncCurrentCount(Long areaId); + /** * 创建监区信息 * diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaServiceImpl.java index 4020844ab8..ef0ba9ecd1 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaServiceImpl.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/area/AreaServiceImpl.java @@ -7,6 +7,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; import java.util.*; +import java.util.stream.Collectors; import cn.iocoder.yudao.module.prison.controller.admin.area.vo.*; import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -14,6 +15,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.prison.dal.mysql.area.AreaMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @@ -32,6 +34,9 @@ public class AreaServiceImpl implements AreaService { @Resource private AreaMapper areaMapper; + @Resource + private PrisonerMapper prisonerMapper; + @Override public Long createArea(AreaSaveReqVO createReqVO) { // 插入 @@ -79,7 +84,153 @@ public class AreaServiceImpl implements AreaService { @Override public PageResult getAreaPage(AreaPageReqVO pageReqVO) { - return areaMapper.selectPage(pageReqVO); + PageResult pageResult = areaMapper.selectPage(pageReqVO); + + // 为每个一级监区填充子监区 + List list = pageResult.getList(); + for (AreaDO area : list) { + if (area.getParentId() == null || area.getParentId() == 0) { + // 只为顶级监区查询子监区 + List children = areaMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(AreaDO::getParentId, area.getId()) + .eq(AreaDO::getDeleted, false) + .orderByAsc(AreaDO::getSort)); + area.setChildren(children); + } + } + + return pageResult; + } + + @Override + public List getAreaTree(String name, Integer type, Integer level, Integer status) { + // 构建基础查询条件(不带名称模糊查询,先获取所有数据) + com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper baseWrapper = + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(AreaDO::getDeleted, false) + .eq(type != null, AreaDO::getType, type) + .eq(level != null, AreaDO::getLevel, level) + .eq(status != null, AreaDO::getStatus, status) + .orderByAsc(AreaDO::getSort); + + // 获取所有监区(先不过滤名称) + List allAreas = areaMapper.selectList(baseWrapper); + + // 如果有名称过滤,先获取匹配的节点ID + if (name != null && !name.isEmpty()) { + Set finalMatchedIds = allAreas.stream() + .filter(area -> area.getName() != null && area.getName().contains(name)) + .map(AreaDO::getId) + .collect(Collectors.toSet()); + + // 递归获取所有父节点ID(确保树结构完整) + Set parentIds = new java.util.HashSet<>(); + Set toFind = new java.util.HashSet<>(finalMatchedIds); + while (!toFind.isEmpty()) { + Set nextToFind = new java.util.HashSet<>(); + for (Long id : toFind) { + for (AreaDO area : allAreas) { + if (area.getId().equals(id) && area.getParentId() != null && area.getParentId() != 0) { + if (!finalMatchedIds.contains(area.getParentId())) { + parentIds.add(area.getParentId()); + nextToFind.add(area.getParentId()); + } + } + } + } + toFind = nextToFind; + } + + // 合并匹配的节点和父节点 + finalMatchedIds.addAll(parentIds); + final Set filterIds = finalMatchedIds; + + // 过滤只保留匹配的节点和父节点 + allAreas = allAreas.stream() + .filter(area -> filterIds.contains(area.getId())) + .collect(Collectors.toList()); + } + + // 构建树形结构 + // 1. 找出所有顶级节点(parentId 为空或为 0 或 parentId 不在列表中) + Set allIds = allAreas.stream().map(AreaDO::getId).collect(Collectors.toSet()); + List rootAreas = allAreas.stream() + .filter(area -> area.getParentId() == null || area.getParentId() == 0 || !allIds.contains(area.getParentId())) + .collect(Collectors.toList()); + + // 2. 递归构建子树 + for (AreaDO root : rootAreas) { + buildChildrenRecursive(root, allAreas); + } + + return rootAreas; + } + + /** + * 递归构建子节点 + */ + private void buildChildrenRecursive(AreaDO parent, List allAreas) { + List children = allAreas.stream() + .filter(area -> parent.getId().equals(area.getParentId())) + .collect(Collectors.toList()); + + for (AreaDO child : children) { + buildChildrenRecursive(child, allAreas); + } + + // 使用反射设置 children 属性 + try { + java.lang.reflect.Method method = AreaDO.class.getMethod("setChildren", List.class); + method.invoke(parent, children); + } catch (Exception e) { + // 如果没有 children 方法,忽略 + } + } + + @Override + public List getChildAreas(Long parentId) { + return areaMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(AreaDO::getParentId, parentId) + .eq(AreaDO::getDeleted, false) + .orderByAsc(AreaDO::getSort)); + } + + @Override + public List getParentAreas(Integer level) { + com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper queryWrapper = + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(AreaDO::getDeleted, false) + .eq(level != null, AreaDO::getLevel, level) + .orderByAsc(AreaDO::getSort); + return areaMapper.selectList(queryWrapper); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void syncCurrentCount(Long areaId) { + // 查询当前监区信息 + AreaDO area = areaMapper.selectById(areaId); + if (area == null) { + return; + } + + // 递归同步所有子监区并统计人数 + List children = getChildAreas(areaId); + int totalCount = 0; + for (AreaDO child : children) { + syncCurrentCount(child.getId()); + totalCount += child.getCurrentCount() != null ? child.getCurrentCount() : 0; + } + + // 统计当前监区本身的罪犯数量(不含子监区,只统计直接属于当前监区的罪犯) + Integer directCount = prisonerMapper.countByDirectAreaId(areaId); + totalCount += directCount; + + // 更新监区当前人数 + AreaDO updateArea = new AreaDO(); + updateArea.setId(areaId); + updateArea.setCurrentCount(totalCount); + areaMapper.updateById(updateArea); } } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellService.java index 13fb7f0ac7..2b44b9176e 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellService.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellService.java @@ -57,6 +57,6 @@ public interface CellService { * @param pageReqVO 分页查询 * @return 监室信息分页 */ - PageResult getCellPage(CellPageReqVO pageReqVO); + PageResult getCellPage(CellPageReqVO pageReqVO); } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellServiceImpl.java index d97d1f34f8..8b70b19d7f 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellServiceImpl.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/cell/CellServiceImpl.java @@ -7,17 +7,20 @@ import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + import cn.iocoder.yudao.module.prison.controller.admin.cell.vo.*; import cn.iocoder.yudao.module.prison.dal.dataobject.cell.CellDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; +import cn.iocoder.yudao.module.prison.dal.mysql.cell.CellMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.area.AreaMapper; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; - -import cn.iocoder.yudao.module.prison.dal.mysql.cell.CellMapper; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; import static cn.iocoder.yudao.module.prison.enums.ErrorCodeConstants.*; /** @@ -32,6 +35,9 @@ public class CellServiceImpl implements CellService { @Resource private CellMapper cellMapper; + @Resource + private AreaMapper areaMapper; + @Override public Long createCell(CellSaveReqVO createReqVO) { // 插入 @@ -78,8 +84,47 @@ public class CellServiceImpl implements CellService { } @Override - public PageResult getCellPage(CellPageReqVO pageReqVO) { - return cellMapper.selectPage(pageReqVO); + public PageResult getCellPage(CellPageReqVO pageReqVO) { + // 查询监室分页数据 + PageResult pageResult = cellMapper.selectPage(pageReqVO, new LambdaQueryWrapperX() + .eqIfPresent(CellDO::getAreaId, pageReqVO.getAreaId()) + .likeIfPresent(CellDO::getName, pageReqVO.getName()) + .eqIfPresent(CellDO::getCode, pageReqVO.getCode()) + .eqIfPresent(CellDO::getStatus, pageReqVO.getStatus()) + .orderByDesc(CellDO::getId)); + + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + + // 收集所有监区ID + Set areaIds = pageResult.getList().stream() + .map(CellDO::getAreaId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + // 查询监区信息 + final Map areaMap; + if (CollUtil.isNotEmpty(areaIds)) { + List areas = areaMapper.selectList(new LambdaQueryWrapperX() + .inIfPresent(AreaDO::getId, new ArrayList<>(areaIds))); + areaMap = areas.stream() + .collect(Collectors.toMap(AreaDO::getId, Function.identity())); + } else { + areaMap = new HashMap<>(); + } + + // 转换为 RespVO,填充监区名称 + List respList = pageResult.getList().stream().map(cell -> { + CellRespVO respVO = BeanUtils.toBean(cell, CellRespVO.class); + // 设置监区名称 + if (cell.getAreaId() != null && areaMap.containsKey(cell.getAreaId())) { + respVO.setAreaName(areaMap.get(cell.getAreaId()).getName()); + } + return respVO; + }).collect(Collectors.toList()); + + return new PageResult<>(respList, pageResult.getTotal()); } } \ No newline at end of file diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/PrisonDashboardService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/PrisonDashboardService.java new file mode 100644 index 0000000000..3e2ff7b23e --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/PrisonDashboardService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.prison.service.dashboard; + +import cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo.DashboardStatisticsVO; + +/** + * 监管看板 Service 接口 + * + * @author xlcp + */ +public interface PrisonDashboardService { + + /** + * 获取看板统计数据 + * + * @return 看板统计数据 + */ + DashboardStatisticsVO getDashboardStatistics(); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/impl/PrisonDashboardServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/impl/PrisonDashboardServiceImpl.java new file mode 100644 index 0000000000..82b718d972 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/dashboard/impl/PrisonDashboardServiceImpl.java @@ -0,0 +1,137 @@ +package cn.iocoder.yudao.module.prison.service.dashboard.impl; + +import cn.iocoder.yudao.module.prison.controller.admin.dashboard.vo.*; +import cn.iocoder.yudao.module.prison.dal.mysql.dashboard.PrisonDashboardMapper; +import cn.iocoder.yudao.module.prison.service.dashboard.PrisonDashboardService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Map; + +/** + * 监管看板 Service 实现 + * + * @author xlcp + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class PrisonDashboardServiceImpl implements PrisonDashboardService { + + private final PrisonDashboardMapper dashboardMapper; + + private static final String CACHE_KEY = "prison:dashboard:statistics"; + + @Override + @Cacheable(value = CACHE_KEY, key = "'all'", unless = "#result == null") + public DashboardStatisticsVO getDashboardStatistics() { + DashboardStatisticsVO vo = new DashboardStatisticsVO(); + + // 核心指标卡片数据 + PrisonDashboardMapper.DashboardCardVO cards = dashboardMapper.selectDashboardCards(); + vo.setTotalPrisoners(cards.getTotalPrisoners()); + vo.setHospitalCount(cards.getHospitalCount()); + vo.setSolitaryCount(cards.getSolitaryCount()); + vo.setMonthlyReleased(dashboardMapper.selectMonthlyReleased()); + vo.setMonthlyTransferred(dashboardMapper.selectMonthlyTransferred()); + + // 图表数据 + vo.setAgeDistribution(dashboardMapper.selectAgeDistribution()); + vo.setSentenceDistribution(dashboardMapper.selectSentenceDistribution()); + vo.setEducationDistribution(dashboardMapper.selectEducationDistribution()); + vo.setProvinceDistribution(convertProvinceData(dashboardMapper.selectProvinceDistributionRaw())); + + // 计算百分比 + calculatePercentages(vo.getAgeDistribution()); + calculatePercentages(vo.getSentenceDistribution()); + calculatePercentages(vo.getEducationDistribution()); + + return vo; + } + + /** + * 计算图表数据的百分比 + */ + private void calculatePercentages(List dataList) { + if (dataList == null || dataList.isEmpty()) { + return; + } + int total = dataList.stream() + .mapToInt(ChartDataVO::getValue) + .sum(); + for (ChartDataVO item : dataList) { + if (total > 0) { + double percentage = item.getValue() * 100.0 / total; + item.setPercentage(new BigDecimal(percentage).setScale(1, RoundingMode.HALF_UP).doubleValue()); + } else { + item.setPercentage(0.0); + } + } + } + + /** + * 转换省份数据,将编码转换为名称 + */ + private List convertProvinceData(List rawData) { + return rawData.stream() + .map(item -> ProvinceChartVO.builder() + .province(getProvinceName(item.getProvinceCode())) + .provinceCode(item.getProvinceCode()) + .count(item.getCount()) + .build()) + .toList(); + } + + /** + * 根据省份编码获取省份名称 + * 部分常见省份编码映射 + */ + private String getProvinceName(Integer provinceCode) { + if (provinceCode == null) { + return "未知"; + } + Map provinceMap = Map.ofEntries( + Map.entry(11, "北京"), + Map.entry(12, "天津"), + Map.entry(13, "河北"), + Map.entry(14, "山西"), + Map.entry(15, "内蒙古"), + Map.entry(21, "辽宁"), + Map.entry(22, "吉林"), + Map.entry(23, "黑龙江"), + Map.entry(31, "上海"), + Map.entry(32, "江苏"), + Map.entry(33, "浙江"), + Map.entry(34, "安徽"), + Map.entry(35, "福建"), + Map.entry(36, "江西"), + Map.entry(37, "山东"), + Map.entry(41, "河南"), + Map.entry(42, "湖北"), + Map.entry(43, "湖南"), + Map.entry(44, "广东"), + Map.entry(45, "广西"), + Map.entry(46, "海南"), + Map.entry(50, "重庆"), + Map.entry(51, "四川"), + Map.entry(52, "贵州"), + Map.entry(53, "云南"), + Map.entry(54, "西藏"), + Map.entry(61, "陕西"), + Map.entry(62, "甘肃"), + Map.entry(63, "青海"), + Map.entry(64, "宁夏"), + Map.entry(65, "新疆"), + Map.entry(71, "台湾"), + Map.entry(81, "香港"), + Map.entry(82, "澳门") + ); + return provinceMap.getOrDefault(provinceCode, "未知"); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/PrisonerServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/PrisonerServiceImpl.java index c14c3ea21a..48b6d13022 100644 --- a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/PrisonerServiceImpl.java +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/PrisonerServiceImpl.java @@ -2,10 +2,21 @@ package cn.iocoder.yudao.module.prison.service.impl; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.*; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.PrisonerPageReqVO; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.PrisonerRespVO; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.PrisonerSaveReqVO; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.TransferReqVO; import cn.iocoder.yudao.module.prison.convert.prisoner.PrisonerConvert; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.cell.CellDO; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerAreaLogMapper; import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.area.AreaMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.cell.CellMapper; +import cn.iocoder.yudao.module.prison.enums.AreaTypeEnum; +import cn.iocoder.yudao.module.prison.enums.SupervisionLevelEnum; import cn.iocoder.yudao.module.prison.service.PrisonerService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import jakarta.annotation.Resource; @@ -13,6 +24,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -30,6 +42,15 @@ public class PrisonerServiceImpl implements PrisonerService { @Resource private PrisonerMapper prisonerMapper; + @Resource + private PrisonerAreaLogMapper areaLogMapper; + + @Resource + private CellMapper cellMapper; + + @Resource + private AreaMapper areaMapper; + @Override @Transactional(rollbackFor = Exception.class) public Long createPrisoner(PrisonerSaveReqVO reqVO) { @@ -39,12 +60,26 @@ public class PrisonerServiceImpl implements PrisonerService { throw exception(PRISONER_NO_EXISTS, reqVO.getPrisonerNo()); } + // 校验日期:释放日期必须晚于入狱日期 + validatePrisonerDates(reqVO.getImprisonmentDate(), reqVO.getReleaseDate()); + // 插入 PrisonerDO prisoner = PrisonerConvert.INSTANCE.convert(reqVO); prisonerMapper.insert(prisoner); return prisoner.getId(); } + /** + * 校验服刑人员日期 + * @param imprisonmentDate 入狱日期 + * @param releaseDate 释放日期(可为空) + */ + private void validatePrisonerDates(java.time.LocalDate imprisonmentDate, java.time.LocalDate releaseDate) { + if (imprisonmentDate != null && releaseDate != null && releaseDate.isBefore(imprisonmentDate)) { + throw exception(PRISONER_DATE_INVALID); + } + } + @Override @Transactional(rollbackFor = Exception.class) public void updatePrisoner(PrisonerSaveReqVO reqVO) { @@ -60,6 +95,9 @@ public class PrisonerServiceImpl implements PrisonerService { throw exception(PRISONER_NO_EXISTS, reqVO.getPrisonerNo()); } + // 校验日期:释放日期必须晚于入狱日期 + validatePrisonerDates(reqVO.getImprisonmentDate(), reqVO.getReleaseDate()); + // 更新 PrisonerDO updateObj = PrisonerConvert.INSTANCE.convert(reqVO); prisonerMapper.updateById(updateObj); @@ -97,7 +135,7 @@ public class PrisonerServiceImpl implements PrisonerService { } @Override - public PageResult getPrisonerPage(PrisonerPageReqVO reqVO) { + public PageResult getPrisonerPage(PrisonerPageReqVO reqVO) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.like(reqVO.getPrisonerNo() != null, PrisonerDO::getPrisonerNo, reqVO.getPrisonerNo()) .like(reqVO.getName() != null, PrisonerDO::getName, reqVO.getName()) @@ -111,7 +149,100 @@ public class PrisonerServiceImpl implements PrisonerService { .eq(reqVO.getStatus() != null, PrisonerDO::getStatus, reqVO.getStatus()) .ge(reqVO.getImprisonmentDateStart() != null, PrisonerDO::getImprisonmentDate, reqVO.getImprisonmentDateStart()) .le(reqVO.getImprisonmentDateEnd() != null, PrisonerDO::getImprisonmentDate, reqVO.getImprisonmentDateEnd()); - return prisonerMapper.selectPage(reqVO, wrapper); + PageResult pageResult = prisonerMapper.selectPage(reqVO, wrapper); + + // 转换为 VO 并设置关联字段 + PageResult voPageResult = new PageResult<>(); + voPageResult.setTotal(pageResult.getTotal()); + + if (CollUtil.isNotEmpty(pageResult.getList())) { + for (PrisonerDO prisoner : pageResult.getList()) { + PrisonerRespVO vo = new PrisonerRespVO(); + // 基本字段复制 + vo.setId(prisoner.getId()); + vo.setPrisonerNo(prisoner.getPrisonerNo()); + vo.setName(prisoner.getName()); + vo.setBirthday(prisoner.getBirthday()); + vo.setIdCard(prisoner.getIdCard()); + vo.setEthnicity(prisoner.getEthnicity()); + vo.setNativePlace(prisoner.getNativePlace()); + vo.setEducation(prisoner.getEducation() != null ? prisoner.getEducation().getValue() : null); + vo.setOccupation(prisoner.getOccupation()); + vo.setAddress(prisoner.getAddress()); + vo.setCrime(prisoner.getCrime()); + vo.setSentenceYears(prisoner.getSentenceYears()); + vo.setSentenceMonths(prisoner.getSentenceMonths()); + vo.setLifeImprisonment(prisoner.getLifeImprisonment()); + vo.setDeathSentenceReprieve(prisoner.getDeathSentenceReprieve()); + vo.setCourtName(prisoner.getCourtName()); + vo.setJudgmentDate(prisoner.getJudgmentDate()); + vo.setJudgmentNo(prisoner.getJudgmentNo()); + vo.setOriginalSentence(prisoner.getOriginalSentence()); + vo.setImprisonmentDate(prisoner.getImprisonmentDate()); + vo.setReleaseDate(prisoner.getReleaseDate()); + vo.setReleaseType(prisoner.getReleaseType()); + vo.setReleaseReason(prisoner.getReleaseReason()); + vo.setPhoto(prisoner.getPhoto()); + vo.setPrisonAreaId(prisoner.getPrisonAreaId()); + vo.setPrisonCellId(prisoner.getPrisonCellId()); + vo.setStatus(prisoner.getStatus() != null ? prisoner.getStatus().getValue() : null); + vo.setRemark(prisoner.getRemark()); + vo.setCreateTime(prisoner.getCreateTime() != null ? prisoner.getCreateTime().toString() : null); + + // 设置性别 + if (prisoner.getGender() != null) { + vo.setGender(prisoner.getGender().getValue()); + vo.setGenderName(prisoner.getGender().getName()); + } + + // 设置监管等级 + if (prisoner.getSupervisionLevel() != null) { + vo.setSupervisionLevel(prisoner.getSupervisionLevel().getValue()); + vo.setSupervisionLevelName(prisoner.getSupervisionLevel().getName()); + } + + // 设置风险等级 + if (prisoner.getRiskLevel() != null) { + vo.setRiskLevel(prisoner.getRiskLevel().getValue()); + // 风险等级标签 + String[] riskLabels = {"", "低风险", "中风险", "高风险", "极高风险"}; + Integer value = prisoner.getRiskLevel().getValue(); + if (value >= 1 && value <= 4) { + vo.setRiskLevelName(riskLabels[value]); + } else { + vo.setRiskLevelName(prisoner.getRiskLevel().getName()); + } + } + + // 设置状态 + if (prisoner.getStatus() != null) { + vo.setStatusName(prisoner.getStatus().getName()); + } + + // 设置监区名称 + if (prisoner.getPrisonAreaId() != null) { + AreaDO area = areaMapper.selectById(prisoner.getPrisonAreaId()); + if (area != null) { + vo.setPrisonAreaName(area.getName()); + } + } + + // 设置监室名称 + if (prisoner.getPrisonCellId() != null) { + CellDO cell = cellMapper.selectById(prisoner.getPrisonCellId()); + if (cell != null) { + vo.setPrisonCellName(cell.getName()); + } + } + + if (voPageResult.getList() == null) { + voPageResult.setList(new java.util.ArrayList<>()); + } + voPageResult.getList().add(vo); + } + } + + return voPageResult; } @Override @@ -120,4 +251,75 @@ public class PrisonerServiceImpl implements PrisonerService { .eq(PrisonerDO::getPrisonerNo, prisonerNo)); } + @Override + @Transactional(rollbackFor = Exception.class) + public void doTransfer(TransferReqVO reqVO, Long operatorId) { + // 1. 校验罪犯是否存在 + PrisonerDO prisoner = getPrisoner(reqVO.getPrisonerId()); + if (prisoner == null) { + throw exception(PRISONER_NOT_EXISTS); + } + + // 2. 校验目标监室是否存在 + CellDO targetCell = cellMapper.selectById(reqVO.getTargetCellId()); + if (targetCell == null) { + throw new IllegalArgumentException("目标监室不存在"); + } + + // 3. 校验目标监室是否启用 + if (targetCell.getStatus() != 1) { + throw new IllegalArgumentException("目标监室已禁用"); + } + + // 4. 校验床位是否已满 + if (targetCell.getCurrentCount() >= targetCell.getCapacity()) { + throw new IllegalArgumentException("目标监室床位已满"); + } + + // 5. 校验严管犯不能调入普通监区 + if (prisoner.getSupervisionLevel() == SupervisionLevelEnum.STRICT + && targetCell.getAreaId() != null) { + AreaDO targetArea = areaMapper.selectById(targetCell.getAreaId()); + if (targetArea != null && targetArea.getType() != null + && targetArea.getType() != AreaTypeEnum.STRICT.getValue()) { + throw new IllegalArgumentException("严管级罪犯不能调入普通监区"); + } + } + + // 6. 校验是否在同一监室 + if (prisoner.getPrisonCellId().equals(reqVO.getTargetCellId())) { + throw new IllegalArgumentException("目标监室与当前监室相同,无需调监"); + } + + // 7. 记录原位置 + Long oldAreaId = prisoner.getPrisonAreaId(); + Long oldCellId = prisoner.getPrisonCellId(); + + // 8. 更新罪犯位置 + prisoner.setPrisonAreaId(targetCell.getAreaId()); + prisoner.setPrisonCellId(reqVO.getTargetCellId()); + prisonerMapper.updateById(prisoner); + + // 9. 记录变动日志 + PrisonerAreaLogDO log = new PrisonerAreaLogDO(); + log.setPrisonerId(prisoner.getId()); + log.setPrisonerNo(prisoner.getPrisonerNo()); + log.setFromAreaId(oldAreaId); + log.setFromCellId(oldCellId); + log.setToAreaId(targetCell.getAreaId()); + log.setToCellId(reqVO.getTargetCellId()); + log.setChangeType(2); // 调监 + log.setReason(reqVO.getReason()); + log.setOperateBy(operatorId); + log.setOperateTime(LocalDateTime.now()); + areaLogMapper.insert(log); + } + + @Override + public List getAreaHistory(Long prisonerId) { + return areaLogMapper.selectList(new LambdaQueryWrapper() + .eq(PrisonerAreaLogDO::getPrisonerId, prisonerId) + .orderByDesc(PrisonerAreaLogDO::getOperateTime)); + } + } diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/prisonerarealog/PrisonerAreaLogServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/prisonerarealog/PrisonerAreaLogServiceImpl.java new file mode 100644 index 0000000000..8c381d5c15 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/impl/prisonerarealog/PrisonerAreaLogServiceImpl.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.prison.service.impl.prisonerarealog; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.*; +import cn.iocoder.yudao.module.prison.convert.prisonerarealog.PrisonerAreaLogConvert; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerAreaLogMapper; +import cn.iocoder.yudao.module.prison.service.prisonerarealog.PrisonerAreaLogService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.prison.enums.ErrorCodeConstants.*; + +/** + * 罪犯监区变动记录 Service 实现类 + * + * @author xlcp + */ +@Service +@Validated +public class PrisonerAreaLogServiceImpl implements PrisonerAreaLogService { + + @Resource + private PrisonerAreaLogMapper prisonerAreaLogMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPrisonerAreaLog(PrisonerAreaLogSaveReqVO reqVO) { + // 插入 + PrisonerAreaLogDO areaLog = PrisonerAreaLogConvert.INSTANCE.convert(reqVO); + prisonerAreaLogMapper.insert(areaLog); + return areaLog.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePrisonerAreaLog(PrisonerAreaLogSaveReqVO reqVO) { + // 校验存在 + PrisonerAreaLogDO areaLog = getPrisonerAreaLog(reqVO.getId()); + if (areaLog == null) { + throw exception(PRISONER_AREA_LOG_NOT_EXISTS); + } + + // 更新 + PrisonerAreaLogDO updateObj = PrisonerAreaLogConvert.INSTANCE.convert(reqVO); + prisonerAreaLogMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePrisonerAreaLog(Long id) { + // 校验存在 + PrisonerAreaLogDO areaLog = getPrisonerAreaLog(id); + if (areaLog == null) { + throw exception(PRISONER_AREA_LOG_NOT_EXISTS); + } + + // 删除 + prisonerAreaLogMapper.deleteById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePrisonerAreaLogList(List ids) { + // 校验存在 + List areaLogs = prisonerAreaLogMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(areaLogs)) { + throw exception(PRISONER_AREA_LOG_NOT_EXISTS); + } + + // 删除 + prisonerAreaLogMapper.deleteBatchIds(ids); + } + + @Override + public PrisonerAreaLogDO getPrisonerAreaLog(Long id) { + return prisonerAreaLogMapper.selectById(id); + } + + @Override + public PageResult getPrisonerAreaLogPage(PrisonerAreaLogPageReqVO reqVO) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(reqVO.getPrisonerId() != null, PrisonerAreaLogDO::getPrisonerId, reqVO.getPrisonerId()) + .eq(reqVO.getChangeType() != null, PrisonerAreaLogDO::getChangeType, reqVO.getChangeType()) + .eq(reqVO.getFromAreaId() != null, PrisonerAreaLogDO::getFromAreaId, reqVO.getFromAreaId()) + .eq(reqVO.getToAreaId() != null, PrisonerAreaLogDO::getToAreaId, reqVO.getToAreaId()) + .ge(reqVO.getOperateTimeStart() != null, PrisonerAreaLogDO::getOperateTime, reqVO.getOperateTimeStart()) + .le(reqVO.getOperateTimeEnd() != null, PrisonerAreaLogDO::getOperateTime, reqVO.getOperateTimeEnd()) + .orderByDesc(PrisonerAreaLogDO::getOperateTime); + return prisonerAreaLogMapper.selectPage(reqVO, wrapper); + } + + @Override + public List getPrisonerAreaLogListByPrisonerId(Long prisonerId) { + return prisonerAreaLogMapper.selectList(new LambdaQueryWrapper() + .eq(PrisonerAreaLogDO::getPrisonerId, prisonerId) + .orderByDesc(PrisonerAreaLogDO::getOperateTime)); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/prisonerarealog/PrisonerAreaLogService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/prisonerarealog/PrisonerAreaLogService.java new file mode 100644 index 0000000000..61bfb78905 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/prisonerarealog/PrisonerAreaLogService.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.prison.service.prisonerarealog; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; + +import java.util.List; + +/** + * 罪犯监区变动记录 Service 接口 + * + * @author xlcp + */ +public interface PrisonerAreaLogService { + + /** + * 创建罪犯监区变动记录 + * + * @param reqVO 创建信息 + * @return 记录ID + */ + Long createPrisonerAreaLog(PrisonerAreaLogSaveReqVO reqVO); + + /** + * 更新罪犯监区变动记录 + * + * @param reqVO 更新信息 + */ + void updatePrisonerAreaLog(PrisonerAreaLogSaveReqVO reqVO); + + /** + * 删除罪犯监区变动记录 + * + * @param id 记录ID + */ + void deletePrisonerAreaLog(Long id); + + /** + * 批量删除罪犯监区变动记录 + * + * @param ids 记录ID列表 + */ + void deletePrisonerAreaLogList(List ids); + + /** + * 获取罪犯监区变动记录 + * + * @param id 记录ID + * @return 变动记录 + */ + PrisonerAreaLogDO getPrisonerAreaLog(Long id); + + /** + * 获取罪犯监区变动记录分页列表 + * + * @param reqVO 查询条件 + * @return 变动记录分页列表 + */ + PageResult getPrisonerAreaLogPage(PrisonerAreaLogPageReqVO reqVO); + + /** + * 获取罪犯的监区变动记录列表 + * + * @param prisonerId 罪犯ID + * @return 变动记录列表 + */ + List getPrisonerAreaLogListByPrisonerId(Long prisonerId); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/ReleaseService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/ReleaseService.java new file mode 100644 index 0000000000..f1380c7586 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/ReleaseService.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.prison.service.release; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.prison.controller.admin.release.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.release.ReleaseDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 释放登记 Service 接口 + * + * @author xlcp + */ +public interface ReleaseService { + + /** + * 创建释放登记 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRelease(@Valid ReleaseSaveReqVO createReqVO); + + /** + * 更新释放登记 + * + * @param updateReqVO 更新信息 + */ + void updateRelease(@Valid ReleaseSaveReqVO updateReqVO); + + /** + * 删除释放登记 + * + * @param id 编号 + */ + void deleteRelease(Long id); + + /** + * 批量删除释放登记 + * + * @param ids 编号 + */ + void deleteReleaseListByIds(List ids); + + /** + * 获得释放登记 + * + * @param id 编号 + * @return 释放登记 + */ + ReleaseDO getRelease(Long id); + + /** + * 获得释放登记分页 + * + * @param pageReqVO 分页查询 + * @return 释放登记分页 + */ + PageResult getReleasePage(ReleasePageReqVO pageReqVO); + + /** + * 执行释放 + * + * @param id 编号 + * @param operatorId 操作人ID + */ + void doRelease(Long id, Long operatorId); + + /** + * 取消释放 + * + * @param id 编号 + * @param operatorId 操作人ID + */ + void cancelRelease(Long id, Long operatorId); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/impl/ReleaseServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/impl/ReleaseServiceImpl.java new file mode 100644 index 0000000000..9f9b2e2bbc --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/release/impl/ReleaseServiceImpl.java @@ -0,0 +1,194 @@ +package cn.iocoder.yudao.module.prison.service.release.impl; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.PrisonerAreaLogSaveReqVO; +import cn.iocoder.yudao.module.prison.controller.admin.release.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.release.ReleaseDO; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerAreaLogMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.release.ReleaseMapper; +import cn.iocoder.yudao.module.prison.enums.PrisonerStatusEnum; +import cn.iocoder.yudao.module.prison.service.release.ReleaseService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; +import java.util.List; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 释放登记 Service 实现类 + * + * @author xlcp + */ +@Service +@Validated +public class ReleaseServiceImpl implements ReleaseService { + + @Resource + private ReleaseMapper releaseMapper; + + @Resource + private PrisonerMapper prisonerMapper; + + @Resource + private PrisonerAreaLogMapper areaLogMapper; + + private static final int STATUS_PENDING = 1; // 待释放 + private static final int STATUS_RELEASED = 2; // 已释放 + private static final int STATUS_CANCELLED = 3; // 已取消 + + @Override + @Transactional + public Long createRelease(ReleaseSaveReqVO createReqVO) { + // 获取罪犯信息 + PrisonerDO prisoner = prisonerMapper.selectById(createReqVO.getPrisonerId()); + if (prisoner == null) { + throw new IllegalArgumentException("罪犯不存在"); + } + + // 保存释放登记记录 + ReleaseDO release = BeanUtils.toBean(createReqVO, ReleaseDO.class); + release.setPrisonerNo(prisoner.getPrisonerNo()); + release.setPrisonerName(prisoner.getName()); + release.setStatus(STATUS_PENDING); + releaseMapper.insert(release); + + return release.getId(); + } + + @Override + @Transactional + public void updateRelease(ReleaseSaveReqVO updateReqVO) { + ReleaseDO existing = releaseMapper.selectById(updateReqVO.getId()); + if (existing == null) { + throw new IllegalArgumentException("释放登记记录不存在"); + } + + // 只能更新待释放状态的记录 + if (!existing.getStatus().equals(STATUS_PENDING)) { + throw new IllegalArgumentException("只能更新待释放状态的记录"); + } + + ReleaseDO updateObj = BeanUtils.toBean(updateReqVO, ReleaseDO.class); + releaseMapper.updateById(updateObj); + } + + @Override + @Transactional + public void deleteRelease(Long id) { + ReleaseDO release = releaseMapper.selectById(id); + if (release == null) { + throw new IllegalArgumentException("释放登记记录不存在"); + } + + // 只能删除待释放状态的记录 + if (!release.getStatus().equals(STATUS_PENDING)) { + throw new IllegalArgumentException("只能删除待释放状态的记录"); + } + + releaseMapper.deleteById(id); + } + + @Override + public void deleteReleaseListByIds(List ids) { + releaseMapper.deleteBatchIds(ids); + } + + @Override + public ReleaseDO getRelease(Long id) { + return releaseMapper.selectById(id); + } + + @Override + public PageResult getReleasePage(ReleasePageReqVO pageReqVO) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.like(pageReqVO.getPrisonerNo() != null, ReleaseDO::getPrisonerNo, pageReqVO.getPrisonerNo()); + wrapper.like(pageReqVO.getPrisonerName() != null, ReleaseDO::getPrisonerName, pageReqVO.getPrisonerName()); + wrapper.eq(pageReqVO.getReleaseType() != null, ReleaseDO::getReleaseType, pageReqVO.getReleaseType()); + wrapper.eq(pageReqVO.getStatus() != null, ReleaseDO::getStatus, pageReqVO.getStatus()); + wrapper.ge(pageReqVO.getActualReleaseDateStart() != null, ReleaseDO::getActualReleaseDate, pageReqVO.getActualReleaseDateStart()); + wrapper.le(pageReqVO.getActualReleaseDateEnd() != null, ReleaseDO::getActualReleaseDate, pageReqVO.getActualReleaseDateEnd()); + wrapper.orderByDesc(ReleaseDO::getId); + + return releaseMapper.selectPage(pageReqVO, wrapper); + } + + @Override + @Transactional + public void doRelease(Long id, Long operatorId) { + ReleaseDO release = releaseMapper.selectById(id); + if (release == null) { + throw new IllegalArgumentException("释放登记记录不存在"); + } + + if (!release.getStatus().equals(STATUS_PENDING)) { + throw new IllegalArgumentException("只有待释放状态的记录可以执行释放"); + } + + // 更新释放登记状态 + release.setStatus(STATUS_RELEASED); + release.setOperatorId(operatorId); + releaseMapper.updateById(release); + + // 更新罪犯状态为已释放 + PrisonerDO prisoner = prisonerMapper.selectById(release.getPrisonerId()); + if (prisoner != null) { + prisoner.setStatus(PrisonerStatusEnum.RELEASED); + prisoner.setReleaseType(release.getReleaseType()); + prisoner.setReleaseReason(release.getReleaseReason()); + prisonerMapper.updateById(prisoner); + + // 记录区域变动日志 + PrisonerAreaLogSaveReqVO logReqVO = new PrisonerAreaLogSaveReqVO(); + logReqVO.setPrisonerId(prisoner.getId()); + logReqVO.setPrisonerNo(prisoner.getPrisonerNo()); + logReqVO.setFromAreaId(prisoner.getPrisonAreaId()); + logReqVO.setFromCellId(prisoner.getPrisonCellId()); + logReqVO.setToAreaId(null); + logReqVO.setToCellId(null); + logReqVO.setChangeType(3); // 出监 + logReqVO.setReason("释放:" + getReleaseTypeName(release.getReleaseType())); + logReqVO.setOperateTime(LocalDateTime.now()); + areaLogMapper.insert(BeanUtils.toBean(logReqVO, PrisonerAreaLogDO.class)); + } + } + + @Override + @Transactional + public void cancelRelease(Long id, Long operatorId) { + ReleaseDO release = releaseMapper.selectById(id); + if (release == null) { + throw new IllegalArgumentException("释放登记记录不存在"); + } + + if (!release.getStatus().equals(STATUS_PENDING)) { + throw new IllegalArgumentException("只有待释放状态的记录可以取消"); + } + + release.setStatus(STATUS_CANCELLED); + release.setOperatorId(operatorId); + releaseMapper.updateById(release); + } + + private String getReleaseTypeName(Integer releaseType) { + if (releaseType == null) return ""; + return switch (releaseType) { + case 1 -> "刑满释放"; + case 2 -> "假释"; + case 3 -> "暂予监外执行"; + case 4 -> "减刑"; + case 5 -> "法院裁定释放"; + case 6 -> "死亡"; + case 7 -> "其他"; + default -> ""; + }; + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/NotifyService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/NotifyService.java new file mode 100644 index 0000000000..230f25f3fb --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/NotifyService.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.prison.service.reminder; + +import org.springframework.stereotype.Service; + +/** + * 通知服务(预留,可对接短信、邮件、企业微信等) + * + * @author xlcp + */ +@Service +public class NotifyService { + + /** + * 发送预警通知 + */ + public void sendWarning(String message, NotifyType type) { + // TODO: 根据需求实现具体通知方式 + // 1. 发送系统通知 + // 2. 发送企业微信消息 + // 3. 发送短信/邮件通知 + System.out.println("[预警通知] " + message); + } + + /** + * 发送紧急通知 + */ + public void sendUrgent(String message, NotifyType type) { + // TODO: 根据需求实现具体通知方式 + System.out.println("[紧急通知] " + message); + } + + public enum NotifyType { + RELEASE_REMINDER, // 释放提醒 + RELEASE_OVERDUE // 释放超期 + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/ReminderService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/ReminderService.java new file mode 100644 index 0000000000..15422c83a4 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/reminder/ReminderService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.prison.service.reminder; + +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper; +import cn.iocoder.yudao.module.prison.enums.PrisonerStatusEnum; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.util.List; + +/** + * 余刑预警服务 + * + * @author xlcp + */ +@Service +public class ReminderService { + + private static final int WARNING_DAYS = 30; // 提前30天预警 + + @Resource + private PrisonerMapper prisonerMapper; + + // NotifyService 和 NotifyType 需要根据实际实现进行注入 + // @Resource + // private NotifyService notifyService; + + /** + * 定时任务:检查即将释放的罪犯 + * 每天凌晨2点执行 + */ + @Scheduled(cron = "0 0 2 * * ?") + public void checkUpcomingRelease() { + LocalDate now = LocalDate.now(); + LocalDate thirtyDaysLater = now.plusDays(WARNING_DAYS); + + // 1. 查询30天内即将释放的罪犯 + List upcomingList = prisonerMapper.selectList( + new LambdaQueryWrapper() + .lt(PrisonerDO::getReleaseDate, thirtyDaysLater) + .gt(PrisonerDO::getReleaseDate, now) + .eq(PrisonerDO::getStatus, PrisonerStatusEnum.IMPRISONED) + ); + + // 2. 发送预警通知 + for (PrisonerDO prisoner : upcomingList) { + long daysLeft = ChronoUnit.DAYS.between(now, prisoner.getReleaseDate()); + String message = String.format("罪犯[%s - %s]还有%d天即将释放(释放日期:%s)", + prisoner.getName(), prisoner.getPrisonerNo(), + daysLeft, prisoner.getReleaseDate()); + // notifyService.sendWarning(message, NotifyType.RELEASE_REMINDER); + System.out.println(message); + } + + // 3. 查询超期未释放的罪犯(异常情况) + List overdueList = prisonerMapper.selectList( + new LambdaQueryWrapper() + .lt(PrisonerDO::getReleaseDate, now) + .eq(PrisonerDO::getStatus, PrisonerStatusEnum.IMPRISONED) + ); + + for (PrisonerDO prisoner : overdueList) { + String message = String.format("警告:罪犯[%s - %s]已过释放日期但仍未释放!(释放日期:%s)", + prisoner.getName(), prisoner.getPrisonerNo(), prisoner.getReleaseDate()); + // notifyService.sendUrgent(message, NotifyType.RELEASE_OVERDUE); + System.out.println(message); + } + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/ScoreDetailService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/ScoreDetailService.java new file mode 100644 index 0000000000..da2b7e591f --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/ScoreDetailService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.prison.service.scorerecord; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.prison.controller.admin.scorerecord.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerecord.ScoreDetailDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 考核记录明细 Service 接口 + * + * @author xlcp + */ +public interface ScoreDetailService { + + /** + * 创建考核记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createScoreDetail(@Valid ScoreDetailSaveReqVO createReqVO); + + /** + * 更新考核记录 + * + * @param updateReqVO 更新信息 + */ + void updateScoreDetail(@Valid ScoreDetailSaveReqVO updateReqVO); + + /** + * 删除考核记录 + * + * @param id 编号 + */ + void deleteScoreDetail(Long id); + + /** + * 批量删除考核记录 + * + * @param ids 编号 + */ + void deleteScoreDetailListByIds(List ids); + + /** + * 获得考核记录 + * + * @param id 编号 + * @return 考核记录 + */ + ScoreDetailDO getScoreDetail(Long id); + + /** + * 获得考核记录分页 + * + * @param pageReqVO 分页查询 + * @return 考核记录分页 + */ + PageResult getScoreDetailPage(ScoreDetailPageReqVO pageReqVO); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/impl/ScoreDetailServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/impl/ScoreDetailServiceImpl.java new file mode 100644 index 0000000000..4836eefe22 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerecord/impl/ScoreDetailServiceImpl.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.prison.service.scorerecord.impl; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.scorerecord.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerecord.ScoreDetailDO; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.scorerecord.ScoreDetailMapper; +import cn.iocoder.yudao.module.prison.service.scorerecord.ScoreDetailService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 考核记录明细 Service 实现类 + * + * @author xlcp + */ +@Service +@Validated +public class ScoreDetailServiceImpl implements ScoreDetailService { + + @Resource + private ScoreDetailMapper scoreDetailMapper; + + @Resource + private PrisonerMapper prisonerMapper; + + @Override + public Long createScoreDetail(ScoreDetailSaveReqVO createReqVO) { + // 获取罪犯信息 + PrisonerDO prisoner = prisonerMapper.selectById(createReqVO.getPrisonerId()); + if (prisoner == null) { + throw new IllegalArgumentException("罪犯不存在"); + } + + ScoreDetailDO scoreDetail = BeanUtils.toBean(createReqVO, ScoreDetailDO.class); + scoreDetail.setPrisonerNo(prisoner.getPrisonerNo()); + if (scoreDetail.getStatus() == null) { + scoreDetail.setStatus(1); // 默认有效 + } + scoreDetailMapper.insert(scoreDetail); + + return scoreDetail.getId(); + } + + @Override + public void updateScoreDetail(ScoreDetailSaveReqVO updateReqVO) { + ScoreDetailDO existing = scoreDetailMapper.selectById(updateReqVO.getId()); + if (existing == null) { + throw new IllegalArgumentException("考核记录不存在"); + } + + ScoreDetailDO updateObj = BeanUtils.toBean(updateReqVO, ScoreDetailDO.class); + scoreDetailMapper.updateById(updateObj); + } + + @Override + public void deleteScoreDetail(Long id) { + scoreDetailMapper.deleteById(id); + } + + @Override + public void deleteScoreDetailListByIds(List ids) { + scoreDetailMapper.deleteBatchIds(ids); + } + + @Override + public ScoreDetailDO getScoreDetail(Long id) { + return scoreDetailMapper.selectById(id); + } + + @Override + public PageResult getScoreDetailPage(ScoreDetailPageReqVO pageReqVO) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(pageReqVO.getPrisonerId() != null, ScoreDetailDO::getPrisonerId, pageReqVO.getPrisonerId()); + wrapper.like(pageReqVO.getPrisonerNo() != null, ScoreDetailDO::getPrisonerNo, pageReqVO.getPrisonerNo()); + wrapper.eq(pageReqVO.getRuleId() != null, ScoreDetailDO::getRuleId, pageReqVO.getRuleId()); + wrapper.eq(pageReqVO.getScoreType() != null, ScoreDetailDO::getScoreType, pageReqVO.getScoreType()); + wrapper.eq(pageReqVO.getStatus() != null, ScoreDetailDO::getStatus, pageReqVO.getStatus()); + wrapper.ge(pageReqVO.getRecordDateStart() != null, ScoreDetailDO::getRecordDate, pageReqVO.getRecordDateStart()); + wrapper.le(pageReqVO.getRecordDateEnd() != null, ScoreDetailDO::getRecordDate, pageReqVO.getRecordDateEnd()); + wrapper.orderByDesc(ScoreDetailDO::getRecordDate); + wrapper.orderByDesc(ScoreDetailDO::getId); + + return scoreDetailMapper.selectPage(pageReqVO, wrapper); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/ScoreRuleService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/ScoreRuleService.java new file mode 100644 index 0000000000..b114e82984 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/ScoreRuleService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.prison.service.scorerule; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.prison.controller.admin.scorerule.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerule.ScoreRuleDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 考核规则配置 Service 接口 + * + * @author xlcp + */ +public interface ScoreRuleService { + + /** + * 创建考核规则 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createScoreRule(@Valid ScoreRuleSaveReqVO createReqVO); + + /** + * 更新考核规则 + * + * @param updateReqVO 更新信息 + */ + void updateScoreRule(@Valid ScoreRuleSaveReqVO updateReqVO); + + /** + * 删除考核规则 + * + * @param id 编号 + */ + void deleteScoreRule(Long id); + + /** + * 批量删除考核规则 + * + * @param ids 编号 + */ + void deleteScoreRuleListByIds(List ids); + + /** + * 获得考核规则 + * + * @param id 编号 + * @return 考核规则 + */ + ScoreRuleDO getScoreRule(Long id); + + /** + * 获得考核规则分页 + * + * @param pageReqVO 分页查询 + * @return 考核规则分页 + */ + PageResult getScoreRulePage(ScoreRulePageReqVO pageReqVO); + + /** + * 根据类别获取考核规则列表 + * + * @param category 类别 + * @return 考核规则列表 + */ + List getScoreRuleListByCategory(Integer category); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/impl/ScoreRuleServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/impl/ScoreRuleServiceImpl.java new file mode 100644 index 0000000000..20560736e8 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/scorerule/impl/ScoreRuleServiceImpl.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.prison.service.scorerule.impl; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.scorerule.vo.*; +import cn.iocoder.yudao.module.prison.dal.dataobject.scorerule.ScoreRuleDO; +import cn.iocoder.yudao.module.prison.dal.mysql.scorerule.ScoreRuleMapper; +import cn.iocoder.yudao.module.prison.service.scorerule.ScoreRuleService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.prison.enums.ErrorCodeConstants; + +/** + * 考核规则配置 Service 实现类 + * + * @author xlcp + */ +@Service +@Validated +public class ScoreRuleServiceImpl implements ScoreRuleService { + + @Resource + private ScoreRuleMapper scoreRuleMapper; + + @Override + public Long createScoreRule(ScoreRuleSaveReqVO createReqVO) { + // 检查编码是否重复 + Long count = scoreRuleMapper.selectCount(new LambdaQueryWrapper() + .eq(ScoreRuleDO::getItemCode, createReqVO.getItemCode())); + if (count > 0) { + throw new IllegalArgumentException("项目编码已存在"); + } + + ScoreRuleDO scoreRule = BeanUtils.toBean(createReqVO, ScoreRuleDO.class); + if (scoreRule.getStatus() == null) { + scoreRule.setStatus(1); // 默认启用 + } + if (scoreRule.getSort() == null) { + scoreRule.setSort(0); + } + scoreRuleMapper.insert(scoreRule); + return scoreRule.getId(); + } + + @Override + public void updateScoreRule(ScoreRuleSaveReqVO updateReqVO) { + ScoreRuleDO existing = scoreRuleMapper.selectById(updateReqVO.getId()); + if (existing == null) { + throw new IllegalArgumentException("考核规则不存在"); + } + + // 检查编码是否重复(排除自己) + Long count = scoreRuleMapper.selectCount(new LambdaQueryWrapper() + .eq(ScoreRuleDO::getItemCode, updateReqVO.getItemCode()) + .ne(ScoreRuleDO::getId, updateReqVO.getId())); + if (count > 0) { + throw new IllegalArgumentException("项目编码已存在"); + } + + ScoreRuleDO updateObj = BeanUtils.toBean(updateReqVO, ScoreRuleDO.class); + scoreRuleMapper.updateById(updateObj); + } + + @Override + public void deleteScoreRule(Long id) { + scoreRuleMapper.deleteById(id); + } + + @Override + public void deleteScoreRuleListByIds(List ids) { + scoreRuleMapper.deleteBatchIds(ids); + } + + @Override + public ScoreRuleDO getScoreRule(Long id) { + return scoreRuleMapper.selectById(id); + } + + @Override + public PageResult getScoreRulePage(ScoreRulePageReqVO pageReqVO) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(pageReqVO.getCategory() != null, ScoreRuleDO::getCategory, pageReqVO.getCategory()); + wrapper.like(pageReqVO.getItemName() != null, ScoreRuleDO::getItemName, pageReqVO.getItemName()); + wrapper.eq(pageReqVO.getItemCode() != null, ScoreRuleDO::getItemCode, pageReqVO.getItemCode()); + wrapper.eq(pageReqVO.getStatus() != null, ScoreRuleDO::getStatus, pageReqVO.getStatus()); + wrapper.orderByAsc(ScoreRuleDO::getCategory); + wrapper.orderByAsc(ScoreRuleDO::getSort); + + return scoreRuleMapper.selectPage(pageReqVO, wrapper); + } + + @Override + public List getScoreRuleListByCategory(Integer category) { + return scoreRuleMapper.selectList(new LambdaQueryWrapper() + .eq(ScoreRuleDO::getCategory, category) + .eq(ScoreRuleDO::getStatus, 1) // 只查询启用的规则 + .orderByAsc(ScoreRuleDO::getSort)); + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/TransferService.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/TransferService.java new file mode 100644 index 0000000000..379855a56e --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/TransferService.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.prison.service.transfer; + +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.TransferReqVO; + +/** + * 调监服务接口 + * + * @author xlcp + */ +public interface TransferService { + + /** + * 执行调监 + * + * @param reqVO 调监请求 + * @param operatorId 操作人ID + */ + void doTransfer(TransferReqVO reqVO, Long operatorId); + + /** + * 校验调监是否合法 + * + * @param reqVO 调监请求 + */ + void validateTransfer(TransferReqVO reqVO); + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/impl/TransferServiceImpl.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/impl/TransferServiceImpl.java new file mode 100644 index 0000000000..afd2057ecc --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/service/transfer/impl/TransferServiceImpl.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.prison.service.transfer.impl; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.arealog.vo.PrisonerAreaLogSaveReqVO; +import cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo.TransferReqVO; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerAreaLogDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; +import cn.iocoder.yudao.module.prison.dal.dataobject.cell.CellDO; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerAreaLogMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper; +import cn.iocoder.yudao.module.prison.dal.mysql.cell.CellMapper; +import cn.iocoder.yudao.module.prison.enums.AreaChangeTypeEnum; +import cn.iocoder.yudao.module.prison.enums.SupervisionLevelEnum; +import cn.iocoder.yudao.module.prison.service.transfer.TransferService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +/** + * 调监服务实现类 + * + * @author xlcp + */ +@Service +public class TransferServiceImpl implements TransferService { + + @Resource + private PrisonerMapper prisonerMapper; + + @Resource + private CellMapper cellMapper; + + @Resource + private PrisonerAreaLogMapper areaLogMapper; + + @Override + @Transactional + public void doTransfer(TransferReqVO reqVO, Long operatorId) { + // 1. 校验 + validateTransfer(reqVO); + + // 2. 获取原位置信息 + PrisonerDO prisoner = prisonerMapper.selectById(reqVO.getPrisonerId()); + Long oldAreaId = prisoner.getPrisonAreaId(); + Long oldCellId = prisoner.getPrisonCellId(); + + // 3. 获取目标位置信息 + CellDO targetCell = cellMapper.selectById(reqVO.getTargetCellId()); + + // 4. 更新罪犯位置 + prisoner.setPrisonAreaId(targetCell.getAreaId()); + prisoner.setPrisonCellId(reqVO.getTargetCellId()); + prisonerMapper.updateById(prisoner); + + // 5. 同步监区人数 + syncAreaCount(oldAreaId, targetCell.getAreaId()); + + // 6. 记录变动日志 + PrisonerAreaLogSaveReqVO logReqVO = new PrisonerAreaLogSaveReqVO(); + logReqVO.setPrisonerId(prisoner.getId()); + logReqVO.setPrisonerNo(prisoner.getPrisonerNo()); + logReqVO.setFromAreaId(oldAreaId); + logReqVO.setFromCellId(oldCellId); + logReqVO.setToAreaId(targetCell.getAreaId()); + logReqVO.setToCellId(reqVO.getTargetCellId()); + logReqVO.setChangeType(AreaChangeTypeEnum.TRANSFER_OUT.getValue()); // 调出 + logReqVO.setReason(reqVO.getReason()); + logReqVO.setOperateTime(LocalDateTime.now()); + logReqVO.setOperateBy(operatorId); + areaLogMapper.insert(BeanUtils.toBean(logReqVO, PrisonerAreaLogDO.class)); + } + + @Override + public void validateTransfer(TransferReqVO reqVO) { + // 1. 校验罪犯是否存在 + PrisonerDO prisoner = prisonerMapper.selectById(reqVO.getPrisonerId()); + if (prisoner == null) { + throw new IllegalArgumentException("罪犯不存在"); + } + + // 2. 校验目标监室是否存在 + CellDO targetCell = cellMapper.selectById(reqVO.getTargetCellId()); + if (targetCell == null) { + throw new IllegalArgumentException("目标监室不存在"); + } + + // 3. 校验目标监室是否启用 + if (targetCell.getStatus() != 1) { + throw new IllegalArgumentException("目标监室已禁用"); + } + + // 4. 校验床位是否已满 + if (targetCell.getCurrentCount() >= targetCell.getCapacity()) { + throw new IllegalArgumentException("目标监室床位已满"); + } + + // 5. 校验是否在同一监室 + if (prisoner.getPrisonCellId() != null + && prisoner.getPrisonCellId().equals(reqVO.getTargetCellId())) { + throw new IllegalArgumentException("目标监室与当前监室相同,无需调监"); + } + } + + /** + * 同步监区人数 + */ + private void syncAreaCount(Long oldAreaId, Long newAreaId) { + // 原监区人数减1,新监区人数加1 + // 调用AreaService的syncCurrentCount方法 + } + +} diff --git a/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/util/DataMaskUtils.java b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/util/DataMaskUtils.java new file mode 100644 index 0000000000..9b1f7309a0 --- /dev/null +++ b/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/util/DataMaskUtils.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.prison.util; + +import cn.hutool.core.util.StrUtil; + +/** + * 数据脱敏工具类 + * + * 用于对敏感信息进行脱敏处理,保护个人隐私 + * + * @author xlcp + */ +public class DataMaskUtils { + + /** + * 身份证号脱敏 + * 110101199001011234 -> 110***********1234 + * + * @param idCard 身份证号 + * @return 脱敏后的身份证号 + */ + public static String maskIdCard(String idCard) { + if (StrUtil.isBlank(idCard) || idCard.length() < 7) { + return idCard; + } + return idCard.substring(0, 3) + "*".repeat(idCard.length() - 7) + idCard.substring(idCard.length() - 4); + } + + /** + * 手机号脱敏 + * 13812345678 -> 138****5678 + * + * @param phone 手机号 + * @return 脱敏后的手机号 + */ + public static String maskPhone(String phone) { + if (StrUtil.isBlank(phone) || phone.length() < 7) { + return phone; + } + return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4); + } + + /** + * 姓名脱敏 + * 张三丰 -> 张** + * + * @param name 姓名 + * @return 脱敏后的姓名 + */ + public static String maskName(String name) { + if (StrUtil.isBlank(name) || name.length() == 1) { + return name; + } + return name.charAt(0) + "*".repeat(name.length() - 1); + } + + /** + * 地址脱敏 + * 北京市海淀区中关村大街1号 -> 北京市海淀区*** + * + * @param address 地址 + * @return 脱敏后的地址 + */ + public static String maskAddress(String address) { + if (StrUtil.isBlank(address)) { + return address; + } + // 查找最后一个区/县分隔符 + int lastSeparator = Math.max(address.lastIndexOf('区'), address.lastIndexOf('县')); + if (lastSeparator > 0 && lastSeparator < address.length() - 1) { + return address.substring(0, lastSeparator + 1) + "***"; + } + return address; + } + + /** + * 银行卡号脱敏 + * 6222021234567890123 -> 6222 **** **** 0123 + * + * @param cardNo 银行卡号 + * @return 脱敏后的银行卡号 + */ + public static String maskBankCard(String cardNo) { + if (StrUtil.isBlank(cardNo) || cardNo.length() < 8) { + return cardNo; + } + StringBuilder sb = new StringBuilder(); + sb.append(cardNo, 0, 4); + sb.append(" **** **** "); + sb.append(cardNo, cardNo.length() - 4, cardNo.length()); + return sb.toString(); + } + +} diff --git a/yudao-module-prison/src/main/resources/mapper/PrisonerMapper.xml b/yudao-module-prison/src/main/resources/mapper/PrisonerMapper.xml index 6cebb85773..864fd82886 100644 --- a/yudao-module-prison/src/main/resources/mapper/PrisonerMapper.xml +++ b/yudao-module-prison/src/main/resources/mapper/PrisonerMapper.xml @@ -2,7 +2,7 @@ - + @@ -18,11 +18,21 @@ + + + + + + + + + + @@ -31,6 +41,28 @@ + + + + + + + + diff --git a/yudao-module-prison/src/main/resources/sql/preset_area_data.sql b/yudao-module-prison/src/main/resources/sql/preset_area_data.sql new file mode 100644 index 0000000000..17a55efbe5 --- /dev/null +++ b/yudao-module-prison/src/main/resources/sql/preset_area_data.sql @@ -0,0 +1,149 @@ +-- ===================================================== +-- 预设监区数据 - 带层级结构(大队 → 中队 → 监室) +-- 执行前请确保 prison_area 和 prison_cell 表已创建 +-- ===================================================== + +-- 清空现有数据 +TRUNCATE TABLE prison_cell; +TRUNCATE TABLE prison_area; + +-- ===================================================== +-- 第一级:监区(大队) +-- ===================================================== +INSERT INTO prison_area (id, name, code, type, capacity, current_count, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES +-- 普通监区(大队) +(1, '一大队', 'AREA_001', 1, 300, 0, 1, 1, '一大队,负责日常改造工作', 'admin', NOW(), 'admin', NOW(), 0, 0), +(2, '二大队', 'AREA_002', 1, 300, 0, 2, 1, '二大队,负责日常改造工作', 'admin', NOW(), 'admin', NOW(), 0, 0), +(3, '三大队', 'AREA_003', 1, 300, 0, 3, 1, '三大队,负责日常改造工作', 'admin', NOW(), 'admin', NOW(), 0, 0), +(4, '四大队', 'AREA_004', 1, 300, 0, 4, 1, '四大队,负责日常改造工作', 'admin', NOW(), 'admin', NOW(), 0, 0), +(5, '五大队', 'AREA_005', 1, 300, 0, 5, 1, '五大队,负责日常改造工作', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 严管监区 +(6, '严管大队', 'AREA_STRICT_001', 2, 150, 0, 6, 1, '严管大队,负责重点管控', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 监狱医院 +(7, '监狱医院', 'AREA_HOSPITAL_001', 3, 80, 0, 7, 1, '监狱医院,负责医疗救治', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 禁闭室 +(8, '禁闭室', 'AREA_SOLITARY_001', 4, 30, 0, 8, 1, '禁闭室,负责违纪处理', 'admin', NOW(), 'admin', NOW(), 0, 0); + +-- ===================================================== +-- 第二级:分监区(中队) +-- type=2 表示分监区,parent_id 关联大队 +-- ===================================================== +INSERT INTO prison_area (id, name, code, type, parent_id, capacity, current_count, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES +-- 一大队的分监区 +(101, '一中队', 'AREA_001_001', 2, 1, 100, 0, 1, 1, '一大队一中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(102, '二中队', 'AREA_001_002', 2, 1, 100, 0, 2, 1, '一大队二中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(103, '三中队', 'AREA_001_003', 2, 1, 100, 0, 3, 1, '一大队三中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 二大队的分监区 +(201, '一中队', 'AREA_002_001', 2, 2, 100, 0, 1, 1, '二大队一中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(202, '二中队', 'AREA_002_002', 2, 2, 100, 0, 2, 1, '二大队二中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(203, '三中队', 'AREA_002_003', 2, 2, 100, 0, 3, 1, '二大队三中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 三大队的分监区 +(301, '一中队', 'AREA_003_001', 2, 3, 100, 0, 1, 1, '三大队一中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(302, '二中队', 'AREA_003_002', 2, 3, 100, 0, 2, 1, '三大队二中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(303, '三中队', 'AREA_003_003', 2, 3, 100, 0, 3, 1, '三大队三中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 四大队的分监区 +(401, '一中队', 'AREA_004_001', 2, 4, 100, 0, 1, 1, '四大队一中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(402, '二中队', 'AREA_004_002', 2, 4, 100, 0, 2, 1, '四大队二中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(403, '三中队', 'AREA_004_003', 2, 4, 100, 0, 3, 1, '四大队三中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 五大队分监区 +(501, '一中队', 'AREA_005_001', 2, 5, 100, 0, 1, 1, '五大队一中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(502, '二中队', 'AREA_005_002', 2, 5, 100, 0, 2, 1, '五大队二中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(503, '三中队', 'AREA_005_003', 2, 5, 100, 0, 3, 1, '五大队三中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 严管大队分监区 +(601, '一中队', 'AREA_STRICT_001_001', 2, 6, 50, 0, 1, 1, '严管一中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(602, '二中队', 'AREA_STRICT_001_002', 2, 6, 50, 0, 2, 1, '严管二中队', 'admin', NOW(), 'admin', NOW(), 0, 0), +(603, '三中队', 'AREA_STRICT_001_003', 2, 6, 50, 0, 3, 1, '严管三中队', 'admin', NOW(), 'admin', NOW(), 0, 0); + +-- ===================================================== +-- 第三级:监室 +-- area_id 关联分监区(中队) +-- ===================================================== +INSERT INTO prison_cell (area_id, name, code, capacity, current_count, sort, status, remark, creator, create_time, updater, update_time, deleted, tenant_id) VALUES +-- 一大队监室 +(101, '101监室', 'CELL_101_101', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(101, '102监室', 'CELL_101_102', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(101, '103监室', 'CELL_101_103', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(101, '104监室', 'CELL_101_104', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(102, '201监室', 'CELL_102_201', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(102, '202监室', 'CELL_102_202', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(102, '203监室', 'CELL_102_203', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(102, '204监室', 'CELL_102_204', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(103, '301监室', 'CELL_103_301', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(103, '302监室', 'CELL_103_302', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(103, '303监室', 'CELL_103_303', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(103, '304监室', 'CELL_103_304', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 二大队监室 +(201, '101监室', 'CELL_201_101', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(201, '102监室', 'CELL_201_102', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(201, '103监室', 'CELL_201_103', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(201, '104监室', 'CELL_201_104', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(202, '201监室', 'CELL_202_201', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(202, '202监室', 'CELL_202_202', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(202, '203监室', 'CELL_202_203', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(202, '204监室', 'CELL_202_204', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(203, '301监室', 'CELL_203_301', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(203, '302监室', 'CELL_203_302', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(203, '303监室', 'CELL_203_303', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(203, '304监室', 'CELL_203_304', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 三大队监室 +(301, '101监室', 'CELL_301_101', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(301, '102监室', 'CELL_301_102', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(301, '103监室', 'CELL_301_103', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(301, '104监室', 'CELL_301_104', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(302, '201监室', 'CELL_302_201', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(302, '202监室', 'CELL_302_202', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(302, '203监室', 'CELL_302_203', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(302, '204监室', 'CELL_302_204', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(303, '301监室', 'CELL_303_301', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(303, '302监室', 'CELL_303_302', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(303, '303监室', 'CELL_303_303', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(303, '304监室', 'CELL_303_304', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 四大队监室 +(401, '101监室', 'CELL_401_101', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(401, '102监室', 'CELL_401_102', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(401, '103监室', 'CELL_401_103', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(401, '104监室', 'CELL_401_104', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(402, '201监室', 'CELL_402_201', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(402, '202监室', 'CELL_402_202', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(402, '203监室', 'CELL_402_203', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(402, '204监室', 'CELL_402_204', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(403, '301监室', 'CELL_403_301', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(403, '302监室', 'CELL_403_302', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(403, '303监室', 'CELL_403_303', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(403, '304监室', 'CELL_403_304', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 五大队监室 +(501, '101监室', 'CELL_501_101', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(501, '102监室', 'CELL_501_102', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(501, '103监室', 'CELL_501_103', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(501, '104监室', 'CELL_501_104', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(502, '201监室', 'CELL_502_201', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(502, '202监室', 'CELL_502_202', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(502, '203监室', 'CELL_502_203', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(502, '204监室', 'CELL_502_204', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(503, '301监室', 'CELL_503_301', 12, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(503, '302监室', 'CELL_503_302', 12, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(503, '303监室', 'CELL_503_303', 12, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(503, '304监室', 'CELL_503_304', 12, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 严管大队监室 +(601, '严管101室', 'CELL_STRICT_601_101', 10, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(601, '严管102室', 'CELL_STRICT_601_102', 10, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(601, '严管103室', 'CELL_STRICT_601_103', 10, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(602, '严管201室', 'CELL_STRICT_602_201', 10, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(602, '严管202室', 'CELL_STRICT_602_202', 10, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(602, '严管203室', 'CELL_STRICT_602_203', 10, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(603, '严管301室', 'CELL_STRICT_603_301', 10, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(603, '严管302室', 'CELL_STRICT_603_302', 10, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(603, '严管303室', 'CELL_STRICT_603_303', 10, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 监狱医院监室 +(701, '病房101', 'CELL_HOSP_701_101', 8, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(701, '病房102', 'CELL_HOSP_701_102', 8, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(701, '病房103', 'CELL_HOSP_701_103', 8, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(702, '病房201', 'CELL_HOSP_702_201', 8, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(702, '病房202', 'CELL_HOSP_702_202', 8, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(702, '病房203', 'CELL_HOSP_702_203', 8, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +-- 禁闭室 +(801, '禁闭室1', 'CELL_SOL_801_1', 4, 0, 1, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(801, '禁闭室2', 'CELL_SOL_801_2', 4, 0, 2, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(801, '禁闭室3', 'CELL_SOL_801_3', 4, 0, 3, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(801, '禁闭室4', 'CELL_SOL_801_4', 4, 0, 4, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0), +(801, '禁闭室5', 'CELL_SOL_801_5', 4, 0, 5, 1, '', 'admin', NOW(), 'admin', NOW(), 0, 0); diff --git a/yudao-module-prison/src/main/resources/sql/prison_module.sql b/yudao-module-prison/src/main/resources/sql/prison_module.sql index 3fd11f78ea..8f8a11a0b2 100644 --- a/yudao-module-prison/src/main/resources/sql/prison_module.sql +++ b/yudao-module-prison/src/main/resources/sql/prison_module.sql @@ -206,15 +206,15 @@ CREATE TABLE IF NOT EXISTS `prison_score` ( -- ===================================================== -- 菜单权限 SQL -- 注意: 请将 ${table.parentMenuId} 替换为实际的父菜单ID --- 监狱管理模块的父菜单ID通常为 2000 (系统管理) 或对应的监狱模块菜单ID +-- 监狱管理模块的父菜单ID通常为 5047 (系统管理) 或对应的监狱模块菜单ID -- ===================================================== --- 获取监狱模块父菜单ID (假设为 2000,请根据实际情况调整) --- SELECT @parentId := 2000; +-- 获取监狱模块父菜单ID (假设为 5047,请根据实际情况调整) +-- SELECT @parentId := 5047; -- 1. 监区信息管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('监区信息管理', '', 2, 1, 2000, 'area', '', 'prison/area/index', 0, 'Area'); +VALUES ('监区信息管理', '', 2, 1, 5047, 'area', '', 'prison/area/index', 0, 'Area'); SELECT @areaParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('监区信息查询', 'prison:area:query', 3, 1, @areaParentId, '', '', '', 0); @@ -229,7 +229,7 @@ VALUES ('监区信息导出', 'prison:area:export', 3, 5, @areaParentId, '', '', -- 2. 监室信息管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('监室信息管理', '', 2, 2, 2000, 'cell', '', 'prison/cell/index', 0, 'Cell'); +VALUES ('监室信息管理', '', 2, 2, 5047, 'cell', '', 'prison/cell/index', 0, 'Cell'); SELECT @cellParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('监室信息查询', 'prison:cell:query', 3, 1, @cellParentId, '', '', '', 0); @@ -244,7 +244,7 @@ VALUES ('监室信息导出', 'prison:cell:export', 3, 5, @cellParentId, '', '', -- 3. 消费记录管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('消费记录管理', '', 2, 3, 2000, 'consumption', '', 'prison/consumption/index', 0, 'Consumption'); +VALUES ('消费记录管理', '', 2, 3, 5047, 'consumption', '', 'prison/consumption/index', 0, 'Consumption'); SELECT @consumptionParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('消费记录查询', 'prison:consumption:query', 3, 1, @consumptionParentId, '', '', '', 0); @@ -259,7 +259,7 @@ VALUES ('消费记录导出', 'prison:consumption:export', 3, 5, @consumptionPar -- 4. 问卷模板管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('问卷模板管理', '', 2, 4, 2000, 'questionnaire', '', 'prison/questionnaire/index', 0, 'Questionnaire'); +VALUES ('问卷模板管理', '', 2, 4, 5047, 'questionnaire', '', 'prison/questionnaire/index', 0, 'Questionnaire'); SELECT @questionnaireParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('问卷模板查询', 'prison:questionnaire:query', 3, 1, @questionnaireParentId, '', '', '', 0); @@ -274,7 +274,7 @@ VALUES ('问卷模板导出', 'prison:questionnaire:export', 3, 5, @questionnair -- 5. 问卷问题管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('问卷问题管理', '', 2, 5, 2000, 'question', '', 'prison/question/index', 0, 'Question'); +VALUES ('问卷问题管理', '', 2, 5, 5047, 'question', '', 'prison/question/index', 0, 'Question'); SELECT @questionParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('问卷问题查询', 'prison:question:query', 3, 1, @questionParentId, '', '', '', 0); @@ -289,7 +289,7 @@ VALUES ('问卷问题导出', 'prison:question:export', 3, 5, @questionParentId, -- 6. 问卷答题记录管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('问卷答题记录管理', '', 2, 6, 2000, 'questionnaire-record', '', 'prison/questionnairerecord/index', 0, 'QuestionnaireRecord'); +VALUES ('问卷答题记录管理', '', 2, 6, 5047, 'questionnaire-record', '', 'prison/questionnairerecord/index', 0, 'QuestionnaireRecord'); SELECT @recordParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('问卷答题记录查询', 'prison:questionnaire-record:query', 3, 1, @recordParentId, '', '', '', 0); @@ -304,7 +304,7 @@ VALUES ('问卷答题记录导出', 'prison:questionnaire-record:export', 3, 5, -- 7. 危险评估管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('危险评估管理', '', 2, 7, 2000, 'risk-assessment', '', 'prison/riskassessment/index', 0, 'RiskAssessment'); +VALUES ('危险评估管理', '', 2, 7, 5047, 'risk-assessment', '', 'prison/riskassessment/index', 0, 'RiskAssessment'); SELECT @riskParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('危险评估查询', 'prison:risk-assessment:query', 3, 1, @riskParentId, '', '', '', 0); @@ -319,7 +319,7 @@ VALUES ('危险评估导出', 'prison:risk-assessment:export', 3, 5, @riskParent -- 8. 计分考核管理菜单 INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) -VALUES ('计分考核管理', '', 2, 8, 2000, 'score', '', 'prison/score/index', 0, 'Score'); +VALUES ('计分考核管理', '', 2, 8, 5047, 'score', '', 'prison/score/index', 0, 'Score'); SELECT @scoreParentId := LAST_INSERT_ID(); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('计分考核查询', 'prison:score:query', 3, 1, @scoreParentId, '', '', '', 0); @@ -331,3 +331,19 @@ INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, co VALUES ('计分考核删除', 'prison:score:delete', 3, 4, @scoreParentId, '', '', '', 0); INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) VALUES ('计分考核导出', 'prison:score:export', 3, 5, @scoreParentId, '', '', '', 0); + +-- ===================================================== +-- 9. 数据结构迁移 SQL (2026-01-14) +-- ===================================================== +-- 移除 prison_prisoner 表中的 sub_area_id 字段 +-- 执行此迁移前请备份数据库 +ALTER TABLE `prison_prisoner` DROP COLUMN IF EXISTS `sub_area_id`; + +-- ===================================================== +-- 10. 字典数据 SQL +-- ===================================================== +-- 监室状态字典 +INSERT INTO system_dict_type (name, type, status, creator, create_time) VALUES ('监室状态', 'prison_cell_status', 0, 'admin', NOW()); +INSERT INTO system_dict_data (dict_type, sort, label, value, color_type, css_class, status, creator, create_time) VALUES +('prison_cell_status', 1, '启用', '1', 'success', '', 0, 'admin', NOW()), +('prison_cell_status', 2, '禁用', '2', 'danger', '', 0, 'admin', NOW()); diff --git a/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/EducationEnumTest.java b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/EducationEnumTest.java new file mode 100644 index 0000000000..a362762c87 --- /dev/null +++ b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/EducationEnumTest.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.prison.enums; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * EducationEnum 枚举测试 + * + * @author xlcp + */ +@DisplayName("文化程度枚举测试") +class EducationEnumTest { + + @Test + @DisplayName("测试所有枚举值存在") + void testAllEnumValuesExist() { + assertNotNull(EducationEnum.ILLITERATE); + assertNotNull(EducationEnum.PRIMARY_SCHOOL); + assertNotNull(EducationEnum.MIDDLE_SCHOOL); + assertNotNull(EducationEnum.HIGH_SCHOOL); + assertNotNull(EducationEnum.TECHNICAL_SCHOOL); + assertNotNull(EducationEnum.COLLEGE); + assertNotNull(EducationEnum.BACHELOR_OR_ABOVE); + } + + @Test + @DisplayName("测试文盲枚举值") + void testIlliterateValue() { + assertEquals(1, EducationEnum.ILLITERATE.getValue()); + assertEquals("文盲", EducationEnum.ILLITERATE.getName()); + } + + @Test + @DisplayName("测试小学枚举值") + void testPrimarySchoolValue() { + assertEquals(2, EducationEnum.PRIMARY_SCHOOL.getValue()); + assertEquals("小学", EducationEnum.PRIMARY_SCHOOL.getName()); + } + + @Test + @DisplayName("测试初中枚举值") + void testMiddleSchoolValue() { + assertEquals(3, EducationEnum.MIDDLE_SCHOOL.getValue()); + assertEquals("初中", EducationEnum.MIDDLE_SCHOOL.getName()); + } + + @Test + @DisplayName("测试高中枚举值") + void testHighSchoolValue() { + assertEquals(4, EducationEnum.HIGH_SCHOOL.getValue()); + assertEquals("高中", EducationEnum.HIGH_SCHOOL.getName()); + } + + @Test + @DisplayName("测试中专枚举值") + void testTechnicalSchoolValue() { + assertEquals(5, EducationEnum.TECHNICAL_SCHOOL.getValue()); + assertEquals("中专", EducationEnum.TECHNICAL_SCHOOL.getName()); + } + + @Test + @DisplayName("测试大专枚举值") + void testCollegeValue() { + assertEquals(6, EducationEnum.COLLEGE.getValue()); + assertEquals("大专", EducationEnum.COLLEGE.getName()); + } + + @Test + @DisplayName("测试本科及以上枚举值") + void testBachelorOrAboveValue() { + assertEquals(7, EducationEnum.BACHELOR_OR_ABOVE.getValue()); + assertEquals("本科及以上", EducationEnum.BACHELOR_OR_ABOVE.getName()); + } + + @Test + @DisplayName("测试枚举数量") + void testEnumCount() { + assertEquals(7, EducationEnum.values().length); + } +} diff --git a/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/GenderEnumTest.java b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/GenderEnumTest.java new file mode 100644 index 0000000000..ba08e9b553 --- /dev/null +++ b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/GenderEnumTest.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.prison.enums; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * GenderEnum 枚举测试 + * + * @author xlcp + */ +@DisplayName("性别枚举测试") +class GenderEnumTest { + + @Test + @DisplayName("测试所有枚举值存在") + void testAllEnumValuesExist() { + assertNotNull(GenderEnum.MALE); + assertNotNull(GenderEnum.FEMALE); + } + + @Test + @DisplayName("测试男性枚举值") + void testMaleValue() { + assertEquals(1, GenderEnum.MALE.getValue()); + assertEquals("男", GenderEnum.MALE.getName()); + } + + @Test + @DisplayName("测试女性枚举值") + void testFemaleValue() { + assertEquals(2, GenderEnum.FEMALE.getValue()); + assertEquals("女", GenderEnum.FEMALE.getName()); + } + + @Test + @DisplayName("测试枚举数量") + void testEnumCount() { + assertEquals(2, GenderEnum.values().length); + } +} diff --git a/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnumTest.java b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnumTest.java new file mode 100644 index 0000000000..b4b17961d5 --- /dev/null +++ b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/PrisonerStatusEnumTest.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.prison.enums; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * PrisonerStatusEnum 枚举测试 + * + * @author xlcp + */ +@DisplayName("服刑人员状态枚举测试") +class PrisonerStatusEnumTest { + + @Test + @DisplayName("测试所有枚举值存在") + void testAllEnumValuesExist() { + assertNotNull(PrisonerStatusEnum.IMPRISONED); + assertNotNull(PrisonerStatusEnum.PAROLED); + assertNotNull(PrisonerStatusEnum.OUTSIDE_EXECUTION); + assertNotNull(PrisonerStatusEnum.RELEASED); + assertNotNull(PrisonerStatusEnum.DECEASED); + } + + @Test + @DisplayName("测试在押状态值") + void testImprisonedValue() { + assertEquals(1, PrisonerStatusEnum.IMPRISONED.getValue()); + assertEquals("在押", PrisonerStatusEnum.IMPRISONED.getName()); + } + + @Test + @DisplayName("测试假释状态值") + void testParoledValue() { + assertEquals(2, PrisonerStatusEnum.PAROLED.getValue()); + assertEquals("假释", PrisonerStatusEnum.PAROLED.getName()); + } + + @Test + @DisplayName("测试暂予监外执行状态值") + void testOutsideExecutionValue() { + assertEquals(3, PrisonerStatusEnum.OUTSIDE_EXECUTION.getValue()); + assertEquals("暂予监外执行", PrisonerStatusEnum.OUTSIDE_EXECUTION.getName()); + } + + @Test + @DisplayName("测试已释放状态值") + void testReleasedValue() { + assertEquals(4, PrisonerStatusEnum.RELEASED.getValue()); + assertEquals("已释放", PrisonerStatusEnum.RELEASED.getName()); + } + + @Test + @DisplayName("测试已死亡状态值") + void testDeceasedValue() { + assertEquals(5, PrisonerStatusEnum.DECEASED.getValue()); + assertEquals("已死亡", PrisonerStatusEnum.DECEASED.getName()); + } + + @Test + @DisplayName("测试通过值获取枚举") + void testGetEnumByValue() { + for (PrisonerStatusEnum status : PrisonerStatusEnum.values()) { + PrisonerStatusEnum found = PrisonerStatusEnum.valueOf(status.name()); + assertEquals(status.getValue(), found.getValue()); + } + } + + @Test + @DisplayName("测试枚举数量") + void testEnumCount() { + assertEquals(5, PrisonerStatusEnum.values().length); + } +} diff --git a/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnumTest.java b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnumTest.java new file mode 100644 index 0000000000..0343a7092b --- /dev/null +++ b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/RiskLevelEnumTest.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.prison.enums; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * RiskLevelEnum 枚举测试 + * + * @author xlcp + */ +@DisplayName("风险等级枚举测试") +class RiskLevelEnumTest { + + @Test + @DisplayName("测试所有枚举值存在") + void testAllEnumValuesExist() { + assertNotNull(RiskLevelEnum.HIGH); + assertNotNull(RiskLevelEnum.MEDIUM); + assertNotNull(RiskLevelEnum.LOW); + } + + @Test + @DisplayName("测试高风险枚举值") + void testHighRiskValue() { + assertEquals(1, RiskLevelEnum.HIGH.getValue()); + assertEquals("高风险", RiskLevelEnum.HIGH.getName()); + } + + @Test + @DisplayName("测试中风险枚举值") + void testMediumRiskValue() { + assertEquals(2, RiskLevelEnum.MEDIUM.getValue()); + assertEquals("中风险", RiskLevelEnum.MEDIUM.getName()); + } + + @Test + @DisplayName("测试低风险枚举值") + void testLowRiskValue() { + assertEquals(3, RiskLevelEnum.LOW.getValue()); + assertEquals("低风险", RiskLevelEnum.LOW.getName()); + } + + @Test + @DisplayName("测试枚举数量") + void testEnumCount() { + assertEquals(3, RiskLevelEnum.values().length); + } +} diff --git a/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnumTest.java b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnumTest.java new file mode 100644 index 0000000000..9ad4ae305b --- /dev/null +++ b/yudao-module-prison/src/test/java/cn/iocoder/yudao/module/prison/enums/SupervisionLevelEnumTest.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.prison.enums; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * SupervisionLevelEnum 枚举测试 + * + * @author xlcp + */ +@DisplayName("监管等级枚举测试") +class SupervisionLevelEnumTest { + + @Test + @DisplayName("测试所有枚举值存在") + void testAllEnumValuesExist() { + assertNotNull(SupervisionLevelEnum.STRICT); + assertNotNull(SupervisionLevelEnum.NORMAL); + assertNotNull(SupervisionLevelEnum.RELAXED); + } + + @Test + @DisplayName("测试严管级枚举值") + void testStrictValue() { + assertEquals(1, SupervisionLevelEnum.STRICT.getValue()); + assertEquals("严管级", SupervisionLevelEnum.STRICT.getName()); + } + + @Test + @DisplayName("测试普管级枚举值") + void testNormalValue() { + assertEquals(2, SupervisionLevelEnum.NORMAL.getValue()); + assertEquals("普管级", SupervisionLevelEnum.NORMAL.getName()); + } + + @Test + @DisplayName("测试宽管级枚举值") + void testRelaxedValue() { + assertEquals(3, SupervisionLevelEnum.RELAXED.getValue()); + assertEquals("宽管级", SupervisionLevelEnum.RELAXED.getName()); + } + + @Test + @DisplayName("测试枚举数量") + void testEnumCount() { + assertEquals(3, SupervisionLevelEnum.values().length); + } +} diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index f8fa7dcfcc..2223b3c6aa 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -16,10 +16,10 @@ spring: enabled: true stat-view-servlet: enabled: true - allow: # 设置白名单,不填则允许所有访问 + allow: 127.0.0.1 # 设置白名单,仅允许本地访问 url-pattern: /druid/* - login-username: # 控制台管理用户名和密码 - login-password: + login-username: ${DRUID_USERNAME:admin} # 控制台管理用户名,建议通过环境变量配置 + login-password: ${DRUID_PASSWORD:admin123} # 控制台管理密码,建议通过环境变量配置 filter: stat: enabled: true @@ -55,8 +55,8 @@ spring: # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 # url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例 - username: xlcp_dev - password: xlcp_dev + username: ${DB_USERNAME:xlcp_dev} # 数据库用户名,建议通过环境变量配置 + password: ${DB_PASSWORD:xlcp_dev} # 数据库密码,建议通过环境变量配置 # username: sa # SQL Server 连接的示例 # password: Yudao@2024 # SQL Server 连接的示例 # username: SYSDBA # DM 连接的示例 @@ -65,9 +65,9 @@ spring: # password: Yudao@2024 # OpenGauss 连接的示例 slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 - url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true - username: xlcp_dev - password: xlcp_dev + url: jdbc:mysql://${DB_HOST_SLAVE:127.0.0.1}:${DB_PORT_SLAVE:3306}/${DB_NAME_SLAVE:ruoyi-vue-pro}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true + username: ${DB_USERNAME_SLAVE:xlcp_dev} + password: ${DB_PASSWORD_SLAVE:xlcp_dev} # tdengine: # IoT 数据库(需要 IoT 物联网再开启噢!) # url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro # driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver @@ -79,10 +79,10 @@ spring: # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: redis: - host: 192.168.10.130 - port: 6379 - database: 0 - password: redis_8a8EYH + host: 192.168.10.126 # 地址 + port: 46379 # 端口 + database: 0 # 数据库索引 + password: redis_Dbdb2F # 密码 --- #################### 定时任务相关配置 #################### @@ -166,7 +166,7 @@ spring: # 日志文件配置 logging: file: - name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + name: ./logs/${spring.application.name}.log # 日志文件名,相对于项目目录 level: # 配置自己写的 MyBatis Mapper 打印日志 cn.iocoder.yudao.module.bpm.dal.mysql: debug diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index f844a5ee9e..16036acc4b 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -69,7 +69,7 @@ mybatis-plus: map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 global-config: db-config: - id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 + id-type: NONE # "智能"模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 # id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库 # id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库 # id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解 @@ -104,7 +104,7 @@ aj: captcha: jigsaw: classpath:images/jigsaw # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 pic-click: classpath:images/pic-click # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 - cache-type: redis # 缓存 local/redis... + cache-type: local # 缓存 local/redis... cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 type: blockPuzzle # 验证码类型 default 三种都实例化。blockPuzzle 滑块拼图、clickWord 文字点选、pictureWord 文本输入