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

feat: 增加中间编辑区点击节点选中事件,并联动展开左侧节点树

parent 291c0f5a
<template>
<div :style="customStyle" class="zero-custom-cmp zero-custom-node">
<div :style="customStyle" @click.self.stop="clickViewHandle(view)" class="zero-custom-cmp zero-custom-node">
<p class="custom-node-html" v-if="selfText">{{selfText}}</p>
<slot></slot>
</div>
......@@ -30,12 +30,21 @@ export default {
properties: {
type: Object,
default: () => {}
},
view: {
type: Object,
default: () => {}
}
},
computed: {
selfText() {
return this.properties ? this.properties.text || '' : '';
}
},
methods: {
clickViewHandle(data) {
this.$store.dispatch('activeComponent', {data, fromPlayground: true});
}
}
};
</script>
......@@ -3,13 +3,13 @@
*/
import Vue from "vue";
import JSZip from "jszip";
import {projectApi} from "../../api";
import { projectApi } from "../../api";
import path from "path";
import generateUUID from "uuid/v4";
import {getCmpProps, flattenViews, getCmpByUUID} from '../../utils/common';
import {clonePureObj, saveAs} from "../../utils";
import {template} from "../../template";
import {importView, uploadFile} from "../../api/project";
import { getCmpProps, flattenViews, getCmpByUUID } from '../../utils/common';
import { clonePureObj, saveAs } from "../../utils";
import { template } from "../../template";
import { importView, uploadFile } from "../../api/project";
import events from "@/global-events";
const defaultOptions = {
......@@ -23,8 +23,8 @@ const defaultOptions = {
rendererType: 'webgl',
tpl: template,
env: [
{name: 'appID', value: ''},
{name: 'projectID', value: ''},
{ name: 'appID', value: '' },
{ name: 'projectID', value: '' },
],
};
......@@ -61,14 +61,14 @@ export const projectStore = {
state.dirty = dirty;
},
updateProject(state, project) {
const {id, name, creator, data} = project;
const { id, name, creator, data } = project;
state.id = id;
state.name = name;
state.creator = creator;
const localData = state.data;
if (data) {
const {views, assets, dataMapping, processes, options, customs,} = JSON.parse(data);
const { views, assets, dataMapping, processes, options, customs, } = JSON.parse(data);
Vue.set(localData, 'options', options || getDefaultOptions());
Vue.set(localData, 'views', views || []);
......@@ -255,7 +255,7 @@ export const projectStore = {
modifyProject(state) {
},
addNode(state, {node, name, type}) {
addNode(state, { node, name, type }) {
const child = {
name,
type,
......@@ -275,19 +275,19 @@ export const projectStore = {
importView(state, view) {
state.data.views.push(view);
},
deleteNode(state, {node, parentNode}) {
deleteNode(state, { node, parentNode }) {
const parentChildren = parentNode.children || parentNode;
const index = parentChildren.indexOf(node);
parentChildren.splice(index, 1);
},
copyNode(state, {node, parentNode}) {
// const parentChildren = parentNode.children || parentNode;
// const index = parentChildren.indexOf(node);
// parentNode.children.push(node);
// parentChildren.push(parentChildren[index]);
copyNode(state, { node, parentNode }) {
// const parentChildren = parentNode.children || parentNode;
// const index = parentChildren.indexOf(node);
// parentNode.children.push(node);
// parentChildren.push(parentChildren[index]);
const child = {
name:node.name,
type:node.type,
name: node.name,
type: node.type,
properties: node.properties,
events: node.events,
uuid: generateUUID(),
......@@ -304,7 +304,7 @@ export const projectStore = {
importAssets(state, assets) {
state.data.assets.push(...assets);
},
addAsset(state, {url, file}) {
addAsset(state, { url, file }) {
const ext = path.extname(file.name);
state.data.assets.push({
name: path.basename(file.name, ext),
......@@ -314,7 +314,7 @@ export const projectStore = {
})
},
deleteAsset(state, uuid) {
const {assets} = state.data;
const { assets } = state.data;
for (let i = 0, li = assets.length; i < li; i++) {
const asset = state.data.assets[i];
if (asset.uuid === uuid) {
......@@ -324,7 +324,7 @@ export const projectStore = {
}
},
deleteAllAssets(state) {
const {assets} = state.data;
const { assets } = state.data;
assets.splice(0);
},
modifyAsset(state, asset) {
......@@ -378,7 +378,7 @@ export const projectStore = {
},
getters: {
project(state) {
const {id, name, creator, data} = state;
const { id, name, creator, data } = state;
return {
id, name, creator,
data: JSON.stringify(data),
......@@ -443,17 +443,17 @@ export const projectStore = {
}
},
actions: {
saveToLocal({getters, commit}) {
const {project} = getters;
saveToLocal({ getters, commit }) {
const { project } = getters;
localStorage.setItem('project-' + project.id, JSON.stringify(project));
commit('setDirty', true);
},
localVersionExist({commit}, projectID) {
localVersionExist({ commit }, projectID) {
let json = localStorage.getItem('project-' + projectID);
return !!json;
},
loadFromLocal({commit}, projectID) {
loadFromLocal({ commit }, projectID) {
let json = localStorage.getItem('project-' + projectID);
if (json) {
const project = JSON.parse(json);
......@@ -461,11 +461,11 @@ export const projectStore = {
commit('setDirty', true);
}
},
deleteLocalVersion({state, commit}, projectID) {
deleteLocalVersion({ state, commit }, projectID) {
localStorage.removeItem('project-' + projectID);
commit('setDirty', false);
},
async loadFromRemote({commit, dispatch}, projectID) {
async loadFromRemote({ commit, dispatch }, projectID) {
const project = await projectApi.fetchOne(projectID);
if (project) {
dispatch('deleteLocalVersion', projectID);
......@@ -474,11 +474,11 @@ export const projectStore = {
throw new Error('Project does not exist')
}
},
async saveToRemote({state, dispatch, getters}) {
async saveToRemote({ state, dispatch, getters }) {
await projectApi.saveOne(getters.project);
dispatch('deleteLocalVersion', state.id);
},
async updateProject({commit}, projectID) {
async updateProject({ commit }, projectID) {
const project = await projectApi.getData(projectID);
commit('updateProject', project);
},
......@@ -496,10 +496,13 @@ export const projectStore = {
return getTopView(node.parent);
}
};
let _view = getTopView(data.node);
if (_view && _view.data) {
context.state.activeViews = _view.data.uuid;
if (!data.fromPlayground) {
// 点击视图区域选中节点
// 则需要切换当前节点所在的最顶层视图
let _view = getTopView(data.node);
if (_view && _view.data) {
context.state.activeViews = _view.data.uuid;
}
}
context.commit('activeComponent', data.data);
......@@ -507,7 +510,7 @@ export const projectStore = {
/**
* 修改属性
*/
modifyProperties({commit, state, getters}, props) {
modifyProperties({ commit, state, getters }, props) {
// debugger;
// 如果当前修改的是“来源”属性,节点又没有高度宽度,则取图片的高度宽度
let _props = _.cloneDeep(state.activeComponent.properties);
......@@ -546,13 +549,13 @@ export const projectStore = {
* @param {*} param0
* @param {*} props
*/
modifyCopyProperties({commit}, props) {
modifyCopyProperties({ commit }, props) {
commit('modifyCopyProperties', props)
},
/**
* 修改当前选中的节点
*/
modifyActiveView({commit}, view) {
modifyActiveView({ commit }, view) {
commit('modifyActiveView', view)
},
......@@ -561,7 +564,7 @@ export const projectStore = {
* @param {*} param0
* @param {*} data
*/
addNodeScript({commit, state}, script) {
addNodeScript({ commit, state }, script) {
let _scripts = _.cloneDeep(state.activeComponent.scripts || []);
_scripts.push({
script: script,
......@@ -571,8 +574,8 @@ export const projectStore = {
scripts: _scripts
})
},
async importView({commit}, {file, action}) {
const {view, assets} = await importView(file);
async importView({ commit }, { file, action }) {
const { view, assets } = await importView(file);
switch (action) {
case 0: //单视图
view.name = file.name.substring(0, file.name.lastIndexOf('.'));
......@@ -586,14 +589,14 @@ export const projectStore = {
}
commit('importAssets', assets);
},
exportView({state}, view) {
exportView({ state }, view) {
let zip = new JSZip();
zip.file('view.json', JSON.stringify(view));
zip.generateAsync({type: "blob"}).then(function (content) {
zip.generateAsync({ type: "blob" }).then(function (content) {
saveAs(content, `view-${view.name}.zrv`);
});
},
async uploadFiles({commit}, files) {
async uploadFiles({ commit }, files) {
const failedList = [];
let ps = [];
for (let file of files) {
......@@ -607,8 +610,8 @@ export const projectStore = {
}
const result = await Promise.all(ps);
for (let item of result) {
const {url, __originFile} = item;
commit('addAsset', {url, file: __originFile});
const { url, __originFile } = item;
commit('addAsset', { url, file: __originFile });
}
/*for (let file of files) {
try {
......@@ -621,7 +624,7 @@ export const projectStore = {
}*/
return failedList;
},
async packProject({state}, debug) {
async packProject({ state }, debug) {
const result = await projectApi.pack(state.id, debug);
console.log(result);
return result;
......
......@@ -17,7 +17,10 @@
:data="views"
:props="defaultProps"
:expand-on-click-node="false"
:default-expanded-keys="expandedKeys"
draggable
ref="tree"
node-key="uuid"
highlight-current
:default-expand-all="false"
@node-click="handleNodeClick"
......@@ -54,7 +57,7 @@
</template>
<script>
import {mapState, mapMutations, mapActions} from 'vuex';
import {mapState, mapMutations, mapActions, mapGetters} from 'vuex';
import Pane from '../../components/Pane';
import {selectFile} from "../../utils";
import events from "../../global-events";
......@@ -71,13 +74,22 @@
uploadHeaders: {
authorization: 'Bearer ' + window['zeroing_token'],
},
expandedKeys: []
};
},
computed: {
...mapGetters(['activeComponentId']),
...mapState({
views: state => state.project.data.views
})
},
watch: {
activeComponentId: function(val) {
this.$refs.tree.setCheckedKeys([val]); // 设置选中节点
this.$refs.tree.setCurrentKey(val); // 设置高亮节点
this.expandedKeys = [val]; // 展开对应的节点
}
},
methods: {
allowDrag(draggingNode) {
return draggingNode.parent.parent;
......
<template>
<div class="views-tree">
<custom-node v-for="view in views" :key="view.uuid" :custom-style="styleObject(view)" :properties="view.properties">
<custom-node v-for="view in views" :key="view.uuid" :view="view" :custom-style="styleObject(view)" :properties="view.properties">
<template v-if="view.children">
<views-tree :views="view.children"></views-tree>
</template>
......
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