diff --git a/.claude/agents/configure-dependencies.md b/.claude/agents/configure-dependencies.md new file mode 100644 index 0000000..be14176 --- /dev/null +++ b/.claude/agents/configure-dependencies.md @@ -0,0 +1,13 @@ +--- +name: configure-dependencies +description: Configure Maven dependencies +model: sonnet +color: blue +--- +为 Ruoyi-vue-pro 单应用版本配置 Maven 依赖。请修改 pom.xml 文件,添加新模块的依赖配置。 + +需要完成: +1. 在 yudao-framework 中添加模块的 starter 依赖(如果需要) +2. 在主 pom.xml 中添加模块声明 +3. 确保依赖版本与现有模块一致 +4. 检查是否有版本冲突 \ No newline at end of file diff --git a/.claude/agents/create-database.md b/.claude/agents/create-database.md new file mode 100644 index 0000000..42c0bc4 --- /dev/null +++ b/.claude/agents/create-database.md @@ -0,0 +1,17 @@ +--- +name: create-database +description: Create database tables +model: sonnet +color: blue +--- +为 Ruoyi-vue-pro 单应用版本创建数据库表。请根据用户提供的表名和模块信息,创建符合 Ruoyi 规范的数据库表脚本。 + +要求: +1. 表名前缀:{模块名}_(如:system_user) +2. 公共字段:id, creator, create_time, updater, update_time, deleted, tenant_id +3. 使用 soft delete(deleted 字段) +4. 包含 tenant_id 支持 +5. 生成标准的 MySQL 建表语句 +6. 创建对应的菜单权限 SQL + +请将生成的 SQL 脚本保存到文件 resources/sql/{模块名}.sql,并输出脚本内容供后续执行。 \ No newline at end of file diff --git a/.claude/agents/create-structure.md b/.claude/agents/create-structure.md new file mode 100644 index 0000000..cc57ae4 --- /dev/null +++ b/.claude/agents/create-structure.md @@ -0,0 +1,23 @@ +--- +name: create-structure +description: Create project structure +model: sonnet +color: blue +--- +为 Ruoyi-vue-pro 单应用版本创建新应用的项目结构。请根据用户提供的模块名称,创建以下目录结构: + +后端结构: +- src/main/java/cn/iocoder/yudao/module/{模块名}/ + - controller/admin/{模块名}/ + - service/{模块名}/ + - dal/dataobject/{模块名}/ + - dal/mysql/{模块名}/ + - convert/{模块名}/ + - enums/ +- src/main/resources/{模块名}/ + +前端结构: +- src/views/{模块名}/ +- src/api/{模块名}/ + +请创建基础的包结构和必要的占位文件(如空白的Controller、Service接口等)。 \ No newline at end of file diff --git a/.claude/agents/implement-backend.md b/.claude/agents/implement-backend.md new file mode 100644 index 0000000..d04ebcb --- /dev/null +++ b/.claude/agents/implement-backend.md @@ -0,0 +1,22 @@ +--- +name: implement-backend +description: Implement backend code +model: sonnet +color: blue +--- +实现 Ruoyi-vue-pro 单应用版本的后端代码。请根据用户提供的模块信息,生成完整的后端代码: + +需要生成的代码: +1. DO(Entity)类 - 使用 MyBatis-Plus 注解 +2. Mapper 接口 - 继承 BaseMapper +3. Service 接口和实现类 +4. Controller - 完整的 CRUD 接口 +5. VO 对象 - SaveReqVO、PageReqVO、RespVO +6. Convert 转换类 - 使用 MapStruct +7. 枚举类(如有需要) + +代码规范: +- 包名:cn.iocoder.yudao.module.{模块名} +- API 路径:/{模块名}/xxx +- 权限前缀:{模块名}:xxx +- 遵循现有代码风格 \ No newline at end of file diff --git a/.claude/agents/implement-frontend.md b/.claude/agents/implement-frontend.md new file mode 100644 index 0000000..3613b16 --- /dev/null +++ b/.claude/agents/implement-frontend.md @@ -0,0 +1,20 @@ +--- +name: implement-frontend +description: Implement frontend code +model: sonnet +color: blue +--- +实现 Ruoyi-vue-pro 单应用版本的前端代码。请根据用户提供的模块信息,生成完整的前端代码: + +需要生成的代码: +1. API 文件 - src/api/{模块名}/index.ts +2. 列表页面 - src/views/{模块名}/index.vue +3. 表单页面 - src/views/{模块名}/{模块名}Form.vue +4. TypeScript 类型定义 + +代码规范: +- 使用 Element Plus 组件 +- 遵循现有代码风格 +- 支持 CRUD 操作 +- 包含分页、搜索、导出功能 +- 国际化支持 \ No newline at end of file diff --git a/.claude/agents/subagent-fix.md b/.claude/agents/subagent-fix.md new file mode 100644 index 0000000..ef1828a --- /dev/null +++ b/.claude/agents/subagent-fix.md @@ -0,0 +1,14 @@ +--- +name: subagent-fix +description: Generate fix suggestions for code issues +tools: Read,Write +model: sonnet +--- +基于之前的代码审查结果,{请在此处粘贴不符合规范的问题列表}。 + +请为每个问题提供: +1. 具体的整改代码示例 +2. 整改前后的对比 +3. 整改后的文件完整内容 + +请确保提供的代码示例完整、准确,可以直接使用。 \ No newline at end of file diff --git a/.claude/agents/subagent-review.md b/.claude/agents/subagent-review.md new file mode 100644 index 0000000..e531ed8 --- /dev/null +++ b/.claude/agents/subagent-review.md @@ -0,0 +1,71 @@ +--- +name: subagent-review +description: Review code against ruoyi-vue-pro standards +tools: Read,Grep,Glob +model: sonnet +--- +请对提供的代码进行全面的 ruoyi-vue-pro (芋道) 规范审查。 + +## 审查标准(根据芋道官方文档) + +### 1. 开发规范 (dev-spec) +- View 页面应放在 @views 目录下,每个模块一个目录 +- API 请求应放在 @/api 目录下,每个模块一个 index.ts 文件 +- 接口应定义 TypeScript interface 类型 +- 分页列表、树形列表应参考系统管理示例 + +### 2. 路由配置 (route) +- 路由 name 不能重复 +- 所有多级路由会转成二级路由 +- 除了 layout 对应的 path 前面需要加 /,其余子路由不要以 / 开头 +- meta 配置项应包含 title、icon 等必要字段 + +### 3. 图标使用 (icon) +- 应使用 加载本地 SVG 图标 +- 或使用 加载 Iconify 图标 +- 在 ElButton 等组件中使用 useIcon 钩子 +- 自定义图标应放在 /src/assets/svgs 目录 + +### 4. 字典数据 (dict) +- 应使用 DICT_TYPE 枚举来引用字典类型 +- 字典展示应使用 组件 +- 或通过 CRUD schemas 的 dictType 和 dictClass 属性 +- 下拉框应使用 getIntDictOptions、getStrDictOptions 等工具方法 + +### 5. 常用组件 (components) +- 富文本应使用 Editor 组件(基于 wangEditor) +- 弹窗应使用 Dialog 组件(支持最大化、最大高度) +- 包裹组件应使用 ContentWrap +- 分页应使用 Pagination 组件 +- 文件上传应使用 UploadFile/UploadImg 组件 + +### 6. 工具方法 (util) +- 缓存应使用 wsCache.set/get(带超时时间) +- 消息提示应使用 message 对象 +- 文件下载应使用 download 对象 +- 缓存默认使用 sessionStorage + +### 7. 配置读取 (config-center) +- 应通过 getConfigKey 方法读取动态配置 +- 配置可在基础设施 -> 配置管理中动态修改 + +### 8. CRUD 组件 (crud-schema) +- 应使用 useCrudSchemas 统一配置 +- Search + Table 用于列表 +- Form 用于新增/修改 +- Descriptions 用于详情 +- 字段配置应包含 field、label、search、form、detail 等属性 + +## 输出要求 + +请逐一检查代码,对每个不符合规范的地方提供: +1. 文件路径 +2. 问题描述 +3. 不符合的具体规范 +4. 建议的整改方案 +5. 正确的代码示例 + +最后输出: +- 通过的项目列表 +- 不符合规范的项目列表及整改建议 +- 整体审查结论 \ No newline at end of file diff --git a/.claude/commands/ruoyi-app-scaffold.md b/.claude/commands/ruoyi-app-scaffold.md new file mode 100644 index 0000000..b49d426 --- /dev/null +++ b/.claude/commands/ruoyi-app-scaffold.md @@ -0,0 +1,137 @@ +--- +description: ruoyi-app-scaffold +--- +```mermaid +flowchart TD + start_node_default([Start]) + ask_basic_info{AskUserQuestion:
请输入新应用的基本信息:模块英文名(如:system)、模块中文名(如:系统管理)、表名(如:system_user)、以及应用描述} + create_structure[create-structure] + configure_dependencies[configure-dependencies] + create_database[create-database] + ask_execute_method{AskUserQuestion:
数据库脚本已生成。请选择执行方式:} + if_execute_choice{If/Else:
Conditional Branch} + execute_sql[[MCP: mysql_write_query]] + show_script[数据库脚本已生成完成!] + implement_backend[implement-backend] + ask_frontend{AskUserQuestion:
是否需要创建前端代码?} + implement_frontend[implement-frontend] + skip_frontend[前端代码创建已跳过。] + end_node_default([End]) + + start_node_default --> ask_basic_info + ask_basic_info --> create_structure + create_structure --> configure_dependencies + configure_dependencies --> create_database + create_database --> ask_execute_method + ask_execute_method --> if_execute_choice + if_execute_choice -->|Direct Execute| execute_sql + if_execute_choice -->|Show Script| show_script + execute_sql --> implement_backend + show_script --> implement_backend + implement_backend --> ask_frontend + ask_frontend -->|是| implement_frontend + ask_frontend -->|否| skip_frontend + implement_frontend --> end_node_default + skip_frontend --> end_node_default +``` + +## Workflow Execution Guide + +Follow the Mermaid flowchart above to execute the workflow. Each node type has specific execution methods as described below. + +### Execution Methods by Node Type + +- **Rectangle nodes**: Execute Sub-Agents using the Task tool +- **Diamond nodes (AskUserQuestion:...)**: Use the AskUserQuestion tool to prompt the user and branch based on their response +- **Diamond nodes (Branch/Switch:...)**: Automatically branch based on the results of previous processing (see details section) +- **Rectangle nodes (Prompt nodes)**: Execute the prompts described in the details section below + +## MCP Tool Nodes + +#### execute_sql(mysql_write_query) + +**Description**: Execute SQL script to create database tables + +**MCP Server**: mysql + +**Tool Name**: mysql_write_query + +**Validation Status**: valid + +**Configured Parameters**: + +- `query` (string): /* SQL script from create-database step will be inserted here */ + +**Available Parameters**: + +- `query` (string) (required): SQL query to execute (CREATE TABLE or ALTER TABLE statements) + +This node invokes an MCP (Model Context Protocol) tool. When executing this workflow, use the configured parameters to call the tool via the MCP server. + +### Prompt Node Details + +#### show_script(数据库脚本已生成完成!) + +``` +数据库脚本已生成完成! + +执行步骤: +1. 打开生成的 SQL 脚本文件:resources/sql/{模块名}.sql +2. 连接到目标数据库 +3. 执行脚本创建表和菜单权限 + +生成的脚本包含: +- 主表创建语句 +- 菜单权限 SQL +- 初始化数据(如有需要) + +请确保数据库连接信息正确后执行脚本。 +``` + +#### skip_frontend(前端代码创建已跳过。) + +``` +前端代码创建已跳过。 + +后端代码已创建完成,您可以在以下位置找到代码: +- 后端:cn.iocoder.yudao.module.{模块名} +- 数据库脚本:resources/sql/{模块名}.sql + +请手动执行数据库脚本,然后启动项目测试后端接口。 +``` + +### AskUserQuestion Node Details + +#### ask_basic_info(请输入新应用的基本信息:模块英文名(如:system)、模块中文名(如:系统管理)、表名(如:system_user)、以及应用描述) + +**Selection mode:** Single Select (branches based on the selected option) + +**Options:** +- **继续创建**: 确认信息并开始创建应用 +- **取消**: 取消本次创建 + +#### ask_execute_method(数据库脚本已生成。请选择执行方式:) + +**Selection mode:** Single Select (branches based on the selected option) + +**Options:** +- **直接执行**: 使用 MySQL MCP 直接在数据库中执行脚本(推荐用于开发环境) +- **查看脚本**: 只生成脚本,手动执行(推荐用于生产环境) + +#### ask_frontend(是否需要创建前端代码?) + +**Selection mode:** Single Select (branches based on the selected option) + +**Options:** +- **是**: 创建前端页面和 API +- **否**: 跳过前端创建 + +### If/Else Node Details + +#### if_execute_choice(Binary Branch (True/False)) + +**Branch conditions:** +- **Direct Execute**: User selected direct execution +- **Show Script**: User selected to view script only + +**Execution method**: Evaluate the results of the previous processing and automatically select the appropriate branch based on the conditions above. diff --git a/.claude/commands/yudao-code-review-fix.md b/.claude/commands/yudao-code-review-fix.md new file mode 100644 index 0000000..59b2488 --- /dev/null +++ b/.claude/commands/yudao-code-review-fix.md @@ -0,0 +1,75 @@ +--- +description: yudao-code-review-fix +--- +```mermaid +flowchart TD + start_node_default([Start]) + prompt_input[请提供要审查的代码文件路径或Git diff信息。] + subagent_review[subagent-review] + switch_results{Switch:
Conditional Branch} + prompt_pass[代码审查已通过!🎉] + subagent_fix[subagent-fix] + end_pass([End]) + end_fix([End]) + + start_node_default --> prompt_input + prompt_input --> subagent_review + subagent_review --> switch_results + switch_results -->|全部通过| prompt_pass + switch_results -->|存在问题| subagent_fix + prompt_pass --> end_pass + subagent_fix --> end_fix +``` + +## Workflow Execution Guide + +Follow the Mermaid flowchart above to execute the workflow. Each node type has specific execution methods as described below. + +### Execution Methods by Node Type + +- **Rectangle nodes**: Execute Sub-Agents using the Task tool +- **Diamond nodes (AskUserQuestion:...)**: Use the AskUserQuestion tool to prompt the user and branch based on their response +- **Diamond nodes (Branch/Switch:...)**: Automatically branch based on the results of previous processing (see details section) +- **Rectangle nodes (Prompt nodes)**: Execute the prompts described in the details section below + +### Prompt Node Details + +#### prompt_input(请提供要审查的代码文件路径或Git diff信息。) + +``` +请提供要审查的代码文件路径或Git diff信息。 + +支持以下输入方式: +1. 单个文件路径(如:src/views/system/post/index.vue) +2. 目录路径(如:src/views/system/post/) +3. Git diff 输出 +4. 要审查的功能描述 + +请提供完整的信息以便进行代码审查。 +``` + +#### prompt_pass(代码审查已通过!🎉) + +``` +代码审查已通过!🎉 + +所有代码都符合 ruoyi-vue-pro (芋道) 开发规范。 + +审查通过的项目: +{请在此处列出通过的项目} + +这是对代码质量的肯定,请继续保持! +``` + +### Switch Node Details + +#### switch_results(Multiple Branch (2-N)) + +**Evaluation Target**: 检查审查结果中是否存在不符合规范的问题 + +**Branch conditions:** +- **全部通过**: 没有发现任何不符合规范的问题 +- **存在问题**: 发现一个或多个不符合规范的问题 +- **default**: Other cases + +**Execution method**: Evaluate the results of the previous processing and automatically select the appropriate branch based on the conditions above. diff --git a/backend b/backend index 5f9bcfc..bbcf68b 160000 --- a/backend +++ b/backend @@ -1 +1 @@ -Subproject commit 5f9bcfc9b2a1765d775dafa990e23f0f8c964747 +Subproject commit bbcf68bdb84aeec934a8f5c8fca30d216428837b diff --git a/requirements/实施文档-计分考核-前端.md b/requirements/实施文档-计分考核-前端.md new file mode 100644 index 0000000..08f4f5a --- /dev/null +++ b/requirements/实施文档-计分考核-前端.md @@ -0,0 +1,1639 @@ +# 计分考核模块 - 前端实施文档 + +> 版本:v1.0 +> 创建日期:2026-01-14 +> 优先级:P0 + +--- + +## 一、概述 + +### 1.1 文档说明 +本文档为计分考核模块的前端实施指南,基于需求文档「需求-03-计分考核.md」和后端实施文档编写。 + +### 1.2 前端文件结构 + +``` +frontend/src/ +├── views/prison/score/ +│ ├── subject/ # 考核规则配置 +│ │ ├── index.vue # 列表页 +│ │ └── SubjectForm.vue # 新增/编辑表单 +│ ├── record/ # 日常考核记录 +│ │ ├── index.vue # 列表页 +│ │ └── RecordForm.vue # 新增/编辑表单(含批量录入) +│ ├── monthly/ # 月度考核汇总 +│ │ ├── index.vue # 列表页 +│ │ └── MonthlyDetail.vue # 月度明细 +│ ├── level/ # 等级规则配置 +│ │ └── index.vue # 配置页 +│ ├── notice/ # 考核公示 +│ │ ├── index.vue # 列表页 +│ │ └── NoticeForm.vue # 新增/编辑/发布表单 +│ └── parole/ # 减刑假释数据 +│ └── index.vue # 数据提取页 +│ +└── api/prison/score/ + ├── subject.ts # 考核规则API + ├── record.ts # 日常记录API + ├── monthly.ts # 月度汇总API + ├── level.ts # 等级规则API + ├── notice.ts # 公示公告API + └── parole.ts # 减刑假释API +``` + +--- + +## 二、API接口定义 + +### 2.1 考核规则科目API(subject.ts) + +```typescript +import { request } from '@/config/axios' +import type { PageData, PageResult } from '@/types' + +/** 考核规则科目接口 */ +export interface ScoreSubject { + id: number + code: string + name: string + category: number + categoryName: string + score: number + dailyLimit: number + monthlyLimit: number + description: string + status: number + statusName: string + sort: number + createTime: string +} + +/** 查询参数 */ +export interface ScoreSubjectQuery extends PageData { + code?: string + name?: string + category?: number + status?: number +} + +/** 保存参数 */ +export interface ScoreSubjectSaveParams { + id?: number + code: string + name: string + category: number + score: number + dailyLimit?: number + monthlyLimit?: number + description?: string + status?: number + sort?: number +} + +/** 考核类别选项 */ +export const CATEGORY_OPTIONS = [ + { value: 1, label: '劳动改造' }, + { value: 2, label: '教育改造' }, + { value: 3, label: '日常行为' }, + { value: 4, label: '卫生纪律' }, + { value: 5, label: '加分项' }, + { value: 6, label: '扣分项' } +] + +export const ScoreSubjectApi = { + /** 分页查询 */ + getPage: async (params: ScoreSubjectQuery) => { + return await request.get({ url: '/score/subject/page', params }) + }, + + /** 获取详情 */ + get: async (id: number) => { + return await request.get({ url: `/score/subject/get?id=${id}` }) + }, + + /** 获取列表(无分页) */ + getList: async (params?: Omit) => { + return await request.get({ url: '/score/subject/list', params }) + }, + + /** 创建 */ + create: async (data: ScoreSubjectSaveParams) => { + return await request.post({ url: '/score/subject/create', data }) + }, + + /** 更新 */ + update: async (data: ScoreSubjectSaveParams) => { + return await request.put({ url: '/score/subject/update', data }) + }, + + /** 删除 */ + delete: async (id: number) => { + return await request.delete({ url: `/score/subject/delete?id=${id}` }) + }, + + /** 批量删除 */ + deleteList: async (ids: number[]) => { + return await request.delete({ url: `/score/subject/delete-list?ids=${ids.join(',')}` }) + }, + + /** 更新状态 */ + updateStatus: async (id: number, status: number) => { + return await request.put({ url: '/score/subject/update-status', params: { id, status } }) + }, + + /** 导出Excel */ + export: async (params: ScoreSubjectQuery) => { + return await request.download({ url: '/score/subject/export-excel', params }) + } +} +``` + +### 2.2 日常考核记录API(record.ts) + +```typescript +import { request } from '@/config/axios' +import type { PageData, PageResult } from '@/types' + +/** 日常考核记录接口 */ +export interface ScoreRecord { + id: number + prisonerId: number + prisonerNo: string + prisonerName: string + prisonAreaId: number + prisonAreaName: string + recordDate: string + subjectId: number + subjectName: string + category: number + categoryName: string + score: number + actualScore: number + remark: string + recorderId: number + recorderName: string + createTime: string +} + +/** 查询参数 */ +export interface ScoreRecordQuery extends PageData { + prisonerNo?: string + prisonerName?: string + recordDate?: string + recordDateRange?: string[] + category?: number + subjectId?: number + prisonAreaId?: number +} + +/** 保存参数 */ +export interface ScoreRecordSaveParams { + id?: number + prisonerId: number + recordDate: string + subjectId: number + score: number + remark?: string +} + +/** 批量创建参数 */ +export interface ScoreRecordBatchParams { + recordDate: string + prisonerIds: number[] + subjectId: number + score: number + remark?: string +} + +export const ScoreRecordApi = { + /** 分页查询 */ + getPage: async (params: ScoreRecordQuery) => { + return await request.get({ url: '/score/record/page', params }) + }, + + /** 获取详情 */ + get: async (id: number) => { + return await request.get({ url: `/score/record/get?id=${id}` }) + }, + + /** 获取罪犯考核明细 */ + getByPrisoner: async (prisonerId: number, year?: number, month?: number) => { + return await request.get({ url: '/score/record/get-by-prisoner', params: { prisonerId, year, month } }) + }, + + /** 创建 */ + create: async (data: ScoreRecordSaveParams) => { + return await request.post({ url: '/score/record/create', data }) + }, + + /** 批量创建 */ + batchCreate: async (data: ScoreRecordBatchParams) => { + return await request.post({ url: '/score/record/batch-create', data }) + }, + + /** 更新 */ + update: async (data: ScoreRecordSaveParams) => { + return await request.put({ url: '/score/record/update', data }) + }, + + /** 删除 */ + delete: async (id: number) => { + return await request.delete({ url: `/score/record/delete?id=${id}` }) + }, + + /** 导出Excel */ + export: async (params: ScoreRecordQuery) => { + return await request.download({ url: '/score/record/export-excel', params }) + } +} +``` + +### 2.3 月度考核汇总API(monthly.ts) + +```typescript +import { request } from '@/config/axios' +import type { PageData } from '@/types' + +/** 月度考核汇总接口 */ +export interface ScoreMonthly { + id: number + prisonerId: number + prisonerNo: string + prisonerName: string + prisonAreaId: number + prisonAreaName: string + year: number + month: number + baseScore: number + rewardScore: number + penaltyScore: number + totalScore: number + level: number + levelName: string + assessorId: number + assessorName: string + status: number + statusName: string + remark: string + createTime: string +} + +/** 查询参数 */ +export interface ScoreMonthlyQuery extends PageData { + prisonerNo?: string + prisonerName?: string + year: number + month?: number + level?: number + status?: number + prisonAreaId?: number +} + +/** 月度汇总明细 */ +export interface ScoreMonthlyDetail { + monthly: ScoreMonthly + records: ScoreRecord[] +} + +/** 减刑假释数据 */ +export interface ScoreParoleData { + prisonerId: number + prisonerNo: string + prisonerName: string + monthlyScores: Array<{ + year: number + month: number + totalScore: number + level: number + levelName: string + }> + yearlyTotalScore: number + praiseCount: number + warningCount: number + suggestion: { + canApplyReduction: boolean + suggestedReductionMonths: number + canApplyParole: boolean + paroleOpinion: string + } +} + +export const ScoreMonthlyApi = { + /** 分页查询 */ + getPage: async (params: ScoreMonthlyQuery) => { + return await request.get({ url: '/score/monthly/page', params }) + }, + + /** 获取汇总详情 */ + getSummary: async (id: number) => { + return await request.get({ url: `/score/monthly/get-summary?id=${id}` }) + }, + + /** 获取月度汇总明细 */ + getDetail: async (id: number) => { + return await request.get({ url: `/score/monthly/get-detail?id=${id}` }) + }, + + /** 手动触发月度汇总计算 */ + calculate: async (year: number, month: number) => { + return await request.post({ url: '/score/monthly/calculate', params: { year, month } }) + }, + + /** 提交审核 */ + submitAudit: async (id: number) => { + return await request.post({ url: '/score/monthly/submit-audit', params: { id } }) + }, + + /** 审核通过 */ + auditPass: async (id: number, remark?: string) => { + return await request.post({ url: '/score/monthly/audit', params: { id, status: 2, remark } }) + }, + + /** 审核驳回 */ + auditReject: async (id: number, remark: string) => { + return await request.post({ url: '/score/monthly/audit', params: { id, status: 3, remark } }) + }, + + /** 导出Excel */ + export: async (params: ScoreMonthlyQuery) => { + return await request.download({ url: '/score/monthly/export-excel', params }) + }, + + /** 获取减刑假释数据 */ + getParoleData: async (prisonerId: number) => { + return await request.get({ url: '/score/parole/get-data', params: { prisonerId } }) + }, + + /** 生成减刑假释建议 */ + generateSuggestion: async (prisonerId: number) => { + return await request.post({ url: '/score/parole/generate-suggestion', params: { prisonerId } }) + } +} +``` + +### 2.4 等级规则API(level.ts) + +```typescript +import { request } from '@/config/axios' + +/** 等级规则接口 */ +export interface ScoreLevelRule { + id: number + level: number + levelName: string + minScore: number + maxScore: number + description: string + sort: number + status: number +} + +/** 基础分配置 */ +export interface BaseScoreConfig { + baseScore: number +} + +export const ScoreLevelApi = { + /** 获取等级规则列表 */ + getList: async () => { + return await request.get({ url: '/score/level/get' }) + }, + + /** 更新等级规则 */ + update: async (data: ScoreLevelRule[]) => { + return await request.put({ url: '/score/level/update', data }) + }, + + /** 获取基础分配置 */ + getBaseScore: async () => { + return await request.get({ url: '/score/level/get-base-score' }) + }, + + /** 更新基础分配置 */ + updateBaseScore: async (baseScore: number) => { + return await request.put({ url: '/score/level/update-base-score', params: { baseScore } }) + } +} +``` + +### 2.5 公示公告API(notice.ts) + +```typescript +import { request } from '@/config/axios' +import type { PageData } from '@/types' + +/** 公示公告接口 */ +export interface ScoreNotice { + id: number + title: string + noticeType: number + noticeTypeName: string + startDate: string + endDate: string + scopeType: number + scopeTypeName: string + scopePrisonAreaIds: string + scopePrisonAreaNames: string + content: string + status: number + statusName: string + publisherId: number + publisherName: string + publishTime: string + createTime: string +} + +/** 查询参数 */ +export interface ScoreNoticeQuery extends PageData { + title?: string + noticeType?: number + status?: number + startDate?: string + endDate?: string +} + +/** 保存参数 */ +export interface ScoreNoticeSaveParams { + id?: number + title: string + noticeType: number + startDate: string + endDate: string + scopeType: number + scopePrisonAreaIds?: string + content?: string +} + +export const ScoreNoticeApi = { + /** 分页查询 */ + getPage: async (params: ScoreNoticeQuery) => { + return await request.get({ url: '/score/notice/page', params }) + }, + + /** 获取详情 */ + get: async (id: number) => { + return await request.get({ url: `/score/notice/get?id=${id}` }) + }, + + /** 创建 */ + create: async (data: ScoreNoticeSaveParams) => { + return await request.post({ url: '/score/notice/create', data }) + }, + + /** 更新 */ + update: async (data: ScoreNoticeSaveParams) => { + return await request.put({ url: '/score/notice/update', data }) + }, + + /** 发布 */ + publish: async (id: number) => { + return await request.put({ url: `/score/notice/publish?id=${id}` }) + }, + + /** 撤回 */ + withdraw: async (id: number) => { + return await request.put({ url: `/score/notice/withdraw?id=${id}` }) + }, + + /** 删除 */ + delete: async (id: number) => { + return await request.delete({ url: `/score/notice/delete?id=${id}` }) + } +} +``` + +--- + +## 三、页面组件设计 + +### 3.1 考核规则配置页面(subject/index.vue) + +```vue + + + +``` + +### 3.2 考核规则表单组件(subject/SubjectForm.vue) + +```vue + + + +``` + +### 3.3 日常考核记录页面(record/index.vue) + +```vue + + + +``` + +### 3.4 批量录入表单组件(record/BatchRecordForm.vue) + +```vue + + + +``` + +### 3.5 月度考核汇总页面(monthly/index.vue) + +```vue + + + + + +``` + +### 3.6 月度明细组件(monthly/MonthlyDetail.vue) + +```vue + + + +``` + +--- + +## 四、路由配置 + +```typescript +// router/routes/modules/prison.ts + +{ + path: '/prison/score', + component: Layout, + redirect: '/prison/score/subject', + name: 'PrisonScore', + meta: { + title: '计分考核', + icon: 'score', + alwaysShow: true + }, + children: [ + { + path: 'subject', + component: () => import('@/views/prison/score/subject/index.vue'), + name: 'PrisonScoreSubject', + meta: { + title: '考核规则配置', + icon: 'list', + permissions: ['prison:score:subject:query'] + } + }, + { + path: 'record', + component: () => import('@/views/prison/score/record/index.vue'), + name: 'PrisonScoreRecord', + meta: { + title: '日常考核记录', + icon: 'edit', + permissions: ['prison:score:record:query'] + } + }, + { + path: 'monthly', + component: () => import('@/views/prison/score/monthly/index.vue'), + name: 'PrisonScoreMonthly', + meta: { + title: '月度考核汇总', + icon: 'date', + permissions: ['prison:score:monthly:query'] + } + }, + { + path: 'level', + component: () => import('@/views/prison/score/level/index.vue'), + name: 'PrisonScoreLevel', + meta: { + title: '等级规则配置', + icon: 'setting', + permissions: ['prison:score:level:query'] + } + }, + { + path: 'notice', + component: () => import('@/views/prison/score/notice/index.vue'), + name: 'PrisonScoreNotice', + meta: { + title: '考核公示', + icon: 'notification', + permissions: ['prison:score:notice:query'] + } + }, + { + path: 'parole', + component: () => import('@/views/prison/score/parole/index.vue'), + name: 'PrisonScoreParole', + meta: { + title: '减刑假释数据', + icon: 'document', + permissions: ['prison:score:parole:query'] + } + } + ] +} +``` + +--- + +## 五、菜单权限SQL + +```sql +-- 计分考核模块菜单权限 + +-- 1. 考核规则配置 +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component) VALUES +('考核规则配置', '', 2, 1, (SELECT id FROM system_menu WHERE name = '计分考核'), 'subject', 'list', 'prison/score/subject/index'); + +-- 2. 日常考核记录 +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component) VALUES +('日常考核记录', '', 2, 2, (SELECT id FROM system_menu WHERE name = '计分考核'), 'record', 'edit', 'prison/score/record/index'); + +-- 3. 月度考核汇总 +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component) VALUES +('月度考核汇总', '', 2, 3, (SELECT id FROM system_menu WHERE name = '计分考核'), 'monthly', 'date', 'prison/score/monthly/index'); + +-- 4. 等级规则配置 +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component) VALUES +('等级规则配置', '', 2, 4, (SELECT id FROM system_menu WHERE name = '计分考核'), 'level', 'setting', 'prison/score/level/index'); + +-- 5. 考核公示 +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component) VALUES +('考核公示', '', 2, 5, (SELECT id FROM system_menu WHERE name = '计分考核'), 'notice', 'notification', 'prison/score/notice/index'); + +-- 6. 减刑假释数据 +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component) VALUES +('减刑假释数据', '', 2, 6, (SELECT id FROM system_menu WHERE name = '计分考核'), 'parole', 'document', 'prison/score/parole/index'); +``` + +--- + +## 六、验收标准 + +- [ ] 考核规则配置页面:支持规则的增删改查、状态切换 +- [ ] 日常考核记录页面:支持单条录入和批量录入 +- [ ] 月度考核汇总页面:支持月度统计展示、明细查看 +- [ ] 等级规则配置页面:支持等级标准和基础分配置 +- [ ] 考核公示页面:支持公示的发布和撤回 +- [ ] 减刑假释数据页面:支持考核数据提取和展示 +- [ ] 所有页面通过TypeScript类型检查 +- [ ] 所有页面响应式适配 diff --git a/requirements/实施文档-计分考核-后端.md b/requirements/实施文档-计分考核-后端.md new file mode 100644 index 0000000..799e505 --- /dev/null +++ b/requirements/实施文档-计分考核-后端.md @@ -0,0 +1,657 @@ +# 计分考核模块 - 后端实施文档 + +> 版本:v1.0 +> 创建日期:2026-01-14 +> 优先级:P0 + +--- + +## 一、概述 + +### 1.1 文档说明 +本文档为计分考核模块的后端实施指南,基于需求文档「需求-03-计分考核.md」编写。 + +### 1.2 现有模块状态 +- **已有**:基础的月度考核汇总表(prison_score)和CRUD接口 +- **缺失**:考核规则配置、日常考核记录、自动计算、等级评定、公示功能 + +### 1.3 新增数据表规划 + +| 序号 | 表名 | 说明 | 优先级 | +|-----|-----|------|-------| +| 1 | `prison_score_subject` | 考核规则科目表 | P0 | +| 2 | `prison_score_record` | 日常考核记录表 | P0 | +| 3 | `prison_score_level_rule` | 考核等级评定规则表 | P0 | +| 4 | `prison_score_notice` | 考核公示公告表 | P1 | + +--- + +## 二、数据库设计 + +### 2.1 考核规则科目表 (prison_score_subject) + +```sql +CREATE TABLE `prison_score_subject` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '规则ID', + `code` varchar(50) NOT NULL COMMENT '规则编码(唯一)', + `name` varchar(100) NOT NULL COMMENT '规则名称', + `category` tinyint NOT NULL COMMENT '考核类别:1-劳动改造 2-教育改造 3-日常行为 4-卫生纪律 5-加分项 6-扣分项', + `score` decimal(10,2) NOT NULL COMMENT '分值(正数为加分,负数为扣分)', + `daily_limit` decimal(10,2) NOT NULL DEFAULT 0 COMMENT '日最高分限制', + `monthly_limit` decimal(10,2) NOT NULL DEFAULT 0 COMMENT '月最高分限制', + `description` varchar(500) DEFAULT NULL COMMENT '规则说明', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:1-启用 2-禁用', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_category` (`category`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB COMMENT='考核规则科目表'; +``` + +**枚举定义**: +```java +/** + * 考核类别枚举 + */ +public enum ScoreSubjectCategoryEnum { + LABOR(1, "劳动改造"), + EDUCATION(2, "教育改造"), + DAILY_BEHAVIOR(3, "日常行为"), + HYGIENE_DISCIPLINE(4, "卫生纪律"), + BONUS(5, "加分项"), + PENALTY(6, "扣分项"); + + private final Integer value; + private final String name; +} + +/** + * 状态枚举 + */ +public enum ScoreSubjectStatusEnum { + ENABLED(1, "启用"), + DISABLED(2, "禁用"); +} +``` + +### 2.2 日常考核记录表 (prison_score_record) + +```sql +CREATE TABLE `prison_score_record` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '记录ID', + `prisoner_id` bigint NOT NULL COMMENT '罪犯ID', + `prisoner_no` varchar(50) NOT NULL COMMENT '罪犯编号', + `record_date` date NOT NULL COMMENT '考核日期', + `subject_id` bigint NOT NULL COMMENT '考核规则ID', + `subject_name` varchar(100) NOT NULL COMMENT '规则名称', + `category` tinyint NOT NULL COMMENT '考核类别', + `score` decimal(10,2) NOT NULL COMMENT '得分', + `actual_score` decimal(10,2) NOT NULL COMMENT '实际得分(日限月限校验后)', + `remark` varchar(500) DEFAULT NULL COMMENT '备注说明', + `recorder_id` bigint NOT NULL COMMENT '记录人ID', + `recorder_name` varchar(50) NOT NULL COMMENT '记录人姓名', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_prisoner_date` (`prisoner_no`, `record_date`), + KEY `idx_record_date` (`record_date`), + KEY `idx_subject` (`subject_id`) +) ENGINE=InnoDB COMMENT='日常考核记录表'; +``` + +### 2.3 考核等级评定规则表 (prison_score_level_rule) + +```sql +CREATE TABLE `prison_score_level_rule` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '规则ID', + `level` tinyint NOT NULL COMMENT '等级:1-优秀 2-良好 3-合格 4-不合格', + `level_name` varchar(20) NOT NULL COMMENT '等级名称', + `min_score` decimal(10,2) NOT NULL COMMENT '最低分(含)', + `max_score` decimal(10,2) NOT NULL COMMENT '最高分(含)', + `description` varchar(500) DEFAULT NULL COMMENT '说明', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:1-启用 2-禁用', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_level` (`level`), + KEY `idx_min_score` (`min_score`) +) ENGINE=InnoDB COMMENT='考核等级评定规则表'; +``` + +**默认数据**: +```sql +INSERT INTO `prison_score_level_rule` (`level`, `level_name`, `min_score`, `max_score`, `description`, `sort`, `status`) VALUES +(1, '优秀', 120.00, 9999.99, '表现突出', 1, 1), +(2, '良好', 100.00, 119.99, '表现良好', 2, 1), +(3, '合格', 80.00, 99.99, '表现一般', 3, 1), +(4, '不合格', 0.00, 79.99, '表现较差', 4, 1); +``` + +### 2.4 考核公示公告表 (prison_score_notice) + +```sql +CREATE TABLE `prison_score_notice` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `title` varchar(200) NOT NULL COMMENT '公告标题', + `notice_type` tinyint NOT NULL DEFAULT 1 COMMENT '公示类型:1-月度考核结果 2-专项考核', + `start_date` date NOT NULL COMMENT '公示开始日期', + `end_date` date NOT NULL COMMENT '公示结束日期', + `scope_type` tinyint NOT NULL DEFAULT 1 COMMENT '公示范围:1-全狱 2-指定监区', + `scope_prison_area_ids` varchar(500) DEFAULT NULL COMMENT '指定监区ID列表', + `content` text COMMENT '公示内容', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:1-草稿 2-已发布 3-已撤回', + `publisher_id` bigint DEFAULT NULL COMMENT '发布人ID', + `publisher_name` varchar(50) DEFAULT NULL COMMENT '发布人姓名', + `publish_time` datetime DEFAULT NULL COMMENT '发布时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_status` (`status`), + KEY `idx_publish_time` (`publish_time`) +) ENGINE=InnoDB COMMENT='考核公示公告表'; +``` + +--- + +## 三、后端接口设计 + +### 3.1 考核规则科目接口 + +**Controller路径**:`controller/admin/score/subject/` + +| 方法 | 端点 | 权限 | 说明 | +|-----|-----|-----|------| +| POST | `/prison/score/subject/create` | prison:score:subject:create | 创建规则 | +| PUT | `/prison/score/subject/update` | prison:score:subject:update | 更新规则 | +| DELETE | `/prison/score/subject/delete` | prison:score:subject:delete | 删除规则 | +| GET | `/prison/score/subject/get` | prison:score:subject:query | 获取详情 | +| GET | `/prison/score/subject/page` | prison:score:subject:query | 分页查询 | +| GET | `/prison/score/subject/list` | prison:score:subject:query | 列表查询(无分页) | +| PUT | `/prison/score/subject/update-status` | prison:score:subject:update | 更新状态 | +| GET | `/prison/score/subject/export-excel` | prison:score:subject:export | 导出Excel | + +**VO对象**: +```java +// ScoreSubjectSaveReqVO.java +public class ScoreSubjectSaveReqVO { + @ApiModelProperty(value = "规则编码", required = true, example = "RULE001") + @NotBlank(message = "规则编码不能为空") + private String code; + + @ApiModelProperty(value = "规则名称", required = true, example = "超额完成生产任务") + @NotBlank(message = "规则名称不能为空") + private String name; + + @ApiModelProperty(value = "考核类别", required = true, example = "1", notes = "1-劳动改造 2-教育改造 3-日常行为 4-卫生纪律 5-加分项 6-扣分项") + @NotNull(message = "考核类别不能为空") + private Integer category; + + @ApiModelProperty(value = "分值", required = true, example = "2.00") + @NotNull(message = "分值不能为空") + private BigDecimal score; + + @ApiModelProperty(value = "日最高分限制", example = "5.00") + private BigDecimal dailyLimit; + + @ApiModelProperty(value = "月最高分限制", example = "30.00") + private BigDecimal monthlyLimit; + + @ApiModelProperty(value = "规则说明", example = "超额完成生产任务") + private String description; + + @ApiModelProperty(value = "状态", example = "1") + private Integer status; + + @ApiModelProperty(value = "排序", example = "1") + private Integer sort; +} + +// ScoreSubjectRespVO.java +public class ScoreSubjectRespVO { + private Long id; + private String code; + private String name; + private Integer category; + private String categoryName; + private BigDecimal score; + private BigDecimal dailyLimit; + private BigDecimal monthlyLimit; + private String description; + private Integer status; + private String statusName; + private Integer sort; + private Date createTime; +} +``` + +### 3.2 日常考核记录接口 + +**Controller路径**:`controller/admin/score/record/` + +| 方法 | 端点 | 权限 | 说明 | +|-----|-----|-----|------| +| POST | `/prison/score/record/create` | prison:score:record:create | 创建记录 | +| POST | `/prison/score/record/batch-create` | prison:score:record:create | 批量创建记录 | +| PUT | `/prison/score/record/update` | prison:score:record:update | 更新记录 | +| DELETE | `/prison/score/record/delete` | prison:score:record:delete | 删除记录 | +| GET | `/prison/score/record/get` | prison:score:record:query | 获取详情 | +| GET | `/prison/score/record/page` | prison:score:record:query | 分页查询 | +| GET | `/prison/score/record/export-excel` | prison:score:record:export | 导出Excel | +| GET | `/prison/score/record/get-by-prisoner` | prison:score:record:query | 获取罪犯考核明细 | + +**VO对象**: +```java +// ScoreRecordSaveReqVO.java +public class ScoreRecordSaveReqVO { + @ApiModelProperty(value = "罪犯ID", required = true) + @NotNull(message = "罪犯ID不能为空") + private Long prisonerId; + + @ApiModelProperty(value = "考核日期", required = true, example = "2026-01-14") + @NotNull(message = "考核日期不能为空") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date recordDate; + + @ApiModelProperty(value = "考核规则ID", required = true) + @NotNull(message = "考核规则ID不能为空") + private Long subjectId; + + @ApiModelProperty(value = "得分", required = true, example = "2.00") + @NotNull(message = "得分不能为空") + private BigDecimal score; + + @ApiModelProperty(value = "备注说明") + private String remark; +} + +// ScoreRecordBatchCreateReqVO.java +public class ScoreRecordBatchCreateReqVO { + @ApiModelProperty(value = "考核日期", required = true) + @NotNull(message = "考核日期不能为空") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date recordDate; + + @ApiModelProperty(value = "罪犯ID列表", required = true) + @NotEmpty(message = "罪犯ID列表不能为空") + private List prisonerIds; + + @ApiModelProperty(value = "考核规则ID", required = true) + @NotNull(message = "考核规则ID不能为空") + private Long subjectId; + + @ApiModelProperty(value = "得分", required = true) + @NotNull(message = "得分不能为空") + private BigDecimal score; + + @ApiModelProperty(value = "备注说明") + private String remark; +} + +// ScoreRecordRespVO.java +public class ScoreRecordRespVO { + private Long id; + private Long prisonerId; + private String prisonerNo; + private String prisonerName; + private Long prisonAreaId; + private String prisonAreaName; + private Date recordDate; + private Long subjectId; + private String subjectName; + private Integer category; + private String categoryName; + private BigDecimal score; + private BigDecimal actualScore; + private String remark; + private Long recorderId; + private String recorderName; + private Date createTime; +} +``` + +### 3.3 月度考核汇总接口 + +**Controller路径**:`controller/admin/score/monthly/` + +| 方法 | 端点 | 权限 | 说明 | +|-----|-----|-----|------| +| POST | `/prison/score/monthly/calculate` | prison:score:monthly:calculate | 手动触发月度汇总计算 | +| GET | `/prison/score/monthly/get-summary` | prison:score:monthly:query | 获取月度汇总详情 | +| GET | `/prison/score/monthly/page` | prison:score:monthly:query | 分页查询月度汇总 | +| POST | `/prison/score/monthly/submit-audit` | prison:score:monthly:audit | 提交审核 | +| POST | `/prison/score/monthly/audit` | prison:score:monthly:audit | 审核通过/驳回 | +| GET | `/prison/score/monthly/export-excel` | prison:score:monthly:export | 导出Excel | +| GET | `/prison/score/monthly/get-detail` | prison:score:monthly:query | 获取月度汇总明细 | + +**业务逻辑**: +```java +/** + * 月度汇总计算逻辑 + */ +public void calculateMonthlySummary(Integer year, Integer month) { + // 1. 获取所有罪犯列表 + List prisoners = prisonerService.getActivePrisonerList(); + + // 2. 遍历每个罪犯 + for (Prisoner prisoner : prisoners) { + // 3. 获取该罪犯当月所有日常考核记录 + List records = getMonthlyRecords(prisoner.getId(), year, month); + + // 4. 计算加分合计(考虑日限月限) + BigDecimal rewardScore = calculateRewardScore(records); + + // 5. 计算扣分合计(考虑日限月限) + BigDecimal penaltyScore = calculatePenaltyScore(records); + + // 6. 获取基础分配置 + BigDecimal baseScore = getBaseScoreConfig(); + + // 7. 计算总分 + BigDecimal totalScore = baseScore.add(rewardScore).add(penaltyScore); + + // 8. 评定等级 + Integer level = assessLevel(totalScore); + + // 9. 保存或更新月度汇总记录 + saveOrUpdateMonthlySummary(prisoner, year, month, baseScore, rewardScore, penaltyScore, totalScore, level); + } +} + +/** + * 计算加分(考虑日限月限) + */ +private BigDecimal calculateRewardScore(List records) { + // 按规则分组,计算每条规则的加分 + // 超过日限的按日限计算 + // 超过月限的按月限计算 + // 返回最终加分合计 +} +``` + +### 3.4 考核等级规则接口 + +**Controller路径**:`controller/admin/score/level/` + +| 方法 | 端点 | 权限 | 说明 | +|-----|-----|-----|------| +| PUT | `/prison/score/level/update` | prison:score:level:update | 更新等级规则 | +| GET | `/prison/score/level/get` | prison:score:level:query | 获取等级规则列表 | +| GET | `/prison/score/level/get-base-score` | prison:score:level:query | 获取基础分配置 | +| PUT | `/prison/score/level/update-base-score` | prison:score:level:update | 更新基础分配置 | + +### 3.5 考核公示公告接口 + +**Controller路径**:`controller/admin/score/notice/` + +| 方法 | 端点 | 权限 | 说明 | +|-----|-----|-----|------| +| POST | `/prison/score/notice/create` | prison:score:notice:create | 创建公示 | +| PUT | `/prison/score/notice/update` | prison:score:notice:update | 更新公示 | +| PUT | `/prison/score/notice/publish` | prison:score:notice:publish | 发布公示 | +| PUT | `/prison/score/notice/withdraw` | prison:score:notice:publish | 撤回公示 | +| DELETE | `/prison/score/notice/delete` | prison:score:notice:delete | 删除公示 | +| GET | `/prison/score/notice/get` | prison:score:notice:query | 获取详情 | +| GET | `/prison/score/notice/page` | prison:score:notice:query | 分页查询 | + +### 3.6 减刑假释数据提取接口 + +**Controller路径**:`controller/admin/score/parole/` + +| 方法 | 端点 | 权限 | 说明 | +|-----|-----|-----|------| +| GET | `/prison/score/parole/get-data` | prison:score:parole:query | 获取减刑假释考核数据 | +| POST | `/prison/score/parole/generate-suggestion` | prison:score:parole:query | 生成减刑假释建议 | + +**返回数据结构**: +```java +public class ScoreParoleDataVO { + private Long prisonerId; + private String prisonerNo; + private String prisonerName; + + // 近6个月月度考核数据 + private List monthlyScores; + + // 年度累计考核分 + private BigDecimal yearlyTotalScore; + + // 表扬次数 + private Integer praiseCount; + + // 警告次数 + private Integer warningCount; + + // 等级评定记录 + private List levelRecords; + + // 减刑假释建议 + private ParoleSuggestionVO suggestion; +} +``` + +--- + +## 四、批量SQL脚本 + +```sql +-- ==================== 计分考核模块 DDL ==================== + +-- 1. 考核规则科目表 +CREATE TABLE `prison_score_subject` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '规则ID', + `code` varchar(50) NOT NULL COMMENT '规则编码', + `name` varchar(100) NOT NULL COMMENT '规则名称', + `category` tinyint NOT NULL COMMENT '考核类别', + `score` decimal(10,2) NOT NULL COMMENT '分值', + `daily_limit` decimal(10,2) NOT NULL DEFAULT 0 COMMENT '日最高分限制', + `monthly_limit` decimal(10,2) NOT NULL DEFAULT 0 COMMENT '月最高分限制', + `description` varchar(500) DEFAULT NULL COMMENT '规则说明', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_category` (`category`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB COMMENT='考核规则科目表'; + +-- 2. 日常考核记录表 +CREATE TABLE `prison_score_record` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '记录ID', + `prisoner_id` bigint NOT NULL COMMENT '罪犯ID', + `prisoner_no` varchar(50) NOT NULL COMMENT '罪犯编号', + `record_date` date NOT NULL COMMENT '考核日期', + `subject_id` bigint NOT NULL COMMENT '考核规则ID', + `subject_name` varchar(100) NOT NULL COMMENT '规则名称', + `category` tinyint NOT NULL COMMENT '考核类别', + `score` decimal(10,2) NOT NULL COMMENT '得分', + `actual_score` decimal(10,2) NOT NULL COMMENT '实际得分', + `remark` varchar(500) DEFAULT NULL COMMENT '备注说明', + `recorder_id` bigint NOT NULL COMMENT '记录人ID', + `recorder_name` varchar(50) NOT NULL COMMENT '记录人姓名', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_prisoner_date` (`prisoner_no`, `record_date`), + KEY `idx_record_date` (`record_date`), + KEY `idx_subject` (`subject_id`) +) ENGINE=InnoDB COMMENT='日常考核记录表'; + +-- 3. 考核等级评定规则表 +CREATE TABLE `prison_score_level_rule` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '规则ID', + `level` tinyint NOT NULL COMMENT '等级', + `level_name` varchar(20) NOT NULL COMMENT '等级名称', + `min_score` decimal(10,2) NOT NULL COMMENT '最低分', + `max_score` decimal(10,2) NOT NULL COMMENT '最高分', + `description` varchar(500) DEFAULT NULL COMMENT '说明', + `sort` int NOT NULL DEFAULT 0 COMMENT '排序', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_level` (`level`), + KEY `idx_min_score` (`min_score`) +) ENGINE=InnoDB COMMENT='考核等级评定规则表'; + +-- 4. 考核公示公告表 +CREATE TABLE `prison_score_notice` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `title` varchar(200) NOT NULL COMMENT '公告标题', + `notice_type` tinyint NOT NULL DEFAULT 1 COMMENT '公示类型', + `start_date` date NOT NULL COMMENT '公示开始日期', + `end_date` date NOT NULL COMMENT '公示结束日期', + `scope_type` tinyint NOT NULL DEFAULT 1 COMMENT '公示范围', + `scope_prison_area_ids` varchar(500) DEFAULT NULL COMMENT '指定监区ID列表', + `content` text COMMENT '公示内容', + `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态', + `publisher_id` bigint DEFAULT NULL COMMENT '发布人ID', + `publisher_name` varchar(50) DEFAULT NULL COMMENT '发布人姓名', + `publish_time` datetime DEFAULT NULL COMMENT '发布时间', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`), + KEY `idx_status` (`status`), + KEY `idx_publish_time` (`publish_time`) +) ENGINE=InnoDB COMMENT='考核公示公告表'; + +-- 5. 初始化等级规则数据 +INSERT INTO `prison_score_level_rule` (`level`, `level_name`, `min_score`, `max_score`, `description`, `sort`, `status`) VALUES +(1, '优秀', 120.00, 9999.99, '表现突出', 1, 1), +(2, '良好', 100.00, 119.99, '表现良好', 2, 1), +(3, '合格', 80.00, 99.99, '表现一般', 3, 1), +(4, '不合格', 0.00, 79.99, '表现较差', 4, 1); + +-- 6. 初始化示例规则数据 +INSERT INTO `prison_score_subject` (`code`, `name`, `category`, `score`, `daily_limit`, `monthly_limit`, `description`, `status`, `sort`) VALUES +('LABOR001', '超额完成生产任务', 1, 2.00, 5.00, 30.00, '超额完成生产任务', 1, 1), +('LABOR002', '完成生产任务', 1, 1.00, 3.00, 20.00, '完成生产任务', 1, 2), +('EDU001', '参加义务劳动', 2, 1.00, 2.00, 10.00, '参加义务劳动', 1, 1), +('EDU002', '考试合格', 2, 1.00, 3.00, 15.00, '考试合格', 1, 2), +('DAILY001', '获得表扬', 3, 2.00, 5.00, 20.00, '获得表扬', 1, 1), +('DAILY002', '主动报告隐患', 3, 1.00, 2.00, 10.00, '主动报告隐患', 1, 2), +('HYGIENE001', '内务不整洁', 4, -0.50, -3.00, -10.00, '内务不整洁', 1, 1), +('HYGIENE002', '违规吸烟', 4, -2.00, -5.00, -20.00, '违规吸烟', 1, 2), +('PENALTY001', '打架斗殴', 6, -5.00, -10.00, -30.00, '打架斗殴', 1, 1), +('PENALTY002', '私藏违禁品', 6, -10.00, -20.00, -50.00, '私藏违禁品', 1, 2); +``` + +--- + +## 五、目录结构 + +``` +backend/yudao-module-prison/src/main/java/cn/iocoder/yudao/module/prison/ +├── controller/admin/score/ +│ ├── subject/ # 考核规则科目 +│ │ ├── PrisonScoreSubjectController.java +│ │ └── vo/ +│ │ ├── ScoreSubjectPageReqVO.java +│ │ ├── ScoreSubjectSaveReqVO.java +│ │ └── ScoreSubjectRespVO.java +│ ├── record/ # 日常考核记录 +│ │ ├── PrisonScoreRecordController.java +│ │ └── vo/ +│ │ ├── ScoreRecordPageReqVO.java +│ │ ├── ScoreRecordSaveReqVO.java +│ │ ├── ScoreRecordBatchCreateReqVO.java +│ │ └── ScoreRecordRespVO.java +│ ├── monthly/ # 月度汇总 +│ │ ├── PrisonScoreMonthlyController.java +│ │ └── vo/ +│ │ ├── ScoreMonthlyPageReqVO.java +│ │ ├── ScoreMonthlyRespVO.java +│ │ └── ScoreMonthlyDetailRespVO.java +│ ├── level/ # 等级规则 +│ │ ├── PrisonScoreLevelController.java +│ │ └── vo/ +│ │ └── ScoreLevelRespVO.java +│ ├── notice/ # 公示公告 +│ │ ├── PrisonScoreNoticeController.java +│ │ └── vo/ +│ │ ├── ScoreNoticePageReqVO.java +│ │ ├── ScoreNoticeSaveReqVO.java +│ │ └── ScoreNoticeRespVO.java +│ └── parole/ # 减刑假释 +│ ├── PrisonScoreParoleController.java +│ └── vo/ +│ └── ScoreParoleDataRespVO.java +│ +├── service/score/ +│ ├── ScoreSubjectService.java +│ ├── impl/ScoreSubjectServiceImpl.java +│ ├── ScoreRecordService.java +│ ├── impl/ScoreRecordServiceImpl.java +│ ├── ScoreMonthlyService.java +│ ├── impl/ScoreMonthlyServiceImpl.java +│ ├── ScoreLevelService.java +│ ├── impl/ScoreLevelServiceImpl.java +│ ├── ScoreNoticeService.java +│ ├── impl/ScoreNoticeServiceImpl.java +│ └── ScoreParoleService.java +│ └── impl/ScoreParoleServiceImpl.java +│ +├── dal/dataobject/score/ +│ ├── ScoreSubjectDO.java +│ ├── ScoreRecordDO.java +│ ├── ScoreLevelRuleDO.java +│ ├── ScoreNoticeDO.java +│ └── ScoreDO.java # 已有 +│ +└── dal/mysql/score/ + ├── ScoreSubjectMapper.java + ├── ScoreRecordMapper.java + ├── ScoreLevelRuleMapper.java + ├── ScoreNoticeMapper.java + └── ScoreMapper.java # 已有 +``` + +--- + +## 六、验收标准 + +- [ ] 创建考核规则科目表并实现CRUD接口 +- [ ] 创建日常考核记录表并实现CRUD接口(含批量录入) +- [ ] 创建考核等级规则表并实现配置接口 +- [ ] 创建考核公示公告表并实现发布功能 +- [ ] 实现月度汇总自动计算逻辑 +- [ ] 实现日/月最高分限制校验 +- [ ] 实现减刑假释数据提取接口 +- [ ] 所有接口通过单元测试