Files
leaudit-platform-backend/docs/系统使用统计/系统使用统计表设计.md
T
2026-05-09 20:04:08 +08:00

14 KiB

系统使用统计表设计

1. 设计目标

基于《系统使用统计最终需求》和《系统使用统计接口设计》,设计一套可落地的数据库方案,用于支持以下统计场景:

  • 登录统计
  • 文档上传统计
  • 文档评查统计
  • 按用户、部门、地区、文档大类、文档类型、入口模块进行动态汇总
  • 支持时间范围查询、排行榜、趋势图与明细导出

本次设计遵循两个原则:

  • 能复用现有业务表的地方尽量复用
  • 只为现有表无法满足的统计能力补最小新增表结构

2. 总体设计思路

统计数据来源分为两类:

  • 现有业务事实表
  • 新增统计事件表

其中:

  • 上传、评查相关统计,尽量直接复用现有业务表
  • 登录统计由于当前没有稳定入库明细,需要新增登录事件表
  • 为了提升用户管理页的查询效率,建议给 sso_users 增加最近登录时间字段

3. 现有可复用表

3.1 用户表 sso_users

用途:

  • 用户基础信息来源
  • 部门、地区、组织维度来源
  • 最近登录时间展示

当前已使用字段:

  • id
  • sub
  • username
  • nick_name
  • phone_number
  • email
  • ou_id
  • ou_name
  • area
  • tenant_name
  • dep_name
  • dep_short_name
  • status
  • deleted_at

代码参考:

  • fastapi_modules/fastapi_leaudit/services/impl/authServiceImpl.py:36
  • fastapi_modules/fastapi_leaudit/services/impl/rbacAdminServiceImpl.py:374

3.2 文档主表 leaudit_documents

用途:

  • 文档主记录
  • 文档类型、地区、版本、处理状态来源

主要字段:

  • id
  • type_id
  • group_id
  • region
  • processing_status
  • current_run_id
  • version_group_key
  • version_no
  • is_latest_version
  • created_at
  • updated_at
  • deleted_at

代码参考:

  • fastapi_modules/fastapi_leaudit/models/leauditDocument.py:19

3.3 文档文件表 leaudit_document_files

用途:

  • 上传主文件统计
  • 上传附件统计
  • 上传人、上传时间明细来源

主要字段:

  • id
  • document_id
  • file_role
  • file_name
  • file_ext
  • mime_type
  • file_size
  • oss_url
  • is_active
  • created_by
  • created_at

口径建议:

  • 主文件上传:file_role = 'primary'
  • 附件上传:file_role = 'attachment'

代码参考:

  • fastapi_modules/fastapi_leaudit/models/leauditDocumentFile.py:15
  • fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py:224
  • fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py:889

3.4 评查运行表 leaudit_audit_runs

用途:

  • 评查发起次数
  • 评查完成次数
  • 评查失败次数
  • 评查时间趋势
  • 评查状态与结果明细

主要字段:

  • id
  • document_id
  • document_file_id
  • run_no
  • trigger_source
  • trigger_user_id
  • status
  • phase
  • rule_set_id
  • rule_version_id
  • result_status
  • total_score
  • passed_count
  • failed_count
  • skipped_count
  • started_at
  • finished_at
  • created_at
  • updated_at

现状说明:

  • 表结构已预留 trigger_user_id
  • 但当前代码创建 run 时尚未写入该字段
  • 统计功能上线前建议补齐该字段写入逻辑

代码参考:

  • fastapi_modules/fastapi_leaudit/models/leauditAuditRun.py:16
  • fastapi_modules/fastapi_leaudit/services/impl/auditServiceImpl.py:203

3.5 评查指标表 leaudit_run_metrics

用途:

  • 评查页数
  • 评查耗时
  • 规则数量等运行指标

主要字段:

  • run_id
  • ocr_seconds
  • normalize_seconds
  • extract_seconds
  • evaluate_seconds
  • rescue_seconds
  • total_seconds
  • page_count
  • sub_document_count
  • field_count
  • rule_count
  • llm_call_count
  • vlm_call_count
  • rescue_rule_count
  • artifact_count

代码参考:

  • fastapi_modules/fastapi_leaudit/leaudit_bridge/storage_adapter.py:260

3.6 文档类型表 leaudit_document_types

用途:

  • 文档类型维度统计
  • 入口模块归属

建议依赖字段:

  • id
  • code
  • name
  • entry_module_id
  • is_enabled
  • sort_order

3.7 入口模块表 leaudit_entry_modules

用途:

  • 入口模块维度统计
  • 首页/业务模块使用分析

建议依赖字段:

  • id
  • name
  • path
  • sort_order
  • is_enabled

4. 建议调整的现有表

4.1 为 sso_users 增加最近登录时间字段

建议新增字段

ALTER TABLE sso_users
ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ NULL;

字段说明

字段 类型 允许空 说明
last_login_at TIMESTAMPTZ 最近一次登录成功时间

用途

  • 用户列表展示“最近登录时间”
  • 后台快速判断用户活跃情况
  • 避免每次都扫登录事件表取最大时间

更新规则

  • 登录成功:更新 last_login_at
  • 登录失败:不更新

5. 新增表设计

5.1 登录事件表 usage_login_events

设计目的

当前系统缺少结构化登录明细表,无法稳定支撑:

  • 登录次数
  • 登录用户数
  • 按部门登录统计
  • 按地区登录统计
  • 登录趋势图
  • 最近登录明细导出

因此建议新增登录事件表。

建表建议

CREATE TABLE IF NOT EXISTS usage_login_events (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT NULL,
    sub VARCHAR(128) NULL,
    username_snapshot VARCHAR(128) NULL,
    nick_name_snapshot VARCHAR(128) NULL,
    department_name_snapshot VARCHAR(255) NULL,
    ou_id_snapshot VARCHAR(128) NULL,
    ou_name_snapshot VARCHAR(255) NULL,
    area_snapshot VARCHAR(64) NULL,
    login_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    login_result VARCHAR(16) NOT NULL,
    login_type VARCHAR(32) NOT NULL,
    ip_address VARCHAR(64) NULL,
    user_agent VARCHAR(1024) NULL,
    client_type VARCHAR(32) NULL,
    token_jti VARCHAR(128) NULL,
    failure_reason VARCHAR(255) NULL,
    extra JSONB NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

字段说明

字段 类型 说明
id BIGSERIAL 主键
user_id BIGINT 用户 ID,失败登录时可为空
sub VARCHAR(128) 登录标识,兼容账号字段
username_snapshot VARCHAR(128) 登录时用户名快照
nick_name_snapshot VARCHAR(128) 登录时姓名快照
department_name_snapshot VARCHAR(255) 登录时部门快照
ou_id_snapshot VARCHAR(128) 登录时组织 ID 快照
ou_name_snapshot VARCHAR(255) 登录时组织名称快照
area_snapshot VARCHAR(64) 登录时地区快照
login_time TIMESTAMPTZ 登录时间
login_result VARCHAR(16) success / failed
login_type VARCHAR(32) password / oauth
ip_address VARCHAR(64) 登录来源 IP
user_agent VARCHAR(1024) 浏览器/终端标识
client_type VARCHAR(32) pc / mobile / other
token_jti VARCHAR(128) 成功登录后的 token jti,可选
failure_reason VARCHAR(255) 失败原因
extra JSONB 扩展字段
created_at TIMESTAMPTZ 记录创建时间

索引建议

CREATE INDEX IF NOT EXISTS idx_usage_login_events_login_time
ON usage_login_events(login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_user_id
ON usage_login_events(user_id, login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_department
ON usage_login_events(department_name_snapshot, login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_area
ON usage_login_events(area_snapshot, login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_result
ON usage_login_events(login_result, login_time DESC);

统计口径建议

  • 登录次数:仅统计 login_result = 'success'
  • 登录失败次数:统计 login_result = 'failed'
  • 最近登录时间:按用户取最后一次成功登录时间

5.2 文档大类映射表 usage_document_category_mappings(可选但强烈建议)

设计目的

需求中明确要求:

  • 不写死“合同类”“案卷类”
  • 后续新增文档大类、文档类型后可自动纳入统计

如果当前系统已经有稳定的一级文档大类实体,可直接复用; 如果没有一张适合统计使用的稳定“大类表”,建议新增一张统计映射表。

建表建议

CREATE TABLE IF NOT EXISTS usage_document_category_mappings (
    id BIGSERIAL PRIMARY KEY,
    category_code VARCHAR(64) NOT NULL,
    category_name VARCHAR(128) NOT NULL,
    document_type_id BIGINT NOT NULL,
    entry_module_id BIGINT NULL,
    is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
    sort_order INTEGER NOT NULL DEFAULT 0,
    created_by BIGINT NULL,
    updated_by BIGINT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ NULL
);

字段说明

字段 类型 说明
id BIGSERIAL 主键
category_code VARCHAR(64) 统计大类编码
category_name VARCHAR(128) 统计大类名称
document_type_id BIGINT 关联文档类型 ID
entry_module_id BIGINT 可选,关联入口模块
is_enabled BOOLEAN 是否启用
sort_order INTEGER 排序
created_by BIGINT 创建人
updated_by BIGINT 更新人
created_at TIMESTAMPTZ 创建时间
updated_at TIMESTAMPTZ 更新时间
deleted_at TIMESTAMPTZ 软删除时间

约束与索引建议

CREATE UNIQUE INDEX IF NOT EXISTS uq_usage_document_category_type
ON usage_document_category_mappings(document_type_id)
WHERE deleted_at IS NULL;

CREATE INDEX IF NOT EXISTS idx_usage_document_category_code
ON usage_document_category_mappings(category_code, is_enabled);

CREATE INDEX IF NOT EXISTS idx_usage_document_category_module
ON usage_document_category_mappings(entry_module_id, is_enabled);

说明

  • 一种文档类型只归属一个统计大类
  • 若后续系统已有成熟的一级文档大类表,可取消本表,直接复用业务表

6. 查询口径与表关系建议

6.1 登录统计

来源:

  • usage_login_events
  • sso_users.last_login_at

用途:

  • 登录次数
  • 登录用户数
  • 最近登录时间
  • 按部门、地区统计登录情况

6.2 上传统计

来源:

  • leaudit_document_files
  • leaudit_documents
  • sso_users
  • leaudit_document_types
  • leaudit_entry_modules
  • usage_document_category_mappings(若启用)

口径:

  • 主文件上传:leaudit_document_files.file_role = 'primary'
  • 附件上传:leaudit_document_files.file_role = 'attachment'

6.3 评查统计

来源:

  • leaudit_audit_runs
  • leaudit_documents
  • leaudit_document_types
  • leaudit_entry_modules
  • usage_document_category_mappings(若启用)

口径:

  • 发起评查次数:leaudit_audit_runs 记录数
  • 完成评查次数:status = 'completed'
  • 失败评查次数:status = 'failed'

6.4 地区统计

支持两种口径:

  • 用户地区口径
    • 登录:取 usage_login_events.area_snapshot
    • 上传:取上传人 sso_users.area
    • 评查:优先取触发人地区
  • 文档地区口径
    • 上传:取 leaudit_documents.region
    • 评查:取 leaudit_documents.region

7. 一期是否需要聚合表

7.1 一期建议

一期先不新增日汇总聚合表,先使用:

  • 明细事实表 + SQL 聚合

原因:

  • 功能验证阶段,需求还可能变
  • 统计范围目前只有登录、上传、评查三类,复杂度可控
  • 先把口径跑通,比过早做聚合更重要

7.2 二期建议

若后续数据量变大,再补以下日汇总表:

  • usage_user_daily_stats
  • usage_department_daily_stats
  • usage_area_daily_stats
  • usage_document_category_daily_stats
  • usage_entry_module_daily_stats

8. 配套代码改造建议

8.1 登录成功时

需要做两件事:

  • 写入 usage_login_events
  • 更新 sso_users.last_login_at

8.2 登录失败时

建议:

  • 写入 usage_login_events
  • 不更新 sso_users.last_login_at

8.3 触发评查时

建议补齐:

  • leaudit_audit_runs.trigger_user_id

当前表已存在该字段,但创建 run 时未写入,需要补逻辑。

9. 推荐 SQL 变更清单

9.1 为 sso_users 增加最近登录时间

ALTER TABLE sso_users
ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ NULL;

9.2 新增登录事件表

CREATE TABLE IF NOT EXISTS usage_login_events (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT NULL,
    sub VARCHAR(128) NULL,
    username_snapshot VARCHAR(128) NULL,
    nick_name_snapshot VARCHAR(128) NULL,
    department_name_snapshot VARCHAR(255) NULL,
    ou_id_snapshot VARCHAR(128) NULL,
    ou_name_snapshot VARCHAR(255) NULL,
    area_snapshot VARCHAR(64) NULL,
    login_time TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    login_result VARCHAR(16) NOT NULL,
    login_type VARCHAR(32) NOT NULL,
    ip_address VARCHAR(64) NULL,
    user_agent VARCHAR(1024) NULL,
    client_type VARCHAR(32) NULL,
    token_jti VARCHAR(128) NULL,
    failure_reason VARCHAR(255) NULL,
    extra JSONB NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

9.3 新增登录事件索引

CREATE INDEX IF NOT EXISTS idx_usage_login_events_login_time
ON usage_login_events(login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_user_id
ON usage_login_events(user_id, login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_department
ON usage_login_events(department_name_snapshot, login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_area
ON usage_login_events(area_snapshot, login_time DESC);

CREATE INDEX IF NOT EXISTS idx_usage_login_events_result
ON usage_login_events(login_result, login_time DESC);

9.4 新增统计大类映射表(可选)

CREATE TABLE IF NOT EXISTS usage_document_category_mappings (
    id BIGSERIAL PRIMARY KEY,
    category_code VARCHAR(64) NOT NULL,
    category_name VARCHAR(128) NOT NULL,
    document_type_id BIGINT NOT NULL,
    entry_module_id BIGINT NULL,
    is_enabled BOOLEAN NOT NULL DEFAULT TRUE,
    sort_order INTEGER NOT NULL DEFAULT 0,
    created_by BIGINT NULL,
    updated_by BIGINT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    deleted_at TIMESTAMPTZ NULL
);

10. 一期最终建议

一期最小可落地表设计建议如下:

必须做:

  • sso_users.last_login_at
  • usage_login_events
  • 补齐 leaudit_audit_runs.trigger_user_id 写入逻辑

建议做:

  • usage_document_category_mappings

可后置:

  • 各类日汇总聚合表
  • 复杂会话表
  • 全量行为审计表