Browse Source

feat: 登录修改密码;及路由\导航重构

feature-with-login
wally 4 years ago
parent
commit
6091902ba4
  1. 1
      .eslintrc.js
  2. 101
      src/App.vue
  3. 6
      src/apis/index.js
  4. BIN
      src/assets/u1.jpg
  5. 57
      src/components/navbar.vue
  6. 28
      src/routers/index.js
  7. 12
      src/store/user.js
  8. 2
      src/utils/axios.js
  9. 95
      src/views/Index.vue
  10. 114
      src/views/user/pw-change.vue
  11. 106
      src/views/user/sign-in.vue

1
.eslintrc.js

@ -12,6 +12,7 @@ module.exports = {
rules: {
'import/no-unresolved': 0,
'import/extensions': 0,
'import/no-extraneous-dependencies': 0,
'no-plusplus': 0,
'no-use-before-define': [
'error',

101
src/App.vue

@ -1,98 +1,27 @@
<template>
<el-config-provider :locale="local">
<el-container>
<router-view></router-view>
</el-container>
</el-config-provider>
</template>
<script setup>
import { computed, ref } from 'vue';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import Navbar from 'components/navbar.vue';
import zhCn from 'element-plus/lib/locale/lang/zh-cn';
import { ElMessage } from 'element-plus';
import { routes } from '@/routers/index.js';
import { useRouter } from 'vue-router';
const local = zhCn;
const store = useStore();
let timer = null;
const routeList = ref(routes);
const menu = computed(() => store.state.menu);
const activeMenuIndex = ref(0);
// queryu token
const route = useRoute();
const router = useRouter();
const userString = sessionStorage.getItem('user');
useRouter()
.isReady()
.then(async () => {
activeMenuIndex.value = routes.findIndex(item => item.name === route.name);
const u = computed(() => route.query.u);
if (!u.value) {
// urlu,
ElMessage.error('缺少用户信息参数');
} else {
// userId token
await store.dispatch('user/getTokenByUserId', u.value);
}
});
const token = computed(() => store.getters['user/token']);
//
const getDeviceData = async () => {
if (token && token.value) {
await store.dispatch('device/getDevices');
timer && clearTimeout(timer);
timer = null;
} else {
timer = setTimeout(() => {
getDeviceData();
}, 16);
}
};
getDeviceData();
/**
* 打开页面
* @param {string} path 页面路径
*/
function openPage(path) {
const { query } = route;
router.push({
path,
query,
});
if (userString) {
const user = JSON.parse(userString);
store.commit('user/setUser', user);
} else {
router.push({ name: 'signin' });
}
</script>
<template>
<el-config-provider :locale="local">
<el-container>
<el-header style="padding: 0">
<Navbar />
</el-header>
<el-container class="overflow-hidden">
<!-- <el-aside width="180px" v-if="menu.show"> -->
<el-aside v-if="menu.show" :width="!menu.collapse ? '200px' : '64px'">
<el-menu :collapse="menu.collapse" :default-active="activeMenuIndex" class="el-menu-vertical-demo">
<el-menu-item
v-for="(item, index) in routeList"
:key="item.name"
:index="index"
class="flex items-center"
@click="openPage(item.path)"
>
<i :class="item.meta.icon"></i>
<template #title>{{ item.meta.title }}</template>
</el-menu-item>
</el-menu>
</el-aside>
<el-main style="padding: 0">
<div class="p-4">
<router-view></router-view>
</div>
</el-main>
</el-container>
</el-container>
</el-config-provider>
</template>
<style>
html,
body,

6
src/apis/index.js

@ -9,6 +9,12 @@ const corrosion = `${apiUrl}/gateway/corrosion`;
// 根据userId 获取token
export const getToken = userId => http.get(`${users}/userId`, { params: { userId } });
// 登录
export const signIn = params => http.post(`${users}/signin`, params);
// 修改密码
export const changePassword = params => http.post(`${users}/password/account`, params);
// 获取设备列表
export const getDevices = () => http.get(`${corrosion}/devices`);

BIN
src/assets/u1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

57
src/components/navbar.vue

@ -1,23 +1,56 @@
<template>
<div class="flex items-center justify-between pr-5">
<h1 class="text-lg font-medium py-3 px-6">
<i
v-if="menu.show"
:class="{ 'text-gray-800': !menu.collapse, 'text-gray-400': menu.collapse }"
class="el-icon-guide mr-2"
@click="toggleCollapse"
></i>
{{ $route.meta.title || '智能大气腐蚀监测平台' }}
</h1>
<el-dropdown>
<span class="flex items-center">
<el-avatar class="mr-2" size="small" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png"></el-avatar>
<div class="mr-3">{{ account }}</div>
<el-icon class="el-icon--right">
<ArrowDown />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="openChangePassword">修改密码</el-dropdown-item>
<el-dropdown-item @click="signOut">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import { ArrowDown } from '@element-plus/icons';
const store = useStore();
const router = useRouter();
const toggleCollapse = () => {
console.log('Toggle Collapse');
store.commit('toggleCollapse');
};
const menu = computed(() => store.state.menu);
</script>
const account = computed(() => store.getters['user/account']);
<template>
<h1 class="text-lg font-medium py-3 px-6 shadow">
<i
class="el-icon-guide mr-2"
:class="{ 'text-gray-800': !menu.collapse, 'text-gray-400': menu.collapse }"
@click="toggleCollapse"
v-if="menu.show"
></i>
{{ $route.meta.title || '智能大气腐蚀监测平台' }}
</h1>
</template>
//
function openChangePassword() {
router.push({ name: 'pw-change' });
}
// 退
function signOut() {
store.commit('user/setUser', null);
router.push({ name: 'signin' });
}
</script>

28
src/routers/index.js

@ -67,18 +67,40 @@ export const routes = [
},
];
export const user = [
{
path: '/corrosion/user/signin',
name: 'signin',
meta: {},
component: () => import('views/user/sign-in.vue'),
},
{
path: '/corrosion/user/pw-change',
name: 'pw-change',
meta: {},
component: () => import('views/user/pw-change.vue'),
},
];
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
redirect: '/corrosion/overview',
redirect: '/corrosion/user/signin',
},
{
path: '/corrosion',
redirect: '/corrosion/overview',
redirect: '/corrosion/user/signin',
},
{
path: '/corrosion/home',
name: 'home',
component: () => import('views/Index.vue'),
children: routes,
},
].concat(routes),
...user,
],
});
export default router;

12
src/store/user.js

@ -14,6 +14,10 @@ export default {
if (!user) return null;
return user.id;
},
account({ user }) {
if (!user) return null;
return user.account;
},
},
mutations: {
@ -25,11 +29,11 @@ export default {
setUser(state, user) {
state.user = user;
if (user) {
localStorage.setItem('token', user.token);
localStorage.setItem('user', JSON.stringify(user));
sessionStorage.setItem('token', user.token);
sessionStorage.setItem('user', JSON.stringify(user));
} else {
localStorage.removeItem('token');
localStorage.removeItem('user');
sessionStorage.removeItem('token');
sessionStorage.removeItem('user');
}
},
},

2
src/utils/axios.js

@ -12,7 +12,7 @@ const instance = Axios.create({
// request
instance.interceptors.request.use(
config => {
const token = store.getters['user/token'] || localStorage.getItem('token');
const token = store.getters['user/token'] || sessionStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}

95
src/views/Index.vue

@ -0,0 +1,95 @@
<script setup>
import { computed, ref } from 'vue';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import Navbar from 'components/navbar.vue';
import zhCn from 'element-plus/lib/locale/lang/zh-cn';
import { ElMessage } from 'element-plus';
import { routes } from '@/routers/index.js';
const local = zhCn;
const store = useStore();
const routeList = ref(routes);
const menu = computed(() => store.state.menu);
const activeMenuIndex = ref(0);
// queryu token
const route = useRoute();
const router = useRouter();
//
const getDeviceData = async () => {
try {
await store.dispatch('device/getDevices');
} catch (error) {
ElMessage.error(error || '获取设备信息失败');
}
};
getDeviceData();
/**
* 打开页面
* @param {string} path 页面路径
*/
function openPage(path) {
const { query } = route;
router.push({
path,
query,
});
}
</script>
<template>
<el-config-provider :locale="local">
<el-container>
<el-header style="padding: 0">
<Navbar />
</el-header>
<el-container class="overflow-hidden">
<!-- <el-aside width="180px" v-if="menu.show"> -->
<el-aside v-if="menu.show" :width="!menu.collapse ? '200px' : '64px'">
<el-menu :collapse="menu.collapse" :default-active="activeMenuIndex" class="el-menu-vertical-demo">
<el-menu-item
v-for="(item, index) in routeList"
:key="item.name"
:index="index"
class="flex items-center"
@click="openPage(item.path)"
>
<i :class="item.meta.icon"></i>
<template #title>{{ item.meta.title }}</template>
</el-menu-item>
</el-menu>
</el-aside>
<el-main style="padding: 0">
<div class="p-4">
<router-view></router-view>
</div>
</el-main>
</el-container>
</el-container>
</el-config-provider>
</template>
<style>
html,
body,
#app,
#app > section {
height: 100%;
}
.el-menu {
min-height: 100%;
}
.el-form--label-top .el-form-item__label {
padding-bottom: 0 !important;
}
.el-form-item {
margin-bottom: 10px !important;
}
</style>

114
src/views/user/pw-change.vue

@ -0,0 +1,114 @@
<template>
<div class="wrap">
<div class="content border rounded-md">
<h1 class="text-2xl text-center font-bold mb-10 text-gray-700">智能大气腐蚀监测云平台</h1>
<el-form ref="passwordChangeFormRef" :model="passwordChangeForm" :rules="rules" label-width="70px" status-icon>
<el-form-item class="mb-3" label="账号" prop="account" style="margin-bottom: 22px !important">
<el-input v-model="passwordChangeForm.account" type="text"></el-input>
</el-form-item>
<el-form-item label="旧密码" prop="passwordOld" style="margin-bottom: 22px !important">
<el-input v-model="passwordChangeForm.passwordOld" type="password"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="passwordNew" style="margin-bottom: 22px !important">
<el-input v-model="passwordChangeForm.passwordNew" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button class="float-left" style="display: block; margin-bottom: 22px !important" type="primary" @click="onSubmit">
确认修改
</el-button>
<el-button class="float-right" type="text">
<router-link to="signin">返回登录</router-link>
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { changePassword } from 'apis';
import { ElMessage } from 'element-plus';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
const store = useStore();
const router = useRouter();
const passwordChangeFormRef = ref(null);
const passwordChangeForm = reactive({
account: '',
passwordOld: '',
passwordNew: '',
});
const rules = reactive({
account: [
{
required: true,
message: '请输入账号',
trigger: 'blur',
},
],
passwordOld: [
{
required: true,
message: '请输入旧密码',
trigger: 'blur',
},
],
passwordNew: [
{
required: true,
message: '请输入新密码',
trigger: 'blur',
},
],
});
//
function onSubmit() {
passwordChangeFormRef.value.validate(async valid => {
if (valid) {
try {
const params = { ...passwordChangeForm };
const resData = await changePassword(params);
store.commit('user/setUser', resData);
ElMessage.success('修改成功');
setTimeout(() => {
//
router.push({ name: 'signin' });
}, 1000);
} catch (error) {
ElMessage.error(error);
}
}
});
}
</script>
<style scoped>
.wrap {
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
background: url('@/assets/u1.jpg') no-repeat center center;
background-size: cover;
}
.content {
width: 480px;
padding: 30px;
background: #fff;
}
.content :deep(.el-form-item) {
display: flex;
margin-bottom: 22px !important;
}
</style>

106
src/views/user/sign-in.vue

@ -0,0 +1,106 @@
<template>
<div class="wrap">
<div class="content border rounded-md">
<h1 class="text-2xl text-center font-bold mb-10 text-gray-700">智能大气腐蚀监测云平台</h1>
<el-form ref="signInFormRef" :model="signInForm" :rules="rules" label-width="60px" status-icon>
<el-form-item class="mb-3" label="账号" prop="username" style="margin-bottom: 22px !important">
<el-input v-model="signInForm.username" type="text"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password" style="margin-bottom: 22px !important">
<el-input v-model="signInForm.password" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button class="float-left" style="display: block; margin-bottom: 22px !important" type="primary" @click="onSubmit">
立即登录
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue';
import { signIn } from 'apis';
import { ElMessage } from 'element-plus';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
const store = useStore();
const router = useRouter();
const signInFormRef = ref(null);
const signInForm = reactive({
username: '',
password: '',
});
const rules = reactive({
username: [
{
required: true,
message: '请输入账号',
trigger: 'blur',
},
],
password: [
{
required: true,
message: '请输入密码',
trigger: 'blur',
},
],
});
//
function onSubmit() {
signInFormRef.value.validate(async valid => {
if (valid) {
try {
const params = {
client: 1,
data: {
identifier: signInForm.username,
credential: signInForm.password,
},
type: 3,
};
const resData = await signIn(params);
store.commit('user/setUser', resData);
ElMessage.success('登录成功, 欢迎回来');
setTimeout(() => {
//
router.push({ name: 'overview' });
}, 1000);
} catch (error) {
ElMessage.error(error);
}
}
});
}
</script>
<style scoped>
.wrap {
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
background: url('@/assets/u1.jpg') no-repeat center center;
background-size: cover;
}
.content {
width: 480px;
padding: 30px;
background: #fff;
}
.content :deep(.el-form-item) {
display: flex;
margin-bottom: 22px !important;
}
</style>
Loading…
Cancel
Save