🎨chore: 使用 oxlint, oxfmt&格式化代码
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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'],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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'],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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}`
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user