diff --git a/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationManage.java b/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationManage.java index de54e9ccd5..9564cd1728 100644 --- a/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationManage.java +++ b/core/core-backend/src/main/java/io/dataease/visualization/manage/CoreVisualizationManage.java @@ -286,30 +286,22 @@ public class CoreVisualizationManage { outerParamsMapper.deleteOuterParamsWithVisualizationId(dvId.toString()); } } + @Transactional - public void dvSnapshotCheck(Long dvId){ - /** - * 1.检查当前仪表板(大屏)是否存在镜像 - * 2.如果已经存在 不做处理 - * 3.如果不存在则将主表所有信息拷贝到镜像中 - * */ - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("id", dvId); - if(!snapshotMapper.exists(queryWrapper)){ - // 清理历史数据 - this.removeSnapshot(dvId); - // 导入新数据 - extDataVisualizationMapper.snapshotDataV(dvId); - extDataVisualizationMapper.snapshotViews(dvId); - extDataVisualizationMapper.snapshotLinkJumpTargetViewInfo(dvId); - extDataVisualizationMapper.snapshotLinkJumpInfo(dvId); - extDataVisualizationMapper.snapshotLinkJump(dvId); - extDataVisualizationMapper.snapshotLinkageField(dvId); - extDataVisualizationMapper.snapshotLinkage(dvId); - extDataVisualizationMapper.snapshotOuterParamsTargetViewInfo(dvId); - extDataVisualizationMapper.snapshotOuterParamsInfo(dvId); - extDataVisualizationMapper.snapshotOuterParams(dvId); - } + public void dvSnapshotRecover(Long dvId){ + // 清理历史数据 + this.removeSnapshot(dvId); + // 导入新数据 + extDataVisualizationMapper.snapshotDataV(dvId); + extDataVisualizationMapper.snapshotViews(dvId); + extDataVisualizationMapper.snapshotLinkJumpTargetViewInfo(dvId); + extDataVisualizationMapper.snapshotLinkJumpInfo(dvId); + extDataVisualizationMapper.snapshotLinkJump(dvId); + extDataVisualizationMapper.snapshotLinkageField(dvId); + extDataVisualizationMapper.snapshotLinkage(dvId); + extDataVisualizationMapper.snapshotOuterParamsTargetViewInfo(dvId); + extDataVisualizationMapper.snapshotOuterParamsInfo(dvId); + extDataVisualizationMapper.snapshotOuterParams(dvId); } @Transactional public void dvRestore(Long dvId){ diff --git a/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java b/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java index 0f22ccf4ea..19990a6c5e 100644 --- a/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java +++ b/core/core-backend/src/main/java/io/dataease/visualization/server/DataVisualizationServer.java @@ -51,8 +51,10 @@ import io.dataease.template.dao.ext.ExtVisualizationTemplateMapper; import io.dataease.template.manage.TemplateCenterManage; import io.dataease.utils.*; import io.dataease.visualization.dao.auto.entity.DataVisualizationInfo; +import io.dataease.visualization.dao.auto.entity.SnapshotDataVisualizationInfo; import io.dataease.visualization.dao.auto.entity.VisualizationWatermark; import io.dataease.visualization.dao.auto.mapper.DataVisualizationInfoMapper; +import io.dataease.visualization.dao.auto.mapper.SnapshotDataVisualizationInfoMapper; import io.dataease.visualization.dao.auto.mapper.VisualizationWatermarkMapper; import io.dataease.visualization.dao.ext.mapper.ExtDataVisualizationMapper; import io.dataease.visualization.manage.CoreBusiManage; @@ -144,6 +146,9 @@ public class DataVisualizationServer implements DataVisualizationApi { @Resource private DatasourceServer datasourceServer; + @Resource + private SnapshotDataVisualizationInfoMapper snapshotMapper; + @Override public DataVisualizationVO findCopyResource(Long dvId, String busiFlag) { DataVisualizationVO result = Objects.requireNonNull(CommonBeanFactory.proxy(this.getClass())).findById(new DataVisualizationBaseRequest(dvId, busiFlag)); @@ -164,7 +169,11 @@ public class DataVisualizationServer implements DataVisualizationApi { String resourceTable = request.getResourceTable(); // 如果是编辑查询 则进行镜像检查 if(CommonConstants.RESOURCE_TABLE.SNAPSHOT.equals(resourceTable)){ - coreVisualizationManage.dvSnapshotCheck(dvId); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id", dvId); + if(!snapshotMapper.exists(queryWrapper)){ + coreVisualizationManage.dvSnapshotRecover(dvId); + } } DataVisualizationVO result = extDataVisualizationMapper.findDvInfo(dvId, busiFlag,resourceTable); if (result != null) { @@ -531,6 +540,16 @@ public class DataVisualizationServer implements DataVisualizationApi { } } + @Override + public void recoverToPublished(DataVisualizationBaseRequest request) { + coreVisualizationManage.dvSnapshotRecover(request.getId()); + DataVisualizationInfo visualizationInfo = new DataVisualizationInfo(); + visualizationInfo.setId(request.getId()); + visualizationInfo.setName(request.getName()); + visualizationInfo.setStatus(CommonConstants.DV_STATUS.PUBLISHED); + coreVisualizationManage.innerEdit(visualizationInfo); + } + /** * @Description: 更新基础信息; * 为什么单独接口:1.基础信息更新频繁数据且数据载量较小;2.防止出现更新过多信息的情况,造成图表的误删等操作 diff --git a/core/core-frontend/src/api/visualization/dataVisualization.ts b/core/core-frontend/src/api/visualization/dataVisualization.ts index 420cf663ee..a299c02d2f 100644 --- a/core/core-frontend/src/api/visualization/dataVisualization.ts +++ b/core/core-frontend/src/api/visualization/dataVisualization.ts @@ -63,8 +63,10 @@ export const saveCanvas = data => request.post({ url: '/dataVisualization/saveCanvas', data, loading: true }) export const updatePublishStatus = data => - request.post({ url: '/dataVisualization/updatePublishStatus', data, loading: true }) + request.post({ url: '/dataVisualization/updatePublishStatus', data, loading: false }) +export const recoverToPublished = data => + request.post({ url: '/dataVisualization/recoverToPublished', data, loading: true }) export const appCanvasNameCheck = async data => request.post({ url: '/dataVisualization/appCanvasNameCheck', data, loading: false }) diff --git a/core/core-frontend/src/assets/svg/dv-recover_outlined.svg b/core/core-frontend/src/assets/svg/dv-recover_outlined.svg new file mode 100644 index 0000000000..765f1a03a2 --- /dev/null +++ b/core/core-frontend/src/assets/svg/dv-recover_outlined.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/core/core-frontend/src/components/dashboard/DbToolbar.vue b/core/core-frontend/src/components/dashboard/DbToolbar.vue index 41edae3615..c159e6d78f 100644 --- a/core/core-frontend/src/components/dashboard/DbToolbar.vue +++ b/core/core-frontend/src/components/dashboard/DbToolbar.vue @@ -16,7 +16,9 @@ import icon_undo_outlined from '@/assets/svg/icon_undo_outlined.svg' import icon_redo_outlined from '@/assets/svg/icon_redo_outlined.svg' import icon_pc_fullscreen from '@/assets/svg/icon_pc_fullscreen.svg' import dvPreviewOuter from '@/assets/svg/dv-preview-outer.svg' -import { ElMessage, ElMessageBox } from 'element-plus-secondary' +import dvRecoverOutlined from '@/assets/svg/dv-recover_outlined.svg' +import dvCancelPublish from '@/assets/svg/icon_undo_outlined.svg' +import { ElIcon, ElMessage, ElMessageBox } from 'element-plus-secondary' import eventBus from '@/utils/eventBus' import { useEmbedded } from '@/store/modules/embedded' import { deepCopy } from '@/utils/utils' @@ -85,6 +87,7 @@ const { wsCache } = useCache('localStorage') const userStore = useUserStoreWithOut() const isIframe = computed(() => appStore.getIsIframe) const desktop = wsCache.get('app.desktop') +const emits = defineEmits(['recoverToPublished']) const props = defineProps({ createType: { @@ -180,6 +183,10 @@ const resourceOptFinish = param => { } } +const recoverToPublished = () => { + emits('recoverToPublished') +} + const publishStatusChange = status => { // do update updatePublishStatus({ @@ -189,7 +196,9 @@ const publishStatusChange = status => { type: 'dashboard' }).then(() => { dvMainStore.updateDvInfoCall(status) - ElMessage.success(t('visualization.published_success')) + status + ? ElMessage.success(t('visualization.published_success')) + : ElMessage.success(t('visualization.cancel_publish_tips')) }) } @@ -713,23 +722,35 @@ const initOpenHandler = newWindow => { > {{ t('data_set.save') }} - - {{ t('visualization.re_publish') }} - - - - {{ t('visualization.publish') }} - + + + {{ t('visualization.publish') }} + + + diff --git a/core/core-frontend/src/components/data-visualization/DvToolbar.vue b/core/core-frontend/src/components/data-visualization/DvToolbar.vue index 3d0b048c42..082db16b65 100644 --- a/core/core-frontend/src/components/data-visualization/DvToolbar.vue +++ b/core/core-frontend/src/components/data-visualization/DvToolbar.vue @@ -11,7 +11,9 @@ import icon_copy_filled from '@/assets/svg/icon_copy_filled.svg' import icon_left_outlined from '@/assets/svg/icon_left_outlined.svg' import icon_undo_outlined from '@/assets/svg/icon_undo_outlined.svg' import icon_redo_outlined from '@/assets/svg/icon_redo_outlined.svg' -import { ElMessage, ElMessageBox } from 'element-plus-secondary' +import dvRecoverOutlined from '@/assets/svg/dv-recover_outlined.svg' +import dvCancelPublish from '@/assets/svg/icon_undo_outlined.svg' +import { ElIcon, ElMessage, ElMessageBox } from 'element-plus-secondary' import eventBus from '@/utils/eventBus' import { ref, nextTick, computed, toRefs, onBeforeUnmount, onMounted } from 'vue' import { useEmbedded } from '@/store/modules/embedded' @@ -61,6 +63,7 @@ const outerParamsSetRef = ref(null) const fullScreeRef = ref(null) const userStore = useUserStoreWithOut() const { t } = useI18n() +const emits = defineEmits(['recoverToPublished']) const props = defineProps({ createType: { @@ -68,9 +71,6 @@ const props = defineProps({ default: 'create' } }) - -const { createType } = toRefs(props) - const closeEditCanvasName = () => { nameEdit.value = false if (!inputName.value || !inputName.value.trim()) { @@ -88,6 +88,10 @@ const closeEditCanvasName = () => { inputName.value = '' } +const recoverToPublished = () => { + emits('recoverToPublished') +} + const undo = () => { snapshotStore.undo() } @@ -309,7 +313,9 @@ const publishStatusChange = status => { type: 'dataV' }).then(() => { dvMainStore.updateDvInfoCall(status) - ElMessage.success(t('visualization.published_success')) + status + ? ElMessage.success(t('visualization.published_success')) + : ElMessage.success(t('visualization.cancel_publish_tips')) }) } @@ -467,23 +473,38 @@ const fullScreenPreview = () => { > {{ t('visualization.save') }} - - {{ t('visualization.re_publish') }} - - - - {{ t('visualization.publish') }} - + + + {{ t('visualization.publish') }} + + + diff --git a/core/core-frontend/src/locales/en.ts b/core/core-frontend/src/locales/en.ts index 6cbe221c81..7515b9589c 100644 --- a/core/core-frontend/src/locales/en.ts +++ b/core/core-frontend/src/locales/en.ts @@ -2881,6 +2881,7 @@ export default { column_name: 'Field name' }, visualization: { + publish_recover: 'Revert to the published version', publish_tips1: 'Visible after publication', publish_tips2: 'Available after publication {0}', cancel_publish_tips: 'Successfully unpublished', diff --git a/core/core-frontend/src/locales/tw.ts b/core/core-frontend/src/locales/tw.ts index f857c0615c..f86ea5a1fb 100644 --- a/core/core-frontend/src/locales/tw.ts +++ b/core/core-frontend/src/locales/tw.ts @@ -2802,6 +2802,7 @@ export default { column_name: '欄位名稱' }, visualization: { + publish_recover: '恢復到發佈版本', publish_tips1: '發佈後可查看', publish_tips2: '發佈後可{0}', cancel_publish_tips: '取消發佈成功', diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts index 23d16da102..d0a39f2bc3 100644 --- a/core/core-frontend/src/locales/zh-CN.ts +++ b/core/core-frontend/src/locales/zh-CN.ts @@ -2808,6 +2808,7 @@ export default { column_name: '字段名称' }, visualization: { + publish_recover: '恢复到发布版本', publish_tips1: '发布后可查看', publish_tips2: '发布后可{0}', cancel_publish_tips: '取消发布成功', diff --git a/core/core-frontend/src/views/dashboard/index.vue b/core/core-frontend/src/views/dashboard/index.vue index 082b8be407..5a30a275aa 100644 --- a/core/core-frontend/src/views/dashboard/index.vue +++ b/core/core-frontend/src/views/dashboard/index.vue @@ -33,6 +33,7 @@ import { usePermissionStoreWithOut } from '@/store/modules/permission' import eventBus from '@/utils/eventBus' import { useI18n } from '@/hooks/web/useI18n' import DashboardHiddenComponent from '@/components/dashboard/DashboardHiddenComponent.vue' +import { recoverToPublished } from '@/api/visualization/dataVisualization' const embeddedStore = useEmbedded() const { wsCache } = useCache() const canvasCacheOutRef = ref(null) @@ -158,7 +159,7 @@ const doUseCache = flag => { } } -const initLocalCanvasData = () => { +const initLocalCanvasData = callBack => { const { resourceId, opt, sourcePid } = state const busiFlg = opt === 'copy' ? 'dashboard-copy' : 'dashboard' initCanvasData(resourceId, { busiFlg, resourceTable: 'snapshot' }, function () { @@ -172,6 +173,7 @@ const initLocalCanvasData = () => { }, 1500) } onInitReady({ resourceId: resourceId }) + callBack && callBack() }) } onMounted(async () => { @@ -212,7 +214,9 @@ onMounted(async () => { if (canvasCache) { canvasCacheOutRef.value?.dialogInit({ canvasType: 'dashboard', resourceId: resourceId }) } else { - initLocalCanvasData() + initLocalCanvasData(() => { + // do init + }) } } else if (opt && opt === 'create') { dataInitState.value = false @@ -292,6 +296,19 @@ const cancelHidden = item => { } } +const doRecoverToPublished = () => { + recoverToPublished({ id: dvInfo.value.id, type: 'dashboard', name: dvInfo.value.name }).then( + () => { + initLocalCanvasData(() => { + nextTick(() => { + deCanvasRef.value.canvasInit(false) + dvMainStore.updateDvInfoCall(1) + }) + }) + } + ) +} + onUnmounted(() => { window.removeEventListener('storage', eventCheck) window.removeEventListener('message', winMsgHandle) @@ -305,7 +322,7 @@ onUnmounted(() => { v-loading="requestStore.loadingMap[permissionStore.currentPath]" v-if="loadFinish && !mobileConfig" > - + { }, 2000) }) } else { - initLocalCanvasData() + initLocalCanvasData(() => { + // do init + }) wsCache.delete('DE-DV-CATCH-' + state.resourceId) } } -const initLocalCanvasData = async () => { +const initLocalCanvasData = async callback => { const { opt, sourcePid, resourceId } = state const busiFlag = opt === 'copy' ? 'dataV-copy' : 'dataV' await initCanvasData(resourceId, { busiFlag, resourceTable: 'snapshot' }, function () { @@ -315,6 +318,7 @@ const initLocalCanvasData = async () => { }, 1500) } onInitReady({ resourceId: resourceId }) + callback && callback() }) }) } @@ -401,7 +405,9 @@ onMounted(async () => { if (canvasCache) { canvasCacheOutRef.value?.dialogInit({ canvasType: 'dataV', resourceId: dvId }) } else { - await initLocalCanvasData() + await initLocalCanvasData(() => { + // do init + }) } } else if (opt && opt === 'create') { state.canvasInitStatus = false @@ -498,6 +504,14 @@ const popComponentData = computed(() => componentData.value.filter(ele => ele.category && ele.category === 'hidden') ) +const doRecoverToPublished = () => { + recoverToPublished({ id: dvInfo.value.id, type: 'dataV', name: dvInfo.value.name }).then(() => { + initLocalCanvasData(() => { + dvMainStore.updateDvInfoCall(1) + }) + }) +} + eventBus.on('handleNew', handleNew) eventBus.on('tabSort', tabSort) @@ -509,7 +523,7 @@ eventBus.on('tabSort', tabSort) class="dv-common-layout" :class="isDataEaseBi && !newWindowFromDiv && 'dataease-w-h'" > - +