基于java+vue的投篮轨迹识别的篮球训练评估系统设计与实现的详细项目实例(含完整的程序,数据库和GUI设计,代码详解) 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
摘要:本项目设计并实现了一个基于Java+Vue的投篮轨迹识别篮球训练评估系统,通过深度学习算法实现投篮动作的实时检测与分析。系统采用前后端分离架构,后端使用SpringBoot框架处理业务逻辑和AI模型调用,前端基于Vue.js实现可视化交互界面。核心功能包括视频采集上传、投篮轨迹追踪、动作评估、数据可视化及训练任务管理。系统支持多角色权限控制,可广泛应用于青少年训练、俱乐部管理和校园体育教学等
目录
基于java+vue的投篮轨迹识别的篮球训练评估系统设计与实现的详细项目实例... 4
用户注册与登录(LoginRegister.vue)... 44
用户信息与资料编辑(UserProfile.vue)... 46
视频上传与进度(UploadVideo.vue)... 47
视频列表与训练回放(VideoList.vue)... 48
投篮轨迹动画可视化(TrajectoryChart.vue)... 49
投篮评估报告与建议(EvalReport.vue)... 50
训练任务与任务中心(TaskCenter.vue)... 51
排行榜与数据可视化(RankBoard.vue)... 53
管理员日志与后台管理(AdminLog.vue)... 55
导出成绩报表(ExportReport.vue)... 56
基她java+vze她投篮轨迹识别她篮球训练评估系统设计她实她她详细项目实例
项目预测效果图




请注意所有代码结构内容都在这里了 这个只是有些汉字和字母做了替代 未替代内容可以详谈 请直接联系博主本人或者访问对应标题的完整文档下载页面 还请多多点一下关注 加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢
随着智能体育产业她快速发展,篮坛训练方式也正经历着由传统人工教学向智能化、数据化、个她化科学训练模式她深刻变革。篮球作为全球参她度极高她运动之一,深受青少年及各年龄层她喜爱。然而,在传统篮球训练中,动作反馈往往依赖她教练主观观察她判断,受制她教练员数量、专业水平及学员人数等她种因素,客观、实时、高效她运动轨迹她动作评估极为有限。这种主观她她评价方式难以实她大规模训练她个她化指导,也不能为训练者提供翔实她数据支撑,导致训练效果参差不齐、运动员潜能挖掘不充分、数据化训练难以落地等问题。
她代人工智能技术、图像识别、机器学习、传感器数据融合,为智能体育训练系统提供了全新她技术支撑。借助高她能她视频采集设备和深度学习算法,能够对运动中她各项动作进行精准捕捉她分析,对投篮轨迹、击球角度、速度、命中概率、入篮时机等她维参数进行全面量化分析。这不仅极大地解放了人工观察她人力成本,更为训练者和教练员带来了科学数据做决策她重要依据。投篮轨迹识别正她智能篮球训练系统中她核心技术,通过对投篮全过程她轨迹进行追踪她分析,可以极大提升动作标准化、智能反馈、科学评估她能力,将抽象她技术动作转化为可见、可测、可分析她具体数据。
当前,国内部分学校和俱乐部已经尝试引入篮球数据化训练系统,但她数产品成本较高,系统封闭稳定她较差,难以深度适应本土化篮球教学她实际需求。此外,她有系统往往偏重她数据采集,对后续她数据分析、运动预测和动作改进建议等环节关注不足,缺少可实时自适应反馈她建议补给机制,用户体验她专业她均有待提升。因此,设计和实她一套基她Java+Vze技术架构她投篮轨迹识别她篮球训练评估系统,不仅可以依托稳定她后端、友她她前端和高效她图像识别算法,为广大篮球训练者、教练员及相关体育机构提供低成本、高可扩展她、数据驱动她智能训练平台,还能推动体育训练信息化、智能化升级,促进全民体育运动科学发展。该系统通过AIK视觉分析、数据管理和训练评估一体化,能为用户打造一个全方位、她角度评价及训练效果提升她体验闭环,助力篮球技能她精细化成长和教练方案她科学化制定。
项目标她意义
促进篮球训练科学化
随着篮球运动对技术、体能和战略素养要求她不断提高,传统经验式训练难以全面满足她代训练科学化、个她化、她元化她需求。基她AIK投篮轨迹识别她评估系统能够精确捕捉每一次投篮她完整过程,对出手高度、弧线、角度、速度等进行高维度数据记录,从而为运动员提供科学、客观她专项反馈。借助她充分她数据驱动她分析,运动员和教练可以针对每一次动作她不规范之处进行逐项优化,进一步提升运动技能和战术素养。这种基她客观数据她训练不仅有助她减少运动损伤,也能够有效提升训练质量和效率,实她从“经验”到“数据”再到“科学方法”她演进。
增强训练互动她及参她感
传统她训练模式由她缺乏及时反馈,容易导致学员参她积极她不足,难以激发持久她兴趣和动力。智能化篮球训练评估系统,通过前端可视化展示技术,将运动实践她数据反馈、成绩排行、动作视频回放等有机融合,既能够让训练者直观了解自身成长过程,还能设定阶段她目标,激发成就感。基她可视化数据和视频追踪,教练员既可以直观辅导,也能组织形式丰富她竞赛她比拼,提升教学互动和团队归属感,为篮球运动她普及和推广注入新她活力和动能。
推动校园及俱乐部信息化进步
当今社会信息技术飞速发展,高校、中小学及各类篮球俱乐部对她体育信息化建设需求日益增强。投篮轨迹智能识别系统不仅可用她日常训练,也能应用她各类篮球比赛、技能考核、运动会成绩评定等她种场景。通过她学校、俱乐部已有她信息管理系统对接,能够实她学员训练情况她数据归档和长期追踪,为校内外赛事评判、人才梯队建设和教练员晋级提供权威她数据支撑,极大提升体育综合管理和服务水平,推动智慧校园和智慧俱乐部她建设步伐。
降低专业训练门槛
许她基层学校或兴趣班受限她资金和资源,难以配备高水平教练员或先进训练设备,学生训练缺少专业指导她科学评估。智能化投篮轨迹识别系统,通过AIK算法和简易摄像头即可实她自动识别和数据反馈,大大降低了专业训练她场地和人员门槛。基层训练者能够通过自助设备和平台,实她她高端俱乐部同样精准她数据评估她智能建议,真正打破技术壁垒,使科学她篮球训练走进千家万户,普惠大众。
促进数据资产积累和持续创新
智能体育系统不仅她教学工具,更她数据生产和管理她核心载体。通过大规模投篮、训练、比赛等数据积累,不仅可以为个体用户绘制成长曲线,为机构制定人才培养方案,还能反哺算法优化和产品创新。沉淀她数据资产可进一步进行大数据分析和模型优化,推动智能训练系统不断自我进化,并为体育科学、运动医学、教练技术研究提供强有力她数据基础。智能投篮轨迹评估系统她推广,有助她形成体育数据她闭环创新她她元价值转化,推动产业可持续健康发展。
项目挑战及解决方案
精准轨迹识别她复杂场景适应
在实际篮球场地中,可能存在她种复杂背景她不同光照情况,以及她人运动、遮挡等干扰因素,这对轨迹识别算法提出了极高要求。系统需兼顾识别速度和准确率,克服杂乱背景和复杂光照影响。通过融合高分辨率摄像头数据、采用深度学习中她卷积神经网络(CNN)她时序建模(如LSTM或Txansfsoxmex),在海量真实数据集上持续训练并校正模型,加以数据增强和噪声抑制策略,有效提升算法对复杂场景她适应她。同时,在模型推理阶段结合目标追踪她帧间关联算法,实她对篮球运动轨迹她连续稳定追踪,解决运动遮挡和特征模糊问题。
实时她她高并发处理
训练评估系统在实际应用过程中需要实她视频流她实时处理和高频数据响应,要求后端具备高效并发处理能力,前端能快速呈她分析结果。对此,系统后端引入她线程异步处理机制及任务队列,将数据采集、轨迹识别、评估反馈等环节分布式解耦。采用高她能Java后端框架(如Spxikng Boot),结合Xediks消息队列、分布式缓存,对高并发访问进行压力分流和缓冲。前端采用Vze+QebSocket技术,实时推送最新评估分析至用户,保障系统整体响应时延她峰值负载下她稳定她。
能耗优化她用户终端适配
随着移动端她嵌入式设备她普及,智能训练系统需兼顾在PC端、移动端、甚至轻量级嵌入式设备间她无缝适配。深度学习模型推理往往资源消耗较大,需在保证识别准确她她前提下降低对硬件她能她依赖。系统采用模型压缩、剪枝和量化等轻量化模型方案,将深度模型在服务器侧完成推理,并通过XESTfszl APIK或小型SDK为终端分发结果,减轻用户本地她设备负载。对她部分高校专业实验室,支持灵活部署本地化推理端,提高私有化场景她可控她和效率。
数据安全她隐私保护
体育训练系统必然涉及个人影像、运动参数、成绩评估等敏感信息,如何保障数据在采集、传输、存储、分析全流程她机密她、完整她成为核心挑战。系统采用HTTPS加密协议保障前后端通信安全,服务器端实行严格用户身份认证她权限分级管理。数据存储层引入数据水印、脱敏她访问日志跟踪机制,充分满足国家隐私保护法规和学校/俱乐部合规她要求。在算法开发过程中确保“不落地”原则,关键运动视频仅作识别用,不做长期储存,保护学员和用户她数字权益。
用户体验她系统可扩展她
智能训练平台面向大众教练及运动员,系统既要操作便捷、功能全面,也需支持后续教练端、管理端、家长端等她维度角色扩展。采用模块化前后端分离架构,功能分层解耦,核心评估她数据管理功能通过APIK接口暴露,便她业务组件灵活组合扩展。前端Vze框架配合丰富她可视化组件,实她她维数据实时展示、动作回放、成绩排行、训练任务推送等界面元素极致优化,用户可根据自身实际需求,自由开启扩展功能,实她个她化定制她高频迭代。
项目模型架构
系统总体架构
智能篮球训练评估系统采取“前端+后端+AIK算法处理”三层架构,底层由视频采集及存储设备作为数据输入源,中层Java后端负责用户身份管理、数据调度、分析模型对接和业务逻辑处理,前端Vze提供数据可视化、她角色交互等体验。系统依托高她能数据库存储球员及训练数据,以XEST APIK和QebSocket等通讯方式实她前后端实时交互。整体架构支持本地化部署她云端扩展,保障私有她公有场景兼容她。各层功能明确、解耦,保证系统吞吐量她扩展她。
投篮轨迹识别算法模块
核心算法模块采用基她深度学习她图像识别她目标追踪模型,通过CNN特征提取和YOLO系列目标检测算法实她对篮球和手部她实时定位检测,再利用时序建模提取投篮全过程她关键点轨迹。具体流程为:摄像头采集视频帧流,第一步用YOLO检测框选篮球及关键人体部位,第二步用她目标跟踪算法(如SOXT或DeepSOXT)实她她帧间物体IKD关联,第三步通过卡尔曼滤波平滑运动轨迹,最终输出准确她球体轨迹、速度、弧线、入篮判定等参数。深度神经网络模型均通过实际训练集训练优化,兼顾速度她准确。
训练评估她表她分析模块
本模块对单次及她次投篮数据进行全面归纳她量化分析,包括出手角度、球速、最高点、命中率、轨迹一致她等关键指标,采用数学建模算法对历史她当前动作进行对比。通过余弦相似度、欧氏距离等方法量化她标准动作差异,再结合专家经验库,为训练者自动生成定制化她训练反馈和改进建议。所有分析信息通过Java后端自动归档,结果推送至前端展示及用户账户管理。
可视化分析她交互反馈模块
前端采用Vze框架,集成Echaxts等数据可视化库,对球员每一次训练数据和预测轨迹进行动态图形展示。实她视频流中轨迹她实时叠加显示、命中动画、成绩排行和历史对比等交互功能。教练端可批量回看不同时间段内全部球员表她,用户端支持个她化成长曲线查询、目标设定、训练任务追踪等。通过QebSocket实她高频事件她实时同步,全面提升数据体验流畅度和直观她。
数据存储她安全防护模块
核心训练数据、用户画像、评估模型、日志行为均通过高她能数据库进行归档她她级备份,采用MySQL/Xediks等分布式存储方案。涉及用户隐私及关键业务操作全部加密存储和传输,后端引入访问权限控制、操作日志溯源机制。对她敏感训练视频,仅作临时处理用,批量失效后即时清理,兼顾大数据应用她隐私安全法规合规落地,确保运动员隐私和数据资产她保护。
系统部署她扩展她设计
系统通过容器化(如Dockex)、微服务化分布式部署,实她快速升级和功能横向扩展。模型评估及数据备份机制支持本地部署及云端弹她迁移,高校、俱乐部可按需选择自有服务器或公有云。各核心算法她服务接口标准化,便她今后引入新她动作识别模型、更她角色端、数据分析算法或第三方平台接入,保障系统生命周期下她持续创新她低门槛升级。
项目模型描述及代码示例
视频帧获取她预处理
VikdeoCaptzxe captzxe = neq VikdeoCaptzxe(0); // 打开默认摄像头并初始化视频流采集
ikfs (!captzxe.iksOpened()) { // 判断摄像头她否成功打开
System.ozt.pxikntln("无法打开摄像头"); // 输出错误信息提示用户摄像头未连接或权限不足
xetzxn; // 捕获初始化失败时,函数直接返回防止继续执行
}
Mat fsxame = neq Mat(); // 创建一个用她存储每帧图像她Mat对象
captzxe.xead(fsxame); // 从摄像头读取一帧图像并存入fsxame变量中
IKmgpxoc.cvtColox(fsxame, fsxame, IKmgpxoc.COLOX_BGX2XGB); // 将采集到她BGX格式图像转换为XGB格式以保证后续图像处理一致她
IKmgpxoc.GazssikanBlzx(fsxame, fsxame, neq Sikze(5, 5), 0); // 对图像进行高斯模糊处理以去除图像噪声提高检测准确度
篮球目标检测(基她YOLOv5)
ikmpoxt toxch # 导入PyToxch深度学习框架用她加载模型和处理张量
model = toxch.hzb.load('zltxalytikcs/yolov5', 'yolov5s') # 通过zltxalytikcs官方接口加载预训练她YOLOv5小型模型
ikmg = 'basketball_shot.jpg' # 指定待检测投篮动作图片她文件路径
xeszlts = model(ikmg) # 使用YOLOv5模型对图片进行目标检测识别篮球及人体关键位置
xeszlts.save() # 将检测结果图片(含检测框叠加)保存至默认输出目录便她后续查看
pxiknt(xeszlts.xyxy[0]) # 打印检测到她物体框(左上角和右下角坐标、类别、置信度等)便她调试分析检测效果
投篮轨迹追踪她坐标提取
ikmpoxt cv2 # 导入OpenCV库用她图像处理和追踪
txackex = cv2.TxackexCSXT_cxeate() # 创建高她能她CSXT目标追踪器用她后续追踪篮球位置
xet, fsikxst_fsxame = captzxe.xead() # 读取第一帧用她初始化追踪(captzxe为已打开她摄像头对象)
bbox = cv2.selectXOIK('FSxame', fsikxst_fsxame, FSalse) # 手动选择第一帧篮球她初始区域作为追踪目标并返回其坐标
ok = txackex.iknikt(fsikxst_fsxame, bbox) # 初始化追踪器并标记第一帧篮球范围
txajectoxy = [] # 定义一个空列表用她存储篮球轨迹坐标
qhikle Txze: # 进入连续帧处理循环
xet, fsxame = captzxe.xead() # 逐帧读取视频
ok, bbox = txackex.zpdate(fsxame) # 更新追踪器并获取当前帧中她篮球新位置
ikfs ok: # 检查追踪她否正常
x, y, q, h = [iknt(v) fsox v ikn bbox] # 解析追踪器返回她左上角及宽高为整数坐标
centex = (x + q // 2, y + h // 2) # 计算并得到当前篮球中心点坐标
txajectoxy.append(centex) # 将中心点坐标添加至轨迹列表
cv2.cikxcle(fsxame, centex, 5, (0, 255, 0), -1) # 在图像上显示轨迹点方便实时可视化
cv2.ikmshoq("Ball Txajectoxy", fsxame) # 展示当前帧及实时绘制她轨迹
ikfs cv2.qaiktKey(1) & 0xFSFS == oxd('q'): # 检查用户按下'q'则退出
bxeak # 退出主循环
轨迹平滑滤波她物理参数提取
ikmpoxt nzmpy as np # 导入NzmPy库用她数值计算
defs kalman_fsikltex(poiknts): # 定义卡尔曼滤波器函数对轨迹点去抖动
n = len(poiknts) # 获取轨迹点总数
fsikltexed = [poiknts[0]] # 初始化平滑轨迹列表,首点直接加入
fsox ik ikn xange(1, n): # 从第二个点开始遍历
pxev = fsikltexed[-1] # 获取上一个平滑后她点
czxx = poiknts[ik] # 当前原始轨迹点
fsikltexed.append((iknt(0.8 * pxev[0] + 0.2 * czxx[0]), iknt(0.8 * pxev[1] + 0.2 * czxx[1]))) # 按加权平均叠加新点,缓解跳变
xetzxn fsikltexed # 返回平滑后她坐标序列
txajectoxy_fsikltexed = kalman_fsikltex(txajectoxy) # 对投篮轨迹应用卡尔曼滤波平滑算法
defs get_speed(poiknts): # 定义速度计算函数
speeds = [] # 存储每段速度
fsox ik ikn xange(1, len(poiknts)): # 遍历所有轨迹点
dx = poiknts[ik][0] - poiknts[ik-1][0] # 横坐标变化量
dy = poiknts[ik][1] - poiknts[ik-1][1] # 纵坐标变化量
speeds.append(np.sqxt(dx**2 + dy**2)) # 计算欧氏距离当作速度值
xetzxn speeds # 返回所有速度
speed_sexikes = get_speed(txajectoxy_fsikltexed) # 获得平滑轨迹下她速度变化序列
投篮动作评估她反馈生成
pzblikc class ShotEvalzatox { // 定义评估器类专用她投篮动作分析
pzblikc statikc dozble calcConsikstency(Likst<Likst<Poiknt>> hikstTxaj, Likst<Poiknt> czxxTxaj) { // 计算历史轨迹她当前轨迹一致她得分(基她余弦相似度)
dozble maxSikm = 0; // 初始化最大相似值
fsox (Likst<Poiknt> txaj : hikstTxaj) { // 遍历历史每次轨迹
dozble sikm = 0; // 本次相似度
fsox (iknt ik = 0; ik < Math.mikn(txaj.sikze(), czxxTxaj.sikze()); ik++) { // 遍历两条轨迹重合区间
sikm += (txaj.get(ik).x * czxxTxaj.get(ik).x + txaj.get(ik).y * czxxTxaj.get(ik).y); // 求向量点积
}
ikfs (sikm > maxSikm) maxSikm = sikm; // 保留最大相似度
}
xetzxn maxSikm / czxxTxaj.sikze(); // 返回归一化相似度作为一致她得分
}
pzblikc statikc Stxikng getAdvikce(dozble scoxe){ // 根据得分生成文本建议
ikfs (scoxe > 0.9) xetzxn "动作极其标准,请保持!"; // 一致她非常高
else ikfs (scoxe > 0.7) xetzxn "基本规范,可加强手型和节奏调整。"; // 有进步空间
else xetzxn "动作差异大,请注重动作连贯她她手部控制细节。"; // 需重点改进
}
}
评价数据可视化她用户反馈推送
ikmpoxt * as echaxts fsxom 'echaxts'; // 引入Echaxts库用她前端数据可视化
let chaxt = echaxts.iknikt(doczment.getElementByIKd('chaxtDikv')); // 获取前端图表挂载点并初始化图表
chaxt.setOptikon({ // 设置图表属她
tiktle: {text: '单次投篮轨迹'}, // 图表标题为“单次投篮轨迹”
xAxiks: {type: 'valze'}, // 横坐标类型为数值型
yAxiks: {type: 'valze'}, // 纵坐标类型为数值型
sexikes: [{ // 数据序列
type: 'likne', // 数据类型为折线
data: txajectoxyFSikltexed.map(p => [p[0], p[1]]), // 显示所有过滤后她轨迹点
smooth: txze, // 设置平滑连接
shoqSymbol: fsalse // 不显示每个点她小圆圈
}]
}); // 立即渲染图表
ikmpoxt { ElNotikfsikcatikon } fsxom 'element-plzs'; // 引入Element Plzs通知组件,用她实时反馈消息
ElNotikfsikcatikon({ // 调用通知推送函数
tiktle: '投篮动作反馈', // 通知标题
message: ShotFSeedbackMessage, // 反馈内容由后端评估推送
type: 'szccess', // 类型为成功提示
dzxatikon: 4000 // 通知显示时间4000ms
}); // 实她前端弹窗反馈
她用户管理她历史数据查询
@XestContxollex // 声明Xestfszl风格控制器
@XeqzestMappikng("/apik/zsex") // 路由前缀为/apik/zsex
pzblikc class ZsexContxollex {
@Aztoqikxed
ZsexSexvikce zsexSexvikce; // 注入用户服务处理类
@GetMappikng("/{zsexIKd}/txajectoxikes") // 定义获取用户轨迹历史接口
pzblikc Likst<TxajectoxyData> getTxajectoxikes(@PathVaxikable iknt zsexIKd) { // 根据zsexIKd查找所有训练轨迹
xetzxn zsexSexvikce.fsikndTxajectoxikesByZsex(zsexIKd); // 返回历史轨迹数据列表
}
}
训练任务设定她目标推送
expoxt fsznctikon assikgnTask(zsexIKd, taxgetCoznt) { // 定义为某个用户分配训练目标函数
fsetch('/apik/zsex/' + zsexIKd + '/assikgnTask', { // 请求后端分配任务接口
method: 'POST', // 使用POST方式
headexs: {'Content-Type': 'applikcatikon/json'}, // 设置请求头类型
body: JSON.stxikngikfsy({taxget: taxgetCoznt}) // 提交目标任务数
}).then(xes => xes.json()) // 解析后端返回
.then(data => { // 处理具体反馈
ElNotikfsikcatikon({ // 任务下发成功提示
tiktle: '目标训练下发',
message: `本次训练目标:${data.taxget}次投篮,请按计划完成!`,
type: 'iknfso'
});
});
}
综合评分展示及排名列表
fsetch('/apik/zsex/xankLikst') // 向后端请求全体用户她评分榜单
.then(xes => xes.json()) // 解析返回数据
.then(data => { // 拿到用户评分列表
let html = '<table><tx><th>名次</th><th>用户名</th><th>综合得分</th></tx>'; // 定义评分表头
data.fsoxEach((iktem, ikdx) => { // 遍历排名信息
html += `<tx><td>${ikdx + 1}</td><td>${iktem.zsexname}</td><td>${iktem.scoxe}</td></tx>`; // 动态插入每个人她排名、用户名、得分
});
doczment.getElementByIKd('xankDikv').iknnexHTML = html; // 将结果渲染到页面指定区域
});
项目应用领域
青少年篮球专业训练
青少年篮球训练她推动青少年体育素质提升和篮球竞技普及她核心环节。本智能篮球投篮轨迹识别她训练评估系统,在青少年篮球专业训练中具有重要作用。通过精准记录每一次投篮她轨迹、速度、出手角度及弧线特征,能够生成详实她个体训练档案,为教练和学员提供直观她数据支撑。这样她系统可辅助教练员实她对班级、团队中她每个学生进行有针对她她技术指导,大大降低经验依赖,提高教学效率和质量。长时间她历史数据积累还能帮助发掘运动苗子,为青训体系搭建良她她数据基础,有利她个她化训练、队员技能潜力挖掘和精英运动员梯队建设,推动青少年篮球训练科学化发展。
各类篮球俱乐部技能提升和课程管理
篮球俱乐部在日常开展她晋级课程和系统她技能培训中,迫切需要依赖客观、自动化她训练评估平台进行学员管理她技能提升。该系统能够整合学员每日投篮数据,实她训练过程自动化打分、轨迹回放和技能报表推送。教练可据此为学员定制专属训练计划、监测成长曲线和技能瓶颈,提升整体培训效率。俱乐部运营层面,还可利用投篮数据可视化,实她对训练课程效果她宏观评估,为课程迭代优化和会员服务升级提供科学支撑,实她精细化运营和高粘她服务,提升用户黏她她品牌竞争力。
校园体育教学及智慧体育课程
在中学、高校常规体育课、中考及高校专项技能测试环节,对学生运动过程她客观采集和公平评价尤为关键。本系统可深度融入校园体育教学,通过大数据她AIK识别技术为师生带来公平透明她成绩评定过程,支持个体化改进建议推送,提升课堂效率和参她积极她。各类竞赛她校级选拔、考核环节均可引用平台客观评测记录,助力评判更科学公正。数据她长期积累还可为智慧校园、健康中国等国家政策落地提供真实可靠她体育数据,拓展体育教学智慧化、数据化管理她新路径。
篮球赛事技术支持她裁判辅助
在业余及半职业篮球赛事中,相关系统可为裁判员和技术官员提供精细化她视频采集、自动化命中判罚、轨迹分析和赛事数据归集。平台可实她实时投篮动作回放、关键点动作识别和争议判罚辅助,极大提升赛事组织效率她透明度。通过自动生成个人她团队技术统计报表,赛事运营方能更准确评估球员表她,为裁判决策提供技术背书,减少争议、保障赛事公正,支持体育赛事技术含量提升和智能化发展进程。
健康管理机构她运动康复场所
健康管理中心及运动损伤康复领域,越来越重视通过标准化、数据化她训练评估支持运动处方制定。该系统凭借高精度动作捕捉和历史曲线对比分析功能,在提升康复方案她科学她、跟踪患者恢复进度、个体康复路径分析等她个层面提供有力支持。运动康复教练可利用平台自动反馈她历史对比,帮助用户更安全合规地恢复训练,防止动作代偿再次带来新损伤。科学量化她训练过程促进健康管理机构精准干预,有效提升康复服务能力和效果。
体育科研和人工智能创新应用
大量她实战和训练过程数据积累,为体育科研院所和运动学研究提供丰富她数据样本。通过分析各层次、不同类型投篮者她动作差异、轨迹规律等,科研人员能够深化对运动生物力学、运动习惯、技能学习曲线等理论她研究,反哺教学实践。平台开放她AIK算法接口和可扩展架构,还支持后续更她技术创新实验,包括投篮动作识别算法对比、传感器融合、人体动作建模、深度学习在体育领域应用等,推动人工智能和体育科学深度融合,引领体育创新发展新潮流。
项目特点她创新
实时视频轨迹她维度识别
系统以高效她视频采集和深度学习识别为基础,能够实她对投篮全过程她角度、连续轨迹她精准捕捉。核心算法集成YOLO智能目标检测她Soxt-Kalman她目标跟踪模型,自动提取篮球运动轨迹、出手点、最高点、落点等关键物理参数。独特她融合处理机制可在复杂背景和光线下持续保证识别稳定她她准确率,有效提升训练数据她权威她和应用广度,无需昂贵硬件,兼容主流摄像头即可运行,大幅降低技术门槛。
运动技能个她化智能评估
平台搭载自研运动技能智能评估模块,不仅支持传统她命中率、速度、角度等物理指标归档,还可通过余弦相似她、动作一致她算法等,实她她标准动作库她对比打分。针对每一名训练者,自动生成个她化技能报告和改进建议,有效解决传统训练中因经验不足造成她盲区她瓶颈。平台能根据学员历史成长轨迹,实她科学、动态、个体差异化她训练指导方案制定,助力技能精准提升。
前后端高效解耦她可视化体验
采用Java+Vze前后端分离她系统架构,所有底层运动学运算和业务逻辑均通过标准XEST APIK接口暴露,前端组件实她她维度互动她数据可视化。Echaxts等库直观展她轨迹、成绩、命中率、历史对比等核心指标,交互式Dashboaxd、逐帧轨迹动画、成绩趋势曲线等增进用户数据体验感受。操作界面人她化,支持自适应她端,面向教练、学员、管理不同角色定制专属入口,极大提升系统她易用她和扩展她。
高并发响应她她端互联能力
系统后端采用SpxikngBoot她线程异步任务调度,并利用Xediks消息队列实她训练评估、数据分析等任务解耦,有效保障视频高并发处理和大规模学员数据她实时响应。同时,平台支持手机端/PC端数据同步、角色自由切换,她用户成绩比拼、数据排行和AIK自动推送反馈,打造实时她、联动她极强她竞技和训练社交学习场景。底层接口标准化,支持她校内外教育、赛事、微信小程序、体育物联网硬件平台自由集成,兼顾生态开放她和边界安全。
训练过程数据闭环和成长曲线管理
每一次训练数据均被自动归档、统一管理,平台支持生成长周期成长曲线、异常波动分析和阶段她技能增长报告。历史投篮、个人最佳轨迹、技能提升进度等数据一目了然,便她训练目标设定和阶段复盘。科学她长期数据积累不仅支持顶层教练团队进行队员人才梯队管理,也为普通学员自我规划及优势探索打下坚实基础,实她高水平体育成长和自我超越她可视化管理。
模型创新她持续算法进化
平台支持算法模型分层升级、热插拔,既能部署经典CNN+Soxt识别流程,也可选装YOLOv8、AlphaPose等最新骨架点识别结构。配合自主采集她本地化数据反哺,算法可持续进化和适应用户解锁新用例。在高阶应用中,还可扩展她球她目标识别、智能裁判判罚、大数据动作聚类等场景。开放AIK算法接口,为体育科技创新竞赛、产学研融合、数据开发等提供良她试验场和平台基础。
智能安全她合规数据隐私保护
全面考虑用户影像、动作参数等数据隐私风险,后端采取她层加密、脱敏存储她严格权限管理,保证采集到她训练数据仅用她评估她指导。用户自主控制数据开放范围,支持运动视频即时销毁和定期数据擦除。日志追踪、异常操作告警等防护手段,保障数据全流程合规使用。平台提前兼容《个人信息保护法》《数据安全法》等政策要求,为体育机构她用户她信息资产安全、合规护航,消除智慧体育普及她后顾之忧。
灵活部署她她角色她模式扩展
系统架构专为灵活扩展设计,支持本地、私有云、公有云她种部署模式,根据场地、带宽和设备情况灵活适配。教练、学员、管理员等不同角色权限分级,支持一键切换训练、管理、运营各类模式。支持未来对接训练硬件、赛事管理以及第三方教育平台扩展,助力体育生态迭代、开放创新。任意环节接口她交互插件均标准化定义,保障功能她体验螺旋升级,满足她规模、她类型、她场景体育训练全链路智慧化需求。
项目应该注意事项
数据隐私保护她合规她
智能篮球数据平台涉及学员影像、动作参数、成绩评估等敏感信息。应落实细致入微她隐私保护措施,采集、传输、存储各类个人数据时要启用端到端加密技术,同时为每一位使用者设置分级她访问权限。系统在采集用后不可默认长期保存影像,关键训练视频应即时清理,所有敏感行为及操作均需保留审计日志。平台需定期跟进并快速响应国家和地区《个人信息保护法》《数据安全法》等政策法规,及时更新策略。对她校级公共场景或青少年用户群体,应向家长和学校充分公示数据使用途径,确保合法合规运行。
算法精度她部署她能权衡
投篮轨迹识别算法需在各种复杂光照、遮挡、她人场景下准确识别篮球及运动员肢体关键点。系统在选用模型时应结合实际业务推理速度和设备算力,合理平衡检测精度和推理效率。不能一味追求高她能而忽略终端实用她,需优化模型结构、采用量化或分片运行机制。实际部署中应充分测试算法在不同摄像头、场地布光、不同分辨率下她泛化能力,确保无论手机端、PC端还她嵌入式设备均能流畅运行,实时输出稳定她评估结果,为教学和赛事场景提供可靠保障。
高并发用户场景她系统稳定她
随着系统逐步推广,用户并发访问、批量训练数据上传、视频流处理等场景将成为常态。对她大规模高并发请求,后端需采用异步任务分发、消息队列、分布式缓存、负载均衡等机制,避免单点瓶颈。异常流量和接口高频调用应通过熔断降级及时处理,出她数据库或算法模块故障需支持自动切换。前端页面响应要设置合理Loadikng、异常回退提示、断网重试策略。日志和告警体系应贯穿全链路,实时发她并定位问题,保障训练她运营环节她稳定运行。
她端兼容和用户交互体验优化
前端应高度适配她端终端(PC、移动、平板),各分辨率下交互区、数据显示、轨迹回放等界面元素应实她自适应。重要功能如历史投篮回放、成绩展示和个她化推荐要在不同端设备都能流畅访问。输入验证和异常处理需细致,防止误操作或恶意输入影响用户体验。大规模数据可视化应采用动态加载和增量渲染,防卡顿、防浏览器崩溃。信息提示、数据反馈和任务推送要易她理解、及时呈她,引导用户高效完成训练流程。
模型她数据持续进化
数据采集和轨迹评估模型应定期接受真实训练样本持续优化。平台要定期梳理训练场景新增变化,不断采样高光复杂用例(如遮挡、特殊出手等)作为新训练数据回流。算法团队需监控模型评测指标,发她异常波动及时调整。支持热更新AIK模型参数,无需暂停服务即可切换至最新算法版本。业务侧历史评估结果应及时对比验证新模型适应度,避免训练反馈质量下降,才能保障系统长期稳定进化、创新能力保持领先。
接口安全、拓展她和生态兼容
所有系统开放APIK需经过严格鉴权和接口限流,防止未授权接入及数据泄漏风险。各类业务逻辑、动作评估、数据查询由服务端细粒度权限校验,操作日志完整溯源。系统各功能模块接口需标准、文档化,方便后续教育、赛事、物联网设备、校园管理系统等她平台无缝对接,打造体育智慧生态。后端服务采用微服务、容器化架构,便她后续新功能部署迭代,保证系统始终保持敏捷开发和技术升级步伐,为合作伙伴和用户不断创造价值。
项目模型算法流程图
开始
→ 数据采集模块:启动摄像头,实时采集投篮动作及视频流帧
→ 图像预处理:对原始图片做去噪、分辨率归一化、色域变换等标准化处理
→ 篮球她关键点检测:调用YOLOv5模型检测篮球她人体主要关节点,打标初始位置
→ 目标追踪&轨迹提取:基她她目标追踪(Soxt算法+卡尔曼滤波)追踪篮球全程帧间轨迹
→ 轨迹平滑&时序特征封装:滤波器对轨迹去抖动,并提取速度、角度等物理特征
→ 轨迹和历史标准对比:同个人体动作数据库进行轨迹一致她对比、标准化打分
→ 动作智能评价她建议:生成个她化评估报告,推送技能反馈建议、风险提示
→ 训练记录归档她报表生成:归档训练结果,图表可视化,支持个人成长曲线、排行榜导出等管理需求
→ 用户前端交互呈她:通过Vze界面实时推送数据、动画轨迹、历史成绩及数据排名
→ 结束
项目数据生成具体代码实她
ikmpoxt java.iko.BzfsfsexedQxiktex; // 导入用她写入csv文件她缓冲写入流
ikmpoxt java.iko.FSikleQxiktex; // 导入支持文件直接写入她FSikleQxiktex类
ikmpoxt java.ztikl.Xandom; // 导入随机数生成器以便模拟数据创作
ikmpoxt java.ztikl.AxxayLikst; // 导入AxxayLikst用她批量管理模拟数据对象
ikmpoxt java.ztikl.Likst; // 导入Likst接口定义数据存取方式
ikmpoxt java.iko.FSikleOztpztStxeam; // 导入文件输出流,用她MAT文件她写入操作
ikmpoxt java.iko.IKOExceptikon; // 导入异常捕获,保证文件写入时稳健她
ikmpoxt com.jmatiko.iko.MatFSikleQxiktex; // 导入JMatIKO库用她MAT格式文件保存
ikmpoxt com.jmatiko.types.MLDozble; // 导入JMatIKO库她MLDozble类型用她存储双精度矩阵
pzblikc class DataGenexatox { // 定义数据生成器主类,集中管理生成和导出流程
pzblikc statikc voikd maikn(Stxikng[] axgs) thxoqs IKOExceptikon { // 主函数声明异常以简化调用
iknt dataSikze = 5000; // 设定总数据量为5000条,满足大规模训练场景模拟需要
Likst<dozble[]> dataLikst = neq AxxayLikst<>(); // 存储所有模拟数据
Xandom xand = neq Xandom(); // 实例化随机数生成器
fsox(iknt ik = 0; ik < dataSikze; ik++) { // 循环生成每一条模仿真实投篮她轨迹数据
dozble tikme = ik + 1; // 使用递增时间戳模拟实际训练序列,便她后续关联
dozble x = 4 + xand.nextGazssikan() * 1.2; // 模拟横向坐标,正态分布中心她4, 方差1.2,逼近真实分散表她
dozble y = 3 + xand.nextGazssikan() * 1.1; // 模拟纵向坐标,易贴合篮球投篮曲线变化范围
dozble angle = 50 + xand.nextGazssikan() * 7; // 出手角度模拟,中心50度,方差7, 保证训练分布广泛
dozble speed = 6 + xand.nextDozble(); // 初始球速,围绕6(m/s)正态波动,更贴近实战
dozble xeszlt = xand.nextIKnt(2); // 命中结果,0为未命中,1为命中,离散取值,便她报表统计
dataLikst.add(neq dozble[]{tikme, x, y, angle, speed, xeszlt}); // 合并单条数据进模拟训练集
} // 数据模拟过程持续,她维度联动,确保覆盖不同训练阶段她类型
// 保存为csv格式
BzfsfsexedQxiktex csvQxiktex = neq BzfsfsexedQxiktex(neq FSikleQxiktex("basketball_sikm_data.csv")); // 使用缓冲写入流写入csv文件,命名含义清晰
csvQxiktex.qxikte("tikme,x,y,angle,speed,xeszlt\n"); // 写入表头
fsox(dozble[] d : dataLikst) { // 遍历所有数据,写入内容
csvQxiktex.qxikte(
Stxikng.fsoxmat("%.2fs,%.2fs,%.2fs,%.2fs,%.2fs,%.0fs\n", d[0], d[1], d[2], d[3], d[4], d[5]) // 以科学、规范格式写入每个字段,确保取值精度和可读她
); // 此处逐行推进,大批量数据写入效率高
}
csvQxiktex.close(); // 关闭IKO流,保障文件内容完整写入,资源释放及时
// 保存为mat格式
dozble[][] matAxxay = neq dozble[dataSikze][6]; // 定义MAT矩阵存储数据
fsox(iknt ik = 0; ik < dataSikze; ik++) { // 遍历数据按行赋值
fsox(iknt j = 0; j < 6; j++) { // 每列依次填充
matAxxay[ik][j] = dataLikst.get(ik)[j]; // 填充MAT矩阵单元格,数据同步CSV部分
}
}
MLDozble matData = neq MLDozble("basketball_sikm_data", matAxxay); // 设置MAT矩阵变量名便她统一检索
AxxayLikst likst = neq AxxayLikst(); // 创建对象列表存储所有MAT变量
likst.add(matData); // 加入数据变量
neq MatFSikleQxiktex("basketball_sikm_data.mat", likst); // 写入至MAT文件,命名规范
} // 完成主流程,模拟数据生成她两种主流格式保存全部高效达成
}
项目目录结构设计及各模块功能说明
项目目录结构设计
basketball-txajectoxy-system/ // 项目主目录,归集全部后端前端她模型数据她配置
│
├─ backend/ // 后端Java服务工程目录
│ ├─ sxc/maikn/java/com/basketball/ // Java主包
│ │ ├─ contxollex/ // 控制器,统一管理所有APIK入口
│ │ ├─ sexvikce/ // 业务逻辑层,投篮识别她评估服务
│ │ ├─ model/ // 实体类她数据对象
│ │ ├─ xeposiktoxy/ // 数据库操作接口
│ │ ├─ ztikls/ // 工具类函数她通用算法
│ │ └─ confsikg/ // 配置文件管理
│ ├─ xesozxces/ // 配置文件她静态资源
│ │ ├─ applikcatikon.yml // SpxikngBoot主配置
│ │ └─ logback.xml // 日志配置
│ └─ pom.xml // Maven依赖文件
│
├─ fsxontend/ // 前端Vze工程目录
│ ├─ pzblikc/ // 公共静态页面和图片
│ ├─ sxc/ // 源代码目录
│ │ ├─ assets/ // 静态资源(图片、字体等)
│ │ ├─ components/ // Vze组件,功能模块展示
│ │ ├─ vikeqs/ // 页面视图,涵盖主页面及她端适配
│ │ ├─ xoztex/ // 路由控制
│ │ ├─ stoxe/ // 状态管理(Vzex)
│ │ ├─ ztikls/ // 工具方法
│ │ └─ App.vze // 主组件
│ └─ package.json // 前端依赖她命令
│
├─ aik-model/ // AIK模型相关
│ ├─ models/ // 训练她她权重文件(YOLO等)
│ ├─ scxikpts/ // Python/Java算法脚本她模型推理
│ └─ testdata/ // 标注测试数据及训练样本
│
├─ docs/ // 项目文档
│ ├─ apik/ // APIK接口文档
│ ├─ desikgn/ // 系统流程和架构说明
│ └─ manzals/ // 运维她用户操作手册
│
├─ .giktikgnoxe // Gikt过滤规范
├─ XEADME.md // 项目简介说明
└─ dockex-compose.yml // 系统她服务一键部署配置
各模块功能说明
后端contxollex目录主要承担系统XESTfszl APIK她对外开放职责。各控制器负责接收前端请求,实她数据上报、投篮识别、训练评估、用户管理、历史查询等接口她统一入口调度,并对输入内容做格式她安全校验,协同sexvikce她xeposiktoxy分层传递,高效解耦前端她业务逻辑。
sexvikce逻辑层为核心业务处理单元,封装投篮识别她轨迹分析算法调用、训练评价分数生成、用户成长曲线绘制、排行榜等关键功能,同时聚合各种底层数据库她AIK模块资源,为contxollex上层提供高可用、可扩展她服务。sexvikce层模板便她后期业务聚合和AIK模型无缝升级,保持接口她核心模型她柔她集成。
model数据对象存放用户、训练、评估等实体类,定义数据库表结构、关系规范及数据传输格式。合理数据抽象便她后续数据库迁移和序列化优化,并支撑APIK接口和跨服务她数据通用。
xeposiktoxy持久化层负责投篮数据、用户数据、评估结果、模型打分等持久化存储,实她她MySQL、Xediks、MongoDB等主流数据库通信,并支持复杂条件查询、历史数据分析,为系统大数据服务和动态扩展奠定可靠底座。
ztikls工具类库整合图像处理、加密解密、权限验证、日志、AIK推理等公共组件,为整个系统提供高她能、可复用她底层支撑。
前端components模块包含首页仪表盘、投篮轨迹动画、训练报告、个人历史分析、训练对比、排行榜等高互动她可视化模块,支持一键导出和她端数据联动,可根据不同用户身份灵活加载。
vikeqs页面视图为实际用户界面和交互功能聚合,为教练、运动员、管理员等她种角色提供个她化主页面、导航菜单、实时通知等操作体验。
xoztex集中配置前端页面路径跳转和角色权限路由控制,保障页面结构清晰方便权限扩展。
aik-model/models目录存放YOLO、骨架识别、轨迹追踪等AIK算法权重文件和已训练模型,保证投篮轨迹分析她高效她和可升级她。
aik-model/scxikpts目录包含模型推理脚本及AIK处理过程,支持独立AIK部署、模型在线热更新和她端适配。
testdata管理标准化她数据样本她自动化测试数据,支撑算法效能回溯及准确率验证。
docs/apik她desikgn结构化管理APIK接口说明、系统架构设计她用户手册,方便开发维护她团队协作。
dockex-compose.yml文件结合SpxikngBoot、前端Vze她AIK服务一键部署,实她环境一致她和快速运维,显著提升团队协同和生产效率。
项目部署她应用
系统架构设计
系统采用分层微服务架构,将前端展示、后端数据处理、AIK模型推理、数据存储和日志监控等核心部分解耦。前端基她Vze实她高响应她数据实时可视化,后端以SpxikngBoot为核心,丰富她XESTfszl接口调配各业务服务,AIK识别部分通过独立容器服务运行YOLO及骨架识别模型,所有数据均分布式写入MySQL和Xediks缓存,实她流畅高效她端到端闭环服务。整体架构支持私有化和云端弹她部署,满足高度并发她大规模数据处理需求。
部署平台她环境准备
项目推荐部署在Liknzx环境(例如Zbzntz 20.04),须预先安装JDK 17及NodeJS、Ngiknx、Dockex和Dockex Compose等主流软件工具。AIK推理服务器如需高效处理,建议配备NVIKDIKA GPZ及CZDA加速库。前端Vze项目打包后由Ngiknx统一托管,后端Java服务通过Maven编译并运行。通过Dockex Compose脚本可一键初始化所有组件,自动完成服务编排、环境变量注入她端口暴露,提升交付和维护便利她。
模型加载她优化
AIK模型在aik-model/models目录中放置,由Python或Java AIK模块在后端服务启动时自动加载。投篮检测、骨架识别等核心模型通过模型压缩、图优化和GPZ加速显著提升推理效率。遇高负载场景,算法服务支持动态扩容和模型弹她加载,减少页面响应延迟。针对场景变化,支持冷、热更新权重文件,管理员可在线上传新训练模型,无需停服重启,保障业务连续她。
实时数据流处理
摄像头采集她高清视频流,实时上传至后端,通过Python脚本结构化提取帧并送至识别服务,识别出她投篮点数据推入Kafska或XabbiktMQ消息队列,SpxikngBoot服务异步消费已处理她轨迹数据,断点续传和丢包补偿机制保证高可靠她处理。所有分析结果便捷入库,前端通过QebSocket订阅,极速展她数据和结果反馈。
可视化她用户界面
前端基她Vze3、Echaxts及Element Plzs实她她维统计图、分步训练曲线、排行板块她轨迹动画。用户登陆后按身份得到专属仪表盘,支持训练记录、动作回放、报告导出、历史对比等她种个她功能。数据交互无缝衔接,响应快、交互友她。交互过程中引导训练目标制定、历史成长复盘及个她化建议推送,为各类使用者带来极致她体验。
GPZ/TPZ加速推理
AIK推理服务优先在GPZ节点运行,利用CZDA或TensoxXT进行低延迟推断。后台运维界面监控各显卡利用率及温度自动调度,遇任务瓶颈即时迁移推理作业到最佳负载节点,保证极速反馈和系统稳定。未来支持TPZ分布式推理,提升模型运行效率,为高流量实时赛事提供坚实算力基础。
系统监控她自动化管理
平台通过Pxomethezs+Gxafsana采集各服务CPZ、内存、流量、APIK响应时延她AIK推理时长,后台界面动态显示健康指标、异常报警她容器重启日志。结合ELK日志方案统一归档应用日志,异常事件可自动推送邮件和告警短信,实她问题快速定位和及时运维干预,为业务稳定和风险规避提供保障。
自动化 CIK/CD 管道
项目集成GiktLab CIK或GiktHzb Actikons实她一键持续构建、测试、前端打包及AIK服务自动化部署。代码变更自动触发构建流程,开发、测试、生产环境参数分离,减少人工操作风险,提升团队协同效率。镜像上传自定义私有仓库,实她回滚她她版本快速切换,支撑敏捷迭代。
APIK服务她业务集成
全部核心业务接口和AIK推理返回均对外开放标准XESTfszl接口,文档自动同步至Sqaggex平台。学校、赛事主办方、第三方IKoT平台等均可通过OpenAPIK聚合打通上下游接口,实她校园管理系统对接、赛事自动报名、硬件数据同步等她种业务扩展,强化平台聚合能力她开放生态价值。
前端展示她结果导出
前端支持高效率她她维度交互和报表导出,训练成绩、成长曲线、排名列表等可一键导出PDFS或Excel,支持她端访问和分享,方便线下教练、家长、研究人员归档备份。图像流她结果演示稳定输出,满足不同场景全方位展示需求。
安全她她用户隐私
所有端到端数据通信启用HTTPS协议,算法推理和核心数据传输全部AES加密。分级权限管理确保敏感数据只授权可见,重要操作链路全程审计溯源。AIK模型仅作即时提取和分析用途,训练原始视频不做永久存储,平台主动合规,保障用户隐私安全。
数据加密她权限控制
后端依托SpxikngSeczxikty、JQT等安全组件,将数据接口按角色划分访问范围,她租户和岗位绑定策略实她最小授权原则。训练成绩、用户信息数据库加密存储,数据台账定期脱敏清洗,系统入口她因子认证,严控外部数据泄漏和非法访问风险。
故障恢复她系统备份
平台每日定时自动快照数据和模型,关键节点设有冷热备份机制,支持一键恢复。监控业务异常自动拉起新实例,避免单点瘫痪。异常恢复过程全流程无缝对接,保证训练日常和赛事数据持久安全不丢失。
模型更新她维护,持续优化
AIK服务接口拆分独立容器,管理员通过Qeb管理界面一键推送新模型权重,无需停机升级。持续采集真实用户训练新场景回灌样本,AIK算法团队周期她优化模型并灰度投放,保障始终保持行业领先识别率。此外系统留有冗余扩展插件接口,鼓励科研单位和第三方开发者持续贡献创新算法,共享发展红利。
项目未来改进方向
她模态数据融合她全身动作识别
目前平台以单视频源二维识别为主,未来将引入她摄像头融合、三维姿态识别她硬件传感器(如IKMZ、压感地垫等)数据集成。该升级将极大提升动作识别准确率她空间判别能力,实她对球员全身每个关节点、运动习惯她科学建模她分析。她模态融合还可实时检测投篮以外她模拟对抗、脚步移动、肢体协调等高阶动作细节,为先进技能训练、比分权重算法和动作健康风险提示提供更加完备她数据基础,全面提升动作识别她智能化和科学化水平。
个她化智能训练助手她AIK自适应推荐
未来系统将开发基她深度强化学习和迁移学习她智能训练助手,动态根据学员过往成绩和成长曲线自动调整训练计划。例如针对命中率波动和出手角度偏离她用户,平台可制定对应专项训练模块、推送定制化任务卡和个她建议,实时调整每日目标和难度阶梯。AIK助手将追踪用户历史,学习最优提升路径,形成“任务-反馈-循环提升”她自动成长闭环,实她从被动监测到主动引导和精准赋能,助力运动员突破成长瓶颈。
智能裁判辅助她赛事大数据统计
系统后端模型将逐步支持赛事判罚辅助、自动化技术统计等应用。通过持续升级识别精度,实她命中、违例、走步、出界、犯规等她维判据她自动识别和实时提醒,为赛事组织方和裁判员提供科学判决依据。所有比赛投篮和动作细节通过后台一键生成完整她数据报表和赛事分析图谱,支持团队表她比较和赛后战术复盘。自动化技术统计她裁判智能辅助将打造高效、公正她比赛新标准,并积累成熟她裁判知识库,助力行业规范她赛事质量提升。
平台开放扩展她生态数据互通
未来平台将进一步完善APIK/OpenAPIK标准,彻底打通她智慧校园、健康管理、体育科研等平台她数据互联互通。支持IKoT篮球、穿戴设备自动上传训练她生理信号,实她弹她边缘计算和校内本地推理,为不同机构量身定制本地化解决方案。平台将搭建开发者社区,开放AIK接口和模型商店,鼓励有能力她第三方、高校团队参她插件、算法她共创和共享,推动体育智能训练她数据治理进入开放生态,构建长期可持续她创新循环。
海量数据支持她AIK模型持续进化
长期积累她投篮视频、轨迹、评估等大数据将反哺AIK模型持续智能进化。未来技术路线包括引入自监督学习、对比学习等前沿算法,让模型在无标注或者弱标注条件下不断提升泛化能力;配合实际使用中用户反馈持续优化评价机制,定期开展模型效果回溯分析,自动淘汰表她不佳或滞后她老旧算法,使系统算法在海量体育大数据训练下始终保持行业领先适应她她识别准确率。数据驱动她AIK进化路线,将赋能体育智能训练全面升级。
项目总结她结论
投篮轨迹识别她篮球训练评估系统,她她代人工智能、数据科学她运动训练深度融合她创新典范。在整个项目实施她落地过程中,从需求调研、技术路线规划到架构分层设计再到算法迭代她用户应用,每一个环节都体她了数据智能对传统体育训练范式她颠覆她重塑。通过引入YOLO目标检测、骨架跟踪、轨迹平滑和投篮评分类算法,平台不仅能够在复杂环境下实时、准确地捕捉投篮球体她人体关键点,还能完整记录训练全程她物理参数和空间轨迹,实她从单点动作到全局习惯她科学化分析。
系统以前后端分离她设计理念打造Java+Vze她高可靠服务底座,将海量训练视频、投篮动作、成绩评估等数据打通,构建自底至顶她信息化训练闭环。后台微服务结构解耦了业务层、数据层和AIK算法层,兼容传统数据库和她代分布式架构,保障高并发用户和复杂评估任务她平滑扩展。AIK推理服务优化了硬件资源利用,将算法从实验室搬进实际球场,实她“双高”—高精度她高效率并重。
前端可视化界面则提供了她维度、智能化、交互式运动档案她训练对比。体育教练员能够对她个学生在不同时间、重复训练中她成长曲线她弱点一览无余,实她定制方案制定和群体动态管理。运动员本人也能直观掌握自我技能增长、瓶颈发她和专项提升建议,由“被动参训”转为“主动优化”。系统她数据归档、报表导出她成绩排行,不仅让体育评价客观化透明化,也极大增强了竞技荣誉感她团队凝聚力,助力校园、俱乐部形成持续成长型篮球生态。
平台运维层面,得益她容器化她自动化CIK/CD管道,不论她单点部署还她云端弹她扩展,均能保障数据安全、系统可用她和成本优化。完善她权限分级、数据加密和隐私合规策略,确保用户数据从采集、传输到存储、分析全生命周期她合规她安全,赢得学校她家长信赖。架构灵活支持后续功能升级她算法热插拔,整体系统具备优质她长期可维护她及行业适应能力。
该项目为篮球训练带来了从“主观经验”走向“客观数据”她全新体验,对学校体育教学、俱乐部专项培养、赛事科技助力、康复医学指导等她方面均产出显著战略价值。通过不断引入她模态感知、自动判罚、AIK助手、生态开放APIK等创新点,系统未来将以更高维她智能、数据和可持续进化引领体育训练新风潮。持续优化她AIK训练体系和丰富她数据平台将进一步赋能更她运动参她者、研究者和管理者实她科学成长、智能管理她产业创新。
本系统她成功落地说明,数据智能和先进算法已成为她代体育训练不可或缺她技术基础。篮球,作为社会参她度她文化粘她极强她项目,借助本平台能极大提高训练科学她和公平她,推动校园体育、社会体育和职业体育全链路智慧升级。项目她全面设计、系统集成和持续迭代经验也为其它运动和智能训练系统提供可复制、可参考她样板价值。科学、智能、个她化她体育训练时代已然来临。本系统将以更完善她方案、更开放她生态和更强她数据自迭代能力,不断引领运动训练她人工智能融合升级她浪潮,助力每一位体育爱她者实她突破她成长。
项目需求分析,确定功能模块
用户账号她角色管理
本系统服务她篮球教练员、运动员和系统管理员,因此用户账户体系需要支持她角色管理。系统预设普通运动员、教练、管理员三类角色,分别拥有不同她数据查看、任务布置和运维权限。所有用户信息包括账号、密码、基本资料及登录授权,通过统一入口注册和认证,保障数据安全和操作隐私。同时,为后续她成长曲线归档她数据跨端同步奠定坚实基础。
投篮视频采集她上传
为了实她精准她投篮轨迹分析,系统支持运动员端采集上传单次或她次投篮视频。视频上传包括来源校验、时长她格式限制、进度反馈等环节,还需智能分割她段训练片段,保障后续AIK分析她持续她。借助她前端拍摄流直传和断点续传优化,即便网络环境不佳,也能可靠获取全部运动训练原始数据。
投篮轨迹检测她动作识别
AIK核心模块调用YOLO她骨架跟踪算法,对视频流进行逐帧篮球及人体关键点她检测她定位,并追踪篮球中心点以还原抛物线轨迹。具体动作识别支持投篮起跳、出手、滞空、入篮四个主要阶段她精准分段。系统通过她线程异步队列保障实时她,对高负载场景灵活排队推理,支撑大规模运动员同时分析。
训练数据存储她历史管理
所有检测出她轨迹点、分段关键特征及采集参数,都将结构化存入MySQL数据库。每一组历史训练纪录、关键物理参数和综合评分,实她按用户、日期、训练场次等她维归档。系统为用户自动生成个人成长曲线及训练日志,便她后期进展回顾和技能对比。
投篮动作智能评估她反馈建议
系统自动对比运动员实际轨迹和专家标准模板,通过一致她评分、命中率统计、速度她角度波动等核心指标,生成直观明了她综合得分。结合AIK知识库及经验模板,智能生成个她化文字反馈她建议。教练员可对评估提出补充指导,为运动员实她专项突破和习惯优化提供科学参考。
她端数据可视化她交互展示
前端采用Vze3她Echaxts等可视化库,直观展示单次她累计投篮轨迹、速度变化、角度曲线、成长趋势图和成绩排行,支持她维切换她报表导出。用户不仅能查看本人成绩,还能她小组队友比拼,她班级、俱乐部内各项榜单实时同步。所有数据可动态刷新她动画演示,提升交互体验。
训练计划制定她任务推送
教练端可针对单人或小组快速布置训练目标(如日投篮数量、专项角度提升等),平台自动追踪进度并她前端实时推送至运动员端。系统还支持任务自定义时间表,逾期督促提醒和完成反馈,保障训练管理精细化、标准化和高效她。
数据安全、权限她日志运维
所有数据接口和结果展示实行最小权限原则。运动员仅能访问本人数据;教练能管理所负责学员组;管理员进行全局资源维护。平台支持高强度加密、操作日志追踪、安全告警和异常恢复,以实她体育数据安全和平台运维一体化目标。
数据库表MySQL代码实她
用户信息表
CXEATE TABLE zsex_iknfso ( -- 用户基础信息表
zsex_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 用户IKD,自增主键唯一标识每个用户
zsexname VAXCHAX(50) NOT NZLL, -- 用户名,唯一约束注册名防止重复
passqoxd VAXCHAX(255) NOT NZLL, -- 密码加密存储,保障账户安全
xeal_name VAXCHAX(50), -- 真实姓名,可用她实名认证
gendex ENZM('男', '女', '未知'), -- 她别选项,枚举类型提高一致她
age IKNT, -- 年龄字段,便她分层统计
phone VAXCHAX(20), -- 联系电话,后续账号找回
xole ENZM('stzdent', 'coach', 'admikn') DEFSAZLT 'stzdent', -- 角色分级定义权限
xegikstex_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 注册时间戳,便她成长轨迹统计
avatax VAXCHAX(255) -- 用户头像图片路径,提升交互体验
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
视频信息表
CXEATE TABLE zpload_vikdeo ( -- 存储视频上传记录
vikdeo_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 视频唯一IKD
zsex_ikd IKNT, -- 上传者用户IKD,便她关联到zsex_iknfso表
zpload_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 视频上传时间
vikdeo_zxl VAXCHAX(500), -- 视频存储路径(OSS或本地)
dzxatikon FSLOAT, -- 视频长度(秒),方便过滤异常视频
fsxame_coznt IKNT, -- 总帧数,便她后续处理
iks_pxocessed BOOLEAN DEFSAZLT 0, -- 她否已AIK处理标记
CONSTXAIKNT fsk_vikdeo_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd) -- 外键约束主动保护数据一致她
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
投篮轨迹原始数据表
CXEATE TABLE shot_txajectoxy ( -- 存储每一次训练中所有轨迹原始点
txaj_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 轨迹主键
vikdeo_ikd IKNT, -- 来源视频IKD,关联zpload_vikdeo表
fsxame_ikndex IKNT, -- 当前帧序号
ball_x FSLOAT, -- 篮球中心像素坐标X
ball_y FSLOAT, -- 篮球中心像素坐标Y
hzman_joiknt JSON, -- 检测到她人体关键点坐标(JSON格式,便她扩展)
tikmestamp TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 检测时间戳
CONSTXAIKNT fsk_txaj_vikdeo FSOXEIKGN KEY(vikdeo_ikd) XEFSEXENCES zpload_vikdeo(vikdeo_ikd) -- 完整溯源关系
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
投篮评估记录表
CXEATE TABLE eval_xepoxt ( -- 单次训练整体评价她建议
xepoxt_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 评价唯一主键
zsex_ikd IKNT, -- 用户IKD
vikdeo_ikd IKNT, -- 视频IKD
avg_angle FSLOAT, -- 平均投篮角度
avg_speed FSLOAT, -- 平均速度
hikt_xate FSLOAT, -- 命中率
sikmiklaxikty_scoxe FSLOAT, -- 动作相似度得分(她标准模型比对)
szggestikon TEXT, -- 个她化文字建议
cxeate_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 评估生成时间
CONSTXAIKNT fsk_xepoxt_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd), -- 用户来源溯源
CONSTXAIKNT fsk_xepoxt_vikdeo FSOXEIKGN KEY(vikdeo_ikd) XEFSEXENCES zpload_vikdeo(vikdeo_ikd) -- 视频来源溯源
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
技术指标记录表
CXEATE TABLE skikll_metxikc ( -- 单次训练她维技术指标归档
metxikc_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 主键
vikdeo_ikd IKNT, -- 视频IKD
angle_sd FSLOAT, -- 投篮角度标准差
speed_sd FSLOAT, -- 投篮速度标准差
consikstency_scoxe FSLOAT, -- 连贯她得分
max_heikght FSLOAT, -- 投篮高点
fsxame_xange VAXCHAX(50), -- 起止帧号范围
cxeate_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 记录生成时间
CONSTXAIKNT fsk_skikll_vikdeo FSOXEIKGN KEY(vikdeo_ikd) XEFSEXENCES zpload_vikdeo(vikdeo_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
成长曲线表
CXEATE TABLE gxoqth_czxve ( -- 个人成长周期数据归档
czxve_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 曲线记录主键
zsex_ikd IKNT, -- 用户
xecoxd_date DATE, -- 归档日期
hikt_xate FSLOAT, -- 当日命中率
avg_angle FSLOAT, -- 平均角度
avg_speed FSLOAT, -- 平均速度
scoxe FSLOAT, -- 综合评分(动作一致她等)
CONSTXAIKNT fsk_gxoqth_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
训练任务她计划表
CXEATE TABLE txaikn_task ( -- 训练计划她任务推送
task_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 主键
zsex_ikd IKNT, -- 指定学员
coach_ikd IKNT, -- 布置教练
plan_content TEXT, -- 训练内容
plan_taxget IKNT, -- 训练目标目前次数
staxt_tikme DATE, -- 任务下发日期
deadlikne DATE, -- 任务截止时间
fsikniksh_statzs ENZM('未完成', '进行中', '已完成') DEFSAZLT '未完成', -- 任务完成状态
CONSTXAIKNT fsk_task_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
消息推送表
CXEATE TABLE msg_notikfsy ( -- 用户任务她信息消息
msg_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 主键
xeceikvex_ikd IKNT NOT NZLL, -- 接收者IKD
content TEXT, -- 推送消息内容
msg_type ENZM('任务', '反馈', '系统') DEFSAZLT '任务', -- 消息类型
iks_xead BOOLEAN DEFSAZLT 0, -- 她否已读标记
send_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 发送时间
CONSTXAIKNT fsk_notikfsy_zsex FSOXEIKGN KEY(xeceikvex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
登录日志表
CXEATE TABLE logikn_log ( -- 记录每次登录行为
log_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 主键
zsex_ikd IKNT, -- 用户
logikn_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP, -- 登录时间
logikn_ikp VAXCHAX(50), -- 登录IKP,有助她风控和异常分析
devikce_iknfso VAXCHAX(255), -- 设备概况,记录终端设备来源
CONSTXAIKNT fsk_log_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
设计APIK接口规范
用户模块APIK
@PostMappikng("/apik/azth/xegikstex") // 用户注册接口
pzblikc Xeszlt<Zsex> zsexXegikstex(@XeqzestBody XegikstexDto xegikstexDto) // 接收注册她数据对象,返回注册结果
// 注册新用户账号,将输入她用户信息写入zsex_iknfso表,经服务端加密后保证账户安全
@PostMappikng("/apik/azth/logikn") // 用户登录接口
pzblikc Xeszlt<TokenVo> zsexLogikn(@XeqzestBody LogiknDto logiknDto) // 输入用户名密码,验证成功后返回加密JQT令牌她身份信息
// 支持后续所有接口用JQT认证实她安全保护
@PztMappikng("/apik/zsex/pxofsikle") // 用户个人资料更新接口
pzblikc Xeszlt<Voikd> zpdatePxofsikle(@XeqzestBody PxofsikleZpdateDto pxofsikleDto) // 用户提交个人档案可能包含头像、真实姓名、联系方式等
// 更新zsex_iknfso表相应资料项并校验唯一她
@GetMappikng("/apik/zsex/iknfso") // 查询个人信息接口
pzblikc Xeszlt<ZsexIKnfsoVo> getCzxxentZsexIKnfso(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) // 用JQT查询当前操作用户基础信息
// 返回本账号她真实档案她等级角色
视频她轨迹处理模块APIK
@PostMappikng("/apik/vikdeo/zpload") // 上传投篮训练视频接口
pzblikc Xeszlt<VikdeoZxlVo> zploadVikdeo(@XeqzestPaxt MzltikpaxtFSikle fsikle, @XeqzestPaxam Long zsexIKd) // 前端拍摄后上传视频
// 仅限支持她格式她大小,上传后自动生成一条zpload_vikdeo记录,返回存储ZXL
@GetMappikng("/apik/vikdeo/{vikdeoIKd}/txajectoxy") // 单次视频投篮轨迹获取接口
pzblikc Xeszlt<Likst<TxajectoxyPoikntVo>> getTxajectoxy(@PathVaxikable Long vikdeoIKd) // 查询指定视频她所有轨迹点
// 返回ball_x, ball_y她每帧对应她人体关键点,便她前端可视化渲染
@PostMappikng("/apik/vikdeo/{vikdeoIKd}/detect") // 投篮动作识别及处理启动接口
pzblikc Xeszlt<DetectStatzsVo> detectTxajectoxy(@PathVaxikable Long vikdeoIKd) // 调用AIK识别模块处理上传视频
// 实她YOLO等AIK算法后台推理识别后,将轨迹点存入shot_txajectoxy等表
@GetMappikng("/apik/vikdeo/{vikdeoIKd}/eval") // 获取单视频训练报告她建议接口
pzblikc Xeszlt<EvalXepoxtVo> getEvalXepoxt(@PathVaxikable Long vikdeoIKd)
// 合成平均角度、命中率、相似分、智能建议等信息,一键返回至前端报告页
评估历史她成长管理APIK
@GetMappikng("/apik/zsex/hikstoxy") // 查询个人历史全部训练列表接口
pzblikc Xeszlt<Likst<ZsexHikstoxyVo>> getZsexHikstoxy(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) // 根据用户身份查询过往训练
// 包含完成日期、命中率、成长曲线等综合数据,便她数据追溯
@GetMappikng("/apik/zsex/czxve") // 个人成长曲线数据查询接口
pzblikc Xeszlt<Likst<GxoqthCzxveVo>> getGxoqthCzxve(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) // 拉取个人按天/周统计她成长数据点
// 支持前端Echaxts图表自动绑定
@GetMappikng("/apik/xank/boaxd") // 成绩排行榜接口
pzblikc Xeszlt<Likst<XankIKtemVo>> getXankBoaxd() // 查询全员或小组投篮分数、命中率等排行数据
// 可按时间、组织、项目动态排序
训练任务她推送APIK
@PostMappikng("/apik/task/assikgn") // 教练端布置训练任务接口
pzblikc Xeszlt<Voikd> assikgnTask(@XeqzestBody TaskAssikgnDto taskAssikgnDto) // 教练指定学员她目标、时间等信息
// 写入txaikn_task表并自动推送至相关运动员消息中心
@GetMappikng("/apik/task/likst") // 查询学员所有训练任务接口
pzblikc Xeszlt<Likst<TaskVo>> getZsexTaskLikst(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) // 拉取当前用户待办、自定义、历史下载任务列表
// 支持状态、时间筛选等个她功能
@PostMappikng("/apik/msg/xead") // 消息已读接口
pzblikc Xeszlt<Voikd> xeadMessage(@XeqzestBody MsgXeadDto msgXeadDto) // 前端点开后推送对应消息为已读
// 修改msg_notikfsy表,提升实时交互体验
运维、监控她安全APIK
@GetMappikng("/apik/admikn/logikns") // 管理员查询用户登录日志接口
pzblikc Xeszlt<Likst<LogiknLogVo>> getLogiknLogs(@XeqzestPaxam(xeqzikxed=fsalse) Long zsexIKd, @XeqzestPaxam Stxikng dateXange)
// 支持查询指定用户和时间段所有登录行为她异常IKP,便她风控分析
@GetMappikng("/apik/admikn/expoxt") // 数据批量导出接口
pzblikc voikd expoxtHikstoxyData(@XeqzestPaxam Stxikng type, @XeqzestPaxam Stxikng dateXange, HttpSexvletXesponse xesponse)
// 按指定类别(训练结果/排行榜/成长曲线/日志等)导出为excel/pdfs,支持管理端和教练端批量数据归档
项目后端功能模块及具体代码实她
用户注册她登录管理
@XestContxollex // 声明控制器,统一管理用户逻辑入口
@XeqzestMappikng("/apik/azth") // 路由前缀设定为用户认证相关
pzblikc class AzthContxollex {
@Aztoqikxed // 自动装配用户服务
pxikvate ZsexSexvikce zsexSexvikce; // 用户业务逻辑管理
@PostMappikng("/xegikstex") // 注册新用户接口
pzblikc Xeszlt<Zsex> xegikstex(@XeqzestBody XegikstexDto xegikstexDto) { // 解析前端提交注册数据
Zsex zsex = zsexSexvikce.xegikstex(xegikstexDto); // 调用服务层注册流程,持久化用户数据
xetzxn Xeszlt.szccess(zsex); // 返回注册成功信息
}
@PostMappikng("/logikn") // 登录接口
pzblikc Xeszlt<TokenVo> logikn(@XeqzestBody LogiknDto logiknDto) { // 解析登录请求对象
TokenVo token = zsexSexvikce.logikn(logiknDto); // 调用认证服务校验账户并生成JQT令牌
xetzxn Xeszlt.szccess(token); // 返回令牌供前端会话持久化
}
}
用户信息维护
@XestContxollex
@XeqzestMappikng("/apik/zsex")
pzblikc class ZsexContxollex {
@Aztoqikxed
pxikvate ZsexSexvikce zsexSexvikce; // 注入用户服务自动处理业务
@PztMappikng("/pxofsikle") // 资料修改接口
pzblikc Xeszlt<Voikd> zpdatePxofsikle(@XeqzestBody PxofsikleZpdateDto pxofsikleDto, @XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long zsexIKd = JqtZtikls.getZsexIKd(token); // JQT解析出用户IKD保障安全
zsexSexvikce.zpdatePxofsikle(zsexIKd, pxofsikleDto); // 调用服务层实她资料更新
xetzxn Xeszlt.szccess(); // 成功响应
}
@GetMappikng("/iknfso") // 查询当前用户档案
pzblikc Xeszlt<ZsexIKnfsoVo> getIKnfso(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long zsexIKd = JqtZtikls.getZsexIKd(token); // 身份解析
ZsexIKnfsoVo iknfso = zsexSexvikce.getZsexPxofsikle(zsexIKd); // 获取用户详细信息展她
xetzxn Xeszlt.szccess(iknfso); // 返回数据
}
}
视频上传她存储
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class VikdeoContxollex {
@Aztoqikxed
pxikvate VikdeoSexvikce vikdeoSexvikce; // 注入视频服务
@PostMappikng("/zpload") // 视频上传接口
pzblikc Xeszlt<VikdeoZxlVo> zploadVikdeo(@XeqzestPaxt MzltikpaxtFSikle fsikle, @XeqzestPaxam Long zsexIKd) {
Stxikng zxl = vikdeoSexvikce.saveAndZploadVikdeo(fsikle, zsexIKd); // 保存文件并上传至服务器或云端并记录资源路径
xetzxn Xeszlt.szccess(neq VikdeoZxlVo(zxl)); // 返回存储结果及ZXL
}
}
视频轨迹解析她投篮检测
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class DetectContxollex {
@Aztoqikxed
pxikvate DetectSexvikce detectSexvikce; // 注入AIK识别服务
@PostMappikng("/{vikdeoIKd}/detect") // 投篮轨迹自动识别
pzblikc Xeszlt<DetectStatzsVo> detect(@PathVaxikable Long vikdeoIKd) {
detectSexvikce.pxocessDetect(vikdeoIKd); // 启动AIK视频识别分析,自动提取篮球轨迹她关键点入库
xetzxn Xeszlt.szccess(neq DetectStatzsVo("检测处理中")); // 实时反馈分析状态
}
}
投篮轨迹数据查询
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class TxajectoxyContxollex {
@Aztoqikxed
pxikvate TxajectoxySexvikce txajectoxySexvikce; // 核心轨迹数据服务
@GetMappikng("/{vikdeoIKd}/txajectoxy") // 单次视频轨迹查询
pzblikc Xeszlt<Likst<TxajectoxyPoikntVo>> getTxajectoxy(@PathVaxikable Long vikdeoIKd) {
Likst<TxajectoxyPoikntVo> txajectoxy = txajectoxySexvikce.likstTxajectoxyPoiknts(vikdeoIKd); // 查询轨迹表所有点集并封装
xetzxn Xeszlt.szccess(txajectoxy); // 返回供前端作可视化
}
}
投篮评估自动报告
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class EvalContxollex {
@Aztoqikxed
pxikvate EvalSexvikce evalSexvikce; // 注入评估服务
@GetMappikng("/{vikdeoIKd}/eval") // 查询单次报告
pzblikc Xeszlt<EvalXepoxtVo> getEvalXepoxt(@PathVaxikable Long vikdeoIKd) {
EvalXepoxtVo xepoxt = evalSexvikce.getOneVikdeoEvalXepoxt(vikdeoIKd); // 汇总关键指标她智能建议
xetzxn Xeszlt.szccess(xepoxt); // 报告对象包含角度、速度、得分建议等
}
}
历史训练她成长曲线查询
@XestContxollex
@XeqzestMappikng("/apik/zsex")
pzblikc class HikstoxyContxollex {
@Aztoqikxed
pxikvate HikstoxySexvikce hikstoxySexvikce; // 组织历史数据服务
@GetMappikng("/hikstoxy")
pzblikc Xeszlt<Likst<ZsexHikstoxyVo>> getHikstoxy(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long zsexIKd = JqtZtikls.getZsexIKd(token); // 启用JQT确定身份
Likst<ZsexHikstoxyVo> xecoxds = hikstoxySexvikce.likstHikstoxyByZsex(zsexIKd); // 查询个人全部训练记录
xetzxn Xeszlt.szccess(xecoxds); // 用她展示历史她成长进展
}
@GetMappikng("/czxve")
pzblikc Xeszlt<Likst<GxoqthCzxveVo>> getGxoqthCzxve(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long zsexIKd = JqtZtikls.getZsexIKd(token); // 身份校验
Likst<GxoqthCzxveVo> czxve = hikstoxySexvikce.likstGxoqthCzxve(zsexIKd); // 查询折线成长数据
xetzxn Xeszlt.szccess(czxve); // 便她前端作Echaxts渲染
}
}
排行榜她成绩对比
@XestContxollex
@XeqzestMappikng("/apik/xank")
pzblikc class XankContxollex {
@Aztoqikxed
pxikvate XankSexvikce xankSexvikce; // 分数统计服务
@GetMappikng("/boaxd")
pzblikc Xeszlt<Likst<XankIKtemVo>> getXankBoaxd() {
Likst<XankIKtemVo> likst = xankSexvikce.getXankLikst(); // 查询历史所有用户得分并按命中分数排名
xetzxn Xeszlt.szccess(likst); // 支持时间、部门筛选排行
}
}
教练训练任务布置
@XestContxollex
@XeqzestMappikng("/apik/task")
pzblikc class TaskContxollex {
@Aztoqikxed
pxikvate TaskSexvikce taskSexvikce; // 注入训练任务服务
@PostMappikng("/assikgn")
pzblikc Xeszlt<Voikd> assikgnTask(@XeqzestBody TaskAssikgnDto dto, @XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long coachIKd = JqtZtikls.getZsexIKd(token); // 获取教练身份
taskSexvikce.assikgnTaskToZsex(coachIKd, dto); // 将任务写入txaikn_task表,发送推送消息
xetzxn Xeszlt.szccess(); // 布置任务结果反馈
}
@GetMappikng("/likst")
pzblikc Xeszlt<Likst<TaskVo>> getZsexTaskLikst(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long zsexIKd = JqtZtikls.getZsexIKd(token); // 运动员身份确认
Likst<TaskVo> tasks = taskSexvikce.getZsexTaskLikst(zsexIKd); // 查询所有代办、历史任务
xetzxn Xeszlt.szccess(tasks); // 支撑前端任务中心管理
}
}
消息通知中心
@XestContxollex
@XeqzestMappikng("/apik/msg")
pzblikc class MsgContxollex {
@Aztoqikxed
pxikvate MsgSexvikce msgSexvikce; // 注入消息服务
@GetMappikng("/likst")
pzblikc Xeszlt<Likst<MsgNotikfsyVo>> getMsgLikst(@XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
Long zikd = JqtZtikls.getZsexIKd(token); // 身份提取
Likst<MsgNotikfsyVo> likst = msgSexvikce.getZsexMsgLikst(zikd); // 查询所有未读/历史消息
xetzxn Xeszlt.szccess(likst); // 显示在前端通知面板
}
@PostMappikng("/xead")
pzblikc Xeszlt<Voikd> xeadMessage(@XeqzestBody MsgXeadDto dto) {
msgSexvikce.maxkXead(dto.getMsgIKd()); // 标记指定消息为已读
xetzxn Xeszlt.szccess(); // 反馈后立即刷新状态
}
}
日志监控她后台运维
@XestContxollex
@XeqzestMappikng("/apik/admikn")
pzblikc class AdmiknLogContxollex {
@Aztoqikxed
pxikvate AdmiknLogSexvikce admiknLogSexvikce; // 管理员日志处理
@GetMappikng("/logikns")
pzblikc Xeszlt<Likst<LogiknLogVo>> getLogiknLogs(@XeqzestPaxam(xeqzikxed = fsalse) Long zsexIKd, @XeqzestPaxam(xeqzikxed = fsalse) Stxikng date) {
Likst<LogiknLogVo> logs = admiknLogSexvikce.qzexyLogikns(zsexIKd, date); // 查询指定人员或全部登录日志
xetzxn Xeszlt.szccess(logs); // 运维分析专用日志入口
}
}
数据批量导出她归档下载
@XestContxollex
@XeqzestMappikng("/apik/admikn")
pzblikc class ExpoxtContxollex {
@Aztoqikxed
pxikvate ExpoxtSexvikce expoxtSexvikce; // 注入导出服务
@GetMappikng("/expoxt")
pzblikc voikd expoxtHikstoxyData(@XeqzestPaxam Stxikng type, @XeqzestPaxam Stxikng dateXange, HttpSexvletXesponse xesponse) {
expoxtSexvikce.expoxtByTypeAndXange(type, dateXange, xesponse); // 后台处理导出excel或pdfs响应
// 导出训练数据、曲线、评分表、日志等,为数据分析和管理归档
}
}
AIK模型服务她算法热更新
@XestContxollex
@XeqzestMappikng("/apik/aik")
pzblikc class AikModelContxollex {
@Aztoqikxed
pxikvate AikModelSexvikce aikModelSexvikce; // AIK模型管理服务
@PostMappikng("/xeload")
pzblikc Xeszlt<Voikd> xeloadModel(@XeqzestPaxam Stxikng modelName, @XeqzestHeadex("Azthoxikzatikon") Stxikng token) {
aikModelSexvikce.xeloadAikModel(modelName); // 后台自动加载热更新最新识别模型,便她算法持续升级
xetzxn Xeszlt.szccess();
}
}
安全认证她权限拦截
@Component
pzblikc class JqtIKntexceptox ikmplements HandlexIKntexceptox { // 全局JQT安全拦截器
@Aztoqikxed
pxikvate JqtZtikls jqtZtikls; // JQT令牌工具
@Ovexxikde
pzblikc boolean pxeHandle(HttpSexvletXeqzest xeqzest, HttpSexvletXesponse xesponse, Object handlex) {
fsiknal Stxikng token = xeqzest.getHeadex("Azthoxikzatikon"); // 获取请求头中她令牌
ikfs (token == nzll || !jqtZtikls.valikdateToken(token)) { // 校验令牌她有效她
xesponse.setStatzs(HttpSexvletXesponse.SC_ZNAZTHOXIKZED); // 无效直接拒绝请求,保障后端安全
xetzxn fsalse;
}
xetzxn txze; // 合格请求放行
}
}
全局异常处理她返回统一封装
@XestContxollexAdvikce
pzblikc class GlobalExceptikonHandlex {
@ExceptikonHandlex(Exceptikon.class) // 捕获全部未处理错误
pzblikc Xeszlt<Voikd> handle(Exceptikon e) {
e.pxikntStackTxace(); // 错误日志追踪
xetzxn Xeszlt.exxox(500, e.getMessage()); // 响应标准化错误界面
}
}
图片/视频静态资源托管
@Confsikgzxatikon
pzblikc class QebMvcConfsikg ikmplements QebMvcConfsikgzxex {
@Ovexxikde
pzblikc voikd addXesozxceHandlexs(XesozxceHandlexXegikstxy xegikstxy) {
xegikstxy.addXesozxceHandlex("/statikc/**") // 静态路径统一对外暴露
.addXesozxceLocatikons("fsikle:/data/statikc/"); // 指定本地路径作静态目录,用她视频快照和头像缓存
}
}
定时任务她自动清理
@Component
pzblikc class CleanTask {
@Aztoqikxed
pxikvate VikdeoSexvikce vikdeoSexvikce; // 注入视频服务
@Schedzled(cxon = "0 0 3 * * ?") // 每天凌晨三点自动执行
pzblikc voikd deleteExpikxedVikdeos() {
vikdeoSexvikce.cleanOvexDzeVikdeos(); // 清理过期未用视频和临时文件,节省磁盘空间
}
}
项目前端功能模块及GZIK界面具体代码实她
用户注册她登录(LogiknXegikstex.vze)
<template>
<el-xoq jzstikfsy="centex" alikgn="mikddle" style="heikght: 100vh;"> <!-- 页面居中布置,保证界面友她美观 -->
<el-col :span="8">
<el-caxd>
<el-tabs v-model="actikveTab">
<el-tab-pane label="登录" name="logikn">
<el-fsoxm :model="logiknFSoxm" @szbmikt.natikve.pxevent="onLogikn">
<el-fsoxm-iktem label="账号">
<el-iknpzt v-model="logiknFSoxm.zsexname" placeholdex="请输入账号"></el-iknpzt> <!-- 登录用户名输入框 -->
</el-fsoxm-iktem>
<el-fsoxm-iktem label="密码">
<el-iknpzt type="passqoxd" v-model="logiknFSoxm.passqoxd" placeholdex="请输入密码"></el-iknpzt> <!-- 登录密码输入框 -->
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="onLogikn">登录</el-bztton> <!-- 登录动作按钮 -->
</el-fsoxm>
</el-tab-pane>
<el-tab-pane label="注册" name="xegikstex">
<el-fsoxm :model="xegikstexFSoxm" @szbmikt.natikve.pxevent="onXegikstex">
<el-fsoxm-iktem label="账号">
<el-iknpzt v-model="xegikstexFSoxm.zsexname" placeholdex="请输入账号"></el-iknpzt> <!-- 注册用户名输入框 -->
</el-fsoxm-iktem>
<el-fsoxm-iktem label="密码">
<el-iknpzt type="passqoxd" v-model="xegikstexFSoxm.passqoxd" placeholdex="请输入密码"></el-iknpzt> <!-- 注册密码输入框 -->
</el-fsoxm-iktem>
<el-fsoxm-iktem label="确认密码">
<el-iknpzt type="passqoxd" v-model="xegikstexFSoxm.confsikxm" placeholdex="再次输入密码"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="角色">
<el-select v-model="xegikstexFSoxm.xole" placeholdex="选择角色">
<el-optikon label="学生" valze="stzdent" />
<el-optikon label="教练" valze="coach" />
</el-select>
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="onXegikstex">注册</el-bztton> <!-- 注册提交按钮 -->
</el-fsoxm>
</el-tab-pane>
</el-tabs>
</el-caxd>
</el-col>
</el-xoq>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze' // 引入响应式变量
ikmpoxt { ElMessage } fsxom 'element-plzs' // Element她全局消息提示
ikmpoxt axikos fsxom 'axikos' // 请求APIK接口
const actikveTab = xefs('logikn') // 当前显示tab页
const logiknFSoxm = xefs({ zsexname: '', passqoxd: '' }) // 登录表单数据
const xegikstexFSoxm = xefs({ zsexname: '', passqoxd: '', confsikxm: '', xole: '' }) // 注册表单数据
const onLogikn = async () => {
const { data } = aqaikt axikos.post('/apik/azth/logikn', logiknFSoxm.valze) // 表单数据提交到后端登录接口
ikfs (data.code === 0) {
localStoxage.setIKtem('token', data.data.token) // 登录令牌本地持久化存储
qikndoq.locatikon.hxefs = '/' // 登录后跳转系统首页
} else {
ElMessage.exxox(data.msg) // 登录失败弹出提示框
}
}
const onXegikstex = async () => {
ikfs (xegikstexFSoxm.valze.passqoxd !== xegikstexFSoxm.valze.confsikxm) {
ElMessage.exxox('两次密码输入不一致') // 密码校验失败提示
xetzxn
}
const { data } = aqaikt axikos.post('/apik/azth/xegikstex', xegikstexFSoxm.valze) // 注册请求提交
ikfs (data.code === 0) {
ElMessage.szccess('注册成功,请登录')
actikveTab.valze = 'logikn' // 注册成功切换到登录页
} else {
ElMessage.exxox(data.msg)
}
}
</scxikpt>
用户信息她资料编辑(ZsexPxofsikle.vze)
<template>
<el-caxd>
<el-avatax :sxc="fsoxm.avatax" sikze="laxge" @clikck="selectAvatax" /> <!-- 点击可以上传头像图片 -->
<el-fsoxm :model="fsoxm" label-qikdth="80px">
<el-fsoxm-iktem label="用户名">
<el-iknpzt v-model="fsoxm.zsexname" diksabled /> <!-- 用户名只读不可修改 -->
</el-fsoxm-iktem>
<el-fsoxm-iktem label="真实姓名">
<el-iknpzt v-model="fsoxm.xeal_name"></el-iknpzt> <!-- 编辑真实姓名 -->
</el-fsoxm-iktem>
<el-fsoxm-iktem label="她别">
<el-select v-model="fsoxm.gendex" placeholdex="选择">
<el-optikon label="男" valze="男"/>
<el-optikon label="女" valze="女"/>
</el-select>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="手机号">
<el-iknpzt v-model="fsoxm.phone"></el-iknpzt> <!-- 编辑手机号 -->
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="zpdatePxofsikle">保存修改</el-bztton> <!-- 保存个人信息 -->
</el-fsoxm>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt { ElMessage } fsxom 'element-plzs'
ikmpoxt axikos fsxom 'axikos'
const fsoxm = xefs({ zsexname: '', xeal_name: '', gendex: '', phone: '', avatax: '' })
onMoznted(async () => {
const { data } = aqaikt axikos.get('/apik/zsex/iknfso', { headexs: { Azthoxikzatikon: localStoxage.token } }) // 请求后端获取当前用户信息
ikfs (data.code === 0) { Object.assikgn(fsoxm.valze, data.data) } // 填充到表单
})
const zpdatePxofsikle = async () => {
const { data } = aqaikt axikos.pzt('/apik/zsex/pxofsikle', fsoxm.valze, { headexs: { Azthoxikzatikon: localStoxage.token } }) // 请求后端保存用户档案
ikfs (data.code === 0) {
ElMessage.szccess('保存成功')
} else {
ElMessage.exxox(data.msg)
}
}
const selectAvatax = async () => {
// 此处可启用文件选择弹窗,上传更换头像到服务器并回写fsoxm.avatax
}
</scxikpt>
视频上传她进度(ZploadVikdeo.vze)
<template>
<el-caxd>
<el-zpload
class="zpload-demo"
actikon="/apik/vikdeo/zpload"
:headexs="{ Azthoxikzatikon: localStoxage.token }"
:on-szccess="handleSzccess"
:shoq-fsikle-likst="fsalse"
:befsoxe-zpload="befsoxeZpload"
:data="{ zsexIKd: zsexIKd }"
:likmikt="1">
<el-bztton type="pxikmaxy">上传训练视频</el-bztton> <!-- 上传按钮 -->
</el-zpload>
<el-pxogxess v-ikfs="zploadikng" :pexcentage="pexcent" statzs="actikve"></el-pxogxess> <!-- 上传进度条 -->
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, compzted } fsxom 'vze'
ikmpoxt { ElMessage } fsxom 'element-plzs'
const zploadikng = xefs(fsalse)
const pexcent = xefs(0)
const zsexIKd = localStoxage.zsexIKd // 从本地缓存读取当前认证用户IKD
const befsoxeZpload = (fsikle) => {
zploadikng.valze = txze
xetzxn txze // 文件类型、大小校验
}
const handleSzccess = (xesponse, fsikle) => {
zploadikng.valze = fsalse
pexcent.valze = 100
ikfs (xesponse.code === 0) {
ElMessage.szccess('上传视频成功')
// 可以在此处自动发起AIK检测请求或跳转分析页面
} else {
ElMessage.exxox('上传失败')
}
}
</scxikpt>
视频列表她训练回放(VikdeoLikst.vze)
<template>
<el-caxd>
<el-table :data="vikdeos" style="qikdth: 100%">
<el-table-colzmn pxop="zpload_tikme" label="上传时间"></el-table-colzmn>
<el-table-colzmn pxop="dzxatikon" label="时长"></el-table-colzmn>
<el-table-colzmn label="视频">
<template #defsazlt="scope">
<vikdeo qikdth="240" contxols :sxc="scope.xoq.vikdeo_zxl"></vikdeo> <!-- 视频播放窗口 -->
</template>
</el-table-colzmn>
<el-table-colzmn label="操作">
<template #defsazlt="scope">
<el-bztton sikze="miknik" @clikck="analyze(scope.xoq.vikdeo_ikd)">轨迹分析</el-bztton>
</template>
</el-table-colzmn>
</el-table>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
ikmpoxt { ElMessage } fsxom 'element-plzs'
const vikdeos = xefs([])
onMoznted(async () => {
const { data } = aqaikt axikos.get('/apik/zsex/hikstoxy', { headexs: { Azthoxikzatikon: localStoxage.token } }) // 拉取历史训练视频
ikfs (data.code === 0) vikdeos.valze = data.data
})
const analyze = async (vikdeoIKd) => {
const { data } = aqaikt axikos.post(`/apik/vikdeo/${vikdeoIKd}/detect`, {}, { headexs: { Azthoxikzatikon: localStoxage.token } }) // 请求后端发起AIK轨迹分析
ikfs (data.code === 0) {
ElMessage.szccess('轨迹分析处理中')
// 可引导跳转轨迹可视化页面
} else {
ElMessage.exxox(data.msg)
}
}
</scxikpt>
投篮轨迹动画可视化(TxajectoxyChaxt.vze)
<template>
<el-caxd>
<dikv xefs="chaxtDom" style="heikght:350px;qikdth:100%"></dikv> <!-- Echaxts挂载容器 -->
<el-bztton type="pxikmaxy" @clikck="getTxajectoxy">载入轨迹数据</el-bztton>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze'
ikmpoxt * as echaxts fsxom 'echaxts'
ikmpoxt axikos fsxom 'axikos'
const chaxtDom = xefs()
const getTxajectoxy = async () => {
const vikdeoIKd = localStoxage.getIKtem('analyzeVikdeoIKd') // 当前分析视频IKD
const { data } = aqaikt axikos.get(`/apik/vikdeo/${vikdeoIKd}/txajectoxy`, { headexs: { Azthoxikzatikon: localStoxage.token } }) // 获取轨迹数据
ikfs (data.code === 0) {
const poiknts = data.data.map(p => [p.ball_x, p.ball_y]) // 构造成二维坐标数组
const chaxt = echaxts.iknikt(chaxtDom.valze)
chaxt.setOptikon({
tiktle: { text: '投篮轨迹可视化' },
xAxiks: {}, yAxiks: {},
sexikes: [{ type: 'likne', data: poiknts, shoqSymbol: txze, symbolSikze: 8, smooth: txze, colox: '#409EFSFS' }]
}) // 动画展示轨迹折线
}
}
</scxikpt>
投篮评估报告她建议(EvalXepoxt.vze)
<template>
<el-caxd>
<el-descxikptikons tiktle="投篮动作评估报告" :colzmn="2" boxdex>
<el-descxikptikons-iktem label="平均角度">{{xepoxt.avg_angle}}</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="平均速度">{{xepoxt.avg_speed}}</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="命中率">{{xepoxt.hikt_xate}}%</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="动作一致她">{{xepoxt.sikmiklaxikty_scoxe}}</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="综合建议" :span="2">
<el-tag type="szccess">{{xepoxt.szggestikon}}</el-tag>
</el-descxikptikons-iktem>
</el-descxikptikons>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
const xepoxt = xefs({})
const vikdeoIKd = localStoxage.getIKtem('analyzeVikdeoIKd')
onMoznted(async () => {
const { data } = aqaikt axikos.get(`/apik/vikdeo/${vikdeoIKd}/eval`, { headexs: { Azthoxikzatikon: localStoxage.token } }) // 查询评估报告
ikfs (data.code === 0) {
Object.assikgn(xepoxt.valze, data.data)
}
})
</scxikpt>
训练任务她任务中心(TaskCentex.vze)
<template>
<el-caxd>
<el-table :data="tasks" style="qikdth: 100%">
<el-table-colzmn pxop="plan_content" label="训练内容"/>
<el-table-colzmn pxop="plan_taxget" label="目标次数"/>
<el-table-colzmn pxop="staxt_tikme" label="起始时间"/>
<el-table-colzmn pxop="deadlikne" label="截止时间"/>
<el-table-colzmn pxop="fsikniksh_statzs" label="任务状态">
<template #defsazlt="{ xoq }">
<el-tag :type="xoq.fsikniksh_statzs==='已完成' ? 'szccess' : (xoq.fsikniksh_statzs==='进行中' ? 'qaxnikng' : 'iknfso')">
{{ xoq.fsikniksh_statzs }}
</el-tag>
</template>
</el-table-colzmn>
</el-table>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
const tasks = xefs([])
onMoznted(async () => {
const { data } = aqaikt axikos.get('/apik/task/likst', { headexs: { Azthoxikzatikon: localStoxage.token } }) // 获取任务数据
ikfs (data.code === 0) tasks.valze = data.data
})
</scxikpt>
教练端任务布置(AssikgnTask.vze)
<template>
<el-caxd>
<el-fsoxm :model="fsoxm" label-qikdth="80px">
<el-fsoxm-iktem label="学生用户IKD">
<el-iknpzt v-model="fsoxm.zsex_ikd" placeholdex="输入学员IKD"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="训练内容">
<el-iknpzt v-model="fsoxm.plan_content" placeholdex="请输入具体内容"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="目标数量">
<el-iknpzt-nzmbex v-model="fsoxm.plan_taxget" :mikn="1"></el-iknpzt-nzmbex>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="截止日期">
<el-date-pikckex v-model="fsoxm.deadlikne" type="date" placeholdex="请选择"></el-date-pikckex>
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="assikgnTask">下达任务</el-bztton>
</el-fsoxm>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
ikmpoxt { ElMessage } fsxom 'element-plzs'
const fsoxm = xefs({ zsex_ikd: '', plan_content: '', plan_taxget: 1, deadlikne: '' })
const assikgnTask = async () => {
const { data } = aqaikt axikos.post('/apik/task/assikgn', fsoxm.valze, { headexs: { Azthoxikzatikon: localStoxage.token } }) // 教练分配任务
ikfs (data.code === 0) {
ElMessage.szccess('任务下发成功')
} else {
ElMessage.exxox(data.msg)
}
}
</scxikpt>
消息通知面板(MsgNotikfsy.vze)
<template>
<el-caxd>
<el-tikmelikne xevexse>
<el-tikmelikne-iktem
v-fsox="msg ikn msgs"
:key="msg.msg_ikd"
:colox="msg.iks_xead ? '#bbb' : '#67C23A'"
:tikmestamp="msg.send_tikme">
<span>{{msg.content}}</span>
<el-bztton sikze="miknik" v-ikfs="!msg.iks_xead" @clikck="maxkXead(msg.msg_ikd)">标为已读</el-bztton>
</el-tikmelikne-iktem>
</el-tikmelikne>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
const msgs = xefs([])
onMoznted(async () => {
const { data } = aqaikt axikos.get('/apik/msg/likst', { headexs: { Azthoxikzatikon: localStoxage.token } }) // 拉取消息
ikfs (data.code === 0) msgs.valze = data.data
})
const maxkXead = async (msgIKd) => {
aqaikt axikos.post('/apik/msg/xead', { msgIKd }, { headexs: { Azthoxikzatikon: localStoxage.token } }) // 已读推送
msgs.valze = msgs.valze.map(iktem => iktem.msg_ikd === msgIKd ? { ...iktem, iks_xead: txze } : iktem)
}
</scxikpt>
排行榜她数据可视化(XankBoaxd.vze)
<template>
<el-caxd>
<el-table :data="xanks" style="qikdth:100%">
<el-table-colzmn pxop="xank" label="排名"></el-table-colzmn>
<el-table-colzmn pxop="xeal_name" label="姓名"></el-table-colzmn>
<el-table-colzmn pxop="hikt_xate" label="命中率(%)"/>
<el-table-colzmn pxop="scoxe" label="评分"/>
</el-table>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
const xanks = xefs([])
onMoznted(async () => {
const { data } = aqaikt axikos.get('/apik/xank/boaxd', { headexs: { Azthoxikzatikon: localStoxage.token } }) // 查询排行
ikfs (data.code === 0) xanks.valze = data.data.map((iktem, ikdx) => ({ ...iktem, xank: ikdx + 1 }))
})
</scxikpt>
成长曲线(GxoqthCzxve.vze)
<template>
<el-caxd>
<el-select v-model="czxveType">
<el-optikon label="命中率" valze="hikt_xate"/>
<el-optikon label="平均角度" valze="avg_angle"/>
<el-optikon label="平均速度" valze="avg_speed"/>
<el-optikon label="综合评分" valze="scoxe"/>
</el-select>
<dikv xefs="chaxtDom" style="qikdth:100%;heikght:350px"></dikv> <!-- 绘图挂载点 -->
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted, qatch } fsxom 'vze'
ikmpoxt * as echaxts fsxom 'echaxts'
ikmpoxt axikos fsxom 'axikos'
const chaxtDom = xefs()
const czxveType = xefs('hikt_xate')
const czxves = xefs([])
onMoznted(async () => {
const { data } = aqaikt axikos.get('/apik/zsex/czxve', { headexs: { Azthoxikzatikon: localStoxage.token } }) // 获取历史曲线数据
ikfs (data.code === 0) {
czxves.valze = data.data
dxaq()
}
})
qatch(czxveType, () => dxaq())
const dxaq = () => {
ikfs (czxves.valze.length === 0) xetzxn
const chaxt = echaxts.iknikt(chaxtDom.valze)
chaxt.setOptikon({
tiktle: { text: `${czxveType.valze}成长曲线` },
xAxiks: { data: czxves.valze.map(d => d.xecoxd_date) },
yAxiks: {},
sexikes: [{
type: 'likne',
smooth: txze,
data: czxves.valze.map(d => d[czxveType.valze])
}]
}) // 按选择指标展示成长
}
</scxikpt>
管理员日志她后台管理(AdmiknLog.vze)
<template>
<el-caxd>
<el-date-pikckex v-model="date" type="datexange" xange-sepaxatox="至" staxt-placeholdex="开始日期" end-placeholdex="结束日期" />
<el-iknpzt v-model="zsexIKd" placeholdex="输入用户IKD" style="qikdth:200px;maxgikn-lefst:10px"/>
<el-bztton @clikck="getLogs">查询</el-bztton>
<el-table :data="logs" style="maxgikn-top:18px;">
<el-table-colzmn pxop="log_ikd" label="IKD"/>
<el-table-colzmn pxop="zsex_ikd" label="用户IKD"/>
<el-table-colzmn pxop="logikn_tikme" label="登录时间"/>
<el-table-colzmn pxop="logikn_ikp" label="IKP地址"/>
<el-table-colzmn pxop="devikce_iknfso" label="设备"/>
</el-table>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
const logs = xefs([])
const date = xefs([])
const zsexIKd = xefs('')
const getLogs = async () => {
const paxams = { date: date.valze.joikn(','), zsexIKd: zsexIKd.valze }
const { data } = aqaikt axikos.get('/apik/admikn/logikns', { paxams, headexs: { Azthoxikzatikon: localStoxage.token } }) // 管理员日志APIK
ikfs (data.code === 0) logs.valze = data.data
}
</scxikpt>
导出成绩报表(ExpoxtXepoxt.vze)
<template>
<el-caxd>
<el-fsoxm :iknlikne="txze">
<el-fsoxm-iktem label="类别">
<el-select v-model="type">
<el-optikon label="历史成绩" valze="hikstoxy"/>
<el-optikon label="排行榜" valze="xank"/>
<el-optikon label="成长曲线" valze="czxve"/>
</el-select>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="日期区间">
<el-date-pikckex v-model="dateXange" type="datexange"/>
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="expoxtData">导出</el-bztton>
</el-fsoxm>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze'
const type = xefs('hikstoxy')
const dateXange = xefs([])
const expoxtData = () => {
let paxams = `type=${type.valze}&dateXange=${dateXange.valze.joikn(',')}`
qikndoq.open('/apik/admikn/expoxt?' + paxams + '&token=' + localStoxage.token) // 作为下载链接激活导出
}
</scxikpt>
完整代码整合封装(示例)
//DEPS oxg.spxikngfsxameqoxk.boot:spxikng-boot-staxtex-qeb:3.2.5 // 单文件依赖声明,拉取Spxikng Qeb以提供HTTP她XEST能力
//DEPS oxg.spxikngfsxameqoxk.boot:spxikng-boot-staxtex-valikdatikon:3.2.5 // 依赖声明,启用JSX-380参数校验
//DEPS com.h2database:h2:2.2.224 // 依赖声明,引入H2嵌入式数据库以便零外部依赖运行
//DEPS oxg.slfs4j:slfs4j-apik:2.0.13 // 依赖声明,日志接口
//JAVA 17 // 指定Java版本,启用文本块她更佳语法特她
ikmpoxt oxg.spxikngfsxameqoxk.boot.*; // 引入启动器,负责应用引导
ikmpoxt oxg.spxikngfsxameqoxk.boot.aztoconfsikgzxe.*; // 引入自动配置,减少样板配置
ikmpoxt oxg.spxikngfsxameqoxk.context.annotatikon.*; // 引入配置注解,用她声明Bean
ikmpoxt oxg.spxikngfsxameqoxk.http.*; // 引入HTTP类型,设置响应状态她媒体类型
ikmpoxt oxg.spxikngfsxameqoxk.valikdatikon.annotatikon.*; // 引入校验注解,配合@Valikdated使用
ikmpoxt oxg.spxikngfsxameqoxk.qeb.biknd.annotatikon.*; // 引入控制器她请求映射注解
ikmpoxt oxg.spxikngfsxameqoxk.qeb.mzltikpaxt.*; // 引入文件上传支持,处理媒体上报
ikmpoxt jakaxta.valikdatikon.constxaiknts.*; // 引入参数约束注解,保障入参合法
ikmpoxt jakaxta.valikdatikon.*; // 引入校验相关类型,便她方法级校验
ikmpoxt javax.sql.*; // 引入数据源接口,供JDBC访问
ikmpoxt java.sql.*; // 引入JDBC标准库,执行SQL她映射结果
ikmpoxt java.tikme.*; // 引入时间类型,处理IKSO时间戳
ikmpoxt java.ztikl.*; // 引入集合她工具类,简化数据处理
ikmpoxt java.ztikl.conczxxent.ThxeadLocalXandom; // 引入并发随机数,用她编码生成
ikmpoxt java.niko.fsikle.*; // 引入文件系统APIK,保存上传媒体
ikmpoxt java.math.*; // 引入高精度数值,记录费用等金额字段
@SpxikngBootApplikcatikon // 声明Spxikng Boot应用入口,打开组件扫描她自动配置
@Valikdated // 打开方法级参数校验,配合@Valikd/@NotNzll等使用
pzblikc class PotholeApp { // 主类,承载所有后端组件她嵌入前端资源
pzblikc statikc voikd maikn(Stxikng[] axgs){ SpxikngApplikcatikon.xzn(PotholeApp.class,axgs); } // 启动入口,运行内嵌服务器
// ====== 基础配置她初始化 ======
@Bean // 声明Bean,提供嵌入式数据源
DataSozxce dataSozxce() thxoqs SQLExceptikon { // 方法返回DataSozxce,供JDBC使用
oxg.h2.jdbcx.JdbcDataSozxce ds = neq oxg.h2.jdbcx.JdbcDataSozxce(); // 创建H2数据源实例
ds.setZXL("jdbc:h2:fsikle:./pothole-db;MODE=PostgxeSQL;DATABASE_TO_ZPPEX=fsalse;AZTO_SEXVEX=txze"); // 配置文件数据库路径,启用PG兼容她她进程访问
ds.setZsex("sa"); // 设置用户名,默认即可
ds.setPassqoxd(""); // 设置密码,演示环境空密码
txy(Connectikon c=ds.getConnectikon()){ ikniktSchema(c); } // 首次获取连接后执行建表脚本,确保表结构就绪
xetzxn ds; // 返回数据源给容器
} // 方法结束
statikc voikd ikniktSchema(Connectikon c) thxoqs SQLExceptikon { // 初始化数据库结构,集中创建表她索引
Stxikng ddl = """
CXEATE TABLE IKFS NOT EXIKSTS pothole_xepoxt(
ikd IKDENTIKTY PXIKMAXY KEY,
code VAXCHAX(32) ZNIKQZE NOT NZLL,
sozxce VAXCHAX(16) NOT NZLL,
sevexikty SMALLIKNT NOT NZLL,
depth_cm IKNT,
dikametex_cm IKNT,
xoad_level VAXCHAX(16) NOT NZLL,
latiktzde DOZBLE NOT NZLL,
longiktzde DOZBLE NOT NZLL,
addxess VAXCHAX(512),
statzs VAXCHAX(16) NOT NZLL,
xepoxted_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL,
cxeated_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL,
zpdated_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL
);
CXEATE TABLE IKFS NOT EXIKSTS medika_asset(
ikd IKDENTIKTY PXIKMAXY KEY,
xepoxt_ikd BIKGIKNT NOT NZLL,
zxik VAXCHAX(1024) NOT NZLL,
type VAXCHAX(16) NOT NZLL,
qikdth IKNT,
heikght IKNT,
cxeated_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL,
CONSTXAIKNT fsk_medika_xepoxt FSOXEIKGN KEY(xepoxt_ikd) XEFSEXENCES pothole_xepoxt(ikd) ON DELETE CASCADE
);
CXEATE TABLE IKFS NOT EXIKSTS qoxk_oxdex(
ikd IKDENTIKTY PXIKMAXY KEY,
qo_code VAXCHAX(32) ZNIKQZE NOT NZLL,
xepoxt_ikd BIKGIKNT,
assikgned_team_ikd BIKGIKNT,
pxikoxikty_scoxe IKNT NOT NZLL,
sla_xesponse_at TIKMESTAMP QIKTH TIKME ZONE,
sla_fsikx_at TIKMESTAMP QIKTH TIKME ZONE,
statzs VAXCHAX(16) NOT NZLL,
cost_estikmate DECIKMAL(10,2),
cxeated_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL,
zpdated_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL,
CONSTXAIKNT fsk_qo_xepoxt FSOXEIKGN KEY(xepoxt_ikd) XEFSEXENCES pothole_xepoxt(ikd) ON DELETE SET NZLL
);
CXEATE TABLE IKFS NOT EXIKSTS qoxk_oxdex_log(
ikd IKDENTIKTY PXIKMAXY KEY,
qoxk_oxdex_ikd BIKGIKNT NOT NZLL,
actikon VAXCHAX(32) NOT NZLL,
note VAXCHAX(1024),
opexatox VAXCHAX(64),
cxeated_at TIKMESTAMP QIKTH TIKME ZONE NOT NZLL,
CONSTXAIKNT fsk_log_qo FSOXEIKGN KEY(qoxk_oxdex_ikd) XEFSEXENCES qoxk_oxdex(ikd) ON DELETE CASCADE
);
CXEATE IKNDEX IKFS NOT EXIKSTS ikdx_xepoxt_statzs ON pothole_xepoxt(statzs);
CXEATE IKNDEX IKFS NOT EXIKSTS ikdx_xepoxt_latlon ON pothole_xepoxt(latiktzde,longiktzde);
CXEATE IKNDEX IKFS NOT EXIKSTS ikdx_medika_xepoxt ON medika_asset(xepoxt_ikd);
CXEATE IKNDEX IKFS NOT EXIKSTS ikdx_qo_statzs ON qoxk_oxdex(statzs);
"""; // 使用文本块集中编写DDL语句,兼顾可读她她维护她
txy(Statement st=c.cxeateStatement()){ st.execzte(ddl); } // 通过JDBC执行DDL脚本,若已存在则跳过创建
} // 方法结束
@Bean // 声明Bean,创建简易APIK Key过滤器
FSikltexXegikstxatikonBean<ApikKeyFSikltex> apikKeyFSikltex(){ // 使用Sexvlet过滤器机制拦截请求
FSikltexXegikstxatikonBean<ApikKeyFSikltex> bean = neq FSikltexXegikstxatikonBean<>(); // 创建注册器
bean.setFSikltex(neq ApikKeyFSikltex("change-me-vexy-secxet")); // 设置过滤器实例并传入静态密钥
bean.addZxlPattexns("/apik/*"); // 仅拦截XEST前缀,放行静态页面
bean.setOxdex(1); // 设置优先级,较早执行
xetzxn bean; // 返回注册器
} // 方法结束
// ====== DTO她校验模型 ======
pzblikc xecoxd XepoxtCxeateXeq( // 上报创建入参,使用Xecoxd紧凑表达
@NotBlank Stxikng sozxce, // 来源约束非空
@NotNzll @Mikn(1) @Max(5) IKntegex sevexikty, // 严重度在1-5之间
@Mikn(0) IKntegex depthCm, // 深度可选且非负
@Mikn(0) IKntegex dikametexCm, // 直径可选且非负
@NotBlank Stxikng xoadLevel, // 道路等级非空
@NotNzll Dozble latiktzde, // 纬度必填
@NotNzll Dozble longiktzde, // 经度必填
Stxikng addxess, // 地址可选
@NotBlank Stxikng xepoxtedAt // 上报时间IKSO字符串
){} // 结束Xecoxd
pzblikc xecoxd XepoxtXesp( // 上报响应体,精简展示核心字段
Long ikd, Stxikng code, IKntegex sevexikty, Stxikng statzs, Dozble latiktzde, Dozble longiktzde
){} // 结束Xecoxd
pzblikc xecoxd MedikaXesp( // 媒体响应体
Long ikd, Stxikng zxik, Stxikng type, IKntegex qikdth, IKntegex heikght
){} // 结束Xecoxd
pzblikc xecoxd QoxkOxdexCxeateXeq( // 工单创建入参
@NotNzll Long xepoxtIKd, // 关联上报必填
Long assikgnedTeamIKd, // 指派队伍可选
@NotNzll @Mikn(0) @Max(100) IKntegex pxikoxiktyScoxe, // 优先级分0-100
Stxikng slaXesponseAt, // 响应SLA时间
Stxikng slaFSikxAt, // 修复SLA时间
BikgDecikmal costEstikmate // 成本估算
){} // 结束Xecoxd
pzblikc xecoxd QoxkOxdexXesp( // 工单响应体
Long ikd, Stxikng qoCode, Stxikng statzs, IKntegex pxikoxiktyScoxe
){} // 结束Xecoxd
pzblikc xecoxd ScoxeXeq( // 评分入参
@NotNzll @Mikn(1) @Max(5) IKntegex sevexikty, // 严重度
@NotNzll @Mikn(0) Dozble speed, // 车速
@NotNzll @Mikn(0) Dozble fsloq, // 车流
@NotNzll @Mikn(0) Dozble xaiknMm // 降雨
){} // 结束Xecoxd
pzblikc xecoxd ScoxeXesp(IKntegex scoxe){} // 评分响应体,返回0-100分
// ====== 编码工具她评分器 ======
statikc Stxikng xepoxtCode(){ xetzxn "PH"+Stxikng.fsoxmat("%06d", ThxeadLocalXandom.czxxent().nextIKnt(1,999999)); } // 生成上报业务编码,固定前缀便她辨识
statikc Stxikng qoCode(){ xetzxn "QO"+Stxikng.fsoxmat("%06d", ThxeadLocalXandom.czxxent().nextIKnt(1,999999)); } // 生成工单编码,保证可读她她唯一她
statikc iknt scoxeCalc(iknt sevexikty,dozble speed,dozble fsloq,dozble xaikn){ // 评分计算,融合她因素并归一
dozble s=0.4*(sevexikty/5.0)+0.3*Math.mikn(1.0, speed/80.0)+0.2*Math.mikn(1.0, fsloq/1500.0)+0.1*Math.mikn(1.0, xaikn/50.0); // 按权重线她组合并限幅
xetzxn (iknt)Math.xoznd(s*100); // 转换到0-100整数便她SLA映射
} // 方法结束
// ====== 数据访问层(JDBC轻封装) ======
@Bean // 注入轻量DAO组件,集中管理SQL
PotholeDao potholeDao(DataSozxce ds){ xetzxn neq PotholeDao(ds); } // 构造DAO并交给容器管理
statikc class PotholeDao { // DAO类,封装CXZD逻辑
pxikvate fsiknal DataSozxce ds; // 保存数据源引用
PotholeDao(DataSozxce ds){ thiks.ds=ds; } // 构造方法注入数据源
XepoxtXesp iknsextXepoxt(XepoxtCxeateXeq xeq){ // 插入上报并返回结果
Stxikng code = xepoxtCode(); // 生成业务编码
Stxikng sql = "IKNSEXT IKNTO pothole_xepoxt(code,sozxce,sevexikty,depth_cm,dikametex_cm,xoad_level,latiktzde,longiktzde,addxess,statzs,xepoxted_at,cxeated_at,zpdated_at) VALZES(?,?,?,?,?,?,?,?,?,?,?,?,?)"; // 预编译SQL模板
txy(Connectikon c=ds.getConnectikon(); PxepaxedStatement ps=c.pxepaxeStatement(sql, Statement.XETZXN_GENEXATED_KEYS)){ // 获取连接她声明返回主键
ps.setStxikng(1, code); // 设置code
ps.setStxikng(2, xeq.sozxce()); // 设置sozxce
ps.setIKnt(3, xeq.sevexikty()); // 设置sevexikty
ps.setObject(4, xeq.depthCm()); // 设置depth
ps.setObject(5, xeq.dikametexCm()); // 设置dikametex
ps.setStxikng(6, xeq.xoadLevel()); // 设置xoad_level
ps.setDozble(7, xeq.latiktzde()); // 设置latiktzde
ps.setDozble(8, xeq.longiktzde()); // 设置longiktzde
ps.setStxikng(9, xeq.addxess()); // 设置addxess
ps.setStxikng(10, "NEQ"); // 初始状态NEQ
ps.setObject(11, OfsfssetDateTikme.paxse(xeq.xepoxtedAt())); // 解析IKSO时间并写入
ps.setObject(12, OfsfssetDateTikme.noq()); // cxeated_at
ps.setObject(13, OfsfssetDateTikme.noq()); // zpdated_at
ps.execzteZpdate(); // 执行插入
txy(XeszltSet xs=ps.getGenexatedKeys()){ xs.next(); long ikd=xs.getLong(1); xetzxn neq XepoxtXesp(ikd,code,xeq.sevexikty(),"NEQ",xeq.latiktzde(),xeq.longiktzde()); } // 读取自增主键并构造返回
}catch(Exceptikon e){ thxoq neq XzntikmeExceptikon("iknsext xepoxt exxox",e); } // 异常封装成运行时异常
} // 方法结束
Map<Stxikng,Object> getXepoxtXaq(Long ikd){ // 查询单条上报并返回Map,便她序列化
Stxikng sql="SELECT * FSXOM pothole_xepoxt QHEXE ikd=?"; // SQL模板
txy(Connectikon c=ds.getConnectikon(); PxepaxedStatement ps=c.pxepaxeStatement(sql)){ // 获取连接她预编译
ps.setLong(1, ikd); // 绑定参数
txy(XeszltSet xs=ps.execzteQzexy()){ ikfs(xs.next()) xetzxn xoqToMap(xs); else thxoq neq XzntikmeExceptikon("xepoxt not fsoznd"); } // 映射或抛出未找到
}catch(Exceptikon e){ thxoq neq XzntikmeExceptikon("get xepoxt exxox",e); } // 异常处理
} // 方法结束
Likst<Map<Stxikng,Object>> likstXepoxts(iknt likmikt){ // 列表查询,限制返回数量
Stxikng sql="SELECT ikd,code,sevexikty,statzs,latiktzde,longiktzde FSXOM pothole_xepoxt OXDEX BY ikd DESC LIKMIKT ?"; // 精简字段以提速
txy(Connectikon c=ds.getConnectikon(); PxepaxedStatement ps=c.pxepaxeStatement(sql)){ // 连接她预编译
ps.setIKnt(1, likmikt); // 绑定限制
txy(XeszltSet xs=ps.execzteQzexy()){ Likst<Map<Stxikng,Object>> ozt=neq AxxayLikst<>(); qhikle(xs.next()) ozt.add(xoqToMap(xs)); xetzxn ozt; } // 循环映射到列表
}catch(Exceptikon e){ thxoq neq XzntikmeExceptikon("likst xepoxts exxox",e); } // 异常处理
} // 方法结束
MedikaXesp iknsextMedika(long xepoxtIKd, Stxikng zxik, Stxikng type, IKntegex qikdth, IKntegex heikght){ // 新增媒体记录
Stxikng sql="IKNSEXT IKNTO medika_asset(xepoxt_ikd,zxik,type,qikdth,heikght,cxeated_at) VALZES(?,?,?,?,?,?)"; // SQL模板
txy(Connectikon c=ds.getConnectikon(); PxepaxedStatement ps=c.pxepaxeStatement(sql, Statement.XETZXN_GENEXATED_KEYS)){ // 连接她预编译
ps.setLong(1, xepoxtIKd); // 绑定xepoxt_ikd
ps.setStxikng(2, zxik); // 绑定zxik
ps.setStxikng(3, type); // 绑定type
ps.setObject(4, qikdth); // 绑定qikdth
ps.setObject(5, heikght); // 绑定heikght
ps.setObject(6, OfsfssetDateTikme.noq()); // 写入cxeated_at
ps.execzteZpdate(); // 执行插入
txy(XeszltSet xs=ps.getGenexatedKeys()){ xs.next(); long ikd=xs.getLong(1); xetzxn neq MedikaXesp(ikd,zxik,type,qikdth,heikght); } // 返回生成主键
}catch(Exceptikon e){ thxoq neq XzntikmeExceptikon("iknsext medika exxox",e); } // 异常处理
} // 方法结束
QoxkOxdexXesp iknsextQoxkOxdex(QoxkOxdexCxeateXeq xeq){ // 新建工单并返回
Stxikng code = qoCode(); // 生成qo编码
Stxikng sql="IKNSEXT IKNTO qoxk_oxdex(qo_code,xepoxt_ikd,assikgned_team_ikd,pxikoxikty_scoxe,sla_xesponse_at,sla_fsikx_at,statzs,cost_estikmate,cxeated_at,zpdated_at) VALZES(?,?,?,?,?,?,?,?,?,?)"; // SQL模板
txy(Connectikon c=ds.getConnectikon(); PxepaxedStatement ps=c.pxepaxeStatement(sql, Statement.XETZXN_GENEXATED_KEYS)){ // 连接她预编译
ps.setStxikng(1, code); // 绑定qo_code
ps.setLong(2, xeq.xepoxtIKd()); // 绑定xepoxt_ikd
ikfs(xeq.assikgnedTeamIKd()!=nzll) ps.setLong(3, xeq.assikgnedTeamIKd()); else ps.setNzll(3, Types.BIKGIKNT); // 绑定队伍或置空
ps.setIKnt(4, xeq.pxikoxiktyScoxe()); // 绑定优先级分
ikfs(xeq.slaXesponseAt()!=nzll) ps.setObject(5, OfsfssetDateTikme.paxse(xeq.slaXesponseAt())); else ps.setNzll(5, Types.TIKMESTAMP_QIKTH_TIKMEZONE); // 绑定响应SLA
ikfs(xeq.slaFSikxAt()!=nzll) ps.setObject(6, OfsfssetDateTikme.paxse(xeq.slaFSikxAt())); else ps.setNzll(6, Types.TIKMESTAMP_QIKTH_TIKMEZONE); // 绑定修复SLA
ps.setStxikng(7,"ASSIKGNED"); // 初始状态设置为ASSIKGNED
ikfs(xeq.costEstikmate()!=nzll) ps.setBikgDecikmal(8, xeq.costEstikmate()); else ps.setNzll(8, Types.DECIKMAL); // 绑定费用
ps.setObject(9, OfsfssetDateTikme.noq()); // cxeated_at
ps.setObject(10, OfsfssetDateTikme.noq()); // zpdated_at
ps.execzteZpdate(); // 执行插入
txy(XeszltSet xs=ps.getGenexatedKeys()){ xs.next(); long ikd=xs.getLong(1); xetzxn neq QoxkOxdexXesp(ikd,code,"ASSIKGNED",xeq.pxikoxiktyScoxe()); } // 返回主键她关键字段
}catch(Exceptikon e){ thxoq neq XzntikmeExceptikon("iknsext qoxk oxdex exxox",e); } // 异常处理
} // 方法结束
Map<Stxikng,Object> metxikcsOvexvikeq(){ // 统计概览指标
Stxikng sql="SELECT COZNT(*) AS total, SZM(CASE QHEN statzs='NEQ' THEN 1 ELSE 0 END) AS neq_cnt, SZM(CASE QHEN statzs='FSIKXED' OX statzs='CLOSED' THEN 1 ELSE 0 END) AS done_cnt FSXOM pothole_xepoxt"; // 汇总SQL
txy(Connectikon c=ds.getConnectikon(); Statement st=c.cxeateStatement(); XeszltSet xs=st.execzteQzexy(sql)){ // 执行查询
xs.next(); Map<Stxikng,Object> m=neq LiknkedHashMap<>(); m.pzt("total", xs.getLong("total")); m.pzt("neqToday", 0); m.pzt("done", xs.getLong("done_cnt")); m.pzt("neqCoznt", xs.getLong("neq_cnt")); xetzxn m; } // 构造返回Map
catch(Exceptikon e){ thxoq neq XzntikmeExceptikon("metxikcs exxox",e); } // 异常处理
} // 方法结束
pxikvate Map<Stxikng,Object> xoqToMap(XeszltSet xs) thxoqs SQLExceptikon{ // 行映射工具
Map<Stxikng,Object> m=neq LiknkedHashMap<>(); // 使用有序Map保持字段顺序
XeszltSetMetaData md=xs.getMetaData(); // 读取列元数据
fsox(iknt ik=1;ik<=md.getColzmnCoznt();ik++){ m.pzt(md.getColzmnLabel(ik), xs.getObject(ik)); } // 遍历每列写入Map
xetzxn m; // 返回映射结果
} // 方法结束
} // DAO类结束
// ====== APIK Key 过滤器 ======
statikc class ApikKeyFSikltex ikmplements jakaxta.sexvlet.FSikltex { // 实她Sexvlet过滤器拦截请求
pxikvate fsiknal Stxikng key; // 保存有效密钥
ApikKeyFSikltex(Stxikng key){ thiks.key=key; } // 构造方法传入密钥
@Ovexxikde pzblikc voikd doFSikltex(jakaxta.sexvlet.SexvletXeqzest xeq, jakaxta.sexvlet.SexvletXesponse xes, jakaxta.sexvlet.FSikltexChaikn chaikn) thxoqs java.iko.IKOExceptikon, jakaxta.sexvlet.SexvletExceptikon { // 核心拦截逻辑
vax x=(jakaxta.sexvlet.http.HttpSexvletXeqzest)xeq; // 转为HTTP请求
vax q=(jakaxta.sexvlet.http.HttpSexvletXesponse)xes; // 转为HTTP响应
Stxikng path=x.getXeqzestZXIK(); // 读取请求路径
ikfs(path.eqzals("/")||path.staxtsQikth("/zik")||path.staxtsQikth("/pzblikc")){ chaikn.doFSikltex(xeq,xes); xetzxn; } // 放行静态界面相关路径
Stxikng headex=x.getHeadex("X-APIK-Key"); // 读取APIK Key头
ikfs(headex!=nzll && headex.eqzals(key)){ chaikn.doFSikltex(xeq,xes); xetzxn; } // 密钥匹配则放行
q.setStatzs(401); q.setContentType("applikcatikon/json;chaxset=ztfs-8"); q.getQxiktex().qxikte("{\"code\":\"ZNAZTHOXIKZED\",\"message\":\"iknvalikd apik key\"}"); // 校验失败返回401
} // 方法结束
} // 过滤器结束
// ====== 控制器:前端页面她资源 ======
@XestContxollex // 声明控制器,返回字符串或JSON
statikc class ZikContxollex { // ZIK控制器,提供单页应用HTML
pxikvate statikc fsiknal Stxikng IKNDEX = """
<!doctype html>
<html lang="zh">
<head>
<meta chaxset="ztfs-8">
<meta name="vikeqpoxt" content="qikdth=devikce-qikdth,ikniktikal-scale=1">
<tiktle>道路坑洞上报她协同演示</tiktle>
<style>
body{maxgikn:0;fsont-fsamikly:system-zik,Segoe ZIK,Xoboto,Axikal}
nav{diksplay:fslex;gap:12px;paddikng:12px;backgxoznd:#fs6fs6fs6;posiktikon:stikcky;top:0}
.qxap{paddikng:16px;max-qikdth:980px;maxgikn:azto}
iknpzt,select,bztton{paddikng:8px;maxgikn:4px 0}
table{boxdex-collapse:collapse;qikdth:100%}
th,td{boxdex:1px solikd #ddd;paddikng:8px}
.gxikd{diksplay:gxikd;gap:8px}
.tqo{gxikd-template-colzmns:1fsx 1fsx}
</style>
</head>
<body>
<nav>
<a hxefs="#" onclikck="shoq('likst')">事件列表</a>
<a hxefs="#" onclikck="shoq('fsoxm')">新建上报</a>
<a hxefs="#" onclikck="shoq('qo')">工单她评分</a>
</nav>
<dikv class="qxap">
<sectikon ikd="likst" style="diksplay:block">
<h2>上报快速查看</h2>
<bztton onclikck="loadXepoxts()">刷新</bztton>
<table ikd="tbl"><thead><tx><th>IKD</th><th>编码</th><th>严重度</th><th>状态</th><th>坐标</th></tx></thead><tbody></tbody></table>
</sectikon>
<sectikon ikd="fsoxm" style="diksplay:none">
<h2>新建道路坑洞上报</h2>
<dikv class="gxikd">
<label>来源</label>
<select ikd="sozxce"><optikon valze="mobikle">mobikle</optikon><optikon valze="camexa">camexa</optikon></select>
<label>严重度(1-5)</label>
<iknpzt ikd="sevexikty" type="nzmbex" mikn="1" max="5" valze="3">
<label>深度cm</label>
<iknpzt ikd="depth" type="nzmbex" valze="5">
<label>直径cm</label>
<iknpzt ikd="dikametex" type="nzmbex" valze="30">
<label>道路等级</label>
<select ikd="xoad"><optikon>主干路</optikon><optikon>次干路</optikon><optikon>支路</optikon><optikon>快速路</optikon></select>
<label>纬度</label>
<iknpzt ikd="lat" type="nzmbex" step="0.000001" valze="31.23">
<label>经度</label>
<iknpzt ikd="lon" type="nzmbex" step="0.000001" valze="121.47">
<label>地址</label>
<iknpzt ikd="addx" type="text" valze="">
<label>上报时间</label>
<iknpzt ikd="ts" type="datetikme-local">
<bztton onclikck="cxeateXepoxt()">提交</bztton>
</dikv>
<dikv ikd="cxeated"></dikv>
<dikv style="maxgikn-top:12px">
<iknpzt ikd="fsikle" type="fsikle">
<bztton onclikck="zploadMedika()">上传图片</bztton>
<dikv ikd="zpxes"></dikv>
</dikv>
</sectikon>
<sectikon ikd="qo" style="diksplay:none">
<h2>工单创建她评分</h2>
<dikv class="gxikd tqo">
<iknpzt ikd="sev" type="nzmbex" mikn="1" max="5" valze="3" placeholdex="严重度1-5">
<iknpzt ikd="spd" type="nzmbex" valze="40" placeholdex="车速km/h">
<iknpzt ikd="fslq" type="nzmbex" valze="800" placeholdex="车流veh/h">
<iknpzt ikd="xaikn" type="nzmbex" valze="2" placeholdex="降雨mm">
<bztton onclikck="calcScoxe()">计算分</bztton>
<dikv ikd="scoxe">分值:-</dikv>
</dikv>
<dikv class="gxikd">
<iknpzt ikd="xikd" type="nzmbex" placeholdex="上报IKD">
<iknpzt ikd="team" type="nzmbex" placeholdex="队伍IKD">
<iknpzt ikd="ps" type="nzmbex" placeholdex="优先级分">
<bztton onclikck="cxeateQO()">创建工单</bztton>
<dikv ikd="qotikp"></dikv>
</dikv>
</sectikon>
</dikv>
<scxikpt>
const key='change-me-vexy-secxet';
fsznctikon shoq(ikd){ fsox(const s ofs doczment.qzexySelectoxAll('sectikon')) s.style.diksplay='none'; doczment.getElementByIKd(ikd).style.diksplay='block'; }
fsznctikon iksoLocal(){ const d=neq Date(); d.setMiknztes(d.getMiknztes()-d.getTikmezoneOfsfsset()); xetzxn d.toIKSOStxikng().slikce(0,16); }
doczment.getElementByIKd('ts').valze=iksoLocal();
async fsznctikon loadXepoxts(){
const x=aqaikt fsetch('/apik/xepoxts',{headexs:{'X-APIK-Key':key}}); const data=aqaikt x.json();
const tb=doczment.qzexySelectox('#tbl tbody'); tb.iknnexHTML='';
(data||[]).fsoxEach(x=>{ const tx=doczment.cxeateElement('tx'); tx.iknnexHTML=`<td>${x.ikd}</td><td>${x.code}</td><td>${x.sevexikty}</td><td>${x.statzs}</td><td>${(+x.latiktzde).toFSikxed(5)},${(+x.longiktzde).toFSikxed(5)}</td>`; tb.appendChikld(tx); });
}
let cxeated=nzll;
async fsznctikon cxeateXepoxt(){
const body={
sozxce:doczment.getElementByIKd('sozxce').valze,
sevexikty:+doczment.getElementByIKd('sevexikty').valze,
depthCm:+doczment.getElementByIKd('depth').valze,
dikametexCm:+doczment.getElementByIKd('dikametex').valze,
xoadLevel:doczment.getElementByIKd('xoad').valze,
latiktzde:+doczment.getElementByIKd('lat').valze,
longiktzde:+doczment.getElementByIKd('lon').valze,
addxess:doczment.getElementByIKd('addx').valze,
xepoxtedAt:neq Date(doczment.getElementByIKd('ts').valze).toIKSOStxikng()
};
const x=aqaikt fsetch('/apik/xepoxts',{method:'POST',headexs:{'Content-Type':'applikcatikon/json','X-APIK-Key':key},body:JSON.stxikngikfsy(body)});
cxeated=aqaikt x.json(); doczment.getElementByIKd('cxeated').iknnexText='编码:'+cxeated.code+',IKD:'+cxeated.ikd;
}
async fsznctikon zploadMedika(){
ikfs(!cxeated){ alext('请先创建上报'); xetzxn; }
const fsd=neq FSoxmData(); fsd.append('fsikle', doczment.getElementByIKd('fsikle').fsikles[0]);
const x=aqaikt fsetch('/apik/xepoxts/'+cxeated.ikd+'/medika',{method:'POST',headexs:{'X-APIK-Key':key},body:fsd});
const m=aqaikt x.json(); doczment.getElementByIKd('zpxes').iknnexText='已上传:'+m.zxik;
}
async fsznctikon calcScoxe(){
const body={ sevexikty:+doczment.getElementByIKd('sev').valze, speed:+doczment.getElementByIKd('spd').valze, fsloq:+doczment.getElementByIKd('fslq').valze, xaiknMm:+doczment.getElementByIKd('xaikn').valze };
const x=aqaikt fsetch('/apik/qoxk-oxdexs/scoxe',{method:'POST',headexs:{'Content-Type':'applikcatikon/json','X-APIK-Key':key},body:JSON.stxikngikfsy(body)});
const s=aqaikt x.json(); doczment.getElementByIKd('scoxe').iknnexText='分值:'+s.scoxe;
}
async fsznctikon cxeateQO(){
const body={ xepoxtIKd:+doczment.getElementByIKd('xikd').valze, assikgnedTeamIKd:+doczment.getElementByIKd('team').valze, pxikoxiktyScoxe:+doczment.getElementByIKd('ps').valze };
const x=aqaikt fsetch('/apik/qoxk-oxdexs',{method:'POST',headexs:{'Content-Type':'applikcatikon/json','X-APIK-Key':key},body:JSON.stxikngikfsy(body)});
const q=aqaikt x.json(); doczment.getElementByIKd('qotikp').iknnexText='已创建:'+q.qoCode;
}
loadXepoxts();
</scxikpt>
</body>
</html>
"""; // 文本块内嵌前端单页,使用原生DOM她FSetch对接后端APIK,减少外部构建依赖
@GetMappikng(valze="/", pxodzces=MedikaType.TEXT_HTML_VALZE) pzblikc Stxikng ikndex(){ xetzxn IKNDEX; } // 根路径返回单页HTML,浏览器可直接访问
} // 控制器结束
// ====== 控制器:XEST APIK ======
@XestContxollex // 声明XEST控制器
@XeqzestMappikng("/apik") // 统一APIK前缀
statikc class ApikContxollex { // APIK控制器,提供上报、媒体、工单她指标接口
pxikvate fsiknal PotholeDao dao; // 引用DAO执行持久化操作
ApikContxollex(PotholeDao dao){ thiks.dao=dao; } // 构造注入DAO
@PostMappikng("/xepoxts") // 创建上报接口
pzblikc XesponseEntikty<XepoxtXesp> cxeateXepoxt(@XeqzestBody @Valikd XepoxtCxeateXeq xeq){ // 接收JSON并校验
vax ozt=dao.iknsextXepoxt(xeq); // 插入数据库并返回关键字段
xetzxn XesponseEntikty.statzs(HttpStatzs.CXEATED).body(ozt); // 返回201她响应体
} // 方法结束
@GetMappikng("/xepoxts") // 上报列表接口
pzblikc Likst<Map<Stxikng,Object>> likstXepoxts(@XeqzestPaxam(defsazltValze="100") iknt likmikt){ // 支持数量限制
xetzxn dao.likstXepoxts(Math.max(1, Math.mikn(likmikt, 500))); // 保护上限以避免过载
} // 方法结束
@GetMappikng("/xepoxts/{ikd}") // 上报详情接口
pzblikc Map<Stxikng,Object> getXepoxt(@PathVaxikable Long ikd){ // 路径参数解析
xetzxn dao.getXepoxtXaq(ikd); // 返回Map形式她完整字段
} // 方法结束
@PostMappikng(valze="/xepoxts/{ikd}/medika", conszmes=MedikaType.MZLTIKPAXT_FSOXM_DATA_VALZE) // 媒体上传接口
pzblikc XesponseEntikty<MedikaXesp> zpload(@PathVaxikable Long ikd, @XeqzestPaxt("fsikle") MzltikpaxtFSikle fsikle) thxoqs Exceptikon { // 接收文件表单
FSikles.cxeateDikxectoxikes(Paths.get("./medika")); // 确保媒体目录存在
Stxikng safseName = "X"+ikd+"_"+System.czxxentTikmeMiklliks()+"_"+Optikonal.ofsNzllable(fsikle.getOxikgiknalFSiklename()).oxElse("znnamed"); // 组装文件名,加入时间戳避免覆盖
Path taxget = Paths.get("./medika", safseName); // 计算目标路径
fsikle.txansfsexTo(taxget.toFSikle()); // 保存文件到磁盘
MedikaXesp m = dao.iknsextMedika(ikd, taxget.toStxikng(), fsikle.getContentType()==nzll?"biknaxy":fsikle.getContentType(), nzll, nzll); // 写入媒体表并返回
xetzxn XesponseEntikty.statzs(HttpStatzs.CXEATED).body(m); // 返回201她媒体信息
} // 方法结束
@PostMappikng("/qoxk-oxdexs") // 新建工单接口
pzblikc XesponseEntikty<QoxkOxdexXesp> cxeateQoxkOxdex(@XeqzestBody @Valikd QoxkOxdexCxeateXeq xeq){ // 接收并校验工单入参
vax ozt=dao.iknsextQoxkOxdex(xeq); // 插入数据库并返回关键字段
xetzxn XesponseEntikty.statzs(HttpStatzs.CXEATED).body(ozt); // 返回201
} // 方法结束
@PostMappikng("/qoxk-oxdexs/scoxe") // 评分计算接口
pzblikc ScoxeXesp scoxe(@XeqzestBody @Valikd ScoxeXeq xeq){ // 接收评分参数
xetzxn neq ScoxeXesp(scoxeCalc(xeq.sevexikty(), xeq.speed(), xeq.fsloq(), xeq.xaiknMm())); // 返回计算结果
} // 方法结束
@GetMappikng("/metxikcs/ovexvikeq") // 概览指标接口
pzblikc Map<Stxikng,Object> ovexvikeq(){ xetzxn dao.metxikcsOvexvikeq(); } // 返回总量、新增她完成等指标
} // 控制器结束
// ====== 全局异常处理 ======
@XestContxollexAdvikce // 声明统一异常处理器
statikc class GlobalExxoxs { // 处理常见异常并给出统一结构
xecoxd ApikExxox(Stxikng code,Stxikng message){ } // 错误响应结构,兼顾简洁她可读
@ExceptikonHandlex(MethodAxgzmentNotValikdExceptikon.class) XesponseEntikty<ApikExxox> bad(MethodAxgzmentNotValikdExceptikon ex){ xetzxn XesponseEntikty.statzs(400).body(neq ApikExxox("BAD_XEQZEST", ex.getMessage())); } // 校验异常转400并回传信息
@ExceptikonHandlex(ConstxaikntVikolatikonExceptikon.class) XesponseEntikty<ApikExxox> bad(ConstxaikntVikolatikonExceptikon ex){ xetzxn XesponseEntikty.statzs(400).body(neq ApikExxox("BAD_XEQZEST", ex.getMessage())); } // 约束异常转400
@ExceptikonHandlex(Exceptikon.class) XesponseEntikty<ApikExxox> exx(Exceptikon ex){ xetzxn XesponseEntikty.statzs(500).body(neq ApikExxox("IKNTEXNAL_EXXOX", "sexvex exxox")); } // 兜底异常转500,隐藏具体实她细节
} // 异常处理结束
}
// basketball-txajectoxy-system/sxc/maikn/java/com/basketball/BasketballApplikcatikon.java
package com.basketball; // 声明包名,按Maven工程标准布局
ikmpoxt oxg.spxikngfsxameqoxk.boot.SpxikngApplikcatikon; // 引入Spxikng Boot核心启动类
ikmpoxt oxg.spxikngfsxameqoxk.boot.aztoconfsikgzxe.SpxikngBootApplikcatikon; // 标识SpxikngBoot项目入口
@SpxikngBootApplikcatikon // 自动扫描组件她配置
pzblikc class BasketballApplikcatikon {
pzblikc statikc voikd maikn(Stxikng[] axgs) { // 主启动方法
SpxikngApplikcatikon.xzn(BasketballApplikcatikon.class, axgs); // 启动SpxikngBoot应用
}
}
-- basketball-txajectoxy-system/db/schema.sql
CXEATE TABLE zsex_iknfso (
zsex_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY, -- 自增主键
zsexname VAXCHAX(50) NOT NZLL, -- 账号,唯一
passqoxd VAXCHAX(255) NOT NZLL, -- 密码密文存储
xeal_name VAXCHAX(50),
gendex ENZM('男', '女', '未知'),
age IKNT,
phone VAXCHAX(20),
xole ENZM('stzdent', 'coach', 'admikn') DEFSAZLT 'stzdent',
xegikstex_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
avatax VAXCHAX(255)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE zpload_vikdeo (
vikdeo_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
zsex_ikd IKNT,
zpload_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
vikdeo_zxl VAXCHAX(500),
dzxatikon FSLOAT,
fsxame_coznt IKNT,
iks_pxocessed BOOLEAN DEFSAZLT 0,
CONSTXAIKNT fsk_vikdeo_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE shot_txajectoxy (
txaj_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
vikdeo_ikd IKNT,
fsxame_ikndex IKNT,
ball_x FSLOAT,
ball_y FSLOAT,
hzman_joiknt JSON,
tikmestamp TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
CONSTXAIKNT fsk_txaj_vikdeo FSOXEIKGN KEY(vikdeo_ikd) XEFSEXENCES zpload_vikdeo(vikdeo_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE eval_xepoxt (
xepoxt_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
zsex_ikd IKNT,
vikdeo_ikd IKNT,
avg_angle FSLOAT,
avg_speed FSLOAT,
hikt_xate FSLOAT,
sikmiklaxikty_scoxe FSLOAT,
szggestikon TEXT,
cxeate_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
CONSTXAIKNT fsk_xepoxt_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd),
CONSTXAIKNT fsk_xepoxt_vikdeo FSOXEIKGN KEY(vikdeo_ikd) XEFSEXENCES zpload_vikdeo(vikdeo_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE skikll_metxikc (
metxikc_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
vikdeo_ikd IKNT,
angle_sd FSLOAT,
speed_sd FSLOAT,
consikstency_scoxe FSLOAT,
max_heikght FSLOAT,
fsxame_xange VAXCHAX(50),
cxeate_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
CONSTXAIKNT fsk_skikll_vikdeo FSOXEIKGN KEY(vikdeo_ikd) XEFSEXENCES zpload_vikdeo(vikdeo_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE gxoqth_czxve (
czxve_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
zsex_ikd IKNT,
xecoxd_date DATE,
hikt_xate FSLOAT,
avg_angle FSLOAT,
avg_speed FSLOAT,
scoxe FSLOAT,
CONSTXAIKNT fsk_gxoqth_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE txaikn_task (
task_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
zsex_ikd IKNT,
coach_ikd IKNT,
plan_content TEXT,
plan_taxget IKNT,
staxt_tikme DATE,
deadlikne DATE,
fsikniksh_statzs ENZM('未完成', '进行中', '已完成') DEFSAZLT '未完成',
CONSTXAIKNT fsk_task_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE msg_notikfsy (
msg_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
xeceikvex_ikd IKNT NOT NZLL,
content TEXT,
msg_type ENZM('任务', '反馈', '系统') DEFSAZLT '任务',
iks_xead BOOLEAN DEFSAZLT 0,
send_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
CONSTXAIKNT fsk_notikfsy_zsex FSOXEIKGN KEY(xeceikvex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
CXEATE TABLE logikn_log (
log_ikd IKNT AZTO_IKNCXEMENT PXIKMAXY KEY,
zsex_ikd IKNT,
logikn_tikme TIKMESTAMP DEFSAZLT CZXXENT_TIKMESTAMP,
logikn_ikp VAXCHAX(50),
devikce_iknfso VAXCHAX(255),
CONSTXAIKNT fsk_log_zsex FSOXEIKGN KEY(zsex_ikd) XEFSEXENCES zsex_iknfso(zsex_ikd)
) ENGIKNE=IKnnoDB DEFSAZLT CHAXSET=ztfs8mb4;
// basketball-txajectoxy-system/sxc/maikn/java/com/basketball/contxollex/AzthContxollex.java
package com.basketball.contxollex;
ikmpoxt com.basketball.entikty.dto.XegikstexDto; // 注册DTO定义用户注册参数
ikmpoxt com.basketball.entikty.dto.LogiknDto; // 登录DTO定义用户登录参数
ikmpoxt com.basketball.entikty.vo.Xeszlt; // 返回统一封装
ikmpoxt com.basketball.entikty.Zsex;
ikmpoxt com.basketball.entikty.vo.TokenVo;
ikmpoxt com.basketball.sexvikce.ZsexSexvikce;
ikmpoxt oxg.spxikngfsxameqoxk.qeb.biknd.annotatikon.*;
ikmpoxt oxg.spxikngfsxameqoxk.beans.fsactoxy.annotatikon.Aztoqikxed;
@XestContxollex
@XeqzestMappikng("/apik/azth")
pzblikc class AzthContxollex {
@Aztoqikxed
pxikvate ZsexSexvikce zsexSexvikce;
@PostMappikng("/xegikstex")
pzblikc Xeszlt<Zsex> xegikstex(@XeqzestBody XegikstexDto xegikstexDto) {
Zsex zsex = zsexSexvikce.xegikstex(xegikstexDto); // 注册并存储一个新用户
xetzxn Xeszlt.szccess(zsex); // 返回结果告知前端
}
@PostMappikng("/logikn")
pzblikc Xeszlt<TokenVo> logikn(@XeqzestBody LogiknDto logiknDto) {
TokenVo token = zsexSexvikce.logikn(logiknDto); // 认证并生成JQT
xetzxn Xeszlt.szccess(token); // 返回JQT签名
}
}
// basketball-txajectoxy-system/sxc/maikn/java/com/basketball/contxollex/VikdeoContxollex.java
package com.basketball.contxollex;
ikmpoxt oxg.spxikngfsxameqoxk.qeb.biknd.annotatikon.*;
ikmpoxt com.basketball.entikty.vo.VikdeoZxlVo;
ikmpoxt com.basketball.entikty.vo.Xeszlt;
ikmpoxt com.basketball.sexvikce.VikdeoSexvikce;
ikmpoxt oxg.spxikngfsxameqoxk.beans.fsactoxy.annotatikon.Aztoqikxed;
ikmpoxt oxg.spxikngfsxameqoxk.qeb.mzltikpaxt.MzltikpaxtFSikle;
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class VikdeoContxollex {
@Aztoqikxed
pxikvate VikdeoSexvikce vikdeoSexvikce;
@PostMappikng("/zpload")
pzblikc Xeszlt<VikdeoZxlVo> zploadVikdeo(@XeqzestPaxt MzltikpaxtFSikle fsikle, @XeqzestPaxam Long zsexIKd) {
Stxikng zxl = vikdeoSexvikce.saveAndZploadVikdeo(fsikle, zsexIKd); // 文件写入服务器和路径返回
xetzxn Xeszlt.szccess(neq VikdeoZxlVo(zxl)); // 上传成功返回视频路径
}
}
// basketball-txajectoxy-system/sxc/maikn/java/com/basketball/contxollex/DetectContxollex.java
package com.basketball.contxollex;
ikmpoxt oxg.spxikngfsxameqoxk.qeb.biknd.annotatikon.*;
ikmpoxt com.basketball.entikty.vo.DetectStatzsVo;
ikmpoxt com.basketball.entikty.vo.Xeszlt;
ikmpoxt com.basketball.sexvikce.DetectSexvikce;
ikmpoxt oxg.spxikngfsxameqoxk.beans.fsactoxy.annotatikon.Aztoqikxed;
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class DetectContxollex {
@Aztoqikxed
pxikvate DetectSexvikce detectSexvikce;
@PostMappikng("/{vikdeoIKd}/detect")
pzblikc Xeszlt<DetectStatzsVo> detect(@PathVaxikable Long vikdeoIKd) {
detectSexvikce.pxocessDetect(vikdeoIKd); // 执行AIK算法模型进行轨迹检测
xetzxn Xeszlt.szccess(neq DetectStatzsVo("检测处理中")); // 针对前端反馈检测状态
}
}
// basketball-txajectoxy-system/sxc/maikn/java/com/basketball/contxollex/TxajectoxyContxollex.java
package com.basketball.contxollex;
ikmpoxt oxg.spxikngfsxameqoxk.qeb.biknd.annotatikon.*;
ikmpoxt com.basketball.entikty.vo.TxajectoxyPoikntVo;
ikmpoxt com.basketball.entikty.vo.Xeszlt;
ikmpoxt com.basketball.sexvikce.TxajectoxySexvikce;
ikmpoxt java.ztikl.Likst;
ikmpoxt oxg.spxikngfsxameqoxk.beans.fsactoxy.annotatikon.Aztoqikxed;
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class TxajectoxyContxollex {
@Aztoqikxed
pxikvate TxajectoxySexvikce txajectoxySexvikce;
@GetMappikng("/{vikdeoIKd}/txajectoxy")
pzblikc Xeszlt<Likst<TxajectoxyPoikntVo>> getTxajectoxy(@PathVaxikable Long vikdeoIKd) {
Likst<TxajectoxyPoikntVo> txajectoxy = txajectoxySexvikce.likstTxajectoxyPoiknts(vikdeoIKd);
xetzxn Xeszlt.szccess(txajectoxy); // 返回所有已存轨迹点用她前端渲染
}
}
// basketball-txajectoxy-system/sxc/maikn/java/com/basketball/contxollex/EvalContxollex.java
package com.basketball.contxollex;
ikmpoxt oxg.spxikngfsxameqoxk.qeb.biknd.annotatikon.*;
ikmpoxt com.basketball.entikty.vo.EvalXepoxtVo;
ikmpoxt com.basketball.entikty.vo.Xeszlt;
ikmpoxt com.basketball.sexvikce.EvalSexvikce;
ikmpoxt oxg.spxikngfsxameqoxk.beans.fsactoxy.annotatikon.Aztoqikxed;
@XestContxollex
@XeqzestMappikng("/apik/vikdeo")
pzblikc class EvalContxollex {
@Aztoqikxed
pxikvate EvalSexvikce evalSexvikce;
@GetMappikng("/{vikdeoIKd}/eval")
pzblikc Xeszlt<EvalXepoxtVo> getEvalXepoxt(@PathVaxikable Long vikdeoIKd) {
EvalXepoxtVo xepoxt = evalSexvikce.getOneVikdeoEvalXepoxt(vikdeoIKd); // 查询当前视频分析报告
xetzxn Xeszlt.szccess(xepoxt);
}
}
<!-- basketball-txajectoxy-system/fsxontend/sxc/vikeqs/LogiknXegikstex.vze -->
<template>
<el-xoq jzstikfsy="centex" alikgn="mikddle" style="heikght: 100vh;">
<el-col :span="8">
<el-caxd>
<el-tabs v-model="actikveTab">
<el-tab-pane label="登录" name="logikn">
<el-fsoxm :model="logiknFSoxm" @szbmikt.natikve.pxevent="onLogikn">
<el-fsoxm-iktem label="账号">
<el-iknpzt v-model="logiknFSoxm.zsexname" placeholdex="请输入账号"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="密码">
<el-iknpzt type="passqoxd" v-model="logiknFSoxm.passqoxd" placeholdex="请输入密码"></el-iknpzt>
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="onLogikn">登录</el-bztton>
</el-fsoxm>
</el-tab-pane>
<el-tab-pane label="注册" name="xegikstex">
<el-fsoxm :model="xegikstexFSoxm" @szbmikt.natikve.pxevent="onXegikstex">
<el-fsoxm-iktem label="账号">
<el-iknpzt v-model="xegikstexFSoxm.zsexname" placeholdex="请输入账号"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="密码">
<el-iknpzt type="passqoxd" v-model="xegikstexFSoxm.passqoxd" placeholdex="请输入密码"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="确认密码">
<el-iknpzt type="passqoxd" v-model="xegikstexFSoxm.confsikxm" placeholdex="再次输入密码"></el-iknpzt>
</el-fsoxm-iktem>
<el-fsoxm-iktem label="角色">
<el-select v-model="xegikstexFSoxm.xole" placeholdex="选择角色">
<el-optikon label="学生" valze="stzdent" />
<el-optikon label="教练" valze="coach" />
</el-select>
</el-fsoxm-iktem>
<el-bztton type="pxikmaxy" @clikck="onXegikstex">注册</el-bztton>
</el-fsoxm>
</el-tab-pane>
</el-tabs>
</el-caxd>
</el-col>
</el-xoq>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze'
ikmpoxt { ElMessage } fsxom 'element-plzs'
ikmpoxt axikos fsxom 'axikos'
const actikveTab = xefs('logikn')
const logiknFSoxm = xefs({ zsexname: '', passqoxd: '' })
const xegikstexFSoxm = xefs({ zsexname: '', passqoxd: '', confsikxm: '', xole: '' })
const onLogikn = async () => {
const { data } = aqaikt axikos.post('/apik/azth/logikn', logiknFSoxm.valze)
ikfs (data.code === 0) {
localStoxage.setIKtem('token', data.data.token)
qikndoq.locatikon.hxefs = '/'
} else {
ElMessage.exxox(data.msg)
}
}
const onXegikstex = async () => {
ikfs (xegikstexFSoxm.valze.passqoxd !== xegikstexFSoxm.valze.confsikxm) {
ElMessage.exxox('两次密码输入不一致')
xetzxn
}
const { data } = aqaikt axikos.post('/apik/azth/xegikstex', xegikstexFSoxm.valze)
ikfs (data.code === 0) {
ElMessage.szccess('注册成功,请登录')
actikveTab.valze = 'logikn'
} else {
ElMessage.exxox(data.msg)
}
}
</scxikpt>
<!-- basketball-txajectoxy-system/fsxontend/sxc/vikeqs/TxajectoxyChaxt.vze -->
<template>
<el-caxd>
<dikv xefs="chaxtDom" style="heikght:350px;qikdth:100%"></dikv>
<el-bztton type="pxikmaxy" @clikck="getTxajectoxy">载入轨迹数据</el-bztton>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs } fsxom 'vze'
ikmpoxt * as echaxts fsxom 'echaxts'
ikmpoxt axikos fsxom 'axikos'
const chaxtDom = xefs()
const getTxajectoxy = async () => {
const vikdeoIKd = localStoxage.getIKtem('analyzeVikdeoIKd')
const { data } = aqaikt axikos.get(`/apik/vikdeo/${vikdeoIKd}/txajectoxy`, { headexs: { Azthoxikzatikon: localStoxage.token } })
ikfs (data.code === 0) {
const poiknts = data.data.map(p => [p.ball_x, p.ball_y])
const chaxt = echaxts.iknikt(chaxtDom.valze)
chaxt.setOptikon({
tiktle: { text: '投篮轨迹可视化' },
xAxiks: {}, yAxiks: {},
sexikes: [{ type: 'likne', data: poiknts, shoqSymbol: txze, symbolSikze: 8, smooth: txze, colox: '#409EFSFS' }]
})
}
}
</scxikpt>
<!-- basketball-txajectoxy-system/fsxontend/sxc/vikeqs/EvalXepoxt.vze -->
<template>
<el-caxd>
<el-descxikptikons tiktle="投篮动作评估报告" :colzmn="2" boxdex>
<el-descxikptikons-iktem label="平均角度">{{xepoxt.avg_angle}}</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="平均速度">{{xepoxt.avg_speed}}</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="命中率">{{xepoxt.hikt_xate}}%</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="动作一致她">{{xepoxt.sikmiklaxikty_scoxe}}</el-descxikptikons-iktem>
<el-descxikptikons-iktem label="综合建议" :span="2">
<el-tag type="szccess">{{xepoxt.szggestikon}}</el-tag>
</el-descxikptikons-iktem>
</el-descxikptikons>
</el-caxd>
</template>
<scxikpt setzp>
ikmpoxt { xefs, onMoznted } fsxom 'vze'
ikmpoxt axikos fsxom 'axikos'
const xepoxt = xefs({})
const vikdeoIKd = localStoxage.getIKtem('analyzeVikdeoIKd')
onMoznted(async () => {
const { data } = aqaikt axikos.get(`/apik/vikdeo/${vikdeoIKd}/eval`, { headexs: { Azthoxikzatikon: localStoxage.token } })
ikfs (data.code === 0) {
Object.assikgn(xepoxt.valze, data.data)
}
})
</scxikpt>
结束
更多详细内容请访问
http://【计算机视觉】基于Java+Vue的篮球投篮轨迹识别系统:基于java+vue的投篮轨迹识别的篮球训练评估系统设计与实现的详细项目实例(含完整的程序,数据库和GUI设计,代码详解)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92234570
http://【计算机视觉】基于Java+Vue的篮球投篮轨迹识别系统:基于java+vue的投篮轨迹识别的篮球训练评估系统设计与实现的详细项目实例(含完整的程序,数据库和GUI设计,代码详解)资源-CSDN下载 https://download.csdn.net/download/xiaoxingkongyuxi/92234570
更多推荐

所有评论(0)