Commit 6cd8cf2b authored by 张晨辰's avatar 张晨辰

feat: 撤销重做&属性值undefined问题修复

parent f87bd87a
...@@ -22,6 +22,8 @@ const defaultOptions = { ...@@ -22,6 +22,8 @@ const defaultOptions = {
tpl: template, tpl: template,
}; };
const OPERATE_MAX_LENGTH = 200; // 撤销重做栈最大值
function getDefaultOptions() { function getDefaultOptions() {
return JSON.parse(JSON.stringify(defaultOptions)); return JSON.parse(JSON.stringify(defaultOptions));
} }
...@@ -103,10 +105,10 @@ export const projectStore = { ...@@ -103,10 +105,10 @@ export const projectStore = {
// 则把操作index之后的数据都丢弃 // 则把操作index之后的数据都丢弃
state.operateStack = state.operateStack.slice(state.stackIndex); state.operateStack = state.operateStack.slice(state.stackIndex);
} }
let _last_operate = state.operateStack[0]; let lastOperate = state.operateStack[0];
// 上一次的操作和最新一次操作uuid不同,表示发生了不同视图的操作 // // 上一次的操作和最新一次操作uuid不同,表示发生了不同视图的操作
// 需要记录当前视图的原始数据 // // 需要记录当前视图的原始数据
if (_last_operate.uuid !== oldView.uuid) { if (lastOperate.uuid !== oldView.uuid) {
state.operateStack.unshift(_.cloneDeep(oldView)); state.operateStack.unshift(_.cloneDeep(oldView));
} }
} else { } else {
...@@ -116,25 +118,49 @@ export const projectStore = { ...@@ -116,25 +118,49 @@ export const projectStore = {
} }
state.stackIndex = 0; // 开始编辑的时候,重置操作栈的下标 state.stackIndex = 0; // 开始编辑的时候,重置操作栈的下标
let newView = _.merge(oldView, view); let newView = _.merge({}, oldView, view);
// 如果是scripts和events的修改,直接覆盖 不merge // 如果是scripts和events的修改,直接覆盖 不merge
if (view.scripts) { if (view.scripts) {
newView.scripts = _.cloneDeep(view.scripts) newView.scripts = _.cloneDeep(view.scripts);
} }
if (view.events) { if (view.events) {
newView.events = _.cloneDeep(view.events) newView.events = _.cloneDeep(view.events);
} }
// 修改properties时,做减量操作,判断是否有属性的值被清空
if (view.properties) {
newView.properties = _.cloneDeep(view.properties);
_.forIn(newView.properties, (value, key) => {
if (value === null || value === undefined) {
delete newView.properties[key];
}
});
}
if (view.type) {
// view.type有值说明修改了节点的类型
// 如果修改了节点类型,需要删除无用的属性
let defaultProps = Object.keys(getCmpProps(view.type));
_.forIn(newView.properties, (value, key) => {
if (defaultProps.indexOf(key) === -1) {
delete newView.properties[key];
}
});
}
console.log('newView', newView);
// curOperate.push(_.cloneDeep(newView)) // 保存操作之后的配置
// 在操作栈中插入最新值 // 在操作栈中插入最新值
state.operateStack.unshift(_.cloneDeep(_.assign({ uuid: newView.uuid }, view))); state.operateStack.unshift(_.cloneDeep(newView));
// 操作栈最大200 // 超过最大保存数就丢弃
if (state.operateStack.length > 200) { if (state.operateStack.length > OPERATE_MAX_LENGTH) {
state.operateStack.pop(); state.operateStack.pop();
} }
// 将数据更新至当前选中的节点上 // 将数据更新至当前选中的节点上
_.forIn(view, (value, key) => { _.forIn(newView, (value, key) => {
// if (key === 'properties') { // if (key === 'properties') {
// horizonCenter和left\right // horizonCenter和left\right
// verticalCenter和top\bottom // verticalCenter和top\bottom
...@@ -165,20 +191,7 @@ export const projectStore = { ...@@ -165,20 +191,7 @@ export const projectStore = {
// } // }
Vue.set(state.activeComponent, key, newView[key]); Vue.set(state.activeComponent, key, newView[key]);
}) });
if (view.type) {
// view.type有值说明修改了节点的类型
// 如果修改了节点类型,需要删除无用的属性
let defaultProps = Object.keys(getCmpProps(view.type));
let _properties = _.cloneDeep(state.activeComponent.properties);
_.forIn(_properties, (value, key, prop) => {
if (defaultProps.indexOf(key) === -1) {
delete prop[key];
}
});
Vue.set(state.activeComponent, 'properties', _properties);
}
// 同步修改镜像节点 // 同步修改镜像节点
state.activeComponentCopy = _.cloneDeep(state.activeComponent); state.activeComponentCopy = _.cloneDeep(state.activeComponent);
...@@ -222,9 +235,13 @@ export const projectStore = { ...@@ -222,9 +235,13 @@ export const projectStore = {
if (_operate) { if (_operate) {
let _cmp = getCmpByUUID(_operate.uuid, state.data.views); let _cmp = getCmpByUUID(_operate.uuid, state.data.views);
if (_cmp) { if (_cmp) {
_cmp = _.merge(_cmp, _operate); _.forIn(_operate, (value, key) => {
if (_operate.uuid === state.activeComponentCopy.uuid) { _cmp[key] = value;
state.activeComponentCopy = _.cloneDeep(_cmp) });
// _cmp = _.cloneDeep(_operate); //_.merge(_cmp, _operate);
if (_operate.uuid === state.activeComponent.uuid) {
state.activeComponentCopy = _.cloneDeep(_operate);
state.activeComponent = _.cloneDeep(_operate);
} }
} }
} }
...@@ -364,7 +381,6 @@ export const projectStore = { ...@@ -364,7 +381,6 @@ export const projectStore = {
} else { } else {
_view = state.data.views.length ? [].concat(state.data.views[0]) : []; _view = state.data.views.length ? [].concat(state.data.views[0]) : [];
} }
console.log('_view', _view);
return _view; return _view;
} }
...@@ -437,10 +453,14 @@ export const projectStore = { ...@@ -437,10 +453,14 @@ export const projectStore = {
modifyProperties({ commit, state, getters }, props) { modifyProperties({ commit, state, getters }, props) {
// debugger; // debugger;
// 如果当前修改的是“来源”属性,节点又没有高度宽度,则取图片的高度宽度 // 如果当前修改的是“来源”属性,节点又没有高度宽度,则取图片的高度宽度
if (props.source) { let _props = _.cloneDeep(state.activeComponent.properties);
let _props = state.activeComponent.properties; _.forIn(props, (value, key) => {
_props[key] = value;
});
if (_props.source) {
if (!_props.width || !_props.height) { if (!_props.width || !_props.height) {
let _url = props.source; //_source.value; let _url = _props.source; //_source.value;
if (_url.indexOf('asset://') === 0) { if (_url.indexOf('asset://') === 0) {
let uuid = _url.split('//')[1]; let uuid = _url.split('//')[1];
let asset = state.data.assets.find(a => a.uuid === uuid); let asset = state.data.assets.find(a => a.uuid === uuid);
...@@ -449,28 +469,17 @@ export const projectStore = { ...@@ -449,28 +469,17 @@ export const projectStore = {
let _img = new Image(); let _img = new Image();
_img.src = _url; _img.src = _url;
_img.onload = function () { _img.onload = function () {
_props.width = _img.width;
_props.height = _img.height;
commit('modifyActiveView', { commit('modifyActiveView', {
properties: { properties: _props
width: _img.width,
height: _img.height
}
}); });
} }
} }
} }
let finalProps = _.merge({}, _.cloneDeep(state.activeComponent.properties), props);
// 属性冲突&属性关联计算
// if (finalProps.left && finalProps.right) {
// left right 同时存在,计算其宽度
// }
commit('modifyActiveView', { commit('modifyActiveView', {
properties: props properties: _props
}) })
}, },
/** /**
......
...@@ -151,24 +151,24 @@ function inheritProps(props, parent, onlyOpera) { ...@@ -151,24 +151,24 @@ function inheritProps(props, parent, onlyOpera) {
} }
let rule = propsComputeRules[key]; let rule = propsComputeRules[key];
// 加法 // 加法
if (rule === 'add') { // if (rule === 'add') {
if (props[key] === null || props[key] === undefined) { // if (props[key] === null || props[key] === undefined) {
props[key] = 0; // props[key] = 0;
} // }
props[key] += _pValue; // props[key] += _pValue;
} // }
// 乘法 // 乘法
if (rule === 'multi') { // if (rule === 'multi') {
if (props[key] === null || props[key] === undefined) { // if (props[key] === null || props[key] === undefined) {
props[key] = 1; // props[key] = 1;
} // }
props[key] *= _pValue; // props[key] *= _pValue;
} // }
// 可见,特殊处理 // 可见,特殊处理
// 节点和父节点的visible只要有一个是false,值就是false,否则为true // 节点和父节点的visible只要有一个是false,值就是false,否则为true
if (rule === 'visible') { // if (rule === 'visible') {
props[key] = !props[key] || !_pValue ? false : true; // props[key] = !props[key] || !_pValue ? false : true;
} // }
}); });
} }
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
<template> <template>
<div class="zero-draw-panel-container" > <div class="zero-draw-panel-container" >
<div class="zero-components-container" > <div class="zero-components-container" >
<div <!-- <div
:key="item.uuid" :key="item.uuid"
v-for="item in componentList" v-for="item in componentList"
> >
<wrap :component-data="item"/> <wrap :component-data="item"/>
</div> </div> -->
<!-- <views-tree :views="views"></views-tree> --> <views-tree :views="views"></views-tree>
<template v-if="!!this.activeComponentId"> <!-- <template v-if="!!this.activeComponentId">
<vue-draggable-resizable <vue-draggable-resizable
:prevent-deactivation="true" :prevent-deactivation="true"
class-name="db-draggable" class-name="db-draggable"
...@@ -26,109 +26,109 @@ ...@@ -26,109 +26,109 @@
@deactivated="handleDeactivated" @deactivated="handleDeactivated"
> >
</vue-draggable-resizable> </vue-draggable-resizable>
</template> </template> -->
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { mapState, mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import wrap from './wrap'; // import wrap from './wrap';
import viewsTree from './viewsTree'; import viewsTree from './viewsTree';
import { styles } from '../../../utils/common'; // import { styles } from '../../../utils/common';
import properties from '../../../utils/properties'; // import properties from '../../../utils/properties';
import VueDraggableResizable from 'vue-draggable-resizable'; // import VueDraggableResizable from 'vue-draggable-resizable';
export default { export default {
components: { wrap, VueDraggableResizable, viewsTree }, components: { viewsTree },
methods: { methods: {
handleDeactivated() { // handleDeactivated() {
// this.$store.dispatch('changeEditaleStatus', false); // // this.$store.dispatch('changeEditaleStatus', false);
}, // },
handleResize(x, y, w, h) { // handleResize(x, y, w, h) {
if (!this.active || !this.activeComponentId) { // if (!this.active || !this.activeComponentId) {
return false; // return false;
} // }
let _prop = this.activeComponentCopy.properties; // let _prop = this.activeComponentCopy.properties;
if (_prop.x !== x || _prop.y !== y || _prop.width !== w || _prop.height !== h) { // if (_prop.x !== x || _prop.y !== y || _prop.width !== w || _prop.height !== h) {
this.$store.dispatch('modifyCopyProperties', { // this.$store.dispatch('modifyCopyProperties', {
x: x, // x: x,
y: y, // y: y,
width: w, // width: w,
height: h // height: h
}); // });
// console.log('handleResize', x, y, w, h); // // console.log('handleResize', x, y, w, h);
} // }
}, // },
handleDragging(x, y) { // handleDragging(x, y) {
if (!this.active || !this.activeComponentId) { // if (!this.active || !this.activeComponentId) {
return false; // return false;
} // }
let _prop = this.activeComponentCopy.properties; // let _prop = this.activeComponentCopy.properties;
if (_prop.x !== x || _prop.y !== y) { // if (_prop.x !== x || _prop.y !== y) {
this.$store.dispatch('modifyCopyProperties', { // this.$store.dispatch('modifyCopyProperties', {
x: x, // x: x,
y: y // y: y
}); // });
// console.log('handleDragging', x, y); // // console.log('handleDragging', x, y);
} // }
}, // },
handleResizeStop(x, y, w, h) { // handleResizeStop(x, y, w, h) {
if (!this.active || !this.activeComponentId) { // if (!this.active || !this.activeComponentId) {
return false; // return false;
} // }
let _prop = this.activeComponent.properties; // let _prop = this.activeComponent.properties;
if (_prop.x !== x || _prop.y !== y || _prop.width !== w || _prop.height !== h) { // if (_prop.x !== x || _prop.y !== y || _prop.width !== w || _prop.height !== h) {
this.$store.dispatch('modifyProperties', { // this.$store.dispatch('modifyProperties', {
x: x, // x: x,
y: y, // y: y,
width: w, // width: w,
height: h // height: h
}); // });
} // }
}, // },
handleDragStop(x, y) { // handleDragStop(x, y) {
if (!this.active || !this.activeComponentId) { // if (!this.active || !this.activeComponentId) {
return false; // return false;
} // }
let _prop = this.activeComponent.properties; // let _prop = this.activeComponent.properties;
if (_prop.x !== x || _prop.y !== y) { // if (_prop.x !== x || _prop.y !== y) {
this.$store.dispatch('modifyProperties', { // this.$store.dispatch('modifyProperties', {
x: x, // x: x,
y: y // y: y
}); // });
} // }
} // }
}, },
computed: { computed: {
...mapState(['project']), // ...mapState(['project']),
...mapGetters(['activeComponent', 'activeComponentCopy', 'views', 'componentList', 'activeComponentId']), ...mapGetters(['views']),
active() { // active() {
return !!this.activeComponentId; // return !!this.activeComponentId;
// return this.activeComponentId === (this.activeComponent || {}).uuid; // // return this.activeComponentId === (this.activeComponent || {}).uuid;
}, // },
styleObject() { // styleObject() {
return styles.getComponentStyle(this.activeComponentCopy, this.project, this.componentList, true); // return styles.getComponentStyle(this.activeComponentCopy, this.project, this.componentList, true);
}, // },
position() { // position() {
let _props = this.activeComponentCopy.properties || {}; // let _props = this.activeComponentCopy.properties || {};
const _node = properties.node; // const _node = properties.node;
// console.log('********', _props); // // console.log('********', _props);
let result = { // let result = {
x: _props.x || _node.x.value, // x: _props.x || _node.x.value,
y: _props.y || _node.y.value, // y: _props.y || _node.y.value,
w: _props.width || _node.width.value, // w: _props.width || _node.width.value,
h: _props.height || _node.height.value // h: _props.height || _node.height.value
}; // };
// console.log('####position', result); // // console.log('####position', result);
return result; // return result;
} // }
} }
}; };
</script> </script>
......
...@@ -5,6 +5,23 @@ ...@@ -5,6 +5,23 @@
<views-tree :views="view.children"></views-tree> <views-tree :views="view.children"></views-tree>
</template> </template>
</custom-node> </custom-node>
<vue-draggable-resizable
v-if="hasDrag"
:prevent-deactivation="true"
class-name="db-draggable"
:min-width="1"
:min-height="1"
:z="2"
:active="true"
:style="dragStyleObject"
v-bind="position"
@dragging="handleDragging"
@dragstop="handleDragStop"
@resizing="handleResize"
@resizestop="handleResizeStop"
@deactivated="handleDeactivated"
>
</vue-draggable-resizable>
</div> </div>
</template> </template>
...@@ -12,6 +29,8 @@ ...@@ -12,6 +29,8 @@
import { mapState, mapGetters } from 'vuex'; import { mapState, mapGetters } from 'vuex';
import { styles } from '../../../utils/common'; import { styles } from '../../../utils/common';
import customNode from '../../../components/customElement/node/index.vue'; import customNode from '../../../components/customElement/node/index.vue';
import properties from '../../../utils/properties';
import VueDraggableResizable from 'vue-draggable-resizable';
export default { export default {
name: 'viewsTree', name: 'viewsTree',
...@@ -22,11 +41,38 @@ export default { ...@@ -22,11 +41,38 @@ export default {
} }
}, },
components: { components: {
VueDraggableResizable,
'custom-node': customNode 'custom-node': customNode
}, },
computed: { computed: {
...mapState(['project']), ...mapState(['project']),
...mapGetters(['activeComponentCopy', 'componentList']) ...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList', 'activeComponentId']),
active() {
return !!this.activeComponentId;
},
dragStyleObject() {
return styles.getComponentStyle(this.activeComponentCopy, this.project, this.componentList, true);
},
position() {
let _props = this.activeComponentCopy.properties || {};
const _node = properties.node;
// console.log('********', _props);
let result = {
x: _props.x || _node.x.value,
y: _props.y || _node.y.value,
w: _props.width || _node.width.value,
h: _props.height || _node.height.value
};
// console.log('####position', result);
return result;
},
hasDrag() {
let _ids = this.views.map(v => v.uuid);
// console.log('_ids', _ids);
// console.log('activeComponentId', this.activeComponentId, _ids.indexOf(this.activeComponentId));
return this.activeComponentId && _ids.indexOf(this.activeComponentId) > -1 ? true : false;
}
}, },
methods: { methods: {
styleObject(view) { styleObject(view) {
...@@ -37,6 +83,66 @@ export default { ...@@ -37,6 +83,66 @@ export default {
result = styles.getComponentStyle(view, this.project, this.componentList); result = styles.getComponentStyle(view, this.project, this.componentList);
} }
return result; return result;
},
handleDeactivated() {
// this.$store.dispatch('changeEditaleStatus', false);
},
handleResize(x, y, w, h) {
if (!this.active || !this.activeComponentId) {
return false;
}
let _prop = this.activeComponentCopy.properties;
if (_prop.x !== x || _prop.y !== y || _prop.width !== w || _prop.height !== h) {
this.$store.dispatch('modifyCopyProperties', {
x: x,
y: y,
width: w,
height: h
});
}
},
handleDragging(x, y) {
if (!this.active || !this.activeComponentId) {
return false;
}
let _prop = this.activeComponentCopy.properties;
if (_prop.x !== x || _prop.y !== y) {
this.$store.dispatch('modifyCopyProperties', {
x: x,
y: y
});
}
},
handleResizeStop(x, y, w, h) {
if (!this.active || !this.activeComponentId) {
return false;
}
let _prop = this.activeComponent.properties;
if (_prop.x !== x || _prop.y !== y || _prop.width !== w || _prop.height !== h) {
this.$store.dispatch('modifyProperties', {
x: x,
y: y,
width: w,
height: h
});
}
},
handleDragStop(x, y) {
if (!this.active || !this.activeComponentId) {
return false;
}
let _prop = this.activeComponent.properties;
if (_prop.x !== x || _prop.y !== y) {
this.$store.dispatch('modifyProperties', {
x: x,
y: y
});
}
} }
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment