refactor: dashboard canvas edit update

This commit is contained in:
wangjiahao
2025-07-18 14:03:11 +08:00
parent 2eef41131d
commit b498355d44
10 changed files with 115 additions and 8 deletions
+1
View File
@@ -32,6 +32,7 @@
"password_reset_successful": "Password reset successful"
},
"dashboard": {
"add_component_tips": "Select components from the top toolbar and add them here to create a dashboard",
"add_view": "Add Chart",
"delete_dashboard_warn": "Delete This Dashboard: {0}",
"rename_dashboard": "Rename Dashboard",
+1
View File
@@ -34,6 +34,7 @@
"password_reset_successful": "重置密码成功"
},
"dashboard": {
"add_component_tips": "从顶部工具栏中选择组件,添加到这里创建仪表板",
"add_view": "添加图表",
"delete_dashboard_warn": "是否删除仪表板:{0}",
"rename_dashboard": "重命名仪表板",
@@ -35,6 +35,9 @@ export const dashboardStore = defineStore('dashboard', {
},
},
actions: {
setFullscreenFlag(val: boolean) {
this.fullscreenFlag = val
},
setCurComponent(value: any) {
this.curComponent = value
this.curComponentId = value && value.id ? value.id : null
@@ -8,7 +8,10 @@ import { findComponent } from '@/views/dashboard/components/component-list.ts'
import { storeToRefs } from 'pinia'
import { useEmitt, useEmittLazy } from '@/utils/useEmitt.ts'
import html2canvas from 'html2canvas'
import EmptyBackground from '@/views/dashboard/common/EmptyBackground.vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const dashboardStore = dashboardStoreWithOut()
const canvasLocked = ref(false) // Is the canvas movement locked, Default false
const emits = defineEmits(['parentAddItemBox'])
@@ -1174,6 +1177,11 @@ defineExpose({
@mouseup="endMove()"
@mousemove="moving()"
>
<EmptyBackground
v-if="!canvasComponentData.length"
:description="t('dashboard.add_component_tips')"
img-type="selectDashboard"
/>
<template v-if="renderOk">
<CanvasShape
v-for="(item, index) in canvasComponentData"
@@ -3,7 +3,7 @@ import { type PropType } from 'vue'
import nothingInput from '@/assets/img/nothing-input.png'
import nothingSelect from '@/assets/img/nothing-select.png'
import nothingTable from '@/assets/img/nothing-table.png'
import nothingSelectDashoard from '@/assets/img/none-dashboard.png'
import nothingSelectDashboard from '@/assets/img/none-dashboard.png'
import none from '@/assets/img/none.png'
import error from '@/assets/img/error.png'
import nothingTree from '@/assets/img/nothing-tree.png'
@@ -30,7 +30,7 @@ const getAssetsFile = {
table: nothingTable,
noneWhite: nothingNone,
tree: nothingTree,
selectDashboard: nothingSelectDashoard,
selectDashboard: nothingSelectDashboard,
error,
none,
}
@@ -0,0 +1,64 @@
<script lang="ts" setup>
import { dashboardStoreWithOut } from '@/stores/dashboard/dashboard.ts'
const dashboardStore = dashboardStoreWithOut()
import { nextTick, onBeforeUnmount, onMounted } from 'vue'
import { useEmitt } from '@/utils/useEmitt.ts'
defineProps({
themes: {
type: String,
default: 'light',
},
componentType: {
type: String,
default: 'button',
},
showPosition: {
required: false,
type: String,
default: 'preview',
},
})
const fullscreenChange = () => {
const isFullscreen = !!document.fullscreenElement
dashboardStore.setFullscreenFlag(isFullscreen)
setTimeout(() => {
useEmitt().emitter.emit('custom-canvas-resize')
}, 100)
}
const toggleFullscreen = () => {
const bodyNode = document.querySelector('body')
if (!document.fullscreenElement) {
bodyNode?.requestFullscreen()
} else {
document.exitFullscreen()
}
}
// 针对钉钉windows版无法退出全屏问题 这里主动退出
const handleKeydown = (event) => {
if (event.key === 'Escape' && document.fullscreenElement) {
document.exitFullscreen()
}
}
onMounted(() => {
document.addEventListener('fullscreenchange', fullscreenChange)
document.addEventListener('keydown', handleKeydown)
})
onBeforeUnmount(() => {
document.removeEventListener('fullscreenchange', fullscreenChange)
document.removeEventListener('keydown', handleKeydown)
})
defineExpose({
toggleFullscreen,
})
</script>
<template><span></span></template>
<style lang="less" scoped></style>
@@ -2,6 +2,7 @@
position: relative;
user-select: none;
width: 100%;
height: 100%;
* {
box-sizing: border-box;
@@ -2,7 +2,7 @@
import CanvasCore from '@/views/dashboard/canvas/CanvasCore.vue'
import { nextTick, onMounted, type PropType, ref } from 'vue'
import type { CanvasItem } from '@/utils/canvas.ts'
import { useEmittLazy } from '@/utils/useEmitt.ts'
import { useEmitt, useEmittLazy } from '@/utils/useEmitt.ts'
const canvasCoreRef = ref(null)
const dashboardEditorRef = ref(null)
@@ -85,6 +85,11 @@ const addItemToBox = (item: CanvasItem) => {
canvasCoreRef.value.addItemBox(item)
}
useEmitt({
name: 'custom-canvas-resize',
callback: canvasSizeInit,
})
defineExpose({
canvasSizeInit,
addItemToBox,
@@ -14,10 +14,11 @@ import icon_redo_outlined from '@/assets/svg/icon_redo_outlined.svg'
import icon_arrow_left_outlined from '@/assets/svg/icon_arrow-left_outlined.svg'
import { saveDashboardResource } from '@/views/dashboard/utils/canvasUtils.ts'
import ChatChartSelection from '@/views/dashboard/editor/ChatChartSelection.vue'
import icon_pc_outlined from '@/assets/svg/icon_pc_outlined.svg'
const fullScreeRef = ref(null)
const { t } = useI18n()
const dashboardStore = dashboardStoreWithOut()
const { dashboardInfo } = storeToRefs(dashboardStore)
const { dashboardInfo, fullscreenFlag } = storeToRefs(dashboardStore)
const snapshotStore = snapshotStoreWithOut()
const { snapshotIndex } = storeToRefs(snapshotStore)
@@ -30,6 +31,7 @@ const openViewDialog = () => {
}
import cloneDeep from 'lodash/cloneDeep'
import SQFullscreen from '@/views/dashboard/common/SQFullscreen.vue'
let nameEdit = ref(false)
let inputName = ref('')
@@ -136,10 +138,16 @@ const addChatChart = (views: any) => {
emits('addComponent', 'SQView', cloneDeep(view))
})
}
const previewInner = () => {
if (fullScreeRef.value) {
fullScreeRef.value.toggleFullscreen()
}
}
</script>
<template>
<div class="toolbar-main">
<div class="toolbar-main" :class="{ 'toolbar-main-hidden': fullscreenFlag }">
<el-icon class="custom-el-icon back-icon" @click="backToMain()">
<Icon name="icon_left_outlined">
<icon_arrow_left_outlined class="toolbar-hover-icon toolbar-icon" />
@@ -204,6 +212,14 @@ const addChatChart = (views: any) => {
</component-button-label>
</div>
<div class="right-toolbar">
<el-button secondary @click="previewInner">
<template #icon>
<icon name="icon_pc_outlined">
<icon_pc_outlined class="svg-icon" />
</icon>
</template>
{{ t('dashboard.preview') }}
</el-button>
<el-button
style="float: right; margin-right: 12px"
type="primary"
@@ -226,10 +242,14 @@ const addChatChart = (views: any) => {
@add-chat-chart="addChatChart"
@finish="chartSelectionFinish"
></ChatChartSelection>
<SQFullscreen ref="fullScreeRef" show-position="edit"></SQFullscreen>
</div>
</template>
<style scoped lang="less">
.toolbar-main-hidden {
display: none !important;
}
.toolbar-main {
width: 100%;
height: 56px;
@@ -13,7 +13,7 @@ import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const dashboardStore = dashboardStoreWithOut()
const { componentData, canvasViewInfo } = storeToRefs(dashboardStore)
const { componentData, canvasViewInfo, fullscreenFlag } = storeToRefs(dashboardStore)
const dataInitState = ref(true)
const state = reactive({
@@ -75,7 +75,7 @@ const baseParams = computed(() => {
</script>
<template>
<div class="editor-content">
<div class="editor-content" :class="{ 'editor-content-fullscreen': fullscreenFlag }">
<div class="editor-main">
<Toolbar :base-params="baseParams" @add-component="addComponent"></Toolbar>
<DashboardEditor
@@ -97,6 +97,10 @@ const baseParams = computed(() => {
background: #fff;
overflow: hidden;
}
.editor-content-fullscreen {
padding: 0 !important;
}
.editor-main {
border-radius: 12px;
position: relative;