Files
home/docs/.vitepress/theme/stores/settings.ts
2026-02-25 18:45:56 +08:00

222 lines
6.4 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,
videoBrightness: 0.3
}
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,
videoBrightness: savedTheme.videoBrightness ?? defaultTheme.videoBrightness
}
}
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']
}
})