mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
refactor: dashboard view
This commit is contained in:
@@ -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 ###
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ''
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)!
|
||||
|
||||
@@ -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)"
|
||||
>
|
||||
<component
|
||||
:is="findComponent(item.component)"
|
||||
:ref="'shape_component_' + item.id"
|
||||
class="sql-component dragHandle"
|
||||
class="sql-component slot-component dragHandle"
|
||||
:config-item="item"
|
||||
:view-info="canvasViewInfo[item.id]"
|
||||
@parent-add-item-box="(subItem: any) => addItemBox(subItem)"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import { type CanvasItem } from '@/utils/canvas.ts'
|
||||
import { ref, toRefs, type PropType } from 'vue'
|
||||
import ResizeHandle from '@/views/dashboard/canvas/ResizeHandle.vue'
|
||||
import DragHandle from '@/views/dashboard/canvas/DragHandle.vue'
|
||||
import ComponentBar from '@/views/dashboard/canvas/ComponentBar.vue'
|
||||
|
||||
const shapeRef = ref(null)
|
||||
// Props
|
||||
@@ -38,6 +40,10 @@ const props = defineProps({
|
||||
return {}
|
||||
},
|
||||
},
|
||||
canvasId: {
|
||||
type: String,
|
||||
default: 'canvas-main',
|
||||
},
|
||||
})
|
||||
|
||||
const { draggable } = toRefs(props)
|
||||
@@ -61,6 +67,13 @@ const shapeClick = (e: MouseEvent) => {
|
||||
@click="shapeClick"
|
||||
@mousedown="startMove($event, configItem, itemIndex)"
|
||||
>
|
||||
<component-bar
|
||||
:config-item="configItem"
|
||||
:active="active"
|
||||
:show-position="'canvas'"
|
||||
:canvas-id="canvasId"
|
||||
></component-bar>
|
||||
<drag-handle></drag-handle>
|
||||
<slot></slot>
|
||||
<resize-handle
|
||||
v-if="active"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<script setup lang="ts">
|
||||
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)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="component-bar-main" :class="{ 'bar-hidden': !active }">
|
||||
<div>
|
||||
<el-icon class="handle-icon" @click="doDeleteComponent">
|
||||
<Icon>
|
||||
<icon_delete class="svg-icon"></icon_delete>
|
||||
</Icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.component-bar-main {
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
display: flex;
|
||||
z-index: 5;
|
||||
cursor: pointer !important;
|
||||
.handle-icon {
|
||||
color: #646a73;
|
||||
}
|
||||
&:hover {
|
||||
background-color: #e8f0fe;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.bar-hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -60,7 +60,7 @@ const shadowStyle = (size: number, index: number) => {
|
||||
.dragHandle {
|
||||
background: #c1e2e8;
|
||||
position: absolute;
|
||||
cursor: move;
|
||||
cursor: move !important;
|
||||
z-index: 3;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ const curSelectChange = (value: boolean) => {
|
||||
position: relative;
|
||||
padding: 15px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
.select-area {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
|
||||
@@ -272,6 +272,7 @@ const addChatChart = (views: any) => {
|
||||
width: 300px;
|
||||
text-align: left;
|
||||
color: #a6a6a6;
|
||||
display: none;
|
||||
|
||||
.opt-icon-redo {
|
||||
margin-left: 12px;
|
||||
|
||||
@@ -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(() => {
|
||||
<Toolbar :base-params="baseParams" @add-component="addComponent"></Toolbar>
|
||||
<DashboardEditor
|
||||
v-if="dataInitState"
|
||||
ref="dashboardEditorRef"
|
||||
ref="dashboardEditorInnerRef"
|
||||
:canvas-component-data="componentData"
|
||||
:canvas-view-info="canvasViewInfo"
|
||||
>
|
||||
|
||||
@@ -55,14 +55,13 @@ const viewDemoInnerId = computed(() => 'enlarge-inner-content-' + configItem.val
|
||||
<style lang="less" scoped>
|
||||
.wrapper-outer {
|
||||
position: absolute;
|
||||
|
||||
overflow: hidden;
|
||||
.wrapper-inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
background-size: 100% 100% !important;
|
||||
|
||||
.wrapper-inner-adaptor {
|
||||
position: relative;
|
||||
transform-style: preserve-3d;
|
||||
|
||||
@@ -9,6 +9,7 @@ import { dashboardStoreWithOut } from '@/stores/dashboard/dashboard.ts'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import SQComponentWrapper from '@/views/dashboard/preview/SQComponentWrapper.vue'
|
||||
import type { CanvasItem } from '@/utils/canvas.ts'
|
||||
import { useEmittLazy } from '@/utils/useEmitt.ts'
|
||||
|
||||
const props = defineProps({
|
||||
canvasStyleData: {
|
||||
@@ -48,7 +49,7 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const { canvasStyleData, componentData, showPosition, canvasId } = toRefs(props)
|
||||
const { componentData, showPosition, canvasId } = toRefs(props)
|
||||
const domId = 'preview-' + canvasId.value
|
||||
const previewCanvas = ref(null)
|
||||
const renderReady = ref(true)
|
||||
@@ -93,6 +94,7 @@ const sizeInit = () => {
|
||||
cellWidth.value = baseWidth.value + baseMarginLeft.value
|
||||
cellHeight.value = baseHeight.value + baseMarginTop.value
|
||||
}
|
||||
useEmittLazy('view-render-all')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -120,7 +122,7 @@ defineExpose({
|
||||
:key="index"
|
||||
:active="!!curComponent && item.id === curComponent['id']"
|
||||
:config-item="item"
|
||||
:canvas-view-info="canvasStyleData"
|
||||
:canvas-view-info="canvasViewInfo"
|
||||
:show-position="showPosition"
|
||||
:canvas-id="canvasId"
|
||||
:style="nowItemStyle(item)"
|
||||
|
||||
@@ -3,37 +3,43 @@ import { dashboardStoreWithOut } from '@/stores/dashboard/dashboard.ts'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const dashboardStore = dashboardStoreWithOut()
|
||||
const { componentData, canvasStyleData } = storeToRefs(dashboardStore)
|
||||
const { componentData, canvasStyleData, canvasViewInfo } = storeToRefs(dashboardStore)
|
||||
|
||||
const workspace_id = 'default' // temp
|
||||
export const load_resource_prepare = (params: any, callBack: (obj: any) => void) => {
|
||||
dashboardApi.load_resource(params).then((canvasInfo: any) => {
|
||||
const dashboardInfo = {
|
||||
id: canvasInfo.id,
|
||||
name: canvasInfo.name,
|
||||
pid: canvasInfo.pid,
|
||||
workspaceId: canvasInfo.workspace_id,
|
||||
status: canvasInfo.status,
|
||||
type: canvasInfo.type,
|
||||
createName: canvasInfo.create_name,
|
||||
updateName: canvasInfo.update_name,
|
||||
createTime: canvasInfo.create_time,
|
||||
updateTime: canvasInfo.update_time,
|
||||
contentId: canvasInfo.content_id,
|
||||
}
|
||||
const canvasDataResult = JSON.parse(canvasInfo.component_data)
|
||||
const canvasStyleResult = JSON.parse(canvasInfo.canvas_style_data)
|
||||
const canvasViewInfoPreview = JSON.parse(canvasInfo.canvas_view_Info || '{}')
|
||||
callBack({ dashboardInfo, canvasDataResult, canvasStyleResult, canvasViewInfoPreview })
|
||||
})
|
||||
dashboardApi
|
||||
.load_resource(params)
|
||||
.then((canvasInfo: any) => {
|
||||
const dashboardInfo = {
|
||||
id: canvasInfo.id,
|
||||
name: canvasInfo.name,
|
||||
pid: canvasInfo.pid,
|
||||
workspaceId: canvasInfo.workspace_id,
|
||||
status: canvasInfo.status,
|
||||
type: canvasInfo.type,
|
||||
createName: canvasInfo.create_name,
|
||||
updateName: canvasInfo.update_name,
|
||||
createTime: canvasInfo.create_time,
|
||||
updateTime: canvasInfo.update_time,
|
||||
contentId: canvasInfo.content_id,
|
||||
}
|
||||
const canvasDataResult = JSON.parse(canvasInfo.component_data)
|
||||
const canvasStyleResult = JSON.parse(canvasInfo.canvas_style_data)
|
||||
const canvasViewInfoPreview = JSON.parse(canvasInfo.canvas_view_info || '{}')
|
||||
callBack({ dashboardInfo, canvasDataResult, canvasStyleResult, canvasViewInfoPreview })
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('load_resource_prepare', err)
|
||||
callBack({})
|
||||
})
|
||||
}
|
||||
|
||||
export const initCanvasData = (params: any, callBack: () => void) => {
|
||||
load_resource_prepare(params, function (result: any) {
|
||||
dashboardStore.setDashboardInfo(result.dashboardInfo)
|
||||
dashboardStore.setCanvasStyleData(result.canvasStyleResult)
|
||||
dashboardStore.setComponentData(result.canvasDataResult)
|
||||
dashboardStore.setCanvasViewInfo(result.canvasViewInfoPreview)
|
||||
dashboardStore.setDashboardInfo(result?.dashboardInfo)
|
||||
dashboardStore.setCanvasStyleData(result?.canvasStyleResult)
|
||||
dashboardStore.setComponentData(result?.canvasDataResult)
|
||||
dashboardStore.setCanvasViewInfo(result?.canvasViewInfoPreview)
|
||||
callBack()
|
||||
})
|
||||
}
|
||||
@@ -49,6 +55,7 @@ export const saveDashboardResource = (params: any, callBack: Function) => {
|
||||
...params,
|
||||
component_data: JSON.stringify(componentData.value),
|
||||
canvas_style_data: JSON.stringify(canvasStyleData.value),
|
||||
canvas_view_info: JSON.stringify(canvasViewInfo.value),
|
||||
}
|
||||
dashboardApi.create_canvas(requestParams).then((res: any) => {
|
||||
dashboardStore.updateDashboardInfo({ id: res.id, dataState: 'ready' })
|
||||
@@ -67,6 +74,7 @@ export const saveDashboardResource = (params: any, callBack: Function) => {
|
||||
...params,
|
||||
component_data: JSON.stringify(componentData.value),
|
||||
canvas_style_data: JSON.stringify(canvasStyleData.value),
|
||||
canvas_view_info: JSON.stringify(canvasViewInfo.value),
|
||||
}
|
||||
dashboardApi.update_canvas(requestParams).then(() => {
|
||||
callBack()
|
||||
|
||||
Reference in New Issue
Block a user