做了很久的管理系统,本次版本突然说首页要在移动端也能展示为自适应的登录,所以进行了一些改造:
判断当前设备是手机端或者pc端,根据设备展示页面 在项目中经常会遇到支持 pc端 与手机端的需求。但是 pc
端和手机端尺寸差距很大,一个文件很难实现这种需求。 这个时候就需要判断当前的设备,根据设备来跳转不同的路由。
项目 router 文件夹下的 index.js 中有两个路由,分别是 pc 端路由和移动端路由
export default new Router({
routes: [
{
path: '/',
redirect:'/pc-home'
},
// pc端的路由
{
path:'/pc-home',
name:'pc-home',
component:()=>import('@/components/pc/Home')
},
// 手机端的路由
{
path:'/phone-home',
name:'phone-home',
component:()=>import('@/components/phone/Home')
}
]
})
在 App.vue 中判断当前设备进行跳转路由
export default {
name: "App",
mounted() {
if (this._isMobile()) {
// 跳转至手机端路由
alert("手机端");
this.$router.replace("/phone-home");
} else {
// 跳转至 pc 端路由
alert("pc端");
this.$router.replace("/pc-home");
}
},
methods: {
_isMobile() {
let flag = navigator.userAgent.match(
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
);
return flag;
},
},
};
根据这种不同的页面,进行适配两套,在移动端以及pc端的展示,成功解决
pc端展示的界面
<template>
<div class="login-container">
<div class="bg01">
<div class="content">
<div>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" auto-complete="on" class="login-form" label-position="left">
<div>
<img alt="" src="../../icons/logo.png" style="width: 40px; height: 40px"/>
</div>
<div class="title-container">
<span class="title">欢迎您登录638医品管理系统</span>
</div>
<el-form-item prop="managerPhoneNumber">
<img alt="" class="svg-container" src="../../icons/zhanghao@3x.png"/>
<el-input ref="managerPhoneNumber" v-model="loginForm.managerPhoneNumber" auto-complete="on" name="managerPhoneNumber" placeholder="请输入手机号" maxlength="11" tabindex="1" type="text"/>
</el-form-item>
<el-form-item prop="password">
<img alt="" class="svg-container" src="../../icons/mima@3x.png"/>
<el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" auto-complete="on" name="password" placeholder="请输入密码" tabindex="2" @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" style="width: 100%; margin-bottom: 30px" type="primary" @click.native.prevent="handleLogin">登录 </el-button>
<div class="tips">
<span>竭诚为患者服务,为医药、卫生事业服务</span>
<div class="lintliet"></div>
<div class="lintright"></div>
</div>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import {setSessionStorage} from '@/utils/auth.js'
export default {
name: "Login",
data() {
return {
loginForm: {
managerPhoneNumber: "",
password: "",
},
loginRules: {
managerPhoneNumber: [
{required: true, message: "请输入手机号", trigger: "blur"},
{pattern:/^1[3456789]\d{9}$/, message: '手机格式错误', trigger: 'blur'}
],
password: [
{required: true, message: "密码不能少于6位", trigger: "blur"},
{min: 6, max: 16, message: "长度在 6 到 16 个字符", trigger: "blur"}
],
},
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() {
let Base64 = require('js-base64').Base64;
this.loginForm.password = Base64.encode(this.loginForm.password)
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true;
this.$http.requestPost({
url: '/login',
param: this.loginForm,
loading: false
}).then(res => {
setSessionStorage('userToken', res.data.token)
setSessionStorage('userInfo', res.data)
this.getMenuTree(res.data)
}).catch(err => {
this.loading = false;
})
} else {
console.log("error submit!!");
return false;
}
});
},
// 获取用户菜单
getMenuTree(data) {
this.$http.requestGet({ url:'/login/getMenuTree/' + data.managerId, loading:false }).then(res => {
this.routes = res.data
this.$store.commit('user/SET_MENU_LIST', res.data)
this.loading = false;
let url = '';
if (this.routes.length < 1) return this.$message.warning('该用户没有权限,请先去设置权限!')
url = this.getUrl(this.routes[0].children, this.routes[0].path)
this.$router.push(url);
})
},
getUrl(arr, str) {
if (arr.length == 0) return ''
str += '/' + arr[0].path
if (arr[0].children.length > 0) {
return this.getUrl(arr[0].children, str)
} else {
return str
}
}
},
};
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
// $bg: #283443;
$light_gray: #000;
$cursor: #000;
@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: #f7f7f7;
border-radius: 5px;
color: #000;
}
}
</style>
<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #f5f5f5;
$light_gray: #000;
$blueness: #3c8fee;
.login-container {
z-index: 99999999;
height: 100vh;
width: 100%;
overflow: hidden;
.bg01 {
position: relative;
width: 100%;
/* 无限高 */
min-height: 100vh;
background: url(../../icons/bg01.png) no-repeat;
background-size: cover;
overflow: hidden;
.content {
position: relative;
display: flex;
width: 60%;
min-width: 900px;
height: 410px;
margin: 212px auto 0;
background: url(../../icons/bg02.png) no-repeat;
background-size: cover;
}
.login-form {
position: absolute;
right: -5px;
top: -120px;
width: 380px;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
position: relative;
font-size: 12px;
color: $blueness;
margin: -10px 40px 10px;
.lintliet {
position: absolute;
top: 6px;
left: -30px;
width: 20px;
height: 1px;
background-color: $blueness;
}
.lintright {
position: absolute;
top: 6px;
right: -20px;
width: 20px;
height: 1px;
background-color: $blueness;
}
}
.svg-container {
margin: 0 0 5px 10px;
color: $dark_gray;
vertical-align: middle;
width: 15px;
height: 15px;
display: inline-block;
}
.title-container {
position: relative;
margin: 10px auto 20px;
.title {
font-size: 12px;
color: #333333;
text-align: center;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
}
</style>
移动端展示的界面
<template>
<div class="login-container">
<div class="bg01">
<div class="content">
<div>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" auto-complete="on" class="login-form" label-position="left">
<div>
<img alt="" src="../../icons/logo.png" style="width: 40px; height: 40px"/>
</div>
<div class="title-container">
<span class="title">欢迎您登录638医品管理系统</span>
</div>
<el-form-item prop="managerPhoneNumber">
<img alt="" class="svg-container" src="../../icons/zhanghao@3x.png"/>
<el-input ref="managerPhoneNumber" v-model="loginForm.managerPhoneNumber" auto-complete="on" name="managerPhoneNumber" placeholder="请输入手机号" maxlength="11" tabindex="1" type="text"/>
</el-form-item>
<el-form-item prop="password">
<img alt="" class="svg-container" src="../../icons/mima@3x.png"/>
<el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" auto-complete="on" name="password" placeholder="请输入密码" tabindex="2" @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" style="width: 100%; margin-bottom: 30px" type="primary" @click.native.prevent="handleLogin">登录 </el-button>
<div class="tips">
<span>竭诚为患者服务,为医药、卫生事业服务</span>
<div class="lintliet"></div>
<div class="lintright"></div>
</div>
</el-form>
</div>
</div>
</div>
</div>
</template>
<script>
import {setSessionStorage} from '@/utils/auth.js'
export default {
name: "Login",
data() {
return {
loginForm: {
managerPhoneNumber: "",
password: "",
},
loginRules: {
managerPhoneNumber: [
{required: true, message: "请输入手机号", trigger: "blur"},
{pattern:/^1[3456789]\d{9}$/, message: '手机格式错误', trigger: 'blur'}
],
password: [
{required: true, message: "密码不能少于6位", trigger: "blur"},
{min: 6, max: 16, message: "长度在 6 到 16 个字符", trigger: "blur"}
],
},
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() {
let Base64 = require('js-base64').Base64;
this.loginForm.password = Base64.encode(this.loginForm.password)
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true;
this.$http.requestPost({
url: '/login',
param: this.loginForm,
loading: false
}).then(res => {
setSessionStorage('userToken', res.data.token)
setSessionStorage('userInfo', res.data)
this.getMenuTree(res.data)
}).catch(err => {
this.loading = false;
})
} else {
console.log("error submit!!");
return false;
}
});
},
// 获取用户菜单
getMenuTree(data) {
this.$http.requestGet({ url:'/login/getMenuTree/' + data.managerId, loading:false }).then(res => {
this.routes = res.data
this.$store.commit('user/SET_MENU_LIST', res.data)
this.loading = false;
let url = '';
if (this.routes.length < 1) return this.$message.warning('该用户没有权限,请先去设置权限!')
url = this.getUrl(this.routes[0].children, this.routes[0].path)
this.$router.push(url);
})
},
getUrl(arr, str) {
if (arr.length == 0) return ''
str += '/' + arr[0].path
if (arr[0].children.length > 0) {
return this.getUrl(arr[0].children, str)
} else {
return str
}
}
},
};
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
// $bg: #283443;
$light_gray: #000;
$cursor: #000;
@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: #f7f7f7;
border-radius: 5px;
color: #000;
}
}
</style>
<style lang="scss" scoped>
$bg: #2d3a4b;
$dark_gray: #f5f5f5;
$light_gray: #000;
$blueness: #3c8fee;
.login-container {
z-index: 99999999;
height: 100vh;
width: 100%;
overflow: hidden;
.bg01 {
position: relative;
width: 100%;
/* 无限高 */
min-height: 100vh;
background: url(../../icons/bg01.png) no-repeat;
background-size: cover;
overflow: hidden;
.content {
position: relative;
display: flex;
width: 20%;
min-width: 23rem;
height: 300px;
margin: 212px auto 0;
// background: url(../../icons/bg02.png) no-repeat;
border: 1px solid #fff;
background: #fff;
background-size: cover;
}
.login-form {
position: absolute;
right: -5px;
top: -120px;
width: 380px;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
position: relative;
font-size: 12px;
color: $blueness;
margin: -10px 40px 10px;
.lintliet {
position: absolute;
top: 6px;
left: -30px;
width: 20px;
height: 1px;
background-color: $blueness;
}
.lintright {
position: absolute;
top: 6px;
right: -20px;
width: 20px;
height: 1px;
background-color: $blueness;
}
}
.svg-container {
margin: 0 0 5px 10px;
color: $dark_gray;
vertical-align: middle;
width: 15px;
height: 15px;
display: inline-block;
}
.title-container {
position: relative;
margin: 10px auto 20px;
.title {
font-size: 12px;
color: #333333;
text-align: center;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
}
</style>