<script setup lang="ts">
import icon_collection_outlined from '@/assets/svg/icon_collection_outlined.svg'
import visualStar from '@/assets/svg/visual-star.svg'
import dvInfoSvg from '@/assets/svg/dv-info.svg'
import dvHeadMore from '@/assets/svg/dv-head-more.svg'
import icon_pc_fullscreen from '@/assets/svg/icon_pc_fullscreen.svg'
import icon_pc_outlined from '@/assets/svg/icon_pc_outlined.svg'
import icon_download_outlined from '@/assets/svg/icon_download_outlined.svg'
import icon_replace_outlined from '@/assets/svg/icon_replace_outlined.svg'
import icon_edit_outlined from '@/assets/svg/icon_edit_outlined.svg'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import { useI18n } from '@/hooks/web/useI18n'
import { useAppStoreWithOut } from '@/store/modules/app'
import DvDetailInfo from '@/views/common/DvDetailInfo.vue'
import { useEmbedded } from '@/store/modules/embedded'
import { storeApi, storeStatusApi } from '@/api/visualization/dataVisualization'
import { ref, watch, computed } from 'vue'
import ShareVisualHead from '@/views/share/share/ShareVisualHead.vue'
import { XpackComponent } from '@/components/plugin'
import { useEmitt } from '@/hooks/web/useEmitt'
import { useShareStoreWithOut } from '@/store/modules/share'
import { exportPermission } from '@/utils/utils'
import { useCache } from '@/hooks/web/useCache'
import { isDesktop } from '@/utils/ModelUtil'
const shareStore = useShareStoreWithOut()
const { wsCache } = useCache('localStorage')
const dvMainStore = dvMainStoreWithOut()
const appStore = useAppStoreWithOut()
const { dvInfo } = storeToRefs(dvMainStore)
const emit = defineEmits(['reload', 'download', 'downloadAsAppTemplate'])
const { t } = useI18n()
const embeddedStore = useEmbedded()
const openType = wsCache.get('open-backend') === '1' ? '_self' : '_blank'
const favorited = ref(false)
const preview = () => {
const baseUrl = isDataEaseBi.value ? embeddedStore.baseUrl : ''
const url =
baseUrl +
'#/preview?dvId=' +
dvInfo.value.id +
'&dvType=' +
dvInfo.value['type'] +
'&ignoreParams=true'
const newWindow = window.open(url, '_blank')
initOpenHandler(newWindow)
}
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
const isIframe = computed(() => appStore.getIsIframe)
const shareDisable = computed(() => shareStore.getShareDisable || isDesktop())
const exportPermissions = computed(() =>
exportPermission(dvInfo.value['weight'], dvInfo.value['ext'])
)
const reload = () => {
emit('reload', dvInfo.value.id)
}
const download = type => {
emit('download', type)
}
const downloadAsAppTemplate = downloadType => {
emit('downloadAsAppTemplate', downloadType)
}
const dvEdit = () => {
if (isDataEaseBi.value || isIframe.value) {
embeddedStore.clearState()
if (dvInfo.value.type === 'dataV') {
embeddedStore.setDvId(dvInfo.value.id)
} else {
embeddedStore.setResourceId(dvInfo.value.id)
}
useEmitt().emitter.emit(
'changeCurrentComponent',
dvInfo.value.type === 'dataV' ? 'VisualizationEditor' : 'DashboardEditor'
)
return
}
const baseUrl = dvInfo.value.type === 'dataV' ? '#/dvCanvas?dvId=' : '#/dashboard?resourceId='
const newWindow = window.open(baseUrl + dvInfo.value.id, openType)
initOpenHandler(newWindow)
}
const executeStore = () => {
const param = {
id: dvInfo.value.id,
type: dvInfo.value.type === 'dashboard' ? 'panel' : 'screen'
}
storeApi(param).then(() => {
storeQuery()
})
}
const storeQuery = () => {
if (!dvInfo?.value?.id) return
storeStatusApi(dvInfo.value.id).then(res => {
favorited.value = res.data
})
}
storeQuery()
watch(
() => dvInfo.value.id,
() => {
storeQuery()
}
)
const openHandler = ref(null)
const initOpenHandler = newWindow => {
if (openHandler?.value) {
const pm = {
methodName: 'initOpenHandler',
args: newWindow
}
openHandler.value?.invokeMethod(pm)
}
}
</script>
<template>
<div class="preview-head flex-align-center">
<div :title="dvInfo.name" class="canvas-name ellipsis">{{ dvInfo.name }}</div>
<div v-show="dvInfo.status === 2" class="canvas-have-update">
{{ t('visualization.publish_update_tips') }}
</div>
<el-tooltip
effect="dark"
:content="favorited ? t('visualization.cancel_store') : t('visualization.store')"
placement="top"
>
<el-icon
v-if="dvInfo.status !== 0"
class="custom-icon hover-icon"
@click="executeStore"
:style="{ color: favorited ? '#FFC60A' : '#646A73' }"
>
<icon
><component
class="svg-icon"
:is="favorited ? visualStar : icon_collection_outlined"
></component
></icon>
</el-icon>
</el-tooltip>
<el-divider style="margin: 0 16px 0 7px" direction="vertical" />
<div class="create-area flex-align-center">
<span style="line-height: 22px"
>{{ t('visualization.creator') }}:{{ dvInfo.creatorName }}</span
>
<el-popover show-arrow :offset="8" placement="bottom" width="400" trigger="hover">
<template #reference>
<el-icon class="info-tips"
><Icon name="dv-info"><dvInfoSvg class="svg-icon" /></Icon
></el-icon>
</template>
<dv-detail-info></dv-detail-info>
</el-popover>
</div>
<div class="canvas-opt-button">
<el-button
v-if="!isIframe"
:disabled="dvInfo.status === 0"
secondary
@click="() => useEmitt().emitter.emit('canvasFullscreen')"
>
<template #icon>
<icon name="icon_pc_fullscreen"><icon_pc_fullscreen class="svg-icon" /></icon>
</template>
{{ t('visualization.fullscreen') }}</el-button
>
<el-button secondary @click="preview()" :disabled="dvInfo.status === 0">
<template #icon>
<icon name="icon_pc_outlined"><icon_pc_outlined class="svg-icon" /></icon>
</template>
{{ t('template_manage.preview') }}
</el-button>
<ShareVisualHead
v-if="!shareDisable"
:disabled="dvInfo.status === 0"
:resource-id="dvInfo.id"
:weight="dvInfo.weight"
:resource-type="dvInfo.type"
/>
<el-button class="custom-button" v-if="dvInfo.weight > 6" type="primary" @click="dvEdit()">
<template #icon>
<icon name="icon_edit_outlined"><icon_edit_outlined class="svg-icon" /></icon>
</template>
{{ t('visualization.edit') }}</el-button
>
<el-dropdown :disabled="dvInfo.status === 0" popper-class="pad12" trigger="click">
<el-icon class="head-more-icon">
<Icon name="dv-head-more"><dvHeadMore class="svg-icon" /></Icon>
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="reload()"
><el-icon color="#646A73" size="16"><icon_replace_outlined /></el-icon
>{{ t('visualization.refresh_data') }}
</el-dropdown-item>
<el-dropdown
style="width: 100%; overflow: hidden"
trigger="hover"
popper-class="pad12"
placement="left-start"
v-if="exportPermissions[0]"
>
<div class="ed-dropdown-menu__item flex-align-center icon">
<el-icon color="#646A73" size="16"><icon_download_outlined /></el-icon>
{{ t('visualization.export_as') }}
<el-icon color="#646A73" size="16" class="arrow-right_icon"><ArrowRight /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="download('pdf')">PDF</el-dropdown-item>
<el-dropdown-item @click="downloadAsAppTemplate('template')">{{
t('visualization.style_template')
}}</el-dropdown-item>
<el-dropdown-item @click="downloadAsAppTemplate('app')">{{
t('visualization.apply_template')
}}</el-dropdown-item>
<el-dropdown-item @click="download('img')">{{
t('chart.image')
}}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
<XpackComponent ref="openHandler" jsname="L2NvbXBvbmVudC9lbWJlZGRlZC1pZnJhbWUvT3BlbkhhbmRsZXI=" />
</template>
<style lang="less">
.pad12 {
.ed-dropdown-menu__item {
padding: 5px 36px 5px 12px !important;
.ed-icon {
margin-right: 8px;
}
.arrow-right_icon {
position: absolute;
right: 12px;
margin-right: 0;
}
&:has(.arrow-right_icon) {
width: 100%;
}
}
}
.preview-head {
width: 100%;
min-width: 300px;
height: 56px;
padding: 16px 24px;
border-bottom: 1px solid rgba(31, 35, 41, 0.15);
.canvas-name {
max-width: 400px;
font-size: 16px;
font-weight: 500;
}
.canvas-have-update {
background-color: rgba(52, 199, 36, 0.2);
color: rgba(44, 169, 31, 1);
font-weight: 400;
font-size: 12px;
line-height: 20px;
vertical-align: middle;
padding: 0 4px;
margin-left: 8px;
}
.custom-icon {
cursor: pointer;
margin-left: 8px;
}
.create-area {
color: #646a73;
font-weight: 400;
font-size: 14px;
}
.canvas-opt-button {
display: flex;
justify-content: right;
align-items: center;
flex: 1;
.head-more-icon {
color: #1f2329;
margin-left: 12px;
cursor: pointer;
font-size: 20px;
border-radius: 6px;
position: relative;
&:hover {
&::after {
content: '';
position: absolute;
top: -4px;
left: -4px;
border-radius: 6px;
height: 28px;
width: 28px;
background: #1f23291a;
}
}
}
}
}
.info-tips {
margin-left: 4px;
font-size: 16px;
color: #646a73;
}
.custom-button {
margin-left: 12px;
}
</style>