feat(prison): 完善监室管理功能及代码优化

- 修复监室状态枚举显示问题,使用标准字典类型
- 优化监区树形选择组件,改用 el-tree-select
- 修复 PrisonerDO.subAreaId 字段相关编译错误
- 优化 CellServiceImpl 关联查询监区名称
- 修复 lambda 表达式变量引用问题
- 配置 Redis 密码 redis_Dbdb2F
This commit is contained in:
tangweijie 2026-01-15 12:16:55 +08:00
parent 8077990e5d
commit 5f9bcfc9b2
89 changed files with 4824 additions and 89 deletions

View File

@ -3,20 +3,20 @@
-- ============================================ -- ============================================
-- 1. 监管等级 (prison_supervision_level) -- 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); 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 VALUES
(200801, 1, '严管级', '1', 'danger', '', 'prison_supervision_level', '0', '需要重点监控', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (200803, 3, '宽管级', '3', 'success', '', 'prison_supervision_level', '0', '表现良好,给予更多自主权', 'admin', NOW(), 'admin', NOW(), 0);
-- 2. 风险等级 (prison_risk_level) -- 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); 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 VALUES
(200901, 1, '低风险', '1', 'success', '', 'prison_risk_level', '0', '低风险,表现稳定', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (200904, 4, '极高风险', '4', 'danger', '', 'prison_risk_level', '0', '极高风险,需要重点监控', 'admin', NOW(), 'admin', NOW(), 0);
-- 3. 服刑人员状态 (prisoner_status) -- 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); 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 VALUES
(201001, 1, '在押', '1', 'primary', '', 'prisoner_status', '0', '正在服刑', 'admin', NOW(), 'admin', NOW(), 0), (201001, 1, '在押', '1', 'primary', '', 'prisoner_status', '0', '正在服刑', 'admin', NOW(), 'admin', NOW(), 0),
(201002, 2, '假释', '2', 'warning', '', '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); (201005, 5, '已死亡', '5', 'danger', '', 'prisoner_status', '0', '已死亡', 'admin', NOW(), 'admin', NOW(), 0);
-- 4. 文化程度 (prison_education) -- 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); 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 VALUES
(201101, 1, '文盲', '1', 'info', '', 'prison_education', '0', '未接受过教育', 'admin', NOW(), 'admin', NOW(), 0), (201101, 1, '文盲', '1', 'info', '', 'prison_education', '0', '未接受过教育', 'admin', NOW(), 'admin', NOW(), 0),
(201102, 2, '小学', '2', '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); (201107, 7, '本科及以上', '7', 'success', '', 'prison_education', '0', '本科及以上学历', 'admin', NOW(), 'admin', NOW(), 0);
-- 5. 问卷问题类型 (prison_question_type) -- 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); 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 VALUES
(201201, 1, '单选', '1', 'primary', '', 'prison_question_type', '0', '单选题', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (201204, 4, '评分', '4', 'info', '', 'prison_question_type', '0', '评分题', 'admin', NOW(), 'admin', NOW(), 0);
-- 6. 问卷状态 (prison_questionnaire_status) -- 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); 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 VALUES
(201301, 1, '草稿', '1', 'info', '', 'prison_questionnaire_status', '0', '问卷草稿', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (201303, 3, '已禁用', '3', 'danger', '', 'prison_questionnaire_status', '0', '问卷已禁用', 'admin', NOW(), 'admin', NOW(), 0);
-- 6.1 问卷类型 (prison_questionnaire_type) -- 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); 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 VALUES
(202101, 1, '心理测评', '1', 'primary', '', 'prison_questionnaire_type', '0', '心理测评问卷', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (202103, 3, '满意度调查', '3', 'success', '', 'prison_questionnaire_type', '0', '满意度调查问卷', 'admin', NOW(), 'admin', NOW(), 0);
-- 7. 消费类型 (prison_consumption_type) -- 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); 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 VALUES
(201401, 1, '存款', '1', 'success', '', 'prison_consumption_type', '0', '存款', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (201403, 3, '转账', '3', 'warning', '', 'prison_consumption_type', '0', '转账', 'admin', NOW(), 'admin', NOW(), 0);
-- 8. 消费状态 (prison_consumption_status) -- 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); 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 VALUES
(201501, 1, '成功', '1', 'success', '', 'prison_consumption_status', '0', '交易成功', 'admin', NOW(), 'admin', NOW(), 0), (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); (201502, 2, '失败', '2', 'danger', '', 'prison_consumption_status', '0', '交易失败', 'admin', NOW(), 'admin', NOW(), 0);
-- 9. 评估类型 (prison_assessment_type) -- 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); 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 VALUES
(201601, 1, '入狱评估', '1', 'primary', '', 'prison_assessment_type', '0', '入狱时评估', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (201603, 3, '专项评估', '3', 'warning', '', 'prison_assessment_type', '0', '专项评估', 'admin', NOW(), 'admin', NOW(), 0);
-- 10. 考核等级 (prison_score_level) -- 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); 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 VALUES
(201701, 1, '优秀', '1', 'success', '', 'prison_score_level', '0', '表现优秀', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (201704, 4, '不合格', '4', 'danger', '', 'prison_score_level', '0', '表现不合格', 'admin', NOW(), 'admin', NOW(), 0);
-- 11. 考核状态 (prison_score_status) -- 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); 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 VALUES
(201801, 1, '待审核', '1', 'info', '', 'prison_score_status', '0', '待审核', 'admin', NOW(), 'admin', NOW(), 0), (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), (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); (201803, 3, '已驳回', '3', 'danger', '', 'prison_score_status', '0', '已驳回', 'admin', NOW(), 'admin', NOW(), 0);
-- 12. 监区类型 (prison_area_type) -- 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); 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 VALUES
(201901, 1, '普通监区', '1', 'primary', '', 'prison_area_type', '0', '普通管理监区', 'admin', NOW(), 'admin', NOW(), 0), (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), (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), (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) -- 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); 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 VALUES
(202001, 1, '启用', '1', 'success', '', 'prison_cell_status', '0', '监室启用', 'admin', NOW(), 'admin', NOW(), 0), (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); (202002, 2, '禁用', '2', 'danger', '', 'prison_cell_status', '0', '监室禁用', 'admin', NOW(), 'admin', NOW(), 0);

View File

@ -19,6 +19,12 @@ CREATE TABLE IF NOT EXISTS `prison_prisoner` (
`crime` varchar(200) NOT NULL COMMENT '罪名', `crime` varchar(200) NOT NULL COMMENT '罪名',
`sentence_years` int DEFAULT 0 COMMENT '刑期(年)', `sentence_years` int DEFAULT 0 COMMENT '刑期(年)',
`sentence_months` 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 '入狱日期', `imprisonment_date` date DEFAULT NULL COMMENT '入狱日期',
`release_date` date DEFAULT NULL COMMENT '释放日期', `release_date` date DEFAULT NULL COMMENT '释放日期',
`supervision_level` tinyint DEFAULT 2 COMMENT '监管等级1-严管 2-普管 3-宽管', `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_questionnaire_id` (`questionnaire_id`),
KEY `idx_prisoner_id` (`prisoner_id`) KEY `idx_prisoner_id` (`prisoner_id`)
) ENGINE=InnoDB COMMENT='问卷答题记录表'; ) 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='罪犯监区变动记录表';

View File

@ -101,4 +101,42 @@ public class PrisonAreaController {
BeanUtils.toBean(list, AreaRespVO.class)); BeanUtils.toBean(list, AreaRespVO.class));
} }
@GetMapping("/tree")
@Operation(summary = "获得监区树形结构")
@PreAuthorize("@ss.hasPermission('prison:area:query')")
public CommonResult<List<AreaRespVO>> 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<AreaDO> 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<List<AreaRespVO>> getChildAreas(@RequestParam("parentId") Long parentId) {
List<AreaDO> 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<List<AreaRespVO>> getParentAreas(@RequestParam(value = "level", required = false) Integer level) {
List<AreaDO> 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<Boolean> syncCurrentCount(@RequestParam("areaId") Long areaId) {
areaService.syncCurrentCount(areaId);
return success(true);
}
} }

View File

@ -24,8 +24,16 @@ public class AreaRespVO {
@ExcelProperty("监区编码") @ExcelProperty("监区编码")
private String code; private String code;
@Schema(description = "监区类型1-普通监区 2-严管监区 3-医院 4-禁闭室", example = "1") @Schema(description = "父级ID0表示顶级监区")
@ExcelProperty("监区类型1-普通监区 2-严管监区 3-医院 4-禁闭室") @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; private Integer type;
@Schema(description = "容纳人数") @Schema(description = "容纳人数")
@ -52,4 +60,7 @@ public class AreaRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "子监区列表,仅一级监区返回")
private List<AreaRespVO> children;
} }

View File

@ -20,7 +20,13 @@ public class AreaSaveReqVO {
@NotEmpty(message = "监区编码不能为空") @NotEmpty(message = "监区编码不能为空")
private String code; private String code;
@Schema(description = "监区类型1-普通监区 2-严管监区 3-医院 4-禁闭室", example = "1") @Schema(description = "父级ID0表示顶级监区")
private Long parentId;
@Schema(description = "级别1-监区(大队) 2-分监区(中队)")
private Integer level;
@Schema(description = "监区类型1-普通监区 2-严管监区 3-集训监区 4-出监监区 5-医院 6-禁闭室", example = "1")
private Integer type; private Integer type;
@Schema(description = "容纳人数") @Schema(description = "容纳人数")

View File

@ -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.Parameter;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.constraints.*;
import jakarta.validation.*; import jakarta.validation.*;
import jakarta.servlet.http.*; import jakarta.servlet.http.*;
import java.util.*; import java.util.*;
import java.io.IOException; 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.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@ -38,6 +39,9 @@ public class PrisonCellController {
@Resource @Resource
private CellService cellService; private CellService cellService;
@Resource
private AreaMapper areaMapper;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建监室信息") @Operation(summary = "创建监室信息")
@PreAuthorize("@ss.hasPermission('prison:cell:create')") @PreAuthorize("@ss.hasPermission('prison:cell:create')")
@ -77,15 +81,25 @@ public class PrisonCellController {
@PreAuthorize("@ss.hasPermission('prison:cell:query')") @PreAuthorize("@ss.hasPermission('prison:cell:query')")
public CommonResult<CellRespVO> getCell(@RequestParam("id") Long id) { public CommonResult<CellRespVO> getCell(@RequestParam("id") Long id) {
CellDO cell = cellService.getCell(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") @GetMapping("/page")
@Operation(summary = "获得监室信息分页") @Operation(summary = "获得监室信息分页")
@PreAuthorize("@ss.hasPermission('prison:cell:query')") @PreAuthorize("@ss.hasPermission('prison:cell:query')")
public CommonResult<PageResult<CellRespVO>> getCellPage(@Valid CellPageReqVO pageReqVO) { public CommonResult<PageResult<CellRespVO>> getCellPage(@Valid CellPageReqVO pageReqVO) {
PageResult<CellDO> pageResult = cellService.getCellPage(pageReqVO); return success(cellService.getCellPage(pageReqVO));
return success(BeanUtils.toBean(pageResult, CellRespVO.class));
} }
@GetMapping("/export-excel") @GetMapping("/export-excel")
@ -95,10 +109,9 @@ public class PrisonCellController {
public void exportCellExcel(@Valid CellPageReqVO pageReqVO, public void exportCellExcel(@Valid CellPageReqVO pageReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<CellDO> list = cellService.getCellPage(pageReqVO).getList(); List<CellRespVO> list = cellService.getCellPage(pageReqVO).getList();
// 导出 Excel // 导出 Excel
ExcelUtils.write(response, "监室信息.xls", "数据", CellRespVO.class, ExcelUtils.write(response, "监室信息.xls", "数据", CellRespVO.class, list);
BeanUtils.toBean(list, CellRespVO.class));
} }
} }

View File

@ -20,6 +20,10 @@ public class CellRespVO {
@ExcelProperty("所属监区ID") @ExcelProperty("所属监区ID")
private Long areaId; private Long areaId;
@Schema(description = "所属监区名称", example = "一监区")
@ExcelProperty("所属监区")
private String areaName;
@Schema(description = "监室名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") @Schema(description = "监室名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
@ExcelProperty("监室名称") @ExcelProperty("监室名称")
private String name; private String name;

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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<ChartDataVO> ageDistribution;
@Schema(description = "刑期分布")
private List<ChartDataVO> sentenceDistribution;
@Schema(description = "文化程度分布")
private List<ChartDataVO> educationDistribution;
@Schema(description = "省份分布")
private List<ProvinceChartVO> provinceDistribution;
}

View File

@ -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;
}

View File

@ -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.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 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.controller.admin.prisoner.vo.*;
import cn.iocoder.yudao.module.prison.convert.prisoner.PrisonerConvert; 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.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 cn.iocoder.yudao.module.prison.service.PrisonerService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; 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.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/** /**
* 服刑人员信息管理 Controller * 服刑人员信息管理 Controller
@ -39,6 +47,12 @@ public class PrisonerController {
@Resource @Resource
private PrisonerService prisonerService; private PrisonerService prisonerService;
@Resource
private AreaMapper areaMapper;
@Resource
private CellMapper cellMapper;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "新增服刑人员") @Operation(summary = "新增服刑人员")
@PreAuthorize("@ss.hasPermission('prison:prisoner:create')") @PreAuthorize("@ss.hasPermission('prison:prisoner:create')")
@ -76,21 +90,108 @@ public class PrisonerController {
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获取服刑人员详情") @Operation(summary = "获取服刑人员详情")
@Parameter(name = "id", description = "编号", required = true) @Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('prison:prisoner:read')")
public CommonResult<PrisonerRespVO> getPrisoner(@RequestParam("id") Long id) { public CommonResult<PrisonerRespVO> getPrisoner(@RequestParam("id") Long id) {
PrisonerDO prisoner = prisonerService.getPrisoner(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") @GetMapping("/page")
@Operation(summary = "获取服刑人员分页列表") @Operation(summary = "获取服刑人员分页列表")
@PreAuthorize("@ss.hasPermission('prison:prisoner:read')")
public CommonResult<PageResult<PrisonerRespVO>> getPrisonerPage(@Valid PrisonerPageReqVO reqVO) { public CommonResult<PageResult<PrisonerRespVO>> getPrisonerPage(@Valid PrisonerPageReqVO reqVO) {
PageResult<PrisonerDO> pageResult = prisonerService.getPrisonerPage(reqVO); return success(prisonerService.getPrisonerPage(reqVO));
return success(PrisonerConvert.INSTANCE.convertPage(pageResult));
} }
@GetMapping("/get-by-no") @GetMapping("/get-by-no")
@Operation(summary = "根据服刑人员编号获取服刑人员") @Operation(summary = "根据服刑人员编号获取服刑人员")
@Parameter(name = "prisonerNo", description = "服刑人员编号", required = true) @Parameter(name = "prisonerNo", description = "服刑人员编号", required = true)
@PreAuthorize("@ss.hasPermission('prison:prisoner:read')")
public CommonResult<PrisonerRespVO> getPrisonerByNo(@RequestParam("prisonerNo") String prisonerNo) { public CommonResult<PrisonerRespVO> getPrisonerByNo(@RequestParam("prisonerNo") String prisonerNo) {
PrisonerDO prisoner = prisonerService.getPrisonerByNo(prisonerNo); PrisonerDO prisoner = prisonerService.getPrisonerByNo(prisonerNo);
return success(PrisonerConvert.INSTANCE.convert(prisoner)); return success(PrisonerConvert.INSTANCE.convert(prisoner));
@ -101,9 +202,37 @@ public class PrisonerController {
@ApiAccessLog(operateType = EXPORT) @ApiAccessLog(operateType = EXPORT)
@PreAuthorize("@ss.hasPermission('prison:prisoner:export')") @PreAuthorize("@ss.hasPermission('prison:prisoner:export')")
public void exportExcel(HttpServletResponse response, @Valid PrisonerPageReqVO reqVO) throws IOException { public void exportExcel(HttpServletResponse response, @Valid PrisonerPageReqVO reqVO) throws IOException {
PageResult<PrisonerDO> pageResult = prisonerService.getPrisonerPage(reqVO); PageResult<PrisonerRespVO> pageResult = prisonerService.getPrisonerPage(reqVO);
List<PrisonerExcelVO> excelVOs = PrisonerConvert.INSTANCE.convertExcelList(pageResult.getList()); List<PrisonerExcelVO> excelVOs = PrisonerConvert.INSTANCE.convertExcelListFromRespVO(pageResult.getList());
ExcelUtils.write(response, "服刑人员数据.xls", "服刑人员列表", PrisonerExcelVO.class, excelVOs); 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<Boolean> 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<List<PrisonerAreaLogRespVO>> getAreaHistory(@RequestParam("id") Long id) {
List<PrisonerAreaLogDO> list = prisonerService.getAreaHistory(id);
return success(PrisonerAreaLogConvert.INSTANCE.convertList(list));
}
} }

View File

@ -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<Long> createPrisonerAreaLog(@Valid @RequestBody PrisonerAreaLogSaveReqVO reqVO) {
return success(prisonerAreaLogService.createPrisonerAreaLog(reqVO));
}
@PutMapping("/update")
@Operation(summary = "更新罪犯监区变动记录")
@PreAuthorize("@ss.hasPermission('prison:prisoner-area-log:update')")
public CommonResult<Boolean> 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<Boolean> 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<Boolean> deletePrisonerAreaLogList(@RequestParam("ids") List<Long> ids) {
prisonerAreaLogService.deletePrisonerAreaLogList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获取罪犯监区变动记录")
@Parameter(name = "id", description = "记录ID", required = true)
public CommonResult<PrisonerAreaLogRespVO> 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<PageResult<PrisonerAreaLogRespVO>> getPrisonerAreaLogPage(@Valid PrisonerAreaLogPageReqVO reqVO) {
PageResult<PrisonerAreaLogDO> 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<List<PrisonerAreaLogRespVO>> getPrisonerAreaLogListByPrisonerId(
@RequestParam("prisonerId") Long prisonerId) {
List<PrisonerAreaLogDO> list = prisonerAreaLogService.getPrisonerAreaLogListByPrisonerId(prisonerId);
return success(PrisonerAreaLogConvert.INSTANCE.convertList(list));
}
}

View File

@ -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;
}

View File

@ -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 = "沪狱刑调2024001号")
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;
}

View File

@ -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 = "沪狱刑调2024001号")
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;
}

View File

@ -28,9 +28,6 @@ public class PrisonerExcelVO {
@ExcelProperty("出生日期") @ExcelProperty("出生日期")
private LocalDate birthday; private LocalDate birthday;
@ExcelProperty("身份证号")
private String idCard;
@ExcelProperty("民族") @ExcelProperty("民族")
private String ethnicity; private String ethnicity;

View File

@ -61,12 +61,39 @@ public class PrisonerRespVO {
@Schema(description = "刑期(月)", example = "6") @Schema(description = "刑期(月)", example = "6")
private Integer sentenceMonths; 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") @Schema(description = "入狱日期", example = "2024-01-01")
private LocalDate imprisonmentDate; private LocalDate imprisonmentDate;
@Schema(description = "释放日期", example = "2027-07-01") @Schema(description = "释放日期", example = "2027-07-01")
private LocalDate releaseDate; 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") @Schema(description = "监管等级", example = "2")
private Integer supervisionLevel; private Integer supervisionLevel;

View File

@ -1,8 +1,7 @@
package cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo; package cn.iocoder.yudao.module.prison.controller.admin.prisoner.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.*;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@ -21,10 +20,12 @@ public class PrisonerSaveReqVO {
@Schema(description = "服刑人员编号", example = "ZF2024001") @Schema(description = "服刑人员编号", example = "ZF2024001")
@NotBlank(message = "服刑人员编号不能为空") @NotBlank(message = "服刑人员编号不能为空")
@Size(max = 50, message = "服刑人员编号长度不能超过50")
private String prisonerNo; private String prisonerNo;
@Schema(description = "姓名", example = "张三") @Schema(description = "姓名", example = "张三")
@NotBlank(message = "姓名不能为空") @NotBlank(message = "姓名不能为空")
@Size(max = 50, message = "姓名长度不能超过50")
private String name; private String name;
@Schema(description = "性别", example = "1", required = true) @Schema(description = "性别", example = "1", required = true)
@ -36,33 +37,69 @@ public class PrisonerSaveReqVO {
private LocalDate birthday; private LocalDate birthday;
@Schema(description = "身份证号", example = "310101199001011234") @Schema(description = "身份证号", example = "310101199001011234")
@Pattern(regexp = "^[0-9]{17}[0-9Xx]$", message = "身份证号格式不正确")
private String idCard; private String idCard;
@Schema(description = "民族", example = "汉族") @Schema(description = "民族", example = "汉族")
@Size(max = 50, message = "民族长度不能超过50")
private String ethnicity; private String ethnicity;
@Schema(description = "籍贯", example = "上海") @Schema(description = "籍贯", example = "上海")
@Size(max = 100, message = "籍贯长度不能超过100")
private String nativePlace; private String nativePlace;
@Schema(description = "文化程度", example = "3") @Schema(description = "文化程度", example = "3")
private Integer education; private Integer education;
@Schema(description = "职业", example = "无业") @Schema(description = "职业", example = "无业")
@Size(max = 100, message = "职业长度不能超过100")
private String occupation; private String occupation;
@Schema(description = "家庭住址", example = "上海市浦东新区xxx") @Schema(description = "家庭住址", example = "上海市浦东新区xxx")
@Size(max = 500, message = "家庭住址长度不能超过500")
private String address; private String address;
@Schema(description = "罪名", example = "盗窃罪", required = true) @Schema(description = "罪名", example = "盗窃罪", required = true)
@NotBlank(message = "罪名不能为空") @NotBlank(message = "罪名不能为空")
@Size(max = 100, message = "罪名长度不能超过100")
private String crime; private String crime;
@Schema(description = "刑期(年)", example = "3") @Schema(description = "刑期(年)", example = "3")
@Min(value = 0, message = "刑期(年)不能为负数")
@Max(value = 150, message = "刑期不能超过150")
private Integer sentenceYears; private Integer sentenceYears;
@Schema(description = "刑期(月)", example = "6") @Schema(description = "刑期(月)", example = "6")
@Min(value = 0, message = "刑期(月)不能为负数")
@Max(value = 11, message = "刑期不能超过11")
private Integer sentenceMonths; 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) @Schema(description = "入狱日期", example = "2024-01-01", required = true)
@NotNull(message = "入狱日期不能为空") @NotNull(message = "入狱日期不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
@ -88,6 +125,7 @@ public class PrisonerSaveReqVO {
private Integer status; private Integer status;
@Schema(description = "备注", example = "") @Schema(description = "备注", example = "")
@Size(max = 500, message = "备注长度不能超过500")
private String remark; private String remark;
} }

View File

@ -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;
}

View File

@ -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<Long> createRelease(@Valid @RequestBody ReleaseSaveReqVO createReqVO) {
return success(releaseService.createRelease(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新释放登记")
@PreAuthorize("@ss.hasPermission('prison:release:update')")
public CommonResult<Boolean> updateRelease(@Valid @RequestBody ReleaseSaveReqVO updateReqVO) {
releaseService.updateRelease(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除释放登记")
@PreAuthorize("@ss.hasPermission('prison:release:delete')")
public CommonResult<Boolean> deleteRelease(@RequestParam("id") Long id) {
releaseService.deleteRelease(id);
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "批量删除释放登记")
@PreAuthorize("@ss.hasPermission('prison:release:delete')")
public CommonResult<Boolean> deleteReleaseList(@RequestParam("ids") List<Long> ids) {
releaseService.deleteReleaseListByIds(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得释放登记")
@PreAuthorize("@ss.hasPermission('prison:release:query')")
public CommonResult<ReleaseRespVO> 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<PageResult<ReleaseRespVO>> getReleasePage(@Valid ReleasePageReqVO pageReqVO) {
PageResult<ReleaseDO> pageResult = releaseService.getReleasePage(pageReqVO);
List<ReleaseRespVO> 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<Boolean> 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<Boolean> 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 -> "";
};
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<Long> createScoreDetail(@Valid @RequestBody ScoreDetailSaveReqVO createReqVO) {
return success(scoreDetailService.createScoreDetail(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新考核记录")
@PreAuthorize("@ss.hasPermission('prison:score-detail:update')")
public CommonResult<Boolean> updateScoreDetail(@Valid @RequestBody ScoreDetailSaveReqVO updateReqVO) {
scoreDetailService.updateScoreDetail(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除考核记录")
@PreAuthorize("@ss.hasPermission('prison:score-detail:delete')")
public CommonResult<Boolean> 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<Boolean> deleteScoreDetailList(@RequestParam("ids") List<Long> ids) {
scoreDetailService.deleteScoreDetailListByIds(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得考核记录")
@PreAuthorize("@ss.hasPermission('prison:score-detail:query')")
public CommonResult<ScoreDetailRespVO> 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<PageResult<ScoreDetailRespVO>> getScoreDetailPage(@Valid ScoreDetailPageReqVO pageReqVO) {
PageResult<ScoreDetailDO> pageResult = scoreDetailService.getScoreDetailPage(pageReqVO);
List<ScoreDetailRespVO> list = pageResult.getList().stream()
.map(item -> BeanUtils.toBean(item, ScoreDetailRespVO.class))
.collect(Collectors.toList());
return success(new PageResult<>(list, pageResult.getTotal()));
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<Long> createScoreRule(@Valid @RequestBody ScoreRuleSaveReqVO createReqVO) {
return success(scoreRuleService.createScoreRule(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新考核规则")
@PreAuthorize("@ss.hasPermission('prison:score-rule:update')")
public CommonResult<Boolean> updateScoreRule(@Valid @RequestBody ScoreRuleSaveReqVO updateReqVO) {
scoreRuleService.updateScoreRule(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除考核规则")
@PreAuthorize("@ss.hasPermission('prison:score-rule:delete')")
public CommonResult<Boolean> 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<Boolean> deleteScoreRuleList(@RequestParam("ids") List<Long> ids) {
scoreRuleService.deleteScoreRuleListByIds(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得考核规则")
@PreAuthorize("@ss.hasPermission('prison:score-rule:query')")
public CommonResult<ScoreRuleRespVO> 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<PageResult<ScoreRuleRespVO>> getScoreRulePage(@Valid ScoreRulePageReqVO pageReqVO) {
PageResult<ScoreRuleDO> pageResult = scoreRuleService.getScoreRulePage(pageReqVO);
List<ScoreRuleRespVO> 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<List<ScoreRuleRespVO>> getScoreRuleListByCategory(
@RequestParam("category") Integer category) {
List<ScoreRuleDO> list = scoreRuleService.getScoreRuleListByCategory(category);
return success(list.stream()
.map(item -> BeanUtils.toBean(item, ScoreRuleRespVO.class))
.collect(Collectors.toList()));
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<AreaRespVO> convertList(List<AreaDO> list);
PageResult<AreaRespVO> convertPage(PageResult<AreaDO> page);
}

View File

@ -3,7 +3,14 @@ package cn.iocoder.yudao.module.prison.convert.prisoner;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.*;
import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; 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.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.util.List; import java.util.List;
@ -18,8 +25,33 @@ public interface PrisonerConvert {
PrisonerConvert INSTANCE = Mappers.getMapper(PrisonerConvert.class); 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); 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); PrisonerRespVO convert(PrisonerDO bean);
List<PrisonerRespVO> convertList(List<PrisonerDO> list); List<PrisonerRespVO> convertList(List<PrisonerDO> list);
@ -28,4 +60,44 @@ public interface PrisonerConvert {
List<PrisonerExcelVO> convertExcelList(List<PrisonerDO> list); List<PrisonerExcelVO> convertExcelList(List<PrisonerDO> list);
List<PrisonerExcelVO> convertExcelListFromRespVO(List<PrisonerRespVO> 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<PrisonerDO> page, PageResult<PrisonerRespVO> result) {
if (page.getList() != null) {
for (int i = 0; i < page.getList().size(); i++) {
afterConvert(page.getList().get(i), result.getList().get(i));
}
}
}
} }

View File

@ -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<PrisonerAreaLogRespVO> convertList(List<PrisonerAreaLogDO> list);
PageResult<PrisonerAreaLogRespVO> convertPage(PageResult<PrisonerAreaLogDO> page);
}

View File

@ -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;
}

View File

@ -92,6 +92,36 @@ public class PrisonerDO extends BaseDO {
*/ */
private Integer sentenceMonths; 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; 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; private Long prisonAreaId;
/**
* 当前分区ID
*/
private Long subAreaId;
/** /**
* 当前监室ID * 当前监室ID
*/ */

View File

@ -6,6 +6,7 @@ import java.time.LocalDateTime;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableField;
/** /**
* 监区信息 DO * 监区信息 DO
@ -36,9 +37,17 @@ public class AreaDO extends BaseDO {
*/ */
private String code; private String code;
/** /**
* 监区类型1-普通监区 2-严管监区 3-医院 4-禁闭室 * 监区类型1-普通监区 2-严管监区 3-集训监区 4-出监监区 5-医院 6-禁闭室
*/ */
private Integer type; private Integer type;
/**
* 父级ID0表示顶级监区
*/
private Long parentId;
/**
* 级别1-监区(大队) 2-分监区(中队)
*/
private Integer level;
/** /**
* 容纳人数 * 容纳人数
*/ */
@ -60,5 +69,11 @@ public class AreaDO extends BaseDO {
*/ */
private String remark; private String remark;
/**
* 子监区列表非数据库字段
*/
@TableField(exist = false)
private List<AreaDO> children;
} }

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<PrisonerAreaLogDO> {
}

View File

@ -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.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO; import cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/** /**
* 服刑人员信息 Mapper * 服刑人员信息 Mapper
@ -12,4 +13,20 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper
public interface PrisonerMapper extends BaseMapperX<PrisonerDO> { public interface PrisonerMapper extends BaseMapperX<PrisonerDO> {
/**
* 统计某监区含子监区下的罪犯数量
*
* @param areaId 监区ID
* @return 罪犯数量
*/
Integer countByAreaIdOrChildren(@Param("areaId") Long areaId);
/**
* 统计直接属于某监区的罪犯数量不含子监区
*
* @param areaId 监区ID
* @return 罪犯数量
*/
Integer countByDirectAreaId(@Param("areaId") Long areaId);
} }

View File

@ -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<ChartDataVO> 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<ChartDataVO> 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<ChartDataVO> 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<ProvinceChartVO> 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;
}
}
}

View File

@ -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<ReleaseDO> {
}

View File

@ -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<ScoreDetailDO> {
}

View File

@ -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<ScoreRuleDO> {
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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<Integer> {
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;
}
}

View File

@ -12,4 +12,18 @@ public interface DictTypeConstants {
String PRISONER_STATUS = "prisoner_status"; // 服刑人员状态 String PRISONER_STATUS = "prisoner_status"; // 服刑人员状态
String PRISON_EDUCATION = "prison_education"; // 文化程度 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"; // 考核类别
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.prison.enums; package cn.iocoder.yudao.module.prison.enums;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -22,6 +23,7 @@ public enum EducationEnum {
BACHELOR_OR_ABOVE(7, "本科及以上"); BACHELOR_OR_ABOVE(7, "本科及以上");
@EnumValue @EnumValue
@JsonValue
private final Integer value; private final Integer value;
private final String name; private final String name;

View File

@ -12,6 +12,7 @@ public class ErrorCodeConstants {
// ========== 服刑人员信息 1xxxx ========== // ========== 服刑人员信息 1xxxx ==========
public static final ErrorCode PRISONER_NOT_EXISTS = new ErrorCode(1_000_001, "服刑人员信息不存在"); 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_NO_EXISTS = new ErrorCode(1_000_002, "服刑人员编号【{0}】已存在");
public static final ErrorCode PRISONER_DATE_INVALID = new ErrorCode(1_000_003, "释放日期必须晚于入狱日期");
// ========== 监区管理 2xxxx ========== // ========== 监区管理 2xxxx ==========
public static final ErrorCode PRISON_AREA_NOT_EXISTS = new ErrorCode(2_000_001, "监区信息不存在"); public static final ErrorCode PRISON_AREA_NOT_EXISTS = new ErrorCode(2_000_001, "监区信息不存在");
@ -35,6 +36,9 @@ public class ErrorCodeConstants {
// ========== 消费记录 7xxxx ========== // ========== 消费记录 7xxxx ==========
public static final ErrorCode PRISON_CONSUMPTION_NOT_EXISTS = new ErrorCode(7_000_001, "消费记录不存在"); 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生成的代码) ========== // ========== 别名 (兼容codegen生成的代码) ==========
public static final ErrorCode AREA_NOT_EXISTS = PRISON_AREA_NOT_EXISTS; public static final ErrorCode AREA_NOT_EXISTS = PRISON_AREA_NOT_EXISTS;
public static final ErrorCode CELL_NOT_EXISTS = PRISON_CELL_NOT_EXISTS; public static final ErrorCode CELL_NOT_EXISTS = PRISON_CELL_NOT_EXISTS;

View File

@ -1,9 +1,12 @@
package cn.iocoder.yudao.module.prison.enums; package cn.iocoder.yudao.module.prison.enums;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
/** /**
* 性别枚举 * 性别枚举
* *
@ -17,7 +20,15 @@ public enum GenderEnum {
FEMALE(2, ""); FEMALE(2, "");
@EnumValue @EnumValue
@JsonValue
private final Integer value; private final Integer value;
private final String name; private final String name;
public static GenderEnum fromValue(Integer value) {
return Arrays.stream(values())
.filter(e -> e.getValue().equals(value))
.findFirst()
.orElse(null);
}
} }

View File

@ -1,9 +1,12 @@
package cn.iocoder.yudao.module.prison.enums; package cn.iocoder.yudao.module.prison.enums;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
/** /**
* 服刑人员状态枚举 * 服刑人员状态枚举
* *
@ -20,7 +23,15 @@ public enum PrisonerStatusEnum {
DECEASED(5, "已死亡"); DECEASED(5, "已死亡");
@EnumValue @EnumValue
@JsonValue
private final Integer value; private final Integer value;
private final String name; private final String name;
public static PrisonerStatusEnum fromValue(Integer value) {
return Arrays.stream(values())
.filter(e -> e.getValue().equals(value))
.findFirst()
.orElse(null);
}
} }

View File

@ -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;
}

View File

@ -1,9 +1,12 @@
package cn.iocoder.yudao.module.prison.enums; package cn.iocoder.yudao.module.prison.enums;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
/** /**
* 风险等级枚举 * 风险等级枚举
* *
@ -18,7 +21,15 @@ public enum RiskLevelEnum {
LOW(3, "低风险"); LOW(3, "低风险");
@EnumValue @EnumValue
@JsonValue
private final Integer value; private final Integer value;
private final String name; private final String name;
public static RiskLevelEnum fromValue(Integer value) {
return Arrays.stream(values())
.filter(e -> e.getValue().equals(value))
.findFirst()
.orElse(null);
}
} }

View File

@ -1,9 +1,12 @@
package cn.iocoder.yudao.module.prison.enums; package cn.iocoder.yudao.module.prison.enums;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.Arrays;
/** /**
* 监管等级枚举 * 监管等级枚举
* *
@ -18,7 +21,15 @@ public enum SupervisionLevelEnum {
RELAXED(3, "宽管级"); RELAXED(3, "宽管级");
@EnumValue @EnumValue
@JsonValue
private final Integer value; private final Integer value;
private final String name; private final String name;
public static SupervisionLevelEnum fromValue(Integer value) {
return Arrays.stream(values())
.filter(e -> e.getValue().equals(value))
.findFirst()
.orElse(null);
}
} }

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.prison.service;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.*;
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.PrisonerDO;
import java.util.List; import java.util.List;
@ -56,7 +57,7 @@ public interface PrisonerService {
* @param reqVO 查询条件 * @param reqVO 查询条件
* @return 服刑人员分页列表 * @return 服刑人员分页列表
*/ */
PageResult<PrisonerDO> getPrisonerPage(PrisonerPageReqVO reqVO); PageResult<PrisonerRespVO> getPrisonerPage(PrisonerPageReqVO reqVO);
/** /**
* 根据服刑人员编号获取服刑人员 * 根据服刑人员编号获取服刑人员
@ -66,4 +67,20 @@ public interface PrisonerService {
*/ */
PrisonerDO getPrisonerByNo(String prisonerNo); PrisonerDO getPrisonerByNo(String prisonerNo);
/**
* 执行调监
*
* @param reqVO 调监请求
* @param operatorId 操作人ID
*/
void doTransfer(TransferReqVO reqVO, Long operatorId);
/**
* 获取罪犯位置历史轨迹
*
* @param prisonerId 罪犯ID
* @return 位置历史记录列表
*/
List<PrisonerAreaLogDO> getAreaHistory(Long prisonerId);
} }

View File

@ -14,6 +14,40 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
*/ */
public interface AreaService { public interface AreaService {
/**
* 获取监区树形结构
*
* @param name 监区名称可选
* @param type 监区类型可选
* @param level 监区级别可选
* @param status 状态可选
* @return 树形结构列表
*/
List<AreaDO> getAreaTree(String name, Integer type, Integer level, Integer status);
/**
* 获取子监区列表
*
* @param parentId 父级ID
* @return 子监区列表
*/
List<AreaDO> getChildAreas(Long parentId);
/**
* 获取父级监区列表用于新增/编辑时选择
*
* @param level 监区级别可选
* @return 父级监区列表
*/
List<AreaDO> getParentAreas(Integer level);
/**
* 同步监区人数
*
* @param areaId 监区ID
*/
void syncCurrentCount(Long areaId);
/** /**
* 创建监区信息 * 创建监区信息
* *

View File

@ -7,6 +7,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.yudao.module.prison.controller.admin.area.vo.*; import cn.iocoder.yudao.module.prison.controller.admin.area.vo.*;
import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO; import cn.iocoder.yudao.module.prison.dal.dataobject.area.AreaDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.prison.dal.mysql.area.AreaMapper; 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.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.convertList;
@ -32,6 +34,9 @@ public class AreaServiceImpl implements AreaService {
@Resource @Resource
private AreaMapper areaMapper; private AreaMapper areaMapper;
@Resource
private PrisonerMapper prisonerMapper;
@Override @Override
public Long createArea(AreaSaveReqVO createReqVO) { public Long createArea(AreaSaveReqVO createReqVO) {
// 插入 // 插入
@ -79,7 +84,153 @@ public class AreaServiceImpl implements AreaService {
@Override @Override
public PageResult<AreaDO> getAreaPage(AreaPageReqVO pageReqVO) { public PageResult<AreaDO> getAreaPage(AreaPageReqVO pageReqVO) {
return areaMapper.selectPage(pageReqVO); PageResult<AreaDO> pageResult = areaMapper.selectPage(pageReqVO);
// 为每个一级监区填充子监区
List<AreaDO> list = pageResult.getList();
for (AreaDO area : list) {
if (area.getParentId() == null || area.getParentId() == 0) {
// 只为顶级监区查询子监区
List<AreaDO> children = areaMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<AreaDO>()
.eq(AreaDO::getParentId, area.getId())
.eq(AreaDO::getDeleted, false)
.orderByAsc(AreaDO::getSort));
area.setChildren(children);
}
}
return pageResult;
}
@Override
public List<AreaDO> getAreaTree(String name, Integer type, Integer level, Integer status) {
// 构建基础查询条件不带名称模糊查询先获取所有数据
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<AreaDO> baseWrapper =
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<AreaDO>()
.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<AreaDO> allAreas = areaMapper.selectList(baseWrapper);
// 如果有名称过滤先获取匹配的节点ID
if (name != null && !name.isEmpty()) {
Set<Long> finalMatchedIds = allAreas.stream()
.filter(area -> area.getName() != null && area.getName().contains(name))
.map(AreaDO::getId)
.collect(Collectors.toSet());
// 递归获取所有父节点ID确保树结构完整
Set<Long> parentIds = new java.util.HashSet<>();
Set<Long> toFind = new java.util.HashSet<>(finalMatchedIds);
while (!toFind.isEmpty()) {
Set<Long> 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<Long> filterIds = finalMatchedIds;
// 过滤只保留匹配的节点和父节点
allAreas = allAreas.stream()
.filter(area -> filterIds.contains(area.getId()))
.collect(Collectors.toList());
}
// 构建树形结构
// 1. 找出所有顶级节点parentId 为空或为 0 parentId 不在列表中
Set<Long> allIds = allAreas.stream().map(AreaDO::getId).collect(Collectors.toSet());
List<AreaDO> 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<AreaDO> allAreas) {
List<AreaDO> 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<AreaDO> getChildAreas(Long parentId) {
return areaMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<AreaDO>()
.eq(AreaDO::getParentId, parentId)
.eq(AreaDO::getDeleted, false)
.orderByAsc(AreaDO::getSort));
}
@Override
public List<AreaDO> getParentAreas(Integer level) {
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<AreaDO> queryWrapper =
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<AreaDO>()
.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<AreaDO> 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);
} }
} }

View File

@ -57,6 +57,6 @@ public interface CellService {
* @param pageReqVO 分页查询 * @param pageReqVO 分页查询
* @return 监室信息分页 * @return 监室信息分页
*/ */
PageResult<CellDO> getCellPage(CellPageReqVO pageReqVO); PageResult<CellRespVO> getCellPage(CellPageReqVO pageReqVO);
} }

View File

@ -7,17 +7,20 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; 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.controller.admin.cell.vo.*;
import cn.iocoder.yudao.module.prison.dal.dataobject.cell.CellDO; 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.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.prison.dal.mysql.cell.CellMapper;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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.*; import static cn.iocoder.yudao.module.prison.enums.ErrorCodeConstants.*;
/** /**
@ -32,6 +35,9 @@ public class CellServiceImpl implements CellService {
@Resource @Resource
private CellMapper cellMapper; private CellMapper cellMapper;
@Resource
private AreaMapper areaMapper;
@Override @Override
public Long createCell(CellSaveReqVO createReqVO) { public Long createCell(CellSaveReqVO createReqVO) {
// 插入 // 插入
@ -78,8 +84,47 @@ public class CellServiceImpl implements CellService {
} }
@Override @Override
public PageResult<CellDO> getCellPage(CellPageReqVO pageReqVO) { public PageResult<CellRespVO> getCellPage(CellPageReqVO pageReqVO) {
return cellMapper.selectPage(pageReqVO); // 查询监室分页数据
PageResult<CellDO> pageResult = cellMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<CellDO>()
.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<Long> areaIds = pageResult.getList().stream()
.map(CellDO::getAreaId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 查询监区信息
final Map<Long, AreaDO> areaMap;
if (CollUtil.isNotEmpty(areaIds)) {
List<AreaDO> areas = areaMapper.selectList(new LambdaQueryWrapperX<AreaDO>()
.inIfPresent(AreaDO::getId, new ArrayList<>(areaIds)));
areaMap = areas.stream()
.collect(Collectors.toMap(AreaDO::getId, Function.identity()));
} else {
areaMap = new HashMap<>();
}
// 转换为 RespVO填充监区名称
List<CellRespVO> 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());
} }
} }

View File

@ -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();
}

View File

@ -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<ChartDataVO> 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<ProvinceChartVO> convertProvinceData(List<ProvinceChartVO> 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<Integer, String> 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, "未知");
}
}

View File

@ -2,10 +2,21 @@ package cn.iocoder.yudao.module.prison.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.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.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.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 cn.iocoder.yudao.module.prison.service.PrisonerService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -13,6 +24,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -30,6 +42,15 @@ public class PrisonerServiceImpl implements PrisonerService {
@Resource @Resource
private PrisonerMapper prisonerMapper; private PrisonerMapper prisonerMapper;
@Resource
private PrisonerAreaLogMapper areaLogMapper;
@Resource
private CellMapper cellMapper;
@Resource
private AreaMapper areaMapper;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createPrisoner(PrisonerSaveReqVO reqVO) { public Long createPrisoner(PrisonerSaveReqVO reqVO) {
@ -39,12 +60,26 @@ public class PrisonerServiceImpl implements PrisonerService {
throw exception(PRISONER_NO_EXISTS, reqVO.getPrisonerNo()); throw exception(PRISONER_NO_EXISTS, reqVO.getPrisonerNo());
} }
// 校验日期释放日期必须晚于入狱日期
validatePrisonerDates(reqVO.getImprisonmentDate(), reqVO.getReleaseDate());
// 插入 // 插入
PrisonerDO prisoner = PrisonerConvert.INSTANCE.convert(reqVO); PrisonerDO prisoner = PrisonerConvert.INSTANCE.convert(reqVO);
prisonerMapper.insert(prisoner); prisonerMapper.insert(prisoner);
return prisoner.getId(); 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 @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updatePrisoner(PrisonerSaveReqVO reqVO) { public void updatePrisoner(PrisonerSaveReqVO reqVO) {
@ -60,6 +95,9 @@ public class PrisonerServiceImpl implements PrisonerService {
throw exception(PRISONER_NO_EXISTS, reqVO.getPrisonerNo()); throw exception(PRISONER_NO_EXISTS, reqVO.getPrisonerNo());
} }
// 校验日期释放日期必须晚于入狱日期
validatePrisonerDates(reqVO.getImprisonmentDate(), reqVO.getReleaseDate());
// 更新 // 更新
PrisonerDO updateObj = PrisonerConvert.INSTANCE.convert(reqVO); PrisonerDO updateObj = PrisonerConvert.INSTANCE.convert(reqVO);
prisonerMapper.updateById(updateObj); prisonerMapper.updateById(updateObj);
@ -97,7 +135,7 @@ public class PrisonerServiceImpl implements PrisonerService {
} }
@Override @Override
public PageResult<PrisonerDO> getPrisonerPage(PrisonerPageReqVO reqVO) { public PageResult<PrisonerRespVO> getPrisonerPage(PrisonerPageReqVO reqVO) {
LambdaQueryWrapper<PrisonerDO> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<PrisonerDO> wrapper = new LambdaQueryWrapper<>();
wrapper.like(reqVO.getPrisonerNo() != null, PrisonerDO::getPrisonerNo, reqVO.getPrisonerNo()) wrapper.like(reqVO.getPrisonerNo() != null, PrisonerDO::getPrisonerNo, reqVO.getPrisonerNo())
.like(reqVO.getName() != null, PrisonerDO::getName, reqVO.getName()) .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()) .eq(reqVO.getStatus() != null, PrisonerDO::getStatus, reqVO.getStatus())
.ge(reqVO.getImprisonmentDateStart() != null, PrisonerDO::getImprisonmentDate, reqVO.getImprisonmentDateStart()) .ge(reqVO.getImprisonmentDateStart() != null, PrisonerDO::getImprisonmentDate, reqVO.getImprisonmentDateStart())
.le(reqVO.getImprisonmentDateEnd() != null, PrisonerDO::getImprisonmentDate, reqVO.getImprisonmentDateEnd()); .le(reqVO.getImprisonmentDateEnd() != null, PrisonerDO::getImprisonmentDate, reqVO.getImprisonmentDateEnd());
return prisonerMapper.selectPage(reqVO, wrapper); PageResult<PrisonerDO> pageResult = prisonerMapper.selectPage(reqVO, wrapper);
// 转换为 VO 并设置关联字段
PageResult<PrisonerRespVO> 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 @Override
@ -120,4 +251,75 @@ public class PrisonerServiceImpl implements PrisonerService {
.eq(PrisonerDO::getPrisonerNo, prisonerNo)); .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<PrisonerAreaLogDO> getAreaHistory(Long prisonerId) {
return areaLogMapper.selectList(new LambdaQueryWrapper<PrisonerAreaLogDO>()
.eq(PrisonerAreaLogDO::getPrisonerId, prisonerId)
.orderByDesc(PrisonerAreaLogDO::getOperateTime));
}
} }

View File

@ -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<Long> ids) {
// 校验存在
List<PrisonerAreaLogDO> 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<PrisonerAreaLogDO> getPrisonerAreaLogPage(PrisonerAreaLogPageReqVO reqVO) {
LambdaQueryWrapper<PrisonerAreaLogDO> 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<PrisonerAreaLogDO> getPrisonerAreaLogListByPrisonerId(Long prisonerId) {
return prisonerAreaLogMapper.selectList(new LambdaQueryWrapper<PrisonerAreaLogDO>()
.eq(PrisonerAreaLogDO::getPrisonerId, prisonerId)
.orderByDesc(PrisonerAreaLogDO::getOperateTime));
}
}

View File

@ -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<Long> ids);
/**
* 获取罪犯监区变动记录
*
* @param id 记录ID
* @return 变动记录
*/
PrisonerAreaLogDO getPrisonerAreaLog(Long id);
/**
* 获取罪犯监区变动记录分页列表
*
* @param reqVO 查询条件
* @return 变动记录分页列表
*/
PageResult<PrisonerAreaLogDO> getPrisonerAreaLogPage(PrisonerAreaLogPageReqVO reqVO);
/**
* 获取罪犯的监区变动记录列表
*
* @param prisonerId 罪犯ID
* @return 变动记录列表
*/
List<PrisonerAreaLogDO> getPrisonerAreaLogListByPrisonerId(Long prisonerId);
}

View File

@ -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<Long> ids);
/**
* 获得释放登记
*
* @param id 编号
* @return 释放登记
*/
ReleaseDO getRelease(Long id);
/**
* 获得释放登记分页
*
* @param pageReqVO 分页查询
* @return 释放登记分页
*/
PageResult<ReleaseDO> 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);
}

View File

@ -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<Long> ids) {
releaseMapper.deleteBatchIds(ids);
}
@Override
public ReleaseDO getRelease(Long id) {
return releaseMapper.selectById(id);
}
@Override
public PageResult<ReleaseDO> getReleasePage(ReleasePageReqVO pageReqVO) {
LambdaQueryWrapper<ReleaseDO> 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 -> "";
};
}
}

View File

@ -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 // 释放超期
}
}

View File

@ -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<PrisonerDO> upcomingList = prisonerMapper.selectList(
new LambdaQueryWrapper<PrisonerDO>()
.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<PrisonerDO> overdueList = prisonerMapper.selectList(
new LambdaQueryWrapper<PrisonerDO>()
.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);
}
}
}

View File

@ -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<Long> ids);
/**
* 获得考核记录
*
* @param id 编号
* @return 考核记录
*/
ScoreDetailDO getScoreDetail(Long id);
/**
* 获得考核记录分页
*
* @param pageReqVO 分页查询
* @return 考核记录分页
*/
PageResult<ScoreDetailDO> getScoreDetailPage(ScoreDetailPageReqVO pageReqVO);
}

View File

@ -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<Long> ids) {
scoreDetailMapper.deleteBatchIds(ids);
}
@Override
public ScoreDetailDO getScoreDetail(Long id) {
return scoreDetailMapper.selectById(id);
}
@Override
public PageResult<ScoreDetailDO> getScoreDetailPage(ScoreDetailPageReqVO pageReqVO) {
LambdaQueryWrapper<ScoreDetailDO> 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);
}
}

View File

@ -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<Long> ids);
/**
* 获得考核规则
*
* @param id 编号
* @return 考核规则
*/
ScoreRuleDO getScoreRule(Long id);
/**
* 获得考核规则分页
*
* @param pageReqVO 分页查询
* @return 考核规则分页
*/
PageResult<ScoreRuleDO> getScoreRulePage(ScoreRulePageReqVO pageReqVO);
/**
* 根据类别获取考核规则列表
*
* @param category 类别
* @return 考核规则列表
*/
List<ScoreRuleDO> getScoreRuleListByCategory(Integer category);
}

View File

@ -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<ScoreRuleDO>()
.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<ScoreRuleDO>()
.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<Long> ids) {
scoreRuleMapper.deleteBatchIds(ids);
}
@Override
public ScoreRuleDO getScoreRule(Long id) {
return scoreRuleMapper.selectById(id);
}
@Override
public PageResult<ScoreRuleDO> getScoreRulePage(ScoreRulePageReqVO pageReqVO) {
LambdaQueryWrapper<ScoreRuleDO> 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<ScoreRuleDO> getScoreRuleListByCategory(Integer category) {
return scoreRuleMapper.selectList(new LambdaQueryWrapper<ScoreRuleDO>()
.eq(ScoreRuleDO::getCategory, category)
.eq(ScoreRuleDO::getStatus, 1) // 只查询启用的规则
.orderByAsc(ScoreRuleDO::getSort));
}
}

View File

@ -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);
}

View File

@ -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方法
}
}

View File

@ -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();
}
}

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper"> <mapper namespace="cn.iocoder.yudao.module.prison.dal.mysql.PrisonerMapper">
<resultMap id="BaseResultMap" type="cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO"> <resultMap id="BaseResultMap" type="cn.iocoder.yudao.module.prison.dal.dataobject.PrisonerDO" autoMapping="true">
<id property="id" column="id"/> <id property="id" column="id"/>
<result property="tenantId" column="tenant_id"/> <result property="tenantId" column="tenant_id"/>
<result property="prisonerNo" column="prisoner_no"/> <result property="prisonerNo" column="prisoner_no"/>
@ -18,11 +18,21 @@
<result property="crime" column="crime"/> <result property="crime" column="crime"/>
<result property="sentenceYears" column="sentence_years"/> <result property="sentenceYears" column="sentence_years"/>
<result property="sentenceMonths" column="sentence_months"/> <result property="sentenceMonths" column="sentence_months"/>
<result property="lifeImprisonment" column="life_imprisonment"/>
<result property="deathSentenceReprieve" column="death_sentence_reprieve"/>
<result property="courtName" column="court_name"/>
<result property="judgmentDate" column="judgment_date"/>
<result property="judgmentNo" column="judgment_no"/>
<result property="originalSentence" column="original_sentence"/>
<result property="imprisonmentDate" column="imprisonment_date"/> <result property="imprisonmentDate" column="imprisonment_date"/>
<result property="releaseDate" column="release_date"/> <result property="releaseDate" column="release_date"/>
<result property="releaseType" column="release_type"/>
<result property="releaseReason" column="release_reason"/>
<result property="photo" column="photo"/>
<result property="supervisionLevel" column="supervision_level"/> <result property="supervisionLevel" column="supervision_level"/>
<result property="riskLevel" column="risk_level"/> <result property="riskLevel" column="risk_level"/>
<result property="prisonAreaId" column="prison_area_id"/> <result property="prisonAreaId" column="prison_area_id"/>
<result property="subAreaId" column="sub_area_id"/>
<result property="prisonCellId" column="prison_cell_id"/> <result property="prisonCellId" column="prison_cell_id"/>
<result property="status" column="status"/> <result property="status" column="status"/>
<result property="remark" column="remark"/> <result property="remark" column="remark"/>
@ -31,6 +41,28 @@
<result property="updater" column="updater"/> <result property="updater" column="updater"/>
<result property="updateTime" column="update_time"/> <result property="updateTime" column="update_time"/>
<result property="deleted" column="deleted"/> <result property="deleted" column="deleted"/>
<!-- 注意prisonAreaName 和 prisonCellName 是非数据库字段,使用 @TableField(exist = false) -->
<!-- 不要在这里添加这两个字段的映射,否则 MPJ 拦截器会尝试查询这些列 -->
</resultMap> </resultMap>
<!-- 统计某监区(含子监区)下的罪犯数量 -->
<select id="countByAreaIdOrChildren" resultType="java.lang.Integer">
SELECT COUNT(*)
FROM prison_prisoner
WHERE deleted = 0
AND status IN (1, 2) -- 在押或已释放状态
AND prison_area_id IN (
SELECT id FROM prison_area WHERE deleted = 0 AND (id = #{areaId} OR parent_id = #{areaId})
)
</select>
<!-- 统计直接属于某监区的罪犯数量(不含子监区) -->
<select id="countByDirectAreaId" resultType="java.lang.Integer">
SELECT COUNT(*)
FROM prison_prisoner
WHERE deleted = 0
AND status IN (1, 2, 3, 4) -- 在押、假释、监外执行、已释放
AND prison_area_id = #{areaId}
</select>
</mapper> </mapper>

View File

@ -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);

View File

@ -206,15 +206,15 @@ CREATE TABLE IF NOT EXISTS `prison_score` (
-- ===================================================== -- =====================================================
-- 菜单权限 SQL -- 菜单权限 SQL
-- 注意: 请将 ${table.parentMenuId} 替换为实际的父菜单ID -- 注意: 请将 ${table.parentMenuId} 替换为实际的父菜单ID
-- 监狱管理模块的父菜单ID通常为 2000 (系统管理) 或对应的监狱模块菜单ID -- 监狱管理模块的父菜单ID通常为 5047 (系统管理) 或对应的监狱模块菜单ID
-- ===================================================== -- =====================================================
-- 获取监狱模块父菜单ID (假设为 2000,请根据实际情况调整) -- 获取监狱模块父菜单ID (假设为 5047,请根据实际情况调整)
-- SELECT @parentId := 2000; -- SELECT @parentId := 5047;
-- 1. 监区信息管理菜单 -- 1. 监区信息管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @areaParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('监区信息查询', 'prison:area:query', 3, 1, @areaParentId, '', '', '', 0); VALUES ('监区信息查询', 'prison:area:query', 3, 1, @areaParentId, '', '', '', 0);
@ -229,7 +229,7 @@ VALUES ('监区信息导出', 'prison:area:export', 3, 5, @areaParentId, '', '',
-- 2. 监室信息管理菜单 -- 2. 监室信息管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @cellParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('监室信息查询', 'prison:cell:query', 3, 1, @cellParentId, '', '', '', 0); VALUES ('监室信息查询', 'prison:cell:query', 3, 1, @cellParentId, '', '', '', 0);
@ -244,7 +244,7 @@ VALUES ('监室信息导出', 'prison:cell:export', 3, 5, @cellParentId, '', '',
-- 3. 消费记录管理菜单 -- 3. 消费记录管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @consumptionParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('消费记录查询', 'prison:consumption:query', 3, 1, @consumptionParentId, '', '', '', 0); VALUES ('消费记录查询', 'prison:consumption:query', 3, 1, @consumptionParentId, '', '', '', 0);
@ -259,7 +259,7 @@ VALUES ('消费记录导出', 'prison:consumption:export', 3, 5, @consumptionPar
-- 4. 问卷模板管理菜单 -- 4. 问卷模板管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @questionnaireParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('问卷模板查询', 'prison:questionnaire:query', 3, 1, @questionnaireParentId, '', '', '', 0); VALUES ('问卷模板查询', 'prison:questionnaire:query', 3, 1, @questionnaireParentId, '', '', '', 0);
@ -274,7 +274,7 @@ VALUES ('问卷模板导出', 'prison:questionnaire:export', 3, 5, @questionnair
-- 5. 问卷问题管理菜单 -- 5. 问卷问题管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @questionParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('问卷问题查询', 'prison:question:query', 3, 1, @questionParentId, '', '', '', 0); VALUES ('问卷问题查询', 'prison:question:query', 3, 1, @questionParentId, '', '', '', 0);
@ -289,7 +289,7 @@ VALUES ('问卷问题导出', 'prison:question:export', 3, 5, @questionParentId,
-- 6. 问卷答题记录管理菜单 -- 6. 问卷答题记录管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @recordParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('问卷答题记录查询', 'prison:questionnaire-record:query', 3, 1, @recordParentId, '', '', '', 0); VALUES ('问卷答题记录查询', 'prison:questionnaire-record:query', 3, 1, @recordParentId, '', '', '', 0);
@ -304,7 +304,7 @@ VALUES ('问卷答题记录导出', 'prison:questionnaire-record:export', 3, 5,
-- 7. 危险评估管理菜单 -- 7. 危险评估管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @riskParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('危险评估查询', 'prison:risk-assessment:query', 3, 1, @riskParentId, '', '', '', 0); VALUES ('危险评估查询', 'prison:risk-assessment:query', 3, 1, @riskParentId, '', '', '', 0);
@ -319,7 +319,7 @@ VALUES ('危险评估导出', 'prison:risk-assessment:export', 3, 5, @riskParent
-- 8. 计分考核管理菜单 -- 8. 计分考核管理菜单
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status, component_name) 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(); SELECT @scoreParentId := LAST_INSERT_ID();
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('计分考核查询', 'prison:score:query', 3, 1, @scoreParentId, '', '', '', 0); 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); VALUES ('计分考核删除', 'prison:score:delete', 3, 4, @scoreParentId, '', '', '', 0);
INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status) INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, status)
VALUES ('计分考核导出', 'prison:score:export', 3, 5, @scoreParentId, '', '', '', 0); 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());

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -16,10 +16,10 @@ spring:
enabled: true enabled: true
stat-view-servlet: stat-view-servlet:
enabled: true enabled: true
allow: # 设置白名单,不填则允许所有访问 allow: 127.0.0.1 # 设置白名单,仅允许本地访问
url-pattern: /druid/* url-pattern: /druid/*
login-username: # 控制台管理用户名和密码 login-username: ${DRUID_USERNAME:admin} # 控制台管理用户名,建议通过环境变量配置
login-password: login-password: ${DRUID_PASSWORD:admin123} # 控制台管理密码,建议通过环境变量配置
filter: filter:
stat: stat:
enabled: true enabled: true
@ -55,8 +55,8 @@ spring:
# url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 # 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:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例
username: xlcp_dev username: ${DB_USERNAME:xlcp_dev} # 数据库用户名,建议通过环境变量配置
password: xlcp_dev password: ${DB_PASSWORD:xlcp_dev} # 数据库密码,建议通过环境变量配置
# username: sa # SQL Server 连接的示例 # username: sa # SQL Server 连接的示例
# password: Yudao@2024 # SQL Server 连接的示例 # password: Yudao@2024 # SQL Server 连接的示例
# username: SYSDBA # DM 连接的示例 # username: SYSDBA # DM 连接的示例
@ -65,9 +65,9 @@ spring:
# password: Yudao@2024 # OpenGauss 连接的示例 # password: Yudao@2024 # OpenGauss 连接的示例
slave: # 模拟从库,可根据自己需要修改 slave: # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度 lazy: true # 开启懒加载,保证启动速度
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true 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: xlcp_dev username: ${DB_USERNAME_SLAVE:xlcp_dev}
password: xlcp_dev password: ${DB_PASSWORD_SLAVE:xlcp_dev}
# tdengine: # IoT 数据库(需要 IoT 物联网再开启噢!) # tdengine: # IoT 数据库(需要 IoT 物联网再开启噢!)
# url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro # url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro
# driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver # driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver
@ -79,10 +79,10 @@ spring:
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data: data:
redis: redis:
host: 192.168.10.130 host: 192.168.10.126 # 地址
port: 6379 port: 46379 # 端口
database: 0 database: 0 # 数据库索引
password: redis_8a8EYH password: redis_Dbdb2F # 密码
--- #################### 定时任务相关配置 #################### --- #################### 定时任务相关配置 ####################
@ -166,7 +166,7 @@ spring:
# 日志文件配置 # 日志文件配置
logging: logging:
file: file:
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 name: ./logs/${spring.application.name}.log # 日志文件名,相对于项目目录
level: level:
# 配置自己写的 MyBatis Mapper 打印日志 # 配置自己写的 MyBatis Mapper 打印日志
cn.iocoder.yudao.module.bpm.dal.mysql: debug cn.iocoder.yudao.module.bpm.dal.mysql: debug

View File

@ -69,7 +69,7 @@ mybatis-plus:
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
global-config: global-config:
db-config: db-config:
id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 id-type: NONE # "智能"模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
# id-type: AUTO # 自增 ID适合 MySQL 等直接自增的数据库 # id-type: AUTO # 自增 ID适合 MySQL 等直接自增的数据库
# id-type: INPUT # 用户输入 ID适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库 # id-type: INPUT # 用户输入 ID适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库
# id-type: ASSIGN_ID # 分配 ID默认使用雪花算法。注意Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解 # id-type: ASSIGN_ID # 分配 ID默认使用雪花算法。注意Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
@ -104,7 +104,7 @@ aj:
captcha: captcha:
jigsaw: classpath:images/jigsaw # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 jigsaw: classpath:images/jigsaw # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径
pic-click: classpath:images/pic-click # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径 pic-click: classpath:images/pic-click # 滑动验证,底图路径,不配置将使用默认图片;以 classpath: 开头,取 resource 目录下路径
cache-type: redis # 缓存 local/redis... cache-type: local # 缓存 local/redis...
cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存 cache-number: 1000 # local 缓存的阈值,达到这个值,清除缓存
timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行 timing-clear: 180 # local定时清除过期缓存(单位秒),设置为0代表不执行
type: blockPuzzle # 验证码类型 default 三种都实例化。blockPuzzle 滑块拼图、clickWord 文字点选、pictureWord 文本输入 type: blockPuzzle # 验证码类型 default 三种都实例化。blockPuzzle 滑块拼图、clickWord 文字点选、pictureWord 文本输入