# 数据库表结构 投研平台后端当前使用 SQLite(`data/ir.db`)。表结构与种子数据由 **`sql/init.sql`** 一次性脚本初始化(应用代码不再做建表/灌种子): ``` sqlite3 data/ir.db < sql/init.sql ``` 脚本中所有 DDL/DML 使用 `IF NOT EXISTS` / `INSERT OR IGNORE`,可重复执行。 --- ## 1. demo_user — 演示用户表 > 供数据源演示接口 `/api/datasource/*` 使用。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY AUTOINCREMENT | 主键,自增 | | name | TEXT | NOT NULL | 姓名 | | created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | --- ## 2. sys_user — 系统用户表 > 默认管理员 `admin / admin123` 由 `sql/init.sql` 灌入(BCrypt 哈希)。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY AUTOINCREMENT | 主键,自增 | | username | TEXT | NOT NULL UNIQUE | 登录名(唯一) | | password | TEXT | NOT NULL | BCrypt 加密后的密码 | | nickname | TEXT | — | 昵称 | | enabled | INTEGER | NOT NULL DEFAULT 1 | 是否启用(0=禁用,1=启用) | | created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | --- ## 3. sys_role — 角色表 > 内置种子角色:`ADMIN`(超级管理员)、`USER`(普通用户)。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY AUTOINCREMENT | 主键,自增 | | code | TEXT | NOT NULL UNIQUE | 角色编码(唯一) | | name | TEXT | NOT NULL | 角色名称 | | description | TEXT | — | 描述 | | created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | --- ## 4. sys_permission — 权限表 > 内置种子权限:`user:list/create/update/delete`、`role:list/create/update/delete/assign`、`permission:list/create/delete`、`data:query/write`。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY AUTOINCREMENT | 主键,自增 | | code | TEXT | NOT NULL UNIQUE | 权限编码(唯一) | | name | TEXT | NOT NULL | 权限名称 | | description | TEXT | — | 描述 | | created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | --- ## 5. sys_user_role — 用户-角色关联表 > 多对多,复合主键;删除用户/角色时对应关联一并清理。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | user_id | INTEGER | NOT NULL,PRIMARY KEY(user_id, role_id) | 用户 ID → `sys_user.id` | | role_id | INTEGER | NOT NULL,PRIMARY KEY(user_id, role_id) | 角色 ID → `sys_role.id` | --- ## 6. sys_role_permission — 角色-权限关联表 > 多对多,复合主键;删除角色/权限时对应关联一并清理。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | role_id | INTEGER | NOT NULL,PRIMARY KEY(role_id, permission_id) | 角色 ID → `sys_role.id` | | permission_id | INTEGER | NOT NULL,PRIMARY KEY(role_id, permission_id) | 权限 ID → `sys_permission.id` | --- ## 7. sys_menu — 菜单表(独立菜单权限体系) > 菜单与接口权限(`sys_permission`)**完全解耦**:菜单自身是一棵树,通过 `sys_role_menu` 直接授予角色,不读取任何接口权限编码。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY AUTOINCREMENT | 主键,自增 | | parent_id | INTEGER | — | 父菜单 id → `sys_menu.id`;NULL = 顶级 | | name | TEXT | NOT NULL | 菜单名称 | | type | TEXT | NOT NULL DEFAULT 'menu' | 类型:`dir`=目录 / `menu`=菜单 | | route | TEXT | — | 前端路由 path | | component | TEXT | — | 前端组件路径 | | icon | TEXT | — | 菜单图标 | | sort | INTEGER | DEFAULT 0 | 排序号(升序) | | visible | INTEGER | DEFAULT 1 | 是否可见(0=隐藏,不参与用户菜单下发) | | status | INTEGER | DEFAULT 1 | 是否启用(0=停用) | | created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | ## 8. sys_role_menu — 角色-菜单关联表 > 多对多,复合主键;`RbacService#deleteRole` 与 `MenuService#deleteMenu` 会同步清理关联。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | role_id | INTEGER | NOT NULL,PRIMARY KEY(role_id, menu_id) | 角色 ID → `sys_role.id` | | menu_id | INTEGER | NOT NULL,PRIMARY KEY(role_id, menu_id) | 菜单 ID → `sys_menu.id` | --- ## 9. indicator — 指标元数据表 > 投研指标(基本面、政策面等)的元数据;`id` 由脚本固定写死,便于 API 按 id 路由。 > 一行代表一个指标(例如"中国:GDP:现价:当季同比"),其时序值存于 `indicator_value`。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY | 指标主键(由种子数据写死,不自增) | | category | TEXT | NOT NULL | 一级分类(如 GDP / 投资 / 出口 / 消费 / 通胀 / 供给 / 景气度) | | subcategory | TEXT | — | 二级分类 | | name | TEXT | NOT NULL | 指标全称 | | region | TEXT | — | 区域(中国 / 美国 …) | | frequency | TEXT | NOT NULL | 频度(`日`/`周`/`月`/`季`/`年` …) | | unit | TEXT | — | 单位(%、亿美元、点 …) | | wind_code | TEXT | UNIQUE | Wind 编码 | | source | TEXT | — | 数据来源 | | data_start | TEXT | — | 数据起始期(`YYYY-MM` 或 `YYYY-MM-DD`) | | data_end | TEXT | — | 数据截止期 | | refreshed_at | TEXT | — | 最近刷新日期 | | remark | TEXT | — | 备注 | ## 10. indicator_value — 指标时序值表 > 同一指标 `(indicator_id, obs_date)` 唯一;`obs_date` 为文本(SQLite TEXT 排序即字典序,按 `YYYY-MM-DD` / `YYYY-MM` 录入时与时间序一致)。 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | INTEGER | PRIMARY KEY AUTOINCREMENT | 主键 | | indicator_id | INTEGER | NOT NULL → `indicator.id`,ON DELETE CASCADE | 指标 ID | | obs_date | TEXT | NOT NULL,UNIQUE(indicator_id, obs_date) | 观察期 | | value | REAL | — | 指标取值 | 索引:`idx_indicator_value ON (indicator_id, obs_date)`。 --- ## 表关系 ```text ┌─────────────── 接口权限(RBAC,sys_permission 管接口) ───────────────┐ sys_user ──< sys_user_role >── sys_role ──< sys_role_permission >── sys_permission (用户) (多对多) (角色) (多对多) (权限) ┌─────────────── 菜单权限(sys_menu,独立体系,与接口权限解耦) ───────────────┐ sys_user ──< sys_user_role >── sys_role ──< sys_role_menu >── sys_menu (用户) (多对多) (角色) (多对多) (菜单树) ``` - 一个用户可拥有多个角色;一个角色可被多个用户持有。 - 一个角色可拥有多个权限;一个权限可授予多个角色。 - 用户的最终权限 = 其所有角色权限的并集(查询时已 `DISTINCT` 去重)。 - 用户的可见菜单 = 其所有角色被授予菜单的并集;下发时向上补全父级、剔除空目录。 --- ## 指标数据初始化 `indicator` 表的元数据(51 条)由 `sql/init.sql` 一并灌入;时序值 `indicator_value` 数据量较大(>1万行),单独放在 `sql/indicator_values_seed.sql`,需在初始化完成后单独执行一次: ```bash sqlite3 data/ir.db < sql/init.sql sqlite3 data/ir.db < sql/indicator_values_seed.sql ``` 两个脚本均使用 `IF NOT EXISTS` / `INSERT OR IGNORE`,可重复执行。 ## 种子数据(由 `sql/init.sql` 一次性灌入) | 类别 | 内容 | |---|---| | 角色 | `ADMIN`(超级管理员,拥有全部权限)、`USER`(普通用户,默认注册用户角色) | | 权限 | `user:list` `user:create` `user:update` `user:delete`、`role:list` `role:create` `role:update` `role:delete` `role:assign`、`permission:list` `permission:create` `permission:delete`、`data:query` `data:write` | | 菜单 | `工作台`、`系统管理(目录)→ 用户管理/角色管理/权限管理/菜单管理`、`数据源演示`、投研业务 6 个一级目录(`基本面 / 政策面 / 资金面 / 债市分析 / 权益分析 / 多资产`),其中 `基本面` 下含 7 个二级菜单(`GDP / 投资 / 出口 / 消费 / 通胀 / 供给 / 景气度`);脚本一次性把全部菜单授权给 `ADMIN`,新建菜单仍会运行时自动授权给 `ADMIN` | | 管理员 | `admin / admin123`(BCrypt 哈希写死在脚本首注,使用前请尽快改密) | 新注册用户由 `UserService` 在运行时自动分配默认角色 `USER`。