Views: 0
逻辑
核心功能:
管理员可以查看所有专业列表(带分页)
能按专业名称搜索专业 可以新增/编辑/删除专业信息
每个专业必须绑定到一个学院(通过下拉框选择)
数据关系:
专业和学院是父子关系(一个学院有多个专业)
前端显示专业时会同时显示所属学院名称(而不是只显示学院ID)
操作流程:
点”新增” → 填专业名称 + 选择所属学院 → 保存 点”编辑” → 修改专业名称或调整所属学院 → 保存 点”删除” → 确认弹窗 → 真的删了
创建数据库
CREATE TABLE `speciality` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '专业名称',
`college_id` int DEFAULT NULL COMMENT '学院ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='专业信息';
entity—Speciality.java
package com.example.entity;
public class Speciality {
private Integer id;
private String name;
private Integer collegeId;
private String collegeName;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCollegeId() {
return collegeId;
}
public void setCollegeId(Integer collegeId) {
this.collegeId = collegeId;
}
public String getCollegeName() {
return collegeName;
}
public void setCollegeName(String collegeName) {
this.collegeName = collegeName;
}
}
前端
Manager.vue
<el-menu-item index="/speciality" v-if ="data.user.role === 'ADMIN'">
<el-icon><School /></el-icon>
<span>专业信息</span>
</el-menu-item>
index.js
配置路由
{ path: 'speciality', component: () => import('@/views/manager/Speciality.vue')},
Speciality.vue
<template>
<div>
<div class="card" style="margin-bottom: 5px;">
<el-input v-model="data.name" style="width: 300px; margin-right: 10px" placeholder="请输入专业名称查询"></el-input>
<el-button type="primary" @click="load">查询</el-button>
<el-button type="info" style="margin: 0 10px" @click="reset">重置</el-button>
</div>
<div class="card" style="margin-bottom: 5px">
<div style="margin-bottom: 10px">
<el-button type="primary" @click="handleAdd">新增</el-button>
</div>
<el-table :data="data.tableData" stripe>
<el-table-column label="专业名称" prop="name"></el-table-column>
<el-table-column label="所属学院" prop="collegeName"></el-table-column>
<el-table-column label="操作" align="center" width="160">
<template #default="scope">
<el-button type="primary" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="card">
<el-pagination background layout="prev, pager, next" v-model:page-size="data.pageSize" v-model:current-page="data.pageNum" :total="data.total"/>
</div>
<el-dialog title="专业信息" width="40%" v-model="data.formVisible" :close-on-click-modal="false" destroy-on-close>
<el-form :model="data.form" label-width="100px" style="padding-right: 50px">
<el-form-item label="专业名称" prop="name">
<el-input v-model="data.form.name" autocomplete="off" />
</el-form-item>
<el-form-item label="所属学院" prop="collegeId">
<!-- 专业信息是关联学院的,所以在新增(编辑)专业信息的时候,需要选择对应的学院,绑定起来。-->
<el-select v-model="data.form.collegeId" placeholder="请选择学院" style="width: 100%">
<el-option v-for="item in data.collegeDate"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
<!-- v-model="data.form.collegeId" 绑定专业信息的学院id-->
<!-- placeholder="请选择学院" 提示用户选择学院-->
<!-- style="width: 100%" 设置下拉框的宽度为100%-->
<!-- v-for="item in data.collegeDate" 遍历学院信息-->
<!-- :key="item.id" 设置每个学院的key为id-->
<!-- :label="item.name" 设置每个学院的label为name-->
<!-- :value="item.id" 设置每个学院的value为id-->
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="data.formVisible = false">取 消</el-button>
<el-button type="primary" @click="save">保 存</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import request from "@/utils/request";
import {reactive} from "vue";
import {ElMessageBox, ElMessage} from "element-plus";
const data = reactive({
pageNum: 1,
pageSize: 10,
total: 0,
formVisible: false,
form: {},
tableData: [],
name: null,
collegeDate: []// 用于存储学院信息
})
// 分页查询
const load = () => {
request.get('/speciality/selectPage', {
params: {
pageNum: data.pageNum,
pageSize: data.pageSize,
name: data.name
}
}).then(res => {
data.tableData = res.data?.list
data.total = res.data?.total
})
}
// 新增
const handleAdd = () => {
data.form = {}
data.formVisible = true
}
// 编辑
const handleEdit = (row) => {
data.form = JSON.parse(JSON.stringify(row))
data.formVisible = true
}
// 新增保存
const add = () => {
request.post('/speciality/add', data.form).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
data.formVisible = false
} else {
ElMessage.error(res.msg)
}
})
}
// 编辑保存
const update = () => {
request.put('/speciality/update', data.form).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
data.formVisible = false
} else {
ElMessage.error(res.msg)
}
})
}
// 弹窗保存
const save = () => {
// data.form有id就是更新,没有就是新增
data.form.id ? update() : add()
}
// 删除
const handleDelete = (id) => {
ElMessageBox.confirm('删除后数据无法恢复,您确定删除吗?', '删除确认', { type: 'warning' }).then(res => {
request.delete('/speciality/deleteById/' + id).then(res => {
if (res.code === '200') {
load()
ElMessage.success('操作成功')
} else {
ElMessage.error(res.msg)
}
})
}).catch(err => {})
}
// 重置
const reset = () => {
data.name = null
load()
}
const loadCollege= () => {//查询所有学院信息
request.get('/college/selectAll').then(res => {//调用后端接口查询所有学院信息
if (res.code === '200') {//如果查询成功,将查询到的学院信息赋值给data.collegeDate
data.collegeDate = res.data
}else {//如果查询失败,提示用户
ElMessage.error(res.msg)
}
})
}
load()
loadCollege()
</script>
Controller—SpecialityController.java
/**
* 专业信息模块前端操作接口入口
* 拿到数据后,调用service层的方法,返回结果
* 前端调用接口时,需要传入参数,调用service层的方法,返回结果
**/
@RestController
@RequestMapping("/speciality")
public class SpecialityController {
@Resource
// 注入SpecialityService
private SpecialityService specialityService;
/**
* 新增专业信息
* */
@PostMapping("/add")
public Result add(@RequestBody Speciality speciality){
specialityService.add(speciality);
return Result.success();
}
/**
* 更新专业信息
*/
@PutMapping("/update")//更新专业信息信息,前端调用接口时,需要传入参数,调用service层的方法,返回结果
public Result update(@RequestBody Speciality speciality){//接收前端传来的参数
specialityService.updateById(speciality);//调用service层的方法,返回结果
return Result.success();
}
/**
* 删除专业信息
*/
@DeleteMapping("/deleteById/{id}")
public Result deleteById(@PathVariable Integer id) {
specialityService.deleteById(id);
return Result.success();
}
/**
* 分页查询
* */
@GetMapping("selectPage")
public Result selectPage(Speciality speciality,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "5") Integer pageSize){
// 调用service层的方法,返回结果
PageInfo<Speciality> pageInfo = specialityService.selectPage(speciality,pageNum,pageSize);
// 总数
return Result.success(pageInfo);
}
/**
* 查询所有专业信息
*/
@GetMapping("/selectAll")
public Result selectAll(){
List<Speciality> list = specialityService.selectAll();
return Result.success(list);
}
}
SpecialityService.java
/**
* 专业模块业务逻辑接口
* 要把数据往数据库里存,调用mapper层的方法,返回结果
* 业务逻辑接口调用mapper层的方法,返回结果
*/
@Service
public class SpecialityService {
// 注入SpecialityMapper
@Resource
private SpecialityMapper specialityMapper;
/**
* 新增专业
*/
public void add(Speciality speciality) {
specialityMapper.insert(speciality);
}
/**
* 分页查询
*/
public PageInfo<Speciality> selectPage(Speciality speciality,Integer pageNum, Integer pageSize) {
// ToDo 分页查询逻辑处理
// 1. 分页查询专业信息
// 2. 返回专业信息
// 3. 如果没有专业信息,返回空列表
// 4. 如果有专业信息,返回专业信息列表
List<Speciality> list;//定义一个list集合
PageHelper.startPage(pageNum,pageSize);//分页查询
if(ObjectUtil.isNotEmpty(speciality.getName())){//如果name不为空,就查询name对应的专业信息
list = specialityMapper.selectByName(speciality.getName());
}else{//如果name为空,就查询所有专业信息
list = specialityMapper.selectAll();
}
return PageInfo.of(list);//返回专业信息列表
}
//根据id查询专业信息,返回一个speciality对象
public void updateById(Speciality speciality) {//传入一个speciality对象
specialityMapper.updateById(speciality);//调用mapper层的方法,返回结果
}
//根据id删除专业信息
public void deleteById(Integer id) {
specialityMapper.deleteById(id);
}
//查询所有专业信息
public List<Speciality> selectAll() {
return specialityMapper.selectAll();
}
}
Mapper
SpecialityMapper.java
Mapper
public interface SpecialityMapper {
//新增
void insert(Speciality speciality);
//查询所有
@Select("select speciality.*, college.name as collegeName from speciality left join college on speciality.college_id = college.id")
//查询所有专业信息,并且把专业信息对应的学院名称也查询出来
//left join college on speciality.college_id = college.id
List<Speciality> selectAll();
//根据name查询
@Select("select speciality.*, college.name as collegeName from speciality " +
"left join college on speciality.college_id = college.id " +
"where speciality.name like concat('%',#{name},'%')")
//查询所有专业信息,并且把专业信息对应的学院名称也查询出来
List<Speciality> selectByName(String name);
//修改
void updateById(Speciality speciality);
//删除
@Delete("delete from speciality where id = #{id}")
void deleteById(Integer id);
}
SpecialityMapper.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.example.mapper.SpecialityMapper">
<insert id="insert" parameterType="com.example.entity.Speciality" useGeneratedKeys="true">
insert into speciality (name, college_id)
values (#{name}, #{collegeId})
</insert>
<update id="updateById" parameterType="com.example.entity.Speciality">
update speciality
set name = #{name}, college_id = #{collegeId}
where id = #{id}
-- 这里的id是实体类中的属性名,不是数据库中的字段名
</update>
</mapper>
如果后面遇到这种什么字段缺少getter/setter方法,除了去这个实体类里面排查一下之外,记住还有一个地方可能出现问题:xxxMapper.xml
当这个字段是有下划线的时候,要注意:获取它的值的变量要是驼峰。
vue :https://element-plus.org/zh-CN/
当你在页面操作的时候,没有反应,怎么办??怎么去排查??
- 按F12打开前台页面控制台,看一下前端有没有报错?
- 看一下网络请求,接口有没有调用或者参数有没有传对,如果不对,那在前端检查一下参数的传递;如果对了,那就检查一下后端有没有报错,或者有没有其他问题
- 检查后端控制台信息,如果报错了,找到报错的地方,断点看一下;如果没有报错,必须要debug跟一下了,看看每一步的数据对不对。
有个关联查询很重要!!!
ambiguous:模棱两可的