Commit d60fcb79 authored by rockyl's avatar rockyl

版本库锁定完成开发

parent 4a6afcb8
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"upload": "node scripts/copy-index.js && ali-oss-publish -c oss.config.js -e dist", "upload": "node scripts/pre-process.js && ali-oss-publish -c oss.config.js -e dist",
"build:upload": "npm run build&&npm run upload", "build:upload": "npm run build&&npm run upload",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'" "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'",
"link:all": "yarn link zeroing-code-divider zeroing-template-fill props-compute"
}, },
"dependencies": { "dependencies": {
"codemirror": "^5.50.0", "codemirror": "^5.50.0",
...@@ -18,11 +19,11 @@ ...@@ -18,11 +19,11 @@
"indexdbwrapper": "^1.0.4", "indexdbwrapper": "^1.0.4",
"jszip": "^3.2.2", "jszip": "^3.2.2",
"moment": "^2.24.0", "moment": "^2.24.0",
"monaco-editor": "^0.19.0", "monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.8.1", "monaco-editor-webpack-plugin": "^1.9.0",
"path": "^0.12.7", "path": "^0.12.7",
"psd-parse-web": "http://gitlab2.dui88.com/laoqifeng/psd-parse-web.git",
"props-compute": "http://gitlab2.dui88.com/laoqifeng/props-compute.git", "props-compute": "http://gitlab2.dui88.com/laoqifeng/props-compute.git",
"psd-parse-web": "http://gitlab2.dui88.com/laoqifeng/psd-parse-web.git",
"querystringify": "^2.1.1", "querystringify": "^2.1.1",
"semver": "^7.1.1", "semver": "^7.1.1",
"socket.io-client": "^2.3.0", "socket.io-client": "^2.3.0",
...@@ -30,11 +31,12 @@ ...@@ -30,11 +31,12 @@
"string-width": "^4.1.0", "string-width": "^4.1.0",
"uuid": "^3.3.3", "uuid": "^3.3.3",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-codemirror": "^4.0.6",
"vue-i18n": "^8.0.0", "vue-i18n": "^8.0.0",
"vue-monaco": "http://gitlab2.dui88.com/laoqifeng/vue-monaco.git",
"vue-router": "^3.0.3", "vue-router": "^3.0.3",
"vuex": "^3.0.1", "vuex": "^3.0.1",
"zeroing-code-divider": "http://gitlab2.dui88.com/laoqifeng/zeroing-code-divider.git" "zeroing-code-divider": "http://gitlab2.dui88.com/laoqifeng/zeroing-code-divider.git",
"zeroing-template-fill": "http://gitlab2.dui88.com/laoqifeng/zeroing-template-fill.git"
}, },
"devDependencies": { "devDependencies": {
"@kazupon/vue-i18n-loader": "^0.3.0", "@kazupon/vue-i18n-loader": "^0.3.0",
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>烽火台</title> <title>烽火台</title>
<script src="//yun.duiba.com.cn/js-libs/jshint/2.10.2/jshint.min.js"></script>
<script src="//yun.duiba.com.cn/js-libs/jsonlint/1.6.0/jsonlint.min.js"></script>
<script src="//yun.duiba.com.cn/js-libs/psd.js/3.2.0/psd.min.js"></script> <script src="//yun.duiba.com.cn/js-libs/psd.js/3.2.0/psd.min.js"></script>
</head> </head>
<body> <body>
......
<template>
<div style="width: 100%; height: 100%" ref="container"></div>
</template>
<script>
import * as monaco from 'monaco-editor';
export default {
name: "MonacoEditor",
data() {
return {
}
},
props: {
value: {
type: String,
default: '',
},
language: {
type: String,
default: 'javascript',
},
theme: {
type: String,
default: 'vs',
},
editorOptions: {
type: Object,
default: function(){
return {
selectOnLineNumbers: true,
roundedSelection: false,
readOnly: false, // 只读
cursorStyle: 'line', //光标样式
automaticLayout: false, //自动布局
glyphMargin: true, //字形边缘
useTabStops: false,
fontSize: 28, //字体大小
autoIndent:true,//自动布局
}
},
},
},
mounted() {
this.initEditor();
},
watch: {
value(value){
if(this.editor && value !== this.editor.getValue()){
this.editor.setValue(value);
}
}
},
methods: {
initEditor() {
this.editor = monaco.editor.create(this.$refs.container, {
value: this.value,
language: this.language,
theme: this.theme,
lineNumbers: 'on',
tabSize: 2,
insertSpaces: false,
editorOptions: this.editorOptions,
});
this.editor.onDidChangeModelContent(event => {
const value = this.editor.getValue();
this.$emit('input', value);
});
this.editor.updateOptions({
})
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
...@@ -6,8 +6,8 @@ export let API_HOST; ...@@ -6,8 +6,8 @@ export let API_HOST;
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
//API_HOST = '//10.10.95.74:7777'; //API_HOST = '//10.10.95.74:7777';
//API_HOST = '//192.168.1.16:7777'; //API_HOST = '//192.168.1.16:7777';
API_HOST = '//192.168.2.143:7777'; API_HOST = '//10.10.92.100:7777';
//API_HOST = '//10.10.92.33:7777'; //API_HOST = '//192.168.0.106:7777';
//API_HOST = '//localhost:3002'; //API_HOST = '//localhost:3002';
//API_HOST = window.__data.apiHost; //API_HOST = window.__data.apiHost;
//API_HOST = ''; //API_HOST = '';
......
...@@ -3,13 +3,15 @@ ...@@ -3,13 +3,15 @@
"Confirm": "确认", "Confirm": "确认",
"Cancel": "取消", "Cancel": "取消",
"Close": "关闭", "Close": "关闭",
"Still Close": "仍然关闭", "Refresh": "刷新",
"Still Close": "直接关闭",
"Save": "保存", "Save": "保存",
"Save And Preview": "保存并预览", "Save And Preview": "保存并预览",
"Save And Close": "保存并关闭", "Save And Close": "保存并关闭",
"Reset": "重置", "Reset": "重置",
"Copy": "复制", "Copy": "复制",
"Assets": "素材", "Assets": "素材",
"Version": "版本",
"Paste same level":"粘贴(同级)", "Paste same level":"粘贴(同级)",
"Paste child":"粘贴(子级)", "Paste child":"粘贴(子级)",
"Exit": "退出", "Exit": "退出",
...@@ -173,6 +175,9 @@ ...@@ -173,6 +175,9 @@
"Import view success": "视图导入成功", "Import view success": "视图导入成功",
"Input projectx id": "请输入{envName}星速台项目ID", "Input projectx id": "请输入{envName}星速台项目ID",
"Save template to projectx": "是否保存皮肤到星速台", "Save template to projectx": "是否保存皮肤到星速台",
"All versions": "全部版本",
"Dependencies missing": "依赖缺失",
"missingDependenciesNotice": "<i class=\"el-icon-warning\"></i>依赖缺失,请到【<span style=\"font-weight: bold,\">详情>包管理</span>】进行安装",
"eventGroup": { "eventGroup": {
"in": "接收", "in": "接收",
"out": "派发" "out": "派发"
...@@ -296,8 +301,9 @@ ...@@ -296,8 +301,9 @@
"race": "负责最先" "race": "负责最先"
}, },
"dependenciesTypes": { "dependenciesTypes": {
"library": "运行时库",
"process": "过程库", "process": "过程库",
"custom": "模块库", "script": "脚本库",
"script": "脚本库" "custom": "模块库"
} }
} }
\ No newline at end of file
...@@ -4,13 +4,13 @@ import router from './router' ...@@ -4,13 +4,13 @@ import router from './router'
import store from './store/index' import store from './store/index'
import i18n from './i18n' import i18n from './i18n'
import './vue-resize' import './vue-resize'
import './time-format-plugin'
Vue.config.productionTip = false;
import './assets/style.css' import './assets/style.css'
import './plugins/element.js' import './plugins/element.js'
import './themes/light/index.scss' import './themes/light/index.scss'
Vue.config.productionTip = false;
import './token' import './token'
new Vue({ new Vue({
......
...@@ -12,10 +12,11 @@ import {arrayFind} from "element-ui/src/utils/util"; ...@@ -12,10 +12,11 @@ import {arrayFind} from "element-ui/src/utils/util";
export const behaviorStore = { export const behaviorStore = {
state: { state: {
data: {}, projectData: {},
processes: null,
originProcesses: null,
currentBehavior: null, currentBehavior: null,
processContext: [], processContext: [],
originData: null,
currentProcess: null, currentProcess: null,
processStack: [], processStack: [],
...@@ -27,33 +28,44 @@ export const behaviorStore = { ...@@ -27,33 +28,44 @@ export const behaviorStore = {
boardOffset: {x: 0, y: 0}, boardOffset: {x: 0, y: 0},
boardScale: 1, boardScale: 1,
}, },
dirty: false,
}, },
mutations: { mutations: {
makeBehaviorDirty(state){
state.dirty = true;
},
behavior_startEdit(state, {originData, behavior}) { behavior_startEdit(state, {originData, behavior}) {
state.originData = originData; state.dirty = false;
state.data = clonePureObj(originData); state.projectData = originData;
state.originProcesses = originData.processes;
state.processes = clonePureObj(originData.processes);
state.currentBehavior = clonePureObj(behavior); state.currentBehavior = clonePureObj(behavior);
this.commit('updateCustomProcesses', state.processes);
}, },
behavior_save(state) { behavior_save(state) {
state.originData.processes = state.data.processes; state.originProcesses.splice(0);
state.originProcesses.push(...state.processes);
}, },
addProcessMeta(state, meta) { addProcessMeta(state, meta) {
state.data.processes.push(meta); state.processes.push(meta);
this.commit('makeBehaviorDirty');
return process; return process;
}, },
updateProcesses(state, {targetMetaID, replaceMetaID}) { updateProcesses(state, {targetMetaID, replaceMetaID}) {
updateProcesses(state.data.processes, targetMetaID, replaceMetaID); updateProcesses(state.processes, targetMetaID, replaceMetaID);
}, },
deleteProcessMeta(state, {meta, process}) { deleteProcessMeta(state, {meta, process}) {
let container; let container;
if (meta.isInline) { if (meta.isInline) {
container = process.meta.metas; container = process.meta.metas;
} else { } else {
container = state.data.processes; container = state.processes;
} }
if (container) { if (container) {
deleteProcessMeta(meta.id, container); deleteProcessMeta(meta.id, container);
} }
this.commit('makeBehaviorDirty');
}, },
clearProcessStack(state) { clearProcessStack(state) {
state.processStack.splice(0); state.processStack.splice(0);
...@@ -83,14 +95,14 @@ export const behaviorStore = { ...@@ -83,14 +95,14 @@ export const behaviorStore = {
getters: { getters: {
customProcessMap: state => { customProcessMap: state => {
let map = {}; let map = {};
for (let process of state.data.processes) { for (let process of state.processes) {
map[process.id] = process; map[process.id] = process;
} }
return map; return map;
}, },
metaInUse: state => targetMetaID => { metaInUse: state => targetMetaID => {
let allMetasInUse = []; let allMetasInUse = [];
for (let process of state.data.processes) { for (let process of state.processes) {
let usedMetas = metaInUse(process, targetMetaID); let usedMetas = metaInUse(process, targetMetaID);
allMetasInUse.push(...usedMetas); allMetasInUse.push(...usedMetas);
/*if (usedMetas.length > 0) { /*if (usedMetas.length > 0) {
...@@ -102,7 +114,7 @@ export const behaviorStore = { ...@@ -102,7 +114,7 @@ export const behaviorStore = {
}, },
metaIDExists: state => id => { metaIDExists: state => id => {
let result = false; let result = false;
for (let process of state.data.processes) { for (let process of state.processes) {
if (process.id === id) { if (process.id === id) {
result = true; result = true;
break; break;
...@@ -111,14 +123,14 @@ export const behaviorStore = { ...@@ -111,14 +123,14 @@ export const behaviorStore = {
return result; return result;
}, },
behavior_getAssetByUUID: state => uuid => { behavior_getAssetByUUID: state => uuid => {
return state.data.assets.find(item => item.uuid === uuid); return state.projectData.assets.find(item => item.uuid === uuid);
}, },
behavior_views: state => { behavior_views: state => {
return state.data.views; return state.projectData.views;
}, },
behavior_searchViewNode: state => uuid => { behavior_searchViewNode: state => uuid => {
if(uuid){ if(uuid){
return searchViewNode(state.data.views, uuid); return searchViewNode(state.projectData.views, uuid);
} }
} }
}, },
...@@ -161,7 +173,7 @@ export const behaviorStore = { ...@@ -161,7 +173,7 @@ export const behaviorStore = {
return meta; return meta;
}, },
searchMeta({state}, {keyword}) { searchMeta({state}, {keyword}) {
searchMeta(state.data.processes, keyword); searchMeta(state.processes, keyword);
}, },
} }
}; };
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
import {envApi} from "../../api"; import {envApi} from "../../api";
import i18n from "../../i18n";
const storeKey = 'code-sync-serve-config'; const storeKey = 'code-sync-serve-config';
...@@ -41,51 +40,6 @@ export const editorStore = { ...@@ -41,51 +40,6 @@ export const editorStore = {
}, },
}, },
getters: { getters: {
prefabProcessTree: state => {
return groupProcesses(state.processes, process => process.isPrefab);
},
builtinProcessTree: state => {
const builtin = groupProcesses(state.processes, process => !process.isPrefab);
let tree = [
{
name: 'builtin',
children: builtin,
}
];
const dividerProcess = {
id: 'divider',
name: 'Divider',
desc: i18n.t('Divider node desc'),//'分流节点,出口会按顺序一次执行',
};
tree.unshift(dividerProcess);
const customProcess = {
id: 'custom',
name: 'Custom',
desc: i18n.t('Custom node desc'),//'自定义节点',
};
tree.unshift(customProcess);
tree.push({
name: 'trigger',
from: 'trigger',
children: [],
});
tree.push({
name: 'custom',
from: 'custom',
children: [],
});
return tree;
},
builtinsProcessMap: state => {
let map = {};
for (let process of state.processes) {
map[process.id] = process;
}
return map;
}
}, },
actions: { actions: {
async updateEnv({state, commit}) { async updateEnv({state, commit}) {
...@@ -96,19 +50,3 @@ export const editorStore = { ...@@ -96,19 +50,3 @@ export const editorStore = {
}, },
} }
}; };
function groupProcesses(processes, filterFunc) {
const result = [];
processes
.filter(filterFunc)
.forEach(process => {
const groupName = process.group || 'others';
let group = result.find(group => group.name === groupName);
if (!group) {
group = {name: groupName, children: []};
result.push(group);
}
group.children.push(process);
});
return result;
}
import db from "../../utils/db-storage";
import {packageApi} from "../../api";
import maxSatisfying from "semver/ranges/max-satisfying";
/** /**
* Created by rockyl on 2020-01-04. * Created by rockyl on 2020-01-04.
*/ */
export const typeMapping = [ import db from "../../utils/db-storage";
'', import {packageApi} from "../../api";
'process', import maxSatisfying from "semver/ranges/max-satisfying";
'custom', import i18n from "../../i18n";
'script', import events from "@/global-events.js"
]; import {timeFormat, typeMapping} from "../../utils";
const storeName = 'packages';
export const packageStore = { export const packageStore = {
state: { state: {
packageInfos: { packageInfos: {
library: [],
process: [], process: [],
custom: [], custom: [],
script: [], script: [],
}, },
packages: [], packages: {
library: {},
process: {},
custom: {},
script: {},
},
processTree: [],
triggerProcesses: [],
customProcesses: [],
}, },
mutations: { mutations: {
updatePackageInfos(state, packageInfos) { updatePackageInfos(state, packageInfos) {
for (let i = 1, li = typeMapping.length; i < li; i++) { for (let i = 0, li = typeMapping.length; i < li; i++) {
state.packageInfos[typeMapping[i]].splice(0); state.packageInfos[typeMapping[i]].splice(0);
} }
for (let packageInfo of packageInfos) { for (let packageInfo of packageInfos) {
packageInfo.versions = packageInfo.versions.split(','); packageInfo.versions = packageInfo.versions.split(',').reverse();
state.packageInfos[typeMapping[packageInfo.type]].push(packageInfo) packageInfo.remarks = packageInfo.remarks.split(',').reverse();
packageInfo.update_times = packageInfo.update_times.split(',').map(time => timeFormat(time)).reverse();
packageInfo.update_time = timeFormat(packageInfo.update_time);
state.packageInfos[typeMapping[packageInfo.type]].push(packageInfo);
} }
}, },
updatePackages(state, packages) { updatePackage(state, packageItem) {
state.packages = packages ? JSON.parse(packages) : []; let group = state.packages[typeMapping[packageItem.type]];
let pid = packageItem.package_id;
group[pid] = JSON.parse(packageItem.data);
},
updateProcessTree(state) {
let processes = this.getters.processPackages;
const prefabs = groupProcesses(processes, process => process.isPrefab);
const builtins = groupProcesses(processes, process => !process.isPrefab);
const normalsTree = [];
let tree = [
{
name: 'prefab',
children: prefabs,
},
{
name: 'normal',
children: normalsTree,
}
];
const dividerProcess = {
id: 'divider',
name: 'Divider',
desc: i18n.t('Divider node desc'),
};
normalsTree.push(dividerProcess);
const customProcess = {
id: 'custom',
name: 'Custom',
desc: i18n.t('Custom node desc'),
};
normalsTree.push(customProcess);
normalsTree.push({
name: 'builtin',
children: builtins,
});
normalsTree.push(state.triggerProcesses = {
name: 'trigger',
from: 'trigger',
children: [],
});
normalsTree.push(state.customProcesses = {
name: 'custom',
from: 'custom',
children: [],
});
state.processTree = tree;
},
updateCustomProcesses(state, processes) {
state.triggerProcesses.children = processes;
state.customProcesses.children = processes;
}, },
}, },
getters: { getters: {
getPackage: (state) => (packageId, version) => { processPackages: state => {
let packageVersions = state.packages[packageId]; return state.packages[typeMapping[1]];
if (packageVersions) { },
return packageVersions[version]; scriptPackages: state => {
} return state.packages[typeMapping[2]];
},
customPackages: state => {
return state.packages[typeMapping[3]];
},
processTree: state => {
return state.processTree;
} }
}, },
actions: { actions: {
async loadPackageInfos({state, commit}, id) { async loadPackageInfos({state, commit}) {
const packageInfos = await packageApi.fetchPackageInfos(); const packageInfos = await packageApi.fetchPackageInfos();
commit('updatePackageInfos', packageInfos); commit('updatePackageInfos', packageInfos);
console.log(packageInfos);
}, },
async loadPackages({state, commit, dispatch}, id) { getAllPackageMetas() {
dispatch('loadPackageInfos'); return db.getAll(storeName);
let packages = await db.get('packages', id);
commit('updatePackages', packages);
}, },
async applyModifyDependencies({state, commit, getters}, dependencies) { async downloadDependencies({state, commit, getters, dispatch}, dependencies) {
let schema = {}; let schema = {};
let packageMetas = await db.getAll(storeName);
for (let packageId in dependencies) { for (let packageId in dependencies) {
let version = dependencies[packageId]; let version = dependencies[packageId];
let packageData = getters.getPackage(packageId, version); let exists = packageExists(packageMetas, packageId, version);
if (!packageData) { if (!exists) {
schema[packageId] = version; schema[packageId] = version;
} }
} }
if (Object.keys(schema).length > 0) { if (Object.keys(schema).length > 0) {
console.log(schema); let packages = await packageApi.fetchPackages(schema);
await packageApi.fetchPackages(schema); for (let packageItem of packages) {
let versions = await db.get(storeName, packageItem.package_id);
if (!versions) {
versions = {
id: packageItem.package_id,
type: packageItem.type,
};
}
versions[packageItem.version] = packageItem;
db.put(storeName, versions);
}
}
},
async applyDependencies({commit}, dependencies) {
let missings = [];
for (let packageId in dependencies) {
let version = dependencies[packageId];
let versions = await db.get(storeName, packageId);
if (versions) {
if (versions[version]) {
commit('updatePackage', versions[version]);
} else {
missings.push({
packageId,
version,
})
}
} else {
missings.push({
packageId,
version,
})
}
} }
commit('updateProcessTree');
if (missings.length > 0) {
setTimeout(function () {
events.$emit('show-missing-packages', missings);
}, 500);
}
return missings;
},
async fillLastVersion({dispatch, state, getters}) {
const dependencies = getters.dependencies;
for (let group in state.packageInfos) {
for (let packageInfo of state.packageInfos[group]) {
const {package_id, versions} = packageInfo;
if (!dependencies[package_id]) {
dependencies[package_id] = maxSatisfying(versions, '*');
}
}
}
await dispatch('applyDependencies', dependencies);
} }
}, },
}; };
export function fillLastVersion(dependencies, packageInfos) { export function packageExists(packageMetas, packageId, version) {
for (let group in packageInfos) { let exists;
for (let packageInfo of packageInfos[group]) { let versions = packageMetas.find(item => item.id === packageId);
const {package_id, versions} = packageInfo; if (versions) {
if (!dependencies[package_id]) { exists = versions[version];
dependencies[package_id] = maxSatisfying(versions, '*'); }
return exists;
}
function groupProcesses(processes, filterFunc) {
const result = [];
for (let pid in processes) {
let process = processes[pid];
if (filterFunc(process)) {
const groupName = process.group || 'others';
let group = result.find(group => group.name === groupName);
if (!group) {
group = {name: groupName, children: []};
result.push(group);
} }
group.children.push(process);
} }
} }
return result;
} }
...@@ -153,7 +153,7 @@ export const projectStore = { ...@@ -153,7 +153,7 @@ export const projectStore = {
Vue.set(localData, 'dependencies', {}); Vue.set(localData, 'dependencies', {});
} }
fillLastVersion(state.data.dependencies, state.package.packageInfos); this.dispatch('fillLastVersion');
state.mockServeEnabled = getMockServeEnabled(id); state.mockServeEnabled = getMockServeEnabled(id);
updateMock(localData.mock); updateMock(localData.mock);
...@@ -481,6 +481,9 @@ export const projectStore = { ...@@ -481,6 +481,9 @@ export const projectStore = {
options(state) { options(state) {
return state.data.options; return state.data.options;
}, },
envKeys(state) {
return state.data.options.env.map(item => item.name);
},
/** /**
* 当前激活的组件 * 当前激活的组件
*/ */
...@@ -532,6 +535,9 @@ export const projectStore = { ...@@ -532,6 +535,9 @@ export const projectStore = {
getProcess: state => behavior => { getProcess: state => behavior => {
return findProcess(behavior.meta, state.data.processes); return findProcess(behavior.meta, state.data.processes);
}, },
dependencies(state) {
return state.data.dependencies;
},
}, },
actions: { actions: {
async saveToLocal({getters, commit}) { async saveToLocal({getters, commit}) {
...@@ -547,7 +553,7 @@ export const projectStore = { ...@@ -547,7 +553,7 @@ export const projectStore = {
return !!json; return !!json;
}, },
async loadFromLocal({commit, dispatch}, projectID) { async loadFromLocal({commit, dispatch}, projectID) {
await dispatch('loadPackages', projectID); await dispatch('loadPackageInfos');
let json = await db.get(storeName, projectID); let json = await db.get(storeName, projectID);
//let json = localStorage.getItem('project-' + projectID); //let json = localStorage.getItem('project-' + projectID);
if (json) { if (json) {
...@@ -562,7 +568,7 @@ export const projectStore = { ...@@ -562,7 +568,7 @@ export const projectStore = {
commit('setDirty', false); commit('setDirty', false);
}, },
async loadFromRemote({commit, dispatch}, projectID) { async loadFromRemote({commit, dispatch}, projectID) {
await dispatch('loadPackages', projectID); await dispatch('loadPackageInfos');
const project = await projectApi.fetchOne(projectID); const project = await projectApi.fetchOne(projectID);
if (project) { if (project) {
dispatch('deleteLocalVersion', projectID); dispatch('deleteLocalVersion', projectID);
...@@ -572,7 +578,7 @@ export const projectStore = { ...@@ -572,7 +578,7 @@ export const projectStore = {
} }
}, },
async loadFromDataUrl({commit, dispatch}, {project, dataUrl}) { async loadFromDataUrl({commit, dispatch}, {project, dataUrl}) {
await dispatch('loadPackages', project.id); await dispatch('loadPackageInfos');
const projectData = await projectApi.fetchOneFromDataUrl(dataUrl); const projectData = await projectApi.fetchOneFromDataUrl(dataUrl);
if (projectData) { if (projectData) {
project.data = projectData; project.data = projectData;
...@@ -590,12 +596,6 @@ export const projectStore = { ...@@ -590,12 +596,6 @@ export const projectStore = {
const project = await projectApi.getData(projectID); const project = await projectApi.getData(projectID);
commit('updateProject', project); commit('updateProject', project);
}, },
async resolveDependencies({state}) {
for (let key in state.data.dependencies) {
let version = state.data.dependencies[key];
}
},
/** /**
* 选中节点 * 选中节点
...@@ -755,7 +755,7 @@ export const projectStore = { ...@@ -755,7 +755,7 @@ export const projectStore = {
savePreview({state, rootState, getters}) { savePreview({state, rootState, getters}) {
const {project} = getters; const {project} = getters;
const {processes, scripts, customs} = rootState.editor; const packages = state.package.packages;
/*const data = { /*const data = {
processes, scripts, customs, processes, scripts, customs,
data: state.data, data: state.data,
...@@ -763,7 +763,7 @@ export const projectStore = { ...@@ -763,7 +763,7 @@ export const projectStore = {
localStorage.setItem('preview-project-' + project.id, JSON.stringify(data)); localStorage.setItem('preview-project-' + project.id, JSON.stringify(data));
localStorage.setItem('preview-ts', Date.now().toString());*/ localStorage.setItem('preview-ts', Date.now().toString());*/
preprocess(project, state.data, clonePureObj(processes), clonePureObj(scripts), clonePureObj(customs)) preprocess(project, state.data, clonePureObj(packages));
}, },
addBehaviorDirect({state}, {behaviors, alias}) { addBehaviorDirect({state}, {behaviors, alias}) {
......
...@@ -324,7 +324,6 @@ $dock-pin-width: 9px; ...@@ -324,7 +324,6 @@ $dock-pin-width: 9px;
} }
.meta-editor-wrapper { .meta-editor-wrapper {
//height: 40vh;
display: flex; display: flex;
height: 100%; height: 100%;
padding: 5px; padding: 5px;
...@@ -337,15 +336,6 @@ $dock-pin-width: 9px; ...@@ -337,15 +336,6 @@ $dock-pin-width: 9px;
.script-editor { .script-editor {
flex: 1; flex: 1;
} }
.vue-codemirror {
flex: 1;
height: 0;
}
.CodeMirror {
height: 100%;
}
} }
.props-editor-dialog { .props-editor-dialog {
......
...@@ -93,13 +93,52 @@ ...@@ -93,13 +93,52 @@
} }
.package-manager { .package-manager {
.item{ .item {
border-bottom: 1px solid $--border-color-base; border-bottom: 1px solid $--border-color-base;
padding-bottom: 5px; padding-bottom: 5px;
.update-time{ .update-time {
margin-right: 5px; margin-right: 5px;
} }
.version-select {
//width: 80px;
}
}
}
.package-version-list {
padding-right: 10px;
.item {
border-bottom: 1px solid $--border-color-base;
padding: 2px;
.use-checkbox{
margin-right: 5px;
}
.version {
font-weight: bold;
float: left;
}
.update-time {
float: right;
}
}
}
.version-select-popover {
.version-label {
float: left;
}
.version-notice {
float: right;
color: $--color-warning;
font-size: 13px;
} }
} }
...@@ -129,13 +168,29 @@ ...@@ -129,13 +168,29 @@
} }
} }
.project-editor { .project-scrollbar {
height: 100%; height: 100%;
display: flex;
flex-direction: column;
.project-scrollbar { .project-editor {
flex: 1; height: 100%;
form {
height: 100%;
display: flex;
flex-direction: column;
.tpl-editor {
flex: 1;
.el-form-item__content {
height: 100%;
.editor {
height: 100%;
}
}
}
}
} }
} }
...@@ -174,6 +229,10 @@ ...@@ -174,6 +229,10 @@
.mock-table { .mock-table {
flex: 1; flex: 1;
} }
.editor {
height: 300px;
}
} }
} }
...@@ -225,3 +284,16 @@ ...@@ -225,3 +284,16 @@
} }
} }
} }
.missing-packages-dialog {
.wrapper {
height: 50vh;
display: flex;
flex-direction: column;
.list {
flex: 1;
height: 0;
}
}
}
/**
* Created by rockyl on 2020-02-20.
*/
import Vue from 'vue'
import {timeFormat} from "./utils";
Vue.use(function () {
Vue.prototype.$timeFormat = function(time, format){
return timeFormat(time, format);
}
});
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Created by rockyl on 2019-12-18. * Created by rockyl on 2019-12-18.
*/ */
const version = 4; const version = 5;
const storeConfigs = [ const storeConfigs = [
{name: 'project', key: 'id'}, {name: 'project', key: 'id'},
{name: 'mock', key: 'path'}, {name: 'mock', key: 'path'},
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import {Message, Loading} from "element-ui"; import {Message, Loading} from "element-ui";
import i18n from '../i18n' import i18n from '../i18n'
import generateUUID from "uuid/v4"; import generateUUID from "uuid/v4";
import moment from "moment";
/** /**
* 动态数据图标映射 * 动态数据图标映射
...@@ -18,6 +19,13 @@ export const dynamicIconMapping = { ...@@ -18,6 +19,13 @@ export const dynamicIconMapping = {
'env': 'E', 'env': 'E',
}; };
export const typeMapping = [
'library',
'process',
'script',
'custom',
];
/** /**
* 节点方案 * 节点方案
* @type {string} * @type {string}
...@@ -309,3 +317,7 @@ export function getViewNodePath(node, sep = '/') { ...@@ -309,3 +317,7 @@ export function getViewNodePath(node, sep = '/') {
} }
return segs.join(sep) return segs.join(sep)
} }
export function timeFormat(time, format = 'YYYY-MM-DD HH:mm:ss'){
return moment(time).format(format)
}
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
<pack-result-dialog ref="packResultDialog"/> <pack-result-dialog ref="packResultDialog"/>
<mock-editor-dialog ref="mockEditorDialog"/> <mock-editor-dialog ref="mockEditorDialog"/>
<code-sync-serve-dialog ref="codeSyncServeDialog"/> <code-sync-serve-dialog ref="codeSyncServeDialog"/>
<missing-packages-dialog ref="missingPackagesDialog"/>
</div> </div>
</template> </template>
...@@ -37,11 +38,12 @@ ...@@ -37,11 +38,12 @@
import {startCodeSyncServe} from "../code-sync-serve"; import {startCodeSyncServe} from "../code-sync-serve";
import BottomBar from "./Editor/BottomBar"; import BottomBar from "./Editor/BottomBar";
import CodeSyncServeDialog from "./Editor/dialogs/CodeSyncServeDialog"; import CodeSyncServeDialog from "./Editor/dialogs/CodeSyncServeDialog";
import MissingPackagesDialog from "./Editor/dialogs/MissingPackagesDialog";
export default { export default {
name: 'Editor', name: 'Editor',
components: { components: {
MissingPackagesDialog,
CodeSyncServeDialog, CodeSyncServeDialog,
BottomBar, BottomBar,
MockEditorDialog, MockEditorDialog,
...@@ -82,6 +84,7 @@ ...@@ -82,6 +84,7 @@
events.$on('save-and-preview', () => { events.$on('save-and-preview', () => {
this.clickMenu("preview"); this.clickMenu("preview");
}); });
events.$on('show-missing-packages', this.showMissingPackages);
events.$on('show-code-sync-serve-dialog', () => { events.$on('show-code-sync-serve-dialog', () => {
this.$refs.codeSyncServeDialog.show(); this.$refs.codeSyncServeDialog.show();
...@@ -90,7 +93,7 @@ ...@@ -90,7 +93,7 @@
await playWaiting(this.prepare(), this.$t('Preparing')).catch(e => { await playWaiting(this.prepare(), this.$t('Preparing')).catch(e => {
console.log(e); console.log(e);
}); });
if(this.codeSyncServeConfig.autoLaunch){ if (this.codeSyncServeConfig.autoLaunch) {
setTimeout(() => { setTimeout(() => {
startCodeSyncServe(this.codeSyncServeConfig); startCodeSyncServe(this.codeSyncServeConfig);
}, 100); }, 100);
...@@ -101,7 +104,8 @@ ...@@ -101,7 +104,8 @@
}); });
}, },
destroyed() { destroyed() {
document.removeEventListener('keydown', this.onKeyPress) document.removeEventListener('keydown', this.onKeyPress);
events.$off('show-missing-packages', this.showMissingPackages);
}, },
methods: { methods: {
...@@ -258,7 +262,7 @@ ...@@ -258,7 +262,7 @@
if (!debug) { if (!debug) {
cancel = await this.saveProject(false); cancel = await this.saveProject(false);
} }
if(cancel){ if (cancel) {
return; return;
} }
const loading = this.$loading({ const loading = this.$loading({
...@@ -313,6 +317,9 @@ ...@@ -313,6 +317,9 @@
window.open(previewUrl.href, 'blank'); window.open(previewUrl.href, 'blank');
}, 300); }, 300);
}, },
showMissingPackages(missingPackages) {
this.$refs.missingPackagesDialog.show(missingPackages);
},
...mapActions([ ...mapActions([
'loadPackages', 'loadPackages',
'localVersionExist', 'localVersionExist',
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<el-dropdown trigger="click" @command="handleAddScript" placement="top" size="small"> <el-dropdown trigger="click" @command="handleAddScript" placement="top" size="small">
<el-button size="mini">{{$t('Add')}}</el-button> <el-button size="mini">{{$t('Add')}}</el-button>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(script, key) of scripts" :command="script.id" :key="key">{{script.name}}</el-dropdown-item> <el-dropdown-item v-for="(script, key) of scriptPackages" :command="script.id" :key="key">{{script.name}}</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
...@@ -76,11 +76,9 @@ export default { ...@@ -76,11 +76,9 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList']), ...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList', 'scriptPackages']),
...mapState({ ...mapState({
scripts(state){
return state.editor.scripts;
}
}), }),
}, },
methods: { methods: {
...@@ -88,7 +86,7 @@ export default { ...@@ -88,7 +86,7 @@ export default {
* 脚本预设对象选中 * 脚本预设对象选中
*/ */
handleAddScript(command) { handleAddScript(command) {
console.log('handleAddScript', command); //console.log('handleAddScript', command);
this.$store.dispatch('addNodeScript', command); this.$store.dispatch('addNodeScript', command);
}, },
/** /**
...@@ -140,11 +138,11 @@ export default { ...@@ -140,11 +138,11 @@ export default {
return scriptTypeMap[_type].component; return scriptTypeMap[_type].component;
}, },
getScriptName(id) { getScriptName(id) {
let _script = this.scripts.find(script => script.id === id); let _script = this.scriptPackages[id];
return _script ? _script.name : ''; return _script ? _script.name : '';
}, },
getScriptOptions(id) { getScriptOptions(id) {
let _script = this.scripts.find(script => script.id === id); let _script = this.scriptPackages[id];
return _script ? _script.props : {}; return _script ? _script.props : {};
}, },
/** /**
......
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
<div class="behavior"> <div class="behavior">
<split-panes> <split-panes>
<split-panes splitpanes-min="10" :splitpanes-size="10" horizontal> <split-panes splitpanes-min="10" :splitpanes-size="10" horizontal>
<process-list @edit-meta="onEditMeta" @delete-meta="onDeleteMeta" :data="prefabProcessTree" <process-list @edit-meta="onEditMeta" @delete-meta="onDeleteMeta" :data="processTree[0].children"
class="background full-size" splitpanes-min="20" class="background full-size" splitpanes-min="20"
:splitpanes-size="20"/> :splitpanes-size="20"/>
<process-list @edit-meta="onEditMeta" @delete-meta="onDeleteMeta" :data="normalProcessTree" <process-list @edit-meta="onEditMeta" @delete-meta="onDeleteMeta" :data="processTree[1].children"
class="background full-size" splitpanes-min="20" class="background full-size" splitpanes-min="20"
:splitpanes-size="80"/> :splitpanes-size="80"/>
</split-panes> </split-panes>
...@@ -44,7 +44,6 @@ ...@@ -44,7 +44,6 @@
import events from "@/global-events.js" import events from "@/global-events.js"
import MetaSearchDialog from "./MetaSearchDialog"; import MetaSearchDialog from "./MetaSearchDialog";
export default { export default {
name: "BehaviorEditor", name: "BehaviorEditor",
components: {MetaSearchDialog, MetaEditorDialog, PropertiesEditor, EditPath, ProcessList, Board, SplitPanes,}, components: {MetaSearchDialog, MetaEditorDialog, PropertiesEditor, EditPath, ProcessList, Board, SplitPanes,},
...@@ -56,27 +55,18 @@ ...@@ -56,27 +55,18 @@
}, },
computed: { computed: {
processContext() { processContext() {
const {builtinsProcessMap, customProcessMap} = this.$store.getters; const {processPackages, customProcessMap} = this.$store.getters;
return [ return [
builtinsProcessMap, processPackages,
customProcessMap, customProcessMap,
] ]
}, },
normalProcessTree() {
const tree = this.builtinProcessTree;
const customGroup = tree.find(item => item.name === 'custom');
customGroup.children = this.$store.state.behavior.data.processes;
const triggerGroup = tree.find(item => item.name === 'trigger');
triggerGroup.children = this.$store.state.behavior.data.processes;
return tree;
},
...mapState({ ...mapState({
behavior: state => state.behavior.currentBehavior, behavior: state => state.behavior.currentBehavior,
processStack: state=>state.behavior.processStack, processStack: state=>state.behavior.processStack,
}), }),
...mapGetters([ ...mapGetters([
'prefabProcessTree', 'processTree',
'builtinProcessTree',
]), ]),
}, },
methods: { methods: {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
@down-pin="onPinDown" @down-pin="onPinDown"
@delete="onProcessNodeDelete" @delete="onProcessNodeDelete"
@copy="onProcessNodeCopy" @copy="onProcessNodeCopy"
@change-position="onProcessNodeMove"
@edit-meta="onEditMeta" @edit-meta="onEditMeta"
@dblclick="editSubProcess(process)" @dblclick="editSubProcess(process)"
@meta-modified="onProcessMetaModified" @meta-modified="onProcessMetaModified"
...@@ -89,6 +90,7 @@ ...@@ -89,6 +90,7 @@
...mapMutations([ ...mapMutations([
'deleteProcessMeta', 'deleteProcessMeta',
'setScale', 'setScale',
'makeBehaviorDirty',
]), ]),
async edit(process, resolveProcess) { async edit(process, resolveProcess) {
this.boardOffset.x = 0; this.boardOffset.x = 0;
...@@ -119,8 +121,6 @@ ...@@ -119,8 +121,6 @@
this.$set(this.subProcessMap, uuid, process); this.$set(this.subProcessMap, uuid, process);
} else { } else {
console.log('节点丢失:', uuid); console.log('节点丢失:', uuid);
} }
}, },
showInlineChoose() { showInlineChoose() {
...@@ -164,6 +164,7 @@ ...@@ -164,6 +164,7 @@
this.$set(this.process.meta, 'sub', {}); this.$set(this.process.meta, 'sub', {});
} }
this.$set(this.process.meta.sub, data.uuid, data); this.$set(this.process.meta.sub, data.uuid, data);
this.makeBehaviorDirty();
return data; return data;
}, },
onDragOver(e) { onDragOver(e) {
...@@ -215,6 +216,7 @@ ...@@ -215,6 +216,7 @@
this.$nextTick(() => { this.$nextTick(() => {
events.$emit('update-dock-pin-pos'); events.$emit('update-dock-pin-pos');
}); });
this.makeBehaviorDirty();
}, },
onResize() { onResize() {
const {x, y} = this.$el.getBoundingClientRect(); const {x, y} = this.$el.getBoundingClientRect();
...@@ -305,12 +307,14 @@ ...@@ -305,12 +307,14 @@
this.addLine(this.processDrawing, this.drawState.targetUUID, this.pointDrawing, 0); this.addLine(this.processDrawing, this.drawState.targetUUID, this.pointDrawing, 0);
this.drawState.targetUUID = null; this.drawState.targetUUID = null;
this.makeBehaviorDirty();
} }
}, },
onDeleteLine(line) { onDeleteLine(line) {
const {prev, outputType, outputIndex, id} = line; const {prev, outputType, outputIndex, id} = line;
prev.output[outputType].splice(outputIndex, 1); prev.output[outputType].splice(outputIndex, 1);
this.$delete(this.lines, id); this.$delete(this.lines, id);
this.makeBehaviorDirty();
}, },
onProcessNodeDelete(process, meta) { onProcessNodeDelete(process, meta) {
this.$delete(this.subProcessMap, process.uuid); this.$delete(this.subProcessMap, process.uuid);
...@@ -341,6 +345,7 @@ ...@@ -341,6 +345,7 @@
}); });
} }
} }
this.makeBehaviorDirty();
}, },
onProcessNodeCopy(data, meta) { onProcessNodeCopy(data, meta) {
if (meta.isInline) { //内联直接复制 if (meta.isInline) { //内联直接复制
...@@ -356,6 +361,9 @@ ...@@ -356,6 +361,9 @@
}); });
} }
}, },
onProcessNodeMove(data){
this.makeBehaviorDirty();
},
onEditMeta(data, meta) { onEditMeta(data, meta) {
this.$emit('edit-meta', meta); this.$emit('edit-meta', meta);
}, },
...@@ -377,6 +385,7 @@ ...@@ -377,6 +385,7 @@
} }
} }
} }
this.makeBehaviorDirty();
}, },
onClickProcessNode(process, uuid) { onClickProcessNode(process, uuid) {
for (let key in this.$refs) { for (let key in this.$refs) {
......
<template>
<codemirror ref="codeEditor"
:value="value"
:options="cmOptions"
@input="onChange"
@inputRead="inputRead"/>
</template>
<script>
import {codemirror} from "vue-codemirror";
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/ayu-mirage.css'
import 'codemirror/addon/edit/closebrackets.js'
import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/lint/lint.js'
import 'codemirror/addon/lint/lint.css'
import 'codemirror/addon/lint/javascript-lint.js'
import 'codemirror/addon/search/searchcursor.js'
import 'codemirror/addon/search/search.js'
import 'codemirror/addon/search/jump-to-line.js'
import 'codemirror/addon/dialog/dialog.js'
import 'codemirror/addon/dialog/dialog.css'
import '../../../utils/javascript-hint.js'
export default {
name: "CodeEditor",
components: {codemirror},
data(){
return {
cmOptions: {
tabSize: 2,
styleActiveLine: true,
theme: 'ayu-mirage',
line: true,
matchBrackets: true,
autoCloseBrackets: true,
extraKeys: {
"Alt-Space": "autocomplete",
},
lineNumbers: true,
mode: {name: 'javascript', globalVars: true},
gutters: ["CodeMirror-lint-markers"],
lint: {
esversion: 6
},
keyword: {
caseInsensitive: true,
}
}
}
},
props: {
value: {
type: String,
default: '',
}
},
methods:{
inputRead(codemirror) {
if (codemirror.state.completionActive) {
return;
}
let cur = codemirror.getCursor();
let token = codemirror.getTokenAt(cur);
let string = '';
if (token.string.match(/^[.`\w@]\w*$/)) {
string = token.string;
}
if (string.length > 0) {
codemirror.showHint({ completeSingle: false });
}
},
onChange(v){
this.$emit('input', v);
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
...@@ -90,22 +90,7 @@ ...@@ -90,22 +90,7 @@
item item
}}</el-tag> }}</el-tag>
</div> </div>
<!--<el-input v-if="meta" class="script-editor" :readonly=" !editable" type="textarea" :placeholder="$t('Code')" <process-script-editor v-if="meta" :meta="meta"/>
v-model="meta.script"></el-input>-->
<!-- <codemirror
ref="codeEditor"
v-if="meta"
v-model="meta.script"
:options="cmOptions"
@cursorActivity="onCodeChange"
/>-->
<monaco-editor
ref="codeEditor"
v-if="meta"
:code="meta.script"
:options="monacoConfig"
/>
<!-- <code-editor v-if="meta" v-model="meta.script" /> -->
</div> </div>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<div> <div>
...@@ -132,23 +117,21 @@ ...@@ -132,23 +117,21 @@
</template> </template>
<script> <script>
import PropsEditorDialog from "./PropsEditorDialog"; import PropsEditorDialog from "./PropsEditorDialog";
import MonacoEditor from "../components/MonacoEditor"; import copy from "copy-to-clipboard";
import copy from "copy-to-clipboard"; import {clonePureObj} from "../../../utils";
import { clonePureObj } from "../../../utils"; import events from "../../../global-events";
import events from "../../../global-events"; import CodeSyncIndicator from "../BottomBar/CodeSyncIndicator";
import CodeSyncIndicator from "../BottomBar/CodeSyncIndicator"; import ProcessScriptEditor from "./ProcessScriptEditor";
import CodeEditor from "./CodeEditor";
const exposeVariables = ["args", "props", "target", "global", "vm", "engine", 'scope']; const exposeVariables = ["args", "props", "target", "global", "vm", "engine", 'scope'];
export default { export default {
name: "MetaEditorDialog", name: "MetaEditorDialog",
components: { components: {
CodeEditor, ProcessScriptEditor,
CodeSyncIndicator, CodeSyncIndicator,
PropsEditorDialog, PropsEditorDialog,
"monaco-editor": MonacoEditor
}, },
data() { data() {
return { return {
...@@ -161,25 +144,6 @@ export default { ...@@ -161,25 +144,6 @@ export default {
id: [{ required: true, trigger: "blur" }], id: [{ required: true, trigger: "blur" }],
name: [{ required: true, trigger: "blur" }] name: [{ required: true, trigger: "blur" }]
}, },
cmOptions: {
tabSize: 2,
styleActiveLine: true,
theme: "default",
line: true,
matchBrackets: true,
autoCloseBrackets: true,
extraKeys: {
"Alt-Space": "autocomplete"
},
lineNumbers: true,
mode: { name: "javascript", globalVars: true },
gutters: ["CodeMirror-lint-markers"],
lint: true
},
monacoConfig: {
language: "javascript"
}
}; };
}, },
mounted() { mounted() {
...@@ -222,10 +186,8 @@ export default { ...@@ -222,10 +186,8 @@ export default {
this.$t("Alert") this.$t("Alert")
).catch(e => {}); ).catch(e => {});
} else { } else {
this.meta.script = this.$refs.codeEditor.editor.getValue();
this.$emit("input", this.meta, isPreview); this.$emit("input", this.meta, isPreview);
this.visible = false; this.visible = false;
this.meta = null;
} }
} else { } else {
return false; return false;
...@@ -234,7 +196,6 @@ export default { ...@@ -234,7 +196,6 @@ export default {
}, },
cancel() { cancel() {
this.visible = false; this.visible = false;
this.meta = null;
}, },
copyMeta() { copyMeta() {
copy(JSON.stringify(this.meta)); copy(JSON.stringify(this.meta));
...@@ -246,8 +207,7 @@ export default { ...@@ -246,8 +207,7 @@ export default {
let metaStr = e.clipboardData.getData("Text"); let metaStr = e.clipboardData.getData("Text");
if (metaStr) { if (metaStr) {
try { try {
let meta = JSON.parse(metaStr); this.meta = JSON.parse(metaStr);
this.meta = meta;
} catch (e) {} } catch (e) {}
} }
}, },
......
<template>
<monaco-editor
class="script-editor"
ref="editor"
v-model="meta.script"
language="javascript"
:options="monacoConfig"
@editorWillMount="editorWillMount"
/>
</template>
<script>
import MonacoEditor from "vue-monaco";
const typesUrl = [
"http://yun.duiba.com.cn/editor/zeroing/types/types.v2.d.ts",
"http://yun.duiba.com.cn/editor/zeroing/types/process-context.v8.d.ts",
];
let types;
const metaDtsTpl =
`declare function next(type: $OUTPUT_TYPES$, payload?: any);
declare interface ProcessProps {
$PROPS_TYPES$
}
declare interface EnvProps {
$ENV_PROPS$
}
`;
export default {
name: "ProcessScriptEditor",
components: {
MonacoEditor,
},
props: ['meta'],
data() {
return {
monacoConfig: {},
}
},
mounted() {
this.updateMetaDts();
},
watch: {
meta(v) {
this.updateMetaDts();
},
},
methods: {
async editorWillMount(monaco) {
this.monaco = monaco;
if (!types) {
types = (await Promise.all(typesUrl.map(async url => {
const res = await fetch(url);
return res.text();
}))).join("\n");
this.monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES6,
allowNonTsExtensions: true,
allowJs: true
});
this.monaco.languages.typescript.javascriptDefaults.addExtraLib(types);
this.updateMetaDts();
}
},
updateMetaDts() {
if (!types) {
return;
}
let meta = this.meta;
let outputTypes = meta.output.map(item => `'${item}'`).join('|');
let envKeys = this.$store.getters.envKeys;
let props = [];
for (let key in meta.props) {
let propConfig = meta.props[key];
let propType = 'string';
switch(propConfig.type){
case 'boolean':
case 'number':
propType = propConfig.type;
break;
case 'dynamic':
case 'map':
propType = 'any';
break;
case 'node':
propType = 'NodeClass';
break;
case 'enum':
propType = '{' + propConfig.enum.join(',') + '}';
break;
}
props.push(key + ':' + propType + ';');
}
let metaDts = metaDtsTpl
.replace('$OUTPUT_TYPES$', outputTypes)
.replace('$PROPS_TYPES$', props.join('\n'))
.replace('$ENV_PROPS$', envKeys.join('\n'))
console.log(metaDts);
this.monaco.languages.typescript.javascriptDefaults.addExtraLib(metaDts, 'meta.d.ts');
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div id="container"></div>
</template>
<script>
import * as monaco from "monaco-editor";
const typesUrl = [
"http://yun.duiba.com.cn/editor/zeroing/types/types.d.ts",
"http://yun.duiba.com.cn/editor/zeroing/types/process-context.v4.d.ts",
];
export default {
name: "MonacoEditor",
props: {
options: Object,
code: String
},
async mounted() {
const {options, code} = this;
const types = await Promise.all(typesUrl.map(async url => {
const res = await fetch(url);
return res.text();
}));
const defaultConfig = {
language: "javascript",
value: "",
minimap: {
enabled: false
}
};
// compiler options
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES6,
allowNonTsExtensions: true,
allowJs: true
});
// extra libraries
monaco.languages.typescript.javascriptDefaults.addExtraLib(
types.join("\n")
);
const config = Object.assign({}, defaultConfig, options, {value: code});
this.editor = monaco.editor.create(
document.getElementById("container"),
config
);
},
destroyed() {
this.editor.dispose();
}
};
</script>
<style lang="scss" scoped>
#container {
width: 100%;
height: 100%;
}
</style>
...@@ -6,8 +6,11 @@ ...@@ -6,8 +6,11 @@
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<div></div> <div></div>
<div> <div>
<el-button size="mini" @click="onSave(true)">{{$t('Save And Preview')}}</el-button> <!--<el-button size="mini" @click="onSave(true)">{{$t('Save And Preview')}}</el-button>
<el-button size="mini" type="primary" @click="onSave(false)">{{$t('Save And Close')}}</el-button> <el-button size="mini" type="primary" @click="onSave(false)">{{$t('Save And Close')}}</el-button>-->
<el-badge :hidden="!showBadge" is-dot>
<el-button size="mini" type="primary" @click="onSave()">{{$t('Save')}}</el-button>
</el-badge>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
...@@ -30,7 +33,7 @@ ...@@ -30,7 +33,7 @@
computed: { computed: {
...mapState({ ...mapState({
data: state => state.project.data, data: state => state.project.data,
showBadge: state => state.behavior.dirty,
}), }),
}, },
created() { created() {
...@@ -63,20 +66,29 @@ ...@@ -63,20 +66,29 @@
} }
}, },
beforeClose(done) { beforeClose(done) {
this.$confirm(this.$t('Save this behavior before'), this.$t('Alert'), { if (this.$store.state.behavior.dirty) {
showClose: false, this.$confirm(this.$t('Save this behavior before'), this.$t('Alert'), {
closeOnClickModal: false, closeOnClickModal: false,
closeOnPressEscape: false, closeOnPressEscape: false,
confirmButtonText: this.$t('Confirm'), confirmButtonText: this.$t('Save And Close'),
cancelButtonText: this.$t('Still Close'), cancelButtonText: this.$t('Still Close'),
type: 'warning' distinguishCancelAndClose: true,
}).then(() => { type: 'warning'
this.onSave(); }).then(() => {
done(); this.onSave();
}).catch((e) => { done();
this.$emit('cancel'); }).catch((action) => {
switch (action) {
case 'close':
break;
case 'cancel':
done();
break;
}
});
} else {
done(); done();
}); }
}, },
onOpened() { onOpened() {
this.editorReady = true; this.editorReady = true;
......
...@@ -6,24 +6,24 @@ ...@@ -6,24 +6,24 @@
fullscreen fullscreen
custom-class="flex-dialog details-dialog" custom-class="flex-dialog details-dialog"
> >
<el-tabs v-model="activeName" class="tabs"> <el-tabs v-model="activeName" class="tabs" @tab-click="onClickTab">
<el-tab-pane :label="$t('Project')" name="project"> <el-tab-pane :label="$t('Project')" name="projectEditor">
<project-editor ref="projectEditor"/> <project-editor ref="projectEditor"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('Env constant')" name="env"> <el-tab-pane :label="$t('Env constant')" name="envEditor">
<env-editor ref="envEditor"/> <env-editor ref="envEditor"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('Data mapping')" name="data-mapping"> <el-tab-pane :label="$t('Data mapping')" name="dataMappingEditor">
<data-mapping-editor ref="dataMappingEditor"/> <data-mapping-editor ref="dataMappingEditor"/>
</el-tab-pane> </el-tab-pane>
<!--<el-tab-pane :label="$t('Custom module')" name="custom"> <el-tab-pane :label="$t('Custom module')" name="customModuleEditor">
<custom-module-editor ref="customModuleEditor"/> <custom-module-editor ref="customModuleEditor"/>
</el-tab-pane>--> </el-tab-pane>
<el-tab-pane :label="$t('Package manager')" name="package-manager"> <el-tab-pane :label="$t('Package manager')" name="packageManager">
<package-manager-editor ref="packageManager"/> <package-manager-editor ref="packageManager"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('Projectx config')" name="projectx"> <el-tab-pane :label="$t('Projectx config')" name="projectxConfig">
<projectx-config ref="projectxConfig" /> <projectx-config ref="projectxConfig"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
'projectEditor', 'projectEditor',
'envEditor', 'envEditor',
'dataMappingEditor', 'dataMappingEditor',
//'customModuleEditor', 'customModuleEditor',
'packageManager', 'packageManager',
'projectxConfig', 'projectxConfig',
]; ];
...@@ -58,11 +58,12 @@ ...@@ -58,11 +58,12 @@
name: "DetailsDialog", name: "DetailsDialog",
components: { components: {
PackageManagerEditor, DataMappingEditor, CustomModuleEditor, EnvEditor, ProjectEditor, PackageManagerEditor, DataMappingEditor, CustomModuleEditor, EnvEditor, ProjectEditor,
ProjectxConfig}, ProjectxConfig
},
data() { data() {
return { return {
visible: false, visible: false,
activeName: 'project', activeName: 'projectEditor',
} }
}, },
methods: { methods: {
...@@ -70,8 +71,8 @@ ...@@ -70,8 +71,8 @@
this.visible = true; this.visible = true;
}, },
onSave() { onSave() {
for (let ref of refs) { for (let key in this.activedTabs) {
this.$refs[ref].save(); this.$refs[key].save();
} }
this.visible = false; this.visible = false;
this.modifyProjectDetails(); this.modifyProjectDetails();
...@@ -80,9 +81,23 @@ ...@@ -80,9 +81,23 @@
this.visible = false; this.visible = false;
}, },
onOpen() { onOpen() {
for (let ref of refs) { this.activedTabs = {};
this.$refs[ref].edit();
this.onClickTab(this.activeName);
},
onClickTab(tab) {
let tabName;
if (typeof tab === 'string') {
tabName = tab;
} else {
tabName = tab.name;
}
let tabView = this.$refs[tabName];
if (!this.activedTabs[tab.name]) {
tabView.edit && tabView.edit();
this.activedTabs[tabName] = true;
} }
tabView.active && tabView.active();
}, },
...mapMutations([ ...mapMutations([
'modifyProjectDetails', 'modifyProjectDetails',
......
<template>
<el-dialog :title="$t('Dependencies missing')" width="50%" :visible.sync="visible"
:append-to-body="true"
custom-class="flex-dialog missing-packages-dialog"
>
<div class="wrapper">
<p v-html="$t('missingDependenciesNotice')"></p>
<div class="list">
<el-table
height="100%"
:data="missingPackages">
<el-table-column
prop="packageId"
label="ID">
</el-table-column>
<el-table-column
prop="version"
:label="$t('Version')">
</el-table-column>
</el-table>
</div>
</div>
<div slot="footer" class="dialog-footer">
<div></div>
<div>
<el-button size="mini" @click="onConfirm" type="primary">{{$t('Confirm')}}</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: "MissingPackagesDialog",
components: {},
data() {
return {
visible: false,
missingPackages: [],
}
},
methods: {
show(missingPackages) {
this.missingPackages = missingPackages;
this.visible = true;
},
onConfirm() {
this.visible = false;
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
...@@ -14,9 +14,12 @@ ...@@ -14,9 +14,12 @@
<el-table class="mock-table" :data="mocks" height="100%" stripe size="mini"> <el-table class="mock-table" :data="mocks" height="100%" stripe size="mini">
<el-table-column type="expand"> <el-table-column type="expand">
<template slot-scope="props"> <template slot-scope="props">
<codemirror ref="codeEditor" <monaco-editor
v-model="props.row.data" class="editor"
:options="cmOptions"/> v-model="props.row.data"
language="json"
:options="monacoConfig"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
...@@ -82,30 +85,20 @@ ...@@ -82,30 +85,20 @@
import {mapState, mapMutations, mapActions} from 'vuex' import {mapState, mapMutations, mapActions} from 'vuex'
import EnabledSetter from "../components/EnabledSetter"; import EnabledSetter from "../components/EnabledSetter";
import {clonePureObj} from "../../../utils"; import {clonePureObj} from "../../../utils";
import {codemirror} from "vue-codemirror";
import 'codemirror/addon/lint/lint.js' import 'codemirror/addon/lint/lint.js'
import 'codemirror/addon/lint/lint.css' import 'codemirror/addon/lint/lint.css'
import 'codemirror/addon/lint/json-lint.js' import 'codemirror/addon/lint/json-lint.js'
import MonacoEditor from "vue-monaco";
export default { export default {
name: "MockEditorDialog", name: "MockEditorDialog",
components: {EnabledSetter, codemirror}, components: {MonacoEditor, EnabledSetter},
data() { data() {
return { return {
visible: false, visible: false,
mocks: [], mocks: [],
cmOptions: { monacoConfig: {
tabSize: 2,
styleActiveLine: true,
theme: 'default',
line: true,
matchBrackets: true,
autoCloseBrackets: true,
lineNumbers: true,
mode: "application/json",
gutters: ["CodeMirror-lint-markers"],
lint: true
} }
} }
}, },
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
</template> </template>
<script> <script>
import {mapState, mapMutations} from 'vuex' import {mapState, mapMutations, mapGetters} from 'vuex'
import {clonePureObj} from "../../../../utils"; import {clonePureObj} from "../../../../utils";
import AssetMappingEditorDialog from "./AssetMappingEditorDialog"; import AssetMappingEditorDialog from "./AssetMappingEditorDialog";
import PropsEditorDialog from "./CustomModuleEditor/PropsEditorDialog"; import PropsEditorDialog from "./CustomModuleEditor/PropsEditorDialog";
...@@ -92,12 +92,19 @@ ...@@ -92,12 +92,19 @@
...mapState({ ...mapState({
customs: state => state.project.data.customs, customs: state => state.project.data.customs,
}), }),
...mapGetters([
'customPackages',
])
}, },
methods: { methods: {
edit() { edit() {
this.editData = clonePureObj(this.customs); this.editData = clonePureObj(this.customs);
},
active(){
this.customMetas.splice(0); this.customMetas.splice(0);
for (let meta of this.$store.state.editor.customs) { let packageDatas = this.customPackages;
for (let pid in packageDatas) {
let meta = packageDatas[pid];
let editData = this.editData.find(item => item.id === meta.id); let editData = this.editData.find(item => item.id === meta.id);
let data = editData ? editData : (editData || {}); let data = editData ? editData : (editData || {});
if (!data.props) { if (!data.props) {
......
<template> <template>
<el-scrollbar v-if="editData" class="scrollbar" wrap-class="wrap-x-hidden" view-class="view"> <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="view">
<div class="mapping-list"> <div class="mapping-list">
<el-button class="add-button" icon="el-icon-plus" size="mini" circle @click="onAdd"/> <el-button class="add-button" icon="el-icon-plus" size="mini" circle @click="onAdd"/>
<div class="list"> <div class="list" v-if="editData">
<div class="item" v-for="(link, index) in editData"> <div class="item" v-for="(link, index) in editData">
<el-input size="mini" style="width: 30%" v-model="link.name"/> <el-input size="mini" style="width: 30%" v-model="link.name"/>
<el-icon class="el-icon-connection"/> <el-icon class="el-icon-connection"/>
......
<template> <template>
<el-scrollbar v-if="editData" class="scrollbar" wrap-class="wrap-x-hidden" view-class="view"> <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="view">
<div class="mapping-list"> <div class="mapping-list">
<el-button class="add-button" icon="el-icon-plus" size="mini" circle @click="onAdd"/> <el-button class="add-button" icon="el-icon-plus" size="mini" circle @click="onAdd"/>
<div class="list"> <div class="list" v-if="editData">
<div class="item" v-for="(link, index) in editData"> <div class="item" v-for="(link, index) in editData">
<el-input size="mini" style="width: 30%" v-model="link.name"/> <el-input size="mini" style="width: 30%" v-model="link.name"/>
<el-icon class="el-icon-connection"/> <el-icon class="el-icon-connection"/>
......
<template> <template>
<div style="height: 100%;display: flex;flex-direction: column;"> <div style="height: 100%;display: flex;flex-direction: column;">
<el-tabs style="flex: 1;height: 0;" class="tabs" v-model="activeName"> <el-tabs style="flex: 1;height: 0;" class="tabs" v-model="activeName">
<el-tab-pane v-for="(group, key) in packageInfos" :label="$t('dependenciesTypes')[key]" :name="key"> <el-tab-pane v-for="(group, key, index) in packageInfos" :label="$t('dependenciesTypes')[key]" :name="key" :key="key">
<el-scrollbar v-if="editData" class="scrollbar" wrap-class="wrap-x-hidden" view-class="view package-manager"> <el-scrollbar v-if="editData" class="scrollbar" wrap-class="wrap-x-hidden" view-class="view package-manager">
<div class="mapping-list"> <div class="mapping-list">
<div class="list"> <div class="list">
<div class="item" v-for="packageInfo in group"> <div class="item" v-for="packageInfo in group" :key="packageInfo.id">
<div style="flex: 1;"> <div style="flex: 1;">
<i class="el-icon-s-cooperation"></i>
{{packageInfo.package_id}} {{packageInfo.package_id}}
</div> </div>
<el-tag class="update-time" size="mini" type="success">{{moment(packageInfo.update_time)}}</el-tag> <el-tag class="update-time" size="mini" type="success">{{$timeFormat(packageInfo.update_time)}}</el-tag>
<el-select size="mini" v-model="editData[packageInfo.package_id]"> <el-select class="version-select" size="mini" v-model="editData[packageInfo.package_id]"
popper-class="version-select-popover">
<el-option v-for="(version, index) in packageInfo.versions" <el-option v-for="(version, index) in packageInfo.versions"
:key="index" :key="index"
:value="version" :value="version"
:label="version" :label="versionLabel(packageInfo.package_id, version)"
></el-option>
>
<span class="version-label">{{ version }}</span>
<span class="version-notice">{{ versionLabel(packageInfo.package_id, version, false) }}</span>
</el-option>
</el-select> </el-select>
<el-popover
placement="left-start"
:title="$t('All versions')"
:open-delay="500"
width="250"
style="margin-left: 5px;"
trigger="click">
<div>
<el-scrollbar style="height: 200px;" wrap-class="wrap-x-hidden" view-class="package-version-list">
<div v-for="(version, index) in packageInfo.versions" :key="index" class="item">
<span class="version">v{{version}}</span>
<span class="update-time">
<i class="el-icon-time"></i>
{{packageInfo.update_times[index]}}
</span>
<br>
<span>{{packageInfo.remarks[index]}}</span>
</div>
</el-scrollbar>
</div>
<el-button slot="reference" circle icon="el-icon-files" class="micro" plain/>
</el-popover>
</div> </div>
</div> </div>
</div> </div>
...@@ -26,15 +54,16 @@ ...@@ -26,15 +54,16 @@
<div style="margin-top: 5px;"> <div style="margin-top: 5px;">
<el-button size="mini" @click="applyModify" type="primary">{{$t('Apply')}}</el-button> <el-button size="mini" @click="applyModify" type="primary">{{$t('Apply')}}</el-button>
<el-button size="mini" @click="resetModify">{{$t('Reset')}}</el-button> <el-button size="mini" @click="resetModify">{{$t('Reset')}}</el-button>
<el-button size="mini" @click="refresh" type="success" plain>{{$t('Refresh')}}</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import {mapState, mapMutations, mapActions} from 'vuex' import {mapState, mapMutations, mapActions, mapGetters} from 'vuex'
import {clonePureObj} from "../../../../utils"; import {clonePureObj, playWaiting} from "../../../../utils";
import moment from "moment"; import {packageExists} from "../../../../store/modules/package";
export default { export default {
name: "PackageManagerEditor", name: "PackageManagerEditor",
...@@ -46,34 +75,58 @@ ...@@ -46,34 +75,58 @@
}, },
computed: { computed: {
...mapState({ ...mapState({
dependencies: state => state.project.data.dependencies, dependencies: state => {
return state.project.data.dependencies;
},
packageInfos: state => { packageInfos: state => {
console.log(state.project);
return state.project.package.packageInfos; return state.project.package.packageInfos;
}, },
}), }),
...mapGetters([
'getPackage',
])
}, },
methods: { methods: {
moment(time) { async edit() {
return moment(time).format('YYYY-MM-DD HH:mm:ss'); this.packageMetas = await this.getAllPackageMetas();
},
edit() {
this.editData = clonePureObj(this.dependencies); this.editData = clonePureObj(this.dependencies);
}, },
save() { async save() {
this.modifyDependencies(this.editData); this.modifyDependencies(this.editData);
await playWaiting(this.applyDependencies(this.editData), 'Saving…');
}, },
async applyModify() { async applyModify() {
await this.applyModifyDependencies(this.editData); await playWaiting(this.downloadDependencies(this.editData), 'Downloading…');
await this.save();
this.editData = null;
this.$nextTick(async () => {
this.packageMetas = await this.getAllPackageMetas();
this.edit();
});
}, },
resetModify() { resetModify() {
this.edit(); this.edit();
}, },
async refresh() {
await playWaiting((async()=>{
await this.loadPackageInfos();
await this.fillLastVersion();
})(), 'Refreshing…');
},
versionLabel(packageId, version, withVersion = true) {
let exists = packageExists(this.packageMetas, packageId, version);
return (withVersion ? version + ' ' : '') + (!exists ? '(待下载)' : '');
},
...mapMutations([ ...mapMutations([
'modifyDependencies', 'modifyDependencies',
]), ]),
...mapActions([ ...mapActions([
'applyModifyDependencies', 'downloadDependencies',
'applyDependencies',
'getAllPackageMetas',
'loadPackageInfos',
'fillLastVersion',
]), ]),
} }
} }
......
<template> <template>
<div class="project-editor"> <el-scrollbar v-if="editData" class="project-scrollbar" wrap-class="wrap-x-hidden" view-class="project-editor">
<el-scrollbar v-if="editData" class="project-scrollbar" wrap-class="wrap-x-hidden" view-class="view"> <el-form @submit.native.prevent ref="form" :model="editData" size="mini" label-position="right"
<el-form @submit.native.prevent ref="form" :model="editData" size="mini" label-position="right" label-width="150px">
label-width="150px"> <el-form-item prop="pageTitle" :label="$t('Page title')">
<el-form-item prop="pageTitle" :label="$t('Page title')"> <el-input v-model="editData.pageTitle"/>
<el-input v-model="editData.pageTitle"/> </el-form-item>
</el-form-item> <el-form-item prop="entrySceneView" :label="$t('Entry scene view')">
<el-form-item prop="entrySceneView" :label="$t('Entry scene view')"> <el-select v-model="editData.entrySceneView">
<el-select v-model="editData.entrySceneView"> <el-option v-for="(view, index) in project.data.views"
<el-option v-for="(view, index) in project.data.views" :key="index"
:key="index" :value="view.name"
:value="view.name" :label="view.name"
:label="view.name" ></el-option>
></el-option> </el-select>
</el-select> </el-form-item>
</el-form-item> <el-form-item prop="containerId" :label="$t('Container ID')">
<el-form-item prop="containerId" :label="$t('Container ID')"> <el-input v-model="editData.containerId"/>
<el-input v-model="editData.containerId"/> </el-form-item>
</el-form-item> <el-form-item prop="designWidth" :label="$t('Design width')">
<el-form-item prop="designWidth" :label="$t('Design width')"> <el-input-number v-model="editData.designWidth" controls-position="right"/>
<el-input-number v-model="editData.designWidth" controls-position="right"/> </el-form-item>
</el-form-item> <el-form-item prop="designHeight" :label="$t('Design height')">
<el-form-item prop="designHeight" :label="$t('Design height')"> <el-input-number v-model="editData.designHeight" controls-position="right"/>
<el-input-number v-model="editData.designHeight" controls-position="right"/> </el-form-item>
</el-form-item> <el-form-item prop="frameRate" :label="$t('Frame Rate')">
<el-form-item prop="frameRate" :label="$t('Frame Rate')"> <el-input-number v-model="editData.frameRate" :max="60" :min="0" controls-position="right"/>
<el-input-number v-model="editData.frameRate" :max="60" :min="0" controls-position="right"/> </el-form-item>
</el-form-item> <el-form-item prop="scaleMode" :label="$t('Scale Mode')">
<el-form-item prop="scaleMode" :label="$t('Scale Mode')"> <el-select v-model="editData.scaleMode">
<el-select v-model="editData.scaleMode"> <el-option v-for="(label, key) in scaleMode"
<el-option v-for="(label, key) in scaleMode" :key="key"
:key="key" :value="key"
:value="key" :label="label"
:label="label" ></el-option>
></el-option> </el-select>
</el-select> </el-form-item>
</el-form-item> <el-form-item prop="rendererType" :label="$t('Renderer Type')">
<el-form-item prop="rendererType" :label="$t('Renderer Type')"> <el-select v-model="editData.rendererType">
<el-select v-model="editData.rendererType"> <el-option v-for="(label, key) in rendererType"
<el-option v-for="(label, key) in rendererType" :key="key"
:key="key" :value="key"
:value="key" :label="label"
:label="label" ></el-option>
></el-option> </el-select>
</el-select> </el-form-item>
</el-form-item> <el-form-item prop="tpl" :label="$t('Template')" class="tpl-editor">
<el-form-item prop="tpl" :label="$t('Template')"> <monaco-editor
<!-- <el-input type="textarea" v-model="options.tpl" :rows="10"/> --> class="editor"
<codemirror ref="codeEditor" v-model="editData.tpl"
v-model="editData.tpl" language="html"
:options="cmOptions" :options="monacoConfig"
@cursorActivity="onCodeChange" />
> </el-form-item>
</codemirror> </el-form>
</el-form-item> </el-scrollbar>
</el-form>
</el-scrollbar>
<!--<div class="operate-bar">
<el-button size="mini" @click="onReset">{{$t('Reset')}}</el-button>
<el-button size="mini" type="primary" @click="onSave">{{$t('Save')}}</el-button>
</div>-->
</div>
</template> </template>
<script> <script>
import {mapState, mapGetters, mapMutations} from 'vuex'; import {mapState, mapGetters, mapMutations} from 'vuex';
import {codemirror} from "vue-codemirror";
import 'codemirror/mode/javascript/javascript.js' import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/lib/codemirror.css' import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/monokai.css' import 'codemirror/theme/monokai.css'
...@@ -73,10 +65,11 @@ ...@@ -73,10 +65,11 @@
import 'codemirror/addon/hint/show-hint.js' import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/hint/show-hint.css' import 'codemirror/addon/hint/show-hint.css'
import {clonePureObj} from "../../../../utils"; import {clonePureObj} from "../../../../utils";
import MonacoEditor from "vue-monaco";
export default { export default {
name: "ProjectEditor", name: "ProjectEditor",
components: {codemirror}, components: { MonacoEditor},
data() { data() {
const scaleMode = this.$t('scaleMode'); const scaleMode = this.$t('scaleMode');
const rendererType = this.$t('rendererType'); const rendererType = this.$t('rendererType');
...@@ -85,16 +78,9 @@ ...@@ -85,16 +78,9 @@
editData: null, editData: null,
scaleMode, scaleMode,
rendererType, rendererType,
cmOptions: { monacoConfig: {
tabSize: 2,
mode: 'text/javascript', },
styleActiveLine: true,
theme: 'default',
lineNumbers: true,
line: true,
matchBrackets: true,
autoCloseBrackets: true,
}
} }
}, },
computed: { computed: {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="project-info"> <div class="project-info">
<span class="project-name">{{scope.row.name}}</span> <span class="project-name">{{scope.row.name}}</span>
<el-tag size="mini" type="success">{{scope.row.operator}}</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> <el-tag size="mini" type="warning">{{$timeFormat(scope.row.update_time)}}</el-tag>
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
...@@ -96,7 +96,6 @@ ...@@ -96,7 +96,6 @@
import {mapState, mapActions} from 'vuex' import {mapState, mapActions} from 'vuex'
import CreateProjectDialog from "./Home/CreateProjectDialog"; import CreateProjectDialog from "./Home/CreateProjectDialog";
import {playWaiting, readTextFile, saveAs, selectFile} from "../utils"; import {playWaiting, readTextFile, saveAs, selectFile} from "../utils";
import moment from "moment";
import DuplicateProjectDialog from "./Home/DuplicateProjectDialog"; import DuplicateProjectDialog from "./Home/DuplicateProjectDialog";
import {PROJECT_PAGE_SIZE} from "../config"; import {PROJECT_PAGE_SIZE} from "../config";
import ProjectHistoryDialog from "./Home/ProjectHistoryDialog"; import ProjectHistoryDialog from "./Home/ProjectHistoryDialog";
...@@ -137,9 +136,6 @@ ...@@ -137,9 +136,6 @@
this.handleCurrentChange(1), this.handleCurrentChange(1),
]) ])
}, },
moment(time) {
return moment(time).format('YYYY-MM-DD HH:mm:ss');
},
showCreateProjectDialog() { showCreateProjectDialog() {
this.$refs.createProjectDialog.show(); this.$refs.createProjectDialog.show();
}, },
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
width="200"> width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<i class="el-icon-time"></i> <i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ moment(scope.row.operator_time) }}</span> <span style="margin-left: 10px">{{ $timeFormat(scope.row.operator_time) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
...@@ -64,7 +64,6 @@ ...@@ -64,7 +64,6 @@
<script> <script>
import {mapState, mapActions} from 'vuex' import {mapState, mapActions} from 'vuex'
import {HISTORY_PAGE_SIZE} from "../../config"; import {HISTORY_PAGE_SIZE} from "../../config";
import moment from "moment";
export default { export default {
name: "ProjectHistoryDialog", name: "ProjectHistoryDialog",
...@@ -93,9 +92,6 @@ ...@@ -93,9 +92,6 @@
}, },
onOpen() { onOpen() {
},
moment(time) {
return moment(time).format('YYYY-MM-DD HH:mm:ss');
}, },
async handleCurrentChange(page) { async handleCurrentChange(page) {
const loading = this.$loading({ const loading = this.$loading({
......
...@@ -34,9 +34,6 @@ ...@@ -34,9 +34,6 @@
} }
}, },
async mounted() { async mounted() {
this.codes = {};
this.urls = {};
if (!this.ts) { if (!this.ts) {
this.ts = localStorage.getItem('preview-ts'); this.ts = localStorage.getItem('preview-ts');
} }
...@@ -94,39 +91,12 @@ ...@@ -94,39 +91,12 @@
return; return;
} }
const {projectID} = this.$route.params; const {projectID} = this.$route.params;
const {data, codes} = await db.get('preview', projectID); const {data, tpl} = await db.get('preview', projectID);
console.log(data); console.log(data);
let {options: {tpl, pageTitle, containerId}} = data; let {options: {pageTitle, }, } = data;
//const dataName = projectID + "_data";
//const launchCode = `engine.launchWithWindowVariable("${dataName}");`;
const scripts = [];
for (let key in codes) {
let oldCode = this.codes[key];
let code = codes[key];
let url;
if (oldCode !== code) {
url = this.urls[key] = URL.createObjectURL(new Blob([code]));
} else {
url = this.urls[key];
}
scripts.push(newScriptEl(url));
}
scripts.push(newScriptContent('var proxy_mode=true;'));
this.codes = codes;
const dataUrl = URL.createObjectURL(new Blob([JSON.stringify(data)]));
document.title = pageTitle; document.title = pageTitle;
tpl = tpl
.replace('$PAGE_TITLE$', pageTitle)
.replace('$CONTAINER_ID$', containerId)
.replace('$SCRIPTS$', scripts.join('\n'))
.replace('//yun.duiba.com.cn/aurora/$VERSION$-data.json', dataUrl);
const doc = this.$refs.iframe.contentDocument; const doc = this.$refs.iframe.contentDocument;
const win = this.$refs.iframe.contentWindow; const win = this.$refs.iframe.contentWindow;
doc.write(tpl); doc.write(tpl);
...@@ -172,7 +142,7 @@ ...@@ -172,7 +142,7 @@
bottom: 10px; bottom: 10px;
} }
.proxy-iframe-wrapper{ .proxy-iframe-wrapper {
/*display: none;*/ /*display: none;*/
top: 0; top: 0;
position: absolute; position: absolute;
......
/** /**
* Created by rockyl on 2019-12-20. * Created by rockyl on 2019-12-20.
*/ */
import {clonePureObj} from "../../utils"; import {clonePureObj, newScriptContent, typeMapping} from "../../utils";
import {divideCode} from "zeroing-code-divider"; import {divideCode} from "zeroing-code-divider";
import {generateLibraryScriptEl, fillTemplate, generateJsScriptEl} from "zeroing-template-fill";
import db from "../../utils/db-storage"; import db from "../../utils/db-storage";
const storeName = 'preview'; const storeName = 'preview';
function getPack(packs) { let codesCache = {};
return function (ids) { let urlsCache = {};
return packs.filter(pack => ids.includes(pack.id))
function getPackages(packages) {
return async function (schema, type) {
let ids = Object.keys(schema);
let result = ids.map(pid=>{
let packageItem = packages[typeMapping[type]][pid];
return {
data: packageItem,
};
}).filter(item=>!!item);
return result;
} }
} }
export async function preprocess(project, data, processes, scripts, customs) { export async function preprocess(project, data, packages) {
let newData = clonePureObj(data); let newData = clonePureObj(data);
const codes = await divideCode(newData, { const codes = await divideCode(newData, {
debug: true, debug: true,
getProcesses: getPack(processes), getPackages: getPackages(packages),
getScripts: getPack(scripts), dependencies: data.dependencies,
getCustoms: getPack(customs),
}); });
let {options: {tpl, pageTitle, containerId}, dependencies} = data;
let scripts = [];
for (let key in codes) {
let oldCode = codesCache[key];
let code = codes[key];
let url;
if (oldCode !== code) {
url = urlsCache[key] = URL.createObjectURL(new Blob([code]));
} else {
url = urlsCache[key];
}
scripts.push(url);
}
scripts = scripts.map(item => generateJsScriptEl(item));
scripts.push(newScriptContent('var proxy_mode=true;'));
codesCache = codes;
const dataUrl = URL.createObjectURL(new Blob([JSON.stringify(newData)]));
const {libraryScriptElMap, analyseResult} = await generateLibraryScriptEl(tpl, dependencies, getPackages(packages), '//yun.duiba.com.cn/editor/zeroing/libs/');
tpl = fillTemplate(tpl, {
pageTitle,
containerId,
scripts: scripts.join('\n'),
libraries: libraryScriptElMap,
});
tpl = tpl.replace('//yun.duiba.com.cn/aurora/$VERSION$-data.json', dataUrl);
db.set(storeName, { db.set(storeName, {
id: project.id, id: project.id,
data: newData, data: newData,
codes, tpl,
}); });
localStorage.setItem('preview-ts', Date.now().toString()); localStorage.setItem('preview-ts', Date.now().toString());
} }
const serverHost = 'http://10.10.95.74:7777' const serverHost = 'http://10.10.95.74:7777';
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = { module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '//yun.duiba.com.cn/editor/zeroing/v1/' : '', publicPath: process.env.NODE_ENV === 'production' ? '//yun.duiba.com.cn/editor/zeroing/v1/' : '',
...@@ -30,9 +30,9 @@ module.exports = { ...@@ -30,9 +30,9 @@ module.exports = {
configureWebpack: { configureWebpack: {
plugins: [ plugins: [
new MonacoWebpackPlugin({ new MonacoWebpackPlugin({
languages: ['javascript', 'typescript', 'json'], languages: ['javascript', 'typescript', 'json', 'html'],
publicPath: process.env.NODE_ENV === 'production' ? "/monaco" : "", publicPath: process.env.NODE_ENV === 'production' ? "/monaco" : "",
}) })
] ]
} }
} };
...@@ -1976,7 +1976,7 @@ camelcase@^3.0.0: ...@@ -1976,7 +1976,7 @@ camelcase@^3.0.0:
resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
camelcase@^5.0.0: camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1" version "5.3.1"
resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA= integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=
...@@ -2226,7 +2226,7 @@ code-point-at@^1.0.0: ...@@ -2226,7 +2226,7 @@ code-point-at@^1.0.0:
resolved "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" resolved "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codemirror@^5.41.0, codemirror@^5.50.0: codemirror@^5.50.0:
version "5.50.2" version "5.50.2"
resolved "https://registry.npm.taobao.org/codemirror/download/codemirror-5.50.2.tgz#32ddfe2b50193fcf573d8141c4a31d267c92b4a3" resolved "https://registry.npm.taobao.org/codemirror/download/codemirror-5.50.2.tgz#32ddfe2b50193fcf573d8141c4a31d267c92b4a3"
integrity sha1-Mt3+K1AZP89XPYFBxKMdJnyStKM= integrity sha1-Mt3+K1AZP89XPYFBxKMdJnyStKM=
...@@ -2961,11 +2961,6 @@ detect-node@^2.0.4: ...@@ -2961,11 +2961,6 @@ detect-node@^2.0.4:
resolved "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" resolved "https://registry.npm.taobao.org/detect-node/download/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
integrity sha1-AU7o+PZpxcWAI9pkuBecCDooxGw= integrity sha1-AU7o+PZpxcWAI9pkuBecCDooxGw=
diff-match-patch@^1.0.0:
version "1.0.4"
resolved "https://registry.npm.taobao.org/diff-match-patch/download/diff-match-patch-1.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdiff-match-patch%2Fdownload%2Fdiff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
integrity sha1-asS1UjdGN2HE2vDcYD64aRJHRLE=
diffie-hellman@^5.0.0: diffie-hellman@^5.0.0:
version "5.0.3" version "5.0.3"
resolved "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" resolved "https://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
...@@ -5482,17 +5477,17 @@ moment@^2.24.0: ...@@ -5482,17 +5477,17 @@ moment@^2.24.0:
resolved "https://registry.npm.taobao.org/moment/download/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" resolved "https://registry.npm.taobao.org/moment/download/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s= integrity sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s=
monaco-editor-webpack-plugin@^1.8.1: monaco-editor-webpack-plugin@^1.9.0:
version "1.8.1" version "1.9.0"
resolved "https://registry.npm.taobao.org/monaco-editor-webpack-plugin/download/monaco-editor-webpack-plugin-1.8.1.tgz#5701bfce16c14c51503a607726d97fd92784af26" resolved "https://registry.npm.taobao.org/monaco-editor-webpack-plugin/download/monaco-editor-webpack-plugin-1.9.0.tgz#5b547281b9f404057dc5d8c5722390df9ac90be6"
integrity sha1-VwG/zhbBTFFQOmB3Jtl/2SeEryY= integrity sha1-W1Rygbn0BAV9xdjFciOQ35rJC+Y=
dependencies: dependencies:
loader-utils "^1.2.3" loader-utils "^1.2.3"
monaco-editor@^0.19.0: monaco-editor@^0.20.0:
version "0.19.0" version "0.20.0"
resolved "https://registry.npm.taobao.org/monaco-editor/download/monaco-editor-0.19.0.tgz#c6e774210f3b292ff739e96f45a1cc78bf5ac2e7" resolved "https://registry.npm.taobao.org/monaco-editor/download/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
integrity sha1-xud0IQ87KS/3OelvRaHMeL9awuc= integrity sha1-XVAJNDpVASRCbLTZZaTSejSLTeo=
move-concurrently@^1.0.1: move-concurrently@^1.0.1:
version "1.0.1" version "1.0.1"
...@@ -5559,6 +5554,11 @@ nan@^2.12.1, nan@^2.13.2: ...@@ -5559,6 +5554,11 @@ nan@^2.12.1, nan@^2.13.2:
resolved "https://registry.npm.taobao.org/nan/download/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" resolved "https://registry.npm.taobao.org/nan/download/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha1-eBj3IgJ7JFmobwKV1DTR/CM2xSw= integrity sha1-eBj3IgJ7JFmobwKV1DTR/CM2xSw=
nano-assign@^1.0.0:
version "1.0.1"
resolved "https://registry.npm.taobao.org/nano-assign/download/nano-assign-1.0.1.tgz#abb1c50d0416b865fb37bbd155c5368bb54378e5"
integrity sha1-q7HFDQQWuGX7N7vRVcU2i7VDeOU=
nanomatch@^1.2.9: nanomatch@^1.2.9:
version "1.2.13" version "1.2.13"
resolved "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" resolved "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
...@@ -8663,14 +8663,6 @@ vue-cli-plugin-i18n@^0.6.0: ...@@ -8663,14 +8663,6 @@ vue-cli-plugin-i18n@^0.6.0:
vue-i18n "^8.0.0" vue-i18n "^8.0.0"
vue-i18n-extract "^0.4.13" vue-i18n-extract "^0.4.13"
vue-codemirror@^4.0.6:
version "4.0.6"
resolved "https://registry.npm.taobao.org/vue-codemirror/download/vue-codemirror-4.0.6.tgz#b786bb80d8d762a93aab8e46f79a81006f0437c4"
integrity sha1-t4a7gNjXYqk6q45G95qBAG8EN8Q=
dependencies:
codemirror "^5.41.0"
diff-match-patch "^1.0.0"
vue-draggable-resizable@^2.0.1: vue-draggable-resizable@^2.0.1:
version "2.1.0" version "2.1.0"
resolved "https://registry.npm.taobao.org/vue-draggable-resizable/download/vue-draggable-resizable-2.1.0.tgz#b590212aef3c07d040aeceda784438068170fb08" resolved "https://registry.npm.taobao.org/vue-draggable-resizable/download/vue-draggable-resizable-2.1.0.tgz#b590212aef3c07d040aeceda784438068170fb08"
...@@ -8709,6 +8701,13 @@ vue-loader@^15.7.0: ...@@ -8709,6 +8701,13 @@ vue-loader@^15.7.0:
vue-hot-reload-api "^2.3.0" vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0" vue-style-loader "^4.1.0"
"vue-monaco@http://gitlab2.dui88.com/laoqifeng/vue-monaco.git":
version "0.3.1"
resolved "http://gitlab2.dui88.com/laoqifeng/vue-monaco.git#13de23ce8ba73525cf08678227ae0c579fe2319d"
dependencies:
monaco-editor "^0.20.0"
nano-assign "^1.0.0"
vue-router@^3.0.3: vue-router@^3.0.3:
version "3.1.3" version "3.1.3"
resolved "https://registry.npm.taobao.org/vue-router/download/vue-router-3.1.3.tgz#e6b14fabc0c0ee9fda0e2cbbda74b350e28e412b" resolved "https://registry.npm.taobao.org/vue-router/download/vue-router-3.1.3.tgz#e6b14fabc0c0ee9fda0e2cbbda74b350e28e412b"
...@@ -9168,3 +9167,9 @@ yeast@0.1.2: ...@@ -9168,3 +9167,9 @@ yeast@0.1.2:
"zeroing-code-divider@http://gitlab2.dui88.com/laoqifeng/zeroing-code-divider.git": "zeroing-code-divider@http://gitlab2.dui88.com/laoqifeng/zeroing-code-divider.git":
version "1.0.1" version "1.0.1"
resolved "http://gitlab2.dui88.com/laoqifeng/zeroing-code-divider.git#b2b6d191972fd597388795f249a09071db8f33eb" resolved "http://gitlab2.dui88.com/laoqifeng/zeroing-code-divider.git#b2b6d191972fd597388795f249a09071db8f33eb"
"zeroing-template-fill@http://gitlab2.dui88.com/laoqifeng/zeroing-template-fill.git":
version "1.0.0"
resolved "http://gitlab2.dui88.com/laoqifeng/zeroing-template-fill.git#574fc720889a52714ec437fc5cc6dcbc002083b3"
dependencies:
camelcase "^5.3.1"
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