feat(仪表板、数据大屏): 仪表板和数据大屏从编辑到保存期间若被其他人保存了,则给出提示,支持覆盖和取消

This commit is contained in:
wangjiahao 2024-11-18 17:25:28 +08:00
parent facf7a1477
commit 643eb9b0bb
13 changed files with 116 additions and 12 deletions

View File

@ -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;
}

View File

@ -6,11 +6,11 @@ import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* 可视化大屏信息表 Mapper 接口
* </p>
*
* @author fit2cloud
* @since 2024-04-11
* @since 2024-11-18
*/
@Mapper
public interface DataVisualizationInfoMapper extends BaseMapper<DataVisualizationInfo> {

View File

@ -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<DataVisualizationInfo> 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

View File

@ -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 '内容标识';

View File

@ -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';
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 '内容标识';

View File

@ -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}

View File

@ -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 })

View File

@ -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 = () => {

View File

@ -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 }
},

View File

@ -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({

View File

@ -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")

View File

@ -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;

View File

@ -145,6 +145,11 @@ public class DataVisualizationVO implements Serializable {
*/
private Integer version;
/**
* 内容标识
*/
private String contentId;
/**
* 图表基本信息
*/