SpringBoot 项目构建:SpringBoot + MySQL8 + MyBatis-Plus + Redis +定时任务框架(elastic-job) + Spring Security + JWT(前后端分离Token)
csdn 下载地址:https://download.csdn.net/download/zhouzhiwengang/16136915
Vue项目构建:Vue + Vue-Route +Vuex + Element-UI + Axios 项目管理后台模板
Vue项目创建:
#创建一个基于webpack模板的新项目
vue init webpack C:\node_workspace\two
# 切换至项目路径
cd C:\node_workspace\two
# 安装项目依赖文件
cnpm install
# 项目启动
cnpm run dev
Vue 项目集成Vuex + Element-UI + Axios框架依赖
C:\node_workspace\two>cnpm i element-ui -S
√ Installed 1 packages
√ Linked 8 latest versions
√ Run 0 scripts
√ All packages installed (6 packages installed from npm registry, used 4s(network 4s), speed 21.08kB/s, json 9(81.21kB), tarball 0B)
C:\node_workspace\two>cnpm i vuex -S
√ Installed 1 packages
√ Linked 1 latest versions
√ Run 0 scripts
√ All packages installed (1 packages installed from npm registry, used 260ms(network 255ms), speed 156.22kB/s, json 2(39.84kB), tarball 0B)
C:\node_workspace\two>cnpm i axios -S
√ Installed 1 packages
√ Linked 1 latest versions
√ Run 0 scripts
√ All packages installed (1 packages installed from npm registry, used 363ms(network 360ms), speed 26.39kB/s, json 2(9.5kB), tarball 0B)
Vue 之 移除初始化模板样式和数据
1、在App.vue 文件中移除原有Vue的logo 标签和样式文件。下面是修改后的App.Vue 文件
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,body{
width: 100%;
height: 100%;
}
#app {
height: 100%;
}
</style>
Vue 之Vuex 功能封装
1、在src 文件夹下新增store 文件夹并新增index.js 。index.js 新增内容如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
// 存储token
token: localStorage.getItem('token') ? localStorage.getItem('token') : ''
},
mutations: {
// 修改token,并将token存入localStorage
changeLogin (state, user) {
state.token = user.token;
localStorage.setItem('token', user.token);
},
logout (state, user) {
state.token = ''
localStorage.removeItem('token')
}
}
});
export default store;
Vue 之Element-ui、axios、store功能基础
1、在mian.js 集成element-ui、axios、store 。main.js 内容如下:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
// 集成element-ui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 集成vuex
import store from'./store'
// 集成axios
import axios from '../node_modules/axios'
// 设置跨域
axios.defaults.withCredentials = true
// 设置后端请求地址
axios.defaults.baseURL='http://192.168.1.74:8198/house'
Vue.prototype.$axios = axios
Vue.use(ElementUI);
Vue.config.productionTip = false
// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(
config => {
if (localStorage.getItem('token')) {
config.headers.token = localStorage.getItem('token');
}
return config;
},
error => {
return Promise.reject(error);
});
// 添加响应拦截器,移除token
axios.interceptors.response.use(
response =>{
return response;
},
error=>{
if(error.response){
switch(error.response.status){
case 401:
localStorage.removeItem('token');
this.$router.push('/login');
}
}
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
Vue 之路由配置
1、重点修改router文件夹下的index.js 文件,index.js 配置文件内容如下:
import Vue from 'vue'
import Router from 'vue-router'
import login from '@/components/login';
import home from '@/components/home';
// 新房管理
import newHouse from '@/components/view/newHouse'
// 二手房管理
import secondHouse from '@/components/view/secondHouse'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'login',
component: login
},
{
path: '/home',
name: 'home',
component: home,
children: [{
path: '/newHouse',
name: 'newHouse',
component: newHouse
},
{
path: '/secondHouse',
name: 'secondHouse',
component: secondHouse
}]
}
]
})
// 导航守卫
// 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆
router.beforeEach((to, from, next) => {
if (to.path === '/login') {
next();
} else {
let token = localStorage.getItem('token');
if (token === null || token === '') {
next('/login');
} else {
next();
}
}
});
export default router;
Vue 组件之 login.vue(登入首页)
<template>
<div class="login-container">
<el-form label-position="left"
label-width="0px"
status-icon>
<h3 class="login_title">系统登录</h3>
<el-form-item>
<el-input
type="text"
v-model="loginForm.username"
auto-coplete="off"
placeholder="账号">
</el-input>
</el-form-item>
<el-form-item>
<el-input
type="password"
v-model="loginForm.password"
auto-coplete="off"
placeholder="密码">
</el-input>
</el-form-item>
<el-form-item style="width: 100%">
<el-button type="primary" @click.native.prevent="login" style="width: 100%">登录</el-button>
<!--
<el-button type="primary" @click.native.prevent="register" style="width: 100%; margin-top: 30px">注册</el-button>
-->
</el-form-item>
</el-form>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
export default {
data () {
return {
loginForm: {
username: '',
password: ''
},
userToken: ''
};
},
methods: {
// 调用store 存储
...mapMutations(['changeLogin']),
login () {
let _this = this;
if (this.loginForm.username === '' || this.loginForm.password === '') {
alert('账号或密码不能为空');
} else {
// 发起登入请求
this.$axios({
method: 'post',
url: '/auth/login',
headers: {
'Content-Type':'application/json;charset=utf-8'
},
data:{"username":_this.loginForm.username,"password":_this.loginForm.password},
}).then(res => {
console.log('123456');
console.log(res);
console.log(res.data.datas.token);
_this.userToken = res.data.datas.token;
// 将用户token保存到vuex中
_this.changeLogin({ token: _this.userToken });
// 用户登入成功,自动跳转至系统首页
_this.$router.push('/home');
alert('登陆成功');
}).catch(error => {
alert('账号或密码错误');
console.log(error);
});
}
}
}
};
</script>
<style scoped>
.login-container{
border-radius: 15px;
background-clip: padding-box;
margin: 10% auto;
width: 350px;
padding: 35px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
}
.login_title{
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
</style>
Vue 组件之 home.vue(系统首页)
<style>
.el-main {
background-color: #f5f7f9;
}
.el-header,
.el-footer {
background-color: white;
box-sizing: border-box;
border-bottom: 1px solid #f5f1f1;
}
.el-container {
height: 100%;
}
</style>
<template>
<el-container>
<!-- header部分 -->
<el-header>
<navtop></navtop>
</el-header>
<el-container>
<!-- aside部分 -->
<leftNav></leftNav>
<el-main>
<!-- main部分 -->
<router-view />
</el-main>
</el-container>
</el-container>
</template>
<script>
import navtop from "@/components/part/nav-top.vue";
import leftNav from "@/components/part/nav.vue";
export default {
components: {
navtop,
leftNav
},
data() {
return {};
},
methods: {}
};
</script>
Vue 组件之 系统首页涉及公共页面(nav-top.vue 和nav.vue)
注意:在src/components/part 新增上述两个vue 文件
nav-top.vue
<style scoped>
.el-aside {
display: flex;
justify-content: center;
align-items: center;
}
section{
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
.logo {
width: 200px;
}
.headerLogo,.logo{
cursor: pointer;
}
</style>
<template>
<el-container>
<el-aside width="auto" class="header-logo tap" >
<img class="logo" src="@/assets/logo.png" alt="Logo" />
</el-aside>
<el-aside width="auto" class="header-logo tap" >
<el-avatar icon="el-icon-user-solid" class="headerLogo"></el-avatar>
</el-aside>
</el-container>
</template>
<script>
export default {
data() {
return {
activeIndex: "1",
};
},
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
}
}
};
</script>
nav.vue
<style scoped>
.el-row{
height: 100%;
}
.el-menu{
border-right:none;
}
.el-aside{
border-right: 1px solid #f5f1f1;
}
</style>
<template>
<el-aside width="200px">
<el-row class="tac">
<el-col>
<el-menu
default-active="1"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
>
<el-menu-item index="1" @click="goPage('centre')">
<i class="el-icon-menu"></i>
<span slot="title">首页</span>
</el-menu-item>
<el-submenu index="3">
<template slot="title">
<i class="el-icon-location"></i>
<span>房屋管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="3-1" @click="goPage('newHouse')">新房管理</el-menu-item>
</el-menu-item-group>
<el-menu-item-group>
<el-menu-item index="3-2" @click="goPage('secondHouse')">二手房管理</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</el-aside>
</template>
<script>
var $this = {};
export default {
data() {
return {};
},
beforeCreate() {
$this = this;
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
goPage(link) {
// 跳转至首页
if (link === "centre") {
$this.$router.push("/centre").catch(error => error);
}
// 跳转至会员管理
else if ((link === "newHouse")) {
$this.$router.push("/newHouse").catch(error => error);
}
// 跳转至收获地址
else if ((link === "secondHouse")) {
$this.$router.push("/secondHouse").catch(error => error);
}
}
}
};
</script>
Vue 组件之业务组件
注意:在src/components/view 新增上述业务组件Vue
业务组件之newHouse.vue(新房管理)
<style>
</style>
<template>
<div id="new_house">
<h1>新房管理</h1>
</div>
</template>
<script>
export default{
name: 'new_house'
}
</script>
业务组件之secondHouse.vue(二手房管理)
<style>
</style>
<template>
<div id="second_house">
<h1>二手房管理</h1>
</div>
</template>
<script>
export default{
name: 'second_house'
}
</script>
Vue 后台租房管理系统功能演示: