refactor: support sq add view to dashboard

This commit is contained in:
wangjiahao
2025-07-29 11:20:06 +08:00
parent df4dc1672a
commit c068ae5780
5 changed files with 291 additions and 13 deletions
@@ -18,6 +18,7 @@ import icon_window_mini_outlined from '@/assets/svg/icon_window-mini_outlined.sv
import icon_copy_outlined from '@/assets/svg/icon_copy_outlined.svg'
import { useI18n } from 'vue-i18n'
import SQLComponent from '@/views/chat/component/SQLComponent.vue'
import AddViewDashboard from '@/views/dashboard/common/AddViewDashboard.vue'
const props = withDefaults(
defineProps<{
@@ -34,7 +35,7 @@ const props = withDefaults(
)
const { t } = useI18n()
const addViewRef = ref(null)
const emits = defineEmits(['exitFullScreen'])
const dataObject = computed<{
@@ -188,7 +189,8 @@ function showSql() {
}
function addToDashboard() {
console.log('todo')
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment
addViewRef.value?.optInit()
}
function copy() {
@@ -300,6 +302,7 @@ function copy() {
/>
</div>
<AddViewDashboard ref="addViewRef"></AddViewDashboard>
<el-dialog
v-if="!enlarge"
v-model="dialogVisible"
@@ -0,0 +1,249 @@
<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import {
findNextComponentIndex,
saveDashboardResourceTarget,
} from '@/views/dashboard/utils/canvasUtils.ts'
import { useI18n } from 'vue-i18n'
import { dashboardApi } from '@/api/dashboard.ts'
import type { SQTreeNode } from '@/views/dashboard/utils/treeNode.ts'
import cloneDeep from 'lodash/cloneDeep'
import { findNewComponentFromList } from '@/views/dashboard/components/component-list.ts'
import { guid } from '@/utils/canvas.ts'
const { t } = useI18n()
const resource = ref(null)
const optInit = (viewInfo: any) => {
resourceDialogShow.value = true
state.viewInfo = viewInfo
}
const state = reactive({
dashboardList: [] as SQTreeNode[],
viewInfo: null,
})
const resourceDialogShow = ref(false)
const loading = ref(false)
const resourceForm = reactive({
addType: 'history',
dashboardId: '',
dashboardName: '',
})
const resourceFormRulesNew = ref({
dashboardName: [
{
required: true,
min: 1,
max: 64,
message: t('dashboard.length_limit64'),
trigger: 'change',
},
],
})
const resourceFormRulesHistory = ref({
dashboardId: [
{
required: true,
min: 1,
max: 64,
message: '请选择仪表板',
trigger: 'change',
},
],
})
const resetForm = () => {
resourceForm.dashboardId = ''
resourceForm.dashboardName = ''
resourceDialogShow.value = false
}
const saveResourcePrepare = () => {
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment
resource.value?.validate((result) => {
if (result) {
const component = cloneDeep(findNewComponentFromList('SQView'))
const newComponentId = guid()
if (resourceForm.addType === 'history' && component) {
findNextComponentIndex({ id: resourceForm.dashboardId }, (result: any) => {
const {
bottomPosition,
dashboardInfo,
canvasDataResult,
canvasStyleResult,
canvasViewInfoPreview,
} = result
const params = {
opt: 'updateLeaf',
pid: 'root',
id: resourceForm.dashboardId,
name: dashboardInfo.name,
}
component['id'] = newComponentId
component['y'] = bottomPosition + 1
canvasDataResult.push(component)
canvasViewInfoPreview[newComponentId] = state.viewInfo
const commonParams = {
componentData: canvasDataResult,
canvasStyleData: canvasStyleResult,
canvasViewInfo: canvasViewInfoPreview,
}
saveResource(params, commonParams)
})
} else if (resourceForm.addType === 'new' && component) {
const params = { opt: 'newLeaf', pid: 'root', name: resourceForm.dashboardName }
component['id'] = newComponentId
const commonParams = {
componentData: [component],
canvasStyleData: {},
canvasViewInfo: { newComponentId: state.viewInfo },
}
saveResource(params, commonParams)
}
}
})
}
const saveResource = (params: any, commonParams: any) => {
saveDashboardResourceTarget(params, commonParams, function () {
const messageTips = t('common.save_success')
ElMessage({
type: 'success',
message: messageTips,
})
resetForm()
})
}
const initDashboardList = () => {
state.dashboardList = []
const params = {}
dashboardApi.list_resource(params).then((res: SQTreeNode[]) => {
state.dashboardList = res || []
})
}
onMounted(() => {
initDashboardList()
})
defineExpose({
optInit,
})
</script>
<template>
<el-dialog
v-model="resourceDialogShow"
class="create-dialog"
title="添加到仪表板"
width="420px"
:before-close="resetForm"
append-to-body
@submit.prevent
>
<el-form
ref="resource"
v-loading="loading"
label-position="top"
require-asterisk-position="right"
:model="resourceForm"
:rules="resourceForm.addType === 'new' ? resourceFormRulesNew : resourceFormRulesHistory"
@submit.prevent
>
<el-form-item label="仪表板名称" required prop="addType">
<el-radio-group v-model="resourceForm.addType">
<el-radio value="history">存量仪表板</el-radio>
<el-radio value="new">新建仪表板</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="resourceForm.addType === 'new'"
label="仪表板"
required
prop="dashboardName"
>
<el-input
v-model="resourceForm.dashboardName"
clearable
placeholder="请输入仪表板名称"
@keydown.stop
@keyup.stop
/>
</el-form-item>
<el-form-item
v-if="resourceForm.addType === 'history'"
label="仪表板"
required
prop="dashboardId"
>
<el-select v-model="resourceForm.dashboardId" placeholder="请选择仪表板">
<el-option
v-for="item in state.dashboardList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button secondary @click="resetForm()">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="saveResourcePrepare()">{{ t('common.confirm') }}</el-button>
</template>
</el-dialog>
</template>
<style lang="less" scoped>
.tree-content {
width: 552px;
height: 380px;
border: 1px solid #dee0e3;
border-radius: 4px;
padding: 8px;
overflow-y: auto;
.empty-search {
width: 100%;
margin-top: 57px;
display: flex;
flex-direction: column;
align-items: center;
img {
width: 100px;
height: 100px;
margin-bottom: 8px;
}
span {
font-family: var(--de-custom_font, 'PingFang');
font-size: 14px;
font-weight: 400;
line-height: 22px;
color: #646a73;
}
}
}
.custom-tree-node {
display: flex;
align-items: center;
span {
margin-left: 8.75px;
width: 120px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
.custom-tree-folder {
color: rgb(255, 198, 10);
}
</style>
@@ -115,10 +115,6 @@ const propsTree = {
isLeaf: (node) => !node.children?.length,
}
// const showPid = computed(() => {
// return state.opt && ['newLeaf'].includes(state.opt) && state.parentSelect
// })
const showPid = false
const saveResource = () => {
@@ -2,7 +2,6 @@
import ChartComponent from '@/views/chat/component/ChartComponent.vue'
import icon_window_mini_outlined from '@/assets/svg/icon_window-mini_outlined.svg'
import SqViewDisplay from '@/views/dashboard/components/sq-view/index.vue'
import _ from 'lodash'
const props = defineProps({
viewInfo: {
type: Object,
@@ -48,8 +48,39 @@ export const initCanvasData = (params: any, callBack: () => void) => {
})
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export const findNextComponentIndex = async (params: any, callBack: Function) => {
load_resource_prepare(params, function (result: any) {
let bottomPosition = 0
const { dashboardInfo, canvasDataResult, canvasStyleResult, canvasViewInfoPreview } = result
canvasDataResult.forEach((component: any) => {
const componentBottom = component.y + component.sizeY
if (componentBottom > bottomPosition) {
bottomPosition = componentBottom
}
})
callBack({
bottomPosition,
dashboardInfo,
canvasDataResult,
canvasStyleResult,
canvasViewInfoPreview,
})
})
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export const saveDashboardResource = (params: any, callBack: Function) => {
const commonParams = {
componentData: componentData.value,
canvasStyleData: canvasStyleData.value,
canvasViewInfo: canvasViewInfo.value,
}
saveDashboardResourceTarget(params, commonParams, callBack)
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
export const saveDashboardResourceTarget = (params: any, commonParams: any, callBack: Function) => {
params['workspace_id'] = workspace_id
dashboardApi.check_name(params).then((resCheck: any) => {
if (resCheck) {
@@ -57,9 +88,9 @@ export const saveDashboardResource = (params: any, callBack: Function) => {
// create canvas
const requestParams = {
...params,
component_data: JSON.stringify(componentData.value),
canvas_style_data: JSON.stringify(canvasStyleData.value),
canvas_view_info: JSON.stringify(canvasViewInfo.value),
component_data: JSON.stringify(commonParams.componentData),
canvas_style_data: JSON.stringify(commonParams.canvasStyleData),
canvas_view_info: JSON.stringify(commonParams.canvasViewInfo),
}
dashboardApi.create_canvas(requestParams).then((res: any) => {
dashboardStore.updateDashboardInfo({
@@ -81,9 +112,9 @@ export const saveDashboardResource = (params: any, callBack: Function) => {
} else if (params.opt === 'updateLeaf') {
const requestParams = {
...params,
component_data: JSON.stringify(componentData.value),
canvas_style_data: JSON.stringify(canvasStyleData.value),
canvas_view_info: JSON.stringify(canvasViewInfo.value),
component_data: JSON.stringify(commonParams.componentData),
canvas_style_data: JSON.stringify(commonParams.canvasStyleData),
canvas_view_info: JSON.stringify(commonParams.canvasViewInfo),
}
dashboardApi.update_canvas(requestParams).then(() => {
callBack()