Commit 2e7fbec3 authored by rockyl's avatar rockyl

init

parents
Pipeline #160765 failed with stages
in 0 seconds
> 1%
last 2 versions
VUE_APP_I18N_LOCALE=en
VUE_APP_I18N_FALLBACK_LOCALE=en
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# zeroing-editor
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn run serve
```
### Compiles and minifies for production
```
yarn run build
```
### Run your tests
```
yarn run test
```
### Lints and fixes files
```
yarn run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/app'
]
}
# Records
## Typescript or Javascript?
两者都兼容,最终都会被翻译为es2015。
## 参数和返回值配置?
需要开发者自己编写,同级目录的meta.json即为该过程的。
## 过程嵌套
过程可以嵌套,预设就是一种嵌套封装。
嵌套的配置和过程的配置一样,多了subProcesses。
嵌套的option通过映射方式映射到子过程的option。
映射关系,field-uuid.field。
## 渲染引擎
初期承载于白鹭引擎。
## PSD导入成UI
通过psd.js导出原始的图层信息,然后通过各自的实现来导出目标格式。
## 动作编辑器
使用dom来做节点,svg来做连线(曲线)
## PSD
1个psd文件对应1个皮肤
## 前端框架
vue + element-ui
File added
<!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
{
"success": true,
"data": {
"id": "6e1c9eadf8e28",
"name": "测试",
"creator": "卞龙亭",
"operator": "卞龙亭",
"create_time": "2019-09-19T06:56:01.000Z",
"update_time": "2019-09-19T06:56:01.000Z"
}
}
{
"success": true,
"data": {
"name": "Zeroing Editor",
"version": "1.0.0",
"templates": {
"builtin": ["blank"],
"custom": []
},
"components": [
],
"processes": [
]
}
}
\ No newline at end of file
{
"data": [
{
"id": "0514db3756d4e",
"name": "呼呼",
"creator": "卞龙亭",
"operator": "卞龙亭",
"create_time": "2019-09-19T06:55:56.000Z",
"update_time": "2019-09-19T07:07:46.000Z"
},
{
"id": "6e1c9eadf8e27",
"name": "hhaa",
"creator": "卞龙亭",
"operator": "卞龙亭",
"create_time": "2019-09-19T06:56:01.000Z",
"update_time": "2019-09-19T06:56:01.000Z"
}
],
"success": true
}
\ No newline at end of file
{
"name": "zeroing-editor",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'"
},
"dependencies": {
"cookie": "^0.4.0",
"core-js": "^2.6.5",
"element-ui": "^2.4.5",
"moment": "^2.24.0",
"querystringify": "^2.1.1",
"splitpanes": "^1.14.5",
"vue": "^2.6.10",
"vue-i18n": "^8.0.0",
"vue-router": "^3.0.3",
"vuex": "^3.0.1"
},
"devDependencies": {
"@kazupon/vue-i18n-loader": "^0.3.0",
"@vue/cli-plugin-babel": "^3.11.0",
"@vue/cli-service": "^3.11.0",
"node-sass": "^4.9.2",
"sass": "^1.22.9",
"sass-loader": "^7.2.0",
"vue-cli-plugin-element": "^1.0.1",
"vue-cli-plugin-i18n": "^0.6.0",
"vue-template-compiler": "^2.6.10"
},
"appVersion": "0.1.0"
}
module.exports = {
plugins: {
autoprefixer: {}
}
}
<!DOCTYPE html>
<html lang="en">
<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>
</html>
<template>
<div id="app" class="theme-light">
<router-view/>
</div>
</template>
<script>
import events from './global-events'
export default {
name: "App",
mounted() {
},
methods: {
},
}
</script>
<style>
</style>
/**
* Created by rockyl on 2019-09-19.
*/
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();
if (name) {
this.name = name;
}
if (code) {
this.code = code;
}
if (message) {
this.message = message;
}
}
}
export async function fetchApi(uri, {params, method, contentType, errMessage} = {method: 'get', contentType: 'form'}) {
let url = API_HOST + uri;
const options = {
method,
headers: {
authorization: user_cookie,
},
};
if (params) {
if (method.toLowerCase() === 'post') {
if (contentType === 'form') {
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
options.body = stringify(params);
} else if (contentType === 'json') {
options.headers['Content-Type'] = 'application/json';
options.body = JSON.stringify(params);
}
} else {
url += (url.indexOf('?') < 0 ? '?' : '') + (url.endsWith('&') ? '' : '&') + stringify(params);
}
}
const response = await fetch(url, options);
const jsonObj = await response.json();
console.log(jsonObj);
if (jsonObj.success) {
return jsonObj.data;
}
throw new ApiError('call api failed', jsonObj.code, errMessage);
}
\ No newline at end of file
/**
* Created by rockyl on 2019-09-19.
*
* 环境相关api
*/
import {fetchApi} from "./common";
export async function fetchEnv() {
return await fetchApi('/api/project/env', {
errMessage: 'Failed to fetch env',
})
}
/**
* Created by rockyl on 2019-09-19.
*/
import * as envApi from './env'
import * as projectApi from './project'
export {
envApi,
projectApi,
}
/**
* Created by rockyl on 2019-09-19.
*
* 项目相关api
*/
import {fetchApi} from "./common";
export async function fetchAll() {
return await fetchApi('/api/project/query', {
errMessage: 'Failed to fetch projects',
})
}
export async function createOne(project) {
return await fetchApi('/api/project/create', {
params: project,
method: 'post',
contentType: 'json',
errMessage: 'Failed to create project',
})
}
export async function duplicateOne(project) {
return await fetchApi('/api/project/duplicate', {
params: project,
method: 'post',
contentType: 'json',
errMessage: 'Failed to duplicate project',
})
}
export async function deleteOne(id) {
return await fetchApi('/api/project/delete', {
params: {id},
method: 'delete',
errMessage: 'Failed to delete project',
})
}
export async function getOne(id) {
return await fetchApi('/api/project/detail', {
params: {id},
method: 'get',
errMessage: 'Failed to get project',
})
}
export async function updateOne(project) {
return await fetchApi('/api/project/update', {
params: project,
method: 'post',
contentType: 'json',
errMessage: 'Failed to save project',
})
}
<template>
<p>{{ $t('hello') }}</p>
</template>
<script>
export default {
name: 'HelloI18n'
}
</script>
<i18n>
{
"en": {
"hello": "Hello i18n in SFC!"
}
}
</i18n>
<template>
<div class="pane" tabindex="1">
<div class="content background">
<slot>
<span style="color: #cccccc;align-self: center; flex: 1;text-align: center;">Empty pane</span>
</slot>
</div>
<div class="title-bar">
<div class="name-icon background">
<i :class="icon"></i>
<span>{{title}}</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Pane",
data() {
return {}
},
props: ['title', 'icon'],
methods: {
onClickMore(){
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div class="menu">
<el-link @click="clickItem(key)" v-for="(item, key) of data" :icon="item.icon">
{{item.text}}
</el-link>
</div>
</template>
<script>
export default {
name: "SampleMenu",
props: ['data'],
data() {
return {}
},
methods: {
clickItem(key) {
this.$emit('click-menu', key);
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
/**
* Created by rockyl on 2019-09-19.
*/
//export const API_HOST = 'http://10.10.94.31:7777';
export const API_HOST = 'http://localhost:3002';
/**
* Created by rockyl on 2019-09-19.
*
* 全局事件
*/
import Vue from 'vue'
const events = new Vue();
export default events;
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
function loadLocaleMessages () {
const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
const messages = {}
locales.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)\./i)
if (matched && matched.length > 1) {
const locale = matched[1]
messages[locale] = locales(key)
}
})
return messages
}
export default new VueI18n({
locale: process.env.VUE_APP_I18N_LOCALE || 'en',
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: loadLocaleMessages()
})
{
"Alert": "Alert",
"Confirm": "Confirm",
"Cancel": "Cancel",
"In processing": "In processing",
"Projects": "Projects",
"copy": "copy",
"No projects": "No projects",
"Create": "Create",
"Project name": "Project name",
"Template": "Template",
"Preparing": "Preparing…",
"Create project": "Create project",
"Creating project": "Creating project…",
"Create project success": "Create project success",
"Duplicate project": "Duplicate project",
"Duplicating project": "Duplicating project…",
"Duplicate project success": "Duplicate project success",
"Project name cannot be empty": "Project name cannot be empty",
"This action will permanently delete project": "This action will permanently delete project[{projectName}], continue?",
"Failed to fetch env": "Failed to fetch env",
"Failed to fetch projects": "Failed to fetch projects",
"Failed to create project": "Failed to create project",
"Failed to duplicate project": "Failed to duplicate project",
"Failed to delete project": "Failed to delete project",
"Failed to get project": "Failed to get project",
"Failed to save project": "Failed to save project",
"menu": {
"save": "Save",
"details": "Details",
"preview": "Preview",
"publish": "Publish",
"data-mapping": "DataMapping",
"exit": "Exit"
},
"panes": {
"Assets": "Assets",
"Inspector": "Inspector",
"Playground": "Playground",
"Views": "Views"
}
}
\ No newline at end of file
{
"Alert": "提示",
"Confirm": "确定",
"Cancel": "取消",
"In processing": "处理中…",
"Projects": "项目列表",
"copy": "副本",
"No projects": "没有项目",
"Create": "创建",
"Project name": "项目名称",
"Template": "模板",
"Preparing": "准备中…",
"Create project": "创建项目",
"Creating project": "项目创建中…",
"Create project success": "创建项目成功",
"Duplicate project": "复制项目",
"Duplicating project": "项目复制中…",
"Duplicate project success": "复制项目成功",
"Project name cannot be empty": "项目名不能为空",
"This action will permanently delete project": "即将永久删除项目[{projectName}], 是否继续?",
"Failed to fetch env": "环境获取失败",
"Failed to fetch projects": "项目列表获取失败",
"Failed to create project": "创建项目失败",
"Failed to duplicate project": "复制项目失败",
"Failed to delete project": "删除项目失败",
"Failed to get project": "获取项目失败",
"Failed to save project": "保存项目失败"
}
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store/index'
import i18n from './i18n'
Vue.config.productionTip = false
import './plugins/element.js'
import './themes/light/index.scss'
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount('#app')
/*
Write your variables here. All available variables can be
found in element-ui/packages/theme-chalk/src/common/var.scss.
For example, to overwrite the theme color:
*/
@import "../themes/light/var.scss";
@import "../../node_modules/element-ui/packages/theme-chalk/src/index";
import Vue from 'vue'
import Element from 'element-ui'
Vue.use(Element)
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/editor',
name: 'editor',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "editor" */ './views/Editor.vue')
}
]
})
/**
* Created by rockyl on 2019-09-18.
*/
import Vue from 'vue'
import Vuex from 'vuex'
import {envStore} from "./modules/env";
import {projectsStore} from "./modules/projects";
import {projectStore} from "./modules/project";
Vue.use(Vuex);
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {
env: envStore,
projects: projectsStore,
project: projectStore,
},
})
/**
* Created by rockyl on 2019-09-19.
*
* 环境
*/
import {envApi} from "../../api";
export const envStore = {
state: {
name: 'Zeroing Editor',
version: '1.0.0',
templates: {
builtin: ['blank'],
custom: [],
},
components: [],
processes: [],
},
mutations: {
updateEnv(state, env) {
Object.assign(state, env);
},
},
actions: {
async updateEnv({commit}) {
const env = await envApi.fetchEnv();
commit('updateEnv', env);
}
}
};
/**
* Created by rockyl on 2019-09-19.
*/
import {projectApi} from "../../api";
export const projectStore = {
state: {
id: '',
name: '',
creator: '',
views: [],
assets: [],
},
mutations: {
updateProject(state, project) {
const {id, name, creator} = project;
state.id = id;
state.name = name;
state.creator = creator;
},
},
actions: {
async updateProject({commit}, projectID) {
const project = await projectApi.getOne(projectID);
commit('updateProject', project);
},
},
};
/**
* Created by rockyl on 2019-09-19.
*/
import {projectApi} from "../../api";
export const projectsStore = {
state: [],
mutations: {
updateProjects(state, projects) {
state.splice(0);
state.push(...projects);
},
addProject(state, project){
state.push(project);
},
},
actions: {
async updateProjects({commit}) {
const projects = await projectApi.fetchAll();
commit('updateProjects', projects);
},
async createProject({commit}, data) {
const project = await projectApi.createOne(data);
commit('addProject', project);
return project;
},
async duplicateProject({commit}, data) {
const project = await projectApi.duplicateOne(data);
commit('addProject', project);
return project;
},
},
};
\ No newline at end of file
html, body, #app {
height: 100%;
margin: 0;
padding: 0;
border: 0;
}
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: flex;
font-family: Arial, sans-serif;
}
@import "splitspanes";
@import "pane";
.editor {
display: flex;
flex: 1;
flex-direction: column;
.tool-bar {
background-color: $--pane-background-color;
margin-bottom: 1px;
.menu{
padding: 5px 10px;
a:not(:first-child){
margin-left: 10px;
}
}
}
.pane-container {
height: 100%;
}
}
.bottom-bar, .toolbar{
background-color: $--pane-background-color;
}
@import "var";
.home {
padding: 20px 30px;
display: flex;
flex: 1;
flex-direction: column;
main {
display: flex;
flex: 1;
flex-direction: column;
}
.editor-name {
font-size: 50px;
color: $--color-primary;
}
.editor-version {
font-size: 16px;
margin-left: 10px;
}
.project-list {
flex: 1;
}
.project-info {
flex: 1;
display: flex;
align-items: flex-end;
line-height: normal;
}
.project-name {
flex: 1;
font-size: 30px;
font-weight: bold;
}
.project-detail {
}
}
\ No newline at end of file
/**
* Created by rockyl on 2019-09-18.
*/
@import "./var.scss";
@import "./base.scss";
@import "./home.scss";
@import "./editor.scss";
@import "~element-ui/packages/theme-chalk/src/index.scss";
@import "var";
.pane {
height: 100%;
display: flex;
flex-direction: column-reverse;
&:focus {
outline: none;
& > .background {
background-color: mix($--pane-background-color, $--color-white, 80%);
border-color: mix($--pane-border-color, $--color-white, 80%);
}
& > .title-bar > .background {
background-color: mix($--pane-background-color, $--color-white, 80%);
border-color: mix($--pane-border-color, $--color-white, 80%);
}
}
.background{
background-color: $--pane-background-color;
border: 1px solid $--pane-border-color;
}
.content {
display: flex;
flex: 1;
border-radius: 2px;
}
.title-bar {
height: 20px;
display: flex;
justify-content: space-between;
padding-right: 1px;
color: $--color-text-regular;
font-size: 12px;
span {
margin-left: 3px;
}
.name-icon {
display: flex;
align-items: center;
height: 100%;
padding: 0 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom: 0;
}
.el-button {
padding: 0 3px;
}
}
}
$--splitter-size: 2px;
.#{splitpanes} {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
width: 100%;
height: 100%;
&--vertical {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row
}
&--horizontal {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column
}
&--dragging * {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
&__pane {
width: 100%;
height: 100%;
overflow: hidden;
-webkit-transition: width .2s ease-out, height .2s ease-out;
transition: width .2s ease-out, height .2s ease-out
}
&--dragging &__pane {
-webkit-transition: none;
transition: none
}
&__splitter {
-ms-touch-action: none;
touch-action: none
}
&--vertical > &__splitter {
min-width: 1px;
cursor: col-resize
}
&--horizontal > &__splitter {
min-height: 1px;
cursor: row-resize
}
& &__pane {
//background-color: #f2f2f2
}
& &__splitter {
background-color: #fff;
-webkit-box-sizing: border-box;
box-sizing: border-box;
position: relative
}
& &__splitter:after, & &__splitter:before {
content: "";
position: absolute;
top: 50%;
left: 50%;
background-color: rgba(0, 0, 0, .15);
-webkit-transition: background-color .3s;
transition: background-color .3s
}
& &__splitter:hover:after, & &__splitter:hover:before {
background-color: rgba(0, 0, 0, .25)
}
& & &__splitter {
z-index: 1
}
&--vertical > &__splitter, &--vertical > &__splitter {
width: $--splitter-size;
//border-left: 1px solid #eee;
//margin-left: -1px
}
&--vertical > &__splitter:after, &--vertical > &__splitter:after, &--vertical > &__splitter:before, &--vertical > &__splitter:before {
/*-webkit-transform: translateY(-50%);
transform: translateY(-50%);
width: 1px;
height: 30px*/
}
&--vertical > &__splitter:before, &--vertical > &__splitter:before {
margin-left: -1px
}
&--vertical > &__splitter:after, &--vertical > &__splitter:after {
margin-left: 1px
}
&--horizontal > &__splitter, &--horizontal > &__splitter {
height: $--splitter-size;
//border-top: 1px solid #eee;
//margin-top: -1px
}
&--horizontal > &__splitter:after, &--horizontal > &__splitter:after, &--horizontal > &__splitter:before, &--horizontal > &__splitter:before {
/*-webkit-transform: translateX(-50%);
transform: translateX(-50%);
width: 30px;
height: 1px*/
}
&--horizontal > &__splitter:before, &--horizontal > &__splitter:before {
margin-top: -1px
}
&--horizontal > &__splitter:after, &--horizontal > &__splitter:after {
margin-top: 1px
}
}
$--color-primary: #9b82e3 !default;
$--color-success: #67C23A !default;
$--color-warning: #E6A23C !default;
$--color-danger: #F56C6C !default;
$--color-info: #909399 !default;
$--color-text-primary: #303133 !default;
$--color-text-regular: #606266 !default;
$--color-text-secondary: #909399 !default;
$--color-text-placeholder: #C0C4CC !default;
$--border-color-base: #DCDFE6 !default;
$--border-color-light: #E4E7ED !default;
$--border-color-lighter: #EBEEF5 !default;
$--border-color-extra-light: #F2F6FC !default;
$--color-white: #FFFFFF !default;
$--color-black: #000000 !default;
$--background-color-base: #F5F5F5;
$--font-path: '~element-ui/lib/theme-chalk/fonts';
//customs
$--pane-background-color: mix($--background-color-base, $--color-black, 90%);
$--pane-border-color: mix($--background-color-base, $--color-black, 80%);
$main-border-color: mix($--background-color-base, $--color-white, 80%);
$block-blur-border-color: $main-border-color;
$block-hover-border-color: mix($main-border-color, $--color-white, 80%);
$block-focus-border-color: mix($main-border-color, $--color-white, 50%);
$block-header-blur-background-color: mix($--color-black, $--color-white, 50%);
$block-header-hover-background-color: mix($--color-primary, $block-header-blur-background-color, 40%);
$block-header-focus-background-color: $--color-primary;
$dock-item-color: $block-blur-border-color;
$dock-item-hover-color: deepskyblue;
$--design-border-color: $--color-primary;
\ No newline at end of file
/**
* Created by rockyl on 2019-09-19.
*/
import {Message, Loading} from "element-ui";
import i18n from './i18n'
export function messageError(e) {
Message({
dangerouslyUseHTMLString: true,
message: `<p style="margin-bottom: 5px;"><strong>${i18n.t(e.message)}</strong></p><p>${e.name}</p>`,
type: 'error'
})
}
export function playWaiting(promise, text) {
const loading = Loading.service({
lock: true,
text: text || i18n.t('In processing'),
});
return promise.catch(e => {
messageError(e);
throw e;
}).finally(() => {
loading.close();
})
}
<template>
<div class="editor">
<tool-bar @click-menu="clickMenu"/>
<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>
<playground splitpanes-min="20" :splitpanes-size="getSize(2, 1)"></playground>
</split-panes>
<assets splitpanes-min="20" :splitpanes-size="getSize(1, 1)"></assets>
</split-panes>
<inspector splitpanes-min="20" :splitpanes-size="getSize(0, 1)"></inspector>
</split-panes>
</div>
</template>
<script>
import SplitPanes from 'splitpanes'
import ToolBar from "./Editor/ToolBar";
import Inspector from "./Editor/Inspector";
import Views from "./Editor/Views";
import Playground from "./Editor/Playground";
import Assets from "./Editor/Assets";
export default {
name: 'Editor',
components: {
Assets,
Playground,
Views,
Inspector,
ToolBar,
SplitPanes,
},
data() {
const panesConfig = localStorage.panesConfig ? JSON.parse(localStorage.panesConfig) : [0.8, 0.8, 0.3];
return {
panesConfig,
}
},
mounted() {
},
methods: {
getSize(id, side) {
let ratio = this.panesConfig[id];
return (side === 0 ? ratio : 1 - ratio) * 100
},
onPanesReSized(id, configs) {
this.panesConfig[id] = configs[0].width / 100;
localStorage.panesConfig = JSON.stringify(this.panesConfig);
},
clickMenu(menuItem){
console.log(menuItem);
}
}
}
</script>
<style lang="scss">
</style>
\ No newline at end of file
<template>
<pane icon="el-icon-s-shop" :title="$t('panes.Assets')">
</pane>
</template>
<script>
import Pane from "../../components/Pane";
export default {
name: "Assets",
components: {Pane}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<pane icon="el-icon-s-operation" :title="$t('panes.Inspector')">
</pane>
</template>
<script>
import Pane from "../../components/Pane";
export default {
name: "Inspector",
components: {Pane}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<pane icon="el-icon-s-open" :title="$t('panes.Playground')">
</pane>
</template>
<script>
import Pane from "../../components/Pane";
export default {
name: "Playground",
components: {Pane}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div class="tool-bar">
<sample-menu :data="menu" @click-menu="clickMenu"/>
</div>
</template>
<script>
import SampleMenu from "../../components/SampleMenu";
export default {
name: "ToolBar",
components: {SampleMenu},
data() {
const menuConfig = this.$t('menu');
const menu = {};
for (let item of Object.keys(menuConfig)) {
menu[item] = {text: menuConfig[item]}
}
return {
menu,
}
},
methods: {
clickMenu(menuItem) {
this.$emit('click-menu', menuItem);
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<pane icon="el-icon-s-grid" :title="$t('panes.Views')">
</pane>
</template>
<script>
import Pane from "../../components/Pane";
export default {
name: "Views",
components: {Pane}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div class="home">
<p class="editor-name" style="font-weight: bold">{{env.name}}<span
class="editor-version">{{env.version}}</span></p>
<main>
<div class="project-list">
<div>
<el-table
:data="projects"
:empty-text="$t('No projects')"
style="width: 100%"
>
<el-table-column
:label="$t('Projects')">
<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="warning">{{moment(scope.row.update_time)}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
fixed="right"
width="140">
<template slot-scope="scope">
<el-button
@click.native.prevent="selectProject(scope.row)"
type="primary" icon="el-icon-edit"
size="small" circle plain>
</el-button>
<el-button
@click.native.prevent="showDuplicateProjectDialog(scope.row)"
type="success" icon="el-icon-document-copy"
size="small" circle plain>
</el-button>
<el-button
@click.native.prevent="deleteProject(scope.row)"
type="danger" icon="el-icon-delete"
size="small" circle plain>
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div>
<el-button @click="showCreateProjectDialog()">{{$t('Create')}}</el-button>
</div>
<create-project-dialog ref="createProjectDialog" @success="onCreateProject"/>
<duplicate-project-dialog ref="duplicateProjectDialog" @success="onDuplicateProject"/>
</main>
</div>
</template>
<script>
import {mapState, mapActions} from 'vuex'
import CreateProjectDialog from "./Home/CreateProjectDialog";
import {playWaiting} from "../utils";
import moment from "moment";
import DuplicateProjectDialog from "./Home/DuplicateProjectDialog";
export default {
name: "Home",
components: {DuplicateProjectDialog, CreateProjectDialog},
data() {
return {
appVersion: 'v1.0.0',
}
},
mounted() {
playWaiting(this.prepare(), this.$t('Preparing')).catch(e => {});
},
computed: {
...mapState([
'projects',
'env',
]),
},
methods: {
prepare(){
return Promise.all([
this.updateProjects(),
this.updateEnv(),
])
},
moment(time) {
return moment(time).format('YYYY-MM-DD HH:mm:ss');
},
showCreateProjectDialog() {
this.$refs.createProjectDialog.show();
},
showDuplicateProjectDialog(project) {
this.$refs.duplicateProjectDialog.show(project);
},
selectProject(row, event) {
this.editProject(row.id);
},
async deleteProject(row, event) {
this.deleteAlert(row);
},
onCreateProject(projectID) {
this.editProject(projectID);
},
onDuplicateProject(projectID) {
this.editProject(projectID);
},
editProject(projectID) {
this.$router.push({name: 'editor', projectID});
},
deleteAlert(project) {
return this.$confirm(this.$t('This action will permanently delete project', {projectName: project.name}), this.$t('Alert'), {
confirmButtonText: this.$t('Confirm'),
cancelButtonText: this.$t('Cancel'),
type: 'warning'
})
},
...mapActions([
'updateProjects',
'updateEnv',
]),
},
}
</script>
<style>
</style>
<template>
<el-dialog :title="$t('Create project')" width="70%" :visible.sync="createDialogVisible" @open="onOpen"
:append-to-body="true">
<el-form ref="form" :model="project" :rules="rules" size="mini" label-position="right" label-width="110px" @submit.native.prevent>
<el-form-item :label="$t('Project name')" prop="name">
<el-input v-model="project.name" :maxlength="64"></el-input>
</el-form-item>
<el-form-item :label="$t('Template')">
<el-select v-model="template" placeholder="Select a template" no-data-text="No templates">
<el-option-group
v-for="(group, groupName) in env.templates" v-if="Object.keys(group).length > 0"
:key="groupName"
:label="groupName">
<el-option
v-for="item in group"
:key="item"
:label="item"
:value="item">
</el-option>
</el-option-group>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="createDialogVisible=false">{{$t('Cancel')}}</el-button>
<el-button size="mini" type="primary" @click="doCreateProject">{{$t('Create')}}</el-button>
</div>
</el-dialog>
</template>
<script>
import {mapState, mapActions} from 'vuex'
import {playWaiting} from "../../utils";
export default {
name: "CreateProjectDialog",
data() {
return {
createDialogVisible: false,
project: {
name: ''
},
template: 'blank',
rules: {
name: [
{required: true, message: this.$t('Project name cannot be empty'), trigger: 'blur'},
]
}
}
},
computed: {
...mapState([
'env',
]),
},
watch: {},
methods: {
async show() {
this.createDialogVisible = true;
},
doCreateProject() {
this.$refs.form.validate(async (valid) => {
if (valid) {
try {
const project = await playWaiting(this.createProject(this.project), this.$t('Creating project'));
this.createDialogVisible = false;
this.$message({
message: this.$t('Create project success'),
type: 'success'
});
this.$emit('success', project.id);
} catch (e) {
}
}
})
},
onOpen() {
this.project.name = '';
},
...mapActions([
'createProject',
]),
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<el-dialog :title="$t('Duplicate project')" width="70%" :visible.sync="createDialogVisible" @open="onOpen" :append-to-body="true">
<el-form ref="form" :model="project" :rules="rules" size="mini" label-position="right" label-width="110px" @submit.native.prevent>
<el-form-item :label="$t('Project name')" prop="name">
<el-input v-model="project.name" :maxlength="64"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="createDialogVisible=false">{{$t('Cancel')}}</el-button>
<el-button size="mini" type="primary" @click="doCreateProject">{{$t('Create')}}</el-button>
</div>
</el-dialog>
</template>
<script>
import {mapState, mapActions} from 'vuex'
import {playWaiting} from "../../utils";
export default {
name: "DuplicateProjectDialog",
data() {
return {
createDialogVisible: false,
project: {
name: ''
},
template: 'blank',
templates: {
builtin: ['blank'],
custom: [],
},
rules: {
name: [
{required: true, message: this.$t('Project name cannot be empty'), trigger: 'blur'},
]
}
}
},
methods: {
async show(project) {
this.project.name = project.name + '-' + this.$t('copy') + '-' + Math.floor(Math.random() * 10000);
this.createDialogVisible = true;
},
doCreateProject() {
this.$refs.form.validate(async (valid)=>{
if(valid){
try {
const project = await playWaiting(this.createProject(this.project), this.$t('Duplicating project'));
this.createDialogVisible = false;
this.$message({
message: this.$t('Duplicate project success'),
type: 'success'
});
this.$emit('success', project.id);
}catch (e) {
}
}
})
},
onOpen() {
//this.project.name = '';
},
...mapActions([
'createProject',
]),
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
module.exports = {
pluginOptions: {
i18n: {
locale: 'en',
fallbackLocale: 'en',
localeDir: 'locales',
enableInSFC: true
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
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