diff --git a/.codex-police-test-pom.xml b/.codex-police-test-pom.xml
new file mode 100644
index 0000000..decf7a0
--- /dev/null
+++ b/.codex-police-test-pom.xml
@@ -0,0 +1,374 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.3.2
+
+
+ com.biutag
+ supervision
+ 0.0.1-SNAPSHOT
+ supervision
+ 长沙公安数据督察
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 17
+
+
+
+
+ org.jfree
+ jfreechart
+ 1.5.4
+
+
+
+ com.deepoove
+ poi-tl
+ 1.12.2
+
+
+ org.apache.poi
+ poi
+
+
+ org.apache.poi
+ poi-ooxml
+
+
+ org.apache.poi
+ poi-ooxml-lite
+
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ org.mapstruct
+ mapstruct
+ 1.5.5.Final
+
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ 1.5.5.Final
+ provided
+
+
+
+
+ com.google.guava
+ guava
+ 32.1.2-jre
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis-reactive
+
+
+
+
+
+ com.dameng
+ DmJdbcDriver18
+ 8.1.3.140
+
+
+
+
+
+
+
+
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+
+
+ com.microsoft.sqlserver
+ mssql-jdbc
+ 12.8.1.jre11
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.0
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ 2.3.0
+
+
+ com.sun.xml.bind
+ jaxb-core
+ 2.3.0
+
+
+ javax.activation
+ activation
+ 1.1.1
+
+
+
+
+ com.gbase
+ gbase-jdbc
+ system
+ 8.3.81.53-build55.2.1-bin
+ ${project.basedir}/src/main/resources/lib/gbase-connector-java-8.3.81.53-build52.8-bin.jar
+
+
+
+
+ com.dameng
+ DmJdbcDriver18
+ 8.1.3.140
+
+
+
+
+ org.postgresql
+ postgresql
+ 42.7.4
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.2.22
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ 3.5.7
+
+
+
+ com.alibaba
+ easyexcel
+ 4.0.1
+
+
+
+ commons-io
+ commons-io
+ 2.17.0
+
+
+
+ cn.hutool
+ hutool-all
+ 5.8.29
+
+
+
+
+ cn.hutool
+ hutool-core
+ 5.8.29
+
+
+ cn.hutool
+ hutool-http
+ 5.8.29
+
+
+
+ com.baomidou
+ dynamic-datasource-spring-boot3-starter
+ 4.3.1
+
+
+
+ org.freemarker
+ freemarker
+ 2.3.32
+
+
+
+ org.springframework.security
+ spring-security-crypto
+
+
+
+ com.github.tobato
+ fastdfs-client
+ 1.27.2
+
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+ 4.1.0
+
+
+
+ com.alibaba
+ fastjson
+ 2.0.53
+
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ 4.9
+
+
+
+
+ com.aspose
+ aspose-words
+ 15.8.0
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ cn.com.jit
+ authSDK
+ 3.0.3
+
+
+ commons-httpclient
+ commons-httpclient
+ 3.0.1
+
+
+
+ org.jsoup
+ jsoup
+ 1.17.2
+
+
+
+
+
+
+
+ src/main/resources
+ false
+
+
+
+ src/main/resources
+
+ application.yml
+
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+ false
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+ supervision
+
+
+
+
+ local
+
+
+ local
+
+
+
+
+ true
+
+
+
+ dev
+
+
+ dev
+
+
+
+ prod
+
+ prod
+
+
+
+
+
diff --git a/pom.codex-query-verify.xml b/pom.codex-query-verify.xml
new file mode 100644
index 0000000..decf7a0
--- /dev/null
+++ b/pom.codex-query-verify.xml
@@ -0,0 +1,374 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.3.2
+
+
+ com.biutag
+ supervision
+ 0.0.1-SNAPSHOT
+ supervision
+ 长沙公安数据督察
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 17
+
+
+
+
+ org.jfree
+ jfreechart
+ 1.5.4
+
+
+
+ com.deepoove
+ poi-tl
+ 1.12.2
+
+
+ org.apache.poi
+ poi
+
+
+ org.apache.poi
+ poi-ooxml
+
+
+ org.apache.poi
+ poi-ooxml-lite
+
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ org.mapstruct
+ mapstruct
+ 1.5.5.Final
+
+
+
+
+ org.mapstruct
+ mapstruct-processor
+ 1.5.5.Final
+ provided
+
+
+
+
+ com.google.guava
+ guava
+ 32.1.2-jre
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis-reactive
+
+
+
+
+
+ com.dameng
+ DmJdbcDriver18
+ 8.1.3.140
+
+
+
+
+
+
+
+
+
+
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
+
+
+
+ com.microsoft.sqlserver
+ mssql-jdbc
+ 12.8.1.jre11
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.0
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ 2.3.0
+
+
+ com.sun.xml.bind
+ jaxb-core
+ 2.3.0
+
+
+ javax.activation
+ activation
+ 1.1.1
+
+
+
+
+ com.gbase
+ gbase-jdbc
+ system
+ 8.3.81.53-build55.2.1-bin
+ ${project.basedir}/src/main/resources/lib/gbase-connector-java-8.3.81.53-build52.8-bin.jar
+
+
+
+
+ com.dameng
+ DmJdbcDriver18
+ 8.1.3.140
+
+
+
+
+ org.postgresql
+ postgresql
+ 42.7.4
+
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.2.22
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+ 3.5.7
+
+
+
+ com.alibaba
+ easyexcel
+ 4.0.1
+
+
+
+ commons-io
+ commons-io
+ 2.17.0
+
+
+
+ cn.hutool
+ hutool-all
+ 5.8.29
+
+
+
+
+ cn.hutool
+ hutool-core
+ 5.8.29
+
+
+ cn.hutool
+ hutool-http
+ 5.8.29
+
+
+
+ com.baomidou
+ dynamic-datasource-spring-boot3-starter
+ 4.3.1
+
+
+
+ org.freemarker
+ freemarker
+ 2.3.32
+
+
+
+ org.springframework.security
+ spring-security-crypto
+
+
+
+ com.github.tobato
+ fastdfs-client
+ 1.27.2
+
+
+
+
+ com.github.xiaoymin
+ knife4j-openapi3-jakarta-spring-boot-starter
+ 4.1.0
+
+
+
+ com.alibaba
+ fastjson
+ 2.0.53
+
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ 4.9
+
+
+
+
+ com.aspose
+ aspose-words
+ 15.8.0
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+ cn.com.jit
+ authSDK
+ 3.0.3
+
+
+ commons-httpclient
+ commons-httpclient
+ 3.0.1
+
+
+
+ org.jsoup
+ jsoup
+ 1.17.2
+
+
+
+
+
+
+
+ src/main/resources
+ false
+
+
+
+ src/main/resources
+
+ application.yml
+
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+ false
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+ supervision
+
+
+
+
+ local
+
+
+ local
+
+
+
+
+ true
+
+
+
+ dev
+
+
+ dev
+
+
+
+ prod
+
+ prod
+
+
+
+
+
diff --git a/sql/20261027_profile_query_explain.sql b/sql/20261027_profile_query_explain.sql
new file mode 100644
index 0000000..344b40c
--- /dev/null
+++ b/sql/20261027_profile_query_explain.sql
@@ -0,0 +1,267 @@
+-- MySQL 5.7.21:只读诊断脚本,请先选中生产业务库。
+-- 下面默认查询全部时间、全部单位,与列表初次打开一致。
+-- 请先返回本文件的版本、行数估计、索引、8 份 EXPLAIN 结果;不要先执行建索引脚本。
+-- EXPLAIN 不返回业务明细,不代表真实耗时;验证耗时需另行运行实际 SQL。
+SELECT VERSION(), DATABASE();
+SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES
+WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME IN ('negative','negative_blame','sup_police','sup_depart','sup_depart_police_size');
+SHOW INDEX FROM negative;
+SHOW INDEX FROM negative_blame;
+SHOW INDEX FROM sup_police;
+SHOW INDEX FROM sup_depart;
+SHOW INDEX FROM sup_depart_police_size;
+
+SET @beginTime = '1949-01-01 00:00:00';
+SET @endTime = NOW();
+
+-- 单位问题库:优化前列表查询(第一页 10 条)
+EXPLAIN
+SELECT
+ d.id depart_id,
+ d1.short_name parent_depart_name,
+ d.short_name depart_name,
+ p.police_size,
+ p.aux_size,
+ count(DISTINCT nb.blameIdCode) verify_police_size,
+ count(DISTINCT n.id) verify_size
+ FROM sup_depart d
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id
+ LEFT JOIN sup_depart_police_size p ON p.depart_id = d.id
+ INNER JOIN negative n ON d.id = n.involveDepartId
+ LEFT JOIN negative_blame nb ON n.id = nb.negativeId
+ WHERE d.level = 3
+ AND n.crtTime BETWEEN @beginTime AND @endTime
+
+
+
+ GROUP BY d.id, d1.short_name, d.short_name, p.police_size, p.aux_size
+ ORDER BY
+ verify_size
+ DESC , d.id ASC
+LIMIT 0, 10;
+
+-- 单位问题库:优化前分页总数
+EXPLAIN
+SELECT count(*) FROM (
+SELECT
+ d.id depart_id,
+ d1.short_name parent_depart_name,
+ d.short_name depart_name,
+ p.police_size,
+ p.aux_size,
+ count(DISTINCT nb.blameIdCode) verify_police_size,
+ count(DISTINCT n.id) verify_size
+ FROM sup_depart d
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id
+ LEFT JOIN sup_depart_police_size p ON p.depart_id = d.id
+ INNER JOIN negative n ON d.id = n.involveDepartId
+ LEFT JOIN negative_blame nb ON n.id = nb.negativeId
+ WHERE d.level = 3
+ AND n.crtTime BETWEEN @beginTime AND @endTime
+
+
+
+ GROUP BY d.id, d1.short_name, d.short_name, p.police_size, p.aux_size
+) counted;
+
+-- 单位问题库:优化后列表查询(第一页 10 条)
+EXPLAIN
+SELECT DISTINCT
+ d.id depart_id,
+ d1.short_name parent_depart_name,
+ d.short_name depart_name,
+ p.police_size,
+ p.aux_size,
+ stats.verify_police_size,
+ stats.verify_size
+ FROM (
+ SELECT d.id depart_id,
+ count(DISTINCT nb.blameIdCode) verify_police_size,
+ count(DISTINCT n.id) verify_size
+ FROM sup_depart d
+ INNER JOIN negative n ON d.id = n.involveDepartId
+ LEFT JOIN negative_blame nb ON n.id = nb.negativeId
+ WHERE
+ d.level = 3
+
+
+
+
+ AND n.crtTime BETWEEN @beginTime AND @endTime
+ GROUP BY d.id
+ ) stats
+ INNER JOIN sup_depart d ON d.id = stats.depart_id
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id
+ LEFT JOIN sup_depart_police_size p ON p.depart_id = d.id
+ ORDER BY
+ verify_size
+ DESC , d.id ASC
+LIMIT 0, 10;
+
+-- 单位问题库:优化后分页总数
+EXPLAIN
+SELECT count(*) FROM (
+ SELECT DISTINCT d.id, p.police_size, p.aux_size
+ FROM sup_depart d
+ LEFT JOIN sup_depart_police_size p ON p.depart_id = d.id
+ WHERE
+ d.level = 3
+
+
+
+
+ AND EXISTS (
+ SELECT 1 FROM negative n
+ WHERE n.involveDepartId = d.id
+ AND n.crtTime BETWEEN @beginTime AND @endTime
+ )
+ ) counted;
+
+-- 个人问题库:优化前列表查询(第一页 10 条)
+EXPLAIN
+SELECT
+ p.id_code,
+ p.NAME,
+ p.emp_no,
+ p.position,
+ p.employment_date,
+ p.person_type,
+ d.short_name depart_name,
+ d.id depart_id,
+ d1.short_name parent_depart_name,
+ count(DISTINCT n.id) verify_size
+ FROM
+ sup_police p
+ LEFT JOIN sup_depart d ON p.org_id = d.id
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id and d1.level >= 2
+ INNER JOIN negative_blame nb ON p.id_code = nb.blameIdCode AND nb.type = 'personal'
+ INNER JOIN negative n ON nb.negativeId = n.id
+ WHERE
+ p.del = 0
+ AND n.checkStatus IN ('1', '2')
+ AND n.processing_status = 'completed'
+ AND n.discoveryTime BETWEEN @beginTime AND @endTime
+
+
+
+
+
+ GROUP BY
+ p.id_code,
+ p.NAME,
+ p.emp_no,
+ p.employment_date,
+ p.position,
+ p.person_type,
+ d.short_name,
+ d.id,
+ d1.short_name
+ ORDER BY
+ verify_size
+ DESC , p.id_code ASC
+LIMIT 0, 10;
+
+-- 个人问题库:优化前分页总数
+EXPLAIN
+SELECT count(*) FROM (
+SELECT
+ p.id_code,
+ p.NAME,
+ p.emp_no,
+ p.position,
+ p.employment_date,
+ p.person_type,
+ d.short_name depart_name,
+ d.id depart_id,
+ d1.short_name parent_depart_name,
+ count(DISTINCT n.id) verify_size
+ FROM
+ sup_police p
+ LEFT JOIN sup_depart d ON p.org_id = d.id
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id and d1.level >= 2
+ INNER JOIN negative_blame nb ON p.id_code = nb.blameIdCode AND nb.type = 'personal'
+ INNER JOIN negative n ON nb.negativeId = n.id
+ WHERE
+ p.del = 0
+ AND n.checkStatus IN ('1', '2')
+ AND n.processing_status = 'completed'
+ AND n.discoveryTime BETWEEN @beginTime AND @endTime
+
+
+
+
+
+ GROUP BY
+ p.id_code,
+ p.NAME,
+ p.emp_no,
+ p.employment_date,
+ p.position,
+ p.person_type,
+ d.short_name,
+ d.id,
+ d1.short_name
+) counted;
+
+-- 个人问题库:优化后列表查询(第一页 10 条)
+EXPLAIN
+SELECT DISTINCT
+ p.id_code, p.name, p.emp_no, p.position, p.employment_date, p.person_type,
+ d.short_name depart_name, d.id depart_id, d1.short_name parent_depart_name
+ , stats.verify_size
+ FROM (
+ SELECT nb.blameIdCode, count(DISTINCT n.id) verify_size
+ FROM negative n
+ INNER JOIN negative_blame nb ON nb.negativeId = n.id
+ WHERE
+ nb.type = 'personal'
+ AND n.checkStatus IN ('1', '2')
+ AND n.processing_status = 'completed'
+ AND n.discoveryTime BETWEEN @beginTime AND @endTime
+
+ GROUP BY nb.blameIdCode
+ ) stats
+ INNER JOIN sup_police p ON p.id_code = stats.blameIdCode
+ LEFT JOIN sup_depart d ON p.org_id = d.id
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id AND d1.level >= 2
+ WHERE
+ p.del = 0
+
+
+
+
+
+ ORDER BY verify_size
+ DESC , p.id_code ASC
+LIMIT 0, 10;
+
+-- 个人问题库:优化后分页总数
+EXPLAIN
+SELECT count(*) FROM (
+ SELECT DISTINCT
+ p.id_code, p.name, p.emp_no, p.position, p.employment_date, p.person_type,
+ d.short_name depart_name, d.id depart_id, d1.short_name parent_depart_name
+
+ FROM sup_police p
+ LEFT JOIN sup_depart d ON p.org_id = d.id
+ LEFT JOIN sup_depart d1 ON d.pid = d1.id AND d1.level >= 2
+ WHERE
+ p.del = 0
+
+
+
+
+
+ AND EXISTS (
+ SELECT 1 FROM negative_blame nb
+ INNER JOIN negative n ON nb.negativeId = n.id
+ WHERE nb.blameIdCode = p.id_code
+ AND
+ nb.type = 'personal'
+ AND n.checkStatus IN ('1', '2')
+ AND n.processing_status = 'completed'
+ AND n.discoveryTime BETWEEN @beginTime AND @endTime
+
+ )
+ ) counted;
+
diff --git a/sql/20261027_profile_query_indexes.sql b/sql/20261027_profile_query_indexes.sql
new file mode 100644
index 0000000..106b831
--- /dev/null
+++ b/sql/20261027_profile_query_indexes.sql
@@ -0,0 +1,95 @@
+-- 单位/个人问题库查询索引,MySQL InnoDB。
+-- 在目标业务库执行;先核对字段类型、索引长度和剩余磁盘空间。
+-- 按完整左前缀识别已有等价索引;LOCK=NONE 不支持时会报错,不自动降级为锁表。
+-- 在低峰期逐条执行,建索引会消耗 I/O;无需删除任何现有索引或业务数据。
+
+SET @profile_index_sql = IF(
+ EXISTS (
+ SELECT 1 FROM (
+ SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') AS columns_in_index,
+ SUM(SUB_PART IS NOT NULL) AS prefix_parts
+ FROM information_schema.STATISTICS
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'negative' AND INDEX_TYPE = 'BTREE'
+ GROUP BY INDEX_NAME
+ ) existing_indexes
+ WHERE prefix_parts = 0 AND (columns_in_index = 'involveDepartId,crtTime' OR columns_in_index LIKE 'involveDepartId,crtTime,%')
+ ),
+ 'SELECT ''idx_profile_depart_time: existing equivalent index, skipped'' AS result',
+ 'ALTER TABLE `negative` ADD INDEX `idx_profile_depart_time` (`involveDepartId`, `crtTime`), ALGORITHM=INPLACE, LOCK=NONE'
+);
+PREPARE profile_index_stmt FROM @profile_index_sql;
+EXECUTE profile_index_stmt;
+DEALLOCATE PREPARE profile_index_stmt;
+
+SET @profile_index_sql = IF(
+ EXISTS (
+ SELECT 1 FROM (
+ SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') AS columns_in_index,
+ SUM(SUB_PART IS NOT NULL) AS prefix_parts
+ FROM information_schema.STATISTICS
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'negative' AND INDEX_TYPE = 'BTREE'
+ GROUP BY INDEX_NAME
+ ) existing_indexes
+ WHERE prefix_parts = 0 AND (columns_in_index = 'processing_status,checkStatus,discoveryTime' OR columns_in_index LIKE 'processing_status,checkStatus,discoveryTime,%')
+ ),
+ 'SELECT ''idx_profile_verified_time: existing equivalent index, skipped'' AS result',
+ 'ALTER TABLE `negative` ADD INDEX `idx_profile_verified_time` (`processing_status`, `checkStatus`, `discoveryTime`), ALGORITHM=INPLACE, LOCK=NONE'
+);
+PREPARE profile_index_stmt FROM @profile_index_sql;
+EXECUTE profile_index_stmt;
+DEALLOCATE PREPARE profile_index_stmt;
+
+SET @profile_index_sql = IF(
+ EXISTS (
+ SELECT 1 FROM (
+ SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') AS columns_in_index,
+ SUM(SUB_PART IS NOT NULL) AS prefix_parts
+ FROM information_schema.STATISTICS
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'negative_blame' AND INDEX_TYPE = 'BTREE'
+ GROUP BY INDEX_NAME
+ ) existing_indexes
+ WHERE prefix_parts = 0 AND (columns_in_index = 'negativeId,type,blameIdCode' OR columns_in_index LIKE 'negativeId,type,blameIdCode,%')
+ ),
+ 'SELECT ''idx_profile_problem_person: existing equivalent index, skipped'' AS result',
+ 'ALTER TABLE `negative_blame` ADD INDEX `idx_profile_problem_person` (`negativeId`, `type`, `blameIdCode`), ALGORITHM=INPLACE, LOCK=NONE'
+);
+PREPARE profile_index_stmt FROM @profile_index_sql;
+EXECUTE profile_index_stmt;
+DEALLOCATE PREPARE profile_index_stmt;
+
+SET @profile_index_sql = IF(
+ EXISTS (
+ SELECT 1 FROM (
+ SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') AS columns_in_index,
+ SUM(SUB_PART IS NOT NULL) AS prefix_parts
+ FROM information_schema.STATISTICS
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'negative_blame' AND INDEX_TYPE = 'BTREE'
+ GROUP BY INDEX_NAME
+ ) existing_indexes
+ WHERE prefix_parts = 0 AND (columns_in_index = 'blameIdCode,type,negativeId' OR columns_in_index LIKE 'blameIdCode,type,negativeId,%')
+ ),
+ 'SELECT ''idx_profile_person_problem: existing equivalent index, skipped'' AS result',
+ 'ALTER TABLE `negative_blame` ADD INDEX `idx_profile_person_problem` (`blameIdCode`, `type`, `negativeId`), ALGORITHM=INPLACE, LOCK=NONE'
+);
+PREPARE profile_index_stmt FROM @profile_index_sql;
+EXECUTE profile_index_stmt;
+DEALLOCATE PREPARE profile_index_stmt;
+
+SET @profile_index_sql = IF(
+ EXISTS (
+ SELECT 1 FROM (
+ SELECT GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') AS columns_in_index,
+ SUM(SUB_PART IS NOT NULL) AS prefix_parts
+ FROM information_schema.STATISTICS
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'sup_police' AND INDEX_TYPE = 'BTREE'
+ GROUP BY INDEX_NAME
+ ) existing_indexes
+ WHERE prefix_parts = 0 AND (columns_in_index = 'id_code,del' OR columns_in_index LIKE 'id_code,del,%')
+ ),
+ 'SELECT ''idx_profile_police_identity: existing equivalent index, skipped'' AS result',
+ 'ALTER TABLE `sup_police` ADD INDEX `idx_profile_police_identity` (`id_code`, `del`), ALGORITHM=INPLACE, LOCK=NONE'
+);
+PREPARE profile_index_stmt FROM @profile_index_sql;
+EXECUTE profile_index_stmt;
+DEALLOCATE PREPARE profile_index_stmt;
+
diff --git a/sql/20261027_profile_query_performance.md b/sql/20261027_profile_query_performance.md
new file mode 100644
index 0000000..7adc03d
--- /dev/null
+++ b/sql/20261027_profile_query_performance.md
@@ -0,0 +1,23 @@
+# 单位 / 个人问题库查询优化(MySQL 5.7.21)
+
+## 本次改动
+
+- 先按单位 ID / 身份证号聚合明细,再连接名称、职务等展示字段,避免在多字段的明细结果上分组。
+- 分页使用自定义 count SQL,使用 EXISTS 判断是否有符合条件的问题,不再重复统计每个单位的涉及人数或每个人的问题数。
+- 保留 DISTINCT 去重语义、筛选条件、全量排序后分页及总数。不新增缓存,不降低数据实时性。
+- 单位仍按问题创建时间统计;个人仍按发现时间、已办结、属实/部分属实及个人责任记录统计,不调整业务口径。
+
+## 生产核查步骤
+
+1. 在业务库执行 `20261027_profile_query_explain.sql`,收集版本、表规模估计、索引及优化前后 8 份 EXPLAIN。默认不限时间、不选单位;如果慢请求带筛选条件,应按实际请求补上同样条件。
+2. 检查 `negative_blame` 是否按 `negativeId` / `blameIdCode` 走索引、`negative` 是否使用对应时间和状态索引,以及连接字段的数据类型和字符集是否一致。小的聚合结果出现临时表或排序不等于优化失败。
+3. 对照现有索引评估 `20261027_profile_query_indexes.sql`。脚本按完整左前缀跳过已有等价索引,不删除旧索引。先确认 InnoDB、字段长度、磁盘空间和同名索引冲突;低峰期执行。在线建索引仍消耗 I/O 并可能等待元数据锁,LOCK=NONE 不支持时会停止,不降级为锁表。
+4. 索引准备后部署后端改动,再执行优化后 EXPLAIN 和实际请求。MySQL 5.7 不支持 EXPLAIN ANALYZE;EXPLAIN 的 rows 是估计值,不能用来证明 3 秒达标。
+5. 性能验收同时计入总数 SQL、列表 SQL、接口开销和网络耗时。分别验证首次请求与重复请求、不限时间与短时间范围、单位/姓名筛选、升降序、后续分页,以及实际并发下的耗时。避免把查询缓存命中误判为 SQL 本身已优化。
+
+## 验证状态
+
+- 后端编译、SQL 映射与排序/筛选回归测试已通过。
+- 本地模拟使用 SQLite 内存数据库及 12 万条问题,属于结果一致性和优化方向验证,不是生产 MySQL 5.7 性能验收。
+- 开发数据库连接失败;生产索引、执行计划和端到端耗时尚未取得,不能承诺已达到 3 秒。
+- 索引脚本尚未对任何数据库执行;本次未改前端或运行前端构建。
diff --git a/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfileDepartController.java b/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfileDepartController.java
index 7816790..ca1d0c7 100644
--- a/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfileDepartController.java
+++ b/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfileDepartController.java
@@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -19,7 +20,6 @@ import com.biutag.supervision.pojo.model.DepartNegativeModel;
import com.biutag.supervision.pojo.param.DepartNegativeQueryParam;
import com.biutag.supervision.pojo.vo.NegativeProfile;
import com.biutag.supervision.service.*;
-import dm.jdbc.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
@@ -64,8 +64,10 @@ public class ProfileDepartController {
beginTime = param.getCrtTime().get(0);
endTime = param.getCrtTime().get(1);
}
- Page page = profileDepartMapper.queryDepartNegative(Page.of(param.getCurrent(), param.getSize()), beginTime, endTime,
- param.getDepartName(), param.getDepartId(), param.getDepartGroupId());
+ Page pagination = Page.of(param.getCurrent(), param.getSize());
+ pagination.setCountId("com.biutag.supervision.mapper.ProfileDepartMapper.countDepartNegative");
+ Page page = profileDepartMapper.queryDepartNegative(pagination, beginTime, endTime,
+ param.getDepartName(), param.getDepartId(), param.getDepartGroupId(), param.getSortField(), param.getSortOrder());
return Result.success(page);
}
@@ -90,11 +92,8 @@ public class ProfileDepartController {
profileDepart.getDepartInfo().setMainRole(polices.stream().filter(item -> "正职".equals(item.getPosition())).findFirst().map(SupPolice::getName).orElse(null));
profileDepart.getDepartInfo().setDeputyRole(polices.stream().filter(item -> "副职".equals(item.getPosition())).map(SupPolice::getName).toList());
- List list = negativeScoreDepartService.list(new LambdaQueryWrapper()
- .eq(NegativeScoreDepart::getDepartId, departId)
- .between(NegativeScoreDepart::getDiscoveryTime, beginTime, endTime));
-
- List negativeIds = list.stream().map(NegativeScoreDepart::getNegativeId).toList();
+ List negatives = profileDepartMapper.selectDepartProblems(departId, beginTime, endTime);
+ List negativeIds = negatives.stream().map(Negative::getId).toList();
SupDepartPoliceSize policeSize = departPoliceSizeService.getById(departId);
if(Objects.nonNull(policeSize)){
profileDepart.getDepartInfo().setPoliceSize(policeSize.getPoliceSize());
@@ -104,12 +103,15 @@ public class ProfileDepartController {
if (negativeIds.isEmpty()) {
return Result.success(profileDepart);
}
+ List list = negativeScoreDepartService.list(new LambdaQueryWrapper()
+ .eq(NegativeScoreDepart::getDepartId, departId)
+ .in(NegativeScoreDepart::getNegativeId, negativeIds));
int negativePoliceSize = profileDepartMapper.countByNegativeIdsAndPersonTypes(negativeIds, List.of(PersonTypeEnum.police.getValue()));
profileDepart.getDepartInfo().setNegativePoliceSize(negativePoliceSize);
int negativeAuxSize = profileDepartMapper.countByNegativeIdsAndPersonTypes(negativeIds, List.of(PersonTypeEnum.aux.getValue(), PersonTypeEnum.xj.getValue()));
profileDepart.getDepartInfo().setNegativeAuxSize(negativeAuxSize);
- profileDepart.getNegativeInfo().setSize(list.size());
+ profileDepart.getNegativeInfo().setSize(negatives.size());
int jcj110BusinessSize = businessDepartService.list(new LambdaQueryWrapper()
.between(BusinessDepart::getDate, beginTime, endTime)
@@ -129,30 +131,29 @@ public class ProfileDepartController {
.stream().mapToInt(BusinessDepart::getNumber).sum();
profileDepart.getNegativeInfo()
- .setJcj110Size(list.stream().filter(item -> BusinessTypeEnum.JCJ_110.getValue().equals(item.getBusinessTypeCode())).count())
+ .setJcj110Size(negatives.stream().filter(item -> BusinessTypeEnum.JCJ_110.getValue().equals(item.getBusinessTypeCode())).count())
.setJcj110BusinessSize(jcj110BusinessSize)
- .setJcj122Size(list.stream().filter(item -> BusinessTypeEnum.JCJ_122.getValue().equals(item.getBusinessTypeCode())).count())
+ .setJcj122Size(negatives.stream().filter(item -> BusinessTypeEnum.JCJ_122.getValue().equals(item.getBusinessTypeCode())).count())
.setJcj122BusinessSize(jcj122BusinessSize)
.setZfbaBusinessSize(zfbaBusinessSize)
- .setZfbaSize(list.stream().filter(item -> BusinessTypeEnum.ZFBA.getValue().equals(item.getBusinessTypeCode())).count());
- List negatives = negativeService.listByIds(negativeIds);
+ .setZfbaSize(negatives.stream().filter(item -> BusinessTypeEnum.ZFBA.getValue().equals(item.getBusinessTypeCode())).count());
// 问题来源占比
- Map> problemSourcesGroup = negatives.stream().collect(Collectors.groupingBy(Negative::getProblemSourcesCode));
+ Map> problemSourcesGroup = negatives.stream().collect(Collectors.groupingBy(item -> StrUtil.blankToDefault(item.getProblemSourcesCode(), "未分类")));
List problemSourcesList = problemSourcesGroup.keySet().stream().map(key -> new PieItem(Optional.ofNullable(ProblemSourcesEnum.get(key)).map(ProblemSourcesEnum::getLabel).orElse(key), problemSourcesGroup.get(key).size())).toList();
profileDepart.setProblemSourcesList(problemSourcesList);
// 业务类型占比
- Map> businessTypeGroup = negatives.stream().collect(Collectors.groupingBy(Negative::getBusinessTypeCode));
+ Map> businessTypeGroup = negatives.stream().collect(Collectors.groupingBy(item -> StrUtil.blankToDefault(item.getBusinessTypeCode(), "未分类")));
List businessTypeList = businessTypeGroup.keySet().stream().map(key -> new PieItem(Optional.ofNullable(BusinessTypeEnum.get(key)).map(BusinessTypeEnum::getLabel).orElse(key),
businessTypeGroup.get(key).size())).toList();
profileDepart.setBusinessTypeList(businessTypeList);
// 问题涉及方面
List negativeProblemRelations = negativeProblemRelationService.list(new LambdaQueryWrapper().in(NegativeProblemRelation::getNegativeId, negativeIds));
- Map> problemGroup = negativeProblemRelations.stream().collect(Collectors.groupingBy(NegativeProblemRelation::getOneLevelContent));
+ Map> problemGroup = negativeProblemRelations.stream().collect(Collectors.groupingBy(item -> StrUtil.blankToDefault(item.getOneLevelContent(), "未分类")));
List problemTypeList = problemGroup.keySet().stream().map(key -> new PieItem(key, problemGroup.get(key).size())).sorted(Comparator.comparing(PieItem::getValue).reversed()).toList();
profileDepart.setProblemTypeList(problemTypeList);
// 个人问题排名
List blames = blameService.list(new LambdaQueryWrapper().in(NegativeBlame::getNegativeId, negativeIds).eq(NegativeBlame::getType, BlameType.personal.name()));
- blames= blames.stream().filter(s-> StringUtil.isNotEmpty(s.getBlameEmpNo())).toList();
+ blames= blames.stream().filter(s-> StrUtil.isNotBlank(s.getBlameEmpNo())).toList();
if(CollectionUtil.isNotEmpty(blames)){
Map> policeGroup = blames.stream().collect(Collectors.groupingBy(NegativeBlame::getBlameEmpNo));
List policeBarList = policeGroup.keySet().stream().map(key -> {
@@ -162,7 +163,7 @@ public class ProfileDepartController {
}).sorted(Comparator.comparing(BarItem::getValue).reversed()).toList();
profileDepart.setPoliceBarList(policeBarList);
// 问题涉及领导
- Map> policeLeadGroup = blames.stream().collect(Collectors.groupingBy(NegativeBlame::getLeadEmpNo));
+ Map> policeLeadGroup = blames.stream().filter(item -> StrUtil.isNotBlank(item.getLeadEmpNo())).collect(Collectors.groupingBy(NegativeBlame::getLeadEmpNo));
List policeLeadBarList = policeLeadGroup.keySet().stream().map(key -> {
List list1 = policeLeadGroup.get(key);
String name = list1.get(0).getLeadName();
@@ -219,8 +220,7 @@ public class ProfileDepartController {
months.add(month);
long value = negativeService.count(new LambdaQueryWrapper()
.eq(Negative::getInvolveDepartId, departId)
- .in(Negative::getCheckStatus, List.of(InspectCaseEnum.TRUE.getValue(), InspectCaseEnum.PARTIALLY_TRUE.getValue()))
- .apply(" DATE_FORMAT(DiscoveryTime, '%Y年%m月') = '" + month + "'"));
+ .apply(" DATE_FORMAT(crtTime, '%Y年%m月') = '" + month + "'"));
values.add(value);
}
JSONObject jsonObject = new JSONObject().fluentPut("months", months).fluentPut("values", values);
diff --git a/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfilePoliceController.java b/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfilePoliceController.java
index 06e3651..355ccd6 100644
--- a/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfilePoliceController.java
+++ b/src/main/java/com/biutag/supervision/controller/sensitiveperception/ProfilePoliceController.java
@@ -20,6 +20,7 @@ import com.biutag.supervision.pojo.dto.common.PieItem;
import com.biutag.supervision.pojo.entity.*;
import com.biutag.supervision.pojo.model.PoliceNegativeModel;
import com.biutag.supervision.pojo.param.DepartPoliceQueryParam;
+import com.biutag.supervision.pojo.param.PoliceProfileQuery;
import com.biutag.supervision.pojo.vo.NegativeProfile;
import com.biutag.supervision.service.*;
import lombok.RequiredArgsConstructor;
@@ -66,13 +67,15 @@ public class ProfilePoliceController {
beginTime = param.getCrtTime().get(0);
endTime = param.getCrtTime().get(1);
}
- Page page = profilePoliceMapper.queryPoliceNegative(Page.of(param.getCurrent(), param.getSize()), beginTime, endTime,
- param.getName(),param.getEmpNo(), param.getDepartId(), param.getDepartGroupId());
+ Page pagination = Page.of(param.getCurrent(), param.getSize());
+ pagination.setCountId("com.biutag.supervision.mapper.ProfilePoliceMapper.countPoliceNegative");
+ Page page = profilePoliceMapper.queryPoliceNegative(pagination, beginTime, endTime,
+ param.getName(),param.getEmpNo(), param.getDepartId(), param.getDepartGroupId(), param.getSortOrder());
return Result.success(page);
}
@GetMapping("{idCode}")
- public Result profile(@PathVariable String idCode, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date beginTime, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime) {
+ public Result profile(@PathVariable String idCode, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date beginTime, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, PoliceProfileQuery scope) {
if (Objects.isNull(beginTime)) {
beginTime = DateUtil.parse("1949", "yyyy");
}
@@ -83,8 +86,11 @@ public class ProfilePoliceController {
profilePolice.setDays(DateUtil.between(beginTime, endTime, DateUnit.DAY));
profilePolice.setPoliceInfo(policeService.getByIdCode(idCode));
- List negativeScorePolices = negativeScorePoliceService.list(new LambdaQueryWrapper()
- .between(NegativeScorePolice::getDiscoveryTime, beginTime, endTime).eq(NegativeScorePolice::getIdCode, idCode));
+ List negatives = profilePoliceMapper.selectPoliceProblems(idCode, beginTime, endTime, scope);
+ Set negativeIds = negatives.stream().map(Negative::getId).collect(Collectors.toSet());
+ List negativeScorePolices = negativeIds.isEmpty() ? Collections.emptyList()
+ : negativeScorePoliceService.list(new LambdaQueryWrapper()
+ .in(NegativeScorePolice::getNegativeId, negativeIds).eq(NegativeScorePolice::getIdCode, idCode));
int jcj110BusinessSize = businessPoliceService.list(new LambdaQueryWrapper()
.between(BusinessPolice::getDate, beginTime, endTime)
@@ -111,20 +117,18 @@ public class ProfilePoliceController {
profilePolice.getNegativeInfo()
.setScore(NumberUtil.round(negativeScorePolices.stream().mapToDouble(NegativeScorePolice::getScore).sum(), 2).doubleValue())
.setJcj110BusinessSize(jcj110BusinessSize)
- .setSize(negativeScorePolices.size())
- .setJcj110Size(negativeScorePolices.stream().filter(item -> BusinessTypeEnum.JCJ_110.getValue().equals(item.getBusinessTypeCode())).count())
+ .setSize(negatives.size())
+ .setJcj110Size(negatives.stream().filter(item -> BusinessTypeEnum.JCJ_110.getValue().equals(item.getBusinessTypeCode())).count())
.setJcj122BusinessSize(jcj122BusinessSize)
- .setJcj122Size(negativeScorePolices.stream().filter(item -> BusinessTypeEnum.JCJ_122.getValue().equals(item.getBusinessTypeCode())).count())
+ .setJcj122Size(negatives.stream().filter(item -> BusinessTypeEnum.JCJ_122.getValue().equals(item.getBusinessTypeCode())).count())
.setZfbaBusinessSize(zfbaBusinessSize)
- .setZfbaSize(negativeScorePolices.stream().filter(item -> BusinessTypeEnum.ZFBA.getValue().equals(item.getBusinessTypeCode())).count());
+ .setZfbaSize(negatives.stream().filter(item -> BusinessTypeEnum.ZFBA.getValue().equals(item.getBusinessTypeCode())).count());
- Set negativeIds = negativeScorePolices.stream().map(NegativeScorePolice::getNegativeId).collect(Collectors.toSet());
if (negativeIds.isEmpty()) {
return Result.success(profilePolice);
}
- List negatives = negativeService.listByIds(negativeIds);
// 问题来源占比
- Map> problemSourcesGroup = negatives.stream().collect(Collectors.groupingBy(Negative::getProblemSourcesCode));
+ Map> problemSourcesGroup = negatives.stream().collect(Collectors.groupingBy(item -> StrUtil.blankToDefault(item.getProblemSourcesCode(), "未分类")));
List problemSourcesList = problemSourcesGroup.keySet().stream()
.map(key -> new PieItem(Optional.ofNullable(ProblemSourcesEnum.get(key)).map(ProblemSourcesEnum::getLabel).orElse(key),
problemSourcesGroup.get(key).size())).toList();
@@ -132,7 +136,7 @@ public class ProfilePoliceController {
// 问题类型占比
List problemRelations = negativeProblemRelationService.list(new LambdaQueryWrapper()
.in(NegativeProblemRelation::getNegativeId, negativeIds));
- Map> groups = problemRelations.stream().collect(Collectors.groupingBy(NegativeProblemRelation::getOneLevelContent));
+ Map> groups = problemRelations.stream().collect(Collectors.groupingBy(item -> StrUtil.blankToDefault(item.getOneLevelContent(), "未分类")));
List problemTypeList = groups.keySet().stream().map(key -> new PieItem(key, groups.get(key).size())).toList();
profilePolice.setProblemTypeList(problemTypeList);
@@ -180,19 +184,18 @@ public class ProfilePoliceController {
}
@GetMapping("{idCode}/month")
- public Result listByMonth(@PathVariable String idCode) {
+ public Result listByMonth(@PathVariable String idCode, PoliceProfileQuery scope) {
LocalDate now = LocalDate.now();
List months = new ArrayList<>();
List values = new ArrayList<>();
- Set negativeIds = negativeBlameService.list(new LambdaQueryWrapper().eq(NegativeBlame::getBlameIdCode, idCode)).stream().map(NegativeBlame::getNegativeId).collect(Collectors.toSet());
+ List negatives = profilePoliceMapper.selectPoliceProblems(idCode,
+ DateUtil.beginOfMonth(DateUtil.offsetMonth(new Date(), -11)), DateUtil.endOfDay(new Date()), scope);
for (int i = 11; i >= 0; i--) {
String month = now.minusMonths(i).format(DateTimeFormatter.ofPattern("yyyy年MM月"));
months.add(month);
- long value = negativeIds.isEmpty() ? 0 : negativeService.count(new LambdaQueryWrapper()
- .in(Negative::getId, negativeIds)
- .in(Negative::getCheckStatus, List.of(InspectCaseEnum.TRUE.getValue(), InspectCaseEnum.PARTIALLY_TRUE.getValue()))
- .apply(" DATE_FORMAT(DiscoveryTime, '%Y年%m月') = '" + month + "'"));
+ long value = negatives.stream().filter(item -> month.equals(
+ item.getCrtTime().format(DateTimeFormatter.ofPattern("yyyy年MM月")))).count();
values.add(value);
}
JSONObject jsonObject = new JSONObject().fluentPut("months", months).fluentPut("values", values);
diff --git a/src/main/java/com/biutag/supervision/mapper/ProfileDepartMapper.java b/src/main/java/com/biutag/supervision/mapper/ProfileDepartMapper.java
index 367d4c3..450c44b 100644
--- a/src/main/java/com/biutag/supervision/mapper/ProfileDepartMapper.java
+++ b/src/main/java/com/biutag/supervision/mapper/ProfileDepartMapper.java
@@ -3,6 +3,7 @@ package com.biutag.supervision.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.biutag.supervision.pojo.dto.common.BarItem;
import com.biutag.supervision.pojo.model.DepartNegativeModel;
+import com.biutag.supervision.pojo.entity.Negative;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
@@ -14,7 +15,9 @@ import java.util.List;
*/
public interface ProfileDepartMapper {
- Page queryDepartNegative(Page page, Date beginTime, Date endTime, String departName, String departId, String departGroupId);
+ List selectDepartProblems(String departId, Date beginTime, Date endTime);
+
+ Page queryDepartNegative(Page page, Date beginTime, Date endTime, String departName, String departId, String departGroupId, String sortField, String sortOrder);
List selectPoliceNegativeCount(String departId, Date beginTime, Date endTime);
diff --git a/src/main/java/com/biutag/supervision/mapper/ProfilePoliceMapper.java b/src/main/java/com/biutag/supervision/mapper/ProfilePoliceMapper.java
index fb8b32b..7b0baa9 100644
--- a/src/main/java/com/biutag/supervision/mapper/ProfilePoliceMapper.java
+++ b/src/main/java/com/biutag/supervision/mapper/ProfilePoliceMapper.java
@@ -2,7 +2,8 @@ package com.biutag.supervision.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.biutag.supervision.pojo.dto.common.BarItem;
-import com.biutag.supervision.pojo.model.DepartNegativeModel;
+import com.biutag.supervision.pojo.entity.Negative;
+import com.biutag.supervision.pojo.param.PoliceProfileQuery;
import com.biutag.supervision.pojo.model.PoliceNegativeModel;
import java.util.Date;
@@ -14,7 +15,10 @@ import java.util.List;
*/
public interface ProfilePoliceMapper {
- Page queryPoliceNegative(Page page, Date beginTime, Date endTime, String name, String empNo, String departId, String departGroupId);
+ List selectPoliceProblems(String idCode, Date beginTime, Date endTime,
+ PoliceProfileQuery scope);
+
+ Page queryPoliceNegative(Page page, Date beginTime, Date endTime, String name, String empNo, String departId, String departGroupId, String sortOrder);
List selectProblemType(String idCode, Date beginTime, Date endTime);
diff --git a/src/main/java/com/biutag/supervision/pojo/dto/common/BarItem.java b/src/main/java/com/biutag/supervision/pojo/dto/common/BarItem.java
index bcc18ee..aa574fa 100644
--- a/src/main/java/com/biutag/supervision/pojo/dto/common/BarItem.java
+++ b/src/main/java/com/biutag/supervision/pojo/dto/common/BarItem.java
@@ -20,6 +20,13 @@ public class BarItem {
private String label;
private BigDecimal value;
private String detailId;
+ private String empNo;
+
+ public BarItem(String label, BigDecimal value, String detailId) {
+ this.label = label;
+ this.value = value;
+ this.detailId = detailId;
+ }
public BarItem(String label, BigDecimal value) {
this.label = label;
diff --git a/src/main/java/com/biutag/supervision/pojo/model/DepartNegativeModel.java b/src/main/java/com/biutag/supervision/pojo/model/DepartNegativeModel.java
index 12ec20c..45b7177 100644
--- a/src/main/java/com/biutag/supervision/pojo/model/DepartNegativeModel.java
+++ b/src/main/java/com/biutag/supervision/pojo/model/DepartNegativeModel.java
@@ -3,7 +3,6 @@ package com.biutag.supervision.pojo.model;
import lombok.Getter;
import lombok.Setter;
-import java.math.BigDecimal;
/**
* @author wxc
@@ -28,5 +27,4 @@ public class DepartNegativeModel {
// 查实问题数
private Integer verifySize;
- private BigDecimal score;
}
diff --git a/src/main/java/com/biutag/supervision/pojo/model/PoliceNegativeModel.java b/src/main/java/com/biutag/supervision/pojo/model/PoliceNegativeModel.java
index 0983b69..4d7b7e5 100644
--- a/src/main/java/com/biutag/supervision/pojo/model/PoliceNegativeModel.java
+++ b/src/main/java/com/biutag/supervision/pojo/model/PoliceNegativeModel.java
@@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
-import java.math.BigDecimal;
import java.time.LocalDate;
/**
@@ -32,5 +31,4 @@ public class PoliceNegativeModel {
private String departId;
private String parentDepartName;
- private BigDecimal score;
}
diff --git a/src/main/java/com/biutag/supervision/pojo/param/DepartNegativeQueryParam.java b/src/main/java/com/biutag/supervision/pojo/param/DepartNegativeQueryParam.java
index 94d438f..6540de5 100644
--- a/src/main/java/com/biutag/supervision/pojo/param/DepartNegativeQueryParam.java
+++ b/src/main/java/com/biutag/supervision/pojo/param/DepartNegativeQueryParam.java
@@ -22,4 +22,6 @@ public class DepartNegativeQueryParam extends BasePage {
private String departId;
private String departGroupId;
+ private String sortField;
+ private String sortOrder;
}
diff --git a/src/main/java/com/biutag/supervision/pojo/param/DepartPoliceQueryParam.java b/src/main/java/com/biutag/supervision/pojo/param/DepartPoliceQueryParam.java
index cb104fa..f38b172 100644
--- a/src/main/java/com/biutag/supervision/pojo/param/DepartPoliceQueryParam.java
+++ b/src/main/java/com/biutag/supervision/pojo/param/DepartPoliceQueryParam.java
@@ -22,5 +22,6 @@ public class DepartPoliceQueryParam extends BasePage {
private String empNo;
private String departId;
private String departGroupId;
+ private String sortOrder;
}
diff --git a/src/main/java/com/biutag/supervision/pojo/param/PoliceProfileQuery.java b/src/main/java/com/biutag/supervision/pojo/param/PoliceProfileQuery.java
new file mode 100644
index 0000000..c7be893
--- /dev/null
+++ b/src/main/java/com/biutag/supervision/pojo/param/PoliceProfileQuery.java
@@ -0,0 +1,13 @@
+package com.biutag.supervision.pojo.param;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class PoliceProfileQuery {
+ private String groupId;
+ private String category;
+ private String rankName;
+ private String rankEmpNo;
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index c528328..1c6b50f 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -80,6 +80,7 @@ spring:
host: localhost
# 端口,默认为6379
port: 6379
+ password: 123456
# 数据库索引
database: 1
# 连接超时时间
diff --git a/src/main/resources/mapper/ProfileDepartMapper.xml b/src/main/resources/mapper/ProfileDepartMapper.xml
index 1fedd0e..06d1e47 100644
--- a/src/main/resources/mapper/ProfileDepartMapper.xml
+++ b/src/main/resources/mapper/ProfileDepartMapper.xml
@@ -4,48 +4,75 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+ d.level = 3
+
+ AND d.statistics_group_id = #{departGroupId}
+
+
+ AND d.short_name like concat('%', #{departName}, '%')
+
+
+ AND (d.id = #{departId} OR d.pid = #{departId})
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/main/resources/mapper/ProfilePoliceMapper.xml b/src/main/resources/mapper/ProfilePoliceMapper.xml
index fedf6e8..0b3a347 100644
--- a/src/main/resources/mapper/ProfilePoliceMapper.xml
+++ b/src/main/resources/mapper/ProfilePoliceMapper.xml
@@ -4,53 +4,97 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-