Commit 7756514c authored by 张晨辰's avatar 张晨辰

feat: scripts alias & enum

parents 7ebafe76 91d21a31
VUE_APP_I18N_LOCALE=en
VUE_APP_I18N_LOCALE=zh-CN
VUE_APP_I18N_FALLBACK_LOCALE=en
# 问题
1. 新建的label选中会报错
2. 脚本中属性无法渲染
1. [x] 新建的label选中会报错
2. [x] 脚本中属性无法渲染
# 修改
1. node类型增加属性:`left,top,right,bottom,horizonCenter,verticalCenter`
2. rect类型增加属性:`borderRadius`
3. label类型增加属性:`verticalAlign(options: up,middle,down)`
4. 增加circle类型,属性同rect
5. 属性中增加alias为别名,用来呈现中文别名(`{alias: '文本', type: 'string', default: '你好'}`)
6. 属性中枚举的类型,type改为enum,增加以enum为名字的字符串存放枚举项(`{alias: '类型', type: 'enum', enum: ['rotate', 'jump', 'breath'], default: 'rotate'}`)
7. 编辑区需要能设置尺寸,默认`750*1334`,增加缩放功能,缩放可由按钮或者滚轮控制
8. 增加删除脚本功能
9. 增加删除行为功能
1. [ ] node类型增加属性:`left,top,right,bottom,horizonCenter,verticalCenter`
2. [x] rect类型增加属性:`borderRadius`
3. [ ] label类型增加属性:`verticalAlign(options: up,middle,down)`
4. [x] 增加circle类型,属性同rect
5. [x] 属性中增加alias为别名,用来呈现中文别名(`{alias: '文本', type: 'string', default: '你好'}`)
6. [x] 属性中枚举的类型,type改为enum,增加以enum为名字的字符串存放枚举项(`{alias: '类型', type: 'enum', enum: ['rotate', 'jump', 'breath'], default: 'rotate'}`)
7. [ ] 编辑区需要能设置尺寸,默认`750*1334`,增加缩放功能,缩放可由按钮或者滚轮控制
8. [x] 增加删除脚本功能
9. [x] 增加删除行为功能
This diff is collapsed.
......@@ -14,7 +14,8 @@
</noscript>
<script>
window.__data = {
token : "<%= process.env.NODE_ENV === 'development' ? 'eyJhbGciOiJIUzI1NiJ9.5Yqz55Cq5bOw.wixVqBeqGS2FBY_VWF1cC_Vg5Zr0vYgRTfuncjGthYY' : '$TOKEN$' %>"
token : "<%= process.env.NODE_ENV === 'development' ? 'eyJhbGciOiJIUzI1NiJ9.5Y2e6b6Z5Lqt.2fNMm0oJt0l0ZzsSYwo4ie8Bs7yLU9EmS2mtrmLPktY' : '$TOKEN$' %>",
apiHost : "<%= process.env.NODE_ENV === 'development' ? 'http://beacon.duibadev.com.cn' : '$API_HOST$' %>"
}
</script>
<div id="app"></div>
......
......@@ -3,12 +3,12 @@
*/
export let API_HOST;
if(process.env.NODE_ENV === 'development'){
if (process.env.NODE_ENV === 'development') {
//API_HOST = 'http://10.10.95.74:7777';
//API_HOST = 'http://localhost:3002';
API_HOST = 'http://beacon.duibadev.com.cn'
}else{
API_HOST = 'http://beacon.duibadev.com.cn'
API_HOST = window.__data.apiHost;
} else {
API_HOST = window.__data.apiHost;
}
export const UPLOAD_FILE_URL = API_HOST + '/api/uploadFile';
......
......@@ -7,6 +7,8 @@
"Save": "Save",
"Copy": "Copy",
"Exit": "Exit",
"Props": "Props",
"Behavior": "Behavior",
"Add": "Add",
"Delete": "Delete",
"Import": "Import",
......@@ -20,6 +22,8 @@
"Code": "Code",
"Desc": "Desc",
"Empty": "Empty",
"Key": "Key",
"Default": "Default",
"Event": "Event",
"No desc": "No desc",
"Description": "Description",
......@@ -61,7 +65,6 @@
"Scale Mode": "Scale Mode",
"Renderer Type": "Renderer Type",
"Props Editor": "Props Editor",
"Edit Behavior": "Edit Behavior",
"Trigger once": "Trigger once",
"Meta Editor": "Meta Editor",
"As inline": "As inline",
......@@ -131,5 +134,37 @@
"static": "Static",
"arguments": "Arguments",
"data-center": "DataCenter"
},
"prosTypes": {
"boolean": "Boolean",
"string": "String",
"number": "Number",
"enum": "Enum",
"color": "Color",
"asset": "Asset",
"node": "Node",
"data": "Data"
},
"events": {
"init": "Init",
"awake": "Awake",
"sleep": "Sleep",
"data-center": "DataCenter",
"click": "Click",
"touchstart": "Touchstart",
"touchend": "Touchend",
"touchmove": "Touchmove"
},
"scaleMode": {
"exactFit": "EXACT_FIT",
"noBorder": "NO_BORDER",
"noScale": "NO_SCALE",
"showAll": "SHOW_ALL",
"fixedWidth": "FIXED_WIDTH",
"fixedHeight": "FIXED_HEIGHT"
},
"rendererType": {
"webgl": "WEBGL",
"canvas": "CANVAS"
}
}
\ No newline at end of file
{
"Alert": "提示",
"Confirm": "确定",
"Confirm": "确认",
"Cancel": "取消",
"In processing": "处理中…",
"Projects": "项目列表",
"copy": "副本",
"No projects": "没有项目",
"Close": "关闭",
"Still Close": "仍然关闭",
"Save": "保存",
"Copy": "复制",
"Exit": "退出",
"Props": "属性",
"Behavior": "行为",
"Add": "添加",
"Delete": "删除",
"Import": "导入",
"Export": "导出",
"Upload": "上传",
"Edit": "编辑",
"ID": "ID",
"Name": "名字",
"Alias": "别名",
"Output": "输出",
"Code": "代码",
"Desc": "描述",
"Empty": "空",
"Key": "属性名",
"Default": "默认值",
"Event": "事件",
"No desc": "无描述",
"Description": "描述",
"Failed to fetch": "网络错误!",
"In processing": "处理中……",
"Projects": "项目",
"copy": "复制",
"No projects": "无项目",
"Create": "创建",
"Project name": "项目名称",
"Project details": "项目详情",
"Project does not exist": "项目不存在",
"Project name": "项目名",
"Data mapping": "数据映射",
"Behavior Editor": "行为编辑器",
"Template": "模板",
"Preparing": "准备中…",
"Deleting": "删除中…",
"Saving": "保存中…",
"Divider": "分流节点",
"Custom": "自定义节点",
"Entry": "入口",
"Packing": "打包",
"Type": "类型",
"Group": "分组",
"Access denied": "无权限",
"Invalid router": "无效的页面",
"Jump after": "{cd}秒后跳转",
"Open in new tab": "新标签打开",
"Pack project successfully": "项目打包成功",
"Pack project failed": "项目打包失败",
"Create project": "创建项目",
"Rename project": "重命名项目",
"Entry scene view": "入口场景视图",
"Page title": "页面标题",
"Container ID": "容器ID",
"Design width": "设计宽度",
"Design height": "设计高度",
"Frame Rate": "帧率",
"Scale Mode": "缩放模式",
"Renderer Type": "渲染模式",
"Props Editor": "属性编辑器",
"Trigger once": "触发一次",
"Meta Editor": "过程元配置",
"As inline": "作为内联",
"Link to parent": "连接到父节点",
"Input project name": "输入项目名",
"Invalid project name": "无效的项目名",
"Creating project": "项目创建中…",
"Create project success": "创建项目成功",
"Create project success": "项目创建成功",
"Duplicate project": "复制项目",
"Duplicating project": "项目复制中…",
"Duplicate project success": "复制项目成功",
"Duplicate project success": "项目复制成功",
"Project name cannot be empty": "项目名不能为空",
"This action will permanently delete project": "即将永久删除项目[{projectName}], 是否继续?",
"Failed to fetch env": "环境获取失败",
"Failed to fetch projects": "项目列表获取失败",
"This action will permanently delete project": "您将删除项目[{projectName}], 是否继续?",
"Fetching projects": "获取项目列表…",
"Failed to fetch env": "获取环境失败",
"Failed to fetch projects": "获取项目列表失败",
"Failed to fetch project": "获取项目失败",
"Failed to create project": "创建项目失败",
"Failed to duplicate project": "复制项目失败",
"Failed to delete project": "删除项目失败",
"Failed to get project": "获取项目失败",
"Failed to save project": "保存项目失败",
"Save project successfully": "保存项目成功",
"Input view name": "输入视图名",
"Invalid view name": "无效的视图名",
"Unsaved version found locally": "本地发现了未保存保本,请选择版本打开",
"Local Version": "本地版本",
"Remote Version": "远程版本",
"Confirm to exit the editor": "确定退出编辑器吗?",
"Confirm to publish": "确定发布吗?",
"Are you sure to delete this asset": "确定删除素材吗",
"Are you sure to delete this link": "确定删除映射吗",
"Rename asset": "重命名素材",
"Input asset name": "输入素材名",
"Invalid asset name": "无效的素材名",
"Copied field to clipboard": "已复制 {field} 到剪切板",
"Unsaved Alert": "项目还未保存,是否保存?",
"Meta is in use, can not delete": "过程元正在使用中,不能删除!",
"Are you sure to delete this meta": "确定删除这个过程元吗?",
"This Meta ID is in use, can not save": "这个ID正在被使用,不能保存!",
"Custom node desc": "自定义节点",
"Divider node desc": "分流节点,出口会按顺序一次执行",
"Save this behavior before": "是否先保存这个行为?",
"menu": {
"save": "保存",
"details": "详情",
"preview": "预览",
"publish": "发布",
"pack": "发布",
"data-mapping": "数据映射",
"exit": "退出"
"exit": "退出",
"undo": "撤销",
"redo": "重做"
},
"view_node_menu": {
"node": "节点",
"image": "图片",
"label": "标签",
"rect": "矩形"
},
"panes": {
"Assets": "素材",
"Inspector": "属性",
"Playground": "编辑",
"Playground": "画布",
"Views": "视图"
},
"dataTypes": {
"static": "静态",
"arguments": "入参",
"data-center": "数据中心"
},
"prosTypes": {
"boolean": "布尔",
"string": "字符串",
"number": "数字",
"enum": "枚举",
"color": "颜色",
"asset": "素材",
"node": "节点",
"data": "数据"
},
"events": {
"init": "初始化",
"awake": "激活",
"sleep": "入眠",
"data-center": "数据中心",
"click": "触摸点击",
"touchstart": "触摸按下",
"touchend": "触摸弹起",
"touchmove": "触摸移动"
},
"scaleMode": {
"exactFit": "精确适配",
"noBorder": "无边框",
"noScale": "不缩放",
"showAll": "全部展示",
"fixedWidth": "宽度锁定",
"fixedHeight": "高度锁定"
},
"rendererType": {
"webgl": "WEBGL",
"canvas": "CANVAS"
}
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
import Vue from "vue";
import i18n from "../../i18n";
import generateUUID from "uuid/v4";
import {metaInUse, updateProcesses} from "../../utils";
import {clonePureObj, metaInUse, updateProcesses} from "../../utils";
export const behaviorStore = {
state: {
......@@ -25,14 +25,15 @@ export const behaviorStore = {
targetUUID: '',
lineID: 0,
boardOffset: {x: 0, y: 0},
boardScale: 1,
},
},
mutations: {
behavior_startEdit(state, {originData, behaviors, event}) {
state.originData = originData;
state.originBehaviors = behaviors;
state.behaviors = JSON.parse(JSON.stringify(behaviors));
state.data = JSON.parse(JSON.stringify(originData));
state.behaviors = clonePureObj(behaviors);
state.data = clonePureObj(originData);
if (state.behaviors.length > 0) {
state.currentBehavior = state.behaviors[0];
......@@ -78,12 +79,12 @@ export const behaviorStore = {
},
deleteProcessMeta(state, {meta, process}) {
let container;
if(meta.isInline){
if (meta.isInline) {
container = process.meta.metas;
}else{
} else {
container = state.data.processes;
}
if(container){
if (container) {
for (let i = 0, li = container.length; i < li; i++) {
const process = container[i];
......@@ -106,6 +107,15 @@ export const behaviorStore = {
state.processStack.splice(index);
updatePropsEditable(state);
},
setScale(state, value) {
let scale = state.drawState.boardScale;
if (value === 0) {
scale = 1;
} else {
scale += value;
}
state.drawState.boardScale = Math.max(Math.min(4, scale), 0.1);
}
},
getters: {
customProcessMap: state => {
......@@ -143,7 +153,7 @@ export const behaviorStore = {
}
},
actions: {
addCustomProcessMeta({commit, state}, {process, isInline, processId}) {
addCustomProcessMeta({commit, state}, {masterProcess, isInline, processId}) {
let meta = {
id: generateUUID(),
script: '',
......@@ -161,19 +171,33 @@ export const behaviorStore = {
meta.isDivider = true;
break;
}
if (isInline) {
if (!process.meta.metas) {
Vue.set(process.meta, 'metas', []);
}
process.meta.metas.push(meta);
} else {
commit('addProcessMeta', meta);
}
addProcessMeta(commit, isInline, masterProcess, meta);
return meta;
},
addProcessFromPrefab({commit, state}, {masterProcess, isInline, meta: pMeta}){
let meta = clonePureObj(pMeta);
meta.id = generateUUID();
meta.isInline = isInline;
delete meta.type;
addProcessMeta(commit, isInline, masterProcess, meta);
return meta;
}
}
};
function updatePropsEditable(state) {
state.editable = state.processStack.filter(item => item.meta.type === 'builtin') <= 0;
}
function addProcessMeta(commit, isInline, masterProcess, meta){
if (isInline) {
if (!masterProcess.meta.metas) {
Vue.set(masterProcess.meta, 'metas', []);
}
masterProcess.meta.metas.push(meta);
} else {
commit('addProcessMeta', meta);
}
}
......@@ -22,8 +22,8 @@ export const envStore = {
mutations: {
updateEnv(state, env) {
Object.assign(state, env);
parseItem(state.processes);
parseItem(state.scripts);
state.processes = parseItem(state.processes);
state.scripts = parseItem(state.scripts);
state.initialized = true;
},
......@@ -90,7 +90,16 @@ function groupProcesses(processes, filterFunc) {
}
function parseItem(list) {
let hasError, result = [];
for (let i = 0, li = list.length; i < li; i++) {
list[i] = JSON.parse(list[i].data);
try {
result.push(JSON.parse(list[i].data));
} catch (e) {
hasError = true;
}
}
if (hasError) {
console.warn('parse env error');
}
return result;
}
......@@ -7,7 +7,7 @@ import { projectApi } from "../../api";
import path from "path";
import generateUUID from "uuid/v4";
import { getCmpProps, flattenViews, getCmpByUUID } from '../../utils/common';
import { saveAs } from "../../utils";
import {clonePureObj, saveAs} from "../../utils";
import { template } from "../../template";
const defaultOptions = {
......@@ -25,7 +25,7 @@ const defaultOptions = {
const OPERATE_MAX_LENGTH = 200; // 撤销重做栈最大值
function getDefaultOptions() {
return JSON.parse(JSON.stringify(defaultOptions));
return clonePureObj(defaultOptions);
}
export const projectStore = {
......
......@@ -62,6 +62,12 @@ $dock-pin-width: 9px;
border-bottom: 1px solid $--border-color-light;
}
.operate-bar{
padding: 3px;
border-bottom: 1px solid $--border-color-light;
}
}
.board {
......
......@@ -47,3 +47,12 @@
padding: 5px 0 5px 5px;
}
.el-input-number.is-controls-right .el-input__inner {
padding-left: 5px;
padding-right: 40px;
}
.el-input-number--mini .el-input-number__increase, .el-input-number--mini .el-input-number__decrease {
width: 16px;
}
......@@ -18,10 +18,10 @@ export const componentsMap = [
label: '矩形',
value: 'rect'
},
/*{
{
label: '圆形',
value: 'circle'
},*/
}
];
// 属性的计算方法
......@@ -293,6 +293,11 @@ export const styles = {
});
result += `background-position: center;background-size: 100% 100%;`
if (component.type === 'circle' && !onlyOpera) {
// 如果是circle类型,加圆角
result += 'border-radius: 50%;'
}
// console.log('getComponentStyle',component.name, result);
return result;
}
......
export default ['init', 'awake', 'sleep', 'datacenter', 'click', 'touchstart', 'touchend', 'touchmove']
\ No newline at end of file
......@@ -6,20 +6,6 @@ import {Message, Loading} from "element-ui";
import i18n from '../i18n'
import generateUUID from "uuid/v4";
export const SCALE_MODES = {
EXACT_FIT: "exactFit",
NO_BORDER: "noBorder",
NO_SCALE: "noScale",
SHOW_ALL: "showAll",
FIXED_WIDTH: "fixedWidth",
FIXED_HEIGHT: "fixedHeight",
};
export const RENDERER_TYPES= {
WEBGL: 'webgl',
CANVAS: 'canvas',
};
export function messageError(e) {
Message({
dangerouslyUseHTMLString: true,
......@@ -103,3 +89,7 @@ export function metaInUse(process, targetMetaID) {
}
return result;
}
export function clonePureObj(obj){
return JSON.parse(JSON.stringify(obj));
}
......@@ -170,15 +170,15 @@
duration: 1000,
});
this.$confirm(this.$t('Pack project successfully'), this.$t('Alert'), {
confirmButtonText: this.$t('Close'),
cancelButtonText: this.$t('Open in new tab'),
confirmButtonText: this.$t('Open in new tab'),
cancelButtonText: this.$t('Close'),
type: 'warning'
}).then(() => {
}).catch(() => {
setTimeout(()=>{
window.open(tplUrl, 'blank');
}, 500);
}).catch(() => {
});
}catch (e) {
this.$message({
......
<template>
<pane icon="el-icon-s-operation" :title="$t('panes.Inspector')">
<el-tabs v-model="tab" type="border-card" class="inspector-tabs">
<el-tab-pane label="Props" name="properties">
<el-tab-pane :label="$t('Props')" name="properties">
<props-tab/>
</el-tab-pane>
<el-tab-pane label="Behavior" name="behavior">
<el-tab-pane :label="$t('Behavior')" name="behavior">
<behavior-tab/>
</el-tab-pane>
</el-tabs>
......
......@@ -4,14 +4,13 @@
<el-form ref="form" size="mini" label-width="60px">
<div v-for="(evn, key) in eventsObj" :key="key">
<el-form-item :label="$t('Event') + ':'">
<div>{{key}}</div>
<div>{{events[key]}}</div>
<div >
<el-tooltip :content="$t('Trigger once')" placement="top">
<!--<el-tooltip :content="$t('Trigger once')" placement="top">
<el-switch v-model="evn.once" @change="v => handleOnceChange(key, v)"></el-switch>
</el-tooltip>
<el-button size="mini" @click="showBehaviorEditor(evn, key)" style="margin-left: 20px;">
{{$t('Edit Behavior')}}
<i v-if="evn.behaviors && evn.behaviors.length" class="el-icon-check el-icon--right"></i>
</el-tooltip>-->
<el-button size="mini" @click="showBehaviorEditor(evn, key)" style="margin-left: 20px;" icon="el-icon-edit">
<!--<i v-if="evn.behaviors && evn.behaviors.length" class="el-icon-check el-icon&#45;&#45;right"></i>-->
</el-button>
<el-button icon="el-icon-delete" size="mini" v-if="evn.behaviors && evn.behaviors.length" @click="deleteBehavior(key)">
</el-button>
......@@ -27,20 +26,21 @@
<script>
import { mapGetters } from 'vuex';
import _ from 'lodash';
import events from '../../../utils/events';
import BehaviorEditorDialog from '../dialogs/BehaviorEditorDialog';
export default {
name: 'BehaviorTab',
data() {
let eventsObj = {};
events.forEach(event => {
const events = this.$t('events');
Object.keys(events).forEach(event => {
eventsObj[event] = {
once: false,
behaviors: []
};
});
return {
events,
eventsObj,
behaviors: [],
currentEvent: ''
......
......@@ -31,7 +31,7 @@
<template v-for="(script, index) in activeComponent.scripts">
<el-collapse-item :title="getScriptName(script.script)" :key="script + index">
<template v-for="(p, key) in getScriptOptions(script.script)">
<el-form-item :key="activeComponent.uuid + index + key" :label="key">
<el-form-item :key="activeComponent.uuid + index + key" :label="p.alias|| key">
<dynamic-component :component-value="getScriptValue(p, key, index)" :component-props="getScriptProps(p, index)" :component-type="getScriptType(p, index)" @onChange="v => handleScriptChange(index, key, v)"></dynamic-component>
</el-form-item>
</template>
......@@ -167,6 +167,8 @@ export default {
return getCmpProps(this.activeComponent.type);
},
scripts: function() {
console.log('scripts', this.$store.state.env.scripts);
return _.filter(this.$store.state.env.scripts, s => {
return s !== null && s !== undefined;
});
......@@ -253,7 +255,7 @@ export default {
getScriptProps(item, index) {
let _type = item.type;
let _options = [];
if (type === 'enum') {
if (_type === 'enum') {
// 如果脚本选项对应的类型是数组,说明是枚举类型
_options = item.enum.map(i => {
return {
......@@ -277,7 +279,10 @@ export default {
},
getScriptType(item, index) {
// 如果脚本选项对应的类型是数组,说明是枚举类型
let _type = _.isArray(item.type) ? 'select' : item.type;
let _type = item.type;
if (_type === 'enum') {
_type = 'select';
}
return scriptTypeMap[_type].component;
},
getScriptName(id) {
......
......@@ -11,6 +11,13 @@
</split-panes>
<div class="center full-size background" splitpanes-min="20" :splitpanes-size="70">
<edit-path :processStack="processStack" @pop="onPop"/>
<div class="operate-bar">
<!--<el-button-group>
<el-button size="mini" icon="el-icon-zoom-out" @click="setScale(-0.1)"/>
<el-button size="mini" @click="setScale(0)">1:1</el-button>
<el-button size="mini" icon="el-icon-zoom-in" @click="setScale(0.1)"/>
</el-button-group>-->
</div>
<board ref="board" @select-process-node="onSelectProcessNode" @edit-process="editProcess" @edit-meta="onEditMeta"/>
</div>
<div class="properties background full-size" splitpanes-min="20" :splitpanes-size="20">
......@@ -106,7 +113,7 @@
cancelButtonText: this.$t('Cancel'),
type: 'warning'
}).then(() => {
this.deleteProcessMeta(meta.id);
this.deleteProcessMeta({meta});
}).catch((e) => {
});
}
......@@ -132,6 +139,7 @@
'clearProcessStack',
'pushProcessStack',
'popProcessStack',
'setScale',
]),
...mapGetters([
'metaInUse',
......
<template>
<div class="board" @dragover="onDragOver" @drop="onDrop" v-resize="onResize">
<svg class="svg-board full-size" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<!--<el-scrollbar class="full-size">-->
<svg ref="board" class="svg-board full-size" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" @mousedown="onBoardMouseDown">
<g ref="borderWrapper" :style="boardStyle">
<g id="layer" stroke-width="2" fill="none" fill-rule="evenodd">
<link-line v-for="(line, key, index) in lines" :data="line" :key="index" @dblclick="onDeleteLine"></link-line>
<path v-show="lineDrawing.visible" class="line hover" :d="lineDrawing.path"></path>
</g>
<g id="nodes">
<process-node v-for="(process, key, index) of subProcessMap" :ref="'pn_' + key" :process="process" :key="index"
<process-node v-for="(process, key, index) of subProcessMap" :ref="'pn_' + key" :process="process"
:key="index"
@click="onClickProcessNode(process, key)"
@hover-pin="onPinHover"
@leave-pin="onPinLeave"
......@@ -18,13 +21,16 @@
@meta-modified="onProcessMetaModified"
/>
</g>
</g>
</svg>
<!--</el-scrollbar>-->
<tool-tip ref="toolTip"/>
<inline-choose-dialog ref="inlineChooseDialog"/>
</div>
</template>
<script>
//:style="boardStyle"
import {mapState, mapMutations, mapGetters, mapActions} from 'vuex'
import ProcessNode from "./Board/ProcessNode";
import Process from "./Board/Process";
......@@ -36,7 +42,7 @@
import InlineChooseDialog from "./InlineChooseDialog";
const customs = ['custom', 'divider'];
//todo 缩放功能
export default {
name: "Board",
components: {InlineChooseDialog, ToolTip, LinkLine, ProcessNode,},
......@@ -52,6 +58,10 @@
path: '',
process: null,
},
boardOffset: {
x: 0,
y: 0,
}
}
},
mounted() {
......@@ -61,17 +71,27 @@
...mapState({
drawState: state => state.behavior.drawState,
editable: state => state.behavior.editable,
})
scale: state => state.behavior.drawState.boardScale,
}),
boardStyle() {
return {
transform: `scale(${this.scale}) translate(${this.boardOffset.x}px, ${this.boardOffset.y}px)`
}
},
},
methods: {
...mapActions([
'addCustomProcessMeta',
'addDividerProcessMeta',
'addProcessFromPrefab',
]),
...mapMutations([
'deleteProcessMeta',
'setScale',
]),
async edit(process, resolveProcess) {
this.boardOffset.x = 0;
this.boardOffset.y = 0;
this.setScale(0);
this.selectedProcessNode = null;
this.process = process;
this.resolveProcess = resolveProcess;
......@@ -96,7 +116,7 @@
this.$set(this.subProcessMap, uuid, process);
},
async addSubProcessData(processId, pos) {
let process, processMeta, isInline;
let meta, isInline;
if (customs.includes(processId)) {
try {
......@@ -106,15 +126,24 @@
return;
}
processMeta = await this.addCustomProcessMeta({process: this.process, isInline, processId});
processId = processMeta.id;
meta = await this.addCustomProcessMeta({masterProcess: this.process, isInline, processId});
}else{
meta = this.process.resolveMeta(processId);
}
process = this.process.resolveMeta(processId);
if(meta.isPrefab){
try {
const result = await this.$refs.inlineChooseDialog.show();
isInline = result.isInline;
} catch (e) {
return;
}
meta = await this.addProcessFromPrefab({masterProcess: this.process, isInline, meta})
}
let data = {
uuid: generateUUID(),
meta: process.id,
meta: meta.id,
design: {
x: pos.x,
y: pos.y,
......@@ -140,10 +169,10 @@
}
const data = await this.addSubProcessData(processId, {
x: e.offsetX - 9,
y: e.offsetY,
x: e.offsetX - this.boardOffset.x - 9,
y: e.offsetY - this.boardOffset.y,
});
if(!data){
if (!data) {
return;
}
this.addSubProcess(data.uuid, data);
......@@ -154,8 +183,8 @@
},
onResize() {
const {x, y} = this.$el.getBoundingClientRect();
this.drawState.boardOffset.x = x;
this.drawState.boardOffset.y = y;
this.drawState.boardOffset.x = x + this.boardOffset.x;
this.drawState.boardOffset.y = y + this.boardOffset.y;
},
measure() {
this.onResize();
......@@ -213,9 +242,10 @@
this.onMouseMove(e);
},
onMouseMove(e) {
const scale = this.scale;
let x = e.x - this.drawState.boardOffset.x;
let y = e.y - this.drawState.boardOffset.y;
this.lineDrawing.path = this.drawingLineStart + `${x},${y} ${x},${y}`;
this.lineDrawing.path = this.drawingLineStart + `${x / scale},${y / scale} ${x / scale},${y / scale}`;
},
onMouseUp(e) {
document.removeEventListener("mousemove", this.onMouseMove);
......@@ -256,11 +286,11 @@
});
}
},
onEditMeta(data, meta){
onEditMeta(data, meta) {
this.$emit('edit-meta', meta);
},
editSubProcess(process) {
if (!process.meta.isDivider && (this.editable || process.meta.sub && Object.keys(process.meta.sub).length > 0)) {
if (!process.meta.isDivider && this.editable && (process.meta.type !== 'builtin' || process.meta.sub && Object.keys(process.meta.sub).length > 0)) {
this.$emit('edit-process', process);
}
},
......@@ -309,7 +339,45 @@
}
}
});
},
onBoardMouseDown(e) {
if (e.target !== this.$refs.board) {
return;
}
document.addEventListener("mousemove", this.onBoardMouseMove);
document.addEventListener("mouseup", this.onBoardMouseUp);
const {screenX, screenY} = e;
this.boardDragDownPos = {x: screenX, y: screenY};
this.boardDragStartPos = {
x: this.boardOffset.x,
y: this.boardOffset.y,
}
},
onBoardMouseMove(e) {
if (!this.boardDragDownPos) {
return;
}
const {x, y} = this.boardDragDownPos;
const {screenX, screenY} = e;
const offset = {
x: screenX - x,
y: screenY - y,
};
this.boardOffset.x = this.boardDragStartPos.x + offset.x / this.scale;
this.boardOffset.y = this.boardDragStartPos.y + offset.y / this.scale;
//console.log(this.boardOffset.x, this.boardOffset.y);
},
onBoardMouseUp(e) {
if (!this.boardDragDownPos) {
return;
}
this.onResize();
this.boardDragDownPos = null;
},
}
}
</script>
......
......@@ -4,7 +4,7 @@
@mouseleave="onMouseLeave" @click="onClick" @dblclick="onDblclick">
<div class="top-bar" v-if="meta.id !== 'entry' && editable">
<el-link icon="el-icon-delete" :underline="false" @mousedown.stop.prevent @click.stop="onClickDelete"/>
<el-link icon="el-icon-edit" :underline="false" v-if="meta.type !== 'builtin'" @mousedown.stop.prevent @click.stop="onClickEdit"/>
<el-link icon="el-icon-edit" :underline="false" v-if="meta.type !== 'builtin' && !meta.isDivider" @mousedown.stop.prevent @click.stop="onClickEdit"/>
</div>
<div class="header">
<i v-if="meta.isInline">i</i>
......@@ -158,8 +158,8 @@
const {x, y, dx, dy} = this.mouseDownPos;
const offset = this.offset = {x: e.screenX - x, y: e.screenY - y};
const tx = offset.x + dx;
const ty = offset.y + dy;
const tx = offset.x / this.drawState.boardScale + dx;
const ty = offset.y / this.drawState.boardScale + dy;
this.data.design.x = tx;
this.data.design.y = ty;
......
......@@ -5,13 +5,13 @@
<div class="meta-editor-wrapper">
<el-form ref="form" v-if="meta" :model="meta" :rules="rules" :show-message="false" class="info-editor" size="mini" label-position="right" label-width="70px" @submit.native.prevent>
<template>
<el-form-item prop="id" label="ID">
<el-form-item prop="id" :label="$t('ID')">
<el-input v-model="meta.id" :placeholder="$t('ID')" :readonly="!editable"/>
</el-form-item>
<el-form-item prop="name" label="Name">
<el-form-item prop="name" :label="$t('Name')">
<el-input v-model="meta.name" :placeholder="$t('Name')" :readonly="!editable"/>
</el-form-item>
<el-form-item prop="desc" label="Desc">
<el-form-item prop="desc" :label="$t('Desc')">
<el-input v-model="meta.desc" :placeholder="$t('Description')" :readonly="!editable"/>
</el-form-item>
<!--<el-form-item prop="type" label="Type">
......@@ -20,7 +20,7 @@
<el-form-item prop="group" label="Group">
<el-input v-model="meta.group" :placeholder="$t('Group')" :readonly="!editable"/>
</el-form-item>-->
<el-form-item label="Props">
<el-form-item :label="$t('Props')">
<el-link :underline="false" @click="onClickEditProps" :disabled="!editable">
<template v-if="Object.keys(meta.props).length">
<el-tag type="success" size="mini" v-for="(option, key) in meta.props" :key="key">{{key}}</el-tag>
......@@ -28,7 +28,7 @@
<template v-else>{{$t('Empty')}}</template>
</el-link>
</el-form-item>
<el-form-item label="Output">
<el-form-item :label="$t('Output')">
<div style="display: flex;flex: 1;">
<el-select style="flex: 1;" v-model="meta.output" :disabled="!editable" allow-create filterable multiple
:placeholder="$t('Output')"/>
......@@ -48,8 +48,8 @@
<el-button size="mini" slot="reference" plain @click="pasteMeta">PasteMeta</el-button>
</el-popover>
</el-button-group>
<el-button size="mini" plain @click="cancel">Cancel</el-button>
<el-button size="mini" plain @click="save">Save</el-button>
<el-button size="mini" plain @click="cancel">{{$t('Cancel')}}</el-button>
<el-button size="mini" plain @click="save">{{$t('Save')}}</el-button>
</div>
</div>
<props-editor-dialog ref="propsEditorDialog"/>
......@@ -60,6 +60,7 @@
import ElFormItem from "./inputs/form-item";
import PropsEditorDialog from "./PropsEditorDialog";
import copy from 'copy-to-clipboard'
import {clonePureObj} from "../../../utils";
export default {
name: "MetaEditorDialog",
......@@ -91,7 +92,7 @@
methods: {
edit(meta) {
this.visible = true;
this.meta = JSON.parse(JSON.stringify(meta));
this.meta = clonePureObj(meta);
this.oldMetaID = this.meta.id;
},
onClickEditProps() {
......
......@@ -11,13 +11,13 @@
:data="props"
style="width: 100%">
<el-table-column
label="Type"
:label="$t('Type')"
width="100">
<template slot-scope="scope">
<el-select v-model="scope.row.option.type" size="mini">
<el-option v-for="type in types"
<el-option v-for="(str, type) in types"
:key="type"
:label="type"
:label="str"
:value="type"
>
</el-option>
......@@ -25,21 +25,21 @@
</template>
</el-table-column>
<el-table-column
label="Key"
width="120">
:label="$t('Key')"
width="200">
<template slot-scope="scope">
<el-input v-model="scope.row.key" size="mini"/>
</template>
</el-table-column>
<el-table-column
label="Alias"
width="100">
:label="$t('Alias')"
width="200">
<template slot-scope="scope">
<el-input v-model="scope.row.option.alias" size="mini"/>
</template>
</el-table-column>
<el-table-column
label="Default">
:label="$t('Default')">
<template slot-scope="scope">
<el-input v-if="scope.row.option.type === 'string' || scope.row.option.type === 'enum'" class="default-value" v-model="scope.row.option.default" size="mini" placeholder="Default"/>
<el-input-number v-if="scope.row.option.type === 'number'" controls-position="right" class="default-value" v-model="scope.row.option.default" size="mini" placeholder="Default"/>
......@@ -72,14 +72,16 @@
</div>
<div slot="footer" class="dialog-footer">
<div class="button-bar">
<el-button size="mini" plain @click="cancel">Cancel</el-button>
<el-button size="mini" plain @click="save">Save</el-button>
<el-button size="mini" plain @click="cancel">{{$t('Cancel')}}</el-button>
<el-button size="mini" plain @click="save">{{$t('Save')}}</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import {clonePureObj} from "../../../utils";
export default {
name: "PropsEditorDialog",
data() {
......@@ -88,23 +90,14 @@
originProps: null,
copiedProps: null,
props: [],
types: [
'boolean',
'string',
'number',
'enum',
'color',
'asset',
'node',
'data',
],
types: this.$t('prosTypes'),
}
},
methods: {
edit(props) {
this.visible = true;
this.originProps = props;
this.copiedProps = JSON.parse(JSON.stringify(props));
this.copiedProps = clonePureObj(props);
this.props.splice(0);
for (let key in this.copiedProps) {
let option = this.copiedProps[key];
......
......@@ -11,7 +11,7 @@
:disabled="!editable"
>
<el-radio-group v-model="editValue.type" size="mini" @change="onChange" :disabled="!editable">
<el-radio-button v-for="(item, key) in dataTypes" :label="key">{{item}}</el-radio-button>
<el-radio-button v-for="(item, key) in dataTypes" :label="key" :key="key">{{item}}</el-radio-button>
</el-radio-group>
<el-input clearable slot="reference" :value="editValue.value" @input="onInput" @change="onChange"
:readonly="!editable"
......
......@@ -33,19 +33,19 @@
</el-form-item>
<el-form-item prop="scaleMode" :label="$t('Scale Mode')">
<el-select v-model="options.scaleMode">
<el-option v-for="(value, key) in SCALE_MODES"
<el-option v-for="(label, key) in scaleMode"
:key="key"
:value="value"
:label="key"
:value="key"
:label="label"
></el-option>
</el-select>
</el-form-item>
<el-form-item prop="rendererType" :label="$t('Renderer Type')">
<el-select v-model="options.rendererType">
<el-option v-for="(value, key) in RENDERER_TYPES"
<el-option v-for="(label, key) in rendererType"
:key="key"
:value="value"
:label="key"
:value="key"
:label="label"
></el-option>
</el-select>
</el-form-item>
......@@ -65,13 +65,16 @@
import {mapState, mapGetters, mapMutations} from 'vuex';
import {RENDERER_TYPES, SCALE_MODES} from "../../../utils";
export default {
name: "ProjectDetailsDialog",
data() {
const scaleMode = this.$t('scaleMode');
const rendererType = this.$t('rendererType');
return {
visible: false,
SCALE_MODES,
RENDERER_TYPES,
scaleMode,
rendererType,
}
},
computed: {
......
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