From 7efac43e55a4373cd7b9adc05d7569ab5f57cbbe Mon Sep 17 00:00:00 2001 From: wangjiahao <1522128093@qq.com> Date: Sat, 9 Oct 2021 00:02:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E7=94=BB=E6=9D=BF=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../panel/PanelViewLinkageController.java | 4 +- frontend/package.json | 5 +- frontend/src/components/DeDrag/drag.js | 948 ++++++++++++++ frontend/src/components/DeDrag/drag.less | 112 ++ frontend/src/components/DeDrag/drag.vue | 986 +++++++++++++++ frontend/src/components/DeDrag/index.vue | 71 +- frontend/src/components/DeDrag/shadow.vue | 51 +- .../canvas/components/Editor/EditBar.vue | 26 +- .../canvas/components/Editor/PGrid.vue | 47 + .../canvas/components/Editor/index.vue | 1103 ++++++++++++++++- .../canvas/custom-component/UserView.vue | 16 +- .../canvas/custom-component/component-list.js | 45 +- frontend/src/lang/en.js | 4 +- frontend/src/lang/tw.js | 4 +- frontend/src/lang/zh.js | 4 +- frontend/src/store/index.js | 18 +- frontend/src/styles/deicon/demo_index.html | 456 ++++--- frontend/src/styles/deicon/iconfont.css | 30 +- frontend/src/styles/deicon/iconfont.js | 2 +- frontend/src/styles/deicon/iconfont.json | 42 + frontend/src/styles/deicon/iconfont.ttf | Bin 15060 -> 16320 bytes frontend/src/styles/deicon/iconfont.woff | Bin 9288 -> 17537 bytes frontend/src/styles/deicon/iconfont.woff2 | Bin 7784 -> 8360 bytes .../src/views/panel/AssistComponent/index.vue | 9 + frontend/src/views/panel/ViewSelect/index.vue | 10 + frontend/src/views/panel/drag/base.vue | 139 +++ frontend/src/views/panel/edit/index.vue | 87 +- frontend/src/views/panel/filter/index.vue | 19 +- 28 files changed, 3966 insertions(+), 272 deletions(-) create mode 100644 frontend/src/components/DeDrag/drag.js create mode 100644 frontend/src/components/DeDrag/drag.less create mode 100644 frontend/src/components/DeDrag/drag.vue create mode 100644 frontend/src/components/canvas/components/Editor/PGrid.vue create mode 100644 frontend/src/views/panel/drag/base.vue diff --git a/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java b/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java index c994a835f7..5dae15e2ef 100644 --- a/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java +++ b/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java @@ -26,14 +26,14 @@ public class PanelViewLinkageController { @Resource private PanelViewLinkageService panelViewLinkageService; - @ApiOperation("获取仪表板视图联动信息") + @ApiOperation("获取仪表板所有视图联动信息") @PostMapping("/getViewLinkageGather") public Map getViewLinkageGather(@RequestBody PanelLinkageRequest request){ return panelViewLinkageService.getViewLinkageGather(request); } - @ApiOperation("获取仪表板视图联动信息") + @ApiOperation("保存仪表板视图联动信息") @PostMapping("/saveLinkage") public void saveLinkage(@RequestBody PanelLinkageRequest request){ panelViewLinkageService.saveLinkage(request); diff --git a/frontend/package.json b/frontend/package.json index 4f9a709770..be23130c08 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -45,14 +45,15 @@ "vue-codemirror": "^4.0.6", "vue-fullscreen": "^2.5.2", "vue-i18n": "7.3.2", - "vue-power-drag": "^0.2.0", "vue-router": "3.0.6", "vue-to-pdf": "^1.0.0", "vue-uuid": "2.0.2", "vuedraggable": "^2.24.3", "vuex": "3.1.0", "webpack": "^4.46.0", - "xlsx": "^0.17.0" + "xlsx": "^0.17.0", + "lodash": "^4.17.4", + "jquery": "^3.1.1" }, "devDependencies": { "@babel/core": "^7.4.0-0", diff --git a/frontend/src/components/DeDrag/drag.js b/frontend/src/components/DeDrag/drag.js new file mode 100644 index 0000000000..23530987a8 --- /dev/null +++ b/frontend/src/components/DeDrag/drag.js @@ -0,0 +1,948 @@ +import _ from 'lodash' +import $ from 'jquery' + +let positionBox = [] +let coordinates = [] // 坐标点集合 + +let lastTask +let isOverlay = false // 是否正在交换位置 +let moveTime = 80 // 移动动画时间 + +let itemMaxY = 0 +let itemMaxX = 0 + +function debounce(func, time) { + if (!isOverlay) { + (function(t) { + isOverlay = true + setTimeout(function() { + t() + setTimeout(function() { + isOverlay = false + if (lastTask !== undefined) { + debounce(lastTask, time) + } + }, moveTime) + }, time) + })(func) + lastTask = undefined + } else { + lastTask = func + } +} + +function scrollScreen(e) { + if (e.clientY + 50 >= window.innerHeight) { + const body = $(document.body) + body.scrollTop(body.scrollTop() + 20) + } else if (e.clientY <= 150) { + const body = $(document.body) + body.scrollTop(body.scrollTop() - 20) + } +} + +/** + * 重置位置盒子 + * + */ +function resetPositionBox() { + // 根据当前容器的宽度来决定多少列 + itemMaxX = this.maxCell + const rows = 1 // 初始100行,后面根据需求会自动增加 + for (let i = 0; i < rows; i++) { + const row = [] + + for (let j = 0; j < this.maxCell; j++) { + row.push({ + el: false + }) + } + + positionBox.push(row) + } +} + +/** + * 填充位置盒子 + * + * @param {any} item + */ +function addItemToPositionBox(item) { + const pb = positionBox + if (item.x <= 0 || item.y <= 0) return + + for (let i = item.x - 1; i < item.x - 1 + item.sizex; i++) { + for (let j = item.y - 1; j < item.y - 1 + item.sizey; j++) { + if (pb[j][i]) { + pb[j][i].el = item + } + } + } +} + +function fillPositionBox(maxY) { + const pb = positionBox + maxY += 2 + for (let j = 0; j < maxY; j++) { + if (pb[j] === undefined) { + const row = [] + for (let i = 0; i < itemMaxX; i++) { + row.push({ + el: false + }) + } + pb.push(row) + } + } + + itemMaxY = maxY + + $(this.$el).css('height', ((itemMaxY + 2) * this.cellHeight) + 'px') +} + +function removeItemFromPositionBox(item) { + const pb = positionBox + if (item.x <= 0 || item.y <= 0) return + for (let i = item.x - 1; i < item.x - 1 + item.sizex; i++) { + for (let j = item.y - 1; j < item.y - 1 + item.sizey; j++) { + if (pb[j][i]) { + pb[j][i].el = false + } + } + } +} + +/** + * 重新计算宽度,使最小单元格能占满整个容器 + * + */ +function recalcCellWidth() { + const containerNode = this.$refs['container'] + const containerWidth = containerNode.offsetWidth + + const cells = Math.round(containerWidth / this.cellWidth) + this.maxCell = cells + + // if (containerWidth % this.cellWidth !=== 0) { + // this.cellWidth += containerWidth % this.cellWidth / cells; + // } +} + +function init() { + this.cellWidth = this.baseWidth + this.baseMarginLeft + this.cellHeight = this.baseHeight + this.baseMarginTop + + positionBox = [] + coordinates = [] // 坐标点集合 + + lastTask = undefined + isOverlay = false // 是否正在交换位置 + moveTime = 80 // 移动动画时间 + + itemMaxY = 0 + itemMaxX = 0 + + const vm = this + + recalcCellWidth.call(this) + + resetPositionBox.call(this) + + let i = 0 + const timeid = setInterval(function() { + if (i >= vm.yourList.length) { + clearInterval(timeid) + vm.$nextTick(function() { + vm.moveAnimate = true + }) + } else { + const item = vm.yourList[i] + addItem.call(vm, item, i) + i++ + } + }, 1) + vm.renderOk = true +} + +function resizePlayer(item, newSize) { + const vm = this + removeItemFromPositionBox(item) + + const belowItems = findBelowItems.call(this, item) + + _.forEach(belowItems, function(upItem) { + const canGoUpRows = canItemGoUp(upItem) + + if (canGoUpRows > 0) { + moveItemUp.call(vm, upItem, canGoUpRows) + } + }) + + item.sizex = newSize.sizex + item.sizey = newSize.sizey + + if (item.sizex + item.x - 1 > itemMaxX) { + item.sizex = itemMaxX - item.x + 1 + } + + if (item.sizey + item.y > itemMaxY) { + fillPositionBox.call(this, item.y + item.sizey) + } + + emptyTargetCell.call(this, item) + + addItemToPositionBox.call(this, item) + + changeItemCoord.call(this, item) + + const canGoUpRows = canItemGoUp(item) + + if (canGoUpRows > 0) { + moveItemUp.call(this, item, canGoUpRows) + } +} + +/** + * 检查移动的位置,如果不合法,会自动修改 + * + * @param {any} item + * @param {any} position + */ +function checkItemPosition(item, position) { + position = position || {} + position.x = position.x || item.x + position.y = position.y || item.y + + // 检查位置 + if (item.x < 1) { + item.x = 1 + } + + // 检查大小 + if (item.sizex > itemMaxX) { + item.sizex = itemMaxX + } + + if (item.sizex < 1) { + item.sizex = 1 + } + + if (item.x + item.sizex - 1 > itemMaxX) { + item.x = itemMaxX - item.sizex + 1 + if (item.x < 1) { + item.x = 1 + } + } + + if (item.y < 1) { + item.y = 1 + } + + if (item.sizey < 1) { + item.sizey = 1 + } + + if (item.y + item.sizey > itemMaxY - 1) { + fillPositionBox.call(this, item.y + item.sizey - 1) + } +} + +/** + * 移动正在拖动的元素 + * + * @param {any} item + * @param {any} position + */ +function movePlayer(item, position) { + const vm = this + removeItemFromPositionBox(item) + + const belowItems = findBelowItems.call(this, item) + + _.forEach(belowItems, function(upItem) { + const canGoUpRows = canItemGoUp(upItem) + if (canGoUpRows > 0) { + moveItemUp.call(vm, upItem, canGoUpRows) + } + }) + + item.x = position.x + item.y = position.y + + checkItemPosition.call(this, item, position) + + emptyTargetCell.call(this, item) + + addItemToPositionBox.call(this, item) + + changeItemCoord.call(this, item) + + const canGoUpRows = canItemGoUp(item) + + if (canGoUpRows > 0) { + moveItemUp.call(this, item, canGoUpRows) + } +} + +function removeItem(index) { + const vm = this + const item = this.yourList[index] + removeItemFromPositionBox(item) + + const belowItems = findBelowItems.call(this, item) + + // $(this.$refs['item' + item._dragId][0]).remove(); + + _.forEach(belowItems, function(upItem) { + const canGoUpRows = canItemGoUp(upItem) + + if (canGoUpRows > 0) { + moveItemUp.call(vm, upItem, canGoUpRows) + } + }) + + this.yourList.splice(index, 1, {}) +} + +function addItem(item, index) { + if (index < 0) { + index = this.yourList.length + } + item._dragId = index + + checkItemPosition.call(this, item, { + x: item.x, + y: item.y + }) + + emptyTargetCell.call(this, item) + + addItemToPositionBox.call(this, item) + + const canGoUpRows = canItemGoUp(item) + + if (canGoUpRows > 0) { + moveItemUp.call(this, item, canGoUpRows) + } + + // 生成坐标点 + // makeCoordinate.call(this, item); +} + +function changeToCoord(left, top, width, height) { + return { + x1: left, + x2: left + width, + y1: top, + y2: top + height, + c1: left + width / 2, + c2: top + height / 2 + } +} + +/** + * 检测有无碰撞,并作出处理 + * + * @param {any} tCoord 比对对象的坐标 + */ +function findClosetCoords(item, tCoord) { + if (isOverlay) return + let i = coordinates.length + let collisionsItem = [] + while (i--) { + const nowCoord = coordinates[i] + if (item._dragId === nowCoord.el._dragId) { + continue + } + + if (tCoord.x2 < nowCoord.x1 || tCoord.x1 > nowCoord.x2 || tCoord.y2 < nowCoord.y1 || tCoord.y1 > nowCoord.y2) { + continue + } else { + collisionsItem.push({ + centerDistance: Math.sqrt(Math.pow(tCoord.c1 - nowCoord.c1, 2) + Math.pow(tCoord.c2 - nowCoord.c2, 2)), + coord: nowCoord + }) + } + } + + if (collisionsItem.length <= 0) { + return + } + + isOverlay = true + + collisionsItem = _.sortBy(collisionsItem, 'area') + + movePlayer.call(this, item, { + x: collisionsItem[0].coord.el.x, + y: collisionsItem[0].coord.el.y + }) + + setTimeout(function() { + isOverlay = false + }, 200) +} + +/** + * 生成坐标点 + * + * @param {any} item + */ +function makeCoordinate(item) { + const width = this.cellWidth * (item.sizex) - this.baseMarginLeft + const height = this.cellHeight * (item.sizey) - this.baseMarginTop + const left = this.cellWidth * (item.x - 1) + this.baseMarginLeft + const top = this.cellHeight * (item.y - 1) + this.baseMarginTop + + const coord = { + x1: left, + x2: left + width, + y1: top, + y2: top + height, + c1: left + width / 2, + c2: top + height / 2, + el: item + } + + coordinates.push(coord) +} + +function changeItemCoord(item) { + const width = this.cellWidth * (item.sizex) - this.baseMarginLeft + const height = this.cellHeight * (item.sizey) - this.baseMarginTop + const left = this.cellWidth * (item.x - 1) + this.baseMarginLeft + const top = this.cellHeight * (item.y - 1) + this.baseMarginTop + + const coord = { + x1: left, + x2: left + width, + y1: top, + y2: top + height, + c1: left + width / 2, + c2: top + height / 2, + el: item + } + + const index = _.findIndex(coordinates, function(o) { + return o.el._dragId === item._dragId + }) + if (index !== -1) { + coordinates.splice(index, 1, coord) + } +} + +/** + * 清空目标位置的元素 + * + * @param {any} item + */ +function emptyTargetCell(item) { + const vm = this + const belowItems = findBelowItems(item) + + _.forEach(belowItems, function(downItem, index) { + if (downItem._dragId === item._dragId) return + const moveSize = item.y + item.sizey - downItem.y + if (moveSize > 0) { + moveItemDown.call(vm, downItem, moveSize) + } + }) +} + +/** + * 当前位置的item能否上浮 + * + * @param {any} item + * @returns + */ +function canItemGoUp(item) { + let upperRows = 0 + for (let row = item.y - 2; row >= 0; row--) { + for (let cell = item.x - 1; cell < item.x - 1 + item.sizex; cell++) { + if (positionBox[row][cell] && positionBox[row][cell].el) { + return upperRows + } + } + upperRows++ + } + + return upperRows +} + +/** + * 在移动之前,找到当前下移的元素的下面的元素(递归) + * + * @param {any} items + * @param {any} size + */ +function moveItemDown(item, size) { + const vm = this + removeItemFromPositionBox(item) + + const belowItems = findBelowItems(item) + + _.forEach(belowItems, function(downItem, index) { + if (downItem._dragId === item._dragId) return + const moveSize = calcDiff(item, downItem, size) + if (moveSize > 0) { + moveItemDown.call(vm, downItem, moveSize) + } + }) + + const targetPosition = { + y: item.y + size + } + setPlayerPosition.call(this, item, targetPosition) + checkItemPosition.call(this, item, targetPosition) + + addItemToPositionBox.call(this, item) + + changeItemCoord.call(this, item) +} + +function setPlayerPosition(item, position) { + const vm = this + position = position || {} + + const targetX = position.x || item.x + const targetY = position.y || item.y + + item.x = targetX + item.y = targetY + + if (item.y + item.sizey > itemMaxY) { + itemMaxY = item.y + item.sizey + } +} + +/** + * 寻找子元素到父元素的最大距离 + * + * @param {any} parent + * @param {any} son + * @param {any} size + */ +function calcDiff(parent, son, size) { + const diffs = [] + + for (let i = son.x - 1; i < son.x - 1 + son.sizex; i++) { + let temp_y = 0 + + for (let j = parent.y - 1 + parent.sizey; j < son.y - 1; j++) { + if (positionBox[j][i] && positionBox[j][i].el === false) { + temp_y++ + } + } + diffs.push(temp_y) + } + + const max_diff = Math.max.apply(Math, diffs) + size = size - max_diff + + return size > 0 ? size : 0 +} + +function moveItemUp(item, size) { + // console.log('moveItemUp') + const vm = this + + removeItemFromPositionBox(item) + + const belowItems = findBelowItems.call(this, item) + + // item.y -= size; + setPlayerPosition.call(this, item, { + y: item.y - size + }) + + addItemToPositionBox.call(this, item) + + changeItemCoord.call(this, item) + + _.forEach(belowItems, function(upItem, index) { + const moveSize = canItemGoUp(upItem) + if (moveSize > 0) { + moveItemUp.call(vm, upItem, moveSize) + } + }) +} + +function findBelowItems(item) { + const belowItems = {} + for (let cell = item.x - 1; cell < item.x - 1 + item.sizex; cell++) { + for (let row = item.y - 1; row < positionBox.length; row++) { + const target = positionBox[row][cell] + if (target && target.el) { + belowItems[target.el._dragId] = target.el + break + } + } + } + + return _.sortBy(_.values(belowItems), 'y') +} + +export default { + name: 'vue-power-drag', + props: { + yourList: { + required: true, + type: Array // String,Number,Boolean,Function,Object,Array + }, + baseWidth: { + required: false, + type: Number, + default: 100 + }, + baseHeight: { + required: false, + type: Number, + default: 50 + }, + baseMarginLeft: { + required: false, + type: Number, + default: 20 + }, + baseMarginTop: { + required: false, + type: Number, + default: 20 + }, + draggable: { + required: false, + default: true, + type: Boolean + }, + dragStart: { + required: false, + type: Function, + default: function() {} + }, + dragging: { + required: false, + type: Function, + default: function() {} + }, + dragEnd: { + required: false, + type: Function, + default: function() {} + }, + resizable: { + required: false, + type: Boolean, + default: true + }, + resizeStart: { + required: false, + type: Function, + default: function() {} + }, + resizing: { + required: false, + type: Function, + default: function() {} + }, + resizeEnd: { + required: false, + type: Function, + default: function() {} + } + }, + data() { + return { + renderOk: false, + moveAnimate: false, + list: [], + cellWidth: 0, + cellHeight: 0, + maxCell: 0 + } + }, + computed: { + positionBox() { + return positionBox + }, + coordinates() { + return coordinates + } + }, + methods: { + removeItem: removeItem, + startResize(e, item, index) { + console.log('startResize:' + index) + if (!this.resizable) return + this.resizeStart.call(null, e, item, index) + + // e.preventDefault(); + const target = $(e.target) + + if (!this.infoBox) { + this.infoBox = {} + } + + const itemNode = target.parents('.item') + + this.infoBox.resizeItem = item + this.infoBox.resizeItemIndex = index + }, + containerMouseDown(e) { + console.log('containerMouseDown:') + + // e.preventDefault(); + if (!this.infoBox) { + this.infoBox = {} + } + + this.infoBox.startX = e.pageX + this.infoBox.startY = e.pageY + }, + startMove(e, item, index) { + console.log('startMove:' + index) + const vm = this + // e.preventDefault(); + + if (!this.infoBox) { + this.infoBox = {} + } + const infoBox = this.infoBox + const target = $(e.target) + + let className = target.attr('class') + className = className || '' + if (className.indexOf('dragHandle') === -1 && className.indexOf('item') === -1 && className.indexOf('resizeHandle') === -1) { + return + } + + if (className.includes('resizeHandle')) { + + } else if (this.draggable && (className.includes('dragHandle') || className.includes('item'))) { + this.dragStart.call(null, e, item, index) + infoBox.moveItem = item + infoBox.moveItemIndex = index + } + + infoBox.cloneItem = null + infoBox.nowItemNode = null + + if (target.attr('class') && target.attr('class').indexOf('item') !== -1) { + infoBox.nowItemNode = target + infoBox.cloneItem = target.clone() + } else { + infoBox.nowItemNode = target.parents('.item') + infoBox.cloneItem = infoBox.nowItemNode.clone() + } + infoBox.cloneItem.addClass('cloneNode') + + $(this.$el).append(infoBox.cloneItem) + + infoBox.orignX = infoBox.cloneItem.position().left // 克隆对象原始X位置 + infoBox.orignY = infoBox.cloneItem.position().top + infoBox.oldX = item.x // 实际对象原始X位置 + infoBox.oldY = item.y + infoBox.oldSizeX = item.sizex + infoBox.oldSizeY = item.sizey + infoBox.orignWidth = infoBox.cloneItem.prop('offsetWidth') + infoBox.orignHeight = infoBox.cloneItem.prop('offsetHeight') + + function itemMouseMove(e) { + // console.log('itemMouseMove') + const moveItem = _.get(infoBox, 'moveItem') + const resizeItem = _.get(infoBox, 'resizeItem') + + if (resizeItem) { // 调整大小时 + console.log('resizeItem') + vm.resizing.call(null, e, resizeItem, resizeItem._dragId) + + vm.$set(resizeItem, 'isPlayer', true) + const nowItemIndex = infoBox.resizeItemIndex + const cloneItem = infoBox.cloneItem + const startX = infoBox.startX + const startY = infoBox.startY + const oldSizeX = infoBox.oldSizeX + const oldSizeY = infoBox.oldSizeY + const orignWidth = infoBox.orignWidth + const orignHeight = infoBox.orignHeight + + const moveXSize = e.pageX - startX // X方向移动的距离 + const moveYSize = e.pageY - startY // Y方向移动的距离 + + const addSizex = (moveXSize) % vm.cellWidth > (vm.cellWidth / 4 * 1) ? parseInt(((moveXSize) / vm.cellWidth + 1)) : parseInt(((moveXSize) / vm.cellWidth)) + const addSizey = (moveYSize) % vm.cellHeight > (vm.cellHeight / 4 * 1) ? parseInt(((moveYSize) / vm.cellHeight + 1)) : parseInt(((moveYSize) / vm.cellHeight)) + + const nowX = oldSizeX + addSizex > 0 ? oldSizeX + addSizex : 1 + const nowY = oldSizeY + addSizey > 0 ? oldSizeY + addSizey : 1 + + debounce((function(addSizex, addSizey) { + return function() { + resizePlayer.call(vm, resizeItem, { + sizex: nowX, + sizey: nowY + }) + } + })(addSizex, addSizey), 10) + + let nowWidth = orignWidth + moveXSize + nowWidth = nowWidth <= vm.baseWidth ? vm.baseWidth : nowWidth + let nowHeight = orignHeight + moveYSize + nowHeight = nowHeight <= vm.baseHeight ? vm.baseHeight : nowHeight + // 克隆元素实时改变大小 + cloneItem.css({ + width: nowWidth, + height: nowHeight + }) + } else if (moveItem) { + console.log('moveItem') + + scrollScreen(e) + if (!vm.draggable) return + vm.dragging.call(null, e, moveItem, moveItem._dragId) + + vm.$set(moveItem, 'isPlayer', true) + // this.$set(moveItem, "show", false); + const nowItemIndex = infoBox.moveItemIndex + const cloneItem = infoBox.cloneItem + const startX = infoBox.startX + const startY = infoBox.startY + const orignX = infoBox.orignX + const orignY = infoBox.orignY + const oldX = infoBox.oldX + const oldY = infoBox.oldY + + const moveXSize = e.pageX - startX // X方向移动的距离 + const moveYSize = e.pageY - startY // Y方向移动的距离 + + const nowCloneItemX = orignX + moveXSize + const nowCloneItemY = orignY + moveYSize + + let newX = parseInt((nowCloneItemX + (cloneItem.width() / 12) - vm.baseMarginLeft) / vm.cellWidth + 1) + let newY = parseInt((nowCloneItemY + (cloneItem.height() / 12) - vm.baseMarginTop) / vm.cellHeight + 1) + newX = newX > 0 ? newX : 1 + newY = newY > 0 ? newY : 1 + + debounce((function(newX, oldX, newY, oldY) { + return function() { + if (newX !== oldX || oldY !== newY) { + // console.log("move"); + movePlayer.call(vm, moveItem, { + x: newX, + y: newY + }) + + infoBox.oldX = newX + infoBox.oldY = newY + } + } + })(newX, oldX, newY, oldY), 10) + + cloneItem.css({ + left: nowCloneItemX + 'px', + top: nowCloneItemY + 'px' + }) + } + } + + $(window).mousemove(itemMouseMove) + + $(window).mouseup(function itemMouseUp(e) { + if (_.isEmpty(vm.infoBox)) return + if (vm.infoBox.cloneItem) { + vm.infoBox.cloneItem.remove() + } + if (vm.infoBox.resizeItem) { + vm.$delete(vm.infoBox.resizeItem, 'isPlayer') + vm.resizeEnd.call(null, e, vm.infoBox.resizeItem, vm.infoBox.resizeItem._dragId) + } + if (vm.infoBox.moveItem) { + vm.dragEnd.call(null, e, vm.infoBox.moveItem, vm.infoBox.moveItem._dragId) + vm.$set(vm.infoBox.moveItem, 'show', true) + vm.$delete(vm.infoBox.moveItem, 'isPlayer') + } + vm.infoBox = {} + + $(this).off('mousemove', itemMouseMove) + $(this).off('mouseup', itemMouseUp) + }) + }, + endMove(e) { + + }, + moving(e) { + + }, + /** + * 计算当前item的位置和大小 + * + * @param {any} item + * @returns + */ + nowItemStyle(item, index) { + return { + width: (this.cellWidth * (item.sizex) - this.baseMarginLeft) + 'px', + height: (this.cellHeight * (item.sizey) - this.baseMarginTop) + 'px', + left: (this.cellWidth * (item.x - 1) + this.baseMarginLeft) + 'px', + top: (this.cellHeight * (item.y - 1) + this.baseMarginTop) + 'px' + } + }, + getList() { + console.log('getList:') + + const returnList = _.sortBy(_.cloneDeep(this.yourList), 'y') + const finalList = [] + _.forEach(returnList, function(item, index) { + if (_.isEmpty(item)) return + delete item['_dragId'] + delete item['show'] + finalList.push(item) + }) + return finalList + }, + /** + * 获取x最大值 + * + * @returns + */ + getMaxCell() { + console.log('getMaxCell:') + + return this.maxCell + }, + /** + * 获取渲染状态 + * + * @returns + */ + getRenderState() { + console.log('getRenderState:') + + return this.moveAnimate + }, + addItem: addItem, + init: init, + afterInitOk(func) { + const timeid = setInterval(() => { + if (this.moveAnimate) { + clearInterval(timeid) + func() + } + }, 100) + }, + addItemBox(item) { + this.yourList.push(item) + + this.$nextTick(function() { + addItem.call(this, item, this.yourList.length - 1) + }) + } + }, + created() { + + }, + updated() { + + }, + mounted() { + // init.call(this); + } +} diff --git a/frontend/src/components/DeDrag/drag.less b/frontend/src/components/DeDrag/drag.less new file mode 100644 index 0000000000..51212914dd --- /dev/null +++ b/frontend/src/components/DeDrag/drag.less @@ -0,0 +1,112 @@ +.dragAndResize +{ + position: relative; + + user-select: none; + + * + { + box-sizing: border-box; + margin: 0; + padding: 0; + } + + .item + { + position: absolute; + + width: 100px; + height: 100px; + + cursor: move; + + border: 1px solid; + background-color: #fff; + + .resizeHandle + { + position: absolute; + right: 2px; + bottom: 2px; + + width: 0; + height: 0; + + cursor: nw-resize; + + opacity: .5; + border-bottom: 10px solid black; + border-left: 10px solid transparent; + } + } + + .moveAnimation + { + transition: top 80ms ease; + } + + .canNotDrag + { + cursor: default!important; + } + + .cloneNode + { + z-index: 3; + + transition: none; + + background-color: #bec1c9; + opacity: 0.5; + + } + + .movingItem + { + position: absolute; + + border: none; + &:before + { + position: absolute; + z-index: 2; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + content: 'movingItem'; + + background-color: #3d66e7; + } + } + + .positionBox + { + position: fixed; + top: 0; + right: 100px; + + overflow: auto; + + width: 500px; + height: 500px; + + border: 1px solid; + } + + .coords + { + position: fixed; + right: 100px; + bottom: 200px; + + overflow: auto; + + width: 200px; + height: 200px; + + border: 1px solid; + } +} diff --git a/frontend/src/components/DeDrag/drag.vue b/frontend/src/components/DeDrag/drag.vue new file mode 100644 index 0000000000..51de27065f --- /dev/null +++ b/frontend/src/components/DeDrag/drag.vue @@ -0,0 +1,986 @@ + + + + + diff --git a/frontend/src/components/DeDrag/index.vue b/frontend/src/components/DeDrag/index.vue index 5828cae258..59d71d3a94 100644 --- a/frontend/src/components/DeDrag/index.vue +++ b/frontend/src/components/DeDrag/index.vue @@ -434,6 +434,7 @@ export default { } }, style() { + // console.log('style-top:' + this.y + '--' + this.top) return { transform: `translate(${this.left}px, ${this.top}px) rotate(${this.rotate}deg)`, width: this.computedWidth, @@ -482,7 +483,7 @@ export default { return 'auto' } } - if (this.canvasStyleData.auxiliaryMatrix) { + if (this.element.auxiliaryMatrix) { const width = Math.round(this.width / this.curCanvasScale.matrixStyleWidth) * this.curCanvasScale.matrixStyleWidth return width + 'px' } else { @@ -496,7 +497,7 @@ export default { return 'auto' } } - if (this.canvasStyleData.auxiliaryMatrix) { + if (this.element.auxiliaryMatrix) { const height = Math.round(this.height / this.curCanvasScale.matrixStyleHeight) * this.curCanvasScale.matrixStyleHeight return height + 'px' } else { @@ -594,13 +595,15 @@ export default { this.maxH = val }, w(val) { + console.log('changeWidthCK:' + this.resizing) + if (this.resizing || this.dragging) { return } if (this.parent) { this.bounds = this.calcResizeLimits() } - // console.log('changeWidth:' + val) + console.log('changeWidth:' + val) this.changeWidth(val) }, h(val) { @@ -696,6 +699,8 @@ export default { } // 阻止冒泡事件 e.stopPropagation() + // 此处阻止冒泡 但是外层需要获取pageX pageY + this.element.auxiliaryMatrix && this.$emit('elementMouseDown', e) this.$store.commit('setCurComponent', { component: this.element, index: this.index }) eventsFor = events.mouse this.elementDown(e) @@ -707,6 +712,8 @@ export default { } const target = e.target || e.srcElement if (this.$el.contains(target)) { + // 挤压式画布设计 drag start 通知 + this.element.auxiliaryMatrix && this.$emit('onDragStart', e, this.element, this.index) if (this.onDragStart(e) === false) { return } @@ -800,6 +807,7 @@ export default { if (e instanceof MouseEvent && e.which !== 1) { return false } + this.element.auxiliaryMatrix && this.$emit('onResizeStart', e, this.element, this.index) if (this.onResizeStart(handle, e) === false) { return false } @@ -982,6 +990,10 @@ export default { this.bottom = bottom await this.snapCheck() this.$emit('dragging', this.left, this.top) + // 如果当前视图遵循矩阵设计则 进行位置挤压检查 + if (this.element.auxiliaryMatrix) { + this.$emit('onDragging', e, this.element) + } // private 记录当前样式 this.recordCurStyle() @@ -1156,7 +1168,8 @@ export default { // console.log('width2:' + this.width) this.height = newH - this.$emit('resizing', this.left, this.top, this.width, this.height) + // this.$emit('resizing', this.left, this.top, this.width, this.height) + this.element.auxiliaryMatrix && this.$emit('onResizing', e, this.element) // private 记录当前组件样式 this.recordCurStyle() @@ -1179,7 +1192,7 @@ export default { this.right = right this.bottom = bottom this.width = width - // console.log('width3:' + this.width) + console.log('width3:' + this.width) this.height = height }, changeHeight(val) { @@ -1201,7 +1214,7 @@ export default { this.height = height }, // 从控制柄松开 - async handleUp(e) { + handleUp(e) { this.handle = null // 初始化辅助线数据 const temArr = new Array(3).fill({ display: false, position: '', origin: '', lineLength: '' }) @@ -1215,7 +1228,8 @@ export default { this.lastMouseY = mouseY if (this.resizing) { this.resizing = false - await this.conflictCheck() + console.log('resizing2:' + this.resizing) + this.conflictCheck() this.$emit('refLineParams', refLine) // this.$emit('resizestop', this.left, this.top, this.width, this.height) // private @@ -1223,7 +1237,7 @@ export default { } if (this.dragging) { this.dragging = false - await this.conflictCheck() + this.conflictCheck() this.$emit('refLineParams', refLine) this.$emit('dragstop', this.left, this.top) } @@ -1235,8 +1249,9 @@ export default { // private 记录snapshot // 如果辅助设计 需要最后调整矩阵 - if (this.canvasStyleData.auxiliaryMatrix) { - this.recordMatrixCurStyle() + if (this.element.auxiliaryMatrix) { + // this.recordMatrixCurStyle() + this.recordMatrixCurShadowStyle() } this.hasMove && this.$store.commit('recordSnapshot', 'handleUp') // 记录snapshot后 移动已记录设置为false @@ -1246,6 +1261,9 @@ export default { // private 删除handle Up事件 防止重复recordSnapshot removeEvent(document.documentElement, eventsFor.stop, this.handleUp) + + // 挤占式画布设计 handleUp + this.element.auxiliaryMatrix && this.$emit('onHandleUp', e) }, // 新增方法 ↓↓↓ // 设置属性 @@ -1549,11 +1567,38 @@ export default { // this.hasMove = true this.$store.commit('setShapeStyle', style) + // resize + self.$emit('resizeView') + // const self = this + // setTimeout(function() { + // self.$emit('resizeView') + // }, 200) + }, + // 记录当前样式 跟随阴影位置 矩阵处理 + recordMatrixCurShadowStyle() { + console.log('recordMatrixCurShadowStyle') + // debugger + const left = (this.element.x - 1) * this.curCanvasScale.matrixStyleWidth + const top = (this.element.y - 1) * this.curCanvasScale.matrixStyleHeight + const width = this.element.sizex * this.curCanvasScale.matrixStyleWidth + const height = this.element.sizey * this.curCanvasScale.matrixStyleHeight + const style = { + ...this.defaultStyle + } + style.left = left + style.top = top + style.width = width + style.height = height + style.rotate = this.rotate + // this.hasMove = true + this.$store.commit('setShapeStyle', style) + // resize const self = this - setTimeout(function() { - self.$emit('resizeView') - }, 200) + self.$emit('resizeView') + // setTimeout(function() { + // self.$emit('resizeView') + // }, 200) }, mountedFunction() { // private 冲突检测 和水平设计值保持一致 diff --git a/frontend/src/components/DeDrag/shadow.vue b/frontend/src/components/DeDrag/shadow.vue index 1277038296..0e2ea24993 100644 --- a/frontend/src/components/DeDrag/shadow.vue +++ b/frontend/src/components/DeDrag/shadow.vue @@ -1,5 +1,7 @@ + + diff --git a/frontend/src/components/canvas/components/Editor/index.vue b/frontend/src/components/canvas/components/Editor/index.vue index f39215d14a..5012449261 100644 --- a/frontend/src/components/canvas/components/Editor/index.vue +++ b/frontend/src/components/canvas/components/Editor/index.vue @@ -1,6 +1,7 @@ + + + + diff --git a/frontend/src/views/panel/edit/index.vue b/frontend/src/views/panel/edit/index.vue index 5315426aa3..9b1b56660a 100644 --- a/frontend/src/views/panel/edit/index.vue +++ b/frontend/src/views/panel/edit/index.vue @@ -96,7 +96,7 @@
scaleHeight ? scaleWith : scaleHeight scale = scale > 1 ? scale : 1 - this.$store.commit('addComponent', { - component: { - ...commonAttr, - id: generateID(), - component: 'Picture', - label: '图片', - icon: '', - propValue: fileResult, - style: { - ...commonStyle, - top: _this.dropComponentInfo.shadowStyle.y, - left: _this.dropComponentInfo.shadowStyle.x, - width: _this.dropComponentInfo.shadowStyle.width, - height: _this.dropComponentInfo.shadowStyle.height - } + const component = { + ...commonAttr, + id: generateID(), + component: 'Picture', + label: '图片', + icon: '', + propValue: fileResult, + style: { + ...commonStyle } + } + component.auxiliaryMatrix = _this.canvasStyleData.auxiliaryMatrix + if (_this.canvasStyleData.auxiliaryMatrix) { + component.x = _this.dropComponentInfo.x + component.y = _this.dropComponentInfo.y + component.sizex = _this.dropComponentInfo.sizex + component.sizey = _this.dropComponentInfo.sizey + component.style.left = (_this.dropComponentInfo.x - 1) * _this.curCanvasScale.matrixStyleOriginWidth + component.style.top = (_this.dropComponentInfo.y - 1) * _this.curCanvasScale.matrixStyleOriginHeight + component.style.width = _this.dropComponentInfo.sizex * _this.curCanvasScale.matrixStyleOriginWidth + component.style.height = _this.dropComponentInfo.sizey * _this.curCanvasScale.matrixStyleOriginHeight + } else { + component.style.top = _this.dropComponentInfo.shadowStyle.y + component.style.left = _this.dropComponentInfo.shadowStyle.x + component.style.width = _this.dropComponentInfo.shadowStyle.width + component.style.height = _this.dropComponentInfo.shadowStyle.height + } + this.$store.commit('addComponent', { + component: component }) this.$store.commit('recordSnapshot', 'handleFileChange') @@ -784,7 +824,8 @@ export default { .this_canvas{ height: calc(100vh - 91px); - overflow: auto; + overflow-x: hidden; + overflow-y: auto; } .el-main{ height: calc(100vh - 91px); diff --git a/frontend/src/views/panel/filter/index.vue b/frontend/src/views/panel/filter/index.vue index 83e1389500..aa23f51e24 100644 --- a/frontend/src/views/panel/filter/index.vue +++ b/frontend/src/views/panel/filter/index.vue @@ -31,6 +31,8 @@