1.系统介绍
基于权限脚手架基础开发的项目,本系统专属功能点如下
1.课程管理:课程id, 课程名称,课程类型,课程描述,课时,学分,课程开始时间,课程结束时间,上课人数,已选人数,课件资料。
2.课程类型管理:id,类型名称,描述。
3.专业管理:id,专业名称,专业描述,图片。
4.学院管理:id,名称,描述,学分限制 。
5.我的选课:id,课程id,学生id,创建时间。
6.宿舍管理:id,宿舍名称,宿舍位置,宿舍描述,宿舍规模,宿舍入住人数,宿舍图片。
7.宿舍报修管理:id,学生id,宿舍id,问题描述,报修图片,创建时间,完成维修时间,维修状态。
角色分为:管理员,教师,学生
项目视频地址:1.系统介绍和运行权限项目_哔哩哔哩_bilibili
功能图
本系统是基于之前的权限项目完成的,先运行权限项目
2.代码生成器
使用代码生成器自动生成java后端的 entity,mapper,service,serviceImpl,controller类信息,节省时间,先添加依赖:
<!-- 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
创建代码生成器工具类
package com.example.authority.utils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import javax.sql.DataSource;
import java.io.File;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* mp代码生成器
*/
public class CodeGenerator {
// ----------------------------------------以下必须修改------------------------------------------
// 数据库名称
private static final String DATASOURCE = "student_manage";
// 你自己的项目路径,一定要改成你自己的!!结尾必须是: \\springboot\\
private static final String basePath = System.getProperty("user.dir");
// 数据库需要生成代码的表名
private static final String tableName = "course_type";
// ----------------------------------------以上必须修改-----------------------------------------
// 数据库密码 (填你自己的密码,默认 123456)
private static final String PASSWORD = "root";
public static void main(String[] args) throws Exception {
String property = System.getProperty("user.dir");
System.out.println(property);
// 生成SpringBoot
generate(tableName);
}
private static final String url = "jdbc:mysql://localhost:3306/" + DATASOURCE;
private static final String username = "root";
private static final String password = PASSWORD;
/**
* 生成SpringBoot文件
*/
private static void generate(String tableName) {
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> {
builder.author("程序员云翼") // 设置作者
.enableSwagger()
.fileOverride() // 覆盖已生成文件
.disableOpenDir()
.outputDir(basePath + "/src/main/java/"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.example.authority") // 设置父包名
.moduleName(null) // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, basePath + "\\src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.entityBuilder().enableLombok();
builder.serviceBuilder().formatServiceFileName("%sService");
// builder.mapperBuilder().enableMapperAnnotation().build();
builder.controllerBuilder().enableHyphenStyle() // 开启驼峰转连字符
.enableRestStyle(); // 开启生成@RestController 控制器
builder.addInclude(tableName) // 设置需要生成的表名
.addTablePrefix("t_", "sys_"); // 设置过滤表前缀
})
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
在resources目录下创建templates目录,把 自定义 controller.java.vm 模板放进去,作用是改造生成的controller类。
package ${package.Controller};
import org.springframework.web.bind.annotation.RequestMapping;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.authority.common.Result;
import com.example.authority.entity.CourseType;
import com.example.authority.service.CourseTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import ${package.Service}.${table.serviceName};
import ${package.Entity}.${entity};
#if(${restControllerStyle})
import org.springframework.web.bind.annotation.RestController;
#else
import org.springframework.stereotype.Controller;
#end
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end
/**
* <p>
* $!{table.comment} 前端控制器
* </p>
* table.entityPath ${table.entityPath}
* table.serviceName ${table.serviceName}
* table.entityPath ${table.entityPath}
* entity ${entity}
* @author ${author}
* @since ${date}
*/
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("/${table.entityPath}")
#if(${kotlin})
class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end
#else
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
public class ${table.controllerName} {
#end
@Autowired
private ${table.serviceName} ${table.entityPath}Service;
/**
* 新增/修改
* @param ${table.entityPath}
* @return
*/
@PostMapping("/save")
public Result save(@RequestBody ${entity} ${table.entityPath}){
boolean b = ${table.entityPath}Service.saveOrUpdate(${table.entityPath});
if(b){
return Result.success();
}else{
return Result.error();
}
}
/**
* 根据id删除
* @param id
* @return
*/
@DeleteMapping("/deleteById/{id}")
public Result deleteById(@PathVariable Integer id){
boolean b = ${table.entityPath}Service.removeById(id);
if(b){
return Result.success();
}else{
return Result.error();
}
}
/**
* 根据id批量删除
* @param idList
* @return
*/
@PostMapping("/deleteBatch")
public Result deleteBatch(@RequestBody List<Integer> idList){
boolean b= ${table.entityPath}Service.removeByIds(idList);
if(b){
return Result.success();
}else{
return Result.error();
}
}
/**
* 查询全部数据
* @return
*/
@GetMapping("/findAll")
public Result findAll(){
return Result.success(${table.entityPath}Service.list());
}
/**
* 根据id查询文章信息
* @return
*/
@GetMapping("/findById/{id}")
public Result findById(@PathVariable("id") Integer id){
${entity} ${table.entityPath} = ${table.entityPath}Service.getById(id);
if(null != ${table.entityPath}){
return Result.success(${table.entityPath});
}else{
return Result.error("500","找不到信息");
}
}
/**
* 分页查询
* @param pageNum:页码
* @param pageSize:每页条数
* @param name:名称
* @return
*/
@GetMapping("/findPage")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(name = "name",defaultValue = "") String name){
Page<${entity}> page = new Page<>(pageNum,pageSize);
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
if(StringUtils.isNotBlank(name)){
queryWrapper.like("name",name);
}
Page<${entity}> ${table.entityPath}Page = ${table.entityPath}Service.page(page, queryWrapper);
return Result.success(${table.entityPath}Page);
}
}
#end
这样就可以一键生成后端全部的模板代码了
3.课程类型管理
java后端:一键生成
前端页面
<template>
<div>
<div>
<!-- 搜索栏-->
<el-input style="width: 200px;margin-right: 20px" placeholder="请输入课程类型名称" v-model="name" prefix-icon="el-icon-user"></el-input>
<el-button style="margin-left: 10px;" type="primary" @click="load" class="el-icon-search">搜索</el-button>
<el-button style="margin-left: 10px;" type="warning" @click="reset" class="el-icon-refresh">重置</el-button>
</div>
<div style="margin-top:20px;margin-bottom: 20px;">
<!-- 新增。批量删除-->
<el-button style="margin-right: 10px;" type="success" class="el-icon-plus" @click="save">新增</el-button>
<el-popconfirm
confirm-button-text='确定'
cancel-button-text='取消'
icon="el-icon-info"
icon-color="red"
title="确定删除这些数据吗?"
@confirm="deleteBatch"
@cancel="cancel">
<el-button slot="reference" type="danger" style="margin-left:5px;" class="el-icon-delete">批量删除</el-button>
</el-popconfirm>
</div>
<el-table :data="tableData" border stripe :header-cell-style="getRowClass" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="id"></el-table-column>
<el-table-column prop="name" label="课程类型名称"></el-table-column>
<el-table-column prop="description" label="课程类型描述"></el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button type="primary" class="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
<el-popconfirm
confirm-button-text='确定'
cancel-button-text='取消'
icon="el-icon-info"
icon-color="red"
title="确定删除这些数据吗?"
@confirm="handleDelete(scope.row.id)"
@cancel="cancel">
<el-button slot="reference" type="danger" style="margin-left:5px;" class="el-icon-delete">删除</el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="block" style="padding:10px 0;align-content: center;margin-left: 30%;margin-top:30px;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[5, 10, 15, 20]"
:page-size="10"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<el-dialog title="课程类型信息" :visible.sync="dialogFormVisible" width="30%">
<el-form :model="form">
<el-form-item label="课程类型名称" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="描述" :label-width="formLabelWidth">
<el-input v-model="form.description" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="handleAdd">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "CourseType",
data(){
return{
pageSize:10,
pageNum:1,
name:'',
tableData:[],
dialogFormVisible:false,
form:{},
formLabelWidth: '100px',
multipleSelection:[],
total:0
}
},
created() {
this.load();
},
methods:{
load(){
this.request.get("/courseType/findPage",{
params:{
pageNum:this.pageNum,
pageSize:this.pageSize,
name:this.name,
}
}).then(res => {
this.tableData = res.data.records;
this.total = res.data.total;
})
},
getRowClass({rowIndex,columnIndex}){
if(rowIndex === 0){
return 'background:#ccc'
}
},
reset(){
this.name = '';
this.load();
},
save(){
this.dialogFormVisible = true;
this.form = {};
},
handleAdd(){
this.request.post("/courseType/save",this.form).then(res => {
if(res.code === '200'){
if(this.form.id){
this.$message.success('编辑成功');
}else{
this.$message.success('新增成功');
}
this.dialogFormVisible = false;
this.load();
}else{
this.$message.error(res.msg)
}
})
},
handleEdit(row){
this.form = JSON.parse(JSON.stringify(row));
this.dialogFormVisible = true;
},
handleDelete(id){
if(id){
this.request.delete('/courseType/deleteById/' + id).then(res => {
if(res.code === '200'){
this.$message.success('删除数据成功');
this.handleCalPageNum();
}else{
this.$message.error(res.msg)
}
})
}else{
this.$message.error('没有id信息,无法删除');
}
},
cancel(){
this.$message.success('取消操作成功');
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
deleteBatch(){
//批量删除数据
if(this.multipleSelection.length === 0){
this.$message.warning("请先选择要删除的数据");
return
}
const ids = this.multipleSelection.map(v => v.id);
this.request.post('/courseType/deleteBatch',ids).then(res => {
if(res.code === '200'){
this.$message.success('批量删除成功');
this.handleCalPageNum();
}else{
this.$message.error(res.msg);
}
})
},
handleSizeChange(val) {
this.pageSize = val;
this.load();
},
handleCurrentChange(val) {
this.pageNum = val;
this.load();
},
handleCalPageNum(){
this.request.get("/courseType/findPage",{
params:{
pageNum:this.pageNum,
pageSize:this.pageSize,
name:this.name,
}
}).then(res => {
this.total = res.data.total;
this.pageNum = (this.total % this.pageSize === 0) ? (this.total / this.pageSize) : Math.floor((this.total / this.pageSize) + 1);
if(this.pageNum < 1){
this.pageNum = 1;
}
this.load();
})
}
}
}
</script>
<style scoped>
</style>
4.课程管理
课程表:联系作者获取
一键生成后端代码
前端看视频操作
5.专业管理
专业表:联系作者获取
一键生成后端代码
前端看视频操作
6.学院管理
学院表:联系作者获取
一键生成后端代码
前端看视频操作
7.我的选课
学生在课程页面进行选课操作,可以查看自己的选课记录也可以取消选课
管理员可以查看全部学生的选课信息
选课表:联系作者获取
然后把学生的角色单独抽出做一个学生管理页面,给学生分配专业,学院,宿舍
8.宿舍管理
宿舍表:联系作者获取
9.宿舍报修管理
宿舍报修表:联系作者获取
具体代码看视频
10.项目bug处理
1.学生管理页面的角色没有默认是学生
2.aside的滚动条可以去掉
3.选课的显示
11.项目总结
功能总结和学生的person页面添加了字段