合并 ts

This commit is contained in:
LiuHao 2023-06-20 19:15:58 +08:00
commit 319b37fe98
15 changed files with 285 additions and 21 deletions

View File

@ -13,7 +13,7 @@ VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
# xxl-job 控制台地址
VITE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin'
# powerjob 控制台地址
VITE_APP_POWERJOB_ADMIN = 'http://localhost:7700/'
VITE_APP_PORT = 80

View File

@ -10,8 +10,8 @@ VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITRO_ADMIN = '/admin/applications'
# 监控地址
VITE_APP_XXL_JOB_ADMIN = '/xxl-job-admin'
# powerjob 控制台地址
VITE_APP_POWERJOB_ADMIN = '/powerjob'
# 生产环境
VITE_APP_BASE_API = '/prod-api'

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
.DS_Store
.history
node_modules/
dist/
npm-debug.log*

View File

@ -60,6 +60,21 @@ export function getCodeImg(): AxiosPromise<VerifyCodeResult> {
timeout: 20000
});
}
/**
*
* @param source
* */
export function socialLogin(source: string, code: any, state: any): AxiosPromise<any> {
const data = {
code,
state
};
return request({
url: '/auth/social-login/' + source,
method: 'get',
params: data
});
}
// 获取用户详细信息
export function getInfo(): AxiosPromise<UserInfo> {

View File

@ -0,0 +1,24 @@
import request from '@/utils/request';
// 绑定账号
export function authBinding(source: string) {
return request({
url: '/auth/binding/' + source,
method: 'get'
});
}
// 解绑账号
export function authUnlock(authId: string) {
return request({
url: '/auth/unlock/' + authId,
method: 'delete'
});
}
//获取授权列表
export function getAuthList() {
return request({
url: '/system/social/list',
method: 'get'
});
}

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686919908144" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2521" width="200" height="200" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 992C246.895625 992 32 777.104375 32 512S246.895625 32 512 32s480 214.895625 480 480-214.895625 480-480 480z m242.9521875-533.3278125h-272.56875a23.7121875 23.7121875 0 0 0-23.71125 23.7121875l-0.024375 59.255625c0 13.08 10.6078125 23.7121875 23.6878125 23.7121875h165.96c13.104375 0 23.7121875 10.6078125 23.7121875 23.6878125v11.855625a71.1121875 71.1121875 0 0 1-71.1121875 71.1121875h-225.215625a23.7121875 23.7121875 0 0 1-23.6878125-23.7121875V423.1278125a71.1121875 71.1121875 0 0 1 71.0878125-71.1121875h331.824375a23.7121875 23.7121875 0 0 0 23.6878125-23.71125l0.0721875-59.2565625a23.7121875 23.7121875 0 0 0-23.68875-23.7121875H423.08a177.76875 177.76875 0 0 0-177.76875 177.7921875V754.953125c0 13.1034375 10.60875 23.7121875 23.713125 23.7121875h349.63125a159.984375 159.984375 0 0 0 159.984375-159.984375V482.36a23.7121875 23.7121875 0 0 0-23.7121875-23.6878125z" fill="#515151" p-id="2522"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,36 @@
<template>
<div v-loading="loading" class="social-login"></div>
</template>
<script setup lang="ts">
import {socialLogin} from '@/api/login';
import {setToken} from '@/utils/auth';
const route = useRoute();
const router = useRouter();
/**
* 接收Route传递的参数
* @param {Object} route.query.
*/
const code = route.query.code;
const state = route.query.state;
const source = route.query.source as string;
const loading = ref(true);
await socialLogin(source, code, state)
.then(async (res) => {
if (res.code !== 200) {
ElMessage.error(res.msg);
router.go(-2);
return;
}
loading.value = false;
setToken(res.msg);
ElMessage.success('登录成功');
router.go(-2);
})
.catch(() => {
loading.value = false;
});
</script>

View File

@ -10,7 +10,7 @@ import useSettingsStore from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';
NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register'];
const whiteList = ['/login', '/register', '/social-login'];
router.beforeEach(async (to, from, next) => {
NProgress.start();

View File

@ -37,6 +37,11 @@ export const constantRoutes: RouteOption[] = [
}
]
},
{
path: '/social-login',
hidden: true,
component: () => import('@/layout/components/SocialLogin/index.vue')
},
{
path: '/login',
component: () => import('@/views/login.vue'),

2
src/types/env.d.ts vendored
View File

@ -65,7 +65,7 @@ interface ImportMetaEnv {
VITE_APP_BASE_URL: string;
VITE_APP_CONTEXT_PATH: string;
VITE_APP_MONITRO_ADMIN: string;
VITE_APP_XXL_JOB_ADMIN: string;
VITE_APP_POWERJOB_ADMIN: string;
VITE_APP_ENV: string;
}
interface ImportMeta {

View File

@ -21,7 +21,7 @@
* 分布式锁 Lock4j 注解锁工具锁 多种多样<br />
* 分布式幂等 Lock4j 基于分布式锁实现<br />
* 分布式链路追踪 SkyWalking 支持链路追踪网格分析度量聚合可视化<br />
* 分布式任务调度 Xxl-Job 高性能 高可靠 易扩展<br />
* 分布式任务调度 PowerJob 高性能 高可靠 易扩展<br />
* 文件存储 Minio 本地存储<br />
* 文件存储 七牛阿里腾讯 云存储<br />
* 监控框架 SpringBoot-Admin 全方位服务监控<br />

View File

@ -36,6 +36,20 @@
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
</el-form-item>
<div style="display: flex;justify-content: flex-end;flex-direction: row;">
<el-button circle>
<svg-icon icon-class="qq" @click="doSocialLogin('qq')" />
</el-button>
<el-button circle>
<svg-icon icon-class="wechat" @click="doSocialLogin('wechat')" />
</el-button>
<el-button circle>
<svg-icon icon-class="gitee" @click="doSocialLogin('gitee')" />
</el-button>
<el-button circle>
<svg-icon icon-class="github" @click="doSocialLogin('github')" />
</el-button>
</div>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
@ -46,11 +60,13 @@
<script setup lang="ts">
import { getCodeImg, getTenantList } from '@/api/login';
import { authBinding } from '@/api/system/social/auth';
import Cookies from 'js-cookie';
import { encrypt, decrypt } from '@/utils/jsencrypt';
import { useUserStore } from '@/store/modules/user';
import { LoginData, TenantVO } from '@/api/types';
import { to } from 'await-to-js';
import { HttpStatus } from "@/enums/RespEnum";
const userStore = useUserStore();
const router = useRouter();
@ -82,12 +98,12 @@ const tenantEnabled = ref(true);
//
const register = ref(false);
const redirect = ref(undefined);
const loginRef = ref(ElForm);
const loginRef = ref<ElFormInstance>();
//
const tenantList = ref<TenantVO[]>([]);
const handleLogin = () => {
loginRef.value.validate(async (valid: boolean, fields: any) => {
loginRef.value?.validate(async (valid: boolean, fields: any) => {
if (valid) {
loading.value = true;
// cookie
@ -104,7 +120,6 @@ const handleLogin = () => {
Cookies.remove('rememberMe');
}
// action
// prittier-ignore
const [err] = await to(userStore.login(loginForm.value));
if (!err) {
await router.push({ path: redirect.value || '/' });
@ -161,6 +176,21 @@ const initTenantList = async () => {
}
}
}
/**
* 第三方登录
* @param type
*/
const doSocialLogin = (type: string) => {
authBinding(type).then((res: any) => {
if (res.code === HttpStatus.SUCCESS) {
window.location.href = res.msg;
} else {
ElMessage.error(res.msg);
}
});
};
onMounted(() => {
getCode();

View File

@ -5,5 +5,5 @@
</template>
<script setup lang="ts">
const url = ref(import.meta.env.VITE_APP_XXL_JOB_ADMIN);
const url = ref(import.meta.env.VITE_APP_POWERJOB_ADMIN);
</script>

View File

@ -55,6 +55,9 @@
<el-tab-pane label="修改密码" name="resetPwd">
<resetPwd />
</el-tab-pane>
<el-tab-pane label="第三方应用" name="thirdParty">
<thirdParty :auths="state.auths" />
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
@ -66,13 +69,16 @@
import userAvatar from "./userAvatar.vue";
import userInfo from "./userInfo.vue";
import resetPwd from "./resetPwd.vue";
import thirdParty from "./thirdParty.vue";
import { getAuthList } from "@/api/system/social/auth";
import { getUserProfile } from "@/api/system/user";
const activeTab = ref("userinfo");
const state = ref<Record<string, any>>({
user: {},
roleGroup: '',
postGroup: ''
postGroup: '',
auths: []
});
const userForm = ref({});
@ -85,7 +91,13 @@ const getUser = async () => {
state.value.postGroup = res.data.postGroup;
};
const getAuths = async () => {
const res = await getAuthList();
state.value.auths = res.data;
};
onMounted(() => {
getUser();
getAuths();
})
</script>

View File

@ -0,0 +1,140 @@
<template>
<div>
<el-table :data="auths" style="width: 100%; height: 100%; font-size: 10px">
<el-table-column label="序号" width="50" type="index"></el-table-column>
<el-table-column label="绑定账号平台" width="140" align="center" prop="source" show-overflow-tooltip />
<el-table-column label="头像" width="120" align="center" prop="avatar">
<template v-slot="scope">
<img :src="scope.row.avatar" style="width: 45px; height: 45px" />
</template>
</el-table-column>
<el-table-column label="系统账号" width="180" align="center" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="绑定时间" width="180" align="center" prop="createTime" />
<el-table-column label="操作" width="80" align="center" class-name="small-padding fixed-width">
<template v-slot="scope">
<el-button size="small" type="text" @click="unlockAuth(scope.row)">解绑</el-button>
</template>
</el-table-column>
</el-table>
<div id="git-user-binding">
<h4 class="provider-desc">你可以绑定以下第三方帐号</h4>
<div id="authlist" class="user-bind">
<a class="third-app" href="#" @click="authUrl('gitee');" title="使用 Gitee 账号授权登录">
<div class="git-other-login-icon">
<svg-icon icon-class="gitee" />
</div>
<span class="app-name">Gitee</span>
</a>
<a class="third-app" href="#" @click="authUrl('github');" title="使用 GitHub 账号授权登录">
<div class="git-other-login-icon">
<svg-icon icon-class="github" />
</div>
<span class="app-name">Github</span>
</a>
<a class="third-app" href="#" @click="authUrl('wechar');" title="使用 微信 账号授权登录">
<div class="git-other-login-icon">
<svg-icon icon-class="wechat" />
</div>
<span class="app-name">WeiXin</span>
</a>
<a class="third-app" href="#" @click="authUrl('qq');" title="使用 QQ 账号授权登录">
<div class="git-other-login-icon">
<svg-icon icon-class="qq" />
</div>
<span class="app-name">QQ</span>
</a>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { authUnlock, authBinding } from "@/api/system/social/auth";
import { PropType } from "vue";
const props = defineProps({
auths: {
type: Object as PropType<any>,
}
});
const auths = computed(() => props.auths);
const unlockAuth = (row: any) => {
ElMessageBox.confirm('您确定要解除"' + row.source + '"的账号绑定吗?')
.then(() => {
return authUnlock(row.id);
}).then((res: any) => {
if (res.code === 200) {
ElMessage.success("解绑成功");
} else {
ElMessage.error(res.msg);
}
}).catch(() => { });
};
const authUrl = (source: string) => {
authBinding(source).then((res: any) => {
if (res.code === 200) {
window.location.href = res.msg;
} else {
ElMessage.error(res.msg);
}
});
};
</script>
<style type="text/css">
.user-bind .third-app {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
min-width: 80px;
float: left;
}
.user-bind {
font-size: 1rem;
text-align: start;
height: 50px;
margin-top: 10px;
}
.git-other-login-icon>img {
height: 32px;
}
a {
text-decoration: none;
cursor: pointer;
color: #005980;
}
.provider-desc {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Liberation Sans",
"PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Wenquanyi Micro Hei",
"WenQuanYi Zen Hei", "ST Heiti", SimHei, SimSun, "WenQuanYi Zen Hei Sharp",
sans-serif;
font-size: 1.071rem;
}
td>img {
height: 20px;
width: 20px;
display: inline-block;
border-radius: 50%;
margin-right: 5px;
}
</style>