
目录
--使用管理员身份运行VSCode,然后在终端打开dos命令行界面

--设置国内的镜像
- #经过下面的配置,以后所有的 npm install 都会经过淘宝的镜像地址下载
- npm config set registry https://registry.npm.taobao.org
--安装vue-cli的插件\全局安装
- npm install vue-cli -g
-
- npm install -g @vue/cli-init 或者 npm install -g '@vue/cli-init'
--安装webpack的插件\全局安装
npm install -g webpack
注意:shell命令策略设置【当命令执行失败时操作、没有问题就不用管、继续下一步即可】

- 像这种都是策略问题,用管理员打开vscode,然后设置策略
- get-ExecutionPolicy
-
- 执行set-ExecutionPolicy RemoteSigned 然后 get-ExecutionPolicy,显示RemoteSigned就是ok了
-
- set-ExecutionPolicy RemoteSigned
--通过vue-cli脚手架来创建一个项目
vue init webpack vaccinum-vue

--切换到当前项目路径下、然后在启动vue项目测试【npm run dev】

- cd vaccinum-vue
-
- npm run dev


路由主要是实现页面跳转【实际上是请求地址映射vue页面】
--在components中创建两个vue页面文件

- <template>
- <div class="hello">
- <h2>Demo1111 Linksh2>
- div>
- template>
- <template>
- <div class="hello">
- <h2>Demo222 Linksh2>
- div>
- template>
--在router路由配置文件中配置页面的访问地址


- import Vue from 'vue'
- import Router from 'vue-router'
- import HelloWorld from '@/components/HelloWorld'
- Vue.use(Router)
- export default new Router({
- routes: [
- {
- path: '/',
- name: 'HelloWorld',
- component: HelloWorld
- },
- {
- path: '/demo1',
- name: 'demo1',
- component: ()=>import('@/components/demo1')
- },
- {
- path: '/demo2',
- name: 'demo2',
- component: ()=>import('@/components/demo2')
- }
- ]
- })
--在App.vue中提供两个链接,然后测试

- <router-link to="/demo1">demo1router-link>
- <router-link to="/demo2">demo2router-link>
-
--布局效果图

--element-ui网站【参考学习】
https://element.eleme.cn/#/zh-CN/component/installation
--ctrl+c 结束程序,然后执行命令下载element-ui依赖
--添加elementui依赖
--在vue项目目录下使用下面命令,添加ElementUI 依赖
npm i element-ui -S
--在src中的main.js中配置、导入element-ui组件及样式文件

- // 导入ElementUI
- import ElementUI from 'element-ui';
- import 'element-ui/lib/theme-chalk/index.css';
- Vue.use(ElementUI);//在vue使用ElementUI
--创建页面

--页面布局:在components下创建Layout.vue
- <template>
- <div>
-
- <Header />
-
-
- <div style="display: flex">
-
- <Aside />
-
- <router-view style="flex: 1" />
- div>
- div>
- template>
-
-
- <script>
- // 导入组件
- import Header from "@/components/Header";
- import Aside from "@/components/Aside";
-
- export default {
- name: "Layout",
- // 使用哪些组件
- components: {
- Aside,
- Header,
- },
- };
- script>
--页面布局:在components下创建Header.vue文件
- <template>
- <div
- style="
- height: 50px;
- line-height: 50px;
- border-bottom: 1px solid #ccc;
- display: flex;
- "
- >
- <div
- style="
- width: 200px;
- padding-left: 30px;
- font-weight: bold;
- color: dodgerblue;
- "
- >
- 管理系统
- div>
- <div style="flex: 1">div>
- <div style="width: 150px">
- <el-dropdown @command="handleCommand">
- <span class="el-dropdown-link">
- <el-avatar
- src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
- >el-avatar>
- admin<i class="el-icon-arrow-down el-icon--right">i>
- span>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item command="a">个人信息el-dropdown-item>
- <el-dropdown-item command="b">退出系统el-dropdown-item>
- el-dropdown-menu>
- el-dropdown>
- div>
- div>
- template>
-
- <script>
- import router from "@/router";
-
- export default {
- name: "Header",
- data() {
- return {
- name: "未登录",
- };
- },
- created() {},
- methods: {
- handleCommand(command) {},
- },
- };
- script>
--页面布局:在components下创建Aside.vue文件
- <template>
- <div>
- <el-menu
- style="width: 250px; min-height: calc(100vh - 50px)"
- default-active="2"
- class="el-menu-vertical-demo"
- @open="handleOpen"
- @close="handleClose"
- :default-openeds="[path]"
- router
- >
- <el-submenu index="1">
- <template slot="title">
- <i class="el-icon-location">i>
- <span>导航一span>
- template>
- <el-menu-item-group>
- <template slot="title">分组一template>
- <el-menu-item index="/list">选项1el-menu-item>
- <el-menu-item index="1-2">选项2el-menu-item>
- el-menu-item-group>
- <el-menu-item-group title="分组2">
- <el-menu-item index="1-3">选项3el-menu-item>
- el-menu-item-group>
- <el-submenu index="1-4">
- <template slot="title">选项4template>
- <el-menu-item index="1-4-1">选项1el-menu-item>
- el-submenu>
- el-submenu>
- <el-menu-item index="2">
- <i class="el-icon-menu">i>
- <span slot="title">导航二span>
- el-menu-item>
- <el-menu-item index="3" disabled>
- <i class="el-icon-document">i>
- <span slot="title">导航三span>
- el-menu-item>
- <el-menu-item index="4">
- <i class="el-icon-setting">i>
- <span slot="title">导航四span>
- el-menu-item>
- el-menu>
- div>
- template>
-
- <script>
- export default {
- data() {
- return {
- //path变量
- path: this.$route.path,
- };
- },
- methods: {
- handleOpen(key, keyPath) {
- console.log(key, keyPath);
- },
- handleClose(key, keyPath) {
- console.log(key, keyPath);
- },
- },
- };
- script>
--把App.vue的图标注释掉

--路由:在router下index.js修改请求映射

- import Vue from 'vue'
- import Router from 'vue-router'
- //导入局部的页面Layout
- import Layout from '@/components/Layout'
- Vue.use(Router)
- export default new Router({
- routes: [
- // 也就是-- / 映射到了 Layout的页面
- {
- path: '/',
- name: 'Layout',
- component: Layout
- }
- ]
- })
--重新启动前端项目-访问即可

--1、在components下创建Login.vue
- <template>
- <div class="login">
-
- <div class="login-form">
-
- <el-row :gutter="20">
- <el-col :span="12">
- <div>
- <img
- src="../assets/logo.png"
- alt=""
- style="
- position: relative;
- left: -100px;
- width: 250px;
- height: 85px;
- "
- />
- div>
- <div style="position: relative; left: 50px">
- <img src="../assets/icon-big.png" alt="" />
- div>
- el-col>
- <el-col :span="2">el-col>
- <el-col :span="10">
-
- <el-form
- ref="loginForm"
- :model="loginForm"
- style="margin-left: 150px; margin-top: 150px"
- >
- <el-form-item>
- <el-tabs
- v-model="roleType"
- @tab-click="selectRole"
- :stretch="true"
- >
- <el-tab-pane label="用户登录" name="用户">el-tab-pane>
- <el-tab-pane label="医生登录" name="医生">el-tab-pane>
- <el-tab-pane label="管理员登录" name="管理员">el-tab-pane>
- el-tabs>
- el-form-item>
- <el-form-item prop="name" v-if="roleType === '管理员'">
- <el-input
- prefix-icon="el-icon-user"
- v-model="loginForm.name"
- type="text"
- placeholder="账号"
- >
- el-input>
- el-form-item>
- <el-form-item prop="phone" v-if="roleType !== '管理员'">
- <el-input
- prefix-icon="el-icon-user"
- v-model="loginForm.phone"
- type="text"
- placeholder="账号"
- >
- el-input>
- el-form-item>
- <el-form-item prop="password">
- <el-input
- prefix-icon="el-icon-lock"
- v-model="loginForm.password"
- autocomplete="off"
- show-password
- placeholder="密码"
- >
- el-input>
- el-form-item>
- <el-form-item prop="code" v-if="captchaEnabled">
- <el-input
- v-model="loginForm.code"
- placeholder="请输入验证码"
- style="width: 63%"
- >
- el-input>
- <div class="login-code">
- <el-avatar
- shape="square"
- style="width: 100px"
- :src="codeUrl"
- >el-avatar>
- div>
- el-form-item>
- <el-form-item style="width: 100%">
- <el-button
- size="medium"
- type="primary"
- style="width: 100%; background-color: rgb(77, 167, 252)"
- @click="doLogin()"
- >
- <span style="font-size: 20px">登 录span>
- el-button>
- el-form-item>
- <el-form-item style="width: 100%">
- <el-button
- size="medium"
- type="primary"
- style="width: 100%; background-color: rgb(77, 167, 252)"
- v-if="roleType == '用户'"
- @click="registerFormVisible = true"
- >
- <span style="font-size: 20px">注 册span>
- el-button>
- el-form-item>
- el-form>
-
- el-col>
- el-row>
- div>
-
- <el-dialog
- title="用户注册"
- :visible.sync="registerFormVisible"
- :close-on-click-modal="false"
- >
- <el-form
- label-position="top"
- :model="registerForm"
- status-icon
- ref="registerForm"
- label-width="100px"
- class="demo-registerForm"
- >
-
- <el-form-item label="头像" prop="image">
- <el-upload
- class="avatar-uploader"
- action="http://localhost:80/vaccinum/common/upload"
- :show-file-list="false"
- :on-success="handleAvatarSuccess"
- :before-upload="beforeAvatarUpload"
- >
- <img v-if="imageUrl" :src="imageUrl" class="avatar" />
- <i v-else class="el-icon-plus avatar-uploader-icon">i>
- el-upload>
-
- <input type="hidden" name="avatar" v-model="registerForm.image" />
- el-form-item>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="用户名" prop="name">
- <el-input
- type="text"
- v-model="registerForm.name"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- <el-col :span="12">
- <el-form-item label="性别" prop="sex">
- <el-input
- type="text"
- v-model="registerForm.sex"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- el-row>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="年龄" prop="age">
- <el-input
- type="text"
- v-model="registerForm.age"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- <el-col :span="12">
- <el-form-item label="身份证号" prop="codeid">
- <el-input
- type="text"
- v-model="registerForm.codeid"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- el-row>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="密 码" prop="password">
- <el-input
- type="password"
- v-model="registerForm.password"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- <el-col :span="12">
- <el-form-item label="确认密码" prop="password_check">
- <el-input
- type="password"
- v-model="registerForm.password_check"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- el-row>
-
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="手机号" prop="phone">
- <el-input
- type="text"
- v-model="registerForm.phone"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- <el-col :span="12">
- <el-form-item label="地址" prop="address">
- <el-input
- type="text"
- v-model="registerForm.address"
- autocomplete="off"
- >el-input>
- el-form-item>
- el-col>
- el-row>
- <el-form-item>
- <el-button type="primary" @click="registerSumbit">提交el-button>
- <el-button
- @click="
- registerFormVisible = false;
- this.registerForm = {
- name: '',
- password: '',
- password_check: '',
- phone: '',
- };
- "
- >取消
- >
- el-form-item>
- el-form>
- el-dialog>
-
-
- <div class="el-login-footer">
- <span>Copyright © 2018-2022 gec All Rights Reserved.span>
- div>
-
- div>
- template>
- <script>
- import router from "@/router";
- export default {
- name: "Login",
- data() {
- return {
- password_type: "password", //密码显示类型
- imageUrl: "", //头像上传路径
- codeUrl: "",
- loginForm: {
- //登录的表单数据
- name: "12345678909",
- phone: "12345678909",
- password: "123",
- code: "",
- },
- registerForm: {
- //注册的表单数据
- name: "",
- sex: "",
- age: "",
- password: "",
- password_check: "",
- image: "",
- codeid: "",
- phone: "",
- address: "",
- },
- loading: false,
- captchaEnabled: true,
- register: true,
- registerFormVisible: false,
- roleType: "用户",
- };
- },
- created() {},
- methods: {
- //修改密码显示类型
- cho() {
- this.password_type = this.password_type == "text" ? "password" : "text";
- }, //选择哪个用户类型就显示那个类型
- selectRole() {
- console.log(this.roleType); // this.roleType = command;
- },
- //登录的处理函数
- doLogin() {
- if (this.loginForm.phone=="12345678909"&&this.loginForm.password=="123") {
- this.$message.success("登录成功!");
- //跳转到Layout页面【首页】
- router.push("/Layout");
- } else {
- //登录失败提示信息
- this.$message.error("登录失败!");
- }
- }, //注册函数
- registerSumbit() {
- //发起了异步请求
- request
- .post("register", this.registerForm) //回调函数
- .then((res) => {
- if (res.flag == true) {
- this.$message.success("注册成功!");
- this.registerFormVisible = false;
- this.registerForm = {
- name: "",
- sex: "",
- age: "",
- password: "",
- password_check: "",
- image: "",
- codeid: "",
- phone: "",
- address: "",
- };
- this.imageUrl = "";
- } else {
- //注册失败提示信息
- this.$message.error(res.message);
- }
- });
- }, //在上传成功后处理函数中,获取服务端返回的图片文件名或URL
- handleAvatarSuccess(res, file) {
- this.registerForm.image = res.fileName;
- this.imageUrl = URL.createObjectURL(file.raw);
- }, // 在上传之前,清空旧图片信息
- beforeAvatarUpload(file) {
- this.registerForm.image = "";
- this.imageUrl = "";
- const isJPG = file.type === "image/jpeg";
- const isLt2M = file.size / 1024 / 1024 < 2;
- if (!isJPG) {
- this.$message.error("上传头像图片只能是 JPG 格式!");
- }
- if (!isLt2M) {
- this.$message.error("上传头像图片大小不能超过 2MB!");
- }
- return isJPG && isLt2M;
- },
- },
- };
- script>
-
- <style>
- .el-dialog {
- border-radius: 45px;
- }
- .login {
- position: absolute;
- width: 100%;
- height: 100%;
- overflow: hidden;
- background-image: url("../assets/1.png");
- background-size: 100% 100%;
- background-repeat: no-repeat;
- }
- .title {
- margin: 0px auto 30px auto;
- text-align: center;
- color: #707070;
- }
- .login-form {
- margin: 150px auto;
- background-image: url("../assets/beijing.png");
- border-radius: 45px;
- background-position: -35px, -35px;
- width: 1240px;
- height: 657px;
- /* padding: 25px 25px 5px 25px; */
- }
- .el-input {
- height: 38px;
- }
- input {
- height: 38px;
- }
- .input-icon {
- height: 39px;
- width: 14px;
- margin-left: 2px;
- }
- .login-tip {
- font-size: 13px;
- text-align: center;
- color: #bfbfbf;
- }
- .login-code {
- width: 33%;
- height: 38px;
- float: right;
- }
- .el-login-footer {
- height: 40px;
- line-height: 40px;
- position: fixed;
- bottom: 0;
- width: 100%;
- text-align: center;
- /* color: #fff; */
- font-family: Arial;
- font-size: 12px;
- letter-spacing: 1px;
- }
- .login-code-img {
- height: 38px;
- }
- .avatar-uploader .el-upload {
- /* border: 1px dashed #d9d9d9; */
- border: 1px solid black;
- border-radius: 6px;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- }
- .avatar-uploader .el-upload:hover {
- border-color: #409eff;
- }
- .avatar-uploader-icon {
- font-size: 28px;
- color: #8c939d;
- width: 178px;
- height: 178px;
- line-height: 178px;
- text-align: center;
- }
- .avatar {
- width: 178px;
- height: 178px;
- display: block;
- }
- style>
--2、在路由index.js中配置根目录访问登录页面、然后修改首页的

- import Vue from 'vue'
- import Router from 'vue-router'
- //导入局部的页面Layout
- import Layout from '@/components/Layout'
- import Login from '@/components/Login'
- Vue.use(Router)
- export default new Router({
- routes: [
- // 也就是-- / 映射到了 Login的页面
- {
- path: '/',
- name: 'Login',
- component: Login
- },
- {
- path: '/Layout',
- name: 'Layout',
- component: Layout
- }
- ]
- })
--3、替换src中的assets文件中的图片

五、user登录后端接口完善【后端】
--1、在UserController中提供登录的处理方法、接收数据,响应json格式的数据

- //json 的解析工具
- ObjectMapper jsonTool = new ObjectMapper();
-
- // http://localhost:8085/user/loginUser?phone=sdfsdf&password=xxxx
- // 定义user的登录查询的请求接口【根据手机号码和密码进行登录】
- @RequestMapping("/loginUser")
- public String loginUser(String phone,String password) throws JsonProcessingException {
- // map集合-结果集
- HashMap result =new HashMap();
- //調用业务层的查询方法,根据手机号码和密码进行查询
- QueryWrapper
wrapper = new QueryWrapper<>(); - wrapper.eq("phone",phone).eq("password",password);
- //条件查询,获取一个对象
- User user = userService.getOne(wrapper);
- //业务逻辑的判断
- if(user!=null){//登录成功
- result.put("flag",true);
- result.put("user",user);
- result.put("role","user");
- }else{//登录失败
- result.put("flag",false);
- result.put("message","用戶名或密碼錯誤!!!");
- }
- //返回json格式的数据
- return jsonTool.writeValueAsString(result);
- }
--2、启动项目然后测试
http://localhost:8085/user/loginUser?phone=123451645602&password=123sdfsdfsdfsd

六、user登录前端-请求工具-请求发起【前端】
--结束前端程序ctrl+c
--执行命令、安装axios和cookie依赖
- npm install axios --save
- npm install --save js-cookie
--在src下创建utils文件夹、并创建request.js文件

- import axios from 'axios'
- import router from "@/router";
- import qs from "qs"
- import Cookies from "js-cookie";
- axios.defaults.withCredentials=true //让ajax请求携带cookie
- //1、目的是封装请求对象 2、目的对请求和响应数据进行格式
- // 创建对象
- const request = axios.create({
- baseURL: 'http://localhost:8085', // 注意!! 这里是全局统一加上了 baseURL 前缀,
- timeout: 5000
- })
-
- // request 拦截器
- request.interceptors.request.use(
- config => {
- //对请求的数据进行处理
- if (config.method != 'get') {
- config.data = qs.stringify(config.data);
- }
- // post请求方式的content格式
- config.headers['content-Type'] = 'application/x-www-form-urlencoded';//允许通过访问
- return config;
- },
- error => {
- console.log('err' + error) // for debug
- return Promise.reject(error)
- }
- )
-
- // response 拦截器
- // 可以在接口响应后统一处理结果
- request.interceptors.response.use(
- response => {
- let res = response.data;
- // 如果是返回的文件
- if (response.config.responseType === 'blob') {
- return res
- }
- // 兼容服务端返回的字符串数据
- if (typeof res === 'string') {
- res = res ? JSON.parse(res) : res
- }
- return res;
- },
- error => {
- console.log('err' + error) // for debug
- return Promise.reject(error)
- }
- )
-
- export default request
--修改Login.vue中的登录请求处理函数、发起异步请求

- //注意导入请求工具类和cookie
- import Cookies from "js-cookie";
- import request from "@/utils/request.js";

- doLogin() {
- //通过请求对象发起一个异步请求操作【axios】
- request
- .post("/user/loginUser", this.loginForm) //第一个参数是请求地址、第二个参数提交的数据 //回调函数\获取服务器响应的结果
- .then((res) => {
- //如果成功flag
- if (res.flag == true) {
- this.$message.success("登录成功!"); //把user信息、角色信息存放在cookie中
- Cookies.set("user", JSON.stringify(res.user), { expires: 0.3 });
- Cookies.set("role", res.role, { expires: 0.3 });
- //通过路由跳转、登录成功后跳转到首页
- router.push("/Layout");
- } else {
- //登录失败提示信息
- this.$message.error(res.message);
- }
- });
- },
--点击登录按钮进行测试、请求是成功发起的,但是发现跨域拦截:

七、请求的跨域-访问策略
--后端项目中创建config包,然后创建配置类提供跨域访问策略:

- import org.springframework.stereotype.Component;
-
- import javax.servlet.*;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- //定义拦截器允许跨域访问
- @Component
- public class UrlCorsConfiguration implements Filter {
-
- public void doFilter(ServletRequest req, ServletResponse res,
- FilterChain chain) throws IOException, ServletException {
-
- HttpServletResponse response = (HttpServletResponse) res;
- // 允许跨域访问的地址【前端项目部署的地址】
- response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
- //允许跨域的请求方法GET, POST, HEAD 等
- response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
- //重新预检验跨域的缓存时间 (s)
- response.setHeader("Access-Control-Max-Age", "3600");
- //允许跨域的请求头
- response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
- //是否携带cookie
- response.setHeader("Access-Control-Allow-Credentials", "true");
- // 设置响应的类型及字符集编码
- response.setContentType("text/json;charset=utf-8");
- //设置响应的中文编码
- chain.doFilter(req, res);
- }
-
- public void init(FilterConfig filterConfig) {
- }
-
- public void destroy() {
- }
-
- }
--重启后端项目,然后发起请求查看

八、完善项目的页面布局、导航菜单以及权限划分
--替换Aside.vue后端项目
- <template>
- <div>
- <el-menu
- style="width: 250px; min-height: calc(100vh - 50px);padding-top: 10px;"
- default-active="2"
- class="el-menu-vertical-demo"
- @open="handleOpen"
- @close="handleClose"
- :default-openeds="[path]"
- router
- >
- <el-submenu index="1" v-if="role == 'manager'">
- <template slot="title">
- <i class="el-icon-s-management">i>
-
- <span style="font-size: 17px; font-weight: bold;font-family:'苹方'">管理员模块span>
- template>
- <el-menu-item-group>
- <el-menu-item index="/Layout/adminList"
- ><i class="el-icon-link">i>管理员列表
- >
- el-menu-item-group>
- el-submenu>
- <el-submenu index="2">
- <template slot="title">
- <i class="el-icon-first-aid-kit">i>
- <span style="font-size: 17px; font-weight: bold;font-family:'苹方'">医生模块span>
- template>
- <el-menu-item-group>
-
- <el-menu-item index="/Layout/doctorList"
- ><i class="el-icon-link">i> 医生列表
- >
- <el-menu-item
- index="/Layout/registration"
- v-if="role == 'manager' || role == 'doctor' || role == 'user'"
- ><i class="el-icon-link">i>挂号记录
- >
- <el-menu-item index="/Layout/vaccineRecord" v-if="role != 'doctor'"
- ><i class="el-icon-link">i>接种记录
- >
- el-menu-item-group>
- el-submenu>
- <el-submenu index="3" v-if="role == 'manager' || role == 'user'">
- <template slot="title">
- <i class="el-icon-user">i>
- <span style="font-size: 17px; font-weight: bold;font-family:'苹方'">用户模块span>
- template>
- <el-menu-item-group>
- <el-menu-item index="/Layout/userList" v-if="role == 'manager'"
- ><i class="el-icon-link">i>用户列表
- >
- <el-menu-item index="/Layout/userRegis" v-if="role == 'user'"
- ><i class="el-icon-link">i>预约挂号
- >
- el-menu-item-group>
- el-submenu>
- <el-submenu index="4">
- <template slot="title">
- <i class="el-icon-office-building">i>
- <span style="font-size: 17px; font-weight: bold;font-family:'苹方'">医院模块span>
- template>
- <el-menu-item-group>
- <el-menu-item index="/Layout/hosList"
- ><i class="el-icon-link">i>医院列表
- >
- <el-menu-item index="/Layout/deptList"
- ><i class="el-icon-link">i>科室列表
- >
- el-menu-item-group>
- el-submenu>
- <el-submenu index="5">
- <template slot="title">
- <i class="el-icon-office-building">i>
- <span style="font-size: 17px; font-weight: bold;font-family:'苹方'">疫苗模块span>
- template>
- <el-menu-item-group>
- <el-menu-item index="/Layout/vaccineType"
- ><i class="el-icon-link">i>疫苗种类
- >
- <el-menu-item index="/Layout/vaccine"
- ><i class="el-icon-link">i>疫苗信息
- >
- <el-menu-item index="/Layout/appVaccineList"
- ><i class="el-icon-link">i>可预约疫苗
- >
- el-menu-item-group>
- el-submenu>
- el-menu>
- div>
- template>
- <style>
- .icon1 {
- display: inline-block;
- width: 50px;
- height: 50px;
- background-image: url("../assets/BUTTON_NOOPEN.png");
- background-position: center center;
- background-repeat: no-repeat;
- }
- .icon_line {
- display: block;
- width: 20px;
- height: 20px;
- background-image: url("../assets/line1.png");
- position: relative;
- left: 75px;
- background-repeat: no-repeat;
- }
- style>
-
- <script>
- import Cookies from "js-cookie";
- import request from "@/utils/request";
- export default {
- data() {
- return {
- //path变量
- path: this.$route.path,
- role: "",
- userId: "",
- timer: null,
- };
- },
- //生命周期【当页面对象创建成功,触发的函数】
- created() {
- //获取manager信息
- var userJson = JSON.parse(Cookies.get("user"));
- this.role = Cookies.get("role");
- console.log("this.role="+this.role);
- this.userId = userJson.id;
- // 启动定时器,每5秒钟检查一次
- this.timer = setInterval(this.checkDatabaseChanges, 5000);
- },
- methods: {
- //获取数据库最新数据,持续更新cookie
- checkDatabaseChanges() {
- //判断是哪种用户
- let url =
- this.role == "manager"
- ? "/manager/selectById"
- : this.role == "doctor"
- ? "/doctor/selectById"
- : "/user/selectById";
- // 通过请求获取最新的数据
- request
- .get(url, {
- params: {
- id: this.userId,
- },
- })
- //回调函数
- .then((res) => {
- if (res.flag == true) {
- //更新Cookie值
- Cookies.set("user", JSON.stringify(res.user), { expires: 0.3 });
- }
- });
- },
- handleOpen(key, keyPath) {
- console.log(key, keyPath);
- console.log("打开");
- },
- handleClose(key, keyPath) {
- console.log(key, keyPath);
- console.log("关闭");
- },
- },
- beforeDestroy() {
- // 销毁定时器
- clearInterval(this.timer);
- },
- };
- script>
--替换Header.vue
- <template>
- <div
- style="
- height: 65px;
- line-height: 65px;
- border-bottom: 1px solid #ccc;
- background-color: #254175;
- display: flex;
- "
- >
- <div
- style="
- width: 200px;
- padding-left: 30px;
- font-weight: bold;
- color: dodgerblue;
- "
- >
- <img
- src="../assets/logo-06.png"
- style="width: 200px; height: 50px; padding-top: 5px"
- alt=""
- />
- div>
- <div style="flex: 1">div>
- <div style="width: 250px">
- <el-dropdown @command="handleCommand">
- <span class="el-dropdown-link">
- <el-row :gutter="5">
- <el-col :span="12" style="padding-top: 9px;"><el-avatar :src="image" shape="square" :size="50">el-avatar>el-col>
- <el-col :span="9" style="color:#fff;font-weight: bold;">{{ name }}el-col>
- <el-col :span="3" style="color:#fff;font-weight: bold;"><i class="el-icon-arrow-down el-icon--right">i>el-col>
- el-row>
- span>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item command="a" v-if="role !== 'manager'"
- >个人信息
- >
- <el-dropdown-item command="b">退出系统el-dropdown-item>
- el-dropdown-menu>
- el-dropdown>
- div>
- div>
- template>
-
- <script>
- import router from "@/router";
- import Cookies from "js-cookie";
- export default {
- name: "Header",
- data() {
- return {
- name: "未登录",
- image: "",
- role: "",
- };
- },
- created() {
- //获取登录用户信息
- var userJson = JSON.parse(Cookies.get("user"));
- this.name = userJson.name;
- this.image = userJson.image;
- this.role = Cookies.get("role");
- },
- methods: {
- handleCommand(command) {
- if (command == "b") {
- Cookies.remove("user");
- //跳转到登录
- router.push("/login");
- } else {
- //跳转到个人信息
- router.push("/Layout/personalInfo");
- }
- },
- },
- };
- script>
--修改后端UserController中-的登录请求要返回user的对象数据、用户的角色
- // 在结果集中保存user对象以及角色信息
- result.put("user", user);
- result.put("role", "user");
--登录页面的登录函数中存储user和role角色信息

--重新登录测试即可
九、实现疫苗分类的查询及分析流程
--后端:VaccineType实体类中添加主键变量

- /**
- * 主键
- */
- @TableId(type = IdType.AUTO)
- private Integer id;
--后端:VaccineTypeController中定义查询请求接口
- @RestController
- @RequestMapping("/vaccinetype")
- public class VaccineTypeController {
-
- //json
- ObjectMapper json = new ObjectMapper();
-
- //service
- @Autowired
- IVaccineTypeService typeService;
-
- // 测试 http://localhost:8085/vaccinetype/query
- //查询分类、响应json数据【键值对的数据】
- @RequestMapping("/query")
- public String query() throws JsonProcessingException {
- //结果的存放集合
- HashMap result = new HashMap();
- // 1\调用业务层方法执行查询操作
- List
list = typeService.list(); - // 2\在结果集中存放list集合
- result.put("list", list);
- // 返回json数据
- return json.writeValueAsString(result);
- }
-
- }
--前端:在src下创建type文件夹,然后创建TypeList.vue

--前端:从element-ui中获取组件代码、提供请求操作和修改table中的字段名
- <template>
- <el-table :data="tableData" stripe style="width: 100%">
- <el-table-column prop="id" label="编号"> el-table-column>
- <el-table-column prop="name" label="名称"> el-table-column>
- <el-table-column prop="remark" label="描述"> el-table-column>
- el-table>
- template>
-
- <script>
- import request from "@/utils/request.js";
- export default {
- data() {
- return {
- tableData: [],
- };
- },
- // 页面中的vue对象创建成功后触发
- created() {
- //发起查询请求
- request
- .get("/vaccinetype/query") //第一个参数是请求地址、第二个参数提交的数据 //回调函数\获取服务器响应的结果
- .then((res) => {
- this.tableData = res.list;
- });
- },
- };
- script>
--前端:修改路由、在Layout路径下配置子url的映射【router中的index.js文件】
- import Vue from 'vue'
- import Router from 'vue-router'
- //导入局部的页面Layout
- import Layout from '@/components/Layout'
- import Login from '@/components/Login'
- Vue.use(Router)
- export default new Router({
- routes: [
- // 也就是-- / 映射到了 Login的页面
- {
- path: '/',
- name: 'Login',
- component: Login
- },
- // 页面布局的映射
- {
- path: '/Layout',
- name: 'Layout',
- component: Layout,
- children: [
- {
- path: 'vaccineType',// --> /Layout/vaccineType
- name: 'vaccineType',
- component: ()=>import('@/type/TypeList')
- },
- ],
- }
- ]
- })

十、疫苗分类--页面完善、以及添加、修改及删除实现
--后端:在VaccineTypeController中提供删除、添加和修改的请求接口
- @RestController
- @RequestMapping("/vaccinetype")
- public class VaccineTypeController {
-
- //依賴VaccineType业务层对象
- @Autowired //自动注入
- IVaccineTypeService typeService;
-
- //json 的解析工具
- ObjectMapper jsonTool = new ObjectMapper();
-
- // http://localhost:8085/vaccinetype/query
- // 定义查询的请求接口
- @RequestMapping("/query")
- public String query(String phone,String password) throws JsonProcessingException {
- // map集合-结果集
- HashMap result =new HashMap();
- //調用业务层的查询方法
- List
list = typeService.list(); - result.put("list",list);
- //返回json格式的数据
- return jsonTool.writeValueAsString(result);
- }
-
- // http://localhost:8085/vaccinetype/update
- // 定义修改的请求接口
- @RequestMapping("/update")
- public String update(VaccineType type) throws JsonProcessingException {
- // map集合-结果集
- HashMap result =new HashMap();
- //調用业务层的查询方法
- boolean update = typeService.updateById(type);
- result.put("flag",update);
- //返回json格式的数据
- return jsonTool.writeValueAsString(result);
- }
-
- // http://localhost:8085/vaccinetype/insert
- // 定义添加的请求接口
- @RequestMapping("/insert")
- public String insert(VaccineType type) throws JsonProcessingException {
- // map集合-结果集
- HashMap result =new HashMap();
- //調用业务层的查询方法
- boolean insert = typeService.save(type);
- result.put("flag",insert);
- //返回json格式的数据
- return jsonTool.writeValueAsString(result);
- }
-
- // http://localhost:8085/vaccinetype/insert
- // 定义刪除的请求接口
- @RequestMapping("/delete")
- public String delete(Integer id) throws JsonProcessingException {
- // map集合-结果集
- HashMap result =new HashMap();
- //調用业务层的查询方法
- boolean delete = typeService.removeById(id);
- result.put("flag",delete);
- //返回json格式的数据
- return jsonTool.writeValueAsString(result);
- }
-
- }
--替换TypeList.vue页面即可、效果如下:

- <template>
- <div style="width: 100%">
- <div class="top_div">
-
- <el-form
- :inline="true"
- class="demo-form-inline"
- style="padding-top: 22px"
- >
-
- <el-form-item v-if="role == 'manager' || role == 'nurse'">
- <el-popconfirm
- title="删除后无法恢复,确定吗?"
- icon-color="red"
- @confirm="batch_delete()"
- >
- <el-button slot="reference" plain type="danger">批量删除el-button>
- el-popconfirm>
- el-form-item>
- <el-form-item>
- <el-input
- v-model="name"
- placeholder="请输入疫苗种类名关键字"
- >el-input>
- el-form-item>
- <el-form-item>
- <el-button
- type="primary"
- style="background-color: #254175"
- @click="selectPage"
- >查询
- >
- <el-button
- type="primary"
- style="background-color: #254175"
- @click="addOperate"
- >新增
- >
- el-form-item>
- el-form>
- div>
- <div class="botoom_div">
-
- <el-table
- :data="tableData"
- style="width: 100%"
- @selection-change="handleSelectionChange"
- >
-
- <el-table-column
- type="selection"
- width="55"
- v-if="role == 'manager' || role == 'nurse'"
- >el-table-column>
- <el-table-column prop="id" label="种类编号"> el-table-column>
- <el-table-column prop="name" label="种类名称" sortable>
- el-table-column>
- <el-table-column prop="remark" label="介绍">
- <template #default="scope">
- <el-popover
- placement="top-start"
- width="100"
- trigger="click"
- :content="scope.row.remark"
- >
- <el-button slot="reference" class="ellipsis-button">{{
- scope.row.remark
- }}el-button>
- el-popover>
- template>
- el-table-column>
-
- <el-table-column prop="status" label="状态">
- <template #default="scope">
- <el-tag type="success" v-if="scope.row.status == 1">正常el-tag>
- <el-tag type="danger" v-if="scope.row.status == 0">禁用el-tag>
- template>
- el-table-column>
-
- <el-table-column label="管理">
- <template #default="scope">
- <el-button
- size="small"
- v-if="scope.row.status == 1"
- type="danger"
- @click="updateStatus(scope.row)"
- >禁用
- >
- <el-button
- size="small"
- v-if="scope.row.status == 0"
- type="success"
- @click="updateStatus(scope.row)"
- >启用
- >
- template>
- el-table-column>
-
- <el-table-column label="操作">
- <template #default="scope">
- <el-button size="small" @click="handleEdit(scope.$index, scope.row)"
- >修改
- >
- <el-popconfirm
- title="删除后无法恢复,确定吗?"
- icon-color="red"
- @confirm="handleDelete(scope.$index, scope.row)"
- >
- <el-button slot="reference" size="small" type="danger"
- >删除
- >
- el-popconfirm>
- template>
- el-table-column>
- el-table>
-
- <el-dialog
- :title="!vaccineType.id ? '疫苗种类-添加' : '疫苗种类-修改'"
- :visible.sync="formVisible"
- :close-on-click-modal="false"
- >
- <el-form
- :model="vaccineType"
- status-icon
- :rules="rules"
- ref="addType"
- label-width="50px"
- class="demo-vaccineType"
- >
- <el-form-item label="编号" prop="id" v-if="vaccineType.id">
- <el-input v-model="vaccineType.id" disabled>el-input>
- el-form-item>
- <el-form-item label="种类名" prop="name">
- <el-input
- type="text"
- v-model="vaccineType.name"
- autocomplete="off"
- >el-input>
- el-form-item>
- <el-form-item label="介绍" prop="remark">
- <el-input
- type="textarea"
- v-model="vaccineType.remark"
- autocomplete="off"
- >el-input>
- el-form-item>
- <el-form-item>
- <el-button type="primary" @click="submitForm('addType')"
- >提交
- >
- <el-button @click="formVisible = false">取消el-button>
- el-form-item>
- el-form>
- el-dialog>
- div>
- div>
- template>
- <script>
- //导入request工具
- import request from "@/utils/request";
- import Cookies from "js-cookie";
- export default {
- data() {
- return {
- role: "",
- name: "", //模糊查询数据 //表格数据
- tableData: [],
- ids: [], //根据id批量删除存放的容器
- vaccineType: {
- id: "",
- name: "",
- remark: "",
- },
- rules: {
- name: [
- { required: true, message: "请输入疫苗种类名称", trigger: "blur" },
- ],
- remark: [
- { required: true, message: "请输入疫苗种类介绍", trigger: "blur" },
- ],
- },
- formVisible: false,
- };
- }, //当vue创建后,发起请求查询数据
- created() {
- if (Cookies.get("user")) {
- //获取登录用户角色
- var userJson = JSON.parse(Cookies.get("user"));
- this.role = userJson.role;
- }
- this.selectPage();
- },
- methods: {
- //分页-模糊查询函数
- selectPage() {
- //发送请求
- request
- .get("/vaccinetype/query", {
- params: {
- name: this.name,
- },
- })
- .then((res) => {
- //处理响应
- if (res.flag == false) {
- //查询失败
- this.$message.error(res.message);
- } else {
- this.$message.success("查询成功"); //将查询到的数据赋值到当前tableData中
- this.tableData = res.list;
- }
- });
- }, //当复选框状态改变时,自动调用该函数,将复选框选中的行的数据id存入ids数组中
- handleSelectionChange(selection) {
- //遍历selection数组,存储id值
- this.ids = selection.map((item) => item.id);
- }, //批量删除函数
- batch_delete(index, row) {
- if (this.ids != "") {
- request
- .get("/vaccinetype/batchDelete", {
- params: {
- ids: this.ids.toString(),
- },
- })
- .then((res) => {
- //处理响应
- if (res.flag == false) {
- //删除失败
- this.$message.error(res.message);
- } else {
- this.$message.success("删除成功");
- this.selectPage();
- }
- });
- } else {
- this.$message.error("请先选择需要删除的数据!");
- }
- }, //删除函数
- handleDelete(index, row) {
- request
- .get("/vaccinetype/delete", {
- params: {
- //参数
- id: row.id,
- },
- })
- .then((res) => {
- //处理响应
- if (res.flag == false) {
- //删除失败
- this.$message.error(res.message);
- } else {
- this.$message.success("删除成功");
- this.selectPage();
- }
- });
- }, //每页展示多少条
- handleSizeChange(val) {
- this.pageSize = val;
- this.selectPage();
- }, //当前页为多少页
- handleCurrentChange(val) {
- this.currentPage = val;
- this.selectPage();
- }, //打开添加表单
- addOperate() {
- this.formVisible = true; //对该表单项进行移除校验结果
- this.$refs.addType.resetFields();
- this.vaccineType = {
- id: "",
- name: "",
- remark: "",
- };
- }, //修改-添加表单提交函数
- submitForm(formName) {
- //validate校验代码
- this.$refs[formName].validate((valid) => {
- // ok--通过校验
- if (valid) {
- if (this.vaccineType.id) {//id存在则是进行修改操作
- request
- .post("/vaccinetype/update", this.vaccineType)
- .then((res) => {
- if (res.flag == false) {
- //修改失败
- this.$message.error(res.message);
- // 查询方法
- this.selectPage();
- } else {
- //修改成功
- this.formVisible = false;
- this.$message.success("修改成功");
- this.vaccineType = {
- id: "",
- name: "",
- remark: "",
- };
- this.selectPage();
- }
- });
- } else {//id不存在则是进行添加操作
- //发送请求
- request
- .post("/vaccinetype/insert", this.vaccineType)
- .then((res) => {
- //处理响应
- if (res.flag == false) {
- //添加失败
- this.$message.error(res.message);
- } else {
- this.$message.success("添加成功"); //关闭模态框
- this.formVisible = false; //清空数据
- this.vaccineType = {
- id: "",
- name: "",
- remark: "",
- }; //重新查询数据
- this.selectPage();
- }
- });
- }
- }
- });
- }, // 打开修改表单函数
- handleEdit(index, row) {
- //打开嵌套表单的修改对话框
- this.formVisible = true; //将数据进行回显
- this.vaccineType.id = row.id;
- this.vaccineType.name = row.name;
- this.vaccineType.remark = row.remark; //对该表单项进行移除校验结果 // this.$refs.addType.clearValidate();
- },
- },
- };
- script>
- <style>
- .top_div {
- border-radius: 15px;
- box-shadow: rgba(0, 0, 0, 0.32) 0px 2px 5px;
- margin-bottom: 50px;
- background-color: #fff;
- }
- .botoom_div {
- border-radius: 15px;
- padding-top: 25px;
- padding-bottom: 25px;
- box-shadow: rgba(0, 0, 0, 0.32) 0px 2px 5px;
- margin-bottom: 50px;
- background-color: #fff;
- }
- .ellipsis-button {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- height: 50px;
- max-width: 200px;
- /* 假设按钮最大宽度为100px,根据需要进行调整 */
- }
- style>
--重启后端服务进行测试、建议可以先新增一些数据,然后再测试修改和删除的操作
-
相关阅读:
通过股票数据接口如何看懂Level-2行情?
Spring5.3学习——from 官网 day1-1
2023 年《网络建设与运维》赛题解析
python开发MYSQL代理服务器
汽车IVI中控开发入门及进阶(二十四):杰发科技AC8015
30-cookie和session模式
datax使用笔记
各扫描方法原理及特点总结
spring boot 1.封装分页插件pagehelp并做统一做返回值 2.封装SQL 3.redis在mybatis里面使用(大综合)
7.20日 ksjsb上车说明及注意事项
-
原文地址:https://blog.csdn.net/dogxixi/article/details/133977509
-
最新文章
-
沪漂五周年了:我越来越迷茫了
Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
MySQL-Seconds_behind_master的精度误差
[MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
Agent OS :五种驯服不确定性的范式
PortSwigger SQL注入LAB11
数据库即时编译JIT
[Begin]AI Learn Data Day 0
深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU