src/router/index.js
//课程分类
{
path: 'subject',
component: Layout,
redirect: '/edu/subject/list',
name: 'Subject',
meta: {
title: '课程分类管理', icon: 'nested' },
children: [
{
path: '/list',
name: '课程分类列表',
component: () => import('@/views/edu/subject/list.vue'),
meta: {
title: '课程分类列表', icon: 'table' }
},
{
path: 'import',
name: '课程分类导入',
component: () => import('@/views/edu/subject/import.vue'),
meta: {
title: '导入课程分类', icon: 'nested' }
}
]
}
data() {
return {
BASE_API: process.env.BASE_API, // 接口API地址
importBtnDisabled: false, // 按钮是否禁用,
loading: false,
};
}
<div class="app-container">
<el-form label-width="120px">
<el-form-item label="信息描述">
<el-tag type="info">excel模版说明el-tag>
<el-tag>
<i class="el-icon-download" />
<a :href="'/static/1.xlsx'">点击下载模版a>
el-tag>
el-form-item>
<el-form-item label="选择Excel">
<el-upload
ref="upload"
:auto-upload="false"
:on-success="fileUploadSuccess"
:on-error="fileUploadError"
:disabled="importBtnDisabled"
:limit="1"
:action="BASE_API + '/eduservice/edu-subject/addSubject'"
name="file"
accept="application/vnd.ms-excel"
>
<el-button slot="trigger" size="small" type="primary"
>选取文件el-button
>
<el-button
:loading="loading"
style="margin-left: 10px"
size="small"
type="success"
@click="submitUpload"
>上传到服务器el-button
>
el-upload>
el-form-item>
el-form>
div>
methods: {
//点击按钮上传文件到接口
submitUpload() {
this.importBtnDisabled = true;
this.loading = true;
this.$refs.upload.submit();
},
//上传成功后
fileUploadSuccess(resp) {
if (resp.success === true) {
this.loading = false;
this.$message({
type: "success",
message: resp.message,
});
}
},
//上传失败后
fileUploadError(resp) {
this.loading = false;
this.$message({
type: "error",
message: "导入失败",
});
},
}
用于封装树形数据结构
//一级分类
@Data
public class OneSubject {
private String id;
private String title;
//一个一级分类有多个二级分类
private List<TwoSubject> children = new ArrayList<>();
}
//二级分类
@Data
public class TwoSubject {
private String id;
private String title;
}
//课程分类列表(树形)
@ApiOperation(value = "嵌套数据列表")
@GetMapping("/getAllSubject")
public R getAllSubject(){
//ist集合泛型是一级分类,一级分类中本身含有二级分类
List<OneSubject> list = eduSubjectService.getAllOneTwoSubject();
return R.ok().data("list",list);
}
接口
List<OneSubject> getAllOneTwoSubject();
Impl
@Override
public List<OneSubject> getAllOneTwoSubject() {
//查询所有一级分类 parent_id = 0
QueryWrapper<EduSubject> wrapperOne = new QueryWrapper();
wrapperOne.eq("parent_id","0");
List<EduSubject> oneSubjectsList = baseMapper.selectList(wrapperOne);
//查询所有二级分类 parent_id != 0
QueryWrapper<EduSubject> wrapperTwo = new QueryWrapper();
wrapperTwo.ne("parent_id","0");
List<EduSubject> twoSubjectsList = baseMapper.selectList(wrapperTwo);
//创建list集合,用于封装最终数据
List<OneSubject> finalSubjectList = new ArrayList<>();
//封装一级分类
//查询出来所有的一级分类list集合遍历,得到每个一级分类对象,获取每个一级分类对象值
//封装到要求的最终list集合中
for (int i = 0; i < oneSubjectsList.size(); i++) {
//遍历oneSubjectList集合
//得到oneSubjectsList中每个eduSubject对象
EduSubject oSubject = oneSubjectsList.get(i);
//把eduSubject里面值获取出来,放到oneSubject对象中去
OneSubject oneSubject = new OneSubject();
// oneSubject.setId(eduSubject.getId());
// oneSubject.setTitle(eduSubject.getTitle());
//把eduSubject值复制到oneSubject中去【要求两个类的复制注入的属性名一致】
BeanUtils.copyProperties(oSubject,oneSubject);
//多个OneSubject放到finalSubjectList里面
finalSubjectList.add(oneSubject);
//在一级分类循环遍历查询所有的二级分类
//创建list集合封装每个一级分类的二级分类
ArrayList<TwoSubject> finalTwoSubjects = new ArrayList<>();
//遍历二级list集合
for (int j = 0; j < twoSubjectsList.size(); j++) {
//获取每个二级分类
EduSubject tSubject = twoSubjectsList.get(j);
//判断二级分类parentid和一级分类id是否一样
if (tSubject.getParentId().equals(oSubject.getId())){
//把tSubject值复制到TwoSubject,最终放在twoSubjectsList中
TwoSubject twoSubject = new TwoSubject();
BeanUtils.copyProperties(tSubject,twoSubject);
finalTwoSubjects.add(twoSubject);
}
}
//把一级下面所有二级分类放到oneSubject里面
oneSubject.setChildren(finalTwoSubjects);
}
//封装二级分类
return ;
}
api/teacher/subject.js
import request from '@/utils/request' //引入已经封装好的axios 和 拦截器
export default{
//课程分类
getSubjectList(){
return request({
url:"/eduservice/edu-subject/getAllSubject",
method: 'get'
})
}
}
<template>
<div class="app-container">
<el-input
v-model="filterText"
placeholder="Filter keyword"
style="margin-bottom: 30px"
/>
<el-tree
ref="tree2"
:data="data"
:props="defaultProps"
:filter-node-method="filterNode"
class="filter-tree"
default-expand-all
/>
div>
template>
<script>
import subject from '@/api/teacher/subject.js'
export default {
data() {
return {
filterText: "",
data: [], //返回所有分类的数据
defaultProps: {
children: "children",
label: "title",
},
};
},
watch: {
filterText(val) {
this.$refs.tree2.filter(val);
},
},
methods: {
getAllSubjectList(){
subject.getSubjectList()
.then(resp=>{
this.data = resp.data.list
})
},
filterNode(value, data) {
if (!value) return true;
return data.title.indexOf(value) !== -1;
},
},
created() {
this.getAllSubjectList()
},
};
script>
filterNode(value, data) {
if (!value) return true
return data.title.toLowerCase().indexOf(value.toLowerCase()) !== -1
}
下面的edu_teacher
、edu_subject
已经在上面的流程创建过了
存储课程简介信息
CREATE TABLE `edu_course_description` (
`id` char(19) NOT NULL COMMENT '课程ID',
`description` text COMMENT '课程简介',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程简介';
#
# Data for table "edu_course_description"
#
INSERT INTO `edu_course_description` VALUES ('1104870479077879809','11
','2019-03-11 06:23:44','2019-03-11 06:23:44'),('1192252213659774977','测试
','2019-11-07 09:27:33','2019-11-13 16:21:28'),('14','','2019-03-13 06:04:43','2019-03-13 06:05:33'),('15','','2019-03-13 06:03:33','2019-03-13 06:04:22'),('18','本套Java视频完全针对零基础学员,课堂实录,自发布以来,好评如潮!Java视频中注重与学生互动,讲授幽默诙谐、细致入微,覆盖Java基础所有核心知识点,同类Java视频中也是代码量大、案例多、实战性强的。同时,本Java视频教程注重技术原理剖析,深入JDK源码,辅以代码实战贯穿始终,用实践驱动理论,并辅以必要的代码练习。
\n------------------------------------
\n视频特点:
\n通过学习本Java视频教程,大家能够真正将Java基础知识学以致用、活学活用,构架Java编程思想,牢牢掌握\"源码级\"的Javase核心技术,并为后续JavaWeb等技术的学习奠定扎实基础。
1.通俗易懂,细致入微:每个知识点高屋建瓴,深入浅出,简洁明了的说明问题
2.具实战性:全程真正代码实战,涵盖上百个企业应用案例及练习
3.深入:源码分析,更有 Java 反射、动态代理的实际应用等
4.登录尚硅谷官网,技术讲师免费在线答疑
','2019-03-06 18:06:36','2019-10-30 19:58:36');
存储章节里面小节信息
CREATE TABLE `edu_video` (
`id` char(19) NOT NULL COMMENT '视频ID',
`course_id` char(19) NOT NULL COMMENT '课程ID',
`chapter_id` char(19) NOT NULL COMMENT '章节ID',
`title` varchar(50) NOT NULL COMMENT '节点名称',
`video_source_id` varchar(100) DEFAULT NULL COMMENT '云端视频资源',
`video_original_name` varchar(100) DEFAULT NULL COMMENT '原始文件名称',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序字段',
`play_count` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '播放次数',
`is_free` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否可以试听:0收费 1免费',
`duration` float NOT NULL DEFAULT '0' COMMENT '视频时长(秒)',
`status` varchar(20) NOT NULL DEFAULT 'Empty' COMMENT 'Empty未上传 Transcoding转码中 Normal正常',
`size` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '视频源文件大小(字节)',
`version` bigint(20) unsigned NOT NULL DEFAULT '1' COMMENT '乐观锁',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_course_id` (`course_id`),
KEY `idx_chapter_id` (`chapter_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='课程视频';
#
# Data for table "edu_video"
#
INSERT INTO `edu_video` VALUES ('1182499307429339137','18','32','第一节','','',0,0,0,0,'',0,1,'2019-10-11 11:32:59','2019-10-11 11:57:38'),('1185312444399071234','14','1','12','','',0,0,0,0,'Empty',0,1,'2019-10-19 05:51:23','2019-10-19 05:51:33'),('1189434737808990210','18','44','测试','','',1,0,0,0,'Empty',0,1,'2019-10-30 14:51:55','2019-10-30 14:51:55'),('1189471423678939138','18','1181729226915577857','test','2b887dc9584d4dc68908780ec57cd3b9','视频',1,0,0,0,'Empty',0,1,'2019-10-30 17:17:41','2019-10-30 17:17:41'),('1189476403626409986','18','1181729226915577857','22','5155c73dc112475cbbddccf4723f7cef','视频.mp4',0,0,0,0,'Empty',0,1,'2019-10-30 17:37:29','2019-10-30 17:37:29'),('1192252824606289921','1192252213659774977','1192252428399751169','第一课时','756cf06db9cb4f30be85a9758b19c645','eae2b847ef8503b81f5d5593d769dde2.mp4',0,0,0,0,'Empty',0,1,'2019-11-07 09:29:59','2019-11-07 09:29:59'),('1192628092797730818','1192252213659774977','1192252428399751169','第二课时','2a02d726622f4c7089d44cb993c531e1','eae2b847ef8503b81f5d5593d769dde2.mp4',0,0,1,0,'Empty',0,1,'2019-11-08 10:21:10','2019-11-08 10:21:22'),('1192632495013380097','1192252213659774977','1192252428399751169','第三课时','4e560c892fdf4fa2b42e0671aa42fa9d','eae2b847ef8503b81f5d5593d769dde2.mp4',0,0,1,0,'Empty',0,1,'2019-11-08 10:38:40','2019-11-08 10:38:40'),('1194117638832111617','1192252213659774977','1192252428399751169','第四课时','4e560c892fdf4fa2b42e0671aa42fa9d','eae2b847ef8503b81f5d5593d769dde2.mp4',0,0,0,0,'Empty',0,1,'2019-11-12 13:00:05','2019-11-12 13:00:05'),('1196263770832023554','1192252213659774977','1192252428399751169','第五课时','27d21158b0834cb5a8d50710937de330','eae2b847ef8503b81f5d5593d769dde2.mp4',5,0,0,0,'Empty',0,1,'2019-11-18 11:08:03','2019-11-18 11:08:03'),('17','18','15','第一节:Java简介','196116a6fee742e1ba9f6c18f65bd8c1','1',1,1000,1,100,'Draft',0,1,'2019-01-01 13:08:57','2019-10-11 11:26:39'),('18','18','15','第二节:表达式和赋值语句','2d99b08ca0214909899910c9ba042d47','7 - How Do I Find Time for My ',2,999,1,100,'Draft',0,1,'2019-01-01 13:09:02','2019-03-08 03:30:27'),('19','18','15','第三节:String类','51120d59ddfd424cb5ab08b44fc8b23a','eae2b847ef8503b81f5d5593d769dde2.mp4',3,888,0,100,'Draft',0,1,'2019-01-01 13:09:05','2019-11-12 12:50:45'),('20','18','15','第四节:程序风格','2a38988892d84df598752226c50f3fa3','00-day10总结.avi',4,666,0,100,'Draft',0,1,'2019-01-01 13:09:05','2019-10-11 09:20:09');
存储课程基本信息
CREATE TABLE `edu_course` (
`id` char(19) NOT NULL COMMENT '课程ID',
`teacher_id` char(19) NOT NULL COMMENT '课程讲师ID',
`subject_id` char(19) NOT NULL COMMENT '课程专业ID',
`subject_parent_id` char(19) NOT NULL COMMENT '课程专业父级ID',
`title` varchar(50) NOT NULL COMMENT '课程标题',
`price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '课程销售价格,设置为0则可免费观看',
`lesson_num` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '总课时',
`cover` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '课程封面图片路径',
`buy_count` bigint(10) unsigned NOT NULL DEFAULT '0' COMMENT '销售数量',
`view_count` bigint(10) unsigned NOT NULL DEFAULT '0' COMMENT '浏览数量',
`version` bigint(20) unsigned NOT NULL DEFAULT '1' COMMENT '乐观锁',
`status` varchar(10) NOT NULL DEFAULT 'Draft' COMMENT '课程状态 Draft未发布 Normal已发布',
`is_deleted` tinyint(3) DEFAULT NULL COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_title` (`title`),
KEY `idx_subject_id` (`subject_id`),
KEY `idx_teacher_id` (`teacher_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='课程';
#
# Data for table "edu_course"
#
INSERT INTO `edu_course` VALUES ('1192252213659774977','1189389726308478977','1178214681139539969','1178214681118568449','java基础课程:test',0.01,2,'https://guli-file-190513.oss-cn-beijing.aliyuncs.com/cover/default.gif',4,387,1,'Normal',0,'2019-11-07 09:27:33','2019-11-18 13:35:03'),('14','1189389726308478977','1101348944971091969','1101348944920760321','XHTML CSS2 JS整站制作教程课程学习',0.00,3,'http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/13/d0086eb0-f2dc-45f7-bba1-744d95e5be0f.jpg',3,44,15,'Normal',0,'2018-04-02 18:33:34','2019-11-16 21:21:45'),('15','1189389726308478977','1101348944971091969','1101348944920760321','HTML5入门课程学习',0.00,23,'http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/13/22997b8e-3606-4d2e-9b4f-09f48418b6e4.jpg',0,51,17,'Normal',0,'2018-04-02 18:34:32','2019-11-12 10:19:20'),('18','1189389726308478977','1178214681139539969','1178214681118568449','Java精品课程',0.01,20,'http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg',151,737,6,'Normal',0,'2018-04-02 21:28:46','2019-11-18 11:14:52');
存储课程章节信息
CREATE TABLE `edu_chapter` (
`id` char(19) NOT NULL COMMENT '章节ID',
`course_id` char(19) NOT NULL COMMENT '课程ID',
`title` varchar(50) NOT NULL COMMENT '章节名称',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '显示排序',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_course_id` (`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='课程';
#
# Data for table "edu_chapter"
#
INSERT INTO `edu_chapter` VALUES ('1','14','第一章:HTML',0,'2019-01-01 12:27:40','2019-01-01 12:55:30'),('1181729226915577857','18','第七章:I/O流',70,'2019-10-09 08:32:58','2019-10-09 08:33:20'),('1192252428399751169','1192252213659774977','第一章节',0,'2019-11-07 09:28:25','2019-11-07 09:28:25'),('15','18','第一章:Java入门',0,'2019-01-01 12:27:40','2019-10-09 09:13:19'),('3','14','第二章:CSS',0,'2019-01-01 12:55:35','2019-01-01 12:27:40'),('32','18','第二章:控制台输入和输出',0,'2019-01-01 12:27:40','2019-01-01 12:27:40'),('44','18','第三章:控制流',0,'2019-01-01 12:27:40','2019-01-01 12:27:40'),('48','18','第四章:类的定义',0,'2019-01-01 12:27:40','2019-01-01 12:27:40'),('63','18','第五章:数组',0,'2019-01-01 12:27:40','2019-01-01 12:27:40'),('64','18','第六章:继承',61,'2019-01-01 12:27:40','2019-10-09 08:32:47');
表与表之间的关系分:一对一、一对多、多对多
@Test
public void run() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir("D:\\JavaStudy\\gulixueyuan\\guli_parent\\service\\service_edu" + "/src/main/java"); //输出目录
gc.setAuthor("achang"); //作者名
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("00000");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
//生成包:com.achang.eduservice
pc.setModuleName("eduservice"); //模块名
pc.setParent("com.achang");
//生成包:com.achang.oss.controller
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("edu_course","edu_chapter","edu_course_description","edu_video");//根据数据库哪张表生成,有多张表就加逗号继续填写
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
也在service_edu模块中
所以只需要修改对应的数据库表:
"edu_course","edu_chapter","edu_course_description","edu_video"
因为课程简介是依赖于课程的,所以删掉EduCourseDescriptionController
@ApiModel(value = "课程基本信息", description = "编辑课程基本信息的表单对象")
@Data
public class CourseInfoForm implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "课程ID")
private String id;
@ApiModelProperty(value = "课程讲师ID")
private String teacherId;
@ApiModelProperty(value = "课程专业ID")
private String subjectId;
@ApiModelProperty(value = "课程标题")
private String title;
@ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")
private BigDecimal price;
@ApiModelProperty(value = "总课时")
private Integer lessonNum;
@ApiModelProperty(value = "课程封面图片路径")
private String cover;
@ApiModelProperty(value = "课程简介")
private String description;
}
@RestController
@RequestMapping("/eduservice/edu-course")
@CrossOrigin //解决跨域问题
public class EduCourseController {
@Autowired
private EduCourseService eduCourseService;
//添加课程基本信息方法
@PostMapping("/addCourseInfo")
public R addCourseInfo(@RequestBody CourseInfoForm courseInfoForm){
eduCourseService.saveCourseInfo(courseInfoForm);
return R.ok();
}
}
public interface EduCourseService extends IService<EduCourse> {
//添加课程基本信息方法
void saveCourseInfo(CourseInfoForm courseInfoForm);
}
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
//课程描述注入
@Autowired
private EduCourseDescriptionService eduCourseDescriptionService;
@Override
public void saveCourseInfo(CourseInfoForm courseInfoForm) {
//向课程表里面添加课程基本信息
//CourseInfoForm对象 转换成 EduCourse对象
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoForm,eduCourse);
int result = baseMapper.insert(eduCourse);
if (result<=0){
//表示添加失败
throw new AchangException(20001,"添加课程信息失败");
}
//想课程简介表里面添加课程简介
EduCourseDescription eduCourseDescription = new EduCourseDescription();
eduCourseDescription.setDescription(courseInfoForm.getDescription());
eduCourseDescriptionService.save(eduCourseDescription);
}
}
注意Entity中EduCourse和EduCourseDescription加入:不然报错
启动8001,访问:http://localhost:8001/swagger-ui.html
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
//课程描述注入
@Autowired
private EduCourseDescriptionService eduCourseDescriptionService;
@Override
public String saveCourseInfo(CourseInfoForm courseInfoForm) {
//向课程表里面添加课程基本信息
//CourseInfoForm对象 转换成 EduCourse对象
EduCourse eduCourse = new EduCourse();
BeanUtils.copyProperties(courseInfoForm,eduCourse);
int result = baseMapper.insert(eduCourse);
if (result<=0){
//表示添加失败
throw new AchangException(20001,"添加课程信息失败");
}
//获取添加之后课程信息的id
String cid = eduCourse.getId();
//想课程简介表里面添加课程简介
EduCourseDescription eduCourseDescription = new EduCourseDescription();
eduCourseDescription.setDescription(courseInfoForm.getDescription());
//手动设置描述课程表的id,与上面的课程信息表id关联
eduCourseDescription.setId(cid);
eduCourseDescriptionService.save(eduCourseDescription);
return cid;
}
}
手动输入
@RestController
@RequestMapping("/eduservice/edu-course")
@CrossOrigin //解决跨域问题
public class EduCourseController {
@Autowired
private EduCourseService eduCourseService;
//添加课程基本信息方法
@PostMapping("/addCourseInfo")
public R addCourseInfo(@RequestBody CourseInfoForm courseInfoForm){
//返回添加之后课程id,为了后面添加大纲使用
String id = eduCourseService.saveCourseInfo(courseInfoForm);
return R.ok().data("courseId",id);
}
}
public interface EduCourseService extends IService<EduCourse> {
//添加课程基本信息方法
String saveCourseInfo(CourseInfoForm courseInfoForm);
}
1)、添加路由
//课程信息管理
{
path: '/course',
component: Layout,
redirect: '/course/list',
name: '课程管理',
meta: {
title: '课程管理', icon: 'nested' },
children: [
{
path: 'list',
name: '课程列表',
component: () => import('@/views/edu/course/list.vue'),
meta: {
title: '课程列表', icon: 'table' }
},
{
path: 'info',
name: '添加课程',
component: () => import('@/views/edu/course/info.vue'),
meta: {
title: '添加课程', icon: 'nested' }
},
{
path: 'info/:id',
name: 'EduCourseInfoEdit',
component: () => import('@/views/edu/course/info.vue'),
meta: {
title: '编辑课程基本信息', noCache: true },
hidden: true
},
{
path: 'chapter/:id',
name: 'EduCourseChapterEdit',
component: () => import('@/views/edu/course/chapter.vue'),
meta: {
title: '编辑课程大纲', noCache: true },
hidden: true
},
{
path: 'publish/:id',
name: 'EduCoursePublishEdit',
component: () => import('@/views/edu/course/publish.vue'),
meta: {
title: '发布课程', noCache: true },
hidden: true
}
]
},
2)、添加vue组件
参考http://element-cn.eleme.io/#/zh-CN/component/steps
1)、课程信息页面
info.vue
.<template>
<div class="app-container">
<h2 style="text-align: center">发布新课程h2>
<el-steps
:active="1"
process-status="wait"
align-center
style="margin-
bottom: 40px;"
>
<el-step title="填写课程基本信息" />
<el-step title="创建课程大纲" />
<el-step title="最终发布" />
el-steps>
<el-form label-width="120px">
<el-form-item>
<el-button :disabled="saveBtnDisabled" type="primary" @click="next"
>保 存并下一步el-button
>
el-form-item>
el-form>
div>
template>
<script>
export default {
data() {
return {
saveBtnDisabled:false,
};
},
methods: {
next() {
//跳转到第二步
this.$router.push({
path:'/course/chapter/1'})
},
},
created(){
}
};
script>
<style>style>
2)、课程大纲页面
chapter.vue
.<template>
<div class="app-container">
<h2 style="text-align: center">发布新课程h2>
<el-steps
:active="2"
process-status="wait"
align-center
style="margin-
bottom: 40px;"
>
<el-step title="填写课程基本信息" />
<el-step title="创建课程大纲" />
<el-step title="最终发布" />
el-steps>
<el-form label-width="120px">
<el-form-item>
<el-button @click="previous">上一步el-button>
<el-button :disabled="saveBtnDisabled" type="primary" @click="next"
>下 一步el-button
>
el-form-item>
el-form>
div>
template>
<script>
export default {
data() {
return {
saveBtnDisabled: false,
};
},
methods: {
//跳转到上一步
previous() {
this.$router.push({
path: "/course/info/1" });
},
next() {
//跳转到第三步
this.$router.push({
path: "/course/publish/1" });
},
},
created() {
},
};
script>
<style>
style>
3)、课程发布页面
publish.vue
.<template>
<div class="app-container">
<h2 style="text-align: center">发布新课程h2>
<el-steps
:active="3"
process-status="wait"
align-center
style="margin-
bottom: 40px;"
>
<el-step title="填写课程基本信息" />
<el-step title="创建课程大纲" />
<el-step title="最终发布" />
el-steps>
<el-form label-width="120px">
<el-form-item>
<el-button @click="previous">返回修改el-button>
<el-button :disabled="saveBtnDisabled" type="primary" @click="publish"
>发布课程el-button
>
el-form-item>
el-form>
div>
template>
<script>
export default {
data() {
return {
saveBtnDisabled: false,
};
},
methods: {
//跳转到上一步
previous() {
this.$router.push({
path: "/course/chapter/1" });
},
publish(){
this.$router.push({
path: "/course/list" });
}
},
};
script>
<style>
style>
1)、定义api
import request from '@/utils/request' //引入已经封装好的axios 和 拦截器
export default{
//添加课程信息功能
addCourseInfo(courseInfo){
return request({
url:"/eduservice/edu-course/addCourseInfo",
method: 'post',
data: courseInfo,
})
}
}
2)、组件模板
.<template>
<div class="app-container">
<h2 style="text-align: center">发布新课程h2>
<el-steps
:active="1"
process-status="wait"
align-center
style="margin-
bottom: 40px;"
>
<el-step title="填写课程基本信息" />
<el-step title="创建课程大纲" />
<el-step title="最终发布" />
el-steps>
<el-form label-width="120px">
<el-form-item label="课程标题">
<el-input
v-model="courseInfo.title"
placeholder=" 示例:机器学习项目课:从基础到搭建项目视频课程。专业名称注意大小写"
/>
el-form-item>
<el-form-item label="总课时">
<el-input-number
:min="0"
v-model="courseInfo.lessonNum"
controls-position="right"
placeholder="请填写课程的总课时数"
/>
el-form-item>
<el-form-item label="课程简介">
<el-input v-model="courseInfo.description" placeholder="" />
el-form-item>
<el-form-item label="课程价格">
<el-input-number
:min="0"
v-model="courseInfo.price"
controls-position="right"
placeholder="免费课程请设置为0元"
/>
元
el-form-item>
<el-form-item>
<el-button
:disabled="saveBtnDisabled"
type="primary"
@click="saveOrUpdate"
>保存并下一步el-button
>
el-form-item>
el-form>
div>
template>
<script>
import course from "@/api/teacher/course.js";
export default {
data() {
return {
saveBtnDisabled: false,
courseInfo:
{
title: "",
subjectId: "",
teacherId: "",
lessonNum: 0,
description: "",
cover: "",
price: 0,
},
};
},
methods: {
saveOrUpdate() {
course.addCourseInfo(this.courseInfo).then(resp => {
this.$message({
message: "添加课程信息成功",
type: "success",
})
//跳转到第二步,并带着这个课程生成的id
this.$router.push({
path: "/course/chapter/"+resp.data.courseId });
});
},
},
created() {
},
};
script>
<style>
style>
1)、组件模板
guli-admin\src\views\edu\course\info.vue
<el-form-item label="课程讲师">
<el-select v-model="courseInfo.teacherId" placeholder="请选择">
<el-option
v-for="teacher in teacherLists"
:key="teacher.id"
:label="teacher.name"
:value="teacher.id"
>el-option>
el-select>
el-form-item>
2)、定义api
src\api\teacher\course.js
//查询所有讲师
getAllTeacher(){
return request({
url:"/eduservice/edu-teacher/findAll",
method: 'get',
})
}
组件中引入teacher api
import course from "@/api/teacher/course.js";
3)、组件脚本
export default {
data() {
return {
...
teacherLists: [], //封装所有讲师数据
};
},
methods: {
//查询所有讲师
getListTeacher() {
course.getAllTeacher().then((resp) => {
this.teacherLists = resp.data.items;
});
},
....
created() {
//初始化所有讲师
this.getListTeacher();
},
};
</script>
1、组件数据定义
定义在 data 中
subjectOneLists: [], //封装所以一级分类数据
subjectTwoLists: [], //封装二级分类数据
2、组件模板
<el-select
v-model="courseInfo.subjectParentId"
placeholder="一级分类"
@change="subjectLevelOneChanged"
>
<el-option
v-for="subject in subjectOneLists"
:key="subject.id"
:label="subject.title"
:value="subject.id"
>el-option>
el-select>
3、组件脚本
表单初始化时获取一级分类嵌套列表,引入subject api
import subject from "@/api/teacher/subject.js";
定义方法
//课程分类
getSubjectList(){
return request({
url:"/eduservice/edu-subject/getAllSubject",
method: 'get'
})
}
1、组件模板
<el-select v-model="courseInfo.subjectId" placeholder="二级分类">
<el-option
v-for="subject in subjectTwoLists"
:key="subject.id"
:label="subject.title"
:value="subject.id"
>el-option>
el-select>
2、注册change事件
在一级分类的< el-select >组件中注册change事件
3、定义change事件方法
//点击某个一级分类,触发change事件,显示对应的二级分类
subjectLevelOneChanged(value) {
//value就是一级分类的id值
for (let i = 0; i < this.subjectOneLists.length; i++) {
if (this.subjectOneLists[i].id === value) {
this.subjectTwoLists = this.subjectOneLists[i].children;
this.courseInfo.subjectId = "";
}
}
}
4、然后在created()生命周期调用
created() {
//初始化所有讲师
this.getListTeacher();
//初始化一级分类
this.getOneSubject();
}
BASE_API: process.env.BASE_API, // 接口API地址
<el-form-item label="课程封面">
<el-upload
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:action="BASE_API + '/edu_oss/fileoss/upload'"
class="avatar-uploader"
>
<img :src="courseInfo.cover" />
el-upload>
el-form-item>
//上传封面成功调用的方法
handleAvatarSuccess(resp,file) {
this.courseInfo.cover = resp.data.url
},
//上传之前要调用的方法
beforeAvatarUpload(file) {
const isJPG = file.type === "image/jpeg";
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error("上传头像图片只能是 JPG 格式!");
}
if (!isLt2M) {
this.$message.error("上传头像图片大小不能超过 2MB!");
}
return isJPG && isLt2M;
}