From 14a905e194f925cacd24db83dc8ac52c0ba1d9a4 Mon Sep 17 00:00:00 2001 From: Leon <147289645+LeoninCS@users.noreply.github.com> Date: Fri, 26 Dec 2025 18:24:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=89=8D=E7=AB=AF=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/client.ts | 41 +++ frontend/src/api/like.ts | 6 +- frontend/src/api/video.ts | 16 +- frontend/src/style.css | 6 + frontend/src/utils/jwt.ts | 9 +- frontend/src/views/AccountView.vue | 121 +++++++- frontend/src/views/VideoView.vue | 451 ++++++++++++++++++----------- frontend/vite.config.ts | 3 +- 8 files changed, 468 insertions(+), 185 deletions(-) diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index e313fc0..1531b58 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -56,3 +56,44 @@ export async function postJson(path: string, body: unknown, options?: { authR return data as T } + +export async function postForm(path: string, body: FormData, options?: { authRequired?: boolean }): Promise { + const auth = useAuthStore() + const token = auth.token + + if (options?.authRequired && !token) { + throw new ApiError('需要先登录(缺少 token)', 401) + } + + const headers: Record = {} + if (token) headers.Authorization = `Bearer ${token}` + + const res = await fetch(`${API_BASE}${path}`, { + method: 'POST', + headers, + body, + }) + + const text = await res.text() + let data: unknown = null + if (text) { + try { + data = JSON.parse(text) + } catch { + data = text + } + } + + if (!res.ok) { + if (res.status === 401) { + auth.clearToken() + } + const msg = + data && typeof data === 'object' && (data as ApiErrorBody).error + ? String((data as ApiErrorBody).error) + : `请求失败 (${res.status})` + throw new ApiError(msg, res.status, data) + } + + return data as T +} diff --git a/frontend/src/api/like.ts b/frontend/src/api/like.ts index 289d737..ce80cc0 100644 --- a/frontend/src/api/like.ts +++ b/frontend/src/api/like.ts @@ -1,5 +1,5 @@ import { postJson } from './client' -import type { IsLikedResponse, MessageResponse } from './types' +import type { IsLikedResponse, MessageResponse, Video } from './types' export function like(videoId: number) { return postJson('/like/like', { video_id: videoId }, { authRequired: true }) @@ -12,3 +12,7 @@ export function unlike(videoId: number) { export function isLiked(videoId: number) { return postJson('/like/isLiked', { video_id: videoId }, { authRequired: true }) } + +export function listMyLikedVideos() { + return postJson('/like/listMyLikedVideos', {}, { authRequired: true }) +} diff --git a/frontend/src/api/video.ts b/frontend/src/api/video.ts index 5cc1eca..85e8781 100644 --- a/frontend/src/api/video.ts +++ b/frontend/src/api/video.ts @@ -1,10 +1,24 @@ -import { postJson } from './client' +import { postForm, postJson } from './client' import type { Video } from './types' export function publishVideo(input: { title: string; description: string; play_url: string; cover_url: string }) { return postJson