国保数据库调整记录批量导入开发全记录

一、需求背景

国保数据库已收录5052条全国重点文物保护单位数据,但存在以下问题:

问题 说明
调整记录分散 238条合并/归入记录存储在JSON文件中,未写入数据库
最新名称缺失 文物改名后,数据库只有原名称,无最新名称
历史信息不完整 详情页无法展示文物的调整历史
搜索受限 无法通过调整记录内容搜索文物

核心目标:将 merge_adjustments.json 中的238条调整记录批量导入数据库,更新文物的 Content 和 LatestName 字段。


二、数据结构分析

1. JSON 数据格式

{
  "第四批": {
    "year": "1996",
    "type": "归入",
    "count": 12,
    "data": [
      {
        "name": "镇朔楼",
        "time": "明",
        "location": "河北省张家口市",
        "note": "归入清远楼"
      }
    ]
  }
}

2. 调整记录类型

类型 示例 说明
归入 "归入清远楼" A文物归入B文物
并入 "并入第六批全国重点文物保护单位牡丹江边墙" A文物并入B文物
合并+改名 "与第五批全国重点文物保护单位古荥冶铁遗址合并,名称:荥阳故城" A和B合并,新名称为C

3. 关键逻辑理解

最初的理解错误:

镇朔楼 → 归入 → 清远楼
         ↓
    错误:查找"镇朔楼",更新镇朔楼

正确的业务逻辑:

镇朔楼 → 归入 → 清远楼
         ↓
    正确:查找"清远楼"(被归入的目标文物),更新清远楼的Content字段
    记录:清远楼 ← 镇朔楼归入于此

三、批量导入脚本开发

1. 脚本信息

2. 核心逻辑

def parse_target_name(note):
    """从 note 字段中提取目标文物名称"""

    # 情况1:有"名称:"(合并改名)
    if '名称:' in note:
        new_name = note.split('名称:')[1].strip()
        # 提取旧名称,去掉批次前缀和连接词
        old_name = before_name.replace('与', '').replace('合并', '')
        return (old_name, new_name)  # 返回(数据库中的旧名称, 新名称)

    # 情况2:普通归入/并入
    target = note
    if target.startswith('归入'):
        target = target[2:]
    elif target.startswith('并入'):
        target = target[2:]

    # 去掉批次前缀
    for prefix in ['第一批全国重点文物保护单位', ...]:
        target = target.replace(prefix, '')

    return (target.strip(), None)

3. 处理流程

1. 备份数据库(带时间戳)
   ↓
2. 读取 JSON 数据
   ↓
3. 遍历所有批次的调整记录
   ↓
4. 对每条记录:
   a. 提取目标文物名称(从note字段)
   b. 在数据库中查找目标文物
   c. 解析或创建 Content JSON
   d. 追加调整记录到 adjustments 数组
   e. 如果有新名称,更新 LatestName
   f. 更新数据库
   ↓
5. 输出统计报告

4. 数据库更新示例

冯焕阙的 Content 字段:

{
  "adjustments": [
    {
      "batch": "第五批",
      "year": "2001",
      "type": "合并",
      "source": "冯焕阙",
      "note": "冯焕阙 与赵家村汉阙、王家坪汉阙、蒲家湾汉阙、沈府君阙合并,名称:渠县汉阙"
    }
  ]
}

同时设置: LatestName = "渠县汉阙"


四、技术难点与解决方案

难点 1:目标文物识别逻辑

现象:最初查找来源文物(如"镇朔楼"),但应该查找目标文物(如"清远楼")

根因:理解错误,调整记录是记录"谁归入到了目标文物",而不是"来源文物被归入"

解决: - 从 note 字段解析目标文物名称 - 处理批次前缀("归入第六批全国重点文物保护单位牡丹江边墙" → "牡丹江边墙") - 在数据库中查找目标文物并更新

难点 2:合并改名类的旧名称提取

现象:"与第五批全国重点文物保护单位古荥冶铁遗址合并,名称:荥阳故城"

需要提取: - 旧名称:古荥冶铁遗址(数据库中的名称) - 新名称:荥阳故城(LatestName)

解决:

# 去掉批次前缀
old_name = old_name.replace('第五批全国重点文物保护单位', '')
# 去掉连接词
old_name = old_name.replace('与', '').replace('合并', '').replace(',', '')

难点 3:Content 字段追加而非覆盖

需求:一个文物可能有多次调整记录(如大运河在第七批和第八批都有调整)

解决:

# 读取现有 Content
if content_json:
    content_data = json.loads(content_json)
else:
    content_data = {'adjustments': []}

# 追加新记录
content_data['adjustments'].append(new_adjustment)

# 写回数据库
cursor.execute('UPDATE ... SET Content = ?', (json.dumps(content_data),))

难点 4:空字符串与 NULL 的区分

现象:Content IS NOT NULL 包含空字符串,导致筛选不准确

解决:

-- 修改前
WHERE Content IS NOT NULL

-- 修改后
WHERE Content IS NOT NULL AND Content != ''

五、前端展示优化

1. 列表页显示新名称

需求:在列表中显示文物的最新名称

实现:

<strong>{{ site.NameC }}</strong>
{% if site.LatestName and site.LatestName != site.NameC %}
<span style="color: #e74c3c; margin: 0 4px; font-weight: bold;">→</span>
<strong style="color: #c0392b;">{{ site.LatestName }}</strong>
{% endif %}

效果:

冯焕阙 → 渠县汉阙
         ↑ 红色箭头 + 红色新名称

2. 详情页调整历史展示

需求:美观展示文物的调整历史

实现:

{% if adj.type == '合并' and '名称:' in adj.note %}
<strong>合并后名称:</strong>
<span class="new-name-highlight">{{ adj.note.split('名称:')[1].strip() }}</span>
<p class="adjustment-note">{{ adj.source }} 合并说明</p>
{% elif adj.type == '归入' or adj.type == '并入' %}
<strong>归入/合并至:</strong>{{ adj.note }}
{% endif %}

样式:

.new-name-highlight {
    background: #e8f4f8;
    color: #2c5f6b;
    border: 1px solid #b8e0ed;
    padding: 3px 10px;
    border-radius: 4px;
}

效果:

📋 调整历史

第五批  2001年  [合并]
━━━━━━━━━━━━━━━━━━━━━━━━
合并后名称:渠县汉阙

冯焕阙 赵家村汉阙、王家坪汉阙、蒲家湾汉阙、沈府君阙

六、执行结果

统计报告

============================================================
导入统计报告
============================================================
总调整记录数: 238
匹配成功: 220
更新成功: 220
更新失败: 0
未匹配总数: 18

⚠️  未匹配的合并改名类(8 条):
------------------------------------------------------------
  来源: 荥阳故城
  旧名: 古荥冶铁遗址
  新名: 荥阳故城
  批次: 第六批
  说明: 与第五批全国重点文物保护单位古荥冶铁遗址合并,名称:荥阳故城

⚠️  未匹配的普通归入/并入类(10 条):
------------------------------------------------------------
  - 清远楼 (来源: 镇朔楼, 第四批)
    归入清远楼
============================================================

功能验证

功能 状态 说明
批量导入 ✓ 220条成功导入
最新名称显示 ✓ 列表页红色箭头显示
调整历史展示 ✓ 详情页卡片式时间线
搜索增强 ✓ Content字段全文检索
调整记录列表 ✓ 专用路由 /adjusted/

七、后续优化方向

1. 未匹配记录处理

当前有18条未匹配记录,可能原因: - 数据库中名称与JSON中的名称不一致 - 目标文物尚未录入数据库 - 批次前缀解析不完整

建议: - 手动核对未匹配列表 - 修正数据库中的文物名称 - 更新 JSON 数据

2. 数据维护机制

3. 后台管理系统


八、技术要点总结

1. 业务逻辑

2. 数据处理

3. 前端展示


九、相关资源

代码文件

数据源

数据库


十、版本历史

日期 版本 说明
2026-05-07 v1.0 初始版本,完成批量导入脚本开发
2026-05-07 v1.1 修正目标文物识别逻辑
2026-05-07 v1.2 优化合并改名类名称解析
2026-05-07 v1.3 前端展示优化,实现新名称和调整历史展示

总结:通过批量导入脚本,成功将238条国保调整记录导入数据库,实现了文物最新名称显示和调整历史展示。核心技术突破在于正确理解了"目标文物"的业务逻辑,以及处理了多种格式的note字段。前端采用优雅的配色方案,避免了视觉突兀,提升了用户体验。

相关笔记