Skip to content

Commit 0c98f3c

Browse files
committed
refactor: dashboard view
1 parent aebcace commit 0c98f3c

File tree

15 files changed

+322
-44
lines changed

15 files changed

+322
-44
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""msg...
2+
3+
Revision ID: 941e2355a94d
4+
Revises: 8dc3b1bdbfef
5+
Create Date: 2025-06-18 14:58:21.977676
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
from sqlalchemy.dialects import postgresql
12+
13+
# revision identifiers, used by Alembic.
14+
revision = '941e2355a94d'
15+
down_revision = '8dc3b1bdbfef'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
op.add_column('core_dashboard', sa.Column('canvas_views', sa.Text(), nullable=True))
22+
# ### end Alembic commands ###
23+
24+
25+
def downgrade():
26+
# ### commands auto generated by Alembic - please adjust! ###
27+
op.drop_column('core_dashboard', 'canvas_views')
28+
# ### end Alembic commands ###

backend/apps/dashboard/crud/dashboard_service.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def create_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashb
7171
record.node_type = dashboard.node_type
7272
record.component_data = dashboard.component_data
7373
record.canvas_style_data = dashboard.canvas_style_data
74+
record.canvas_views = dashboard.canvas_views
7475
session.add(record)
7576
session.flush()
7677
session.refresh(record)
@@ -85,6 +86,7 @@ def update_canvas(session: SessionDep, user: CurrentUser, dashboard: CreateDashb
8586
record.update_time = int(time.time())
8687
record.component_data = dashboard.component_data
8788
record.canvas_style_data = dashboard.canvas_style_data
89+
record.canvas_views = dashboard.canvas_views
8890
session.add(record)
8991
session.commit()
9092
return record

backend/apps/dashboard/models/dashboard_model.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class CoreDashboard(SQLModel, table=True):
5050
default=None,
5151
sa_column=Column(Text, nullable=True)
5252
)
53+
canvas_views: str = Field(
54+
default=None,
55+
sa_column=Column(Text, nullable=True)
56+
)
5357
mobile_layout: int = Field(
5458
default=0,
5559
sa_column=Column(SmallInteger, nullable=True)
@@ -156,4 +160,5 @@ class QueryDashboard(BaseDashboard):
156160
class CreateDashboard(QueryDashboard):
157161
canvas_style_data: str =''
158162
component_data: str = ''
163+
canvas_views: str = ''
159164
description: str = ''

frontend/src/stores/dashboard/dashboard.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ export const dashboardStore = defineStore('dashboard', {
5656
},
5757
updateDashboardInfo(params: any) {
5858
Object.keys(params).forEach((key: string) => {
59-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
60-
// @ts-expect-error
59+
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment
6160
this.dashboardInfo[key] = params[key]
6261
})
6362
},
6463
setCanvasViewInfo(params: any) {
6564
this.canvasViewInfo = params
6665
},
66+
addCanvasViewInfo(params: any) {
67+
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment
68+
this.canvasViewInfo[params.id] = params
69+
},
6770
canvasDataInit() {},
6871
},
6972
})

frontend/src/utils/useEmitt.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import mitt from 'mitt'
2+
import { onBeforeUnmount } from 'vue'
3+
4+
type EventCallback = (...args: any[]) => void
5+
6+
interface Option {
7+
name: string
8+
callback: EventCallback
9+
}
10+
11+
const emitter = mitt()
12+
13+
// Map to store debounce information
14+
const lazyDebounceMap = new Map<
15+
string,
16+
{
17+
timer: any | null
18+
isPending: boolean
19+
}
20+
>()
21+
22+
/**
23+
* Basic event emitter hook
24+
* @param option - Optional configuration with event name and callback
25+
* @returns Object containing the emitter instance
26+
*/
27+
export const useEmitt = (option?: Option) => {
28+
if (option) {
29+
emitter.on(option.name, option.callback)
30+
31+
onBeforeUnmount(() => {
32+
emitter.off(option.name, option.callback)
33+
})
34+
}
35+
return {
36+
emitter,
37+
}
38+
}
39+
40+
/**
41+
* Debounced event emitter
42+
* @param eventName - Name of the event to emit
43+
* @param params - Parameters to pass with the event
44+
* @param delay - Debounce delay in milliseconds (default: 300ms)
45+
*/
46+
export const useEmittLazy = (eventName: string, params: any = null, delay = 500) => {
47+
// If there's already a pending execution, skip this call
48+
if (lazyDebounceMap.has(eventName)) {
49+
const entry = lazyDebounceMap.get(eventName)!
50+
if (entry.isPending) {
51+
return
52+
}
53+
}
54+
55+
// Clear existing timer if present
56+
if (lazyDebounceMap.has(eventName)) {
57+
const { timer } = lazyDebounceMap.get(eventName)!
58+
if (timer) {
59+
clearTimeout(timer)
60+
}
61+
}
62+
63+
// Set up a new timer
64+
const timer = setTimeout(() => {
65+
emitter.emit(eventName, params)
66+
67+
// Mark execution as complete
68+
if (lazyDebounceMap.has(eventName)) {
69+
lazyDebounceMap.get(eventName)!.isPending = false
70+
}
71+
}, delay)
72+
73+
// Store timer information and mark as pending
74+
lazyDebounceMap.set(eventName, {
75+
timer,
76+
isPending: true,
77+
})
78+
79+
// Clean up on component unmount
80+
onBeforeUnmount(() => {
81+
if (lazyDebounceMap.has(eventName)) {
82+
const { timer } = lazyDebounceMap.get(eventName)!
83+
if (timer) {
84+
clearTimeout(timer)
85+
}
86+
lazyDebounceMap.delete(eventName)
87+
}
88+
})
89+
}

frontend/src/views/chat/component/ChartComponent.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { computed, onMounted, onUnmounted } from 'vue'
33
import { getChartInstance } from '@/views/chat/component/index.ts'
44
import type { BaseChart, ChartAxis, ChartData } from '@/views/chat/component/BaseChart.ts'
5+
import { useEmitt } from '@/utils/useEmitt.ts'
56
67
const params = withDefaults(
78
defineProps<{
@@ -61,6 +62,16 @@ function destroyChart() {
6162
}
6263
}
6364
65+
useEmitt({
66+
name: 'view-render-all',
67+
callback: renderChart,
68+
})
69+
70+
useEmitt({
71+
name: `view-render-${params.id}`,
72+
callback: renderChart,
73+
})
74+
6475
defineExpose({
6576
renderChart,
6677
destroyChart,
@@ -83,7 +94,5 @@ onUnmounted(() => {
8394
.chart-container {
8495
height: 100%;
8596
width: 100%;
86-
min-height: 360px;
87-
min-width: 360px;
8897
}
8998
</style>

frontend/src/views/dashboard/canvas/CanvasCore.vue

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { type CanvasCoord, type CanvasItem } from '@/utils/canvas.ts'
66
import CanvasShape from './CanvasShape.vue'
77
import { findComponent } from '@/views/dashboard/components/component-list.ts'
88
import { storeToRefs } from 'pinia'
9+
import { useEmittLazy } from '@/utils/useEmitt.ts'
910
1011
const dashboardStore = dashboardStoreWithOut()
1112
const canvasLocked = ref(false) // Is the canvas movement locked, Default false
@@ -25,12 +26,17 @@ const props = defineProps({
2526
dashboardInfo: {
2627
type: Object,
2728
required: false,
28-
default: null,
29+
default: () => {},
2930
},
3031
canvasStyleData: {
3132
type: Object,
3233
required: false,
33-
default: null,
34+
default: () => {},
35+
},
36+
canvasViewInfo: {
37+
type: Object,
38+
required: false,
39+
default: () => {},
3440
},
3541
canvasComponentData: {
3642
type: Array as PropType<CanvasItem[]>,
@@ -317,6 +323,9 @@ function resizePlayer(item: CanvasItem, newSize: any) {
317323
if (canGoUpRows > 0) {
318324
moveItemUp(item, canGoUpRows)
319325
}
326+
if (item.component === 'SQView') {
327+
useEmittLazy(`view-render-${item.id}`)
328+
}
320329
}
321330
322331
/**
@@ -1167,8 +1176,9 @@ defineExpose({
11671176
<component
11681177
:is="findComponent(item.component)"
11691178
:ref="'shape_component_' + item.id"
1170-
class="sql-component slot-component dragHandle"
1179+
class="sql-component dragHandle"
11711180
:config-item="item"
1181+
:view-info="canvasViewInfo[item.id]"
11721182
@parent-add-item-box="(subItem: any) => addItemBox(subItem)"
11731183
>
11741184
</component>
Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,45 @@
11
<script setup lang="ts">
22
import ChartComponent from '@/views/chat/component/ChartComponent.vue'
3-
import { reactive } from 'vue'
4-
import type { ChartAxis, ChartData } from '@/views/chat/component/BaseChart.ts'
5-
6-
const state = reactive({
7-
chartInfo: {
8-
id: null as string | null,
9-
type: '' as string,
10-
columns: [] as ChartAxis[],
11-
xAxis: [] as ChartAxis[],
12-
yAxis: [] as ChartAxis[],
13-
series: [] as ChartAxis[],
14-
data: [] as ChartData[],
3+
defineProps({
4+
viewInfo: {
5+
type: Object,
6+
required: true,
157
},
168
})
9+
10+
import { ref } from 'vue'
11+
12+
const chartRef = ref(null)
13+
const renderChart = () => {
14+
//@ts-expect-error eslint-disable-next-line @typescript-eslint/no-unused-expressions
15+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
16+
chartRef.value?.renderChart
17+
}
18+
19+
defineExpose({
20+
renderChart,
21+
})
1722
</script>
1823

1924
<template>
2025
<div class="chart-base-container">
21-
<div>
26+
<div style="height: 100%; width: 100%">
2227
<ChartComponent
23-
v-if="state.chartInfo.id"
24-
:id="state.chartInfo.id"
28+
v-if="viewInfo.id"
29+
:id="viewInfo.id"
2530
ref="chartRef"
26-
:type="state.chartInfo.type"
27-
:columns="state.chartInfo.columns"
28-
:x="state.chartInfo.xAxis"
29-
:y="state.chartInfo.yAxis"
30-
:series="state.chartInfo.series"
31-
:data="state.chartInfo.data"
31+
:type="viewInfo.chart.type"
32+
:columns="viewInfo.chart.columns"
33+
:x="viewInfo.chart?.xAxis"
34+
:y="viewInfo.chart?.yAxis"
35+
:series="viewInfo.chart?.series"
36+
:data="viewInfo.data?.data"
3237
/>
3338
</div>
3439
</div>
3540
</template>
3641

3742
<style scoped lang="less">
3843
.chart-base-container {
39-
padding: 20px;
40-
background: rgba(224, 224, 226, 0.29);
4144
}
4245
</style>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue'
3+
import SQView from '@/views/dashboard/components/sq-view/index.vue'
4+
5+
const isSelected = ref(false)
6+
7+
const props = defineProps({
8+
viewInfo: {
9+
type: Object,
10+
required: true,
11+
},
12+
selectChange: {
13+
type: Function,
14+
default: () => {
15+
return {}
16+
},
17+
},
18+
})
19+
20+
const curSelectChange = (value: boolean) => {
21+
props.selectChange(value)
22+
}
23+
</script>
24+
25+
<template>
26+
<div class="chart-selection-container">
27+
<el-checkbox class="select-area" :value="isSelected" @change="curSelectChange"></el-checkbox>
28+
<SQView :view-info="viewInfo"></SQView>
29+
</div>
30+
</template>
31+
32+
<style scoped lang="less">
33+
.chart-selection-container {
34+
width: 33%;
35+
height: 250px;
36+
position: relative;
37+
padding: 15px;
38+
float: left;
39+
.select-area {
40+
position: absolute;
41+
top: 20px;
42+
right: 20px;
43+
}
44+
}
45+
</style>

0 commit comments

Comments
 (0)