feat: 仪表板编辑时可以按照仪表板复用视图

This commit is contained in:
wangjiahao 2022-05-24 22:32:11 +08:00
parent 292ecf16d5
commit da26a5b40f
27 changed files with 913 additions and 73 deletions

View File

@ -97,6 +97,13 @@ public class PanelGroupController {
return panelGroupService.queryPanelViewTree(); return panelGroupService.queryPanelViewTree();
} }
@ApiOperation("仪表板视图复用信息")
@PostMapping("/queryPanelMultiplexingViewTree")
@I18n
public List<VAuthModelDTO> queryPanelMultiplexingViewTree() {
return panelGroupService.queryPanelMultiplexingViewTree();
}
@ApiOperation("仪表板组件信息") @ApiOperation("仪表板组件信息")
@GetMapping("/queryPanelComponents/{id}") @GetMapping("/queryPanelComponents/{id}")
@I18n @I18n

View File

@ -265,6 +265,7 @@ public class PanelGroupService {
List<String> panelIds = panelResult.stream().map(VAuthModelDTO::getId).collect(Collectors.toList()); List<String> panelIds = panelResult.stream().map(VAuthModelDTO::getId).collect(Collectors.toList());
VAuthModelRequest viewRequest = new VAuthModelRequest(); VAuthModelRequest viewRequest = new VAuthModelRequest();
viewRequest.setPids(panelIds); viewRequest.setPids(panelIds);
// Version 1.11 only gets the current panel
List<VAuthModelDTO> viewResult = extVAuthModelMapper.queryAuthModelViews(viewRequest); List<VAuthModelDTO> viewResult = extVAuthModelMapper.queryAuthModelViews(viewRequest);
if (CollectionUtils.isNotEmpty(viewResult)) { if (CollectionUtils.isNotEmpty(viewResult)) {
result.addAll(viewResult); result.addAll(viewResult);
@ -282,6 +283,36 @@ public class PanelGroupService {
return result; return result;
} }
public List<VAuthModelDTO> queryPanelMultiplexingViewTree() {
List<VAuthModelDTO> result = new ArrayList<>();
VAuthModelRequest panelRequest = new VAuthModelRequest();
panelRequest.setUserId(String.valueOf(AuthUtils.getUser().getUserId()));
panelRequest.setModelType("panel");
List<VAuthModelDTO> panelResult = extVAuthModelMapper.queryAuthModel(panelRequest);
// 获取仪表板下面的视图
if (CollectionUtils.isNotEmpty(panelResult)) {
result.addAll(panelResult);
List<String> panelIds = panelResult.stream().map(VAuthModelDTO::getId).collect(Collectors.toList());
VAuthModelRequest viewRequest = new VAuthModelRequest();
viewRequest.setPids(panelIds);
// Version 1.11 only gets the current panel
// List<VAuthModelDTO> viewResult = extVAuthModelMapper.queryAuthModelViews(viewRequest);
// if (CollectionUtils.isNotEmpty(viewResult)) {
// result.addAll(viewResult);
// }
result = TreeUtils.mergeTree(result, "panel_list");
// if (AuthUtils.getUser().getIsAdmin()) {
// // 原有视图的目录结构
// List<VAuthModelDTO> viewOriginal = extVAuthModelMapper.queryAuthViewsOriginal(viewRequest);
// if (CollectionUtils.isNotEmpty(viewOriginal) && viewOriginal.size() > 1) {
// result.addAll(TreeUtils.mergeTree(viewOriginal, "public_chart"));
// }
// }
}
return result;
}
public String panelGroupCopy(PanelGroupRequest request, String newPanelId, boolean checkName) { public String panelGroupCopy(PanelGroupRequest request, String newPanelId, boolean checkName) {
String sourcePanelId = request.getId(); //源仪表板ID String sourcePanelId = request.getId(); //源仪表板ID
if (StringUtils.isEmpty(newPanelId)) { if (StringUtils.isEmpty(newPanelId)) {

View File

@ -165,6 +165,14 @@ export function queryPanelViewTree() {
}) })
} }
export function queryPanelMultiplexingViewTree() {
return request({
url: '/panel/group/queryPanelMultiplexingViewTree',
method: 'post',
loading: false
})
}
export function initPanelComponentsData(panelId, callback) { export function initPanelComponentsData(panelId, callback) {
// 加载仪表板组件视图数据 // 加载仪表板组件视图数据
queryPanelComponents(panelId).then(rep => { queryPanelComponents(panelId).then(rep => {

View File

@ -39,8 +39,8 @@ export default {
z-index: 10; z-index: 10;
height: 20px; height: 20px;
border-radius:2px; border-radius:2px;
padding-left: 5px; padding-left: 3px;
padding-right: 2px; padding-right: 0px;
cursor:pointer!important; cursor:pointer!important;
opacity: 0.8; opacity: 0.8;
/*background-color: #0a7be0;*/ /*background-color: #0a7be0;*/

View File

@ -45,8 +45,8 @@ export default {
float:right; float:right;
z-index: 2; z-index: 2;
border-radius:2px; border-radius:2px;
padding-left: 5px; padding-left: 3px;
padding-right: 2px; padding-right: 0px;
cursor:pointer!important; cursor:pointer!important;
background-color: #0a7be0; background-color: #0a7be0;
} }

View File

@ -37,6 +37,8 @@
:filters="filters" :filters="filters"
:terminal="terminal" :terminal="terminal"
:screen-shot="screenShot" :screen-shot="screenShot"
:canvas-style-data="canvasStyleData"
:show-position="showPosition"
/> />
</div> </div>
</div> </div>
@ -88,6 +90,18 @@ export default {
screenShot: { screenShot: {
type: Boolean, type: Boolean,
default: false default: false
},
canvasStyleData: {
type: Object,
required: false,
default: function() {
return {}
}
},
showPosition: {
type: String,
required: false,
default: 'NotProvided'
} }
}, },
data() { data() {
@ -129,7 +143,6 @@ export default {
}, },
...mapState([ ...mapState([
'mobileLayoutStatus', 'mobileLayoutStatus',
'canvasStyleData',
'curComponent', 'curComponent',
'componentGap' 'componentGap'
]) ])

View File

@ -286,8 +286,8 @@ export default {
float:right; float:right;
z-index: 2; z-index: 2;
border-radius:2px; border-radius:2px;
padding-left: 5px; padding-left: 3px;
padding-right: 2px; padding-right: 0px;
cursor:pointer!important; cursor:pointer!important;
background-color: rgba(10,123,224, 1); background-color: rgba(10,123,224, 1);
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="bar-main"> <div class="bar-main">
<div> <div v-if="!positionCheck('multiplexing')">
<span v-if="isEdit" :title="$t('panel.edit')"> <span v-if="isEdit" :title="$t('panel.edit')">
<i class="icon iconfont icon-edit" @click.stop="edit" /> <i class="icon iconfont icon-edit" @click.stop="edit" />
</span> </span>
@ -8,7 +8,9 @@
<i class="icon iconfont icon-fangda" @click.stop="showViewDetails" /> <i class="icon iconfont icon-fangda" @click.stop="showViewDetails" />
</span> </span>
</div> </div>
<div v-if="positionCheck('multiplexing')" style="margin-right: -1px;width: 18px;z-index: 5">
<el-checkbox size="medium" @change="multiplexingCheck" />
</div>
</div> </div>
</template> </template>
@ -17,14 +19,24 @@ import bus from '@/utils/bus'
import { mapState } from 'vuex' import { mapState } from 'vuex'
export default { export default {
props: { props: {
element: {
type: Object,
default: null
},
viewId: { viewId: {
type: String, type: String,
required: true required: true
}, },
// Deprecated
isEdit: { isEdit: {
type: Boolean, type: Boolean,
required: false, required: false,
default: true default: true
},
showPosition: {
type: String,
required: false,
default: 'NotProvided'
} }
}, },
data() { data() {
@ -39,10 +51,19 @@ export default {
} }
}, },
computed: { computed: {
// gapStyle() {
// return {
// 'right': this.curGap + 'px!important'
// }
// },
// curGap() {
// return (this.canvasStyleData.panel.gap === 'yes' && this.element.auxiliaryMatrix) ? this.componentGap : 0
// },
...mapState([ ...mapState([
'linkageSettingStatus', 'linkageSettingStatus',
'componentData', 'componentData',
'canvasStyleData' 'canvasStyleData',
'componentGap'
]) ])
}, },
mounted() { mounted() {
@ -63,8 +84,21 @@ export default {
}, },
showViewDetails() { showViewDetails() {
this.$emit('showViewDetails') this.$emit('showViewDetails')
},
positionCheck(position) {
return this.showPosition === position
},
multiplexingCheck(val) {
if (val) {
// push
this.$store.commit('addCurMultiplexingComponent', { 'component': this.element, 'componentId': this.viewId })
} else {
// remove
this.$store.commit('removeCurMultiplexingComponentWithId', this.viewId)
} }
} }
}
} }
</script> </script>
@ -74,9 +108,9 @@ export default {
right: 0px; right: 0px;
float:right; float:right;
z-index: 2; z-index: 2;
border-radius:2px; border-radius:2px!important;
padding-left: 5px; padding-left: 3px!important;
padding-right: 2px; padding-right: 0px!important;
cursor:pointer!important; cursor:pointer!important;
background-color: #0a7be0; background-color: #0a7be0;
} }

View File

@ -29,6 +29,8 @@
:terminal="terminal" :terminal="terminal"
:filters="filterMap[item.propValue && item.propValue.viewId]" :filters="filterMap[item.propValue && item.propValue.viewId]"
:screen-shot="screenShot" :screen-shot="screenShot"
:canvas-style-data="canvasStyleData"
:show-position="showPosition"
/> />
<!--视图详情--> <!--视图详情-->
<el-dialog <el-dialog
@ -114,6 +116,25 @@ export default {
type: String, type: String,
required: false, required: false,
default: 'none' default: 'none'
},
componentData: {
type: Array,
required: false,
default: function() {
return []
}
},
canvasStyleData: {
type: Object,
required: false,
default: function() {
return {}
}
},
showPosition: {
type: String,
required: false,
default: 'NotProvided'
} }
}, },
data() { data() {
@ -224,11 +245,7 @@ export default {
return this.componentDataShow return this.componentDataShow
}, },
...mapState([ ...mapState([
'isClickComponent', 'isClickComponent'
'curComponent',
'componentData',
'canvasStyleData',
'componentGap'
]), ]),
filterMap() { filterMap() {
const map = buildFilterMap(this.componentData) const map = buildFilterMap(this.componentData)

View File

@ -1,6 +1,12 @@
<template> <template>
<div v-loading="dataLoading" class="bg" :style="bgStyle"> <div v-loading="dataLoading" class="bg" :style="bgStyle">
<Preview v-if="!dataLoading" :back-screen-shot="backScreenShot" @mainHeightChange="mainHeightChange" /> <Preview
v-if="!dataLoading"
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:back-screen-shot="backScreenShot"
@mainHeightChange="mainHeightChange"
/>
</div> </div>
</template> </template>
<script> <script>
@ -10,6 +16,7 @@ import { initPanelData } from '@/api/panel/panel'
import { queryTargetPanelJumpInfo } from '@/api/panel/linkJump' import { queryTargetPanelJumpInfo } from '@/api/panel/linkJump'
import { proxyInitPanelData } from '@/api/panel/shareProxy' import { proxyInitPanelData } from '@/api/panel/shareProxy'
import { getOuterParamsInfo } from '@/api/panel/outerParams' import { getOuterParamsInfo } from '@/api/panel/outerParams'
import { mapState } from 'vuex'
export default { export default {
components: { Preview }, components: { Preview },
@ -28,7 +35,11 @@ export default {
} else { } else {
return { height: '100vh!important' } return { height: '100vh!important' }
} }
} },
...mapState([
'canvasStyleData',
'componentData'
])
}, },
watch: { watch: {
'$route.params.reportId': function() { '$route.params.reportId': function() {

View File

@ -1,7 +1,12 @@
<template> <template>
<div style="width: 100%;height: 100vh;"> <div style="width: 100%;height: 100vh;">
<fullscreen style="height:100%;background: #f7f8fa;overflow-y: auto" :fullscreen.sync="fullscreen" @change="fullscreenChange"> <fullscreen style="height:100%;background: #f7f8fa;overflow-y: auto" :fullscreen.sync="fullscreen" @change="fullscreenChange">
<Preview v-if="fullscreen" :in-screen="!fullscreen" /> <Preview
v-if="fullscreen"
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:in-screen="!fullscreen"
/>
</fullscreen> </fullscreen>
</div> </div>
</template> </template>
@ -10,9 +15,16 @@
import Preview from './Preview' import Preview from './Preview'
import bus from '@/utils/bus' import bus from '@/utils/bus'
import { mapState } from 'vuex'
export default { export default {
components: { Preview }, components: { Preview },
computed: {
...mapState([
'canvasStyleData',
'componentData'
])
},
data() { data() {
return { return {
fullscreen: false fullscreen: false

View File

@ -15,7 +15,6 @@
> >
<!-- 网格线 --> <!-- 网格线 -->
<Grid v-if="showGrid" :matrix-style="matrixStyle" /> <Grid v-if="showGrid" :matrix-style="matrixStyle" />
<!-- positionBox:{{positionBoxInfo}}-->
<PGrid v-if="psDebug" :position-box="positionBoxInfoArray" :matrix-style="matrixStyle" /> <PGrid v-if="psDebug" :position-box="positionBoxInfoArray" :matrix-style="matrixStyle" />
<!-- 仪表板联动清除按钮--> <!-- 仪表板联动清除按钮-->
@ -99,6 +98,7 @@
:active="item === curComponent" :active="item === curComponent"
:edit-mode="'edit'" :edit-mode="'edit'"
:h="getShapeStyleIntDeDrag(item.style,'height')" :h="getShapeStyleIntDeDrag(item.style,'height')"
:canvas-style-data="canvasStyleData"
@input="handleInput" @input="handleInput"
/> />
</de-drag> </de-drag>
@ -212,12 +212,6 @@ import { buildFilterMap } from '@/utils/conditionUtil'
import _ from 'lodash' import _ from 'lodash'
import $ from 'jquery' import $ from 'jquery'
import Background from '@/views/background/index' import Background from '@/views/background/index'
import { ApplicationContext } from '@/utils/ApplicationContext'
import {
BASE_MOBILE_STYLE,
COMMON_BACKGROUND_NONE,
HYPERLINKS
} from '@/components/canvas/custom-component/component-list'
let positionBox = [] let positionBox = []
let coordinates = [] // let coordinates = [] //
@ -1013,12 +1007,6 @@ export default {
} }
}, },
watch: { watch: {
// 'canvasStyleData.aidedDesign.matrixBase': {
// handler(newVal, oldVal) {
// this.changeComponentSizePoint(newVal / oldVal)
// },
// deep: true
// },
customStyle: { customStyle: {
handler(newVal) { handler(newVal) {
// //

View File

@ -8,7 +8,14 @@
'rect-shape' 'rect-shape'
]" ]"
> >
<EditBarView v-if="editBarViewShowFlag" :is-edit="isEdit" :view-id="element.propValue.viewId" @showViewDetails="openChartDetailsDialog" /> <EditBarView
v-if="editBarViewShowFlag"
:element="element"
:show-position="showPosition"
:is-edit="isEdit"
:view-id="element.propValue.viewId"
@showViewDetails="openChartDetailsDialog"
/>
<div v-if="requestStatus==='error'" class="chart-error-class"> <div v-if="requestStatus==='error'" class="chart-error-class">
<div class="chart-error-message-class"> <div class="chart-error-message-class">
{{ message }},{{ $t('chart.chart_show_error') }} {{ message }},{{ $t('chart.chart_show_error') }}
@ -163,6 +170,18 @@ export default {
filters: { filters: {
type: Array, type: Array,
default: () => [] default: () => []
},
canvasStyleData: {
type: Object,
required: false,
default: function() {
return {}
}
},
showPosition: {
type: String,
required: false,
default: 'NotProvided'
} }
}, },
data() { data() {
@ -214,7 +233,7 @@ export default {
} }
}, },
editBarViewShowFlag() { editBarViewShowFlag() {
return this.active && this.inTab && !this.mobileLayoutStatus return (this.active && this.inTab && !this.mobileLayoutStatus) || this.showPosition === 'multiplexing'
}, },
charViewShowFlag() { charViewShowFlag() {
return this.httpRequest.status && this.chart.type && !this.chart.type.includes('table') && !this.chart.type.includes('text') && this.chart.type !== 'label' && this.renderComponent() === 'echarts' return this.httpRequest.status && this.chart.type && !this.chart.type.includes('table') && !this.chart.type.includes('text') && this.chart.type !== 'label' && this.renderComponent() === 'echarts'
@ -298,13 +317,11 @@ export default {
return this.element.commonBackground && this.element.commonBackground.innerPadding || 0 return this.element.commonBackground && this.element.commonBackground.innerPadding || 0
}, },
...mapState([ ...mapState([
'canvasStyleData',
'nowPanelTrackInfo', 'nowPanelTrackInfo',
'nowPanelJumpInfo', 'nowPanelJumpInfo',
'publicLinkStatus', 'publicLinkStatus',
'previewCanvasScale', 'previewCanvasScale',
'mobileLayoutStatus', 'mobileLayoutStatus',
'componentData',
'panelViewDetailsInfo', 'panelViewDetailsInfo',
'componentViewsData', 'componentViewsData',
'curBatchOptComponents' 'curBatchOptComponents'

View File

@ -351,7 +351,7 @@ const list = [
height: 200 height: 200
}, },
x: 1, x: 1,
y: 36, y: 108,
sizex: 12, sizex: 12,
sizey: 6, sizey: 6,
auxiliaryMatrix: true, auxiliaryMatrix: true,

View File

@ -8,9 +8,60 @@ import { uuid } from 'vue-uuid'
export default { export default {
state: { state: {
copyData: null, // 复制粘贴剪切 copyData: null, // 复制粘贴剪切
isCut: false isCut: false,
viewBase: {
style: {
width: 300,
height: 200,
top: 0,
left: 0
},
x: 1,
y: 108,
sizex: 48,
sizey: 24
}
}, },
mutations: { mutations: {
copyMultiplexingComponents(state) {
const _this = this
state.isCut = false
const canvasStyleData = state.canvasStyleData
const curCanvasScale = state.curCanvasScale
const componentGap = state.componentGap
Object.keys(state.curMultiplexingComponents).forEach(function(viewId, index) {
const component =
{
...deepCopy(state.curMultiplexingComponents[viewId]),
...deepCopy(state.viewBase),
'auxiliaryMatrix': canvasStyleData.auxiliaryMatrix
}
const tilePosition = index % 3
const divisiblePosition = parseInt(index / 3)
if (canvasStyleData.auxiliaryMatrix) {
const width = component.sizex * curCanvasScale.matrixStyleOriginWidth
// 取余 平铺4个 此处x 位置偏移
component.x = component.x + component.sizex * tilePosition
component.style.left = (component.x - 1) * curCanvasScale.matrixStyleOriginWidth
component.style.top = (component.y - 1) * curCanvasScale.matrixStyleOriginHeight
component.style.width = width
component.style.height = component.sizey * curCanvasScale.matrixStyleOriginHeight
} else {
const width = component.style.width
const height = component.style.height
component.style.top = component.style.top + divisiblePosition * (height + componentGap)
component.style.left = component.style.left + tilePosition * (width + componentGap)
component.style.width = width
component.style.height = height
}
state.copyData = {
data: component,
index: index
}
_this.commit('paste', true)
})
},
copy(state) { copy(state) {
if (!state.curComponent) return if (!state.curComponent) return
state.copyData = { state.copyData = {

View File

@ -68,6 +68,14 @@ export function mobile2MainCanvas(mainSource, mobileSource) {
} }
export function panelInit(componentData, componentStyle) { export function panelInit(componentData, componentStyle) {
panelDataPrepare(componentData, componentStyle, function() {
// 将data 和 style 数据设置到全局store中
store.commit('setComponentData', resetID(componentData))
store.commit('setCanvasStyle', componentStyle)
})
}
export function panelDataPrepare(componentData, componentStyle, callback) {
// style初始化 // style初始化
componentStyle.refreshTime = (componentStyle.refreshTime || 5) componentStyle.refreshTime = (componentStyle.refreshTime || 5)
componentStyle.refreshViewLoading = (componentStyle.refreshViewLoading || false) componentStyle.refreshViewLoading = (componentStyle.refreshViewLoading || false)
@ -109,9 +117,10 @@ export function panelInit(componentData, componentStyle) {
}) })
// 初始化密度为最高密度 // 初始化密度为最高密度
componentStyle.aidedDesign.matrixBase = 4 componentStyle.aidedDesign.matrixBase = 4
// 将data 和 style 数据设置到全局store中 callback({
store.commit('setComponentData', resetID(componentData)) 'componentData': resetID(componentData),
store.commit('setCanvasStyle', componentStyle) 'componentStyle': componentStyle
})
} }
export function resetID(data) { export function resetID(data) {

View File

@ -1447,6 +1447,7 @@ export default {
sure_bt: 'Confirm' sure_bt: 'Confirm'
}, },
panel: { panel: {
multiplexing: 'Multiplexing',
panel_off: 'Off the shelf', panel_off: 'Off the shelf',
batch_opt: 'Batch Operation', batch_opt: 'Batch Operation',
edit_leave_tips: 'Do You Want To Abandon And Leave The Current Page?', edit_leave_tips: 'Do You Want To Abandon And Leave The Current Page?',

View File

@ -131,8 +131,8 @@ export default {
default_login: '普通登錄' default_login: '普通登錄'
}, },
commons: { commons: {
publish: '布', publish: '布',
unpublished: '取消布', unpublished: '取消布',
default_pwd: '初始密碼', default_pwd: '初始密碼',
stop: '停止', stop: '停止',
first_login_tips: '您使用的是初始密碼,記得修改密碼哦', first_login_tips: '您使用的是初始密碼,記得修改密碼哦',
@ -915,10 +915,10 @@ export default {
color_fast: '輕快', color_fast: '輕快',
color_spiritual: '靈動', color_spiritual: '靈動',
chart_details: '視圖明細', chart_details: '視圖明細',
details: '明', details: '明',
image: '片', image: '片',
export_details: '導出明細', export_details: '導出明細',
export: '出', export: '出',
chart_data: '數據', chart_data: '數據',
chart_style: '樣式', chart_style: '樣式',
drag_block_type_axis: '類別軸', drag_block_type_axis: '類別軸',
@ -1096,7 +1096,7 @@ export default {
unit_million: '百萬', unit_million: '百萬',
unit_hundred_million: '億', unit_hundred_million: '億',
formatter_decimal_count_error: '請輸入0-10的整數', formatter_decimal_count_error: '請輸入0-10的整數',
gauge_threshold_compare_error: '值範圍需逐級遞增', gauge_threshold_compare_error: '值範圍需逐級遞增',
tick_count: '刻度間隔數', tick_count: '刻度間隔數',
custom_sort: '自定義', custom_sort: '自定義',
custom_sort_tip: '自定義排序優先級最高,且僅支持單個字段自定義', custom_sort_tip: '自定義排序優先級最高,且僅支持單個字段自定義',
@ -1340,8 +1340,8 @@ export default {
}, },
datasource: { datasource: {
auth_method: '認證方式', auth_method: '認證方式',
passwd: '用户名密码', passwd: '用戶名密碼',
kerbers_info: '请确保 krb5.Conf、Keytab Key已经添加到路径/opt/dataease/conf', kerbers_info: '請確保 krb5.Conf、Keytab Key已經添加到路徑/opt/dataease/conf',
client_principal: 'Client Principal', client_principal: 'Client Principal',
keytab_Key_path: 'Keytab Key Path', keytab_Key_path: 'Keytab Key Path',
datasource: '數據源', datasource: '數據源',
@ -1448,16 +1448,17 @@ export default {
sure_bt: '確定' sure_bt: '確定'
}, },
panel: { panel: {
panel_off: '仪表板已下架', multiplexing: '復用',
panel_off: '儀表板已下架',
batch_opt: '批量操作', batch_opt: '批量操作',
edit_leave_tips: '是否放弃编辑离开当前界面?', edit_leave_tips: '是否放棄編輯離開當前界面?',
hyperlinks: '超鏈接', hyperlinks: '超鏈接',
is_live: '是否直播', is_live: '是否直播',
yes: '是', yes: '是',
no: '否', no: '否',
live_tips: '優先HTTPS鏈接', live_tips: '優先HTTPS鏈接',
stream_media_add_tips: '請點擊添加配置流媒體信息...', stream_media_add_tips: '請點擊添加配置流媒體信息...',
stream_mobile_tips: 'IOS终端可能无法显示', stream_mobile_tips: 'IOS終端可能無法顯示',
json_params_error: '第三方參數解析失敗,請檢查參數格式是否正確', json_params_error: '第三方參數解析失敗,請檢查參數格式是否正確',
inner_padding: '內邊距', inner_padding: '內邊距',
board_radio: '邊框半徑', board_radio: '邊框半徑',
@ -1544,7 +1545,7 @@ export default {
save_to_panel: '保存爲模闆', save_to_panel: '保存爲模闆',
export_to_panel: '導出爲模闆', export_to_panel: '導出爲模闆',
export_to_pdf: '導出爲PDF', export_to_pdf: '導出爲PDF',
export_to_img: '導出爲片', export_to_img: '導出爲片',
preview: '預覽', preview: '預覽',
fullscreen_preview: '全屏預覽', fullscreen_preview: '全屏預覽',
new_tab_preview: '新Tab頁預覽', new_tab_preview: '新Tab頁預覽',
@ -2052,6 +2053,6 @@ export default {
passwd: '密碼' passwd: '密碼'
}, },
plugin_style: { plugin_style: {
border: '框' border: '框'
} }
} }

View File

@ -1455,6 +1455,7 @@ export default {
sure_bt: '确定' sure_bt: '确定'
}, },
panel: { panel: {
multiplexing: '复用',
panel_off: '仪表板已下架', panel_off: '仪表板已下架',
batch_opt: '批量操作', batch_opt: '批量操作',
edit_leave_tips: '是否放弃编辑离开当前界面?', edit_leave_tips: '是否放弃编辑离开当前界面?',

View File

@ -21,7 +21,7 @@ import event from '@/components/canvas/store/event'
import layer from '@/components/canvas/store/layer' import layer from '@/components/canvas/store/layer'
import snapshot from '@/components/canvas/store/snapshot' import snapshot from '@/components/canvas/store/snapshot'
import lock from '@/components/canvas/store/lock' import lock from '@/components/canvas/store/lock'
import { valueValid, formatCondition, formatLinkageCondition } from '@/utils/conditionUtil' import { valueValid, formatCondition } from '@/utils/conditionUtil'
import { Condition } from '@/components/widget/bean/Condition' import { Condition } from '@/components/widget/bean/Condition'
import { import {
@ -118,6 +118,8 @@ const data = {
batchOptStatus: false, batchOptStatus: false,
// Currently selected components // Currently selected components
curBatchOptComponents: [], curBatchOptComponents: [],
// Currently selected Multiplexing components
curMultiplexingComponents: {},
mixProperties: [], mixProperties: [],
mixPropertiesInner: {}, mixPropertiesInner: {},
batchOptChartInfo: null, batchOptChartInfo: null,
@ -559,6 +561,14 @@ const data = {
} }
} }
}, },
removeCurMultiplexingComponentWithId(state, id) {
delete state.curMultiplexingComponents[id]
},
addCurMultiplexingComponent(state, { component, componentId }) {
if (componentId) {
state.curMultiplexingComponents[componentId] = component
}
},
setBatchOptChartInfo(state) { setBatchOptChartInfo(state) {
let render = null let render = null
let type = null let type = null
@ -647,9 +657,11 @@ const data = {
this.commit('setCurComponent', { component: null, index: null }) this.commit('setCurComponent', { component: null, index: null })
this.commit('clearLinkageSettingInfo', false) this.commit('clearLinkageSettingInfo', false)
this.commit('resetViewEditInfo') this.commit('resetViewEditInfo')
this.commit('initCurMultiplexingComponents')
state.batchOptStatus = false state.batchOptStatus = false
// Currently selected components // Currently selected components
state.curBatchOptComponents = [] state.curBatchOptComponents = []
state.curMultiplexingComponents = {}
state.mixProperties = [] state.mixProperties = []
state.mixPropertyInnder = {} state.mixPropertyInnder = {}
state.batchOptChartInfo = null state.batchOptChartInfo = null
@ -664,6 +676,9 @@ const data = {
plugin.isPlugin = true plugin.isPlugin = true
}) })
state.allViewRender = [...TYPE_CONFIGS, ...pluginViews] state.allViewRender = [...TYPE_CONFIGS, ...pluginViews]
},
initCurMultiplexingComponents(state) {
state.curMultiplexingComponents = {}
} }
}, },
modules: { modules: {

View File

@ -1,6 +1,10 @@
<template> <template>
<div style="width: 100%;height: 100vh;background-color: #f7f8fa"> <div style="width: 100%;height: 100vh;background-color: #f7f8fa">
<Preview v-if="show" /> <Preview
v-if="show"
:component-data="componentData"
:canvas-style-data="canvasStyleData"
/>
</div> </div>
</template> </template>
@ -12,6 +16,7 @@ import { getPanelAllLinkageInfo } from '@/api/panel/linkage'
import { queryPanelJumpInfo, queryTargetPanelJumpInfo } from '@/api/panel/linkJump' import { queryPanelJumpInfo, queryTargetPanelJumpInfo } from '@/api/panel/linkJump'
import { panelInit } from '@/components/canvas/utils/utils' import { panelInit } from '@/components/canvas/utils/utils'
import { getOuterParamsInfo } from '@/api/panel/outerParams' import { getOuterParamsInfo } from '@/api/panel/outerParams'
import { mapState } from 'vuex'
export default { export default {
name: 'LinkView', name: 'LinkView',
@ -31,6 +36,12 @@ export default {
show: false show: false
} }
}, },
computed: {
...mapState([
'canvasStyleData',
'componentData'
])
},
created() { created() {
this.show = false this.show = false
this.setPanelInfo() this.setPanelInfo()

View File

@ -0,0 +1,264 @@
<template>
<el-col v-loading="loading">
<el-row style="margin-top: 5px">
<el-row style="margin-left: 5px;margin-right: 5px">
<el-col>
<el-input
v-model="templateFilterText"
:placeholder="$t('panel.filter_keywords')"
size="mini"
clearable
prefix-icon="el-icon-search"
/>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-tree
ref="templateTree"
:default-expanded-keys="defaultExpandedKeys"
:show-checkbox="selectModel"
:data="data"
node-key="id"
:props="defaultProps"
draggable
:allow-drop="allowDrop"
:allow-drag="allowDrag"
:expand-on-click-node="true"
:filter-node-method="filterNode"
:highlight-current="true"
@node-drag-start="handleDragStart"
@check="checkChanged"
@node-drag-end="dragEnd"
>
<span slot-scope="{ node, data }" class="custom-tree-node-list father">
<span style="display: flex; flex: 1 1 0%; width: 0px;">
<span v-if="data.modelInnerType==='history'">
<i class="el-icon-collection" />
</span>
<span v-else-if="data.nodeType === 'spine'">
<i class="el-icon-folder" />
</span>
<span v-else-if="data.modelType==='panel'&& data.nodeType === 'leaf'">
<svg-icon icon-class="panel" class="ds-icon-scene" />
</span>
<span v-else>
<svg-icon :icon-class="data.isPlugin && data.type && data.type !== 'buddle-map' ? ('/api/pluginCommon/staticInfo/' + data.modelInnerType + '/svg') : data.modelInnerType" style="width: 14px;height: 14px" />
</span>
<span style="margin-left: 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;" :title="data.name">{{ data.name }}</span>
</span>
<span v-if="data.mode===1" class="child">
<span @click.stop>
<el-button
icon="el-icon-delete"
type="text"
size="small"
@click="deleteHistory(data, node)"
/>
</span>
</span>
</span>
</el-tree>
</el-row>
</el-row>
</el-col>
</template>
<script>
import componentList from '@/components/canvas/custom-component/component-list'
import { deepCopy } from '@/components/canvas/utils/utils'
import eventBus from '@/components/canvas/utils/eventBus'
import { mapState } from 'vuex'
import { queryPanelViewTree } from '@/api/panel/panel'
import { deleteCircle } from '@/api/chart/chart'
import { pluginTypes } from '@/api/chart/chart'
import { matrixBaseChange } from '@/components/canvas/utils/utils'
export default {
name: 'ViewSelect',
props: {
selectModel: {
type: Boolean,
default: false
}
},
data() {
return {
templateFilterText: '',
defaultExpandedKeys: [],
defaultProps: {
children: 'children',
label: 'name',
disabled: 'disabled'
},
data: [],
showdetail: false,
detailItem: null,
loading: false,
plugins: null
}
},
computed: {
...mapState([
'canvasStyleData'
])
},
watch: {
templateFilterText(val) {
this.$refs.templateTree.filter(val)
}
},
created() {
this.plugins = localStorage.getItem('plugin-views') && JSON.parse(localStorage.getItem('plugin-views'))
if (this.plugins) {
this.loadData()
} else {
pluginTypes().then(res => {
this.plugins = res.data
localStorage.setItem('plugin-views', JSON.stringify(res.data))
this.loadData()
}).catch(e => {
localStorage.setItem('plugin-views', null)
this.plugins = null
this.loadData()
})
}
},
methods: {
filterNode(value, data) {
if (!value) return true
return data.name.indexOf(value) !== -1
},
loadData() {
this.loading = true
queryPanelViewTree().then(res => {
const nodeDatas = res.data
if (this.selectModel) {
this.setParentDisable(nodeDatas)
}
this.data = nodeDatas
this.loading = false
})
},
handleDragStart(node, ev) {
this.$store.commit('setDragComponentInfo', this.viewComponentInfo())
ev.dataTransfer.effectAllowed = 'copy'
const dataTrans = {
type: 'view',
id: node.data.innerId
}
ev.dataTransfer.setData('componentInfo', JSON.stringify(dataTrans))
eventBus.$emit('startMoveIn')
},
dragEnd() {
this.$store.commit('clearDragComponentInfo')
},
//
allowDrag(draggingNode) {
if (draggingNode.data.modelType === 'panel' || draggingNode.data.nodeType === 'spine') {
return false
} else {
return true
}
},
allowDrop(draggingNode, dropNode, type) {
return false
},
newChart() {
this.$emit('newChart')
},
checkChanged(node, status) {
this.$refs.templateTree.setCheckedNodes([])
if (status.checkedKeys && status.checkedKeys.length > 0) {
this.$refs.templateTree.setCheckedNodes([node])
}
},
getCurrentSelected() {
const nodes = this.$refs.templateTree.getCheckedNodes(true, false)
return nodes
},
setParentDisable(nodes) {
nodes.forEach(node => {
if (node.modelType === 'panel' || node.nodeType === 'spine') {
node.disabled = true
}
if (node.modelType === 'view' && node.modelInnerType && this.plugins && this.plugins.length) {
node.isPlugin = this.plugins.some(plugin => plugin.value === node.modelInnerType)
}
if (node.children && node.children.length > 0) {
this.setParentDisable(node.children)
}
})
},
viewComponentInfo() {
let component
//
componentList.forEach(componentTemp => {
if (componentTemp.type === 'view') {
component = matrixBaseChange(deepCopy(componentTemp))
}
})
component.auxiliaryMatrix = this.canvasStyleData.auxiliaryMatrix
component.moveStatus = 'start'
return component
},
deleteHistory(data, node) {
deleteCircle(data.id).then(() => {
this.$success(this.$t('commons.delete_success'))
this.remove(node, data)
// this.loadData()
})
},
remove(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === data.id)
children.splice(index, 1)
},
showDetails(node, data) {
this.$emit('showDetails', {
'showType': data.nodeType,
'showId': data.id
})
}
}
}
</script>
<style lang="scss" scoped>
.top-div-class {
max-height: calc(100vh - 335px);
width: 100%;
position: fixed;
overflow-y : auto
}
.detail-class {
width: 300px;
position: fixed;
bottom: 0px;
}
.view-list-thumbnails {
width: 100%;
height: 100%;
}
.father .child {
/*display: none;*/
visibility: hidden;
}
.father:hover .child {
/*display: inline;*/
visibility: visible;
}
.custom-tree-node-list {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding:0 8px;
}
</style>

View File

@ -0,0 +1,122 @@
<template>
<de-container
v-loading="panelLoading"
class="main-class"
>
<de-aside-container v-loading="viewLoading" class="aside-class" type="panel">
<multiplexing-view :view-data="viewData" @showDetails="showDetails" />
</de-aside-container>
<de-main-container>
<Preview
v-if="selectedPanel"
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:show-position="'multiplexing'"
/>
<el-col v-else style="height: 100%;">
<el-row style="height: 100%; background-color: var(--ContentBG);" class="custom-position">
{{ $t('panel.select_panel_from_left') }}
</el-row>
</el-col>
</de-main-container>
</de-container>
</template>
<script>
import DeMainContainer from '@/components/dataease/DeMainContainer'
import DeContainer from '@/components/dataease/DeContainer'
import DeAsideContainer from '@/components/dataease/DeAsideContainer'
import { findOne } from '@/api/panel/panel'
import { panelDataPrepare } from '@/components/canvas/utils/utils'
import Preview from '@/components/canvas/components/Editor/Preview'
import MultiplexingView from '@/views/panel/ViewSelect/multiplexingView'
export default {
name: 'Multiplexing',
components: { MultiplexingView, Preview, DeMainContainer, DeContainer, DeAsideContainer },
props: {
viewData: {
type: Array,
required: true
}
},
data() {
return {
activeName: 'PanelList',
viewLoading: false,
panelLoading: false,
showShare: false,
showEnshrine: false,
msgPanelIds: null,
componentData: [],
canvasStyleData: {},
selectedPanel: null
}
},
watch: {
},
mounted() {
},
methods: {
showDetails(params) {
const _this = this
_this.selectedPanel = params.showId
if (params.showType === 'panel') {
this.panelLoading = true
findOne(params.showId).then(response => {
this.panelLoading = false
panelDataPrepare(JSON.parse(response.data.panelData), JSON.parse(response.data.panelStyle), function(rsp) {
_this.componentData = rsp.componentData
_this.canvasStyleData = rsp.componentStyle
})
})
}
}
}
}
</script>
<style scoped>
.ms-aside-container {
height: calc(100vh - 120px);
padding: 0px;
min-width: 260px;
max-width: 460px;
}
.ms-main-container {
height: calc(100vh - 120px);
padding: 0px;
}
.tab-panel{
height: 100%;
overflow-y: auto;
}
.tab-panel>>>.el-tabs__nav-wrap{
padding: 0 10px;
}
.tab-panel>>>.el-tabs__nav-wrap::after {
height: 1px;
}
.tab-panel>>>.el-tabs__item{
/* width: 10px; */
padding: 0 10px;
}
.main-class {
border: 1px gainsboro solid;
}
::v-deep .drag-bar{
height: calc(100vh - 120px)!important;
}
.custom-position {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
flex-flow: row nowrap;
color: #9ea6b2;
}
</style>

View File

@ -0,0 +1,165 @@
<template>
<el-col v-loading="loading" style="height: 100%; overflow-y: auto">
<el-row style="margin-top: 5px">
<el-row style="margin-left: 5px;margin-right: 5px">
<el-col>
<el-input
v-model="templateFilterText"
:placeholder="$t('panel.filter_keywords')"
size="mini"
clearable
prefix-icon="el-icon-search"
/>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-tree
ref="templateTree"
:data="viewData"
node-key="id"
:props="defaultProps"
:expand-on-click-node="true"
:filter-node-method="filterNode"
:highlight-current="true"
@node-click="showDetails"
>
<span slot-scope="{ node, data }" class="custom-tree-node-list father">
<span style="display: flex; flex: 1 1 0%; width: 0px;">
<span v-if="data.modelInnerType==='history'">
<i class="el-icon-collection" />
</span>
<span v-else-if="data.nodeType === 'spine'">
<i class="el-icon-folder" />
</span>
<span v-else-if="data.modelType==='panel'&& data.nodeType === 'leaf'">
<svg-icon icon-class="panel" class="ds-icon-scene" />
</span>
<span v-else>
<svg-icon :icon-class="data.isPlugin && data.type && data.type !== 'buddle-map' ? ('/api/pluginCommon/staticInfo/' + data.modelInnerType + '/svg') : data.modelInnerType" style="width: 14px;height: 14px" />
</span>
<span style="margin-left: 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;" :title="data.name">{{ data.name }}</span>
</span>
<span v-if="data.mode===1" class="child">
<span @click.stop>
<el-button
icon="el-icon-delete"
type="text"
size="small"
@click="deleteHistory(data, node)"
/>
</span>
</span>
</span>
</el-tree>
</el-row>
</el-row>
</el-col>
</template>
<script>
import { mapState } from 'vuex'
import { deleteCircle } from '@/api/chart/chart'
export default {
name: 'MultiplexingView',
props: {
selectModel: {
type: Boolean,
default: false
},
viewData: {
type: Array,
required: true
}
},
data() {
return {
templateFilterText: '',
defaultProps: {
children: 'children',
label: 'name',
disabled: 'disabled'
},
data: [],
detailItem: null,
loading: false,
plugins: null
}
},
computed: {
...mapState([
'canvasStyleData'
])
},
watch: {
templateFilterText(val) {
this.$refs.templateTree.filter(val)
}
},
created() {
},
methods: {
filterNode(value, data) {
if (!value) return true
return data.name.indexOf(value) !== -1
},
deleteHistory(data, node) {
deleteCircle(data.id).then(() => {
this.$success(this.$t('commons.delete_success'))
this.remove(node, data)
// this.loadData()
})
},
remove(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === data.id)
children.splice(index, 1)
},
showDetails(node, data) {
if (data.data.nodeType === 'leaf') {
this.$emit('showDetails', {
'showType': data.data.modelType,
'showId': data.data.id
})
}
}
}
}
</script>
<style lang="scss" scoped>
.top-div-class {
max-height: calc(100vh - 335px);
width: 100%;
position: fixed;
overflow-y : auto
}
.detail-class {
width: 300px;
position: fixed;
bottom: 0px;
}
.view-list-thumbnails {
width: 100%;
height: 100%;
}
.father .child {
/*display: none;*/
visibility: hidden;
}
.father:hover .child {
/*display: inline;*/
visibility: visible;
}
.custom-tree-node-list {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding:0 8px;
}
</style>

View File

@ -111,11 +111,10 @@
style=" width: 24px;height: 24px;text-align: center;line-height: 1;position: relative;margin: 16px auto 0px;" style=" width: 24px;height: 24px;text-align: center;line-height: 1;position: relative;margin: 16px auto 0px;"
> >
<el-button <el-button
:class="show&&showIndex===0? 'button-show':'button-closed'"
circle circle
class="el-icon-copy-document" class="el-icon-copy-document button-closed"
size="mini" size="mini"
@click="showPanel(0)" @click="showMultiplexing(true)"
/> />
</div> </div>
<div class="button-text" style="position: relative; margin: 18px auto 16px;"> <div class="button-text" style="position: relative; margin: 18px auto 16px;">
@ -123,7 +122,7 @@
style="max-width: 100%;text-align: center;white-space: nowrap;text-overflow: ellipsis;position: relative;flex-shrink: 0;" style="max-width: 100%;text-align: center;white-space: nowrap;text-overflow: ellipsis;position: relative;flex-shrink: 0;"
> >
<!-- {{ $t('panel.view') }}--> <!-- {{ $t('panel.view') }}-->
复用 {{ $t('panel.multiplexing') }}
</div> </div>
</div> </div>
<div style="height: 1px; position: relative; margin: 0px auto;background-color:#E6E6E6;"> <div style="height: 1px; position: relative; margin: 0px auto;background-color:#E6E6E6;">
@ -150,7 +149,7 @@
:close-on-press-escape="false" :close-on-press-escape="false"
:modal-append-to-body="true" :modal-append-to-body="true"
> >
<view-select v-show=" show && showIndex===0" @newChart="newChart" /> <!-- <view-select v-show=" show && showIndex===0" @newChart="newChart" />-->
<filter-group v-show=" show &&showIndex===1" /> <filter-group v-show=" show &&showIndex===1" />
<subject-setting v-show=" show &&showIndex===2" /> <subject-setting v-show=" show &&showIndex===2" />
<assist-component v-show=" show &&showIndex===3" /> <assist-component v-show=" show &&showIndex===3" />
@ -276,6 +275,8 @@
v-if="previewVisible" v-if="previewVisible"
:in-screen="!previewVisible" :in-screen="!previewVisible"
:show-type="canvasStyleData.selfAdaption?'full':'width'" :show-type="canvasStyleData.selfAdaption?'full':'width'"
:canvas-style-data="canvasStyleData"
:component-data="componentData"
/> />
</fullscreen> </fullscreen>
<input <input
@ -312,6 +313,25 @@
<OuterParamsSet v-if="outerParamsSetVisible" @outerParamsSetVisibleChange="outerParamsSetVisibleChange" /> <OuterParamsSet v-if="outerParamsSetVisible" @outerParamsSetVisibleChange="outerParamsSetVisibleChange" />
</el-dialog> </el-dialog>
<!--复用视图全屏显示框-->
<el-dialog
:visible="multiplexingShow"
:show-close="false"
class="dialog-css"
:fullscreen="true"
>
<multiplexing v-if="multiplexingShow" :view-data="viewData" />
<div slot="title" class="dialog-footer title-text">
<span style="font-size: 14px;">
{{ $t('panel.multiplexing') }}
</span>
<span style="float: right;">
<el-button type="primary" size="mini" @click="saveMultiplexing()">{{ $t('commons.confirm') }}</el-button>
<el-button size="mini" @click="showMultiplexing(false)">{{ $t('commons.cancel') }}</el-button>
</span>
</div>
</el-dialog>
</el-row> </el-row>
</template> </template>
@ -325,7 +345,7 @@ import ViewSelect from '../ViewSelect'
import SubjectSetting from '../SubjectSetting' import SubjectSetting from '../SubjectSetting'
import bus from '@/utils/bus' import bus from '@/utils/bus'
import Editor from '@/components/canvas/components/Editor/index' import Editor from '@/components/canvas/components/Editor/index'
import { deepCopy, matrixBaseChange, panelInit } from '@/components/canvas/utils/utils' import { deepCopy, matrixBaseChange } from '@/components/canvas/utils/utils'
import componentList, { import componentList, {
BASE_MOBILE_STYLE, BASE_MOBILE_STYLE,
COMMON_BACKGROUND, COMMON_BACKGROUND,
@ -334,7 +354,7 @@ import componentList, {
import { mapState } from 'vuex' import { mapState } from 'vuex'
import { uuid } from 'vue-uuid' import { uuid } from 'vue-uuid'
import Toolbar from '@/components/canvas/components/Toolbar' import Toolbar from '@/components/canvas/components/Toolbar'
import { initPanelData, initViewCache } from '@/api/panel/panel' import { initPanelData, initViewCache, queryPanelMultiplexingViewTree } from '@/api/panel/panel'
import Preview from '@/components/canvas/components/Editor/Preview' import Preview from '@/components/canvas/components/Editor/Preview'
import elementResizeDetectorMaker from 'element-resize-detector' import elementResizeDetectorMaker from 'element-resize-detector'
import AssistComponent from '@/views/panel/AssistComponent' import AssistComponent from '@/views/panel/AssistComponent'
@ -354,10 +374,12 @@ import { deleteEnshrine, saveEnshrine, starStatus } from '@/api/panel/enshrine'
import ChartEdit from '@/views/chart/view/ChartEdit' import ChartEdit from '@/views/chart/view/ChartEdit'
import OuterParamsSet from '@/views/panel/OuterParamsSet/index' import OuterParamsSet from '@/views/panel/OuterParamsSet/index'
import ChartStyleBatchSet from '@/views/chart/view/ChartStyleBatchSet' import ChartStyleBatchSet from '@/views/chart/view/ChartStyleBatchSet'
import Multiplexing from '@/views/panel/ViewSelect/multiplexing'
export default { export default {
name: 'PanelEdit', name: 'PanelEdit',
components: { components: {
Multiplexing,
ChartStyleBatchSet, ChartStyleBatchSet,
OuterParamsSet, OuterParamsSet,
ComponentWait, ComponentWait,
@ -378,6 +400,8 @@ export default {
}, },
data() { data() {
return { return {
viewData: [],
multiplexingShow: false,
asideToolType: 'none', asideToolType: 'none',
outerParamsSetVisible: false, outerParamsSetVisible: false,
autoMoveOffSet: 15, autoMoveOffSet: 15,
@ -545,6 +569,9 @@ export default {
return this.pcMatrixCount return this.pcMatrixCount
} }
}, },
multiplexingDisabled() {
return Object.keys(this.curMultiplexingComponents) === 0
},
...mapState([ ...mapState([
'curComponent', 'curComponent',
'curCanvasScale', 'curCanvasScale',
@ -560,7 +587,8 @@ export default {
'mobileMatrixCount', 'mobileMatrixCount',
'mobileLayoutStyle', 'mobileLayoutStyle',
'scrollAutoMove', 'scrollAutoMove',
'batchOptStatus' 'batchOptStatus',
'curMultiplexingComponents'
]) ])
}, },
@ -616,12 +644,18 @@ export default {
_this.restore() _this.restore()
}) })
}) })
this.loadMultiplexingViewTree()
}, },
beforeDestroy() { beforeDestroy() {
const elx = this.$refs.rightPanel const elx = this.$refs.rightPanel
elx && elx.remove() elx && elx.remove()
}, },
methods: { methods: {
loadMultiplexingViewTree() {
queryPanelMultiplexingViewTree().then(res => {
this.viewData = res.data
})
},
closeOuterParamsSetDialog() { closeOuterParamsSetDialog() {
this.outerParamsSetVisible = false this.outerParamsSetVisible = false
}, },
@ -1080,6 +1114,15 @@ export default {
const canvasInfoMobile = document.getElementById('canvasInfoMobile') const canvasInfoMobile = document.getElementById('canvasInfoMobile')
canvasInfoMobile.scrollTop = canvasInfoMobile.scrollTop + offset canvasInfoMobile.scrollTop = canvasInfoMobile.scrollTop + offset
this.$store.commit('setScrollAutoMove', this.scrollAutoMove + offset) this.$store.commit('setScrollAutoMove', this.scrollAutoMove + offset)
},
showMultiplexing(type) {
this.multiplexingShow = type
},
saveMultiplexing() {
this.showMultiplexing(false)
this.$store.commit('copyMultiplexingComponents')
this.$store.commit('recordSnapshot')
this.$store.state.styleChangeTimes++
} }
} }
} }
@ -1348,4 +1391,15 @@ export default {
height: calc(100vh - 100px); height: calc(100vh - 100px);
} }
.dialog-css ::v-deep .el-dialog__title {
font-size: 14px;
}
.dialog-css ::v-deep .el-dialog__header {
padding: 20px 20px 0;
}
.dialog-css ::v-deep .el-dialog__body {
padding: 10px 20px 20px;
}
</style> </style>

View File

@ -68,7 +68,7 @@ export default {
this.$store.commit('initViewRender', plugins) this.$store.commit('initViewRender', plugins)
}).catch(e => { }).catch(e => {
localStorage.setItem('plugin-views', null) localStorage.setItem('plugin-views', null)
this.$store.commit('initViewRender', plugins) this.$store.commit('initViewRender', [])
}) })
this.clear() this.clear()
}, },

View File

@ -52,13 +52,13 @@
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</span> </span>
<span style="float: right;margin-right: 10px" v-if="panelInfo.status==='publish'"> <span v-if="panelInfo.status==='publish'" style="float: right;margin-right: 10px">
<el-tooltip :content="$t('panel.fullscreen_preview')"> <el-tooltip :content="$t('panel.fullscreen_preview')">
<el-button class="el-icon-view" size="mini" circle @click="clickFullscreen" /> <el-button class="el-icon-view" size="mini" circle @click="clickFullscreen" />
</el-tooltip> </el-tooltip>
</span> </span>
<span style="float: right;margin-right: 10px" v-if="panelInfo.status==='publish'"> <span v-if="panelInfo.status==='publish'" style="float: right;margin-right: 10px">
<el-tooltip :content="$t('panel.new_tab_preview')"> <el-tooltip :content="$t('panel.new_tab_preview')">
<el-button class="el-icon-data-analysis" size="mini" circle @click="newTab" /> <el-button class="el-icon-data-analysis" size="mini" circle @click="newTab" />
</el-tooltip> </el-tooltip>
@ -90,7 +90,15 @@
<!-- <div id="imageWrapper" ref="imageWrapper" style="width: 4096px;height: 2160px">--> <!-- <div id="imageWrapper" ref="imageWrapper" style="width: 4096px;height: 2160px">-->
<div id="imageWrapper" ref="imageWrapper" :style="imageWrapperStyle"> <div id="imageWrapper" ref="imageWrapper" :style="imageWrapperStyle">
<fullscreen style="height: 100%;background: #f7f8fa;overflow-y: auto" :fullscreen.sync="fullscreen"> <fullscreen style="height: 100%;background: #f7f8fa;overflow-y: auto" :fullscreen.sync="fullscreen">
<Preview v-if="showMainFlag" :active-tab="activeTab" :in-screen="!fullscreen" :show-type="'width'" :screen-shot="dataLoading" /> <Preview
v-if="showMainFlag"
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:active-tab="activeTab"
:in-screen="!fullscreen"
:show-type="'width'"
:screen-shot="dataLoading"
/>
</fullscreen> </fullscreen>
</div> </div>
</el-row> </el-row>