阶段1:3.23-4.7 项目标准化框架搭建

核心目标:搭建分层解耦、支持admin/guest双权限的Vue3+Vite+SpringBoot全栈标准化开发框架,统一前后端开发规范。

后端实体体系

1. Guest(普通用户实体)

         
    @Entity    
    @Table(name = "guest")    
    public class Guest {    
        @Id    
        private Integer guestId;          // 用户主键    
        @OneToOne    
        @JoinColumn(name="person_id")    
        @JsonIgnore    
        private Person person;             // 一对一关联人员基础信息    
        private String picture;            // 用户头像    
        public String getNumName(){    
            return person.getNum()+"-" + person.getName();    
        }    
    }    
         

释义:存储普通访客/学生用户专属拓展信息,与人员表一对一绑定。

2. Admin(管理员实体)

         
    @Entity    
    @Table(name = "admin")    
    public class Admin {    
        @Id    
        private Integer adminId;    
        @OneToOne    
        @JoinColumn(name="person_id")    
        @JsonIgnore    
        private Person person;    
        private Integer total;    // 管理统计预留    
        private String picture;    
    }    
         

3. Person(人员基础实体)
存储姓名、账号、个人简介等通用信息,Admin/Guest均一对一关联。

4. User(登录账号实体)
存储登录用户名、加密密码、用户角色(ROLE_ADMIN/ROLE_GUEST),负责鉴权登录。

Repository层
  • GuestRepository:findByPersonNum、分页查询
    PersonRepository:findByNum
    UserRepository:findByPersonPersonId
Controller核心接口

接口

方法

说明

/api/guest/getGuestList

POST

分页查询用户列表

/api/guest/guestEditSave

POST

新增/编辑用户(自动创建Person+User+Guest)

/api/guest/guestDelete

POST

删除用户(顺序:User→Guest→Person)

/api/guest/getGuestInfo

POST

获取用户详情

前端标准化结构
         
    src/    
    ├── models/general.ts      # 统一TS类型    
    ├── services/*Serv.ts      # 按模块拆分请求    
    ├── Views/                  # 按功能分文件夹    
    └── components/Navi.vue    # 全局侧边菜单    
         

前后端调用规范

  • 所有接口POST请求,入参统一@RequestBody DataRequest
  • 权限注解:@PreAuthorize("hasRole('ADMIN')")
  • 统一返回格式:{code, data, msg}

阶段2:4.7-4.18 历史地名时空地图模块

数据源与转换流程

原始数据源:哈佛大学Dataverse公开历史地名数据集(访问数据集地址【https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/WW1PD6】,下载目标文件《v6_time_pref_pts_gbk_xian80.zip》,该压缩包包含了完整的历史地名数据,涵盖地名拼音、中文名、繁体名、经纬度坐标、存在时间、行政类型、治所变迁等关键元数据,为地图可视化提供了核心支撑。)

数据清洗脚本(Python)

         
    import pymysql, json    
    conn = pymysql.connect(host='localhost', database='wenlanzhiwei')    
    cursor = conn.cursor()    
    cursor.execute("""    
        SELECT ogc_fid, name_ch, x_coor, y_coor, type_ch, beg_yr, end_yr    
        FROM county_name WHERE x_coor IS NOT NULL AND y_coor IS NOT NULL    
    """)    
    features = []    
    for row in cursor.fetchall():    
        features.append({    
            "type": "Feature",    
            "geometry": {"type": "Point", "coordinates": [float(row[2]), float(row[3])]},    
            "properties": {"id": row[0], "name_ch": row[1], "type_ch": row[4],     
                           "start_year": row[5], "end_year": row[6]}    
        })    
    with open('historical_places.geojson', 'w') as f:    
        json.dump({"type": "FeatureCollection", "features": features}, f)    
         

数据成果

  • 总计10,522条历史地名数据
  • 覆盖先秦至清朝(前800年-1912年)
  • 输出:historical_places.geojson + time_index.json
后端实体 HistoricalPlace
         
    @Entity    
    @Table(name = "county_name")    
    public class HistoricalPlace {    
        private Integer id;          // ogc_fid    
        private String namePy;       // 拼音    
        private String nameCh;       // 中文    
        private Float xCoor, yCoor;  // 经纬度    
        private Long begYr, endYr;   // 存续年份    
        private String typeCh;       // 行政区划类型    
    }    
         
前端地图核心功能
         
    // 地图初始化    
    const map = new AMap.Map(mapContainer.value, {    
        center: [108, 35], zoom: 5, zooms: [3, 12]    
    });    
         
    // 地名标记渲染 - 按类型分色    
    const typeColors = {'郡':'#f59e0b', '县':'#3b82f6', '州':'#10b981'};    
         
    // 时间轴联动筛选    
    const applyFilters = () => {    
        markers.forEach(m => {    
            const p = m.getExtData();    
            if (p.start_year <= currentYear && p.end_year >= currentYear) {    
                map.add(m); // 显示    
            }    
        });    
    };    

DeepSeek AI调用(地图场景)
         
    // aiServ.ts - 统一调用    
    export async function sendChatMessage(params: {    
        model: string; message: string; history?: any[]    
    }): Promise<any> {    
        return await fetch('/api/ai/chat', {    
            method: 'POST',    
            body: JSON.stringify({model, messages: [...]})    
        });    
    }    
         

提示词:角色定位为中国历史地理专家,结合当前地图朝代、选中地名作答;支持快捷提问(重大事件/人物/典故/朝代更迭)和自定义提问。

阶段3:4.22-5.3 历史人物轨迹前端可视化

前端TS类型定义
         
    interface TrackPoint {    
        time: string;                    // "602年"    
        event: string;                   // 事件描述    
        location: string;                // 古代地名    
        coordinates: [number, number] | null;    
        year?: number;                   // 解析后数字年份    
        source?: string;                 // 史料出处    
    }    
         
    interface PersonTrack {    
        name: string;                    // 人物姓名    
        points: TrackPoint[];    
    }    
         

核心轨迹渲染函数
         
    const drawPersonTrack = (personName: string) => {    
        const track = personTracks.value.find(t => t.name === personName);    
        const validPoints = track.points    
            .filter(p => isValidCoordinate(p.coordinates))    
            .sort((a, b) => (a.year || 0) - (b.year || 0));    
            
        let currentIndex = 0;    
        const playNext = () => {    
            if (currentIndex >= validPoints.length) return;    
            // 绘制渐变轨迹线    
            const progress = currentIndex / (validPoints.length - 1);    
            const lineColor = `rgb(${255-80*progress}, ${140+60*progress}, 0)`;    
            // 创建标记点    
            createNormalMarker(currentIndex, validPoints[currentIndex]);    
            currentIndex++;    
            setTimeout(playNext, 4000 / playbackSpeed);    
        };    
        playNext();    
    };    
         

阶段4:5.4-5.7 CHGIS坐标校对+功能迭代

坐标校对脚本(Node.js)
         
    // 构建三级索引    
    function buildPlaceIndex(historicalPlaces) {    
        const exactIndex = new Map();   // 精确匹配    
        const fuzzyIndex = new Map();    // 模糊匹配    
        const pinyinIndex = new Map();   // 拼音匹配    
        // 提取核心地名(去掉后缀)    
        const coreName = placeName.replace(/(县|邑|城|州|郡|府)$/, '');    
        // 相似度打分    
        return { exactIndex, fuzzyIndex, pinyinIndex };    
    }    
         

校对成果:匹配率78.36%→91.19%,人物扩展至278人

多人对比模式(20色调色板)
         
    const personColorPalette = [    
        '#4caf50', '#2196f3', '#e91e63', '#9c27b0', '#00bcd4',    
        '#ff5722', '#795548', '#607d8b', '#8bc34a', '#ffc107',    
        // ... 共20色    
    ];    
         

阶段5:5.9-5.28 DeepSeek AI后端集成+轨迹全链路生成

后端动态参数适配
         
    // AIService.java    
    private int determineMaxTokens(String message) {    
        if (isTrackQuery(message)) return 6000;   // 轨迹生成    
        if (isCoordinateQuery(message)) return 500; // 坐标查询    
        return 2000;  // 普通对话    
    }    
         
    private double determineTemperature(String message) {    
        if (isTrackQuery(message)) return 0.5;    // 低随机,保格式    
        if (isCoordinateQuery(message)) return 0.1; // 唯一精准    
        return 0.7;    
    }    
         
前端提示词模板(轨迹生成专用)
         
    const DEEPSEEK_PROMPT_TEMPLATE = `# 角色定位    
    你是一位资深的历史学家与历史地理学专家...    
    # 核心任务    
    提取【{personName}】的完整生平轨迹数据,严格按标准JSON格式输出    
    # 输出格式标准    
    {    
      "人物": "{personName}",    
      "轨迹": [{    
        "时间": "352年",    
        "event": "事件详细描述",    
        "地点": "古代地名(按层级)",    
        "出处": "据《史料名称》",    
        "coordinates": [经度, 纬度],    
        "coordinate_confidence": "high/medium/low"    
      }]    
    }`;    
         
三层坐标校对机制
         
    const correctCoordinates = async (trackData) => {    
        for (const point of trackData.轨迹) {    
            // 第1层:特殊地名硬编码映射    
            const found = findPlaceByName(location);    
            if (found) { /* 使用硬编码坐标 */ continue; }    
            // 第2层:保留AI有效坐标    
            if (point.coordinates && isValidCoordinate(point.coordinates)) {    
                /* 保留AI坐标 */ continue;    
            }    
            // 第3层:AI兜底重查    
            const aiCoords = await queryCoordinatesByAI(location);    
        }    
    };    
         

阶段6:5.29-6.7 OCR识别模块从零开发

数据库实体 OCRRecord
         
    @Entity    
    @Table(name = "ocr_records")    
    public class OCRRecord {    
        @Id private Long id;    
        @ManyToOne @JoinColumn(name = "guest_id")    
        @JsonIgnore private Guest guest;    
        private String originalFileName;    
        private String filePath;    
        @Column(columnDefinition = "TEXT")    
        private String originalText;        // 识别原文    
        @Column(columnDefinition = "TEXT")    
        private String modernText;          // 大白话翻译    
        @Column(columnDefinition = "TEXT")    
        private String vocabulary;          // 生词    
        @Column(columnDefinition = "TEXT")    
        private String background;          // 背景介绍    
        private String ocrStatus;           // PROCESSING/ORIGINAL_READY/COMPLETED    
    }    
         
技术选型与原因

模型

速度

准确度

选用

doubao-seed-2-0-pro

⭐⭐⭐⭐⭐

doubao-seed-2-0-lite

⭐⭐⭐⭐

doubao-seed-2-0-mini

较快

⭐⭐⭐⭐

选型原因:mini版本速度是pro的2-3倍,准确度满足古籍识别需求,成本更低。

两步式异步识别流程
         
    // 步骤1:仅识别原文    
    private String step1Recognize(String dataUrl) {    
        // 竖排古文从右至左输出、保留换行    
    }    
         
    // 步骤2:翻译+标点+背景+生词    
    private OCRResult step2Translate(String originalText) {    
        // 返回结构化JSON    
    }    
         
图片预处理参数
  • 最大宽度:400px
  • JPEG质量:0.3
  • 压缩后大小:30-80KB(原图2-5MB)
  • 传输时间减少约70%

阶段7:6.8-6.12 OCR性能&体验优化

优化成果

优化项

优化前

优化后

效果

识别耗时

30-50s

15-35s

↓50%

图片大小

100-200KB

30-60KB

↓60%

提示词

现代文翻译

大白话翻译

可读性↑

提示词优化
         
    优化前:"现代文翻译"    
    优化后:"用大白话翻译(像朋友聊天一样通俗易懂)"    
         
    新增字段:"originalTextWithPunctuation": "给原文加上标点符号"    
         

阶段8:6.13-6.18 轨迹知识库+审核入库体系

数据库双实体设计

1. PersonTrack(主表)

         
    @Entity    
    @Table(name = "person_track")    
    public class PersonTrack {    
        private Integer trackId;    
        private String personName;    
        @Column(columnDefinition = "TEXT")    
        private String trackData;        // JSON冗余备份    
        private String source;           // deepseek/manual/import    
        private String status;           // pending/approved/rejected    
        private Integer trackPointCount;    
        private String reviewNotes;    
        private Integer reviewerId;      // 审核管理员    
        private Integer submitUserId;    // 提交用户    
    }    
         

2. TrackPoint(明细表)

         
    @Entity    
    @Table(name = "track_point")    
    public class TrackPoint {    
        private Integer pointId;    
        private Integer trackId;         // 外键    
        private String timePoint;        // 年份    
        private String event;    
        private String location;    
        private Double longitude, latitude;    
        private String coordinateConfidence;    
        private Integer sortOrder;       // 时序排序    
    }    
         
设计说明

1. 分表原因:减少JSON全表扫描,分页统计更快

2. 保留trackData:用于一键导出、兼容外部GeoJSON导入

3. 状态流转:AI生成默认pending → 管理员审核通过 → approved(公共知识库)

审核队列实体 ReviewQueue
         
    @Entity    
    @Table(name = "review_queue")    
    public class ReviewQueue {    
        private Integer reviewId;    
        private String personName;    
        @Column(columnDefinition = "TEXT")    
        private String trackData;    
        private Integer submitUserId;    
        private String status;    // pending/approved/rejected    
        private String reviewNotes;    
        private Date submitTime;    
    }    
         
核心API接口

接口

方法

说明

/api/track-knowledge/save

POST

保存轨迹数据

/api/track-knowledge/review

POST

审核轨迹

/api/track-knowledge/knowledge-base

GET

获取知识库

/api/track-knowledge/merge

POST

合并轨迹

/api/review/submit

POST

用户提交审核

/api/review/admin/approve

POST

审核通过

/api/review/admin/reject

POST

驳回

前端审核面板功能
  • 轨迹点新增/编辑/删除
  • 合并节点可视化
  • 可信度彩色标签
  • 三种导入渠道:GeoJSON/本地JSON/知识库合并

补充:会话保存功能

后端实体 UserChatSession
         
    @Entity    
    @Table(name = "user_chat_session")    
    public class UserChatSession {    
        private Integer id;    
        private Integer userId;          // guestId    
        private String title;            // 会话标题    
        @Column(columnDefinition = "TEXT")    
        private String messages;         // 消息JSON数组    
        private Integer messageCount;    
        private String status;           // active/archived    
    }    
         
前后端逻辑

1. 用户每次AI对话自动存入当前会话

2. 自动提取第一条用户提问作为会话标题

3. 接口:创建会话、保存消息、查询列表、删除会话

二、两大核心功能:前后端完整汇总

功能一:历史人物轨迹智能生成+地图可视化+审核入库

后端实体体系

实体

作用

关键字段

PersonTrack

主轨迹表

trackId, personName, status, submitUserId

TrackPoint

点位明细

pointId, trackId, timePoint, coordinates

ReviewQueue

审核队列

reviewId, personName, trackData, status

Guest

普通用户

guestId, person

Admin

管理员

adminId, person

Person

人员基础

personId, num, name

HistoricalPlace

地名库

id, name_ch, x_coor, y_coor

Service核心方法
         
    // TrackKnowledgeService    
    saveTrackData()          // AI轨迹拆分入库    
    reviewTrack()            // 管理员审核    
    mergeTrack()             // 合并同一人物多条轨迹    
    batchImport()            // 批量导入    
    getKnowledgeBase()       // 查询公开轨迹    
         
    // ReviewQueueService    
    submitForReview()        // 用户提交    
    reviewTrack()            // 管理员审核(通过则写入知识库)    
    cancelReview()           // 用户撤销    
         
前端类型定义
         
    interface TrackPoint {    
        time: string; event: string; location: string;    
        coordinates: [number, number] | null;    
        coordinate_confidence: "high" | "medium" | "low";    
    }    
    interface PersonTrack {    
        trackId: number; personName: string;    
        status: "pending" | "approved" | "rejected";    
        points: TrackPoint[];    
    }    
    interface ReviewQueueItem {    
        reviewId: number; personName: string;    
        submitUserId: number; status: string;    
    }    
前后端调用链路
         
    用户输入姓名 → generateTrackWithDeepSeek() → POST /api/ai/chat    
      → DeepSeek返回JSON → correctCoordinates()三层校对    
      → 展示审核面板    
          ├── 暂存待审 → POST /api/review/submit    
          │   → ReviewQueueService.submitForReview() → review_queue表    
          └── 审核通过 → POST /api/review/admin/approve    
              → ReviewQueueService.reviewTrack()    
              → TrackKnowledgeService.saveTrackData()    
              → person_track表 + track_point表 → 公共知识库    

功能二:古籍OCR图文识别解析

后端实体 OCRRecord

字段

类型

说明

id

Long

主键

guest

Guest

关联用户

originalFileName

String

原始文件名

filePath

String

存储路径

originalText

TEXT

识别原文

modernText

TEXT

大白话翻译

vocabulary

TEXT

生词解释

background

TEXT

背景介绍

ocrStatus

String

PROCESSING/ORIGINAL_READY/COMPLETED

核心Service方法
         
    // 图片压缩    
    compressImageAdaptive()   // 400px/0.3质量,30-80KB    
         
    // 两步识别    
    step1Recognize()          // AI提取原文(竖排从右至左)    
    step2Translate()          // 生成标点+翻译+生词+背景    
         
    // 异步处理    
    processOCRAsync()         // CompletableFuture后台执行    
         
完整API接口

接口

方法

说明

/api/ocr/upload

POST

上传图片,异步识别

/api/ocr/status

POST

轮询进度

/api/ocr/list

POST

获取记录列表

/api/ocr/detail

POST

单条详情

/api/ocr/re-ocr

POST

重新识别

/api/ocr/edit

POST

手动编辑

/api/ocr/delete

POST

删除记录

/api/ocr/image/{id}

GET

加载原图

前端轮询机制
         
    function startPolling(recordId: number) {    
        pollTimer = setInterval(async () => {    
            const record = await getOCRStatus(recordId);    
            if (record.ocrStatus === 'PROCESSING') {    
                uploadProgress = 45; // 识别原文中    
            } else if (record.ocrStatus === 'ORIGINAL_READY') {    
                uploadProgress = 60; // 翻译生成中    
            } else if (record.ocrStatus === 'COMPLETED') {    
                uploadProgress = 100;    
                clearInterval(pollTimer);    
            }    
        }, 2000);    
    }    
         

三、关键技术点详细说明

1. 地图数据来源与转化流程

         
    哈佛Dataverse数据集 → MySQL(county_name表) → Python清洗脚本    
      → historical_places.geojson(10522条) + time_index.json    
      → 前端fetch加载 → 高德地图渲染    
         
    轨迹坐标转化:Node.js多级地名匹配脚本    
      精确匹配 → 模糊匹配 → 拼音匹配 → 相似度打分    
      覆盖率:78.36% → 91.19%    
         

2. DeepSeek AI完整调用链路

参数控制

场景

temperature

max_tokens

超时

轨迹生成

0.5

6000

120s

坐标查询

0.1

500

30s

普通对话

0.7

2000

30s

提示词模板

  • 角色:中国历史地理HGIS学者
  • 约束:仅输出纯JSON,禁止额外文字
  • 规范:公元纪年、分层地名、附史料出处、WGS84坐标

调用链路

         
    前端输入人名 → 填充模板 → POST /api/ai/chat    
      → DeepSeek API → 正则提取JSON    
      → 三层坐标校对(硬编码→CHGIS库→AI兜底)    
      → 标准化TrackPoint数组 → 地图渲染/提交审核    
         

3. 轨迹生成、校对、入库全流程

         
    AI生成原始JSON    
      → 三层坐标校对(特殊地名→CHGIS匹配→AI兜底)    
      → 过滤无效坐标、按年份排序、合并同地点    
      → 两种分支:    
          ① 保存个人草稿(UserSavedTrack,仅本人可见)    
          ② 提交审核队列(ReviewQueue)    
      → 管理员审核面板(增删改点位)    
          ├── 通过 → PersonTrack公共知识库(approved)    
          └── 驳回 → 用户可修改重提交    
         

4. 会话展开&保存(AI聊天会话)

         
    用户进入AI面板 → 加载会话列表    
    新建会话 → 自动生成标题(第一条提问)    
    每次发送消息 → 追加到该会话messages字段    
    支持:切换历史会话、清空、删除、归档    
         

5. OCR完整工作流程

         
    用户上传图片 → 图片压缩(400px/0.3质量)    
      → 异步任务启动    
          ├── 步骤1:豆包视觉模型识别古文文字    
          │   → 状态更新为ORIGINAL_READY(前端进度60%)    
          └── 步骤2:大模型生成标点+翻译+生词+背景    
              → 状态更新为COMPLETED(前端进度100%)    
      → 数据存入ocr_records表,图片持久化    
      → 前端展示:原图/原文/翻译/生词/背景分栏    
         

四、技术要点总结

坐标精度优化

阶段

方法

精度

初始AI生成

DeepSeek自动生成

~60%

地名库匹配

精确+模糊+拼音索引

78.36%

CHGIS校对

手动+脚本批量校对

91.19%

OCR性能优化

优化项

优化前

优化后

效果

模型选型

pro版本

mini版本

速度↑50%

图片压缩

1000px/0.5

400px/0.3

大小↓60%

识别流程

单步完成

两步异步

用户等待↓

提示词

简单指令

结构化JSON

质量↑

数据库设计要点

原则

实现

收益

一对多拆分

person_track + track_point

数据解耦,查询高效

JSON冗余

track_data字段

兼容多格式,快速导出

状态流转

pending→approved/rejected

规范数据生命周期

用户归属

submitUserId + scope

支持个人/公共分离

前端性能优化

场景

策略

效果

10522个地名标记

按需渲染+缩放控制

流畅交互

278人轨迹数据

异步加载+渐进渲染

<2秒加载

AI轨迹生成

步骤进度展示

用户感知提升

OCR图片上传

轮询状态更新

实时反馈

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐