[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-7uED9n7e":3,"public-project-articles-7uED9n7e":17},{"id":4,"uuid":5,"project_id":6,"title":7,"content":8,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},527,"7uED9n7e",47,"11. Vue3开发登录注册页面","## 在 employee 表加 3 个字段\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1729499206458-5bd058bc-2e82-4fa4-9d3c-c213bd35b3d5.png)\n\n\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fjpeg\u002F751015\u002F1729499871012-2d6ad76f-d97f-4a87-a855-b50bfae6bce2.jpeg)\n\n## 登录页面的设计思路\n\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2024\u002Fpng\u002F751015\u002F1729500900744-6a136d4a-b9be-4dae-a8fe-70bc5c81f628.png)\n\n## 登录逻辑\n\n```java\n@PostMapping(\"\u002Flogin\")\npublic Result login(@RequestBody Employee employee) {\n    employeeService.login(employee);\n    return Result.success();\n}\n```\n\n```java\npublic Employee login(Employee employee) {\n    String username = employee.getUsername();  \u002F\u002F 账号\n    Employee dbEmployee = employeeMapper.selectByUsername(username);\n    if (dbEmployee == null) {  \u002F\u002F 没查询到任何用户   说明没有这个账号\n        throw new CustomException(\"500\", \"账号不存在\");\n    }\n    \u002F\u002F 数据库存在这个账号\n    String password = employee.getPassword();\n    if (!dbEmployee.getPassword().equals(password)) {  \u002F\u002F 用户输入的密码跟数据库账号的密码不匹配\n        throw new CustomException(\"500\", \"账号或密码错误\");\n    }\n    return dbEmployee;\n}\n```\n\n## 注册逻辑\n\n```java\n@PostMapping(\"\u002Fregister\")\npublic Result register(@RequestBody Employee employee) {\n    employeeService.register(employee);\n    return Result.success();\n}\n```\n\n```java\npublic void add(Employee employee) {\n    String username = employee.getUsername();  \u002F\u002F 账号\n    Employee dbEmployee = employeeMapper.selectByUsername(username);\n    if (dbEmployee != null) {  \u002F\u002F 注册的账号已存在  无法注册\n        throw new CustomException(\"500\", \"账号已存在，请更换别的账号\");\n    }\n    if (StrUtil.isBlank(employee.getPassword())) {  \u002F\u002F 密码没填\n        employee.setPassword(\"123\");  \u002F\u002F 默认密码 123\n    }\n    if (StrUtil.isBlank(employee.getName())) {  \u002F\u002F 名字没填\n        employee.setName(employee.getUsername());  \u002F\u002F 默认名称\n    }\n    \u002F\u002F 一定要设置角色\n    employee.setRole(\"EMP\");  \u002F\u002F 员工的角色\n    employeeMapper.insert(employee);\n}\n```\n\n## hutool 工具包\n\n[https:\u002F\u002Fdoc.hutool.cn\u002Fpages\u002Findex\u002F](https:\u002F\u002Fdoc.hutool.cn\u002Fpages\u002Findex\u002F)\n\n```xml\n\u003C!--  hutool 插件包 -->\n\u003Cdependency>\n  \u003CgroupId>cn.hutool\u003C\u002FgroupId>\n  \u003CartifactId>hutool-all\u003C\u002FartifactId>\n  \u003Cversion>5.8.25\u003C\u002Fversion>\n\u003C\u002Fdependency>\n```\n\n## 本节课登录页面\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"login-container\">\n    \u003Cdiv class=\"login-box\">\n      \u003Cdiv style=\"padding: 50px 30px; background-color: white; margin-left: 100px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.2)\">\n        \u003Cel-form ref=\"formRef\" :rules=\"data.rules\" :model=\"data.form\" style=\"width: 300px\">\n          \u003Cdiv style=\"margin-bottom: 30px; font-size: 24px; text-align: center; color: #0742b1; font-weight: bold\">欢迎登录后台管理系统\u003C\u002Fdiv>\n          \u003Cel-form-item prop=\"username\">\n            \u003Cel-input size=\"large\" v-model=\"data.form.username\" placeholder=\"请输入账号\" prefix-icon=\"User\">\u003C\u002Fel-input>\n          \u003C\u002Fel-form-item>\n          \u003Cel-form-item prop=\"password\">\n            \u003Cel-input show-password size=\"large\" v-model=\"data.form.password\" placeholder=\"请输入密码\" prefix-icon=\"Lock\">\u003C\u002Fel-input>\n          \u003C\u002Fel-form-item>\n          \u003Cdiv style=\"margin-bottom: 20px\">\n            \u003Cel-button @click=\"login\" size=\"large\" style=\"width: 100%\" type=\"primary\">登 录\u003C\u002Fel-button>\n          \u003C\u002Fdiv>\n          \u003Cdiv style=\"text-align: right\">还没有账号？请 \u003Ca style=\"color: #0742b1; text-decoration: none\" href=\"\u002Fregister\">注册\u003C\u002Fa>\u003C\u002Fdiv>\n        \u003C\u002Fel-form>\n      \u003C\u002Fdiv>\n\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive, ref } from \"vue\";\nimport { User, Lock } from \"@element-plus\u002Ficons-vue\"\nimport request from \"@\u002Futils\u002Frequest.js\";\nimport {ElMessage} from \"element-plus\";\n\nconst data = reactive({\n  form: {},\n  rules: {\n    username: [\n      { required: true, message: '请输入账号', trigger: 'blur' }\n    ],\n    password: [\n      { required: true, message: '请输入密码', trigger: 'blur' }\n    ]\n  }\n})\nconst formRef = ref()\n\nconst login = () => {\n  formRef.value.validate((valid) => {\n    if (valid) {\n      request.post('\u002Flogin', data.form).then(res => {\n        if (res.code === '200') {  \u002F\u002F 登录成功\n          \u002F\u002F 存储后台返回的用户数据信息\n          localStorage.setItem('xm-pro-user', JSON.stringify(res.data))  \u002F\u002F 把json对象转换成 json字符串存储\n          ElMessage.success('登录成功')\n          setTimeout(() => {\n            location.href = '\u002Fmanager\u002Fhome'\n          }, 500)\n        } else {\n          ElMessage.error(res.msg)\n        }\n      })\n    }\n  })\n}\n\n\u003C\u002Fscript>\n\n\u003Cstyle scoped>\n.login-container {\n  height: 100vh;\n  overflow: hidden;\n  background-image: url(\"@\u002Fassets\u002Fbg.jpg\");\n  background-size: cover;\n  background-position: 0 -50px;\n}\n\n.login-box {\n  width: 50%;\n  height: 100%;\n  display: flex;\n  align-items: center;\n  right: 0;\n  position: absolute;\n}\n\u003C\u002Fstyle>\n```\n\n## 本节课注册页面\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"login-container\">\n    \u003Cdiv class=\"login-box\">\n      \u003Cdiv style=\"padding: 50px 30px; background-color: white; margin-left: 100px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.2)\">\n        \u003Cel-form ref=\"formRef\" :rules=\"data.rules\" :model=\"data.form\" style=\"width: 300px\">\n          \u003Cdiv style=\"margin-bottom: 30px; font-size: 24px; text-align: center; color: #0742b1; font-weight: bold\">欢 迎 注 册\u003C\u002Fdiv>\n          \u003Cel-form-item prop=\"username\">\n            \u003Cel-input size=\"large\" v-model=\"data.form.username\" placeholder=\"请输入账号\" prefix-icon=\"User\">\u003C\u002Fel-input>\n          \u003C\u002Fel-form-item>\n          \u003Cel-form-item prop=\"password\">\n            \u003Cel-input show-password size=\"large\" v-model=\"data.form.password\" placeholder=\"请输入密码\" prefix-icon=\"Lock\">\u003C\u002Fel-input>\n          \u003C\u002Fel-form-item>\n          \u003Cel-form-item prop=\"confirmPassword\">\n            \u003Cel-input show-password size=\"large\" v-model=\"data.form.confirmPassword\" placeholder=\"请确认密码\" prefix-icon=\"Lock\">\u003C\u002Fel-input>\n          \u003C\u002Fel-form-item>\n          \u003Cdiv style=\"margin-bottom: 20px\">\n            \u003Cel-button @click=\"register\" size=\"large\" style=\"width: 100%\" type=\"primary\">注 册\u003C\u002Fel-button>\n          \u003C\u002Fdiv>\n          \u003Cdiv style=\"text-align: right\">已有账号？请 \u003Ca style=\"color: #0742b1; text-decoration: none\" href=\"\u002Flogin\">登录\u003C\u002Fa>\u003C\u002Fdiv>\n        \u003C\u002Fel-form>\n      \u003C\u002Fdiv>\n\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript setup>\nimport { reactive, ref } from \"vue\";\nimport { User, Lock } from \"@element-plus\u002Ficons-vue\"\nimport request from \"@\u002Futils\u002Frequest.js\";\nimport {ElMessage} from \"element-plus\";\n\nconst validatePass = (rule, value, callback) => {\n  if (!value) {\n    callback(new Error('请再次确认密码'))\n  } else if (value !== data.form.password) {\n    callback(new Error(\"两次输入的密码不一致\"))\n  } else {\n    callback()\n  }\n}\n\nconst data = reactive({\n  form: {},\n  rules: {\n    username: [\n      { required: true, message: '请输入账号', trigger: 'blur' }\n    ],\n    password: [\n      { required: true, message: '请输入密码', trigger: 'blur' }\n    ],\n    confirmPassword: [\n      { validator:  validatePass, trigger: 'blur'}\n    ]\n  }\n})\nconst formRef = ref()\n\nconst register = () => {\n  formRef.value.validate((valid) => {\n    if (valid) {\n      request.post('\u002Fregister', data.form).then(res => {\n        if (res.code === '200') {  \u002F\u002F 注册成功\n          ElMessage.success('注册成功')\n          setTimeout(() => {\n            location.href = '\u002Flogin'\n          }, 500)\n        } else {\n          ElMessage.error(res.msg)\n        }\n      })\n    }\n  })\n}\n\n\u003C\u002Fscript>\n\n\u003Cstyle scoped>\n.login-container {\n  height: 100vh;\n  overflow: hidden;\n  background-image: url(\"@\u002Fassets\u002Fbg.jpg\");\n  background-size: cover;\n  background-position: 0 -50px;\n}\n\n.login-box {\n  width: 50%;\n  height: 100%;\n  display: flex;\n  align-items: center;\n  right: 0;\n  position: absolute;\n}\n\u003C\u002Fstyle>\n```\n\n","coding",1,7106,1031,"2024-10-21 17:35:30","2026-05-03 22:49:02","1天学会SpringBoot3+Vue3实战项目开发","learn-springboot-vue",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,27,34,42,49,56,63,70,77,84,91,92,99,106,113,120],{"id":21,"uuid":22,"project_id":6,"title":23,"type":9,"status":10,"public_enabled":10,"views":24,"sort":25,"created_at":26,"updated_at":14,"project_title":15,"project_slug":16},475,"OgrBbww7","01. 1天学会SpringBoot3+Vue3实战项目课程介绍",17862,910,"2024-10-11 16:50:50",{"id":28,"uuid":29,"project_id":6,"title":30,"type":9,"status":10,"public_enabled":10,"views":31,"sort":32,"created_at":33,"updated_at":14,"project_title":15,"project_slug":16},476,"U58ISSFR","02. 从0带你搭建Vue3工程",12899,911,"2024-10-11 16:47:49",{"id":35,"uuid":36,"project_id":6,"title":37,"type":9,"status":10,"public_enabled":10,"views":38,"sort":39,"created_at":40,"updated_at":41,"project_title":15,"project_slug":16},478,"tK3YUYq8","03. Vue3集成Element-Plus",9899,919,"2024-10-14 22:18:17","2026-05-07 15:33:28.189425+00",{"id":43,"uuid":44,"project_id":6,"title":45,"type":9,"status":10,"public_enabled":10,"views":46,"sort":47,"created_at":48,"updated_at":14,"project_title":15,"project_slug":16},488,"J2MV6UAG","04. Element-Plus组件使用速成",8093,938,"2024-10-11 16:49:40",{"id":50,"uuid":51,"project_id":6,"title":52,"type":9,"status":10,"public_enabled":10,"views":53,"sort":54,"created_at":55,"updated_at":14,"project_title":15,"project_slug":16},489,"zGi4XJsb","05. Vue3集成Vue-Router实现路由跳转",7443,939,"2024-10-12 15:44:41",{"id":57,"uuid":58,"project_id":6,"title":59,"type":9,"status":10,"public_enabled":10,"views":60,"sort":61,"created_at":62,"updated_at":14,"project_title":15,"project_slug":16},499,"cwsTdvo9","06. Vue3搭建后台管理系统",7421,964,"2024-10-14 16:02:49",{"id":64,"uuid":65,"project_id":6,"title":66,"type":9,"status":10,"public_enabled":10,"views":67,"sort":68,"created_at":69,"updated_at":14,"project_title":15,"project_slug":16},501,"JlXltpKA","07. Mysql语法简介（速成）",5208,973,"2024-10-15 16:52:18",{"id":71,"uuid":72,"project_id":6,"title":73,"type":9,"status":10,"public_enabled":10,"views":74,"sort":75,"created_at":76,"updated_at":14,"project_title":15,"project_slug":16},509,"c3XrOTcU","08. 从0带你搭建SpringBoot3工程",9397,992,"2024-10-16 15:43:13",{"id":78,"uuid":79,"project_id":6,"title":80,"type":9,"status":10,"public_enabled":10,"views":81,"sort":82,"created_at":83,"updated_at":14,"project_title":15,"project_slug":16},516,"QsKwbDX7","09. SpringBoot3集成Mybatis",10348,1004,"2024-10-17 16:36:15",{"id":85,"uuid":86,"project_id":6,"title":87,"type":9,"status":10,"public_enabled":10,"views":88,"sort":89,"created_at":90,"updated_at":14,"project_title":15,"project_slug":16},519,"qKG13ySo","10. SpringBoot3+Vue3实现基本的增删改查功能",9572,1013,"2024-10-18 16:34:55",{"id":4,"uuid":5,"project_id":6,"title":7,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},{"id":93,"uuid":94,"project_id":6,"title":95,"type":9,"status":10,"public_enabled":10,"views":96,"sort":97,"created_at":98,"updated_at":14,"project_title":15,"project_slug":16},535,"poUfWrWc","12. Vue3管理系统开发个人信息、修改密码页面",5777,1050,"2024-10-22 17:50:30",{"id":100,"uuid":101,"project_id":6,"title":102,"type":9,"status":10,"public_enabled":10,"views":103,"sort":104,"created_at":105,"updated_at":14,"project_title":15,"project_slug":16},542,"FxHR3hNR","13. SpringBoot3+Vue3实现文件上传下载功能",4489,1057,"2024-10-23 17:31:02",{"id":107,"uuid":108,"project_id":6,"title":109,"type":9,"status":10,"public_enabled":10,"views":110,"sort":111,"created_at":112,"updated_at":14,"project_title":15,"project_slug":16},548,"VPZNSTxr","14. SpringBoot3+Vue3实现富文本编辑器功能",3931,1072,"2024-10-24 17:38:21",{"id":114,"uuid":115,"project_id":6,"title":116,"type":9,"status":10,"public_enabled":10,"views":117,"sort":118,"created_at":119,"updated_at":14,"project_title":15,"project_slug":16},555,"nal0yVxM","15. SpringBoot3+Vue3实现数据批量导入导出功能",3577,1090,"2024-10-28 17:39:21",{"id":121,"uuid":122,"project_id":6,"title":123,"type":9,"status":10,"public_enabled":10,"views":124,"sort":125,"created_at":126,"updated_at":14,"project_title":15,"project_slug":16},564,"XxSPPFGi","16. SpringBoot3+Vue3实现数据统计图表功能",4236,1109,"2025-01-09 09:40:57"]