html

<el-form
class="login-form"
:rules="loginRules"
ref="form"
:model="form"
label-width="0"
>
<el-form-item prop="username">
<el-input
size="small"
v-model="form.username"
auto-complete="false"
placeholder="请输入用户名"
@focus="focus(0)"
@blur="blur(0)"
>
<i
slot="prefix"
class="iconfont icon-yonghu1"
:style="isFocus[0] ? 'color:#1c8ffa' : ''"
></i>
</el-input>
<!-- input输入框获取焦点的时候(isFocus[0]为true),蓝线才出来,表示正确,而且存在一个过渡效果 -->
<div
class="bottom-line"
:style="isFocus[0] ? 'left:0%; width:100%;' : ''"
></div>
<!-- 没有填写内容,并且失去焦点的时候,再显示红线,表示错误 -->
<div
class="bottom-error-line"
:style="(errorArr[0] && !isFocus[0]) ? 'left:0%; width:100%;' : ''"
></div>
<!-- 对钩 √-->
<span class="iconfont icon-wancheng1" v-show="correctArr[0]"></span>
<!-- 叉号x -->
<span class="iconfont icon-close" v-show="incorrectArr[0]"></span>
</el-form-item>
<el-form-item prop="password">
<el-input
size="small"
type="password"
v-model="form.password"
auto-complete="false"
placeholder="请输入密码"
@keyup.enter.native="submitForm"
@focus="focus(1)"
@blur="blur(1)"
>
<i
slot="prefix"
class="iconfont icon-mima1"
:style="isFocus[1] ? 'color:#1c8ffa' : ''"
></i>
</el-input>
<div
class="bottom-line"
:style="isFocus[1] ? 'left:0%; width:100%;' : ''"
></div>
<div
class="bottom-error-line"
:style="(errorArr[1] && !isFocus[1]) ? 'left:0%; width:100%;' : ''"
></div>
<span class="iconfont icon-wancheng1" v-show="correctArr[1]"></span>
<span class="iconfont icon-close" v-show="incorrectArr[1]"></span>
</el-form-item>

<div class="more">
<el-checkbox v-model="checked">记住密码</el-checkbox>
</div>

<div
class="login-button"
v-waves="{color:'#ffffff',time:wavesTime}"
@click="submitForm">登 录</div>
</el-form>

css

.bottom-line {
content: "";
width: 0px;
height: 1px;
background: #1c8ffa;
position: absolute;
bottom: -1px;
left: 30%;
transition: all 0.4s;
}
.bottom-error-line {
content: "";
width: 0px;
height: 1px;
background: #f25555;
position: absolute;
bottom: -1px;
left: 50%;
transition: all 0.4s;
}

data

export default {
name: 'user-login',
data() {
// 自定义校验规则:用户名
const validateUser = (rule, value, callback) => {
// if (!isvalidUsername(value)) {
// 检验没有通过
if (!value) {
// 设置不显示对钩
this.$set(this.correctArr, 0, false);
// 设置显示叉号
this.$set(this.incorrectArr, 0, true);
// 设置显示红色的下横线
this.$set(this.errorArr, 0, true);
callback(new Error('请输入用户名'));
// callback();
} else {
// 设置显示对钩
this.$set(this.correctArr, 0, true);
// 设置不显示叉号
this.$set(this.incorrectArr, 0, false);
// 设置不显示红色的下横线
this.$set(this.errorArr, 0, false);
callback();
}
};
// 自定义校验规则:密码
const validatePassword = (rule, value, callback) => {
if (!value) {
this.$set(this.correctArr, 1, false);
this.$set(this.incorrectArr, 1, true);
this.$set(this.errorArr, 1, true);
callback(new Error('请输入密码'));
} else {
this.$set(this.correctArr, 1, true);
this.$set(this.incorrectArr, 1, false);
this.$set(this.errorArr, 1, false);
callback();
}
};
return {
form: {
username: '1',
password: '1',
},
// 记住密码
checked: false,
// 每个选框是否获取焦点
isFocus: [false, false],
// 每个选框是否正确 对号
correctArr: [false, false],
// 每个选框是否正确 叉号
incorrectArr: [false],
// 每个选框是否错误,红色的下横线
errorArr: [false, false],
// 验证规则
loginRules: {
username: [
// validator 自定义校验规则
{ required: true, trigger: 'blur', validator: validateUser },
],
password: [
{ required: true, trigger: 'blur', validator: validatePassword },
],
},
// setTimout对象
timer: null,
};
},

mounted() {
// 记住密码处理
// 每次打开页面的时候,都从cookie里面获取账号,密码,checked
this.form.username = dealCookie.get('E_username');
this.form.password = dealCookie.get('E_password');
this.checked = Boolean(dealCookie.get('E_checked'));
},

methods: {
// 聚焦改变样式
focus(index) {
this.$set(this.isFocus, index, true);
},
// 失焦改变样式
blur(index) {
this.$set(this.isFocus, index, false);
},
// 提交
submitForm() {
// 清除定时器
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.$refs.form.validate((valid) => {
if (valid) {
const params = {
captcha: 'string',
domain: getSecHost(), // 获取二级域名 localhost
mac: 'string',
password: this.form.password,
username: this.form.username,
};
login(params).then((res) => {
if (res.code === '00000') {
// //判断复选框是否被勾选,就保存用户名,密码,时限7天
if (this.checked) {
// 设置cookie,保存7天
dealCookie.set('E_username', this.form.username, 7);
dealCookie.set('E_password', this.form.password, 7);
dealCookie.set('E_checked', true, 7);
} else { // 否则,删除cookie中保存的用户名,密码
dealCookie.delete('E_username');
dealCookie.delete('E_password');
dealCookie.delete('E_checked');
}
// 用户信息
const userInfo = res.data.userInfo || {};
//用户token
const token = res.data.token || '';
// 保存token到vuex和localstorage中
this.$store.commit('SET_TOKEN', token);
// 保存用户信息
this.$store.commit('SET_USERIFNO', userInfo);
this.$message.success('登录成功');
this.$router.push('/home');
} else {
this.$message.error(res.msg);
return false;
}
});
}
});
}, this.wavesTime * 1000);
},

util/util.js

// 设置cookies,获取cookie,删除cookie
export const dealCookie = {
// 设置cookies
set: (name, value, days) => {
const d = new Date();
d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days);
window.document.cookie = `${name}=${value};path=/;expires=${d.toGMTString()}`;
},
// 获取cookie
get: (name) => {
const v = window.document.cookie.match(`(^|;) ?${name}=([^;]*)(;|$)`);
return v ? v[2] : null;
},
// 删除cookie
delete: (name) => {
const d = new Date();
d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * -1);
window.document.cookie = `${name}='';path=/;expires=${d.toGMTString()}`;
},
};

vuex

import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import user from './modules/user';
import common from './modules/common';
import map from './modules/map';
import tags from './modules/tags';
import snow from './modules/snow';
import getters from './getters';

Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
user,
map,
common,
tags,
snow,
},
getters,
// 数据持久化
plugins: [createPersistedState({
storage: window.sessionStorage,
reducer(val) {
return {
// 只储存common模块中的数据
common: val.common,
user: val.user,
};
},
})],
});

export default store;

modules/user.js

import { setStore, getStore } from '@/util/store';

const user = {
state: {
// token,直接获取本地存储的token
token: getStore({ name: 'token' }) || '',
// 用户信息
userInfo: getStore({ name: 'userInfo' }) || {},
},
actions: {
// 退出登录
LOG_OUT: ({ commit }) => {
commit('SET_TOKEN', '');
},
},
mutations: {
// 存token
SET_TOKEN: (state, token) => {
state.token = token;
setStore({ name: 'token', content: state.token });
},
// 存用户信息
SET_USERIFNO: (state, userInfo) => {
setStore({ name: 'userInfo', content: userInfo });
state.userInfo = userInfo;
},

};
export default user;

util/store.js

import {
validatenull,
} from '@/util/validate';
/**
* 存储localStorage
*/
export const setStore = (params) => {
const {
name, // 名称
content, // 内容
type, // 类型
} = params;
const obj = {
dataType: typeof (content),
content,
type,
datetime: new Date().getTime(),
};
if (type) window.sessionStorage.setItem(name, JSON.stringify(obj));
else window.localStorage.setItem(name, JSON.stringify(obj));
};
/**
* 获取localStorage
*/

export const getStore = (params) => {
const {
name,
} = params;
let obj = {};
let content = '';
obj = window.sessionStorage.getItem(name);
if (validatenull(obj)) obj = window.localStorage.getItem(name);
if (validatenull(obj)) {
return undefined;
}
obj = JSON.parse(obj);
if (obj.dataType === 'string') {
content = obj.content;
} else if (obj.dataType === 'number') {
content = Number(obj.content);
} else if (obj.dataType === 'boolean') {
content = !!(obj.content);
} else if (obj.dataType === 'object') {
content = obj.content;
}
// eslint-disable-line
return content;
};
/**
* 删除localStorage
*/
export const removeStore = (params) => {
const {
name,
} = params;
window.localStorage.removeItem(name);
window.sessionStorage.removeItem(name);
};

/**
* 获取全部localStorage
*/
export const getAllStore = (params) => {
const list = [];
const {
type,
} = params;
for (let i = 1; i <= window.sessionStorage.length; i++) {
if (type) {
list.push({
name: window.sessionStorage.key(i),
content: getStore({
name: window.sessionStorage.key(i),
type: 'session',
}),
});
} else {
list.push(getStore({
name: window.localStorage.key(i),
content: getStore({
name: window.localStorage.key(i),
}),
}));
}
}

return list;
};

/**
* 清空全部localStorage
*/
export const clearStore = (params) => {
const {
type,
} = params;
if (type) {
window.sessionStorage.clear();
return;
}
window.localStorage.clear();
};

util/validate.js

/**
* 判断是否为空
*/
export function validatenull(val) {
if (typeof val === 'boolean') {
return false;
}
if (typeof val === 'number') {
return false;
}
if (val instanceof Array) {
if (val.length === 0) return true;
} else if (val instanceof Object) {
if (JSON.stringify(val) === '{}') return true;
} else {
if (val === 'null' || val === null || val === 'undefined' || val === undefined || val === '') return true;
return false;
}
return false;
}