feat: dashboard tab move out

This commit is contained in:
wangjiahao
2025-05-28 16:47:09 +08:00
parent 167aacb969
commit 152773b0b3
7 changed files with 163 additions and 107 deletions
@@ -8,6 +8,7 @@ import {findComponent} from "@/views/dashboard/components/component-list.ts";
const dashboardStore = dashboardStoreWithOut()
const canvasLocked = ref(false) // Is the canvas movement locked, Default false
const emits = defineEmits(["parentAddItemBox"]);
// @ts-ignore
let currentInstance
// Props
@@ -400,11 +401,26 @@ function removeItem(index: number) {
canvasComponentData.value.splice(index, 1)
}
function getNextDragId() {
if (!canvasComponentData.value || canvasComponentData.value.length === 0) {
return 0;
}
//@ts-ignore
const validIds = canvasComponentData.value.map(item => item._dragId).filter(id => id != null && id !== ''); // 过滤 null、undefined 和空字符串
if (validIds.length === 0) {
return 0;
}
//@ts-ignore
const maxDragId = Math.max(...validIds);
return maxDragId + 1;
}
function addItem(item: CanvasItem, index: any) {
if (index < 0) {
index = canvasComponentData.value.length
}
item._dragId = index
item._dragId = getNextDragId()
checkItemPosition(item, {x: item.x, y: item.y})
emptyTargetCell(item)
addItemToPositionBox(item)
@@ -899,15 +915,25 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) {
if (canvasLocked.value) {
const moveItem = infoBox.value.moveItem
// Get the SQTab currently being moved in
const curActiveSQTab = canvasComponentData?.value.find(item => item.component === 'SQTab' && item.moveInActive === true);
if (curActiveSQTab) {
// @ts-ignore
const refTabInstance = currentInstance.refs['shape_component_' + curActiveSQTab.id][0]
refTabInstance.addTabItem(moveItem)
removeItemById(moveItem.id)
curActiveSQTab.collisionActive = false
curActiveSQTab.moveInActive = false
const curActiveMoveInSQTab = canvasComponentData?.value.find(item => item.component === 'SQTab' && item.collisionActive === true);
if (curActiveMoveInSQTab) {
if (curActiveMoveInSQTab.moveInActive) {
// @ts-ignore
const refTabInstance = currentInstance.refs['shape_component_' + curActiveMoveInSQTab.id][0]
refTabInstance.addTabItem(moveItem)
removeItemById(moveItem.id)
}
curActiveMoveInSQTab.collisionActive = false
curActiveMoveInSQTab.moveInActive = false
}
// move out
if (props.parentConfigItem && props.parentConfigItem.moveOutActive) {
emits('parentAddItemBox', _.cloneDeep(moveItem))
removeItemById(moveItem.id)
props.parentConfigItem.moveOutActive = false
}
}
canvasLocked.value = false
}
@@ -1045,6 +1071,7 @@ function tabMoveOutCheckSQ() {
const top = cloneItem.offsetTop
const {tw} = getItemStylePosition(props.parentConfigItem)
props.parentConfigItem.moveOutActive = left < -tabMoveOutXOffset || top < -tabMoveOutYOffset || (left + width - tw) > tabMoveOutXOffset;
canvasLocked.value = props.parentConfigItem.moveOutActive
}
}
@@ -1135,7 +1162,8 @@ defineExpose({
<component :ref="'shape_component_'+item.id"
class="sql-component slot-component dragHandle"
:is="findComponent(item.component)"
:config-item="item">
:config-item="item"
@parentAddItemBox=" (subItem:any) => addItemBox(subItem)">
</component>
</CanvasShape>
</template>
@@ -42,6 +42,7 @@ const { draggable } = toRefs(props)
<template>
<div :class="{
item: true,
itemCursorDefault: configItem.component === 'SQTab',
moveAnimation: moveAnimate,
movingItem: configItem.isPlayer,
canNotDrag: !draggable
@@ -32,7 +32,7 @@ const shadowStyle = (size: number, index: number) => {
height: `${size}px`
}
} else if (index === 3) {
return {
return {
top: 0,
left: 0,
width: `${size}px`,
@@ -44,10 +44,15 @@ const shadowStyle = (size: number, index: number) => {
</script>
<template>
<div class="dragHandle" v-for="(size,index) in sizeList" :style="shadowStyle(size,index)"></div>
<div class="dragHandle dragArea" v-for="(size,index) in sizeList" :style="shadowStyle(size,index)"></div>
</template>
<style scoped lang="less">
.dragArea {
opacity: 0.05;
}
.dragHandle {
background: #c1e2e8;
position: absolute;
@@ -12,6 +12,8 @@ const showTabTitleFlag = ref(true)
let currentInstance
import _ from 'lodash'
const emits = defineEmits(["parentAddItemBox"]);
const tabBaseMatrixCount = {
x: 36,
y: 12
@@ -130,7 +132,7 @@ defineExpose({
</script>
<template>
<div>
<div :class="{'tab-moveout':configItem.moveOutActive}">
<drag-handle></drag-handle>
<custom-tab
v-model="editableTabsValue"
@@ -142,7 +144,7 @@ defineExpose({
:border-active-color="state.headBorderActiveColor"
:hide-title="!showTabTitleFlag"
>
-------{{ configItem.collisionActive }} -- -- {{ configItem.moveInActive }}-- -- {{ configItem.moveOutActive }}
<!-- {{ configItem.collisionActive }} & {{ configItem.moveInActive }}${{ configItem.moveOutActive }}-->
<template :key="tabItem.name" v-for="tabItem in configItem.propValue">
<el-tab-pane
class="el-tab-pane-custom"
@@ -193,12 +195,14 @@ defineExpose({
:class="{ 'switch-hidden': editableTabsValue !== tabItem.name }"
>
<DashboardEditor
class="tab-dashboard-editor-main"
:ref="'tabEditorRef_'+index"
:canvas-component-data="tabItem.componentData"
:move-in-active="configItem.moveInActive"
:base-matrix-count="tabBaseMatrixCount"
:canvas-id="tabItem.name"
:parent-config-item="configItem"
@parentAddItemBox=" item => emits('parentAddItemBox',item)"
>
</DashboardEditor>
</div>
@@ -218,4 +222,18 @@ defineExpose({
height: 100%;
}
.tab-dashboard-editor-main{
height: 100%!important;
}
.tab-moveout {
::v-deep(.ed-tabs__content) {
overflow: visible !important;
}
::v-deep(.dashboard-editor-main) {
overflow: visible !important;
}
}
</style>
@@ -1,105 +1,104 @@
.dragAndResize
{
position: relative;
user-select: none;
width: 100%;
*
{
box-sizing: border-box;
margin: 0;
padding: 0;
}
.item
{
position: absolute;
width: 100px;
height: 100px;
cursor: move;
border: 1px solid #59c7f9;
background-color: #fff;
.resizeHandle
{
position: absolute;
background: #fff;
border: 1px solid #59c7f9;
width: 8px;
height: 8px;
border-radius: 50%;
z-index: 5;
}
.sql-component {
width: 100%;
height: 100%;
}
}
.moveAnimation
{
transition: top 80ms ease;
}
.canNotDrag
{
cursor: default!important;
.dragAndResize {
position: relative;
user-select: none;
width: 100%;
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.itemCursorDefault {
cursor: default!important;
}
.item {
position: absolute;
width: 100px;
height: 100px;
border: 1px solid #59c7f9;
background-color: #fff;
cursor: move;
.resizeHandle {
position: absolute;
background: #fff;
border: 1px solid #59c7f9;
width: 8px;
height: 8px;
border-radius: 50%;
z-index: 5;
}
.cloneNode
{
z-index: 100;
.sql-component {
width: 100%;
height: 100%;
}
}
transition: none;
.moveAnimation {
transition: top 80ms ease;
}
opacity: .5;
.canNotDrag {
cursor: default !important;
}
.cloneNode {
z-index: 100;
transition: none;
opacity: .5;
}
.movingItem {
position: absolute;
border: none;
&:before {
position: absolute;
z-index: 2;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
background-color: #b8d3f9;
}
.movingItem
{
position: absolute;
border: none;
&:before
{
position: absolute;
z-index: 2;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
background-color: #b8d3f9;
}
.resizeHandle
{
display: none;
}
.slot-component {
display: none;
}
.resizeHandle {
display: none;
}
.positionBox
{
position: fixed;
top: 0;
right: 100px;
overflow: auto;
width: 500px;
height: 500px;
border: 1px solid;
.slot-component {
display: none;
}
}
.coords
{
position: fixed;
right: 100px;
bottom: 200px;
.positionBox {
position: fixed;
top: 0;
right: 100px;
overflow: auto;
overflow: auto;
width: 200px;
height: 200px;
width: 500px;
height: 500px;
border: 1px solid;
}
border: 1px solid;
}
.coords {
position: fixed;
right: 100px;
bottom: 200px;
overflow: auto;
width: 200px;
height: 200px;
border: 1px solid;
}
}
@@ -83,6 +83,7 @@ onMounted(() => {
}
})
})
const emits = defineEmits(["parentAddItemBox"]);
</script>
<template>
@@ -99,6 +100,7 @@ onMounted(() => {
:canvas-component-data="canvasComponentData"
:parent-config-item="parentConfigItem"
:canvas-id="canvasId"
@parentAddItemBox=" item => emits('parentAddItemBox',item)"
></CanvasCore>
</div>
@@ -3,7 +3,7 @@ import {ref} from 'vue'
import Toolbar from "@/views/dashboard/editor/Toolbar.vue";
import DashboardEditor from "@/views/dashboard/editor/DashboardEditor.vue";
import {findNewComponentFromList} from "@/views/dashboard/components/component-list.ts";
import {guid} from "@/utils/canvas.ts";
import {type CanvasItem, guid} from "@/utils/canvas.ts";
import cloneDeep from 'lodash/cloneDeep';
@@ -56,7 +56,10 @@ const componentData = ref([
<template>
<div class="editor-main">
<Toolbar @add-component="addComponent"></Toolbar>
<DashboardEditor ref="dashboardEditorRef" :canvas-component-data="componentData"></DashboardEditor>
<DashboardEditor
ref="dashboardEditorRef"
:canvas-component-data="componentData">
</DashboardEditor>
</div>
</template>