Skip to content

Commit 8e85bd9

Browse files
committed
feat: dashboard tab
1 parent 72d7104 commit 8e85bd9

File tree

9 files changed

+257
-165
lines changed

9 files changed

+257
-165
lines changed

frontend/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ declare module '@vue/runtime-core' {
4141
ElTable: typeof import('element-plus-secondary/es')['ElTable']
4242
ElTableColumn: typeof import('element-plus-secondary/es')['ElTableColumn']
4343
ElTabPane: typeof import('element-plus-secondary/es')['ElTabPane']
44+
ElTabPanel: typeof import('element-plus-secondary/es')['ElTabPanel']
4445
ElTabs: typeof import('element-plus-secondary/es')['ElTabs']
4546
ElTooltip: typeof import('element-plus-secondary/es')['ElTooltip']
4647
ElUpload: typeof import('element-plus-secondary/es')['ElUpload']

frontend/src/utils/canvas.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
// @ts-ignore
1+
// @ts-ignore
22
import SnowflakeID from 'snowflake-id';
33

44
const snowflake = new SnowflakeID({
5-
mid: 42,
6-
offset: (2010 - 1970) * 365 * 24 * 3600 * 1000
5+
mid: 42,
6+
offset: (2010 - 1970) * 365 * 24 * 3600 * 1000
77
});
88

9-
export const guid = () => {
10-
return snowflake.generate();
9+
export const guid = (prefix?: string) => {
10+
if (prefix) {
11+
return `${prefix}_${snowflake.generate()}`;
12+
} else {
13+
return snowflake.generate()
14+
}
1115
}
1216

1317
export interface CanvasItem {
@@ -16,6 +20,7 @@ export interface CanvasItem {
1620
y: number
1721
sizeX: number
1822
sizeY: number
23+
1924
[key: string]: any
2025
}
2126

frontend/src/views/dashboard/DashboardEditor.vue

Lines changed: 0 additions & 69 deletions
This file was deleted.

frontend/src/views/dashboard/canvas/CanvasCore.vue

Lines changed: 90 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
<script setup lang="ts">
2-
import {ref, nextTick, toRefs, type PropType} from 'vue'
2+
import {ref, nextTick, toRefs, type PropType, onMounted, getCurrentInstance} from 'vue'
33
import _ from 'lodash'
44
import {dashboardStoreWithOut} from '@/stores/dashboard/dashboard'
55
import {type CanvasCoord, type CanvasItem} from '@/utils/canvas.ts'
66
import CanvasShape from './CanvasShape.vue'
77
import {findComponent} from "@/views/dashboard/components/component-list.ts";
8-
import {storeToRefs} from 'pinia'
98
109
const dashboardStore = dashboardStoreWithOut()
11-
const {
12-
tabCollisionActiveId,
13-
tabMoveInActiveId
14-
} = storeToRefs(dashboardStore)
15-
10+
const canvasLocked = ref(false) // Is the canvas movement locked, Default false
11+
// @ts-ignore
12+
let currentInstance
1613
// Props
1714
const props = defineProps({
15+
canvasId: {
16+
type: String,
17+
default: 'canvas-main'
18+
},
19+
parentConfigItem: {
20+
type: Object as PropType<CanvasItem>,
21+
required: false
22+
},
1823
canvasComponentData: {
1924
type: Array as PropType<CanvasItem[]>,
2025
required: true
@@ -111,7 +116,9 @@ let itemMaxX = 0
111116
let itemMaxY = 0
112117
const moveTime = 80
113118
114-
const tabMoveInYOffset = 70
119+
const tabMoveInYOffset = 30
120+
const tabMoveOutXOffset = 30
121+
const tabMoveOutYOffset = 30
115122
// Effective area of collision depth
116123
const collisionGap = 10
117124
@@ -372,6 +379,13 @@ function movePlayer(item: CanvasItem, position: any) {
372379
}
373380
}
374381
382+
function removeItemById(id: number) {
383+
const index = canvasComponentData.value.findIndex(item => item.id === id);
384+
if (index >= 0) {
385+
removeItem(index)
386+
}
387+
}
388+
375389
function removeItem(index: number) {
376390
const item = canvasComponentData.value[index] as CanvasItem
377391
removeItemFromPositionBox(item)
@@ -383,7 +397,7 @@ function removeItem(index: number) {
383397
}
384398
})
385399
// @ts-ignore
386-
canvasComponentData.value.splice(index, 1, {})
400+
canvasComponentData.value.splice(index, 1)
387401
}
388402
389403
function addItem(item: CanvasItem, index: any) {
@@ -679,6 +693,8 @@ function containerMouseDown(e: MouseEvent) {
679693
}
680694
infoBox.value.startX = e.pageX
681695
infoBox.value.startY = e.pageY
696+
e.preventDefault()
697+
e.stopPropagation()
682698
}
683699
684700
function getNowPosition(addSizeX: number, addSizeY: number, moveXSize: number, moveYSize: number) {
@@ -736,6 +752,7 @@ function getNowPosition(addSizeX: number, addSizeY: number, moveXSize: number, m
736752
}
737753
738754
function startMove(e: MouseEvent, item: CanvasItem, index: number) {
755+
canvasLocked.value = false // Reset canvas lock status
739756
if (!draggable.value) return
740757
dashboardStore.setCurComponent(item)
741758
if (!infoBox.value) {
@@ -787,7 +804,6 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) {
787804
infoBox.value.oldSizeY = item.sizeY
788805
infoBox.value.originWidth = infoBox.value.cloneItem.offsetWidth
789806
infoBox.value.originHeight = infoBox.value.cloneItem.offsetHeight
790-
791807
const itemMouseMove = (e: MouseEvent) => {
792808
const moveItem = _.get(infoBox.value, 'moveItem')
793809
const resizeItem = _.get(infoBox.value, 'resizeItem')
@@ -839,10 +855,17 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) {
839855
840856
let nowCloneItemX = infoBox.value.originX + moveXSize
841857
let nowCloneItemY = infoBox.value.originY + moveYSize
858+
infoBox.value.cloneItem.style.left = `${nowCloneItemX}px`
859+
infoBox.value.cloneItem.style.top = `${nowCloneItemY}px`
860+
tabMoveInCheckSQ()
861+
tabMoveOutCheckSQ()
862+
863+
//If the current canvas is locked, no component movement will be performed
864+
if (canvasLocked.value) return
842865
// Adjust the accuracy of moving coordinate changes
843866
const newX = Math.max(
844867
Math.floor(
845-
(nowCloneItemX + infoBox.value.cloneItem.offsetWidth / 96 - baseMarginLeft.value) /
868+
(nowCloneItemX - 20 + infoBox.value.cloneItem.offsetWidth / 96 - baseMarginLeft.value) /
846869
cellWidth.value +
847870
1
848871
),
@@ -857,26 +880,40 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) {
857880
),
858881
1
859882
)
860-
861883
debounce(() => {
862884
if (newX !== infoBox.value.oldX || newY !== infoBox.value.oldY) {
863885
movePlayer(moveItem, {x: newX, y: newY})
864886
infoBox.value.oldX = newX
865887
infoBox.value.oldY = newY
866888
}
867889
}, 10)
868-
869-
infoBox.value.cloneItem.style.left = `${nowCloneItemX}px`
870-
infoBox.value.cloneItem.style.top = `${nowCloneItemY}px`
871-
tabMoveInCheckSQ()
872890
}
873891
}
874892
875893
window.addEventListener('mousemove', itemMouseMove)
876894
895+
896+
// Need to execute before mouseup
897+
const itemCanvasChange = () => {
898+
// The current canvas movement is in a locked state, indicating that there are components that require canvas switching
899+
if (canvasLocked.value) {
900+
const moveItem = infoBox.value.moveItem
901+
// Get the SQTab currently being moved in
902+
const curActiveSQTab = canvasComponentData?.value.find(item => item.component === 'SQTab' && item.moveInActive === true);
903+
if (curActiveSQTab) {
904+
// @ts-ignore
905+
const refTabInstance = currentInstance.refs['shape_component_' + curActiveSQTab.id][0]
906+
refTabInstance.addTabItem(moveItem)
907+
removeItemById(moveItem.id)
908+
curActiveSQTab.collisionActive = false
909+
curActiveSQTab.moveInActive = false
910+
}
911+
}
912+
canvasLocked.value = false
913+
}
914+
877915
const itemMouseUp = () => {
878916
if (_.isEmpty(infoBox.value)) return
879-
880917
if (infoBox.value.cloneItem) {
881918
infoBox.value.cloneItem.remove()
882919
}
@@ -889,6 +926,7 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) {
889926
infoBox.value.moveItem.show = true
890927
delete infoBox.value.moveItem.isPlayer
891928
}
929+
itemCanvasChange()
892930
infoBox.value = {}
893931
894932
window.removeEventListener('mousemove', itemMouseMove)
@@ -960,27 +998,28 @@ function moving() {
960998
// Obtain matrix position
961999
function getItemMatrixPosition(item: CanvasItem) {
9621000
return {
963-
tw: cellWidth.value * item.sizeX - baseMarginLeft.value,
964-
th: cellHeight.value * item.sizeY - baseMarginTop.value,
965-
tl: cellWidth.value * (item.x - 1) + baseMarginLeft.value,
966-
tr: cellWidth.value * (item.sizeX + item.x - 1) + baseMarginLeft.value,
967-
tt: cellHeight.value * (item.y - 1) + baseMarginTop.value,
968-
tb: cellHeight.value * (item.sizeY + item.y - 1) + baseMarginLeft.value
1001+
tw: item.sizeX,
1002+
th: item.sizeY,
1003+
tl: item.x - 1,
1004+
tr: item.sizeX + item.x - 1,
1005+
tt: item.y - 1,
1006+
tb: item.sizeY + item.y - 1
9691007
}
9701008
}
9711009
9721010
// Get style location
9731011
function getItemStylePosition(item: CanvasItem) {
9741012
const {tw, th, tl, tr, tt, tb} = getItemMatrixPosition(item)
9751013
return {
976-
tw: tw * (cellWidth.value + baseMarginLeft.value) - baseMarginLeft.value,
977-
th: th * (cellHeight.value + baseMarginTop.value) - baseMarginTop.value,
1014+
tw: tw * cellWidth.value - baseMarginLeft.value,
9781015
tl: cellWidth.value * tl + baseMarginLeft.value,
9791016
tr: cellWidth.value * tr + baseMarginLeft.value,
1017+
th: th * cellHeight.value - baseMarginTop.value,
9801018
tt: cellHeight.value * tt + baseMarginTop.value,
981-
tb: cellHeight.value * tb + baseMarginLeft.value
1019+
tb: cellHeight.value * tb + baseMarginTop.value
9821020
}
9831021
}
1022+
9841023
// @ts-ignore
9851024
function tabMoveInCheck(cloneRefItem) {
9861025
//1. If the current cloneItem type is not a tab,
@@ -998,8 +1037,19 @@ function tabMoveInCheck(cloneRefItem) {
9981037
}
9991038
}
10001039
1040+
function tabMoveOutCheckSQ() {
1041+
const {cloneItem, moveItem} = infoBox.value
1042+
if (cloneItem && moveItem && props.canvasId.includes('tab') && props.parentConfigItem) {
1043+
const left = cloneItem.offsetLeft
1044+
const width = cloneItem.offsetWidth
1045+
const top = cloneItem.offsetTop
1046+
const {tw} = getItemStylePosition(props.parentConfigItem)
1047+
props.parentConfigItem.moveOutActive = left < -tabMoveOutXOffset || top < -tabMoveOutYOffset || (left + width - tw) > tabMoveOutXOffset;
1048+
}
1049+
}
1050+
10011051
function tabMoveInCheckSQ() {
1002-
const {cloneItem,moveItem} = infoBox.value.cloneItem
1052+
const {cloneItem, moveItem} = infoBox.value
10031053
if (cloneItem && moveItem && moveItem !== 'SQTab') {
10041054
const width = cloneItem.offsetWidth
10051055
const height = cloneItem.offsetHeight
@@ -1022,12 +1072,8 @@ function tabMoveInCheckSQ() {
10221072
// Near the lower right corner area
10231073
const brAndBr =
10241074
collisionT + collisionH >= top + height && collisionL + collisionW >= left + width
1025-
if (tfAndTf && bfAndBf && trAndTr && brAndBr) {
1026-
dashboardStore.setTabCollisionActiveId(item.id)
1027-
} else if (tabCollisionActiveId.value === item.id) {
1028-
dashboardStore.setTabCollisionActiveId(null)
1029-
}
1030-
1075+
item.collisionActive = tfAndTf && bfAndBf && trAndTr && brAndBr;
1076+
canvasLocked.value = item.collisionActive // Contains collision move in operation, locking canvas
10311077
10321078
//Move into effective area for inspection
10331079
//Collision effective area inspection
@@ -1044,17 +1090,17 @@ function tabMoveInCheckSQ() {
10441090
const activeTrAndTr = activeT <= top && activeL + activeW >= left + width
10451091
// Near the lower right corner area
10461092
const activeBrAndBr = activeT + activeH >= top + height && activeL + activeW >= left + width
1047-
if (activeTfAndTf && activeBfAndBf && activeTrAndTr && activeBrAndBr) {
1048-
dashboardStore.setTabMoveInActiveId(item.id)
1049-
} else if (tabMoveInActiveId.value === item.id) {
1050-
dashboardStore.setTabMoveInActiveId(null)
1051-
}
1093+
1094+
item.moveInActive = activeTfAndTf && activeBfAndBf && activeTrAndTr && activeBrAndBr
10521095
}
10531096
})
10541097
}
1055-
10561098
}
10571099
1100+
onMounted(() => {
1101+
currentInstance = getCurrentInstance()
1102+
})
1103+
10581104
10591105
defineExpose({
10601106
getRenderState,
@@ -1086,7 +1132,11 @@ defineExpose({
10861132
:start-resize="startResize"
10871133
:key="'item' + index"
10881134
:style="nowItemStyle(item)">
1089-
<component class="slot-component" :is="findComponent(item.component)" :config-item="item"></component>
1135+
<component :ref="'shape_component_'+item.id"
1136+
class="sql-component slot-component dragHandle"
1137+
:is="findComponent(item.component)"
1138+
:config-item="item">
1139+
</component>
10901140
</CanvasShape>
10911141
</template>
10921142
</div>

0 commit comments

Comments
 (0)