app.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style lang="less">
</style>
index.vue
<template>
<div class="login-container">
<!--必须用el-form进行包裹-->
<div class="login-head"></div>
<!--配置表单验证
//必须为表单提供验证对象
2添加prop属性
3通过el-form组件库里面的rules-->
<el-form class="login-form" ref="login-form" :model="user" :rules="formRules">
<el-form-item prop="mobile">
<el-input v-model="user.mobile" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item prop="code">
<el-input v-model="user.code" placeholder="请输入验证码"></el-input>
</el-form-item>
<el-form-item prop="agree">
<el-checkbox v-model="checked">我已阅读并同意用户协议和隐私条款</el-checkbox>
</el-form-item>
<el-form-item>
<el-button class="login-btn" type="primary" :loading="loginLoading" @click="onLogin">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { login } from '@/api/user'
export default {
name: 'LoginIndex',
components: {
},
props: {},
data () {
return {
user: {
mobile: '', // 手机号
code: '', // 验证码
agree: false// 是否同意协议
},
loginLoading: false, // 登录的loding状态
/* checked: false, // 是否同意协议 */
formRules: {
mobile: [{
required: true,
message: '手机号不能为空',
trigger: 'change'
},
{ pattern: /^1[3|5|7|9]\d{9}$/, message: '请输入正确的号码格式', trigger: 'change' }
],
code: [{
required: true,
message: '验证码不能为空',
trigger: 'change'
},
{ pattern: /^\d{6}$/, message: '请输入正确的验证码格式', trigger: 'change' }
],
agree: [{
// 调用
validator: (rule, value, callback) => {
if (value) {
callback()
} else {
callback(new Error('请同意用户协议'))
}
},
trigger: 'change'
}]
}
}
},
methods: {
onLogin () {
// 获取表单数据
// const user = this.user
// 触发表单验证 validate是异步
this.$refs['login-form'].validate((valid, err) => {
console.log(valid)
console.log(err)
// 如果
if (!valid) {
return
}
this.login()
})
},
login () {
// 开启loading
this.loginLoading = true
// 验证通过
// 请求直接封装
login(this.user).then(res => {
console.log(res)
this.$message({
message: '登录成功',
type: 'success'
})
this.loginLoading = false
}).catch(err => {
console.log('登录失败', err)
this.$message.error({
message: '手机号或者验证码错误',
type: 'warning'
})
this.loginLoading = false
})
}
}
}
</script>
<style scoped lang="less">
.login-container{
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background: url("./login_bg.jpg") no-repeat;
background-size: cover;
.login-head{
width: 300px;
height: 57px;
background:url("./logo_index.png") no-repeat;
margin-bottom: 30px;
}
.login-form{
background-color: #fff;
padding: 50px;
min-width: 300px;
.login-btn{
width: 100%;
}
}
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './styles/index.less'
// 加载组件库
import ElementUI from 'element-ui'
// 加载样式
import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false
// 注册组件库
Vue.use(ElementUI)
new Vue({
router,
render: h => h(App)
}).$mount('#app')
index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/login/index'
Vue.use(VueRouter)
// 路由配置表
const routes = [{
path: '/login',
name: 'login',
component: Login
}]
const router = new VueRouter({
routes
})
export default router
user.js
// 用户登录的请求模块
import request from '@/utils/request'
export const login = data => {
return request({
method: 'POST',
url: '/mp/v1_0/authorizations',
data
})
}
// 获取用户信息
export const getUserProfile = () => {
const user = JSON.parse(window.localStorage.getItem('user'))
console.log(user)
return request({
method: 'GET',
url: '/mp/v1_0/user/profile'
// axios通过headers
/* headers: {
Authorization: `Bearer ${user.token}`
} */
})
}
index.vue
<template>
<div class="home-container">首页</div>
</template>
<script>
export default {
name: 'HomeIndex',
data () {
return {
}
}
}
</script>
<style scoped lang="less">
</style>
index.vue
<template>
<el-container class="layout-container">
<el-aside class="aside" width="auto">
<app-aside class="aside-menu" :is-collapse="isCollapse"></app-aside>
</el-aside>
<el-container>
<el-header class="header">
<div>
<i :class="{'el-icon-s-fold':isCollapse,
'el-icon-s-unfold':!isCollapse}" @click="isCollapse=!isCollapse"></i>
<span>江苏传智播客科技教育有限公司</span>
</div>
<el-dropdown>
<div class="avatar-wrap">
<img class="avatar" :src="user.photo" alt="">
<span>{{user.name}}</span>
<i class="el-icon-arrow-down el-icon--right"></i>
</div>
<!--<span>
下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
</span>-->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>设置</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-header>
<el-main class="main">
<router-view /></el-main>
</el-container>
</el-container>
</template>
<script>
import AppAside from './component/aside'
import { getUserProfile } from '@/api/user'
export default {
name: 'LayoutIndex',
components: { AppAside },
component: {
AppAside
},
data () {
return {
user: {},
isCollapse: false// 侧边栏展开状态
}
},
created () {
this.loadUserProfile()
},
methods: {
loadUserProfile () {
// 这个接口需要授权才能使用
getUserProfile().then(res => {
console.log(res)
this.user = res.data.data
})
}
}
}
</script>
<style scoped lang="less">
.layout-container{
position: fixed;
left:0;
right:0;
top:0;
bottom: 0;
}
.aside{
width: 100px;
background-color: #d3dce6;
.aside-menu{
height: 100%;
}
}
.header{
height: 60px;
background-color: #b3c0d1;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #ccc;
}
.main{
background-color: #e9eef3;
}
.avatar-wrap{
display: flex;
align-items: center;
.avatar{
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
}
</style>
aside.vue
<template>
<!--
el-menu-item 的 index 不能重复,确保唯一即可
-->
<el-menu
class="nav-menu el-menu-vertical-demo"
:default-active="$route.path"
background-color="#002033"
text-color="#fff"
active-text-color="#ffd04b"
router
:collapse="isCollapse"
>
<el-menu-item index="/">
<i class="el-icon-s-home"></i>
<span slot="title">首页</span>
</el-menu-item>
<el-menu-item index="/article">
<i class="el-icon-document"></i>
<span slot="title">内容管理</span>
</el-menu-item>
<el-menu-item index="/image">
<i class="iconfont iconimage"></i>
<span slot="title">素材管理</span>
</el-menu-item>
<el-menu-item index="/publish">
<i class="iconfont iconpublish"></i>
<span slot="title">发布文章</span>
</el-menu-item>
<el-menu-item index="/comment">
<i class="iconfont iconcomment"></i>
<span slot="title">评论管理</span>
</el-menu-item>
<el-menu-item index="/fans">
<i class="el-icon-setting"></i>
<span slot="title">粉丝管理</span>
</el-menu-item>
<el-menu-item index="/settings">
<i class="el-icon-setting"></i>
<span slot="title">个人设置</span>
</el-menu-item>
</el-menu>
</template>
<script>
export default {
name: 'AppAside',
data () {
return {
/* isCollapse: false */
}
},
props: ['is-collapse'],
methods: {
handleOpen (key, keyPath) {
console.log(key, keyPath)
},
handleClose (key, keyPath) {
console.log(key, keyPath)
}
}
}
</script>
<style scoped lang="less">
.nav-menu {
.iconfont {
margin-right: 10px;
padding-left: 5px;
}
}
</style>
request.js
// axios
import axios from 'axios'
// 创建实例 通过实例发送请求
const request = axios.create({
// 请求的基本路径
baseURL: 'http://ttapi.research.itcast.cn/'
})
// 导出
export default request
// 请求拦截器
request.interceptors.request.use(
function (config) {
console.log(config)
const user = JSON.parse(window.localStorage.getItem('user'))
if (user) {
config.headers.Authorization = `Bearer ${user.token}`
}
return config
}, function (error) {
return Promise.reject(error)
}
)
// 响应烂机器
/*
import request from 'request.js'
request.xxx
request({
method:,
url:''
})
*/
运行结果

浙公网安备 33010602011771号