HTML VUE

4 篇文章 0 订阅
3 篇文章 0 订阅

VUE

创建vue

我们再导入的时候选择第一个,第二个是压缩过得,会少的提示

在这里插入图片描述

注意文件名不可以为中文

webStorm 创建方式
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

vue 有两种方法

这里推荐上面注释掉的方法
这两种都是一样的,就是后面的东西只适配上面的一种
在这里插入图片描述

在这里插入图片描述

简写单击时间

这些都是不传值的方法

在这里插入图片描述

在这里插入图片描述

这里的方法的两种写法

在这里插入图片描述

下面是传值方法

在这里插入图片描述

在这里插入图片描述

双击事件

在这里插入图片描述

在这里插入图片描述

值改变时间
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

失去焦点
在这里插入图片描述

这里是输入了1,然后点击勒空白页面

在这里插入图片描述

键盘事件

在这里插入图片描述

输入值后按回车

在这里插入图片描述

练习 计数器

题目
css


body{
  background-color: #f5f5f5;
}
#app {
  width: 480px;
  height: 80px;
  margin: 200px auto;
}
.input-num {
  margin-top:20px;
  height: 100%;
  display: flex;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 4px 4px 4px #adadad;
  border: 1px solid #c7c7c7;
  background-color: #c7c7c7;
}
.input-num button {
  width: 150px;
  height: 100%;
  font-size: 40px;
  color: #ad2a27;
  cursor: pointer;
  border: none;
  outline: none;
  background-color:rgba(0, 0, 0, 0);
}
.input-num span {
  height: 100%;
  font-size: 40px;
  flex: 1;
  text-align: center;
  line-height: 80px;
  font-family:auto;
  background-color: white;
}
img{
  float: right;
  margin-top: 50px;
}

页面

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>计数器</title>
  <link rel="stylesheet" href="./css/index.css" />
</head>

<body>
  <!-- html结构 -->
  <div id="app">
    <!-- 计数器功能区域 -->
    <div class="input-num">
      <button >
        -
      </button>
      <span>1</span>
      <button >
        +
      </button>
    </div>
    
  </div>
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <!-- 编码 -->
  <script>
  // 创建Vue实例
  
  </script>
</body>

</html>

答案

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>计数器</title>
    <link rel="stylesheet" href="./css/index.css"/>
</head>

<body>
<!-- html结构 -->
<div id="app">
    <!-- 计数器功能区域 -->
    <div class="input-num">
<!--        <button @click="deletenum">-->
        <button @click="num--">
            -
        </button>
        <span>{{num}}</span>
<!--        <button @click="addnum">-->
        <button @click="num++">
            +
        </button>
    </div>

</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
<!-- 编码 -->

<script>
    // 创建Vue实例
    new Vue({
        el:"#app",
        data: {
            num:1
        },
        <!--复杂版-->
        // methods: {
        //     deletenum() {
        //         // 数字减一
        //         // num = num - 1;
        //         this.num--;
        //     },
        //     addnum() {
        //         // 数字加一
        //         num = num + 1;
        //     }
        // }
    })
</script>
</body>

</html>

数据绑定

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

双向绑定

实例1

在这里插入图片描述

在这里插入图片描述

实例2
这里点击按钮后所有的值会变成你好

在这里插入图片描述

在这里插入图片描述

对象数组

在这里插入图片描述

获取对象中对象的值

在这里插入图片描述

在这里插入图片描述

数组取值

在这里插入图片描述

在这里插入图片描述

遍历数组

在这里插入图片描述

循环行
在这里插入图片描述

在这里插入图片描述

h1
循环列
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

实例 记事本

页面

<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <title>小黑记事本</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <meta name="robots" content="noindex, nofollow" />
  <meta name="googlebot" content="noindex, nofollow" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>

<body>
  <!-- 主体区域 -->
  <section id="todoapp">
    <!-- 输入框 -->
    <header class="header">
      <h1>小黑记事本</h1>
      <input autofocus="autofocus" autocomplete="off" placeholder="请输入任务"
        class="new-todo" />
    </header>
    <!-- 列表区域 -->
    <section class="main">
      <ul class="todo-list">
        <li class="todo" >
          <div class="view">
            <span class="index"></span>
            <label></label>
            <button class="destroy" @click=""></button>
          </div>
        </li>
      </ul>
    </section>
    <!-- 统计和清空 -->
    <footer class="footer" >
      <span class="todo-count">
        <strong>1</strong> items left
      </span>
      <button class="clear-completed">
        Clear
      </button>
    </footer>
  </section>
  <!-- 底部 -->
  <footer class="info">
    
  </footer>
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
   
  </script>
</body>

</html>

js

const app = new Vue({
  el: "#todoapp",
  data: {
    //  总数据
    todoList: ["吃饭饭", "睡觉觉", "写代码"],
    //  输入的内容
    inputValue: "",
  },
  // 方法
  methods: {
    // 增加任务
    addTodo() {
      this.todoList.push(this.inputValue);
    },
    // 删除任务
    delTodo(index) {
      this.todoList.splice(index, 1);
    },
    clearTodo() {
      this.todoList = [];
    }
  }
});

css

html,
body {
  margin: 0;
  padding: 0;
}
body {
  background: #fff;
}
button {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 100%;
  vertical-align: baseline;
  font-family: inherit;
  font-weight: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
  line-height: 1.4em;
  background: #f5f5f5;
  color: #4d4d4d;
  min-width: 230px;
  max-width: 550px;
  margin: 0 auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 300;
}

:focus {
  outline: 0;
}

.hidden {
  display: none;
}

#todoapp {
  background: #fff;
  margin: 180px 0 40px 0;
  position: relative;
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}

#todoapp input::-webkit-input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#todoapp input::-moz-placeholder {
  font-style: italic;
  font-weight: 300;
  color: #e6e6e6;
}

#todoapp input::input-placeholder {
  font-style: italic;
  font-weight: 300;
  color: gray;
}

#todoapp h1 {
  position: absolute;
  top: -160px;
  width: 100%;
  font-size: 60px;
  font-weight: 100;
  text-align: center;
  color: rgba(175, 47, 47, .8);
  -webkit-text-rendering: optimizeLegibility;
  -moz-text-rendering: optimizeLegibility;
  text-rendering: optimizeLegibility;
}

.new-todo,
.edit {
  position: relative;
  margin: 0;
  width: 100%;
  font-size: 24px;
  font-family: inherit;
  font-weight: inherit;
  line-height: 1.4em;
  border: 0;
  color: inherit;
  padding: 6px;
  border: 1px solid #999;
  box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.new-todo {
  padding: 16px;
  border: none;
  background: rgba(0, 0, 0, 0.003);
  box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}

.main {
  position: relative;
  z-index: 2;
  border-top: 1px solid #e6e6e6;
}

.toggle-all {
  width: 1px;
  height: 1px;
  border: none; /* Mobile Safari */
  opacity: 0;
  position: absolute;
  right: 100%;
  bottom: 100%;
}

.toggle-all + label {
  width: 60px;
  height: 34px;
  font-size: 0;
  position: absolute;
  top: -52px;
  left: -13px;
  -webkit-transform: rotate(90deg);
  transform: rotate(90deg);
}

.toggle-all + label:before {
  content: "❯";
  font-size: 22px;
  color: #e6e6e6;
  padding: 10px 27px 10px 27px;
}

.toggle-all:checked + label:before {
  color: #737373;
}

.todo-list {
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 420px;
  overflow: auto;
}

.todo-list li {
  position: relative;
  font-size: 24px;
  border-bottom: 1px solid #ededed;
  height: 60px;
  box-sizing: border-box;
}

.todo-list li:last-child {
  border-bottom: none;
}

.todo-list .view .index {
  position: absolute;
  color: gray;
  left: 10px;
  top: 20px;
  font-size: 16px;
}

.todo-list li .toggle {
  text-align: center;
  width: 40px;
  /* auto, since non-WebKit browsers doesn't support input styling */
  height: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto 0;
  border: none; /* Mobile Safari */
  -webkit-appearance: none;
  appearance: none;
}

.todo-list li .toggle {
  opacity: 0;
}

.todo-list li .toggle + label {
  /*
		Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
		IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
	*/
  background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center left;
}

.todo-list li .toggle:checked + label {
  background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E");
}

.todo-list li label {
  word-break: break-all;
  padding: 15px 15px 15px 60px;
  display: block;
  line-height: 1.2;
  transition: color 0.4s;
}

.todo-list li.completed label {
  color: #d9d9d9;
  text-decoration: line-through;
}

.todo-list li .destroy {
  display: none;
  position: absolute;
  top: 0;
  right: 10px;
  bottom: 0;
  width: 40px;
  height: 40px;
  margin: auto 0;
  font-size: 30px;
  color: #cc9a9a;
  margin-bottom: 11px;
  transition: color 0.2s ease-out;
}

.todo-list li .destroy:hover {
  color: #af5b5e;
}

.todo-list li .destroy:after {
  content: "×";
}

.todo-list li:hover .destroy {
  display: block;
}

.todo-list li .edit {
  display: none;
}

.todo-list li.editing:last-child {
  margin-bottom: -1px;
}

.footer {
  color: #777;
  padding: 10px 15px;
  height: 20px;
  text-align: center;
  border-top: 1px solid #e6e6e6;
}

.footer:before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 50px;
  overflow: hidden;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6,
    0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6,
    0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

.todo-count {
  float: left;
  text-align: left;
}

.todo-count strong {
  font-weight: 300;
}

.filters {
  margin: 0;
  padding: 0;
  list-style: none;
  position: absolute;
  right: 0;
  left: 0;
}

.filters li {
  display: inline;
}

.filters li a {
  color: inherit;
  margin: 3px;
  padding: 3px 7px;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 3px;
}

.filters li a:hover {
  border-color: rgba(175, 47, 47, 0.1);
}

.filters li a.selected {
  border-color: rgba(175, 47, 47, 0.2);
}

.clear-completed,
html .clear-completed:active {
  float: right;
  position: relative;
  line-height: 20px;
  text-decoration: none;
  cursor: pointer;
}

.clear-completed:hover {
  text-decoration: underline;
}

.info {
  margin: 50px auto 0;
  color: #bfbfbf;
  font-size: 15px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  text-align: center;
}

.info p {
  line-height: 1;
}

.info a {
  color: inherit;
  text-decoration: none;
  font-weight: 400;
}

.info a:hover {
  text-decoration: underline;
}

/*
	Hack to remove background from Mobile Safari.
	Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio: 0) {
  .toggle-all,
  .todo-list li .toggle {
    background: none;
  }

  .todo-list li .toggle {
    height: 40px;
  }
}

@media (max-width: 430px) {
  .footer {
    height: 50px;
  }

  .filters {
    bottom: 10px;
  }
}

下面是页面截图,可以参考
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
答案

<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <title>小黑记事本</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <meta name="robots" content="noindex, nofollow" />
  <meta name="googlebot" content="noindex, nofollow" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>

<body>
  <!-- 主体区域 -->
  <section id="todoapp">
    <!-- 输入框 -->
    <header class="header">
      <h1>小黑记事本</h1>
      <input autofocus="autofocus" autocomplete="off" placeholder="请输入任务"
        class="new-todo" v-model="testmsg" @keyup.enter="addtestmsg"/>
    </header>
    <!-- 列表区域 -->
    <section class="main">
      <ul class="todo-list">
        <li class="todo" v-for="(x,i) in arr">
          <div class="view">
            <span class="index">{{i+1}}.</span>
            <label>{{x}}</label>
            <button class="destroy" @click="deleteArr(i)"></button>
          </div>
        </li>
      </ul>
    </section>
    <!-- 统计和清空 -->
    <footer class="footer" >
      <span class="todo-count">
        <strong>{{arr.length}}}</strong> items left
      </span>
      <button class="clear-completed" @click="clearArr">
        Clear
      </button>
    </footer>
  </section>
  <!-- 底部 -->
  <footer class="info">
    {{testmsg}}--{{arr}}
  </footer>
  <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  <script>
   new Vue({
     el:'#todoapp',
     data:{
       testmsg:'',
       arr:[]
     },
     methods:{
       addtestmsg(){
         // 添加数据到最后一位
         this.arr.push(this.testmsg)
       },
       clearArr(){
         // 清空数组
         this.arr = [];
       },
       deleteArr(v){
         console.log(v)
         this.arr.splice(v,1)
       }
     }
   })
  </script>
</body>

</html>

if 语句

在这里插入图片描述

在这里插入图片描述

if else

在这里插入图片描述

在这里插入图片描述

v-show

在这里插入图片描述

在这里插入图片描述

两者区别
if - else 的dom 对象是没有的,if -else 有多重分支
v-show 是有dom 对象的 ,v-show 是没有多重分支的
如下图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

下面提供代码可以自行尝试

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- if  (表达式)  true 执行 判断 -->
			
			<h1 v-if="true">hello......1</h1>
			<h1 v-if="1 == 1">hello.......2</h1>
			<h1 v-if="1 > 2">hello.......3</h1>
			<!-- if else   分支判断 -->
			<h1 v-if="num == 1"> if else .....1</h1>
			<h1 v-else-if ="num == 2"> if else .....2</h1>
			<h1 v-else-if ="num == 3"> if else .....3</h1>
			<h1 v-else> if else .....4</h1>
			<!-- v-show   显示隐藏    -->
			<!-- 1  不同   if 有多重判断 show 没有 -->
			<!-- 2  if 如果false dom没有了   show 如果false 的  dom 还是存在的  只是样式隐藏 -->
			<h1 v-show="true">v-show...1</h1>
			
			<br>
			<button @click="flagif = true">显示v-if</button>
			<!-- true的 反  就是false    false 的反值 就是true -->
			<button @click="flagif = !flagif">显示v-if</button>
			<h1 v-if="flagif">hello</h1>
			<br>
			<button @click="flagshow = !flagshow">显示v-show</button>
			<h1 v-show="flagshow">v-show...2</h1>
		</div>
		
		<script>
		 new Vue({
			 el:"#app",
			 data:{
				 num:4,
				 flagif:false,
				 flagshow:false
			 },
			 methods:{
				 
			 }
		 })
		</script>
	</body>
</html>

图片

在这里插入图片描述

在这里插入图片描述

上上面那张图片,会有问题,因为当数组长度到达-1或者数组的长度是就会出问题

在这里插入图片描述

改进版

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

详情代码

<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta http-equiv="X-UA-Compatible" content="ie=edge" />
		<title>图片切换</title>
		<link rel="stylesheet" href="./css/index.css" />
	</head>

	<body>
		<div id="mask">
			<div class="center">
				<h2 class="title">
					深圳创维校区环境{{index}}
				</h2>
				<!-- 图片 -->
				<!-- <img  alt="" src="images/02.jpg" /> -->
				<img alt="" :src="imgArr[index]" />
				<!-- 左箭头 -->
				<!-- <a href="javascript:void(0)" v-show="index!=0" @click="prev" class="left">
        <img src="./images/prev.png" alt="" />
      </a> -->
				<!-- <a href="javascript:void(0)" v-if="true" @click="index--" class="left"> -->
				<a href="javascript:void(0)" v-if="true" @click="index > 0 ?index-- : index = 10" class="left">
					<img src="./images/prev.png" alt="" />
				</a>
				<!-- 右箭头 -->
				<!-- index <10? index++ : index ?之前 index <10 表达式 为真的 就执行 :前面的 否则执行后面的 -->
				<!-- if else    if(index <10){index++}else{index} -->
				<a href="javascript:void(0)" v-show="true" @click="index <10? index++ : index = 0" class="right">
					<img src="./images/next.png" alt="" />
				</a>
			</div>
		</div>

		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

		<script>
			var app = new Vue({
				el: "#mask",
				data: {
					imgArr: [
						"./images/00.jpg",
						"./images/01.jpg",
						"./images/02.jpg",
						"./images/03.jpg",
						"./images/04.jpg",
						"./images/05.jpg",
						"./images/06.jpg",
						"./images/07.jpg",
						"./images/08.jpg",
						"./images/09.jpg",
						"./images/10.jpg",
					],
					index: 0
				},
				methods: {
					prev: function() {

					},
					next: function() {

					}
				},
			})
		</script>
	</body>

</html>

表单

在这里插入图片描述
演示代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<h1>用户注册</h1>
			用户名:<input placeholder="请输入用户名" v-model="userinfo.username" />
			<br>
			性别:<input type="radio" value="" name="sex" v-model="userinfo.sex" /><input type="radio" value="" name="sex" v-model="userinfo.sex" /><br>
			爱好:<input type="checkbox" value="游戏" v-model="userinfo.hobby" />游戏
			<input type="checkbox" value="篮球"   v-model="userinfo.hobby" />篮球
			<input type="checkbox" value="足球"   v-model="userinfo.hobby" />足球
			<input type="checkbox" value="电影"   v-model="userinfo.hobby" />电影
			<br>
			班级:<select  v-model="userinfo.cla" >
				<option value="班级1">班级1</option>
				<option value="班级2">班级2</option>
				<option value="班级3">班级3</option>
			</select>
			<br>
			自我介绍:<textarea rows="5" cols="30"  v-model="userinfo.remark" ></textarea>
			<br>
			生日:<input type="date"  v-model="userinfo.udate" />
			<br>
			<button @click="registerUser">注册</button>
			<br>
		</div>
		
		<script>
		 new Vue({
			 el:"#app",
			 data:{
				 // 数据绑定   v-model
				 userinfo:{
					 username:'',
					 sex:'',
					 hobby:[],
					 cla:'',
					 remark:'',
					 udate:''
				 }
			 },
			 methods:{
				 registerUser(){
					 console.log("用户信息:",this.userinfo)
				 }
			 }
		 })
		</script>
	</body>
</html>

跨越

一、为什么会出现跨域问题
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

二、什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

当前页面url 被请求页面url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 否 同源(协议、域名、端口号相同)
http://www.test.com/ https://www.test.com/index.html 跨域 协议不同(http/https)
http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口号不同(8080/7001)
三、非同源限制
【1】无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB

【2】无法接触非同源网页的 DOM

【3】无法向非同源地址发送 AJAX 请求

示例

不包含注册

前端页面

注意需要这些文件
在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/jquery-1.8.2.min.js" type="text/javascript"></script>
	</head>
	<body>
		<div id="app">
			<h1>用户注册</h1>
			用户名:<input placeholder="请输入用户名" v-model="userinfo.username" />
			<br>
			性别:<input type="radio" value="" name="sex" v-model="userinfo.sex" /><input type="radio" value="" name="sex" v-model="userinfo.sex" /><br>
			爱好:<input type="checkbox" value="游戏" v-model="userinfo.hobby" />游戏
			<input type="checkbox" value="篮球"   v-model="userinfo.hobby" />篮球
			<input type="checkbox" value="足球"   v-model="userinfo.hobby" />足球
			<input type="checkbox" value="电影"   v-model="userinfo.hobby" />电影
			<br>
			班级:<select  v-model="userinfo.cla" >
				<option value="班级1">班级1</option>
				<option value="班级2">班级2</option>
				<option value="班级3">班级3</option>
			</select>
			<br>
			自我介绍:<textarea rows="5" cols="30"  v-model="userinfo.remark" ></textarea>
			<br>
			生日:<input type="date"  v-model="userinfo.udate" />
			<br>
			<button @click="registerUser">注册</button>
			<br>
		</div>
		
		<script>
		 new Vue({
			 el:"#app",
			 data:{
				 // 数据绑定   v-model
				 userinfo:{
					 username:'',
					 sex:'',
					 hobby:[],
					 cla:'',
					 remark:'',
					 udate:''
				 }
			 },
			 methods:{
				 registerUser(){
					 console.log("用户信息:",this.userinfo)
					 // 1   jquery  ajax 异步请求 
					 $.ajax({
						 //   url  服务器的 接口地址
						 url:'http://localhost:8080/users/add',
						 //   data   参数
						 data:this.userinfo,
						 //   回调函数   服务器返回的数据
						 success:function(d){
							 console.log(d)
						 }
					 })
				 }
			 }
		 })
		</script>
	</body>
</html>

后端代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>vue-java</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>vue-java</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

跨域请求设置

CrossConfig

package com.example.config;


import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Description
 * @Autor 伍军
 * @Date 2021/9/13 15:01
 * @Version 1.0
 **/
@Configuration
//@EnableTransactionManagement
public class CrossConfig implements WebMvcConfigurer {
    @Override
//      java  配置 跨域请求的设置
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")/*所有的当前站点的请求地址,都支持跨域访问*/
                .allowedOrigins("*")/*所有的外部域都可跨域访问*/
                //.allowedOriginPatterns("*")
                .allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")/*哪些请求 需要跨域配置*/
                .allowCredentials(false) /*是否支持跨域用户凭证*/
                .maxAge(3600)/*超时时长设置为6分钟。 时间单位是秒。*/
                .allowedHeaders("*");/*请求体的头部*/
    }

//    @Bean
//    public PaginationInterceptor paginationInterceptor(){
//        return new PaginationInterceptor();
//    }
//
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }
//
//    @Bean
//    public MybatisPlusInterceptor mybatisPlusInterceptor(){
//        MybatisPlusInterceptor mi = new MybatisPlusInterceptor();
//        mi.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//        return mi;
//    }
//
//    @Value("${staticpath}")
//    String urlpath;
//    @Value("${uploadpath}")
//    String localpath;
//
//    @Override
//    public void addResourceHandlers(ResourceHandlerRegistry registry) {
//        System.out.println(urlpath);
//        System.out.println(localpath);
//        //  addResourceHandler  请求路径
//        //  addResourceLocations  具体的文件路径
//        registry.addResourceHandler(urlpath).addResourceLocations(localpath);
        registry.addResourceHandler("/file/**").addResourceLocations("file:D:/img/");
//    }
}

MybatisConfig

ssm xml 配置文件

package com.example.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
// == ssm 中  xml 配置文件
public class MybatisConfig {

//    @Bean
     <bean>
//    public PaginationInnerInterceptor paginationInnerInterceptor(){
//        return new PaginationInnerInterceptor();
//    }

    @Bean
    public MybatisPlusInterceptor plusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}

TestController

package com.example.controller;

import com.example.model.Users;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/*
*  用来测试  vue 用户注册  异步请求
* */

@RestController
// controller  responesbody
@RequestMapping("/users")
public class TestController {

    @RequestMapping("/add")
    public boolean register(Users users){
        System.out.println(users);
        return false;
    }
}

UserControlle

package com.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.dao.UserDao;
import com.example.model.UserInfoTest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

// @RestController  =  @controller + @ responsebody
@RestController
public class UserControlle {

    @Resource
    UserDao userDao;

    @RequestMapping("/list")
    public Object list(String name,Integer rows,Integer page){
        System.out.println("list............"+name+rows+page);
        QueryWrapper<UserInfoTest> qw = new QueryWrapper<>();
        if("".equals(name) || name == null){

        }else{
//            like 模糊查询
            qw.like("name",name);
        }
//        List<UserInfo> userInfos = userDao.selectList(qw);
        // 分页方法  selectpage
        Page<UserInfoTest> pages = new Page<>(page,rows);// page 表示当前的页数  rows 表示返回的数据个数
        Page<UserInfoTest> userInfoPage = userDao.selectPage(pages, qw);
        return userInfoPage;
    }
}

UserInfoTest

这些是bean ,这里需要 这个插件

在这里插入图片描述

package com.example.model;

import lombok.Data;

@Data
public class UserInfoTest {

    private Integer id;
    private String name;
    private String pwd;
}

package com.example.model;

import lombok.Data;

import java.util.List;

@Data
public class Users {
    private Integer id;
    private String username ;
    private String sex;
    private List<String> hobby;
    private String cla;
    private String remark;
    private String udate;
}

配置文件

application.properties



spring.datasource.url=jdbc:mysql://localhost:3306/test220707?serverTimezone=GMT
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root123

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

vue 脚手架

上面的项目不是独立的项目,不可以独立运行

sh

在这里插入图片描述

选择版本进行安装

安装完后

在这里插入图片描述

设置缓存文件夹

在这里插入图片描述

npm config set cache “D:\Program Files\nodejs\node_cache”
npm config set prefix “D:\Program Files\nodejs\node_global”

npm config set cache “D:\Program Files\nodejs\node_cache” 报错 有两个原因 1 nodejs安装有问题 2 cmd 命令行 系统 必须用管理员打开

镜像下载

npm install -g cnpm --registry=https://registry.npm.taobao.org

这样就好了
在这里插入图片描述

设置环境变量

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

安装vue

cnpm install vue -g

在这里插入图片描述

安装vue 命令行工具,即 vue-cli 脚手架

cnpm install vue-cli -g

在这里插入图片描述

存放项目

在这里插入图片描述

创建项目

vue init webpack 项目名称

在这里插入图片描述

在这里插入图片描述
完成后回车,会自动下载项目

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

直接点击这个就可以进入了
手动输入也可以

http://localhost:8080/#/

在这里插入图片描述

在这里插入图片描述

修改端口号避免和idea 重复

autoOpenBrowser 这个是自动打开游览器 把这个改成 true

在这里插入图片描述

文件

在这里插入图片描述

导入axios 和 vue-router

npm install vue-router
cnpm install axios

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

import Axios from 'axios'


//  vue 自定义的一个变量   把引入进来的Axios赋值给变量  代码用变量来使用
Vue.prototype.$axios = Axios;

创建文件

在这里插入图片描述

在这里插入图片描述

login.vue 文件

<template>
<div>
  用户名: <input type="text" placeholder="请输入用户名">
  密码: <input type="text" placeholder="请输入密码">
</div>
</template>

<script>
export default {
  name: "login"
}
</script>

<style scoped>

</style>

这样打开是什么都没有的

在这里插入图片描述

添加路由
需要添加 index.js 里面的路径

在这里插入图片描述

在这里插入图片描述

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

import login from '@/components/login'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },

    {
      path: '/login',
      name: 'login',
      component: login
    }
  ]
})


可以看见都有了

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
然后在使用异步

这里不适用ajax,用刚刚导入的 axios

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

写了 err 后会在控制台输出
在这里插入图片描述

完整代码

<template>
  <div>
    用户名: <input type="text" placeholder="请输入用户名" v-model="user.name">
    密码: <input type="text" placeholder="请输入密码" v-model="user.pwd">
    <button @click="login">登录</button>
  </div>
</template>

<script>
export default {
  methods: {
    login() {
      console.log(this.user)
      this.$axios.get("http://localhost:8080/login"
        ,{params:this.user}).then(function (d){
        console.log(d) // success
        if (d.data){
          location.href = "/"
        }else{
          alert("登录失败")
        }
      },function (e){
        console.log(e) // err
      })
    }
  },

  mounted() {

  },

  data() {
    return {
      msg: "123",
      user:{
        name:'',
        pwd:''
      }
    }
  }
}
</script>

<style scoped>

</style>

使用最上面的项目 vue -java

在userController里添加代码

 @RequestMapping("/login")
    public boolean login(Userinfotest userInfo) {
        System.out.println(userInfo);
//        获取登录信息   查询数据库  如果登陆成功 返回true  失败 返回false
        QueryWrapper<Userinfotest> qw = new QueryWrapper<>();
        qw.eq("name", userInfo.getName());
        qw.eq("pwd", userInfo.getPwd());
        Userinfotest userInfo1 = userDao.selectOne(qw);
        if (userInfo1 == null) {
            return false;
        }
        return true;
    }

在这里插入图片描述

路径

在这里插入图片描述

在这里插入图片描述

修改登录页面

页面文件见
vue 修改登录页面文件123

在这里插入图片描述


import './assets/css/global.css'
import './assets/fonts/iconfont.css'

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里样式还是不行,需要添加东西

cnpm i element-ui -S

在这里插入图片描述

在 main.js 里面添加代码

//引入element-ui 组件
import ElementUI from 'element-ui'
//引入element-ui 的样式
import 'element-ui/lib/theme-chalk/index.css'
//全局加载element-ui 组件
Vue.use(ElementUI)

在这里插入图片描述

登录和注册页面

<template>
  <div class="login_container">
    <!-- 登录盒子  -->
    <div class="login_box">
      <!-- 头像 -->
      <div class="avatar_box">
        <img src="../assets/logo.png" alt="">
      </div>
      <!-- 登录表单 -->
      <el-form :model="loginForm" ref="LoginFormRef" label-width="0px" class="login_form">
        <!-- 用户名 -->
        <el-form-item prop="username">
          <el-input placeholder="请输入用户名" v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
        </el-form-item>
        <!-- 密码 -->
        <el-form-item prop="password">
          <el-input placeholder="请输入密码" type="password" v-model="loginForm.password"
                    prefix-icon="iconfont icon-3702mima"></el-input>
        </el-form-item>
        <el-form-item prop="checkcode">
          <el-input placeholder="请输入验证码" v-model="checkcode" prefix-icon="iconfont icon-3702mima"></el-input>
        </el-form-item>

        <canvas class="mycanvas" width="80" height="30" @click="changecode">抱歉,您的浏览器不支持canvas元素,换个浏览器试试?</canvas>
        {{ message }}
        <!-- 按钮 -->
        <el-form-item class="btns">
          <el-button type="primary" @click="login">登录</el-button>
          <el-button type="info" @click="resetLoginForm">重置</el-button>
          <el-button type="primary" @click="toregister">注册</el-button>
        </el-form-item>
      </el-form>
    </div>


    <!-- 添加用户dialog对话框 -->
    <!-- :visible.sync  v-if v-show  -->
    <el-dialog align="left" title="添加用户" :visible.sync="addUserVisible" width="50%" @close="">
      <!--主体部分 -->
      <el-form status-icon ref="addUserFormRel" label-width="100px" class="demo-ruleForm">
        <el-form-item label="用户名" prop="userName">
          <el-input v-model="addUserForm.username" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="userPwd">
          <el-input type="password" v-model="addUserForm.password" autocomplete="off"></el-input>
        </el-form-item>


      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="addUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="adduser">确 定</el-button>
      </span>
    </el-dialog>

  </div>
</template>

<script>
export default {
  data() {
    return {
      //数据绑定
      loginForm: {
        id: "1",
        username: 'admin',
        password: '123'
      },

      checkcode: "",
      value: "",
      code: "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
      message: "",
      addUserVisible: false,

      addUserForm: {
        username: "",
        password: "",
      },
    }
  },
  //添加行为,
  methods: {
    adduser() {
      console.log(this.addUserForm)
      let url = "http://localhost:8080/adduser";
      this.$axios.get(url, {params: this.addUserForm}).then(
        (d) => {
          if (d.data) {
            alert("添加成功");
          } else {
            alert("添加失败");
          }
          this.addUserVisible = false;
        }
      )
    },
    getrolelist() {

    },
    toregister() {
      //this.getrolelist();
      this.addUserVisible = true;
    },
    login() {
      console.log(this.loginForm)
      console.log("----" + this.checkcode)
      console.log("****" + this.value)
      if (this.checkcode.toLowerCase() === this.value.toLowerCase()) {
        this.message = "验证码正确"
        // 异步请求
        let url = "http://localhost:8080/login";
        this.$axios.get(url, {params: this.loginForm}).then(
          (d) => {
            // d 服务器返回的数据
            console.log(d)
            if (d.data == '' || d.data == null) {
              this.message = "用户名或者密码错误"
            } else {
              this.message = "登录成功"
              // location.href="/"
              this.$router.push({path: "/home", query: d.data})
            }
          }
        );
      } else {
        this.message = "验证码错误"
      }

    },
    resetLoginForm() {
      this.loginForm.username = "";
      this.loginForm.password = "";
      this.checkcode = '';
    },
    changecode() {
      this.fourCode();
    },
    randomColor() {
      //得到随机的颜色值
      var r = Math.floor(Math.random() * 256);
      var g = Math.floor(Math.random() * 256);
      var b = Math.floor(Math.random() * 256);
      return "rgb(" + r + "," + g + "," + b + ")";
    },
    fourCode() {
      this.value = "";
      for (let a = 0; a < 4; a++) {
        this.value += this.code1();
      }
      this.doDraw();
    },
    code1() {
      let index = Math.floor(Math.random() * (this.code.length - 1) + 1);
      return this.code[index];
    },
    doDraw() {
      var x = 20;
      var y = 20 + Math.random() * 8;
      var deg = (Math.random() * 30 * Math.PI) / 180;
      //  获取canvas
      var canvas = document.getElementsByClassName("mycanvas");
      canvas[0].width = canvas[0].width; //清空画布
      canvas[0].height = canvas[0].height;
      var canvas_width = canvas[0].width;
      var canvas_height = canvas[0].height;
      var context = canvas[0].getContext("2d");
      context.font = "bold 23px 微软雅黑";
      context.fillText(this.value, 15, 30);
      context.translate(x, y); //canvas原点的偏移量
      context.rotate(deg); //旋转度数
      context.fillStyle = this.randomColor(); //设置颜色
      context.strokeStyle = this.randomColor(); //设置颜色
      context.rotate(-deg);
      context.translate(-x, -y);
      for (var i = 0; i <= 15; i++) {
        //验证码上显示线条
        context.strokeStyle = this.randomColor(); //轮廓风格
        context.beginPath();
        context.moveTo(
          Math.random() * canvas_width,
          Math.random() * canvas_height
        );
        context.lineTo(
          Math.random() * canvas_width,
          Math.random() * canvas_height
        );
        context.stroke();
      }
      for (var i = 0; i <= 30; i++) {
        //验证码上显示小点
        context.strokeStyle = this.randomColor();
        context.beginPath(); //新建一条路径
        var x = Math.random() * canvas_width;
        var y = Math.random() * canvas_height;
        context.moveTo(x, y); //吧画笔移动到指定位置
        context.lineTo(x + 1, y + 1); //想指定位置移动
        context.stroke();
      }
    },

  },
  mounted() {
    this.fourCode();
    this.checkcode = this.value
  }
}
</script>

<style scoped>
.login_container {
  background-color: #2b5b6b;
  height: 100%;
}

.login_box {
  width: 450px;
  height: 300px;
  background: #fff;
  border-radius: 3px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

}

.avatar_box {
  height: 130px;
  width: 130px;
  border: 1px solid #eee;
  border-radius: 50%;
  padding: 10px;
  box-shadow: 0 0 10px #ddd;
  position: absolute;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;

}

.avatar_box img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #eee;
}

.login_form {
  position: absolute;
  bottom: 0;
  width: 100%;
  padding: 0 20px;
  box-sizing: border-box;
}

.btns {
  display: flex;
  justify-content: flex-end;
}

.mycanvas {
  border: 1px solid rgb(199, 198, 198);
  border-radius: 20%;
}
</style>

后台代码

 @RequestMapping("/login")
    public Userinfotest login(Userinfotest userInfo) {
        System.out.println(userInfo);
//        获取登录信息   查询数据库  如果登陆成功 返回true  失败 返回false
        QueryWrapper<Userinfotest> qw = new QueryWrapper<>();
        qw.eq("username", userInfo.getUsername());
        qw.eq("password", userInfo.getPassword());
        return userDao.selectOne(qw);
    }

主页

<template>
  <div class="home-container">
    <el-container>
      <el-header>
        <div>
          <img src="../assets/logo.png" />
          <span>租房管理系统</span>
          <span>用户名:{{user.username}}</span>

        </div>

        <el-button @click="loginOut">退出</el-button>
      </el-header>
      <el-container>
        <el-aside :width="isCollapse ? '60px':'200px'">
          <div style="color: #fff;" @click="isCollapse=!isCollapse">|||</div>
          <!-- 导航菜单 -->
          <el-menu default-active="2" class="el-menu-vertical-demo" background-color="#333744" text-color="#fff"
            :unique-opened="true" :collapse="isCollapse" :router="true" :default-active="activePath"
            :collapse-transition="false" active-text-color="#ffd04b">
            <!-- 一级菜单 -->
            <el-submenu :index="item.menu.menuId+''" v-for="item in menulists" :key="item.menu.menuId">
              <template slot="title">
                <i :class="objicon[item.menu.menuId]"></i>
                <span>{{item.menu.menuName}}</span>
              </template>
              <!-- 二级菜单  -->
              <el-menu-item :index="'/'+item2.menuUrl" v-for="item2 in item.children" :key="item2.menuId"
                @click="activeSave('/'+item2.menuUrl)">
                <template slot="title">
                  <i class="el-icon-menu"></i>
                  <span> {{item2.menuName}}</span>
                </template>
              </el-menu-item>
            </el-submenu>

          </el-menu>

        </el-aside>
        <el-main>
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
  export default {
    name: 'Home',
    data() {
      return {
        //左侧菜单
        menulists: [{menu:{menuId:1,menuName:'菜单1'},children:[{menuId:4,menuName:'菜单4',menuUrl:''}]},
        {menu:{menuId:2,menuName:'菜单2'} ,children:[{menuId:3,menuName:'菜单3',menuUrl:''}],
        }],
        objicon: {
          "125": 'iconfont icon-icon_user',
          "103": 'iconfont icon-shangpin',
          "101": 'iconfont icon-danju',
          "102": 'iconfont icon-tijikongjian',
          "145": 'iconfont icon-baobiao'
        },
        //是否水平折叠菜单
        isCollapse: false,
        //当前激活的路径
        activePath: '',
        user:{}
      }
    },
    methods: {
      getPowerByUserId() {

      },
      //退出登录
      loginOut() {
        window.sessionStorage.clear();
        this.$router.push({
          path: '/login'
        })
      },
      //点击导航,有激活的状态
      activeSave(path) {
        this.activePath = path;
        window.sessionStorage.setItem('activePath', path);
      },

    },
    mounted() {
      this.user =this.$route.query;
      console.log("----",this.user)
    }

  }
</script>

<style scoped="scoped">
  .home-container {
    height: 100%;
    background: #c4c4c4;
  }

  .el-container {
    height: 100%;
  }

  .el-header {
    background: #333744;
    display: flex;
    justify-content: space-between;
    color: #fff;
    font-size: 20px;
  }

  .el-header img {
    vertical-align: middle;
    width: 60px;
    height: 65px;
  }

  .el-aside {
    background: #333744;
    height: 100%;
    box-sizing: border-box;
  }

  .el-main {
    background: #ececec;
  }
</style>

首页菜单

创建类

在这里插入图片描述

在这里插入图片描述

UserController

添加后端代码

在这里插入图片描述

创建Power 类

package com.example.model;

import lombok.Data;

@Data
public class Power {
    private Integer powerId;
    private String powerName;
    private String powerUrl;
    private Integer parentId;
    private Integer indexId;

}
//    CREATE TABLE `power` (
//        `power_id` int(11) NOT NULL AUTO_INCREMENT,
//        `power_name` varchar(255) DEFAULT NULL COMMENT '菜单名称',
//        `power_url` varchar(255) DEFAULT NULL COMMENT '菜单路径',
//        `parent_id` int(11) DEFAULT NULL COMMENT '父类id',
//        `index_id` int(11) DEFAULT NULL COMMENT '每一级菜单的下标',
//        PRIMARY KEY (`power_id`) USING BTREE
//        ) ENGINE=InnoDB

在userDao里面添加方法

在这里插入图片描述

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.model.Power;
import com.example.model.Userinfotest;

import java.util.List;

public interface UserDao extends BaseMapper<Userinfotest> {

    List<Power> getPowerByUserId(Integer userId);
}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.dao.UserDao">
    <select id="getPowerByUserId" resultType="com.example.model.Power">
        select u.*, p.*
        from user_info u
                 LEFT JOIN user_role ur on u.id = ur.user_id
                 LEFT JOIN role r on r.role_id = ur.role_id
                 LEFT JOIN role_power rp on r.role_id = rp.role_id
                 LEFT JOIN power p on p.power_id = rp.power_id
        where u.id = #{userId}
        order by u.id
    </select>
</mapper>

修改后端代码

在这里插入图片描述

 // 通过用户id 查询对应的菜单
    @RequestMapping("getPowerByUserId")
    public List<Menu> getPowerByUserId(Integer userId) {
        System.out.println("用户id:" + userId);
        // 获取菜单的方法
        List<Power> list = userDao.getPowerByUserId(userId);
//        list.forEach(System.out::println);
        List<Menu> menus = new ArrayList<>();
        // 如果查询不到任何菜单 就直接返回null
        if ( list == null || list.size() < 1 ){
            return null;
        }
        for (Power p1 : list) {
            if (p1 == null || p1.getPowerId() == null){
                break;
            }

            // 把一级菜单 添加到 返回对象里面
            if (p1.getParentId() == 0) {
                Menu menu = new Menu();
                MenuInfo menuInfo1 = new MenuInfo(); // 一级菜单的对象
                menuInfo1.setMenuId(p1.getPowerId());
                menuInfo1.setMenuName(p1.getPowerName());
//                : 1 ,用户管理,null,0,1
                menu.setMenu(menuInfo1);
                List<MenuInfo> children = new ArrayList<>();

                // 把二级菜单放到对应的一级菜单
                for (Power p2 : list) {
                    // 二级菜单
                    if (p2.getParentId() != 0 && p2.getParentId() == p1.getPowerId()) {
                        MenuInfo menuInfo2 = new MenuInfo();
                        menuInfo2.setMenuId(p2.getPowerId());
                        menuInfo2.setMenuName(p2.getPowerName());
                        menuInfo2.setMenuUrl(p2.getPowerUrl());
                        // 2,用户列表,userlist,1,1
                        children.add(menuInfo2);
                    }
                }
                menu.setChildren(children);
                menus.add(menu);
            }
        }
        return menus;
    }

在这里插入图片描述

用户列表

power

<template>
  <div>

    <!-- 面包屑内容 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>管理模块</el-breadcrumb-item>
      <el-breadcrumb-item>菜单权限列表</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 主体内容	 -->
    <el-card>
      <!-- 搜索区域 -->
      <el-row>
        <el-col :span="6">
          <el-input placeholder="请输入权限名" v-model="queryInfo.menuName" class="input-with-select" clearable
            @clear="getMenuList">
            <el-button slot="append" icon="el-icon-search" @click="getMenuList2"></el-button>
          </el-input>
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="openaddmenu">添加菜单权限</el-button>
        </el-col>
        <el-col :span="2">
          -
        </el-col>

      </el-row>

      <!-- 列表用户内容区域	 -->
      <el-table :data="menuList" border style="width: 100%">
        <el-table-column type="index" label="编号" width="60">
          <template slot-scope="scope">
            <!-- scope.$index  当前循环的 每一次index值  从0开始 -->
            <span>1</span>
          </template>
        </el-table-column>
        <el-table-column prop="menuName" label="菜单名称" width="120">
        </el-table-column>
        <el-table-column prop="menuUrl" label="菜单路径" width="120">
        </el-table-column>
        <el-table-column prop="" label="父级名称" width="120">
          <!-- levelfirstlist 一级菜单 -->
          <template slot-scope="scope" >
           <div v-for="x in levelfirstlist" v-if="x.menuId == scope.row.menuPid" >
             {{x.menuName}}
           </div>
            </template>
        </el-table-column>
        <el-table-column prop="" label="菜单级别" width="200">
          <template slot-scope="scope">
          {{scope.row.menuLevel == 1?'一级菜单':'二级菜单'}}
           </template>
        </el-table-column>
        <el-table-column prop="menuIndex" label="顺序id" width="120">
        </el-table-column>

        <el-table-column prop="address" label="操作">
          <template slot-scope="scope">
            <el-button type="primary" icon="el-icon-edit" size="mini" @click="toedituser(scope.row)"></el-button>
            <!-- <el-popconfirm title="确定删除吗"> -->
            <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteUser(scope.row)"></el-button>
            <!-- </el-popconfirm> -->

          </template>
        </el-table-column>
      </el-table>

      <!-- 分页功能 -->
      <el-pagination align="left" @size-change="SizeChange" @current-change="CurrentChange"
        :current-page="queryInfo.page" :page-sizes="[1,2,3,5]" :page-size="queryInfo.rows"
        layout="total, sizes, prev, pager, next, jumper" :total="total">
      </el-pagination>
    </el-card>

    <!-- 添加用户dialog对话框 -->
    <!-- :visible.sync  v-if v-show  -->
    <el-dialog align="left" title="添加权限" :visible.sync="addUserVisible" width="50%" @close="">
      <!--主体部分 -->
      <el-form status-icon  label-width="100px" class="demo-ruleForm">
        <el-form-item label="菜单名称" >
          <el-input v-model="addmenuForm.menuName" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="菜单级别" >
         <el-radio v-model="addmenuForm.menuPid" label="0" :disabled="editMenudis" >一级菜单</el-radio>
         <el-radio v-model="addmenuForm.menuPid" label="1" :disabled="editMenudis">二级菜单</el-radio>
        </el-form-item>
        <el-form-item label="一级菜单" v-if="addmenuForm.menuPid != 0" >
        <!-- <el-radio v-for="x in levelfirstlist" v-model="addmenuForm.menuPidval"
         :label="x.menuId" :key="x.menuId"
          >{{x.menuName}}</el-radio> -->
          <el-radio v-if="addmenuPid" v-for="x in levelfirstlist" v-model="addmenuEx"
          :label="x" :key="x.menuId"
           >{{x.menuName}}</el-radio>
           <el-radio v-if="editmenuPid" v-for="x in levelfirstlist" v-model="addmenuForm.menuPidval"
           :label="x.menuId" :key="x.menuId"
            >{{x.menuName}}</el-radio>
        </el-form-item>
        <el-form-item label="菜单路径" v-if="addmenuForm.menuPid != 0">
          <el-input v-model="addmenuForm.menuUrl" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="addUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="addmenu">确 定</el-button>
      </span>

      {{addmenuForm}}
    </el-dialog>

<!-- {{levelfirstlist}} -->
  </div>
</template>

<script>
  export default {
    data() {
      return {
        //搜索的neirong
        searchVal: '',
        //用户列表参数
        queryInfo: {
          menuName: '',
          page: 1,
          rows: 5
        },
        //用户列表
        menuList: null,
        //总的数据条数
        total: 0,
        addUserVisible: false,
        addmenuForm: {
          menuId:"",
          menuName: "",
          menuPid: '0',
          menuPidval:'',
          menuUrl:'',
          menuLevel:'1',
          menuIndex:''
        },
        addmenuEx:{},
        levelfirstlist:[],   //  所有的一级菜单
        powerVisible:false,
        url:'',
        editMenudis:false,
        addmenuPid:false,
        editmenuPid:false
      }
    },
    mounted() {
      this.getMenuList();
      this.getlevellist(1);
    },
    methods: {
      getlevellist(v){
        
      },
      toedituser(v){
        this.editMenudis = true;
        this.addmenuPid = false;
        this.editmenuPid = true;
        this.addUserVisible = true;
        this.addmenuForm.menuId = v.menuId;
        this.addmenuForm.menuName = v.menuName;
        this.addmenuForm.menuUrl = v.menuUrl;
        this.addmenuForm.menuLevel = v.menuLevel;
        this.addmenuForm.menuIndex = v.menuIndex;
        this.url = '/api/user/updateMenu';
        if(v.menuLevel == '1'){  // 一级菜单
          this.addmenuForm.menuPid = v.menuPid+'';
          this.addmenuForm.menuPidval = '';
        }else{ // 二级菜单
        //  把 父级id  赋值给  powerParentidval
        console.log(v.menuPid);
          this.addmenuForm.menuPidval = v.menuPid;
          //  把二级猜的 父类id  赋值 1
          this.addmenuForm.menuPid = '1';
          this.addmenuEx = ''
        }
      },
      deleteUser(v){
        let that = this;
        this.$confirm('此操作将永久删除该菜单, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {   // lambo 表达式 简写
          //alert(1)
          
        }).catch(function(){
          //alert(2)
        })
      },
      addmenu() {
        if (this.addmenuForm.menuName.trim() == '' || this.addmenuForm.menuPid.trim() == '') {
          //this.message = "用户名或者密码为空";
          alert("菜单名称或者父类菜单为空");
          return;
        }
        let that = this;
        // 调用后台  注册接口
        console.log(this.addmenuForm);
        console.log(this.url);
        if(this.addmenuEx == null || this.addmenuEx == ''){

        }else{
          this.addmenuForm.menuPidval = this.addmenuEx.menuId;
          this.addmenuForm.menuIndex = this.addmenuEx.menuIndex;
        }
       
      },
      openaddmenu() {
        this.addUserVisible = true;
        this.addmenuForm.menuName = '';
        this.addmenuForm.menuPid = '0';
        this.addmenuForm.menuPidval = '';
        this.addmenuForm.menuUrl = '';
        this.url = '/api/user/addmenu';
        this.addmenuForm.menuId = '';
        this.addmenuForm.menuIndex = '';
         this.editMenudis = false;
         this.addmenuPid = true;
         this.editmenuPid = false;
      },
      getMenuList2() {
        this.queryInfo.page = 1;
        this.getMenuList();
      },
      // 获取用户列表
      
      },
      //每页数据条数改变时触发
      SizeChange(newval) {
        this.queryInfo.rows = newval;
        this.getMenuList();
      },
      //当前页面改变时触发
      CurrentChange(newval) {
        this.queryInfo.page = newval;
        this.getMenuList();
      },

    }
  }
</script>

<style>
</style>

role

<template>
  <div>

    <!-- 面包屑内容 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>管理模块</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 主体内容	 -->
    <el-card>

      <!-- 列表用户内容区域	 -->
      <el-table :data="roleList" border style="width: 100%">
        <el-table-column type="index" label="编号" width="60">
          <template slot-scope="scope">
            <!-- scope.$index  当前循环的 每一次index值  从0开始 -->
            <span>1</span>
          </template>
        </el-table-column>
        <el-table-column prop="roleName" label="角色名" width="120">
        </el-table-column>
        <el-table-column prop="menuName" label="权限名" width="400">
        </el-table-column>
        <el-table-column prop="address" label="操作">
          <template slot-scope="scope">
            <!-- </el-popconfirm> -->
            <el-tooltip class="item" effect="dark" content="分配权限" placement="top">
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="toroleUser(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
</el-card>

 <!-- 分配角色diaolog对话框 -->
    <el-dialog align="left" title="分配权限" :visible.sync="editRoleVisible" width="50%">
      <!--主体部分 -->
      <div>
        <p>当前的角色:<strong>{{roleForm.roleName}}</strong></p>
        <p>当前的角色权限:<strong>{{roleForm.menuName}}</strong></p>

<span class="demonstration">请选择角色对应的菜单权限</span>
  <el-cascader
    :options="options"
    :props="props"
    v-model="selval"
    clearable></el-cascader>


      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editRoleVisible = false">取 消</el-button>
        <el-button type="primary" @click="editRollist">确 定</el-button>
      </span>

{{selval}}

    </el-dialog>
<!--    {{checkedsecondpower}}</br>
    {{secondpower}}</br>
    {{secondpowerids}}</br> -->
  </div>
</template>

<script>
  export default {
    data() {
      return {
        //角色列表
        roleList: null,
        editRoleVisible:false,
        roleForm:{
          roleName:'',
          roleId:'',
          menuName:''
        },
        selval:[],
         props: { multiple: true },  //  表示多选
         options: []   // 数据源
      }
    },
    mounted() {
      this.getRolePowerList();
      this.getMenulist();
    },
    methods: {
      // getnodevalue(v){
      //   console.log(v)
      // },
      // 查询所有的菜单
      getMenulist(){

      },
      toroleUser(v){
        this.editRoleVisible = true;
        this.roleForm.menuName = v.menuName;
        this.roleForm.roleName = v.roleName;
        this.roleForm.roleId = v.roleId;
        //   点击分配角色时  把当前角色  默认的菜单  显示出来
        // 用户管理,用户列表,角色列表,房东管理,房源列表,菜单列表  变成   [ [ 1, 2 ], [ 1, 4 ], [ 1, 5 ] ]
        
      },
      editRollist(){
        //  [ [ 1, 2 ], [ 1, 4 ], [ 1, 5 ] ]  :this.selval   数组 第一个表示一级菜单id  第二个表示二级菜单id
        
      },


      // 获取角色列表
      getRolePowerList() {
        
      },

    }
  }
</script>

<style>
</style>

user

<template>
  <div>

    <!-- 面包屑内容 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>管理模块</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 主体内容	 -->
    <el-card>
      <!-- 搜索区域 -->
      <el-row>
        <el-col :span="6">
          <el-input placeholder="请输入用户名" v-model="queryInfo.userName" class="input-with-select" clearable
            @clear="getUserList">
            <el-button slot="append" icon="el-icon-search" @click="getUserList2"></el-button>
          </el-input>
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="openadduser">添加用户</el-button>
        </el-col>
        <el-col :span="2">
          -
        </el-col>
        <el-col :span="2">
          <el-button type="primary" @click="exportUser">导出用户</el-button>
        </el-col>
      </el-row>

      <!-- 列表用户内容区域	 -->
      <el-table :data="userList" border style="width: 100%">
        <el-table-column type="index" label="编号" width="60">
          <template slot-scope="scope">
            <!-- scope.$index  当前循环的 每一次index值  从0开始 -->
            <span>1</span>
          </template>
        </el-table-column>
        <el-table-column prop="userName" label="姓名" width="120">
        </el-table-column>
        <el-table-column prop="userPwd" label="密码" width="80">
        </el-table-column>
        <el-table-column prop="userCreateTime" label="创建时间" width="200">
        </el-table-column>
        <el-table-column prop="roleName" label="角色" width="120">
        </el-table-column>
        <el-table-column prop="deleted" label="状态">
          <template slot-scope="scope">
            <!-- <el-switch v-model="scope.row.mg_state" @change="editStatus(scope.row.id,scope.row.mg_state)"> </el-switch> -->
            <!-- scope.row.status 的status  就是java类的属性  -->
            <!-- scope.row.status == 1   这是返回的  布尔  true 或者 false -->
            <!-- <el-switch @change=""> </el-switch> -->
            <el-switch @change="updatestats(scope.row)" v-model="scope.row.deleted"
            :active-value="0" :inactive-value="1"> </el-switch>
          </template>
        </el-table-column>
        <el-table-column prop="address" label="操作">
          <template slot-scope="scope">
            <el-button type="primary" icon="el-icon-edit" size="mini" @click="toedituser(scope.row)"></el-button>
            <!-- <el-popconfirm title="确定删除吗"> -->
            <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteUser(scope.row.userId)"></el-button>
            <!-- </el-popconfirm> -->
            <el-tooltip class="item" effect="dark" content="分配角色" placement="top">
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="toroleUser(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页功能 -->
      <el-pagination align="left" @size-change="SizeChange" @current-change="CurrentChange"
        :current-page="queryInfo.page" :page-sizes="[1,2,3,5]" :page-size="queryInfo.rows"
        layout="total, sizes, prev, pager, next, jumper" :total="total">
      </el-pagination>
    </el-card>

    <!-- 添加用户dialog对话框 -->
    <!-- :visible.sync  v-if v-show  -->
    <el-dialog align="left" title="添加用户" :visible.sync="addUserVisible" width="50%" @close="">
      <!--主体部分 -->
      <el-form status-icon ref="addUserFormRel" label-width="100px" class="demo-ruleForm">
        <el-form-item label="用户名" prop="userName">
          <el-input v-model="addUserForm.userName" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="性别" prop="userSex">
            <el-switch  v-model="addUserForm.userSex"
            :active-value="0" :inactive-value="1"
            active-text=""
              inactive-text=""> </el-switch>
        </el-form-item>
        <el-form-item label="电话" prop="userTel">
          <el-input v-model="addUserForm.userTel" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="地址" prop="userAddr">
          <el-input v-model="addUserForm.userAddr" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="userPwd">
          <el-input type="password" v-model="addUserForm.userPwd" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="角色" prop="roleId">
            <el-radio-group v-model="addUserForm.roleId">
                <el-radio v-for="x in rolelist"
                :label="x.roleId" :key="x.roleId">{{x.roleName}}</el-radio>
                <!-- <el-radio :label="2">房东</el-radio>
                <el-radio :label="3">租户</el-radio> -->
              </el-radio-group>
        </el-form-item>
        <el-form-item label="图像" prop="userImg">
        <el-upload
          class="avatar-uploader"
          action="/api/user/userImg"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeAvatarUpload">
          <img v-if="addUserForm.userImg" :src="addUserForm.userImg" class="avatar">
          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>
         </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="addUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="adduser">确 定</el-button>
      </span>
    </el-dialog>

<!-- 修改用户dialog对话框 -->
    <!-- :visible.sync  v-if v-show  -->
    <el-dialog align="left" title="修改用户" :visible.sync="editUserVisible" width="50%" @close="">
      <!--主体部分 -->
      <el-form status-icon  label-width="100px" class="demo-ruleForm">
        <el-form-item label="用户名" >
          <el-input v-model="editUserForm.userName" disabled autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="原密码" >
          <el-input type="password" v-model="editUserForm.oldpwd" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="新密码" >
          <el-input type="password" v-model="editUserForm.oldselfpwd" autocomplete="off"></el-input>
        </el-form-item>
        <!-- <el-form-item label="创建时间" prop="userCreateTime">
          <el-date-picker type="datetime" placeholder="选择日期" value-format="yyyy-MM-dd HH:mm:ss"
          v-model="editUserForm.userCreateTime" style="width: 100%;" disabled></el-date-picker>
        </el-form-item> -->
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="editUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="edituser">确 定</el-button>
      </span>
    </el-dialog>

 <!-- 分配用户角色diaolog对话框 -->
    <el-dialog align="left" title="分配用户角色" :visible.sync="editRoleVisible" width="50%">
      <!--主体部分 -->
      <div>
        <p>当前的用户:<strong>{{roleForm.userName}}</strong></p>
        <p>当前的角色:<strong>{{roleForm.roleName}}</strong></p>
        <span>分配新角色:</span>
        <el-select v-model="roleForm.roleId" slot="prepend" placeholder="请选择">
          <!-- <el-option label="王者" value="王者"></el-option>
								  <el-option label="黄铜" value="黄铜"></el-option>
								  <el-option label="钻石" value="钻石"></el-option> -->
          <el-option v-for="x in rolelist"
          :label="x.roleName" :value="x.roleId" :key="x.roleId"></el-option>
        </el-select>
        <!-- {{selectVal}} -->
      </div>

      <span slot="footer" class="dialog-footer">
        <el-button @click="editRoleVisible = false">取 消</el-button>
        <el-button type="primary" @click="editRollist">确 定</el-button>
      </span>
    </el-dialog>





<!-- <img :src="imageUrl"> -->
<!-- <img src="file:///D://img//1657089792394wzry001.jpg"> -->


  </div>
</template>

<script>
  export default {
    data() {
      return {
        //搜索的neirong
        searchVal: '',
        //用户列表参数
        queryInfo: {
          userName: '',
          page: 1,
          rows: 3
        },
        //用户列表
        userList: null,
        //总的数据条数
        total: 0,
        addUserVisible: false,
        addUserForm: {
          userName: "",
          userPwd: "",
          userSex:1,
          userTel:'',
          userAddr:"",
          roleId:4,
          userImg:''
        },
        editUserVisible:false,
        editUserForm: {
          userId:"",
          userName: "",
          oldpwd: "",// 修改框中 输入的原密码
          userPwd:"",  //  数据库原来的密码
          userCreateTime:"",
          oldselfpwd:"" ,// 修改框中 输入的新密码,
          version:0
        },
        editRoleVisible:false,
        roleForm:{
          roleId:"",
          userId:"",
          userName:"",
          roleName:""
        },
        rolelist:[],
        // imageUrl: ''
      }
    },
    mounted() {
      this.getUserList();
      this.getrolelist();
    },
    methods: {
      getrolelist(){
        
      },
      toroleUser(v){
        this.editRoleVisible = true;
        this.roleForm.userName = v.userName;
        this.roleForm.roleName = v.roleName;
        this.roleForm.userId = v.userId;
        // this.getrolelist(); //  打开分配角色的窗口 查询 角色数据
      },
      editRollist(){
        
      },
      exportUser(){
        let form = $("<form>"); //创建form标签
        form.attr("style","display:none");
        form.attr("method","get");//设置请求方式
        form.attr("action","/api/user/exportUser"); //action属性设置请求路径
        $("body").append(form); //页面添加form标签
        form.submit();//表单提交即可下载!
      },
      toedituser(v){
        this.editUserVisible = true;
        this.editUserForm.userName = v.userName;
        this.editUserForm.userId = v.userId;
        this.editUserForm.userPwd = v.userPwd;
        this.editUserForm.userCreateTime = v.userCreateTime;
        this.editUserForm.version = v.version;
        // data.replace(“,”,”+”);//只能替换掉第一个,号。result ==>”数据1+数据2,数据3”
        // var reg = new RegExp(“,”,”g”);//g,表示全部替换。
        // data.replace(reg,”+”);
        // data.replace('-','年')
        // this.editUserForm.createtime = v.createtime;
        //this.editUserForm.createtime = '2022-04-06 16:07:14';
      },
      edituser(){
          //var userinfo = JSON.parse(sessionStorage.getItem('user'));
          if(this.editUserForm.oldpwd != this.editUserForm.userPwd){ // 输入的原密码和 登录的密码不同
            alert('原密码输入错误');
            return;
          }
         
      },
      deleteUser(id){
        let that = this;
        this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {   // lambo 表达式 简写
          //alert(1)
          
        }).catch(function(){
          //alert(2)
        })
      },
      updatestats(v){
        console.log(v);
        
      },
      adduser() {
        console.log(this.addUserForm)
        if (this.addUserForm.userName.trim() == '' || this.addUserForm.userPwd.trim() == '') {
          //this.message = "用户名或者密码为空";
          alert("用户名或者密码为空");
          return;
        }
        
      },
      openadduser() {
        //this.getrolelist();
        this.addUserVisible = true;
      },
      getUserList2() {
        this.queryInfo.page = 1;
        this.getUserList();
      },
      // 获取用户列表
      getUserList() {
        
      },
      //每页数据条数改变时触发
      SizeChange(newval) {
        this.queryInfo.rows = newval;
        this.getUserList();
      },
      //当前页面改变时触发
      CurrentChange(newval) {
        this.queryInfo.page = newval;
        this.getUserList();
      },
      handleAvatarSuccess(res, file) {
        console.log(res)
        console.log(file)
        this.addUserForm.userImg = res.data;
        // this.imageUrl = URL.createObjectURL(file.raw);
      },
      beforeAvatarUpload(file) {
        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>
  .avatar-uploader .el-upload {
      border: 1px dashed #d9d9d9;
      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>

在这里插入图片描述

添加路径

在这里插入图片描述

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

import login from '@/components/Login.vue'
import home from '@/components/Home.vue'

import userList from '@/components/user/User.vue'
import power from '@/components/user/power.vue'
import role from '@/components/user/role.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },

    {
      path: '/login',
      name: '登录页面',
      component: login
    },

    {
      path: '/home',
      name: '首页',
      component: home,
      children:[{
        path: '/userList',
        name: '用户列表',
        component: userList
      }]
    }

    ]

})

设置拦截器(前置守卫)

在这里插入图片描述

把用户信息存到 session 作用域中

在这里插入图片描述

注意上面的 abc 这里为修改了一下
在这里插入图片描述

继续完成用户列表

导入其他的页面

在这里插入图片描述

编写方法

在这里插入图片描述

在数据库添加列

在这里插入图片描述

修改实体类

注意修改其他地方的名字

package com.example.model;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

@Data
public class UserInfo {

    @TableId(type = IdType.AUTO)
    private Integer id;
    @TableField("username")
    private String userName;
    @TableField("password")
    private String passPwd;
    private Integer status;// '1 正常  2  停用',
    @TableField("create_time")
    private String userCreateTime;
    private Integer version;
    private String updateTime;
    private Integer deleted;
    private Integer userSex; // 0 女 1男
    private String userTel;
    private String userAddr;
}


分页

添加分页插件

在这里插入图片描述

 @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mi = new MybatisPlusInterceptor();
        mi.addInnerInterceptor(new PaginationInnerInterceptor());
        return mi;
    }

User.vue
在这里插入图片描述

后端添加此方法

在这里插入图片描述


@RequestMapping("/getPowerByUserId")
    public Page<UserInfo> list(QueryInfo queryInfo) {
        System.out.println(queryInfo);
        QueryWrapper<UserInfo> qw = new QueryWrapper<>();
        qw.like("username",queryInfo.getUserName());
        if (StringUtils.isNotBlank(queryInfo.getUserName())){
            qw.like("username",queryInfo.getUserName());
        }
//        List<UserInfo> userInfos = userDao.selectList(qw);
        Page<UserInfo> page = new Page<>(queryInfo.getPage(),queryInfo.getRows());
        Page<UserInfo> page1 = userDao.selectPage(page, qw);
        return page1;
    }

再修改前端

在这里插入图片描述

// 获取用户列表
      getUserList() {
        let url = "http://localhost:8080/getUserList";
        this.$axios.get(url,{params:this.queryInfo}).then(
          (d)=>{
            console.log(d)
            this.userList = d.data.records;
            this.total = d.data.total;
          }
        )
      },

上面的方法是不会显示角色的,我们要显示角色要自己写分页

在userdao 添加接口

Page<UserInfo> selectPageUR(Page<UserInfo> page, @Param("ew") QueryWrapper<UserInfo> qw);

添加SQL 语句

<select id="selectPageUR" resultType="com.example.model.UserInfo">
       select u.id, u.username as userName, u.password userPwd,  u.create_time userCreateTime,  u.deleted,
        u.user_sex,u.user_tel,u.user_addr,
        r.role_name from user_info as u
        LEFT JOIN user_role ur on u.id = ur.user_id
        LEFT JOIN role r on r.role_id = ur.role_id
         ${ew.customSqlSegment}
    </select>

这里要添加属性到UserInfo 表

package com.example.model;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

@Data
public class UserInfo {

    @TableId(type = IdType.AUTO)
    private Integer id;
    @TableField("username")
    private String userName;
    @TableField("password")
    private String passPwd;
    private Integer status;// '1 正常  2  停用',
    @TableField("create_time")
    private String userCreateTime;
    private Integer version;
    private String updateTime;
    private Integer deleted;
    private Integer userSex; // 0 女 1男
    private String userTel;
    private String userAddr;
    // 告诉mybatis roleName 这个属性 不是userinfo 表的字段
    @TableField(exist = false)
    private String roleName;
}

添加信息

在这里插入图片描述

在这里插入图片描述

修改信息

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

删除信息

在这里插入图片描述
在这里插入图片描述

导出

导入依赖

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.11</version>
        </dependency>

添加工具类

package com.example.util;


import com.example.model.UserInfo;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;

public class ExcelUtil {

        /**
         * 用户信息导出类
         * @param response 响应
         * @param fileName 文件名
         * @param columnList 每列的标题名
         * @param dataList 导出的数据
         */
        public static void uploadExcelAboutUser(HttpServletResponse response, String fileName, List<String> columnList, List<List<String>> dataList){
            //声明输出流
            OutputStream os = null;
            //设置响应头
            setResponseHeader(response,fileName);
            try {
                //获取输出流
                os = response.getOutputStream();
                //内存中保留1000条数据,以免内存溢出,其余写入硬盘
                SXSSFWorkbook wb = new SXSSFWorkbook(1000);
                //获取该工作区的第一个sheet
                Sheet sheet1 = wb.createSheet("sheet1");
                int excelRow = 0;
                //创建标题行
                Row titleRow = sheet1.createRow(excelRow++);
                for(int i = 0;i<columnList.size();i++){
                    //创建该行下的每一列,并写入标题数据
                    Cell cell = titleRow.createCell(i);
                    cell.setCellValue(columnList.get(i));
                }
                //设置内容行
                if(dataList!=null && dataList.size()>0){
                    //序号是从1开始的
                    int count = 1;
                    //外层for循环创建行
                    for(int i = 0;i<dataList.size();i++){
                        Row dataRow = sheet1.createRow(excelRow++);
                        //内层for循环创建每行对应的列,并赋值
                        for(int j = -1;j<dataList.get(0).size();j++){//由于多了一列序号列所以内层循环从-1开始
                            Cell cell = dataRow.createCell(j+1);
                            if(j==-1){//第一列是序号列,不是在数据库中读取的数据,因此手动递增赋值
                                cell.setCellValue(count++);
                            }else{//其余列是数据列,将数据库中读取到的数据依次赋值
                                cell.setCellValue(dataList.get(i).get(j));
                            }
                        }
                    }
                }
                //将整理好的excel数据写入流中
                wb.write(os);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    // 关闭输出流
                    if (os != null) {
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    public static void uploadExcelAboutUser2(HttpServletResponse response, String fileName, List<String> columnList, List<UserInfo> dataList){
        //声明输出流
        OutputStream os = null;
        //设置响应头
        setResponseHeader(response,fileName);
        try {
            //获取输出流
            os = response.getOutputStream();
            //内存中保留1000条数据,以免内存溢出,其余写入硬盘
            SXSSFWorkbook wb = new SXSSFWorkbook(900);
            //获取该工作区的第一个sheet
            Sheet sheet1 = wb.createSheet("用户列表");
            Sheet sheet2 = wb.createSheet("角色列表");
            int excelRow = 0;
            //创建标题行
            Row titleRow = sheet1.createRow(excelRow++);
            for(int i = 0;i<columnList.size();i++){
                //创建该行下的每一列,并写入标题数据
                Cell cell = titleRow.createCell(i);
                cell.setCellValue(columnList.get(i));
            }
            //设置内容行
            if(dataList!=null && dataList.size()>0){
                //序号是从1开始的
                int count = 1;
                //外层for循环创建行
                for(int i = 0;i<dataList.size();i++){
                    Row dataRow = sheet1.createRow(excelRow++);
                    UserInfo userInfo = dataList.get(i);
                    Cell cell0 = dataRow.createCell(0);
                    cell0.setCellValue(count++);
                    Cell cell1 = dataRow.createCell(1);
                    cell1.setCellValue(userInfo.getUserName());
                    Cell cell2 = dataRow.createCell(2);
//                    cell2.setCellValue(userInfo.getUserSex()==1?"男":"女");
                    cell2.setCellValue(userInfo.getUserPwd());
                    Cell cell3 = dataRow.createCell(3);
//                    cell2.setCellValue(userInfo.getUserSex()==1?"男":"女");
                    cell3.setCellValue(userInfo.getUserCreateTime());
                }
            }
            //将整理好的excel数据写入流中
            wb.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭输出流
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

        /*
            设置浏览器下载响应头
         */
        private static void setResponseHeader(HttpServletResponse response, String fileName) {
            try {
                try {
                    fileName = new String(fileName.getBytes(),"ISO8859-1");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                response.setContentType("application/octet-stream;charset=UTF-8");
                response.setHeader("Content-Disposition", "attachment;filename="+ fileName);
                response.addHeader("Pargam", "no-cache");
                response.addHeader("Cache-Control", "no-cache");
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

后端

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

分配角色

在这里插入图片描述

创建bean

package com.example.model;

import lombok.Data;

@Data
public class Role {
    private Integer roleId;
    private String roleName;
}

新建dao
RoleDao

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.model.Role;

public interface RoleDao extends BaseMapper<Role> {

}

查询所有

package com.example.controller;

import com.example.dao.RoleDao;
import com.example.model.Role;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import java.util.List;

@Controller
@RequestMapping("/role")
public class RoleController {
    @Resource
    RoleDao roleDao;

    @RequestMapping("/getrolelist")
    public List<Role> getrolelist(){
        List<Role> roles = roleDao.selectList(null);
        return roles;
    }
}

在这里插入图片描述

修改Role bean

package com.example.model;

import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

@Data
public class Role {
    private Integer roleId;
    private String roleName;
    // 表示 id  不是角色边的字段 只是作为 java 类里面的属性使用
    @TableField(exist = false)
    private Integer id;
}

编写dao 层

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.model.Role;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

public interface RoleDao extends BaseMapper<Role> {

    @Select("select count(1) from user_role where user_id = #{id}")
    int selectURByUserId(Integer id);

    @Update("update user_role set role_id = #{roleId} where user_id = #{id}")
    void updateURByUserId(Role role);

    @Insert("insert into user_role values(null,#{id},#{roleId})")
    void insertURByUserId(Role role);
}


修改控制层代码

package com.example.controller;

import com.example.dao.RoleDao;
import com.example.model.Role;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/role")
public class RoleController {
    @Resource
    RoleDao roleDao;

    // 显示
    @RequestMapping("/getrolelist")
    public List<Role> getrolelist(){
        System.out.println("123");
        List<Role> roles = roleDao.selectList(null);
        return roles;
    }

    // 通过用户id 查询 user_role 关系表
    @RequestMapping("/editRollist")
    public boolean editRollist(Role role){
        System.out.println(role);
        boolean flag = false;
        try {
            // 通过用户id 查询 user_role  关系表
            int count = roleDao.selectURByUserId(role.getId());
            // 有数据 修改 角色 id
            if (count > 0){
                roleDao.updateURByUserId(role);
            }else{
                // 没有数据 新增一条关系数据
                roleDao.insertURByUserId(role);
            }
            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return flag;
    }
}


修改前端代码

 //   修改角色  点击确定 执行方法
    editRollist() {
      let url = "http://localhost:8080/role/editRollist"
      this.$axios.get(url,{params:this.roleForm}).then((d) =>{
        if(d.data){
          alert("修改角色成功")
          this.editRoleVisible = false;
          this.getUserList()
        }else{
          alert("修改角色失败")
        }
      })

    },

代码发邮箱

pom 里面的驱动

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <version>2.5.6</version>
        </dependency>

工具类

package com.example.util;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;

/**
 * @Description
 * @Autor 伍军
 * @Date 2021/9/15 13:58
 * @Version 1.0
 **/
@Component
public class MyEmail {

    //注入邮件发送类
    @Resource
    JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    private String formEmail;
    /**
     * 发送邮件
     * @param email 收件人的邮箱
     * @param content 邮件正文
     * @return
     */
    public HashMap<String,Object> sendEmail(String email,String content,String title){
        HashMap<String,Object> map = new HashMap<String,Object>();

        try{
            //创建一个邮件
            SimpleMailMessage message = new SimpleMailMessage();
            //写入收件人邮箱
            message.setTo(email);
            //写入发件人邮箱
            message.setFrom(formEmail);
            //写入邮件标题
            message.setSubject(title);
            //写入邮件正文
            message.setText(content);
            //发送邮件
            javaMailSender.send(message);
            map.put("info","发送成功");
        }catch(Exception e){
            e.printStackTrace();
            map.put("info","发送失败");
        }
        return map;
    }

//    public void forSend(List<Auding> list){
//        String title = "请尽快审核房屋提交信息";
//        String content = "";
//        for(Auding a : list){
//            content = "这是要审核的房屋名称"+a.getAudeHouseName();
//            sendEmail(a.getUserEmail(),content,title);
//        }
//    }

}

在这里插入图片描述

    @Resource
    MyEmail myEmail;

    @RequestMapping("/sendEmail")
    public void sendEmail(){
        // 第一个参数 接受者的邮箱
        myEmail.sendEmail("1243835377@qq.com","你好","测试邮箱");
    }

如果你的配置文件是 por的话 使用这个配置文件

#邮箱配置
spring.mail.host=smtp.qq.com
spring.mail.username=767920412@qq.com
spring.mail.password=fobsqzeugtptbgaf
spring.mail.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.default-encoding=UTF-8

如果你的配置文件是 yml 的话 使用这个配置文件

mail:
    host: smtp.qq.com
    username: 767920412@qq.com
    password: fobsqzeugtptbgaf
    port: 465
    properties:
      mail:
        smtp:
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory
    default-encoding: utf-8


spring:
    datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/testvue?useSSL=false
        username: root
        password: root123
    application:
        name: provider-service
        
    mail:
        host: smtp.qq.com
        username: 767920412@qq.com
        password: fobsqzeugtptbgaf
        port: 465
        properties:
            mail:
                smtp:
                    socketFactory:
                        class: javax.net.ssl.SSLSocketFactory
        default-encoding: utf-8

mybatis-plus:
    configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    mapper-locations: classpath:mapper/*.xml


权限名

前端

在这里插入图片描述

<template>
  <div>

    <!-- 面包屑内容 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>管理模块</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 主体内容	 -->
    <el-card>

      <!-- 列表用户内容区域	 -->
      <el-table :data="roleList" border style="width: 100%">
        <el-table-column type="index" label="编号" width="60">
          <template slot-scope="scope">
            <!-- scope.$index  当前循环的 每一次index值  从0开始 -->
            <span>{{scope.$index+1}}</span>
          </template>
        </el-table-column>
        <el-table-column prop="roleName" label="角色名" width="120">
        </el-table-column>
        <el-table-column prop="menuName" label="权限名" width="400">
        </el-table-column>
        <el-table-column prop="address" label="操作">
          <template slot-scope="scope">
            <!-- </el-popconfirm> -->
            <el-tooltip class="item" effect="dark" content="分配权限" placement="top">
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="toroleUser(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 分配角色diaolog对话框 -->
    <el-dialog align="left" title="分配权限" :visible.sync="editRoleVisible" width="50%">
      <!--主体部分 -->
      <div>
        <p>当前的角色:<strong>{{roleForm.roleName}}</strong></p>
        <p>当前的角色权限:<strong>{{roleForm.menuName}}</strong></p>

        <span class="demonstration">请选择角色对应的菜单权限</span>
        <el-cascader
          :options="options"
          :props="props"
          v-model="selval"
          clearable></el-cascader>


      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editRoleVisible = false">取 消</el-button>
        <el-button type="primary" @click="editRollist">确 定</el-button>
      </span>

      {{selval}}

    </el-dialog>
    <!--    {{checkedsecondpower}}</br>
        {{secondpower}}</br>
        {{secondpowerids}}</br> -->
  </div>
</template>

<script>
export default {
  data() {
    return {
      //角色列表
      roleList: null,
      editRoleVisible:false,
      roleForm:{
        roleName:'',
        roleId:'',
        menuName:''
      },
      selval:[],
      props: { multiple: true },  //  表示多选
      options: [{
        value: 'zhinan',
        label: '指南',
        children: [{
          value: 'shejiyuanze',
          label: '设计原则',
          // children:[
          //   {value:'key1',label:'value2',},
          //   {value:'key2',label:'value2',},
          // ],
        },
          {
            value: 'shejiyuanze2',
            label: '设计原则2',
          },
        ]
      },
        {
          value: 'zhinan2',
          label: '指南2',
        }
      ],    // 数据源
    }
  },
  mounted() {
    this.getRolePowerList();
    this.getMenulist();
  },
  methods: {
    // getnodevalue(v){
    //   console.log(v)
    // },
    // 查询所有的菜单
    getMenulist(){

    },
    toroleUser(v){
      this.editRoleVisible = true;
      this.roleForm.menuName = v.menuName;
      this.roleForm.roleName = v.roleName;
      this.roleForm.roleId = v.roleId;
      //   点击分配角色时  把当前角色  默认的菜单  显示出来
      // 用户管理,用户列表,角色列表,房东管理,房源列表,菜单列表  变成   [ [ 1, 2 ], [ 1, 4 ], [ 1, 5 ] ]

    },
    editRollist(){
      //  [ [ 1, 2 ], [ 1, 4 ], [ 1, 5 ] ]  :this.selval   数组 第一个表示一级菜单id  第二个表示二级菜单id

    },


    // 获取角色列表
    getRolePowerList() {
      let url = "http://localhost:8080/role/getrolelistPower"
      this.$axios.get(url).then((d) =>{
        this.roleList = d.data;
      })
    },

  }
}
</script>

<style>
</style>

修改 Role bean 文件

package com.example.model;

import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

@Data
public class Role {
    private Integer roleId;
    private String roleName;
    // 表示 id  不是角色边的字段 只是作为 java 类里面的属性使用
    @TableField(exist = false)
    private Integer id;
    // 表示 id 不是角色表的字段 只是作为java类里面的属性使用
    @TableField(exist = false)
    private String menuName;
}

新建 sql 映射文件

RoleDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.dao.RoleDao">
    <select id="getrolelistPower" resultType="com.example.model.Role">
        select r.role_id,r.role_name, GROUP_CONCAT(p.power_name) menuName
        from  role r
                  LEFT JOIN role_power rp on r.role_id = rp.role_id
                  LEFT JOIN power p on p.power_id = rp.power_id
        GROUP BY r.role_id,r.role_name
        order by r.role_id
    </select>

</mapper>

添加接口

RoleDao.java

List<Role> getrolelistPower();

添加控制层代码

 @RequestMapping("/getrolelistPower")
    public List<Role> getrolelistPower(){
        return roleDao.getrolelistPower();
    }

Spring Boot 添加定时器

开启自带的定时器功能

在这里插入图片描述

测试类

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSOA6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值