refactor(数据大屏): 保持比例填充展示模式优化 (#16716)

This commit is contained in:
王嘉豪
2025-08-14 12:01:02 +08:00
committed by GitHub
parent 3b5420dbc2
commit 1a835a1196
4 changed files with 93 additions and 17 deletions

View File

@@ -100,6 +100,11 @@ const props = defineProps({
showLinkageButton: {
type: Boolean,
default: true
},
outerScreenAdaptor: {
type: String,
required: false,
default: null
}
})
@@ -115,7 +120,8 @@ const {
outerScale,
outerSearchCount,
showPopBar,
fontFamily
fontFamily,
outerScreenAdaptor
} = toRefs(props)
const domId = 'preview-' + canvasId.value
const scaleWidthPoint = ref(100)
@@ -136,17 +142,21 @@ const state = reactive({
scrollMain: 0
})
const screenAdaptor = computed(() => {
return outerScreenAdaptor.value || canvasStyleData.value?.screenAdaptor
})
const curSearchCount = computed(() => {
return outerSearchCount.value + searchCount.value
})
// 大屏是否保持宽高比例 非全屏 full 都需要保持宽高比例
const dataVKeepRadio = computed(() => {
return canvasStyleData.value?.screenAdaptor !== 'full'
return screenAdaptor.value !== 'full'
})
// 仪表板是否跟随宽度缩放 非全屏 full 都需要保持宽高比例
const dashboardScaleWithWidth = computed(() => {
return isDashboard() && canvasStyleData.value?.dashboardAdaptor === 'withWidth'
return isDashboard() && screenAdaptor.value === 'withWidth'
})
const isReport = computed(() => {
return !!router.currentRoute.value.query?.report
@@ -176,11 +186,11 @@ const canvasStyle = computed(() => {
}
if (canvasStyleData.value && canvasStyleData.value.width && isMainCanvas(canvasId.value)) {
style = getCanvasStyle(canvasStyleData.value)
if (canvasStyleData.value?.screenAdaptor === 'keep') {
if (screenAdaptor.value === 'keep') {
style['height'] = canvasStyleData.value?.height + 'px'
style['width'] = canvasStyleData.value?.width + 'px'
style['margin'] = 'auto'
} else if (canvasStyleData.value?.screenAdaptor === 'keepProportion') {
} else if (screenAdaptor.value === 'keepProportion') {
style['aspect-ratio'] = canvasStyleData.value?.width / canvasStyleData.value?.height
style['height'] = 'auto'
style['width'] = 'auto'
@@ -189,12 +199,11 @@ const canvasStyle = computed(() => {
? downloadStatus.value
? getDownloadStatusMainHeight()
: '100%'
: !canvasStyleData.value?.screenAdaptor ||
canvasStyleData.value?.screenAdaptor === 'widthFirst'
: !screenAdaptor.value || screenAdaptor.value === 'widthFirst'
? changeStyleWithScale(canvasStyleData.value?.height, scaleMin.value) + 'px'
: '100%'
style['width'] =
!dashboardActive.value && canvasStyleData.value?.screenAdaptor === 'heightFirst'
!dashboardActive.value && screenAdaptor.value === 'heightFirst'
? changeStyleWithScale(canvasStyleData.value?.width, scaleHeightPoint.value) + 'px'
: '100%'
}
@@ -518,9 +527,15 @@ const scrollPreview = () => {
}
const showUnpublishFlag = computed(() => dvInfo.value?.status === 0 && isMainCanvas(canvasId.value))
const getPreviewCanvasSize = () => {
return {
innerWidth: previewCanvas.value.clientWidth,
innerHeight: previewCanvas.value.clientHeight
}
}
defineExpose({
restore,
getPreviewCanvasSize,
getDownloadStatusMainHeightV2
})
</script>

View File

@@ -604,6 +604,7 @@ strong {
width: 100%;
height: 100%;
display: inherit;
justify-content: center;
}
.preview-content-inner-height-first {

View File

@@ -1,13 +1,15 @@
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { computed, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import DePreview from '@/components/data-visualization/canvas/DePreview.vue'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const { fullscreenFlag } = storeToRefs(dvMainStore)
const dePreviewRef = ref(null)
const dePreviewOuterRef = ref(null)
const dataInitState = ref(true)
const keepProportion = ref('heightFirst')
const props = defineProps({
canvasStylePreview: {
required: true,
@@ -30,6 +32,11 @@ const props = defineProps({
type: Number,
default: 0
},
// 联动按钮位置
showLinkageButton: {
type: Boolean,
default: true
},
showPosition: {
required: false,
type: String,
@@ -45,17 +52,14 @@ const props = defineProps({
const restore = () => {
dePreviewRef.value.restore()
}
const contentInnerClass = computed(() => {
//屏幕适配方式 widthFirst=宽度优先(默认) heightFirst=高度优先 full=铺满全屏 keepSize=不缩放
if (props.canvasStylePreview.screenAdaptor === 'heightFirst') {
if (screenAdaptor.value === 'heightFirst') {
return 'preview-content-inner-height-first'
} else if (props.canvasStylePreview.screenAdaptor === 'full') {
} else if (screenAdaptor.value === 'full') {
return 'preview-content-inner-full'
} else if (props.canvasStylePreview.screenAdaptor === 'keep') {
} else if (screenAdaptor.value === 'keep') {
return 'preview-content-inner-size-keep'
} else if (props.canvasStylePreview.screenAdaptor === 'keepProportion') {
return 'preview-content-inner-keep-proportion'
} else {
return 'preview-content-inner-width-first'
}
@@ -67,6 +71,43 @@ const outerStyle = computed(() => {
}
})
const screenAdaptor = computed(() => {
if (props.canvasStylePreview.screenAdaptor === 'keepProportion') {
return keepProportion.value
} else {
return props.canvasStylePreview.screenAdaptor
}
})
const keepProportionCheck = outerContentRect => {
const { width, height } = outerContentRect
const { innerWidth, innerHeight } = dePreviewRef.value.getPreviewCanvasSize()
if (width > innerWidth || height < innerHeight) {
keepProportion.value = 'heightFirst'
} else {
keepProportion.value = 'widthFirst'
}
}
onMounted(() => {
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
console.log('元素新尺寸:', entry.contentRect)
// entry.contentRect 包含 width, height, top, left 等属性
keepProportionCheck(entry.contentRect)
}
})
if (dePreviewOuterRef.value) {
observer.observe(dePreviewOuterRef.value)
}
// 在组件卸载时停止观察
onBeforeUnmount(() => {
observer.disconnect()
})
})
defineExpose({
restore
})
@@ -75,6 +116,7 @@ defineExpose({
<template>
<div
id="de-preview-content"
ref="dePreviewOuterRef"
:class="{ 'de-screen-full': fullscreenFlag }"
:style="outerStyle"
class="content-outer"
@@ -90,6 +132,8 @@ defineExpose({
:cur-gap="curPreviewGap"
:show-position="showPosition"
:download-status="downloadStatus"
:outer-screen-adaptor="screenAdaptor"
:show-linkage-button="showLinkageButton"
></de-preview>
</div>
</div>

View File

@@ -19,6 +19,7 @@ import EmptyBackground from '../../components/empty-background/src/EmptyBackgrou
import { useRoute } from 'vue-router_2'
import { filterEnumMapSync } from '@/utils/componentUtils'
import CanvasOptBar from '@/components/visualization/CanvasOptBar.vue'
import DvPreview from '@/views/data-visualization/DvPreview.vue'
const routeWatch = useRoute()
const dvMainStore = dvMainStoreWithOut()
@@ -281,9 +282,24 @@ defineExpose({
:canvas-style-data="state.canvasStylePreview || {}"
:component-data="state.canvasDataPreview || []"
></canvas-opt-bar>
<dv-preview
ref="dvPreviewRef"
style="height: 100vh"
v-if="state.canvasStylePreview && state.initState && state.dvInfo?.type === 'dataV'"
:canvas-data-preview="state.canvasDataPreview"
:canvas-style-preview="state.canvasStylePreview"
:canvas-view-info-preview="state.canvasViewInfoPreview"
:dv-info="state.dvInfo"
:cur-preview-gap="state.curPreviewGap"
:is-selector="props.isSelector"
:download-status="downloadStatus"
:show-pop-bar="true"
:show-position="state.showPosition"
:show-linkage-button="false"
></dv-preview>
<de-preview
ref="dvPreview"
v-if="state.canvasStylePreview && state.initState"
v-if="state.canvasStylePreview && state.initState && state.dvInfo?.type === 'dashboard'"
:component-data="state.canvasDataPreview"
:canvas-style-data="state.canvasStylePreview"
:canvas-view-info="state.canvasViewInfoPreview"