Compare commits

...

243 Commits
main ... dev

Author SHA1 Message Date
小张
fa88b3c164 feat:精选资源视频解析修复 2025-10-20 10:56:56 +08:00
小张
4f9f8d0a88 feat:精选资源视频解析修复 2025-10-17 18:21:03 +08:00
yuk255
d5bbc38ddf feat:考试、练习模块对接完善 2025-10-15 21:11:45 +08:00
小张
e66b21a871 feat:精选资源视频解析修复 2025-10-15 15:18:02 +08:00
yuk255
412a796ecb feat:作业模块对接 2025-10-14 22:03:55 +08:00
小张
5455490811 feat: 集成AI知识库管理系统
- 新增AI知识库管理功能模块
- 实现知识库的增删改查功能
- 实现文档管理(文本/文件/链接)
- 实现向量化功能和测试
- 支持卡片式布局展示
- 完整的响应式设计
- 修复所有TypeScript类型错误
- 添加依赖:marked@^16.4.0, less@^4.2.2
- 打包测试通过

主要文件:
- src/views/teacher/ai-knowledge-naive-ui/ - AI知识库管理模块
- docs/ - 相关API文档
- package.json - 新增依赖配置
2025-10-14 17:33:25 +08:00
小张
5de4c9596f feat:精选资源 2025-10-13 23:28:05 +08:00
yuk255
6a8078e272 feat:学员中心:资料页面对接;教师后台:个人中心对接 2025-10-13 20:54:38 +08:00
小张
b093dcd630 feat:精选资源 2025-10-13 19:04:05 +08:00
小张
3ff9e43877 feat:精选资源 2025-10-13 17:59:51 +08:00
yuk255
42d84ee2fa fix:修复激活菜单图片失效的bug 2025-10-13 16:48:53 +08:00
yuk255
3262b8c979 fix:修复报错 2025-10-10 19:55:00 +08:00
yuk255
949d5f439d feat:学员中心菜单对接接口;教师端菜单添加一个显示的判断 2025-10-10 09:50:46 +08:00
yuk255
49a55c6c26 fix:修复报错 2025-10-09 14:52:18 +08:00
yuk255
68f3652935 fix:修复报错 2025-10-09 14:49:41 +08:00
yuk255
5b125c15b2 fix:修复学员中心页面的打包错误 2025-10-09 10:00:28 +08:00
yuk255
8d2b4037d4 Merge branch 'dev' of http://110.42.96.64:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-09-29 22:03:44 +08:00
yuk255
00ae37c216 Merge branch 'dev' of http://110.42.96.64:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-09-29 22:02:59 +08:00
小张
3bd9e1fac3 feat:首页对接 2025-09-29 22:01:20 +08:00
yuk255
dd1c8de407 feat:对接学院个人中心-我的课程页面 2025-09-29 21:27:37 +08:00
yuk255
4c43226c91 feat:教师端菜单栏替换为接口获取动态渲染 2025-09-29 21:26:56 +08:00
小张
d9c455d946 feat:首页对接 2025-09-29 17:38:56 +08:00
QDKF
a7d8b00fe9 fix: 修复教学建设接口数据渲染问题 2025-09-27 20:59:06 +08:00
QDKF
080ce9e724 fix: 修复学员端我的消息滚动问题 2025-09-27 20:51:47 +08:00
QDKF
fed060545a feat: 学员端我的消息: 消息加载动画、@功能、表情/图片发送、5s轮询、空状态适配;接入课程教学统计接口 2025-09-27 20:37:31 +08:00
小张
b52a954e86 feat:bug修改 2025-09-27 01:21:47 +08:00
QDKF
a55bf916c2 feat: 学员端调整页面, 接入部分接口 2025-09-26 20:33:47 +08:00
yuk255
a5bb4de1fe feat: 教师端个人中心页面修改重构 2025-09-26 18:15:45 +08:00
小张
d5346675ae feat:今日视频logo等等bug修改 2025-09-25 22:16:22 +08:00
QDKF
cb0de218fa feat: 注释AI助教和智能体编排功能模块 2025-09-25 20:55:32 +08:00
QDKF
41cccd9f7a fix: 修复班级切换时选中状态保持问题 2025-09-25 20:29:08 +08:00
QDKF
8297d62258 fix: 修复批量调班功能问题 2025-09-25 20:16:25 +08:00
QDKF
97d8e99689 feat: 完善消息中心和班级管理功能 2025-09-25 20:01:32 +08:00
QDKF
8a8fd09137 feat: 调整课程内容和字幕列表样式 2025-09-25 11:42:31 +08:00
yuk255
03f9d1b423 fix:修复章节预览弹窗部分报错;修改评论页面布局;隐藏资源菜单 2025-09-25 10:27:51 +08:00
QDKF
82ae528785 feat: 课程详细页面:课程介绍,课程介绍,教学团队,章节目录,评论接入接口; 课程内容,字幕列表接入接口 2025-09-24 20:49:26 +08:00
QDKF
6b3846ea50 feat: 调整教师团队管理表格内容 2025-09-23 19:20:43 +08:00
QDKF
17ed40fc23 feat: 教师团队管理接入接口 2025-09-23 19:12:00 +08:00
小张
978713b316 feat:新增loading, 2025-09-23 18:09:59 +08:00
QDKF
ce6a0d41eb perf: 优化聊天体验,移除发送图片和文件后的重新加载 2025-09-23 17:37:58 +08:00
QDKF
2a7da14df5 merge: 解决合并冲突 2025-09-23 17:29:00 +08:00
QDKF
0e176e8d3c merge: 解决冲突并合并远程更新 2025-09-23 17:25:10 +08:00
QDKF
5c14a13f5e feat: 完善班级管理,消息中心对接接口,添加样式,修复打包报错 2025-09-23 17:24:16 +08:00
yuk255
75fd712a32 style:消息中心滚动样式修复 2025-09-23 16:53:12 +08:00
yuk255
254fb72d0d feat:添加小节预览功能;完善章节编辑功能 2025-09-23 16:47:14 +08:00
小张
ce54a41f4a feat:练习讨论对接接口 2025-09-23 16:23:02 +08:00
小张
7aa5257cbd feat:讨论点赞切换切图 2025-09-23 15:12:30 +08:00
小张
fbe2060425 feat:讨论点赞切换切图 2025-09-23 15:11:58 +08:00
小张
52e57b7cf3 feat:投诉弹窗,ai伴学页面完善,未报名已报名修改,ai区域样式调整 2025-09-23 14:32:44 +08:00
小张
9b6ad60913 feat:播放器添加清晰度,然后讨论添加icon 2025-09-23 14:31:39 +08:00
yuk255
0de7531c1a style:试题编辑页面滚动样式问题修复 2025-09-23 12:36:43 +08:00
小张
5519a849a3 feat:练习讨论 2025-09-23 12:22:00 +08:00
小张
9aa5fbcea0 feat:bug修复 2025-09-23 10:41:09 +08:00
小张
2e3b6a6cf7 feat:ai对话和我们的视频播放 2025-09-23 09:31:08 +08:00
yuk255
f152497cab style: 页面样式优化 2025-09-22 22:27:17 +08:00
yuk255
f80fcb7025 feat:作业编辑接口替换;章节编辑新增字段替换,回显功能完善 2025-09-22 22:26:58 +08:00
QDKF
b2ec1e2015 feat: 修复班级管理报错;添加课程内容,字幕列表页面;即时消息接入部分接口且完善接口所需样式 2025-09-22 21:12:48 +08:00
QDKF
62143affd5 feat: 消息中心接入部分接口,调整样式 2025-09-22 14:58:12 +08:00
yuk255
3e1f1fdc67 feat:课程模块下接口对接 2025-09-22 14:07:28 +08:00
小张
52b9e9a475 feat:bug统一修复 2025-09-22 11:58:34 +08:00
小张
bf6496b755 feat:bug统一修复 2025-09-21 04:12:09 +08:00
小张
6d6ded74b4 feat:bug修改 2025-09-20 18:02:40 +08:00
QDKF
50adc24979 feat: 调整路由 2025-09-20 14:35:59 +08:00
QDKF
b5db02d95c fix: 修复系统消息API响应数据格式解析错误 2025-09-19 20:41:08 +08:00
QDKF
dd73e28b08 fix: 修复消息中心角标显示问题 2025-09-19 20:26:43 +08:00
QDKF
23c54eaf40 feat: 消息中心接入接口,修复分页功能样式,新增班级Excel导出,统计页课程详情接入接口 2025-09-19 20:15:10 +08:00
小张
e687fa8ebd feat:讨论模式页面全部完成,bug修改,吴老师说的bug修改 2025-09-19 18:48:17 +08:00
yuk255
061a67a5e8 style:修复侧边栏高度溢出问题;修复课件导航条层级过高,浮动在nav上部错误样式 2025-09-19 10:59:17 +08:00
小张
23f6924711 feat:答题卡页面封装,练习功能全部完成 2025-09-19 01:49:34 +08:00
QDKF
935c68ac6d feat: 即时消息页面重构,新增表情,图片,文件功能,修复聊天区域布局问题,解决消息过多时输入框被挤下去的问题,调整系统消息页面 2025-09-18 22:35:37 +08:00
yuk255
aa87b0e8e4 feat: 课件界面重构,对接接口;章节页面基础框架接口对接;一些样式优化 2025-09-18 19:52:57 +08:00
小张
b20cc50f44 feat:讨论模式页面框架搭建 2025-09-18 02:18:47 +08:00
QDKF
8de56bd07c feat: 证书页面添加过滤动画,空状态样式,搜索反馈 2025-09-17 22:41:42 +08:00
yuk255
3c3c2063b0 fix:修复编辑按钮跳转失败问题 2025-09-17 13:01:27 +08:00
yuk255
e086442a2d fix:修复试卷页面不能跳转批阅和分析页面的bug 2025-09-17 12:57:28 +08:00
yuk255
8a2a8add39 feat:课程新增编辑添加学期和允许资源下载开关 2025-09-17 10:38:18 +08:00
yuk255
a4cd04429a fix:修复打包报错 2025-09-16 20:09:56 +08:00
yuk255
bff716f6b6 fix:修复课程删除报错,修复课程编辑字段保存回显问题 2025-09-16 19:42:33 +08:00
yuk255
568d8fdf47 refactor:重构章节新增编辑页面 2025-09-16 19:41:56 +08:00
yuk255
3425097b15 style: 修复教师端已知的页面滚动和页面过高的样式问题 2025-09-16 19:35:34 +08:00
QDKF
7e540664e2 feat: 添加班级管理搜索,调整学员库数据,批量删除,分页器显示,修复侧边栏高度问题 2025-09-16 19:28:31 +08:00
小张
68c64a96c1 feat:报错修复,练习页面加载, 2025-09-16 18:52:38 +08:00
小张
27b68d2abc feat:新增运维模式 2025-09-16 15:00:36 +08:00
QDKF
ef49c7b6d3 feat: 对接我的会话,查询会话消息,查询群聊成员列表,查询课程评论接口;添加会话消息空状态样式,添加证书中心内容样式,修复班级管理组件删除学员功能 2025-09-15 19:34:25 +08:00
yuk255
ad2ec33c6a fix:修复课程页面进入错误刷新的问题 2025-09-15 16:27:30 +08:00
yuk255
b287cf73b9 feat:修改菜单顺序,修改部分菜单命名 2025-09-15 15:44:23 +08:00
QDKF
760290bfb0 feat: 修复 2025-09-15 11:56:14 +08:00
小张
ed8e688422 feat:根据吴老师进行样式修改 2025-09-15 10:04:37 +08:00
QDKF
1721ab50fc feat: 试卷管理:删除接口,添加试卷部分接口(获取题库,获取题目,导入,导出功能),修复题库管理获取课程列表,分页器显示和切换问题,对接导入题库接口,添加试题接入查询分类,难度接口,修复试题渲染问题,修复编辑题目时选项数据无法正确显示的问题,添加试题编辑接口 2025-09-13 19:50:45 +08:00
yuk255
3461499661 feat:添加学校列表接口 2025-09-13 19:37:59 +08:00
yuk255
d9d80c8337 feat:对接课程下教师的接口;修改章节页面 2025-09-13 16:20:00 +08:00
小张
2031fa4ba4 feat:修复 2025-09-13 15:57:26 +08:00
小张
c35f54fdd9 feat:修复 2025-09-13 15:53:02 +08:00
yuk255
155db7a1e4 feat:对接部分班级页面接口,修改了部分课程页面,对接了一部分接口 2025-09-12 22:59:14 +08:00
QDKF
e645a190dd feat: 课程章节部分接口对接(编辑,查询,删除章节);阅卷中心接口对接: 获取阅卷列表, 获取班级列表;试卷管理接口对接: 获取试卷列表 2025-09-12 19:50:04 +08:00
小张
59c4d9ebc5 feat:修复 2025-09-12 17:26:58 +08:00
QDKF
21845cb21a feat: 课程章节部分接口对接(编辑,查询,删除章节), 合并远程更新并恢复本地 api 修改 2025-09-12 15:28:31 +08:00
小张
0c638147f2 feat:搜索结果展示 2025-09-12 03:11:18 +08:00
小张
7551571f0a feat:注册接口对接 2025-09-11 23:13:47 +08:00
yuk255
7911565249 feat:对接部分课程和班级接口 2025-09-11 14:34:30 +08:00
小张
7fb049d31d feat:即刻对话区域,和顶部logo切换,home页面的80改到50百分之, 2025-09-11 01:12:14 +08:00
QDKF
ec1a19d005 feat: 完善教师端AI助教和个人中心页面;新增AI助教分析页面(AssistantDetail.vue);优化AI助教主页面(Assistant.vue) 2025-09-10 21:30:45 +08:00
QDKF
2a3e6ccd91 fix: 修复白屏问题、路由冲突和TypeScript错误,打包问题,调整tab悬停样式 2025-09-10 16:14:51 +08:00
小张
b283f4e3c7 feat:搜索浮窗,和接口调用 2025-09-09 15:00:37 +08:00
QDKF
9b601f9117 style: 左侧导航栏菜单恢复为调整前样式 2025-09-08 21:01:40 +08:00
QDKF
75d722440f style: 调整左侧导航栏菜单 2025-09-08 20:18:27 +08:00
QDKF
2c1fb5ab7f feat: 完成“我的资源”页面,功能 2025-09-08 19:15:49 +08:00
小张
7de929ac18 feat:新浮窗,和切换语言,和个人中心的字体统一旧函数方法删除 2025-09-08 11:31:04 +08:00
小张
eb4c8504b1 feat:新浮窗,和切换语言,和个人中心的字体统一 2025-09-07 17:50:03 +08:00
QDKF
21b76b9683 feat: 完善课程详情页面;修复课程详情页面打包问题 2025-09-07 03:59:41 +08:00
QDKF
e39010c484 route: 路由调整 2025-09-06 17:20:05 +08:00
小张
f4991929c6 feat:新即时消息页面初步实现,ai伴学判定图标,fixbug修复 2025-09-06 02:18:54 +08:00
QDKF
e1b32c2c3c fix: 修复题目管理页面的 TypeScript 类型错误 2025-09-06 01:20:37 +08:00
QDKF
3d5d34b660 feat: 实现课程讨论管理和学习监控系统:新增讨论管理、评论查看、添加讨论页面;修复打包问题 2025-09-06 01:01:12 +08:00
yuk255
764064bd80 feat:添加试卷分析页面;添加消息中心页面 2025-09-05 21:00:10 +08:00
小张
6b685501dd feat:hls流误删导致视频报错,作业资料接口对接,逻辑处理下载,课程列表按钮按照 后端请求分为需传token 和不需要根据是否登录判断 2025-09-05 19:46:11 +08:00
小张
71ea0bbfb4 feat:hls流误删导致视频报错,作业资料接口对接,逻辑处理下载,课程列表按钮按照 后端请求分为需传token 和不需要根据是否登录判断 2025-09-04 23:15:29 +08:00
yuk255
81c0556559 feat:添加学院中心下班级管理页面和班级管理下的统计分析、学习进度页面 2025-09-04 20:38:53 +08:00
QDKF
580e32d69c fix: 修复打包错误 2025-09-04 17:25:47 +08:00
QDKF
a30e23ab07 feat: 完成学情统计和学生成绩页面开发:新增LearningStatistics.vue学情统计页面,包含6个统计模块和ECharts图表,新增StudentGrades.vue学生成绩页面,支持成绩管理、权重设置和提醒功能 2025-09-04 17:23:05 +08:00
小张
dd11e9aa2d feat:视频删除和之前的方法使用视频的bug修复 2025-09-03 22:55:49 +08:00
小张
177bdbc009 feat:课程列表ai伴学模式修发布评论对接 2025-09-03 22:17:58 +08:00
yuk255
7b993f0648 feat:添加课程管理菜单下的班级管理;优化导入组件;添加学员库页面 2025-09-03 20:51:13 +08:00
QDKF
a0cb27afe4 feat: 添加统计首页, 基础数据,课堂报告页面 2025-09-03 19:19:32 +08:00
小张
39020bd14c feat:课程列表ai伴学模式修改 2025-09-03 16:54:50 +08:00
小张
9a37ff49bc feat:学习进度对接和逻辑计算 2025-09-03 10:07:59 +08:00
yuk255
44e734b50c fix:修复打包报错 2025-09-02 20:29:13 +08:00
yuk255
739ad411c1 feat:添加课程-管理页面;考试管理菜单也同步添加到课程管理下;优化了一些页面 2025-09-02 20:21:02 +08:00
QDKF
f888b0b458 feat: 完善添加,编辑证书和相关页面,功能 2025-09-02 18:39:38 +08:00
小张
adeaf086c4 feat:学习进度对接和逻辑计算 2025-09-02 18:04:22 +08:00
小张
f0320a021d feat:对接ai伴学普通和ai伴学模式 2025-09-02 17:15:46 +08:00
小张
5f199931ca feat:ai伴学普通区分调整 2025-09-02 16:29:25 +08:00
QDKF
2aac753e3a fix: 修复打包报错 2025-09-01 22:38:43 +08:00
guoan
46df63e7fd feat: 更换图片, 调整样式 2025-09-01 22:35:40 +08:00
yuk255
96f433c745 fix: 修复打包报错 2025-09-01 22:04:00 +08:00
小张
5621903f34 feat:bug修复 2025-09-01 21:55:52 +08:00
yuk255
27f41332d4 Merge branches 'dev' and 'dev' of http://110.42.96.64:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-09-01 20:52:10 +08:00
yuk255
02dfa15e75 fix: 课程管理下的页面样式和逻辑补全优化并添加了文件预览页面 2025-09-01 20:51:13 +08:00
小张
b3ed88602f feat:ai伴学的未报名已报名完善央视修改,投诉功能完善,ai助手bug修改, 2025-09-01 20:04:57 +08:00
小张
8e146666f7 fix:配合后端接口变动 2025-09-01 17:56:41 +08:00
yuk255
590af0951f feat: 对接部分题库接口;添加考试界面;部分界面样式优化 2025-08-30 17:50:14 +08:00
小张
57eb57d0ce feat: 优化登录和课程功能
- 修复练习分数显示格式,与考试保持一致
- 增强热门好课报名功能,添加完整的用户反馈和错误处理
- 优化登录流程,添加详细的调试日志
- 修复右上角登录按钮跳转到登录页面
- 添加主标题API接口对接功能
- 改进用户体验和交互反馈
2025-08-30 16:24:08 +08:00
小张
7df60c4ea4 feat:登录功能迁移新登录页面 2025-08-30 15:16:19 +08:00
小张
714de2f19b feat:登录功能迁移新登录页面 2025-08-30 15:13:39 +08:00
小张
1714221e70 feat:登录功能迁移新登录页面 2025-08-30 15:13:24 +08:00
小张
48d80ef281 feat:紧急修复 2025-08-30 14:05:01 +08:00
小张
537a7f8fe6 feat:新评论 2025-08-30 13:46:58 +08:00
小张
06dfacc074 feat:新评论 2025-08-30 03:57:24 +08:00
小张
2aab0f7152 feat:home页面监听滚轮高度实现右下角客服展示等功能 2025-08-30 02:28:29 +08:00
QDKF
8000bde1b9 style: 调整练习考试页面 2025-08-29 22:54:05 +08:00
QDKF
39fff08a0d Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-29 20:12:37 +08:00
QDKF
027253f7b4 save: 更新路由 2025-08-29 20:12:34 +08:00
小张
7bb632f9a9 fix:hls传播问题 2025-08-29 18:28:59 +08:00
yuk255
3d4fa1abb4 feat:对naive ui添加国际化配置;添加考试相关api文件;考试管理菜单下逻辑优化完善;6种题型全部提取为独立组件。 2025-08-29 18:11:47 +08:00
小张
cea9929ebc fix:appheader的样式切换 2025-08-29 17:58:32 +08:00
QDKF
4f90499ada feat: 添加新建证书的页面和功能;页面添加过渡动画;添加证书有效期, 证书分类菜单;添加证书预览功能 2025-08-29 15:39:45 +08:00
小张
7c6c19d8f9 fix:样式UI调整 2025-08-29 03:39:15 +08:00
小张
d841224536 fix:登录页面 2025-08-29 03:09:49 +08:00
QDKF
dc912c3842 feat: 添加教师端证书首页;添加证书详情页;添加证书颁奖页面及一系列功能;添加新增证书页面; 2025-08-28 22:59:34 +08:00
QDKF
597b9a0d3f Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-28 10:37:32 +08:00
QDKF
0d3184104f chore: 保存本地路由调整 2025-08-28 10:37:30 +08:00
小张
8427f0ec82 fix:新登录页面初步实现 2025-08-28 03:26:25 +08:00
yuk255
2c27fe8730 feat:添加试题页面,预览试卷页面,试卷批阅页面添加 2025-08-27 19:53:19 +08:00
QDKF
adf90b1390 style: 调整创建课程页面 2025-08-27 19:06:26 +08:00
QDKF
be64951358 style: 教师端新增批阅作业页面;新增查看作业页面,回复评论 2025-08-27 16:50:14 +08:00
QDKF
788df9a92c Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-27 16:49:13 +08:00
QDKF
1172193733 feat: 更新路由配置 2025-08-27 16:49:10 +08:00
小张
a5a802c4a6 fix:旧方法,mock数据删除 2025-08-26 19:07:48 +08:00
小张
829660dbda feat:课程详情切换ai伴学,里面接口重新调用,dplayer播放器切换,播放器配置, 2025-08-26 18:51:07 +08:00
QDKF
068fc262ab fix: 打包问题 2025-08-26 18:27:42 +08:00
QDKF
541886b6e6 style: 新增添加作业库页面;编辑作业库页面;新增关闭顶部广告功能;调整富文本;添加作业库导入页面 2025-08-26 18:19:23 +08:00
yuk255
638e939fe5 feat:添加添加试题功能页面;添加试题管理的分类对应功能;删除一些不再使用的组件页面;其他样式优化 2025-08-25 20:23:48 +08:00
QDKF
cc7c4ec23a style: 章节模态框 2025-08-25 18:28:46 +08:00
小张
2d0dd00fc4 fix:师资详情页面,积分中心页面路由配置点击,顶部tab切换bug修复 2025-08-25 16:35:54 +08:00
yuk255
37198b3b37 fix:修复教师端考试管理入口被隐藏问题 2025-08-25 11:14:18 +08:00
QDKF
510b2b1b0c style: 教师端页面调整 2025-08-25 10:39:24 +08:00
Wxp
3293384d8e fix: 修复打包问题 2025-08-24 18:31:24 +08:00
Wxp
7be3eca61e style: 课件部分弹窗 2025-08-24 18:20:16 +08:00
Wxp
16ee40e020 style: 换图片 2025-08-23 19:45:38 +08:00
guoan
4d9b5eec2b style: 题库首页,课件弹框 2025-08-23 19:20:14 +08:00
yuk255
844d5721b7 fix: 修改组件路径,修改一些细节样式和报错 2025-08-23 18:43:12 +08:00
yuk255
5e34c71b14 feat: 新增导入组件,支持数据导入及模板下载;修改考试管理对应的路由层级及页面,加入过渡动画效果 2025-08-23 18:27:07 +08:00
小张
8bb211fc33 fix:ai布局调整 2025-08-23 17:56:15 +08:00
yuk255
59faaa25cb feat: 更新侧边栏和二级菜单逻辑,新增题库选择功能 2025-08-22 21:17:10 +08:00
Admin
2d8339ed4e 新增章节编辑器、课件上传弹窗等功能 2025-08-22 21:10:29 +08:00
guoan
56f5e7077e style: 添加课件 2025-08-22 19:59:17 +08:00
guoan
e75ffdf1e8 sytle: 教师端尺寸 2025-08-22 19:52:05 +08:00
小张
c4e96ea899 fix:logo替换 2025-08-22 17:52:39 +08:00
小张
b1a906f176 fix:跳转新增 2025-08-22 17:45:43 +08:00
小张
bc5d21fc76 Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev
# Conflicts:
#	src/views/Faculty.vue
2025-08-22 17:12:06 +08:00
小张
e18d5f610f fix:打包报错 2025-08-22 17:11:28 +08:00
Wxp
4e983b923c merge: integrate origin/dev and resolve conflicts 2025-08-22 17:08:52 +08:00
Wxp
8ce7c66fea style: 章节,作业部分页面 2025-08-22 16:59:07 +08:00
yuk255
8cd22653aa feat:添加练考通模块下的试卷库和新增试卷功能 2025-08-22 16:42:55 +08:00
Wxp
1193c017ee Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-22 16:42:02 +08:00
小张
1a11290c97 fix:ai自适应 2025-08-22 16:40:46 +08:00
小张
ad5b5b5de0 fix:细节修改 2025-08-22 14:53:47 +08:00
小张
f6142edd7d Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-22 13:54:11 +08:00
Wxp
2f13f5da8b Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-21 19:41:58 +08:00
Admin
36be89dac5 新增页面 2025-08-21 19:39:07 +08:00
Wxp
ebae7ab2dd fix: 打包 2025-08-21 16:08:18 +08:00
Admin
7ab20755b4 feat: 添加教师管理图片资源和更新课程组件 2025-08-21 13:07:39 +08:00
Admin
4e58477135 feat: 添加教师管理图片资源和更新课程组件 2025-08-21 11:31:49 +08:00
Admin
b2f00f4801 教师端功能 2025-08-20 23:40:16 +08:00
Admin
9889b6c57d 教师端功能 2025-08-20 22:50:28 +08:00
小张
fea00e8c1a Merge remote-tracking branch 'origin/dev' into dev 2025-08-20 22:30:49 +08:00
小张
7a8ebd903b fix:打包报错 2025-08-20 22:30:37 +08:00
Admin
c6bcb136ad 1 2025-08-20 21:55:23 +08:00
Admin
3fed1249c4 教师端 2025-08-20 21:47:52 +08:00
小张
fa3514dd55 feat:检查报名和报名接口对接 2025-08-20 17:11:43 +08:00
yangdongbit
34738a29e1 教师端页面 2025-08-20 14:10:48 +08:00
小张
a4832dc8fc Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	package-lock.json
#	src/views/CourseDetailEnrolled.vue
2025-08-20 11:16:39 +08:00
小张
5b82a9b044 feat:切换dplayer播放器 2025-08-20 11:15:12 +08:00
Wxp
2ddc067ebc style:换图片 2025-08-19 23:40:22 +08:00
Wxp
f06aef9913 fix: 打包和样式调整 2025-08-19 19:47:12 +08:00
Wxp
d6e76b7c73 merge: 合并远程dev分支,解决冲突 2025-08-19 19:07:54 +08:00
Wxp
0fe429cd79 style: 调整样式 2025-08-19 19:04:11 +08:00
小张
b37cdd3ccc fix:打包报错调整 2025-08-19 02:21:57 +08:00
小张
7cc9a80297 fix:评论调整 2025-08-19 02:06:33 +08:00
小张
bf03f35a35 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	src/views/CourseDetail.vue
#	src/views/CourseDetailEnrolled.vue
2025-08-19 01:59:38 +08:00
小张
9201cc44e5 feat:个人中心对接 2025-08-19 01:50:27 +08:00
Wxp
eff83cfdc3 style:修复个人中心样式冲突 2025-08-18 22:52:22 +08:00
Wxp
713b81c4e1 style:样式 2025-08-18 22:09:42 +08:00
Wxp
fbf783582d style: 完善练习提交页面 2025-08-18 12:03:30 +08:00
Wxp
699c0e733c 优化 2025-08-16 22:48:10 +08:00
Wxp
6e1ad5ea07 样式 2025-08-16 20:39:56 +08:00
Wxp
94ee525ce6 Merge branch 'dev' of http://110.42.96.65:19890/GoCo/OL-LearnPlatform-Frontend into dev 2025-08-16 20:05:35 +08:00
Wxp
7e3e22ee4c 页面 2025-08-16 19:51:39 +08:00
小张
6bdd7d6999 feat:章节对应的视频,视频url切割,可切换清晰度 2025-08-16 13:08:38 +08:00
小张
f4a5f6f782 feat+fix:mock数据后端返回不匹配类型报错,讲师章节树状对接 2025-08-15 18:12:31 +08:00
小张
0e1a73192f fix:mock数据后端返回不匹配类型报错 2025-08-15 13:58:25 +08:00
小张
13113e1bbc feat:对接环境配置,登录,课程相关接口对接 2025-08-15 13:21:10 +08:00
Wxp
a428d2b36b 完善 2025-08-14 17:32:28 +08:00
Wxp
90ffb5a444 修复 2025-08-12 20:26:27 +08:00
Wxp
4bfd6f2351 样式 2025-08-12 19:52:20 +08:00
Wxp
d4db394b58 部分个人中心 2025-08-12 18:22:50 +08:00
Wxp
7e5809afde 样式 2025-08-12 18:10:55 +08:00
Wxp
495d6a2f9e Merge remote-tracking branch 'origin/main' into dev 2025-08-12 17:52:08 +08:00
87cce63ae8 docker compose port 2025-08-11 15:22:31 +08:00
853dd3d7ec 完成合并 dev 分支并解决冲突 2025-08-11 14:00:46 +08:00
a532924668 解决build问题 2025-08-11 10:03:56 +08:00
87478f82f2 ci: 🎡 dockercompose端口 2025-08-10 23:13:30 +08:00
username
c0dbb2c97d init 2025-08-10 22:49:43 +08:00
905 changed files with 247524 additions and 105736 deletions

View File

@ -1,6 +1,8 @@
--- ---
type: "manual" type: "always_apply"
description: "Example description"
--- ---
1、在接下来的每一个步骤当中请帮我实现对页面的响应式设计 1、在接下来的每一个步骤当中请帮我实现对页面的响应式设计
2、必须严格执行我给你的指令一步一步执行不得有缩减 2、必须严格执行我给你的指令一步一步执行不得有缩减
3、我们用的是naive UI组件 TSvue3

2
.env
View File

@ -1,5 +1,5 @@
# API配置 # API配置
VITE_API_BASE_URL=http://110.42.96.65:55510/api VITE_API_BASE_URL=http://103.40.14.23:25526/jeecgboot
# Mock配置 - 禁用Mock使用真实API # Mock配置 - 禁用Mock使用真实API
VITE_ENABLE_MOCK=false VITE_ENABLE_MOCK=false

View File

@ -1,7 +1,7 @@
# 开发环境配置 # 开发环境配置
# API配置 # API配置
VITE_API_BASE_URL=http://110.42.96.65:55510/api VITE_API_BASE_URL=http://103.40.14.23:25526/jeecgboot
# Mock配置 # Mock配置
# 设置为 true 使用Mock数据false 使用真实API # 设置为 true 使用Mock数据false 使用真实API

View File

@ -1,7 +1,7 @@
# 生产环境配置 # 生产环境配置
# API配置 # API配置
VITE_API_BASE_URL=http://110.42.96.65:55510/api VITE_API_BASE_URL=http://103.40.14.23:25526/jeecgboot
# Mock配置 - 生产环境禁用Mock使用真实API # Mock配置 - 生产环境禁用Mock使用真实API
VITE_ENABLE_MOCK=false VITE_ENABLE_MOCK=false

View File

@ -6,6 +6,6 @@ services:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
ports: ports:
- "55514:80" - "25527:80"
container_name: vue3-nginx container_name: vue3-nginx
restart: unless-stopped restart: unless-stopped

View File

@ -0,0 +1,320 @@
# DPlayer 集成指南
## 什么是 DPlayer
**DPlayer** 是由 [DIYGod](https://github.com/DIYGod) 开发的一个开源的 HTML5 视频播放器,具有以下特点:
- 🎨 **界面美观**:现代化的设计风格
- 🎯 **轻量级**:体积小,加载快
- 🌏 **中文友好**:由中国开发者开发,中文文档完善
- 🎮 **功能丰富**:支持弹幕、快捷键、倍速播放等
- 📱 **移动端适配**:响应式设计,支持移动设备
## 主要功能特性
### 基础功能
- ✅ 播放/暂停控制
- ✅ 音量控制
- ✅ 进度条拖拽
- ✅ 全屏切换
- ✅ 倍速播放 (0.5x - 2x)
### 高级功能
- 🎯 键盘快捷键支持
- 🎨 自定义主题色
- 📝 右键菜单自定义
- 🎵 音频可视化
- 📱 移动端手势支持
### 格式支持
- MP4
- WebM
- Ogg
- HLS (.m3u8)
- FLV
- 更多格式通过插件支持
## 安装和集成
### 方法1CDN 引入(推荐用于快速测试)
```html
<!-- 在 index.html 中引入 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.css">
<script src="https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.js"></script>
```
### 方法2NPM 安装(推荐用于生产环境)
```bash
npm install dplayer
```
然后在组件中导入:
```javascript
import DPlayer from 'dplayer'
import 'dplayer/dist/DPlayer.min.css'
```
## 基础使用
### 创建播放器
```javascript
const player = new DPlayer({
container: document.getElementById('dplayer'),
video: {
url: 'video.mp4',
type: 'auto'
},
autoplay: false,
theme: '#007bff',
lang: 'zh-cn'
})
```
### 事件监听
```javascript
player.on('play', () => {
console.log('视频开始播放')
})
player.on('pause', () => {
console.log('视频暂停')
})
player.on('ended', () => {
console.log('视频播放结束')
})
player.on('error', () => {
console.log('播放出错')
})
```
## 配置选项
### 基础配置
```javascript
const options = {
container: document.getElementById('dplayer'), // 容器元素
video: {
url: 'video.mp4', // 视频地址
type: 'auto', // 视频类型auto, normal, hls, flv
defaultQuality: 0, // 默认画质
pic: 'poster.jpg', // 封面图
thumbnails: 'thumbnails.jpg' // 缩略图
},
autoplay: false, // 自动播放
theme: '#007bff', // 主题色
lang: 'zh-cn', // 语言zh-cn, en
hotkey: true, // 启用快捷键
preload: 'auto', // 预加载auto, metadata, none
volume: 0.8, // 默认音量
playbackSpeed: [0.5, 0.75, 1, 1.25, 1.5, 2], // 倍速选项
contextmenu: [ // 右键菜单
{
text: '关于 DPlayer',
link: 'https://github.com/DIYGod/DPlayer'
}
]
}
```
### 高级配置
```javascript
const advancedOptions = {
// 弹幕配置
danmaku: {
id: 'dplayer-danmaku',
api: 'https://api.prprpr.me/dplayer/',
token: 'token',
maximum: 1000,
addition: ['https://api.prprpr.me/dplayer/bilibili?aid=4157142'],
user: 'DIYGod',
bottom: '15%',
unlimited: true
},
// 字幕配置
subtitle: {
url: 'subtitle.vtt',
type: 'webvtt',
fontSize: '20px',
bottom: '10%',
color: '#fff'
},
// 画质切换
video: {
url: [
{
name: '1080P',
url: 'video-1080p.mp4'
},
{
name: '720P',
url: 'video-720p.mp4'
}
],
defaultQuality: 0
}
}
```
## 在 Vue 项目中使用
### 创建 DPlayer 组件
```vue
<template>
<div class="video-player-wrapper">
<div ref="dplayerContainer" class="dplayer-container"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const dplayerContainer = ref()
let player = null
onMounted(() => {
// 确保 DPlayer 已加载
if (window.DPlayer) {
initPlayer()
} else {
loadDPlayer().then(() => {
initPlayer()
})
}
})
const loadDPlayer = () => {
return new Promise((resolve) => {
const cssLink = document.createElement('link')
cssLink.rel = 'stylesheet'
cssLink.href = 'https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.css'
document.head.appendChild(cssLink)
const script = document.createElement('script')
script.src = 'https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.js'
script.onload = resolve
document.head.appendChild(script)
})
}
const initPlayer = () => {
player = new window.DPlayer({
container: dplayerContainer.value,
video: {
url: '/video/first.mp4',
type: 'auto'
},
autoplay: false,
theme: '#007bff',
lang: 'zh-cn',
hotkey: true
})
}
onUnmounted(() => {
if (player) {
player.destroy()
}
})
</script>
<style scoped>
.video-player-wrapper {
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.dplayer-container {
width: 100%;
aspect-ratio: 16/9;
}
</style>
```
## 样式定制
### 自定义主题色
```css
/* 修改播放器主题色 */
.dplayer {
--dplayer-theme: #007bff;
}
/* 自定义进度条颜色 */
.dplayer .dplayer-bar-wrap .dplayer-bar .dplayer-played {
background: #007bff;
}
/* 自定义控制按钮颜色 */
.dplayer .dplayer-icons .dplayer-icon {
color: #fff;
}
.dplayer .dplayer-icons .dplayer-icon:hover {
color: #007bff;
}
```
### 响应式设计
```css
/* 移动端适配 */
@media (max-width: 768px) {
.dplayer {
font-size: 14px;
}
.dplayer .dplayer-icons .dplayer-icon {
font-size: 16px;
}
}
```
## 快捷键支持
DPlayer 默认支持以下快捷键:
- `空格键` - 播放/暂停
- `←` - 后退 10 秒
- `→` - 前进 10 秒
- `↑` - 音量 +10%
- `↓` - 音量 -10%
- `F` - 全屏切换
- `M` - 静音切换
## 与 CKPlayer 对比
| 特性 | CKPlayer | DPlayer |
|------|----------|---------|
| 界面美观度 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 功能丰富度 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 移动端支持 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 中文支持 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 社区活跃度 | ⭐⭐ | ⭐⭐⭐⭐ |
| 文档质量 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 学习成本 | ⭐⭐⭐⭐ | ⭐⭐⭐ |
## 总结
**DPlayer 是一个优秀的视频播放器选择**,特别适合:
- 🎯 需要美观界面的项目
- 🌏 中文用户群体
- 📱 重视移动端体验
- 🎨 需要自定义主题的项目
- ⚡ 追求轻量级解决方案
相比当前的 CKPlayerDPlayer 提供了更好的用户体验和更丰富的功能,是升级视频播放器的理想选择。

523
docs/ExamInfo-API-Usage.md Normal file
View File

@ -0,0 +1,523 @@
# 考试信息API使用文档
## 接口概述
`/aiol/aiolExam/getExamInfo` 接口用于获取教师名下的考试信息列表。
## 接口定义
### 请求方式
- **方法**: GET
- **路径**: `/aiol/aiolExam/getExamInfo`
- **参数**: `userId` (查询参数)
### 请求参数
| 参数名 | 类型 | 必选 | 说明 |
|--------|------|------|------|
| userId | string | 是 | 教师用户ID |
### 响应格式
```typescript
{
"success": boolean,
"message": string,
"code": number,
"result": ExamInfo[],
"timestamp": number
}
```
### ExamInfo 数据结构
```typescript
interface ExamInfo {
id: string // 考试ID
name: string // 考试名称
paperId: string // 试卷ID
startTime: string // 开始时间
endTime: string // 结束时间
totalTime: number // 考试时长(分钟)
type: number // 考试类型0=练习1=考试
status: number // 状态0=未发布1=发布中2=已结束
createBy: string // 创建人
createTime: string // 创建时间
updateBy: string // 更新人
updateTime: string // 更新时间
}
```
## 使用示例
### 1. 在API模块中调用
```typescript
import { ExamApi } from '@/api/modules/exam'
// 获取教师考试信息
const response = await ExamApi.getExamInfo('teacher_user_id')
console.log('考试信息:', response.data)
```
### 2. 在Vue组件中使用
```typescript
import { ExamApi } from '@/api/modules/exam'
import { useUserStore } from '@/stores/user'
export default {
setup() {
const userStore = useUserStore()
const loadExamInfo = async () => {
if (!userStore.user?.id) {
console.error('请先登录')
return
}
try {
const response = await ExamApi.getExamInfo(userStore.user.id.toString())
return response.data || []
} catch (error) {
console.error('加载考试信息失败:', error)
return []
}
}
return {
loadExamInfo
}
}
}
```
### 3. 在试卷管理页面中使用
```typescript
// 在 ExamLibrary.vue 中
import { ExamApi } from '@/api/modules/exam'
import { useUserStore } from '@/stores/user'
import type { ExamInfo } from '@/api/types'
const userStore = useUserStore()
const loadExamInfo = async () => {
loading.value = true
try {
const currentUser = userStore.user
if (!currentUser?.id) {
message.error('请先登录')
return
}
const response = await ExamApi.getExamInfo(currentUser.id.toString())
if (response.data && Array.isArray(response.data)) {
// 数据映射和显示逻辑
const mappedList = response.data.map((item: ExamInfo) => {
// 映射逻辑...
return {
id: item.id,
name: item.name,
// ... 其他字段映射
}
})
examData.value = mappedList
}
} catch (error) {
console.error('加载考试信息失败:', error)
message.error('加载考试信息失败')
} finally {
loading.value = false
}
}
```
## 数据映射说明
### 状态映射
```typescript
const statusMap: { [key: number]: string } = {
0: '未发布',
1: '发布中',
2: '已结束'
}
```
### 类型映射
```typescript
const categoryMap: { [key: number]: string } = {
0: '练习',
1: '考试'
}
```
### 难度映射
```typescript
const difficultyMap: { [key: number]: string } = {
0: '易',
1: '中',
2: '难'
}
```
## 错误处理
接口可能返回以下错误:
1. **401 Unauthorized**: 用户未登录或token过期
2. **403 Forbidden**: 没有权限访问
3. **500 Internal Server Error**: 服务器内部错误
建议在调用时添加适当的错误处理:
```typescript
try {
const response = await ExamApi.getExamInfo(userId)
// 处理成功响应
} catch (error) {
if (error.response?.status === 401) {
// 处理认证错误
console.error('登录已过期,请重新登录')
} else {
// 处理其他错误
console.error('获取考试信息失败:', error.message)
}
}
```
## 注意事项
1. 调用此接口前需要确保用户已登录
2. 只有教师用户才能调用此接口
3. 返回的考试信息按创建时间倒序排列
4. 建议在组件挂载时调用此接口加载数据
5. 可以根据需要添加分页、搜索等参数(需要后端支持)
## 相关文件
- API实现: `src/api/modules/exam.ts`
- 类型定义: `src/api/types.ts`
- 使用示例: `src/api/examples/getExamInfo-example.ts`
- 页面实现: `src/views/teacher/ExamPages/ExamLibrary.vue`
---
# 创建试卷API使用文档
## 接口概述
`POST /aiol/aiolPaper/add` 接口用于创建新的试卷。
## 接口定义
### 请求方式
- **方法**: POST
- **路径**: `/aiol/aiolPaper/add`
- **Content-Type**: `application/json`
### 请求参数
| 参数名 | 类型 | 必选 | 说明 |
|--------|------|------|------|
| title | string | 是 | 试卷标题 |
| generateMode | number | 否 | 组卷模式0=固定试卷组1=随机抽题组卷 |
| rules | string | 否 | 组卷规则(随机抽题时使用) |
| repoId | string | 否 | 题库ID随机抽题时使用 |
| totalScore | number | 是 | 试卷总分 |
| passScore | number | 否 | 及格分数默认总分的60% |
| requireReview | number | 否 | 是否需要批阅0=不需要1=需要 |
### 响应格式
```typescript
{
"success": boolean,
"message": string,
"code": number,
"result": string, // 试卷ID
"timestamp": number
}
```
## 使用示例
### 1. 在API模块中调用
```typescript
import { ExamApi } from '@/api/modules/exam'
// 创建固定试卷组
const response = await ExamApi.createExamPaper({
title: '数学期末考试试卷',
generateMode: 0,
totalScore: 100,
passScore: 60,
requireReview: 0
})
console.log('试卷ID:', response.data)
```
### 2. 在Vue组件中使用
```typescript
// 在 AddExam.vue 中
const saveExam = async () => {
try {
const apiData = {
title: examForm.title,
generateMode: examForm.type === 1 ? 0 : 1,
rules: '',
repoId: '',
totalScore: examForm.totalScore,
passScore: examForm.passScore || Math.floor(examForm.totalScore * 0.6),
requireReview: examForm.useAIGrading ? 1 : 0
}
const response = await ExamApi.createExamPaper(apiData)
console.log('创建试卷成功:', response.data)
} catch (error) {
console.error('创建试卷失败:', error)
}
}
```
### 3. 不同组卷模式示例
```typescript
// 固定试卷组
const fixedPaper = {
title: '固定试卷组示例',
generateMode: 0,
rules: '',
repoId: '',
totalScore: 100,
passScore: 60,
requireReview: 0
}
// 随机抽题组卷
const randomPaper = {
title: '随机抽题组卷示例',
generateMode: 1,
rules: '{"difficulty": [1, 2, 3], "types": [0, 1, 2], "count": 20}',
repoId: 'repo_123',
totalScore: 100,
passScore: 60,
requireReview: 1
}
```
## 相关文件
- API实现: `src/api/modules/exam.ts`
- 页面实现: `src/views/teacher/ExamPages/AddExam.vue`
- 使用示例: `src/api/examples/createPaper-example.ts`
---
# 删除试卷API使用文档
## 接口概述
删除试卷相关的API接口包括单个删除和批量删除功能。
## 接口定义
### 1. 删除单个试卷
- **方法**: DELETE
- **路径**: `/aiol/aiolPaper/delete?id={paperId}`
- **参数**: `id` (查询参数) - 试卷ID
### 2. 批量删除试卷
- **实现方式**: 循环调用单个删除接口(因为后端可能不支持批量删除接口)
- **方法**: 内部调用多个 `DELETE /aiol/aiolPaper/delete?id={paperId}`
- **参数**: `ids: string[]` - 试卷ID数组
### 响应格式
**单个删除响应**:
```typescript
{
"success": boolean,
"message": string,
"code": number,
"result": string,
"timestamp": number
}
```
**批量删除响应**:
```typescript
{
"success": boolean,
"message": string,
"code": number,
"result": {
"success": number, // 成功删除的数量
"failed": number, // 失败删除的数量
"total": number, // 总数量
"errors": string[] // 错误信息数组
},
"timestamp": number
}
```
## 使用示例
### 1. 删除单个试卷
```typescript
import { ExamApi } from '@/api/modules/exam'
// 删除单个试卷
const response = await ExamApi.deleteExamPaper('1962379646322384897')
console.log('删除结果:', response.data)
```
### 2. 批量删除试卷
```typescript
// 批量删除试卷
const paperIds = ['1962379646322384897', '1966450638717292545']
const response = await ExamApi.batchDeleteExamPapers(paperIds)
console.log('批量删除结果:', response.data)
```
### 3. 在Vue组件中使用使用 Naive UI 对话框组件)
```typescript
// 在 ExamLibrary.vue 中
import { useDialog, useMessage } from 'naive-ui'
const dialog = useDialog()
const message = useMessage()
const handleDeletePaper = async (row: any) => {
try {
// 使用 Naive UI 对话框组件
dialog.warning({
title: '确认删除',
content: `确定要删除试卷"${row.name}"吗?此操作不可撤销。`,
positiveText: '确定删除',
negativeText: '取消',
onPositiveClick: async () => {
try {
// 调用删除API
const response = await ExamApi.deleteExamPaper(row.id)
// 显示成功消息
message.success('试卷删除成功!')
// 重新加载试卷列表
await loadExamPaperList()
} catch (error) {
console.error('删除试卷失败:', error)
message.error('删除试卷失败,请重试')
}
}
})
} catch (error) {
console.error('删除试卷失败:', error)
message.error('删除试卷失败,请重试')
}
}
// 批量删除示例
const handleBatchDelete = async () => {
if (checkedRowKeys.value.length === 0) {
message.warning('请先选择要删除的试卷')
return
}
try {
// 使用 Naive UI 对话框组件
dialog.error({
title: '确认批量删除',
content: `确定要删除选中的 ${checkedRowKeys.value.length} 个试卷吗?此操作不可撤销。`,
positiveText: '确定删除',
negativeText: '取消',
onPositiveClick: async () => {
try {
// 调用批量删除API
const response = await ExamApi.batchDeleteExamPapers(checkedRowKeys.value as string[])
// 显示成功消息
message.success(`成功删除 ${checkedRowKeys.value.length} 个试卷!`)
// 清空选中状态
checkedRowKeys.value = []
// 重新加载试卷列表
await loadExamPaperList()
} catch (error) {
console.error('批量删除试卷失败:', error)
message.error('批量删除试卷失败,请重试')
}
}
})
} catch (error) {
console.error('批量删除试卷失败:', error)
message.error('批量删除试卷失败,请重试')
}
}
```
### 4. 错误处理
```typescript
const deletePaperWithErrorHandling = async (paperId: string) => {
try {
const response = await ExamApi.deleteExamPaper(paperId)
if (response.data === 'success') {
return { success: true, message: '删除成功' }
} else {
return { success: false, message: '删除失败,请重试' }
}
} catch (error: any) {
if (error.response?.status === 404) {
return { success: false, message: '试卷不存在' }
} else if (error.response?.status === 403) {
return { success: false, message: '没有权限删除此试卷' }
}
return { success: false, message: '删除失败,请检查网络连接' }
}
}
```
## 功能特性
### 单个删除
- 支持删除单个试卷
- 使用 Naive UI 警告对话框组件
- 删除成功后自动刷新列表
- 完整的错误处理
### 批量删除
- 支持同时删除多个试卷
- 循环调用单个删除接口(避免后端接口不存在的问题)
- 逐个删除,避免对服务器造成过大压力
- 详细的删除结果反馈(成功/失败数量)
- 使用 Naive UI 错误对话框组件(更醒目的警告)
- 删除后清空选中状态
### 用户体验
- **美观的确认对话框**: 使用 Naive UI 组件,样式统一美观
- **不同类型的对话框**: 单个删除使用 warning批量删除使用 error
- **成功/失败消息提示**: 使用 Naive UI 的 message 组件
- **按钮状态管理**: 批量删除按钮在未选中时禁用
- **实时更新选中数量显示**: 动态显示选中的试卷数量
- **异步操作处理**: 在对话框确认后才执行删除操作
## 相关文件
- API实现: `src/api/modules/exam.ts`
- 页面实现: `src/views/teacher/ExamPages/ExamLibrary.vue`
- 使用示例: `src/api/examples/deletePaper-example.ts`

148
docs/ai-model-api-debug.md Normal file
View File

@ -0,0 +1,148 @@
# AI模型字典API调试指南
## 问题描述
在调用AI模型字典API时遇到错误
```
Sign签名校验失败时间戳为空
```
## 已实施的修复措施
### 1. **添加时间戳参数到URL**
```typescript
// 修改前
return request.get('/sys/dict/getDictItems/airag_model%20where%20model_type%20=%20\'LLM\',name,id')
// 修改后
const timestamp = Date.now()
return request.get(`/sys/dict/getDictItems/airag_model%20where%20model_type%20=%20'LLM',name,id?_t=${timestamp}`)
```
### 2. **增强请求头时间戳**
```typescript
// 添加多种时间戳格式
const timestamp = Date.now().toString()
config.headers['X-Request-Time'] = timestamp
config.headers['timestamp'] = timestamp
config.headers['X-Timestamp'] = timestamp
```
### 3. **增强错误调试**
- 在AiAppSetting.vue中添加详细的调试日志
- 在AiModelTest.vue中添加直接请求测试功能
- 显示完整的错误信息和响应数据
## 测试步骤
### 1. 访问测试页面
```
http://localhost:5173/ai-model-test
```
### 2. 检查登录状态
- 确保用户已登录并有有效的token
- 在测试页面中查看"用户Token"状态
### 3. 测试API调用
1. 点击"加载AI模型列表"按钮使用封装的API
2. 点击"直接请求测试"按钮使用原生axios
3. 查看控制台日志和响应数据
### 4. 检查AI应用设置
1. 访问 `/ai/app` 页面
2. 点击任意AI应用卡片
3. 切换到"模型配置"选项卡
4. 查看控制台日志
## 调试信息
### 请求信息
- **URL**: `/sys/dict/getDictItems/airag_model%20where%20model_type%20=%20'LLM',name,id?_t={timestamp}`
- **方法**: GET
- **Base URL**: `/jeecgboot` (或环境变量配置)
### 请求头
```javascript
{
'Content-Type': 'application/json',
'X-Access-Token': '{user_token}',
'X-Request-Time': '{timestamp}',
'timestamp': '{timestamp}',
'X-Timestamp': '{timestamp}'
}
```
### 预期响应格式
```json
{
"success": true,
"message": "",
"code": 0,
"result": [
{
"value": "1890232564262739969",
"text": "OpenAI",
"color": null,
"jsonObject": null,
"label": "OpenAI",
"title": "OpenAI"
}
],
"timestamp": 1759136645858
}
```
## 可能的解决方案
### 1. **检查后端签名算法**
如果问题仍然存在,可能需要:
- 检查后端期望的签名算法
- 添加必要的签名参数
- 确认时间戳格式要求
### 2. **检查接口权限**
- 确认该接口是否需要特定的用户权限
- 检查token是否有效
- 验证用户角色权限
### 3. **检查接口路径**
- 确认接口路径是否正确
- 检查URL编码是否正确
- 验证查询参数格式
## 备用方案
如果API调用仍然失败系统会自动使用备用数据
```typescript
modelOptions.value = [
{ label: 'GPT-3.5 Turbo', value: 'gpt-3.5-turbo' },
{ label: 'GPT-4', value: 'gpt-4' },
{ label: 'Claude-3', value: 'claude-3' }
]
```
## 下一步调试
1. **查看网络请求**
- 打开浏览器开发者工具
- 查看Network选项卡
- 检查实际发送的请求和响应
2. **检查后端日志**
- 查看后端服务器日志
- 确认请求是否到达后端
- 检查签名验证逻辑
3. **联系后端开发**
- 确认接口的正确调用方式
- 获取签名算法详细信息
- 确认必需的请求参数
## 文件修改记录
- `src/api/modules/system.ts`: 添加字典API和时间戳参数
- `src/api/request.ts`: 增强时间戳请求头
- `src/views/Ai/component/AiAppSetting.vue`: 添加详细调试日志
- `src/views/AiModelTest.vue`: 创建专门的测试页面
- `src/router/index.ts`: 添加测试页面路由

234
docs/ai-model-dict-api.md Normal file
View File

@ -0,0 +1,234 @@
# AI模型字典API集成
## 概述
本文档说明如何在AI应用设置弹窗中集成真实的AI模型字典API替换原有的模拟数据。
## API接口信息
### 获取AI模型字典
- **接口地址**: `/sys/dict/getDictItems/airag_model%20where%20model_type%20=%20'LLM',name,id`
- **请求方法**: GET
- **接口说明**: 获取LLM类型的AI模型字典数据
### 响应格式
```json
{
"success": true,
"message": "",
"code": 0,
"result": [
{
"value": "1890232564262739969",
"text": "OpenAI",
"color": null,
"jsonObject": null,
"label": "OpenAI",
"title": "OpenAI"
},
{
"value": "1897481367743143938",
"text": "deepseek",
"color": null,
"jsonObject": null,
"label": "deepseek",
"title": "deepseek"
},
{
"value": "1897883052995006466",
"text": "智谱",
"color": null,
"jsonObject": null,
"label": "智谱",
"title": "智谱"
},
{
"value": "1970031008335876097",
"text": "测试",
"color": null,
"jsonObject": null,
"label": "测试",
"title": "测试"
}
],
"timestamp": 1759136645858
}
```
## 实现的功能
### 1. **API模块扩展** (`src/api/modules/system.ts`)
添加了字典相关的API接口
```typescript
// 字典项接口
export interface DictItem {
value: string
text: string
color: string | null
jsonObject: any | null
label: string
title: string
}
export const SystemApi = {
// 获取字典项
getDictItems(dictCode: string, params?: string): Promise<ApiResponse<DictItem[]>>
// 获取AI模型字典项LLM类型
getAiModelDict(): Promise<ApiResponse<DictItem[]>>
}
```
### 2. **AI应用设置组件更新** (`src/views/Ai/component/AiAppSetting.vue`)
修改了 `loadModelOptions` 函数:
```typescript
// 加载模型选项
const loadModelOptions = async () => {
loadingModels.value = true
try {
const response = await SystemApi.getAiModelDict()
if (response.data.code === 200 || response.data.code === 0) {
modelOptions.value = response.data.data.map(item => ({
label: item.text,
value: item.value
}))
console.log('✅ AI模型列表加载成功:', modelOptions.value)
} else {
throw new Error(response.data.message || '获取模型列表失败')
}
} catch (error: any) {
console.error('❌ 加载模型列表失败:', error)
message.error(error.message || '加载模型列表失败')
// 失败时使用备用数据
modelOptions.value = [
{ label: 'GPT-3.5 Turbo', value: 'gpt-3.5-turbo' },
{ label: 'GPT-4', value: 'gpt-4' },
{ label: 'Claude-3', value: 'claude-3' }
]
} finally {
loadingModels.value = false
}
}
```
### 3. **测试页面** (`src/views/AiModelTest.vue`)
创建了专门的测试页面来验证API调用
- 实时加载AI模型数据
- 显示API响应状态
- 测试选择器功能
- 查看原始数据
## 使用流程
### 1. 点击AI应用卡片
在AI应用列表页面点击任意应用卡片
```vue
<n-card
class="app-card"
hoverable
@click="handleEditApp(item)"
>
```
### 2. 打开设置弹窗
系统会调用 `handleEditApp` 函数,打开应用设置弹窗:
```typescript
const handleEditApp = (app: AiApp) => {
isEditMode.value = true
currentApp.value = { ...app }
showSettingModal.value = true
}
```
### 3. 自动加载模型数据
弹窗打开时,会自动调用 `loadModelOptions()` 函数加载AI模型数据
```typescript
onMounted(() => {
loadModelOptions() // 自动加载模型选项
loadFlowOptions()
loadSelectedKnowledges()
})
```
### 4. 显示模型选择器
在"模型配置"选项卡中用户可以看到从后端加载的真实AI模型列表
- OpenAI
- deepseek
- 智谱
- 测试
## 测试方法
### 1. 访问测试页面
```
http://localhost:5173/ai-model-test
```
### 2. 测试功能
- 点击"加载AI模型列表"按钮
- 查看加载状态和结果
- 测试选择器功能
- 查看原始API响应数据
### 3. 验证AI应用设置
- 访问 `/ai/app` 页面
- 点击任意AI应用卡片
- 在弹窗中切换到"模型配置"选项卡
- 验证AI模型下拉选择器是否显示真实数据
## 错误处理
系统包含完整的错误处理机制:
1. **网络请求失败**: 显示错误消息并使用备用数据
2. **API响应错误**: 解析错误信息并提示用户
3. **数据格式错误**: 容错处理,确保界面正常显示
4. **加载状态**: 显示加载指示器,提升用户体验
## 数据映射
API返回的字典项会被映射为选择器选项
```typescript
// API数据格式
{
"value": "1890232564262739969",
"text": "OpenAI",
"label": "OpenAI",
"title": "OpenAI"
}
// 映射为选择器选项
{
label: "OpenAI", // 显示文本
value: "1890232564262739969" // 选择值
}
```
## 扩展说明
### 添加其他字典类型
可以在 `SystemApi` 中添加其他字典类型的获取方法:
```typescript
// 获取其他类型的字典
getOtherDict(): Promise<ApiResponse<DictItem[]>> {
return request.get('/sys/dict/getDictItems/other_dict_code')
}
```
### 自定义字典查询
使用通用的 `getDictItems` 方法:
```typescript
// 自定义查询条件
const response = await SystemApi.getDictItems('dict_code', 'custom_params')
```
这样就完成了AI模型字典API的集成用户在AI应用设置弹窗中可以看到真实的AI模型数据了

197
docs/dynamic-menu-routes.md Normal file
View File

@ -0,0 +1,197 @@
# 动态菜单路由系统
## 概述
本系统实现了基于后端接口的动态菜单路由加载功能,支持从后端获取菜单配置并自动生成前端路由。
## 接口说明
### 获取首页菜单
- **接口**: `/aiol/aiolMenu/getIndexMenus`
- **方法**: GET
- **返回格式**:
```json
{
"success": true,
"message": "",
"code": 200,
"result": [
{
"id": "1",
"name": "首页",
"path": "/",
"type": "index",
"icon": null,
"parentId": null,
"sortOrder": 99,
"izVisible": 1,
"permissionKey": null
}
],
"timestamp": 1759134778382
}
```
### 获取学生菜单
- **接口**: `/aiol/aiolMenu/getStudentMenus`
- **方法**: GET
- **返回格式**: 同上type为"student"
## 核心文件
### 1. API模块 (`src/api/modules/menu.ts`)
```typescript
export interface MenuItem {
id: string
name: string
path: string
type: string
icon: string | null
parentId: string | null
sortOrder: number
izVisible: number
permissionKey: string | null
}
export class MenuApi {
static async getIndexMenus(): Promise<ApiResponse<MenuItem[]>>
static async getStudentMenus(): Promise<ApiResponse<MenuItem[]>>
}
```
### 2. 路由工具 (`src/utils/routeUtils.ts`)
```typescript
// 根据菜单数据生成路由配置
export function generateRoutesFromMenus(menus: MenuItem[]): RouteRecordRaw[]
// 生成导航菜单数据
export function generateNavMenus(menus: MenuItem[])
// 检查路由是否存在于菜单中
export function isRouteInMenus(path: string, menus: MenuItem[]): boolean
```
### 3. 状态管理 (`src/stores/menu.ts`)
```typescript
export const useMenuStore = defineStore('menu', () => {
// 状态
const indexMenus = ref<MenuItem[]>([])
const studentMenus = ref<MenuItem[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
// 计算属性
const navMenus = computed(() => generateNavMenus(indexMenus.value))
const visibleIndexMenus = computed(() => ...)
// 方法
const fetchIndexMenus = async () => { ... }
const fetchStudentMenus = async () => { ... }
})
```
### 4. 路由配置 (`src/router/index.ts`)
在路由守卫中自动加载动态菜单:
```typescript
router.beforeEach(async (to, from, next) => {
// 加载动态菜单路由(仅在首次访问时)
if (!isMenuLoaded) {
await loadMenuRoutes()
}
// ...
})
```
## 使用方法
### 1. 在组件中使用菜单状态
```vue
<script setup lang="ts">
import { useMenuStore } from '@/stores/menu'
const menuStore = useMenuStore()
// 获取菜单数据
await menuStore.fetchIndexMenus()
// 使用菜单数据
console.log(menuStore.navMenus)
</script>
```
### 2. 使用动态导航组件
```vue
<template>
<DynamicNavigation />
</template>
<script setup lang="ts">
import DynamicNavigation from '@/components/layout/DynamicNavigation.vue'
</script>
```
### 3. 检查路由权限
```typescript
import { useMenuStore } from '@/stores/menu'
const menuStore = useMenuStore()
// 检查路由是否可见
const isVisible = menuStore.isRouteVisible('/courses', 'index')
```
## 路径映射
当前支持的路径映射:
| 菜单名称 | 路径 | 组件 |
|---------|------|------|
| 首页 | / | Home |
| 热门好课 | /courses | Courses |
| 专题训练 | /special-training | SpecialTraining |
| 师资力量 | /faculty | Faculty |
| 精选资源 | /resources | Resources |
| 活动 | /activities | Activities |
| AI体验 | /ai/app | AiAppList |
## 测试页面
访问 `/menu-test` 可以查看动态菜单系统的测试页面,包含:
- 菜单状态监控
- 菜单数据展示
- 路由跳转测试
- 动态导航组件演示
## 响应式设计
动态导航组件支持响应式设计:
- 桌面端:垂直菜单布局
- 移动端:水平滚动菜单布局
## 错误处理
系统包含完整的错误处理机制:
- 网络请求失败重试
- 加载状态显示
- 错误信息提示
- 手动重试功能
## 扩展说明
### 添加新的路径映射
`src/utils/routeUtils.ts` 中的 `componentMap` 添加新的路径映射:
```typescript
const componentMap: Record<string, () => Promise<any>> = {
'/new-path': () => import('@/views/NewComponent.vue'),
// ...
}
```
### 自定义菜单图标
`DynamicNavigation.vue` 中的 `iconMap` 添加新的图标映射:
```typescript
const iconMap: Record<string, any> = {
'new-icon': NewIconComponent,
// ...
}
```

View File

@ -2,13 +2,15 @@
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico"> <!-- <link rel="icon" href="/logo/logo1.png"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线学习平台</title> <title>在线学习平台</title>
<meta name="description" content="专业的在线学习平台,提供优质的编程和技术课程"> <meta name="description" content="专业的在线学习平台,提供优质的编程和技术课程">
<meta name="keywords" content="在线学习,编程课程,技术培训,Vue.js,React,Node.js"> <meta name="keywords" content="在线学习,编程课程,技术培训,Vue.js,React,Node.js">
<!-- CKPlayer CSS --> <!-- CKPlayer CSS -->
<link rel="stylesheet" href="/ckplayer/css/ckplayer.css"> <link rel="stylesheet" href="/ckplayer/css/ckplayer.css">
<!-- HLS.js for m3u8 playback in CKPlayer -->
<script src="/ckplayer/hls.js/hls.min.js"></script>
<!-- CKPlayer JS --> <!-- CKPlayer JS -->
<script src="/ckplayer/js/ckplayer.js"></script> <script src="/ckplayer/js/ckplayer.js"></script>
</head> </head>

2255
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,18 +13,34 @@
"test:ui": "vitest --ui" "test:ui": "vitest --ui"
}, },
"dependencies": { "dependencies": {
"@types/sortablejs": "^1.15.8",
"@vicons/antd": "^0.13.0",
"@vicons/ionicons5": "^0.13.0", "@vicons/ionicons5": "^0.13.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"@wangeditor/plugin-upload-attachment": "^1.1.0",
"axios": "^1.11.0", "axios": "^1.11.0",
"ckplayer": "^3.1.2", "ckplayer": "^3.1.2",
"dplayer": "^1.27.1",
"echarts": "5.6.0",
"marked": "^16.4.0",
"naive-ui": "^2.42.0", "naive-ui": "^2.42.0",
"naive-ui-editor": "^1.0.6",
"pinia": "^3.0.3", "pinia": "^3.0.3",
"quill": "^2.0.3",
"vue": "^3.5.17", "vue": "^3.5.17",
"vue-echarts": "7.0.3",
"vue-i18n": "^9.14.5", "vue-i18n": "^9.14.5",
"vue-router": "^4.5.1" "vue-quill-editor": "^3.0.6",
"vue-router": "^4.5.1",
"vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/dplayer": "^1.25.5",
"@types/node": "^24.0.15", "@types/node": "^24.0.15",
"@vitejs/plugin-vue": "^6.0.0", "@vitejs/plugin-vue": "^6.0.0",
"less": "^4.4.2",
"sass-embedded": "^1.93.2",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"vite": "^7.0.0", "vite": "^7.0.0",
"vite-plugin-vue-devtools": "^7.7.7", "vite-plugin-vue-devtools": "^7.7.7",

916
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/banners/banner8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1011 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 812 B

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
public/images/courses/@.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Some files were not shown because too many files have changed in this diff Show More