import XSystem from '@/core/XSystem.ts' import type { IDesktopAppIcon } from '@/core/desktop/types/IDesktopAppIcon.ts' import { computed, nextTick, onMounted, onUnmounted, reactive, ref, toRaw, toRefs, toValue, useTemplateRef, watch, watchEffect, } from 'vue' import { DesktopEventEnum } from '@/core/events/EventTypes.ts' import { useDraggable } from '@vueuse/core' import type { IGridTemplateParams } from '@/core/desktop/types/IGridTemplateParams.ts' export function useDesktopInit(containerStr: string) { let container:HTMLElement // 初始值 const gridTemplate = reactive({ cellExpectWidth: 90, cellExpectHeight: 110, cellRealWidth: 90, cellRealHeight: 110, gapX: 4, gapY: 4, colCount: 1, rowCount: 1 }) const ro = new ResizeObserver(entries => { const entry= entries[0] const containerRect = entry.contentRect gridTemplate.colCount = Math.floor((containerRect.width + gridTemplate.gapX) / (gridTemplate.cellExpectWidth + gridTemplate.gapX)); gridTemplate.rowCount = Math.floor((containerRect.height + gridTemplate.gapY) / (gridTemplate.cellExpectHeight + gridTemplate.gapY)); const w = containerRect.width - (gridTemplate.gapX * (gridTemplate.colCount - 1)) const h = containerRect.height - (gridTemplate.gapY * (gridTemplate.rowCount - 1)) gridTemplate.cellRealWidth = Number((w / gridTemplate.colCount).toFixed(2)) gridTemplate.cellRealHeight = Number((h / gridTemplate.rowCount).toFixed(2)) }) const gridStyle = computed(() => ({ gridTemplateColumns: `repeat(${gridTemplate.colCount}, minmax(${gridTemplate.cellExpectWidth}px, 1fr))`, gridTemplateRows: `repeat(${gridTemplate.rowCount}, minmax(${gridTemplate.cellExpectHeight}px, 1fr))`, gap: `${gridTemplate.gapX}px ${gridTemplate.gapY}px` })) onMounted(() => { container = document.querySelector(containerStr)! ro.observe(container) }) onUnmounted(() => { ro.unobserve(container) ro.disconnect() }) // 有桌面图标的app const appInfos = XSystem.instance.processManages.processInfos.filter(processInfo => !processInfo.isJustProcess) const oldAppIcons: IDesktopAppIcon[] = JSON.parse(localStorage.getItem('desktopAppIconInfo') || '[]') const appIcons: IDesktopAppIcon[] = appInfos.map((processInfo, index) => { const oldAppIcon = oldAppIcons.find(oldAppIcon => oldAppIcon.name === processInfo.name) // 左上角坐标原点,从上到下从左到右 索引从1开始 const x = Math.floor(index / gridTemplate.rowCount) + 1 const y = index % gridTemplate.rowCount + 1 return { name: processInfo.name, icon: processInfo.icon, path: processInfo.startName, x: oldAppIcon ? oldAppIcon.x : x, y: oldAppIcon ? oldAppIcon.y : y } }) const appIconsRef = ref(appIcons) watch(() => [gridTemplate.rowCount, gridTemplate.colCount], ([nRows, nCols], [oRows, oCols]) => { if (oCols == 1 && oRows == 1) return appIconsRef.value = rearrangeIcons(toRaw(appIconsRef.value), nCols, nRows, oCols, oRows) }) XSystem.instance.eventManages.addEventListener(DesktopEventEnum.onDesktopAppIconPos, (iconInfo) => { localStorage.setItem('desktopAppIconInfo', JSON.stringify(toValue(appIconsRef.value))) }) return { gridTemplate, appIconsRef, gridStyle } } /** * 重新安排图标位置 * @param appIcons 图标信息 * @param newCols 新的列数 * @param newRows 新的行数 * @param oldCols 旧的列数 * @param oldRows 旧的行数 */ function rearrangeIcons( appIcons: IDesktopAppIcon[], newCols: number, newRows: number, oldCols: number, oldRows: number ): IDesktopAppIcon[] { if (oldCols === newCols && oldRows === newRows) { return appIcons; } const occupied = new Set(); function key(x: number, y: number) { return `${x},${y}`; } const result: IDesktopAppIcon[] = [] const exceed: IDesktopAppIcon[] = [] for (const appIcon of appIcons) { const { x, y } = appIcon; if (x <= newCols && y <= newRows) { if (!occupied.has(key(x, y))) { occupied.add(key(x, y)) result.push({ ...appIcon, x, y }) } } else { exceed.push(appIcon) } } for (const appIcon of exceed) { // 最后格子也被占 → 从 (1,1) 开始找空位 let placed = false; for (let c = 1; c <= newCols; c++) { for (let r = 1; r <= newRows; r++) { if (!occupied.has(key(c, r))) { occupied.add(key(c, r)); result.push({ ...appIcon, x: c, y: r }); placed = true; break; } } if (placed) break; } } return result; }