feat: 新增广告

This commit is contained in:
xlsea 2024-09-22 18:56:28 +08:00
parent b4d0b576f3
commit 664797ca46
8 changed files with 167 additions and 164 deletions

4
.env
View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
public/ad-tencent-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 KiB

View File

@ -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">
&ensp;Star
</n-a>
您的支持将是我们前行的动力 👨💻👨💻👨💻
</div>
<div class="mt-20px">
🚀 本系统将在
<n-a href="https://gitee.com/aizuda/snail-job" target="_blank">
&ensp;Star&ensp;
</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">&ensp;Star&ensp;</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>

View File

@ -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!" />

View 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>
&nbsp;
<NButton text @click="href('https://snailjob.opensnail.com/docs/sponsor.html')">成为赞助商</NButton>
&nbsp;
</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>