feat:登录接口接入
This commit is contained in:
parent
40aeda6bfc
commit
d055a11921
|
|
@ -9,6 +9,8 @@
|
|||
"dependencies": {
|
||||
"axios": "^0.24.0",
|
||||
"element-plus": "^1.2.0-beta.3",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"screenfull": "^6.0.0",
|
||||
"vue": "^3.2.16",
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ import request from "@utils/request";
|
|||
export function login(data: object) {
|
||||
return request({
|
||||
url: '/youlai-auth/oauth/token',
|
||||
method:'post',
|
||||
params: data,
|
||||
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() {
|
||||
return request({
|
||||
url: '/captcha',
|
||||
url: '/captcha?t='+(new Date()).getTime().toString(),
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
|
@ -10,14 +10,7 @@
|
|||
|
||||
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
|
||||
<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">{{
|
||||
t("route." + item.meta.title)
|
||||
}}</span>
|
||||
|
|
@ -36,7 +29,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import path from 'path'
|
||||
import path from 'path-browserify'
|
||||
import { isExternal } from '@utils/validate'
|
||||
import AppLink from './Link.vue'
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import ScrollPane from './ScrollPane.vue'
|
||||
import path from 'path'
|
||||
import path from 'path-browserify'
|
||||
import {useStore} from "@store";
|
||||
import {
|
||||
defineComponent,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ import '@styles/index.scss'
|
|||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
|
||||
import 'virtual:svg-icons-register';
|
||||
|
||||
|
||||
import '@/permission'
|
||||
|
||||
const app=createApp(App)
|
||||
app
|
||||
.use(router)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import router from "@router";
|
||||
import NProgress from 'nprogress';
|
||||
import {Local} from "@utils/storage";
|
||||
import {useStore} from "@store";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {store} from "@store";
|
||||
|
||||
NProgress.configure({showSpinner: false})
|
||||
|
||||
|
|
@ -10,11 +9,9 @@ NProgress.configure({showSpinner: false})
|
|||
const whiteList = ['/login', '/auth-redirect']
|
||||
|
||||
router.beforeEach(async (to, form, next) => {
|
||||
|
||||
NProgress.start()
|
||||
const store = useStore()
|
||||
|
||||
const hasToken = Local.get(`token`)
|
||||
const hasToken =store.state.user.token
|
||||
if (hasToken) {
|
||||
// 如果登录成功,跳转到首页
|
||||
if (to.path === '/login') {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ const userModule: Module<UserState, RootStateTypes> = {
|
|||
const accessToken = token_type + " " + access_token
|
||||
Local.set("token", accessToken)
|
||||
commit('SET_TOKEN', accessToken)
|
||||
resolve(access_token)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import axios from "axios";
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
import {Local} from "@utils/storage";
|
||||
import {store} from "@store";
|
||||
|
||||
|
||||
// 创建 axios 实例
|
||||
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,
|
||||
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
||||
})
|
||||
|
|
@ -16,8 +17,10 @@ service.interceptors.request.use(
|
|||
if (!config?.headers) {
|
||||
throw new Error(`Expected 'config' and 'config.headers' not to be undefined`);
|
||||
}
|
||||
config.headers.Authorization = `${Local.get('token')}`;
|
||||
|
||||
if (store.state.user.token) {
|
||||
config.headers.Authorization = `${Local.get('token')}`;
|
||||
}
|
||||
return config
|
||||
}, (error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
|
@ -39,6 +42,7 @@ service.interceptors.response.use(
|
|||
}
|
||||
},
|
||||
(error) => {
|
||||
console.log('error', error)
|
||||
const {code, msg} = error.response.data
|
||||
if (code === 'A0230') { // token 过期
|
||||
Local.clear(); // 清除浏览器全部缓存
|
||||
|
|
|
|||
|
|
@ -40,11 +40,29 @@
|
|||
</span>
|
||||
</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">
|
||||
<span style="margin-right:20px;">username: admin</span>
|
||||
<span> password: any</span>
|
||||
<span style="margin-right:20px;">用户名: admin</span>
|
||||
<span> 密码: 123456</span>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
|
|
@ -53,6 +71,7 @@
|
|||
|
||||
<script>
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue';
|
||||
import {getCaptcha} from "@/api/login";
|
||||
|
||||
export default {
|
||||
name: 'Login',
|
||||
|
|
@ -70,7 +89,9 @@ export default {
|
|||
return {
|
||||
loginForm: {
|
||||
username: 'admin',
|
||||
password: '111111'
|
||||
password: '123456',
|
||||
code: undefined,
|
||||
uuid: undefined
|
||||
},
|
||||
loginRules: {
|
||||
username: [{ required: true, trigger: 'blur'}],
|
||||
|
|
@ -78,9 +99,14 @@ export default {
|
|||
},
|
||||
loading: false,
|
||||
passwordType: 'password',
|
||||
redirect: undefined
|
||||
redirect: undefined,
|
||||
base64Captcha: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 生成验证码
|
||||
this.getCaptcha()
|
||||
},
|
||||
watch: {
|
||||
$route: {
|
||||
handler: function(route) {
|
||||
|
|
@ -104,11 +130,6 @@ export default {
|
|||
this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
|
||||
// 暂跳转首页控制台,后续整合登录
|
||||
this.$router.push({ path: '/' })
|
||||
return false
|
||||
|
||||
this.$store.dispatch('user/login', this.loginForm).then(() => {
|
||||
this.$router.push({ path: this.redirect || '/' })
|
||||
this.loading = false
|
||||
|
|
@ -120,6 +141,14 @@ export default {
|
|||
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;
|
||||
user-select: none;
|
||||
}
|
||||
.validate-code {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
img {
|
||||
height: 52px;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
135
vite.config.ts
135
vite.config.ts
|
|
@ -1,82 +1,85 @@
|
|||
import {defineConfig, ConfigEnv, loadEnv} from 'vite'
|
||||
import {UserConfig, ConfigEnv, loadEnv} from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
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'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default ({mode}: ConfigEnv) => {
|
||||
// @see: https://gitee.com/holysheng/vite2-config-description/blob/master/vite.config.ts
|
||||
|
||||
export default ({command, mode}: ConfigEnv): UserConfig => {
|
||||
// 获取 .env 环境配置文件
|
||||
const env = loadEnv(mode, process.cwd())
|
||||
|
||||
return defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
viteSvgIcons({
|
||||
// 指定需要缓存的图标文件夹
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
|
||||
// 指定symbolId格式
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
})
|
||||
return (
|
||||
{
|
||||
plugins: [
|
||||
vue(),
|
||||
viteSvgIcons({
|
||||
// 指定需要缓存的图标文件夹
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
|
||||
// 指定symbolId格式
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
})
|
||||
|
||||
],
|
||||
// 本地反向代理解决跨域
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: Number(env.VITE_APP_PORT),
|
||||
open: true, // 运行自动打开浏览器
|
||||
proxy: {
|
||||
[env.VITE_APP_BASE_API]: {
|
||||
target: 'http://localhost:9999',
|
||||
changeOrigin: true,
|
||||
rewrite: path => path.replace(/^\/api/, '') //TODO
|
||||
],
|
||||
// 本地反向代理解决跨域
|
||||
server: {
|
||||
host: 'localhost',
|
||||
port: Number(env.VITE_APP_PORT),
|
||||
open: true, // 运行自动打开浏览器
|
||||
proxy: {
|
||||
[env.VITE_APP_BASE_API]: {
|
||||
target: 'http://localhost:9999',
|
||||
changeOrigin: true,
|
||||
rewrite: path => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')
|
||||
}
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
// Vite2设置别名路径方式一
|
||||
// alias:{
|
||||
// "/@":path.resolve("./src"), // 相对路径别名配置,@表示src
|
||||
// },
|
||||
// Vite2设置别名路径方式二
|
||||
alias: [
|
||||
{
|
||||
find: "@",
|
||||
replacement: path.resolve("./src")
|
||||
},
|
||||
{
|
||||
find: "@image",
|
||||
replacement: path.resolve("./src/assets/images")
|
||||
},
|
||||
{
|
||||
find: "@router",
|
||||
replacement: path.resolve("./src/router")
|
||||
},
|
||||
{
|
||||
find: "@store",
|
||||
replacement: path.resolve("./src/store")
|
||||
},
|
||||
{
|
||||
find: "@api",
|
||||
replacement: path.resolve("./src/api")
|
||||
},
|
||||
{
|
||||
find: "@utils",
|
||||
replacement: path.resolve("./src/utils")
|
||||
},
|
||||
{
|
||||
find: "@views",
|
||||
replacement: path.resolve("./src/views")
|
||||
},
|
||||
{
|
||||
find: "@styles",
|
||||
replacement: path.resolve("./src/styles")
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
// Vite2设置别名路径方式一
|
||||
// alias:{
|
||||
// "/@":path.resolve("./src"), // 相对路径别名配置,@表示src
|
||||
// },
|
||||
// Vite2设置别名路径方式二
|
||||
alias: [
|
||||
{
|
||||
find: "@",
|
||||
replacement: path.resolve("./src")
|
||||
},
|
||||
{
|
||||
find: "@image",
|
||||
replacement: path.resolve("./src/assets/images")
|
||||
},
|
||||
{
|
||||
find: "@router",
|
||||
replacement: path.resolve("./src/router")
|
||||
},
|
||||
{
|
||||
find: "@store",
|
||||
replacement: path.resolve("./src/store")
|
||||
},
|
||||
{
|
||||
find: "@api",
|
||||
replacement: path.resolve("./src/api")
|
||||
},
|
||||
{
|
||||
find: "@utils",
|
||||
replacement: path.resolve("./src/utils")
|
||||
},
|
||||
{
|
||||
find: "@views",
|
||||
replacement: path.resolve("./src/views")
|
||||
},
|
||||
{
|
||||
find: "@styles",
|
||||
replacement: path.resolve("./src/styles")
|
||||
},
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue