提交data-visualization\components\visualization文件

This commit is contained in:
limengnan 2025-07-01 15:11:19 +08:00
parent 9982d69156
commit 540fb2e873
16 changed files with 331 additions and 215 deletions

View File

@ -1,6 +1,6 @@
<template> <template>
<div style="width: 100%" ref="bgForm"> <div style="width: 100%" ref="bgForm">
<el-form label-position="top" style="width: 100%; margin-bottom: 16px"> <el-form size="small" label-position="top" style="width: 100%; margin-bottom: 16px">
<el-form-item <el-form-item
class="form-item no-margin-bottom" class="form-item no-margin-bottom"
:class="'form-item-' + themes" :class="'form-item-' + themes"

View File

@ -33,12 +33,8 @@
import warnTree from '@/assets/svg/warn-tree.svg' import warnTree from '@/assets/svg/warn-tree.svg'
import { ref } from 'vue' import { ref } from 'vue'
import { useI18n } from '@/data-visualization/hooks/web/useI18n' import { useI18n } from '@/data-visualization/hooks/web/useI18n'
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
const dvMainStore = dvMainStoreWithOut()
const dialogShow = ref(false) const dialogShow = ref(false)
const { t } = useI18n() const { t } = useI18n()
import { useCache } from '@/data-visualization/hooks/web/useCache'
const { wsCache } = useCache()
const emits = defineEmits(['doUseCache']) const emits = defineEmits(['doUseCache'])
const dialogInfo = { const dialogInfo = {

View File

@ -0,0 +1,84 @@
<template>
<div
v-if="showButton && (!dvMainStore.mobileInPc || isMobile())"
class="bar-main-right"
@mousedown="handOptBarMousedown"
>
<el-button size="mini" type="info" @click="exitFullscreen">
<el-icon style="margin-right: 8px">
<Icon name="exit_fullscreen"
><exit_fullscreen style="font-size: 16px" class="svg-icon"
/></Icon>
</el-icon>
{{ $t('visualization.ext_fullscreen') }}</el-button
>
</div>
</template>
<script lang="ts" setup>
import exit_fullscreen from '@/assets/svg/exit-fullscreen.svg'
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
import { computed } from 'vue'
import { isMainCanvas } from '@/data-visualization/utils/canvasUtils'
import { isMobile } from '@/data-visualization/utils/utils'
import { storeToRefs } from 'pinia'
import Icon from '../icon-custom/src/Icon.vue'
import { ElIcon } from 'element-plus-secondary'
const dvMainStore = dvMainStoreWithOut()
const { fullscreenFlag } = storeToRefs(dvMainStore)
const props = defineProps({
canvasId: {
type: String,
required: false,
default: 'canvas-main'
},
showPosition: {
required: false,
type: String,
default: 'preview'
}
})
const handOptBarMousedown = e => {
e.preventDefault()
e.stopPropagation()
}
const showButton = computed(() => {
if (isMainCanvas(props.canvasId)) {
return fullscreenFlag.value && props.showPosition === 'preview'
} else {
return false
}
})
const exitFullscreen = () => {
document.exitFullscreen()
}
</script>
<style lang="less" scoped>
.bar-main-right {
top: 2px;
right: 2px;
opacity: 0.8;
z-index: 1;
position: absolute;
}
.bar-main-edit-right {
top: 8px;
right: 102px !important;
}
.bar-main-left {
left: 0px;
opacity: 0;
height: fit-content;
&:hover {
opacity: 0.8;
}
}
</style>

View File

@ -2,10 +2,13 @@
<div <div
v-if="existLinkage && (!dvMainStore.mobileInPc || isMobile())" v-if="existLinkage && (!dvMainStore.mobileInPc || isMobile())"
class="bar-main-right" class="bar-main-right"
:class="{ 'bar-main-edit-right': dvEditMode }" :class="{
'bar-main-preview-fixed': dvPreviewMode,
'bar-main-preview-fixed-fullscreen': fullscreenFlag
}"
@mousedown="handOptBarMousedown" @mousedown="handOptBarMousedown"
> >
<el-button size="mini" type="warning" @click="clearAllLinkage" <el-button type="warning" @click="clearAllLinkage"
><el-icon class="bar-base-icon"> ><el-icon class="bar-base-icon">
<Icon name="dv-bar-unLinkage"><dvBarUnLinkage class="svg-icon" /></Icon></el-icon <Icon name="dv-bar-unLinkage"><dvBarUnLinkage class="svg-icon" /></Icon></el-icon
>{{ $t('visualization.remove_all_linkage') }}</el-button >{{ $t('visualization.remove_all_linkage') }}</el-button
@ -20,7 +23,9 @@ import { computed } from 'vue'
import { isMainCanvas } from '@/data-visualization/utils/canvasUtils' import { isMainCanvas } from '@/data-visualization/utils/canvasUtils'
import { useEmitt } from '@/data-visualization/hooks/web/useEmitt' import { useEmitt } from '@/data-visualization/hooks/web/useEmitt'
import { isMobile } from '@/data-visualization/utils/utils' import { isMobile } from '@/data-visualization/utils/utils'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { fullscreenFlag } = storeToRefs(dvMainStore)
const props = defineProps({ const props = defineProps({
canvasStyleData: { canvasStyleData: {
@ -35,6 +40,10 @@ const props = defineProps({
type: String, type: String,
required: false, required: false,
default: 'canvas-main' default: 'canvas-main'
},
isFixed: {
type: Boolean,
default: false
} }
}) })
@ -48,9 +57,10 @@ const clearAllLinkage = () => {
useEmitt().emitter.emit('clearPanelLinkage', { viewId: 'all' }) useEmitt().emitter.emit('clearPanelLinkage', { viewId: 'all' })
} }
const dvEditMode = computed(() => { const dvPreviewMode = computed(() => {
return dvMainStore.dvInfo.type === 'dataV' && dvMainStore.editMode === 'preview' && !isMobile() return dvMainStore.dvInfo.type === 'dataV' && props.isFixed
}) })
const existLinkage = computed(() => { const existLinkage = computed(() => {
if (isMainCanvas(props.canvasId)) { if (isMainCanvas(props.canvasId)) {
let linkageFiltersCount = 0 let linkageFiltersCount = 0
@ -87,7 +97,7 @@ const existLinkage = computed(() => {
top: 2px; top: 2px;
right: 2px; right: 2px;
opacity: 0.8; opacity: 0.8;
z-index: 1; z-index: 2;
position: absolute; position: absolute;
} }
@ -104,4 +114,14 @@ const existLinkage = computed(() => {
opacity: 0.8; opacity: 0.8;
} }
} }
.bar-main-preview-fixed {
position: fixed;
top: 120px;
right: 5px;
}
.bar-main-preview-fixed-fullscreen {
top: 5px !important;
}
</style> </style>

View File

@ -21,9 +21,7 @@ const emits = defineEmits(['customClick'])
<el-row class="group_icon" :title="tips" @click="emits('customClick')"> <el-row class="group_icon" :title="tips" @click="emits('customClick')">
<el-col :span="24" class="group_inner" :class="{ 'inner-active': active }"> <el-col :span="24" class="group_inner" :class="{ 'inner-active': active }">
<Icon><component class="svg-icon toolbar-icon" :is="iconName"></component></Icon> <Icon><component class="svg-icon toolbar-icon" :is="iconName"></component></Icon>
<span>{{ title }}</span>
<!-- <img src="@/assets/newimg/avatar.png" alt="" srcset=""> -->
<span >{{ title }}</span>
</el-col> </el-col>
</el-row> </el-row>
<el-divider class="group-right-border" v-if="showSplitLine" direction="vertical" /> <el-divider class="group-right-border" v-if="showSplitLine" direction="vertical" />

View File

@ -171,6 +171,7 @@
<xpack-component <xpack-component
:chart="element" :chart="element"
resource-table="snapshot"
jsname="L2NvbXBvbmVudC90aHJlc2hvbGQtd2FybmluZy9FZGl0QmFySGFuZGxlcg==" jsname="L2NvbXBvbmVudC90aHJlc2hvbGQtd2FybmluZy9FZGl0QmFySGFuZGxlcg=="
@close-item="closeItem" @close-item="closeItem"
/> />
@ -267,7 +268,8 @@ const emits = defineEmits([
'showViewDetails', 'showViewDetails',
'amRemoveItem', 'amRemoveItem',
'linkJumpSetOpen', 'linkJumpSetOpen',
'linkageSetOpen' 'linkageSetOpen',
'componentImageDownload'
]) ])
const { t } = useI18n() const { t } = useI18n()
const { emitter } = useEmitt() const { emitter } = useEmitt()
@ -479,13 +481,12 @@ const exportAsExcel = () => {
const chartExtRequest = dvMainStore.getLastViewRequestInfo(element.value.id) const chartExtRequest = dvMainStore.getLastViewRequestInfo(element.value.id)
const viewInfo = dvMainStore.getViewDetails(element.value.id) const viewInfo = dvMainStore.getViewDetails(element.value.id)
const chart = { ...viewInfo, chartExtRequest, data: viewDataInfo, busiFlag: dvInfo.value.type } const chart = { ...viewInfo, chartExtRequest, data: viewDataInfo, busiFlag: dvInfo.value.type }
exportExcelDownload(chart, () => { exportExcelDownload(chart, dvInfo.value.name, () => {
openMessageLoading(callbackExport) openMessageLoading(callbackExport)
}) })
} }
const exportAsImage = () => { const exportAsImage = () => {
// do export emits('componentImageDownload')
useEmitt().emitter.emit('componentImageDownload-' + element.value.id)
} }
const deleteComponent = () => { const deleteComponent = () => {
eventBus.emit('removeMatrixItem-' + canvasId.value, index.value) eventBus.emit('removeMatrixItem-' + canvasId.value, index.value)

View File

@ -1,8 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, reactive, ref } from 'vue' import { computed, reactive, ref } from 'vue'
import { deepCopy } from '@/data-visualization/utils/utils' import { deepCopy } from '@/data-visualization/utils/utils'
import { useEmitt } from '@/data-visualization/hooks/web/useEmitt'
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain' import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { ElMessage } from 'element-plus-secondary'
const loading = ref(false) const loading = ref(false)
const subject = ref() const subject = ref()
const subjectDialogShow = ref(false) const subjectDialogShow = ref(false)
@ -31,7 +33,13 @@ const optInit = item => {
} }
const saveSubject = () => { const saveSubject = () => {
if (disabledCheck.value) {
ElMessage.error('请输入正确参数')
return
}
canvasViewInfo.value[state.viewId]['calParams'] = curDataSetParamsInfo.value
useEmitt().emitter.emit('calcData-' + state.viewId, canvasViewInfo.value[state.viewId])
resetForm()
} }
const disabledCheck = computed(() => { const disabledCheck = computed(() => {
@ -57,8 +65,6 @@ defineExpose({
statesCheck, statesCheck,
resetForm resetForm
}) })
const emits = defineEmits(['finish'])
</script> </script>
<template> <template>

View File

@ -1,7 +1,7 @@
<template> <template>
<el-dialog <el-dialog
ref="previewPopDialog" ref="previewPopDialog"
:custom-class="'preview_pop_custom'" modal-class="preview_pop_custom"
:append-to-body="true" :append-to-body="true"
:fullscreen="state.fullscreen" :fullscreen="state.fullscreen"
v-model="state.dialogShow" v-model="state.dialogShow"
@ -23,8 +23,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, reactive } from 'vue' import { computed, reactive, ref } from 'vue'
import { useEmbedded } from '@/data-visualization/store/modules/embedded'
const state = reactive({ const state = reactive({
dialogShow: false, dialogShow: false,
name: '', name: '',
@ -33,7 +33,6 @@ const state = reactive({
width: '70vw', width: '70vw',
height: '70%' height: '70%'
}) })
const dialogStyle = computed(() => { const dialogStyle = computed(() => {
if (state.fullscreen) { if (state.fullscreen) {
return {} return {}
@ -46,7 +45,7 @@ const previewInit = params => {
if (params.url.includes('?')) { if (params.url.includes('?')) {
state.url = `${params.url}&popWindow=true` state.url = `${params.url}&popWindow=true`
} else { } else {
state.url = `${params.url}&popWindow=true` state.url = `${params.url}?popWindow=true`
} }
if (params.size === 'large') { if (params.size === 'large') {
state.fullscreen = true state.fullscreen = true

View File

@ -5,21 +5,15 @@ import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visu
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { snapshotStoreWithOut } from '@/data-visualization//modules/data-visualization/snapshot' import { snapshotStoreWithOut } from '@/data-visualization//modules/data-visualization/snapshot'
import Icon from '../icon-custom/src/Icon.vue' import Icon from '../icon-custom/src/Icon.vue'
import dvInfoSvg from '@/assets/svg/dv-info.svg'
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
import combinationSvg from '@/assets/svg/combinationpage.svg'
import scatterSvg from '@/assets/svg/scatterpage.svg'
import { composeStoreWithOut } from '@/data-visualization/store/modules/data-visualization/compose'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { canvasCollapse,curComponent } = storeToRefs(dvMainStore) const { canvasCollapse } = storeToRefs(dvMainStore)
let componentNameEdit = ref(false) let componentNameEdit = ref(false)
let inputComponentName = ref({ id: null, name: null }) let inputComponentName = ref({ id: null, name: null })
let componentNameInputAttr = ref(null) let componentNameInputAttr = ref(null)
import dvInfoSvg from '@/assets/svg/dv-info.svg'
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
const snapshotStore = snapshotStoreWithOut() const snapshotStore = snapshotStoreWithOut()
const composeStore = composeStoreWithOut()
const { areaData } = storeToRefs(composeStore)
const { t } = useI18n() const { t } = useI18n()
const emit = defineEmits(['close', 'rename'])
const props = defineProps({ const props = defineProps({
element: { element: {
required: false, required: false,
@ -64,13 +58,10 @@ const props = defineProps({
type: String as PropType<EditorTheme>, type: String as PropType<EditorTheme>,
default: 'light' default: 'light'
}, },
title: String, title: String
activePosition: {
type: String,
default: 'canvas'
}
}) })
const { width, asidePosition, sideName, themeInfo, view, themes, element,activePosition } = toRefs(props)
const { width, asidePosition, sideName, themeInfo, view, themes, element } = toRefs(props)
const collapseChange = () => { const collapseChange = () => {
canvasCollapse.value[sideName.value] = !canvasCollapse.value[sideName.value] canvasCollapse.value[sideName.value] = !canvasCollapse.value[sideName.value]
} }
@ -131,33 +122,6 @@ const editComponentName = () => {
const onComponentNameChange = () => { const onComponentNameChange = () => {
snapshotStore.recordSnapshotCache('onComponentNameChange') snapshotStore.recordSnapshotCache('onComponentNameChange')
} }
//
const combinationclick = () => {
if(areaData.value.components.length){
composeStore.compose()
snapshotStore.recordSnapshotCache('componentCompose')
menuOpt('componentCompose')
}else{
ElMessage.warning('请选择多个组件进行组合!')
return
}
}
//
const scatterclick= () => {
if(curComponent.value['component'] == 'Group'){
composeStore.decompose()
snapshotStore.recordSnapshotCache('decompose')
menuOpt('decompose')
}else{
ElMessage.warning('请选择组合!')
return
}
}
const menuOpt = optName => {
const param = { opt: optName }
activePosition.value === 'aside' && emit('close', param)
}
</script> </script>
<template> <template>
@ -173,7 +137,7 @@ const menuOpt = optName => {
:id="'attr-slide-component-name' + slideIndex" :id="'attr-slide-component-name' + slideIndex"
v-if="!canvasCollapse[sideName]" v-if="!canvasCollapse[sideName]"
class="name-area-attr" class="name-area-attr"
style="max-width: 180px; text-overflow: ellipsis; white-space: nowrap;" style="max-width: 180px; text-overflow: ellipsis; white-space: nowrap"
:style="{ width: componentNameEdit ? '300px' : 'auto' }" :style="{ width: componentNameEdit ? '300px' : 'auto' }"
:class="{ 'component-name-dark': themeInfo === 'dark' }" :class="{ 'component-name-dark': themeInfo === 'dark' }"
@dblclick="editComponentName" @dblclick="editComponentName"
@ -191,7 +155,7 @@ const menuOpt = optName => {
<span> <span>
<el-icon <el-icon
v-show="element && element['id']" v-show="element && element['id']"
style="margin: 6px 0 0 4px; cursor: pointer" style="margin: 2px 0 0 4px; cursor: pointer"
><Icon><dvInfoSvg class="svg-icon" /></Icon ><Icon><dvInfoSvg class="svg-icon" /></Icon
></el-icon> ></el-icon>
</span> </span>
@ -204,15 +168,6 @@ const menuOpt = optName => {
</div> </div>
</el-popover> </el-popover>
</div> </div>
<div style="display: flex;">
<div v-if="!canvasCollapse[sideName] && asidePosition === 'left'">
<el-icon title="组合" style="font-size: 16px;margin-right: 8px;cursor: pointer" @click="combinationclick">
<Icon><combinationSvg class="svg-icon" /></Icon>
</el-icon>
<el-icon title="打散" style="font-size: 16px;margin-right: 5px;cursor: pointer" @click="scatterclick">
<Icon><scatterSvg class="svg-icon" /></Icon>
</el-icon>
</div>
<el-icon <el-icon
:title="title" :title="title"
:class="['custom-icon-' + themeInfo, 'collapse-icon-' + themeInfo]" :class="['custom-icon-' + themeInfo, 'collapse-icon-' + themeInfo]"
@ -227,7 +182,6 @@ const menuOpt = optName => {
/> />
<Fold v-else /> <Fold v-else />
</el-icon> </el-icon>
</div>
</el-row> </el-row>
<div class="main-content" v-if="!canvasCollapse[sideName]"> <div class="main-content" v-if="!canvasCollapse[sideName]">
<el-scrollbar> <el-scrollbar>
@ -399,15 +353,16 @@ const menuOpt = optName => {
</style> </style>
<style> <style>
.ed-popper.is-light { .ed-popper.is-light {
border: 1px solid #434343; border: 1px solid #434343 !important;
background: rgba(41, 41, 41, 1) !important; background: rgba(41, 41, 41, 1) !important;
color: #ffffff ;
} }
.ed-popper[data-popper-placement^=bottom] .ed-popper__arrow::before { .ed-popper[data-popper-placement^=bottom] .ed-popper__arrow::before {
background: rgba(41, 41, 41, 1) !important; background: rgba(41, 41, 41, 1) !important;
} }
.ed-popover.ed-popper{ .ed-popover.ed-popper{
background: rgba(41, 41, 41, 1); background: rgba(41, 41, 41, 1) !important;
border: 1px solid #434343; border: 1px solid #434343 !important;
} }
.ed-collapse-item.ed-collapse--light .ed-collapse-item__header{ .ed-collapse-item.ed-collapse--light .ed-collapse-item__header{
background-color: #1a1a1a; background-color: #1a1a1a;
@ -466,14 +421,14 @@ const menuOpt = optName => {
color: #ebebeb !important; color: #ebebeb !important;
} }
.ed-collapse-item__wrap .ed-input-number__decrease, .ed-input-number__increase{ .ed-collapse-item__wrap .ed-input-number__decrease, .ed-input-number__increase{
background-color: #434343; background-color: #434343 !important;
color:#ffffff; color:#ffffff !important;
} }
.ed-input-number__decrease, .ed-input-number__increase{ .ed-input-number__decrease, .ed-input-number__increase{
color:#ffffff; color:#ffffff !important;
} }
.ed-collapse-item__wrap .ed-input-number.is-controls-right .ed-input-number__increase{ .ed-collapse-item__wrap .ed-input-number.is-controls-right .ed-input-number__increase{
border-bottom: 1px solid #5f5f5f !important; border-bottom: 1px solid #434343 !important;
border-left: 1px solid #5f5f5f !important; border-left: 1px solid #5f5f5f !important;
} }
.ed-collapse-item__wrap .ed-input-number.is-controls-right .ed-input-number__decrease{ .ed-collapse-item__wrap .ed-input-number.is-controls-right .ed-input-number__decrease{
@ -569,7 +524,7 @@ color: #ffffff !important;
} }
.ed-input-number--dark:not(.is-disabled) .ed-input-number__decrease:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper, .ed-input-number--dark:not(.is-disabled) .ed-input-number__increase:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper{ .ed-input-number--dark:not(.is-disabled) .ed-input-number__decrease:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper, .ed-input-number--dark:not(.is-disabled) .ed-input-number__increase:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper{
box-shadow: none !important; box-shadow: none !important;
border: 1px solid #0089ff; border: 1px solid #0089ff !important;
} }
.ed-input__wrapper.is-focus { .ed-input__wrapper.is-focus {
box-shadow: none !important; box-shadow: none !important;
@ -582,15 +537,18 @@ color: #ffffff !important;
} }
.ed-input-number--light:not(.is-disabled).is-controls-right .ed-input-number__decrease:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper, .ed-input-number--light:not(.is-disabled).is-controls-right .ed-input-number__increase:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper{ .ed-input-number--light:not(.is-disabled).is-controls-right .ed-input-number__decrease:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper, .ed-input-number--light:not(.is-disabled).is-controls-right .ed-input-number__increase:not(.is-disabled):hover~.ed-input:not(.is-disabled) .ed-input__wrapper{
box-shadow: none !important; box-shadow: none !important;
border: 1px solid #0089ff; border: 1px solid #0089ff !important;
} }
.ed-input-number--light .ed-input-number__decrease.is-disabled .ed-icon, .ed-input-number--light .ed-input-number__increase.is-disabled .ed-icon { .ed-input-number--light .ed-input-number__decrease.is-disabled .ed-icon, .ed-input-number--light .ed-input-number__increase.is-disabled .ed-icon {
color: #ffffff; color: #ffffff;
} }
.ed-input-number__decrease:hover, .ed-input-number__increase:hover { .ed-input-number__decrease:hover, .ed-input-number__increase:hover {
color: #0089ff; color: #0089ff !important;
} }
.ed-select .ed-input.is-disabled:not(.ed-input--dark) .ed-input__wrapper:hover{ .ed-select .ed-input.is-disabled:not(.ed-input--dark) .ed-input__wrapper:hover{
box-shadow: none!important;; box-shadow: none!important;;
} }
.icon-checkbox:before{
content:''
}
</style> </style>

View File

@ -40,7 +40,7 @@ const setNameIdTrans = (from, to, originName, name2Auto?: string[]) => {
pre[next[from]] = next[to] pre[next[from]] = next[to]
return pre return pre
}, {}) }, {})
const on = originName.match(/\[(.+?)\]/g) const on = originName.match(/\[(.+?)\]/g) || []
if (on) { if (on) {
on.forEach(itm => { on.forEach(itm => {
const ele = itm.slice(1, -1) const ele = itm.slice(1, -1)

View File

@ -236,7 +236,12 @@
state.linkJumpInfo?.jumpType === 'newPop' state.linkJumpInfo?.jumpType === 'newPop'
}" }"
> >
<el-scrollbar height="fit-content" max-height="178px"> <el-scrollbar
height="fit-content"
:max-height="
state.linkJumpInfo?.jumpType === 'newPop' ? '138px' : '178px'
"
>
<div <div
style="display: flex; margin-bottom: 6px" style="display: flex; margin-bottom: 6px"
v-for="( v-for="(
@ -667,11 +672,6 @@ const selectSourceTips = t('visualization.select_target_resource')
const targetSource = t('visualization.target_dashboard_dataV') const targetSource = t('visualization.target_dashboard_dataV')
const curSource =
dvInfo.value.type === 'dashboard'
? t('visualization.cur_dashboard')
: t('visualization.cur_screen')
const state = reactive({ const state = reactive({
curDataVWeight: 0, curDataVWeight: 0,
activeCollapse: 'view', activeCollapse: 'view',
@ -746,6 +746,28 @@ const dialogInit = viewItem => {
init(viewItem) init(viewItem)
} }
const initCurFilterFieldArray = componentDataCheck => {
componentDataCheck.forEach(componentItem => {
if (componentItem.component === 'VQuery' && componentItem.propValue instanceof Array) {
componentItem.propValue.forEach(filterItem => {
if (filterItem.checkedFields.includes(state.viewId)) {
state.linkJumpCurFilterFieldArray.push({
id: filterItem.id,
name: filterItem.name,
deType: 'filter'
})
}
})
} else if (componentItem.component === 'Group') {
initCurFilterFieldArray(componentItem.propValue)
} else if (componentItem.component === 'DeTabs') {
componentItem.propValue.forEach(tabItem => {
initCurFilterFieldArray(tabItem.componentData)
})
}
})
}
const init = viewItem => { const init = viewItem => {
state.initState = false state.initState = false
state.viewId = viewItem.id state.viewId = viewItem.id
@ -792,19 +814,7 @@ const init = viewItem => {
// 1. 2. // 1. 2.
state.linkJumpCurFilterFieldArray = [] state.linkJumpCurFilterFieldArray = []
componentData.value.forEach(componentItem => { initCurFilterFieldArray(componentData.value)
if (componentItem.component === 'VQuery' && componentItem.propValue instanceof Array) {
componentItem.propValue.forEach(filterItem => {
if (filterItem.checkedFields.includes(state.viewId)) {
state.linkJumpCurFilterFieldArray.push({
id: filterItem.id,
name: filterItem.name,
deType: 'filter'
})
}
})
}
})
if (chartDetails.tableId) { if (chartDetails.tableId) {
// //

View File

@ -158,7 +158,23 @@
</el-col> </el-col>
<el-col :span="16" class="preview-show"> <el-col :span="16" class="preview-show">
<el-row class="content-head">{{ t('visualization.linkage_setting_tips1') }}</el-row> <el-row class="content-head">{{ t('visualization.linkage_setting_tips1') }}</el-row>
<el-row v-if="state.linkageInfo && state.linkageInfo.linkageActive"> <el-row
v-if="
state.linkageInfo &&
state.linkageInfo.linkageActive &&
curComponent?.innerType === 'indicator'
"
style="height: 100%"
class="custom-position"
>
<Icon name="dv-empty"
><dvEmpty style="width: 125px; height: 125px" class="svg-icon"
/></Icon>
<span style="margin-top: 8px; font-size: 14px">
{{ t('visualization.indicator_linkage') }}</span
>
</el-row>
<el-row v-else-if="state.linkageInfo && state.linkageInfo.linkageActive">
<el-row style="margin-top: 5px"> <el-row style="margin-top: 5px">
<div style="display: flex" class="inner-content"> <div style="display: flex" class="inner-content">
<div style="flex: 1">{{ t('visualization.current_chart_source_field') }}</div> <div style="flex: 1">{{ t('visualization.current_chart_source_field') }}</div>
@ -367,7 +383,10 @@ const sameDsShow = computed(
) )
const diffDsShow = computed( const diffDsShow = computed(
() => curLinkageTargetViewsInfoDiffDs.value && curLinkageTargetViewsInfoDiffDs.value.length > 0 () =>
curLinkageTargetViewsInfoDiffDs.value &&
curLinkageTargetViewsInfoDiffDs.value.length > 0 &&
curComponent.value.innerType !== 'indicator'
) )
const dialogInit = viewItem => { const dialogInit = viewItem => {
@ -387,7 +406,8 @@ const linkageSetting = curViewId => {
dvId: dvInfo.value.id, dvId: dvInfo.value.id,
sourceViewId: curViewId, sourceViewId: curViewId,
targetViewIds: targetViewIds, targetViewIds: targetViewIds,
linkageInfo: null linkageInfo: null,
resourceTable: 'snapshot'
} }
getViewLinkageGatherArray(requestInfo).then(rsp => { getViewLinkageGatherArray(requestInfo).then(rsp => {
// () // ()
@ -556,12 +576,19 @@ const linkageFieldAdaptor = async data => {
JSON.stringify(state.curLinkageViewInfo.xAxisExt) + JSON.stringify(state.curLinkageViewInfo.xAxisExt) +
(state.curLinkageViewInfo.type.includes('chart-mix') (state.curLinkageViewInfo.type.includes('chart-mix')
? JSON.stringify(state.curLinkageViewInfo.extBubble) ? JSON.stringify(state.curLinkageViewInfo.extBubble)
: '') +
(['indicator'].includes(state.curLinkageViewInfo.type)
? JSON.stringify(state.curLinkageViewInfo.yAxis)
: '') : '')
const targetCheckAllAxisStr = const targetCheckAllAxisStr =
JSON.stringify(targetChartDetails.xAxis) + JSON.stringify(targetChartDetails.xAxis) +
JSON.stringify(targetChartDetails.xAxisExt) + JSON.stringify(targetChartDetails.xAxisExt) +
JSON.stringify(state.curLinkageViewInfo.extStack) +
(targetChartDetails.type.includes('chart-mix') (targetChartDetails.type.includes('chart-mix')
? JSON.stringify(targetChartDetails.extBubble) ? JSON.stringify(targetChartDetails.extBubble)
: '') +
(['indicator'].includes(state.curLinkageViewInfo.type)
? JSON.stringify(state.curLinkageViewInfo.yAxis)
: '') : '')
state.sourceLinkageInfo.targetViewFields.forEach(item => { state.sourceLinkageInfo.targetViewFields.forEach(item => {
if ( if (
@ -586,10 +613,11 @@ const sourceLinkageInfoFilter = computed(() => {
JSON.stringify(state.curLinkageViewInfo.xAxis) + JSON.stringify(state.curLinkageViewInfo.xAxis) +
JSON.stringify(state.curLinkageViewInfo.drillFields) + JSON.stringify(state.curLinkageViewInfo.drillFields) +
JSON.stringify(state.curLinkageViewInfo.xAxisExt) + JSON.stringify(state.curLinkageViewInfo.xAxisExt) +
JSON.stringify(state.curLinkageViewInfo.extStack) +
(state.curLinkageViewInfo.type.includes('chart-mix') (state.curLinkageViewInfo.type.includes('chart-mix')
? JSON.stringify(state.curLinkageViewInfo.extBubble) ? JSON.stringify(state.curLinkageViewInfo.extBubble)
: '') + : '') +
(state.curLinkageViewInfo.type.includes('table-normal') (['table-normal', 'indicator'].includes(state.curLinkageViewInfo.type)
? JSON.stringify(state.curLinkageViewInfo.yAxis) ? JSON.stringify(state.curLinkageViewInfo.yAxis)
: '') : '')
return state.sourceLinkageInfo.targetViewFields.filter(item => return state.sourceLinkageInfo.targetViewFields.filter(item =>
@ -644,7 +672,7 @@ defineExpose({
.preview { .preview {
margin-top: 5px; margin-top: 5px;
border: 1px solid rgb(61,61,61); border: 1px solid #e6e6e6;
border-radius: 4px; border-radius: 4px;
height: 470px !important; height: 470px !important;
overflow: hidden; overflow: hidden;
@ -652,7 +680,7 @@ defineExpose({
} }
.preview-show { .preview-show {
border-left: 1px solid #5f5f5f; border-left: 1px solid #e6e6e6;
height: 470px; height: 470px;
background-size: 100% 100% !important; background-size: 100% 100% !important;
} }
@ -701,7 +729,7 @@ defineExpose({
flex-direction: column; flex-direction: column;
span { span {
line-height: 22px; line-height: 22px;
color: #909399; color: #646a73;
} }
} }
@ -742,7 +770,7 @@ defineExpose({
margin-right: 16px; margin-right: 16px;
font-weight: 400; font-weight: 400;
font-size: 12px; font-size: 12px;
color: #d2d2d2; color: #646a73;
.ed-switch { .ed-switch {
margin-left: 8px; margin-left: 8px;
} }

View File

@ -21,13 +21,11 @@ const props = defineProps({
} }
}) })
const selection = ref()
const selectionChange = () => { const selectionChange = () => {
// do selection // do selection
} }
const { title, themes, actionSelection } = toRefs(props) const { actionSelection } = toRefs(props)
</script> </script>
<template> <template>
@ -44,7 +42,7 @@ const { title, themes, actionSelection } = toRefs(props)
<el-icon style="margin: 5px 0 0 5px"><Setting /></el-icon <el-icon style="margin: 5px 0 0 5px"><Setting /></el-icon
></span> ></span>
</template> </template>
<el-row style="color: #fff;"> <el-row>
{{ t('visualization.select_linkage_tips') }} {{ t('visualization.select_linkage_tips') }}
</el-row> </el-row>
<el-row> <el-row>

View File

@ -50,7 +50,7 @@
style="width: 100%" style="width: 100%"
v-model="data.paramName" v-model="data.paramName"
:placeholder="$t('visualization.input_param_name')" :placeholder="$t('visualization.input_param_name')"
@blur="closeEdit" @blur="closeEdit(data)"
/> />
</div> </div>
<span class="tree-select-field" v-else-if="data.paramName"> <span class="tree-select-field" v-else-if="data.paramName">
@ -62,8 +62,7 @@
</span> </span>
<span class="icon-more" v-if="!(curEditDataId === data.paramsInfoId)"> <span class="icon-more" v-if="!(curEditDataId === data.paramsInfoId)">
<handle-more <handle-more
style="margin-right: 15px;" style="margin-right: 15px"
class="icon-more-box"
@handle-command="cmd => outerParamsOperation(cmd, node, data)" @handle-command="cmd => outerParamsOperation(cmd, node, data)"
:menu-list="state.optMenu" :menu-list="state.optMenu"
:icon-name="icon_more_vertical_outlined" :icon-name="icon_more_vertical_outlined"
@ -465,11 +464,18 @@ const validateArgs = (val, id) => {
} }
} }
const viewSelectedField = computed(() => const closeEdit = params => {
state.outerParamsInfo?.targetViewInfoList?.map(targetViewInfo => targetViewInfo.targetViewId) if (!params.paramName || params.paramName.length < 2 || params.paramName.length > 25) {
) ElMessage({
message: t('commons.params_value') + t('common.input_limit', [2, 25]),
const closeEdit = () => { type: 'warning',
showClose: true
})
if (params.paramName.length > 25) {
params.paramName = params.paramName.splice(0.25)
}
return
}
curEditDataId.value = null curEditDataId.value = null
} }
@ -481,18 +487,6 @@ const outerParamsOperation = (cmd, node, data) => {
} }
} }
const fieldIdDisabledCheck = targetViewInfo => {
return (
state.viewIdFieldArrayMap[targetViewInfo.targetViewId] &&
state.viewIdFieldArrayMap[targetViewInfo.targetViewId].length === 1 &&
state.viewIdFieldArrayMap[targetViewInfo.targetViewId][0].id === 'empty'
)
}
const getFieldArray = id => {
return state.viewIdFieldArrayMap[id]
}
const initParams = async () => { const initParams = async () => {
state.baseFilterInfo = [] state.baseFilterInfo = []
state.baseDatasetInfo = [] state.baseDatasetInfo = []
@ -720,28 +714,6 @@ const getPanelViewList = dvId => {
}) })
} }
const addOuterParamsField = () => {
state.outerParamsInfo.targetViewInfoList.push({
targetViewId: '',
targetFieldId: ''
})
}
const deleteOuterParamsField = index => {
state.outerParamsInfo.targetViewInfoList.splice(index, 1)
}
const viewInfoOnChange = targetViewInfo => {
if (
state.viewIdFieldArrayMap[targetViewInfo.targetViewId] &&
state.viewIdFieldArrayMap[targetViewInfo.targetViewId].length === 1 &&
state.viewIdFieldArrayMap[targetViewInfo.targetViewId][0].id === 'empty'
) {
targetViewInfo.targetFieldId = 'empty'
} else {
targetViewInfo.targetFieldId = null
}
}
const initSelected = data => { const initSelected = data => {
nextTick(() => { nextTick(() => {
outerParamsInfoTree.value.setCurrentKey(data.paramsInfoId) outerParamsInfoTree.value.setCurrentKey(data.paramsInfoId)
@ -809,20 +781,11 @@ defineExpose({
.root-class { .root-class {
margin: 15px 0px 5px; margin: 15px 0px 5px;
justify-content: right; justify-content: right;
.ed-button{
color: #F2F4F5;
background-color: #212121;
border: 1px solid #434343;
}
.ed-button--primary{
background-color:#0089FF;
border: 1px solid #0089FF;
}
} }
.preview { .preview {
margin-top: 5px; margin-top: 5px;
border: 1px solid #434343; border: 1px solid #e6e6e6;
border-radius: 4px; border-radius: 4px;
height: 470px !important; height: 470px !important;
overflow: hidden; overflow: hidden;
@ -922,18 +885,13 @@ defineExpose({
margin-left: auto; margin-left: auto;
display: none; display: none;
} }
&:hover {
.icon-more { &:hover .icon-more {
margin-left: auto; margin-left: auto;
display: unset; display: unset;
} }
}
.icon-more-box:hover{
border-radius: 4px;
background: #434343;
}
} }
rgb(2, 1, 1)
.link-icon-join { .link-icon-join {
font-size: 20px; font-size: 20px;
margin-top: 7px; margin-top: 7px;
@ -1156,7 +1114,7 @@ rgb(2, 1, 1)
} }
.params-attach-setting { .params-attach-setting {
border-left: 1px solid #434343; border-left: 1px solid #e6e6e6;
} }
.params-attach-content { .params-attach-content {

View File

@ -7,6 +7,7 @@
width="70vw" width="70vw"
trigger="click" trigger="click"
class="userViewEnlarge-class" class="userViewEnlarge-class"
@close="handleClose"
> >
<template #header v-if="!isIframe"> <template #header v-if="!isIframe">
<div class="header-title"> <div class="header-title">
@ -34,12 +35,12 @@
size="middle" size="middle"
@click="downloadViewImage" @click="downloadViewImage"
> >
<el-icon color="#ffffff" size="16" style="margin-right: 3px" <el-icon color="#1F2329" size="16" style="margin-right: 3px"
><icon_download_outlined ><icon_download_outlined
/></el-icon> /></el-icon>
{{ t('chart.export_img') }} {{ t('chart.export_img') }}
</el-button> </el-button>
<!-- <el-button <el-button
class="m-button" class="m-button"
v-if="optType === 'details' && exportPermissions[1]" v-if="optType === 'details' && exportPermissions[1]"
link link
@ -68,7 +69,7 @@
state.dataFrom === 'template' state.dataFrom === 'template'
" "
> >
<el-icon color="#ffffff" size="16" style="margin-right: 3px" <el-icon color="#1F2329" size="16" style="margin-right: 3px"
><icon_download_outlined ><icon_download_outlined
/></el-icon> /></el-icon>
{{ t('chart.export_raw_details') }} {{ t('chart.export_raw_details') }}
@ -85,7 +86,7 @@
><icon_download_outlined ><icon_download_outlined
/></el-icon> /></el-icon>
{{ t('chart.export_excel_formatter') }} {{ t('chart.export_excel_formatter') }}
</el-button> --> </el-button>
<el-divider <el-divider
class="close-divider" class="close-divider"
direction="vertical" direction="vertical"
@ -107,6 +108,7 @@
:class="{ :class="{
'enlarge-inner-with-header': optType === 'details' && sourceViewType.includes('chart-mix') 'enlarge-inner-with-header': optType === 'details' && sourceViewType.includes('chart-mix')
}" }"
v-loading="requestStore.loadingMap[permissionStore.currentPath]"
ref="viewContainer" ref="viewContainer"
:style="customExport" :style="customExport"
> >
@ -179,19 +181,19 @@ import { activeWatermarkCheckUser } from '@/data-visualization/components/waterm
import { getCanvasStyle } from '@/data-visualization/utils/style' import { getCanvasStyle } from '@/data-visualization/utils/style'
import { exportPermission } from '@/data-visualization/utils/utils' import { exportPermission } from '@/data-visualization/utils/utils'
import EmptyBackground from '../empty-background/src/EmptyBackground.vue' import EmptyBackground from '../empty-background/src/EmptyBackground.vue'
// import { supportExtremumChartType } from '@/data-visualization/chart/components/js/extremumUitl'
const downLoading = ref(false) const downLoading = ref(false)
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const dialogShow = ref(false) const dialogShow = ref(false)
// const requestStore = useRequestStoreWithOut() // const requestStore = useRequestStoreWithOut()
let viewInfo = ref<DeepPartial<ChartObj>>(null) let viewInfo = ref<DeepPartial<ChartObj>>(null)
const config = ref(null) const config = ref(null)
const canvasStyleData = ref(null)
const viewContainer = ref(null) const viewContainer = ref(null)
const { t } = useI18n() const { t } = useI18n()
const optType = ref(null) const optType = ref(null)
const chartComponentDetails = ref(null) const chartComponentDetails = ref(null)
const chartComponentDetails2 = ref(null) const chartComponentDetails2 = ref(null)
const { dvInfo, editMode, isIframe } = storeToRefs(dvMainStore) const { dvInfo, isIframe, canvasStyleData } = storeToRefs(dvMainStore)
const exportLoading = ref(false) const exportLoading = ref(false)
const sourceViewType = ref() const sourceViewType = ref()
const activeName = ref('left') const activeName = ref('left')
@ -308,7 +310,6 @@ const dialogInit = (canvasStyle, view, item, opt, params = { scale: 0.5 }) => {
viewInfo.value = deepCopy(view) as DeepPartial<ChartObj> viewInfo.value = deepCopy(view) as DeepPartial<ChartObj>
viewInfo.value.customStyle.text.show = false viewInfo.value.customStyle.text.show = false
config.value = deepCopy(item) config.value = deepCopy(item)
canvasStyleData.value = canvasStyle
if (opt === 'details') { if (opt === 'details') {
if (!viewInfo.value.type?.includes('table')) { if (!viewInfo.value.type?.includes('table')) {
assign(viewInfo.value, DETAIL_CHART_ATTR) assign(viewInfo.value, DETAIL_CHART_ATTR)
@ -372,7 +373,7 @@ const downloadViewDetails = (downloadType = 'view') => {
busiFlag: dvInfo.value.type busiFlag: dvInfo.value.type
} }
exportLoading.value = true exportLoading.value = true
exportExcelDownload(chart, () => { exportExcelDownload(chart, dvInfo.value.name, () => {
openMessageLoading(exportData) openMessageLoading(exportData)
}) })
exportLoading.value = false exportLoading.value = false
@ -416,10 +417,19 @@ const openMessageLoading = cb => {
customClass customClass
}) })
} }
//
const mapChartTypes = ['bubble-map', 'flow-map', 'heat-map', 'map', 'symbolic-map']
const htmlToImage = () => { const htmlToImage = () => {
downLoading.value = true debugger
downLoading.value = mapChartTypes.includes(viewInfo.value.type) ? false : true
useEmitt().emitter.emit('renderChart-' + viewInfo.value.id) useEmitt().emitter.emit('renderChart-' + viewInfo.value.id)
const renderTime = viewInfo.value.type?.includes('table') ? 2000 : 500 useEmitt().emitter.emit('l7-prepare-picture', viewInfo.value.id)
// 2000500
const renderTime =
viewInfo.value.type?.includes('table') ||
supportExtremumChartType({ type: viewInfo.value.type })
? 2000
: 500
setTimeout(() => { setTimeout(() => {
initWatermark() initWatermark()
toPng(viewContainer.value) toPng(viewContainer.value)
@ -429,12 +439,14 @@ const htmlToImage = () => {
a.setAttribute('download', viewInfo.value.title) a.setAttribute('download', viewInfo.value.title)
a.href = dataUrl a.href = dataUrl
a.click() a.click()
useEmitt().emitter.emit('l7-unprepare-picture', viewInfo.value.id)
useEmitt().emitter.emit('renderChart-' + viewInfo.value.id) useEmitt().emitter.emit('renderChart-' + viewInfo.value.id)
initWatermark() initWatermark()
}) })
.catch(error => { .catch(error => {
downLoading.value = false downLoading.value = false
initWatermark() initWatermark()
useEmitt().emitter.emit('l7-unprepare-picture', viewInfo.value.id)
useEmitt().emitter.emit('renderChart-' + viewInfo.value.id) useEmitt().emitter.emit('renderChart-' + viewInfo.value.id)
console.error('oops, something went wrong!', error) console.error('oops, something went wrong!', error)
}) })
@ -582,4 +594,30 @@ defineExpose({
.ed-select-group__wrap:not(:last-of-type)::after{ .ed-select-group__wrap:not(:last-of-type)::after{
background: #434343 !important; background: #434343 !important;
} }
.ed-select .ed-input.is-focus .ed-input__wrapper{
box-shadow: none !important;
}
.ed-select:hover:not(.ed-select--disabled) .ed-input__wrapper{
box-shadow: none !important;
}
.ed-select .ed-input__wrapper.is-focus{
box-shadow: none !important;
}
.ed-dropdown-menu{
background-color: rgb(41, 41, 41);
}
.ed-dropdown-menu__item{
color: #fff;
}
.ed-dropdown-menu__item--divided{
border-top: 1px solid #5f5f5f;
}
.ed-dropdown-menu__item:not(.is-disabled):hover{
background-color: rgb(61, 61, 61);
}
.ed-dropdown__popper.ed-popper{
border: 1px solid #5f5f5f;
background:transparent;
}
</style> </style>

View File

@ -1,6 +1,11 @@
<template> <template>
<div> <div>
<el-dropdown :teleported="false" trigger="click"> <el-dropdown
:id="'view-track-bar-' + chartId"
:teleported="false"
trigger="click"
@visible-change="visibleChange"
>
<input id="input" ref="trackButton" type="button" hidden /> <input id="input" ref="trackButton" type="button" hidden />
<template #dropdown> <template #dropdown>
<div :class="{ 'data-mobile': isDataVMobile }"> <div :class="{ 'data-mobile': isDataVMobile }">
@ -12,6 +17,7 @@
<el-dropdown-item <el-dropdown-item
v-for="(item, key) in trackMenu" v-for="(item, key) in trackMenu"
:key="key" :key="key"
@mousedown.stop
@click="trackMenuClick(item)" @click="trackMenuClick(item)"
><span class="menu-item">{{ state.i18n_map[item] }}</span></el-dropdown-item ><span class="menu-item">{{ state.i18n_map[item] }}</span></el-dropdown-item
> >
@ -52,11 +58,27 @@ const state = reactive({
linkage: t('visualization.linkage'), linkage: t('visualization.linkage'),
linkageAndDrill: t('visualization.linkage_and_drill'), linkageAndDrill: t('visualization.linkage_and_drill'),
jump: t('visualization.jump'), jump: t('visualization.jump'),
enlarge: t('visualization.enlarge') enlarge: t('visualization.enlarge'),
event_jump: t('visualization.jump'),
event_download: t('visualization.download'),
event_share: t('visualization.share'),
event_fullScreen: t('visualization.fullscreen'),
event_showHidden: t('visualization.pop_area'),
event_refreshDataV: t('visualization.refresh'),
event_refreshView: t('visualization.refresh_view')
} }
}) })
const visibleChange = () => {
const trackButtonClick = () => { document.querySelectorAll('.g2-tooltip')?.forEach(tooltip => {
if (tooltip.id?.includes(chartId.value)) {
tooltip.classList.toggle('hidden-tooltip', true)
}
})
}
// tooltip
const chartId = ref(null)
const trackButtonClick = (id?: string) => {
chartId.value = id
setTimeout(() => { setTimeout(() => {
trackButton.value.click() trackButton.value.click()
}, 50) }, 50)