feat: 新增广告
This commit is contained in:
parent
b4d0b576f3
commit
664797ca46
4
.env
4
.env
@ -54,6 +54,6 @@ VITE_STORAGE_PREFIX=sj_
|
||||
# used to control whether the program automatically detects updates
|
||||
VITE_AUTOMATICALLY_DETECT_UPDATE=Y
|
||||
|
||||
VITE_UPDATE_NOTIFY=N
|
||||
VITE_UPDATE_NOTIFY=Y
|
||||
|
||||
VITE_LOGIN_CODE=N
|
||||
VITE_LOGIN_CODE=Y
|
||||
|
BIN
public/ad-ali-1.png
Normal file
BIN
public/ad-ali-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 186 KiB |
BIN
public/ad-ali-2.png
Normal file
BIN
public/ad-ali-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 244 KiB |
BIN
public/ad-tencent-1.png
Normal file
BIN
public/ad-tencent-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
BIN
public/ad-tencent-2.png
Normal file
BIN
public/ad-tencent-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 903 KiB |
@ -1,13 +1,10 @@
|
||||
<script setup lang="tsx">
|
||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import Vcode from 'vue3-puzzle-vcode';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { NA } from 'naive-ui';
|
||||
import { md5 } from '@/utils/common';
|
||||
import { $t } from '@/locales';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'PwdLogin'
|
||||
@ -40,45 +37,8 @@ async function handleSubmit() {
|
||||
}
|
||||
|
||||
const codeShow = ref(false);
|
||||
const starred = ref<boolean>(true);
|
||||
|
||||
const validateCode = async () => {
|
||||
if (!starred.value) {
|
||||
window.$dialog?.error({
|
||||
icon: () => {
|
||||
return <SvgIcon icon="material-symbols:favorite" class="color-#f5222d" />;
|
||||
},
|
||||
title: () => {
|
||||
return <>您的支持将是我们前行的动力</>;
|
||||
},
|
||||
content: () => {
|
||||
return (
|
||||
<div class="mt-20px text-base">
|
||||
<div>
|
||||
💖 如果您喜欢 Snail Job,请给它一个
|
||||
<n-a href="https://gitee.com/aizuda/snail-job" target="_blank">
|
||||
 Star
|
||||
</n-a>
|
||||
,您的支持将是我们前行的动力。 👨💻👨💻👨💻
|
||||
</div>
|
||||
<div class="mt-20px">
|
||||
🚀 本系统将在
|
||||
<n-a href="https://gitee.com/aizuda/snail-job" target="_blank">
|
||||
 Star 
|
||||
</n-a>
|
||||
后正常开放展示,感谢您的理解与支持 🙇
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
positiveText: '去 Start',
|
||||
onPositiveClick: () => {
|
||||
window.open('https://gitee.com/aizuda/snail-job', '_blank');
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const { VITE_LOGIN_CODE } = import.meta.env;
|
||||
await validate();
|
||||
if (VITE_LOGIN_CODE === 'Y') {
|
||||
@ -96,110 +56,9 @@ const onSuccess = () => {
|
||||
handleSubmit();
|
||||
};
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
async function userStarred() {
|
||||
const accessToken = localStorage.getItem('gitee_access_token');
|
||||
if (!accessToken) {
|
||||
authorize();
|
||||
return;
|
||||
}
|
||||
const response = await fetch(`https://gitee.com/api/v5/user/starred/aizuda/snail-job?access_token=${accessToken}`);
|
||||
|
||||
if (response.status === 401) {
|
||||
refreshTokenFn();
|
||||
}
|
||||
|
||||
starred.value = response.status === 204;
|
||||
}
|
||||
|
||||
function authorize() {
|
||||
const clientId = 'aae2edfddf290269fe0a756bc1c1ec1614e41dfabdb71c19322293e2b5179377';
|
||||
const redirectUri = 'https://preview.snailjob.opensnail.com/login';
|
||||
// const redirectUri = 'http://localhost:9527/login';
|
||||
location.href = `https://gitee.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=user_info`;
|
||||
}
|
||||
|
||||
async function refreshTokenFn() {
|
||||
const refreshToken = localStorage.getItem('gitee_refresh_token');
|
||||
if (!refreshToken) {
|
||||
authorize();
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch('https://gitee.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
'Content-Type': 'application/json'
|
||||
}),
|
||||
body: JSON.stringify({
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: refreshToken
|
||||
})
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('gitee_access_token');
|
||||
localStorage.removeItem('gitee_refresh_token');
|
||||
authorize();
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await response.json();
|
||||
|
||||
localStorage.setItem('gitee_access_token', res.access_token);
|
||||
localStorage.setItem('gitee_refresh_token', res.refresh_token);
|
||||
userStarred();
|
||||
}
|
||||
|
||||
async function oauth2() {
|
||||
const code = route.query.code;
|
||||
if (!code) {
|
||||
return;
|
||||
}
|
||||
const response = await fetch('/api/oauth2/login', {
|
||||
method: 'POST',
|
||||
headers: new Headers({
|
||||
'Content-Type': 'application/json'
|
||||
}),
|
||||
body: JSON.stringify({ code })
|
||||
});
|
||||
|
||||
const res = await response.json();
|
||||
|
||||
if (res.code !== 200) {
|
||||
authorize();
|
||||
return;
|
||||
}
|
||||
|
||||
const accessToken = res.data.access_token;
|
||||
const refreshToken = res.data.refresh_token;
|
||||
localStorage.setItem('gitee_access_token', accessToken);
|
||||
localStorage.setItem('gitee_refresh_token', refreshToken);
|
||||
}
|
||||
|
||||
function handleVisibilitychange() {
|
||||
const state = document.visibilityState;
|
||||
if (state === 'visible') {
|
||||
userStarred();
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('visibilitychange', handleVisibilitychange);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('visibilitychange', handleVisibilitychange);
|
||||
});
|
||||
|
||||
async function init() {
|
||||
if (starred.value) return;
|
||||
await oauth2();
|
||||
await userStarred();
|
||||
}
|
||||
|
||||
init();
|
||||
const codePopoverStytle = {
|
||||
padding: 0
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -216,15 +75,7 @@ init();
|
||||
/>
|
||||
</NFormItem>
|
||||
<NSpace vertical :size="24">
|
||||
<div v-if="!starred" class="flex-col-center justify-between">
|
||||
<div>
|
||||
💖 如果您喜欢 Snail Job,请给它一个
|
||||
<NA href="https://gitee.com/aizuda/snail-job" target="_blank" rel="noopener noreferrer"> Star </NA>
|
||||
,
|
||||
</div>
|
||||
<div>您的支持将是我们前行的动力。 👨💻👨💻👨💻</div>
|
||||
</div>
|
||||
<NPopover :show="codeShow" row>
|
||||
<NPopover :show="codeShow" row :style="codePopoverStytle">
|
||||
<template #trigger>
|
||||
<NButton type="primary" size="large" round block :loading="authStore.loginLoading" @click="validateCode">
|
||||
{{ $t('page.login.common.login') }}
|
||||
@ -245,8 +96,4 @@ init();
|
||||
</NForm>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.n-popover) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
<style scoped></style>
|
||||
|
@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { fetchCardCount } from '@/service/api';
|
||||
import HeaderBanner from './modules/header-banner.vue';
|
||||
// import HeaderBanner from './modules/header-banner.vue';
|
||||
import CardData from './modules/card-data.vue';
|
||||
import TaskTab from './modules/task-tab.vue';
|
||||
import AdCarousel from './modules/ad-carousel.vue';
|
||||
|
||||
const cardCount = ref<Api.Dashboard.CardCount>();
|
||||
|
||||
@ -19,7 +20,7 @@ getCardData();
|
||||
|
||||
<template>
|
||||
<NSpace vertical :size="16" class="home-main">
|
||||
<HeaderBanner />
|
||||
<AdCarousel />
|
||||
<CardData v-model="cardCount!" />
|
||||
<NCard :bordered="false" class="card-wrapper p-t-136px 2xl:p-t-0 lg:p-t-36px md:p-t-90px">
|
||||
<TaskTab v-model="cardCount!" />
|
||||
|
155
src/views/home/modules/ad-carousel.vue
Normal file
155
src/views/home/modules/ad-carousel.vue
Normal file
@ -0,0 +1,155 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
|
||||
defineOptions({
|
||||
name: 'AdCarousel'
|
||||
});
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
const gap = computed(() => (appStore.isMobile ? 0 : 16));
|
||||
|
||||
const href = (url: string) => {
|
||||
window.open(url, '_blank');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGi class="flex-center" span="24 l:12">
|
||||
<NCard title="广告" :bordered="false" class="w-1000px card-wrapper">
|
||||
<template #header-extra>❤️ 开源不易,敬请谅解 ❤️</template>
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGi class="flex-center" span="24 s:9">
|
||||
<NCarousel
|
||||
autoplay
|
||||
direction="vertical"
|
||||
dot-type="line"
|
||||
dot-placement="left"
|
||||
class="h-130px w-260px"
|
||||
:interval="3000"
|
||||
mousewheel
|
||||
>
|
||||
<NCarouselItem>
|
||||
<NA href="https://curl.qcloud.com/2j1RuHbf" target="_blank" rel="noopener noreferrer">
|
||||
<img class="carousel-img" src="/ad-tencent-1.png" />
|
||||
</NA>
|
||||
</NCarouselItem>
|
||||
<NCarouselItem>
|
||||
<NA href="https://curl.qcloud.com/HvUPpDGE" target="_blank" rel="noopener noreferrer">
|
||||
<img class="carousel-img" src="/ad-tencent-2.png" />
|
||||
</NA>
|
||||
</NCarouselItem>
|
||||
</NCarousel>
|
||||
</NGi>
|
||||
<NGi class="flex-center" span="24 s:15">
|
||||
<NCarousel
|
||||
autoplay
|
||||
direction="vertical"
|
||||
dot-type="line"
|
||||
dot-placement="left"
|
||||
class="h-130px w-500px"
|
||||
:interval="3000"
|
||||
mousewheel
|
||||
>
|
||||
<NCarouselItem>
|
||||
<NA
|
||||
href="https://www.aliyun.com/daily-act/ecs/activity_selection?userCode=4rntegyg"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img class="carousel-img" src="/ad-ali-1.png" />
|
||||
</NA>
|
||||
</NCarouselItem>
|
||||
<NCarouselItem>
|
||||
<NA
|
||||
href="https://www.aliyun.com/daily-act/ecs/ecs_trial_benefits?userCode=4rntegyg"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img class="carousel-img" src="/ad-ali-2.png" />
|
||||
</NA>
|
||||
</NCarouselItem>
|
||||
</NCarousel>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<NGi class="flex-center" span="24 l:12">
|
||||
<NCard title="赞助商" :bordered="false" class="card-wrapper">
|
||||
<template #header-extra>
|
||||
❤️
|
||||
<NButton text @click="href('https://snailjob.opensnail.com/docs/sponsor.html')">成为赞助商</NButton>
|
||||
❤️
|
||||
</template>
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGi class="h-130px w-250px flex-center" span="24 s:12">
|
||||
<div class="float-right max-w-250px w-full flex flex-col-reverse">
|
||||
<div class="order-9999 m-6px max-w-240px text-13px color-gray">
|
||||
<span>官号</span>
|
||||
</div>
|
||||
<NButton quaternary class="h-full" @click="href('https://space.bilibili.com/3493144058399579')">
|
||||
<NThing class="max-w-full flex-center">
|
||||
<template #avatar>
|
||||
<SvgIcon class="text-66px color-#00aeec" local-icon="bilibili" />
|
||||
</template>
|
||||
<template #header>
|
||||
<div class="bilibili-title color-#00aeec font-semibold">Open Snail</div>
|
||||
<div class="flow-long-title ml-3px font-semibold">bilibili 官方账号</div>
|
||||
</template>
|
||||
</NThing>
|
||||
</NButton>
|
||||
</div>
|
||||
</NGi>
|
||||
<NGi class="h-130px w-250px flex-center" span="24 s:12">
|
||||
<div class="float-right max-w-250px w-full flex flex-col-reverse">
|
||||
<div class="order-9999 m-6px max-w-240px text-13px color-gray">
|
||||
<span>赞助商</span>
|
||||
</div>
|
||||
<NButton quaternary class="h-full" @click="href('https://doc.flowlong.com/?from=snail-job')">
|
||||
<NThing class="max-w-full flex-center">
|
||||
<template #avatar>
|
||||
<SvgIcon class="text-66px" local-icon="flowlong" />
|
||||
</template>
|
||||
<template #header>
|
||||
<div class="flow-long-title-color font-semibold">FlowLong</div>
|
||||
<div class="flow-long-title font-semibold">飞龙工作流引擎</div>
|
||||
</template>
|
||||
</NThing>
|
||||
</NButton>
|
||||
</div>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
</NCard>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.carousel-img {
|
||||
height: 130px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.flow-long-title-color {
|
||||
text-align: left;
|
||||
line-height: 36px;
|
||||
font-size: 28px;
|
||||
background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff);
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.flow-long-title {
|
||||
text-align: left;
|
||||
line-height: 22px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.bilibili-title {
|
||||
text-align: cneter;
|
||||
line-height: 36px;
|
||||
font-size: 26px;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user