保存一下
This commit is contained in:
21
src/core/desktop/types/IGridTemplateParams.ts
Normal file
21
src/core/desktop/types/IGridTemplateParams.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* 桌面网格模板参数
|
||||||
|
*/
|
||||||
|
export interface IGridTemplateParams {
|
||||||
|
/** 单元格预设宽度 */
|
||||||
|
cellExpectWidth: number
|
||||||
|
/** 单元格预设高度 */
|
||||||
|
cellExpectHeight: number
|
||||||
|
/** 单元格实际宽度 */
|
||||||
|
cellRealWidth: number
|
||||||
|
/** 单元格实际高度 */
|
||||||
|
cellRealHeight: number
|
||||||
|
/** 列间距 */
|
||||||
|
gapX: number
|
||||||
|
/** 行间距 */
|
||||||
|
gapY: number
|
||||||
|
/** 总列数 */
|
||||||
|
colCount: number
|
||||||
|
/** 总行数 */
|
||||||
|
rowCount: number
|
||||||
|
}
|
||||||
@@ -4,9 +4,10 @@
|
|||||||
class="w-full h-full pos-relative"
|
class="w-full h-full pos-relative"
|
||||||
>
|
>
|
||||||
<div ref="desktopRootDom" class="desktop-root">
|
<div ref="desktopRootDom" class="desktop-root">
|
||||||
<div class="desktop-container">
|
<div class="desktop-container"
|
||||||
<div v-for="icon in appIconsRef" class="icon-container"
|
:style="gridStyle">
|
||||||
:style="`grid-row: ${icon.row}/${icon.row + 1};grid-column: ${icon.col}/${icon.col + 1}};`">{{ icon.name }}</div>
|
<AppIcon v-for="(appIcon, i) in appIconsRef" :key="i"
|
||||||
|
:icon="appIcon" :gridTemplate="gridTemplate" />
|
||||||
</div>
|
</div>
|
||||||
<div class="task-bar"></div>
|
<div class="task-bar"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,42 +23,12 @@ import { DesktopEventEnum } from '@/core/events/EventTypes.ts'
|
|||||||
import { useIconDrag } from '@/core/desktop/utils/useIconDrag.ts'
|
import { useIconDrag } from '@/core/desktop/utils/useIconDrag.ts'
|
||||||
import type { IDesktopAppIcon } from '@/core/desktop/types/IDesktopAppIcon.ts'
|
import type { IDesktopAppIcon } from '@/core/desktop/types/IDesktopAppIcon.ts'
|
||||||
import { useDesktopInit } from '@/core/desktop/ui/useDesktopInit.ts'
|
import { useDesktopInit } from '@/core/desktop/ui/useDesktopInit.ts'
|
||||||
|
import AppIcon from '@/core/desktop/ui/components/AppIcon.vue'
|
||||||
|
|
||||||
const props = defineProps<{ process: DesktopProcess }>()
|
const props = defineProps<{ process: DesktopProcess }>()
|
||||||
// console.log(props.process)
|
// console.log(props.process)
|
||||||
|
|
||||||
const { colCount, rowCount, appIconsRef } = useDesktopInit('.desktop-container')
|
const { appIconsRef, gridStyle, gridTemplate } = useDesktopInit('.desktop-container')
|
||||||
|
|
||||||
const iconArr: IDesktopAppIcon[] = [
|
|
||||||
{
|
|
||||||
name: '文件管理器',
|
|
||||||
icon: '🗂',
|
|
||||||
path: '/',
|
|
||||||
col: 1,
|
|
||||||
row: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '浏览器',
|
|
||||||
icon: '🌐',
|
|
||||||
path: '/',
|
|
||||||
col: 1,
|
|
||||||
row: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '记事本',
|
|
||||||
icon: '📄',
|
|
||||||
path: '/',
|
|
||||||
col: 1,
|
|
||||||
row: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '音乐播放器',
|
|
||||||
icon: '🎵',
|
|
||||||
path: '/',
|
|
||||||
col: 1,
|
|
||||||
row: 4,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
XSystem.instance.eventManages.addEventListener(
|
XSystem.instance.eventManages.addEventListener(
|
||||||
DesktopEventEnum.onDesktopRootDomResize,
|
DesktopEventEnum.onDesktopRootDomResize,
|
||||||
@@ -81,20 +52,15 @@ const iconsInit = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
$icon-width: 80px;
|
|
||||||
$icon-height: 110px;
|
|
||||||
|
|
||||||
.desktop-root {
|
.desktop-root {
|
||||||
@apply w-full h-full flex flex-col;
|
@apply w-full h-full flex flex-col;
|
||||||
|
|
||||||
.desktop-container {
|
.desktop-container {
|
||||||
@apply w-full flex-1 grid gap-4 grid-auto-flow-col p-4 pos-relative;
|
@apply w-full flex-1 grid grid-auto-flow-col pos-relative;
|
||||||
grid-template-columns: repeat(auto-fill, minmax($icon-width, 1fr));
|
|
||||||
grid-template-rows: repeat(auto-fill, minmax($icon-height, 1fr));
|
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
width: $icon-width;
|
width: 100%;
|
||||||
height: $icon-height;
|
height: 100%;
|
||||||
@apply flex flex-col items-center justify-center rounded bg-gray-200;
|
@apply flex flex-col items-center justify-center rounded bg-gray-200;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
src/core/desktop/ui/components/AppIcon.vue
Normal file
46
src/core/desktop/ui/components/AppIcon.vue
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="icon-container"
|
||||||
|
:style="`grid-column: ${icon.col}/${icon.col + 1};grid-row: ${icon.row}/${icon.row + 1};`"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart="onDragStart"
|
||||||
|
@dragend="onDragEnd"
|
||||||
|
>
|
||||||
|
{{ icon.name }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { IDesktopAppIcon } from '@/core/desktop/types/IDesktopAppIcon.ts'
|
||||||
|
import type { IGridTemplateParams } from '@/core/desktop/types/IGridTemplateParams.ts'
|
||||||
|
|
||||||
|
const { icon, gridTemplate } = defineProps<{ icon: IDesktopAppIcon, gridTemplate: IGridTemplateParams }>()
|
||||||
|
|
||||||
|
const onDragStart = (e: DragEvent) => {}
|
||||||
|
|
||||||
|
const onDragEnd = (e: DragEvent) => {
|
||||||
|
const el = e.target as HTMLElement | null
|
||||||
|
if (!el) return
|
||||||
|
// 获取容器边界
|
||||||
|
const rect = el.parentElement!.getBoundingClientRect()
|
||||||
|
|
||||||
|
// 鼠标相对容器左上角坐标
|
||||||
|
const mouseX = e.clientX - rect.left
|
||||||
|
const mouseY = e.clientY - rect.top
|
||||||
|
|
||||||
|
// 计算鼠标所在单元格坐标(向上取整,从1开始)
|
||||||
|
const gridX = Math.ceil(mouseX / gridTemplate.cellRealWidth)
|
||||||
|
const gridY = Math.ceil(mouseY / gridTemplate.cellRealHeight)
|
||||||
|
console.log(gridX, gridY)
|
||||||
|
icon.col = gridX
|
||||||
|
icon.row = gridY
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.icon-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
@apply flex flex-col items-center justify-center rounded bg-gray-200;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import XSystem from '@/core/XSystem.ts'
|
import XSystem from '@/core/XSystem.ts'
|
||||||
import type { IDesktopAppIcon } from '@/core/desktop/types/IDesktopAppIcon.ts'
|
import type { IDesktopAppIcon } from '@/core/desktop/types/IDesktopAppIcon.ts'
|
||||||
import {
|
import {
|
||||||
|
computed,
|
||||||
nextTick,
|
nextTick,
|
||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
@@ -12,13 +13,18 @@ import {
|
|||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { DesktopEventEnum } from '@/core/events/EventTypes.ts'
|
import { DesktopEventEnum } from '@/core/events/EventTypes.ts'
|
||||||
import { useDraggable } from '@vueuse/core'
|
import { useDraggable } from '@vueuse/core'
|
||||||
|
import type { IGridTemplateParams } from '@/core/desktop/types/IGridTemplateParams.ts'
|
||||||
|
|
||||||
export function useDesktopInit(containerStr: string) {
|
export function useDesktopInit(containerStr: string) {
|
||||||
let container:HTMLElement
|
let container:HTMLElement
|
||||||
const gridTemplate = reactive({
|
// 初始值
|
||||||
cellWidth: 90,
|
const gridTemplate = reactive<IGridTemplateParams>({
|
||||||
cellHeight: 110,
|
cellExpectWidth: 90,
|
||||||
gap: 10,
|
cellExpectHeight: 110,
|
||||||
|
cellRealWidth: 90,
|
||||||
|
cellRealHeight: 110,
|
||||||
|
gapX: 4,
|
||||||
|
gapY: 4,
|
||||||
colCount: 1,
|
colCount: 1,
|
||||||
rowCount: 1
|
rowCount: 1
|
||||||
})
|
})
|
||||||
@@ -26,17 +32,28 @@ export function useDesktopInit(containerStr: string) {
|
|||||||
const ro = new ResizeObserver(entries => {
|
const ro = new ResizeObserver(entries => {
|
||||||
const entry= entries[0]
|
const entry= entries[0]
|
||||||
const containerRect = entry.contentRect
|
const containerRect = entry.contentRect
|
||||||
gridTemplate.colCount = Math.floor(containerRect.width / gridTemplate.cellWidth);
|
gridTemplate.colCount = Math.floor((containerRect.width + gridTemplate.gapX) / (gridTemplate.cellExpectWidth + gridTemplate.gapX));
|
||||||
gridTemplate.rowCount = Math.floor(containerRect.height / (gridTemplate.cellHeight));
|
gridTemplate.rowCount = Math.floor((containerRect.height + gridTemplate.gapY) / (gridTemplate.cellExpectHeight + gridTemplate.gapY));
|
||||||
console.log('resize', gridTemplate)
|
|
||||||
|
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(() => {
|
onMounted(() => {
|
||||||
container = document.querySelector(containerStr)!
|
container = document.querySelector(containerStr)!
|
||||||
ro.observe(container)
|
ro.observe(container)
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
ro.unobserve(container)
|
ro.unobserve(container)
|
||||||
|
ro.disconnect()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 有桌面图标的app
|
// 有桌面图标的app
|
||||||
@@ -62,11 +79,11 @@ export function useDesktopInit(containerStr: string) {
|
|||||||
appIcon.col = x
|
appIcon.col = x
|
||||||
appIcon.row = y
|
appIcon.row = y
|
||||||
})
|
})
|
||||||
console.log(appIconsRef)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...toRefs(gridTemplate),
|
gridTemplate,
|
||||||
appIconsRef
|
appIconsRef,
|
||||||
|
gridStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,10 @@
|
|||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"target": "ES6",
|
"target": "ES6",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"strictPropertyInitialization": false // 严格属性初始化检查
|
"strictPropertyInitialization": false, // 严格属性初始化检查
|
||||||
|
"noUnusedLocals": false, // 检查未使用的局部变量
|
||||||
|
"noUnusedParameters": false, // 检查未使用的参数
|
||||||
|
"noImplicitReturns": true, // 检查函数所有路径是否都有返回值
|
||||||
|
"noImplicitOverride": true, // 检查子类是否正确覆盖了父类方法
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user