提交 0f42b6ca authored 作者: longfei's avatar longfei

登录注册规则校验、mock接口联调登录登出

上级 4bffbcf8
NODE_ENV = 'development'
VUE_APP_CURRENTMODE = 'dev'
VUE_APP_BASEURL = '本地开发api地址'
\ No newline at end of file
VUE_APP_BASE_API = 'http://127.0.0.1:4523/m1/1100718-0-default/'
\ No newline at end of file
......@@ -8,8 +8,11 @@
"name": "exhibition_page",
"version": "0.1.0",
"dependencies": {
"axios": "^0.27.2",
"core-js": "^3.8.3",
"element-ui": "^2.15.9",
"js-cookie": "^3.0.1",
"mockjs": "^1.1.0",
"qrcodejs2": "^0.0.2",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
......@@ -3300,6 +3303,11 @@
"babel-runtime": "6.x"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
......@@ -3332,6 +3340,15 @@
"postcss": "^8.1.0"
}
},
"node_modules/axios": {
"version": "0.27.2",
"resolved": "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"dependencies": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"node_modules/babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
......@@ -3953,11 +3970,21 @@
"integrity": "sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g==",
"dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true,
"engines": {
"node": ">= 12"
}
......@@ -4645,6 +4672,14 @@
"node": ">= 0.4"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
......@@ -6086,7 +6121,6 @@
"version": "1.15.1",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"dev": true,
"engines": {
"node": ">=4.0"
},
......@@ -6096,6 +6130,19 @@
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
......@@ -7069,6 +7116,14 @@
"@sideway/pinpoint": "^2.0.0"
}
},
"node_modules/js-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==",
"engines": {
"node": ">=12"
}
},
"node_modules/js-message": {
"version": "1.0.7",
"resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz",
......@@ -7650,7 +7705,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
......@@ -7659,7 +7713,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
......@@ -7784,6 +7837,17 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/mockjs": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz",
"integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==",
"dependencies": {
"commander": "*"
},
"bin": {
"random": "bin/random"
}
},
"node_modules/module-alias": {
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.2.tgz",
......@@ -14001,6 +14065,11 @@
"babel-runtime": "6.x"
}
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
......@@ -14021,6 +14090,15 @@
"postcss-value-parser": "^4.2.0"
}
},
"axios": {
"version": "0.27.2",
"resolved": "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"requires": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"babel-helper-vue-jsx-merge-props": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
......@@ -14540,11 +14618,18 @@
"integrity": "sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g==",
"dev": true
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
},
"commondir": {
"version": "1.0.1",
......@@ -15077,6 +15162,11 @@
"object-keys": "^1.1.1"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
......@@ -16243,8 +16333,17 @@
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"dev": true
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"forwarded": {
"version": "0.2.0",
......@@ -17017,6 +17116,11 @@
"@sideway/pinpoint": "^2.0.0"
}
},
"js-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw=="
},
"js-message": {
"version": "1.0.7",
"resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz",
......@@ -17484,14 +17588,12 @@
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"requires": {
"mime-db": "1.52.0"
}
......@@ -17591,6 +17693,14 @@
"minimist": "^1.2.6"
}
},
"mockjs": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz",
"integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==",
"requires": {
"commander": "*"
}
},
"module-alias": {
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.2.tgz",
......
......@@ -10,8 +10,11 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.27.2",
"core-js": "^3.8.3",
"element-ui": "^2.15.9",
"js-cookie": "^3.0.1",
"mockjs": "^1.1.0",
"qrcodejs2": "^0.0.2",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
......
import request from '@/utils/request'
export function login(data) {
return request({
url: '/user/login',
method: 'post',
data
})
}
export function updatePassword(data) {
return request({
url: '/auth/user/modifyPass',
method: 'put',
data
})
}
export function getInfo(token) {
return request({
url: '/user/getUserInfo',
method: 'get',
params: {
token
}
})
}
export function logout() {
return request({
url: '/qljc-web-vue/user/logout',
method: 'post'
})
}
// 手机短信验证
export function sendSmsCode(params) {
return request({
url: '/auth/api/smsCaptcha',
method: 'post',
params: params
})
}
/** *
* 获取eventType常量
*/
export function getEventTypePage() {
return request({
url: '/eventType/page?size=20',
method: 'get'
})
}
/** *
* 获取用户姓名
*/
export function getUserNameById(params) {
return request({
url: '/auth/user/userInfo',
method: 'get',
params
})
}
// /** *
// * 上传头像
// */
// export function uploadFileByFile(data) {
// return request({
// url: '/common/oss/uploadFileByFile',
// method: 'post',
// data,
// headers: {
// 'Content-Type': 'multipart/form-data'
// }
// })
// }
// /** *
// * 更新头像
// */
// export function updateHeadPic(params) {
// return request({
// url: '/auth/user/updateHeadPic',
// method: 'get',
// params
// })
// }
<template>
<div class="nav">
<div class="title">贵州省精品展览展示平台</div>
<div class="tabs" v-for="(item, index) in pages" :key="index">
<router-link :to="item.path">{{ item.name }}</router-link>
</div>
<div class="operation">
<span class="operation-item">登录</span>|
<router-link to="/personal" class="operation-item">个人中心</router-link>|
<span class="operation-item">退出</span>
</div>
<div class="title">贵州省精品展览展示平台</div>
<div class="tabs" v-for="(item, index) in pages" :key="index">
<router-link :to="item.path">{{ item.name }}</router-link>
</div>
<div class="operation">
<span v-if="isLogged">欢迎你,{{ userInfo.userName }}</span>
<router-link v-if="!isLogged" to="/login" class="operation-item"
>登陆</router-link
>|
<router-link to="/personal" class="operation-item">个人中心</router-link>|
<span class="logout">
<el-popover
placement="bottom"
width="200"
trigger="click"
v-model="logoutDialogVisible"
>
<p>确定退出吗?</p>
<div style="text-align: right; margin: 0">
<el-button
size="mini"
type="text"
@click="logoutDialogVisible = false"
>取消</el-button
>
<el-button type="primary" size="mini" @click="handleLogOut"
>确定</el-button
>
</div>
<span class="operation-item" slot="reference">退出</span>
</el-popover>
</span>
</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "NavBar",
computed: {
...mapGetters(["token", "userInfo"]),
isLogged() {
return this.userInfo && this.userInfo.userName;
},
},
data() {
return {
pages: [
......@@ -39,34 +70,42 @@ export default {
path: "/culturalRelic",
},
],
userName: "",
logoutDialogVisible: false,
};
},
methods: {
async handleLogOut() {
await this.$store.dispatch("user/logout");
this.logoutDialogVisible = false;
this.$router.push(`/login?redirect=${this.$route.fullPath}`);
},
},
};
</script>
<style lang="scss" scoped>
a{
a {
color: #000;
text-decoration: none;
}
.nav{
.nav {
display: flex;
height: 120px;
align-items: center;
justify-content: space-between;
// padding: 0 16%;
margin: auto;
width: 1200px;
.title{
.title {
font-size: 30px;
font-weight: bold;
}
.tabs{
.tabs {
display: flex;
margin-right: 5px;
}
.operation{
.operation-item{
.operation {
.operation-item {
margin-right: 8px;
cursor: pointer;
color: #000;
......
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import store from './store/index'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
......
......@@ -53,6 +53,19 @@ const routes = [
name: 'personal',
component: () => import('@/views/personal')
},
// 登录
{
path: '/login',
name: 'login',
component: () => import('@/views/login')
},
// 注册页
{
path: '/register',
name: 'register',
component: () => import('@/views/register')
},
]
const router = new VueRouter({
......
const getters = {
// 用户
token: state => state.user.token,
avatar: state => state.user.userInfo.avatar,
name: state => state.user.userInfo.name,
userInfo: state => state.user.userInfo,
}
export default getters
\ No newline at end of file
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
const store = new Vuex.Store({
modules: {
}
user,
},
getters
})
export default store
import {
login,
// getInfo,
// getAsyncRouter
} from '@/api/user'
import {
getToken,
setToken,
removeToken,
getUserInfo,
setUserInfo,
removeUserInfo,
} from '@/utils/auth'
const getDefaultState = () => {
return {
token: getToken(),
userInfo: getUserInfo(),
}
}
const state = getDefaultState()
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
SET_TOKEN: (state, token) => {
state.token = token
console.log('登录后存在vuex中token',token);
},
SET_INFO: (state, userInfo) => {
state.userInfo = userInfo
},
}
const actions = {
// user login
login({
commit
}, userInfo) {
return new Promise((resolve, reject) => {
login(userInfo).then(response => {
if (response.code != 0) {
userInfo.fail(response)
} else {
const {
data,
token
} = response
commit('SET_TOKEN', token)
commit('SET_INFO', data)
setToken(token)
setUserInfo(data)
resolve()
}
}).catch(error => {
reject(error)
})
})
},
// get user info
getInfo({
commit,
state
}) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const {
data
} = response
if (!data) {
reject('Verification failed, please Login again.')
}
commit('SET_INFO', data)
setUserInfo(data)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
// user logout
logout({
commit,
state
}) {
return new Promise((resolve, reject) => {
// logout(state.token).then(() => {
removeToken() // must remove token first
removeUserInfo()
commit('RESET_STATE')
resolve()
})
},
// remove token
resetToken({
commit
}) {
return new Promise(resolve => {
removeToken() // must remove token first
removeUserInfo()
commit('RESET_STATE')
resolve()
})
},
}
export default {
namespaced: true,
state,
mutations,
actions
}
import Cookies from 'js-cookie'
const TokenKey = 'bwgzl_token'
const UserInfoKey = 'bwgzl_user_info'
export function getToken() {
console.log('刷新后getToken',Cookies.get(TokenKey));
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token, { sameSite: 'None', secure: true })
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
export function getUserInfo() {
console.log('刷新后getUserInfo',JSON.parse(localStorage.getItem(UserInfoKey)));
return JSON.parse(localStorage.getItem(UserInfoKey))
}
export function setUserInfo(userInfo) {
return localStorage.setItem(UserInfoKey, JSON.stringify(userInfo))
}
export function removeUserInfo() {
return localStorage.removeItem(UserInfoKey)
}
/**** request.js ****/
// 导入axios
import axios from 'axios'
// 使用element-ui Message做消息提醒
import { Message} from 'element-ui';
import {
Message
} from 'element-ui';
import {
getToken
} from '@/utils/auth'
//1. 创建新的axios实例,
const service = axios.create({
// 公共接口--这里注意后面会讲
baseURL: process.env.BASE_API,
// baseURL: process.env.BASE_API,
baseURL: '/api',
// 超时时间 单位是ms,这里设置了3s的超时时间
timeout: 3 * 1000
})
// 2.请求拦截器
service.interceptors.request.use(config => {
//发请求前做的一些处理,数据转化,配置请求头,设置token,设置loading等,根据需求去添加
config.data = JSON.stringify(config.data); //数据转化,也可以使用qs转换
config.headers = {
'Content-Type':'application/x-www-form-urlencoded' //配置请求头
}
//注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie
// const token = getCookie('名称');//这里取token之前,你肯定需要先拿到token,存一下
// if(token){
// config.params = {'token':token} //如果要求携带在参数中
// config.headers.token= token; //如果要求携带在请求头中
// }
config.data = JSON.stringify(config.data); //数据转化,也可以使用qs转换
config.headers = {
'Content-Type': 'application/x-www-form-urlencoded' //配置请求头
}
const token = getToken();
if (token) {
config.params = {
'token': token
} //如果要求携带在参数中
config.headers.token = token; //如果要求携带在请求头中
}
return config
}, error => {
Promise.reject(error)
......@@ -30,33 +35,32 @@ service.interceptors.request.use(config => {
// 3.响应拦截器
service.interceptors.response.use(
(response) => {
const res = response.data
if (response.config.responseType !== 'blob') {
if (res.code !== 0) {
Message({
message: res.msg || 'Error',
type: 'error',
duration: 3 * 1000,
})
return Promise.reject(new Error(res.msg || 'Error'))
} else {
return res
}
}
(response) => {
const res = response.data
if (response.config.responseType !== 'blob') {
if (res.code !== 0) {
Message({
message: res.msg || 'Error',
type: 'error',
duration: 3 * 1000,
})
return Promise.reject(new Error(res.msg || 'Error'))
} else {
return res
},
(error) => {
let res = error.response
if (error.response) {
if (res.status == 401) {
Vue.prototype.parentFns.portal_logout()
}
}
return Promise.reject(error)
}
}
return res
},
(error) => {
let res = error.response
if (error.response) {
if (res.status == 401) {
Vue.prototype.parentFns.portal_logout()
}
}
return Promise.reject(error)
}
)
//4.导入文件
export default service
<!-- -->
<template>
<div class="login">
<el-tabs v-model="activeName" class="login-box">
<el-tab-pane label="账号登录" name="account">
<el-form
:model="accountForm"
:label-position="labelPosition"
:rules="accountRules"
ref="accountForm"
>
<el-form-item
label="账号"
:label-width="formLabelWidth"
prop="account"
>
<el-input
v-model="accountForm.account"
autocomplete="off"
clearable
></el-input>
</el-form-item>
<el-form-item label="密码" :label-width="formLabelWidth" prop="pwd">
<el-input
v-model="accountForm.pwd"
autocomplete="off"
type="password"
clearable
show-password
></el-input>
<div class="register">
<router-link to="/register" @click.native="closeDialog">
没有账号?去注册
</router-link>
</div>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="手机号登录" name="phoneNumber">
<el-form
:model="phoneForm"
label-position="labelPosition"
:rules="phoneRules"
ref="phoneForm"
>
<el-form-item
label="手机号"
:label-width="formLabelWidth"
prop="phoneNumber"
>
<el-input
v-model="phoneForm.phoneNumber"
autocomplete="off"
clearable
></el-input>
</el-form-item>
<el-form-item
label="验证码"
:label-width="formLabelWidth"
prop="captcha"
>
<el-input
v-model="phoneForm.captcha"
autocomplete="off"
style="width: 46%; margin-right: 8px"
clearable
></el-input>
<el-button :disabled="isDisabled" @click.native="handleSend">{{
sendButtonText
}}</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<el-button @click="handleSubmitLogin">登 陆</el-button>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
data() {
return {
accountForm: {
account: "",
pwd: "",
},
phoneForm: {
phoneNumber: "",
captcha: "",
},
accountRules: {
account: [{ message: "请输入账号", required: true }],
pwd: [{ message: "请输入密码", required: true }],
},
phoneRules: {
phoneNumber: [
{ required: true, message: "请输入手机号", trigger: "blur" },
{
pattern: /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/,
message: "请输入合法手机号/电话号",
trigger: "blur",
},
],
captcha: [{ message: "请输入验证码", required: true }],
},
formLabelWidth: "70px",
labelPosition: "right",
activeName: "account",
isDisabled: true,
sendButtonText: "发送验证码",
second: 60,
};
},
watch: {
"phoneForm.phoneNumber": {
handler: function (value) {
this.$refs["phoneForm"].validateField("phoneNumber", (errorMessage) => {
let valid = errorMessage == "";
if (valid) {
this.isDisabled = false;
} else {
this.isDisabled = true;
}
});
},
deep: true,
},
},
mounted() {},
methods: {
handleClickLogin() {
this.loginDialogVisible = true;
},
// 登录提交
handleSubmitLogin() {
if (this.activeName == "account") {
this.$refs["accountForm"].validate((isTrue) => {
if (isTrue) {
if (this.accountForm.account) {
var params = {
userName: this.accountForm.account,
pwd: this.accountForm.pwd,
};
this.$store
.dispatch("user/login", params)
.then(() => {
this.$message.success("登录成功!");
var redirect = this.$route.query.redirect;
this.$router.push({
path: redirect || "/",
});
})
.catch((err) => {
this.$message.error(err);
console.log(err);
});
}
}
});
} else {
this.$refs["phoneForm"].validate((isTrue) => {
if (isTrue) {
// TODO:调用登录接口
this.$message.info("需调用登录接口");
this.closeDialog();
}
});
}
},
// 点击发送验证码
handleSend() {
this.isDisabled = true;
this.second = 60;
var timer = setInterval(() => {
if (this.second < 1) {
this.isDisabled = false;
clearInterval(timer);
timer = null;
this.sendButtonText = "发送验证码";
} else {
this.second--;
this.sendButtonText = `${this.second}秒后重新发送`;
}
}, 1 * 1000);
},
},
};
</script>
<style lang="scss" scoped>
.login {
width: 500px;
margin: 50px auto;
.login-box {
width: 500px;
margin: auto;
}
}
.register {
display: flex;
justify-content: flex-end;
}
.dialog-footer {
display: flex;
justify-content: center;
}
</style>
......@@ -9,8 +9,8 @@
<el-button @click="editPassword">修改密码</el-button>
</el-form-item>
</el-form>
<el-dialog title="修改个人信息" :visible.sync="dialogFormVisible" >
<el-form :model="infoData" v-if="isEditBasicInfo" :label-position="'right'">
<el-dialog title="修改个人信息" :visible.sync="dialogFormVisible" width="400px">
<el-form :model="infoData" v-if="isEditBasicInfo" label-position="right" label-width="80px">
<el-form-item label="昵称" >
<el-input v-model="infoData.name" autocomplete="off"></el-input>
</el-form-item>
......@@ -21,25 +21,22 @@
<el-input v-model="infoData.phone" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<el-form :model="pwdData" v-else>
<el-form-item label="旧密码">
<el-form :model="pwdData" v-else label-position="right" label-width="80px">
<el-form-item label="旧密码" >
<el-input
v-model="pwdData.oldPwd"
autocomplete="off"
type="password"
></el-input>
</el-form-item>
<el-form-item label="新密码" >
<el-input
v-model="pwdData.newPwd"
autocomplete="off"
type="password"
></el-input>
</el-form-item>
<el-form-item label="重复密码" >
<el-input
v-model="pwdData.repeatPwd"
autocomplete="off"
type="password"
></el-input>
</el-form-item>
......@@ -73,6 +70,7 @@ export default {
isEditBasicInfo: true,
};
},
methods: {
editInfo() {
this.dialogFormVisible = true;
......@@ -84,4 +82,9 @@ export default {
},
},
};
</script>
\ No newline at end of file
</script>
<style lang="scss" scoped>
.el-input{
width: 80%;
}
</style>
\ No newline at end of file
<template>
<div class="register">
<el-form
:model="form"
status-icon
:rules="rules"
ref="registerForm"
label-width="100px"
class="register-form"
>
<el-form-item label="手机号" prop="phoneNumber">
<el-input v-model="form.phoneNumber" autocomplete="off"></el-input>
<!-- <el-button style="margin-left:16px">发送验证码</el-button> -->
</el-form-item>
<el-form-item label="验证码" prop="captcha">
<el-input
v-model="form.captcha"
autocomplete="off"
style="width: 46%; margin-right: 8px"
clearable
></el-input>
<el-button :disabled="isDisabled" @click.native="handleSend">{{
sendButtonText
}}</el-button>
</el-form-item>
<el-form-item label="账号" prop="account">
<el-input v-model="form.account" autocomplete="off"></el-input>
</el-form-item>
<!-- <el-form-item label="手机号" prop="pass">
<el-input v-model="ruleForm.account" autocomplete="off"></el-input>
<el-button>发送验证码</el-button>
</el-form-item> -->
<el-form-item label="密码" prop="pass">
<el-input
type="password"
v-model="form.pass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input
type="password"
v-model="form.checkPass"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('registerForm')"
>提交</el-button
>
<el-button @click="resetForm('registerForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
var validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
} else {
var pattern =
/^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\W_!@#$%^&*`~()-+=]{8,30}$/;
if (!pattern.test(value)) {
callback(
new Error(
"密码长度至少8位,至少含数字,大写字母,小写字母,特殊符其中三种"
)
);
}
if (this.form.checkPass !== "") {
this.$refs.registerForm.validateField("checkPass");
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== this.form.pass) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
return {
form: {
account: "",
pass: "",
checkPass: "",
captcha: "",
},
isDisabled: true,
sendButtonText: "发送验证码",
second: 60,
rules: {
account: [
{ message: "请输入账号", trigger: "blur", required: true },
{
pattern: /^[0-9a-zA-Z|_]{6,20}$/g,
message: "账号长度6-20个字符,只能包括字母、数字、下划线",
trigger: "blur",
},
],
phoneNumber: [
{ required: true, message: "请输入手机号", trigger: "blur" },
{
pattern: /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/,
message: "请输入合法手机号/电话号",
trigger: "blur",
},
],
captcha: [{ message: "请输入验证码", required: true }],
pass: [{ validator: validatePass, trigger: "blur", required: true }],
checkPass: [
{ validator: validatePass2, trigger: "blur", required: true },
],
},
};
},
watch: {
"form.phoneNumber": {
handler: function (value) {
this.$refs["registerForm"].validateField("phoneNumber", (errorMessage) => {
let valid = errorMessage == "";
if (valid) {
this.isDisabled = false;
} else {
this.isDisabled = true;
}
});
},
deep: true,
},
},
methods: {
// 点击发送验证码
handleSend() {
this.isDisabled = true;
this.second = 60;
var timer = setInterval(() => {
if (this.second < 1) {
this.isDisabled = false;
clearInterval(timer);
timer = null;
this.sendButtonText = "发送验证码";
} else {
this.second--;
this.sendButtonText = `${this.second}秒后重新发送`;
}
}, 1 * 1000);
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert("submit!");
} else {
console.log("error submit!!");
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<style lang="scss" scoped>
.register {
width: 1200px;
margin: 50px auto;
.register-form {
width: 500px;
margin: auto;
}
}
</style>
\ No newline at end of file
......@@ -13,7 +13,16 @@ module.exports = defineConfig({
host: 'localhost',
port: '8080',
open: true,
hot:true
hot: true,
proxy: {
'/api': {
target: 'http://127.0.0.1:4523/m1/1100718-0-default',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
},
publicPath: './',
chainWebpack: config => {
......@@ -37,5 +46,5 @@ module.exports = defineConfig({
}
return configuration
},
// TODO:接口代理
})
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论