SpringBoot3+Vue3实战(Vue3快速开发登录注册页面并对接后端接口、表单项自定义校验规则、Hutool工具类)(4)
目录
一、SpringBoot3+Vue3实现基本增删改查。前后端通信交互、配置后端跨域请求。数据批量删除。(博客链接)
二、SpringBoot3+Vue3快速开发登录、注册页面并实现对接。
(1)操作数据表employee(员工信息表)。
<1>修改employee表的字段组成。
<2>填补对应数据库数据。
(2)修改Employee实体类。
<1>新增对应成员属性。
<2>新增对应getter、setter方法。
<3>修改之前的toString()方法。
(3)修改mapper层代码。
<1>修改新增SQL。
<2>修改更新SQL。
<3>EmployeeMapper接口代码示例。
(4)员工信息(Employee.vue)页面。
<1>前端代码示例。
<2>员工信息的页面渲染效果。
<3>对话框—新增—某些字段设为必填项。(表单校验)
表单标签(el-form)添加ref。
保存按钮绑定事件函数save中触发校验。
表单标签(el-form)绑定校验规则。(:rules)
针对username设置校验规则。(required、message、trigger)
在对话框的对应需校验表单项添加prop属性。
给名称(name)、工号(no)也绑定校验“必填项”。
关闭对话框销毁旧对话框对象。(属性destroy-on-close)
(5)新建登录页面。(Login.vue)
<1>登录页面基本框架。
配置路由。(不是嵌套子路由)
导航栏—退出登录。(index)
<2>登录页面代码示例。
前端登录页面渲染效果图示。
表单项(username、password)校验。(属性ref、:rules)
表单项对应规则。(属性prop)
表单项校验效果图示。(鼠标未输入、且失焦)
登录绑定login函数。(若校验成功—>post请求后端接口"/login")
(6)后端代码编写。(登录功能)
<1>controller层登录接口。
<2>service层的登录业务编写。
自定义异常。(CustomerException)
封装返回前端数据结果类。(Result)
全局异常捕获处理器。(GlobalExceptionHandler)
前端处理请求(request)和响应(response)的工具类。
配置前后端跨域配置类。
service层登录逻辑代码示例。
<3>mapper层SQL。
<4>登录页面进行登录操作图示。
<5>获取后端返回的员工对象。(实时渲染右上角用户名称)
存储用户信息。(localStorage.setItem(xxx))
主页面(Manager.vue)获取登录时存储的用户信息。
(7)新建注册页面。(Register.vue)
<1>复制粘贴(Login.vue)并稍加修改。
基本框架。
配置路由。
<2>密码与二次确认密码的自定义校验。(:rules、ref、prop)
官方操作演示。(element-plus)
根据官方演示手动实现。(代码示例)
表单项校验的页面渲染效果。
(8)后端代码编写。(注册功能)
<1>controller层注册接口。
<2>service层的注册业务编写。
引入Hutool工具类插件依赖。
add()方法修改与完善。
register方法。
<3>mapper层。(接口与SQL映射文件)
<4>注册页面进行注册、登录操作图示。
一、SpringBoot3+Vue3实现基本增删改查。前后端通信交互、配置后端跨域请求。数据批量删除。(博客链接)
- SpringBoot3实战(SpringBoot3+Vue3基本增删改查、前后端通信交互、配置后端跨域请求、数据批量删除(超详细))(3)-CSDN博客
- 注意:关于本篇博客的案例《员工信息的前端页面代码、后端接口(controller)、service、mapper层代码》基本都在上面那篇博客中已实现。需要的可以自取。
- 这篇博客的主要内容:学习《使用Vue3快速开发登录、注册页面并对接后台》。前端Vue页面与后端SpringBoot服务器进行对接。实现员工登录或注册进入系统的功能。
二、SpringBoot3+Vue3快速开发登录、注册页面并实现对接。
(1)操作数据表employee(员工信息表)。
<1>修改employee表的字段组成。
- employee表字段原组成。
- 添加3个字段:用户名(username)、密码(password)、角色(role)。
<2>填补对应数据库数据。
(2)修改Employee实体类。
<1>新增对应成员属性。
package com.hyl.entity;public class Employee {private Integer id;private String username;private String password;private String role;private String name;private String sex;private String no;private Integer age;private String description;//数据库字段:department_id (下划线命名)//实体类属性:departmentId (驼峰命名)private Integer departmentId; }
<2>新增对应getter、setter方法。
public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}
<3>修改之前的toString()方法。
//toString方法@Overridepublic String toString() {return "Employee{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", role='" + role + '\'' +", name='" + name + '\'' +", sex='" + sex + '\'' +", no='" + no + '\'' +", age=" + age +", description='" + description + '\'' +", departmentId=" + departmentId +'}';}
(3)修改mapper层代码。
<1>修改新增SQL。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hyl.mapper.EmployeeMapper"><insert id="insert" parameterType="com.hyl.entity.Employee">insert into `employee`(username,password,role,name,sex,no,age,description,department_id)values (#{username},#{password},#{role},#{name},#{sex},#{no},#{age},#{description},#{departmentId})</insert></mapper>
<2>修改更新SQL。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hyl.mapper.EmployeeMapper"><update id="updateById" parameterType="com.hyl.entity.Employee">update `employee` set username = #{username},password = #{password},role = #{role}, name = #{name},sex=#{sex},no=#{no},age=#{age},description=#{description},department_id=#{departmentId}where id = #{id}</update></mapper>
<3>EmployeeMapper接口代码示例。
package com.hyl.mapper;import com.hyl.entity.Employee; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Select;import java.util.List;public interface EmployeeMapper {//通过注解形式完成SQL语句的查询//简单SQL可以直接使用注解形式。动态SQL最好使用XML文件形式@Select("select * from `employee` where id = #{id}")Employee selectById(Integer id);List<Employee> selectAll(Employee employee);void insert(Employee employee);void updateById(Employee employee);@Delete("delete from `employee` where id = #{id}")void deleteById(Integer id); }
(4)员工信息(Employee.vue)页面。
<1>前端代码示例。
<el-table-column label="用户名" prop="username"/>
<el-table-column label="角色" prop="role"><template #default="scope"><span v-if="scope.row.role === 'EMP'">员工</span></template> </el-table-column>
<2>员工信息的页面渲染效果。
- 一般员工信息页面只会显示用户名、角色。而密码将不会直接显示。
<3>对话框—新增—某些字段设为必填项。(表单校验)
<el-form-item label="用户名"><el-input v-model="data.form.name" autocomplete="off" placeholder="请输入用户名"/> </el-form-item>
表单标签(el-form)添加ref。
<el-form ref="formRef" :model="data.form" label-width="80px" style="padding-right: 50px;padding-top: 20px">
import {reactive,ref} from "vue";const formRef = ref();
保存按钮绑定事件函数save中触发校验。
//对话框的保存按钮事件 const save = () =>{formRef.value.validate((valid)=>{//通过校验才能点击更新或新增的保存操作if(valid){//有id进行更新操作。无id进行新增操作data.form.id ? update() : add()}}) }
表单标签(el-form)绑定校验规则。(:rules)
<el-form ref="formRef" :rules="data.rules" :model="data.form" label-width="80px" style="padding-right: 50px;padding-top: 20px">
针对username设置校验规则。(required、message、trigger)
- 设置了required为true表示该字段必填。message是当未满足必填条件时显示的提示信息 “请输入用户名” 。trigger为blur表示在输入框失去焦点时触发验证。
import {reactive,ref} from "vue";const formRef = ref();const data = reactive({rules:{username:[{ required:true , message: '请输入用户名' , trigger:'blur'}]} })
在对话框的对应需校验表单项添加prop属性。
<el-form-item label="用户名" prop="username"><el-input v-model="data.form.username" autocomplete="off" placeholder="请输入用户名"/> </el-form-item>
给名称(name)、工号(no)也绑定校验“必填项”。
<el-form-item label="名称" prop="name"><el-input v-model="data.form.name" autocomplete="off" placeholder="请输入名称"/> </el-form-item><el-form-item label="工号" prop="no"><el-input v-model="data.form.no" autocomplete="off" placeholder="请输入工号"/> </el-form-item>
import {reactive,ref} from "vue";const data = reactive({rules:{username:[{ required:true , message: '请输入用户名' , trigger:'blur'}],name:[{ required:true , message: '请输入名称' , trigger:'blur'}],no:[{ required:true , message: '请输入工号' , trigger:'blur'}]} })
- 页面渲染效果。
关闭对话框销毁旧对话框对象。(属性destroy-on-close)
<el-dialog title="员工信息" v-model="data.formVisible" width="500" destroy-on-close><el-form ref="formRef" :rules="data.rules" :model="data.form" label-width="80px" style="padding-right: 50px;padding-top: 20px"><el-form-item label="用户名" prop="username"><el-input v-model="data.form.username" autocomplete="off" placeholder="请输入用户名"/></el-form-item><el-form-item label="名称" prop="name"><el-input v-model="data.form.name" autocomplete="off" placeholder="请输入名称"/></el-form-item><el-form-item label="性别"><el-radio-group v-model="data.form.sex"><el-radio value="男">男</el-radio><el-radio value="女">女</el-radio></el-radio-group></el-form-item><el-form-item label="工号" prop="no"><el-input v-model="data.form.no" autocomplete="off" placeholder="请输入工号"/></el-form-item><!-- 设置最小年龄18 最大年龄100 --><el-form-item label="年龄"><el-input-number v-model="data.form.age" :min="18" :max="100" style="width: 250px" autocomplete="off" placeholder="年龄>=18与年龄<=100"/></el-form-item><!-- 设置类型:文本域 :rows设置默认显示三行 --><el-form-item label="个人简介"><el-input type="textarea" :rows="3" v-model="data.form.description" autocomplete="off" placeholder="请输入个人简介"/></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="data.formVisible = false">取消</el-button><el-button type="primary" @click="save">保存</el-button></div></template> </el-dialog>
- 这样点击“取消”关闭某次对话框时,下次新对话框就不会存留着上次的校验失败提示。
(5)新建登录页面。(Login.vue)
<1>登录页面基本框架。
配置路由。(不是嵌套子路由)
导航栏—退出登录。(index)
<2>登录页面代码示例。
<template><div><div class="login-container"> <!-- 登录表单容器 --><div class="login-box"><div style="padding: 40px 30px;background-color: #fbfcf8;margin-left: 200px;border-radius: 5px"><div style="margin-bottom: 30px;font-weight: bold;font-size: 24px;color: #514343;text-align: center" >欢迎登录hyl信息管理系统</div><el-form ref="formRef" :model="data.form" style="width: 350px"><el-form-item><el-input v-model="data.form.username" placeholder="请输入用户名" prefix-icon="User"></el-input></el-form-item><el-form-item><el-input v-model="data.form.password" placeholder="请输入密码" prefix-icon="Lock" show-password></el-input></el-form-item><div style="margin-top: 20px;margin-bottom: 20px"><el-button size="large" style="width: 100%;" type="primary">登 录</el-button></div><div style="margin-bottom: 20px"><el-button size="large" style="width: 100%;" type="primary">注 册</el-button></div><!-- 可以使用text-decoration:none 让链接不显示下划线 --><div style="text-align: right">没有账号?请 <a style="color: #1967e3;" href="/register">注册</a></div></el-form></div></div></div></div> </template><script setup>import {reactive} from "vue";const data = reactive({form:{}, })</script><style scoped> .login-container {/*占满可视高度*/height: 100vh;/*隐藏超出高度*/overflow: hidden;/*背景图*/background-image: url("@/assets/bimage2.jpeg");/*背景图片大小*/background-size: cover;/*设置背景图移动*/background-position: -450px -120px; }.login-box {/*绝对定位*/position: absolute;width: 50%;height: 100vh;/*靠右*/right: 0;/*flex布局*/display: flex;align-items: center;background-color: #f1ebe2; }</style>
前端登录页面渲染效果图示。
表单项(username、password)校验。(属性ref、:rules)
<el-form ref="formRef" :rules="data.rules" :model="data.form" style="width: 350px">
import {reactive,ref} from "vue";const formRef = ref()const data = reactive({form:{},rules:{username :[{ required: true ,message:'请输入用户名',trigger:'blur'}],password :[{ required: true ,message:'请输入密码',trigger:'blur'}],}, })
表单项对应规则。(属性prop)
<el-form-item prop="username"><el-input v-model="data.form.username" placeholder="请输入用户名" prefix-icon="User"></el-input> </el-form-item><el-form-item prop="password"><el-input v-model="data.form.password" placeholder="请输入密码" prefix-icon="Lock" show-password></el-input> </el-form-item>
表单项校验效果图示。(鼠标未输入、且失焦)
登录绑定login函数。(若校验成功—>post请求后端接口"/login")
<div style="margin-top: 20px;margin-bottom: 20px"><el-button size="large" style="width: 100%;" type="primary" @click="login">登 录</el-button> </div>
import {reactive,ref} from "vue"; import request from "@/utils/request.js"; import {ElMessage} from "element-plus";const formRef = ref()//登录按钮操作方法 const login = () =>{//开始校验formRef.value.validate((valid)=>{if(valid){//表单项(字段)验证通过request.post("/login",data.form).then(res=>{if(res.code === '200'){ //登录成功ElMessage.success('登录成功')//登录成功后,跳转主页。等500ms进行跳转setTimeout(()=>{location.href = '/manager/home'},500)}else { //登录失败ElMessage.error(res.msg)}})}}) }
(6)后端代码编写。(登录功能)
<1>controller层登录接口。
package com.hyl.controller;import com.hyl.common.Result; import com.hyl.entity.Employee;import com.hyl.service.EmployeeService; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController;//表示对外提供可访问接口的类 @RestController public class WebController {@Resourceprivate EmployeeService employeeService;//测试接口(不必理会)@GetMapping("/hello")public Result hello(){return Result.success("hello");}//登录接口//返回登录成功后的员工对象通过@RestController响应成JSON对象给前端//前端(res.data)再将JSON对象转换成JSON字符串临时存储用户信息@PostMapping("/login")public Result login(@RequestBody Employee employee){Employee dbEmployee = employeeService.login(employee);return Result.success(dbEmployee);}}
<2>service层的登录业务编写。
自定义异常。(CustomerException)
package com.hyl.exception;public class CustomerException extends RuntimeException{private String code;private String msg;public CustomerException(String code, String msg) {this.code = code;this.msg = msg;}//getter|setter方法public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;} }
封装返回前端数据结果类。(Result)
package com.hyl.common;/*** 统一后端返回的数据结果类型*/ public class Result {//请求状态码private String code;//成功或错误信息private String msg;//返回数据结果private Object data;//常用静态方法//请求成功且无数据返回public static Result success(){Result result = new Result();result.setCode("200");result.setMsg("请求成功");return result;}//请求成功且有数据返回。public static Result success(Object data) {//直接调用静态方法设置状态码、请求成功信息Result result = Result.success();result.setData(data);return result;}//请求失败且无数据返回public static Result error(){Result result = new Result();result.setCode("500");result.setMsg("系统出错了!");return result;}//请求失败且无数据返回。适配自定义异常(传递code、msg)public static Result error(String code,String msg){Result result = new Result();result.setCode(code);result.setMsg(msg);return result;}//getter、setter方法public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;} }
全局异常捕获处理器。(GlobalExceptionHandler)
package com.hyl.exception;import com.hyl.common.Result; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody;//标识全局异常处理器并设置捕获路径 //因为异常产生最终都会归宿到controller中,所有异常统一在controller包中接口中处理。 @ControllerAdvice("com.hyl.controller") public class GlobalExceptionHandler {@ExceptionHandler(Exception.class) //捕获所有系统异常@ResponseBody//返回json串public Result error(Exception e) {//更清晰看到后端控制台报的错误e.printStackTrace();//返回Result的error()方法设置的错误信息(code、msg)给前端return Result.error();}@ExceptionHandler(CustomerException.class) //捕获自定义异常@ResponseBody//返回json串public Result error(CustomerException e) { //自定义异常的参数code、msg//更清晰看到后端控制台报的错误e.printStackTrace();//Result的error(String code,String Msg)方法设置获取到的错误信息(code、msg)return Result.error(e.getCode(),e.getMsg());}}
前端处理请求(request)和响应(response)的工具类。
import { ElMessage } from 'element-plus' import axios from "axios";const request = axios.create({//设置后台请求地址baseURL: 'http://localhost:9090',timeout: 30000 // 后台接口超时时间设置 })// request 拦截器(数据请求) // 可以自请求发送前对请求做一些处理 request.interceptors.request.use(config => {//设置统一的数据传输格式json、数据传输编码utf-8config.headers['Content-Type'] = 'application/json;charset=utf-8';return config }, error => {return Promise.reject(error) });// response 拦截器 // 可以在接口响应后统一处理结果 request.interceptors.response.use(response => {//响应对象response中提取实际数据部分,存储在变量res中let res = response.data;// 兼容服务端返回的字符串数据//如果res是字符串且不为空字符串,则使用JSON.parse方法将其解析为JavaScript对象;//如果 res 为空字符串,则保持原样。if (typeof res === 'string') {res = res ? JSON.parse(res) : res}return res;},error => {if(error.response.status === 404){//404 状态码表示请求的资源未找到,通常意味着请求的接口不存在ElMessage.error('未找到请求接口')}else if(error.response.status === 500){//500:之前后端设置的全局系统异常处理捕获//500 状态码表示服务器内部错误,通常是由于后端代码出现异常ElMessage.error('系统异常,请查看后端控制台报错')}else{//其它情况统一打印错误信息console.error(error.message)}//将错误继续抛出,以便后续的代码可以继续处理该错误return Promise.reject(error)} )export default request
配置前后端跨域配置类。
package com.hyl.common;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter;/*** 跨域配置类。用于解决前端和后端由于不同源(协议、域名、端口不同)导致的跨域请求问题* @Configuration 让该配置类注入到Spring容器中并能够扫描到其下类下注解*/ @Configuration public class CorsConfig {/*** 创建并注册CorsFilter bean,用于处理跨域请求* @return CorsFilter实例,Spring会在请求处理过程中使用该过滤器处理跨域请求* @Bean 注解会让该方法的返回值注入到Spring容器中*/@Beanpublic CorsFilter corsFilter() {// 创建一个基于URL的跨域配置源对象,用于存储和管理不同URL路径的跨域配置UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();// 创建一个跨域配置对象,用于设置具体的跨域规则CorsConfiguration corsConfiguration = new CorsConfiguration();// 设置允许访问的源地址,这里使用通配符"*",表示允许所有源地址访问corsConfiguration.addAllowedOrigin("*");// 设置允许的请求头,"*"表示允许所有请求头,即前端可以在请求中携带任意请求头corsConfiguration.addAllowedHeader("*");// 设置允许的请求方法,"*"表示允许所有的HTTP请求方法,如GET、POST、PUT、DELETE等corsConfiguration.addAllowedMethod("*");// 将跨域配置应用到所有的接口路径上,"/**"表示匹配所有路径source.registerCorsConfiguration("/**", corsConfiguration);// 创建并返回CorsFilter实例,传入配置源对象,Spring会使用该过滤器处理跨域请求return new CorsFilter(source);} }
service层登录逻辑代码示例。
public Employee login(Employee employee){//用户名String username = employee.getUsername();//先查询数据库中是否有该用户名Employee dbEmployee = employeeMapper.selectByUserName(username);if(Objects.isNull(dbEmployee)){ //未查询到用户//返回自定义异常。交给全局异常捕获器处理//将错误状态码返回前端,前端捕获返回的res.code。提示登录失败与错误信息:用户不存在throw new CustomerException("500","用户不存在");}//用户存在//判断密码是否正确String password = employee.getPassword();if(!dbEmployee.getPassword().equals(password)){//用户输入的密码与数据库的密码不匹配//返回自定义异常。交给全局异常捕获器处理//将错误状态码返回前端,前端捕获返回的res.code。提示登录失败与错误信息:账号或密码错误throw new CustomerException("500","账号或密码错误");}//所有逻辑判断没有问题,返回数据库的Employee对象return dbEmployee;}
<3>mapper层SQL。
@Select("select * from `employee` where username = #{username}")Employee selectByUserName(String username);
<4>登录页面进行登录操作图示。
<5>获取后端返回的员工对象。(实时渲染右上角用户名称)
存储用户信息。(localStorage.setItem(xxx))
//登录按钮操作方法 const login = () =>{//开始校验formRef.value.validate((valid)=>{if(valid){//表单项(字段)验证通过request.post("/login",data.form).then(res=>{if(res.code === '200'){ //登录成功ElMessage.success('登录成功')//登录成功后,跳转主页。等500ms进行跳转setTimeout(()=>{location.href = '/manager/home'},500)//存储后台返回的员工对象信息//把后端传来的JSON对象转换成JSON字符串存储localStorage.setItem('xm-pro-user',JSON.stringify(res.data))}else { //登录失败ElMessage.error(res.msg)}})}}) }
主页面(Manager.vue)获取登录时存储的用户信息。
import {reactive} from "vue";const data = reactive({//记得将拿到的JSON字符串转换成JSON对象。这样才能获取到员工名称:data.user.nameuser: JSON.parse(localStorage.getItem('xm-pro-user')) })
<!-- 右半部分-头像 --><div style="width: 150px;display: flex;align-items: center"><img src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" alt="" style="width: 40px;height: 40px"><span style="margin-left: 5px;color: white">{{data.user.name}}</span></div>
- 删除登录页面表单项“注册”按钮。
(7)新建注册页面。(Register.vue)
<1>复制粘贴(Login.vue)并稍加修改。
基本框架。
<template><div><div class="login-container"> <!-- 登录表单容器 --><div class="login-box"><div style="padding: 40px 30px;background-color: #fbfcf8;margin-left: 200px;border-radius: 5px"><div style="margin-bottom: 30px;font-weight: bold;font-size: 24px;color: #514343;text-align: center" >欢迎注册hyl信息管理系统</div><el-form ref="formRef" :rules="data.rules" :model="data.form" style="width: 350px"><el-form-item prop="username"><el-input v-model="data.form.username" placeholder="请输入用户名" prefix-icon="User"></el-input></el-form-item><el-form-item prop="password"><el-input v-model="data.form.password" placeholder="请输入密码" prefix-icon="Lock" show-password></el-input></el-form-item><el-form-item prop="confirmPassword"><el-input v-model="data.form.confirmPassword" placeholder="请再次输入密码" prefix-icon="Lock" show-password></el-input></el-form-item><div style="margin-top: 20px;margin-bottom: 20px"><el-button size="large" style="width: 100%;" type="primary" @click="register">注 册</el-button></div><!-- 可以使用text-decoration:none 让链接不显示下划线 --><div style="text-align: right">已有账号?请 <a style="color: #1967e3;" href="/login">登 录</a></div></el-form></div></div></div></div> </template><script setup>import {reactive,ref} from "vue"; import request from "@/utils/request.js"; import {ElMessage} from "element-plus";const formRef = ref()const data = reactive({form:{},rules:{username :[{ required: true ,message:'请输入用户名',trigger:'blur'}],password :[{ required: true ,message:'请输入密码',trigger:'blur'}],}, })//注册按钮操作方法 const register = () =>{//开始校验formRef.value.validate((valid)=>{if(valid){//表单项(字段)验证通过request.post("/register",data.form).then(res=>{if(res.code === '200'){ //注册成功ElMessage.success('注册成功')//注册成功后,跳转登录页面。等500ms进行跳转setTimeout(()=>{location.href = '/login'},500)//注册成功不要存储用户信息}else { //注册失败ElMessage.error(res.msg)}})}}) }</script><style scoped> .login-container {/*占满可视高度*/height: 100vh;/*隐藏超出高度*/overflow: hidden;/*背景图*/background-image: url("@/assets/bimage2.jpeg");/*背景图片大小*/background-size: cover;/*设置背景图移动*/background-position: -450px -120px; }.login-box {/*绝对定位*/position: absolute;width: 50%;height: 100vh;/*靠右*/right: 0;/*flex布局*/display: flex;align-items: center;background-color: #f1ebe2; }</style>
配置路由。
import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path:'/',redirect:'/manager/home'},{path:'/manager',meta:{ title:'父级页面'},component: () => import('../views/Manager.vue'),children:[{path: 'home', name: 'home', meta:{ title:'主页'}, component: () => import('../views/Home.vue')}, // url:/manager/home{path: 'test', name: 'test', meta:{ title:'测试数据页01'}, component: () => import('../views/Test.vue')}, // url:/manager/test{path: 'demo', name: 'demo', meta:{ title:'测试数据页02'}, component: () => import('../views/Demo.vue')}, // url:/manager/demo{path: 'data', name: 'data', meta:{ title:'数据展示页面'}, component: () => import('../views/Data.vue')}, // url:/manager/data{path: 'employee', name: 'employee', meta:{ title:'员工信息页面'}, component: () => import('../views/Employee.vue')}, // url:/manager/employee]},{path: '/login', name: 'login', meta:{ title:'登录页面'}, component: () => import('../views/Login.vue')},{path: '/register', name: 'register', meta:{ title:'欢迎注册'}, component: () => import('../views/Register.vue')},{path: '/404', name: 'NotFound', meta:{ title:'404找不到页面'}, component: () => import('../views/404.vue')},{path:'/:pathMatch(.*)',redirect:'/404'}], })router.beforeEach((to,from,next)=>{//设置即将跳转的路由页面的网页标题document.title=to.meta.titlenext() //必须调用的方法 })export default router
<2>密码与二次确认密码的自定义校验。(:rules、ref、prop)
官方操作演示。(element-plus)
- 绑定校验规则(:rules)、绑定校验方法(ref)。
根据官方演示手动实现。(代码示例)
<el-form ref="formRef" :rules="data.rules" :model="data.form" style="width: 350px"><el-form-item prop="username"><el-input v-model="data.form.username" placeholder="请输入用户名" prefix-icon="User"></el-input></el-form-item><el-form-item prop="password"><el-input v-model="data.form.password" placeholder="请输入密码" prefix-icon="Lock" show-password></el-input></el-form-item><el-form-item prop="confirmPassword"><el-input v-model="data.form.confirmPassword" placeholder="请再次输入密码" prefix-icon="Lock" show-password></el-input></el-form-item><div style="margin-top: 20px;margin-bottom: 20px"><el-button size="large" style="width: 100%;" type="primary" @click="register">注 册</el-button></div><!-- 可以使用text-decoration:none 让链接不显示下划线 --><div style="text-align: right">已有账号?请 <a style="color: #1967e3;" href="/login">登 录</a></div> </el-form>
import {reactive,ref} from "vue"; import request from "@/utils/request.js"; import {ElMessage} from "element-plus";const formRef = ref()//校验二次确认密码与密码 const validateConfirmPass = (rule, value, callback) => {if (!value) { //输入二次密码为空callback(new Error('请再次确认密码'))} else if (value !== data.form.password) { //两次密码不一致callback(new Error("两次输入的密码不一致"))} else {callback()} }const data = reactive({form:{},rules:{username :[{ required: true ,message:'请输入用户名',trigger:'blur'}],password :[{ required: true ,message:'请输入密码',trigger:'blur'}],confirmPassword :[{validator: validateConfirmPass ,trigger:'blur'}],}, })
表单项校验的页面渲染效果。
- 表单项为空校验、输入框鼠标失焦时。
- 首次输入密码与二次输入密码不一致校验。
(8)后端代码编写。(注册功能)
<1>controller层注册接口。
package com.hyl.controller;import com.hyl.common.Result; import com.hyl.entity.Employee;import com.hyl.service.EmployeeService; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController;//表示对外提供可访问接口的类 @RestController public class WebController {@Resourceprivate EmployeeService employeeService;//测试接口(不必理会)@GetMapping("/hello")public Result hello(){return Result.success("hello");}//员工登录接口//返回登录成功后的员工对象通过@RestController响应成JSON对象给前端//前端(res.data)再将JSON对象转换成JSON字符串临时存储用户信息@PostMapping("/login")public Result login(@RequestBody Employee employee){Employee dbEmployee = employeeService.login(employee);return Result.success(dbEmployee);}//员工注册接口@PostMapping("/register")public Result register(@RequestBody Employee employee){//注册成功不需要向前端返回用户信息employeeService.register(employee);return Result.success();}}
<2>service层的注册业务编写。
引入Hutool工具类插件依赖。
<!-- hutool工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.25</version></dependency>
- 官方API基本介绍。
add()方法修改与完善。
package com.hyl.service;import cn.hutool.core.util.StrUtil; import com.hyl.entity.Employee; import com.hyl.exception.CustomerException; import com.hyl.mapper.EmployeeMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service;import java.util.List; import java.util.Objects;@Service public class EmployeeService {@Resourceprivate EmployeeMapper employeeMapper;//新增员工方法public void add(Employee employee) {//用户名String username = employee.getUsername();//先查询数据库中是否有该用户Employee dbEmployee = employeeMapper.selectByUserName(username);//如果有则代表该账号(用户名)已被注册。注册失败if(Objects.nonNull(dbEmployee)){throw new CustomerException("500","该用户名已被注册,请更换其它用户名");}//引入Hutool工具类。判断字符串是否为空的方法//isBlank()是空的if(StrUtil.isBlank(employee.getPassword())){//添加员工账号时,密码为空,默认密码设置123employee.setPassword("123");}//名称未填写时默认使用用户名if(StrUtil.isBlank(employee.getName())){//注册员工账号时,名称没有填写,默认名称则设置员工账号employee.setName(employee.getUsername());}//最后一定设置角色employee.setRole("EMP");employeeMapper.insert(employee);} }
register方法。
package com.hyl.service;import com.hyl.entity.Employee; import com.hyl.mapper.EmployeeMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service;import java.util.List; import java.util.Objects;@Service public class EmployeeService {@Resourceprivate EmployeeMapper employeeMapper;public void register(Employee employee) {//逻辑相同。调用新增add方法this.add(employee);} }
<3>mapper层。(接口与SQL映射文件)
package com.hyl.mapper;import com.hyl.entity.Employee; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Select;import java.util.List;public interface EmployeeMapper {void insert(Employee employee);@Select("select * from `employee` where username = #{username}")Employee selectByUserName(String username); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hyl.mapper.EmployeeMapper"><insert id="insert" parameterType="com.hyl.entity.Employee">insert into `employee`(username,password,role,name,sex,no,age,description,department_id)values (#{username},#{password},#{role},#{name},#{sex},#{no},#{age},#{description},#{departmentId})</insert></mapper>
<4>注册页面进行注册、登录操作图示。
- 用户名已被注册。
- 正常注册。
- 注册成功!
- 到这里算是基本完成SpringBoot3+Vue3快速实现登录、注册页面以及前后端的通信对接。
相关文章:
SpringBoot3+Vue3实战(Vue3快速开发登录注册页面并对接后端接口、表单项自定义校验规则、Hutool工具类)(4)
目录 一、SpringBoot3Vue3实现基本增删改查。前后端通信交互、配置后端跨域请求。数据批量删除。(博客链接) 二、SpringBoot3Vue3快速开发登录、注册页面并实现对接。 (1)操作数据表employee(员工信息表)。 <1>修改employee表的字段组成。 <2&g…...
OpenCV图像拼接项目指南
引言 图像拼接是计算机视觉领域中的一个重要应用,它可以将多张有重叠区域的图像拼接成一张全景图。这项技术广泛应用于虚拟现实、医学影像、卫星图像处理等领域。OpenCV作为一个强大的开源计算机视觉库,提供了丰富的工具和函数来实现图像拼接。本文将详…...
机器学习--DBSCAN聚类算法详解
目录 引言 1. 什么是DBSCAN聚类? 2. DBSCAN聚类算法的原理 3. DBSCAN算法的核心概念 3.1 邻域(Neighborhood) 3.2 核心点(Core Point) 3.3 直接密度可达(Directly Density-Reachable) 3…...
使用 Docker 构建 LangChain 开发环镜及 ChatOllama 示例
文章目录 Github官网简介Dockerfilerequirements.txt构建 LangChain 镜像ChatOllama 示例Ollama 示例模拟 tools Github https://github.com/langchain-ai/langchain 官网 https://python.langchain.com/docs/introduction/ 简介 LangChain 是一个用于构建 LLM 驱动的应用…...
持续集成与持续交付:这里有从开发到部署的全流程优化
阅读原文 在上一篇中,我们深入探讨了安全测试的核心内容,强调了它在发现安全漏洞和提升系统安全性中的重要作用。接下来,我们将聚焦于持续集成(CI)与持续交付(CD),这是现代软件开发…...
CH32V208蓝牙内部带运放32位RISC-V工业级微控制器CH32V208CBU6、CH32V208GBU6开发板原理图和PCB
开发板 CH32V208CBU6立创格式的开发板上述链接可下载,官方文件进行了转换,使用前请仔细核对。 CH32V208CBU6原理图,上述图片为芯片部分。已进行DRC。 CH32V208CBU6 PCB三维图,上述图片为芯片部分。已进行DRC。 CH32V208GBU6开发…...
机器臂运动控制算法工程师面试
大厂的经验总结: 一、基础概念理解 请解释机器臂运动学正解和逆解的概念,并分别说明其用途。 正解:已知机器臂各关节的角度(或位移),通过运动学模型计算出机器臂末端执行器在笛卡尔空间中的位置和姿态。用途在于可以根据给定的关节驱动值,预测末端的实际位置,用于运动…...
【一起来学kubernetes】21、Secret使用详解
Secret 的详细介绍 Secret 是 Kubernetes 中用于存储和管理敏感信息(如密码、令牌、密钥等)的资源对象。Secret的设计目的是为了安全地存储和传输敏感信息,如密码、API密钥、证书等。这些信息通常不应该直接硬编码在配置文件或镜像中&#x…...
Java架构师成长之路
概述 本教程主要从6个方面,全面讲解Java技术栈的知识。 1.性能调优 深入理解MySQL底层原理、索引逻辑,数据结构与算法。使用Explain进行优化分析MVCC原理剖析日志机制解析 2.框架源码 掌握Spring底层原理带你手写一个Spring解析IOC、AOP源码、以及事…...
Cyberchef实用功能之-json line格式文件美化和查询
本文将介绍一下如何使用cyberchef对json line格式数据进行美化方便阅读,以及json line格式数据的批量查询操作。 之前的文章介绍了json格式数据的美化和查询,即Cyberchef实用功能之-json解析美化和转换,Cyberchef实用功能之-批量提取json数据…...
span与span之间的空白如何解决?
<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>标题</title> <style>div{background: yellow;}span:first-of-type{background: red;}span:last-of-type{background: blue;}</styl…...
2024年MathorCup数学建模B题甲骨文智能识别中原始拓片单字自动分割与识别研究解题全过程文档加程序
2024年第十四届MathorCup高校数学建模挑战赛 B题 甲骨文智能识别中原始拓片单字自动分割与识别研究 原题再现: 甲骨文是我国目前已知的最早成熟的文字系统,它是一种刻在龟甲或兽骨上的古老文字。甲骨文具有极其重要的研究价值,不仅对中国文…...
3.23学习总结
字符串 String java.lang,String 类代表字符串,Java程序中所有的字符串文字都为此类的对象 字符串的内容是不会发生改变的,它的对象在创建之后不能呗更改 字符串的内存模型 当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在。 …...
RT-Thread CI编译产物artifacts自动上传功能介绍
近期在RT-Thread开源项目中,我们引入了一项实用的功能改进——将每次CI(持续集成)编译生成的产物(artifacts)自动上传到GitHub,方便开发者和用户能够更便捷地获取和测试最新的编译结果。 参考链接…...
Android adb调试应用程序
启动app 有的时候app不是预先安装的,也不能从界面start一个app,这时需要后台拉起app。 $adb shell am start package.name/Activity.name 例如,android原生camera app, 包名为com.android.camera2, mainActivity名为…...
仅靠prompt,Agent难以自救
Alexander的观点很明确:未来 AI 智能体的发展方向还得是模型本身,而不是工作流(Work Flow)。还拿目前很火的 Manus 作为案例:他认为像 Manus 这样基于「预先编排好的提示词与工具路径」构成的工作流智能体,…...
【嵌入式学习2】函数
目录 ## 函数 ## 函数分类 ## 函数定义 1、无参数无返回值 2、有参数无返回值 3、有参数有返回值 ## 函数声明 ## 局部变量和全局变量 ## 多文件编程 如何避免把同一个头文件 include 多次,或者头文件嵌套包含? 命令行编译文件 头文件包含的…...
平芯微PW5012应用电路
PW5012应用电路板介绍: 1.1 单节和两节锂电池升压 12V 或 9V, 1A 至 3A 电路板, 1.2 应用: 升压电压转换板 1.3 VIN 输入电压: 3V-9V 1.4 VOUT 输出电压: 9V 2A(VIN3.7V) ࿰…...
Langchain4J框架相关面试题
以下是关于Langchain4J框架的面试题目及答案 ### Langchain4J基础概念类 1. **Langchain4J框架是什么?它的核心功能有哪些?** Langchain4J是一个用于构建语言模型应用的Java框架,它为开发者提供了一套简洁高效的API,使得在Jav…...
【MySQL】用户管理
目录 一、用户1.1 用户信息1.2 创建用户1.3 删除用户1.4 修改用户密码1.4.1 用户修改自己密码1.4.2 root用户修改指定用户的密码 二、数据库的权限2.1 给用户授权2.2 回收用户权限 结尾 一、用户 1.1 用户信息 MySQL中的用户,都存储在系统数据库mysql的user表中。…...
5.高频加热的原理与常用集成电路介绍
一、高频加热的类型 利用高频电源加热通常由两种方法:电介质加热(被加热物体绝缘)与感应加热(被加热物体导电),详细解释如下: 电介质加热(利用高频电压的高频电场导致物体自身分子摩…...
Elasticsearch:可配置的推理 API 端点分块设置
作者:来自 Elastic Daniel Rubinstein Elasticsearch 开放推理 API 现已支持可配置的分块,以便在文档摄取时处理语义文本字段。 Elasticsearch 推理 API 允许用户利用各种提供商的机器学习模型执行推理操作。其中一个常见用例是在索引中支持用于语义搜索…...
从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.1.2多头注意力扩展与掩码机制(因果掩码与填充掩码)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.1.2 多头注意力扩展与掩码机制(`因果掩码与填充掩码`)1. 多头注意力机制:分治策略的数学实现1.1 多头注意力核心公式2. 逐行代码实现2.1 多头拆分与合并3. 掩码机制:注意力控制的核心技术3.1 因果…...
Scikit-learn模型评估全流程解析:从数据划分到交叉验证优化
模型评估的步骤、scikit-learn函数及实例说明 1. 数据划分(Train-Test Split) 函数:train_test_split使用场景:将数据分为训练集和测试集,避免模型过拟合。作用:确保模型在未见过的数据上验证性能。示例&…...
大模型量化框架GPTQModel的基本使用方法
接上一篇博客:AutoGPTQ报torch._C._LinAlgError: linalg.cholesky: The factorization could not be completed的解决办法-CSDN博客 如果Llama factory量化一直报错,可以改用其他的量化框架,例如GPTQ:https://github.com/ModelCl…...
HTTP长连接与短连接的前世今生
HTTP长连接与短连接的前世今生 大家好!作为一名在互联网摸爬滚打多年的开发者,今天想跟大家聊聊HTTP中的长连接和短连接这个话题。 记得我刚入行时,对这些概念一头雾水,希望这篇文章能帮助新入行的朋友少走些弯路。 什么是HTTP…...
线程控制学习
1、线程创建: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void*), void *arg); 参数 thread:返回线程ID;attr:设置线程的属性,attr为nullptr表示使用默认属性(一般…...
使用 Node.js 从零搭建 Kafka 生产消费系统
目录 一、Kafka 核心概念速览 二、环境准备 三、生产者实现:发送消息 四、消费者实现:处理消息 五、高级配置与最佳实践 六、常见问题解决 七、应用场景示例 总结 Apache Kafka 作为高吞吐、分布式的消息队列系统,在实时数据流处理中…...
【Linux系统】Linux权限讲解!!!超详细!!!
目录 Linux文件类型 区分方法 文件类型 Linux用户 用户创建与删除 用户之间的转换 su指令 普通用户->超级用户(root) 超级用户(root) ->普通用户 普通账户->普通账户 普通用户的权限提高 sudo指令 注: Linux权限 定义 权限操作 1、修改文…...
Ubuntu安装TensorFlow 2.13-GPU版全流程指南(anaconda)
目录 一、安装前准备1.版本选择依据2.创建独立环境 二、详细安装步骤1.通过conda自动安装依赖2.手动验证依赖版本 三、补充说明1.组件依赖关系表2.常见问题解决方案3.性能验证脚本 一、安装前准备 1.版本选择依据 当前最新稳定版:TensorFlow 2.13&a…...
Spring事务管理
介绍了事务的概念,事务的特性,JDBC 事务管理的步骤和操作过程,以及Spring事务管理的两种实现方式:编程式事务管理和声明式事务管理。 1.事务的概念 事务(Transaction)就是将一系列的数据库操作作为一个整体…...
避雷 :C语言中 scanf() 函数的错误❌使用!!!
1. 返回值说明 scanf函数会返回成功匹配并赋值的输入项个数,而不是返回输入的数据。 可以通过检查返回值数量来确认输入是否成功。若返回值与预期不符,就表明输入存在问题。 #include <stdio.h>int main() {int num;if (scanf("%d", …...
判断一个操作是不是允许
一、目的 简单探索一个URL请求是不是允许的。 二、具体过程 (一)系统的初始化 系统数据库有账户"admin",密码是"123"。 账号"admin"的角色是管理员"manager"。 假设管理员身份设定的权限是: 1、对于/user/开头的…...
【FPGA开发】Cordic原理推导、Xilinx PG105手册解读
目录 Cordic原理推导PG105手册解读IP核总览核心计算功能总览基本握手信号非阻塞模式 NonBlocking Mode阻塞模式 Block Mode 数据格式数据映射 本文针对Cordic算法本身,以及Xilinx官方CORDIC IP做学习记录,如有纰漏,欢迎指正! Cord…...
数据结构与算法:宽度优先遍历
前言 进入图论部分难度明显提升了一大截,思路想不到一点…… 一、宽度优先遍历 1.内容 宽度优先遍历主要用于在图上求最短路。 (1)特点 宽度优先遍历的特点就是逐层扩展,最短路即层数 (2)使用条件 …...
PyTorch 面试题及参考答案(精选100道)
目录 PyTorch 的动态计算图与 TensorFlow 的静态计算图有何区别?动态图的优势是什么? 解释张量(Tensor)与 NumPy 数组的异同,为何 PyTorch 选择张量作为核心数据结构? 什么是 torch.autograd 模块?它在反向传播中的作用是什么? 如何理解 PyTorch 中的 nn.Module 类?…...
【数理基础】【概率论与数理统计】概率论与数理统计本科课程总结、资料汇总、个人理解
1 前言 概率论与数理统计是数学系核心的基础专业课,我本科的时候,是拆开上的,对应工科专业的高数中的概率论与数理统计,在量子力学,机器学习,计算机领域深度学习,大模型,机器人控制…...
美制 / 英制单位换算/公制/帝国制 单位转换速查表
文章目录 💡Introduction📏 英制(美制)单位与公制换算速查表🧱 一、长度(Length)🧴 二、体积(Volume / Liquid Measure)⚖️ 三、质量 / 重量(Wei…...
ENSP学习day9
ACL访问控制列表实验 ACL(Access Control List,访问控制列表)是一种用于控制用户或系统对资源(如文件、文件夹、网络等)访问权限的机制。通过ACL,系统管理员可以定义哪些用户或系统可以访问特定资源&#x…...
我爱学算法之——滑动窗口攻克子数组和子串难题(中)
学习算法,继续加油!!! 一、将 x 减到 0 的最小操作数 题目解析 来看这一道题,题目给定一个数组nums和一个整数x;我们可以在数组nums的左边或者右边进行操作(x减去该位置的值)&#…...
Linux centos 7 vsftp本地部署脚本
下面是脚本: #!/bin/bash #function:vsftpd脚本 #author: 20230323 IT 小旋风# 判断是否是root用户 if [ "$USER" ! "root" ]; thenecho "不是root 装个蛋啊"exit 1 fi# 关闭防火墙 systemctl stop firewalld && systemctl disable …...
编程考古-安德斯·海尔斯伯格(Anders Hejlsberg)回答离开Borland的原因
安德斯海尔斯伯格(Anders Hejlsberg)是著名的编程语言和工具开发者,曾主导开发了 Turbo Pascal、Delphi(Borland 时期),以及加入微软后参与的 C# 和 TypeScript。关于他离开 Borland 的原因,可以…...
数据库数值函数详解
各类资料学习下载合集 https://pan.quark.cn/s/8c91ccb5a474 数值函数是数据库中用于处理数值数据的函数,可以用于执行各种数学运算、统计计算等。数值函数在数据分析及处理时非常重要,能够帮助我们进行数据的聚合、计算和转换。在本篇博客中,我们将详细介绍常用的…...
SpringBoot与Redisson整合,用注解方式解决分布式锁的使用问题
文章引用:https://mp.weixin.qq.com/s/XgdKE2rBKL0-nFk2NJPuyg 一、单个服务 1.代码 该接口的作用是累加一个值,访问一次该值加1 RestController public class LockController {Autowiredprivate StringRedisTemplate stringRedisTemplate;GetMappin…...
Bash 脚本基础
一、Bash 脚本基础 什么是 Bash 脚本:Bash 脚本是一种文本文件,其中包含了一系列的命令,这些命令可以被 Bash shell 执行。它用于自动化重复性的任务,提高工作效率。 Bash 脚本的基本结构:以 #!/bin/bash 开头&#x…...
【Linux】线程库
一、线程库管理 tid其实是一个地址 void* start(void* args) {const char* name (const char *)args;while(true){printf("我是新线程 %s ,我的地址:0x%lx\n",name,pthread_self());sleep(1);}return nullptr; }int main() {pthread_t tid…...
Smith3.0 4.0的阻抗匹配操作方法
阅读了这篇文章中,我get到一些知识点的总结: 百度安全验证https://baijiahao.baidu.com/s?id1822624157494292625 1)红色圆代表阻抗圆,绿色圆代表导纳圆。 2)圆心位于50欧,最左侧为0欧,最右侧…...
装饰器模式 (Decorator Pattern)
装饰器模式 (Decorator Pattern) 是一种结构型设计模式,它动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式相比生成子类更为灵活。 一、基础 1 意图 动态地给一个对象添加一些额外的职责。 就增加功能来说,装饰器模式相比生成子类更为灵活。 2 适用场景 当…...
生活电子类常识——搭建openMauns工作流+搭建易犯错解析
前言 小白一句话生成一个网站?小白一句话生成一个游戏?小白一句话生成一个ppt?小白一句话生成一个视频? 可以 原理 总体的执行流程是 1,用户下达指令 2,大模型根据用户指令,分解指令任务为多个细分步骤…...
题型笔记 | Apriori算法
目录 内容拓展知识 内容 其步骤如下: 扫描全部数据,产生候选项 1 1 1 项集的集合 C 1 C_1 C1根据最小支持度,由候选 1 1 1 项集的集合 C 1 C_1 C1 产生频繁 1 1 1 项集的集合 L 1 L_1 L1。若 k > 1 k > 1 k>1…...