import { Revoke } from "@/utils/revoke"; import { getToken } from "@/utils/auth"; import { getToolByCode } from "@/views/bigscreenDesigner/designer/tools/index"; import { insertDashboard, detailDashboard, exportDashboard, } from "@/api/bigscreen"; const mixin = { data() { return { reportCode: this.$route.query.reportCode, uploadUrl: process.env.BASE_API + "/reportDashboard/import/" + this.$route.query.reportCode, revoke: null, //处理历史记录 rightClickIndex: -1, rightClickWidget: null, } }, computed: { step() { return Number(100 / (this.bigscreenScaleInWorkbench * 100)); }, headers() { return { Authorization: getToken(), }; }, // 初始的缩放百分比 和 下标 defaultSize() { const obj = { index: -1, size: "50", }; this.sizeRange.some((item, index) => { if (item <= 100 * this.bigscreenScaleInWorkbench) { obj.index = index; obj.size = 100 * this.bigscreenScaleInWorkbench; } }); if (obj.index === -1) { obj.index = 0; obj.size = this.sizeRange[0]; } return obj; }, }, watch: { defaultSize: { handler(val) { if (val !== -1) { this.currentSizeRangeIndex = val.index; this.scaleNum = val.size; } }, immediate: true, }, bigscreenWidth() { this.initVueRulerTool(); }, bigscreenHeight() { this.initVueRulerTool(); }, }, created() { this.revoke = new Revoke(); this.getData(); }, methods: { /** * @param num: 0缩小 1放大 2默认比例 * sizeRange: [20, 40, 60, 72, 100, 150, 200, 300, 400] */ setSize(num) { switch (num) { case 0: this.currentSizeRangeIndex === 0 ? '' : this.currentSizeRangeIndex -= 1; break; case 1: this.currentSizeRangeIndex === 8 ? '' : this.currentSizeRangeIndex += 1; break; case 2: this.currentSizeRangeIndex = this.defaultSize.index; } this.scaleNum = this.currentSizeRangeIndex === this.defaultSize.index ? this.defaultSize.size : this.sizeRange[this.currentSizeRangeIndex]; }, // 初始化 修正插件样式 initVueRulerTool() { const vueRulerToolDom = this.$refs["vue-ruler-tool"].$el; // 操作面板 第三方插件工具 const contentDom = vueRulerToolDom.querySelector(".vue-ruler-content"); const vueRulerX = vueRulerToolDom.querySelector(".vue-ruler-h"); // 横向标尺 const vueRulerY = vueRulerToolDom.querySelector(".vue-ruler-v"); // 纵向标尺 contentDom.style.width = "100%"; contentDom.style.height = "100%"; let xHtmlContent = ""; let yHtmlContent = ""; let currentNum = 0; while (currentNum < +this.bigscreenWidth) { xHtmlContent += `${currentNum}`; currentNum += 50; } currentNum = 0; while (currentNum < +this.bigscreenHeight) { yHtmlContent += `${currentNum}`; currentNum += 50; } vueRulerX.innerHTML = xHtmlContent; vueRulerY.innerHTML = yHtmlContent; }, // 初始化接口数据 async getData() { const { code, data } = await detailDashboard(this.reportCode); if (code != 200) return; this.widgets = this.initWidgetsData(data); this.dashboard = this.initScreenData(data.dashboard); this.bigscreenWidth = this.dashboard.width; this.bigscreenHeight = this.dashboard.height; }, // 组件数据 initWidgetsData(data) { const widgets = data.dashboard ? data.dashboard.widgets : []; const widgetsData = []; for (let i = 0; i < widgets.length; i++) { const widget = widgets[i] const { setup, data, position } = { ...widget.value } const obj = { type: widget.type, value: { setup, data, position } }; const tool = this.deepClone(getToolByCode(widget.type)); if (!tool) { const message = "暂未提供该组件或该组件下线了,组件code: " + widget.type; if (process.env.NODE_ENV === "development") { this.$message.error(message); } continue; // 找不到就跳过,避免整个报表都加载不出来 } obj.options = this.setDefaultWidgetConfigValue(widget.value, tool.options); obj.value.widgetId = obj.value.setup.widgetId; widgetsData.push(obj); } return widgetsData; }, // 重写默认数据 setDefaultWidgetConfigValue(data, option) { this.setConfigValue(data.setup, option.setup) this.setConfigValue(data.position, option.position) this.setConfigValue(data.data, option.data) return option; }, setConfigValue(objValue, setup) { Object.keys(objValue).forEach(key => { setup.forEach(item => { if (this.isObjectFn(item) && key == item.name) { item.value = objValue[key] } if (this.isArrayFn(item)) { item.forEach(itemChild => { itemChild.list.forEach(el => { if (key == el.name) { el.value = objValue[key] } }) }) } }) }) }, // 大屏数据 initScreenData(data) { const optionScreen = getToolByCode("screen").options; this.setConfigValue(data, optionScreen.setup) this.setOptionsOnClickScreen(); return { backgroundColor: (data && data.backgroundColor) || (!data ? "#1e1e1e" : ""), backgroundImage: (data && data.backgroundImage) || "", height: (data && data.height) || "1080", title: (data && data.title) || "", width: (data && data.width) || "1920", }; }, // 保存数据 async saveData() { if (!this.widgets || this.widgets.length == 0) { return this.$message.error("请添加组件"); } const { title, width, height, backgroundColor, backgroundImage, refreshSeconds } = { ...this.dashboard } const screenData = { reportCode: this.reportCode, dashboard: { title, width, height, backgroundColor, backgroundImage, refreshSeconds }, widgets: this.widgets, }; screenData.widgets.forEach((widget) => { widget.value.setup.widgetId = widget.value.widgetId; widget.value.setup.widgetCode = widget.type }); const { code, data } = await insertDashboard(screenData); if (code == "200") return this.$message.success("保存成功!"); }, // 预览 viewScreen() { let routeUrl = this.$router.resolve({ path: "/bigscreen/viewer", query: { reportCode: this.reportCode }, }); window.open(routeUrl.href, "_blank"); }, async exportDashboard(val) { const fileName = this.reportCode + ".zip"; const param = { reportCode: this.reportCode, showDataSet: val, }; exportDashboard(param).then((res) => { const that = this; const type = res.type; if (type == "application/json") { let reader = new FileReader(); reader.readAsText(res, "utf-8"); reader.onload = function () { const data = JSON.parse(reader.result); that.$message.error(data.message); }; return; } const blob = new Blob([res], { type: "application/octet-stream" }); if (window.navigator.msSaveOrOpenBlob) { //msSaveOrOpenBlob方法返回bool值 navigator.msSaveBlob(blob, fileName); //本地保存 } else { const link = document.createElement("a"); //a标签下载 link.href = window.URL.createObjectURL(blob); link.download = fileName; link.click(); window.URL.revokeObjectURL(link.href); } }); }, handleUndo() { const record = this.revoke.undo(); if (!record) return false; this.widgets = record; }, handleRedo() { const record = this.revoke.redo(); if (!record) return false; this.widgets = record; }, handleUpload(response, file, fileList) { this.$refs.upload.clearFiles(); this.getData(); if (response.code == "200") return this.$message.success('导入成功!') this.$message.error(response.message) }, // 右键 rightClick(event, index) { this.rightClickIndex = index; this.rightClickWidget = this.widgets[index]; const left = event.clientX; const top = event.clientY; if (left || top) { this.styleObj = { left: left + "px", top: top + "px", display: "block", }; } //设置多选和单选的菜单项展示 document.getElementsByName("singleSelect").forEach(e=>{ e.style.display= this.selectedWidgets.length >= 2 ?"none":"block"; }); document.getElementsByName("mulSelect").forEach(e=>{ e.style.display= this.selectedWidgets.length >= 2 ?"block":"none"; }) this.visibleContentMenu = true; return false; }, // 数组 元素互换位置 swapArr(arr, oldIndex, newIndex) { arr[oldIndex] = arr.splice(newIndex, 1, arr[oldIndex])[0]; return arr; }, // 删除 deletelayer() { let _this = this; this.widgets.splice(this.rightClickIndex, 1); this.selectedWidgets.forEach(sw=>{ _this.widgets = _this.widgets.filter(w=>w.value.widgetId !== sw.value.widgetId); }) }, // 锁定 lockLayer() { const obj = this.widgets[this.rightClickIndex]; this.$set(obj.value.position, "disabled", true); }, // 解除锁定 noLockLayer() { const obj = this.widgets[this.rightClickIndex]; this.$set(obj.value.position, "disabled", false); }, // 复制 copylayer() { const obj = this.deepClone(this.widgets[this.rightClickIndex]); obj.value.position.top += 40; // 复制的元素向右下角偏移一点 obj.value.position.left += 40; obj.value.widgetId = Number(Math.random().toString().substr(2)).toString( 36 ); this.widgets.splice(this.widgets.length, 0, obj); this.$nextTick(() => { this.layerClick(this.widgets.length - 1); // 复制后定位到最新的组件 }); }, // 置顶 istopLayer() { if (this.rightClickIndex + 1 < this.widgets.length) { const temp = this.widgets.splice(this.rightClickIndex, 1)[0]; this.widgets.push(temp); } this.widgetIndex = this.widgets.indexOf(this.rightClickWidget); this.widgetsClickFocus(this.widgetIndex); }, // 置底 setlowLayer() { if (this.rightClickIndex != 0) { this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]); } this.widgetIndex = this.widgets.indexOf(this.rightClickWidget); this.widgetsClickFocus(this.widgetIndex); }, // 上移一层 moveupLayer() { if (this.rightClickIndex != 0) { this.widgets[this.rightClickIndex] = this.widgets.splice( this.rightClickIndex - 1, 1, this.widgets[this.rightClickIndex] )[0]; } else { this.widgets.push(this.widgets.shift()); } this.widgetIndex = this.widgets.indexOf(this.rightClickWidget); this.widgetsClickFocus(this.widgetIndex); }, // 下移一层 movedownLayer() { if (this.rightClickIndex != this.widgets.length - 1) { this.widgets[this.rightClickIndex] = this.widgets.splice( this.rightClickIndex + 1, 1, this.widgets[this.rightClickIndex] )[0]; } else { this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]); } this.widgetIndex = this.widgets.indexOf(this.rightClickWidget); this.widgetsClickFocus(this.widgetIndex); }, //对齐 alignment(align) { if(this.selectedWidgets.length <= 1) { this.$message.error("请至少选择两个组件对齐"); return; } console.log("对齐方式:" + align); let topWidget = this.selectedWidgets[0]; //最上组件(左右对齐使用) let leftWidget = this.selectedWidgets[0]; //最左组件(上下对齐使用) let minTop = this.selectedWidgets[0].value.position.top; let minLeft = this.selectedWidgets[0].value.position.left; //如果是框选的话,以【最上组件】【最左组件】为标准对齐;如果是Ctrl多选方式,则以第一个选中的组件为标准对齐,组合多选以框选逻辑为准 if(this.kuangSelectFlag){ for(let i = 0; i< this.selectedWidgets.length; i++){ let widget = this.selectedWidgets[i]; if( minTop > widget.value.position.top){ minTop = widget.value.position.top; topWidget = widget; } if( minLeft > widget.value.position.left){ minLeft = widget.value.position.left; leftWidget = widget; } } } for(let i = 0; i< this.selectedWidgets.length; i++){ let widget = this.selectedWidgets[i]; this.$refs.widgets.forEach(w=>{ if(w.value.widgetId === widget.value.widgetId){ w.$refs.draggable.setActive(false); } }); this.widgets.forEach(w=>{ if(w.value.widgetId === widget.value.widgetId){ switch (align){ case "left": //左对齐 w.value.position.left = topWidget.value.position.left; break; case "right": //右对齐 w.value.position.left = topWidget.value.position.left + topWidget.value.position.width - w.value.position.width; break; case "horizontal_center": //左右居中对齐 w.value.position.left = topWidget.value.position.left + topWidget.value.position.width/2 - w.value.position.width /2; break; case "top": //上对齐 w.value.position.top = leftWidget.value.position.top; break; case "bottom": //下对齐 w.value.position.top = leftWidget.value.position.top + leftWidget.value.position.height - w.value.position.height; break; case "vertical_center": //上下居中对齐 w.value.position.top = leftWidget.value.position.top + leftWidget.value.position.height/2 - w.value.position.height /2; break; } } }); } this.selectedWidgets = []; if(this.rect){ document.getElementById("workbench").removeChild(this.rect); } this.kuangSelectFlag = false; } } } export default mixin