Files
WenwuMap/4-data-model.md
selfrelease 2d847e154f chore: 初始化仓库
中华文明全图鉴——文物全图系统(PC Web 地图 + NestJS API + 管理后台)。
含三大 IP(文物南迁北归 / 国宝海外回归 / 博物馆手艺人)、AI 文物对话、
文物地图与详情、以及 demo-video-kit 演示视频生成工具。
2026-06-13 20:55:44 +08:00

459 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 中华文明全图鉴——数据模型文档
## 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 件文物点位范围查询响应时间符合要求。
- 敏感坐标在游客权限下不可见。
- 机构用户无法访问其他机构文物。
- 文物标签绑定、解绑和筛选结果正确。