{
trigger="click"
placement="bottom-start"
effect="dark"
- hide-timeout="0"
+ :hide-timeout="0"
>
@@ -313,7 +295,7 @@ const handleContextMenu = e => {
trigger="contextmenu"
placement="bottom-start"
effect="dark"
- hide-timeout="0"
+ :hide-timeout="0"
>
+import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
+import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
+import { layerStoreWithOut } from '@/store/modules/data-visualization/layer'
+import { storeToRefs } from 'pinia'
+import { ElIcon, ElRow } from 'element-plus-secondary'
+import Icon from '../icon-custom/src/Icon.vue'
+import { nextTick, ref } from 'vue'
+import draggable from 'vuedraggable'
+import { lockStoreWithOut } from '@/store/modules/data-visualization/lock'
+import ContextMenuAsideDetails from '@/components/data-visualization/canvas/ContextMenuAsideDetails.vue'
+import ComposeShow from '@/components/data-visualization/canvas/ComposeShow.vue'
+import { composeStoreWithOut } from '@/store/modules/data-visualization/compose'
+import RealTimeGroup from '@/components/data-visualization/RealTimeGroup.vue'
+const dropdownMore = ref(null)
+const lockStore = lockStoreWithOut()
+
+const dvMainStore = dvMainStoreWithOut()
+const snapshotStore = snapshotStoreWithOut()
+const layerStore = layerStoreWithOut()
+const composeStore = composeStoreWithOut()
+
+const { areaData, isCtrlOrCmdDown, isShiftDown, laterIndex } = storeToRefs(composeStore)
+
+const { componentData, curComponent, canvasViewInfo } = storeToRefs(dvMainStore)
+const getComponent = index => {
+ return componentData.value[componentData.value.length - 1 - index]
+}
+const transformIndex = index => {
+ return componentData.value.length - 1 - index
+}
+const areaDataPush = component => {
+ if (component && !component.isLock && component.isShow) {
+ areaData.value.components.push(component)
+ }
+}
+// shift 选择算法逻辑
+// 1.记录上次点击的laterIndex(初始状态laterIndex=0);
+// 2.获取当前index curClickIndex;
+// 3.比较laterIndex 和 curClickIndex之间的大小;
+// 4.将[laterIndex,curClickIndex] 或者 [curClickIndex,laterIndex]区域的图层加入areaData.value.components(已包含的不再重复加入);
+const shiftDataPush = curClickIndex => {
+ const areaDataIdArray = areaData.value.components.map(com => com.id)
+ let indexBegin, indexEnd
+ const laterIndexTrans = laterIndex.value === null ? componentData.value.length : laterIndex.value
+ if (laterIndexTrans < curClickIndex) {
+ indexBegin = laterIndexTrans
+ indexEnd = curClickIndex
+ } else {
+ indexBegin = curClickIndex
+ indexEnd = laterIndexTrans
+ }
+ const shiftAreaComponents = componentData.value
+ .slice(indexBegin, indexEnd + 1)
+ .filter(
+ component => !areaDataIdArray.includes(component.id) && !component.isLock && component.isShow
+ )
+ areaData.value.components.push(...shiftAreaComponents)
+ dvMainStore.setCurComponent({ component: null, index: null })
+}
+
+const onClick = (e, index) => {
+ // 初始化点击是 laterIndex=0
+ if (!curComponent.value) {
+ composeStore.setLaterIndex(null)
+ }
+ // ctrl or command 按下时 鼠标点击为选择需要组合的组件(取消需要组合的组件在ComposeShow组件中)
+ if (isCtrlOrCmdDown.value && !areaData.value.components.includes(componentData.value[index])) {
+ areaDataPush(componentData.value[index])
+ if (curComponent.value && curComponent.value.id !== componentData.value[index].id) {
+ areaDataPush(curComponent.value)
+ }
+ dvMainStore.setCurComponent({ component: null, index: null })
+ e.stopPropagation()
+ composeStore.setLaterIndex(index)
+ return
+ }
+ //shift操作逻辑
+ if (isShiftDown.value) {
+ shiftDataPush(index)
+ return
+ }
+
+ //其他情况点击清理选择区域
+ areaData.value.components.splice(0, areaData.value.components.length)
+ setCurComponent(index)
+ composeStore.setLaterIndex(index)
+}
+const setCurComponent = index => {
+ dvMainStore.setCurComponent({ component: componentData.value[index], index })
+}
+
+let nameEdit = ref(false)
+let editComponentId = ref('')
+let inputName = ref('')
+let nameInput = ref(null)
+let curEditComponent = null
+const editComponentName = item => {
+ curEditComponent = curComponent.value
+ editComponentId.value = `#component-label-${item.id}`
+ nameEdit.value = true
+ inputName.value = item.name
+ nextTick(() => {
+ nameInput.value.focus()
+ })
+}
+const closeEditComponentName = () => {
+ nameEdit.value = false
+ if (!inputName.value || !inputName.value.trim()) {
+ return
+ }
+ if (inputName.value.trim() === curEditComponent.name) {
+ return
+ }
+ curEditComponent.name = inputName.value
+ inputName.value = ''
+ curEditComponent = null
+}
+
+const lock = () => {
+ setTimeout(() => {
+ lockStore.lock()
+ snapshotStore.recordSnapshotCache('realTime-lock')
+ })
+}
+
+const unlock = () => {
+ setTimeout(() => {
+ lockStore.unlock()
+ snapshotStore.recordSnapshotCache('realTime-unlock')
+ })
+}
+
+const hideComponent = () => {
+ setTimeout(() => {
+ layerStore.hideComponent()
+ snapshotStore.recordSnapshotCache('realTime-hideComponent')
+ })
+}
+
+const showComponent = () => {
+ setTimeout(() => {
+ layerStore.showComponent()
+ snapshotStore.recordSnapshotCache()
+ })
+}
+
+const dragOnEnd = ({ oldIndex, newIndex }) => {
+ const source = componentData.value[newIndex]
+ const comLength = componentData.value.length
+ // 还原数组
+ componentData.value.splice(newIndex, 1)
+ componentData.value.splice(oldIndex, 0, source)
+ const target = componentData.value[comLength - 1 - oldIndex]
+ // 反向移动数组
+ componentData.value.splice(comLength - 1 - oldIndex, 1)
+ componentData.value.splice(comLength - 1 - newIndex, 0, target)
+ dvMainStore.setCurComponent({ component: target, index: transformIndex(comLength - oldIndex) })
+}
+
+const getIconName = item => {
+ if (item.component === 'UserView') {
+ const viewInfo = canvasViewInfo.value[item.id]
+ return `${viewInfo.type}-origin`
+ } else {
+ return item.icon
+ }
+}
+
+const menuAsideClose = (param, index) => {
+ const iconDom = document.getElementById('close-button')
+ if (iconDom) {
+ iconDom.click()
+ }
+ if (param.opt === 'rename') {
+ setTimeout(() => {
+ editComponentName(getComponent(index))
+ }, 200)
+ }
+}
+
+const handleContextMenu = e => {
+ e.preventDefault()
+ // 获取鼠标点击位置
+ const x = e.clientX
+ const y = e.clientY
+ const customContextMenu = document.createElement('div')
+ customContextMenu.style.position = 'fixed'
+ customContextMenu.style.left = x + 'px'
+ customContextMenu.style.top = y + 'px'
+
+ // 将自定义菜单添加到页面
+ document.body.appendChild(customContextMenu)
+
+ // 为自定义菜单添加事件监听器,例如,点击菜单项后执行的操作
+ customContextMenu.addEventListener('click', () => {
+ // 在这里执行菜单项点击后的操作
+ // 例如,关闭菜单
+ document.body.removeChild(customContextMenu)
+ })
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getComponent(index)?.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/core-frontend/src/views/data-visualization/index.vue b/core/core-frontend/src/views/data-visualization/index.vue
index 960a6e282f..559c0e15bc 100644
--- a/core/core-frontend/src/views/data-visualization/index.vue
+++ b/core/core-frontend/src/views/data-visualization/index.vue
@@ -25,6 +25,7 @@ import { changeComponentSizeWithScale } from '@/utils/changeComponentsSizeWithSc
import { useEmitt } from '@/hooks/web/useEmitt'
import { check, compareStorage } from '@/utils/CrossPermission'
import { useCache } from '@/hooks/web/useCache'
+import RealTimeListTree from '@/components/data-visualization/RealTimeListTree.vue'
const { wsCache } = useCache()
const eventCheck = e => {
if (e.key === 'screen-weight' && !compareStorage(e.oldValue, e.newValue)) {
@@ -253,7 +254,7 @@ eventBus.on('handleNew', handleNew)
id="dv-main-left-sidebar"
:class="{ 'preview-aside': previewStatus }"
>
-
+