Files
biliup/app/lib/api-streamer.ts
T
XiaoMiku01 b3ee6f0e1f 添加登录页面 (#1375)
* feat: 实现完整的用户认证系统

- 添加登录页面和认证上下文
- 创建认证守卫组件保护路由
- 修改API请求添加认证头
- 重构布局组件支持认证状态
- 后端API添加认证中间件

* refactor(auth): 移除调试用的print语句

清理认证中间件中的调试输出,这些语句在生产环境中不需要

* style(login): 更新登录页面样式,添加渐变背景和卡片效果

改进登录页面的视觉设计,使用渐变背景提升整体美观度,并优化卡片样式增加现代感
2025-07-30 04:00:06 +00:00

238 lines
5.9 KiB
TypeScript

// Fetcher implementation.
// The extra argument will be passed via the `arg` property of the 2nd parameter.
// In the example below, `arg` will be `'my_token'`
export async function sendRequest<T>(url: string, { arg }: {arg: T}) {
// 获取认证信息
const auth = typeof window !== 'undefined' ? localStorage.getItem('auth') : null;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
// 如果存在认证信息,则添加到请求头
if (auth) {
headers['Authorization'] = `Basic ${auth}`;
}
const res = await fetch((process.env.NEXT_PUBLIC_API_SERVER ?? '') + url, {
method: 'POST',
headers,
body: JSON.stringify(arg)
});
if(!(res.status >=200 && res.status < 300)) {
throw new Error(await res.text());
}
const data = await res.json();
if (!res.ok) {
throw new Error(data.message);
}
return data;
}
export const fetcher = async (...args: any[]) => {
// 获取认证信息
const auth = typeof window !== 'undefined' ? localStorage.getItem('auth') : null;
// 创建请求配置
const init = args[1] || {};
const headers: HeadersInit = init.headers || {};
// 如果存在认证信息,则添加到请求头
if (auth) {
// 将headers转换为可修改的对象
let headersObj: Record<string, string> = {};
if (headers instanceof Headers) {
headers.forEach((value, key) => {
headersObj[key] = value;
});
} else if (Array.isArray(headers)) {
headersObj = Object.fromEntries(headers);
} else {
headersObj = { ...headers };
}
headersObj['Authorization'] = `Basic ${auth}`;
const res = await fetch((process.env.NEXT_PUBLIC_API_SERVER ?? '') + args[0], {
...init,
headers: headersObj
});
if (!res.ok) {
throw new Error(await res.text());
}
return res.json();
}
// 如果没有认证信息,直接发送请求
const res = await fetch((process.env.NEXT_PUBLIC_API_SERVER ?? '') + args[0], {
...init,
headers
});
if (!res.ok) {
throw new Error(await res.text());
}
return res.json();
}
export const proxy = async (input: RequestInfo | URL, init?: RequestInit | undefined) => {
// 获取认证信息
const auth = typeof window !== 'undefined' ? localStorage.getItem('auth') : null;
// 创建请求配置
const requestInit = init || {};
const headers: HeadersInit = requestInit.headers || {};
// 如果存在认证信息,则添加到请求头
if (auth) {
// 将headers转换为可修改的对象
let headersObj: Record<string, string> = {};
if (headers instanceof Headers) {
headers.forEach((value, key) => {
headersObj[key] = value;
});
} else if (Array.isArray(headers)) {
headersObj = Object.fromEntries(headers);
} else {
headersObj = { ...headers };
}
headersObj['Authorization'] = `Basic ${auth}`;
const res = await fetch((process.env.NEXT_PUBLIC_API_SERVER ?? '') + input, {
...requestInit,
headers: headersObj
});
if (!res.ok) {
throw new Error(await res.text());
}
return res;
}
// 如果没有认证信息,直接发送请求
const res = await fetch((process.env.NEXT_PUBLIC_API_SERVER ?? '') + input, {
...requestInit,
headers
});
if (!res.ok) {
throw new Error(await res.text());
}
return res;
}
export async function requestDelete<T>(url: string, { arg }: {arg: T}) {
// 获取认证信息
const auth = typeof window !== 'undefined' ? localStorage.getItem('auth') : null;
const headers: Record<string, string> = {};
// 如果存在认证信息,则添加到请求头
if (auth) {
headers['Authorization'] = `Basic ${auth}`;
}
const res = await fetch(`${process.env.NEXT_PUBLIC_API_SERVER ?? ''}${url}/${arg}`, {
method: 'DELETE',
headers
});
if (!res.ok) {
throw new Error(await res.text());
}
return res;
}
export async function put<T>(url: string, { arg }: {arg: T}) {
// 获取认证信息
const auth = typeof window !== 'undefined' ? localStorage.getItem('auth') : null;
const headers: Record<string, string> = {
'Content-Type': 'application/json'
};
// 如果存在认证信息,则添加到请求头
if (auth) {
headers['Authorization'] = `Basic ${auth}`;
}
const res = await fetch(`${process.env.NEXT_PUBLIC_API_SERVER ?? ''}${url}`, {
method: 'PUT',
headers,
body: JSON.stringify(arg)
});
if (!res.ok) {
throw new Error(await res.text());
}
return res;
}
type Credit = {
username: string;
uid: number;
};
export interface StudioEntity {
id: number;
template_name: string;
user_cookie: string;
copyright: number;
copyright_source: string;
tid: number;
cover_path: string;
title: string;
description: string;
dynamic: string;
tags: string[];
dtime: number;
// interactive: number;
mission_id?: number;
dolby: number;
hires: number;
no_reprint: number;
is_only_self: number;
up_selection_reply: number;
up_close_reply: number;
up_close_danmu: number;
open_elec: number;
credits: Credit[];
uploader: string;
extra_fields?: string;
}
export interface LiveStreamerEntity {
id: number;
url: string;
remark: string;
filename: string;
split_time?: number;
split_size?: number;
upload_id?: number;
status?: string | React.ReactNode;
format?: string;
time_range?: string | Date[];
excluded_keywords?: string[];
preprocessor?: Record<'run', string>[];
segment_processor?: Record<'run', string>[];
downloaded_processor?: Record<'run', string>[];
postprocessor?: (Record<'run' | 'mv', string> | 'rm')[];
opt_args?: string[];
override?: Record<string, any>;
}
export interface BiliType {
id: number;
children: BiliType[];
name: string;
desc: string;
}
export interface User {
id: number;
name: string;
value: string;
platform: string;
}
export interface FileList {
key: number;
name: string;
updateTime: number;
size: number;
}