2d847e154f
中华文明全图鉴——文物全图系统(PC Web 地图 + NestJS API + 管理后台)。 含三大 IP(文物南迁北归 / 国宝海外回归 / 博物馆手艺人)、AI 文物对话、 文物地图与详情、以及 demo-video-kit 演示视频生成工具。
459 lines
14 KiB
Markdown
459 lines
14 KiB
Markdown
# 中华文明全图鉴——数据模型文档
|
||
|
||
## 1. 数据模型目标
|
||
|
||
本数据模型服务于第一阶段 PC Web 地图站 MVP,覆盖文物、机构、位置、标签、数字资产、权限、操作日志和地图查询所需的核心数据结构。
|
||
|
||
## 2. 设计原则
|
||
|
||
- **PostgreSQL + PostGIS**:结构化业务数据与地理数据统一存储。
|
||
- **多位置记录**:一件文物可有多条位置记录,前台默认展示最新有效位置。
|
||
- **敏感坐标分级**:同一位置可保存精确坐标和公开展示坐标或模糊区域。
|
||
- **标签可扩展**:基础标签固定,扩展标签通过标签分类和标签类型支持动态扩展。
|
||
- **操作可追溯**:核心对象修改必须记录操作日志。
|
||
- **字段可演进**:对角色卡、故事、AI 推荐等中后期能力保留扩展空间。
|
||
|
||
## 3. 枚举定义
|
||
|
||
## 3.1 artifact_category
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| bronze | 青铜 |
|
||
| painting_calligraphy | 书画 |
|
||
| porcelain | 陶瓷 |
|
||
| jade | 玉器 |
|
||
| gold_silver | 金银器 |
|
||
| lacquer | 漆器 |
|
||
| textile | 织绣 |
|
||
| stone_carving | 石刻 |
|
||
| wood_carving | 木雕 |
|
||
| dunhuang | 敦煌 |
|
||
| ancient_book | 古籍 |
|
||
| other | 其他 |
|
||
|
||
## 3.2 artifact_level
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| level_1 | 一级 |
|
||
| level_2 | 二级 |
|
||
| level_3 | 三级 |
|
||
| general | 一般 |
|
||
| unknown | 未定级 |
|
||
|
||
## 3.3 artifact_status
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| at_home | 在家 |
|
||
| away | 离家 |
|
||
| in_transit | 在途 |
|
||
| unknown | 未知 |
|
||
|
||
## 3.4 location_type
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| domestic | 国内 |
|
||
| overseas | 海外 |
|
||
| unknown | 未知 |
|
||
| in_transit | 在途 |
|
||
|
||
## 3.5 location_precision
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| exact_room | 展厅 |
|
||
| exact_building | 建筑 |
|
||
| city | 城市 |
|
||
| country | 国家 |
|
||
| region | 区域 |
|
||
|
||
## 3.6 display_status
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| on_display | 在展 |
|
||
| in_storage | 库藏 |
|
||
| loaned | 外借 |
|
||
| repairing | 修复中 |
|
||
| touring | 巡展中 |
|
||
| unknown | 未知 |
|
||
|
||
## 3.7 source_type
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| institution_feed | 机构直供 |
|
||
| manual_entry | 后台录入 |
|
||
| user_report | 用户报告 |
|
||
| expert_verify | 专家验证 |
|
||
| public_source | 公开资料 |
|
||
|
||
## 3.8 publish_status
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| draft | 草稿 |
|
||
| pending | 待发布 |
|
||
| published | 已发布 |
|
||
| archived | 已归档 |
|
||
| rejected | 已驳回 |
|
||
|
||
## 3.9 tag_value_type
|
||
|
||
| 值 | 含义 |
|
||
|---|---|
|
||
| single | 单选 |
|
||
| multiple | 多选 |
|
||
| boolean | 布尔 |
|
||
| text | 文本 |
|
||
| number | 数字 |
|
||
|
||
## 4. 核心表设计
|
||
|
||
## 4.1 users
|
||
|
||
后台账号和前台用户统一存储,MVP 优先支持后台账号。
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 用户 ID |
|
||
| username | varchar(100) | unique | 登录名 |
|
||
| phone | varchar(30) | nullable | 手机号 |
|
||
| email | varchar(255) | nullable | 邮箱 |
|
||
| password_hash | varchar(255) | nullable | 密码 hash |
|
||
| nickname | varchar(100) | nullable | 昵称 |
|
||
| avatar_url | text | nullable | 头像 |
|
||
| user_type | varchar(30) | not null | admin、institution、public、expert、editor |
|
||
| institution_id | uuid | fk nullable | 绑定机构 |
|
||
| is_active | boolean | default true | 是否启用 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
| updated_at | timestamptz | not null | 更新时间 |
|
||
|
||
## 4.2 roles
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 角色 ID |
|
||
| code | varchar(50) | unique | 角色编码 |
|
||
| name | varchar(100) | not null | 角色名称 |
|
||
| description | text | nullable | 描述 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
## 4.3 permissions
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 权限 ID |
|
||
| code | varchar(100) | unique | 权限编码 |
|
||
| name | varchar(100) | not null | 权限名称 |
|
||
| module | varchar(50) | not null | 模块 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
## 4.4 user_roles
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| user_id | uuid | pk fk | 用户 ID |
|
||
| role_id | uuid | pk fk | 角色 ID |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
## 4.5 institutions
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 机构 ID |
|
||
| name | varchar(255) | not null | 机构名称 |
|
||
| short_name | varchar(100) | nullable | 简称 |
|
||
| code | varchar(100) | unique nullable | 机构编码 |
|
||
| institution_type | varchar(50) | not null | museum、research、private、other |
|
||
| country | varchar(100) | not null | 国家 |
|
||
| province | varchar(100) | nullable | 省份 |
|
||
| city | varchar(100) | nullable | 城市 |
|
||
| address | text | nullable | 地址 |
|
||
| location | geography(Point, 4326) | nullable | 机构坐标 |
|
||
| official_website | text | nullable | 官网 |
|
||
| description | text | nullable | 简介 |
|
||
| is_verified | boolean | default false | 是否认证 |
|
||
| publish_status | publish_status | not null | 发布状态 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
| updated_at | timestamptz | not null | 更新时间 |
|
||
|
||
索引:
|
||
|
||
- `idx_institutions_location_gist`:`GIST(location)`
|
||
- `idx_institutions_name`:`name`
|
||
- `idx_institutions_country_city`:`country, city`
|
||
|
||
## 4.6 artifacts
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 文物 ID |
|
||
| unified_map_id | varchar(50) | unique | 全图唯一编码 |
|
||
| name | varchar(255) | not null | 文物名称 |
|
||
| alternative_names | text[] | nullable | 别名 |
|
||
| category | artifact_category | not null | 门类 |
|
||
| dynasty | varchar(100) | nullable | 年代 |
|
||
| level | artifact_level | default unknown | 文物级别 |
|
||
| material | varchar(255) | nullable | 材质 |
|
||
| dimensions | varchar(255) | nullable | 尺寸 |
|
||
| current_status | artifact_status | default unknown | 在家、离家、在途、未知 |
|
||
| home_institution_id | uuid | fk nullable | 原属或现属国内机构 |
|
||
| summary | text | nullable | 简介 |
|
||
| story_hook | varchar(255) | nullable | 一句话故事钩子 |
|
||
| persona_quote | varchar(255) | nullable | 趣味化角色短句 |
|
||
| publish_status | publish_status | not null | 发布状态 |
|
||
| created_by | uuid | fk nullable | 创建人 |
|
||
| updated_by | uuid | fk nullable | 更新人 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
| updated_at | timestamptz | not null | 更新时间 |
|
||
|
||
索引:
|
||
|
||
- `idx_artifacts_name`:`name`
|
||
- `idx_artifacts_category`:`category`
|
||
- `idx_artifacts_dynasty`:`dynasty`
|
||
- `idx_artifacts_status`:`current_status`
|
||
- `idx_artifacts_home_institution`:`home_institution_id`
|
||
|
||
## 4.7 artifact_locations
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 位置记录 ID |
|
||
| artifact_id | uuid | fk not null | 文物 ID |
|
||
| location_type | location_type | not null | 国内、海外、未知、在途 |
|
||
| institution_id | uuid | fk nullable | 关联机构 |
|
||
| precise_location | geography(Point, 4326) | nullable | 精确坐标 |
|
||
| public_location | geography(Point, 4326) | nullable | 前台可展示坐标 |
|
||
| fuzzy_area | geography(Polygon, 4326) | nullable | 模糊区域 |
|
||
| precision | location_precision | not null | 坐标精度 |
|
||
| floor_plan_ref | varchar(255) | nullable | 展厅平面图编号 |
|
||
| room_name | varchar(255) | nullable | 展厅名称 |
|
||
| cabinet_no | varchar(100) | nullable | 展柜编号 |
|
||
| display_status | display_status | default unknown | 展出状态 |
|
||
| source_type | source_type | not null | 来源类型 |
|
||
| source_description | text | nullable | 来源说明 |
|
||
| discoverer_user_id | uuid | fk nullable | 发现者 |
|
||
| is_current | boolean | default false | 是否当前有效位置 |
|
||
| verified_at | timestamptz | nullable | 审核通过时间 |
|
||
| valid_from | timestamptz | nullable | 有效开始 |
|
||
| valid_until | timestamptz | nullable | 有效截止 |
|
||
| created_by | uuid | fk nullable | 创建人 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
| updated_at | timestamptz | not null | 更新时间 |
|
||
|
||
索引:
|
||
|
||
- `idx_artifact_locations_artifact_id`:`artifact_id`
|
||
- `idx_artifact_locations_institution_id`:`institution_id`
|
||
- `idx_artifact_locations_public_location_gist`:`GIST(public_location)`
|
||
- `idx_artifact_locations_precise_location_gist`:`GIST(precise_location)`
|
||
- `idx_artifact_locations_fuzzy_area_gist`:`GIST(fuzzy_area)`
|
||
- `idx_artifact_locations_current`:`artifact_id, is_current`
|
||
|
||
当前位置规则:
|
||
|
||
1. 优先取 `is_current = true` 的位置记录。
|
||
2. 若存在多条,则取 `verified_at` 最新的一条。
|
||
3. 若 `valid_until` 已过期,则不作为前台当前位置展示。
|
||
4. 无权限用户只能读取 `public_location` 或 `fuzzy_area`。
|
||
|
||
## 4.8 tag_categories
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 标签分类 ID |
|
||
| code | varchar(100) | unique | 分类编码 |
|
||
| name | varchar(100) | not null | 分类名称 |
|
||
| description | text | nullable | 描述 |
|
||
| sort_order | int | default 0 | 排序 |
|
||
| is_system | boolean | default false | 是否系统内置 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
## 4.9 tags
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 标签 ID |
|
||
| category_id | uuid | fk not null | 分类 ID |
|
||
| code | varchar(100) | unique | 标签编码 |
|
||
| name | varchar(100) | not null | 展示名 |
|
||
| value_type | tag_value_type | not null | 值类型 |
|
||
| description | text | nullable | 描述 |
|
||
| color | varchar(20) | nullable | 展示颜色 |
|
||
| icon | varchar(100) | nullable | 图标 |
|
||
| is_system | boolean | default false | 是否系统标签 |
|
||
| is_active | boolean | default true | 是否启用 |
|
||
| sort_order | int | default 0 | 排序 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
| updated_at | timestamptz | not null | 更新时间 |
|
||
|
||
## 4.10 artifact_tags
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 关系 ID |
|
||
| artifact_id | uuid | fk not null | 文物 ID |
|
||
| tag_id | uuid | fk not null | 标签 ID |
|
||
| value_text | text | nullable | 文本值 |
|
||
| value_number | numeric | nullable | 数字值 |
|
||
| confidence | numeric(5,2) | nullable | 置信度 |
|
||
| source_type | source_type | not null | 来源 |
|
||
| review_status | varchar(30) | default approved | pending、approved、rejected |
|
||
| created_by | uuid | fk nullable | 创建人 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
唯一约束:
|
||
|
||
- `artifact_id, tag_id, value_text`
|
||
|
||
## 4.11 digital_assets
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 资产 ID |
|
||
| artifact_id | uuid | fk nullable | 文物 ID |
|
||
| institution_id | uuid | fk nullable | 机构 ID |
|
||
| asset_type | varchar(50) | not null | image、audio、video、model_3d、document |
|
||
| title | varchar(255) | nullable | 标题 |
|
||
| url | text | not null | 资源地址 |
|
||
| thumbnail_url | text | nullable | 缩略图 |
|
||
| mime_type | varchar(100) | nullable | MIME 类型 |
|
||
| size_bytes | bigint | nullable | 文件大小 |
|
||
| copyright_owner | varchar(255) | nullable | 版权方 |
|
||
| license_scope | text | nullable | 授权范围 |
|
||
| sort_order | int | default 0 | 排序 |
|
||
| created_by | uuid | fk nullable | 上传人 |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
## 4.12 operation_logs
|
||
|
||
| 字段 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| id | uuid | pk | 日志 ID |
|
||
| operator_id | uuid | fk nullable | 操作人 |
|
||
| operator_role | varchar(50) | nullable | 操作角色 |
|
||
| action | varchar(100) | not null | 操作类型 |
|
||
| target_type | varchar(100) | not null | 目标类型 |
|
||
| target_id | uuid | nullable | 目标 ID |
|
||
| before_data | jsonb | nullable | 变更前 |
|
||
| after_data | jsonb | nullable | 变更后 |
|
||
| ip_address | varchar(50) | nullable | IP |
|
||
| user_agent | text | nullable | UA |
|
||
| created_at | timestamptz | not null | 创建时间 |
|
||
|
||
索引:
|
||
|
||
- `idx_operation_logs_operator_id`
|
||
- `idx_operation_logs_target`
|
||
- `idx_operation_logs_created_at`
|
||
|
||
## 5. 地图接口视图建议
|
||
|
||
## 5.1 artifact_current_locations_view
|
||
|
||
用途:地图点位与文物详情快速读取。
|
||
|
||
字段:
|
||
|
||
- artifact_id
|
||
- artifact_name
|
||
- category
|
||
- dynasty
|
||
- level
|
||
- current_status
|
||
- story_hook
|
||
- persona_quote
|
||
- institution_id
|
||
- institution_name
|
||
- public_location
|
||
- fuzzy_area
|
||
- precision
|
||
- display_status
|
||
- source_type
|
||
- verified_at
|
||
|
||
## 5.2 map_summary_view
|
||
|
||
用途:顶部统计栏。
|
||
|
||
字段:
|
||
|
||
- total_artifacts
|
||
- domestic_count
|
||
- overseas_count
|
||
- on_display_count
|
||
- in_storage_count
|
||
- loaned_count
|
||
- unknown_location_count
|
||
|
||
## 6. Seed 数据建议
|
||
|
||
## 6.1 系统角色
|
||
|
||
- admin
|
||
- institution_user
|
||
- editor
|
||
- expert
|
||
- public_user
|
||
|
||
## 6.2 标签分类
|
||
|
||
- basic_attribute
|
||
- circulation_experience
|
||
- emotional_attribute
|
||
- content_derivation
|
||
|
||
## 6.3 基础标签
|
||
|
||
- 门类
|
||
- 年代
|
||
- 级别
|
||
- 材质
|
||
- 功能
|
||
- 流失状态
|
||
- 回归状态
|
||
- 南迁北归
|
||
- 修复经历
|
||
- 数字化经历
|
||
- 情绪主调
|
||
- 适合年龄
|
||
|
||
## 7. 数据校验规则
|
||
|
||
## 7.1 文物校验
|
||
|
||
- `name` 必填。
|
||
- `category` 必须在枚举范围内。
|
||
- `unified_map_id` 必须唯一。
|
||
- `current_status` 必须在枚举范围内。
|
||
- 发布时至少需要一条当前有效位置或明确标记为未知位置。
|
||
|
||
## 7.2 位置校验
|
||
|
||
- `location_type = domestic` 时优先要求 `institution_id`。
|
||
- `precision = exact_room` 时需要 `room_name` 或 `floor_plan_ref`。
|
||
- 公开坐标必须符合经纬度范围。
|
||
- 存在敏感位置时,前台不得返回 `precise_location`。
|
||
- `valid_until` 小于当前时间时不作为当前有效位置。
|
||
|
||
## 7.3 标签校验
|
||
|
||
- 系统标签不可随意删除。
|
||
- 禁用标签不允许新增绑定。
|
||
- AI 推荐标签必须人工确认后才能公开展示。
|
||
|
||
## 8. 测试要点
|
||
|
||
- migration 可从空库完整执行。
|
||
- PostGIS 扩展可启用。
|
||
- 空间索引创建成功。
|
||
- 1000 件文物点位范围查询响应时间符合要求。
|
||
- 敏感坐标在游客权限下不可见。
|
||
- 机构用户无法访问其他机构文物。
|
||
- 文物标签绑定、解绑和筛选结果正确。
|