SpringBoot+VUE前后端分离项目学习笔记 - 【25 SpringBoot实现1对1、1对多、多对多关联查询】
新增课程Course页面,实现学生选课功能、课程教授老师选择等功能;涉及到一对一、一对多、多对多的连表查询
·
- 新增课程Course页面,实现学生选课功能、课程教授老师选择等功能
- 1. 课程与授课老师是一对一关系
因为course表仅记录了teacherid,而页面需要的是老师的名字
- select course.*,sys_user.id from
course left join sys_user
**on ** course.teacher_id = sys_user.id- 2. 老师与教授课程是一对多关系
- 3. 学生与已选课程是多对多关系
2与3都需要同时显示在User页面,因此user表除了join学生选课表,还需要join两个course表来分别获取学术已选课程以及老师教授课程的信息,具体见下
- select sys_user.*, sc.name as stuCourseName, tc.name as teacherCourseName,
tc.score as teacherScore, sc.score as stuScore
from sys_user
left join student_course
on sys_user.id = student_course.student_id
left join course sc
on student_course.course_id = sc.id
left join course tc
on sys_user.id = tc.teacher_id
数据库
Menu表
添加页面顺序字段来控制前端路由出现的菜单层级,后端的entity里Menu记得加上该字段
CREATE TABLE `sys_menu` (
`id` int NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '名称',
`path` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '路径',
`icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图标',
`description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '描述',
`pid` int DEFAULT NULL COMMENT '父级id',
`page_path` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '页面路径',
`sort_num` int DEFAULT NULL COMMENT '顺序',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
课程表 course
CREATE TABLE `course` (
`id` int NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '课程名称',
`score` int DEFAULT NULL COMMENT '学分',
`times` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '上课时间',
`state` tinyint(1) DEFAULT NULL COMMENT '是否开课',
`teacher_id` int DEFAULT NULL COMMENT '授课老师id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
学术选课表 student_course
CREATE TABLE `student_course` (
`student_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL,
PRIMARY KEY (`student_id`, `course_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
后台
UserDTO.java
添加ID信息,用于选课表使用
package com.zj.demo.controller.dao;
import com.zj.demo.entity.Menu;
import lombok.Data;
import java.util.List;
/**
* 接受前端登录请求的参数
*/
@Data
public class UserDTO {
private Integer id;
private String username;
private String password;
private String nickname;
private String avatarUrl;
private String token;
private String role;
private List<Menu> menus;
}
CodeGenerator.java
修改表名设置,右键运行,分别生成相应代码
RoleEnum.java
通过前端添加老师和学生两种角色
package com.zj.demo.common;
public enum RoleEnum {
ROLE_ADMIN, ROLE_STUDENT,ROLE_TEACHER;
}
在前端用户管理处随机分配几个学生和老师
Course.java
添加老师名称字段
@TableField(exist = false)
private String teacher;
CourseController.java
增加获取老师信息的接口以及学生选课接口
@GetMapping("/page")
public Result findPage(@RequestParam String name,
@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
// 小白写法按照Course_id获取老师名称
// QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
// queryWrapper.orderByDesc("id");
// Page<Course> page = courseService.page(new Page<>(pageNum, pageSize), queryWrapper);
// List<Course> records = page.getRecords();
// for (Course record : records) {
// User user = userService.getById(record.getTeacherId());
// if(user != null) {
// record.setTeacher(user.getNickname());
// }
//
// }
Page<Course> page = courseService.findPage(new Page<>(pageNum, pageSize), name);
return Result.success(page);
}
@PostMapping("/studentCourse/{courseId}/{studentId}")
public Result studentCourse(@PathVariable Integer courseId, @PathVariable Integer studentId) {
courseService.setStudentCourse(courseId, studentId);
return Result.success();
}
ICourseSerivce.java
package com.zj.demo.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zj.demo.entity.Course;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author Joyce
* @since 2023-01-18
*/
public interface ICourseService extends IService<Course> {
Page<Course> findPage(Page<Course> page, String name);
void setStudentCourse(Integer courseId, Integer studentId);
}
CourseSerivceImpl.java
package com.zj.demo.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zj.demo.entity.Course;
import com.zj.demo.mapper.CourseMapper;
import com.zj.demo.service.ICourseService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* <p>
* 服务实现类
* </p>
*
* @author Joyce
* @since 2023-01-18
*/
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
@Resource
private CourseMapper courseMapper;
@Override
public Page<Course> findPage(Page<Course> page, String name) {
return courseMapper.findPage(page, name);
}
@Transactional
@Override
public void setStudentCourse(Integer courseId, Integer studentId) {
courseMapper.deleteStudentCourse(courseId, studentId);
courseMapper.setStudentCourse(courseId, studentId);
}
}
CourseMapper.java
package com.zj.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zj.demo.entity.Course;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* Mapper 接口
* </p>
*
* @author Joyce
* @since 2023-01-18
*/
public interface CourseMapper extends BaseMapper<Course> {
Page<Course> findPage(Page<Course> page, @Param("name") String name);
void deleteStudentCourse(Integer courseId, Integer studentId);
void setStudentCourse(Integer courseId, Integer studentId);
}
按alt+enter在xml创建方法
CourseMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zj.demo.mapper.CourseMapper">
<delete id="deleteStudentCourse">
delete from student_course where student_id = #{studentId} and course_id = #{courseId}
</delete>
<insert id="setStudentCourse">
insert into student_course(student_id, course_id) values(#{studentId}, #{courseId})
</insert>
<select id="findPage" resultType="com.zj.demo.entity.Course">
select course.*, sys_user.nickname as teacher from course
left join sys_user
on course.teacher_id = sys_user.id
<where>
<if test="name != null and name != ''">
and name like concat('%', #{name},'%')
</if>
</where>
</select>
</mapper>
User.java
增加两个字段分别表示老师教授课程与学术已选课程
@TableField(exist = false)
private List<Course> courses;
@TableField(exist = false)
private List<Course> stuCourses;
UserController.java
1、新增接口,编写对应方法findUsersByRole,返回符合角色类型的用户【用来给课程提供授课老师选项】
2、改写findpage接口,返回用户角色对应的课程信息
============1=============
@GetMapping("/role/{role}")
public Result findUsersByRole(@PathVariable String role) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("role", role);
List<User> list = userService.list(queryWrapper);
return Result.success(list);
}
============2=============
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(defaultValue ="") String username,
@RequestParam(defaultValue ="") String email,
@RequestParam(defaultValue ="") String address
) {
return Result.success(userService.findPage(new Page<>(pageNum, pageSize), username, email, address));
}
IUserService.java
package com.zj.demo.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zj.demo.controller.dao.UserDTO;
import com.zj.demo.controller.dao.UserPasswordDTO;
import com.zj.demo.entity.User;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author Joyce
* @since 2023-01-04
*/
public interface IUserService extends IService<User> {
UserDTO login(UserDTO userDTO);
User register(UserDTO userDTO);
void updatePassword(UserPasswordDTO userPasswordDTO);
Page<User> findPage(Page<User> objectPage, String username, String email, String address);
}
UserServiceImpl.java
@Override
public Page<User> findPage(Page<User> objectPage, String username, String email, String address) {
return userMapper.findPage(page, username, email, address);
}
UserMapper.java
public interface UserMapper extends BaseMapper<User> {
@Update("update sys_user set password = #{newPassword} where username = #{username} and password = #{password}")
int updatePassword(UserPasswordDTO userPasswordDTO);
Page<User> findPage(Page<User> objectPage, String username, String email, String address);
}
UserMapper.xml
具体sql语句在这里,并且通过resultMap将查询结果封装成对象
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zj.demo.mapper.UserMapper">
<resultMap id="pageUser" type="com.zj.demo.entity.User">
<result column="id" property="id" />
<result column="username" property="username" />
<result column="nickname" property="nickname" />
<result column="email" property="email" />
<result column="phone" property="phone" />
<result column="address" property="address" />
<result column="create_time" property="createTime" />
<result column="avatar_url" property="avatarUrl" />
<result column="role" property="role" />
<collection property="courses" javaType="java.util.ArrayList" ofType="com.zj.demo.entity.Course">
<result column="teacherCourseName" property="name" />
<result column="teacherScore" property="score" />
</collection>
<collection property="stuCourses" javaType="java.util.ArrayList" ofType="com.zj.demo.entity.Course">
<result column="stuCourseName" property="name" />
<result column="stuScore" property="score" />
</collection>
</resultMap>
<select id="findPage" resultMap="pageUser">
select sys_user.*, sc.name as stuCourseName, tc.name as teacherCourseName, tc.score as teacherScore,
sc.score as stuScore from sys_user
left join student_course
on sys_user.id = student_course.student_id
left join course sc
on student_course.course_id = sc.id
left join course tc
on sys_user.id = tc.teacher_id
<where>
<if test="username != null and username != ''">
and sys_user.username like concat('%', #{username} ,'%')
</if>
<if test="email != null and email != ''">
and sys_user.email like concat('%', #{email} ,'%')
</if>
<if test="address != null and address != ''">
and sys_user.address like concat('%', #{address} ,'%')
</if>
</where>
</select>
</mapper>
前端
Menu.vue
<template>
<div>
<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" v-model="name"></el-input>
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
<el-button type="warning" @click="reset">重置</el-button>
</div>
<div style="margin: 10px 0">
<el-button type="primary" @click="handleAdd1">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定批量删除这些数据吗?"
@confirm="delBatch"
>
<el-button type="danger" slot="reference">批量删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</div>
<el-table :data="tableData" border stripe :header-cell-class-name="'headerBg'"
row-key="id" default-expand-all @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="path" label="路径"></el-table-column>
<el-table-column prop="pagePath" label="页面路径"></el-table-column>
<el-table-column label="图标" class-name="fontSize16" align="center" label-class-name="fontSize12">
<template slot-scope="scope">
<span :class="scope.row.icon" />
</template>
</el-table-column>
<el-table-column prop="description" label="描述"></el-table-column>
<el-table-column prop="sortNum" label="顺序"></el-table-column>
<el-table-column label="操作" width="300" align="center">
<template slot-scope="scope">
<el-button type="primary" @click="handleAdd(scope.row.id)" v-if="!scope.row.pid && !scope.row.path">新增子菜单 <i class="el-icon-plus"></i></el-button>
<el-button type="success" @click="handleEdit(scope.row)">编辑 <i class="el-icon-edit"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm="del(scope.row.id)"
>
<el-button type="danger" slot="reference">删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-dialog title="菜单信息" :visible.sync="dialogFormVisible" width="30%" >
<el-form label-width="80px" size="small">
<el-form-item label="名称">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="路径">
<el-input v-model="form.path" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="页面路径">
<el-input v-model="form.pagePath" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="图标">
<el-select clearable v-model="form.icon" placeholder="请选择" style="width: 100%">
<el-option v-for="item in options" :key="item.name" :label="item.name" :value="item.value">
<i :class="item.value"/> {{ item.name }}
</el-option>
</el-select>
</el-form-item>
<el-form-item label="描述">
<el-input v-model="form.description" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="顺序">
<el-input v-model="form.sortNum" 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="save">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "Menu",
data() {
return {
tableData: [],
total: 0,
pageNum: 1,
pageSize: 10,
name: "",
path: "",
icon: "",
description: "",
form: {},
dialogFormVisible: false,
multipleSelection: [],
options:[]
}
},
created() {
this.load()
},
methods: {
load() {
this.request.get("/menu", {
params: {
name: this.name,
}
}).then(res => {
this.tableData = res.data
})
},
save() {
this.request.post("/menu", this.form).then(res => {
if (res.code === '200') {
this.$message.success("保存成功")
this.dialogFormVisible = false
this.load()
} else {
this.$message.error("保存失败")
}
})
},
del(id) {
this.request.delete("/menu/" + id).then(res => {
if (res.code === '200') {
this.$message.success("删除成功")
this.load()
} else {
this.$message.error("删除失败")
}
})
},
delBatch() {
let ids = this.multipleSelection.map(v => v.id) // [{}, {}, {}] => [1,2,3]
this.request.post("/menu/del/batch", ids).then(res => {
if (res.code === '200') {
this.$message.success("批量删除成功")
this.load()
} else {
this.$message.error("批量删除失败")
}
})
},
handleAdd1() {
this.dialogFormVisible = true
this.form = {}
},
handleAdd(pid) {
this.dialogFormVisible = true
this.form = {}
if(pid)
{
this.form.pid = pid
}
},
handleEdit(row) {
this.form = row
this.dialogFormVisible = true
// 请求图标的数据
this.request.get("/menu/icons").then(res => {
this.options = res.data
})
},
handleSelectionChange(val) {
console.log(val)
this.multipleSelection = val
},
reset() {
this.name = ""
this.load()
},
handleSizeChange(pageSize) {
console.log(pageSize)
this.pageSize = pageSize
this.load()
},
handleCurrentChange(pageNum) {
console.log(pageNum)
this.pageNum = pageNum
this.load()
},
exp() {
window.open(`http://${serverIp}:9090/role/export`)
},
}
}
</script>
<style>
.headerBg {
background: #eee!important;
}
.fontSize16{
font-size: 16px;
}
.fontSize12{
font-size: 12px;
}
</style>
Course.vue
新增课程页面,其中授课老师的选择涉及到一对一关联查询【因为course表仅记录了teacherid,而页面需要的是老师的名字】
<template>
<div>
<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" v-model="name"></el-input>
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
<el-button type="warning" @click="reset">重置</el-button>
</div>
<div style="margin: 10px 0">
<el-button type="primary" @click="handleAdd" v-if="user.role === 'ROLE_ADMIN'">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定批量删除这些数据吗?"
@confirm="delBatch"
>
<el-button type="danger" slot="reference">批量删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</div>
<el-table :data="tableData" border stripe :header-cell-class-name="'headerBg'"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="name" label="课程名称"></el-table-column>
<el-table-column prop="score" label="学分"></el-table-column>
<el-table-column prop="times" label="课时"></el-table-column>
<el-table-column prop="teacher" label="授课老师"></el-table-column>
<!-- <el-table-column label="启用">-->
<!-- <template slot-scope="scope">-->
<!-- <el-switch v-model="scope.row.state" active-color="#13ce66" inactive-color="#ccc"-->
<!-- @change="changeEnable(scope.row)"></el-switch>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="操作" width="280" align="center">
<template slot-scope="scope">
<el-button type="primary" @click="selectCourse(scope.row.id)">选课</el-button>
<el-button type="success" @click="handleEdit(scope.row)" v-if="user.role === 'ROLE_ADMIN'">编辑 <i class="el-icon-edit"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm="del(scope.row.id)"
>
<el-button type="danger" slot="reference" v-if="user.role === 'ROLE_ADMIN'">删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<el-dialog title="课程信息" :visible.sync="dialogFormVisible" width="30%" >
<el-form label-width="80px" size="small">
<el-form-item label="名称">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="学分">
<el-input v-model="form.score" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="课时">
<el-input v-model="form.times" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="老师">
<el-select clearable v-model="form.teacherId" placeholder="请选择">
<el-option v-for="item in teachers" :key="item.id" :label="item.nickname" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "Course",
data() {
return {
form: {},
tableData: [],
name: '',
multipleSelection: [],
pageNum: 1,
pageSize: 10,
total: 0,
dialogFormVisible: false,
teachers: [],
user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}
}
},
created() {
this.load()
},
methods: {
selectCourse(courseId) {
this.request.post('/course/studentCourse/' + courseId + "/" + this.user.id).then(res => {
if (res.code === '200') {
this.$message.success("选课成功")
} else {
this.$message.success(res.msg)
}
})
},
load() {
this.request.get("/course/page", {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
name: this.name,
}
}).then(res => {
this.tableData = res.data.records
this.total = res.data.total
})
this.request.get("/user/role/ROLE_TEACHER").then(res => {
this.teachers = res.data
})
},
changeEnable(row) {
this.request.post("/course/update", row).then(res => {
if (res.code === '200') {
this.$message.success("操作成功")
}
})
},
handleAdd() {
this.dialogFormVisible = true
this.form = {}
},
handleEdit(row) {
this.form = JSON.parse(JSON.stringify(row))
this.dialogFormVisible = true
},
del(id) {
this.request.delete("/course/" + id).then(res => {
if (res.code === '200') {
this.$message.success("删除成功")
this.load()
} else {
this.$message.error("删除失败")
}
})
},
handleSelectionChange(val) {
console.log(val)
this.multipleSelection = val
},
delBatch() {
let ids = this.multipleSelection.map(v => v.id) // [{}, {}, {}] => [1,2,3]
this.request.post("/course/del/batch", ids).then(res => {
if (res.code === '200') {
this.$message.success("批量删除成功")
this.load()
} else {
this.$message.error("批量删除失败")
}
})
},
save() {
this.request.post("/course", this.form).then(res => {
if (res.code === '200') {
this.$message.success("保存成功")
this.dialogFormVisible = false
this.load()
} else {
this.$message.error("保存失败")
}
})
},
reset() {
this.name = ""
this.load()
},
handleSizeChange(pageSize) {
console.log(pageSize)
this.pageSize = pageSize
this.load()
},
handleCurrentChange(pageNum) {
console.log(pageNum)
this.pageNum = pageNum
this.load()
},
download(url) {
window.open(url)
},
}
}
</script>
<style scoped>
</style>
User.vue
根据用户角色,显示教授课程和已选课程
<template>
<div>
<div style="margin: 10px 0">
<el-input style="width: 200px" placeholder="请输入名称" suffix-icon="el-icon-search" v-model="username"></el-input>
<el-input style="width: 200px" placeholder="请输入邮箱" suffix-icon="el-icon-message" class="ml-5" v-model="email"></el-input>
<el-input style="width: 200px" placeholder="请输入地址" suffix-icon="el-icon-position" class="ml-5" v-model="address"></el-input>
<el-button class="ml-5" type="primary" @click="load">搜索</el-button>
<el-button type="warning" @click="reset">重置</el-button>
</div>
<div style="margin: 10px 0">
<el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定批量删除这些数据吗?"
@confirm="delBatch"
>
<el-button type="danger" slot="reference">批量删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
<el-upload :action="'http://' + serverIp + ':9090/user/import'" :show-file-list="false" accept="xlsx" :on-success="handleExcelImportSuccess" style="display: inline-block">
<el-button type="primary" class="ml-5">导入 <i class="el-icon-bottom"></i></el-button>
</el-upload>
<el-button type="primary" @click="exp" class="ml-5">导出 <i class="el-icon-top"></i></el-button>
</div>
<el-table :data="tableData" border stripe :header-cell-class-name="'headerBg'" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="id" label="ID" width="80"></el-table-column>
<el-table-column prop="username" label="用户名" width="140"></el-table-column>
<el-table-column prop="role" label="角色">
<template slot-scope="scope">
<el-tag type="primary" v-if="scope.row.role === 'ROLE_ADMIN'">管理员</el-tag>
<el-tag type="warning" v-if="scope.row.role === 'ROLE_TEACHER'">老师</el-tag>
<el-tag type="success" v-if="scope.row.role === 'ROLE_STUDENT'">学生</el-tag>
</template>
</el-table-column>
<el-table-column prop="nickname" label="昵称" width="120"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="phone" label="电话"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<el-table-column label="操作" width="500" align="center">
<template slot-scope="scope">
<el-button type="primary" @click="lookCourse(scope.row.courses)" v-if="scope.row.role === 'ROLE_TEACHER'">查看教授课程 <i class="el-icon-document"></i></el-button>
<el-button type="warning" @click="lookStuCourse(scope.row.stuCourses)" v-if="scope.row.role === 'ROLE_STUDENT'">查看已选课程 <i class="el-icon-document"></i></el-button>
<el-button type="success" @click="handleEdit(scope.row)">编辑 <i class="el-icon-edit"></i></el-button>
<el-popconfirm
class="ml-5"
confirm-button-text='确定'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm="del(scope.row.id)"
>
<el-button type="danger" slot="reference">删除 <i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%" >
<el-form label-width="80px" size="small">
<el-form-item label="用户名">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="角色">
<el-select clearable v-model="form.role" placeholder="请选择角色" style="width: 100%">
<el-option v-for="item in roles" :key="item.name" :label="item.name" :value="item.flag"></el-option>
</el-select>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="form.nickname" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="电话">
<el-input v-model="form.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address" 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="save">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="课程信息" :visible.sync="vis" width="30%" >
<el-table :data="courses" border stripe>
<el-table-column prop="name" label="课程名称"></el-table-column>
<el-table-column prop="score" label="学分"></el-table-column>
</el-table>
</el-dialog>
<el-dialog title="课程信息" :visible.sync="stuVis" width="30%" >
<el-table :data="stuCourses" border stripe>
<el-table-column prop="name" label="课程名称"></el-table-column>
<el-table-column prop="score" label="学分"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import {serverIp} from "../../public/config";
export default {
name: "User",
data() {
return {
serverIp: serverIp,
tableData: [],
total: 0,
pageNum: 1,
pageSize: 10,
username: "",
email: "",
address: "",
form: {},
dialogFormVisible: false,
multipleSelection: [],
roles: [],
courses: [],
vis: false,
stuCourses: [],
stuVis: false
}
},
created() {
this.load()
},
methods: {
lookCourse(courses) {
this.courses = courses
this.vis = true
},
lookStuCourse(stuCourses) {
this.stuCourses = stuCourses
this.stuVis = true
},
load() {
this.request.get("/user/page", {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
username: this.username,
email: this.email,
address: this.address,
}
}).then(res => {
this.tableData = res.data.records
this.total = res.data.total
})
this.request.get("/role").then(res => {
this.roles = res.data
})
},
save() {
this.request.post("/user", this.form).then(res => {
if (res.code === '200') {
this.$message.success("保存成功")
this.dialogFormVisible = false
this.load()
} else {
this.$message.error("保存失败")
}
})
},
handleAdd() {
this.dialogFormVisible = true
this.form = {}
},
handleEdit(row) {
this.form = JSON.parse(JSON.stringify(row))
this.dialogFormVisible = true
},
del(id) {
this.request.delete("/user/" + id).then(res => {
if (res.code === '200') {
this.$message.success("删除成功")
this.load()
} else {
this.$message.error("删除失败")
}
})
},
handleSelectionChange(val) {
console.log(val)
this.multipleSelection = val
},
delBatch() {
let ids = this.multipleSelection.map(v => v.id) // [{}, {}, {}] => [1,2,3]
this.request.post("/user/del/batch", ids).then(res => {
if (res.code === '200') {
this.$message.success("批量删除成功")
this.load()
} else {
this.$message.error("批量删除失败")
}
})
},
reset() {
this.username = ""
this.email = ""
this.address = ""
this.load()
},
handleSizeChange(pageSize) {
console.log(pageSize)
this.pageSize = pageSize
this.load()
},
handleCurrentChange(pageNum) {
console.log(pageNum)
this.pageNum = pageNum
this.load()
},
exp() {
window.open(`http://${serverIp}:9090/user/export`)
},
handleExcelImportSuccess() {
this.$message.success("导入成功")
this.load()
}
}
}
</script>
<style>
.headerBg {
background: #eee!important;
}
</style>
页面测试
通过前端页面添加Course路由
Course页面添加几门课程
Course页面进行学生选课
用户页面根据角色显示课程信息
更多推荐
已为社区贡献2条内容
所有评论(0)