feat:迁移vue-element-admin登录页面
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^16.11.7",
|
"@types/node": "^16.11.7",
|
||||||
"@vitejs/plugin-vue": "^1.9.3",
|
"@vitejs/plugin-vue": "^1.9.3",
|
||||||
|
"sass": "^1.43.4",
|
||||||
"typescript": "^4.4.3",
|
"typescript": "^4.4.3",
|
||||||
"vite": "^2.6.4",
|
"vite": "^2.6.4",
|
||||||
"vue-tsc": "^0.3.0"
|
"vue-tsc": "^0.3.0"
|
||||||
|
|||||||
18
src/App.vue
18
src/App.vue
@@ -1,14 +1,12 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<router-view/>
|
<div id="app">
|
||||||
|
<router-view />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<script>
|
||||||
#app {
|
export default {
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
name: 'App'
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #2c3e50;
|
|
||||||
}
|
}
|
||||||
</style>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { createApp } from 'vue'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import {store,key} from './store'
|
import {store,key} from './store'
|
||||||
|
import '@styles/index.scss'
|
||||||
|
|
||||||
import ElementPlus from 'element-plus'
|
import ElementPlus from 'element-plus'
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ import Layout from '@/layout/index.vue'
|
|||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
|
path: '/login',
|
||||||
|
name: 'Login',
|
||||||
|
component: () => import('@views/login/index.vue'),
|
||||||
|
meta: {title: '登录'}
|
||||||
|
}, {
|
||||||
path: '/',
|
path: '/',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: '/dashboard',
|
redirect: '/dashboard',
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// 接口类型声明
|
// 接口类型声明
|
||||||
export interface UserState {
|
export interface UserState {
|
||||||
token: string,
|
token: string,
|
||||||
name: string,
|
nickname: string,
|
||||||
avatar: string,
|
avatar: string,
|
||||||
introduction: string,
|
|
||||||
roles: string[],
|
roles: string[],
|
||||||
perms: string[]
|
perms: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,42 @@
|
|||||||
import {Module} from "vuex";
|
import {Module} from "vuex";
|
||||||
import {UserState, RootStateTypes} from "@store/interface";
|
import {UserState, RootStateTypes} from "@store/interface";
|
||||||
import {Local} from "@utils/storage";
|
import {Local} from "@utils/storage";
|
||||||
import {login} from "@api/login"
|
import {getUserInfo, login,logout} from "@api/login"
|
||||||
import {rejects} from "assert";
|
|
||||||
|
|
||||||
|
const getDefaultState = () => {
|
||||||
|
return {
|
||||||
|
token: Local.get('token'),
|
||||||
|
nickname: '',
|
||||||
|
avatar: '',
|
||||||
|
roles: [],
|
||||||
|
perms: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const userModule: Module<UserState, RootStateTypes> = {
|
const userModule: Module<UserState, RootStateTypes> = {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state: {
|
state: {
|
||||||
token: Local.get('token') || '',
|
token: Local.get('token') || '',
|
||||||
name: '',
|
nickname: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
introduction: '',
|
|
||||||
roles: [],
|
roles: [],
|
||||||
perms: []
|
perms: []
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
RESET_STATE: (state) => {
|
||||||
|
Object.assign(state, getDefaultState())
|
||||||
|
},
|
||||||
SET_TOKEN(state: UserState, token: string) {
|
SET_TOKEN(state: UserState, token: string) {
|
||||||
state.token = token
|
state.token = token
|
||||||
},
|
},
|
||||||
SET_NAME(state: UserState, name: string) {
|
SET_NICKNAME(state: UserState, nickname: string) {
|
||||||
state.name = name
|
state.nickname = nickname
|
||||||
},
|
},
|
||||||
SET_AVATAR(state: UserState, avatar: string) {
|
SET_AVATAR(state: UserState, avatar: string) {
|
||||||
state.avatar = avatar
|
state.avatar = avatar
|
||||||
},
|
},
|
||||||
SET_INTRODUCTION(state: UserState, introduction: string) {
|
|
||||||
state.introduction = introduction
|
|
||||||
},
|
|
||||||
SET_ROLES(state: UserState, roles: string[]) {
|
SET_ROLES(state: UserState, roles: string[]) {
|
||||||
state.roles = roles
|
state.roles = roles
|
||||||
},
|
},
|
||||||
@@ -35,21 +45,77 @@ const userModule: Module<UserState, RootStateTypes> = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
// 登录
|
/**
|
||||||
login({commit}, userInfo: { username: string, password: string }) {
|
* 用户登录请求
|
||||||
const {username, password} = userInfo
|
* @param userInfo 登录用户信息
|
||||||
|
* username: 用户名
|
||||||
|
* password: 密码
|
||||||
|
* code: 验证码
|
||||||
|
* uuid: 匹配正确验证码的 key
|
||||||
|
*/
|
||||||
|
login({commit}, userInfo: { username: string, password: string, code: string, uuid: string }) {
|
||||||
|
const {username, password, code, uuid} = userInfo
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login({ username: username.trim(), password: password }).then(response => {
|
login(
|
||||||
|
{
|
||||||
|
username: username.trim(),
|
||||||
|
password: password,
|
||||||
|
grant_type: 'captcha',
|
||||||
|
code: code,
|
||||||
|
uuid: uuid
|
||||||
|
}
|
||||||
|
).then(response => {
|
||||||
const {access_token, token_type} = response.data
|
const {access_token, token_type} = response.data
|
||||||
const accessToken = token_type + " " + access_token
|
const accessToken = token_type + " " + access_token
|
||||||
Local.set("token",accessToken)
|
Local.set("token", accessToken)
|
||||||
commit('SET_TOKEN',accessToken)
|
commit('SET_TOKEN', accessToken)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取用户信息(昵称、头像、角色集合、权限集合)
|
||||||
|
*/
|
||||||
|
getUserInfo({commit, state}) {
|
||||||
|
return new Promise(((resolve, reject) => {
|
||||||
|
getUserInfo().then(response => {
|
||||||
|
const {data} = response
|
||||||
|
if (!data) {
|
||||||
|
return reject('Verification failed, please Login again.')
|
||||||
|
}
|
||||||
|
const {nickname, avatar, roles, perms} = data
|
||||||
|
if (!roles || roles.length <= 0) {
|
||||||
|
reject('getUserInfo: roles must be a non-null array!')
|
||||||
|
}
|
||||||
|
commit('SET_NICKNAME', nickname)
|
||||||
|
commit('SET_AVATAR', avatar)
|
||||||
|
commit('SET_ROLES', roles)
|
||||||
|
commit('SET_PERMS', perms)
|
||||||
|
|
||||||
|
resolve(data)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销
|
||||||
|
*/
|
||||||
|
logout({commit,state}){
|
||||||
|
return new Promise(((resolve, reject) => {
|
||||||
|
logout().then(()=>{
|
||||||
|
Local.remove('token')
|
||||||
|
commit('RESET_STATE')
|
||||||
|
}).catch(error=>{
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
@import './variables.scss';
|
|
||||||
|
|
||||||
@mixin colorBtn($color) {
|
|
||||||
background: $color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $color;
|
|
||||||
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
background: $color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.blue-btn {
|
|
||||||
@include colorBtn($blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
.light-blue-btn {
|
|
||||||
@include colorBtn($light-blue)
|
|
||||||
}
|
|
||||||
|
|
||||||
.red-btn {
|
|
||||||
@include colorBtn($red)
|
|
||||||
}
|
|
||||||
|
|
||||||
.pink-btn {
|
|
||||||
@include colorBtn($pink)
|
|
||||||
}
|
|
||||||
|
|
||||||
.green-btn {
|
|
||||||
@include colorBtn($green)
|
|
||||||
}
|
|
||||||
|
|
||||||
.tiffany-btn {
|
|
||||||
@include colorBtn($tiffany)
|
|
||||||
}
|
|
||||||
|
|
||||||
.yellow-btn {
|
|
||||||
@include colorBtn($yellow)
|
|
||||||
}
|
|
||||||
|
|
||||||
.pan-btn {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #fff;
|
|
||||||
padding: 14px 36px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
transition: 600ms ease all;
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #fff;
|
|
||||||
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
width: 100%;
|
|
||||||
transition: 600ms ease all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before,
|
|
||||||
&:after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
height: 2px;
|
|
||||||
width: 0;
|
|
||||||
transition: 400ms ease all;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
right: inherit;
|
|
||||||
top: inherit;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-button {
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: pointer;
|
|
||||||
background: #fff;
|
|
||||||
color: #fff;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
text-align: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
outline: 0;
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px 15px;
|
|
||||||
font-size: 14px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
@@ -15,36 +15,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell {
|
|
||||||
.el-tag {
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-padding {
|
|
||||||
.cell {
|
|
||||||
padding-left: 5px;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixed-width {
|
|
||||||
.el-button--mini {
|
|
||||||
padding: 7px 10px;
|
|
||||||
min-width: 60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-col {
|
|
||||||
.cell {
|
|
||||||
padding: 0 10px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.el-tag {
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// to fixed https://github.com/ElemeFE/element/issues/2461
|
// to fixed https://github.com/ElemeFE/element/issues/2461
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
@@ -73,11 +43,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix date-picker ui bug in filter-item
|
|
||||||
.el-range-editor.el-input__inner {
|
|
||||||
display: inline-flex !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to fix el-date-picker css style
|
// to fix el-date-picker css style
|
||||||
.el-range-separator {
|
.el-range-separator {
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
/**
|
|
||||||
* I think element-ui's default theme color is too light for long-term use.
|
|
||||||
* So I modified the default color and you can modify it to your liking.
|
|
||||||
**/
|
|
||||||
|
|
||||||
/* theme color */
|
|
||||||
$--color-primary: #1890ff;
|
|
||||||
$--color-success: #13ce66;
|
|
||||||
$--color-warning: #ffba00;
|
|
||||||
$--color-danger: #ff4949;
|
|
||||||
// $--color-info: #1E1E1E;
|
|
||||||
|
|
||||||
$--button-font-weight: 400;
|
|
||||||
|
|
||||||
// $--color-text-regular: #1f2d3d;
|
|
||||||
|
|
||||||
$--border-color-light: #dfe4ed;
|
|
||||||
$--border-color-lighter: #e6ebf5;
|
|
||||||
|
|
||||||
$--table-border: 1px solid #dfe6ec;
|
|
||||||
|
|
||||||
/* icon font path, required */
|
|
||||||
$--font-path: "~element-ui/lib/theme-chalk/fonts";
|
|
||||||
|
|
||||||
@import "~element-ui/packages/theme-chalk/src/index";
|
|
||||||
|
|
||||||
// the :export directive is the magic sauce for webpack
|
|
||||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
|
||||||
:export {
|
|
||||||
theme: $--color-primary;
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,10 @@
|
|||||||
@import './transition.scss';
|
@import './transition.scss';
|
||||||
@import './element-ui.scss';
|
@import './element-ui.scss';
|
||||||
@import './sidebar.scss';
|
@import './sidebar.scss';
|
||||||
@import './btn.scss';
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
@@ -32,14 +33,6 @@ html {
|
|||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-padding {
|
|
||||||
padding: 0px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.padding-content {
|
|
||||||
padding: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:focus,
|
a:focus,
|
||||||
a:active {
|
a:active {
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -57,34 +50,6 @@ div:focus {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fr {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fl {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pr-5 {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pl-5 {
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pointer {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inlineBlock {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clearfix {
|
.clearfix {
|
||||||
&:after {
|
&:after {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@@ -96,96 +61,7 @@ div:focus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aside {
|
// main-container global css
|
||||||
background: #eef1f6;
|
|
||||||
padding: 8px 24px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 2px;
|
|
||||||
display: block;
|
|
||||||
line-height: 32px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
|
||||||
color: #2c3e50;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #337ab7;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: rgb(32, 160, 255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//main-container全局样式
|
|
||||||
.app-container {
|
.app-container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.components-container {
|
|
||||||
margin: 30px 50px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination-container {
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-center {
|
|
||||||
text-align: center
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-navbar {
|
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
text-align: right;
|
|
||||||
padding-right: 20px;
|
|
||||||
transition: 600ms ease position;
|
|
||||||
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.draft {
|
|
||||||
background: #d0d0d0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.deleted {
|
|
||||||
background: #d0d0d0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-type,
|
|
||||||
.link-type:focus {
|
|
||||||
color: #337ab7;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: rgb(32, 160, 255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-container {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
|
|
||||||
.filter-item {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//refine vue-multiselect plugin
|
|
||||||
.multiselect {
|
|
||||||
line-height: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.multiselect--active {
|
|
||||||
z-index: 1000 !important;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -26,41 +26,3 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin pct($pct) {
|
|
||||||
width: #{$pct};
|
|
||||||
position: relative;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin triangle($width, $height, $color, $direction) {
|
|
||||||
$width: $width/2;
|
|
||||||
$color-border-style: $height solid $color;
|
|
||||||
$transparent-border-style: $width solid transparent;
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
|
|
||||||
@if $direction==up {
|
|
||||||
border-bottom: $color-border-style;
|
|
||||||
border-left: $transparent-border-style;
|
|
||||||
border-right: $transparent-border-style;
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $direction==right {
|
|
||||||
border-left: $color-border-style;
|
|
||||||
border-top: $transparent-border-style;
|
|
||||||
border-bottom: $transparent-border-style;
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $direction==down {
|
|
||||||
border-top: $color-border-style;
|
|
||||||
border-left: $transparent-border-style;
|
|
||||||
border-right: $transparent-border-style;
|
|
||||||
}
|
|
||||||
|
|
||||||
@else if $direction==left {
|
|
||||||
border-right: $color-border-style;
|
|
||||||
border-top: $transparent-border-style;
|
|
||||||
border-bottom: $transparent-border-style;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
// base color
|
|
||||||
$blue:#324157;
|
|
||||||
$light-blue:#3A71A8;
|
|
||||||
$red:#C03639;
|
|
||||||
$pink: #E65D6E;
|
|
||||||
$green: #30B08F;
|
|
||||||
$tiffany: #4AB7BD;
|
|
||||||
$yellow:#FEC171;
|
|
||||||
$panGreen: #30B08F;
|
|
||||||
|
|
||||||
// sidebar
|
// sidebar
|
||||||
$menuText:#bfcbd9;
|
$menuText:#bfcbd9;
|
||||||
$menuActiveText:#409EFF;
|
$menuActiveText:#409EFF;
|
||||||
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
|
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
|
||||||
|
|
||||||
$menuBg:#304156;
|
$menuBg:#304156;
|
||||||
$menuHover:#263445;
|
$menuHover:#263445;
|
||||||
|
|||||||
233
src/views/login/index.vue
Normal file
233
src/views/login/index.vue
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
<template>
|
||||||
|
<div class="login-container">
|
||||||
|
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
|
||||||
|
<div class="title-container">
|
||||||
|
<h3 class="title">Login Form</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<span class="svg-container">
|
||||||
|
<svg-icon icon-class="user" />
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
ref="username"
|
||||||
|
v-model="loginForm.username"
|
||||||
|
placeholder="Username"
|
||||||
|
name="username"
|
||||||
|
type="text"
|
||||||
|
tabindex="1"
|
||||||
|
auto-complete="on"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<span class="svg-container">
|
||||||
|
<svg-icon icon-class="password" />
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
:key="passwordType"
|
||||||
|
ref="password"
|
||||||
|
v-model="loginForm.password"
|
||||||
|
:type="passwordType"
|
||||||
|
placeholder="Password"
|
||||||
|
name="password"
|
||||||
|
tabindex="2"
|
||||||
|
auto-complete="on"
|
||||||
|
@keyup.enter.native="handleLogin"
|
||||||
|
/>
|
||||||
|
<span class="show-pwd" @click="showPwd">
|
||||||
|
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>
|
||||||
|
|
||||||
|
<div class="tips">
|
||||||
|
<span style="margin-right:20px;">username: admin</span>
|
||||||
|
<span> password: any</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Login',
|
||||||
|
data() {
|
||||||
|
const validatePassword = (rule, value, callback) => {
|
||||||
|
if (value.length < 6) {
|
||||||
|
callback(new Error('The password can not be less than 6 digits'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
loginForm: {
|
||||||
|
username: 'admin',
|
||||||
|
password: '111111'
|
||||||
|
},
|
||||||
|
loginRules: {
|
||||||
|
username: [{ required: true, trigger: 'blur'}],
|
||||||
|
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
passwordType: 'password',
|
||||||
|
redirect: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
$route: {
|
||||||
|
handler: function(route) {
|
||||||
|
this.redirect = route.query && route.query.redirect
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showPwd() {
|
||||||
|
if (this.passwordType === 'password') {
|
||||||
|
this.passwordType = ''
|
||||||
|
} else {
|
||||||
|
this.passwordType = 'password'
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.password.focus()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleLogin() {
|
||||||
|
this.$refs.loginForm.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
this.loading = true
|
||||||
|
|
||||||
|
// 暂跳转首页控制台,后续整合登录
|
||||||
|
this.$router.push({ path: '/' })
|
||||||
|
return false
|
||||||
|
|
||||||
|
this.$store.dispatch('user/login', this.loginForm).then(() => {
|
||||||
|
this.$router.push({ path: this.redirect || '/' })
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('error submit!!')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
/* 修复input 背景不协调 和光标变色 */
|
||||||
|
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
|
||||||
|
|
||||||
|
$bg:#283443;
|
||||||
|
$light_gray:#fff;
|
||||||
|
$cursor: #fff;
|
||||||
|
|
||||||
|
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
|
||||||
|
.login-container .el-input input {
|
||||||
|
color: $cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset element-ui css */
|
||||||
|
.login-container {
|
||||||
|
.el-input {
|
||||||
|
display: inline-block;
|
||||||
|
height: 47px;
|
||||||
|
width: 85%;
|
||||||
|
|
||||||
|
input {
|
||||||
|
background: transparent;
|
||||||
|
border: 0px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border-radius: 0px;
|
||||||
|
padding: 12px 5px 12px 15px;
|
||||||
|
color: $light_gray;
|
||||||
|
height: 47px;
|
||||||
|
caret-color: $cursor;
|
||||||
|
|
||||||
|
&:-webkit-autofill {
|
||||||
|
box-shadow: 0 0 0px 1000px $bg inset !important;
|
||||||
|
-webkit-text-fill-color: $cursor !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item {
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$bg:#2d3a4b;
|
||||||
|
$dark_gray:#889aa4;
|
||||||
|
$light_gray:#eee;
|
||||||
|
|
||||||
|
.login-container {
|
||||||
|
min-height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: $bg;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
position: relative;
|
||||||
|
width: 520px;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 160px 35px 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
&:first-of-type {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svg-container {
|
||||||
|
padding: 6px 5px 6px 15px;
|
||||||
|
color: $dark_gray;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 30px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 26px;
|
||||||
|
color: $light_gray;
|
||||||
|
margin: 0px auto 40px auto;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-pwd {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 7px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: $dark_gray;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -45,7 +45,11 @@ export default defineConfig({
|
|||||||
{
|
{
|
||||||
find:"@views",
|
find:"@views",
|
||||||
replacement: path.resolve("./src/views")
|
replacement: path.resolve("./src/views")
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
find:"@styles",
|
||||||
|
replacement: path.resolve("./src/styles")
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user