220 lines
6.3 KiB
TypeScript
220 lines
6.3 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import type { VideoItem, VideoListResponse, ThemeSettings, WidgetState, WindowState } from '../types'
|
|
|
|
const defaultTheme: ThemeSettings = {
|
|
primaryColor: '#007AFF',
|
|
backgroundColor: 'rgba(30, 30, 30, 0.7)',
|
|
glassOpacity: 0.7,
|
|
blurAmount: 20
|
|
}
|
|
|
|
function mergeTheme(savedTheme: Partial<ThemeSettings> | undefined): ThemeSettings {
|
|
if (!savedTheme) return { ...defaultTheme }
|
|
return {
|
|
primaryColor: savedTheme.primaryColor ?? defaultTheme.primaryColor,
|
|
backgroundColor: savedTheme.backgroundColor ?? defaultTheme.backgroundColor,
|
|
glassOpacity: savedTheme.glassOpacity ?? defaultTheme.glassOpacity,
|
|
blurAmount: savedTheme.blurAmount ?? defaultTheme.blurAmount
|
|
}
|
|
}
|
|
|
|
export const useSettingsStore = defineStore('settings', () => {
|
|
const currentVideo = ref<VideoItem | null>(null)
|
|
const videoList = ref<VideoItem[]>([])
|
|
const theme = ref<ThemeSettings>({ ...defaultTheme })
|
|
const widgets = ref<WidgetState[]>([])
|
|
const windows = ref<WindowState[]>([])
|
|
const isMobile = ref(false)
|
|
|
|
function initTheme() {
|
|
theme.value = mergeTheme(theme.value)
|
|
}
|
|
|
|
const isWindowOpen = computed(() => {
|
|
return (id: string) => windows.value.find(w => w.id === id)?.isOpen ?? false
|
|
})
|
|
|
|
const getWindowState = computed(() => {
|
|
return (id: string) => windows.value.find(w => w.id === id)
|
|
})
|
|
|
|
async function fetchVideoList() {
|
|
try {
|
|
const response = await fetch('/api/fs/list', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({
|
|
path: '/mp4',
|
|
password: '',
|
|
page: 1,
|
|
per_page: 0,
|
|
refresh: false
|
|
})
|
|
})
|
|
const data: VideoListResponse = await response.json()
|
|
if (data.code === 200) {
|
|
videoList.value = data.data.content.filter(item => item.name.endsWith('.mp4'))
|
|
if (!currentVideo.value && videoList.value.length > 0) {
|
|
currentVideo.value = videoList.value[0]
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to fetch video list:', error)
|
|
}
|
|
}
|
|
|
|
function setCurrentVideo(video: VideoItem) {
|
|
currentVideo.value = video
|
|
}
|
|
|
|
function updateTheme(newTheme: Partial<ThemeSettings>) {
|
|
theme.value = { ...theme.value, ...newTheme }
|
|
}
|
|
|
|
function resetTheme() {
|
|
theme.value = { ...defaultTheme }
|
|
}
|
|
|
|
function updateWidgetPosition(id: string, position: { x: number; y: number }) {
|
|
const widget = widgets.value.find(w => w.id === id)
|
|
if (widget) {
|
|
widget.position = position
|
|
} else {
|
|
widgets.value.push({ id, position, order: widgets.value.length })
|
|
}
|
|
}
|
|
|
|
function updateWidgetOrder(id: string, newOrder: number) {
|
|
const widget = widgets.value.find(w => w.id === id)
|
|
if (widget) {
|
|
widget.order = newOrder
|
|
}
|
|
}
|
|
|
|
function openWindow(id: string, position?: { x: number; y: number }, size?: { width: number; height: number }) {
|
|
const existingWindow = windows.value.find(w => w.id === id)
|
|
if (existingWindow) {
|
|
existingWindow.isOpen = true
|
|
existingWindow.zIndex = Math.max(...windows.value.map(w => w.zIndex), 0) + 1
|
|
} else {
|
|
const defaultWidth = size?.width ?? 800
|
|
const defaultHeight = size?.height ?? 600
|
|
const defaultX = (window.innerWidth - defaultWidth) / 2
|
|
const defaultY = (window.innerHeight - defaultHeight) / 2
|
|
windows.value.push({
|
|
id,
|
|
isOpen: true,
|
|
position: position ?? { x: Math.max(20, defaultX), y: Math.max(20, defaultY) },
|
|
size: size ?? { width: defaultWidth, height: defaultHeight },
|
|
zIndex: Math.max(...windows.value.map(w => w.zIndex), 0) + 1
|
|
})
|
|
}
|
|
}
|
|
|
|
function closeWindow(id: string) {
|
|
const window = windows.value.find(w => w.id === id)
|
|
if (window) {
|
|
window.isOpen = false
|
|
}
|
|
}
|
|
|
|
function updateWindowPosition(id: string, position: { x: number; y: number }) {
|
|
const window = windows.value.find(w => w.id === id)
|
|
if (window) {
|
|
window.position = position
|
|
}
|
|
}
|
|
|
|
function updateWindowSize(id: string, size: { width: number; height: number }) {
|
|
const window = windows.value.find(w => w.id === id)
|
|
if (window) {
|
|
window.size = size
|
|
}
|
|
}
|
|
|
|
function bringWindowToFront(id: string) {
|
|
const window = windows.value.find(w => w.id === id)
|
|
if (window) {
|
|
window.zIndex = Math.max(...windows.value.map(w => w.zIndex), 0) + 1
|
|
}
|
|
}
|
|
|
|
function setMobile(value: boolean) {
|
|
isMobile.value = value
|
|
}
|
|
|
|
function initWidgets(widgetIds: string[]) {
|
|
const existingIds = widgets.value.map(w => w.id)
|
|
|
|
widgetIds.forEach((id, index) => {
|
|
if (!existingIds.includes(id)) {
|
|
widgets.value.push({
|
|
id,
|
|
position: { x: -1, y: -1 },
|
|
order: index
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
function updateWidgetDefaultPosition(id: string, width: number, height: number) {
|
|
const widget = widgets.value.find(w => w.id === id)
|
|
if (widget) {
|
|
const screenWidth = window.innerWidth
|
|
const screenHeight = window.innerHeight
|
|
|
|
const positions: Record<string, { x: number; y: number }> = {
|
|
calendar: { x: screenWidth - 340, y: 20 },
|
|
taoxin: { x: screenWidth - 320, y: screenHeight - 380 },
|
|
cafe: { x: screenWidth - 660, y: 20 }
|
|
}
|
|
|
|
if (positions[id]) {
|
|
const newPos = positions[id]
|
|
const isDefaultPosition = widget.position.x === 20 && widget.position.y < 500
|
|
const isOutOfBounds = widget.position.x < 0 || widget.position.x > screenWidth - 100 ||
|
|
widget.position.y < 0 || widget.position.y > screenHeight - 100
|
|
|
|
if (isDefaultPosition || isOutOfBounds) {
|
|
widget.position = newPos
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
currentVideo,
|
|
videoList,
|
|
theme,
|
|
widgets,
|
|
windows,
|
|
isMobile,
|
|
isWindowOpen,
|
|
getWindowState,
|
|
fetchVideoList,
|
|
setCurrentVideo,
|
|
updateTheme,
|
|
resetTheme,
|
|
updateWidgetPosition,
|
|
updateWidgetOrder,
|
|
openWindow,
|
|
closeWindow,
|
|
updateWindowPosition,
|
|
updateWindowSize,
|
|
bringWindowToFront,
|
|
setMobile,
|
|
initWidgets,
|
|
initTheme,
|
|
updateWidgetDefaultPosition
|
|
}
|
|
}, {
|
|
persist: {
|
|
key: 'wufangzhen-settings',
|
|
storage: typeof window !== 'undefined' ? localStorage : undefined,
|
|
paths: ['currentVideo', 'theme', 'widgets', 'windows']
|
|
}
|
|
})
|