中华文明全图鉴——数据模型文档
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
当前位置规则:
- 优先取
is_current = true 的位置记录。
- 若存在多条,则取
verified_at 最新的一条。
- 若
valid_until 已过期,则不作为前台当前位置展示。
- 无权限用户只能读取
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 件文物点位范围查询响应时间符合要求。
- 敏感坐标在游客权限下不可见。
- 机构用户无法访问其他机构文物。
- 文物标签绑定、解绑和筛选结果正确。