229 lines
6.4 KiB
Vue
229 lines
6.4 KiB
Vue
// eslint-disable-next-line vue/name-property-casing
|
|
<script setup lang="ts">
|
|
import { RouterView } from 'vue-router';
|
|
import { ref, onMounted, onBeforeUnmount, watchEffect } from 'vue';
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
import { addEventListener, clearEvent } from '@/utils/eventBus';
|
|
import { useLogin } from './utils/hooks/useLogin';
|
|
import { useNotification } from './utils/hooks/useNotice';
|
|
import { useAccount } from './utils/hooks/useAccount';
|
|
import { useAccModal } from './utils/hooks/useAccModal';
|
|
import { NotificationService } from 'vue-devui/notification';
|
|
import { Message } from 'vue-devui/message';
|
|
import { getOrgInfo } from '@/views/Org/hooks/orgInfo';
|
|
import cookie from 'js-cookie';
|
|
import { useGlobalInfoStore } from '@/stores/Global';
|
|
import dayjs from 'dayjs';
|
|
import { getLoginConfig } from './api/user';
|
|
|
|
const globalInfo = useGlobalInfoStore();
|
|
const { login, unMount, isMounted } = useLogin();
|
|
const { openModal, closeModal, isMountedModal } = useAccModal();
|
|
const { notice } = useNotification();
|
|
const { RemoveInfo } = useAccount();
|
|
const status = ref(false);
|
|
const isPending = ref(false);
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
|
|
const toNotice = () => {
|
|
if (localStorage.getItem('validator_email') === 'invalid') {
|
|
notice();
|
|
}
|
|
};
|
|
|
|
const checkoutFirstTime = () => {
|
|
const uuid = cookie.get('uuid_tt_dd');
|
|
const firstTime = cookie.get('gitcode_first_time');
|
|
if (uuid && !firstTime) {
|
|
const expireDate = new Date(`${dayjs().year() + 2}-01-01 00:00:00`);
|
|
const expirationUTC = new Date(
|
|
Date.UTC(
|
|
expireDate.getFullYear(),
|
|
expireDate.getMonth(),
|
|
expireDate.getDate(),
|
|
expireDate.getHours(),
|
|
expireDate.getMinutes(),
|
|
expireDate.getSeconds()
|
|
)
|
|
);
|
|
const domainMatch = (location.host.match(/(gitcode..+)/) || []) as string[];
|
|
cookie.set('gitcode_first_time', dayjs().format('YYYY-MM-DD HH:mm:ss'), { expires: expirationUTC, domain: domainMatch[1] });
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
/** pc端刷新窗口 */
|
|
toNotice();
|
|
addEventListener('logout', (options) => {
|
|
const token = localStorage.getItem('access_token');
|
|
if (!status.value) {
|
|
status.value = true;
|
|
if (isMounted()) {
|
|
setTimeout(() => {
|
|
status.value = false;
|
|
}, 2000);
|
|
} else {
|
|
NotificationService.open({
|
|
type: 'success',
|
|
title: 'Gitcode 提示',
|
|
content: token ? '你的登录信息已过期,请重新登录!' : '登录之后才能开启全新体验哦',
|
|
onClose: () => {
|
|
status.value = false;
|
|
}
|
|
});
|
|
}
|
|
token && RemoveInfo();
|
|
|
|
const data = typeof options === 'boolean' ? { Authorization: options } : options;
|
|
login(data);
|
|
}
|
|
});
|
|
addEventListener('login', (options) => {
|
|
login(options);
|
|
});
|
|
/** 403刷新页面一次 */
|
|
addEventListener('forbiddenRefresh', () => {
|
|
// 暂时跳转组织创建
|
|
if (route.path === '/org/create') {
|
|
localStorage.removeItem('refresh_count');
|
|
return;
|
|
}
|
|
if (!isPending.value) {
|
|
isPending.value = true;
|
|
if (!localStorage.getItem('refresh_count') && route.name !== '403') {
|
|
localStorage.setItem('refresh_count', 'pending');
|
|
router.go(0);
|
|
} else {
|
|
Message.warning({
|
|
message: '权限不足',
|
|
onClose: () => {
|
|
localStorage.removeItem('refresh_count');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
/** mobile暂定全部重定向为首页 */
|
|
addEventListener('notice', toNotice);
|
|
window.addEventListener('message', (event) => {
|
|
if (event.origin === (import.meta as any).env.VITE_HOST) {
|
|
if (event.data.type === 'success') {
|
|
if (isMountedModal()) {
|
|
closeModal();
|
|
}
|
|
if (isMounted()) {
|
|
unMount();
|
|
}
|
|
if (event.data?.path) {
|
|
router.replace(event.data?.path);
|
|
} else {
|
|
router.go(0);
|
|
}
|
|
} else if (event.data.type === 'fail') {
|
|
Message.warning(event.data.message || '授权失败');
|
|
}
|
|
}
|
|
});
|
|
/** 获取用户组织配额权限 */
|
|
if (!localStorage.getItem('group_quota')) {
|
|
const { getUserCreateOrg } = getOrgInfo();
|
|
getUserCreateOrg();
|
|
}
|
|
checkoutFirstTime();
|
|
});
|
|
|
|
watchEffect(async() => {
|
|
if (route?.query?.isLogin && !localStorage.getItem('access_token')) {
|
|
if (!isMountedModal()) {
|
|
const cache_timeStamp = localStorage.getItem('cache_timeStamp');
|
|
const currentTimestamp = Date.now();
|
|
const oneDayMilliseconds = 24 * 60 * 60 * 1000;
|
|
|
|
// 获取不加防打扰的配置
|
|
let loginList = [];
|
|
if (route?.query?.isLogin !== '1') {
|
|
const res = await getLoginConfig();
|
|
loginList = res?.data?.data || [];
|
|
}
|
|
|
|
// isLogin为配置字符串时一直弹窗
|
|
if (loginList.includes(route?.query?.isLogin) || !cache_timeStamp || (Number(cache_timeStamp) + oneDayMilliseconds) < currentTimestamp) {
|
|
setTimeout(() => {
|
|
localStorage.setItem('cache_timeStamp', currentTimestamp.toString());
|
|
openModal();
|
|
}, 1000);
|
|
}
|
|
}
|
|
}
|
|
// 注册来源utm_source保存
|
|
if (route?.query?.utm_source) {
|
|
const currentTime = Date.now();
|
|
localStorage.setItem('utm_source_sign_time', currentTime.toString());
|
|
localStorage.setItem('utm_source_sign', JSON.stringify(route?.query?.utm_source));
|
|
}
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
clearEvent();
|
|
window.removeEventListener('message', () => {});
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<RouterView :class="`g-theme-${globalInfo.globalTheme}`" />
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
.global-notification {
|
|
&-mobile {
|
|
.devui-notification {
|
|
right: 15px;
|
|
left: 15px;
|
|
width: #{calc(100vw - 30px )};
|
|
top: 60px;
|
|
&__title {
|
|
padding: 0;
|
|
}
|
|
}
|
|
.devui-notification-item-container {
|
|
background: rgba(255, 255, 255, 1);
|
|
box-sizing: border-box;
|
|
padding: 15px;
|
|
opacity: 1;
|
|
.devui-notification__item {
|
|
padding: 0;
|
|
}
|
|
}
|
|
}
|
|
&-pc {
|
|
.devui-notification {
|
|
width: 296px;
|
|
right: 22px;
|
|
top: 60px;
|
|
&__title {
|
|
padding: 0;
|
|
}
|
|
}
|
|
.devui-notification-item-container {
|
|
background: rgba(255, 255, 255, 1);
|
|
box-sizing: border-box;
|
|
padding: 22px;
|
|
opacity: 1;
|
|
.devui-notification__item {
|
|
padding: 0;
|
|
}
|
|
}
|
|
}
|
|
.devui-notification__message {
|
|
margin-left: 0;
|
|
}
|
|
.icon-close {
|
|
font-size: 0 !important;
|
|
&:before {
|
|
content: ''
|
|
}
|
|
}
|
|
}
|
|
</style>
|