feat(govdoc): 新增内部公文模块全链路(后端58+前端11文件)

This commit is contained in:
wren
2026-05-13 14:37:12 +08:00
parent 99699e20e1
commit 5d777599bf
63 changed files with 7608 additions and 0 deletions
@@ -0,0 +1,198 @@
-- ============================================================================
-- govdoc 模块建表 DDL
-- 用途:
-- 1. 创建 govdoc 模块专用结果域表(run / rule_result / report_artifact
-- 2. 给 leaudit_documents 补充 engine_type 字段
-- 3. 幂等执行,重复跑不报错
--
-- 设计原则:
-- - 复用 leaudit_documents / leaudit_document_files 作为文档主档
-- - 新建 govdoc 结果域表,不与 leaudit 引擎结果表混用
-- - 后续规则平台化时再补 govdoc_rule_sets / govdoc_rule_versions
-- ============================================================================
BEGIN;
-- ---------------------------------------------------------------------------
-- 1. govdoc_runs —— 公文审查运行主表
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS public.govdoc_runs (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
document_id BIGINT NOT NULL ,
document_file_id BIGINT,
run_no INTEGER NOT NULL DEFAULT 1,
trigger_source VARCHAR(64) NOT NULL DEFAULT 'upload',
trigger_user_id BIGINT,
task_id VARCHAR(128),
-- 运行状态
status VARCHAR(64) NOT NULL DEFAULT 'pending',
phase VARCHAR(32),
-- 引擎快照
engine_version VARCHAR(64),
llm_provider VARCHAR(64),
llm_model VARCHAR(128),
-- 结果汇总
total_score NUMERIC(10, 2),
passed_count INTEGER,
failed_count INTEGER,
skipped_count INTEGER,
result_status VARCHAR(32),
result_summary_json TEXT,
error_message TEXT,
-- 时间
started_at TIMESTAMPTZ,
finished_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ DEFAULT NULL
);
COMMENT ON TABLE public.govdoc_runs IS '公文审查运行主表';
COMMENT ON COLUMN public.govdoc_runs.id IS '自增主键';
COMMENT ON COLUMN public.govdoc_runs.document_id IS '关联 leaudit_documents.id';
COMMENT ON COLUMN public.govdoc_runs.document_file_id IS '输入文件 ID,关联 leaudit_document_files.id';
COMMENT ON COLUMN public.govdoc_runs.run_no IS '同一文档第几次执行';
COMMENT ON COLUMN public.govdoc_runs.trigger_source IS '触发来源:upload/manual/retry/migration';
COMMENT ON COLUMN public.govdoc_runs.trigger_user_id IS '触发人 user_id';
COMMENT ON COLUMN public.govdoc_runs.task_id IS 'Celery 任务 ID';
COMMENT ON COLUMN public.govdoc_runs.status IS 'pending/processing/completed/failed/cancelled';
COMMENT ON COLUMN public.govdoc_runs.phase IS '当前阶段:parsing/executing/reporting';
COMMENT ON COLUMN public.govdoc_runs.engine_version IS '引擎版本号';
COMMENT ON COLUMN public.govdoc_runs.llm_provider IS 'LLM 提供商';
COMMENT ON COLUMN public.govdoc_runs.llm_model IS 'LLM 模型名';
COMMENT ON COLUMN public.govdoc_runs.total_score IS '总分';
COMMENT ON COLUMN public.govdoc_runs.passed_count IS '通过规则数';
COMMENT ON COLUMN public.govdoc_runs.failed_count IS '未通过规则数';
COMMENT ON COLUMN public.govdoc_runs.skipped_count IS '跳过规则数';
COMMENT ON COLUMN public.govdoc_runs.result_status IS '综合结果:pass/fail/partial/error';
COMMENT ON COLUMN public.govdoc_runs.result_summary_json IS '结构化结果摘要 JSON';
COMMENT ON COLUMN public.govdoc_runs.error_message IS '运行失败时错误描述';
COMMENT ON COLUMN public.govdoc_runs.started_at IS '开始执行时间';
COMMENT ON COLUMN public.govdoc_runs.finished_at IS '结束执行时间';
CREATE INDEX IF NOT EXISTS idx_govdoc_runs_document_id ON public.govdoc_runs(document_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_govdoc_runs_status ON public.govdoc_runs(status) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_govdoc_runs_trigger_user_id ON public.govdoc_runs(trigger_user_id);
-- ---------------------------------------------------------------------------
-- 2. govdoc_rule_results —— 单条规则执行结果
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS public.govdoc_rule_results (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
run_id BIGINT NOT NULL,
-- 规则标识
rule_id VARCHAR(128) NOT NULL,
rule_name VARCHAR(256),
severity VARCHAR(32),
category VARCHAR(128),
-- 结果内容
message TEXT,
suggestion TEXT,
actual TEXT,
expected TEXT,
evidence TEXT,
-- 文档定位
paragraph_index INTEGER,
paragraph_text TEXT,
location_path VARCHAR(512),
-- 判定
result VARCHAR(32) NOT NULL DEFAULT 'pass',
score NUMERIC(10, 2),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ DEFAULT NULL
);
COMMENT ON TABLE public.govdoc_rule_results IS '公文规则执行结果明细表';
COMMENT ON COLUMN public.govdoc_rule_results.id IS '自增主键';
COMMENT ON COLUMN public.govdoc_rule_results.run_id IS '关联 govdoc_runs.id';
COMMENT ON COLUMN public.govdoc_rule_results.rule_id IS '规则标识';
COMMENT ON COLUMN public.govdoc_rule_results.rule_name IS '规则名称';
COMMENT ON COLUMN public.govdoc_rule_results.severity IS '严重等级:error/warning/info';
COMMENT ON COLUMN public.govdoc_rule_results.category IS '规则分类';
COMMENT ON COLUMN public.govdoc_rule_results.message IS '结果描述';
COMMENT ON COLUMN public.govdoc_rule_results.suggestion IS '修改建议';
COMMENT ON COLUMN public.govdoc_rule_results.actual IS '实际值';
COMMENT ON COLUMN public.govdoc_rule_results.expected IS '期望值';
COMMENT ON COLUMN public.govdoc_rule_results.evidence IS '证据文本';
COMMENT ON COLUMN public.govdoc_rule_results.paragraph_index IS '段落索引';
COMMENT ON COLUMN public.govdoc_rule_results.paragraph_text IS '段落原文';
COMMENT ON COLUMN public.govdoc_rule_results.location_path IS '文档结构位置路径';
COMMENT ON COLUMN public.govdoc_rule_results.result IS '执行结果:pass/fail/skipped/error';
COMMENT ON COLUMN public.govdoc_rule_results.score IS '本条得分';
CREATE INDEX IF NOT EXISTS idx_govdoc_rule_results_run_id ON public.govdoc_rule_results(run_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_govdoc_rule_results_rule_id ON public.govdoc_rule_results(rule_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_govdoc_rule_results_result ON public.govdoc_rule_results(result) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_govdoc_rule_results_paragraph ON public.govdoc_rule_results(run_id, paragraph_index) WHERE deleted_at IS NULL;
-- ---------------------------------------------------------------------------
-- 3. govdoc_report_artifacts —— 报告产物索引
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS public.govdoc_report_artifacts (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
run_id BIGINT NOT NULL,
artifact_type VARCHAR(64) NOT NULL,
file_name VARCHAR(512) NOT NULL,
file_ext VARCHAR(32),
mime_type VARCHAR(128),
file_size BIGINT,
sha256 VARCHAR(64),
oss_url VARCHAR(2048),
storage_provider VARCHAR(32),
description VARCHAR(512),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ DEFAULT NULL
);
COMMENT ON TABLE public.govdoc_report_artifacts IS '公文审查报告产物索引表';
COMMENT ON COLUMN public.govdoc_report_artifacts.id IS '自增主键';
COMMENT ON COLUMN public.govdoc_report_artifacts.run_id IS '关联 govdoc_runs.id';
COMMENT ON COLUMN public.govdoc_report_artifacts.artifact_type IS '产物类型:html_report/annotated_docx/paragraph_html/json_report/original';
COMMENT ON COLUMN public.govdoc_report_artifacts.file_name IS '文件名';
COMMENT ON COLUMN public.govdoc_report_artifacts.file_ext IS '扩展名';
COMMENT ON COLUMN public.govdoc_report_artifacts.mime_type IS 'MIME 类型';
COMMENT ON COLUMN public.govdoc_report_artifacts.file_size IS '文件大小(字节)';
COMMENT ON COLUMN public.govdoc_report_artifacts.sha256 IS '文件 SHA256';
COMMENT ON COLUMN public.govdoc_report_artifacts.oss_url IS 'OSS 访问地址';
COMMENT ON COLUMN public.govdoc_report_artifacts.storage_provider IS '存储提供商:oss/minio/local';
COMMENT ON COLUMN public.govdoc_report_artifacts.description IS '产物说明';
CREATE INDEX IF NOT EXISTS idx_govdoc_report_artifacts_run_id ON public.govdoc_report_artifacts(run_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_govdoc_report_artifacts_type ON public.govdoc_report_artifacts(run_id, artifact_type) WHERE deleted_at IS NULL;
-- ---------------------------------------------------------------------------
-- 4. leaudit_documents —— 补充 engine_type 字段
-- ---------------------------------------------------------------------------
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'leaudit_documents'
AND column_name = 'engine_type'
) THEN
ALTER TABLE public.leaudit_documents
ADD COLUMN engine_type VARCHAR(32) NOT NULL DEFAULT 'leaudit';
COMMENT ON COLUMN public.leaudit_documents.engine_type IS '引擎类型:leaudit/govdoc/rag';
END IF;
END $$;
-- 为 engine_type 加索引,方便按模块过滤文档列表
CREATE INDEX IF NOT EXISTS idx_leaudit_documents_engine_type ON public.leaudit_documents(engine_type) WHERE deleted_at IS NULL;
COMMIT;
@@ -0,0 +1,140 @@
-- ============================================================================
-- govdoc 模块入口初始化脚本
-- 用途:
-- 1. 为“内部公文 / govdoc”模块补齐首页入口配置
-- 2. 使用幂等写法,重复执行不会产生重复数据
-- 3. 兼容历史库中 entry_modules 时间字段命名差异
--
-- 说明:
-- - 当前模块入口统一收口到 /govdoc/list,与模块路由 seed 保持一致。
-- - 若后续前端改成其他入口页,请同步更新本脚本中的 v_target_path。
-- - 页面访问权限与左侧菜单路由仍依赖 sys_routes / role_route
-- 这部分建议由配套脚本 seed_govdoc_routes.sql 单独维护。
-- ============================================================================
BEGIN;
DO $$
DECLARE
v_name text := '内部公文';
v_description text := '内部公文处理与格式审查入口';
v_target_path text := '/govdoc/list';
v_icon_path text := 'documents/mz/static/img/entry_module_3.png';
v_sort_order integer := 30;
v_areas jsonb := '[
{"area":"梅州","enabled":true,"sort_order":1},
{"area":"云浮","enabled":true,"sort_order":2},
{"area":"揭阳","enabled":true,"sort_order":3},
{"area":"潮州","enabled":true,"sort_order":4},
{"area":"省局","enabled":true,"sort_order":5}
]'::jsonb;
has_created_at boolean;
has_updated_at boolean;
has_create_time boolean;
has_update_time boolean;
has_deleted_at boolean;
sql_stmt text;
BEGIN
SELECT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'leaudit_entry_modules'
AND column_name = 'created_at'
),
EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'leaudit_entry_modules'
AND column_name = 'updated_at'
),
EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'leaudit_entry_modules'
AND column_name = 'create_time'
),
EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'leaudit_entry_modules'
AND column_name = 'update_time'
),
EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'leaudit_entry_modules'
AND column_name = 'deleted_at'
)
INTO has_created_at, has_updated_at, has_create_time, has_update_time, has_deleted_at;
IF NOT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name = 'leaudit_entry_modules'
) THEN
RAISE EXCEPTION '表 public.leaudit_entry_modules 不存在,请先执行入口模块建表脚本';
END IF;
sql_stmt := 'INSERT INTO public.leaudit_entry_modules (' ||
'name, description, path, icon_path, areas, sort_order, is_enabled';
IF has_created_at THEN
sql_stmt := sql_stmt || ', created_at';
ELSIF has_create_time THEN
sql_stmt := sql_stmt || ', create_time';
END IF;
IF has_updated_at THEN
sql_stmt := sql_stmt || ', updated_at';
ELSIF has_update_time THEN
sql_stmt := sql_stmt || ', update_time';
END IF;
IF has_deleted_at THEN
sql_stmt := sql_stmt || ', deleted_at';
END IF;
sql_stmt := sql_stmt || ') VALUES (' ||
'$1, $2, $3, $4, $5, $6, TRUE';
IF has_created_at OR has_create_time THEN
sql_stmt := sql_stmt || ', NOW()';
END IF;
IF has_updated_at OR has_update_time THEN
sql_stmt := sql_stmt || ', NOW()';
END IF;
IF has_deleted_at THEN
sql_stmt := sql_stmt || ', NULL';
END IF;
sql_stmt := sql_stmt || ') ON CONFLICT (name) DO UPDATE SET ' ||
'description = EXCLUDED.description, ' ||
'path = EXCLUDED.path, ' ||
'icon_path = EXCLUDED.icon_path, ' ||
'areas = EXCLUDED.areas, ' ||
'sort_order = EXCLUDED.sort_order, ' ||
'is_enabled = EXCLUDED.is_enabled';
IF has_updated_at THEN
sql_stmt := sql_stmt || ', updated_at = NOW()';
ELSIF has_update_time THEN
sql_stmt := sql_stmt || ', update_time = NOW()';
END IF;
IF has_deleted_at THEN
sql_stmt := sql_stmt || ', deleted_at = NULL';
END IF;
EXECUTE sql_stmt
USING v_name, v_description, v_target_path, v_icon_path, v_areas, v_sort_order;
END $$;
COMMIT;
@@ -0,0 +1,138 @@
-- ============================================================================
-- govdoc 模块权限种子
-- 用途:
-- 1. 为 govdoc 模块插入权限点到 permissions 表
-- 2. 为默认角色分发角色-权限映射到 role_permissions 表
-- 3. 幂等执行,重复跑会更新 description / display_name 等可刷新字段
--
-- 权限键格式:govdoc:{resource}:{action}
-- 角色分发遵循《内部公文模块接口与权限设计》§5
-- ============================================================================
BEGIN;
-- ---------------------------------------------------------------------------
-- 1. 权限点定义
-- ---------------------------------------------------------------------------
INSERT INTO permissions (
permission_key, module, resource, action, description, display_name,
permission_type, is_system, metadata, created_at, updated_at,
sort_order, route_id, api_path, api_method
)
VALUES
-- 模块权限
('govdoc:module:read', 'govdoc', 'module', 'read', '查看内部公文处理模块菜单', '查看公文模块', 'MENU', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 10, NULL, '/govdoc', 'GET'),
-- 文档权限
('govdoc:document:create', 'govdoc', 'document', 'create', '上传公文文档', '上传公文', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 20, NULL, '/api/govdoc/documents', 'POST'),
('govdoc:document:read', 'govdoc', 'document', 'read', '查看公文文档列表与详情', '查看公文', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 21, NULL, '/api/govdoc/documents', 'GET'),
('govdoc:document:update', 'govdoc', 'document', 'update', '更新公文文档基础信息', '编辑公文', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 22, NULL, '/api/govdoc/documents/{DocumentId}', 'PATCH'),
('govdoc:document:delete', 'govdoc', 'document', 'delete', '删除公文文档', '删除公文', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 23, NULL, '/api/govdoc/documents/{DocumentId}', 'DELETE'),
-- 审查运行权限
('govdoc:run:create', 'govdoc', 'run', 'create', '发起公文格式审查', '发起审查', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 30, NULL, '/api/govdoc/runs', 'POST'),
('govdoc:run:read', 'govdoc', 'run', 'read', '查看审查运行状态', '查看审查状态', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 31, NULL, '/api/govdoc/runs/{RunId}', 'GET'),
('govdoc:run:retry', 'govdoc', 'run', 'retry', '失败后重试审查', '重试审查', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 32, NULL, '/api/govdoc/runs/{RunId}/retry', 'POST'),
-- 报告与结果权限
('govdoc:report:read', 'govdoc', 'report', 'read', '下载审查报告(HTML/DOCX/原文)', '下载报告', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 40, NULL, '/api/govdoc/runs/{RunId}/report', 'GET'),
('govdoc:result:read', 'govdoc', 'result', 'read', '查看审查结果(findings/entities/summary', '查看审查结果', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 41, NULL, '/api/govdoc/runs/{RunId}/result', 'GET'),
-- 规则权限
('govdoc:rule:read', 'govdoc', 'rule', 'read', '查看公文规则清单与详情', '查看规则', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 50, NULL, '/api/govdoc/rules', 'GET'),
('govdoc:rule:manage', 'govdoc', 'rule', 'manage', '发布、更新、切换规则版本', '管理规则', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 51, NULL, '/api/govdoc/rule-versions', 'POST'),
-- 配置权限(可选)
('govdoc:settings:read', 'govdoc', 'settings', 'read', '查看公文模块配置', '查看设置', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 60, NULL, '/api/govdoc/settings', 'GET'),
('govdoc:settings:update', 'govdoc', 'settings', 'update', '修改公文模块配置', '修改设置', 'API', TRUE, '{"group":"govdoc"}'::jsonb, NOW(), NOW(), 61, NULL, '/api/govdoc/settings', 'PATCH')
ON CONFLICT (permission_key) DO UPDATE SET
module = EXCLUDED.module,
resource = EXCLUDED.resource,
action = EXCLUDED.action,
description = EXCLUDED.description,
display_name = EXCLUDED.display_name,
api_path = EXCLUDED.api_path,
api_method = EXCLUDED.api_method,
updated_at = NOW();
-- ---------------------------------------------------------------------------
-- 2. 角色权限分发
-- ---------------------------------------------------------------------------
WITH role_map AS (
SELECT id, role_key
FROM roles
WHERE role_key IN ('super_admin', 'provincial_admin', 'admin', 'common')
),
perm_map AS (
SELECT id, permission_key
FROM permissions
WHERE permission_key LIKE 'govdoc:%'
),
seed(role_key, permission_key, grant_type, data_scope) AS (
VALUES
-- super_admin: 全部权限
('super_admin', 'govdoc:module:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:document:create', 'GRANT', 'ALL'),
('super_admin', 'govdoc:document:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:document:update', 'GRANT', 'ALL'),
('super_admin', 'govdoc:document:delete', 'GRANT', 'ALL'),
('super_admin', 'govdoc:run:create', 'GRANT', 'ALL'),
('super_admin', 'govdoc:run:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:run:retry', 'GRANT', 'ALL'),
('super_admin', 'govdoc:report:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:result:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:rule:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:rule:manage', 'GRANT', 'ALL'),
('super_admin', 'govdoc:settings:read', 'GRANT', 'ALL'),
('super_admin', 'govdoc:settings:update', 'GRANT', 'ALL'),
-- provincial_admin: 全部业务权限
('provincial_admin', 'govdoc:module:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:document:create', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:document:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:document:update', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:document:delete', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:run:create', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:run:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:run:retry', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:report:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:result:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:rule:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:rule:manage', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:settings:read', 'GRANT', 'ALL'),
('provincial_admin', 'govdoc:settings:update', 'GRANT', 'ALL'),
-- admin: 模块读写 + 规则查看,不含规则管理与配置修改
('admin', 'govdoc:module:read', 'GRANT', 'REGION'),
('admin', 'govdoc:document:create', 'GRANT', 'REGION'),
('admin', 'govdoc:document:read', 'GRANT', 'REGION'),
('admin', 'govdoc:document:update', 'GRANT', 'REGION'),
('admin', 'govdoc:document:delete', 'GRANT', 'REGION'),
('admin', 'govdoc:run:create', 'GRANT', 'REGION'),
('admin', 'govdoc:run:read', 'GRANT', 'REGION'),
('admin', 'govdoc:run:retry', 'GRANT', 'REGION'),
('admin', 'govdoc:report:read', 'GRANT', 'REGION'),
('admin', 'govdoc:result:read', 'GRANT', 'REGION'),
('admin', 'govdoc:rule:read', 'GRANT', 'REGION'),
-- common: 模块查看 + 文档上传/查看 + 审查发起/查看 + 报告/结果查看 + 规则查看
('common', 'govdoc:module:read', 'GRANT', 'OWN'),
('common', 'govdoc:document:create', 'GRANT', 'OWN'),
('common', 'govdoc:document:read', 'GRANT', 'OWN'),
('common', 'govdoc:run:create', 'GRANT', 'OWN'),
('common', 'govdoc:run:read', 'GRANT', 'OWN'),
('common', 'govdoc:report:read', 'GRANT', 'OWN'),
('common', 'govdoc:result:read', 'GRANT', 'OWN'),
('common', 'govdoc:rule:read', 'GRANT', 'OWN')
)
INSERT INTO role_permissions (role_id, permission_id, grant_type, data_scope, created_at, updated_at)
SELECT rm.id, pm.id, seed.grant_type, seed.data_scope, NOW(), NOW()
FROM seed
JOIN role_map rm ON rm.role_key = seed.role_key
JOIN perm_map pm ON pm.permission_key = seed.permission_key
ON CONFLICT (role_id, permission_id) DO UPDATE SET
grant_type = EXCLUDED.grant_type,
data_scope = EXCLUDED.data_scope,
updated_at = NOW();
COMMIT;
+276
View File
@@ -0,0 +1,276 @@
BEGIN;
-- ============================================================================
-- govdoc 模块前端路由 / 菜单初始化草案
-- 目标:
-- 1. 注册 /govdoc 模块根路由与常用子路由
-- 2. 尽量兼容当前 sys_routes 的父子层级展示方式
-- 3. 为默认角色补齐 role_route 菜单可见性
-- 说明:
-- - 采用 route_path / route_name / route_title 这一套当前仓库主流字段风格
-- - 明细页 / 详情页默认 hidden,避免菜单树出现无意义叶子节点
-- - 幂等执行:重复跑会更新标题、父子关系、显示状态
-- ============================================================================
WITH upsert_root AS (
INSERT INTO sys_routes (
route_path,
route_name,
component,
parent_id,
route_title,
icon,
sort_order,
is_hidden,
is_cache,
meta,
status,
created_at,
updated_at,
deleted_at
)
VALUES (
'/govdoc',
'govdoc',
'govdoc',
NULL,
'内部公文处理',
'ri-file-paper-2-line',
80,
FALSE,
TRUE,
'{"group":"govdoc","module":"govdoc"}'::jsonb,
0,
NOW(),
NOW(),
NULL
)
ON CONFLICT (route_path) WHERE deleted_at IS NULL
DO UPDATE SET
route_name = EXCLUDED.route_name,
component = EXCLUDED.component,
route_title = EXCLUDED.route_title,
icon = EXCLUDED.icon,
sort_order = EXCLUDED.sort_order,
is_hidden = EXCLUDED.is_hidden,
is_cache = EXCLUDED.is_cache,
meta = EXCLUDED.meta,
status = 0,
updated_at = NOW(),
deleted_at = NULL
RETURNING id
),
root_route AS (
SELECT id FROM upsert_root
UNION ALL
SELECT id
FROM sys_routes
WHERE route_path = '/govdoc'
AND deleted_at IS NULL
LIMIT 1
)
INSERT INTO sys_routes (
route_path,
route_name,
component,
parent_id,
route_title,
icon,
sort_order,
is_hidden,
is_cache,
meta,
status,
created_at,
updated_at,
deleted_at
)
VALUES
(
'/govdoc/upload',
'govdoc.upload',
'govdoc.upload',
(SELECT id FROM root_route),
'上传公文',
'ri-upload-cloud-2-line',
1,
FALSE,
TRUE,
'{"group":"govdoc","module":"govdoc","page":"upload"}'::jsonb,
0,
NOW(),
NOW(),
NULL
),
(
'/govdoc/list',
'govdoc.list',
'govdoc.list',
(SELECT id FROM root_route),
'公文列表',
'ri-file-list-3-line',
2,
FALSE,
TRUE,
'{"group":"govdoc","module":"govdoc","page":"list"}'::jsonb,
0,
NOW(),
NOW(),
NULL
),
(
'/govdoc/detail',
'govdoc.detail',
'govdoc.detail',
(SELECT id FROM root_route),
'公文详情',
'ri-file-search-line',
3,
TRUE,
TRUE,
'{"group":"govdoc","module":"govdoc","page":"detail"}'::jsonb,
0,
NOW(),
NOW(),
NULL
),
(
'/govdoc/rules',
'govdoc.rules',
'govdoc.rules',
(SELECT id FROM root_route),
'规则配置',
'ri-scales-3-line',
4,
FALSE,
TRUE,
'{"group":"govdoc","module":"govdoc","page":"rules"}'::jsonb,
0,
NOW(),
NOW(),
NULL
),
(
'/govdoc/settings',
'govdoc.settings',
'govdoc.settings',
(SELECT id FROM root_route),
'模块配置',
'ri-settings-3-line',
5,
FALSE,
TRUE,
'{"group":"govdoc","module":"govdoc","page":"settings"}'::jsonb,
0,
NOW(),
NOW(),
NULL
)
ON CONFLICT (route_path) WHERE deleted_at IS NULL
DO UPDATE SET
route_name = EXCLUDED.route_name,
component = EXCLUDED.component,
parent_id = EXCLUDED.parent_id,
route_title = EXCLUDED.route_title,
icon = EXCLUDED.icon,
sort_order = EXCLUDED.sort_order,
is_hidden = EXCLUDED.is_hidden,
is_cache = EXCLUDED.is_cache,
meta = EXCLUDED.meta,
status = 0,
updated_at = NOW(),
deleted_at = NULL;
-- 修正旧环境中可能已存在但未正确挂到 /govdoc 下的子路由。
UPDATE sys_routes AS child
SET
parent_id = root.id,
route_title = CASE
WHEN child.route_path = '/govdoc/upload' THEN '上传公文'
WHEN child.route_path = '/govdoc/list' THEN '公文列表'
WHEN child.route_path = '/govdoc/detail' THEN '公文详情'
WHEN child.route_path = '/govdoc/rules' THEN '规则配置'
WHEN child.route_path = '/govdoc/settings' THEN '模块配置'
ELSE child.route_title
END,
is_hidden = CASE
WHEN child.route_path = '/govdoc/detail' THEN TRUE
ELSE child.is_hidden
END,
updated_at = NOW()
FROM sys_routes root
WHERE child.deleted_at IS NULL
AND root.deleted_at IS NULL
AND root.route_path = '/govdoc'
AND child.route_path IN (
'/govdoc/upload',
'/govdoc/list',
'/govdoc/detail',
'/govdoc/rules',
'/govdoc/settings'
);
-- 根路由标题兜底,避免历史环境残留旧文案。
UPDATE sys_routes
SET route_title = '内部公文处理',
updated_at = NOW()
WHERE deleted_at IS NULL
AND route_path = '/govdoc';
WITH role_map AS (
SELECT id, role_key
FROM roles
WHERE role_key IN ('super_admin', 'provincial_admin', 'admin', 'common')
),
route_map AS (
SELECT id, route_path
FROM sys_routes
WHERE deleted_at IS NULL
AND route_path IN (
'/govdoc',
'/govdoc/upload',
'/govdoc/list',
'/govdoc/detail',
'/govdoc/rules',
'/govdoc/settings'
)
),
seed(role_key, route_path, permission, status) AS (
VALUES
('super_admin', '/govdoc', 'RW', 1),
('super_admin', '/govdoc/upload', 'RW', 1),
('super_admin', '/govdoc/list', 'RW', 1),
('super_admin', '/govdoc/detail', 'RW', 1),
('super_admin', '/govdoc/rules', 'RW', 1),
('super_admin', '/govdoc/settings', 'RW', 1),
('provincial_admin', '/govdoc', 'RW', 1),
('provincial_admin', '/govdoc/upload', 'RW', 1),
('provincial_admin', '/govdoc/list', 'RW', 1),
('provincial_admin', '/govdoc/detail', 'RW', 1),
('provincial_admin', '/govdoc/rules', 'RW', 1),
('provincial_admin', '/govdoc/settings', 'RW', 1),
('admin', '/govdoc', 'RW', 1),
('admin', '/govdoc/upload', 'RW', 1),
('admin', '/govdoc/list', 'RW', 1),
('admin', '/govdoc/detail', 'RW', 1),
('admin', '/govdoc/rules', 'R', 1),
('common', '/govdoc', 'R', 1),
('common', '/govdoc/upload', 'R', 1),
('common', '/govdoc/list', 'R', 1),
('common', '/govdoc/detail', 'R', 1),
('common', '/govdoc/rules', 'R', 1)
)
INSERT INTO role_route (role_id, route_id, permission, status, created_at, updated_at)
SELECT rm.id, tm.id, s.permission, s.status, NOW(), NOW()
FROM seed s
JOIN role_map rm ON rm.role_key = s.role_key
JOIN route_map tm ON tm.route_path = s.route_path
ON CONFLICT (role_id, route_id) DO UPDATE SET
permission = EXCLUDED.permission,
status = EXCLUDED.status,
updated_at = NOW();
COMMIT;