mirror of
https://github.com/Megghy/vtsuru.live.git
synced 2025-12-06 18:36:55 +08:00
- Added guard member model and statistics interface. - Implemented loading functionality for guard list and statistics. - Introduced a data table to display current guard members with pagination. - Enhanced error handling and loading states for guard data. - Updated UI components to include refresh button and statistics display. feat: Update PointManage and PointGoodsView for Improved User Experience - Added management flag to PointGoodsItem for better handling in PointManage. - Enhanced PointGoodsView with improved tooltip logic for purchase status. - Implemented detailed purchase history alerts and restrictions based on user actions. - Improved visual feedback for purchased and non-purchasable items. docs: Add comprehensive API integration documentation - Documented API modules, data models, and request types. - Included details on live platform integration and data storage mechanisms. docs: Establish development workflow guidelines - Outlined project configuration, environment setup, and code style practices. - Provided deployment process using Docker. docs: Create detailed documentation for the live request system - Described the functionality and data flow of the song request system. - Included main files and features related to the song request functionality. docs: Define project structure and UI components - Documented the overall project structure and key directories. - Listed main UI components and their usage within the project. chore: Analyze and document improvements in AnalyzeView - Detailed enhancements made to the AnalyzeView for better user experience. - Included visual comparisons and technical highlights of the optimizations.
333 lines
9.1 KiB
TypeScript
333 lines
9.1 KiB
TypeScript
import type { AccountInfo, APIRoot, FunctionTypes } from './api-models'
|
|
import { StorageSerializers } from '@vueuse/core'
|
|
import { isSameDay } from 'date-fns'
|
|
import { createDiscreteApi } from 'naive-ui'
|
|
import { ref } from 'vue'
|
|
import { QueryGetAPI, QueryPostAPI, QueryPostAPIWithParams } from '@/api/query'
|
|
import { ACCOUNT_API_URL, USER_CONFIG_API_URL } from '@/data/constants'
|
|
|
|
export const ACCOUNT = ref<AccountInfo>({} as AccountInfo)
|
|
export const isLoadingAccount = ref(true)
|
|
export const isLoggedIn = computed<boolean>(() => {
|
|
return ACCOUNT.value.id > 0
|
|
})
|
|
|
|
const { message } = createDiscreteApi(['message'])
|
|
export const cookie = useLocalStorage<{ cookie: string, refreshDate: number }>('Cookie', { cookie: '', refreshDate: 0 }, { serializer: StorageSerializers.object })
|
|
|
|
export async function GetSelfAccount(token?: string) {
|
|
if (cookie.value.cookie || token) {
|
|
const result = await Self(token)
|
|
if (result.code == 200) {
|
|
if (!ACCOUNT.value.id) {
|
|
ACCOUNT.value = result.data
|
|
} else {
|
|
result.data.settings = ACCOUNT.value.settings
|
|
ACCOUNT.value = result.data
|
|
}
|
|
isLoadingAccount.value = false
|
|
// console.log('[vtsuru] 已获取账户信息')
|
|
if (!cookie.value.cookie || !isSameDay(new Date(), cookie.value.refreshDate)) {
|
|
refreshCookie(token)
|
|
}
|
|
return result.data
|
|
} else if (result.code == 401) {
|
|
localStorage.removeItem('JWT_Token')
|
|
if (!token) {
|
|
cookie.value = undefined
|
|
console.warn('[vtsuru] Cookie 已失效, 需要重新登陆')
|
|
message.error('Cookie 已失效, 需要重新登陆')
|
|
setTimeout(() => {
|
|
location.reload()
|
|
}, 1500)
|
|
}
|
|
} else {
|
|
console.warn(`[vtsuru] ${result.message}`)
|
|
message.error(result.message)
|
|
}
|
|
}
|
|
isLoadingAccount.value = false
|
|
}
|
|
|
|
export function UpdateAccountLoop() {
|
|
setInterval(() => {
|
|
const urlParams = new URLSearchParams(window.location.search)
|
|
if (urlParams.get('as')) {
|
|
return
|
|
}
|
|
if (ACCOUNT.value && window.$route?.name != 'question-display') {
|
|
// 防止在问题详情页刷新
|
|
GetSelfAccount()
|
|
}
|
|
}, 60 * 1000)
|
|
}
|
|
function refreshCookie(token?: string) {
|
|
QueryPostAPIWithParams<string>(`${ACCOUNT_API_URL}refresh-token`, { token }).then((data) => {
|
|
if (data.code == 200) {
|
|
cookie.value = {
|
|
cookie: data.data,
|
|
refreshDate: new Date().getTime(),
|
|
}
|
|
console.log('[vtsuru] 已刷新Cookie')
|
|
}
|
|
})
|
|
}
|
|
export async function SaveAccountSettings() {
|
|
return QueryPostAPI(
|
|
`${ACCOUNT_API_URL}update-setting`,
|
|
ACCOUNT.value?.settings,
|
|
)
|
|
}
|
|
export async function SaveEnableFunctions(functions: FunctionTypes[]) {
|
|
return QueryPostAPI(
|
|
`${ACCOUNT_API_URL}update-enable-functions`,
|
|
functions,
|
|
)
|
|
}
|
|
export async function SaveSetting(
|
|
name:
|
|
| 'Queue'
|
|
| 'Point'
|
|
| 'Index'
|
|
| 'General'
|
|
| 'QuestionDisplay'
|
|
| 'SongRequest'
|
|
| 'QuestionBox'
|
|
| 'SendEmail',
|
|
setting: unknown,
|
|
) {
|
|
const result = await QueryPostAPIWithParams(
|
|
`${ACCOUNT_API_URL}update-single-setting`,
|
|
{
|
|
name,
|
|
},
|
|
setting,
|
|
)
|
|
return result.message
|
|
}
|
|
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)
|
|
} 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) ? '启用' : '禁用'}`,
|
|
)
|
|
} else {
|
|
if (ACCOUNT.value) {
|
|
ACCOUNT.value.settings.enableFunctions = oldValue
|
|
}
|
|
message.error(
|
|
`${ACCOUNT.value?.settings.enableFunctions.includes(func) ? '启用' : '禁用'}失败: ${data.message}`,
|
|
)
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
message.error(
|
|
`${ACCOUNT.value?.settings.enableFunctions.includes(func) ? '启用' : '禁用'}失败: ${err}`,
|
|
)
|
|
})
|
|
}
|
|
}
|
|
export function useAccount() {
|
|
return ACCOUNT
|
|
}
|
|
|
|
export async function Register(
|
|
name: string,
|
|
email: string,
|
|
password: string,
|
|
token: string,
|
|
): Promise<APIRoot<string>> {
|
|
return QueryPostAPI<string>(`${ACCOUNT_API_URL}register`, {
|
|
name,
|
|
email,
|
|
password,
|
|
token,
|
|
})
|
|
}
|
|
|
|
export async function Login(
|
|
nameOrEmail: string,
|
|
password: string,
|
|
): Promise<APIRoot<string>> {
|
|
return QueryPostAPI<string>(`${ACCOUNT_API_URL}login`, {
|
|
nameOrEmail,
|
|
password,
|
|
})
|
|
}
|
|
export async function Self(token?: string): Promise<APIRoot<AccountInfo>> {
|
|
return QueryPostAPIWithParams<AccountInfo>(`${ACCOUNT_API_URL}self`, token ? { token } : undefined)
|
|
}
|
|
export async function AddBiliBlackList(
|
|
id: number,
|
|
name: string,
|
|
): Promise<APIRoot<unknown>> {
|
|
return QueryGetAPI<AccountInfo>(`${ACCOUNT_API_URL}black-list/add-bili`, {
|
|
id,
|
|
name,
|
|
})
|
|
}
|
|
export async function DelBiliBlackList(id: number): Promise<APIRoot<unknown>> {
|
|
return QueryGetAPI<AccountInfo>(`${ACCOUNT_API_URL}black-list/del-bili`, {
|
|
id,
|
|
})
|
|
}
|
|
export async function DelBlackList(id: number): Promise<APIRoot<unknown>> {
|
|
return QueryGetAPI<AccountInfo>(`${ACCOUNT_API_URL}black-list/del`, {
|
|
id,
|
|
})
|
|
}
|
|
export async function downloadConfigDirect(name: string) {
|
|
return QueryGetAPI<string>(`${USER_CONFIG_API_URL}get`, {
|
|
name,
|
|
})
|
|
}
|
|
export type ConfigStatus = 'success' | 'error' | 'notfound'
|
|
export async function DownloadConfig<T>(name: string, id?: number): Promise<
|
|
| {
|
|
msg: undefined
|
|
status: ConfigStatus
|
|
data: T
|
|
}
|
|
| {
|
|
msg: string
|
|
status: ConfigStatus
|
|
data: undefined
|
|
}
|
|
> {
|
|
try {
|
|
const resp = await QueryGetAPI<string>(USER_CONFIG_API_URL + (id ? 'get-user' : 'get'), {
|
|
name,
|
|
id,
|
|
})
|
|
if (resp.code == 200) {
|
|
console.log(`已获取配置文件: ${name}`)
|
|
return {
|
|
msg: undefined,
|
|
status: 'success',
|
|
data: JSON.parse(resp.data) as T,
|
|
}
|
|
} else if (resp.code == 404) {
|
|
console.error(`未找到名为 ${name} 的配置文件`)
|
|
return {
|
|
msg: `未找到名为 ${name} 的配置文件, 需要先上传`,
|
|
status: 'notfound',
|
|
data: undefined,
|
|
}
|
|
} else {
|
|
console.error(`无法获取配置文件 [${name}]: ${resp.message}`)
|
|
return {
|
|
msg: `无法获取配置文件 [${name}]: ${resp.message}`,
|
|
status: 'error',
|
|
data: undefined,
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error(`无法获取配置文件 [${name}]: ${err}`)
|
|
return {
|
|
msg: `无法获取配置文件 [${name}]: ${err}`,
|
|
status: 'error',
|
|
data: undefined,
|
|
}
|
|
}
|
|
}
|
|
export async function UploadConfig(name: string, data: unknown, isPublic: boolean = false) {
|
|
try {
|
|
const resp = await QueryPostAPI(`${USER_CONFIG_API_URL}set`, {
|
|
name,
|
|
json: JSON.stringify(data),
|
|
public: isPublic,
|
|
})
|
|
if (resp.code == 200) {
|
|
console.log(`已保存配置文件至服务器:${name}`)
|
|
return true
|
|
} else {
|
|
console.error(`保存失败: ${resp.message}`)
|
|
}
|
|
} catch (err) {
|
|
console.error(`保存配置文件失败: ${err}`)
|
|
}
|
|
return false
|
|
}
|
|
export async function GetConfigHash(name: string) {
|
|
try {
|
|
const resp = await QueryGetAPI<string>(`${USER_CONFIG_API_URL}hash`, {
|
|
name,
|
|
})
|
|
if (resp.code == 200) {
|
|
return resp.data
|
|
} else {
|
|
console.error(`获取配置文件hash失败: ${resp.message}`)
|
|
return null
|
|
}
|
|
} catch (err) {
|
|
console.error(`获取配置文件hash失败: ${err}`)
|
|
return null
|
|
}
|
|
}
|
|
export async function EnableFunction(func: FunctionTypes) {
|
|
if (ACCOUNT.value) {
|
|
if (ACCOUNT.value.settings.enableFunctions.includes(func)) {
|
|
return true
|
|
} else {
|
|
ACCOUNT.value.settings.enableFunctions.push(func)
|
|
if (await updateFunctionEnable()) {
|
|
return true
|
|
} else {
|
|
ACCOUNT.value.settings.enableFunctions.splice(
|
|
ACCOUNT.value.settings.enableFunctions.indexOf(func),
|
|
1,
|
|
)
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
export async function DisableFunction(func: FunctionTypes) {
|
|
if (ACCOUNT.value) {
|
|
if (!ACCOUNT.value.settings.enableFunctions.includes(func)) {
|
|
return true
|
|
} else {
|
|
ACCOUNT.value.settings.enableFunctions.splice(
|
|
ACCOUNT.value.settings.enableFunctions.indexOf(func),
|
|
1,
|
|
)
|
|
if (await updateFunctionEnable()) {
|
|
return true
|
|
} else {
|
|
ACCOUNT.value.settings.enableFunctions.push(func)
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
async function updateFunctionEnable() {
|
|
if (ACCOUNT.value) {
|
|
try {
|
|
const data = await SaveEnableFunctions(
|
|
ACCOUNT.value.settings.enableFunctions,
|
|
)
|
|
if (data.code == 200) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
} catch (err) {
|
|
console.log(err)
|
|
return false
|
|
}
|
|
}
|
|
}
|