feat: 更新配置和文件上传逻辑, 迁移数据库结构(前端也得改

- 移除不再使用的 vite-plugin-monaco-editor
- 更新 package.json 和 vite.config.mts 文件
- 修改用户配置 API 逻辑,支持上传和下载配置
- 添加对文件上传的支持,优化文件处理逻辑
- 更新多个组件以支持新文件上传功能
- 删除不必要的 VTsuruTypes.ts 文件,整合到 VTsuruConfigTypes.ts 中
This commit is contained in:
2025-05-03 06:18:32 +08:00
parent 4ac793f155
commit 1f47703a8b
25 changed files with 1468 additions and 532 deletions

View File

@@ -1,5 +1,5 @@
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query';
import { ACCOUNT_API_URL, VTSURU_API_URL } from '@/data/constants';
import { ACCOUNT_API_URL, USER_CONFIG_API_URL, VTSURU_API_URL } from '@/data/constants';
import { isSameDay } from 'date-fns';
import { createDiscreteApi } from 'naive-ui';
import { ref } from 'vue';
@@ -184,7 +184,7 @@ export async function DelBlackList(id: number): Promise<APIRoot<unknown>> {
});
}
export function downloadConfigDirect(name: string) {
return QueryGetAPI<string>(VTSURU_API_URL + 'get-config', {
return QueryGetAPI<string>(USER_CONFIG_API_URL + 'get', {
name: name
});
}
@@ -202,7 +202,7 @@ export async function DownloadConfig<T>(name: string, id?: number): Promise<
}
> {
try {
const resp = await QueryGetAPI<string>(VTSURU_API_URL + (id ? 'get-user-config' : 'get-config'), {
const resp = await QueryGetAPI<string>(USER_CONFIG_API_URL + (id ? 'user-get' : 'get'), {
name: name,
id: id
});
@@ -237,11 +237,12 @@ export async function DownloadConfig<T>(name: string, id?: number): Promise<
};
}
}
export async function UploadConfig(name: string, data: unknown) {
export async function UploadConfig(name: string, data: unknown, isPublic: boolean = false) {
try {
const resp = await QueryPostAPI(VTSURU_API_URL + 'set-config', {
const resp = await QueryPostAPI(USER_CONFIG_API_URL + 'set', {
name: name,
json: JSON.stringify(data)
json: JSON.stringify(data),
public: isPublic
});
if (resp.code == 200) {
console.log('已保存配置文件至服务器:' + name);
@@ -256,7 +257,7 @@ export async function UploadConfig(name: string, data: unknown) {
}
export async function GetConfigHash(name: string) {
try {
const resp = await QueryGetAPI<string>(VTSURU_API_URL + 'get-config-hash', {
const resp = await QueryGetAPI<string>(USER_CONFIG_API_URL + 'hash', {
name: name
});
if (resp.code == 200) {

View File

@@ -41,6 +41,7 @@ export interface UserInfo extends UserBasicInfo {
templateTypes: { [key: string]: string }
streamerInfo?: StreamerModel
allowCheckInRanking?: boolean // 是否允许查看签到排行
allowQuestionBoxUploadImage?: boolean // 是否允许问题箱上传图片
}
}
export interface EventFetcherStateModel {
@@ -119,8 +120,8 @@ export enum SaftyLevels {
}
export interface Setting_QuestionBox {
allowUnregistedUser: boolean
saftyLevel: SaftyLevels
allowImageUpload: boolean
}
export interface UserSetting {
sendEmail: Setting_SendEmail
@@ -371,8 +372,8 @@ export interface QAInfo {
id: number
sender: UserBasicInfo
target: UserBasicInfo
question: { message: string; image?: string }
answer?: { message: string; image?: string, createdAt: number }
question: { message: string; }
answer?: { message: string; createdAt: number }
isReaded?: boolean
isSenderRegisted: boolean
isPublic: boolean
@@ -380,6 +381,9 @@ export interface QAInfo {
sendAt: number
isAnonymous: boolean
answerImages?: UploadFileResponse[]
questionImages?: UploadFileResponse[]
tag?: string
reviewResult?: QAReviewInfo
}
@@ -683,7 +687,7 @@ export interface ResponsePointGoodModel {
count?: number
price: number
tags: string[]
cover?: string
cover?: UploadFileResponse
images: string[]
status: GoodsStatus
type: GoodsTypes
@@ -702,17 +706,13 @@ export interface ResponsePointGoodModel {
keySelectionMode?: KeySelectionMode
currentKeyIndex?: number
}
export interface ImageUploadModel {
existImages: string[]
newImagesBase64: string[]
}
export interface UploadPointGoodsModel {
id?: number
name: string
count?: number
price: number
tags: string[]
cover?: ImageUploadModel
cover?: UploadFileResponse
status: GoodsStatus
type: GoodsTypes
collectUrl?: string
@@ -844,3 +844,42 @@ export interface CheckInResult {
consecutiveDays: number
todayRank: number
}
/**
* 文件类型枚举
*/
export enum UserFileTypes {
Image = 0,
Audio = 1,
Video = 2,
Document = 3,
Other = 4
}
/**
* 文件存储位置枚举
*/
export enum UserFileLocation {
Local = 0
}
/**
* 文件上传响应接口
*/
export interface UploadFileResponse {
id: number;
path: string;
name: string;
hash: string;
}
/**
* 扩展的文件信息接口,用于文件上传组件
*/
export interface ExtendedUploadFileInfo {
id: string; // 文件唯一标识符
name: string; // 文件名称
status: 'uploading' | 'finished' | 'error' | 'removed'; // 上传状态
thumbnailUrl?: string; // 缩略图URL
file?: File; // 可选的文件对象
}

View File

@@ -7,13 +7,14 @@ import { cookie } from './account';
export async function QueryPostAPI<T>(
urlString: string,
body?: unknown,
headers?: [string, string][]
headers?: [string, string][],
contentType?: string
): Promise<APIRoot<T>> {
return await QueryPostAPIWithParams<T>(
urlString,
undefined,
body,
'application/json',
contentType || 'application/json',
headers
)
}
@@ -59,11 +60,15 @@ async function QueryPostAPIWithParamsInternal<T>(
})
if (cookie.value.cookie) h['Authorization'] = `Bearer ${cookie.value.cookie}`
h['Content-Type'] = contentType
// 当使用FormData时不手动设置Content-Type让浏览器自动添加boundary
if (!(body instanceof FormData)) {
h['Content-Type'] = contentType
}
return await QueryAPIInternal<T>(url, {
method: 'post',
headers: h,
body: typeof body === 'string' ? body : JSON.stringify(body)
body: body instanceof FormData ? body : typeof body === 'string' ? body : JSON.stringify(body)
})
}
async function QueryAPIInternal<T>(url: URL, init: RequestInit) {