@@ -77,8 +77,14 @@ class Users(CoreModel, AbstractUser):
|
|||||||
objects = CustomUserManager()
|
objects = CustomUserManager()
|
||||||
|
|
||||||
def set_password(self, raw_password):
|
def set_password(self, raw_password):
|
||||||
|
if raw_password:
|
||||||
super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest())
|
super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest())
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.name == "":
|
||||||
|
self.name = self.username
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = table_prefix + "system_users"
|
db_table = table_prefix + "system_users"
|
||||||
verbose_name = "用户表"
|
verbose_name = "用户表"
|
||||||
|
|||||||
@@ -98,10 +98,22 @@ export function formatTwoStageRoutes(arr: any) {
|
|||||||
|
|
||||||
const frameOutRoutes = staticRoutes.map(item => item.path)
|
const frameOutRoutes = staticRoutes.map(item => item.path)
|
||||||
|
|
||||||
|
const checkToken = ()=>{
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const _oauth2_token = urlParams.get('_oauth2_token');
|
||||||
|
if (_oauth2_token) {
|
||||||
|
Session.set('token', _oauth2_token);
|
||||||
|
const cleanUrl = window.location.href.split('?')[0];
|
||||||
|
window.history.replaceState({}, '', cleanUrl);
|
||||||
|
useUserInfo(pinia).setUserInfos();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
// 路由加载前
|
// 路由加载前
|
||||||
router.beforeEach(async (to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
// 检查浏览器本地版本与线上版本是否一致,判断是否需要刷新页面进行更新
|
// 检查浏览器本地版本与线上版本是否一致,判断是否需要刷新页面进行更新
|
||||||
await checkVersion()
|
await checkVersion()
|
||||||
|
checkToken()
|
||||||
NProgress.configure({showSpinner: false});
|
NProgress.configure({showSpinner: false});
|
||||||
if (to.meta.title) NProgress.start();
|
if (to.meta.title) NProgress.start();
|
||||||
const token = Session.get('token');
|
const token = Session.get('token');
|
||||||
|
|||||||
@@ -28,3 +28,10 @@ export function getUserInfo() {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getBackends() {
|
||||||
|
return request({
|
||||||
|
url: '/api/dvadmin3_social_oauth2/backend/get_login_backend/',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
139
web/src/views/system/login/component/oauth2.vue
Normal file
139
web/src/views/system/login/component/oauth2.vue
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<div class="other-fast-way" v-if="backends.length">
|
||||||
|
<div class="fast-title"><span>其他快速方式登录</span></div>
|
||||||
|
<ul class="fast-list">
|
||||||
|
<li v-for="(v, k) in backends" :key="v">
|
||||||
|
<a @click.once="handleOAuth2LoginClick(v)" style="width: 50px;color: #18bc9c">
|
||||||
|
<img :src="v.icon" :alt="v.app_name" />
|
||||||
|
<p>{{ v.app_name }}</p>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
|
||||||
|
import * as loginApi from '../api';
|
||||||
|
import { OAuth2Backend } from '/@/views/system/login/types';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'loginOAuth2',
|
||||||
|
setup() {
|
||||||
|
const handleOAuth2LoginClick = (backend: OAuth2Backend) => {
|
||||||
|
history.replaceState(null, '', location.pathname + location.search);
|
||||||
|
window.location.href = backend.authentication_url + '?next=' + window.location.href;
|
||||||
|
};
|
||||||
|
const state = reactive({
|
||||||
|
handleOAuth2LoginClick: handleOAuth2LoginClick,
|
||||||
|
backends: [],
|
||||||
|
});
|
||||||
|
const getBackends = async () => {
|
||||||
|
loginApi.getBackends().then((ret: any) => {
|
||||||
|
state.backends = ret.data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// const handleTreeClick = (record: MenuTreeItemType) => {
|
||||||
|
// menuButtonRef.value?.handleRefreshTable(record);
|
||||||
|
// menuFieldRef.value?.handleRefreshTable(record)
|
||||||
|
// };
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getBackends();
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.login-content-form {
|
||||||
|
margin-top: 20px;
|
||||||
|
@for $i from 1 through 4 {
|
||||||
|
.login-animation#{$i} {
|
||||||
|
opacity: 0;
|
||||||
|
animation-name: error-num;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-delay: calc($i/10) + s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-content-code {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-content-submit {
|
||||||
|
width: 100%;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
font-weight: 300;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-msg {
|
||||||
|
color: var(--el-text-color-placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.other-fast-way {
|
||||||
|
//height: 240px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
z-index: 1;
|
||||||
|
//display: flex;
|
||||||
|
//align-items: center;
|
||||||
|
//justify-content: center;
|
||||||
|
.fast-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: #ddd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fast-list {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
li {
|
||||||
|
margin-left: 20px;
|
||||||
|
opacity: 0;
|
||||||
|
animation-name: error-num;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-delay: 0.1s;
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
img {
|
||||||
|
width: 35px;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 100%;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -34,6 +34,8 @@
|
|||||||
</el-tab-pane> -->
|
</el-tab-pane> -->
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
<OAuth2 />
|
||||||
|
|
||||||
<!-- <Scan v-if="state.isScan" />-->
|
<!-- <Scan v-if="state.isScan" />-->
|
||||||
<!-- <div class="login-content-main-sacn" @click="state.isScan = !state.isScan">-->
|
<!-- <div class="login-content-main-sacn" @click="state.isScan = !state.isScan">-->
|
||||||
<!-- <i class="iconfont" :class="state.isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i>-->
|
<!-- <i class="iconfont" :class="state.isScan ? 'icon-diannao1' : 'icon-barcode-qr'"></i>-->
|
||||||
@@ -81,6 +83,8 @@ const Account = defineAsyncComponent(() => import('/@/views/system/login/compone
|
|||||||
const Mobile = defineAsyncComponent(() => import('/@/views/system/login/component/mobile.vue'));
|
const Mobile = defineAsyncComponent(() => import('/@/views/system/login/component/mobile.vue'));
|
||||||
const Scan = defineAsyncComponent(() => import('/@/views/system/login/component/scan.vue'));
|
const Scan = defineAsyncComponent(() => import('/@/views/system/login/component/scan.vue'));
|
||||||
const ChangePwd = defineAsyncComponent(() => import('/@/views/system/login/component/changePwd.vue'));
|
const ChangePwd = defineAsyncComponent(() => import('/@/views/system/login/component/changePwd.vue'));
|
||||||
|
const OAuth2 = defineAsyncComponent(() => import('/@/views/system/login/component/oauth2.vue'));
|
||||||
|
|
||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
import {useUserInfo} from "/@/stores/userInfo";
|
import {useUserInfo} from "/@/stores/userInfo";
|
||||||
const { userInfos } = storeToRefs(useUserInfo());
|
const { userInfos } = storeToRefs(useUserInfo());
|
||||||
|
|||||||
8
web/src/views/system/login/types.ts
Normal file
8
web/src/views/system/login/types.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
export interface OAuth2Backend {
|
||||||
|
app_name: string;
|
||||||
|
backend_name: string;
|
||||||
|
icon: string;
|
||||||
|
authentication_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user