fix(数据大屏): 修复Tab部分拖拽问题

This commit is contained in:
wangjiahao 2024-08-19 17:59:22 +08:00
parent 3b85623919
commit 703047630f
3 changed files with 11 additions and 531 deletions

View File

@ -855,14 +855,16 @@ function removeItemById(componentId) {
function removeItem(index) {
let item = componentData.value[index]
if (item && isSameCanvas(item, canvasId.value)) {
removeItemFromPositionBox(item)
let belowItems = findBelowItems(item)
_.forEach(belowItems, function (upItem) {
let canGoUpRows = canItemGoUp(upItem)
if (canGoUpRows > 0) {
moveItemUp(upItem, canGoUpRows)
}
})
if (isDashboard()) {
removeItemFromPositionBox(item)
let belowItems = findBelowItems(item)
_.forEach(belowItems, function (upItem) {
let canGoUpRows = canItemGoUp(upItem)
if (canGoUpRows > 0) {
moveItemUp(upItem, canGoUpRows)
}
})
}
let checkedFields = []
if (item.innerType === 'VQuery') {
;(item.propValue || []).forEach(ele => {

View File

@ -301,6 +301,7 @@ const componentMoveIn = component => {
dvMainStore.setCurComponent({ component: null, index: null })
component.canvasId = element.value.id + '--' + tabItem.name
dataVTabComponentAdd(component, element.value.style)
tabItem.componentData.push(component)
}
}
})

View File

@ -1,523 +0,0 @@
<template>
<div
v-if="state.tabShow"
style="width: 100%; height: 100%"
:class="[headClass, `ed-tabs-${curThemes}`]"
class="custom-tabs-head"
ref="tabComponentRef"
>
<de-custom-tab
v-model="editableTabsValue"
@tab-add="addTab"
:addable="isEditMode"
:font-color="fontColor"
:active-color="activeColor"
:border-color="noBorderColor"
:border-active-color="borderActiveColor"
>
<template :key="tabItem.name" v-for="(tabItem, index) in element.propValue">
<el-tab-pane
class="el-tab-pane-custom"
:lazy="isEditMode"
:label="tabItem.title"
:name="tabItem.name"
>
<template #label>
<span :style="titleStyle(tabItem.name)">{{ tabItem.title }}</span>
<el-dropdown
v-if="isEditMode"
:effect="curThemes"
style="line-height: 4 !important"
trigger="click"
@command="handleCommand"
>
<span class="el-dropdown-link">
<el-icon v-if="isEdit"><ArrowDown /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="beforeHandleCommand('editTitle', tabItem)">
编辑标题
</el-dropdown-item>
<el-dropdown-item
v-if="element.propValue.length > 1"
:command="beforeHandleCommand('deleteCur', tabItem)"
>
删除
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<de-canvas
v-if="isEdit && !mobileInPc"
:ref="'tabCanvas_' + index"
:component-data="tabItem.componentData"
:canvas-style-data="canvasStyleData"
:canvas-view-info="canvasViewInfo"
:canvas-id="element.id + '--' + tabItem.name"
:class="moveActive ? 'canvas-move-in' : ''"
:canvas-active="editableTabsValue === tabItem.name"
></de-canvas>
<de-preview
v-else
:ref="'dashboardPreview'"
:dv-info="dvInfo"
:cur-gap="curPreviewGap"
:component-data="tabItem.componentData"
:canvas-style-data="canvasStyleData"
:canvas-view-info="canvasViewInfo"
:canvas-id="element.id + '--' + tabItem.name"
:preview-active="editableTabsValue === tabItem.name"
:show-position="showPosition"
:outer-scale="scale"
></de-preview>
</el-tab-pane>
</template>
</de-custom-tab>
<el-dialog
title="编辑标题"
:append-to-body="true"
v-model="state.dialogVisible"
width="30%"
:show-close="false"
:close-on-click-modal="false"
center
>
<el-input
v-model="state.textarea"
maxlength="50"
:placeholder="$t('dataset.input_content')"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="state.dialogVisible = false">取消</el-button>
<el-button :disabled="!titleValid" type="primary" @click="sureCurTitle">确认</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import {
computed,
getCurrentInstance,
nextTick,
onBeforeMount,
onMounted,
reactive,
ref,
toRefs,
watch
} from 'vue'
import DeCanvas from '@/views/canvas/DeCanvas.vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import { guid } from '@/views/visualized/data/dataset/form/util'
import eventBus from '@/utils/eventBus'
import { canvasChangeAdaptor, findComponentIndexById, isDashboard } from '@/utils/canvasUtils'
import DeCustomTab from '@/custom-component/de-tabs/DeCustomTab.vue'
import DePreview from '@/components/data-visualization/canvas/DePreview.vue'
import { useEmitt } from '@/hooks/web/useEmitt'
import { getPanelAllLinkageInfo } from '@/api/visualization/linkage'
import { dataVTabComponentAdd, groupSizeStyleAdaptor } from '@/utils/style'
const dvMainStore = dvMainStoreWithOut()
const { tabMoveInActiveId, bashMatrixInfo, editMode, mobileInPc } = storeToRefs(dvMainStore)
const tabComponentRef = ref(null)
let carouselTimer = null
const props = defineProps({
canvasStyleData: {
type: Object,
required: true
},
canvasViewInfo: {
type: Object,
required: true
},
dvInfo: {
type: Object,
required: true
},
element: {
type: Object,
default() {
return {
propValue: []
}
}
},
isEdit: {
type: Boolean,
default: false
},
showPosition: {
type: String,
required: false,
default: 'canvas'
},
scale: {
type: Number,
required: false,
default: 1
}
})
const { element, isEdit, showPosition, canvasStyleData, canvasViewInfo, dvInfo, scale } =
toRefs(props)
const state = reactive({
activeTabName: '',
curItem: {},
textarea: '',
dialogVisible: false,
tabShow: true
})
const tabsAreaScroll = ref(false)
const editableTabsValue = ref(null)
//
const noBorderColor = ref('none')
let currentInstance
const isEditMode = computed(() => editMode.value === 'edit' && isEdit.value && !mobileInPc.value)
const curThemes = isDashboard() ? 'light' : 'dark'
const calcTabLength = () => {
setTimeout(() => {
if (element.value.propValue.length > 1) {
const containerDom = document.getElementById(
'tab-' + element.value.propValue[element.value.propValue.length - 1].name
)
tabsAreaScroll.value =
containerDom.parentNode.clientWidth > tabComponentRef.value.clientWidth - 100
} else {
tabsAreaScroll.value = false
}
})
}
const beforeHandleCommand = (item, param) => {
return {
command: item,
param: param
}
}
const curPreviewGap = computed(() =>
dvInfo.value.type === 'dashboard' && canvasStyleData.value['dashboard'].gap === 'yes'
? canvasStyleData.value['dashboard'].gapSize
: 0
)
function sureCurTitle() {
state.curItem.title = state.textarea
state.dialogVisible = false
}
function addTab() {
const newName = guid()
const newTab = {
name: newName,
title: '新建Tab',
componentData: [],
closable: true
}
element.value.propValue.push(newTab)
editableTabsValue.value = newTab.name
}
function deleteCur(param) {
state.curItem = param
let len = element.value.propValue.length
while (len--) {
if (element.value.propValue[len].name === param.name) {
element.value.propValue.splice(len, 1)
const activeIndex =
(len - 1 + element.value.propValue.length) % element.value.propValue.length
editableTabsValue.value = element.value.propValue[activeIndex].name
state.tabShow = false
nextTick(() => {
state.tabShow = true
})
}
}
}
function editCurTitle(param) {
state.activeTabName = param.name
state.curItem = param
state.textarea = param.title
state.dialogVisible = true
}
function handleCommand(command) {
switch (command.command) {
case 'editTitle':
editCurTitle(command.param)
break
case 'deleteCur':
deleteCur(command.param)
break
}
}
const reloadLinkage = () => {
//
if (dvInfo.value.id) {
getPanelAllLinkageInfo(dvInfo.value.id).then(rsp => {
dvMainStore.setNowPanelTrackInfo(rsp.data)
})
}
}
const componentMoveIn = component => {
element.value.propValue.forEach((tabItem, index) => {
if (editableTabsValue.value === tabItem.name) {
//index
const curIndex = findComponentIndexById(component.id)
//
if (isDashboard()) {
eventBus.emit('removeMatrixItem-canvas-main', curIndex)
dvMainStore.setCurComponent({ component: null, index: null })
component.canvasId = element.value.id + '--' + tabItem.name
const refInstance = currentInstance.refs['tabCanvas_' + index][0]
if (refInstance) {
const matrixBase = refInstance.getBaseMatrixSize() //
canvasChangeAdaptor(component, matrixBase)
component.x = 1
component.y = 200
component.style.left = 0
component.style.top = 0
tabItem.componentData.push(component)
if (isDashboard()) {
nextTick(() => {
refInstance.addItemBox(component) //
})
}
}
} else {
//
dvMainStore.deleteComponent(curIndex)
dvMainStore.setCurComponent({ component: null, index: null })
component.canvasId = element.value.id + '--' + tabItem.name
dataVTabComponentAdd(component, element.value.style)
}
}
})
reloadLinkage()
}
const componentMoveOut = component => {
canvasChangeAdaptor(component, bashMatrixInfo.value, true)
// Tab
eventBus.emit('removeMatrixItemById-' + component.canvasId, component.id)
dvMainStore.setCurComponent({ component: null, index: null })
//
if (isDashboard()) {
eventBus.emit('moveOutFromTab-canvas-main', component)
} else {
addToMain(component)
}
reloadLinkage()
}
const addToMain = component => {
component.canvasId = 'canvas-main'
dvMainStore.addComponent({
component,
index: undefined,
isFromGroup: true
})
}
const moveActive = computed(() => {
return tabMoveInActiveId.value && tabMoveInActiveId.value === element.value.id
})
const headClass = computed(() => {
if (tabsAreaScroll.value) {
return 'tab-head-left'
} else {
return 'tab-head-' + element.value.style.headHorizontalPosition
}
})
const titleStyle = itemName => {
if (editableTabsValue.value === itemName) {
return {
fontSize: (element.value.style.activeFontSize || 18) * scale.value + 'px'
}
} else {
return {
fontSize: (element.value.style.fontSize || 16) * scale.value + 'px'
}
}
}
const fontColor = computed(() => {
if (
element.value &&
element.value.style &&
element.value.style.headFontColor &&
typeof element.value.style.headFontColor === 'string'
) {
return element.value.style.headFontColor
} else {
return 'none'
}
})
const activeColor = computed(() => {
if (
element.value &&
element.value.style &&
element.value.style.headFontActiveColor &&
typeof element.value.style.headFontActiveColor === 'string'
) {
return element.value.style.headFontActiveColor
} else {
return 'none'
}
})
const borderActiveColor = computed(() => {
if (
element.value &&
element.value.style &&
element.value.style.headBorderActiveColor &&
typeof element.value.style.headBorderActiveColor === 'string'
) {
return element.value.style.headBorderActiveColor
} else {
return 'none'
}
})
const titleValid = computed(() => {
return !!state.textarea && !!state.textarea.trim()
})
watch(
() => element.value,
() => {
calcTabLength()
},
{ deep: true }
)
watch(
() => editableTabsValue.value,
() => {
nextTick(() => {
useEmitt().emitter.emit('tabCanvasChange-' + activeCanvasId.value)
})
},
{ deep: true }
)
const activeCanvasId = computed(() => {
return element.value.id + '--' + editableTabsValue.value
})
const reShow = () => {
state.tabShow = false
nextTick(() => {
state.tabShow = true
})
}
watch(
() => isEditMode.value,
() => {
initCarousel()
}
)
const initCarousel = () => {
carouselTimer && clearInterval(carouselTimer)
carouselTimer = null
if (!isEditMode.value) {
if (element.value.carousel?.enable) {
const switchTime = (element.value.carousel.time || 5) * 1000
let switchCount = 1
//
carouselTimer = setInterval(() => {
const nowIndex = switchCount % element.value.propValue.length
switchCount++
nextTick(() => {
editableTabsValue.value = element.value.propValue[nowIndex].name
})
}, switchTime)
}
}
}
onMounted(() => {
if (element.value.propValue.length > 0) {
editableTabsValue.value = element.value.propValue[0].name
}
calcTabLength()
eventBus.on('onTabMoveIn-' + element.value.id, componentMoveIn)
eventBus.on('onTabMoveOut-' + element.value.id, componentMoveOut)
eventBus.on('onTabSortChange-' + element.value.id, reShow)
currentInstance = getCurrentInstance()
initCarousel()
nextTick(() => {
groupSizeStyleAdaptor(element.value)
})
})
onBeforeMount(() => {
eventBus.off('onTabMoveIn-' + element.value.id, componentMoveIn)
eventBus.off('onTabMoveOut-' + element.value.id, componentMoveOut)
eventBus.off('onTabSortChange-' + element.value.id, reShow)
if (carouselTimer) {
clearInterval(carouselTimer)
carouselTimer = null
}
})
</script>
<style lang="less" scoped>
:deep(.ed-tabs__content) {
height: calc(100% - 46px) !important;
}
.ed-tabs-dark {
:deep(.ed-tabs__new-tab) {
margin-right: 25px;
color: #fff;
}
:deep(.el-dropdown-link) {
color: #fff;
}
}
.ed-tabs-light {
:deep(.ed-tabs__new-tab) {
margin-right: 25px;
background-color: #fff;
}
}
.el-tab-pane-custom {
width: 100%;
height: 100%;
}
.canvas-move-in {
border: 2px dotted transparent;
border-color: blueviolet;
}
.tab-head-left :deep(.ed-tabs__nav-scroll) {
display: flex;
justify-content: flex-start;
}
.tab-head-right :deep(.ed-tabs__nav-scroll) {
display: flex;
justify-content: flex-end;
}
.tab-head-center :deep(.ed-tabs__nav-scroll) {
display: flex;
justify-content: center;
}
</style>