feat: 新版webui

This commit is contained in:
bietiaop
2025-01-24 21:13:44 +08:00
parent afc9c7ed8d
commit 31c0c1f4bc
201 changed files with 18454 additions and 3422 deletions

View File

@@ -0,0 +1,124 @@
// Dialog Context
import React from 'react'
import type { ModalProps } from '@/components/modal'
import Modal from '@/components/modal'
export interface AlertProps {
title?: React.ReactNode
content: React.ReactNode
size?: ModalProps['size']
dismissible?: boolean
onConfirm?: () => void
}
export interface ConfirmProps {
title?: React.ReactNode
content: React.ReactNode
size?: ModalProps['size']
dismissible?: boolean
onConfirm?: () => void
onCancel?: () => void
}
export interface ModalItem extends ModalProps {
id: number
}
export interface DialogContextProps {
alert: (config: AlertProps) => void
confirm: (config: ConfirmProps) => void
}
export interface DialogProviderProps {
children: React.ReactNode
}
export const DialogContext = React.createContext<DialogContextProps>({
alert: () => {},
confirm: () => {}
})
const DialogProvider: React.FC<DialogProviderProps> = ({ children }) => {
const [dialogs, setDialogs] = React.useState<ModalItem[]>([])
const alert = (config: AlertProps) => {
const { title, content, dismissible, onConfirm, size = 'md' } = config
setDialogs((before) => {
const id = before[before.length - 1]?.id + 1 || 0
return [
...before,
{
id,
content,
size,
title,
backdrop: 'blur',
showCancel: false,
dismissible: dismissible,
onConfirm: () => {
onConfirm?.()
setTimeout(() => {
setDialogs((before) => before.filter((item) => item.id !== id))
}, 300)
}
}
]
})
}
const confirm = (config: ConfirmProps) => {
const {
title,
content,
dismissible,
onConfirm,
onCancel,
size = 'md'
} = config
setDialogs((before) => {
const id = before[before.length - 1]?.id + 1 || 0
return [
...before,
{
id,
content,
size,
title,
backdrop: 'blur',
showCancel: true,
dismissible: dismissible,
onConfirm: () => {
onConfirm?.()
setTimeout(() => {
setDialogs((before) => before.filter((item) => item.id !== id))
}, 300)
},
onCancel: () => {
onCancel?.()
setTimeout(() => {
setDialogs((before) => before.filter((item) => item.id !== id))
}, 300)
}
}
]
})
}
return (
<DialogContext.Provider
value={{
alert,
confirm
}}
>
{children}
{dialogs?.map(({ id, ...props }) => <Modal key={id} {...props} />)}
</DialogContext.Provider>
)
}
export default DialogProvider

View File

@@ -0,0 +1,90 @@
// Songs Context
import { useLocalStorage } from '@uidotdev/usehooks'
import { createContext, useEffect, useState } from 'react'
import { PlayMode } from '@/const/enum'
import key from '@/const/key'
import AudioPlayer from '@/components/audio_player'
import { get163MusicListSongs, getNextMusic } from '@/utils/music'
import type { FinalMusic } from '@/types/music'
export interface MusicContextProps {
setListId: (id: string) => void
listId: string
onNext: () => void
onPrevious: () => void
}
export interface MusicProviderProps {
children: React.ReactNode
}
export const AudioContext = createContext<MusicContextProps>({
setListId: () => {},
listId: '5438670983',
onNext: () => {},
onPrevious: () => {}
})
const AudioProvider: React.FC<MusicProviderProps> = ({ children }) => {
const [listId, setListId] = useLocalStorage(key.musicID, '5438670983')
const [musicList, setMusicList] = useState<FinalMusic[]>([])
const [musicId, setMusicId] = useState<number>(0)
const [playMode, setPlayMode] = useState<PlayMode>(PlayMode.Loop)
const music = musicList.find((music) => music.id === musicId)
const onNext = () => {
const nextID = getNextMusic(musicList, musicId, playMode)
setMusicId(nextID)
}
const onPrevious = () => {
const index = musicList.findIndex((music) => music.id === musicId)
if (index === 0) {
setMusicId(musicList[musicList.length - 1].id)
} else {
setMusicId(musicList[index - 1].id)
}
}
const onPlayEnd = () => {
const nextID = getNextMusic(musicList, musicId, playMode)
setMusicId(nextID)
}
const changeMode = (mode: PlayMode) => {
setPlayMode(mode)
}
const fetchMusicList = async (id: string) => {
const res = await get163MusicListSongs(id)
setMusicList(res)
setMusicId(res[0].id)
}
useEffect(() => {
fetchMusicList(listId)
}, [listId])
return (
<AudioContext.Provider
value={{
setListId,
listId,
onNext,
onPrevious
}}
>
<AudioPlayer
title={music?.title}
src={music?.url || ''}
artist={music?.artist}
cover={music?.cover}
mode={playMode}
pressNext={onNext}
pressPrevious={onPrevious}
onPlayEnd={onPlayEnd}
onChangeMode={changeMode}
/>
{children}
</AudioContext.Provider>
)
}
export default AudioProvider