diff --git a/docs/20260908_case_risk_warning.sql b/docs/20260908_case_risk_warning.sql new file mode 100644 index 0000000..156e4d1 --- /dev/null +++ b/docs/20260908_case_risk_warning.sql @@ -0,0 +1,109 @@ +-- 案件三色预警:案件快照 + 法律文书抓取 + 活动日志 + 预警单 +-- 红色通报一旦触发不可消除 + +-- 接报案来源:人民检察院通知立案;法院/检察院子项允许普通经侦 +ALTER TABLE t_alarm_report DROP CONSTRAINT IF EXISTS t_alarm_report_case_source_check; +ALTER TABLE t_alarm_report ADD CONSTRAINT t_alarm_report_case_source_check + CHECK (case_source IS NULL OR case_source IN ( + 'party_report', + 'admin_transfer', + 'court_transfer', + 'procuratorate_transfer', + 'procuratorate_notify', + 'superior_assign', + 'work_discovery', + 'other_unit_transfer' + )); + +ALTER TABLE t_alarm_report DROP CONSTRAINT IF EXISTS t_alarm_report_case_source_sub_check; +ALTER TABLE t_alarm_report ADD CONSTRAINT t_alarm_report_case_source_sub_check + CHECK (case_source_sub IS NULL OR case_source_sub IN ('false_litigation', 'other', 'normal')); + +INSERT INTO t_dict_data (dict_id, data_value, data_label, remark, sort_order, disabled_flag, create_time, update_time) +SELECT d.dict_id, 'procuratorate_notify', '人民检察院通知立案', '案件来源', 5, false, NOW(), NOW() +FROM t_dict d +WHERE d.dict_code = 'CASE_SOURCE' + AND NOT EXISTS ( + SELECT 1 FROM t_dict_data x + WHERE x.dict_id = d.dict_id AND x.data_value = 'procuratorate_notify' + ); + +UPDATE t_dict_data SET sort_order = 6 WHERE dict_id = (SELECT dict_id FROM t_dict WHERE dict_code = 'CASE_SOURCE') AND data_value = 'superior_assign'; +UPDATE t_dict_data SET sort_order = 7 WHERE dict_id = (SELECT dict_id FROM t_dict WHERE dict_code = 'CASE_SOURCE') AND data_value = 'work_discovery'; +UPDATE t_dict_data SET sort_order = 8 WHERE dict_id = (SELECT dict_id FROM t_dict WHERE dict_code = 'CASE_SOURCE') AND data_value = 'other_unit_transfer'; + +INSERT INTO t_dict_data (dict_id, data_value, data_label, remark, sort_order, disabled_flag, create_time, update_time) +SELECT d.dict_id, 'normal', '普通经侦案件', '案件来源子项', 0, false, NOW(), NOW() +FROM t_dict d +WHERE d.dict_code = 'CASE_SOURCE_SUB' + AND NOT EXISTS ( + SELECT 1 FROM t_dict_data x + WHERE x.dict_id = d.dict_id AND x.data_value = 'normal' + ); + +CREATE TABLE IF NOT EXISTS t_case_file ( + case_id BIGSERIAL PRIMARY KEY, + case_no VARCHAR(64) NOT NULL, + case_name VARCHAR(200) NOT NULL, + alarm_id BIGINT, + case_source VARCHAR(64), + case_source_sub VARCHAR(64), + handler_name VARCHAR(64), + review_decide_time TIMESTAMP, + accept_time TIMESTAMP, + filing_time TIMESTAMP, + detention_time TIMESTAMP, + arrest_time TIMESTAMP, + residential_time TIMESTAMP, + designated_time TIMESTAMP, + create_time TIMESTAMP DEFAULT NOW(), + update_time TIMESTAMP DEFAULT NOW(), + deleted_flag BOOLEAN DEFAULT FALSE +); +CREATE UNIQUE INDEX IF NOT EXISTS uk_t_case_file_no ON t_case_file(case_no) WHERE deleted_flag = FALSE; + +CREATE TABLE IF NOT EXISTS t_case_legal_doc ( + doc_id BIGSERIAL PRIMARY KEY, + case_id BIGINT NOT NULL, + doc_type VARCHAR(64) NOT NULL, + doc_name VARCHAR(200) NOT NULL, + issue_time TIMESTAMP NOT NULL, + approved_flag BOOLEAN DEFAULT TRUE, + interrogated BOOLEAN DEFAULT FALSE, + seq_no INTEGER DEFAULT 1, + create_time TIMESTAMP DEFAULT NOW() +); +CREATE INDEX IF NOT EXISTS idx_t_case_legal_doc_case ON t_case_legal_doc(case_id, doc_type); + +CREATE TABLE IF NOT EXISTS t_case_activity_log ( + log_id BIGSERIAL PRIMARY KEY, + case_id BIGINT NOT NULL, + activity_time TIMESTAMP NOT NULL, + activity_title VARCHAR(200) NOT NULL, + operator_name VARCHAR(64), + create_time TIMESTAMP DEFAULT NOW() +); +CREATE INDEX IF NOT EXISTS idx_t_case_activity_case ON t_case_activity_log(case_id, activity_time); + +CREATE TABLE IF NOT EXISTS t_case_risk_warning ( + warning_id BIGSERIAL PRIMARY KEY, + warning_no VARCHAR(64) NOT NULL, + case_id BIGINT NOT NULL, + rule_code VARCHAR(64) NOT NULL, + track_key VARCHAR(64) NOT NULL, + color VARCHAR(16) NOT NULL, + reason TEXT NOT NULL, + elapsed_days INTEGER, + sticky_red BOOLEAN DEFAULT FALSE, + status VARCHAR(32) NOT NULL DEFAULT 'open', + process_measure TEXT, + process_remark TEXT, + process_user VARCHAR(64), + process_time TIMESTAMP, + trigger_time TIMESTAMP NOT NULL DEFAULT NOW(), + update_time TIMESTAMP DEFAULT NOW() +); +CREATE UNIQUE INDEX IF NOT EXISTS uk_t_case_risk_warning_no ON t_case_risk_warning(warning_no); +CREATE INDEX IF NOT EXISTS idx_t_case_risk_warning_case ON t_case_risk_warning(case_id, rule_code, track_key); + +COMMENT ON TABLE t_case_risk_warning IS '案件三色预警:红=问题通报 黄=问题预警 蓝=普通提醒;红色 sticky_red 后不可消除'; diff --git a/docs/20260908_case_risk_warning_seed.sql b/docs/20260908_case_risk_warning_seed.sql new file mode 100644 index 0000000..0a924bd --- /dev/null +++ b/docs/20260908_case_risk_warning_seed.sql @@ -0,0 +1,99 @@ +-- 案件三色预警演示数据(相对当前时间构造超期场景) + +INSERT INTO t_case_file ( + case_no, case_name, case_source, case_source_sub, handler_name, + review_decide_time, accept_time, filing_time, + detention_time, arrest_time, residential_time, designated_time +) +SELECT v.case_no, v.case_name, v.case_source, v.case_source_sub, v.handler_name, + v.review_decide_time, v.accept_time, v.filing_time, + v.detention_time, v.arrest_time, v.residential_time, v.designated_time +FROM (VALUES + ('AJFX20260908001', '审议受案超24小时未受案', 'party_report', NULL, '张警官', + NOW() - INTERVAL '36 hour', NULL, NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908002', '普通经侦立案审查第6日', 'party_report', NULL, '李警官', + NOW() - INTERVAL '10 day', NOW() - INTERVAL '6 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908003', '行政机关移送立案审查超期', 'admin_transfer', NULL, '王警官', + NOW() - INTERVAL '20 day', NOW() - INTERVAL '12 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908004', '法院移送普通经侦审查', 'court_transfer', 'normal', '赵警官', + NOW() - INTERVAL '15 day', NOW() - INTERVAL '9 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908005', '法院移送虚假诉讼审查', 'court_transfer', 'false_litigation', '孙警官', + NOW() - INTERVAL '40 day', NOW() - INTERVAL '26 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908006', '检察院通知立案超期', 'procuratorate_notify', NULL, '钱警官', + NOW() - INTERVAL '20 day', NOW() - INTERVAL '16 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908007', '普通经侦一延后审查', 'party_report', NULL, '周警官', + NOW() - INTERVAL '40 day', NOW() - INTERVAL '26 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908008', '中止立案审查期限中', 'work_discovery', NULL, '吴警官', + NOW() - INTERVAL '30 day', NOW() - INTERVAL '28 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908009', '取保候审传讯超期', 'party_report', NULL, '郑警官', + NOW() - INTERVAL '80 day', NOW() - INTERVAL '70 day', NOW() - INTERVAL '65 day', NULL, NULL, NULL, NULL), + ('AJFX20260908010', '受案后长期无活动', 'superior_assign', NULL, '冯警官', + NOW() - INTERVAL '70 day', NOW() - INTERVAL '55 day', NULL, NULL, NULL, NULL, NULL), + ('AJFX20260908011', '立案后长期无活动', 'party_report', NULL, '陈警官', + NOW() - INTERVAL '100 day', NOW() - INTERVAL '90 day', NOW() - INTERVAL '70 day', NULL, NULL, NULL, NULL), + ('AJFX20260908012', '刑拘24小时未制作拘留通知书', 'party_report', NULL, '卫警官', + NOW() - INTERVAL '10 day', NOW() - INTERVAL '8 day', NOW() - INTERVAL '7 day', + NOW() - INTERVAL '30 hour', NULL, NULL, NULL), + ('AJFX20260908013', '逮捕后羁押期限超两个月', 'party_report', NULL, '蒋警官', + NOW() - INTERVAL '90 day', NOW() - INTERVAL '85 day', NOW() - INTERVAL '80 day', + NOW() - INTERVAL '75 day', NOW() - INTERVAL '65 day', NULL, NULL), + ('AJFX20260908014', '监视居住将满6个月', 'admin_transfer', NULL, '沈警官', + NOW() - INTERVAL '200 day', NOW() - INTERVAL '190 day', NOW() - INTERVAL '185 day', + NULL, NULL, NOW() - INTERVAL '185 day', NULL), + ('AJFX20260908015', '指定居所监视居住未通知', 'party_report', NULL, '韩警官', + NOW() - INTERVAL '5 day', NOW() - INTERVAL '4 day', NOW() - INTERVAL '3 day', + NULL, NULL, NULL, NOW() - INTERVAL '30 hour') +) AS v(case_no, case_name, case_source, case_source_sub, handler_name, + review_decide_time, accept_time, filing_time, + detention_time, arrest_time, residential_time, designated_time) +WHERE NOT EXISTS (SELECT 1 FROM t_case_file c WHERE c.case_no = v.case_no AND c.deleted_flag = FALSE); + +-- 一延呈请审批结束 +INSERT INTO t_case_legal_doc (case_id, doc_type, doc_name, issue_time, approved_flag, seq_no) +SELECT c.case_id, 'extend_filing_deadline', '呈请延长立案期限报告书', NOW() - INTERVAL '20 day', TRUE, 1 +FROM t_case_file c +WHERE c.case_no = 'AJFX20260908007' + AND NOT EXISTS (SELECT 1 FROM t_case_legal_doc d WHERE d.case_id = c.case_id AND d.doc_type = 'extend_filing_deadline'); + +-- 中止立案审查(第22日,应出蓝色) +INSERT INTO t_case_legal_doc (case_id, doc_type, doc_name, issue_time, approved_flag, seq_no) +SELECT c.case_id, 'suspend_filing', '中止立案审查期限通知书', NOW() - INTERVAL '22 day', TRUE, 1 +FROM t_case_file c +WHERE c.case_no = 'AJFX20260908008' + AND NOT EXISTS (SELECT 1 FROM t_case_legal_doc d WHERE d.case_id = c.case_id AND d.doc_type = 'suspend_filing'); + +-- 取保候审决定书(约70日前),期间无传讯 +INSERT INTO t_case_legal_doc (case_id, doc_type, doc_name, issue_time, approved_flag, interrogated, seq_no) +SELECT c.case_id, 'bail_decision', '取保候审决定书', NOW() - INTERVAL '70 day', TRUE, FALSE, 1 +FROM t_case_file c +WHERE c.case_no = 'AJFX20260908009' + AND NOT EXISTS (SELECT 1 FROM t_case_legal_doc d WHERE d.case_id = c.case_id AND d.doc_type = 'bail_decision'); + +-- 监视居住决定书 +INSERT INTO t_case_legal_doc (case_id, doc_type, doc_name, issue_time, approved_flag, seq_no) +SELECT c.case_id, 'residential_decision', '监视居住决定书', NOW() - INTERVAL '185 day', TRUE, 1 +FROM t_case_file c +WHERE c.case_no = 'AJFX20260908014' + AND NOT EXISTS (SELECT 1 FROM t_case_legal_doc d WHERE d.case_id = c.case_id AND d.doc_type = 'residential_decision'); + +-- 指定居所决定书(无通知书) +INSERT INTO t_case_legal_doc (case_id, doc_type, doc_name, issue_time, approved_flag, seq_no) +SELECT c.case_id, 'designated_residence', '指定居所监视居住决定书', NOW() - INTERVAL '30 hour', TRUE, 1 +FROM t_case_file c +WHERE c.case_no = 'AJFX20260908015' + AND NOT EXISTS (SELECT 1 FROM t_case_legal_doc d WHERE d.case_id = c.case_id AND d.doc_type = 'designated_residence'); + +-- 活动日志:有立案但长期无后续的案件仅保留立案当时日志 +INSERT INTO t_case_activity_log (case_id, activity_time, activity_title, operator_name) +SELECT c.case_id, c.filing_time, '立案决定', c.handler_name +FROM t_case_file c +WHERE c.case_no = 'AJFX20260908011' + AND c.filing_time IS NOT NULL + AND NOT EXISTS (SELECT 1 FROM t_case_activity_log l WHERE l.case_id = c.case_id); + +INSERT INTO t_case_activity_log (case_id, activity_time, activity_title, operator_name) +SELECT c.case_id, c.accept_time, '受案登记', c.handler_name +FROM t_case_file c +WHERE c.case_no IN ('AJFX20260908002','AJFX20260908003','AJFX20260908004','AJFX20260908005','AJFX20260908006','AJFX20260908007','AJFX20260908008') + AND c.accept_time IS NOT NULL + AND NOT EXISTS (SELECT 1 FROM t_case_activity_log l WHERE l.case_id = c.case_id); diff --git a/docs/20260909_clear_risk_warning_submenu_icons.sql b/docs/20260909_clear_risk_warning_submenu_icons.sql new file mode 100644 index 0000000..bd1914e --- /dev/null +++ b/docs/20260909_clear_risk_warning_submenu_icons.sql @@ -0,0 +1,7 @@ +-- 风险预警 13 条规则子菜单去掉图标 +UPDATE t_menu +SET icon = NULL, + update_time = NOW() +WHERE deleted_flag = 0 + AND menu_type = 2 + AND path LIKE '/case-management/risk-warning/%'; diff --git a/docs/20260909_fix_risk_warning_menu_component.sql b/docs/20260909_fix_risk_warning_menu_component.sql new file mode 100644 index 0000000..cb8a0e9 --- /dev/null +++ b/docs/20260909_fix_risk_warning_menu_component.sql @@ -0,0 +1,7 @@ +-- 风险预警菜单组件路径写错,页面无法加载(空白) +UPDATE t_menu +SET component = '/business/case-management/risk-warning.vue', + update_time = NOW() +WHERE path = '/case-management/risk-warning' + AND deleted_flag = 0 + AND (component IS NULL OR component <> '/business/case-management/risk-warning.vue'); diff --git a/docs/20260909_risk_warning_rule_submenus.sql b/docs/20260909_risk_warning_rule_submenus.sql new file mode 100644 index 0000000..24eee20 --- /dev/null +++ b/docs/20260909_risk_warning_rule_submenus.sql @@ -0,0 +1,63 @@ +-- 风险预警保持二级(仍挂在案件管理下),改为目录后挂 13 条规则三级子菜单 +-- 不改变 parent_id / sort,只把自身从页面改为目录 + +UPDATE t_menu +SET menu_type = 1, + component = NULL, + path = '/case-management/risk-warning', + update_time = NOW() +WHERE menu_name = '风险预警' + AND path = '/case-management/risk-warning' + AND deleted_flag = 0; + +INSERT INTO t_menu (menu_name, menu_type, parent_id, sort, path, component, + frame_flag, cache_flag, visible_flag, disabled_flag, + perms_type, icon, deleted_flag, create_user_id, create_time, update_time) +SELECT v.menu_name, 2, p.menu_id, v.sort_num, v.path, '/business/case-management/risk-warning.vue', + false, false, true, false, 1, NULL, false, 1, NOW(), NOW() +FROM t_menu p +CROSS JOIN (VALUES + ('审议受案超时', 1, '/case-management/risk-warning/accept-timeout', 'accept_timeout'), + ('立案审查期限', 2, '/case-management/risk-warning/filing-deadline', 'filing_deadline'), + ('取保候审传讯', 3, '/case-management/risk-warning/bail-summons', 'bail_summons'), + ('取保候审期限', 4, '/case-management/risk-warning/bail-expire', 'bail_expire'), + ('受案后无活动', 5, '/case-management/risk-warning/accept-inactivity', 'accept_inactivity'), + ('立案后无活动', 6, '/case-management/risk-warning/filing-inactivity', 'filing_inactivity'), + ('刑拘通知书', 7, '/case-management/risk-warning/detention-notice', 'detention_notice'), + ('刑拘羁押期限', 8, '/case-management/risk-warning/detention-deadline', 'detention_deadline'), + ('逮捕通知书', 9, '/case-management/risk-warning/arrest-notice', 'arrest_notice'), + ('逮捕羁押期限', 10, '/case-management/risk-warning/arrest-deadline', 'arrest_deadline'), + ('监视居住期限', 11, '/case-management/risk-warning/residential-expire', 'residential_expire'), + ('监视居住传讯', 12, '/case-management/risk-warning/residential-summons', 'residential_summons'), + ('指定居所通知', 13, '/case-management/risk-warning/designated-notice', 'designated_notice') +) AS v(menu_name, sort_num, path, rule_code) +WHERE p.menu_name = '风险预警' + AND p.path = '/case-management/risk-warning' + AND p.deleted_flag = 0 + AND NOT EXISTS (SELECT 1 FROM t_menu x WHERE x.path = v.path AND x.deleted_flag = 0); + +-- 原功能点仍挂在「风险预警」目录下 +UPDATE t_menu f +SET parent_id = p.menu_id, + context_menu_id = p.menu_id, + update_time = NOW() +FROM t_menu p +WHERE p.menu_name = '风险预警' + AND p.path = '/case-management/risk-warning' + AND p.deleted_flag = 0 + AND f.deleted_flag = 0 + AND f.menu_type = 3 + AND f.web_perms IN ('risk-warning:query', 'risk-warning:view', 'risk-warning:process', 'risk-warning:ignore'); + +-- 有「风险预警」权限的角色同步绑定全部规则子菜单 +INSERT INTO t_role_menu (role_id, menu_id) +SELECT rm.role_id, c.menu_id +FROM t_role_menu rm +JOIN t_menu p ON p.menu_id = rm.menu_id +JOIN t_menu c ON c.parent_id = p.menu_id AND c.deleted_flag = 0 AND c.menu_type = 2 +WHERE p.menu_name = '风险预警' + AND p.path = '/case-management/risk-warning' + AND p.deleted_flag = 0 + AND NOT EXISTS ( + SELECT 1 FROM t_role_menu x WHERE x.role_id = rm.role_id AND x.menu_id = c.menu_id + ); diff --git a/docs/20260928_case_supervision.sql b/docs/20260928_case_supervision.sql new file mode 100644 index 0000000..ca73396 --- /dev/null +++ b/docs/20260928_case_supervision.sql @@ -0,0 +1,150 @@ +-- 案件监督:负面清单巡查 + 周调度 +-- 1) t_case_file 补业务分类/创建单位/办案单位/案件状态 +-- 2) 周调度主表 + 案件快照 + 参会人员 +-- 3) 案件监督改为目录并挂两个子菜单及功能权限 + +-- ========== 案件快照补字段 ========== +ALTER TABLE t_case_file ADD COLUMN IF NOT EXISTS biz_category VARCHAR(32) DEFAULT '经侦'; +ALTER TABLE t_case_file ADD COLUMN IF NOT EXISTS create_dept VARCHAR(128); +ALTER TABLE t_case_file ADD COLUMN IF NOT EXISTS handle_dept VARCHAR(128); +ALTER TABLE t_case_file ADD COLUMN IF NOT EXISTS case_status VARCHAR(32) DEFAULT 'investigating'; + +COMMENT ON COLUMN t_case_file.biz_category IS '业务系统分类:经侦/刑侦等'; +COMMENT ON COLUMN t_case_file.create_dept IS '创建单位'; +COMMENT ON COLUMN t_case_file.handle_dept IS '办案单位'; +COMMENT ON COLUMN t_case_file.case_status IS '案件状态:pending_filing/investigating/closed/withdrawn'; + +UPDATE t_case_file +SET biz_category = COALESCE(NULLIF(biz_category, ''), '经侦'), + case_status = COALESCE(NULLIF(case_status, ''), 'investigating') +WHERE deleted_flag = FALSE; + +-- ========== 周调度 ========== +CREATE TABLE IF NOT EXISTS t_case_weekly_schedule ( + schedule_id BIGSERIAL PRIMARY KEY, + schedule_no VARCHAR(64) NOT NULL, + schedule_content TEXT, + status VARCHAR(32) NOT NULL DEFAULT 'draft', + create_user_id BIGINT, + create_user_name VARCHAR(64), + push_time TIMESTAMP, + lock_time TIMESTAMP, + create_time TIMESTAMP DEFAULT NOW(), + update_time TIMESTAMP DEFAULT NOW(), + deleted_flag BOOLEAN DEFAULT FALSE +); +CREATE UNIQUE INDEX IF NOT EXISTS uk_t_case_weekly_schedule_no + ON t_case_weekly_schedule(schedule_no) WHERE deleted_flag = FALSE; +CREATE INDEX IF NOT EXISTS idx_t_case_weekly_schedule_status + ON t_case_weekly_schedule(status) WHERE deleted_flag = FALSE; + +COMMENT ON TABLE t_case_weekly_schedule IS '案件周调度:draft未推送 / pending_confirm待确认 / confirmed全员确认已锁定'; + +CREATE TABLE IF NOT EXISTS t_case_weekly_schedule_case ( + item_id BIGSERIAL PRIMARY KEY, + schedule_id BIGINT NOT NULL, + case_id BIGINT NOT NULL, + case_no VARCHAR(64) NOT NULL, + case_name VARCHAR(200) NOT NULL, + create_dept VARCHAR(128), + handle_dept VARCHAR(128), + case_status VARCHAR(32), + accept_time TIMESTAMP, + sort_no INTEGER DEFAULT 0, + create_time TIMESTAMP DEFAULT NOW() +); +CREATE INDEX IF NOT EXISTS idx_t_case_weekly_schedule_case_sid + ON t_case_weekly_schedule_case(schedule_id); + +CREATE TABLE IF NOT EXISTS t_case_weekly_schedule_member ( + member_id BIGSERIAL PRIMARY KEY, + schedule_id BIGINT NOT NULL, + employee_id BIGINT NOT NULL, + employee_name VARCHAR(64), + confirmed_flag BOOLEAN DEFAULT FALSE, + confirm_time TIMESTAMP, + create_time TIMESTAMP DEFAULT NOW() +); +CREATE UNIQUE INDEX IF NOT EXISTS uk_t_case_weekly_schedule_member + ON t_case_weekly_schedule_member(schedule_id, employee_id); +CREATE INDEX IF NOT EXISTS idx_t_case_weekly_schedule_member_emp + ON t_case_weekly_schedule_member(employee_id, confirmed_flag); + +-- ========== 菜单:案件监督改为目录 ========== +UPDATE t_menu +SET menu_type = 1, + component = NULL, + path = '/case-management/supervision', + update_time = NOW() +WHERE menu_name = '案件监督' + AND path = '/case-management/supervision' + AND deleted_flag = 0; + +-- 旧功能点挂在原页面上,改为目录后下线 +UPDATE t_menu f +SET deleted_flag = TRUE, + update_time = NOW() +FROM t_menu p +WHERE p.menu_name = '案件监督' + AND p.path = '/case-management/supervision' + AND p.deleted_flag = 0 + AND f.parent_id = p.menu_id + AND f.menu_type = 3 + AND f.deleted_flag = 0 + AND f.web_perms IN ( + 'case:query', + 'case-supervision:query', + 'case-supervision:add', + 'case-supervision:view', + 'case-supervision:supervise' + ); + +INSERT INTO t_menu (menu_name, menu_type, parent_id, sort, path, component, + frame_flag, cache_flag, visible_flag, disabled_flag, + perms_type, icon, deleted_flag, create_user_id, create_time, update_time) +SELECT v.menu_name, 2, p.menu_id, v.sort_num, v.path, v.component, + false, false, true, false, 1, NULL, false, 1, NOW(), NOW() +FROM t_menu p +CROSS JOIN (VALUES + ('负面清单巡查', 1, '/case-management/supervision/negative-list', + '/business/case-management/negative-list.vue'), + ('周调度', 2, '/case-management/supervision/weekly-schedule', + '/business/case-management/weekly-schedule.vue') +) AS v(menu_name, sort_num, path, component) +WHERE p.menu_name = '案件监督' + AND p.path = '/case-management/supervision' + AND p.deleted_flag = 0 + AND NOT EXISTS (SELECT 1 FROM t_menu x WHERE x.path = v.path AND x.deleted_flag = 0); + +-- 功能权限 +INSERT INTO t_menu (menu_name, menu_type, parent_id, sort, frame_flag, cache_flag, + visible_flag, disabled_flag, perms_type, api_perms, web_perms, + context_menu_id, deleted_flag, create_user_id, create_time, update_time) +SELECT v.menu_name, 3, c.menu_id, v.sort_num, false, false, true, false, 1, + v.perms, v.perms, c.menu_id, false, 1, NOW(), NOW() +FROM t_menu c +CROSS JOIN (VALUES + ('查询', 10, 'negative-list:query', '/case-management/supervision/negative-list'), + ('查询', 10, 'weekly-schedule:query', '/case-management/supervision/weekly-schedule'), + ('新增', 20, 'weekly-schedule:add', '/case-management/supervision/weekly-schedule'), + ('查看', 30, 'weekly-schedule:view', '/case-management/supervision/weekly-schedule'), + ('推送', 40, 'weekly-schedule:push', '/case-management/supervision/weekly-schedule'), + ('确认', 50, 'weekly-schedule:confirm', '/case-management/supervision/weekly-schedule'), + ('打印', 60, 'weekly-schedule:print', '/case-management/supervision/weekly-schedule') +) AS v(menu_name, sort_num, perms, child_path) +WHERE c.path = v.child_path + AND c.deleted_flag = 0 + AND NOT EXISTS (SELECT 1 FROM t_menu x WHERE x.web_perms = v.perms AND x.deleted_flag = 0); + +-- 原有「案件监督」权限的角色同步绑定子菜单及功能点 +INSERT INTO t_role_menu (role_id, menu_id) +SELECT DISTINCT rm.role_id, c.menu_id +FROM t_role_menu rm +JOIN t_menu p ON p.menu_id = rm.menu_id +JOIN t_menu c ON c.parent_id = p.menu_id AND c.deleted_flag = 0 AND c.menu_type IN (2, 3) +WHERE p.menu_name = '案件监督' + AND p.path = '/case-management/supervision' + AND p.deleted_flag = 0 + AND NOT EXISTS ( + SELECT 1 FROM t_role_menu x WHERE x.role_id = rm.role_id AND x.menu_id = c.menu_id + ); diff --git a/docs/20260928_case_supervision_seed.sql b/docs/20260928_case_supervision_seed.sql new file mode 100644 index 0000000..9169abf --- /dev/null +++ b/docs/20260928_case_supervision_seed.sql @@ -0,0 +1,58 @@ +-- 案件监督演示数据:补全现有案件单位字段,并插入派出所办案单位案件供负面清单标红 + +UPDATE t_case_file +SET biz_category = '经侦', + create_dept = COALESCE(create_dept, '铜陵市公安局经侦支队'), + handle_dept = CASE case_no + WHEN 'AJFX20260908001' THEN '市经侦支队一大队' + WHEN 'AJFX20260908002' THEN '铜官区分局经侦大队' + WHEN 'AJFX20260908003' THEN '义安区分局经侦大队' + WHEN 'AJFX20260908004' THEN '郊区分局经侦大队' + WHEN 'AJFX20260908005' THEN '市经侦支队二大队' + WHEN 'AJFX20260908006' THEN '枞阳县公安局经侦大队' + WHEN 'AJFX20260908007' THEN '市经侦支队一大队' + WHEN 'AJFX20260908008' THEN '铜官区分局西湖派出所' + WHEN 'AJFX20260908009' THEN '义安区分局五松派出所' + WHEN 'AJFX20260908010' THEN '市经侦支队三大队' + WHEN 'AJFX20260908011' THEN '郊区分局大通派出所' + WHEN 'AJFX20260908012' THEN '市经侦支队一大队' + WHEN 'AJFX20260908013' THEN '铜官区分局经侦大队' + WHEN 'AJFX20260908014' THEN '枞阳县公安局经侦大队' + WHEN 'AJFX20260908015' THEN '市经侦支队二大队' + ELSE COALESCE(handle_dept, '市经侦支队一大队') + END, + case_status = CASE case_no + WHEN 'AJFX20260908004' THEN 'closed' + WHEN 'AJFX20260908008' THEN 'pending_filing' + WHEN 'AJFX20260908014' THEN 'withdrawn' + ELSE COALESCE(NULLIF(case_status, ''), 'investigating') + END, + update_time = NOW() +WHERE deleted_flag = FALSE + AND case_no LIKE 'AJFX20260908%'; + +INSERT INTO t_case_file ( + case_no, case_name, case_source, case_source_sub, handler_name, + review_decide_time, accept_time, filing_time, + biz_category, create_dept, handle_dept, case_status +) +SELECT v.case_no, v.case_name, v.case_source, v.case_source_sub, v.handler_name, + v.review_decide_time, v.accept_time, v.filing_time, + v.biz_category, v.create_dept, v.handle_dept, v.case_status +FROM (VALUES + ('AJFX20260928001', '某商场合同诈骗案', 'party_report', NULL, '刘警官', + NOW() - INTERVAL '8 day', NOW() - INTERVAL '6 day', NOW() - INTERVAL '3 day', + '经侦', '铜陵市公安局经侦支队', '铜官区分局杨家山派出所', 'investigating'), + ('AJFX20260928002', '王某非法吸收公众存款案', 'superior_assign', NULL, '黄警官', + NOW() - INTERVAL '20 day', NOW() - INTERVAL '18 day', NULL, + '经侦', '铜官区分局经侦大队', '铜官区分局阳光社区派出所', 'pending_filing'), + ('AJFX20260928003', '李某虚开增值税发票案', 'work_discovery', NULL, '徐警官', + NOW() - INTERVAL '40 day', NOW() - INTERVAL '35 day', NOW() - INTERVAL '30 day', + '经侦', '义安区分局经侦大队', '义安区分局顺安派出所', 'investigating'), + ('AJFX20260928004', '赵某职务侵占案', 'other_unit_transfer', NULL, '曹警官', + NOW() - INTERVAL '90 day', NOW() - INTERVAL '80 day', NOW() - INTERVAL '70 day', + '经侦', '郊区分局经侦大队', '郊区分局老洲派出所', 'closed') +) AS v(case_no, case_name, case_source, case_source_sub, handler_name, + review_decide_time, accept_time, filing_time, + biz_category, create_dept, handle_dept, case_status) +WHERE NOT EXISTS (SELECT 1 FROM t_case_file c WHERE c.case_no = v.case_no AND c.deleted_flag = FALSE); diff --git a/docs/20261015_alarm_audit_demo_accounts.sql b/docs/20261015_alarm_audit_demo_accounts.sql new file mode 100644 index 0000000..04afd8c --- /dev/null +++ b/docs/20261015_alarm_audit_demo_accounts.sql @@ -0,0 +1,107 @@ +-- 审核监督三人组演示账号 +-- 市局审核法制员 / 公职律师 新开六位警号;经侦支队审核员沿用已有账号章成(zhangcheng) +-- 密码 123456(Argon2id 与系统一致) + +UPDATE t_role +SET role_name = '市局审核法制员', + remark = '审核监督-法制席位', + update_time = NOW() +WHERE role_code = 'alarm_audit_legal'; + +UPDATE t_role +SET role_name = '公职律师', + remark = '审核监督-公职律师席位', + update_time = NOW() +WHERE role_code = 'alarm_audit_lawyer'; + +UPDATE t_role +SET role_name = '经侦支队审核员', + remark = '审核监督-经侦席位(演示:章成)', + update_time = NOW() +WHERE role_code = 'alarm_audit_jz'; + +INSERT INTO t_role (role_name, role_code, remark, create_time, update_time) +SELECT '市局审核法制员', 'alarm_audit_legal', '审核监督-法制席位', NOW(), NOW() +WHERE NOT EXISTS (SELECT 1 FROM t_role WHERE role_code = 'alarm_audit_legal'); + +INSERT INTO t_role (role_name, role_code, remark, create_time, update_time) +SELECT '公职律师', 'alarm_audit_lawyer', '审核监督-公职律师席位', NOW(), NOW() +WHERE NOT EXISTS (SELECT 1 FROM t_role WHERE role_code = 'alarm_audit_lawyer'); + +INSERT INTO t_role (role_name, role_code, remark, create_time, update_time) +SELECT '经侦支队审核员', 'alarm_audit_jz', '审核监督-经侦席位(演示:章成)', NOW(), NOW() +WHERE NOT EXISTS (SELECT 1 FROM t_role WHERE role_code = 'alarm_audit_jz'); + +-- 审核组仅开「接报案中心 → 审核监督」及功能点 +INSERT INTO t_role_menu (role_id, menu_id, create_time, update_time) +SELECT r.role_id, m.menu_id, NOW(), NOW() +FROM t_role r +CROSS JOIN t_menu m +WHERE r.role_code IN ('alarm_audit_legal', 'alarm_audit_lawyer', 'alarm_audit_jz') + AND m.deleted_flag = 0 + AND ( + (m.menu_name = '接报案中心' AND m.menu_type = 1) + OR m.path = '/business/alarm/audit-list' + OR m.menu_id IN (SELECT menu_id FROM t_menu WHERE path = '/business/alarm/audit-list' AND deleted_flag = 0) + OR m.parent_id IN (SELECT menu_id FROM t_menu WHERE path = '/business/alarm/audit-list' AND deleted_flag = 0) + ) + AND NOT EXISTS ( + SELECT 1 FROM t_role_menu x WHERE x.role_id = r.role_id AND x.menu_id = m.menu_id + ); + +INSERT INTO t_employee ( + login_name, login_pwd, actual_name, gender, phone, department_id, email, + disabled_flag, deleted_flag, administrator_flag, remark, create_time, update_time +) +SELECT v.login_name, + '$argon2id$v=19$m=16384,t=2,p=1$e/hqRAZYCYHydMS3SPo7yA$5hdCxLG7q+Jtf6KLJHVg/yb0I8LZrPuKUF66jLq+Drc', + v.actual_name, v.gender, v.phone, + COALESCE((SELECT department_id FROM t_department d WHERE d.department_id = v.dept_id), 1), + CONCAT(v.login_name, '@tl-police.cn'), + 0, 0, 0, v.remark, NOW(), NOW() +FROM (VALUES + ('340704', '孙磊', 1, '13834070401', 118, '市局审核法制员'), + ('340705', '林静', 0, '13834070501', 118, '公职律师') +) AS v(login_name, actual_name, gender, phone, dept_id, remark) +WHERE NOT EXISTS ( + SELECT 1 FROM t_employee e WHERE e.login_name = v.login_name AND e.deleted_flag IN (0, FALSE) +); + +-- 席位一人一岗:解绑旧岗号,避免同席位多人抢票 +DELETE FROM t_role_employee re +USING t_role r, t_employee e +WHERE re.role_id = r.role_id + AND re.employee_id = e.employee_id + AND r.role_code IN ('alarm_audit_legal', 'alarm_audit_lawyer', 'alarm_audit_jz') + AND e.login_name IN ('sjjbazxfzg', 'sjjbazxgzlvg', 'sjjbazxjzg'); + +-- 章成去掉系统演示 cto,保留作废主任 + 经侦审核员 +DELETE FROM t_role_employee re +USING t_role r, t_employee e +WHERE re.role_id = r.role_id + AND re.employee_id = e.employee_id + AND e.login_name = 'zhangcheng' + AND r.role_code = 'cto'; + +INSERT INTO t_role_employee (role_id, employee_id, create_time, update_time) +SELECT r.role_id, e.employee_id, NOW(), NOW() +FROM (VALUES + ('340704', 'alarm_audit_legal'), + ('340705', 'alarm_audit_lawyer'), + ('zhangcheng', 'alarm_audit_jz') +) AS v(login_name, role_code) +JOIN t_employee e ON e.login_name = v.login_name AND e.deleted_flag IN (0, FALSE) +JOIN t_role r ON r.role_code = v.role_code +WHERE NOT EXISTS ( + SELECT 1 FROM t_role_employee x WHERE x.role_id = r.role_id AND x.employee_id = e.employee_id +); + +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM pg_class WHERE relkind = 'S' AND relname = 't_employee_employee_id_seq') THEN + PERFORM setval('t_employee_employee_id_seq', (SELECT COALESCE(MAX(employee_id), 1) FROM t_employee)); + END IF; + IF EXISTS (SELECT 1 FROM pg_class WHERE relkind = 'S' AND relname = 't_role_role_id_seq') THEN + PERFORM setval('t_role_role_id_seq', (SELECT COALESCE(MAX(role_id), 1) FROM t_role)); + END IF; +END $$; diff --git a/docs/20261015_biz_demo_roles_accounts.sql b/docs/20261015_biz_demo_roles_accounts.sql new file mode 100644 index 0000000..4bc9f12 --- /dev/null +++ b/docs/20261015_biz_demo_roles_accounts.sql @@ -0,0 +1,305 @@ +-- 业务演示角色 + 六位警号账号(密码 123456,Argon2id 与系统一致) +-- 市局:案管员 / 财物保管员 / 接报案接待员 +-- 义安分局:大队长 / 分局领导 / 办案民警 / 大队案管员 / 大队财物保管员 / 大队接报案接待员 + +-- 已知 123456 哈希(与 t_employee.admin 相同算法) +-- $argon2id$v=19$m=16384,t=2,p=1$e/hqRAZYCYHydMS3SPo7yA$5hdCxLG7q+Jtf6KLJHVg/yb0I8LZrPuKUF66jLq+Drc + +INSERT INTO t_role (role_name, role_code, remark, create_time, update_time) +SELECT v.role_name, v.role_code, v.remark, NOW(), NOW() +FROM (VALUES + ('市局案管员', 'city_case_manager', '市局案件监督、卷宗登记归档、借阅确认'), + ('涉案财物保管员', 'city_property_keeper', '市局涉案财物入库保管、归还/出库确认'), + ('接报案中心接待员', 'city_alarm_receptionist', '市局接报案中心登记、材料、发起作废'), + ('义安区分局经侦大队大队长', 'yian_brigade_captain', '区县作废审核、财物调用审核、卷宗借阅/复印审核'), + ('分局领导', 'bureau_leader', '分局业务总览、审议审批、领办包保、复印领导审'), + ('大队办案民警', 'brigade_officer', '本大队办案:案件查询、财物录入/调用、本人卷宗借阅'), + ('大队案管员', 'brigade_case_manager', '大队案件监督、卷宗登记、移交市局'), + ('大队涉案财物保管员', 'brigade_property_keeper', '大队涉案财物入库保管、归还/出库确认'), + ('大队接报案中心接待员', 'brigade_alarm_receptionist', '区县接报案分中心登记、材料、发起作废') +) AS v(role_name, role_code, remark) +WHERE NOT EXISTS (SELECT 1 FROM t_role x WHERE x.role_code = v.role_code); + +-- 授权规则:dir=一级目录名;path=页面;children=页面及其功能点 +CREATE TEMP TABLE IF NOT EXISTS tmp_role_menu_rule ( + role_code VARCHAR(64) NOT NULL, + kind VARCHAR(16) NOT NULL, + val VARCHAR(256) NOT NULL +); +TRUNCATE tmp_role_menu_rule; + +INSERT INTO tmp_role_menu_rule (role_code, kind, val) VALUES +-- 市局案管员 +('city_case_manager', 'dir', '案件管理'), +('city_case_manager', 'dir', '案件监督'), +('city_case_manager', 'dir', '风险预警'), +('city_case_manager', 'dir', '卷宗管理'), +('city_case_manager', 'dir', '数据大屏'), +('city_case_manager', 'path_prefix', '/case-management'), +('city_case_manager', 'path_prefix', '/dossier'), +('city_case_manager', 'path', '/bigscreen/data-bigscreen'), +('city_case_manager', 'web_prefix', 'negative-list:'), +('city_case_manager', 'web_prefix', 'weekly-schedule:'), +('city_case_manager', 'web_prefix', 'risk-warning:'), +('city_case_manager', 'web_prefix', 'dossier:'), +-- 市局财物保管员 +('city_property_keeper', 'dir', '涉案财物'), +('city_property_keeper', 'path_prefix', '/property'), +('city_property_keeper', 'web_prefix', 'property:management:'), +('city_property_keeper', 'web_prefix', 'property:unregistered:'), +('city_property_keeper', 'web_prefix', 'property:omission:'), +('city_property_keeper', 'web_prefix', 'property:return:'), +('city_property_keeper', 'web_prefix', 'property:checkout:'), +('city_property_keeper', 'web_prefix', 'property:transfer:query'), +('city_property_keeper', 'web_prefix', 'property:transfer:detail'), +-- 市局接报案接待员 +('city_alarm_receptionist', 'dir', '接报案中心'), +('city_alarm_receptionist', 'path', '/business/alarm/alarm-reception-list'), +('city_alarm_receptionist', 'children', '/business/alarm/alarm-reception-list'), +('city_alarm_receptionist', 'path', '/business/alarm/material-view'), +('city_alarm_receptionist', 'children', '/business/alarm/material-view'), +('city_alarm_receptionist', 'path', '/business/alarm/center-monitor'), +('city_alarm_receptionist', 'children', '/business/alarm/center-monitor'), +('city_alarm_receptionist', 'path', '/business/alarm/no-accept-review-list'), +('city_alarm_receptionist', 'children', '/business/alarm/no-accept-review-list'), +('city_alarm_receptionist', 'web_prefix', 'alarm:void:apply'), +-- 义安大队长 +('yian_brigade_captain', 'dir', '接报案中心'), +('yian_brigade_captain', 'dir', '案件管理'), +('yian_brigade_captain', 'dir', '案件监督'), +('yian_brigade_captain', 'dir', '风险预警'), +('yian_brigade_captain', 'dir', '涉案财物'), +('yian_brigade_captain', 'dir', '卷宗管理'), +('yian_brigade_captain', 'dir', '审议流程'), +('yian_brigade_captain', 'dir', '数据大屏'), +('yian_brigade_captain', 'path', '/business/alarm/alarm-reception-list'), +('yian_brigade_captain', 'children', '/business/alarm/alarm-reception-list'), +('yian_brigade_captain', 'path', '/business/alarm/void-audit-list'), +('yian_brigade_captain', 'children', '/business/alarm/void-audit-list'), +('yian_brigade_captain', 'path_prefix', '/case-management'), +('yian_brigade_captain', 'path_prefix', '/dossier'), +('yian_brigade_captain', 'path', '/property/transfer'), +('yian_brigade_captain', 'children', '/property/transfer'), +('yian_brigade_captain', 'path', '/property/management'), +('yian_brigade_captain', 'children', '/property/management'), +('yian_brigade_captain', 'path', '/bigscreen/data-bigscreen'), +('yian_brigade_captain', 'web_prefix', 'alarm:void:'), +('yian_brigade_captain', 'web_prefix', 'property:transfer:'), +('yian_brigade_captain', 'web_prefix', 'dossier:borrow:audit'), +('yian_brigade_captain', 'web_prefix', 'dossier:copy:audit'), +('yian_brigade_captain', 'web_prefix', 'weekly-schedule:'), +-- 分局领导 +('bureau_leader', 'dir', '接报案中心'), +('bureau_leader', 'dir', '案件管理'), +('bureau_leader', 'dir', '案件监督'), +('bureau_leader', 'dir', '风险预警'), +('bureau_leader', 'dir', '涉案资金'), +('bureau_leader', 'dir', '涉案财物'), +('bureau_leader', 'dir', '卷宗管理'), +('bureau_leader', 'dir', '审议流程'), +('bureau_leader', 'dir', '数据大屏'), +('bureau_leader', 'path', '/business/alarm/alarm-reception-list'), +('bureau_leader', 'children', '/business/alarm/alarm-reception-list'), +('bureau_leader', 'path_prefix', '/case-management'), +('bureau_leader', 'path_prefix', '/fund'), +('bureau_leader', 'path', '/property/management'), +('bureau_leader', 'children', '/property/management'), +('bureau_leader', 'path_prefix', '/dossier'), +('bureau_leader', 'path', '/bigscreen/data-bigscreen'), +('bureau_leader', 'web_prefix', 'review:general:'), +('bureau_leader', 'web_prefix', 'leader-record:'), +('bureau_leader', 'web_prefix', 'dossier:copy:audit'), +('bureau_leader', 'web_prefix', 'risk-warning:query'), +('bureau_leader', 'web_prefix', 'risk-warning:view'), +-- 大队办案民警 +('brigade_officer', 'dir', '案件管理'), +('brigade_officer', 'dir', '案件监督'), +('brigade_officer', 'dir', '风险预警'), +('brigade_officer', 'dir', '涉案财物'), +('brigade_officer', 'dir', '卷宗管理'), +('brigade_officer', 'path', '/case-management/supervision/weekly-schedule'), +('brigade_officer', 'children', '/case-management/supervision/weekly-schedule'), +('brigade_officer', 'path', '/case-management/risk-warning'), +('brigade_officer', 'path_prefix', '/case-management/risk-warning'), +('brigade_officer', 'path', '/property/management'), +('brigade_officer', 'children', '/property/management'), +('brigade_officer', 'path', '/property/transfer'), +('brigade_officer', 'children', '/property/transfer'), +('brigade_officer', 'path', '/dossier/register'), +('brigade_officer', 'children', '/dossier/register'), +('brigade_officer', 'path', '/dossier/borrow-self'), +('brigade_officer', 'children', '/dossier/borrow-self'), +('brigade_officer', 'path', '/dossier/copy-request'), +('brigade_officer', 'children', '/dossier/copy-request'), +('brigade_officer', 'web_prefix', 'weekly-schedule:confirm'), +('brigade_officer', 'web_prefix', 'weekly-schedule:query'), +('brigade_officer', 'web_prefix', 'weekly-schedule:view'), +('brigade_officer', 'web_prefix', 'risk-warning:query'), +('brigade_officer', 'web_prefix', 'risk-warning:view'), +('brigade_officer', 'web_prefix', 'property:management:query'), +('brigade_officer', 'web_prefix', 'property:management:add'), +('brigade_officer', 'web_prefix', 'property:management:detail'), +('brigade_officer', 'web_prefix', 'property:management:invoke'), +('brigade_officer', 'web_prefix', 'dossier:register:query'), +('brigade_officer', 'web_prefix', 'dossier:detail'), +('brigade_officer', 'web_prefix', 'dossier:borrow:apply'), +('brigade_officer', 'web_prefix', 'dossier:copy:apply'), +-- 大队案管员 +('brigade_case_manager', 'dir', '案件管理'), +('brigade_case_manager', 'dir', '案件监督'), +('brigade_case_manager', 'dir', '风险预警'), +('brigade_case_manager', 'dir', '卷宗管理'), +('brigade_case_manager', 'path_prefix', '/case-management/supervision'), +('brigade_case_manager', 'path_prefix', '/case-management/risk-warning'), +('brigade_case_manager', 'path_prefix', '/dossier'), +('brigade_case_manager', 'web_prefix', 'negative-list:'), +('brigade_case_manager', 'web_prefix', 'weekly-schedule:'), +('brigade_case_manager', 'web_prefix', 'risk-warning:'), +('brigade_case_manager', 'web_prefix', 'dossier:'), +-- 大队财物保管员 +('brigade_property_keeper', 'dir', '涉案财物'), +('brigade_property_keeper', 'path_prefix', '/property'), +('brigade_property_keeper', 'web_prefix', 'property:management:'), +('brigade_property_keeper', 'web_prefix', 'property:unregistered:'), +('brigade_property_keeper', 'web_prefix', 'property:omission:'), +('brigade_property_keeper', 'web_prefix', 'property:return:'), +('brigade_property_keeper', 'web_prefix', 'property:checkout:'), +('brigade_property_keeper', 'web_prefix', 'property:transfer:query'), +('brigade_property_keeper', 'web_prefix', 'property:transfer:detail'), +-- 大队接报案接待员 +('brigade_alarm_receptionist', 'dir', '接报案中心'), +('brigade_alarm_receptionist', 'path', '/business/alarm/alarm-reception-list'), +('brigade_alarm_receptionist', 'children', '/business/alarm/alarm-reception-list'), +('brigade_alarm_receptionist', 'path', '/business/alarm/material-view'), +('brigade_alarm_receptionist', 'children', '/business/alarm/material-view'), +('brigade_alarm_receptionist', 'path', '/business/alarm/center-monitor'), +('brigade_alarm_receptionist', 'children', '/business/alarm/center-monitor'), +('brigade_alarm_receptionist', 'path', '/business/alarm/no-accept-review-list'), +('brigade_alarm_receptionist', 'children', '/business/alarm/no-accept-review-list'), +('brigade_alarm_receptionist', 'web_prefix', 'alarm:void:apply'); + +INSERT INTO t_role_menu (role_id, menu_id, create_time, update_time) +SELECT DISTINCT r.role_id, m.menu_id, NOW(), NOW() +FROM tmp_role_menu_rule g +JOIN t_role r ON r.role_code = g.role_code +JOIN t_menu m ON m.deleted_flag = 0 +WHERE ( + (g.kind = 'dir' AND m.menu_type = 1 AND m.menu_name = g.val) + OR (g.kind = 'path' AND m.path = g.val) + OR (g.kind = 'path_prefix' AND (m.path = g.val OR m.path LIKE CONCAT(g.val, '/%'))) + OR (g.kind = 'web_prefix' AND m.web_perms LIKE CONCAT(g.val, '%')) + OR (g.kind = 'children' AND ( + m.path = g.val + OR m.parent_id IN (SELECT menu_id FROM t_menu p WHERE p.path = g.val AND p.deleted_flag = 0) + )) +) +AND NOT EXISTS ( + SELECT 1 FROM t_role_menu x WHERE x.role_id = r.role_id AND x.menu_id = m.menu_id +); + +-- 办案民警去掉财物调用审核、卷宗借阅他人审核等越权点 +DELETE FROM t_role_menu rm +USING t_role r, t_menu m +WHERE rm.role_id = r.role_id + AND rm.menu_id = m.menu_id + AND r.role_code = 'brigade_officer' + AND m.web_perms IN ( + 'property:transfer:audit', + 'dossier:borrow:audit', + 'dossier:borrow:confirm', + 'dossier:return:audit', + 'dossier:copy:audit', + 'dossier:transfer:submit', + 'dossier:register:submit', + 'dossier:sync', + 'weekly-schedule:add', + 'weekly-schedule:push', + 'weekly-schedule:print', + 'property:management:checkout' + ); + +-- 分局领导不作出库/入库操作与作废审批 +DELETE FROM t_role_menu rm +USING t_role r, t_menu m +WHERE rm.role_id = r.role_id + AND rm.menu_id = m.menu_id + AND r.role_code = 'bureau_leader' + AND ( + m.web_perms IN ( + 'property:management:add', + 'property:management:checkout', + 'property:management:invoke', + 'property:transfer:audit', + 'alarm:void:apply', + 'alarm:void:audit', + 'alarm:add', + 'alarm:update' + ) + OR m.path IN ('/business/alarm/void-audit-list', '/property/unregistered', '/property/omission') + OR m.web_perms IN ('weekly-schedule:add', 'weekly-schedule:push') + ); + +-- 财物保管员不审调用 +DELETE FROM t_role_menu rm +USING t_role r, t_menu m +WHERE rm.role_id = r.role_id + AND rm.menu_id = m.menu_id + AND r.role_code IN ('city_property_keeper', 'brigade_property_keeper') + AND m.web_perms = 'property:transfer:audit'; + +INSERT INTO t_employee ( + login_name, login_pwd, actual_name, gender, phone, department_id, email, + disabled_flag, deleted_flag, administrator_flag, remark, create_time, update_time +) +SELECT v.login_name, + '$argon2id$v=19$m=16384,t=2,p=1$e/hqRAZYCYHydMS3SPo7yA$5hdCxLG7q+Jtf6KLJHVg/yb0I8LZrPuKUF66jLq+Drc', + v.actual_name, v.gender, v.phone, + COALESCE((SELECT department_id FROM t_department d WHERE d.department_id = v.dept_id), 1), + v.login_name || '@tl-police.cn', + 0, 0, 0, v.remark, NOW(), NOW() +FROM (VALUES + ('340701', '陈立', 1, '13834070101', 118, '市局案管员'), + ('340702', '刘仓', 1, '13834070201', 118, '涉案财物保管员'), + ('340703', '王敏', 0, '13834070301', 123, '接报案中心接待员'), + ('340711', '赵建军', 1, '13834071101', 3017, '义安区分局经侦大队大队长'), + ('340712', '黄志强', 1, '13834071201', 301, '分局领导'), + ('340713', '张伟', 1, '13834071301', 3017, '大队办案民警'), + ('340714', '李芳', 0, '13834071401', 3017, '大队案管员'), + ('340715', '周海', 1, '13834071501', 3017, '大队涉案财物保管员'), + ('340716', '吴娟', 0, '13834071601', 3017, '大队接报案中心接待员') +) AS v(login_name, actual_name, gender, phone, dept_id, remark) +WHERE NOT EXISTS ( + SELECT 1 FROM t_employee e WHERE e.login_name = v.login_name AND e.deleted_flag IN (0, FALSE) +); + +INSERT INTO t_role_employee (role_id, employee_id, create_time, update_time) +SELECT r.role_id, e.employee_id, NOW(), NOW() +FROM (VALUES + ('340701', 'city_case_manager'), + ('340702', 'city_property_keeper'), + ('340703', 'city_alarm_receptionist'), + ('340703', 'alarm_city_receiver'), + ('340711', 'yian_brigade_captain'), + ('340711', 'alarm_district_captain'), + ('340712', 'bureau_leader'), + ('340713', 'brigade_officer'), + ('340714', 'brigade_case_manager'), + ('340715', 'brigade_property_keeper'), + ('340716', 'brigade_alarm_receptionist'), + ('340716', 'alarm_district_receiver') +) AS v(login_name, role_code) +JOIN t_employee e ON e.login_name = v.login_name AND e.deleted_flag IN (0, FALSE) +JOIN t_role r ON r.role_code = v.role_code +WHERE NOT EXISTS ( + SELECT 1 FROM t_role_employee x WHERE x.role_id = r.role_id AND x.employee_id = e.employee_id +); + +DO $$ +BEGIN + IF EXISTS (SELECT 1 FROM pg_class WHERE relkind = 'S' AND relname = 't_employee_employee_id_seq') THEN + PERFORM setval('t_employee_employee_id_seq', (SELECT COALESCE(MAX(employee_id), 1) FROM t_employee)); + END IF; + IF EXISTS (SELECT 1 FROM pg_class WHERE relkind = 'S' AND relname = 't_role_role_id_seq') THEN + PERFORM setval('t_role_role_id_seq', (SELECT COALESCE(MAX(role_id), 1) FROM t_role)); + END IF; +END $$; diff --git a/docs/20261015_case_source_dict.sql b/docs/20261015_case_source_dict.sql new file mode 100644 index 0000000..32ac41d --- /dev/null +++ b/docs/20261015_case_source_dict.sql @@ -0,0 +1,63 @@ +-- 报案类案件来源字典改为九项平铺(移交→移送;法院两类升主项) + +ALTER TABLE t_alarm_report DROP CONSTRAINT IF EXISTS t_alarm_report_case_source_check; + +-- 历史:人民法院移交 + 子项 → 平铺主项 +UPDATE t_alarm_report +SET case_source = 'court_transfer_false' +WHERE case_source = 'court_transfer' + AND case_source_sub = 'false_litigation'; + +UPDATE t_alarm_report +SET case_source = 'court_transfer_normal' +WHERE case_source = 'court_transfer'; + +UPDATE t_case_file +SET case_source = 'court_transfer_false' +WHERE case_source = 'court_transfer' + AND case_source_sub = 'false_litigation'; + +UPDATE t_case_file +SET case_source = 'court_transfer_normal' +WHERE case_source = 'court_transfer'; + +ALTER TABLE t_alarm_report ADD CONSTRAINT t_alarm_report_case_source_check + CHECK (case_source IS NULL OR case_source IN ( + 'party_report', + 'admin_transfer', + 'court_transfer', + 'court_transfer_normal', + 'court_transfer_false', + 'procuratorate_transfer', + 'procuratorate_notify', + 'superior_assign', + 'work_discovery', + 'other_unit_transfer' + )); + +COMMENT ON COLUMN t_alarm_report.case_source IS '案件来源:当事人报案/行政机关移送/人民法院移送普通案件/人民法院移送虚假诉讼类案件/人民检察院移送/人民检察院通知立案/上级交办/工作中发现/其他单位移送'; +COMMENT ON COLUMN t_alarm_report.case_source_sub IS '历史子项(法院/检察院),新登记由主项派生,可空'; +COMMENT ON COLUMN t_alarm_report.accepting_unit IS '受案单位:人民法院移送两类时填写'; + +DELETE FROM t_dict_data +WHERE dict_id = (SELECT dict_id FROM t_dict WHERE dict_code = 'CASE_SOURCE'); + +INSERT INTO t_dict (dict_name, dict_code, remark, disabled_flag, create_time, update_time) +SELECT '案件来源', 'CASE_SOURCE', '报案类警情登记-案件来源', false, NOW(), NOW() +WHERE NOT EXISTS (SELECT 1 FROM t_dict WHERE dict_code = 'CASE_SOURCE'); + +INSERT INTO t_dict_data (dict_id, data_value, data_label, remark, sort_order, disabled_flag, create_time, update_time) +SELECT d.dict_id, v.data_value, v.data_label, '案件来源', v.sort_order, false, NOW(), NOW() +FROM t_dict d +CROSS JOIN (VALUES + ('party_report', '当事人报案', 1), + ('admin_transfer', '行政机关移送', 2), + ('court_transfer_normal', '人民法院移送普通案件', 3), + ('court_transfer_false', '人民法院移送虚假诉讼类案件', 4), + ('procuratorate_transfer', '人民检察院移送', 5), + ('procuratorate_notify', '人民检察院通知立案', 6), + ('superior_assign', '上级交办', 7), + ('work_discovery', '工作中发现', 8), + ('other_unit_transfer', '其他单位移送', 9) +) AS v(data_value, data_label, sort_order) +WHERE d.dict_code = 'CASE_SOURCE'; diff --git a/docs/20261015_weekly_schedule_minutes.sql b/docs/20261015_weekly_schedule_minutes.sql new file mode 100644 index 0000000..f435d94 --- /dev/null +++ b/docs/20261015_weekly_schedule_minutes.sql @@ -0,0 +1,19 @@ +-- 周调度记录改为「案件调度会议纪要」模板:会议信息 + 主办民警快照 + 逐案调度内容 + +ALTER TABLE t_case_weekly_schedule ADD COLUMN IF NOT EXISTS meeting_time TIMESTAMP; +ALTER TABLE t_case_weekly_schedule ADD COLUMN IF NOT EXISTS meeting_place VARCHAR(200); +ALTER TABLE t_case_weekly_schedule ADD COLUMN IF NOT EXISTS schedule_unit VARCHAR(128); +ALTER TABLE t_case_weekly_schedule ADD COLUMN IF NOT EXISTS host_name VARCHAR(64); +ALTER TABLE t_case_weekly_schedule ADD COLUMN IF NOT EXISTS recorder_name VARCHAR(64); + +COMMENT ON COLUMN t_case_weekly_schedule.meeting_time IS '会议时间'; +COMMENT ON COLUMN t_case_weekly_schedule.meeting_place IS '会议地点'; +COMMENT ON COLUMN t_case_weekly_schedule.schedule_unit IS '调度单位(纪要标题红字)'; +COMMENT ON COLUMN t_case_weekly_schedule.host_name IS '会议主持人'; +COMMENT ON COLUMN t_case_weekly_schedule.recorder_name IS '会议记录人'; + +ALTER TABLE t_case_weekly_schedule_case ADD COLUMN IF NOT EXISTS handler_name VARCHAR(64); +ALTER TABLE t_case_weekly_schedule_case ADD COLUMN IF NOT EXISTS item_content TEXT; + +COMMENT ON COLUMN t_case_weekly_schedule_case.handler_name IS '主办民警快照'; +COMMENT ON COLUMN t_case_weekly_schedule_case.item_content IS '该案调度内容(手填)'; diff --git a/docs/Plan/prd-case-risk-warning.md b/docs/Plan/prd-case-risk-warning.md new file mode 100644 index 0000000..be750d9 --- /dev/null +++ b/docs/Plan/prd-case-risk-warning.md @@ -0,0 +1,40 @@ +# 案件三色预警 PRD + +> 最后更新:2026-10-15 +> 对应页面:`economic-crime-web/src/views/business/case-management/risk-warning.vue`(二级「风险预警」下 13 条规则子菜单共用) +> 后端:`/risk-warning/**`,包 `module/business/caserisk` + +## 1. 级别 + +| 颜色 | 含义 | 消除规则 | +|------|------|----------| +| 红色 | 问题通报 | 一经触发锁定,任何操作不可重置、消除 | +| 黄色 | 问题预警 | 条件消失可清除;可处置/忽略 | +| 蓝色 | 普通提醒 | 条件消失可清除;可处置/忽略 | + +## 2. 规则摘要 + +1. **审议受案超 24 小时未受案** → 红 +2. **立案审查期限**(自受案日起算):按接报案案件来源分流;可抓取「呈请延长立案期限报告书」进入 20/25/31、40/50/61 轮次;法院两类与检察院通知立案不抓延长文书。中止立案审查(不含检察院通知立案)暂停原倒计时。 +3. **取保候审**传讯 + 12 个月解除/起诉 +4. **受案后无活动** 20/30/50 +5. **立案后无活动** 30/60/90,有活动日志后重新检测 +6. **刑拘**:24 小时拘留通知书;3/5/8;7 日内变更羁押 → 20/25/31;30 日内提捕 → 36 黄 / 38 红 +7. **逮捕**:24 小时拘留通知书;40/50/两个月;延长侦查羁押后 3/5/7 个月档 +8. **监视居住**:4/5/6 个月解除或起诉;传讯 1/2/3 月 +9. **指定居所监视居住**:24 小时未制作指定监视居住通知书 → 红 + +## 3. 来源映射 + +| 预警分类 | 接报案 `case_source` | +|----------|----------------------| +| 普通经侦 | 当事人报案、上级交办、工作中发现、其他单位移送 | +| 行政机关移送 | `admin_transfer` | +| 法院普通 | `court_transfer_normal`(兼容历史 `court_transfer`+`normal`) | +| 法院虚假诉讼 | `court_transfer_false`(兼容历史 `court_transfer`+`false_litigation`) | +| 检察院移送 | `procuratorate_transfer`(同普通经侦期限) | +| 检察院通知立案 | `procuratorate_notify` | + +## 4. 表 + +`t_case_file`、`t_case_legal_doc`、`t_case_activity_log`、`t_case_risk_warning` diff --git a/docs/Plan/prd-case-supervision.md b/docs/Plan/prd-case-supervision.md new file mode 100644 index 0000000..899c6a6 --- /dev/null +++ b/docs/Plan/prd-case-supervision.md @@ -0,0 +1,49 @@ +# 案件监督:负面清单巡查 + 周调度 PRD + +> 最后更新:2026-10-15 +> 对应页面:`economic-crime-web/src/views/business/case-management/negative-list.vue`、`weekly-schedule.vue` +> 后端:`/negative-list/**`、`/weekly-schedule/**`,包 `module/business/casesupervision` + +## 1. 菜单 + +「案件监督」由页面改为二级目录: + +| 子菜单 | 路径 | 组件 | +|--------|------|------| +| 负面清单巡查 | `/case-management/supervision/negative-list` | `negative-list.vue` | +| 周调度 | `/case-management/supervision/weekly-schedule` | `weekly-schedule.vue` | + +原 mock 督办页不再挂菜单。 + +权限:`negative-list:query`;`weekly-schedule:query/add/view/push/confirm/print`。 + +## 2. 负面清单巡查 + +自动查询系统内 `t_case_file` 且 `biz_category = 经侦` 的案件(非外网爬取)。 + +列表字段:案件名称、案件编号、创建单位、办案单位、案件状态、受案时间。 + +办案单位包含「派出所」:整行文字标红,办案单位加粗。 + +查询:编号、名称、办案单位、状态、受案时间范围。只读。 + +案件状态:`pending_filing` 待立案 / `investigating` 侦查中 / `closed` 已结案 / `withdrawn` 已撤销。 + +## 3. 周调度 + +状态机:`draft`(草稿,可推送)→ `pending_confirm`(已推送待确认,内容不再改)→ `confirmed`(全部参会人员确认后锁定,可打印不可改)。 + +新增:按案件名称(模糊)或案件编号搜索并勾选 → 按「铜陵市公安局 XX单位案件调度会议纪要」纸面模板填表: + +- 会议时间、会议地点、调度单位、会议主持人、会议记录人(调度单位默认当前部门,标题红字) +- 调度内容区按勾选案件自动标红填入:一、XX案 / 案件编号 / 主办民警,手填该案「调度内容」 +- 会议参与人员来自勾选人员;参会人员签名栏打印留空手签 +- 页脚:注:此表交案管室存档,参会人员可自行复印留存。 + +勾选参加人员后推送站内信。参加人员在列表或详情中点「确认」。全部确认后记录锁定,打印与纸面模板一致,标红字段保持红色。 + +表:`t_case_weekly_schedule`(含会议信息)、`t_case_weekly_schedule_case`(含主办民警与逐案调度内容快照)、`t_case_weekly_schedule_member`。 + +## 4. 数据扩展 + +`t_case_file` 增加 `biz_category`、`create_dept`、`handle_dept`、`case_status`。 diff --git a/economic-crime-api/economic-crime-admin/logs/economic-crime/dev/tomcat-logs/logs/access_log.2026-09-09.log b/economic-crime-api/economic-crime-admin/logs/economic-crime/dev/tomcat-logs/logs/access_log.2026-09-09.log new file mode 100644 index 0000000..e69de29