feat:登录接口接入
This commit is contained in:
@@ -9,6 +9,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"element-plus": "^1.2.0-beta.3",
|
"element-plus": "^1.2.0-beta.3",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
|
"path-browserify": "^1.0.1",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
"screenfull": "^6.0.0",
|
"screenfull": "^6.0.0",
|
||||||
"vue": "^3.2.16",
|
"vue": "^3.2.16",
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import request from "@utils/request";
|
|||||||
export function login(data: object) {
|
export function login(data: object) {
|
||||||
return request({
|
return request({
|
||||||
url: '/youlai-auth/oauth/token',
|
url: '/youlai-auth/oauth/token',
|
||||||
|
method:'post',
|
||||||
params: data,
|
params: data,
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Basic bWFsbC1hZG1pbi13ZWI6MTIzNDU2' // 客户端信息加密摘要认证,明文:mall-admin-web:123456
|
'Authorization': 'Basic bWFsbC1hZG1pbi13ZWI6MTIzNDU2' // 客户端信息Base64明文:mall-admin-web:123456
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,7 @@ export function logout() {
|
|||||||
*/
|
*/
|
||||||
export function getCaptcha() {
|
export function getCaptcha() {
|
||||||
return request({
|
return request({
|
||||||
url: '/captcha',
|
url: '/captcha?t='+(new Date()).getTime().toString(),
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -10,14 +10,7 @@
|
|||||||
|
|
||||||
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
|
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
|
||||||
<template #title>
|
<template #title>
|
||||||
<svg
|
|
||||||
v-if="item.meta && item.meta.icon"
|
|
||||||
class="icon"
|
|
||||||
aria-hidden="true"
|
|
||||||
font-size="16px"
|
|
||||||
>
|
|
||||||
<use :xlink:href="item.meta.icon" />
|
|
||||||
</svg>
|
|
||||||
<span v-if="item.meta && item.meta.title">{{
|
<span v-if="item.meta && item.meta.title">{{
|
||||||
t("route." + item.meta.title)
|
t("route." + item.meta.title)
|
||||||
}}</span>
|
}}</span>
|
||||||
@@ -36,7 +29,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import path from 'path'
|
import path from 'path-browserify'
|
||||||
import { isExternal } from '@utils/validate'
|
import { isExternal } from '@utils/validate'
|
||||||
import AppLink from './Link.vue'
|
import AppLink from './Link.vue'
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ScrollPane from './ScrollPane.vue'
|
import ScrollPane from './ScrollPane.vue'
|
||||||
import path from 'path'
|
import path from 'path-browserify'
|
||||||
import {useStore} from "@store";
|
import {useStore} from "@store";
|
||||||
import {
|
import {
|
||||||
defineComponent,
|
defineComponent,
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ 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'
|
||||||
|
|
||||||
|
|
||||||
import 'virtual:svg-icons-register';
|
import 'virtual:svg-icons-register';
|
||||||
|
|
||||||
|
|
||||||
|
import '@/permission'
|
||||||
|
|
||||||
const app=createApp(App)
|
const app=createApp(App)
|
||||||
app
|
app
|
||||||
.use(router)
|
.use(router)
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import router from "@router";
|
import router from "@router";
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import {Local} from "@utils/storage";
|
|
||||||
import {useStore} from "@store";
|
|
||||||
import {ElMessage} from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
|
import {store} from "@store";
|
||||||
|
|
||||||
NProgress.configure({showSpinner: false})
|
NProgress.configure({showSpinner: false})
|
||||||
|
|
||||||
@@ -10,11 +9,9 @@ NProgress.configure({showSpinner: false})
|
|||||||
const whiteList = ['/login', '/auth-redirect']
|
const whiteList = ['/login', '/auth-redirect']
|
||||||
|
|
||||||
router.beforeEach(async (to, form, next) => {
|
router.beforeEach(async (to, form, next) => {
|
||||||
|
|
||||||
NProgress.start()
|
NProgress.start()
|
||||||
const store = useStore()
|
|
||||||
|
|
||||||
const hasToken = Local.get(`token`)
|
const hasToken =store.state.user.token
|
||||||
if (hasToken) {
|
if (hasToken) {
|
||||||
// 如果登录成功,跳转到首页
|
// 如果登录成功,跳转到首页
|
||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ const userModule: Module<UserState, RootStateTypes> = {
|
|||||||
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)
|
||||||
|
resolve(access_token)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import {ElMessage, ElMessageBox} from "element-plus";
|
import {ElMessage, ElMessageBox} from "element-plus";
|
||||||
import {Local} from "@utils/storage";
|
import {Local} from "@utils/storage";
|
||||||
|
import {store} from "@store";
|
||||||
|
|
||||||
|
|
||||||
// 创建 axios 实例
|
// 创建 axios 实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: import.meta.env.VITE_BASE_API as any,
|
baseURL: import.meta.env.VITE_APP_BASE_API as any,
|
||||||
timeout: 50000,
|
timeout: 50000,
|
||||||
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
||||||
})
|
})
|
||||||
@@ -16,8 +17,10 @@ service.interceptors.request.use(
|
|||||||
if (!config?.headers) {
|
if (!config?.headers) {
|
||||||
throw new Error(`Expected 'config' and 'config.headers' not to be undefined`);
|
throw new Error(`Expected 'config' and 'config.headers' not to be undefined`);
|
||||||
}
|
}
|
||||||
|
if (store.state.user.token) {
|
||||||
config.headers.Authorization = `${Local.get('token')}`;
|
config.headers.Authorization = `${Local.get('token')}`;
|
||||||
|
}
|
||||||
|
return config
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
@@ -39,6 +42,7 @@ service.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
console.log('error', error)
|
||||||
const {code, msg} = error.response.data
|
const {code, msg} = error.response.data
|
||||||
if (code === 'A0230') { // token 过期
|
if (code === 'A0230') { // token 过期
|
||||||
Local.clear(); // 清除浏览器全部缓存
|
Local.clear(); // 清除浏览器全部缓存
|
||||||
|
|||||||
@@ -40,11 +40,29 @@
|
|||||||
</span>
|
</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>
|
|
||||||
|
<el-form-item prop="validateCode">
|
||||||
|
<span class="svg-container">
|
||||||
|
<svg-icon icon-class="validCode"/>
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
v-model="loginForm.code"
|
||||||
|
auto-complete="off"
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
style="width: 65%"
|
||||||
|
@keyup.enter.native="handleLogin"
|
||||||
|
/>
|
||||||
|
<div class="validate-code">
|
||||||
|
<img :src="base64Captcha" @click="getCaptcha" height="38px"/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
|
||||||
|
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button>
|
||||||
|
|
||||||
<div class="tips">
|
<div class="tips">
|
||||||
<span style="margin-right:20px;">username: admin</span>
|
<span style="margin-right:20px;">用户名: admin</span>
|
||||||
<span> password: any</span>
|
<span> 密码: 123456</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -53,6 +71,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
import SvgIcon from '@/components/SvgIcon/index.vue';
|
||||||
|
import {getCaptcha} from "@/api/login";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Login',
|
name: 'Login',
|
||||||
@@ -70,7 +89,9 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loginForm: {
|
loginForm: {
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
password: '111111'
|
password: '123456',
|
||||||
|
code: undefined,
|
||||||
|
uuid: undefined
|
||||||
},
|
},
|
||||||
loginRules: {
|
loginRules: {
|
||||||
username: [{ required: true, trigger: 'blur'}],
|
username: [{ required: true, trigger: 'blur'}],
|
||||||
@@ -78,9 +99,14 @@ export default {
|
|||||||
},
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
passwordType: 'password',
|
passwordType: 'password',
|
||||||
redirect: undefined
|
redirect: undefined,
|
||||||
|
base64Captcha: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
// 生成验证码
|
||||||
|
this.getCaptcha()
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
$route: {
|
$route: {
|
||||||
handler: function(route) {
|
handler: function(route) {
|
||||||
@@ -104,11 +130,6 @@ export default {
|
|||||||
this.$refs.loginForm.validate(valid => {
|
this.$refs.loginForm.validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
// 暂跳转首页控制台,后续整合登录
|
|
||||||
this.$router.push({ path: '/' })
|
|
||||||
return false
|
|
||||||
|
|
||||||
this.$store.dispatch('user/login', this.loginForm).then(() => {
|
this.$store.dispatch('user/login', this.loginForm).then(() => {
|
||||||
this.$router.push({ path: this.redirect || '/' })
|
this.$router.push({ path: this.redirect || '/' })
|
||||||
this.loading = false
|
this.loading = false
|
||||||
@@ -120,6 +141,14 @@ export default {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
// 获取验证码
|
||||||
|
getCaptcha(){
|
||||||
|
getCaptcha().then(response => {
|
||||||
|
const {img, uuid} = response.data
|
||||||
|
this.base64Captcha = "data:image/gif;base64," + img
|
||||||
|
this.loginForm.uuid = uuid;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,5 +262,17 @@ $light_gray:#eee;
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
.validate-code {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 52px;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import {defineConfig, ConfigEnv, loadEnv} from 'vite'
|
import {UserConfig, ConfigEnv, loadEnv} from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import viteSvgIcons from 'vite-plugin-svg-icons';
|
import viteSvgIcons from 'vite-plugin-svg-icons';
|
||||||
// 在 ts 模块中加载 node 核心模块需要安装 node 的类型补充模块: npm i -D @types/node
|
// 如果编辑器提示 path 模块找不到,则可以安装一下 @types/node -> npm i @types/node -D
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// @see: https://gitee.com/holysheng/vite2-config-description/blob/master/vite.config.ts
|
||||||
export default ({mode}: ConfigEnv) => {
|
|
||||||
|
|
||||||
|
export default ({command, mode}: ConfigEnv): UserConfig => {
|
||||||
|
// 获取 .env 环境配置文件
|
||||||
const env = loadEnv(mode, process.cwd())
|
const env = loadEnv(mode, process.cwd())
|
||||||
|
|
||||||
return defineConfig({
|
return (
|
||||||
|
{
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
viteSvgIcons({
|
viteSvgIcons({
|
||||||
@@ -22,14 +24,14 @@ export default ({mode}: ConfigEnv) => {
|
|||||||
],
|
],
|
||||||
// 本地反向代理解决跨域
|
// 本地反向代理解决跨域
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0',
|
host: 'localhost',
|
||||||
port: Number(env.VITE_APP_PORT),
|
port: Number(env.VITE_APP_PORT),
|
||||||
open: true, // 运行自动打开浏览器
|
open: true, // 运行自动打开浏览器
|
||||||
proxy: {
|
proxy: {
|
||||||
[env.VITE_APP_BASE_API]: {
|
[env.VITE_APP_BASE_API]: {
|
||||||
target: 'http://localhost:9999',
|
target: 'http://localhost:9999',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/api/, '') //TODO
|
rewrite: path => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -74,9 +76,10 @@ export default ({mode}: ConfigEnv) => {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user