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 type { IGridTemplateParams } from '@/core/desktop/types/IGridTemplateParams.ts' import { eventManager } from '@/core/events/EventManager.ts' import { processManager } from '@/core/process/ProcessManager.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 = processManager.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 = index % gridTemplate.rowCount + 1 const y = Math.floor(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) const exceedApp = ref([]) watch(() => [gridTemplate.colCount, gridTemplate.rowCount], ([nCols, nRows], [oCols, oRows]) => { // if (oCols == 1 && oRows == 1) return if (oCols === nCols && oRows === nRows) return const { appIcons, hideAppIcons } = rearrangeIcons(toRaw(appIconsRef.value), nCols, nRows) appIconsRef.value = appIcons exceedApp.value = hideAppIcons }) eventManager.addEventListener('onDesktopAppIconPos', (iconInfo) => { localStorage.setItem('desktopAppIconInfo', JSON.stringify(toValue(appIconsRef.value))) }) return { gridTemplate, appIconsRef, gridStyle } } /** * 重新安排图标位置 * @param appIconInfos 图标信息 * @param maxCol 列数 * @param maxRow 行数 */ function rearrangeIcons( appIconInfos: IDesktopAppIcon[], maxCol: number, maxRow: number ): IRearrangeInfo { const occupied = new Set(); function key(x: number, y: number) { return `${x},${y}`; } const appIcons: IDesktopAppIcon[] = [] const hideAppIcons: IDesktopAppIcon[] = [] const temp: IDesktopAppIcon[] = [] for (const appIcon of appIconInfos) { const { x, y } = appIcon; if (x <= maxCol && y <= maxRow) { if (!occupied.has(key(x, y))) { occupied.add(key(x, y)) appIcons.push({ ...appIcon, x, y }) } } else { temp.push(appIcon) } } const max = maxCol * maxRow for (const appIcon of temp) { if (appIcons.length < max) { // 最后格子也被占 → 从 (1,1) 开始找空位 let placed = false; for (let c = 1; c <= maxCol; c++) { for (let r = 1; r <= maxRow; r++) { if (!occupied.has(key(c, r))) { occupied.add(key(c, r)); appIcons.push({ ...appIcon, x: c, y: r }); placed = true; break; } } if (placed) break; } } else { // 放不下了 hideAppIcons.push(appIcon) } } return { appIcons, hideAppIcons }; } interface IRearrangeInfo { /** 正常的桌面图标信息 */ appIcons: IDesktopAppIcon[]; /** 隐藏的桌面图标信息(超出屏幕显示的) */ hideAppIcons: IDesktopAppIcon[]; }