From 03ffa9151728b3ead51964f4bc8251a2909cd1e3 Mon Sep 17 00:00:00 2001 From: Dragon-Fish <xiaoyujun@aojiaogame.com> Date: Mon, 22 Apr 2024 10:57:19 +0800 Subject: [PATCH 1/2] perf: make it modern --- api/utils.ts | 43 +++++++++++++++++++++++++++++++++---------- tsconfig.json | 1 + 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/api/utils.ts b/api/utils.ts index 5ac7b926..b26b3ea1 100644 --- a/api/utils.ts +++ b/api/utils.ts @@ -97,24 +97,47 @@ ajax.interceptors.response.use((ctx) => { export function replacePximgUrlsInString(str: string): string { if (!str.includes('pximg.net')) return str return str - .replace(/https:\/\/i\.pximg\.net\//g, PXIMG_BASEURL_I) - .replace(/https:\/\/s\.pximg\.net\//g, PXIMG_BASEURL_S) + .replaceAll('https://i.pximg.net/', PXIMG_BASEURL_I) + .replaceAll('https://s.pximg.net/', PXIMG_BASEURL_S) } export function replacePximgUrlsInObject( obj: Record<string, any> | string ): Record<string, any> | string { if (typeof obj === 'string') return replacePximgUrlsInString(obj) - if (['arraybuffer', 'blob'].includes(obj.constructor.name.toLowerCase())) { - return obj - } - return JSON.parse(safelyStringify(obj), (key: string, val: any) => { - if (typeof val === 'string' && val.includes('pximg.net')) { - return replacePximgUrlsInString(val) + return deepReplaceString(obj, replacePximgUrlsInString) +} + +function isObject(value: any): value is Record<string, any> { + return typeof value === 'object' && value !== null +} + +export function deepReplaceString<T>( + obj: T, + replacer: (value: string) => string +): T { + if (Array.isArray(obj)) { + return obj.map((value) => + deepReplaceString(value, replacer) + ) as unknown as T + } else if (isObject(obj)) { + if ( + ['arraybuffer', 'blob', 'formdata'].includes( + obj.constructor.name.toLowerCase() + ) + ) { + return obj } - return val - }) + const result: Record<string, any> = {} + for (const [key, value] of Object.entries(obj)) { + result[key] = deepReplaceString(value, replacer) + } + return result as T + } else if (typeof obj === 'string') { + return replacer(obj) as unknown as T + } + return obj } export function safelyStringify(value: any, space?: number) { diff --git a/tsconfig.json b/tsconfig.json index 0ccd2dc0..8e350031 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ "types": ["unplugin-icons/types/vue"] }, "include": [ + "api/**/*.ts", "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", From c797d0ab6773006281f2cc2f63e89cd20b53dd1d Mon Sep 17 00:00:00 2001 From: Dragon-Fish <xiaoyujun@aojiaogame.com> Date: Fri, 26 Apr 2024 12:07:51 +0800 Subject: [PATCH 2/2] feat: + site notice --- components.d.ts | 8 +++-- src/App.vue | 6 ++-- src/components/SiteHeader.vue | 2 +- src/components/SiteNoticeBanner.vue | 52 +++++++++++++++++++++++++++ src/plugins/router.ts | 5 +++ src/view/notifications/2024-04-26.vue | 46 ++++++++++++++++++++++++ 6 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 src/components/SiteNoticeBanner.vue create mode 100644 src/view/notifications/2024-04-26.vue diff --git a/components.d.ts b/components.d.ts index 134580e5..b2548a5c 100644 --- a/components.d.ts +++ b/components.d.ts @@ -25,18 +25,21 @@ declare module 'vue' { LazyLoad: typeof import('./src/components/LazyLoad.vue')['default'] ListLink: typeof import('./src/components/SideNav/ListLink.vue')['default'] NaiveuiProvider: typeof import('./src/components/NaiveuiProvider.vue')['default'] + NAlert: typeof import('naive-ui')['NAlert'] NButton: typeof import('naive-ui')['NButton'] NCard: typeof import('naive-ui')['NCard'] + NCountdown: typeof import('naive-ui')['NCountdown'] NEmpty: typeof import('naive-ui')['NEmpty'] NFlex: typeof import('naive-ui')['NFlex'] + NLi: typeof import('naive-ui')['NLi'] NPagination: typeof import('naive-ui')['NPagination'] - NPaginator: typeof import('naive-ui')['NPaginator'] NProgress: typeof import('./src/components/NProgress.vue')['default'] NSpace: typeof import('naive-ui')['NSpace'] + NStatistic: typeof import('naive-ui')['NStatistic'] NTabPane: typeof import('naive-ui')['NTabPane'] NTabs: typeof import('naive-ui')['NTabs'] - NTabsPane: typeof import('naive-ui')['NTabsPane'] NTag: typeof import('naive-ui')['NTag'] + NUl: typeof import('naive-ui')['NUl'] Placeholder: typeof import('./src/components/Placeholder.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] @@ -45,6 +48,7 @@ declare module 'vue' { SideNav: typeof import('./src/components/SideNav/SideNav.vue')['default'] SiteFooter: typeof import('./src/components/SiteFooter.vue')['default'] SiteHeader: typeof import('./src/components/SiteHeader.vue')['default'] + SiteNoticeBanner: typeof import('./src/components/SiteNoticeBanner.vue')['default'] UgoiraViewer: typeof import('./src/components/UgoiraViewer.vue')['default'] } } diff --git a/src/App.vue b/src/App.vue index 693889dc..07821691 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,11 +1,13 @@ <template lang="pug"> NaiveuiProvider#app-full-container + SiteNoticeBanner + SiteHeader + main article RouterView SideNav - SiteHeader SiteFooter NProgress </template> @@ -51,7 +53,7 @@ onMounted(async () => { flex-direction: column main - padding-top: 50px + // padding-top: 50px position: relative flex: 1 article diff --git a/src/components/SiteHeader.vue b/src/components/SiteHeader.vue index e920f2bb..2ef5a362 100644 --- a/src/components/SiteHeader.vue +++ b/src/components/SiteHeader.vue @@ -142,7 +142,7 @@ onMounted(() => { color: var(--theme-background-color) display: flex align-items: center - position: fixed + position: sticky height: 50px width: 100% box-sizing: border-box diff --git a/src/components/SiteNoticeBanner.vue b/src/components/SiteNoticeBanner.vue new file mode 100644 index 00000000..aa3c56cd --- /dev/null +++ b/src/components/SiteNoticeBanner.vue @@ -0,0 +1,52 @@ +<template lang="pug"> +Transition(name='fade') + #sitenotice-banner(v-if='isShow') + NAlert( + @close='handleClose' + closable + style='font-size: 1.5rem' + title='全站公告' + type='warning' + ) + NUl + NLi: RouterLink(to='/notifications/2024-04-26') 关于 PixivNow 将可能停止服务的通知(2024年4月26日) +</template> + +<script setup lang="ts"> +import {} from 'vue' + +const alreadyShown = ref(false) +const forceShow = computed( + () => + route.name === 'about-us' || Date.now() > new Date('2024-09-01').getTime() +) +const isShow = computed(() => { + if (route.path === '/notifications/2024-04-26') { + return false + } + if (forceShow.value) return true + return !alreadyShown.value +}) +const key = `pixivnow:sitenotice/2024-04-26` +const route = useRoute() + +onMounted(() => { + alreadyShown.value = !!localStorage.getItem(key) +}) + +function handleClose() { + localStorage.setItem(key, '1') + alreadyShown.value = 1 +} +</script> + +<style scoped lang="sass"> +.fade-enter-active, +.fade-leave-active + transition: all 0.5s ease-in-out + +.fade-enter-from, +.fade-leave-to + opacity: 0 + height: 0 +</style> diff --git a/src/plugins/router.ts b/src/plugins/router.ts index 154413ae..2b20b726 100644 --- a/src/plugins/router.ts +++ b/src/plugins/router.ts @@ -61,6 +61,11 @@ const routes: RouteRecordRaw[] = [ name: 'about-us', component: () => import('@/view/about.vue'), }, + { + path: '/notifications/2024-04-26', + name: 'notification-2024-04-26', + component: () => import('@/view/notifications/2024-04-26.vue'), + }, { path: '/:pathMatch(.*)*', name: 'not-found', diff --git a/src/view/notifications/2024-04-26.vue b/src/view/notifications/2024-04-26.vue new file mode 100644 index 00000000..74d3b5f7 --- /dev/null +++ b/src/view/notifications/2024-04-26.vue @@ -0,0 +1,46 @@ +<template lang="pug"> +#notification-view.body-inner + h1.align-center 关于 PixivNow 将可能停止服务的通知(2024年4月26日) + Card + p 各位,早上好中午好晚上好: + p 我们希望通知您,由于 Vercel 在 2024年4月4日 对其<a href="https://vercel.com/blog/improved-infrastructure-pricing" target="_blank">定价策略</a>进行了修改,细化了收费指标,这对我们的项目产生了重大影响。特别是,我们的项目在部分指标上的用量<strong>已经远超过了</strong>免费计划的限额。由于 PixivNow 是一个开源项目,并且到目前为止我们<strong>没有任何盈利</strong>,我们很难为了这个兴趣使然的项目自掏腰包。 + p 幸运的是,Vercel 为现有的免费计划用户提供了 6 个月的缓冲期,这意味着我们的服务在接下来的六个月内不会受到影响。但是在此之后(大约是 2024年9月),我们的服务有极大概率将被迫中断。 + p 在接下来的几个月里,我们将探索所有可能的解决方案以继续提供服务(前提是尽量不要花钱)。 + p 我们非常感谢您一直以来对 PixivNow 的支持和理解。如果您希望继续支持我们,我们正在考虑接受赞助来帮助维持项目的运行。您可以通过访问我们的赞助页面了解更多信息,并考虑成为我们的赞助者。 + + .flex(style='justify-content: center') + NStatistic( + label='死亡倒计时' + style='border: 1px solid #efefef; padding: 0.5rem; border-radius: 0.25rem' + ) + NCountdown(:duration='duration') + + div(style='text-align: right') + strong Dragon Fish + br + time 2024年4月26日 + + Card(title='赞助我们') + .align-center + iframe( + frameborder='0' + height='200' + scrolling='no' + src='https://afdian.net/leaflet?slug=dragon-fish' + width='640' + ) + + Card(title='联系我们') + ul + li QQ群:1026023666 +</template> + +<script setup lang="ts"> +import {} from 'vue' + +const fromTime = new Date() +const toTime = new Date('2024-09-30T23:59:59Z') +const duration = toTime.getTime() - fromTime.getTime() +</script> + +<style scoped lang="sass"></style>