diff --git a/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/entity/DataVisualizationInfo.java b/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/entity/DataVisualizationInfo.java index 591e2c2e85..cdfca78b09 100644 --- a/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/entity/DataVisualizationInfo.java +++ b/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/entity/DataVisualizationInfo.java @@ -128,6 +128,16 @@ public class DataVisualizationInfo implements Serializable { */ private Integer version; + private String contentId; + + public String getContentId() { + return contentId; + } + + public void setContentId(String contentId) { + this.contentId = contentId; + } + public Long getId() { return id; } diff --git a/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/mapper/DataVisualizationInfoMapper.java b/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/mapper/DataVisualizationInfoMapper.java index 4dd49b2d84..9b34106a11 100644 --- a/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/mapper/DataVisualizationInfoMapper.java +++ b/core/core-backend/src/main/java/io/dataease/visualization/dao/auto/mapper/DataVisualizationInfoMapper.java @@ -6,11 +6,11 @@ import org.apache.ibatis.annotations.Mapper; /** *

- * Mapper 接口 + * 可视化大屏信息表 Mapper 接口 *

* * @author fit2cloud - * @since 2024-04-11 + * @since 2024-11-18 */ @Mapper public interface DataVisualizationInfoMapper extends BaseMapper { 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 9c341b14bd..9dc134b5ce 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 @@ -429,6 +429,25 @@ public class DataVisualizationServer implements DataVisualizationApi { } } + @Override + public String checkCanvasChange(DataVisualizationBaseRequest request) { + Long dvId = request.getId(); + Boolean checkHistory = request.getCheckHistory(); + if (dvId == null) { + DEException.throwException("ID can not be null"); + } + // 内容ID校验 + if(checkHistory !=null && checkHistory){ + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("content_id", request.getContentId()); + queryWrapper.eq("id", dvId); + if (visualizationInfoMapper.exists(queryWrapper)) { + return "Repeat"; + } + } + return null; + } + @DeLog(id = "#p0.id", ot = LogOT.MODIFY, stExp = "#p0.type") @Override @Transactional diff --git a/core/core-backend/src/main/resources/db/desktop/V2.10.3__ddl.sql b/core/core-backend/src/main/resources/db/desktop/V2.10.3__ddl.sql index 036684523c..18d88553ff 100644 --- a/core/core-backend/src/main/resources/db/desktop/V2.10.3__ddl.sql +++ b/core/core-backend/src/main/resources/db/desktop/V2.10.3__ddl.sql @@ -1,2 +1,6 @@ INSERT INTO `core_sys_setting`(`id`, `pkey`, `pval`, `type`, `sort`) VALUES (1048232869488627719, 'basic.defaultSort', '1', 'text', 13); + + +ALTER TABLE `data_visualization_info` + ADD COLUMN `content_id` varchar(50) NULL DEFAULT '0' COMMENT '内容标识'; diff --git a/core/core-backend/src/main/resources/db/migration/V2.10.3__ddl.sql b/core/core-backend/src/main/resources/db/migration/V2.10.3__ddl.sql index 60b271c0d5..f7f158b973 100644 --- a/core/core-backend/src/main/resources/db/migration/V2.10.3__ddl.sql +++ b/core/core-backend/src/main/resources/db/migration/V2.10.3__ddl.sql @@ -3,4 +3,7 @@ VALUES (1048232869488627719, 'basic.defaultSort', '1', 'text', 13); INSERT INTO `core_menu` VALUES (70, 0, 1, 'msg', NULL, 200, NULL, '/msg', 1, 1, 0); -UPDATE `xpack_setting_authentication` set `synced` = 0 where `name` = 'oidc' or name = 'cas'; \ No newline at end of file +UPDATE `xpack_setting_authentication` set `synced` = 0 where `name` = 'oidc' or name = 'cas'; + +ALTER TABLE `data_visualization_info` + ADD COLUMN `content_id` varchar(50) NULL DEFAULT '0' COMMENT '内容标识'; diff --git a/core/core-backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml b/core/core-backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml index b87d798459..793a8539d4 100644 --- a/core/core-backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml +++ b/core/core-backend/src/main/resources/mybatis/ExtDataVisualizationMapper.xml @@ -166,7 +166,8 @@ `delete_flag`, `delete_time`, `delete_by`, - `version` + `version`, + `content_id` FROM data_visualization_info where data_visualization_info.delete_flag = 0 and data_visualization_info.id = #{dvId} diff --git a/core/core-frontend/src/api/visualization/dataVisualization.ts b/core/core-frontend/src/api/visualization/dataVisualization.ts index 8084bede74..9f85d62fb3 100644 --- a/core/core-frontend/src/api/visualization/dataVisualization.ts +++ b/core/core-frontend/src/api/visualization/dataVisualization.ts @@ -52,6 +52,9 @@ export const findDvType = async dvId => export const save = data => request.post({ url: '/dataVisualization/save', data }) +export const checkCanvasChange = data => + request.post({ url: '/dataVisualization/checkCanvasChange', data, loading: true }) + export const saveCanvas = data => request.post({ url: '/dataVisualization/saveCanvas', data, loading: true }) diff --git a/core/core-frontend/src/components/data-visualization/DvToolbar.vue b/core/core-frontend/src/components/data-visualization/DvToolbar.vue index 27ea637cc2..04cd0574b1 100644 --- a/core/core-frontend/src/components/data-visualization/DvToolbar.vue +++ b/core/core-frontend/src/components/data-visualization/DvToolbar.vue @@ -26,7 +26,13 @@ import MediaGroup from '@/custom-component/component-group/MediaGroup.vue' import TextGroup from '@/custom-component/component-group/TextGroup.vue' import CommonGroup from '@/custom-component/component-group/CommonGroup.vue' import DeResourceGroupOpt from '@/views/common/DeResourceGroupOpt.vue' -import { canvasSave, initCanvasData } from '@/utils/canvasUtils' +import { + canvasSave, + checkCanvasChangePre, + checkCanvasHistory, + confirmUpdateCanvas, + initCanvasData +} from '@/utils/canvasUtils' import { changeSizeWithScale } from '@/utils/changeComponentsSizeWithScale' import MoreComGroup from '@/custom-component/component-group/MoreComGroup.vue' import { XpackComponent } from '@/components/plugin' @@ -41,6 +47,7 @@ import DeAppApply from '@/views/common/DeAppApply.vue' import { useEmitt } from '@/hooks/web/useEmitt' import { useUserStoreWithOut } from '@/store/modules/user' import TabsGroup from '@/custom-component/component-group/TabsGroup.vue' +import { checkCanvasChange } from '@/api/visualization/dataVisualization' let nameEdit = ref(false) let inputName = ref('') let nameInput = ref(null) @@ -150,7 +157,9 @@ const saveCanvasWithCheck = () => { } return } - saveResource() + checkCanvasChangePre(() => { + saveResource() + }) } const saveResource = () => { diff --git a/core/core-frontend/src/store/modules/data-visualization/dvMain.ts b/core/core-frontend/src/store/modules/data-visualization/dvMain.ts index 9c58c01df6..6ff60705e8 100644 --- a/core/core-frontend/src/store/modules/data-visualization/dvMain.ts +++ b/core/core-frontend/src/store/modules/data-visualization/dvMain.ts @@ -1348,7 +1348,8 @@ export const dvMainStore = defineStore('dataVisualization', { selfWatermarkStatus: null, watermarkInfo: {}, type: null, - mobileLayout: false + mobileLayout: false, + contentId: 0 } this.mainScrollTop = 0 }, @@ -1396,13 +1397,16 @@ export const dvMainStore = defineStore('dataVisualization', { getViewDetails(viewId) { return this.canvasViewInfo[viewId] }, - updateDvInfoId(newId) { + updateDvInfoId(newId, contentId?) { if (this.dvInfo) { this.dvInfo.dataState = 'ready' this.dvInfo.optType = null if (newId) { this.dvInfo.id = newId } + if (contentId) { + this.dvInfo.contentId = contentId + } } }, popAreaActiveSwitch() { @@ -1430,7 +1434,8 @@ export const dvMainStore = defineStore('dataVisualization', { status: 1, selfWatermarkStatus: true, watermarkInfo: watermarkInfo, - mobileLayout: false + mobileLayout: false, + contentId: '0' } const canvasStyleDataNew = dvType === 'dashboard' @@ -1472,7 +1477,8 @@ export const dvMainStore = defineStore('dataVisualization', { selfWatermarkStatus: null, watermarkInfo: {}, type: null, - mobileLayout: false + mobileLayout: false, + contentId: '0' } this.canvasStyleData = { ...deepCopy(DEFAULT_CANVAS_STYLE_DATA_DARK), backgroundColor: null } }, diff --git a/core/core-frontend/src/utils/canvasUtils.ts b/core/core-frontend/src/utils/canvasUtils.ts index efaa745293..6dfaff4e53 100644 --- a/core/core-frontend/src/utils/canvasUtils.ts +++ b/core/core-frontend/src/utils/canvasUtils.ts @@ -11,7 +11,9 @@ import eventBus from '@/utils/eventBus' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { appCanvasNameCheck, + checkCanvasChange, decompression, + deleteLogic, dvNameCheck, findById, findCopyResource, @@ -27,7 +29,8 @@ import { } from '@/views/chart/components/editor/util/chart' import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot' import { deepCopy } from '@/utils/utils' -import { ElMessage } from 'element-plus-secondary' +import { ElMessage, ElMessageBox } from 'element-plus-secondary' +import { guid } from '@/views/visualized/data/dataset/form/util' const dvMainStore = dvMainStoreWithOut() const { inMobile, @@ -332,6 +335,7 @@ export function initCanvasDataPrepare(dvId, busiFlag, callBack) { watermarkInfo: watermarkInfo, weight: canvasInfo.weight, ext: canvasInfo.ext, + contentId: canvasInfo.contentId, mobileLayout: canvasInfo.mobileLayout || false } const canvasVersion = canvasInfo.version @@ -517,6 +521,34 @@ export function checkIsBatchOptView(viewId) { return curBatchOptComponents.value.includes(viewId) } +export function checkCanvasHistory(callBack) { + ElMessageBox.confirm('当前存在变更是否覆盖', { + confirmButtonType: 'danger', + type: 'warning', + tip: '确认覆盖', + autofocus: false, + showClose: false + }).then(() => { + callBack() + }) +} + +export function checkCanvasChangePre(callBack) { + // do pre + const isUpdate = dvInfo.value.id && dvInfo.value.optType !== 'copy' + if (isUpdate) { + checkCanvasChange(dvInfo.value).then(rsp => { + if (rsp.data === 'Repeat') { + checkCanvasHistory(() => { + callBack() + }) + } + }) + } else { + callBack() + } +} + export async function canvasSave(callBack) { dvMainStore.removeGroupArea() const componentDataToSave = cloneDeep(componentData.value) @@ -535,12 +567,14 @@ export async function canvasSave(callBack) { }) } }) + const newContentId = guid() const canvasInfo = { canvasStyleData: JSON.stringify(canvasStyleData.value), componentData: JSON.stringify(componentDataToSave), canvasViewInfo: canvasViewInfo.value, appData: appData.value, ...dvInfo.value, + contentId: newContentId, watermarkInfo: null } @@ -557,7 +591,6 @@ export async function canvasSave(callBack) { ElMessage.error('数据集分组名称已存在') return } - const method = dvInfo.value.id && dvInfo.value.optType !== 'copy' ? updateCanvas : saveCanvas if (method === updateCanvas) { await dvNameCheck({ diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/visualization/DataVisualizationApi.java b/sdk/api/api-base/src/main/java/io/dataease/api/visualization/DataVisualizationApi.java index 31d0e27ccc..3b9401feb9 100644 --- a/sdk/api/api-base/src/main/java/io/dataease/api/visualization/DataVisualizationApi.java +++ b/sdk/api/api-base/src/main/java/io/dataease/api/visualization/DataVisualizationApi.java @@ -53,6 +53,11 @@ public interface DataVisualizationApi { @Operation(summary = "应用名称检查") String appCanvasNameCheck(@RequestBody DataVisualizationBaseRequest request) throws Exception; + @PostMapping("/checkCanvasChange") + @DePermit(value = {"#p0.id + ':manage'"}, busiFlag = "#p0.type") + @Operation(summary = "画布变动校验") + String checkCanvasChange(@RequestBody DataVisualizationBaseRequest request); + @PostMapping("/updateCanvas") @DePermit(value = {"#p0.id + ':manage'"}, busiFlag = "#p0.type") diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/visualization/request/DataVisualizationBaseRequest.java b/sdk/api/api-base/src/main/java/io/dataease/api/visualization/request/DataVisualizationBaseRequest.java index 9049cb77f6..f521cc22b7 100644 --- a/sdk/api/api-base/src/main/java/io/dataease/api/visualization/request/DataVisualizationBaseRequest.java +++ b/sdk/api/api-base/src/main/java/io/dataease/api/visualization/request/DataVisualizationBaseRequest.java @@ -51,6 +51,12 @@ public class DataVisualizationBaseRequest extends DataVisualizationVO { // 数据集分组名称 private String datasetFolderName; + //新赋值的content_id + private String newContentId; + + // 是否强制校验新旧contentId + private Boolean checkHistory = false; + public DataVisualizationBaseRequest(Long id,String busiFlag) { this.busiFlag = busiFlag; diff --git a/sdk/api/api-base/src/main/java/io/dataease/api/visualization/vo/DataVisualizationVO.java b/sdk/api/api-base/src/main/java/io/dataease/api/visualization/vo/DataVisualizationVO.java index 5c048cb767..7ca3a31849 100644 --- a/sdk/api/api-base/src/main/java/io/dataease/api/visualization/vo/DataVisualizationVO.java +++ b/sdk/api/api-base/src/main/java/io/dataease/api/visualization/vo/DataVisualizationVO.java @@ -145,6 +145,11 @@ public class DataVisualizationVO implements Serializable { */ private Integer version; + /** + * 内容标识 + */ + private String contentId; + /** * 图表基本信息 */