particularly complete forum function, add point order export and user delete

This commit is contained in:
2024-03-22 01:47:55 +08:00
parent 87df8d5966
commit 932b83ddcd
52 changed files with 2806 additions and 132 deletions

View File

@@ -9,7 +9,6 @@ import { useRoute } from 'vue-router'
export const ACCOUNT = ref<AccountInfo>({} as AccountInfo)
export const isLoadingAccount = ref(true)
const route = useRoute()
const { message } = createDiscreteApi(['message'])
const cookie = useLocalStorage('JWT_Token', '')
@@ -42,6 +41,7 @@ export async function GetSelfAccount() {
}
export function UpdateAccountLoop() {
setInterval(() => {
const route = useRoute()
if (ACCOUNT.value && route?.name != 'question-display') {
// 防止在问题详情页刷新
GetSelfAccount()
@@ -67,18 +67,14 @@ export async function UpdateFunctionEnable(func: FunctionTypes) {
if (ACCOUNT.value) {
const oldValue = JSON.parse(JSON.stringify(ACCOUNT.value.settings.enableFunctions))
if (ACCOUNT.value?.settings.enableFunctions.includes(func)) {
ACCOUNT.value.settings.enableFunctions = ACCOUNT.value.settings.enableFunctions.filter(
(f) => f != func,
)
ACCOUNT.value.settings.enableFunctions = ACCOUNT.value.settings.enableFunctions.filter((f) => f != func)
} else {
ACCOUNT.value.settings.enableFunctions.push(func)
}
await SaveEnableFunctions(ACCOUNT.value?.settings.enableFunctions)
.then((data) => {
if (data.code == 200) {
message.success(
`${ACCOUNT.value?.settings.enableFunctions.includes(func) ? '启用' : '禁用'}`,
)
message.success(`${ACCOUNT.value?.settings.enableFunctions.includes(func) ? '启用' : '禁用'}`)
} else {
if (ACCOUNT.value) {
ACCOUNT.value.settings.enableFunctions = oldValue
@@ -89,9 +85,7 @@ export async function UpdateFunctionEnable(func: FunctionTypes) {
}
})
.catch((err) => {
message.error(
`${ACCOUNT.value?.settings.enableFunctions.includes(func) ? '启用' : '禁用'}失败: ${err}`,
)
message.error(`${ACCOUNT.value?.settings.enableFunctions.includes(func) ? '启用' : '禁用'}失败: ${err}`)
})
}
}

View File

@@ -3,12 +3,11 @@ export interface APIRoot<T> {
message: string
data: T
}
export interface PaginationResponse<T> {
export interface PaginationResponse<T> extends APIRoot<T> {
total: number
index: number
size: number
hasMore: boolean
datas: T
pn: number
ps: number
more: boolean
}
export enum IndexTypes {
Default,
@@ -661,7 +660,9 @@ export interface ResponsePointOrder2OwnerModel {
customer: BiliAuthModel
address?: AddressInfo
goodsId: number
count: number
createAt: number
updateAt: number
status: PointOrderStatus
trackingNumber?: string
@@ -692,6 +693,7 @@ export interface ResponsePointHisrotyModel {
type: EventDataTypes
from: PointFrom
createAt: number
count: number
extra?: any
}

122
src/api/models/forum.ts Normal file
View File

@@ -0,0 +1,122 @@
import { UserBasicInfo } from '../api-models'
export enum ForumTopicSortTypes {
Time,
Comment,
Like,
}
export enum ForumCommentSortTypes {
Time,
Like,
}
export enum ForumUserLevels {
Guest,
User,
Member,
AuthedMember,
Admin,
}
export interface ForumSetting {
allowedViewerLevel: ForumUserLevels // Assuming the default value is handled elsewhere
allowPost: boolean // Assuming the default value is handled elsewhere
allowedPostLevel: ForumUserLevels // Assuming the default value is handled elsewhere
requireApply: boolean // Assuming the default value is handled elsewhere
requireAuthedToJoin: boolean // Assuming the default value is handled elsewhere
sendTopicDelay: number // Assuming the default value is handled elsewhere
}
export interface ForumUserModel extends UserBasicInfo {
isAdmin: boolean
}
export type ForumModel = {
id: number
name: string
owner: ForumUserModel
description: string
topicCount: number
settings: ForumSetting
admins: ForumUserModel[]
members: ForumUserModel[]
applying: ForumUserModel[]
blackList: ForumUserModel[]
level: ForumUserLevels
isApplied: boolean
sections: ForumSectionModel[]
createAt: number
isAdmin: boolean
}
export type ForumSectionModel = {
id: number
name: string
description: string
createAt: number
}
export enum ForumTopicTypes {
Default,
Vote,
}
export type ForumTopicSetting = {
canReply?: boolean
}
export interface ForumTopicBaseModel {
id: number // Primary and identity fields in C# typically correspond to required fields in TS
user: UserBasicInfo
section: ForumSectionModel
title: string
content: string
latestRepliedBy?: UserBasicInfo
repliedAt?: number
likeCount: number // Assuming the default value is handled elsewhere
commentCount: number // Assuming the default value is handled elsewhere
viewCount: number // Assuming the default value is handled elsewhere
sampleLikedBy: number[]
createAt: Date // DateTime in C# translates to Date in TS
editAt?: Date | null // Nullable DateTime in C# is optional or null in TS
isLiked: boolean
isLocked?: boolean // Assuming the default value is handled elsewhere
isPinned?: boolean // Assuming the default value is handled elsewhere
isHighlighted?: boolean // Assuming the default value is handled elsewhere
}
export interface ForumTopicModel extends ForumTopicBaseModel {
isLocked?: boolean // Assuming the default value is handled elsewhere
isDeleted?: boolean // Assuming the default value is handled elsewhere
isHidden?: boolean // Assuming the default value is handled elsewhere
type?: ForumTopicTypes // Assuming the default value is handled elsewhere
extraTypeId?: number | null // Nullable int in C# is optional or null in TS
likedBy?: number[] // Assuming the default value is handled elsewhere
}
export interface ForumCommentModel {
id: number
user: UserBasicInfo
content: string
replies: ForumReplyModel[]
sendAt: Date
likeCount: number
isLiked: boolean
}
export interface ForumReplyModel {
id: number
user: UserBasicInfo
content: string
replyTo?: number
sendAt: Date
}
export interface ForumPostTopicModel {
section?: number
title: string
content: string
owner: number
type?: ForumTopicTypes
}

View File

@@ -19,23 +19,34 @@ export async function QueryPostAPIWithParams<T>(
contentType?: string,
headers?: [string, string][],
): Promise<APIRoot<T>> {
return await QueryPostAPIWithParamsInternal<APIRoot<T>>(urlString, params, body, contentType, headers)
}
async function QueryPostAPIWithParamsInternal<T>(
urlString: string,
params?: any,
body?: any,
contentType: string = 'application/json',
headers: [string, string][] = [],
) {
const url = new URL(urlString)
url.search = getParams(params)
headers ??= []
if (cookie.value) headers?.push(['Authorization', `Bearer ${cookie.value}`])
if (contentType) headers?.push(['Content-Type', contentType])
return await QueryAPIInternal<T>(url, {
method: 'post',
headers: headers,
body: typeof body === 'string' ? body : JSON.stringify(body),
})
}
async function QueryAPIInternal<T>(url: URL, init: RequestInit) {
try {
const data = await fetch(url, {
method: 'post',
headers: headers,
body: typeof body === 'string' ? body : JSON.stringify(body),
})
const result = (await data.json()) as APIRoot<T>
const data = await fetch(url, init)
const result = (await data.json()) as T
return result
} catch (e) {
console.error(`[POST] API调用失败: ${e}`)
console.error(`[${init.method}] API调用失败: ${e}`)
if (!apiFail.value) {
apiFail.value = true
console.log('默认API异常, 切换至故障转移节点')
@@ -48,30 +59,34 @@ export async function QueryGetAPI<T>(
params?: any,
headers?: [string, string][],
): Promise<APIRoot<T>> {
return await QueryGetAPIInternal<APIRoot<T>>(urlString, params, headers)
}
async function QueryGetAPIInternal<T>(urlString: string, params?: any, headers?: [string, string][]) {
const url = new URL(urlString)
url.search = getParams(params)
if (cookie.value) {
headers ??= []
if (cookie.value) headers?.push(['Authorization', `Bearer ${cookie.value}`])
}
try {
const data = await fetch(url.toString(), {
method: 'get',
headers: headers,
})
const result = (await data.json()) as APIRoot<T>
return result
} catch (e) {
console.error(`[GET] API调用失败: ${e}`)
if (!apiFail.value) {
apiFail.value = true
console.log('默认API异常, 切换至故障转移节点')
}
throw e
}
return await QueryAPIInternal<T>(url, {
method: 'get',
headers: headers,
})
}
function getParams(params?: [string, string][]) {
function getParams(params: any) {
const urlParams = new URLSearchParams(window.location.search)
if (params) {
const keys = Object.keys(params)
if (keys.length > 0) {
keys.forEach((k) => {
if (params[k] == undefined) {
delete params[k]
}
})
}
}
const resultParams = new URLSearchParams(params)
if (urlParams.has('as')) {
resultParams.set('as', urlParams.get('as') || '')
@@ -81,12 +96,12 @@ function getParams(params?: [string, string][]) {
}
return resultParams.toString()
}
export async function QueryPostPaginationAPI<T>(url: string, body?: unknown): Promise<APIRoot<PaginationResponse<T>>> {
return await QueryPostAPI<PaginationResponse<T>>(url, body)
export async function QueryPostPaginationAPI<T>(url: string, body?: unknown): Promise<PaginationResponse<T>> {
return await QueryPostAPIWithParamsInternal<PaginationResponse<T>>(url, undefined, body)
}
export async function QueryGetPaginationAPI<T>(
urlString: string,
params?: unknown,
): Promise<APIRoot<PaginationResponse<T>>> {
return await QueryGetAPI<PaginationResponse<T>>(urlString, params)
export async function QueryGetPaginationAPI<T>(urlString: string, params?: unknown): Promise<PaginationResponse<T>> {
return await QueryGetAPIInternal<PaginationResponse<T>>(urlString, params)
}
export function GetHeaders(): [string, string][] {
return [['Authorization', `Bearer ${cookie.value}`]]
}

View File

@@ -1,9 +1,8 @@
import { QueryGetAPI } from '@/api/query'
import { BASE_API, USER_API_URL, apiFail } from '@/data/constants'
import { APIRoot, UserInfo } from './api-models'
import { USER_API_URL, apiFail } from '@/data/constants'
import { ref } from 'vue'
import { useRouteParams } from '@vueuse/router'
import { useRoute } from 'vue-router'
import { APIRoot, UserInfo } from './api-models'
export const USERS = ref<{ [id: string]: UserInfo }>({})