From 2dc1eadccdcbfcac8f46b222d5bf7c4eb602d32f Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Thu, 15 May 2025 18:20:09 +0800 Subject: [PATCH] feat: dashboard --- frontend/components.d.ts | 1 - frontend/src/stores/dashboard/dashboard.ts | 19 ++++ .../src/views/dashboard/PreviewDashboard.vue | 35 ++++--- .../views/dashboard/canvas/DsCanvasCore.vue | 94 ++++++++++++++----- frontend/src/views/dashboard/css/DeDrag.less | 22 ++--- 5 files changed, 123 insertions(+), 48 deletions(-) create mode 100644 frontend/src/stores/dashboard/dashboard.ts diff --git a/frontend/components.d.ts b/frontend/components.d.ts index bb9f32f9..e8f6eea3 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -11,7 +11,6 @@ declare module 'vue' { ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElButton: typeof import('element-plus/es')['ElButton'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] - ElCol: typeof import('element-plus/es')['ElCol'] ElDialog: typeof import('element-plus/es')['ElDialog'] ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElDropdown: typeof import('element-plus/es')['ElDropdown'] diff --git a/frontend/src/stores/dashboard/dashboard.ts b/frontend/src/stores/dashboard/dashboard.ts new file mode 100644 index 00000000..b8d09f92 --- /dev/null +++ b/frontend/src/stores/dashboard/dashboard.ts @@ -0,0 +1,19 @@ +import { defineStore } from 'pinia' + +export const useDashboardStore = defineStore('dashboardStore', { + state: () => { + return { + curComponent: null + } + }, + getters: { + getCurComponent(): any { + return this.curComponent + } + }, + actions: { + setCurComponent(value: any) { + this.curComponent = value + } + } +}) diff --git a/frontend/src/views/dashboard/PreviewDashboard.vue b/frontend/src/views/dashboard/PreviewDashboard.vue index 606a1da8..642e9f89 100644 --- a/frontend/src/views/dashboard/PreviewDashboard.vue +++ b/frontend/src/views/dashboard/PreviewDashboard.vue @@ -6,29 +6,33 @@ const baseWidth = ref(0) const baseHeight = ref(0) const baseMarginLeft = ref(0) const baseMarginTop = ref(0) +const baseMatrixCount = { + x: 72, + y: 36 +} const componentData = ref([ { id: 4, x: 1, y: 1, - sizeX: 2, - sizeY: 2, + sizeX: 20, + sizeY: 10, _dragId: 0 }, { id: 10, x: 2, y: 1, - sizeX: 2, - sizeY: 2, + sizeX: 20, + sizeY: 10, _dragId: 1 }, { id: 7, x: 1, y: 2, - sizeX: 2, - sizeY: 3, + sizeX: 20, + sizeY: 10, _dragId: 2 } ]) @@ -36,10 +40,12 @@ const componentData = ref([ onMounted(() => { const screenWidth = window.innerWidth const screenHeight = window.innerHeight - baseWidth.value = 90.8333 * (screenWidth / 1366) - baseHeight.value = 100 * (screenHeight / 638) - baseMarginLeft.value = 20 * (screenWidth / 1366) - baseMarginTop.value = 20 * (screenHeight / 638) + baseMarginLeft.value = 10 + baseMarginTop.value = 10 + + baseWidth.value = (screenWidth - baseMarginLeft.value) / baseMatrixCount.x - baseMarginLeft.value + baseHeight.value = (screenHeight - baseMarginTop.value) / baseMatrixCount.y - baseMarginTop.value + nextTick(() => { if (cyGridster.value) { // @ts-ignore @@ -50,7 +56,14 @@ onMounted(() => { diff --git a/frontend/src/views/dashboard/canvas/DsCanvasCore.vue b/frontend/src/views/dashboard/canvas/DsCanvasCore.vue index 5d236be2..a6e16a25 100644 --- a/frontend/src/views/dashboard/canvas/DsCanvasCore.vue +++ b/frontend/src/views/dashboard/canvas/DsCanvasCore.vue @@ -69,6 +69,16 @@ const props = defineProps({ } }) +const { + canvasComponentData, + baseWidth, + baseHeight, + baseMarginLeft, + baseMarginTop, + draggable, + resizable +} = toRefs(props) + type Coord = { x1: number y1: number @@ -94,17 +104,6 @@ type Item = { sizeY: number [key: string]: any } - -const { - canvasComponentData, - baseWidth, - baseHeight, - baseMarginLeft, - baseMarginTop, - draggable, - resizable -} = toRefs(props) - // DOM ref const containerRef = ref(null) const renderOk = ref(false) @@ -115,6 +114,17 @@ const maxCell = ref(0) const positionBox = ref>>([]) const coordinates = ref([]) const infoBox = ref() +const pointList = ['lt', 't', 'rt', 'r', 'rb', 'b', 'lb', 'l'] +const cursors = { + lt: 'nw', + t: 'n', + rt: 'ne', + r: 'e', + rb: 'se', + b: 's', + lb: 'sw', + l: 'w' +} // Position data (non-reactive) @@ -452,9 +462,9 @@ function findClosetCoords(item: { _dragId: string | number }, tCoord: Coord) { } /** * Generate coordinates - * @param {Item} item: The item object to generate coordinates for + * @param {any} item: The item object to generate coordinates for */ -function makeCoordinate(item: Item) { +function makeCoordinate(item: any) { let width = cellWidth.value * item.sizeX - baseMarginLeft.value let height = cellHeight.value * item.sizeY - baseMarginTop.value let left = cellWidth.value * (item.x - 1) + baseMarginLeft.value @@ -645,8 +655,8 @@ function findBelowItems(item: Item) { return _.sortBy(Object.values(belowItems), 'y') } - -function startResize(e: MouseEvent, item: Item, index: number) { +// @ts-ignore +function startResize(e: MouseEvent, point: string, item: Item, index: number) { if (!resizable.value) return props.resizeStart(e, item, index) @@ -707,7 +717,6 @@ function startMove(e: MouseEvent, item: Item, index: number) { infoBox.value.nowItemNode = target.closest('.item') infoBox.value.cloneItem = infoBox.value.nowItemNode.cloneNode(true) } - infoBox.value.cloneItem.classList.add('cloneNode') if( containerRef.value ){ containerRef.value.append(infoBox.value.cloneItem) @@ -882,6 +891,46 @@ function moving() { // do moving } +function getPointStyle(point: string, item: Item) { + const { sizeX, sizeY } = item + const width = sizeX * (baseWidth.value + baseMarginLeft.value) - baseMarginLeft.value + const height = sizeY * (baseHeight.value + baseMarginTop.value) - baseMarginTop.value + + const hasT = /t/.test(point) + const hasB = /b/.test(point) + const hasL = /l/.test(point) + const hasR = /r/.test(point) + let newLeft = 0 + let newTop = 0 + + // 四个角的点 + if (point.length === 2) { + newLeft = hasL ? 0 : width + newTop = hasT ? 0 : height + } else { + // 上下两点的点,宽度居中 + if (hasT || hasB) { + newLeft = width / 2 + newTop = hasT ? 0 : height + } + + // 左右两边的点,高度居中 + if (hasL || hasR) { + newLeft = hasL ? 0 : width + newTop = Math.floor(height / 2) + } + } + + return { + marginLeft: '-4px', + marginTop: '-4px', + left: `${newLeft}px`, + top: `${newTop}px`, + // @ts-ignore + cursor: `${cursors[point]}-resize` + } +} + defineExpose({ getRenderState, init, @@ -922,12 +971,15 @@ defineExpose({ :key="'item' + index" :style="nowItemStyle(item)" > - {{ item }} - {{ item }} -- {{ baseWidth }} + +
+ :style="getPointStyle(point, item)" + @mousedown="startResize($event, point, item, index)" + >
diff --git a/frontend/src/views/dashboard/css/DeDrag.less b/frontend/src/views/dashboard/css/DeDrag.less index 08c48f67..8a6184e5 100644 --- a/frontend/src/views/dashboard/css/DeDrag.less +++ b/frontend/src/views/dashboard/css/DeDrag.less @@ -1,16 +1,13 @@ .dragAndResize { position: relative; - user-select: none; - * { box-sizing: border-box; margin: 0; padding: 0; } - .item { position: absolute; @@ -25,18 +22,13 @@ .resizeHandle { - position: absolute; - right: 2px; - bottom: 2px; - - width: 0; - height: 0; - - cursor: nw-resize; - - opacity: .5; - border-bottom: 10px solid black; - border-left: 10px solid transparent; + position: absolute; + background: #fff; + border: 1px solid #59c7f9; + width: 8px; + height: 8px; + border-radius: 50%; + z-index: 0; } }