【学生选课管理系统】项目笔记

项目难点

涉及到多个关联的数据库

脚手架

在这里我使用的是element-plus框架👉
具体文献参考-> element-plus官网

  • 运行项目(同时运行前端和后端)

    1. program/xsxk/vue/package.json
    2. program/xsxk/springboot/src/main/java/com/example/SpringbootApplication.java
  • 在该脚手架中,加入了自定义异常检查 exception

遇到文件夹名称全红解决方案

IDEA中,如果项目目录显示红色,主要是有版本控制所导致的,解决办法就是------解除版本控制。

  1. 🔺打开 → File->setting->目录映射->VCS->null

一定要注意拼写拼写拼写

批注:formVisible 和 fromVisible

SpringBoot启动失败Application run failed的解决办法

★这个问题得具体问题具体分析,得看下面那些报错什么意思,不能直接去网上找解决办法,查阅好多博主写的文章都没解决,大致出现问题的原因如下:

  1. 注解问题:

    Controller、service层的注解缺失会造成创建bean时出现错误。

    @Controller@Service

  2. 依赖包缺失,检查pom配置文件

    检查pom.xml文件下是否缺失依赖或者有多余的依赖,判断是否对bean的正常创建有影响。

  3. xml包中存在空文件:

    在 XML格式声明中的编码伪属性前面必须有空格

  4. 报错信息:Error parsing Mapper XML. The XML location is 'file [D:\gitee\self_development\program\xsxk\springboot\target\classes\mapper\StudentMapper.xml]'. Cause: org.apache.ibatis.builder.BuilderException: An invalid property 'score' was found in mapping #{collegeId, score = #{score}. Valid properties are javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName

  • An invalid property -- 不合法属性

🔺在解决以上问题之后发现仍然不能运行,所以我就采取最原始的办法,将之前运行成功后写的那些文件一一删除,然后重新写一份,排除错误的代码,然后成功解决🎇(泪目)
真的是实在没有办法了,重写了一份,也不知道哪里有改动,反正就是没出错了 :(

  • 综上所述:还得是要养成一边写代码一边运行的习惯才行,然后记得备注和检查错别字😭

tableDate 和 tableData 找不同

  • 在网页上面显示请求成功,说明已经连接上数据库,但是依旧显示不出教师信息,说明是前端有问题,于是我反过来检查代码,嘿?你猜这么着,拼写错误!😊

⭐嘻嘻,注意不要犯低级错误喔~

405报错

一般是因为请求函数报错,经常是因为请求接口对不上缘故,多检查一下

error: "Method Not Allowed"
path: "/teacher/update"
status: 405
timestamp: "2024-11-05T02:58:22.373+00:00"
  • GET / PUT / POST / DELETE

404报错

  • 接口UI有问题

图片上传失败

添加教师图片,明明已经显示avatar已经修改完成,但是怎么也上传不到数据库,我刚开始以为可能出错有以下几点:

  1. 前端没写好,对接不上
  2. FileController文档
  3. 接口

⚪然而无论我怎么检查代码完全都没有问题时候,灵光一闪,我教师类的avatar是不是没有写好。

🔺嘻嘻,果不其然,没有写getAvatar函数

  • 明明很简答的问题又耽搁很久时间,所以说细心细心再细心,不过能想到教师类的我简直就是天才。日常辛苦我自己了:)

请求错误

  1. 数据库申请代码报错

Cannot read properties of undefined (reading 'sex')

遇到这种报错,基本上是遇到了 xxx.sex,比如form.sex,如果这个xxx(form)是undefined,那么就会出现这样的报错。

点击没反应排查方法

  1. F12查看网络请求,接口和参数有无问题
  2. 后台是否报错
  3. 打断点判断出问题具体环节

user.role,

  • 那么如果这个user是个undefined(未被定义)的时候,再去访问这个user里面的某个属性变量的时候,就会报这种错误。

针对管理员和学生无法看到课程信息bug

  1. 导致teachid可以被三个角色定义,其他角色也调用到teacher的if语句中

  2. 由于教师数据库没有其他角色信息

  3. 故查询不到课程

java 复制代码
// 分页查询
const load = () => {
  let teacherId= null
  if(data.user.role === 'TEACHER') {
    teacherId = data.user.id
  }
  request.get('/course/selectPage', {
    params: {
      pageNum: data.pageNum,
      pageSize: data.pageSize,
      name: data.name,
      teacherId: teacherId  //误写成 data.user.id 
    }
  }).then(res => {
    data.tableData = res.data?.list
    data.total = res.data?.total
  })
}

遗忘知识点

  • type="primary" 表示这个按钮是"主要"按钮,通常用来表示主要操作或强调重要功能。例如,在一个表单中,"提交"按钮通常会被设置为主要按钮,以引起用户的注意。

在 Element UI 中,常见的按钮类型还有:

  • default: 默认按钮
  • success: 成功按钮
  • warning: 警告按钮
  • danger: 危险按钮
  • info: 信息按钮

  • el-form-item:是Element UI库中用来包裹表单项的组件。在表单里,每个表单项都放在el-form-item里,不仅能让布局更整齐,还能给这些项添加标签和做验证

el-form就是整个表单,而el-form-item就是里面的每一个小格子啦。每个el-form-item都可以有个label属性来显示标签,比如"用户名"、"密码"这些。然后里面就可以放各种输入框啦,像el-inputel-select这些。


  • autocomplete="off" -- 用来关闭浏览器的自动填充功能的。

在JavaScript或TypeScript项目中,import 语句用于导入模块。你提到的两种导入方式主要区别在于路径的不同,这会影响代码如何解析和加载相应的模块。

  1. 绝对路径 vs 相对路径

    • import request from "@/utils/request"; 使用了绝对路径(也称为别名路径)。这种路径通常由构建工具(如Webpack)配置的别名来解析。例如,@/ 可能被配置为项目的根目录。
    • import request from "../../utils/request"; 使用的是相对路径,从当前文件的位置向上两级目录找到 utils/request 模块。
  2. 依赖解析

    • 绝对路径:如果使用绝对路径,你需要确保构建工具已经正确配置了这些路径别名,否则会导致模块找不到的问题。
    • 相对路径:相对路径依赖于文件的物理位置,因此在不同的文件结构中可能需要调整路径。
  3. 可维护性

    • 绝对路径:使用绝对路径可以使你的模块导入更加简洁和一致,特别是在大型项目中,可以减少路径深度带来的复杂性。
    • 相对路径:相对路径更直观地反映了文件之间的层级关系,但在项目结构调整时可能需要频繁修改。

示例

  • **import request from "@/utils/request";**和
  • **import request from ".../.../utils/request";**的区别

假设项目结构如下:

project-root/
│
├── src/
│   ├── components/
│   │   └── MyComponent.vue
│   ├── utils/
│   │   └── request.js
│
└── webpack.config.js
Webpack配置(webpack.config.js)
javascript 复制代码
const path = require('path');

module.exports = {
  // ...其他配置...
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  }
};
使用绝对路径

MyComponent.vue 中:

javascript 复制代码
import request from '@/utils/request';
使用相对路径

MyComponent.vue 中:

javascript 复制代码
import request from '../../utils/request';

总结

选择哪种方式取决于项目需求和团队约定。如果项目使用构建工具并且已经配置了路径别名,那么使用绝对路径会更加方便和一致。如果不使用构建工具或者项目较小,相对路径可能会更直接一些。


  • ElMessage.success('操作成功')

这个涉及到的知识点有:

  1. Element UI框架ElMessage.success('操作成功') 是 Element UI 框架中的一个方法,用于显示一个成功的提示信息。在使用该方法前,需要先引入 Element UI 框架。
  2. 字符串模板语法 :如果你想要在 ElMessage.success 中加入变量,可以使用 ES6 的字符串模板语法,例如:const name = "John"; ElMessage.success(Hello, ${name}!);。这样,变量 name 的值就会被插入到字符串中,输出的结果类似于:Hello, John!。你也可以使用拼接字符串的方式,例如:const name = "John"; ElMessage.success("Hello, " + name + "!");
  3. 全局重写 :对于 Vue.js 3,你可以通过在 main.js 文件中全局重写 app.config.globalProperties 来修改 ElMessage.success 的行为。
  4. 组件VNode的生成:无论组件嵌套多深,只要在 Vue.component 中定义全局组件,这些构造函数都会被添加到组件的原型链上。生成的文本和 my-button 组件的 VNode 会一起作为最终 #app VNode 的组成部分。
  5. Scope(作用域)和组件间通信:通过 scope 标签和自定义事件传递数据,推荐使用全局事件总线进行组件间的复杂通信。
  6. 组件定义位置:全局组件的定义应放在 Vue 实例创建之前,因为 Vue 实例在初始化时需要先知道所有的组件信息才能正确挂载。
  7. 确认操作:在用户执行一些重要的操作时,为了防止误操作,可以使用弹窗组件来进行二次确认。

  • placeholder
    它就是input和textarea标签的一个属性,用来在文本框内啥都没输入的时候显示灰色的提示文字。这样用户就知道该填啥啦!不过啊,placeholder属性还没被CSS标准收进去哦。不同浏览器得用不同的伪元素来改它的样式
  1. 比如Chrome、Edge这些就用 ::webkit-input-placeholder
  2. Firefox用的是 ::-moz-placeholder

  • @RequestParam和@RequestBody
JavaScript 复制代码
public Result selectPage(@RequestParam(defaultValue = "1") Integer pageNum,
                         @RequestParam(defaultValue = "5") Integer pageSize) {

这段代码是一个Java方法的声明,通常用于Spring框架中的控制器类(Controller)。这个方法名为selectPage,它接受两个参数:pageNumpageSize,并返回一个Result对象。

知识点解释

  1. Spring MVC:

    • Spring MVC是Spring框架的一部分,用于构建Web应用程序。它使用控制器来处理HTTP请求,并将请求映射到相应的处理方法上。
  2. @RequestParam:

    • @RequestParam注解用于将HTTP请求参数绑定到控制器方法的参数上。
    • defaultValue属性指定了当请求中没有提供相应参数时使用的默认值。例如,如果请求中没有提供pageNum参数,那么它的默认值将是1;如果没有提供pageSize参数,那么它的默认值将是5。
  3. 分页查询:

    • 分页查询是一种常见的数据库操作,用于在大量数据中分批获取数据。pageNum表示当前页码,pageSize表示每页显示的数据条数。
  4. Result:

    • Result是一个自定义的返回类型,通常用于封装API的响应结果。它可以包含状态码、消息以及实际的数据内容。

@RequestParam 和 @RequestBody 的区别

  • @RequestParam:

    • 用于从URL请求参数中获取数据。

    • 适用于GET请求或POST请求中的表单数据。

    • 示例:

      java 复制代码
      @GetMapping("/example")
      public String example(@RequestParam String name) {
          return "Hello, " + name;
      }
  • @RequestBody:

    • 用于从HTTP请求体中获取数据,通常用于POST请求。

    • 适用于接收JSON、XML等格式的数据,并将其转换为Java对象。

    • 示例:

      java 复制代码
      @PostMapping("/example")
      public String example(@RequestBody User user) {
          return "User created: " + user.getName();
      }

总结

这段代码定义了一个分页查询的方法,通过@RequestParam注解从请求中获取分页参数,并返回一个封装了查询结果的Result对象。@RequestParam@RequestBody的主要区别在于它们获取数据的方式不同,前者从URL参数中获取数据,后者从请求体中获取数据。


  • < el-table-column label="职称" prop="title">< /el-table-column>中的prop是什么意思

在 Vue.js 框架中,el-table-column 是 Element UI 库中的一个组件,用于定义表格的列。prop 属性在这个上下文中表示该列对应的数据对象中的字段名。

具体来说,当你使用 el-table-column 时,你通常会将一个数组的数据传递给 el-table 组件,这个数组中的每个对象代表一行数据。prop 属性的值就是这些对象中的属性名,它告诉 el-table-column 应该从每行数据对象中提取哪个属性来显示在表格的这一列中。

例如:

html 复制代码
<el-table :data="tableData">
  <el-table-column label="姓名" prop="name"></el-table-column>
  <el-table-column label="年龄" prop="age"></el-table-column>
  <el-table-column label="职称" prop="title"></el-table-column>
</el-table>

假设 tableData 是这样的:

javascript 复制代码
[
  { name: '张三', age: 25, title: '工程师' },
  { name: '李四', age: 30, title: '经理' }
]

那么,el-table-columnlabel 属性会显示为 "职称",而 prop 属性会告诉表格从每个对象中提取 title 属性的值来填充这一列。因此,表格中第三列会显示 "工程师" 和 "经理"。


  • data.form = JSON.parse(JSON.stringify(row))
    这个代码片段是JavaScript中的一种深拷贝操作,涉及的知识点包括JSON对象、字符串和JavaScript对象的转换。具体来说,它使用了JSON.parse()JSON.stringify()两个方法来实现对象的深拷贝。

详细解释:

  1. JSON.stringify(row):

    • JSON.stringify() 是一个JavaScript内置的方法,用于将JavaScript对象转换为一个JSON格式的字符串。
    • 在这个例子中,它将变量row(假设它是一个对象)转换为一个JSON字符串。
  2. JSON.parse(...):

    • JSON.parse() 是另一个JavaScript内置的方法,用于将JSON格式的字符串解析成JavaScript对象。
    • 这里,它将之前通过JSON.stringify(row)得到的JSON字符串重新解析回一个新的JavaScript对象。

整体作用:

data.form = JSON.parse(JSON.stringify(row)) 这行代码的作用是将row对象进行深拷贝,并将结果赋值给data.form。深拷贝意味着新的对象与原对象之间没有引用关系,修改新对象不会影响到原对象。

涉及的知识点:

  • JSON (JavaScript Object Notation): 一种轻量级的数据交换格式。
  • JSON.stringify(): 将JavaScript对象转换为JSON字符串。
  • JSON.parse(): 将JSON字符串转换为JavaScript对象。
  • 深拷贝 vs 浅拷贝 :
    • 浅拷贝: 只复制对象的引用,不复制对象的内容。
    • 深拷贝: 完全复制对象及其子对象的内容,使得新旧对象之间互不影响。

示例代码:

javascript 复制代码
let row = {
    name: "Alice",
    age: 30,
    address: {
        city: "Wonderland",
        zipCode: "12345"
    }
};

let data = {};
data.form = JSON.parse(JSON.stringify(row));

console.log(data.form); // 输出:{ name: "Alice", age: 30, address: { city: "Wonderland", zipCode: "12345" } }

在这个例子中,data.formrow的一个深拷贝,对data.form的任何修改都不会影响到row

相关推荐
冷眼看人间恩怨31 分钟前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
Hejjon6 小时前
SpringBoot 整合 SQLite 数据库
笔记
西洼工作室8 小时前
【java 正则表达式 笔记】
java·笔记·正则表达式
初学者7.9 小时前
Webpack学习笔记(2)
笔记·学习·webpack
新手上路狂踩坑10 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
stm 学习ing11 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl
尘觉11 小时前
算法的学习笔记—扑克牌顺子(牛客JZ61)
数据结构·笔记·学习·算法
bohu8312 小时前
sentinel学习笔记1-为什么需要服务降级
笔记·学习·sentinel·滑动窗口
初学者7.13 小时前
Webpack学习笔记(3)
笔记·学习·webpack
bohu8314 小时前
sentinel学习笔记5-资源指标数据统计
笔记·sentinel·statisticslot