🎨chore: 使用 oxlint, oxfmt&格式化代码

This commit is contained in:
2026-02-08 21:16:25 +08:00
parent 9d35c6a9d8
commit 3a801ba016
78 changed files with 3367 additions and 1468 deletions

View File

@@ -1,4 +1,6 @@
export const fetchCourseSubtitleUrl = async (course: resp.gen.CourseGenItem) => {
export const fetchCourseSubtitleUrl = async (
course: resp.gen.CourseGenItem
) => {
const loginState = useLoginState()
try {
@@ -25,4 +27,4 @@ export const fetchCourseSubtitleUrl = async (course: resp.gen.CourseGenItem) =>
} catch (err) {
return course.subtitle_url
}
}
}

View File

@@ -8,13 +8,13 @@ export const useBlobUrlFromB64 = (dataurl: string): string => {
if (mimeMatches === null) {
throw new Error('dataurl is not a valid base64 image')
}
const mime = mimeMatches[1] //image/png
const mime = mimeMatches[1] //image/png
const b64data = atob(arr[1])
let length = b64data.length
const u8arr = new Uint8Array(length)
while (length--) {
u8arr[length] = b64data.charCodeAt(length)
}
const blob = new Blob([u8arr], {type: mime})
const blob = new Blob([u8arr], { type: mime })
return URL.createObjectURL(blob)
}
}

View File

@@ -1,22 +1,22 @@
export const useDefer = (maxFrame: number = 1000) => {
const frame = ref(1)
let rafId: number
const frame = ref(1)
let rafId: number
function updateFrame() {
rafId = requestAnimationFrame(() => {
frame.value++
if (frame.value > maxFrame) return
updateFrame()
})
}
function updateFrame() {
rafId = requestAnimationFrame(() => {
frame.value++
if (frame.value > maxFrame) return
updateFrame()
})
}
onMounted(() => {
updateFrame()
})
onUnmounted(() => {
cancelAnimationFrame(rafId)
})
return (n: number) => {
return frame.value >= n
}
}
onMounted(() => {
updateFrame()
})
onUnmounted(() => {
cancelAnimationFrame(rafId)
})
return (n: number) => {
return frame.value >= n
}
}

View File

@@ -1,6 +1,9 @@
import { EventEmitter } from 'events'
export const useDownload = (url: string, filename: string): {
export const useDownload = (
url: string,
filename: string
): {
download: () => void
progressEmitter: EventEmitter
} => {
@@ -18,7 +21,9 @@ export const useDownload = (url: string, filename: string): {
}
xhr.onload = function () {
if (this.status === 200) {
const blob = new Blob([this.response], { type: 'application/octet-stream' })
const blob = new Blob([this.response], {
type: 'application/octet-stream',
})
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url

View File

@@ -1,21 +1,21 @@
import {useFormPayload} from "~/composables/useFormPayload";
import { useFormPayload } from '~/composables/useFormPayload'
export const useFetchWrapped = <TypeReq, TypeResp>(
action: string,
payload?: TypeReq,
options?: {
method?: 'GET' | 'POST'
headers?: Record<string, string>
baseURL?: string
}
action: string,
payload?: TypeReq,
options?: {
method?: 'GET' | 'POST'
headers?: Record<string, string>
baseURL?: string
}
) => {
const runtimeConfig = useRuntimeConfig()
return $fetch<TypeResp>('/', {
baseURL: options?.baseURL || runtimeConfig.public.API_BASE,
method: options?.method || 'POST',
query: {
s: action
},
body: useFormPayload(payload as object)
})
}
const runtimeConfig = useRuntimeConfig()
return $fetch<TypeResp>('/', {
baseURL: options?.baseURL || runtimeConfig.public.API_BASE,
method: options?.method || 'POST',
query: {
s: action,
},
body: useFormPayload(payload as object),
})
}

View File

@@ -1,10 +1,10 @@
export const useFormPayload = (payload: object) => {
const formData = new FormData()
for (const dataKey in payload) {
if (payload.hasOwnProperty(dataKey)) {
// @ts-ignore
formData.append(dataKey, payload[dataKey])
}
const formData = new FormData()
for (const dataKey in payload) {
if (payload.hasOwnProperty(dataKey)) {
// @ts-ignore
formData.append(dataKey, payload[dataKey])
}
return formData
}
return formData
}

View File

@@ -1,5 +1,5 @@
import type {ResultBlockMeta} from '~/components/aigc/drawing';
import type {ChatSession} from "~/typings/llm";
import type { ResultBlockMeta } from '~/components/aigc/drawing'
import type { ChatSession } from '~/typings/llm'
export interface HistoryItem {
fid: string
@@ -9,20 +9,24 @@ export interface HistoryItem {
images?: string[]
}
export const useHistory = defineStore('xsh_assistant_aigc_history', () => {
const text2img = ref<HistoryItem[]>([])
const chatSessions = ref<ChatSession[]>([])
const setChatSessions = (sessions: ChatSession[]) => {
chatSessions.value = sessions
}
export const useHistory = defineStore(
'xsh_assistant_aigc_history',
() => {
const text2img = ref<HistoryItem[]>([])
const chatSessions = ref<ChatSession[]>([])
const setChatSessions = (sessions: ChatSession[]) => {
chatSessions.value = sessions
}
return {
text2img,
chatSessions,
setChatSessions,
return {
text2img,
chatSessions,
setChatSessions,
}
},
{
persist: {
storage: persistedState.localStorage,
},
}
}, {
persist: {
storage: persistedState.localStorage
}
})
)

View File

@@ -1,31 +1,50 @@
import {type ChatMessage, llmModels, type LLMSpark, type MessageRole, type ModelTag} from "~/typings/llm";
import {useFetchWrapped} from "~/composables/useFetchWrapped";
import {
type ChatMessage,
llmModels,
type LLMSpark,
type MessageRole,
type ModelTag,
} from '~/typings/llm'
import { useFetchWrapped } from '~/composables/useFetchWrapped'
export interface LLMRequestOptions {
modelTag: ModelTag
}
export const useLLM = (context: ChatMessage[], options: LLMRequestOptions): Promise<string> => new Promise((resolve, reject) => {
const {modelTag} = options
const model = llmModels.find(model => model.tag === modelTag)
if (!model) return reject('model specified is not available')
const loginState = useLoginState()
useFetchWrapped<LLMSpark.request | AuthedRequest, BaseResponse<LLMSpark.response>>(
model.endpoint,
{
export const useLLM = (
context: ChatMessage[],
options: LLMRequestOptions
): Promise<string> =>
new Promise((resolve, reject) => {
const { modelTag } = options
const model = llmModels.find((model) => model.tag === modelTag)
if (!model) return reject('model specified is not available')
const loginState = useLoginState()
useFetchWrapped<
LLMSpark.request | AuthedRequest,
BaseResponse<LLMSpark.response>
>(model.endpoint, {
token: loginState.token || '',
user_id: loginState.user.id,
prompt: JSON.stringify(context.filter(c => c.content && !c.interrupted).map(c => ({
role: c.role,
content: c.content
})))
}
).then(res => {
if (res.ret !== 200) return reject(res.msg || 'unknown error')
if (res.data.request_msg) return resolve(res.data.request_msg)
if (res.data.request_fail) return reject(res.data.request_fail?.header?.message || 'unknown error')
return reject('unknown error')
}).catch(err => {
reject(err)
prompt: JSON.stringify(
context
.filter((c) => c.content && !c.interrupted)
.map((c) => ({
role: c.role,
content: c.content,
}))
),
})
.then((res) => {
if (res.ret !== 200) return reject(res.msg || 'unknown error')
if (res.data.request_msg) return resolve(res.data.request_msg)
if (res.data.request_fail)
return reject(
res.data.request_fail?.header?.message || 'unknown error'
)
return reject('unknown error')
})
.catch((err) => {
reject(err)
})
})
})

View File

@@ -1,64 +1,79 @@
import {useFetchWrapped} from "~/composables/useFetchWrapped";
import { useFetchWrapped } from '~/composables/useFetchWrapped'
export const useLoginState = defineStore('loginState', () => {
export const useLoginState = defineStore(
'loginState',
() => {
const is_logged_in = ref(false)
const token = ref<string | null>(null)
const user = ref<UserSchema>({} as UserSchema)
const checkSession = () => {
return new Promise<boolean>(resolve => {
if (!token.value) return resolve(false)
useFetchWrapped<AuthedRequest, BaseResponse<resp.user.CheckSession>>('App.User_User.CheckSession', {
token: token.value,
user_id: user.value.id
}).then(res => {
if (res.ret !== 200) {
resolve(false)
return
}
resolve(res.data.is_login)
// update global state
is_logged_in.value = res.data.is_login
}).catch(err => resolve(false))
})
return new Promise<boolean>((resolve) => {
if (!token.value) return resolve(false)
useFetchWrapped<AuthedRequest, BaseResponse<resp.user.CheckSession>>(
'App.User_User.CheckSession',
{
token: token.value,
user_id: user.value.id,
}
)
.then((res) => {
if (res.ret !== 200) {
resolve(false)
return
}
resolve(res.data.is_login)
// update global state
is_logged_in.value = res.data.is_login
})
.catch((err) => resolve(false))
})
}
const updateProfile = () => {
return new Promise<UserSchema>((resolve, reject) => {
if (!token.value) return reject('token is empty')
useFetchWrapped<AuthedRequest, BaseResponse<resp.user.Profile>>('App.User_User.Profile', {
token: token.value,
user_id: user.value.id
}).then(res => {
if (res.ret !== 200) {
reject(res.msg || '未知错误')
return
}
user.value = res.data.profile
resolve(res.data.profile)
}).catch(err => reject(err || '未知错误'))
})
return new Promise<UserSchema>((resolve, reject) => {
if (!token.value) return reject('token is empty')
useFetchWrapped<AuthedRequest, BaseResponse<resp.user.Profile>>(
'App.User_User.Profile',
{
token: token.value,
user_id: user.value.id,
}
)
.then((res) => {
if (res.ret !== 200) {
reject(res.msg || '未知错误')
return
}
user.value = res.data.profile
resolve(res.data.profile)
})
.catch((err) => reject(err || '未知错误'))
})
}
const logout = () => new Promise<void>(resolve => {
const logout = () =>
new Promise<void>((resolve) => {
token.value = null
user.value = {} as UserSchema
is_logged_in.value = false
resolve()
})
})
return {
is_logged_in,
token,
user,
checkSession,
updateProfile,
logout
is_logged_in,
token,
user,
checkSession,
updateProfile,
logout,
}
}, {
},
{
persist: {
key: 'xsh_assistant_persisted_state',
storage: persistedState.localStorage,
paths: ['is_logged_in', 'token', 'user']
}
})
key: 'xsh_assistant_persisted_state',
storage: persistedState.localStorage,
paths: ['is_logged_in', 'token', 'user'],
},
}
)

View File

@@ -1,32 +1,39 @@
export const useTourState = defineStore('tour_state', () => {
const tourState = ref<{ [key: string]: boolean }>({})
export const useTourState = defineStore(
'tour_state',
() => {
const tourState = ref<{ [key: string]: boolean }>({})
const isTourDone = (tourId: string) => tourState.value[tourId] || false
const setTourDone = (tourId: string) => {
tourState.value = {
...tourState.value,
[tourId]: true,
const isTourDone = (tourId: string) => tourState.value[tourId] || false
const setTourDone = (tourId: string) => {
tourState.value = {
...tourState.value,
[tourId]: true,
}
}
const autoDriveTour = (
tourId: string,
driver: ReturnType<typeof useDriver>
) => {
if (isTourDone(tourId)) return
driver.setConfig({
...driver.getConfig(),
onDestroyed: () => setTourDone(tourId),
})
driver.drive()
}
}
const autoDriveTour = (tourId: string, driver: ReturnType<typeof useDriver>) => {
if (isTourDone(tourId)) return
driver.setConfig({
...driver.getConfig(),
onDestroyed: () => setTourDone(tourId),
})
driver.drive()
}
return {
tourState,
isTourDone,
setTourDone,
autoDriveTour,
}
}, {
persist: {
key: 'xsh_assistant_tour_state',
storage: persistedState.localStorage,
paths: ['tourState'],
return {
tourState,
isTourDone,
setTourDone,
autoDriveTour,
}
},
})
{
persist: {
key: 'xsh_assistant_tour_state',
storage: persistedState.localStorage,
paths: ['tourState'],
},
}
)

View File

@@ -51,7 +51,7 @@ const calculateScaledDimensions = (
return { width: finalWidth, height: targetHeight }
}
export type CompositingPhase =
export type CompositingPhase =
| 'loading'
| 'analyzing'
| 'preparing'
@@ -90,9 +90,8 @@ export const useVideoBackgroundCompositing = async (
const backgroundData = await fetchFile(backgroundImage)
progressCallback?.({ progress: 15, phase: 'analyzing' })
const { width: bgWidth, height: bgHeight } = await getImageDimensions(
backgroundData
)
const { width: bgWidth, height: bgHeight } =
await getImageDimensions(backgroundData)
console.log(
`[Compositing] Background image dimensions: ${bgWidth}x${bgHeight}`
)

View File

@@ -3,28 +3,28 @@ import {
EmbedSubtitlesClip,
MP4Clip,
OffscreenSprite,
} from "@webav/av-cliper";
} from '@webav/av-cliper'
export interface SubtitleEmbeddingOptions {
color?: string;
textBgColor?: string | null;
type?: "srt";
fontFamily?: string;
fontSize?: number;
letterSpacing?: string | null;
bottomOffset?: number;
strokeStyle?: string;
lineWidth?: number | null;
lineCap?: CanvasLineCap | null;
lineJoin?: CanvasLineJoin | null;
color?: string
textBgColor?: string | null
type?: 'srt'
fontFamily?: string
fontSize?: number
letterSpacing?: string | null
bottomOffset?: number
strokeStyle?: string
lineWidth?: number | null
lineCap?: CanvasLineCap | null
lineJoin?: CanvasLineJoin | null
textShadow?: {
offsetX: number;
offsetY: number;
blur: number;
color: string;
};
videoWidth?: number;
videoHeight?: number;
offsetX: number
offsetY: number
blur: number
color: string
}
videoWidth?: number
videoHeight?: number
}
export const useVideoSubtitleEmbedding = async (
@@ -36,18 +36,18 @@ export const useVideoSubtitleEmbedding = async (
options = {
videoWidth: 1920,
videoHeight: 1080,
};
}
}
console.log(`video clip: ${videoUrl}`)
const videoClip = new MP4Clip((await fetch(videoUrl)).body!)
const videoSprite = new OffscreenSprite(videoClip)
videoSprite.time = { duration: videoClip.meta.duration, offset: 0 }
await videoSprite.ready;
await videoSprite.ready
const srtSprite = new OffscreenSprite(
new EmbedSubtitlesClip(await(await fetch(srtUrl)).text(), {
new EmbedSubtitlesClip(await (await fetch(srtUrl)).text(), {
videoWidth: 1920,
videoHeight: 1080,
fontSize: 36,
@@ -62,20 +62,20 @@ export const useVideoSubtitleEmbedding = async (
...options,
})
)
await srtSprite.ready;
await srtSprite.ready
srtSprite.time = { duration: videoClip.meta.duration, offset: 0 }
const combinator = new Combinator({
width: 1920,
height: 1080,
});
})
await combinator.addSprite(videoSprite);
await combinator.addSprite(srtSprite);
await combinator.addSprite(videoSprite)
await combinator.addSprite(srtSprite)
const srcBlob = URL.createObjectURL(
await new Response(combinator.output()).blob()
);
)
return srcBlob;
};
return srcBlob
}