当前位置: 首页 > 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.jsqmd.com/news/957370/

相关文章:

  • 【不可逆的临界点已至】:2024全球创意工作者脑电图实测显示——连续使用生成式AI超47分钟,前额叶活跃度下降32%
  • 宿舍党福音:用刷好Padavan的斐讯K2路由器搞定校园网锐捷6.41静态IP认证(附WinSCP详细配置)
  • 2026年居家园艺用品优质品牌推荐:营养土/电动喷壶/气压喷壶/家用园艺工具套装优选盘点 - 海棠依旧大
  • 莆田SEO优化公司|企业网站排名提升,莆田搜索引擎优化服务商选择指南 - 招财兔数字员工
  • 大语言模型实践指南:从理论到部署的完整技术路径
  • AI产品PRD写完即过?12个关键动作揭秘传统PM转型AIPM的必经之路!
  • 《上海企业/机构搬迁服务商评估指南:7个核心维度,避开90%的坑》 - 知行集录
  • 告别数据线!保姆级教程:用Scrcpy和ADB实现Android手机无线投屏到Windows电脑
  • 从网表文件到仿真曲线:HSPICE新手入门,手把手教你跑通第一个TFT仿真
  • 【课程设计/毕业设计】基于SpringBoot与微信小程序的医疗器械预定系统基于springboot+微信小程序的医疗器械预定小程序【附源码、数据库、万字文档】
  • 别再死记硬背了!用Python(NumPy/SymPy)动手验证Hamilton-Cayley定理,理解矩阵的‘宿命’
  • Sora 2深度图生成能力解禁(仅限首批237家认证实验室):动态遮挡补偿+多视角一致性校准双引擎实测报告
  • 别再傻傻分不清!LSI SAS3008直通卡与SAS3108阵列卡工具命令实战对比(附sas3ircu与storcli常用命令清单)
  • FEMTO-ST轴承数据集实战:用LSTM网络做剩余寿命预测(含PyTorch代码)
  • 如何快速掌握免费开源AMD Ryzen调试工具:完整使用指南
  • IEEE/ACM论文模板的‘作者与单位’字段:从基础配置到高级自定义(含hyperref技巧)
  • 揭阳SEO优化公司|企业网站排名提升,揭阳搜索引擎优化服务商选择指南 - 招财兔数字员工
  • AI产品负责人必读:2024最新版用户反馈分级响应机制(含GDPR合规采集checklist)
  • 直播录制终极指南:用DouyinLiveRecorder实现40+平台无人值守录制
  • 3步完成浏览器图片格式转换:Save Image as Type完整指南
  • NS-USBLoader:Switch游戏文件管理的终极解决方案,新手也能轻松上手
  • 小程序毕业设计-基于Android的智能旅游管家的设计与实现基于Android的智慧旅游平台设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • NEURON vs. Brian2 vs. NEST:三大神经模拟器怎么选?从项目需求到上手难度全对比
  • Inter字体完整指南:为什么它是现代数字排版的终极解决方案?
  • 2026年上海浦东新区遗产纠纷律所评测:收费透明度与实力对比 - 奔跑123
  • Dell服务器S系列软RAID管理:除了创建,你更该知道的磁盘交换与状态监控技巧
  • 开源汉字转拼音高效解决方案:为何TinyPinyin是Java/Android开发者的首选?
  • 运维避坑实录:从硬盘D状态到Foreign配置,Storcli/Arcconf排错实战指南
  • SPICE仿真器怎么选?HSPICE、Spectre、PSpice对比与避坑指南
  • 徐州SEO优化公司|物流商贸搜索曝光,徐州网站优化公司能力解析 - 招财兔数字员工