Commit c04cd69a authored by 张晨辰's avatar 张晨辰

Merge branch 'dev' into feature/20190923-feature

parents 6cd8cf2b 8f3347d3
......@@ -10,3 +10,5 @@
5. 属性中增加alias为别名,用来呈现中文别名(`{alias: '文本', type: 'string', default: '你好'}`)
6. 属性中枚举的类型,type改为enum,增加以enum为名字的字符串存放枚举项(`{alias: '类型', type: 'enum', enum: ['rotate', 'jump', 'breath'], default: 'rotate'}`)
7. 编辑区需要能设置尺寸,默认`750*1334`,增加缩放功能,缩放可由按钮或者滚轮控制
8. 增加删除脚本功能
9. 增加删除行为功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
function verification(callback) {
var container = document.createElement('div');
container.style.position = 'fixed';
container.style.zIndex = '99999';
document.body.append(container);
var input = document.createElement('input');
input.placeholder = 'password';
container.append(input);
var button = document.createElement('button');
button.innerText = 'OK';
container.append(button);
button.onclick = function () {
callback(input.value === 'password');
}
var aaa = document.createElement('div');
document.body.append(aaa);
}
verification(function(result){
console.log(result);
})
</script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -228,7 +228,7 @@ const data = {
alias: 'test',
meta: 'test',
props: {
text: '$_linked_$',
},
output: {
success: [],
......
module.exports = {
region: 'oss-cn-hangzhou',
id: 'LTAIqO2wblIxQvwc',
secret: '4brsaSRbRpjxw3oDIxJi6bNMcndIR6',
bucket: 'duiba',
output: '/editor/zeroing/v1'
};
......@@ -4,6 +4,8 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"upload": "cp dist/index.html ../duiba-aurora-node/src/public/index.html&&ali-oss-publish -c oss.config.js -e dist",
"build:upload": "npm run build&&npm run upload",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'"
},
"dependencies": {
......@@ -27,6 +29,7 @@
"@kazupon/vue-i18n-loader": "^0.3.0",
"@vue/cli-plugin-babel": "^3.11.0",
"@vue/cli-service": "^3.11.0",
"ali-oss-publish": "^0.3.0",
"lodash": "^4.17.15",
"node-sass": "^4.9.2",
"sass": "^1.22.9",
......
public/favicon.ico

4.19 KB | W: | H:

public/favicon.ico

4.19 KB | W: | H:

public/favicon.ico
public/favicon.ico
public/favicon.ico
public/favicon.ico
  • 2-up
  • Swipe
  • Onion skin
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>zeroing-editor</title>
</head>
<body>
<noscript>
<strong>We're sorry but zeroing-editor doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<title>烽火台</title>
</head>
<body>
<noscript>
<strong>We're sorry but zeroing-editor doesn't work properly without JavaScript enabled. Please enable it to
continue.</strong>
</noscript>
<script>
window.__data = {
token : "<%= process.env.NODE_ENV === 'development' ? 'eyJhbGciOiJIUzI1NiJ9.5Yqz55Cq5bOw.wixVqBeqGS2FBY_VWF1cC_Vg5Zr0vYgRTfuncjGthYY' : '$TOKEN$' %>"
}
</script>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app" class="theme-light">
<router-view/>
<div class="invalid-route" v-if="ready && invalidRoute">
<p>无效的页面 {{cd}}秒后跳转</p>
<div class="error-tips" v-if="ready && showErrorTips">
<p>{{errorTipsStr}}</p>
<el-button @click="jump">direct link</el-button>
</div>
<router-view v-else/>
</div>
</template>
<script>
import i18n from "./i18n";
import {SSO_VERIFY_PAGE_URL} from "./config";
const errorTipsArr = [
'',
i18n.t('Access denied'),
i18n.t('Invalid router'),
];
export default {
name: "App",
......@@ -15,25 +24,38 @@
return {
cd: 5,
ready: false,
errorType: 0,
errorTips: '',
}
},
computed: {
invalidRoute() {
return !this.$route.matched || this.$route.matched.length === 0;
mounted() {
if (!window['zeroing_token']) {
this.dealError(1);
}
},
computed: {
showErrorTips() {
return !window['zeroing_token'] || !this.$route.matched || this.$route.matched.length === 0;
},
errorTipsStr() {
return this.errorTips + ' ' + this.$t('Jump after', {cd: this.cd});
},
},
watch: {
$route: {
handler: function(val, oldVal){
this.dealInvalidRoute();
this.ready = true;
handler: function (val, oldVal) {
this.dealError(2);
},
deep: true
}
},
methods: {
dealInvalidRoute(){
if (this.invalidRoute) {
dealError(type) {
this.errorType = type;
this.errorTips = errorTipsArr[type];
this.ready = true;
if (this.showErrorTips) {
this.cd = 5;
this.startCD();
}
......@@ -42,18 +64,28 @@
this.timer = setInterval(() => {
if (this.cd <= 0) {
clearInterval(this.timer);
this.$router.replace({name: 'home'});
this.jump();
return;
}
this.cd--;
}, 1000)
},
jump() {
switch (this.errorType) {
case 1:
location.href = SSO_VERIFY_PAGE_URL;
break;
case 2:
this.$router.replace({name: 'home'});
break;
}
},
},
}
</script>
<style>
.invalid-route {
.error-tips {
width: 100%;
height: 100%;
display: flex;
......
......@@ -3,11 +3,8 @@
*/
import {API_HOST} from "../config";
import cookie from "cookie";
import {stringify} from "querystringify";
const user_cookie = cookie.parse(document.cookie).user_cookie;
class ApiError extends Error {
constructor(name, code, message) {
super();
......@@ -33,8 +30,9 @@ export async function fetchApi(uri, {params, method = 'get', contentType = 'json
const options = {
method,
headers: {
authorization: user_cookie,
authorization: 'Bearer ' + window['zeroing_token'],
},
//credentials: 'include',
};
if (params) {
if (method.toLowerCase() === 'post') {
......
......@@ -2,13 +2,20 @@
* Created by rockyl on 2019-09-19.
*/
export const API_HOST = 'http://beacon.duibadev.com.cn';
//export const API_HOST = 'http://10.10.95.74:7777';
//export const API_HOST = 'http://localhost:3002';
export let API_HOST;
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'
}
export const UPLOAD_FILE_URL = API_HOST + '/api/uploadFile';
export const PARSE_BUNDLE_URL = API_HOST + '/api/parsePSD';
export const SSO_VERIFY_PAGE_URL = '/sso/logout';
export const DOCK_POINT_OFFSET = 4;
//文件类型图标 t表示展示缩略图
......
......@@ -15,6 +15,7 @@
"Edit": "Edit",
"ID": "ID",
"Name": "Name",
"Alias": "Alias",
"Output": "Output",
"Code": "Code",
"Desc": "Desc",
......@@ -41,6 +42,11 @@
"Custom": "Custom",
"Entry": "Entry",
"Packing": "Packing",
"Type": "Type",
"Group": "Group",
"Access denied": "Access denied",
"Invalid router": "Invalid router",
"Jump after": "Jump after {cd}s",
"Open in new tab": "Open in new tab",
"Pack project successfully": "Pack project successfully",
"Pack project failed": "Pack project failed",
......@@ -58,6 +64,7 @@
"Edit Behavior": "Edit Behavior",
"Trigger once": "Trigger once",
"Meta Editor": "Meta Editor",
"As inline": "As inline",
"Link to parent": "Link to parent",
"Input project name": "Input project name",
"Invalid project name": "Invalid project name",
......@@ -119,5 +126,10 @@
"Inspector": "Inspector",
"Playground": "Playground",
"Views": "Views"
},
"dataTypes": {
"static": "Static",
"arguments": "Arguments",
"data-center": "DataCenter"
}
}
\ No newline at end of file
......@@ -11,6 +11,8 @@ import './assets/style.css'
import './plugins/element.js'
import './themes/light/index.scss'
import './token'
new Vue({
router,
store,
......
......@@ -4,6 +4,7 @@
* 行为编辑
*/
import Vue from "vue";
import i18n from "../../i18n";
import generateUUID from "uuid/v4";
import {metaInUse, updateProcesses} from "../../utils";
......@@ -75,15 +76,23 @@ export const behaviorStore = {
updateProcesses(process, targetMetaID, replaceMetaID);
}
},
deleteProcessMeta(state, metaID) {
for (let i = 0, li = state.data.processes.length; i < li; i++) {
const process = state.data.processes[i];
deleteProcessMeta(state, {meta, process}) {
let container;
if(meta.isInline){
container = process.meta.metas;
}else{
container = state.data.processes;
}
if(container){
for (let i = 0, li = container.length; i < li; i++) {
const process = container[i];
if (process.id === metaID) {
state.data.processes.splice(i, 1);
if (process.id === meta.id) {
container.splice(i, 1);
break;
}
}
}
},
clearProcessStack(state) {
state.processStack.splice(0);
......@@ -134,25 +143,32 @@ export const behaviorStore = {
}
},
actions: {
addCustomProcessMeta({commit, state}) {
addCustomProcessMeta({commit, state}, {process, isInline, processId}) {
let meta = {
id: generateUUID(),
name: i18n.t('Custom'),
script: '',
props: {},
output: ['success', 'failed'],
};
commit('addProcessMeta', meta);
return meta;
},
addDividerProcessMeta({commit, state}) {
let meta = {
id: generateUUID(),
name: i18n.t('Divider'),
isDivider: true,
output: ['p0'],
isInline,
};
switch (processId) {
case 'custom':
meta.name = i18n.t('Custom');
meta.output = ['success', 'failed'];
break;
case 'divider':
meta.name = i18n.t('Divider');
meta.output = ['p0'];
meta.isDivider = true;
break;
}
if (isInline) {
if (!process.meta.metas) {
Vue.set(process.meta, 'metas', []);
}
process.meta.metas.push(meta);
} else {
commit('addProcessMeta', meta);
}
return meta;
},
}
......
......@@ -17,8 +17,11 @@ $dock-pin-width: 9px;
}
.process-tree {
display: flex;
flex-direction: column;
.scrollbar {
height: 100%;
flex: 1;
.process-tree-node {
flex: 1;
......@@ -72,8 +75,6 @@ $dock-pin-width: 9px;
stroke: $--color-primary;
stroke-dasharray: 5, 1;
}
}
.node {
......@@ -88,6 +89,11 @@ $dock-pin-width: 9px;
user-select: none;
margin: 0 $dock-pin-width;
&:hover {
& > .top-bar {
visibility: visible;
}
}
/*&:hover {
border-color: $block-border-hover-background-color;
......@@ -104,6 +110,21 @@ $dock-pin-width: 9px;
}
}*/
.top-bar {
height: 19px;
padding: 0 3px;
margin: -20px 5px 0;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background-color: rgba(0, 0, 0, 0.1);
align-self: flex-end;
visibility: hidden;
.el-link + .el-link {
margin-left: 5px;
}
}
.header {
min-height: 12px;
background-color: $block-border-blur-background-color;
......@@ -114,17 +135,14 @@ $dock-pin-width: 9px;
color: white;
display: flex;
.title {
flex: 1;
i{
display: block;
//color: $--color-warning;
margin-right: 3px;
}
.delete-button {
padding: 2px;
color: $--border-color-lighter;
&:hover {
color: white;
}
.title {
flex: 1;
}
}
......@@ -150,8 +168,18 @@ $dock-pin-width: 9px;
}
.linked-value {
display: flex;
align-items: center;
justify-content: flex-end;
}
.string-value {
text-align: right;
.tag {
color: $--color-success;
}
}
.color-value {
......@@ -161,11 +189,6 @@ $dock-pin-width: 9px;
float: right;
border: 1px solid $--border-color-base;
}
.linked-icon {
float: right;
color: $--color-success;
}
}
}
......@@ -221,6 +244,10 @@ $dock-pin-width: 9px;
& > .header {
background-color: $block-border-focus-background-color;
}
/*& > .top-bar {
visibility: visible;
}*/
}
}
}
......@@ -229,7 +256,7 @@ $dock-pin-width: 9px;
display: flex;
flex-direction: column;
.linked{
.linked {
display: block;
height: 26px;
overflow: hidden;
......@@ -260,7 +287,7 @@ $dock-pin-width: 9px;
display: flex;
flex-direction: column;
.name-input{
.name-input {
}
......@@ -269,7 +296,7 @@ $dock-pin-width: 9px;
padding-top: 5px;
flex: 1;
.scrollbar-view{
.scrollbar-view {
padding-right: 10px;
}
......@@ -282,11 +309,11 @@ $dock-pin-width: 9px;
}
}
.node-select-container{
.node-select-container {
flex: 1;
}
.string-editor-container{
.string-input-container {
flex: 1;
height: 28px;
}
......@@ -346,13 +373,13 @@ $dock-pin-width: 9px;
}
}
.node-select-popover{
.node-select-popover {
.tree-scrollbar {
width: 100%;
height: 200px;
}
.bottom-bar{
.bottom-bar {
margin-top: 5px;
display: flex;
align-items: center;
......@@ -360,3 +387,9 @@ $dock-pin-width: 9px;
}
}
.linked-prop-popover {
div + div {
margin-top: 5px;
}
}
/**
* Created by rockyl on 2019-11-16.
*/
import cookie from "cookie";
let user_cookie;
user_cookie = cookie.parse(document.cookie).user_cookie;
if (!user_cookie) {
try {
user_cookie = window.__data.token;
} catch (e) {
}
}
if (!user_cookie) {
console.log('Access denied');
}
window['zeroing_token'] = user_cookie;
......@@ -20,8 +20,6 @@ export const RENDERER_TYPES= {
CANVAS: 'canvas',
};
export const linkedFlag = '$_linked_$';
export function messageError(e) {
Message({
dangerouslyUseHTMLString: true,
......@@ -81,7 +79,7 @@ export function saveAs(blob, fileName) {
}
}
export function getEditorDefaultValue(property) {
export function getInputDefaultValue(property) {
return property.hasOwnProperty('default') ? property.default + '' : 'unset';
}
......
......@@ -13,26 +13,26 @@ export default {
type: 'inputNumber',
value: 0,
},
// left: {
// title: '左边距',
// type: 'inputNumber',
// value: undefined,
// },
// right: {
// title: '右边距',
// type: 'inputNumber',
// value: undefined,
// },
// top: {
// title: '上边距',
// type: 'inputNumber',
// value: undefined,
// },
// bottom: {
// title: '下边距',
// type: 'inputNumber',
// value: undefined,
// },
left: {
title: '左边距',
type: 'inputNumber',
value: undefined,
},
right: {
title: '右边距',
type: 'inputNumber',
value: undefined,
},
top: {
title: '上边距',
type: 'inputNumber',
value: undefined,
},
bottom: {
title: '下边距',
type: 'inputNumber',
value: undefined,
},
width: {
title: '宽度',
type: 'inputNumber',
......@@ -43,18 +43,18 @@ export default {
type: 'inputNumber',
value: 1
},
// horizonCenter: {
// title: '水平偏移',
// type: 'inputNumber',
// value: undefined,
// desc: '相对于父元素中心点的水平偏移,0为正中心'
// },
// verticalCenter: {
// title: '垂直偏移',
// type: 'inputNumber',
// value: undefined,
// desc: '相对于父元素中心点的垂直偏移,0为正中心'
// },
horizonCenter: {
title: '水平偏移',
type: 'inputNumber',
value: undefined,
desc: '相对于父元素中心点的水平偏移,0为正中心'
},
verticalCenter: {
title: '垂直偏移',
type: 'inputNumber',
value: undefined,
desc: '相对于父元素中心点的垂直偏移,0为正中心'
},
rotation: {
title: '旋转',
type: 'inputNumber',
......
......@@ -4,7 +4,7 @@
<split-panes class="pane-container" @resized="onPanesReSized(0, $event)">
<split-panes splitpanes-min="40" :splitpanes-size="getSize(0, 0)" horizontal @resized="onPanesReSized(1, $event)">
<split-panes splitpanes-min="20" :splitpanes-size="getSize(1, 0)" @resized="onPanesReSized(2, $event)">
<views splitpanes-min="30" :splitpanes-size="getSize(2, 0)"></views>
<views splitpanes-min="20" :splitpanes-size="getSize(2, 0)"></views>
<playground splitpanes-min="20" :splitpanes-size="getSize(2, 1)"></playground>
</split-panes>
<assets splitpanes-min="20" :splitpanes-size="getSize(1, 1)"></assets>
......@@ -176,7 +176,9 @@
}).then(() => {
}).catch(() => {
setTimeout(()=>{
window.open(tplUrl, 'blank');
}, 500);
});
}catch (e) {
this.$message({
......
......@@ -54,7 +54,7 @@ export default {
showBehaviorEditor(evn, key) {
this.currentEvent = key;
this.behaviors = evn.behaviors || [];
this.$refs.behaviorEditorDialog.show(this.behaviors, key);
this.$refs.behaviorEditorDialog.show(this.behaviors, this.activeComponent.name + '_' + key);
},
/**
* 当前选中组件发生变化时,更新eventsObj的数据
......
......@@ -7,6 +7,7 @@
class="menu-item import-file"
:action="importFileUrl"
name="file"
:headers="uploadHeaders"
:show-file-list="false"
:on-success="uploadFileSuccess"
:on-error="uploadFileError"
......@@ -66,7 +67,10 @@ export default {
defaultProps: {
children: 'children',
label: 'name'
}
},
uploadHeaders: {
authorization: 'Bearer ' + window['zeroing_token'],
},
};
},
computed: {
......
......@@ -11,7 +11,7 @@
</split-panes>
<div class="center full-size background" splitpanes-min="20" :splitpanes-size="70">
<edit-path :processStack="processStack" @pop="onPop"/>
<board ref="board" @select-process-node="onSelectProcessNode" @edit-process="editProcess"/>
<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">
<properties-editor ref="properties"/>
......
......@@ -13,12 +13,14 @@
@leave-pin="onPinLeave"
@down-pin="onPintDown"
@delete="onProcessNodeDelete"
@edit-meta="onEditMeta"
@dblclick="editSubProcess(process)"
@meta-modified="onProcessMetaModified"
/>
</g>
</svg>
<tool-tip ref="toolTip"/>
<inline-choose-dialog ref="inlineChooseDialog"/>
</div>
</template>
......@@ -31,10 +33,13 @@
import {DOCK_POINT_OFFSET} from "../../../config";
import events from "../../../global-events";
import generateUUID from "uuid/v4";
//todo 缩放功能
import InlineChooseDialog from "./InlineChooseDialog";
const customs = ['custom', 'divider'];
//todo 缩放功能
export default {
name: "Board",
components: {ToolTip, LinkLine, ProcessNode,},
components: {InlineChooseDialog, ToolTip, LinkLine, ProcessNode,},
props: [],
data() {
return {
......@@ -46,7 +51,7 @@
visible: false,
path: '',
process: null,
}
},
}
},
mounted() {
......@@ -54,7 +59,8 @@
},
computed: {
...mapState({
drawState: state=>state.behavior.drawState
drawState: state => state.behavior.drawState,
editable: state => state.behavior.editable,
})
},
methods: {
......@@ -90,20 +96,21 @@
this.$set(this.subProcessMap, uuid, process);
},
async addSubProcessData(processId, pos) {
let process, processMeta;
let process, processMeta, isInline;
switch(processId){
case 'custom':
processMeta = await this.addCustomProcessMeta();
processId = processMeta.id;
break;
case 'divider':
processMeta = await this.addDividerProcessMeta();
if (customs.includes(processId)) {
try {
const result = await this.$refs.inlineChooseDialog.show();
isInline = result.isInline;
} catch (e) {
return;
}
processMeta = await this.addCustomProcessMeta({process: this.process, isInline, processId});
processId = processMeta.id;
break;
}
process = this.resolveProcess(processId);
process = this.process.resolveMeta(processId);
let data = {
uuid: generateUUID(),
......@@ -136,13 +143,16 @@
x: e.offsetX - 9,
y: e.offsetY,
});
if(!data){
return;
}
this.addSubProcess(data.uuid, data);
this.$nextTick(() => {
events.$emit('update-dock-pin-pos');
});
},
onResize(){
onResize() {
const {x, y} = this.$el.getBoundingClientRect();
this.drawState.boardOffset.x = x;
this.drawState.boardOffset.y = y;
......@@ -239,16 +249,22 @@
}
}
if(meta.isDivider){ //如果是分流器还要删除对应的meta
this.deleteProcessMeta(meta.id);
if (meta.isDivider || meta.isInline) { //如果是分流节点或者内联节点还要删除对应的meta
this.deleteProcessMeta({
meta,
process: this.process,
});
}
},
onEditMeta(data, meta){
this.$emit('edit-meta', meta);
},
editSubProcess(process) {
if (!process.meta.isDivider && (process.meta.type !== 'builtin' || process.meta.sub && Object.keys(process.meta.sub).length > 0)) {
if (!process.meta.isDivider && (this.editable || process.meta.sub && Object.keys(process.meta.sub).length > 0)) {
this.$emit('edit-process', process);
}
},
onProcessMetaModified(process, meta){
onProcessMetaModified(process, meta) {
let ids = Object.keys(this.lines);
for (let id of ids) {
const line = this.lines[id];
......@@ -256,7 +272,7 @@
if (prev === process) {
const {outputType} = line;
if(meta.output.indexOf(outputType) < 0){
if (meta.output.indexOf(outputType) < 0) {
this.onDeleteLine(line);
}
}
......@@ -279,7 +295,7 @@
}
},
updateProcessNode(metaID) {
this.$nextTick(()=>{
this.$nextTick(() => {
for (let key in this.$refs) {
if (key.startsWith('pn_')) {
......
......@@ -15,7 +15,7 @@ export default class Process {
}
resolveMeta(id) {
let meta = this.meta && this.meta.metas ? this.meta.metas[id] : null;
let meta = this.meta && this.meta.metas ? this.meta.metas.find(meta=>meta.id === id) : null;
if (!meta && this._parent) {
meta = this._parent.resolveMeta(id);
}
......
<template>
<foreignObject :x="data.design.x" :y="data.design.y" :width="width" :height="height">
<div ref="node" :class="{active: active}" class="node" @mousedown="onMouseDown" @mouseenter="onMouseEnter"
<div ref="node" :class="{active: active}" class="node" style="margin-top: 20px;" @mousedown="onMouseDown" @mouseenter="onMouseEnter"
@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"/>
</div>
<div class="header">
<i v-if="meta.isInline">i</i>
<span class="title">{{data.alias || meta.name}}</span>
<i v-if="meta.id !== 'entry'" class="delete-button el-icon-delete" @click.stop="onClickDelete"
@mousedown.stop.prevent></i>
</div>
<div class="body">
<div v-if="meta.isDivider">
......@@ -14,8 +17,17 @@
</div>
<div v-else class="field-item" v-for="(param, key, index) in meta.props" :key="index">
<span class="key">{{param.alias || key}}</span>:
<span class="" v-if="data.props[key] === linkedFlag">
<i class="el-icon-link linked-icon"></i>
<span class="linked-value" v-if="typeof data.props[key] === 'object'">
<span class="string-value">
<template v-if="data.props[key].type === 'link'">
{{data.props[key].alias || ''}}
<i class="el-icon-link tag"></i>
</template>
<template v-else>
{{data.props[key].value || ''}}
<i class="tag">{{data.props[key].type[0].toUpperCase()}}</i>
</template>
</span>
</span>
<template v-else>
<div v-if="param.type === 'color'">
......@@ -43,7 +55,6 @@
import {mapState} from "vuex";
import DockPin from "./DockPin";
import events from "../../../../global-events";
import {linkedFlag} from "../../../../utils";
export default {
name: "ProcessNode",
......@@ -57,7 +68,6 @@
height: 100,
inputMeta,
active: false,
linkedFlag,
}
},
mounted() {
......@@ -76,7 +86,8 @@
return this.process.data;
},
...mapState({
drawState: state=>state.behavior.drawState
drawState: state => state.behavior.drawState,
editable: state => state.behavior.editable,
}),
},
watch: {
......@@ -169,7 +180,7 @@
this.$nextTick(() => {
let bounds = this.$refs.node.getBoundingClientRect();
this.width = bounds.width + 18;
this.height = bounds.height;
this.height = bounds.height + 20;
});
},
updateDockPointPos() {
......@@ -214,6 +225,9 @@
onClickDelete() {
this.$emit('delete', this.data, this.meta);
},
onClickEdit() {
this.$emit('edit-meta', this.data, this.meta);
},
outputPointModify(action) {
let output = this.meta.output;
let count = output.length;
......@@ -234,7 +248,7 @@
}
this.$emit('meta-modified', this.data, this.meta);
this.$nextTick(()=>{
this.$nextTick(() => {
this.updateDockPointPos();
});
}
......
<template>
<el-dialog
:title="$t('Alert')"
:visible.sync="dialogVisible"
append-to-body
@close="onClose"
>
<el-checkbox v-model="asInline">{{$t('As inline')}}</el-checkbox>
<span slot="footer" class="dialog-footer">
<el-button size="mini" @click="dialogVisible = false">{{$t('Cancel')}}</el-button>
<el-button size="mini" type="primary" @click="onConfirm">{{$t('Confirm')}}</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: "InlineChooseDialog",
data() {
return {
dialogVisible: false,
asInline: false,
}
},
methods: {
show() {
this.dialogVisible = true;
return new Promise((resolve, reject) => {
this.p = {resolve, reject};
});
},
onClose() {
if (this.p) {
this.p.reject();
this.p = null;
}
this.dialogVisible = false;
},
onConfirm() {
if (this.p) {
this.p.resolve({
isInline: this.asInline,
});
this.p = null;
}
this.dialogVisible = false;
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
......@@ -14,6 +14,12 @@
<el-form-item prop="desc" label="Desc">
<el-input v-model="meta.desc" :placeholder="$t('Description')" :readonly="!editable"/>
</el-form-item>
<!--<el-form-item prop="type" label="Type">
<el-input v-model="meta.type" :placeholder="$t('Type')" :readonly="!editable"/>
</el-form-item>
<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-link :underline="false" @click="onClickEditProps" :disabled="!editable">
<template v-if="Object.keys(meta.props).length">
......@@ -35,7 +41,13 @@
</div>
<div slot="footer" class="dialog-footer">
<div class="button-bar">
<el-button size="mini" plain @click="printMeta">PrintMeta</el-button>
<el-button-group style="margin-right: 20px;">
<el-button size="mini" plain @click="copyMeta">CopyMeta</el-button>
<el-popover>
<div ref="pasteBoard" @paste="onPaste">Click and Ctrl+V</div>
<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>
</div>
......@@ -45,8 +57,9 @@
</template>
<script>
import ElFormItem from "./editors/form-item";
import ElFormItem from "./inputs/form-item";
import PropsEditorDialog from "./PropsEditorDialog";
import copy from 'copy-to-clipboard'
export default {
name: "MetaEditorDialog",
......@@ -69,7 +82,7 @@
},
computed: {
editable() {
return this.meta && this.meta.type !== 'builtin';
return this.meta;// && this.meta.type !== 'builtin';
},
props() {
return Object.keys(this.meta.props).join(',')
......@@ -103,8 +116,25 @@
cancel() {
this.visible = false;
},
printMeta() {
console.log(JSON.stringify(this.meta));
copyMeta() {
copy(JSON.stringify(this.meta));
},
pasteMeta() {
//setTimeout(this.focusPasteBoard, 1000, this);
},
onPaste(e) {
let metaStr = e.clipboardData.getData("Text");
if(metaStr){
try {
let meta = JSON.parse(metaStr);
this.meta = meta;
}catch (e) {
}
}
},
focusPasteBoard(){
this.$refs.pasteBoard.focus();
},
}
}
......
......@@ -7,7 +7,7 @@
view-class="scrollbar-view">
<el-form v-model="process" size="mini" label-width="80px" label-position="left" @submit.native.prevent>
<component v-for="(property, key) in process.meta.props"
:is="getEditor(property)"
:is="getInput(property)"
v-model="process.data.props[key]"
:propertyName="key"
:property="property"
......@@ -22,27 +22,31 @@
<script>
import {mapState} from "vuex";
import NumberEditor from "./editors/NumberEditor";
import StringEditor from "./editors/StringEditor";
import EnumEditor from "./editors/EnumEditor";
import BooleanEditor from "./editors/BooleanEditor";
import ColorEditor from "./editors/ColorEditor";
import AssetEditor from "./editors/AssetEditor";
import NodeSelectEditor from "./editors/NodeSelectEditor";
import NumberInput from "./inputs/NumberInput";
import StringInput from "./inputs/StringInput";
import EnumInput from "./inputs/EnumInput";
import BooleanInput from "./inputs/BooleanInput";
import ColorInput from "./inputs/ColorInput";
import AssetInput from "./inputs/AssetInput";
import NodeSelectInput from "./inputs/NodeSelectInput";
import DataInput from "./inputs/DataInput";
const editorMapping = {
number: 'NumberEditor',
string: 'StringEditor',
enum: 'EnumEditor',
boolean: 'BooleanEditor',
color: 'ColorEditor',
asset: 'AssetEditor',
node: 'NodeSelectEditor',
const inputMapping = {
number: 'NumberInput',
string: 'StringInput',
enum: 'EnumInput',
boolean: 'BooleanInput',
color: 'ColorInput',
asset: 'AssetInput',
node: 'NodeSelectInput',
data: 'DataInput',
};
export default {
name: "PropertiesEditor",
components: {NodeSelectEditor, AssetEditor, ColorEditor, BooleanEditor, EnumEditor, NumberEditor, StringEditor},
name: "PropertiesInput",
components: {
DataInput,
NodeSelectInput, AssetInput, ColorInput, BooleanInput, EnumInput, NumberInput, StringInput},
data() {
return {
process: null,
......@@ -57,8 +61,8 @@
edit(process) {
this.process = process;
},
getEditor(property) {
return editorMapping[property.type];
getInput(property) {
return inputMapping[property.type];
},
}
}
......
......@@ -96,6 +96,7 @@
'color',
'asset',
'node',
'data',
],
}
},
......
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-select :disabled="!editable" :value="editValue" filterable @input="onInput" :placeholder="property.default" class="el-select">
<el-option
v-for="(item, key) in assets"
......@@ -9,16 +9,16 @@
<span>{{item.name}}</span>
</el-option>
</el-select>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import {mapMutations} from 'vuex'
import EditorWrapper from "./EditorWrapper";
import InputWrapper from "./InputWrapper";
export default {
name: "AssetEditor",
components: {EditorWrapper,},
name: "AssetInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
computed: {
editValue() {
......
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-switch :disabled="!editable" :value="editValue" @input="onInput"
class="picker"></el-switch>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import EditorWrapper from "./EditorWrapper";
import InputWrapper from "./InputWrapper";
export default {
name: "BooleanEditor",
components: {EditorWrapper},
name: "BooleanInput",
components: {InputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() {
return {}
......
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName" class="color-editor-container">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName" class="color-input-container">
<el-color-picker
:disabled="!editable"
class="picker"
......@@ -8,15 +8,15 @@
show-alpha
:predefine="predefineColors">
</el-color-picker>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import EditorWrapper from "./EditorWrapper";
import InputWrapper from "./InputWrapper";
export default {
name: "ColorEditor",
components: {EditorWrapper,},
name: "ColorInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() {
return {
......@@ -54,7 +54,7 @@
</script>
<style scoped>
.color-editor-container {
.color-input-container {
height: 29px;
overflow: hidden;
}
......
<template>
<input-wrapper :editable="editable" :value="value" :container="container" :property="property"
:propertyName="propertyName">
<div style="display: flex;flex: 1;">
<el-popover
placement="top"
popper-class="input-area-popover"
class="string-input-container"
trigger="manual"
v-model="popoverVisible"
: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-group>
<el-input clearable slot="reference" :value="editValue.value" @input="onInput" @change="onChange"
:readonly="!editable"
:placeholder="defaultValue"/>
</el-popover>
<el-button-group>
<el-button @click="onClickEdit" :disabled="!editable">{{editValue.type[0].toUpperCase()}}</el-button>
<el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button>
</el-button-group>
</div>
</input-wrapper>
</template>
<script>
import InputWrapper from "./InputWrapper";
import {getInputDefaultValue} from "../../../../utils";
export default {
name: "DataInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() {
let dataTypes = this.$t('dataTypes');
return {
editValue: this.value || {type: 'static'},
popoverEditValue: this.value,
popoverVisible: false,
dataTypes,
}
},
computed: {
defaultValue() {
return getInputDefaultValue(this.property);
},
},
watch: {
value(v) {
this.editValue = v || {type: 'static'};
},
},
methods: {
onClickEdit() {
this.popoverVisible = !this.popoverVisible;
},
onClickClean() {
this.$emit('input', undefined, this.container, this.propertyName, this.value);
},
onInput(v) {
this.$set(this.editValue, 'value', v);
},
onChange() {
this.$emit('input', this.editValue, this.container, this.propertyName, this.value);
},
},
}
</script>
<style scoped>
.bottom-bar {
margin-top: 5px;
display: flex;
align-items: center;
justify-content: space-between;
}
</style>
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-select :disabled="!editable" :value="editValue" @input="onInput" :placeholder="property.default" class="el-select">
<el-option
v-for="(item, key) in property.enum"
......@@ -10,15 +10,15 @@
<span class="comment"></span>
</el-option>
</el-select>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import EditorWrapper from "./EditorWrapper";
import InputWrapper from "./InputWrapper";
export default {
name: "EnumEditor",
components: {EditorWrapper,},
name: "EnumInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
computed: {
editValue() {
......
<template>
<el-form-item class="editor-wrapper" :label="property.alias || propertyName" content-float="right"
<el-form-item class="input-wrapper" :label="property.alias || propertyName" content-float="right"
:content-width="contentWidth" :labelOffsetTop="labelOffsetTop">
<template v-if="linked">
<span class="linked">Linked to parent</span>
......@@ -11,10 +11,15 @@
trigger="click"
:disabled="!editable"
>
<div class="linked-prop-popover">
<div>
<span>{{$t('Link to parent')}}: </span>
<el-switch :value="linked" @input="onChange"/>
</div>
<div v-if="linked">
<el-input size="mini" v-model="value.alias" :placeholder="$t('Alias')"/>
</div>
</div>
<el-link style="padding: 3px;" slot="reference" icon="el-icon-link" :underline="false"
:type="linked ? 'success' : 'default'" :disabled="!editable"/>
</el-popover>
......@@ -24,10 +29,9 @@
<script>
import camelcase from 'camelcase'
import ElFormItem from "./form-item";
import {linkedFlag} from "../../../../utils";
export default {
name: "EditorWrapper",
name: "InputWrapper",
components: {ElFormItem},
props: {
property: Object,
......@@ -44,15 +48,28 @@
default: 0,
},
},
data(){
return {
}
},
watch: {
value(v){
}
},
computed: {
linked() {
return this.value === linkedFlag
return typeof this.value === 'object' && this.value.type === 'link'
}
},
methods: {
onChange(v) {
if (v) {
this.$set(this.container.data.props, this.propertyName, linkedFlag);
this.$set(this.container.data.props, this.propertyName, {
type: 'link',
alias: undefined,
});
} else {
this.$delete(this.container.data.props, this.propertyName);
}
......
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property"
:propertyName="propertyName">
<div style="display: flex;flex: 1;">
<el-popover
placement="top"
......@@ -34,7 +35,8 @@
</el-button-group>
</div>
</div>
<el-input clearable slot="reference" v-model="editValue" @change="onInput" placeholder="unset" :readonly="!editable">
<el-input clearable slot="reference" v-model="editValue" @change="onInput" placeholder="unset"
:readonly="!editable">
<template slot="prepend">node://</template>
</el-input>
</el-popover>
......@@ -43,18 +45,18 @@
<el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button>
</el-button-group>
</div>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import {mapGetters} from "vuex";
import EditorWrapper from "./EditorWrapper";
import InputWrapper from "./InputWrapper";
const nodeScheme = 'node://';
export default {
name: "NodeSelectEditor",
components: {EditorWrapper,},
name: "NodeSelectInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() {
return {
......@@ -66,15 +68,20 @@
},
}
},
watch: {
value(v) {
this.editValueOrigin = v;
}
},
computed: {
...mapGetters([
'behavior_views'
]),
editValue: {
get(){
return this.editValueOrigin ? this.editValueOrigin.replace(nodeScheme) : '';
get() {
return this.editValueOrigin && typeof this.editValueOrigin !== 'object'? this.editValueOrigin.replace(nodeScheme, '') : '';
},
set(v){
set(v) {
this.editValueOrigin = v;
},
},
......
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-input-number :disabled="!editable" :value="editValue" @input="onInput" controls-position="right"
:placeholder="defaultValue"></el-input-number>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import EditorWrapper from "./EditorWrapper";
import {getEditorDefaultValue} from "../../../../utils";
import InputWrapper from "./InputWrapper";
import {getInputDefaultValue} from "../../../../utils";
export default {
name: "NumberEditor",
components: {EditorWrapper,},
name: "NumberInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
computed: {
editValue() {
return this.value === undefined ? this.property.default : this.value;
},
defaultValue(){
return getEditorDefaultValue(this.property);
return getInputDefaultValue(this.property);
},
},
methods: {
......
<template>
<editor-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<input-wrapper :editable="editable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<div style="display: flex;flex: 1;">
<el-popover
placement="top"
popper-class="input-area-popover"
class="string-editor-container"
class="string-input-container"
trigger="manual"
width="400"
v-model="popoverVisible"
......@@ -34,16 +34,16 @@
<el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button>
</el-button-group>
</div>
</editor-wrapper>
</input-wrapper>
</template>
<script>
import EditorWrapper from "./EditorWrapper";
import {getEditorDefaultValue, linkedFlag} from "../../../../utils";
import InputWrapper from "./InputWrapper";
import {getInputDefaultValue} from "../../../../utils";
export default {
name: "StringEditor",
components: {EditorWrapper,},
name: "StringInput",
components: {InputWrapper,},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() {
return {
......@@ -60,7 +60,7 @@
return this.popoverVisible ? 'el-icon-check' : 'el-icon-edit';
},
defaultValue() {
return getEditorDefaultValue(this.property);
return getInputDefaultValue(this.property);
},
},
watch: {
......
......@@ -14,7 +14,7 @@
<template slot-scope="scope">
<div class="project-info">
<span class="project-name">{{scope.row.name}}</span>
<el-tag size="mini" type="success">{{scope.row.creator}}</el-tag>
<el-tag size="mini" type="success">{{scope.row.operator}}</el-tag>
<el-tag size="mini" type="warning">{{moment(scope.row.update_time)}}</el-tag>
</div>
</template>
......
const serverHost = 'http://10.10.95.74:7777';
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '//yun.duiba.com.cn/editor/zeroing/v1/' : '',
pluginOptions: {
i18n: {
locale: 'en',
......@@ -6,5 +9,20 @@ module.exports = {
localeDir: 'locales',
enableInSFC: true
}
},
devServer: {
host: '0.0.0.0',
port: '8080',
proxy: {
'/sso': {
target: serverHost,
},
'/api': {
target: serverHost,
},
}
}
},
configureWebpack: {
}
};
This source diff could not be displayed because it is too large. You can view the blob instead.
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