feat: 迁移到Cloudflare Workers并重构API请求处理

refactor: 使用fetch替换axios并优化请求处理逻辑

docs: 添加DEPLOYMENT.md部署指南

build: 更新package.json依赖和脚本配置

style: 更新组件类型定义和注释

perf: 优化图片代理和用户数据初始化逻辑
This commit is contained in:
2025-10-08 15:53:36 +08:00
parent 8b93d6f42f
commit 1147cd270b
78 changed files with 11389 additions and 2119 deletions

7
src/components.d.ts vendored
View File

@@ -27,9 +27,16 @@ declare module 'vue' {
ListLink: typeof import('./components/SideNav/ListLink.vue')['default']
NaiveuiProvider: typeof import('./components/NaiveuiProvider.vue')['default']
NAlert: typeof import('naive-ui')['NAlert']
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard']
NEmpty: typeof import('naive-ui')['NEmpty']
NFlex: typeof import('naive-ui')['NFlex']
NLi: typeof import('naive-ui')['NLi']
NPagination: typeof import('naive-ui')['NPagination']
NProgress: typeof import('./components/NProgress.vue')['default']
NSpace: typeof import('naive-ui')['NSpace']
NTabPane: typeof import('naive-ui')['NTabPane']
NTabs: typeof import('naive-ui')['NTabs']
NTag: typeof import('naive-ui')['NTag']
NUl: typeof import('naive-ui')['NUl']
Placeholder: typeof import('./components/Placeholder.vue')['default']

View File

@@ -19,6 +19,7 @@
<script lang="ts" setup>
import Cookies from 'js-cookie'
import { useUserStore } from '@/composables/states'
import { ajax } from '@/utils/ajax'
const store = useUserStore()
@@ -41,20 +42,22 @@ async function submit(): Promise<void> {
if (loading.value) return
try {
loading.value = true
const { data } = await axios.post(
const response = await ajax.post(
`/ajax/illusts/comments/post`,
{
JSON.stringify({
type: 'comment',
illust_id: props.id,
author_user_id: store.userId,
comment,
},
}),
{
headers: {
'X-CSRF-TOKEN': Cookies.get('csrf_token'),
'Content-Type': 'application/json',
},
}
)
const data = await response.json()
comment.value = ''
emit('push-comment', {
img: store.userProfileImg,

View File

@@ -1,5 +1,6 @@
import { PixivUser } from '@/types'
import Cookies from 'js-cookie'
import { ajax } from '@/utils/ajax'
export function existsSessionId(): boolean {
const sessionId = Cookies.get('PHPSESSID')
@@ -13,14 +14,12 @@ export function existsSessionId(): boolean {
export async function initUser(): Promise<PixivUser> {
try {
const { data } = await axios.get<{ userData: PixivUser; token: string }>(
`/api/user`,
{
headers: {
'Cache-Control': 'no-store',
},
}
)
const response = await ajax.get(`/api/user`, {
headers: {
'Cache-Control': 'no-store',
},
})
const data: { userData: PixivUser; token: string } = await response.json()
if (data.token) {
console.log('session ID认证成功', data)
Cookies.set('CSRFTOKEN', data.token, { secure: true, sameSite: 'Strict' })

View File

@@ -1,26 +1,34 @@
import { AxiosRequestConfig } from 'axios'
import nprogress from 'nprogress'
export const ajax = axios.create({
timeout: 15 * 1000,
headers: {
'Content-Type': 'application/json',
},
})
ajax.interceptors.request.use((config) => {
nprogress.start()
return config
})
ajax.interceptors.response.use(
(res) => {
nprogress.done()
return res
},
(err) => {
nprogress.done()
return Promise.reject(err)
const createAjax = () => {
const fetchWithInterceptor = async (
url: string,
options?: RequestInit,
): Promise<Response> => {
nprogress.start()
try {
const response = await fetch(url, options)
return response
} catch (error) {
return Promise.reject(error)
} finally {
nprogress.done()
}
}
)
return {
get: (url: string, options?: RequestInit) =>
fetchWithInterceptor(url, { ...options, method: 'GET' }),
post: (url: string, body?: any, options?: RequestInit) =>
fetchWithInterceptor(url, {
...options,
method: 'POST',
body: body,
}),
}
}
export const ajax = createAjax()
export const ajaxPostWithFormData = (
url: string,
@@ -30,12 +38,13 @@ export const ajaxPostWithFormData = (
| Record<string, string>
| URLSearchParams
| undefined,
config?: AxiosRequestConfig
) =>
ajax.post(url, new URLSearchParams(data).toString(), {
config?: RequestInit,
) => {
return ajax.post(url, new URLSearchParams(data).toString(), {
...config,
headers: {
...config?.headers,
...(config?.headers || {}),
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
},
})
}

View File

@@ -235,9 +235,13 @@ async function init(id: string): Promise<void> {
}
try {
const [{ data: illustData }, { data: illustPage }] = await Promise.all([
ajax.get<Artwork>(`/ajax/illust/${id}?full=1`),
ajax.get<ArtworkGallery[]>(`/ajax/illust/${id}/pages`),
const [illustData, illustPage] = await Promise.all([
ajax
.get(`/ajax/illust/${id}?full=1`)
.then((res) => res.json() as Promise<Artwork>),
ajax
.get(`/ajax/illust/${id}/pages`)
.then((res) => res.json() as Promise<ArtworkGallery[]>),
])
setCache(`illust.${id}`, illustData)
setCache(`illust.${id}.page`, illustPage)
@@ -263,11 +267,16 @@ async function handleUserInit(userId: string): Promise<void> {
}
try {
const [{ data: userData }, { data: profileData }] = await Promise.all([
axios.get<User>(`/ajax/user/${userId}?full=1`),
axios.get<{ illusts: Record<string, ArtworkInfo> }>(
`/ajax/user/${userId}/profile/top`
),
const [userData, profileData] = await Promise.all([
ajax
.get(`/ajax/user/${userId}?full=1`)
.then((res) => res.json() as Promise<User>),
ajax
.get(`/ajax/user/${userId}/profile/top`)
.then(
(res) =>
res.json() as Promise<{ illusts: Record<string, ArtworkInfo> }>
),
])
const { illusts } = profileData
const userValue = {
@@ -286,10 +295,15 @@ async function handleRecommendInit(id: string): Promise<void> {
try {
recommendLoading.value = true
console.log('init recommend')
const { data } = await ajax.get<{
illusts: ArtworkInfo[]
nextIds: string[]
}>(`/ajax/illust/${id}/recommend/init?limit=18`)
const data = await ajax
.get(`/ajax/illust/${id}/recommend/init?limit=18`)
.then(
(res) =>
res.json() as Promise<{
illusts: ArtworkInfo[]
nextIds: string[]
}>
)
recommend.value = data.illusts
recommendNextIds.value = data.nextIds
} catch (err) {
@@ -313,10 +327,15 @@ async function handleMoreRecommend(): Promise<void> {
for (const id of requestIds) {
searchParams.append('illust_ids', id)
}
const { data } = await ajax.get<{
illusts: ArtworkInfo[]
nextIds: string[]
}>('/ajax/illust/recommend/illusts', { params: searchParams })
const data = await ajax
.get(`/ajax/illust/recommend/illusts?${searchParams.toString()}`)
.then(
(res) =>
res.json() as Promise<{
illusts: ArtworkInfo[]
nextIds: string[]
}>
)
recommend.value = recommend.value.concat(data.illusts)
recommendNextIds.value = recommendNextIds.value.concat(data.nextIds)
} catch (err) {