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;
+
/**
* 图表基本信息
*/