当前位置: 首页 > news >正文

前端历史记录管理页面开发

上一次做完登录注册功能之后,系统的用户体系算是搭起来了,但有一个问题一直没解决——用户之前提交的查询记录虽然后端都在存,但前端根本看不到。QueryHistory实体类和QueryHistoryRepository都已经有了,数据也在往里写,就是缺一个页面让用户去查看和管理这些记录。这次就是要把这个缺口补上,做一个完整的历史记录管理页面。

一、开发目标

  1. 后端创建历史记录REST接口,支持分页查询、关键词搜索、状态筛选、时间范围筛选
  2. 后端实现单条和批量删除功能,均校验用户归属权限
  3. 后端实现历史SQL重新执行功能,包含安全校验
  4. 后端实现查询趋势统计接口,支持按日/周/月统计查询次数和成功率
  5. 前端创建历史记录管理页面,包含表格展示、搜索筛选、分页、详情弹窗
  6. 前端实现批量选择和批量删除的交互逻辑
  7. 前端详情弹窗中的执行结果以表格形式可视化展示,重新执行结果也用弹窗表格展示
  8. 前端实现可折叠的查询趋势统计区域,用ECharts双Y轴图表展示
  9. 页面集成统一导航栏和登录态校验

二、核心开发工作

2.1 后端HistoryController

HistoryController一共提供了6个接口,全部从HttpServletRequest的属性中获取userId(由AuthInterceptor在请求进入时设置),确保每个用户只能操作自己的数据。

GET /api/history/list是主查询接口,支持四种筛选条件的组合:关键词搜索(匹配自然语言查询和SQL)、执行状态筛选(SUCCESS/FAIL)、时间范围筛选、以及无条件的默认分页查询。后端根据前端传来的参数组合,调用QueryHistoryRepository中不同的查询方法。返回的数据做了简化处理——把QueryHistory实体转成Map,只取需要的字段,避免@ManyToOne关联的UserInfo实体被序列化时产生循环引用。

DELETE /api/history/{id}做了两层校验:先检查记录是否存在且未删除,再检查记录的userId是否和当前登录用户一致。校验通过后调用queryHistoryRepository.softDeleteById做软删除。

POST /api/history/batch-delete是批量删除接口,接收一个List<Long>的ID列表。后端遍历每个ID,逐条查询记录并校验归属——如果记录不存在或不属于当前用户,就跳过并记录到skippedIds中。最终返回成功删除数、跳过数和被跳过的ID列表,前端据此给出明确提示。

POST /api/history/{id}/reexecute从历史记录中取出之前生成的SQL,先经过SqlSecurityManager的安全校验,校验通过后通过DatabaseService.executeQueryWithSecurityCheck执行SQL,返回的ChatResponse中包含结构化的queryResultsList<Map<String, Object>>),前端可以直接用来渲染表格。

GET /api/history/statistics是统计接口,支持period(day/week/month)和days(7/14/30)两个参数。后端使用JdbcTemplate直接执行原生SQL,按用户ID和时间范围过滤,根据period参数选择不同的GROUP BY策略(DATE()YEARWEEK()DATE_FORMAT())。返回每个时间段的查询总数、成功数、失败数、成功率,以及汇总数据。

2.2 前端history.html页面结构

页面整体分为五个区域:顶部导航栏、标题栏、筛选栏、统计区域、表格和分页。

导航栏沿用了其他页面的统一结构,"历史记录"链接带active类高亮。页面开头有内联JS做登录态校验。

筛选栏包含四个输入项:关键词搜索框(支持回车触发)、执行状态下拉框、开始时间和结束时间的datetime-local选择器,以及查询和重置两个按钮。筛选栏下方是批量操作栏(batch-bar),默认隐藏,选中记录后自动显示"已选X条"和"删除选中"按钮。

统计区域是一个可折叠的面板,默认收起,点击"📊 查询统计"标题展开。展开后显示周期和天数选择器、四个汇总数据卡片(总查询次数、成功次数、失败次数、整体成功率),以及ECharts图表容器。页面引入了ECharts CDN(echarts@5.5.0)。

表格展示8列:复选框、ID、查询问题、生成SQL、执行状态、耗时、查询时间、操作。复选框列支持全选/取消全选,选中的行显示浅蓝色背景。操作列有详情、重执行、删除三个按钮。

页面有两个弹窗:详情弹窗(detailOverlay)和重新执行结果弹窗(reexecuteOverlay),宽度都是max-width: 900px

2.3 前端history.js交互逻辑

history.js用IIFE封装,维护了currentPagetotalPagestotalElementscurrentDetailIdselectedIdsechartStatsInstance六个状态变量。

列表加载和渲染逻辑与之前基本一致,但每行增加了复选框,渲染时会根据selectedIds对象恢复选中状态和行高亮。全选/取消全选通过toggleSelectAll实现,单行选中通过toggleRowSelect实现,两者都会同步更新全选复选框状态、批量操作栏显示和所有复选框的DOM状态。

批量删除调用POST /api/history/batch-delete,把selectedIds的键转成ID数组发送给后端。删除完成后调用clearSelection清空选中状态并刷新列表。

详情弹窗中的执行结果展示做了比较大的改造。parseResultToTable函数会先尝试将结果文本解析为JSON数组,如果失败则尝试按Tab分隔文本解析(跳过第一行表头和第二行分隔线),如果都解析失败就回退到纯文本展示。解析成功后调用buildResultTableHtml渲染为HTML表格,超过100行只展示前100行并提示总数。

重新执行功能不再使用alert展示结果,而是打开独立的reexecuteOverlay弹窗。请求发送后先显示"执行中…"的加载提示,返回结果后如果queryResults有数据就渲染表格,否则显示文本内容。

统计功能通过toggleStatistics控制展开/收起,展开时自动调用loadStatistics加载数据。renderStatistics先渲染四个汇总卡片,然后用ECharts渲染双Y轴图表:左轴是柱状图显示查询次数,右轴是折线图显示成功率百分比。切换周期或天数后图表自动刷新,窗口resize时也会重绘。

三、关键实现细节

3.1 用户数据隔离

整个历史记录模块的数据隔离建立在两层机制上:后端所有接口都从request.getAttribute("userId")获取当前用户ID,查询时通过Repository中带userId参数的方法过滤数据;删除和重新执行时额外校验记录归属。批量删除时,非本人记录会被跳过并在返回结果中告知前端,前端据此提示用户。

3.2 实体序列化与循环引用

QueryHistory实体通过@ManyToOne关联了UserInfo实体,直接返回实体会导致Jackson序列化循环引用。解决方案是在Controller中手动构建Map<String, Object>,只选取需要的字段。统计接口使用JdbcTemplate直接查原生SQL,绕开了JPA实体,返回的数据结构也更灵活。

3.3 执行结果的多格式解析

历史记录中保存的executionResult字段可能是不同格式:后端formatQueryResults生成的是Tab分隔文本(表头 + 分隔线 + 数据行),而重新执行返回的queryResults是结构化的List<Map<String, Object>>。前端parseResultToTable需要兼容这两种格式——先尝试JSON解析,再尝试Tab分隔文本解析,最后回退到纯文本。这种多层降级的策略确保了不同来源的数据都能正确展示。

3.4 ECharts双Y轴图表设计

统计图表使用双Y轴是因为查询次数和成功率的数值量级差异很大——次数可能是几十上百,成功率是0-100的百分比。如果放在同一个Y轴上,成功率的变化趋势会被完全淹没。左轴柱状图展示绝对数量,右轴折线图展示百分比趋势,两者配合可以直观看出查询量和质量的变化关系。

四、开发总结

本次开发完成了历史记录管理页面的全部功能,包括后端6个REST接口(分页查询、关键词搜索、单条删除、批量删除、重新执行、查询统计)和前端完整的页面交互(表格展示、多条件筛选、分页导航、复选框批量选择、批量删除、详情弹窗、执行结果表格可视化、重新执行结果弹窗、ECharts查询趋势统计图表)。页面集成了统一导航栏和登录态校验,导航栏的历史记录入口也随之生效。所有接口都基于用户ID做数据隔离,删除和重新执行操作都有归属权限校验。

五、后续规划

  1. 后续可以考虑支持历史记录导出功能

本次开发提示词

任务二:前端历史记录管理页面

当前状态:没有history.html历史记录管理页面,没有history.js。QueryHistory实体类和QueryHistoryRepository已存在且已完善(含用户ID过滤),但前端无法查看。没有HistoryController.java提供REST接口。

需要实现:

  1. 创建HistoryController.java,提供以下接口:
    • GET /api/history/list — 分页查询当前用户的历史记录(从请求属性获取userId)
    • GET /api/history/search?keyword=xxx — 按关键词搜索当前用户的历史记录
    • DELETE /api/history/{id} — 删除单条历史记录(软删除)
    • POST /api/history/{id}/reexecute — 重新执行某条历史记录的SQL
  2. 创建history.html,包含:
    • 历史记录列表(表格展示:查询时间、自然语言问题、生成的SQL、执行状态)
    • 搜索框(按关键词搜索)
    • 筛选条件(按执行状态、时间范围)
    • 分页组件
    • 删除按钮(单条删除)
    • 重新执行按钮
  3. 创建history.js,实现:
    • 列表加载(调用后端分页接口)
    • 搜索功能
    • 分页切换
    • 删除确认
    • 重新执行(调用后端接口后跳转到chat.html并展示结果)
  4. 导航栏中历史记录链接已预留(href=“history.html”),页面完成后自动生效

补充完善:
5. 批量删除功能:后端新增POST /api/history/batch-delete接口,前端表格添加复选框列和批量操作栏
6. 详情弹窗执行结果表格可视化:解析executionResult为HTML表格展示,重新执行结果用弹窗表格展示替代alert
7. 查询趋势统计:后端新增GET /api/history/statistics接口(按日/周/月统计),前端用ECharts双Y轴图表展示

可复用的现有资源:

  • QueryHistoryRepository已提供完整的按用户ID过滤查询方法
  • QueryHistory实体类字段齐全
  • 前端api.js、stateManager.js可直接复用

要求:

  • 使用Spring Boot标准分层架构
  • 所有类和方法添加中文注释
  • 使用统一的ApiResponse格式返回数据
  • 异常由GlobalExceptionHandler统一处理
  • 前端使用原生HTML/CSS/JS,不使用框架
  • 新页面需添加统一导航栏(复制现有页面导航栏结构)
  • 新页面需添加登录态校验(复制现有页面内联校验脚本)
  • 后端编译无错误
http://www.rkmt.cn/news/1468974.html

相关文章:

  • 【课程设计/毕业设计】基于SpringBoot与微信小程序的医疗器械预定系统基于springboot+微信小程序的医疗器械预定小程序【附源码、数据库、万字文档】
  • 《上海企业/机构搬迁服务商评估指南:7个核心维度,避开90%的坑》 - 知行集录
  • 如何快速掌握免费开源AMD Ryzen调试工具:完整使用指南
  • FEMTO-ST轴承数据集实战:用LSTM网络做剩余寿命预测(含PyTorch代码)
  • AI产品负责人必读:2024最新版用户反馈分级响应机制(含GDPR合规采集checklist)
  • NS-USBLoader:Switch游戏文件管理的终极解决方案,新手也能轻松上手
  • NEURON vs. Brian2 vs. NEST:三大神经模拟器怎么选?从项目需求到上手难度全对比
  • 运维避坑实录:从硬盘D状态到Foreign配置,Storcli/Arcconf排错实战指南
  • 终极程序员投资指南:如何在VSCode中打造你的智能投资工作台
  • 终极B站视频解析实践:如何轻松获取高清视频资源
  • 别再死磕理论!用Multisim/Proteus仿真快速验证电子设计大赛仪器仪表方案(以数字存储示波器为例)
  • 数据驱动的内容增长:CSDN AI数字营销会员卡7天实测——全维度数据监测与多平台分发效率革命
  • 2026年6月知名的超声波振动筛厂商推荐,辣椒粉振动筛/圆形摇摆筛/柠檬酸摇摆筛,超声波振动筛源头厂家有哪些 - 品牌推荐师
  • GeneralUpdate v10.5.0-beta.2 Release Notes
  • 蚌埠SEO优化公司|企业网站排名提升,蚌埠搜索引擎优化服务商选择指南 - 招财兔数字员工
  • 如何用Ultralytics YOLO构建高效的关键点检测数据集:从标注到训练的完整指南
  • 三步打造你的智能仪表盘:用Obsidian实现个性化配置与效率提升
  • 全面解析CaptfEncoder V3:5大核心特性构建的跨平台安全工具套件
  • 从破解到生成:手把手教你用x64dbg和IDA搞定那个KeygenMe(附完整POC代码)
  • 从iPhone信号门到5G体验:聊聊高通发家的BP基带芯片到底有多重要
  • 桂林SEO优化公司|企业网站排名提升,桂林搜索引擎优化服务商选择指南 - 招财兔数字员工
  • 告别手动启动!Win10下为金仓V8数据库添加开机自启服务的保姆级教程
  • QMCDecode免费教程:3步解锁QQ音乐加密格式,实现跨平台播放自由 [特殊字符]
  • NEURON vs. Brian2:两大神经模拟器怎么选?从应用场景到上手难度全对比
  • Kubernetes DaemonSet — 企业级应用场景与实战实例【20260605】002篇
  • 如何快速搭建40+平台直播自动录制系统:终极完整指南
  • 排队免单系统底层设计:四种分配算法拆解,无预支资金的合规营销架构方案
  • 2026年 重庆化工原料厂家推荐榜单:氯化铵/硫酸铵/氯化钾及甲醇/甲醛/甲缩醛/大孔树脂优质供应商精选! - 品牌企业推荐师(官方)
  • 威海SEO优化公司|企业网站排名提升,威海搜索引擎优化服务商选择指南 - 招财兔数字员工
  • GD32F303软件I2C驱动AT24C02避坑指南:从原理图勘误到稳定读写