From 76b757823e90d2747f6a0f8bdd9775aa1a021d2d Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Thu, 19 Jun 2025 08:46:46 +0800 Subject: [PATCH] refactor: dashboard view --- .../941e2355a94d_011_update_dashboard.py | 4 +- .../apps/dashboard/crud/dashboard_service.py | 4 +- .../apps/dashboard/models/dashboard_model.py | 4 +- frontend/package.json | 4 +- frontend/src/style.less | 8 +++ frontend/src/utils/useEmitt.ts | 4 +- .../src/views/dashboard/canvas/CanvasCore.vue | 21 +++++- .../views/dashboard/canvas/CanvasShape.vue | 13 ++++ .../views/dashboard/canvas/ComponentBar.vue | 69 +++++++++++++++++++ .../src/views/dashboard/canvas/DragHandle.vue | 2 +- .../src/views/dashboard/css/CanvasStyle.less | 5 +- .../views/dashboard/editor/ChartSelection.vue | 1 + .../src/views/dashboard/editor/Toolbar.vue | 1 + frontend/src/views/dashboard/editor/index.vue | 10 +-- .../dashboard/preview/SQComponentWrapper.vue | 3 +- .../src/views/dashboard/preview/SQPreview.vue | 6 +- .../src/views/dashboard/utils/canvasUtils.ts | 56 ++++++++------- 17 files changed, 167 insertions(+), 48 deletions(-) create mode 100644 frontend/src/views/dashboard/canvas/ComponentBar.vue diff --git a/backend/alembic/versions/941e2355a94d_011_update_dashboard.py b/backend/alembic/versions/941e2355a94d_011_update_dashboard.py index b1a27e34..c9b3d0e2 100644 --- a/backend/alembic/versions/941e2355a94d_011_update_dashboard.py +++ b/backend/alembic/versions/941e2355a94d_011_update_dashboard.py @@ -18,11 +18,11 @@ depends_on = None def upgrade(): - op.add_column('core_dashboard', sa.Column('canvas_views', sa.Text(), nullable=True)) + op.add_column('core_dashboard', sa.Column('canvas_view_info', sa.Text(), nullable=True)) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_column('core_dashboard', 'canvas_views') + op.drop_column('core_dashboard', 'canvas_view_info') # ### end Alembic commands ### diff --git a/backend/apps/dashboard/crud/dashboard_service.py b/backend/apps/dashboard/crud/dashboard_service.py index 3824038f..93c59607 100644 --- a/backend/apps/dashboard/crud/dashboard_service.py +++ b/backend/apps/dashboard/crud/dashboard_service.py @@ -71,7 +71,7 @@ def create_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashb record.node_type = dashboard.node_type record.component_data = dashboard.component_data record.canvas_style_data = dashboard.canvas_style_data - record.canvas_views = dashboard.canvas_views + record.canvas_view_info = dashboard.canvas_view_info session.add(record) session.flush() session.refresh(record) @@ -86,7 +86,7 @@ def update_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashb record.update_time = int(time.time()) record.component_data = dashboard.component_data record.canvas_style_data = dashboard.canvas_style_data - record.canvas_views = dashboard.canvas_views + record.canvas_view_info = dashboard.canvas_view_info session.add(record) session.commit() return record diff --git a/backend/apps/dashboard/models/dashboard_model.py b/backend/apps/dashboard/models/dashboard_model.py index e3824452..a6c2c808 100644 --- a/backend/apps/dashboard/models/dashboard_model.py +++ b/backend/apps/dashboard/models/dashboard_model.py @@ -50,7 +50,7 @@ class CoreDashboard(SQLModel, table=True): default=None, sa_column=Column(Text, nullable=True) ) - canvas_views: str = Field( + canvas_view_info: str = Field( default=None, sa_column=Column(Text, nullable=True) ) @@ -160,5 +160,5 @@ class QueryDashboard(BaseDashboard): class CreateDashboard(QueryDashboard): canvas_style_data: str ='' component_data: str = '' - canvas_views: str = '' + canvas_view_info: str = '' description: str = '' diff --git a/frontend/package.json b/frontend/package.json index 8b6ad676..30ae5aac 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -18,6 +18,7 @@ "dependencies": { "@antv/g2": "^5.3.3", "@antv/s2": "^2.4.3", + "@eslint/js": "^9.28.0", "@npkg/tinymce-plugins": "^0.0.7", "@tinymce/tinymce-vue": "^5.1.0", "dayjs": "^1.11.13", @@ -27,7 +28,8 @@ "lodash": "^4.17.21", "lodash-es": "^4.17.21", "snowflake-id": "^1.1.0", - "tinymce": "^5.8.2", + "tinymce": "^5.10.9", + "html2canvas": "^1.4.1", "vue": "^3.5.13", "vue-dompurify-html": "^5.3.0", "vue-i18n": "^9.14.4", diff --git a/frontend/src/style.less b/frontend/src/style.less index dbc87dbd..7782fbd2 100644 --- a/frontend/src/style.less +++ b/frontend/src/style.less @@ -137,3 +137,11 @@ body { min-width: 780px !important; flex-wrap: wrap !important; } +.clone_img { + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + z-index: 100; +} diff --git a/frontend/src/utils/useEmitt.ts b/frontend/src/utils/useEmitt.ts index dedd8136..e637ce27 100644 --- a/frontend/src/utils/useEmitt.ts +++ b/frontend/src/utils/useEmitt.ts @@ -41,9 +41,9 @@ export const useEmitt = (option?: Option) => { * Debounced event emitter * @param eventName - Name of the event to emit * @param params - Parameters to pass with the event - * @param delay - Debounce delay in milliseconds (default: 300ms) + * @param delay - Debounce delay in milliseconds (default: 200ms) */ -export const useEmittLazy = (eventName: string, params: any = null, delay = 500) => { +export const useEmittLazy = (eventName: string, params: any = null, delay = 150) => { // If there's already a pending execution, skip this call if (lazyDebounceMap.has(eventName)) { const entry = lazyDebounceMap.get(eventName)! diff --git a/frontend/src/views/dashboard/canvas/CanvasCore.vue b/frontend/src/views/dashboard/canvas/CanvasCore.vue index 17bf1c72..fa3bb2f9 100644 --- a/frontend/src/views/dashboard/canvas/CanvasCore.vue +++ b/frontend/src/views/dashboard/canvas/CanvasCore.vue @@ -6,7 +6,8 @@ import { type CanvasCoord, type CanvasItem } from '@/utils/canvas.ts' import CanvasShape from './CanvasShape.vue' import { findComponent } from '@/views/dashboard/components/component-list.ts' import { storeToRefs } from 'pinia' -import { useEmittLazy } from '@/utils/useEmitt.ts' +import { useEmitt, useEmittLazy } from '@/utils/useEmitt.ts' +import html2canvas from 'html2canvas' const dashboardStore = dashboardStoreWithOut() const canvasLocked = ref(false) // Is the canvas movement locked, Default false @@ -815,7 +816,6 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) { infoBox.value.moveItem = item infoBox.value.moveItemIndex = index } - infoBox.value.cloneItem = null infoBox.value.nowItemNode = null // @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -829,6 +829,15 @@ function startMove(e: MouseEvent, item: CanvasItem, index: number) { infoBox.value.cloneItem = infoBox.value.nowItemNode.cloneNode(true) } infoBox.value.cloneItem.classList.add('cloneNode') + const img = new Image() + img.classList.add('clone_img') + const clonedSlot = infoBox.value.nowItemNode.querySelector('.slot-component') + + html2canvas(clonedSlot).then((canvas) => { + img.src = canvas.toDataURL() + infoBox.value.cloneItem.appendChild(img) + }) + if (containerRef.value) { containerRef.value.append(infoBox.value.cloneItem) } @@ -1130,6 +1139,11 @@ function tabMoveInCheckSQ() { } } +useEmitt({ + name: `editor-delete-${props.canvasId}`, + callback: removeItemById, +}) + onMounted(() => { currentInstance = getCurrentInstance() }) @@ -1171,12 +1185,13 @@ defineExpose({ :move-animate="moveAnimate" :start-move="startMove" :start-resize="startResize" + :canvas-id="canvasId" :style="nowItemStyle(item)" > { @click="shapeClick" @mousedown="startMove($event, configItem, itemIndex)" > + + +import { toRefs } from 'vue' +import icon_delete from '@/assets/svg/icon_delete.svg' +import { Icon } from '@/components/icon-custom' +import { useEmitt } from '@/utils/useEmitt.ts' + +const props = defineProps({ + active: { + type: Boolean, + default: false, + }, + configItem: { + type: Object, + required: true, + }, + showPosition: { + required: false, + type: String, + default: 'preview', + }, + canvasId: { + type: String, + default: 'canvas-main', + }, +}) + +const { configItem } = toRefs(props) + +const doDeleteComponent = (e: MouseEvent) => { + e.stopPropagation() + e.preventDefault() + useEmitt().emitter.emit(`editor-delete-${props.canvasId}`, configItem.value.id) +} + + + + + diff --git a/frontend/src/views/dashboard/canvas/DragHandle.vue b/frontend/src/views/dashboard/canvas/DragHandle.vue index 5a9d7864..8fb8ac80 100644 --- a/frontend/src/views/dashboard/canvas/DragHandle.vue +++ b/frontend/src/views/dashboard/canvas/DragHandle.vue @@ -60,7 +60,7 @@ const shadowStyle = (size: number, index: number) => { .dragHandle { background: #c1e2e8; position: absolute; - cursor: move; + cursor: move !important; z-index: 3; } diff --git a/frontend/src/views/dashboard/css/CanvasStyle.less b/frontend/src/views/dashboard/css/CanvasStyle.less index 88bf2e08..ee551fba 100644 --- a/frontend/src/views/dashboard/css/CanvasStyle.less +++ b/frontend/src/views/dashboard/css/CanvasStyle.less @@ -36,6 +36,7 @@ .sql-component { width: 100%; height: 100%; + overflow: hidden; } } @@ -76,7 +77,7 @@ } .slot-component { - display: none; + opacity: 0; } } @@ -105,4 +106,4 @@ border: 1px solid; } -} \ No newline at end of file +} diff --git a/frontend/src/views/dashboard/editor/ChartSelection.vue b/frontend/src/views/dashboard/editor/ChartSelection.vue index 6ed1996a..a402873d 100644 --- a/frontend/src/views/dashboard/editor/ChartSelection.vue +++ b/frontend/src/views/dashboard/editor/ChartSelection.vue @@ -36,6 +36,7 @@ const curSelectChange = (value: boolean) => { position: relative; padding: 15px; float: left; + overflow: hidden; .select-area { position: absolute; top: 20px; diff --git a/frontend/src/views/dashboard/editor/Toolbar.vue b/frontend/src/views/dashboard/editor/Toolbar.vue index c941b427..2ec55096 100644 --- a/frontend/src/views/dashboard/editor/Toolbar.vue +++ b/frontend/src/views/dashboard/editor/Toolbar.vue @@ -272,6 +272,7 @@ const addChatChart = (views: any) => { width: 300px; text-align: left; color: #a6a6a6; + display: none; .opt-icon-redo { margin-left: 12px; diff --git a/frontend/src/views/dashboard/editor/index.vue b/frontend/src/views/dashboard/editor/index.vue index a9c93e85..be6d1bb0 100644 --- a/frontend/src/views/dashboard/editor/index.vue +++ b/frontend/src/views/dashboard/editor/index.vue @@ -13,17 +13,17 @@ import { initCanvasData } from '@/views/dashboard/utils/canvasUtils.ts' const dashboardStore = dashboardStoreWithOut() const { componentData, canvasViewInfo } = storeToRefs(dashboardStore) -const dataInitState = ref(false) +const dataInitState = ref(true) const state = reactive({ routerPid: null, resourceId: null, opt: null, }) -const dashboardEditorRef = ref(null) +const dashboardEditorInnerRef = ref(null) const addComponent = (componentType: string, viewInfo?: any) => { const component = cloneDeep(findNewComponentFromList(componentType)) - if (component && dashboardEditorRef.value) { + if (component && dashboardEditorInnerRef.value) { component.id = guid() // add view if (component?.component === 'SQView' && !!viewInfo) { @@ -38,7 +38,7 @@ const addComponent = (componentType: string, viewInfo?: any) => { component.activeTabName = subTabName } // @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment - dashboardEditorRef.value.addItemToBox(component) + dashboardEditorInnerRef.value.addItemToBox(component) } } @@ -77,7 +77,7 @@ const baseParams = computed(() => { diff --git a/frontend/src/views/dashboard/preview/SQComponentWrapper.vue b/frontend/src/views/dashboard/preview/SQComponentWrapper.vue index a6c42c0a..c742a428 100644 --- a/frontend/src/views/dashboard/preview/SQComponentWrapper.vue +++ b/frontend/src/views/dashboard/preview/SQComponentWrapper.vue @@ -55,14 +55,13 @@ const viewDemoInnerId = computed(() => 'enlarge-inner-content-' + configItem.val