文澜知微项目实训报告(十)个人汇报总结
阶段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图片上传 |
轮询状态更新 |
实时反馈 |
更多推荐
所有评论(0)