feat: 前端界面

This commit is contained in:
Leon
2025-12-26 18:24:28 +08:00
parent fe292aa1c6
commit 14a905e194
8 changed files with 468 additions and 185 deletions

View File

@@ -56,3 +56,44 @@ export async function postJson<T>(path: string, body: unknown, options?: { authR
return data as T
}
export async function postForm<T>(path: string, body: FormData, options?: { authRequired?: boolean }): Promise<T> {
const auth = useAuthStore()
const token = auth.token
if (options?.authRequired && !token) {
throw new ApiError('需要先登录(缺少 token', 401)
}
const headers: Record<string, string> = {}
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
}

View File

@@ -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<MessageResponse>('/like/like', { video_id: videoId }, { authRequired: true })
@@ -12,3 +12,7 @@ export function unlike(videoId: number) {
export function isLiked(videoId: number) {
return postJson<IsLikedResponse>('/like/isLiked', { video_id: videoId }, { authRequired: true })
}
export function listMyLikedVideos() {
return postJson<Video[]>('/like/listMyLikedVideos', {}, { authRequired: true })
}

View File

@@ -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<Video>('/video/publish', input, { authRequired: true })
}
export type UploadResponse = { url: string; play_url?: string; cover_url?: string }
export function uploadVideo(file: File) {
const fd = new FormData()
fd.append('file', file)
return postForm<UploadResponse>('/video/uploadVideo', fd, { authRequired: true })
}
export function uploadCover(file: File) {
const fd = new FormData()
fd.append('file', file)
return postForm<UploadResponse>('/video/uploadCover', fd, { authRequired: true })
}
export function listByAuthorId(authorId: number) {
return postJson<Video[]>('/video/listByAuthorID', { author_id: authorId })
}