Commit cbea4adce501421098256fff897a8da488801347

Authored by 小小鲁班
Committed by GitHub
2 parents 23ef7209 0d0bf9a7

Merge pull request #248 from ly525/editor-core-package

@luban-h5/core-editor
Showing 100 changed files with 1473 additions and 712 deletions

Too many changes to show.

To preserve performance only 100 of 124 files are displayed.

back-end/h5-api/api/work/config/routes.json
@@ -18,6 +18,14 @@ @@ -18,6 +18,14 @@
18 }, 18 },
19 { 19 {
20 "method": "GET", 20 "method": "GET",
  21 + "path": "/works/editor",
  22 + "handler": "Work.renderCoreEditor",
  23 + "config": {
  24 + "policies": []
  25 + }
  26 + },
  27 + {
  28 + "method": "GET",
21 "path": "/works", 29 "path": "/works",
22 "handler": "Work.find", 30 "handler": "Work.find",
23 "config": { 31 "config": {
back-end/h5-api/api/work/controllers/Work.js
1 /* 1 /*
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-12-04 19:55:24 3 * @Date: 2019-12-04 19:55:24
4 - * @LastEditors : ly525  
5 - * @LastEditTime : 2020-01-01 18:42:41 4 + * @LastEditors: ly525
  5 + * @LastEditTime: 2020-10-11 20:02:09
6 * @FilePath: /luban-h5/back-end/h5-api/api/work/controllers/Work.js 6 * @FilePath: /luban-h5/back-end/h5-api/api/work/controllers/Work.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: 8 * @Description:
@@ -14,7 +14,7 @@ const _ = require('lodash'); @@ -14,7 +14,7 @@ const _ = require('lodash');
14 // 浏览模式 14 // 浏览模式
15 const VIEW_MODE = { 15 const VIEW_MODE = {
16 PREVIEW: 'preview' // 预览 16 PREVIEW: 'preview' // 预览
17 -} 17 +};
18 18
19 /** 19 /**
20 * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html#core-controllers) 20 * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html#core-controllers)
@@ -25,14 +25,17 @@ module.exports = { @@ -25,14 +25,17 @@ module.exports = {
25 // GET /previewOne 25 // GET /previewOne
26 // strapi-hook-ejs: https://github.com/strapi/strapi/tree/master/packages/strapi-hook-ejs 26 // strapi-hook-ejs: https://github.com/strapi/strapi/tree/master/packages/strapi-hook-ejs
27 previewOne: async (ctx) => { 27 previewOne: async (ctx) => {
28 - const { view_mode } = ctx.request.query 28 + const { view_mode } = ctx.request.query;
29 const work = await strapi.services.work.findOne(ctx.params); 29 const work = await strapi.services.work.findOne(ctx.params);
30 // 非发布状态, 查看不到内容 30 // 非发布状态, 查看不到内容
31 // 非预览模式, 查看不到内容 31 // 非预览模式, 查看不到内容
32 - const canRender = view_mode === VIEW_MODE.PREVIEW || work.is_publish  
33 - if (!canRender) work.pages = [] 32 + const canRender = view_mode === VIEW_MODE.PREVIEW || work.is_publish;
  33 + if (!canRender) work.pages = [];
34 return ctx.render('engine', { work }); 34 return ctx.render('engine', { work });
35 }, 35 },
  36 + renderCoreEditor: async (ctx) => {
  37 + return ctx.render('core-editor');
  38 + },
36 submitForm: async (ctx) => { 39 submitForm: async (ctx) => {
37 const work = await strapi.services.work.findOne(ctx.params); 40 const work = await strapi.services.work.findOne(ctx.params);
38 const formData = ctx.request.body; 41 const formData = ctx.request.body;
back-end/h5-api/api/work/documentation/1.0.0/work.json
@@ -114,6 +114,63 @@ @@ -114,6 +114,63 @@
114 "parameters": [] 114 "parameters": []
115 } 115 }
116 }, 116 },
  117 + "/works/editor": {
  118 + "get": {
  119 + "deprecated": false,
  120 + "description": "",
  121 + "responses": {
  122 + "200": {
  123 + "description": "response",
  124 + "content": {
  125 + "application/json": {
  126 + "schema": {
  127 + "properties": {
  128 + "foo": {
  129 + "type": "string"
  130 + }
  131 + }
  132 + }
  133 + }
  134 + }
  135 + },
  136 + "403": {
  137 + "description": "Forbidden",
  138 + "content": {
  139 + "application/json": {
  140 + "schema": {
  141 + "$ref": "#/components/schemas/Error"
  142 + }
  143 + }
  144 + }
  145 + },
  146 + "404": {
  147 + "description": "Not found",
  148 + "content": {
  149 + "application/json": {
  150 + "schema": {
  151 + "$ref": "#/components/schemas/Error"
  152 + }
  153 + }
  154 + }
  155 + },
  156 + "default": {
  157 + "description": "unexpected error",
  158 + "content": {
  159 + "application/json": {
  160 + "schema": {
  161 + "$ref": "#/components/schemas/Error"
  162 + }
  163 + }
  164 + }
  165 + }
  166 + },
  167 + "summary": "",
  168 + "tags": [
  169 + "Work"
  170 + ],
  171 + "parameters": []
  172 + }
  173 + },
117 "/works": { 174 "/works": {
118 "get": { 175 "get": {
119 "deprecated": false, 176 "deprecated": false,
back-end/h5-api/views/core-editor.ejs 0 → 100644
  1 +<html>
  2 + <head>
  3 + <meta charset="UTF-8">
  4 + <title>鲁班H5 编辑器</title>
  5 + <script src="https://unpkg.com/vue"></script>
  6 + <script src="https://unpkg.com/@luban-h5/core-editor"></script>
  7 + </head>
  8 + <body>
  9 + <div id="app"> <core-editor :work-id="id" /></div>
  10 + <script>
  11 + const id = new URLSearchParams(window.location.search).get('id')
  12 + new Vue({ data: () => ({id }), el: '#app'});
  13 + </script>
  14 + </body>
  15 +</html>
0 \ No newline at end of file 16 \ No newline at end of file
front-end/h5/package.json
@@ -11,7 +11,8 @@ @@ -11,7 +11,8 @@
11 "test:e2e": "vue-cli-service test:e2e", 11 "test:e2e": "vue-cli-service test:e2e",
12 "test:unit": "vue-cli-service test:unit", 12 "test:unit": "vue-cli-service test:unit",
13 "build:editor": "cross-env PAGE=EDITOR vue-cli-service build", 13 "build:editor": "cross-env PAGE=EDITOR vue-cli-service build",
14 - "build:engine": "cross-env PAGE=ENGINE vue-cli-service build --target lib --name engine ./src/engine-entry.js" 14 + "build:engine": "cross-env PAGE=ENGINE vue-cli-service build --target lib --name engine ./src/engine-entry.js",
  15 + "build:core_editor": "cross-env PAGE=CORE_EDITOR vue-cli-service build --target lib --name core-editor ./src/components/core/index.js"
15 }, 16 },
16 "dependencies": { 17 "dependencies": {
17 "@luban-h5/lbc-button": "^0.0.3", 18 "@luban-h5/lbc-button": "^0.0.3",
front-end/h5/public/index.html
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 * @FilePath: /luban-h5/front-end/h5/public/index.html 6 * @FilePath: /luban-h5/front-end/h5/public/index.html
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 --> 10 -->
11 <!DOCTYPE html> 11 <!DOCTYPE html>
12 <html lang="en"> 12 <html lang="en">
front-end/h5/src/App.vue
1 <template> 1 <template>
2 <div id="app"> 2 <div id="app">
3 - <!-- <div id="nav">  
4 - <router-link to="/">Home</router-link> |  
5 - <router-link to="/about">About</router-link>  
6 - </div> -->  
7 <router-view/> 3 <router-view/>
8 </div> 4 </div>
9 </template> 5 </template>
front-end/h5/src/components/common/header/LangSelect.vue
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 </template> 20 </template>
21 21
22 <script> 22 <script>
23 -import langMixin from '@/mixins/i18n' 23 +import langMixin from 'core/mixins/i18n'
24 24
25 export default { 25 export default {
26 name: 'LangSelect', 26 name: 'LangSelect',
front-end/h5/src/components/common/header/index.vue 0 → 100644
  1 +<template>
  2 + <a-layout-header class="layout-header">
  3 + <LogoOfHeader />
  4 + <div style="float:right;">
  5 + <Links />
  6 + <slot name="action-menu"></slot>
  7 + <LangSelect />
  8 + </div>
  9 + </a-layout-header>
  10 +</template>
  11 +<script>
  12 +import LogoOfHeader from './logo.js'
  13 +import LangSelect from './LangSelect'
  14 +import Links from './links'
  15 +export default {
  16 + name: 'Header',
  17 + components: {
  18 + LogoOfHeader,
  19 + LangSelect,
  20 + Links
  21 + }
  22 +}
  23 +</script>
  24 +<style lang="scss" scoped>
  25 +.layout-header {
  26 + padding: 0 10px;
  27 + .logo {
  28 + width: 120px;
  29 + height: 31px;
  30 + margin: 16px 28px 16px 0;
  31 + float: left;
  32 +
  33 + line-height: 31px;
  34 + text-align: center;
  35 + color: white;
  36 + font-size: 16px;
  37 + }
  38 +
  39 + .lang-select-activator,
  40 + .user-avatar-activator {
  41 + // float: right;
  42 + background: transparent;
  43 + margin: 0 28px 16px 0;
  44 + cursor: pointer;
  45 +
  46 + .anticon {
  47 + color: white;
  48 + }
  49 + }
  50 +}
  51 +</style>
front-end/h5/src/components/common/header/links.js
@@ -10,7 +10,7 @@ export default { @@ -10,7 +10,7 @@ export default {
10 theme="dark" 10 theme="dark"
11 mode="horizontal" 11 mode="horizontal"
12 defaultSelectedKeys={['2']} 12 defaultSelectedKeys={['2']}
13 - style={{ lineHeight: '64px', display: 'inline-block', float: 'right' }} 13 + style={{ lineHeight: '64px', display: 'inline-block' }}
14 > 14 >
15 <a-menu-item key="dingtalk" > 15 <a-menu-item key="dingtalk" >
16 <a-popover title="👨🏻‍💻👩🏻‍💻欢迎加入鲁班-H5交流群"> 16 <a-popover title="👨🏻‍💻👩🏻‍💻欢迎加入鲁班-H5交流群">
front-end/h5/src/components/common/work/card-cover.js
1 /* 1 /*
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-12-01 18:11:49 3 * @Date: 2019-12-01 18:11:49
4 - * @LastEditors : ly525  
5 - * @LastEditTime : 2020-01-04 13:51:26 4 + * @LastEditors: ly525
  5 + * @LastEditTime: 2020-10-10 23:29:06
6 * @FilePath: /luban-h5/front-end/h5/src/components/common/work/card-cover.js 6 * @FilePath: /luban-h5/front-end/h5/src/components/common/work/card-cover.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import placeholderImg from '@/assets/lbp-picture-placeholder.png' 11 import placeholderImg from '@/assets/lbp-picture-placeholder.png'
  12 +import './card-cover.scss'
12 13
13 function getDefaultStyle (img, isPlaceholder) { 14 function getDefaultStyle (img, isPlaceholder) {
14 return { 15 return {
front-end/h5/src/components/common/work/card-cover.scss 0 → 100644
  1 +.card-cover-wrapper {
  2 + position: relative;
  3 + height: 300px;
  4 + border: 1px dashed #eee;
  5 + color: #aaa;
  6 + padding: 4px;
  7 +}
0 \ No newline at end of file 8 \ No newline at end of file
front-end/h5/src/constants/animation.js renamed to front-end/h5/src/components/core/constants/animation.js
front-end/h5/src/constants/work.js renamed to front-end/h5/src/components/core/constants/work.js
front-end/h5/src/components/core/editor/canvas/edit.js
1 import { mapState, mapActions } from 'vuex' 1 import { mapState, mapActions } from 'vuex'
2 -import Shape from '../../support/shape'  
3 -import ContextMenu from '../../support/contexmenu' 2 +import Shape from 'core/support/shape'
  3 +import ContextMenu from 'core/support/contexmenu'
4 4
5 export default { 5 export default {
6 props: ['elements', 'handleClickElementProp', 'handleClickCanvasProp'], 6 props: ['elements', 'handleClickElementProp', 'handleClickCanvasProp'],
front-end/h5/src/components/core/editor/canvas/index.js 0 → 100644
  1 +import { mapState, mapActions } from 'vuex'
  2 +
  3 +import RenderEditCanvas from './edit'
  4 +import RenderPreviewCanvas from './preview'
  5 +
  6 +export default {
  7 + name: 'EditorCanvas',
  8 + data: () => ({
  9 + isPreviewMode: false
  10 + }),
  11 + computed: {
  12 + ...mapState('editor', {
  13 + editingPage: state => state.editingPage,
  14 + editingElement: state => state.editingElement,
  15 + elements: state => state.editingPage.elements,
  16 + pages: state => state.work.pages,
  17 + work: state => state.work,
  18 + scaleRate: state => state.scaleRate
  19 + }),
  20 + ...mapState('loading', [
  21 + 'saveWork_loading',
  22 + 'previewWork_loading',
  23 + 'setWorkAsTemplate_loading',
  24 + 'uploadWorkCover_loading'
  25 + ])
  26 + },
  27 + methods: {
  28 + ...mapActions('editor', [
  29 + 'elementManager',
  30 + 'pageManager',
  31 + 'saveWork',
  32 + 'createWork',
  33 + 'fetchWork',
  34 + 'updateWork',
  35 + 'setWorkAsTemplate',
  36 + 'setEditingElement',
  37 + 'setEditingPage'
  38 + ]),
  39 + handleToggleMode (isPreviewMode) {
  40 + this.isPreviewMode = isPreviewMode
  41 + if (isPreviewMode) {
  42 + // 当切换到预览模式的时候,清空当前编辑元素
  43 + this.setEditingElement() // 相当于 setEditingElement(null)
  44 + }
  45 + }
  46 + },
  47 + render (h) {
  48 + return (
  49 + <a-layout id="canvas-outer-wrapper">
  50 + <a-radio-group
  51 + class="mode-toggle-wrapper"
  52 + size="small"
  53 + value={this.isPreviewMode}
  54 + onInput={this.handleToggleMode}
  55 + >
  56 + {/* 编辑模式、预览模式 */}
  57 + <a-radio-button label={false} value={false}>{this.$t('editor.centerPanel.mode.edit')}</a-radio-button>
  58 + <a-radio-button label={true} value={true}>{this.$t('editor.centerPanel.mode.preview')}</a-radio-button>
  59 + </a-radio-group>
  60 + <a-layout-content style={{ transform: `scale(${this.scaleRate})`, 'transform-origin': 'center top' }}>
  61 + <div class='canvas-wrapper' style={{
  62 + height: `${this.work.height}px`
  63 + }}>
  64 + { this.isPreviewMode
  65 + ? <RenderPreviewCanvas elements={this.elements}/>
  66 + : <RenderEditCanvas
  67 + class="edit-mode"
  68 + elements={this.elements}
  69 + />
  70 + }
  71 + </div>
  72 + </a-layout-content>
  73 + </a-layout>
  74 + )
  75 + }
  76 +}
front-end/h5/src/components/core/editor/canvas/preview.js
1 -import NodeWrapper from '@/components/preview/node-wrapper.js' 1 +import NodeWrapper from 'core/preview/node-wrapper.js'
2 /** 2 /**
3 * 预览模块 3 * 预览模块
4 * preview h5 work module 4 * preview h5 work module
front-end/h5/src/components/core/editor/fixed-tools/index.js 0 → 100644
  1 +import { mapActions, mapState } from 'vuex'
  2 +import hotkeys from 'hotkeys-js'
  3 +import fixedTools from './options'
  4 +
  5 +export default {
  6 + computed: {
  7 + ...mapState('editor', {
  8 + scaleRate: state => state.scaleRate
  9 + })
  10 + },
  11 + methods: {
  12 + ...mapActions('editor', ['pageManager', 'elementManager', 'updateScaleRate'])
  13 + },
  14 + render () {
  15 + return (
  16 + <a-layout-sider
  17 + width="40"
  18 + theme='light'
  19 + style={{ background: '#fff', border: '1px solid #eee' }}
  20 + >
  21 + <a-button-group style={{ display: 'flex', flexDirection: 'column' }}>
  22 + {
  23 + fixedTools.map(tool => (
  24 + <a-tooltip
  25 + effect="dark"
  26 + placement="left"
  27 + title={this.$t(tool.i18nTooltip, { hotkey: tool.hotkeyTooltip })}>
  28 + <a-button
  29 + block
  30 + class="transparent-bg"
  31 + type="link"
  32 + size="small"
  33 + style={{ height: '40px', color: '#000' }}
  34 + disabled={!!tool.disabled}
  35 + onClick={() => tool.action && tool.action.call(this)}
  36 + >
  37 + {
  38 + tool.icon
  39 + ? <i class={['shortcut-icon', 'fa', `fa-${tool.icon}`]} aria-hidden='true' />
  40 + : (tool.text || this.$t(tool.i18nTooltip))
  41 + }
  42 + </a-button>
  43 + { tool.icon === 'minus' && <div style={{ fontSize: '12px', textAlign: 'center' }}>{this.scaleRate * 100}%</div>}
  44 + </a-tooltip>
  45 + ))
  46 + }
  47 + </a-button-group>
  48 + </a-layout-sider>
  49 + )
  50 + },
  51 + mounted () {
  52 + fixedTools.map(tool => {
  53 + tool.hotkey && hotkeys(tool.hotkey, { splitKey: '&' }, (event, handler) => {
  54 + event.preventDefault()
  55 + event.stopPropagation()
  56 + tool.action && tool.action.call(this)
  57 + })
  58 + })
  59 + }
  60 +}
front-end/h5/src/components/core/editor/fixed-tools/options.js 0 → 100644
  1 +import undoRedoHistory from 'core/store/plugins/undo-redo/History'
  2 +
  3 +const fixedTools = [
  4 + {
  5 + i18nTooltip: 'editor.fixedTool.undo',
  6 + icon: 'mail-reply',
  7 + action: () => undoRedoHistory.undo(),
  8 + hotkey: 'ctrl&z,⌘&z',
  9 + hotkeyTooltip: '(ctrl+z)'
  10 + },
  11 + {
  12 + i18nTooltip: 'editor.fixedTool.redo',
  13 + icon: 'mail-forward',
  14 + action: () => undoRedoHistory.redo(),
  15 + hotkey: 'ctrl&y,⌘&u',
  16 + hotkeyTooltip: '(ctrl+y)'
  17 + },
  18 + {
  19 + i18nTooltip: 'editor.fixedTool.preview',
  20 + icon: 'eye',
  21 + action: function () { this.previewDialogVisible = true }
  22 + },
  23 + {
  24 + i18nTooltip: 'editor.fixedTool.copyCurrentPage',
  25 + icon: 'copy',
  26 + action: function () { this.pageManager({ type: 'copy' }) },
  27 + hotkey: 'ctrl&c,⌘&c'
  28 + },
  29 + {
  30 + i18nTooltip: 'editor.fixedTool.copyCurrentElement',
  31 + icon: 'copy',
  32 + action: function () { this.elementManager({ type: 'copy' }) }
  33 + },
  34 + {
  35 + i18nTooltip: 'editor.fixedTool.importPSD',
  36 + text: 'Ps',
  37 + icon: '', // 优先级: icon > text > i18nTooltip
  38 + action: '',
  39 + disabled: true
  40 + },
  41 + {
  42 + i18nTooltip: 'editor.fixedTool.zoomOut',
  43 + icon: 'plus',
  44 + action: function () { this.updateScaleRate(0.25) },
  45 + hotkey: 'ctrl&=,⌘&=',
  46 + hotkeyTooltip: '(ctrl +)'
  47 + },
  48 + {
  49 + i18nTooltip: 'editor.fixedTool.zoomIn',
  50 + icon: 'minus',
  51 + action: function () { this.updateScaleRate(-0.25) },
  52 + hotkey: 'ctrl&-,⌘&-',
  53 + hotkeyTooltip: '(ctrl -)'
  54 + },
  55 + {
  56 + i18nTooltip: 'editor.fixedTool.issues',
  57 + icon: 'question',
  58 + action: function () { window.open('https://github.com/ly525/luban-h5/issues/110') }
  59 + }
  60 +]
  61 +
  62 +export default fixedTools
front-end/h5/src/components/core/editor/header/action-menu.js 0 → 100644
  1 +import { mapState, mapActions } from 'vuex'
  2 +
  3 +export default {
  4 + name: 'EditorActionMenu',
  5 + data: () => ({
  6 + previewDialogVisible: false,
  7 + propsPanelWidth: 320
  8 + }),
  9 + computed: {
  10 + ...mapState('editor', {
  11 + editingPage: state => state.editingPage,
  12 + editingElement: state => state.editingElement,
  13 + elements: state => state.editingPage.elements,
  14 + pages: state => state.work.pages,
  15 + work: state => state.work
  16 + }),
  17 + ...mapState('loading', [
  18 + 'saveWork_loading',
  19 + 'previewWork_loading',
  20 + 'setWorkAsTemplate_loading',
  21 + 'uploadWorkCover_loading'
  22 + ])
  23 + },
  24 + methods: {
  25 + ...mapActions('editor', [
  26 + 'elementManager',
  27 + 'pageManager',
  28 + 'saveWork',
  29 + 'createWork',
  30 + 'fetchWork',
  31 + 'updateWork',
  32 + 'setWorkAsTemplate',
  33 + // 'setEditingElement',
  34 + 'setEditingPage'
  35 + ]),
  36 + ...mapActions('loading', {
  37 + updateLoading: 'update'
  38 + }),
  39 + handlePreview () {
  40 + this.saveWork({ loadingName: 'previewWork_loading' }).then(() => {
  41 + this.$emit('preview')
  42 + // this.previewDialogVisible = true
  43 + })
  44 + },
  45 + handleSave () {
  46 + this.saveWork({ isSaveCover: true })
  47 + },
  48 + handlePublish () {
  49 + this.updateWork({ is_publish: true })
  50 + this.saveWork({ successMsg: '发布成功' })
  51 + },
  52 + handleSetAsTemplate () {
  53 + this.updateLoading({ type: 'setWorkAsTemplate_loading', value: true })
  54 + this.saveWork().then(() => {
  55 + this.setWorkAsTemplate()
  56 + })
  57 + },
  58 + handleSelectItem ({ key }) {
  59 + switch (key) {
  60 + case 'setAsTemplate':
  61 + this.handleSetAsTemplate()
  62 + }
  63 + }
  64 + },
  65 + render (h) {
  66 + return (
  67 + <a-menu
  68 + slot="action-menu"
  69 + theme="dark"
  70 + mode="horizontal"
  71 + defaultSelectedKeys={['2']}
  72 + style={{ lineHeight: '64px', float: 'right', background: 'transparent' }}
  73 + >
  74 + {/* 保存、预览、发布、设置为模板 */}
  75 + <a-menu-item key="1" class="transparent-bg">
  76 + <a-button
  77 + type="primary"
  78 + size="small"
  79 + onClick={this.handlePreview}
  80 + loading={this.previewWork_loading}
  81 + >{this.$t('editor.header.preview')}</a-button>
  82 + </a-menu-item>
  83 + <a-menu-item key="2" class="transparent-bg">
  84 + <a-button
  85 + size="small"
  86 + onClick={this.handleSave}
  87 + loading={this.saveWork_loading || this.uploadWorkCover_loading}
  88 + >{this.$t('editor.header.save')}</a-button>
  89 + </a-menu-item>
  90 + {/* <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item> */}
  91 + <a-menu-item key="3" class="transparent-bg">
  92 + <a-dropdown-button
  93 + size="small"
  94 + onClick={this.handlePublish}
  95 + loading={this.saveWork_loading || this.uploadWorkCover_loading}
  96 + >
  97 + {this.$t('editor.header.publish') /* 发布 */}
  98 + <a-menu slot="overlay" onClick={this.handleSelectItem}>
  99 + <a-menu-item key="setAsTemplate">
  100 + <a-spin spinning={this.setWorkAsTemplate_loading} size="small">
  101 + {/* 设置为模板 */}
  102 + <a-icon type="cloud-upload" />{this.$t('editor.header.setAsTemplate')}
  103 + </a-spin>
  104 + </a-menu-item>
  105 + {/* <a-menu-item key="2"><a-icon type="user" />2nd menu item</a-menu-item> */}
  106 + {/* <a-menu-item key="3"><a-icon type="user" />3rd item</a-menu-item> */}
  107 + </a-menu>
  108 + </a-dropdown-button>
  109 + </a-menu-item>
  110 + </a-menu>
  111 + )
  112 + }
  113 +}
front-end/h5/src/components/core/editor/index.js deleted 100644 → 0
1 -import { mapState, mapActions } from 'vuex'  
2 -import hotkeys from 'hotkeys-js'  
3 -import undoRedoHistory from '../../../store/plugins/undo-redo/History'  
4 -  
5 -import '../styles/index.scss'  
6 -import 'animate.css'  
7 -  
8 -import RenderEditCanvas from './canvas/edit'  
9 -import RenderPreviewCanvas from './canvas/preview'  
10 -import RenderPropsEditor from './edit-panel/props'  
11 -import RenderScriptEditor from './edit-panel/script'  
12 -import RenderAnimationEditor from './edit-panel/animation'  
13 -import RenderActionEditor from './edit-panel/action'  
14 -import RenderBackgroundEditor from './edit-panel/background'  
15 -import RenderShortcutsPanel from './shortcuts-panel/index'  
16 -import RenderPageManager from './page-manager/index'  
17 -import PreviewDialog from './modals/preview.vue'  
18 -  
19 -import LogoOfHeader from '@/components/common/header/logo.js'  
20 -import ExternalLinksOfHeader from '@/components/common/header/links.js'  
21 -import LangSelect from '@/components/common/header/LangSelect.vue'  
22 -import Feedback from '@/components/common/feedback/index'  
23 -import AdjustLineV from '@/components/core/support/adjust-line/vertical'  
24 -  
25 -import DragMixin from './drag-mixin'  
26 -  
27 -const fixedTools = [  
28 - {  
29 - i18nTooltip: 'editor.fixedTool.undo',  
30 - icon: 'mail-reply',  
31 - action: () => undoRedoHistory.undo(),  
32 - hotkey: 'ctrl&z,⌘&z',  
33 - hotkeyTooltip: '(ctrl+z)'  
34 - },  
35 - {  
36 - i18nTooltip: 'editor.fixedTool.redo',  
37 - icon: 'mail-forward',  
38 - action: () => undoRedoHistory.redo(),  
39 - hotkey: 'ctrl&y,⌘&u',  
40 - hotkeyTooltip: '(ctrl+y)'  
41 - },  
42 - {  
43 - i18nTooltip: 'editor.fixedTool.preview',  
44 - icon: 'eye',  
45 - action: function () { this.previewDialogVisible = true }  
46 - },  
47 - {  
48 - i18nTooltip: 'editor.fixedTool.copyCurrentPage',  
49 - icon: 'copy',  
50 - action: function () { this.pageManager({ type: 'copy' }) },  
51 - hotkey: 'ctrl&c,⌘&c'  
52 - },  
53 - {  
54 - i18nTooltip: 'editor.fixedTool.copyCurrentElement',  
55 - icon: 'copy',  
56 - action: function () { this.elementManager({ type: 'copy' }) }  
57 - },  
58 - {  
59 - i18nTooltip: 'editor.fixedTool.importPSD',  
60 - text: 'Ps',  
61 - icon: '', // 优先级: icon > text > i18nTooltip  
62 - action: '',  
63 - disabled: true  
64 - },  
65 - {  
66 - i18nTooltip: 'editor.fixedTool.zoomOut',  
67 - icon: 'plus',  
68 - action: function () { this.scaleRate += 0.25 },  
69 - hotkey: 'ctrl&=,⌘&=',  
70 - hotkeyTooltip: '(ctrl +)'  
71 - },  
72 - {  
73 - i18nTooltip: 'editor.fixedTool.zoomIn',  
74 - icon: 'minus',  
75 - action: function () { this.scaleRate -= 0.25 },  
76 - hotkey: 'ctrl&-,⌘&-',  
77 - hotkeyTooltip: '(ctrl -)'  
78 - },  
79 - {  
80 - i18nTooltip: 'editor.fixedTool.issues',  
81 - icon: 'question',  
82 - action: function () { window.open('https://github.com/ly525/luban-h5/issues/110') }  
83 - }  
84 -]  
85 -  
86 -export default {  
87 - mixins: [DragMixin],  
88 - name: 'Editor',  
89 - components: {  
90 - LogoOfHeader,  
91 - ExternalLinksOfHeader,  
92 - LangSelect  
93 - },  
94 - data: () => ({  
95 - activeMenuKey: 'pluginList',  
96 - isPreviewMode: false,  
97 - activeTabKey: '属性',  
98 - previewDialogVisible: false,  
99 - scaleRate: 1,  
100 - propsPanelWidth: 320  
101 - }),  
102 - computed: {  
103 - ...mapState('editor', {  
104 - editingPage: state => state.editingPage,  
105 - editingElement: state => state.editingElement,  
106 - elements: state => state.editingPage.elements,  
107 - pages: state => state.work.pages,  
108 - work: state => state.work  
109 - }),  
110 - ...mapState('loading', [  
111 - 'saveWork_loading',  
112 - 'previewWork_loading',  
113 - 'setWorkAsTemplate_loading',  
114 - 'uploadWorkCover_loading'  
115 - ])  
116 - },  
117 - methods: {  
118 - ...mapActions('editor', [  
119 - 'elementManager',  
120 - 'pageManager',  
121 - 'saveWork',  
122 - 'createWork',  
123 - 'fetchWork',  
124 - 'updateWork',  
125 - 'setWorkAsTemplate',  
126 - 'setEditingElement',  
127 - 'setEditingPage'  
128 - ]),  
129 - ...mapActions('loading', {  
130 - updateLoading: 'update'  
131 - }),  
132 - /**  
133 - * !#zh 点击插件,copy 其基础数据到组件树(中间画布)  
134 - * #!en click the plugin shortcut, create new Element with the plugin's meta data  
135 - * pluginInfo {Object}: 插件列表中的基础数据, {name}=pluginInfo  
136 - *  
137 - * shortcutItem: PluginListItem = {  
138 - name: String,  
139 - shortcutProps: {}  
140 - }  
141 - */  
142 - clone (shortcutItem) {  
143 - this.elementManager({  
144 - type: 'add',  
145 - value: shortcutItem  
146 - })  
147 - },  
148 - /**  
149 - * #!zh: 设置 背景图tab 作为 active tab  
150 - * #!en: set background(bg) tab as active tab  
151 - */  
152 - setActiveTab (activeTabKey) {  
153 - this.activeTabKey = activeTabKey  
154 - },  
155 - _renderMenuContent () {  
156 - return (  
157 - <a-tabs  
158 - style="height: 100%;"  
159 - tabBarGutter={10}  
160 - >  
161 - <a-tab-pane key="plugin-list" tab={this.$t('editor.sidebar.components')}>  
162 - <div class="plugin-usage-tip ">  
163 - <a-icon type="info-circle" />  
164 - {/* <span class="ml-1">使用提示: <strong>点击</strong>组件即可</span> */}  
165 - {/* Tip: just click on component */}  
166 - <i18n path="editor.tip.componentUsage" tag="span" class="ml-1">  
167 - <strong>{ this.$t('editor.tip.click') }</strong>{ this.$t('editor.tip.click') }  
168 - </i18n>  
169 - </div>  
170 - <RenderShortcutsPanel  
171 - pluginsList={this.pluginsList}  
172 - handleClickShortcut={this.clone}  
173 - handleDragStart={this.handleDragStartFromMixin}  
174 - />  
175 - </a-tab-pane>  
176 - <a-tab-pane key='page-manager' tab={this.$t('editor.sidebar.pages')}>  
177 - <RenderPageManager  
178 - pages={this.pages}  
179 - editingPage={this.editingPage}  
180 - onSelectMenuItem={(menuKey) => {  
181 - this.pageManager({ type: menuKey })  
182 - }}  
183 - onEditTitle={({ pageIndexForEditingTitle, newTitle }) => {  
184 - this.pageManager({ type: 'editTitle', value: { pageIndexForEditingTitle, newTitle } })  
185 - this.saveWork({ isSaveCover: false })  
186 - }}  
187 - onSelectPage={(pageIndex) => { this.setEditingPage(pageIndex) }}  
188 - />  
189 - </a-tab-pane>  
190 - </a-tabs>  
191 - )  
192 - },  
193 - handlePreview () {  
194 - this.saveWork({ loadingName: 'previewWork_loading' }).then(() => {  
195 - this.previewDialogVisible = true  
196 - })  
197 - },  
198 - handleSave () {  
199 - this.saveWork({ isSaveCover: true })  
200 - },  
201 - handlePublish () {  
202 - this.updateWork({ is_publish: true })  
203 - this.saveWork({ successMsg: '发布成功' })  
204 - }  
205 - },  
206 - mounted () {  
207 - fixedTools.map(tool => {  
208 - tool.hotkey && hotkeys(tool.hotkey, { splitKey: '&' }, (event, handler) => {  
209 - event.preventDefault()  
210 - event.stopPropagation()  
211 - tool.action && tool.action.call(this)  
212 - })  
213 - })  
214 - },  
215 - render (h) {  
216 - return (  
217 - <a-layout id="luban-editor-layout" style={{ height: '100vh' }}>  
218 - <a-layout-header class="header">  
219 - <LogoOfHeader />  
220 - <LangSelect style="float: right;cursor: pointer;" />  
221 - {/* we can show the plugins shortcuts here */}  
222 - <a-menu  
223 - theme="dark"  
224 - mode="horizontal"  
225 - defaultSelectedKeys={['2']}  
226 - style={{ lineHeight: '64px', float: 'right', background: 'transparent' }}  
227 - >  
228 - {/* 保存、预览、发布、设置为模板 */}  
229 - <a-menu-item key="1" class="transparent-bg">  
230 - <a-button  
231 - type="primary"  
232 - size="small"  
233 - onClick={this.handlePreview}  
234 - loading={this.previewWork_loading}  
235 - >{this.$t('editor.header.preview')}</a-button>  
236 - </a-menu-item>  
237 - <a-menu-item key="2" class="transparent-bg">  
238 - <a-button  
239 - size="small"  
240 - onClick={this.handleSave}  
241 - loading={this.saveWork_loading || this.uploadWorkCover_loading}  
242 - >{this.$t('editor.header.save')}</a-button>  
243 - </a-menu-item>  
244 - {/* <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item> */}  
245 - <a-menu-item key="3" class="transparent-bg">  
246 - <a-dropdown-button  
247 - size="small"  
248 - onClick={this.handlePublish}  
249 - loading={this.saveWork_loading || this.uploadWorkCover_loading}  
250 - >  
251 - {/* 发布 */}  
252 - {this.$t('editor.header.publish')}  
253 - <a-menu slot="overlay" onClick={({ key }) => {  
254 - switch (key) {  
255 - case 'setAsTemplate':  
256 - this.updateLoading({ type: 'setWorkAsTemplate_loading', value: true })  
257 - this.saveWork().then(() => {  
258 - this.setWorkAsTemplate()  
259 - })  
260 - }  
261 - }}>  
262 - <a-menu-item key="setAsTemplate">  
263 - <a-spin spinning={this.setWorkAsTemplate_loading} size="small">  
264 - {/* 设置为模板 */}  
265 - <a-icon type="cloud-upload" />{this.$t('editor.header.setAsTemplate')}  
266 - </a-spin>  
267 - </a-menu-item>  
268 - {/* <a-menu-item key="2"><a-icon type="user" />2nd menu item</a-menu-item> */}  
269 - {/* <a-menu-item key="3"><a-icon type="user" />3rd item</a-menu-item> */}  
270 - </a-menu>  
271 - </a-dropdown-button>  
272 - </a-menu-item>  
273 - </a-menu>  
274 - <ExternalLinksOfHeader />  
275 - </a-layout-header>  
276 - <a-layout>  
277 - {/* <a-layout-sider collapsedWidth={40} style="background: #fff" collapsed>  
278 - <a-menu  
279 - mode="inline"  
280 - defaultSelectedKeys={['pluginList']}  
281 - style={{ height: '100%', borderRight: 1 }}  
282 - onSelect={({ key }) => { this.activeMenuKey = key }}  
283 - >  
284 - {  
285 - sidebarMenus.map(menu => (  
286 - <a-menu-item key={menu.value}>  
287 - <a-icon type={menu.antIcon} />  
288 - <span>{this.$t(menu.i18nLabel)}</span>  
289 - </a-menu-item>  
290 - ))  
291 - }  
292 - </a-menu>  
293 - </a-layout-sider> */}  
294 - <a-layout-sider width="240" theme='light' style={{ background: '#fff', padding: '12px' }}>  
295 - { this._renderMenuContent() }  
296 - </a-layout-sider>  
297 - <a-layout id="canvas-outer-wrapper">  
298 - <div class="mode-toggle-wrapper">  
299 - <a-radio-group  
300 - size="small"  
301 - value={this.isPreviewMode}  
302 - onInput={isPreviewMode => {  
303 - this.isPreviewMode = isPreviewMode  
304 - if (isPreviewMode) {  
305 - // 当切换到预览模式的时候,清空当前编辑元素  
306 - this.setEditingElement() // 相当于 setEditingElement(null)  
307 - }  
308 - }}  
309 - >  
310 - {/* 编辑模式、预览模式 */}  
311 - <a-radio-button label={false} value={false}>{this.$t('editor.centerPanel.mode.edit')}</a-radio-button>  
312 - <a-radio-button label={true} value={true}>{this.$t('editor.centerPanel.mode.preview')}</a-radio-button>  
313 - </a-radio-group>  
314 - </div>  
315 - <a-layout-content style={{ transform: `scale(${this.scaleRate})`, 'transform-origin': 'center top' }}>  
316 - <div class='canvas-wrapper' style={{  
317 - height: `${this.work.height}px`  
318 - }}>  
319 - {/* { this.isPreviewMode ? this.renderPreview(h, this.elements) : this.renderCanvas(h, this.elements) } */}  
320 - { this.isPreviewMode  
321 - ? <RenderPreviewCanvas elements={this.elements}/>  
322 - : <RenderEditCanvas  
323 - class="edit-mode"  
324 - elements={this.elements}  
325 - />  
326 - }  
327 - </div>  
328 - </a-layout-content>  
329 - </a-layout>  
330 - <AdjustLineV onLineMove={(offset) => {  
331 - this.propsPanelWidth += offset  
332 - }} />  
333 - <a-layout-sider width="40" theme='light' style={{ background: '#fff', border: '1px solid #eee' }}>  
334 - {/* <div>  
335 - <a-button shape="circle" icon="search" type="link" />  
336 - </div> */}  
337 - <a-button-group style={{ display: 'flex', flexDirection: 'column' }}>  
338 - {  
339 - fixedTools.map(tool => (  
340 - <a-tooltip effect="dark" placement="left" title={this.$t(tool.i18nTooltip, { hotkey: tool.hotkeyTooltip })}>  
341 - <a-button block class="transparent-bg" type="link" size="small" style={{ height: '40px', color: '#000' }} onClick={() => tool.action && tool.action.call(this) } disabled={!!tool.disabled}>  
342 - { tool.icon ? <i class={['shortcut-icon', 'fa', `fa-${tool.icon}`]} aria-hidden='true'/> : (tool.text || this.$t(tool.i18nTooltip)) }  
343 - </a-button>  
344 - { tool.icon === 'minus' && <div style={{ fontSize: '12px', textAlign: 'center' }}>{this.scaleRate * 100}%</div> }  
345 - </a-tooltip>  
346 - ))  
347 - }  
348 - </a-button-group>  
349 - </a-layout-sider>  
350 - <a-layout-sider width={this.propsPanelWidth} data-set-width={this.propsPanelWidth} theme='light' style={{ background: '#fff', padding: '0 0 0 12px' }}>  
351 - <a-tabs  
352 - style="height: 100%;"  
353 - tabBarGutter={10}  
354 - defaultActiveKey={this.activeTabKey}  
355 - activeKey={this.activeTabKey}  
356 - onChange={this.setActiveTab}  
357 - >  
358 - {/*  
359 - #!zh tab 标题:  
360 - #!en tab title  
361 - ElementUI:label  
362 - Ant Design Vue:tab  
363 - */}  
364 - <a-tab-pane key="属性"><span slot="tab">{this.$t('editor.editPanel.tab.prop')}</span><RenderPropsEditor/></a-tab-pane>  
365 - <a-tab-pane label="动画" key='动画' tab={this.$t('editor.editPanel.tab.animation')}><RenderAnimationEditor /></a-tab-pane>  
366 - <a-tab-pane label="动作" key='动作' tab={this.$t('editor.editPanel.tab.action')}>{ this.activeTabKey === '动作' && <RenderActionEditor/> }</a-tab-pane>  
367 - <a-tab-pane label="脚本" key='脚本' tab={this.$t('editor.editPanel.tab.script')}><RenderScriptEditor/></a-tab-pane>  
368 - <a-tab-pane label="背景" key='background' tab={this.$t('editor.editPanel.tab.background')}>{ this.activeTabKey === 'background' && <RenderBackgroundEditor/> }</a-tab-pane>  
369 - </a-tabs>  
370 - </a-layout-sider>  
371 -  
372 - </a-layout>  
373 - {  
374 - <PreviewDialog  
375 - work={this.work}  
376 - visible={this.previewDialogVisible}  
377 - handleClose={() => { this.previewDialogVisible = false }}  
378 - />  
379 - }  
380 - <Feedback />  
381 - </a-layout>  
382 - )  
383 - },  
384 - created () {  
385 - // event bus for editor  
386 - window.getEditorApp = this  
387 - let workId = this.$route.params.workId  
388 - if (workId) {  
389 - this.fetchWork(workId).then(() => this.setActiveTab('background'))  
390 - } else {  
391 - this.$message.error('no work id!')  
392 - }  
393 -  
394 - window.getEditorApp.$on('setEditingElement', ({ name }) => {  
395 - this.setActiveTab(name === 'lbp-background' ? 'background' : '属性')  
396 - })  
397 - }  
398 -}  
front-end/h5/src/components/core/editor/left-panel/index.js 0 → 100644
  1 +import RenderShortcutsPanel from './shortcuts-panel/index'
  2 +import RenderPageManager from './page-manager/index'
  3 +import RenderPageTree from './page-tree/index'
  4 +
  5 +export default {
  6 + name: 'EditorLeftPanel',
  7 + render (h) {
  8 + return (
  9 + <a-layout-sider width="240" theme='light' style={{ background: '#fff', padding: '12px' }}>
  10 + <a-tabs
  11 + style="height: 100%;"
  12 + tabBarGutter={10}
  13 + >
  14 + <a-tab-pane key="plugin-list" tab={this.$t('editor.sidebar.components')}>
  15 + <RenderShortcutsPanel />
  16 + </a-tab-pane>
  17 + <a-tab-pane key='page-manager' tab={this.$t('editor.sidebar.pages')}>
  18 + <RenderPageManager />
  19 + </a-tab-pane>
  20 + <a-tab-pane key='page-tree' tab={this.$t('editor.sidebar.tree')}>
  21 + <RenderPageTree />
  22 + </a-tab-pane>
  23 + </a-tabs>
  24 + </a-layout-sider>
  25 + )
  26 + }
  27 +}
front-end/h5/src/components/core/editor/left-panel/page-manager/index.js 0 → 100644
  1 +import { mapState, mapActions } from 'vuex'
  2 +import PageTitleEditor from './title-editor'
  3 +import PageTitleMenu from './title-menu'
  4 +import PageTitleText from './title-text'
  5 +
  6 +export default {
  7 + data: () => ({
  8 + hoverIndex: -1 // 显示编辑按钮
  9 + }),
  10 + computed: {
  11 + ...mapState('editor', {
  12 + editingPage: state => state.editingPage,
  13 + editingElement: state => state.editingElement,
  14 + elements: state => state.editingPage.elements,
  15 + pages: state => state.work.pages,
  16 + work: state => state.work
  17 + })
  18 + },
  19 + methods: {
  20 + ...mapActions('editor', [
  21 + 'elementManager',
  22 + 'pageManager',
  23 + 'saveWork',
  24 + 'setEditingPage'
  25 + ]),
  26 + onSelectMenuItem (menuKey) {
  27 + this.pageManager({ type: menuKey })
  28 + },
  29 + onEditTitle ({ pageIndex, newTitle }) {
  30 + this.pageManager({ type: 'editTitle', value: { pageIndex, newTitle } })
  31 + this.saveWork({ isSaveCover: false })
  32 + },
  33 + onSelectPage (pageIndex) { this.setEditingPage(pageIndex) },
  34 + onLeave () {
  35 + this.hoverIndex = -1
  36 + }
  37 + },
  38 + render (h) {
  39 + const addPageText = this.$t('editor.pageManager.action.add')
  40 + return (
  41 + <div class="page-manager-panel">
  42 + {
  43 + this.pages.map((page, index) => (
  44 + <span
  45 + class={[
  46 + 'cursor-pointer',
  47 + 'page-manager-panel__item',
  48 + page.uuid === this.editingPage.uuid && 'active'
  49 + ]}
  50 + onClick={() => this.onSelectPage(index)}
  51 + // https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VHover/VHover.ts
  52 + onMouseenter={() => { this.hoverIndex = index }}
  53 + >
  54 + <PageTitleText page={page} pageIndex={index} />
  55 + <span>
  56 + {
  57 + this.hoverIndex === index &&
  58 + <PageTitleEditor
  59 + page={page}
  60 + pageIndex={index}
  61 + onEditTitle={this.onEditTitle}
  62 + />
  63 + }
  64 + <PageTitleMenu onSelectMenuItem={this.onSelectMenuItem} />
  65 + </span>
  66 + </span>
  67 + ))
  68 + }
  69 + <a-button
  70 + icon="plus"
  71 + type="dashed"
  72 + class="footer-actions"
  73 + onClick={() => this.onSelectMenuItem('add') }
  74 + >{addPageText}</a-button>
  75 + </div>
  76 + )
  77 + }
  78 +}
front-end/h5/src/components/core/editor/left-panel/page-manager/title-editor.js 0 → 100644
  1 +export default {
  2 + props: ['page', 'pageIndex'],
  3 + data: () => ({
  4 + editingTitle: '' // 临时缓存当前编辑的 title,点击 Yes 再真正用其更新 page title
  5 + }),
  6 + methods: {
  7 + getTitle () {
  8 + return this.page.title || this.$t('editor.pageManager.title', { index: this.pageIndex })
  9 + }
  10 + },
  11 + render () {
  12 + return (
  13 + <a-popconfirm
  14 + placement="bottom"
  15 + onConfirm={() => {
  16 + this.$emit('editTitle', { newTitle: this.editingTitle, pageIndex: this.pageIndex })
  17 + }}
  18 + onCancel={() => {}}
  19 + okText="Yes"
  20 + cancelText="No"
  21 + >
  22 + <a-input
  23 + slot="title"
  24 + value={this.editingTitle}
  25 + size="small"
  26 + onChange={e => {
  27 + this.editingTitle = e.target.value
  28 + }}
  29 + >
  30 + </a-input>
  31 + <a-icon type="edit" onClick={(e) => {
  32 + e.stopPropagation() // 将 click icon 与 click page item 隔离开。编辑标题的同时不要切换页面
  33 + this.editingTitle = this.getTitle()
  34 + }}/>
  35 + </a-popconfirm>
  36 +
  37 + )
  38 + }
  39 +}
front-end/h5/src/components/core/editor/left-panel/page-manager/title-menu.js 0 → 100644
  1 +export default {
  2 + render () {
  3 + const addPageText = this.$t('editor.pageManager.action.add')
  4 + const copyPageText = this.$t('editor.pageManager.action.copy')
  5 + const deletePageText = this.$t('editor.pageManager.action.delete')
  6 + return (
  7 + <a-dropdown trigger={['hover']} placement='bottomCenter'>
  8 + <a class="ant-dropdown-link" href="#" class="ml-2"><a-icon type="down" /></a>
  9 + <a-menu slot="overlay" onClick={({ key }) => this.$emit('selectMenuItem', key)}>
  10 + <a-menu-item key="add"><a-icon type="plus" />{addPageText}</a-menu-item>
  11 + <a-menu-item key="copy"><a-icon type="copy" />{copyPageText}</a-menu-item>
  12 + <a-menu-item key="delete"><a-icon type="delete" />{deletePageText}</a-menu-item>
  13 + </a-menu>
  14 + </a-dropdown>
  15 + )
  16 + }
  17 +}
front-end/h5/src/components/core/editor/left-panel/page-manager/title-text.js 0 → 100644
  1 +export default {
  2 + props: ['page', 'pageIndex'],
  3 + methods: {
  4 + getTitle () {
  5 + return this.page.title || this.$t('editor.pageManager.title', { index: this.pageIndex })
  6 + }
  7 + },
  8 + render (h) {
  9 + // #!en: Page<Index>
  10 + // #!zh: 第<Index>页面
  11 + return (
  12 + <span>
  13 + <a-badge
  14 + count={this.pageIndex + 1}
  15 + numberStyle={{ backgroundColor: '#fff', color: '#999', boxShadow: '0 0 0 1px #d9d9d9 inset' }}
  16 + />
  17 + <span class="ml-3">{this.getTitle()}</span>
  18 + </span>
  19 + )
  20 + }
  21 +}
front-end/h5/src/components/core/editor/left-panel/page-tree/index.vue 0 → 100644
  1 +<template>
  2 + <a-tree
  3 + class="draggable-tree"
  4 + :default-expanded-keys="expandedKeys"
  5 + draggable
  6 + :tree-data="treeData"
  7 + @dragenter="onDragEnter"
  8 + @drop="onDrop"
  9 + />
  10 +</template>
  11 +
  12 +<script>
  13 +import { mapState } from 'vuex'
  14 +function getTreeNode (ele) {
  15 + return {
  16 + title: ele.name,
  17 + key: ele.uuid,
  18 + children: (ele.children || []).map(getTreeNode)
  19 + }
  20 +}
  21 +
  22 +export default {
  23 + computed: {
  24 + ...mapState('editor', {
  25 + elements: state => state.editingPage.elements
  26 + }),
  27 + treeData () {
  28 + return this.elements.map(getTreeNode)
  29 + }
  30 + },
  31 + data () {
  32 + return {
  33 + gData: [],
  34 + expandedKeys: []
  35 + }
  36 + },
  37 + methods: {
  38 + onDragEnter (info) {
  39 + },
  40 + onDrop (info) {
  41 + }
  42 + }
  43 +}
  44 +</script>
front-end/h5/src/components/core/editor/shortcuts-panel/index.js renamed to front-end/h5/src/components/core/editor/left-panel/shortcuts-panel/index.js
1 import ShortcutButton from './shortcut-button' 1 import ShortcutButton from './shortcut-button'
  2 +import UsageTip from './usage-tip'
2 import LoadNpmPlugins from './load-npm-plugins.vue' 3 import LoadNpmPlugins from './load-npm-plugins.vue'
3 -import langMixin from '@/mixins/i18n' 4 +import langMixin from 'core/mixins/i18n'
  5 +import dragMixin from 'core/mixins/drag'
  6 +import loadPluginsMixin from 'core/plugins/index'
  7 +import { mapActions } from 'vuex'
  8 +
4 export default { 9 export default {
5 - mixins: [langMixin],  
6 - props: {  
7 - pluginsList: {  
8 - required: false,  
9 - type: Array,  
10 - default: () => []  
11 - },  
12 - handleClickShortcut: {  
13 - type: Function  
14 - },  
15 - handleDragStart: {  
16 - type: Function,  
17 - default: (e) => {}  
18 - }  
19 - }, 10 + mixins: [langMixin, dragMixin, loadPluginsMixin],
20 data: () => ({ 11 data: () => ({
21 npmPackages: [] 12 npmPackages: []
22 }), 13 }),
23 methods: { 14 methods: {
24 - onClickShortcut (item) {  
25 - if (this.handleClickShortcut) {  
26 - this.handleClickShortcut(item)  
27 - } 15 + ...mapActions('editor', [
  16 + 'elementManager',
  17 + 'pageManager',
  18 + 'saveWork',
  19 + 'setEditingPage'
  20 + ]),
  21 + ...mapActions('loading', {
  22 + updateLoading: 'update'
  23 + }),
  24 + /**
  25 + * !#zh 点击插件,copy 其基础数据到组件树(中间画布)
  26 + * #!en click the plugin shortcut, create new Element with the plugin's meta data
  27 + * pluginInfo {Object}: 插件列表中的基础数据, {name}=pluginInfo
  28 + *
  29 + * shortcutItem: PluginListItem = {
  30 + name: String,
  31 + shortcutProps: {}
  32 + }
  33 + */
  34 + clone (shortcutItem) {
  35 + this.elementManager({
  36 + type: 'add',
  37 + value: shortcutItem
  38 + })
28 } 39 }
29 /** 40 /**
30 * #!zh 渲染多个插件的快捷方式 41 * #!zh 渲染多个插件的快捷方式
@@ -70,8 +81,8 @@ export default { @@ -70,8 +81,8 @@ export default {
70 // /> 81 // />
71 // }, 82 // },
72 /** 83 /**
73 - * #!zh: 在左侧或顶部导航上显示可用的组件快捷方式,用户点击之后,即可将其添加到中间画布上  
74 - * #!en: render shortcust at the sidebar or the header. if user click the shortcut, the related plugin will be added to the canvas 84 + * #!zh: 在左侧或顶部导航上显示可用的组件快捷方式,用户点击/拖拽之后,即可将其添加到中间画布上
  85 + * #!en: render shortcust at the sidebar or the header. if user click/drag the shortcut, the related plugin will be added to the canvas
75 * @param {Object} group: {children, title, icon} 86 * @param {Object} group: {children, title, icon}
76 */ 87 */
77 // renderShortCutsPanel (groups) { 88 // renderShortCutsPanel (groups) {
@@ -92,23 +103,31 @@ export default { @@ -92,23 +103,31 @@ export default {
92 // ) 103 // )
93 // } 104 // }
94 }, 105 },
  106 + /**
  107 + * #!zh: 在左侧或顶部导航上显示可用的组件快捷方式,用户点击/拖拽之后,即可将其添加到中间画布上
  108 + * #!en: render shortcust at the sidebar or the header.
  109 + * if user click/drag the shortcut, the related plugin will be added to the canvas
  110 + */
95 render (h) { 111 render (h) {
96 // return this.renderShortCutsPanel(this.groups) 112 // return this.renderShortCutsPanel(this.groups)
97 return ( 113 return (
98 <a-row gutter={20} style="max-height: calc(100vh - 140px);overflow: scroll;"> 114 <a-row gutter={20} style="max-height: calc(100vh - 140px);overflow: scroll;">
  115 + <UsageTip />
99 { 116 {
100 - [].concat(this.pluginsList, this.npmPackages).filter(plugin => plugin.visible).map(plugin => (  
101 - <a-col span={12} style={{ marginTop: '10px' }}>  
102 - <ShortcutButton  
103 - clickFn={this.onClickShortcut.bind(this, plugin)}  
104 - mousedownFn={this.handleDragStart.bind(this, plugin)}  
105 - // title={plugin.title}  
106 - title={plugin.i18nTitle[this.currentLang] || plugin.title}  
107 - faIcon={plugin.icon}  
108 - disabled={plugin.disabled}  
109 - />  
110 - </a-col>  
111 - )) 117 + [].concat(this.pluginsList, this.npmPackages)
  118 + .filter(plugin => plugin.visible)
  119 + .map(plugin => (
  120 + <a-col span={12} style={{ marginTop: '10px' }}>
  121 + <ShortcutButton
  122 + clickFn={this.clone.bind(this, plugin)}
  123 + mousedownFn={this.handleDragStartFromMixin.bind(this, plugin)}
  124 + // title={plugin.title}
  125 + title={plugin.i18nTitle[this.currentLang] || plugin.title}
  126 + faIcon={plugin.icon}
  127 + disabled={plugin.disabled}
  128 + />
  129 + </a-col>
  130 + ))
112 } 131 }
113 <LoadNpmPlugins onLoadComplete={npmPackages => { 132 <LoadNpmPlugins onLoadComplete={npmPackages => {
114 this.npmPackages = npmPackages 133 this.npmPackages = npmPackages
front-end/h5/src/components/core/editor/shortcuts-panel/load-npm-plugins.vue renamed to front-end/h5/src/components/core/editor/left-panel/shortcuts-panel/load-npm-plugins.vue
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-23 12:35:43 3 * @Date: 2019-11-23 12:35:43
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2019-11-23 19:37:29  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/shortcuts-panel/load-npm-plugins.vue 5 + * @LastEditTime: 2020-10-10 23:31:49
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/left-panel/shortcuts-panel/load-npm-plugins.vue
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 --> 10 -->
11 11
12 <template> 12 <template>
front-end/h5/src/components/core/editor/shortcuts-panel/shortcut-button.js renamed to front-end/h5/src/components/core/editor/left-panel/shortcuts-panel/shortcut-button.js
front-end/h5/src/components/core/editor/left-panel/shortcuts-panel/usage-tip.js 0 → 100644
  1 +export default {
  2 + render () {
  3 + return (
  4 + <div class="plugin-usage-tip ">
  5 + <a-icon type="info-circle" />
  6 + {/* 使用提示: 点击或拖拽 组件即可 */}
  7 + {/* Tip: just click/drag component */}
  8 + <i18n path="editor.tip.componentUsage" tag="span" class="ml-1">
  9 + <strong>{ this.$t('editor.tip.click') }</strong>{ this.$t('editor.tip.click') }
  10 + </i18n>
  11 + </div>
  12 + )
  13 + }
  14 +}
front-end/h5/src/components/core/editor/page-manager/index.js deleted 100644 → 0
1 -export default {  
2 - props: {  
3 - pages: {  
4 - required: false,  
5 - type: Array,  
6 - default: () => []  
7 - },  
8 - editingPage: {  
9 - type: Object,  
10 - default: () => {}  
11 - }  
12 - },  
13 - data: () => ({  
14 - hoverIndex: -1, // 显示编辑按钮  
15 - editingTitle: '' // 临时缓存当前编辑的 title,点击 Yes 再真正用其更新 page title  
16 - }),  
17 - methods: {  
18 - getTitle (page, index) {  
19 - return page.title || this.$t('editor.pageManager.title', { index })  
20 - },  
21 - _renderEditTitle (page, index) {  
22 - return (  
23 - <a-popconfirm  
24 - placement="bottom"  
25 - onConfirm={() => {  
26 - this.$emit('editTitle', { newTitle: this.editingTitle, pageIndexForEditingTitle: index })  
27 - }}  
28 - onCancel={() => {}}  
29 - okText="Yes"  
30 - cancelText="No"  
31 - >  
32 - <a-input  
33 - slot="title"  
34 - value={this.editingTitle}  
35 - size="small"  
36 - onChange={e => {  
37 - this.editingTitle = e.target.value  
38 - }}  
39 - >  
40 - </a-input>  
41 - <a-icon type="edit" onClick={(e) => {  
42 - e.stopPropagation() // 将 click icon 与 click page item 隔离开。编辑标题的同时不要切换页面  
43 - this.editingTitle = this.getTitle(page, index)  
44 - }}/>  
45 - </a-popconfirm>  
46 - )  
47 - },  
48 - _renderTitleMenu (page, index) {  
49 - const addPageText = this.$t('editor.pageManager.action.add')  
50 - const copyPageText = this.$t('editor.pageManager.action.copy')  
51 - const deletePageText = this.$t('editor.pageManager.action.delete')  
52 - return (  
53 - <a-dropdown trigger={['hover']} placement='bottomCenter'>  
54 - <a class="ant-dropdown-link" href="#" class="ml-2"><a-icon type="down" /></a>  
55 - <a-menu slot="overlay" onClick={({ key }) => this.$emit('selectMenuItem', key)}>  
56 - <a-menu-item key="add"><a-icon type="plus" />{addPageText}</a-menu-item>  
57 - <a-menu-item key="copy"><a-icon type="copy" />{copyPageText}</a-menu-item>  
58 - <a-menu-item key="delete"><a-icon type="delete" />{deletePageText}</a-menu-item>  
59 - </a-menu>  
60 - </a-dropdown>  
61 - )  
62 - },  
63 - onLeave () {  
64 - this.hoverIndex = -1  
65 - }  
66 - },  
67 - render (h) {  
68 - const addPageText = this.$t('editor.pageManager.action.add')  
69 - return (  
70 - <div class="page-manager-panel">  
71 - {  
72 - this.pages.map((page, index) => (  
73 - <span  
74 - class={[  
75 - 'cursor-pointer',  
76 - 'page-manager-panel__item',  
77 - page.uuid === this.editingPage.uuid && 'active'  
78 - ]}  
79 - onClick={() => { this.$emit('selectPage', index) }}  
80 - // https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VHover/VHover.ts  
81 - onMouseenter={() => { this.hoverIndex = index }}  
82 - >  
83 - {/* #!en: Page<Index> */}  
84 - {/* #!zh: 第<Index>页面 */}  
85 - <span>  
86 - <a-badge  
87 - count={index + 1}  
88 - numberStyle={{ backgroundColor: '#fff', color: '#999', boxShadow: '0 0 0 1px #d9d9d9 inset' }}  
89 - />  
90 - <span class="ml-3">{this.getTitle(page, index)}</span>  
91 - </span>  
92 - <span>  
93 - {this.hoverIndex === index && this._renderEditTitle(page, index)}  
94 - {this._renderTitleMenu(page, index)}  
95 - </span>  
96 - </span>  
97 - ))  
98 - }  
99 - <a-button  
100 - icon="plus"  
101 - type="dashed"  
102 - class="footer-actions"  
103 - onClick={() => { this.$emit('selectMenuItem', 'add') }}  
104 - >{addPageText}</a-button>  
105 - </div>  
106 - )  
107 - }  
108 -}  
front-end/h5/src/components/core/editor/edit-panel/action.js renamed to front-end/h5/src/components/core/editor/right-panel/action.js
front-end/h5/src/components/core/editor/edit-panel/animation.js renamed to front-end/h5/src/components/core/editor/right-panel/animation.js
1 import { mapState } from 'vuex' 1 import { mapState } from 'vuex'
2 -import { animationOptions, animationValue2Name, firstLevelAnimationOptions } from '@/constants/animation.js' 2 +import { animationOptions, animationValue2Name, firstLevelAnimationOptions } from 'core/constants/animation.js'
3 3
4 export default { 4 export default {
5 computed: { 5 computed: {
@@ -32,7 +32,7 @@ export default { @@ -32,7 +32,7 @@ export default {
32 }, 32 },
33 runAnimate () { 33 runAnimate () {
34 // front-end/h5/src/components/core/editor/index.js created() 34 // front-end/h5/src/components/core/editor/index.js created()
35 - window.getEditorApp.$emit('RUN_ANIMATIONS') 35 + window.EditorApp.$emit('RUN_ANIMATIONS')
36 }, 36 },
37 renderSecondAnimationTabs (animations) { 37 renderSecondAnimationTabs (animations) {
38 return ( 38 return (
@@ -208,7 +208,7 @@ export default { @@ -208,7 +208,7 @@ export default {
208 const ele = this.editingElement 208 const ele = this.editingElement
209 if (!ele) return (<span>{this.$t('editor.editPanel.common.empty')}</span>) 209 if (!ele) return (<span>{this.$t('editor.editPanel.common.empty')}</span>)
210 return ( 210 return (
211 - <div class="main-animate widget" id="animation-edit-panel"> 211 + <div class="main-animate widget" id="animation-right-panel">
212 <a-button-group> 212 <a-button-group>
213 {/* 添加动画、运行动画 */} 213 {/* 添加动画、运行动画 */}
214 <a-button type="primary" onClick={this.addAnimation}><a-icon type="plus" />{this.$t('editor.editPanel.animation.add')}</a-button> 214 <a-button type="primary" onClick={this.addAnimation}><a-icon type="plus" />{this.$t('editor.editPanel.animation.add')}</a-button>
front-end/h5/src/components/core/editor/edit-panel/background.js renamed to front-end/h5/src/components/core/editor/right-panel/background.js
1 /* 1 /*
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-12-01 18:11:49 3 * @Date: 2019-12-01 18:11:49
4 - * @LastEditors : ly525  
5 - * @LastEditTime : 2020-01-15 01:03:31  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/edit-panel/background.js 4 + * @LastEditors: ly525
  5 + * @LastEditTime: 2020-10-10 23:36:27
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/right-panel/background.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 -import propsEditPanel from './props.js' 11 +import PropsEditPanel from './props.js'
12 import { mapState, mapActions } from 'vuex' 12 import { mapState, mapActions } from 'vuex'
  13 +import RenderWorkMode from './work-mode.vue'
13 14
14 export default { 15 export default {
15 computed: { 16 computed: {
@@ -24,10 +25,15 @@ export default { @@ -24,10 +25,15 @@ export default {
24 }, 25 },
25 render () { 26 render () {
26 const bgEle = this.editingPage.elements.find(e => e.name === 'lbp-background') 27 const bgEle = this.editingPage.elements.find(e => e.name === 'lbp-background')
27 - return <propsEditPanel  
28 - layout="vertical"  
29 - realEditingElement={bgEle}  
30 - /> 28 + return (
  29 + <div>
  30 + <RenderWorkMode />
  31 + <PropsEditPanel
  32 + layout="vertical"
  33 + realEditingElement={bgEle}
  34 + />
  35 + </div>
  36 + )
31 } 37 }
32 38
33 } 39 }
front-end/h5/src/components/core/editor/right-panel/index.js 0 → 100644
  1 +import RenderPropsEditor from './props'
  2 +import RenderScriptEditor from './script'
  3 +import RenderAnimationEditor from './animation'
  4 +import RenderActionEditor from './action'
  5 +import RenderBackgroundEditor from './background'
  6 +export default {
  7 + name: 'ElementPropsEditor',
  8 + props: {
  9 + width: {
  10 + type: Number,
  11 + default: 320
  12 + }
  13 + },
  14 + data: () => ({
  15 + activeTabKey: '页面'
  16 + }),
  17 + methods: {
  18 + /**
  19 + * #!zh: 设置 页面图tab 作为 active tab
  20 + * #!en: set background(bg) tab as active tab
  21 + */
  22 + setActiveTab (activeTabKey) {
  23 + this.activeTabKey = activeTabKey
  24 + }
  25 + },
  26 + render (h) {
  27 + return (
  28 + <a-layout-sider width={this.width} data-set-width={this.width} theme='light' style={{ background: '#fff', padding: '0 12px 0 12px' }}>
  29 + <a-tabs
  30 + style="height: 100%;"
  31 + tabBarGutter={10}
  32 + defaultActiveKey={this.activeTabKey}
  33 + activeKey={this.activeTabKey}
  34 + onChange={this.setActiveTab}
  35 + >
  36 + <a-tab-pane key="属性"><span slot="tab">{this.$t('editor.editPanel.tab.prop')}</span><RenderPropsEditor/></a-tab-pane>
  37 + <a-tab-pane label="动画" key='动画' tab={this.$t('editor.editPanel.tab.animation')}><RenderAnimationEditor /></a-tab-pane>
  38 + <a-tab-pane label="动作" key='动作' tab={this.$t('editor.editPanel.tab.action')}>{ this.activeTabKey === '动作' && <RenderActionEditor/> }</a-tab-pane>
  39 + <a-tab-pane label="脚本" key='脚本' tab={this.$t('editor.editPanel.tab.script')}><RenderScriptEditor/></a-tab-pane>
  40 + <a-tab-pane label="页面" key='页面' tab={this.$t('editor.editPanel.tab.page')}>{ this.activeTabKey === '页面' && <RenderBackgroundEditor/> }</a-tab-pane>
  41 + </a-tabs>
  42 + </a-layout-sider>
  43 + )
  44 + },
  45 + created () {
  46 + window.EditorApp.$on('setEditingElement', ({ name }) => {
  47 + this.setActiveTab(name === 'lbp-background' ? '页面' : '属性')
  48 + })
  49 + }
  50 +}
front-end/h5/src/components/core/editor/edit-panel/props.js renamed to front-end/h5/src/components/core/editor/right-panel/props.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import { mapState, mapActions } from 'vuex' 2 import { mapState, mapActions } from 'vuex'
3 -import { getVM, getComponentsForPropsEditor } from '../../../../utils/element'  
4 -import RenderGlobalWorkPropsEditor from './props/global-work.vue' 3 +import { getVM, getComponentsForPropsEditor } from '@/utils/element'
  4 +import 'core/styles/props-config-panel.scss'
5 5
6 export default { 6 export default {
7 data: () => ({ 7 data: () => ({
@@ -40,7 +40,7 @@ export default { @@ -40,7 +40,7 @@ export default {
40 if (Vue.component(this.customEditorName)) { 40 if (Vue.component(this.customEditorName)) {
41 this.loadCustomEditorFlag = true 41 this.loadCustomEditorFlag = true
42 } else { 42 } else {
43 - import(`../../../plugins/${this.editingElement.name}__editor`).then(component => { 43 + import(`core/plugins/${this.editingElement.name}__editor`).then(component => {
44 this.loadCustomEditorFlag = true 44 this.loadCustomEditorFlag = true
45 Vue.component(this.customEditorName, component.default) 45 Vue.component(this.customEditorName, component.default)
46 }).catch(err => { 46 }).catch(err => {
@@ -122,9 +122,8 @@ export default { @@ -122,9 +122,8 @@ export default {
122 <a-form 122 <a-form
123 ref="form" 123 ref="form"
124 size="mini" 124 size="mini"
125 - id="props-edit-form" 125 + class="props-config-form"
126 layout={this.layout} 126 layout={this.layout}
127 - style="overflow: auto;position: absolute;top: 50px;bottom: 0;width: 100%; "  
128 > 127 >
129 { 128 {
130 // plugin-custom-editor 129 // plugin-custom-editor
@@ -151,17 +150,17 @@ export default { @@ -151,17 +150,17 @@ export default {
151 ) 150 )
152 }, 151 },
153 renderWorkGlobalPropsPanel (h) { 152 renderWorkGlobalPropsPanel (h) {
154 - return <RenderGlobalWorkPropsEditor /> 153 + return <RenderWorkMode />
155 } 154 }
156 }, 155 },
157 render (h) { 156 render (h) {
158 const ele = this.editingElement 157 const ele = this.editingElement
159 - if (!ele) return this.renderWorkGlobalPropsPanel(h) 158 + if (!ele) return '请选择一个元素'
160 this.mixinEnhancedPropsEditor(ele) 159 this.mixinEnhancedPropsEditor(ele)
161 return this.renderPropsEditorPanel(h, ele) 160 return this.renderPropsEditorPanel(h, ele)
162 }, 161 },
163 created () { 162 created () {
164 - window.getEditorApp.$on('setEditingElement', (ele) => { 163 + window.EditorApp.$on('setEditingElement', (ele) => {
165 this.loadCustomEditorForPlugin() 164 this.loadCustomEditorForPlugin()
166 this.componentsForPropsEditor = getComponentsForPropsEditor(ele.name) 165 this.componentsForPropsEditor = getComponentsForPropsEditor(ele.name)
167 }) 166 })
front-end/h5/src/components/core/editor/edit-panel/script.js renamed to front-end/h5/src/components/core/editor/right-panel/script.js
front-end/h5/src/components/core/editor/edit-panel/props/global-work.vue renamed to front-end/h5/src/components/core/editor/right-panel/work-mode.vue
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2020-05-10 23:10:52 3 * @Date: 2020-05-10 23:10:52
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-13 00:09:56  
6 - * @FilePath: /h5/src/components/core/editor/edit-panel/props/global-work.vue 5 + * @LastEditTime: 2020-10-10 23:32:07
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/right-panel/work-mode.vue
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 --> 10 -->
11 <template> 11 <template>
12 <a-form :layout="formLayout"> 12 <a-form :layout="formLayout">
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 22
23 <script> 23 <script>
24 import { mapState, mapActions } from 'vuex' 24 import { mapState, mapActions } from 'vuex'
25 -import { PAGE_MODE, PAGE_MODE_LABEL } from '@/constants/work' 25 +import { PAGE_MODE, PAGE_MODE_LABEL } from 'core/constants/work'
26 26
27 export default { 27 export default {
28 data () { 28 data () {
front-end/h5/src/components/core/index.js 0 → 100644
  1 +import { mapState, mapActions } from 'vuex'
  2 +import Vue from 'vue'
  3 +
  4 +import 'core/support/index.js'
  5 +import 'core/styles/index.scss'
  6 +import 'animate.css'
  7 +
  8 +import FixedTools from 'core/editor/fixed-tools/index'
  9 +import EditorRightPanel from 'core/editor/right-panel/index'
  10 +import EditorCanvas from 'core/editor/canvas/index'
  11 +import EditorActionMenu from 'core/editor/header/action-menu'
  12 +import EditorLeftPanel from 'core/editor/left-panel/index'
  13 +import PreviewDialog from 'core/editor/modals/preview.vue'
  14 +import Header from '@/components/common/header/index'
  15 +import Feedback from '@/components/common/feedback/index'
  16 +import AdjustLineV from 'core/support/adjust-line/vertical'
  17 +
  18 +import store from 'core/store/index'
  19 +import router from 'core/router/index'
  20 +import i18n from '@/locales'
  21 +import '@/plugins/index'
  22 +
  23 +window.EditorApp = new Vue() // event bus
  24 +const CoreEditor = {
  25 + name: 'CoreEditor',
  26 + store,
  27 + i18n,
  28 + router,
  29 + props: {
  30 + workId: {
  31 + type: [Number, String]
  32 + }
  33 + },
  34 + data: () => ({
  35 + previewDialogVisible: false,
  36 + propsPanelWidth: 320
  37 + }),
  38 + computed: {
  39 + ...mapState('editor', {
  40 + work: state => state.work
  41 + })
  42 + },
  43 + methods: {
  44 + ...mapActions('editor', ['fetchWork']),
  45 + handlePreview () { this.previewDialogVisible = true }
  46 + },
  47 + render (h) {
  48 + return (
  49 + <a-layout>
  50 + <Header>
  51 + <EditorActionMenu slot="action-menu" onPreview={this.handlePreview} />
  52 + </Header>
  53 + <a-layout>
  54 + <EditorLeftPanel />
  55 + <EditorCanvas />
  56 + <AdjustLineV onLineMove={(offset) => { this.propsPanelWidth += offset }} />
  57 + <FixedTools />
  58 + <EditorRightPanel width={this.propsPanelWidth} />
  59 + </a-layout>
  60 + {
  61 + <PreviewDialog
  62 + work={this.work}
  63 + visible={this.previewDialogVisible}
  64 + handleClose={() => { this.previewDialogVisible = false }}
  65 + />
  66 + }
  67 + <Feedback />
  68 + </a-layout>
  69 + )
  70 + },
  71 + created () {
  72 + if (this.workId) {
  73 + this.fetchWork(this.workId)
  74 + } else {
  75 + this.$message.error('no work id!')
  76 + }
  77 + }
  78 +}
  79 +
  80 +// Vue install, Vue.use 会调用该方法。
  81 +CoreEditor.install = (Vue, opts = {}) => {
  82 + Vue.component(CoreEditor.name, CoreEditor)
  83 +}
  84 +
  85 +// 通过script标签引入Vue的环境
  86 +if (typeof window !== 'undefined' && window.Vue) {
  87 + CoreEditor.install(window.Vue)
  88 +}
  89 +
  90 +export default CoreEditor
front-end/h5/src/mixins/animation.js renamed to front-end/h5/src/components/core/mixins/animation.js
1 /* 1 /*
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-24 18:51:58 3 * @Date: 2019-11-24 18:51:58
4 - * @LastEditors : ly525  
5 - * @LastEditTime : 2020-01-09 21:57:30  
6 - * @FilePath: /luban-h5/front-end/h5/src/mixins/animation.js 4 + * @LastEditors: ly525
  5 + * @LastEditTime: 2020-10-10 23:35:49
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/mixins/animation.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: 8 * @Description:
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 // https://stackoverflow.com/questions/26874769/getcomputedstyle-and-csstext-in-ie-and-firefox 11 // https://stackoverflow.com/questions/26874769/getcomputedstyle-and-csstext-in-ie-and-firefox
12 function getComputedCSSText (style) { 12 function getComputedCSSText (style) {
@@ -55,7 +55,7 @@ export default { @@ -55,7 +55,7 @@ export default {
55 }, 55 },
56 created () { 56 created () {
57 const that = this 57 const that = this
58 - window.getEditorApp && window.getEditorApp.$on('RUN_ANIMATIONS', () => { 58 + window.EditorApp && window.EditorApp.$on('RUN_ANIMATIONS', () => {
59 that.runAnimations() 59 that.runAnimations()
60 // if (that.active) { 60 // if (that.active) {
61 // that.runAnimations() 61 // that.runAnimations()
front-end/h5/src/components/core/editor/drag-mixin.js renamed to front-end/h5/src/components/core/mixins/drag.js
@@ -2,10 +2,10 @@ @@ -2,10 +2,10 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2020-05-17 17:21:04 3 * @Date: 2020-05-17 17:21:04
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-24 18:09:23  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/drag-mixin.js 5 + * @LastEditTime: 2020-10-11 17:20:39
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/mixins/drag.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 8 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
9 * @Description: 9 * @Description:
10 * 组件拖拽至画布功能 10 * 组件拖拽至画布功能
11 * 其中部分代码参考自:https://github.com/hakubox/haku-form-design,已经征得作者同意,目的是后续考虑做 tab 之类的嵌套容器 11 * 其中部分代码参考自:https://github.com/hakubox/haku-form-design,已经征得作者同意,目的是后续考虑做 tab 之类的嵌套容器
@@ -50,7 +50,6 @@ class Drag { @@ -50,7 +50,6 @@ class Drag {
50 } 50 }
51 51
52 _mouseup (e) { 52 _mouseup (e) {
53 - console.log('mouseup')  
54 this.mouseup(e) 53 this.mouseup(e)
55 this.toggleListener('remove') 54 this.toggleListener('remove')
56 } 55 }
front-end/h5/src/mixins/i18n.js renamed to front-end/h5/src/components/core/mixins/i18n.js
front-end/h5/src/components/core/models/element.js
1 -import { parsePx } from '../../../utils/element.js' 1 +import { parsePx } from '@/utils/element.js'
2 2
3 // #! 编辑状态,不可以点击的按钮,因为点击按钮会触发一些默认行为,比如表单提交等 3 // #! 编辑状态,不可以点击的按钮,因为点击按钮会触发一些默认行为,比如表单提交等
4 const disabledPluginsForEditMode = ['lbp-form-input', 'lbp-form-button', 'lbp-video'] 4 const disabledPluginsForEditMode = ['lbp-form-input', 'lbp-form-button', 'lbp-video']
front-end/h5/src/components/core/models/page.js
1 -import Element from '../models/element'  
2 -import LbpBackground from '../../plugins/lbp-background' 1 +import Element from 'core/models/element'
  2 +import LbpBackground from 'core/plugins/lbp-background'
3 3
4 class Page { 4 class Page {
5 constructor (page = {}) { 5 constructor (page = {}) {
front-end/h5/src/components/core/models/work.js
@@ -2,14 +2,14 @@ @@ -2,14 +2,14 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-24 18:51:58 3 * @Date: 2019-11-24 18:51:58
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-10 23:23:40 5 + * @LastEditTime: 2020-10-10 23:32:31
6 * @FilePath: /luban-h5/front-end/h5/src/components/core/models/work.js 6 * @FilePath: /luban-h5/front-end/h5/src/components/core/models/work.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: work model 8 * @Description: work model
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import Page from './page.js' 11 import Page from './page.js'
12 -import { PAGE_MODE } from '@/constants/work' 12 +import { PAGE_MODE } from 'core/constants/work'
13 13
14 class Work { 14 class Work {
15 constructor (work = {}) { 15 constructor (work = {}) {
front-end/h5/src/components/core/package.json 0 → 100644
  1 +{
  2 + "name": "@luban-h5/core-editor",
  3 + "private": false,
  4 + "version": "0.0.4",
  5 + "description": "luban-h5 core-editor",
  6 + "main": "dist/core-editor.umd.min.js",
  7 + "author": "ly525",
  8 + "license": "GPL-3.0"
  9 +}
front-end/h5/src/components/plugins/charts/chart-mixin.js renamed to front-end/h5/src/components/core/plugins/charts/chart-mixin.js
front-end/h5/src/components/plugins/charts/chart-model.js renamed to front-end/h5/src/components/core/plugins/charts/chart-model.js
front-end/h5/src/components/plugins/charts/chart-model.ts renamed to front-end/h5/src/components/core/plugins/charts/chart-model.ts
front-end/h5/src/components/plugins/charts/line.js renamed to front-end/h5/src/components/core/plugins/charts/line.js
@@ -8,7 +8,7 @@ import &#39;echarts/lib/component/legend&#39; @@ -8,7 +8,7 @@ import &#39;echarts/lib/component/legend&#39;
8 import 'echarts/lib/component/markLine' 8 import 'echarts/lib/component/markLine'
9 import 'echarts/lib/component/markPoint' 9 import 'echarts/lib/component/markPoint'
10 import 'echarts/lib/component/markArea' 10 import 'echarts/lib/component/markArea'
11 -import Parser from '../../../utils/excel-parser' 11 +import Parser from '@/utils/excel-parser'
12 12
13 // const title = str => str.slice(0, 1).toUpperCase() + str.slice(1) 13 // const title = str => str.slice(0, 1).toUpperCase() + str.slice(1)
14 14
front-end/h5/src/mixins/load-plugins.js renamed to front-end/h5/src/components/core/plugins/index.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 // import LbpButton from '@luban-h5/lbc-button' 2 // import LbpButton from '@luban-h5/lbc-button'
3 -import LbpButton from '../components/plugins/lbp-button'  
4 -import LbpPicture from '../components/plugins/lbp-picture'  
5 -import LbpVideo from '../components/plugins/lbp-video'  
6 -import LbpText from '../components/plugins/lbp-text'  
7 -import LbpFormInput from '../components/plugins/lbp-form-input'  
8 -import LbpFormButton from '../components/plugins/lbp-form-button'  
9 -import LbpFormRadioGroup from '../components/plugins/lbp-form-radio-group'  
10 -import LbpFormCheckboxGroup from '../components/plugins/lbp-form-checkbox-group'  
11 -import LbpBackground from '../components/plugins/lbp-background'  
12 -import LbpSlide from '../components/plugins/lbp-slide'  
13 -import LbpBgMusic from '../components/plugins/lbp-bg-music'  
14 -import LbpNoticeBar from '../components/plugins/lbp-notice-bar'  
15 -import LbpRate from '../components/plugins/lbp-rate'  
16 -import LbpQQMap from '../components/plugins/lbp-qq-map/src'  
17 -import LbpLineChart from '../components/plugins/charts/line'  
18 -import LbpTable from '../components/plugins/lbp-table'  
19 -import LbpNewsList from '../components/plugins/lbp-news-list'  
20 -// import LbpTabs from '../components/plugins/lbp-tabs' 3 +import LbpButton from 'core/plugins/lbp-button'
  4 +import LbpPicture from 'core/plugins/lbp-picture'
  5 +import LbpVideo from 'core/plugins/lbp-video'
  6 +import LbpText from 'core/plugins/lbp-text'
  7 +import LbpFormInput from 'core/plugins/lbp-form-input'
  8 +import LbpFormButton from 'core/plugins/lbp-form-button'
  9 +import LbpFormRadioGroup from 'core/plugins/lbp-form-radio-group'
  10 +import LbpFormCheckboxGroup from 'core/plugins/lbp-form-checkbox-group'
  11 +import LbpBackground from 'core/plugins/lbp-background'
  12 +import LbpSlide from 'core/plugins/lbp-slide'
  13 +import LbpBgMusic from 'core/plugins/lbp-bg-music'
  14 +import LbpNoticeBar from 'core/plugins/lbp-notice-bar'
  15 +import LbpRate from 'core/plugins/lbp-rate'
  16 +import LbpQQMap from 'core/plugins/lbp-qq-map/src'
  17 +import LbpLineChart from 'core/plugins/charts/line'
  18 +import LbpTable from 'core/plugins/lbp-table'
  19 +import LbpNewsList from 'core/plugins/lbp-news-list'
  20 +// import LbpTabs from 'core/components/plugins/lbp-tabs'
21 21
22 export const pluginsList = [ 22 export const pluginsList = [
23 { 23 {
front-end/h5/src/components/plugins/lbp-background.js renamed to front-end/h5/src/components/core/plugins/lbp-background.js
@@ -2,14 +2,14 @@ @@ -2,14 +2,14 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-24 18:51:58 3 * @Date: 2019-11-24 18:51:58
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 21:02:47  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-background.js 5 + * @LastEditTime: 2020-10-10 23:32:48
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-background.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: luban-h5 background image/color component/plugin 8 * @Description: luban-h5 background image/color component/plugin
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import PropTypes from '@luban-h5/plugin-common-props' 11 import PropTypes from '@luban-h5/plugin-common-props'
12 -import { renderWaterMark } from '../../utils/dom-helper' 12 +import { renderWaterMark } from '@/utils/dom-helper'
13 13
14 export default { 14 export default {
15 name: 'lbp-background', 15 name: 'lbp-background',
front-end/h5/src/components/plugins/lbp-bg-music.js renamed to front-end/h5/src/components/core/plugins/lbp-bg-music.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2020-01-03 23:43:34 3 * @Date: 2020-01-03 23:43:34
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 20:58:32  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-bg-music.js 5 + * @LastEditTime: 2020-10-10 23:32:41
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-bg-music.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import PropTypes from '@luban-h5/plugin-common-props' 11 import PropTypes from '@luban-h5/plugin-common-props'
12 import './styles/bg-music.scss' 12 import './styles/bg-music.scss'
front-end/h5/src/components/plugins/lbp-button.js renamed to front-end/h5/src/components/core/plugins/lbp-button.js
front-end/h5/src/components/plugins/lbp-form-button.js renamed to front-end/h5/src/components/core/plugins/lbp-form-button.js
front-end/h5/src/components/plugins/lbp-form-checkbox-group.js renamed to front-end/h5/src/components/core/plugins/lbp-form-checkbox-group.js
front-end/h5/src/components/plugins/lbp-form-input.js renamed to front-end/h5/src/components/core/plugins/lbp-form-input.js
front-end/h5/src/components/plugins/lbp-form-radio-group.js renamed to front-end/h5/src/components/core/plugins/lbp-form-radio-group.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-23 12:35:43 3 * @Date: 2019-11-23 12:35:43
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 23:17:23  
6 - * @FilePath: /h5/src/components/plugins/lbp-form-radio-group.js 5 + * @LastEditTime: 2020-10-10 23:33:03
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-form-radio-group.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: 表单单选组组件 #!en: radio group component 8 * @Description: 表单单选组组件 #!en: radio group component
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 11
12 import PropTypes from '@luban-h5/plugin-common-props' 12 import PropTypes from '@luban-h5/plugin-common-props'
front-end/h5/src/components/plugins/lbp-form-radio.js renamed to front-end/h5/src/components/core/plugins/lbp-form-radio.js
@@ -2,15 +2,15 @@ @@ -2,15 +2,15 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2020-05-17 19:54:20 3 * @Date: 2020-05-17 19:54:20
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 19:55:02  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-form-radio.js 5 + * @LastEditTime: 2020-10-10 23:33:11
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-form-radio.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import './styles/radio.scss' 11 import './styles/radio.scss'
12 // https://github.com/luban-h5-components/plugin-common-props 12 // https://github.com/luban-h5-components/plugin-common-props
13 -import { genUUID } from '../../utils/element.js' 13 +import { genUUID } from '@/utils/element.js'
14 14
15 export default { 15 export default {
16 name: 'lbp-form-radio', 16 name: 'lbp-form-radio',
front-end/h5/src/components/plugins/lbp-news-list.js renamed to front-end/h5/src/components/core/plugins/lbp-news-list.js
1 import PropTypes from '@luban-h5/plugin-common-props' 1 import PropTypes from '@luban-h5/plugin-common-props'
2 -import Parser from '../../utils/excel-parser' 2 +import Parser from '@/utils/excel-parser'
3 import './styles/news-list.scss' 3 import './styles/news-list.scss'
4 4
5 export default { 5 export default {
front-end/h5/src/components/plugins/lbp-notice-bar.js renamed to front-end/h5/src/components/core/plugins/lbp-notice-bar.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2020-05-14 08:09:44 3 * @Date: 2020-05-14 08:09:44
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 21:18:32  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-notice-bar.js 5 + * @LastEditTime: 2020-10-10 23:33:19
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-notice-bar.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 11
12 import PropTypes from '@luban-h5/plugin-common-props' 12 import PropTypes from '@luban-h5/plugin-common-props'
front-end/h5/src/components/plugins/lbp-picture-placeholder.png renamed to front-end/h5/src/components/core/plugins/lbp-picture-placeholder.png

23.2 KB

front-end/h5/src/components/plugins/lbp-picture.js renamed to front-end/h5/src/components/core/plugins/lbp-picture.js
front-end/h5/src/components/plugins/lbp-qq-map/README.md renamed to front-end/h5/src/components/core/plugins/lbp-qq-map/README.md
front-end/h5/src/components/plugins/lbp-qq-map/src/Map.js renamed to front-end/h5/src/components/core/plugins/lbp-qq-map/src/Map.js
front-end/h5/src/components/plugins/lbp-qq-map/src/index.vue renamed to front-end/h5/src/components/core/plugins/lbp-qq-map/src/index.vue
front-end/h5/src/components/plugins/lbp-qq-map/src/mixin.js renamed to front-end/h5/src/components/core/plugins/lbp-qq-map/src/mixin.js
front-end/h5/src/components/plugins/lbp-qq-map__editor.js renamed to front-end/h5/src/components/core/plugins/lbp-qq-map__editor.js
front-end/h5/src/components/plugins/lbp-rate.js renamed to front-end/h5/src/components/core/plugins/lbp-rate.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2020-05-17 20:04:23 3 * @Date: 2020-05-17 20:04:23
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 21:33:31  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-rate.js 5 + * @LastEditTime: 2020-10-10 23:33:32
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-rate.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import PropTypes from '@luban-h5/plugin-common-props' 11 import PropTypes from '@luban-h5/plugin-common-props'
12 import { Rate } from 'vant' 12 import { Rate } from 'vant'
front-end/h5/src/components/plugins/lbp-slide.js renamed to front-end/h5/src/components/core/plugins/lbp-slide.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-23 12:35:21 3 * @Date: 2019-11-23 12:35:21
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 21:22:01  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-slide.js 5 + * @LastEditTime: 2020-10-10 23:33:43
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-slide.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: #!zh: 轮播图组件 #!en slide component 8 * @Description: #!zh: 轮播图组件 #!en slide component
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import PropTypes from '@luban-h5/plugin-common-props' 11 import PropTypes from '@luban-h5/plugin-common-props'
12 12
front-end/h5/src/components/plugins/lbp-slide__editor.js renamed to front-end/h5/src/components/core/plugins/lbp-slide__editor.js
front-end/h5/src/components/plugins/lbp-table.js renamed to front-end/h5/src/components/core/plugins/lbp-table.js
front-end/h5/src/components/plugins/lbp-text.js renamed to front-end/h5/src/components/core/plugins/lbp-text.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-11-24 18:51:58 3 * @Date: 2019-11-24 18:51:58
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 21:11:10  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-text.js 5 + * @LastEditTime: 2020-10-10 23:33:50
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-text.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: luban-h5 text component/plugin 8 * @Description: luban-h5 text component/plugin
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import PropTypes from '@luban-h5/plugin-common-props' 11 import PropTypes from '@luban-h5/plugin-common-props'
12 import { quillEditor } from 'vue-quill-editor' 12 import { quillEditor } from 'vue-quill-editor'
front-end/h5/src/components/plugins/lbp-video.js renamed to front-end/h5/src/components/core/plugins/lbp-video.js
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-12-01 18:11:50 3 * @Date: 2019-12-01 18:11:50
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2020-05-17 21:12:55  
6 - * @FilePath: /luban-h5/front-end/h5/src/components/plugins/lbp-video.js 5 + * @LastEditTime: 2020-10-10 23:33:57
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/plugins/lbp-video.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: Do not edit 8 * @Description: Do not edit
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import PropTypes from '@luban-h5/plugin-common-props' 11 import PropTypes from '@luban-h5/plugin-common-props'
12 12
front-end/h5/src/components/plugins/play.svg renamed to front-end/h5/src/components/core/plugins/play.svg
front-end/h5/src/components/plugins/styles/bg-music.scss renamed to front-end/h5/src/components/core/plugins/styles/bg-music.scss
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 right: 0; 26 right: 0;
27 top: 0; 27 top: 0;
28 border-radius: 15px; 28 border-radius: 15px;
29 - background-image: url(../bg-music.svg); 29 + background-image: url(./bg-music.svg);
30 background-size: contain; 30 background-size: contain;
31 background-repeat: no-repeat; 31 background-repeat: no-repeat;
32 32
front-end/h5/src/components/plugins/bg-music.svg renamed to front-end/h5/src/components/core/plugins/styles/bg-music.svg
front-end/h5/src/components/plugins/styles/news-list.scss renamed to front-end/h5/src/components/core/plugins/styles/news-list.scss
front-end/h5/src/components/plugins/styles/radio.scss renamed to front-end/h5/src/components/core/plugins/styles/radio.scss
front-end/h5/src/components/plugins/styles/table.scss renamed to front-end/h5/src/components/core/plugins/styles/table.scss
front-end/h5/src/components/plugins/styles/text-overwrite-quil-snow-theme.scss renamed to front-end/h5/src/components/core/plugins/styles/text-overwrite-quil-snow-theme.scss
front-end/h5/src/components/plugins/styles/video.scss renamed to front-end/h5/src/components/core/plugins/styles/video.scss
front-end/h5/src/components/preview/node-wrapper.js renamed to front-end/h5/src/components/core/preview/node-wrapper.js
1 -import animationMixin from '@/mixins/animation.js' 1 +import animationMixin from 'core/mixins/animation.js'
2 2
3 export default { 3 export default {
4 mixins: [animationMixin], 4 mixins: [animationMixin],
front-end/h5/src/components/core/router/index.js 0 → 100644
  1 +import Vue from 'vue'
  2 +import Router from 'vue-router'
  3 +Vue.use(Router)
  4 +
  5 +export default new Router()
front-end/h5/src/components/core/store/index.js 0 → 100644
  1 +/*
  2 + * @Author: ly525
  3 + * @Date: 2020-10-11 10:13:51
  4 + * @LastEditors: ly525
  5 + * @LastEditTime: 2020-10-11 11:16:37
  6 + * @FilePath: /luban-h5/front-end/h5/src/components/core/store/index.js
  7 + * @Github: https://github.com/ly525/luban-h5
  8 + * @Description: Do not edit
  9 + * @Copyright 2018 - 2019 luban-h5. All Rights Reserved
  10 + */
  11 +import Vue from 'vue'
  12 +import Vuex from 'vuex'
  13 +import undoRedoPlugin from './plugins/undo-redo/index'
  14 +import editor from './modules/editor'
  15 +import user from './modules/user'
  16 +import loading from './modules/loading'
  17 +import i18n from './modules/i18n'
  18 +
  19 +Vue.use(Vuex)
  20 +
  21 +export default new Vuex.Store({
  22 + state: {
  23 +
  24 + },
  25 + mutations: {
  26 +
  27 + },
  28 + actions: {
  29 +
  30 + },
  31 + modules: {
  32 + editor,
  33 + user,
  34 + loading,
  35 + i18n
  36 + },
  37 + plugins: [undoRedoPlugin]
  38 +})
front-end/h5/src/components/core/store/modules/canvas.js 0 → 100644
  1 +// actions
  2 +export const actions = {
  3 + updateScaleRate ({ commit }, payload) {
  4 + commit('updateScaleRate', payload)
  5 + }
  6 +}
  7 +
  8 +// mutations
  9 +export const mutations = {
  10 + /**
  11 + *
  12 + * @param {*} state
  13 + * @param {Number} scaleRateDiff 放大: 0.25, 缩小: -0.25
  14 + */
  15 + updateScaleRate (state, scaleRateDiff) {
  16 + state.scaleRate += scaleRateDiff
  17 + }
  18 +}
front-end/h5/src/components/core/store/modules/editor.js 0 → 100644
  1 +// initial state
  2 +import Work from 'core/models/work'
  3 +import { actions as canvasActions, mutations as canvasMutations } from './canvas'
  4 +import { actions as pageActions, mutations as pageMutations } from './page'
  5 +import { actions as elementActions, mutations as elementMutations } from './element'
  6 +import { actions as workActions, mutations as workMutations } from './work'
  7 +
  8 +const state = {
  9 + works: [],
  10 + work: new Work(),
  11 + editingPage: { elements: [] },
  12 + editingElement: null,
  13 + formDetailOfWork: {
  14 + uuidMap2Name: {},
  15 + formRecords: []
  16 + },
  17 + workTemplates: [],
  18 + scaleRate: 1
  19 +}
  20 +
  21 +// getters
  22 +const getters = {}
  23 +
  24 +// actions
  25 +const actions = {
  26 + ...elementActions,
  27 + ...pageActions,
  28 + ...workActions,
  29 + ...canvasActions
  30 +}
  31 +
  32 +// mutations
  33 +const mutations = {
  34 + ...elementMutations,
  35 + ...pageMutations,
  36 + ...workMutations,
  37 + ...canvasMutations
  38 +}
  39 +
  40 +export default {
  41 + namespaced: true,
  42 + state,
  43 + getters,
  44 + actions,
  45 + mutations
  46 +}
front-end/h5/src/store/modules/element.js renamed to front-end/h5/src/components/core/store/modules/element.js
1 -import Element from '../../components/core/models/element'  
2 -import { swapZindex, getVM } from '../../utils/element' 1 +import Element from 'core/models/element'
  2 +import { swapZindex, getVM } from '@/utils/element'
3 3
4 // actions 4 // actions
5 export const actions = { 5 export const actions = {
6 setEditingElement ({ commit }, payload) { 6 setEditingElement ({ commit }, payload) {
7 commit('setEditingElement', payload) 7 commit('setEditingElement', payload)
8 - payload && window.getEditorApp.$emit('setEditingElement', payload) 8 + payload && window.EditorApp.$emit('setEditingElement', payload)
9 }, 9 },
10 setElementPosition ({ commit }, payload) { 10 setElementPosition ({ commit }, payload) {
11 commit('setElementCommonStyle', payload) 11 commit('setElementCommonStyle', payload)
front-end/h5/src/components/core/store/modules/i18n.js 0 → 100755
  1 +import { loadLanguageAsync } from '@/locales'
  2 +
  3 +const i18n = {
  4 + namespaced: true,
  5 + state: {
  6 + lang: 'zh-CN'
  7 + },
  8 + mutations: {
  9 + SET_LANG: (state, lang) => {
  10 + state.lang = lang
  11 + }
  12 + },
  13 + actions: {
  14 + // 设置界面语言
  15 + SetLang ({ commit }, lang) {
  16 + return new Promise(resolve => {
  17 + commit('SET_LANG', lang)
  18 + loadLanguageAsync(lang)
  19 + resolve()
  20 + })
  21 + }
  22 + }
  23 +}
  24 +
  25 +export default i18n
front-end/h5/src/components/core/store/modules/loading.js 0 → 100644
  1 +/*
  2 + * @Author: ly525
  3 + * @Date: 2019-11-24 18:51:58
  4 + * @LastEditors: ly525
  5 + * @LastEditTime: 2019-12-08 17:21:48
  6 + * @FilePath: /luban-h5/front-end/h5/src/store/modules/loading.js
  7 + * @Github: https://github.com/ly525/luban-h5
  8 + * @Description: loading module
  9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
  10 + */
  11 +// initial state
  12 +const state = {
  13 + saveWork_loading: false,
  14 + previewWork_loading: false,
  15 + fetchWorks_loading: false,
  16 + setWorkAsTemplate_loading: false,
  17 + fetchWorkTemplates_loading: false,
  18 + useTemplate_loading: false,
  19 + uploadWorkCover_loading: false
  20 +}
  21 +
  22 +// getters
  23 +const getters = {
  24 +
  25 +}
  26 +
  27 +// actions
  28 +const actions = {
  29 + update ({ commit }, payload) {
  30 + commit('update', payload)
  31 + }
  32 +}
  33 +
  34 +// mutations
  35 +const mutations = {
  36 + update (state, { type, payload }) {
  37 + state[type] = payload
  38 + }
  39 +}
  40 +
  41 +export default {
  42 + namespaced: true,
  43 + state,
  44 + getters,
  45 + actions,
  46 + mutations
  47 +}
front-end/h5/src/store/modules/page.js renamed to front-end/h5/src/components/core/store/modules/page.js
@@ -2,15 +2,15 @@ @@ -2,15 +2,15 @@
2 * @Author: ly525 2 * @Author: ly525
3 * @Date: 2019-12-08 17:05:09 3 * @Date: 2019-12-08 17:05:09
4 * @LastEditors: ly525 4 * @LastEditors: ly525
5 - * @LastEditTime: 2019-12-15 15:41:56 5 + * @LastEditTime: 2020-10-10 23:34:28
6 * @FilePath: /luban-h5/front-end/h5/src/store/modules/page.js 6 * @FilePath: /luban-h5/front-end/h5/src/store/modules/page.js
7 * @Github: https://github.com/ly525/luban-h5 7 * @Github: https://github.com/ly525/luban-h5
8 * @Description: page module 8 * @Description: page module
9 - * @Copyright 2018 - 2019 luban-h5. All Rights Reserved 9 + * @Copyright 2018 - 2020 luban-h5. All Rights Reserved
10 */ 10 */
11 import { message } from 'ant-design-vue' 11 import { message } from 'ant-design-vue'
12 12
13 -import Page from '../../components/core/models/page' 13 +import Page from 'core/models/page'
14 14
15 // actions 15 // actions
16 export const actions = { 16 export const actions = {
@@ -30,8 +30,8 @@ export const mutations = { @@ -30,8 +30,8 @@ export const mutations = {
30 pageManager (state, { type, value }) { 30 pageManager (state, { type, value }) {
31 switch (type) { 31 switch (type) {
32 case 'editTitle': 32 case 'editTitle':
33 - const { pageIndexForEditingTitle, newTitle } = value  
34 - state.work.pages[pageIndexForEditingTitle].title = newTitle 33 + const { pageIndex, newTitle } = value
  34 + state.work.pages[pageIndex].title = newTitle
35 break 35 break
36 case 'add': 36 case 'add':
37 const page = new Page(value) 37 const page = new Page(value)
front-end/h5/src/store/modules/visible.js renamed to front-end/h5/src/components/core/store/modules/user.js
front-end/h5/src/components/core/store/modules/work.js 0 → 100644
  1 +import Element from 'core/models/element'
  2 +import strapi from '@/utils/strapi'
  3 +import Page from 'core/models/page'
  4 +import Work from 'core/models/work'
  5 +import { AxiosWrapper } from '@/utils/http.js'
  6 +// import router from '@/router.js'
  7 +import { takeScreenshot } from '@/utils/canvas-helper.js'
  8 +
  9 +function setLoading (commit, loadingName, isLoading) {
  10 + commit('loading/update', { type: loadingName, payload: isLoading }, { root: true })
  11 +}
  12 +
  13 +export const actions = {
  14 + previewWork ({ commit }, payload = {}) {
  15 + commit('previewWork', payload)
  16 + },
  17 + deployWork ({ commit }, payload = {}) {
  18 + commit('previewWork', payload)
  19 + },
  20 + // createWork ({ commit }, payload) {
  21 + // strapi.createEntry('works', new Work()).then(entry => {
  22 + // const routeData = router.resolve({ name: 'editor', params: { workId: entry.id } })
  23 + // window.open(routeData.href, '_blank')
  24 + // // 如果希望不打开新 tab,可以注释上面面两行,启用下面一行的代码即可,不过不推荐。将编辑器单独起一个页面更有利于 vuex 的数据管理
  25 + // // router.replace({ name: 'editor', params: { workId: entry.id } })
  26 + // })
  27 + // },
  28 + updateWork ({ commit, state }, payload = {}) {
  29 + // update work with strapi
  30 + const work = {
  31 + ...state.work,
  32 + ...payload
  33 + }
  34 + commit('setWork', work)
  35 + },
  36 + /**
  37 + * isSaveCover {Boolean} 保存作品时,是否保存封面图
  38 + * loadingName {String} saveWork_loading, previewWork_loading
  39 + * 预览作品之前需要先保存,但希望 用户点击保存按钮 和 点击预览按钮 loading_name 能够不同(虽然都调用了 saveWork)
  40 + * 因为 loading 效果要放在不同的按钮上
  41 + */
  42 + saveWork ({ commit, dispatch, state }, { isSaveCover = false, loadingName = 'saveWork_loading', successMsg = '保存作品成功' } = {}) {
  43 + const fn = (callback) => {
  44 + new AxiosWrapper({
  45 + dispatch,
  46 + commit,
  47 + loading_name: loadingName,
  48 + successMsg,
  49 + customRequest: strapi.updateEntry.bind(strapi)
  50 + }).put('works', state.work.id, state.work).then(callback)
  51 + }
  52 + return new Promise((resolve, reject) => {
  53 + if (isSaveCover) {
  54 + setLoading(commit, 'uploadWorkCover_loading', true)
  55 + takeScreenshot().then(file => {
  56 + dispatch('uploadCover', { file }).then(() => {
  57 + setLoading(commit, 'uploadWorkCover_loading', false)
  58 + fn(resolve)
  59 + }) // uploadCover
  60 + }) // takeScreenshot
  61 + } else {
  62 + fn(resolve)
  63 + }
  64 + })
  65 + },
  66 + fetchWork ({ commit, state }, workId) {
  67 + return strapi.getEntry('works', workId).then(entry => {
  68 + commit('setWork', entry)
  69 + commit('setEditingPage')
  70 + })
  71 + },
  72 + fetchWorks ({ commit, dispatch, state }, workId) {
  73 + new AxiosWrapper({
  74 + dispatch,
  75 + commit,
  76 + name: 'editor/setWorks',
  77 + loading_name: 'fetchWorks_loading',
  78 + successMsg: '获取作品列表成功',
  79 + customRequest: strapi.getEntries.bind(strapi)
  80 + }).get('works', { is_template: false })
  81 + },
  82 + fetchWorksWithForms ({ commit, dispatch, state }, workId) {
  83 + new AxiosWrapper({
  84 + dispatch,
  85 + commit,
  86 + name: 'editor/setWorks',
  87 + loading_name: 'fetchWorks_loading',
  88 + successMsg: '获取作品列表成功',
  89 + customRequest: strapi.getEntries.bind(strapi)
  90 + }).get('works/has-forms', { is_template: false })
  91 + },
  92 + fetchWorkTemplates ({ commit, dispatch, state }, workId) {
  93 + new AxiosWrapper({
  94 + dispatch,
  95 + commit,
  96 + name: 'editor/setWorkTemplates',
  97 + loading_name: 'fetchWorkTemplates_loading',
  98 + successMsg: '获取模板列表成功',
  99 + customRequest: strapi.getEntries.bind(strapi)
  100 + }).get('works', { is_template: true })
  101 + },
  102 + /**
  103 + *
  104 + * @param {*} workId
  105 + * response demo:
  106 + {
  107 + "uuidMap2Name": {
  108 + "1565596393441": "姓名",
  109 + "1565596397671": "学校"
  110 + },
  111 + "formRecords": [
  112 + {
  113 + "id": 3,
  114 + "form": {
  115 + "1565369322603": "abc"
  116 + },
  117 + "work": 8,
  118 + "created_at": "2019-08-09T16:52:28.826Z",
  119 + "updated_at": "2019-08-09T16:52:28.832Z"
  120 + },
  121 + {
  122 + "id": 4,
  123 + "form": {
  124 + "1565595388440": "ddd"
  125 + },
  126 + "work": 8,
  127 + "created_at": "2019-08-11T07:36:54.521Z",
  128 + "updated_at": "2019-08-11T07:36:54.526Z"
  129 + },
  130 + {
  131 + "id": 5,
  132 + "form": {
  133 + "1565595388440": "acd"
  134 + },
  135 + "work": 8,
  136 + "created_at": "2019-08-11T07:45:22.000Z",
  137 + "updated_at": "2019-08-11T07:45:22.005Z"
  138 + },
  139 + {
  140 + "id": 6,
  141 + "form": {
  142 + "1565596393441": "b",
  143 + "1565596397671": "a"
  144 + },
  145 + "work": 8,
  146 + "created_at": "2019-08-11T07:59:00.938Z",
  147 + "updated_at": "2019-08-11T07:59:00.943Z"
  148 + },
  149 + {
  150 + "id": 7,
  151 + "form": {
  152 + "1565596393441": "b",
  153 + "1565596397671": "a"
  154 + },
  155 + "work": 8,
  156 + "created_at": "2019-08-11T07:59:37.065Z",
  157 + "updated_at": "2019-08-11T07:59:37.070Z"
  158 + }
  159 + ]
  160 + }
  161 + */
  162 + fetchFormsOfWork ({ commit, state, dispatch }, workId) {
  163 + // 可以 return Promise
  164 + new AxiosWrapper({
  165 + dispatch,
  166 + commit,
  167 + name: 'editor/formDetailOfWork',
  168 + loading_name: 'queryFormsOfWork_loading',
  169 + successMsg: '表单查询完毕'
  170 + }).get(`/works/form/query/${workId}`)
  171 + },
  172 + setWorkAsTemplate ({ commit, state, dispatch }, workId) {
  173 + new AxiosWrapper({
  174 + dispatch,
  175 + commit,
  176 + // name: 'editor/formDetailOfWork',
  177 + loading_name: 'setWorkAsTemplate_loading',
  178 + successMsg: '设置为模板成功'
  179 + }).post(`/works/set-as-template/${workId || state.work.id}`)
  180 + },
  181 + useTemplate ({ commit, state, dispatch }, workId) {
  182 + return new AxiosWrapper({
  183 + dispatch,
  184 + commit,
  185 + // name: 'editor/formDetailOfWork',
  186 + loading_name: 'useTemplate_loading',
  187 + successMsg: '使用模板成功'
  188 + }).post(`/works/use-template/${workId}`)
  189 + },
  190 + uploadCover ({ commit, state, dispatch }, { file } = {}) {
  191 + const formData = new FormData()
  192 + formData.append('files', file, `${+new Date()}.png`)
  193 + formData.append('workId', state.work.id)
  194 + return new AxiosWrapper({
  195 + dispatch,
  196 + commit,
  197 + name: 'editor/setWorkCover',
  198 + loading_name: 'uploadWorkCover_loading',
  199 + successMsg: '上传封面图成功!'
  200 + // }).post(`/works/uploadCover/${state.work.id}`, formData)
  201 + }).post(`/upload/`, formData)
  202 + }
  203 +}
  204 +
  205 +// mutations
  206 +export const mutations = {
  207 + /**
  208 + *
  209 + * @param {*} state
  210 + * @param {Object} payload
  211 + *
  212 + value example: [
  213 + {
  214 + "id": 1,
  215 + "name": "1567769149231.png",
  216 + "hash": "1660b11229e7473b90f99a9f9afe7675",
  217 + "sha256": "lKl7f_csUAgOjf0VRYkBZ64EcTjvt4Dt4beNIhELpTU",
  218 + "ext": ".png",
  219 + "mime": "image/png",
  220 + "size": "6.57",
  221 + "url": "/uploads/1660b11229e7473b90f99a9f9afe7675.png",
  222 + "provider": "local",
  223 + "public_id": null,
  224 + "created_at": "2019-09-06T11:25:49.255Z",
  225 + "updated_at": "2019-09-06T11:25:49.261Z",
  226 + "related": []
  227 + }
  228 + ]
  229 + */
  230 + setWorkCover (state, { type, value }) {
  231 + const [cover] = value
  232 + state.work.cover_image_url = cover.url
  233 + },
  234 + /**
  235 + * payload: {
  236 + * type: @params {String} "editor/setWorks",
  237 + * value: @params {Array} work list
  238 + * }
  239 + */
  240 + setWorks (state, { type, value }) {
  241 + value.sort((a, b) => b.id - a.id)
  242 + state.works = value
  243 + },
  244 + /**
  245 + * payload: {
  246 + * type: @params {String} "editor/setWorks",
  247 + * value: @params {Array} work list
  248 + * }
  249 + */
  250 + setWorkTemplates (state, { type, value }) {
  251 + value.sort((a, b) => b.id - a.id)
  252 + state.workTemplates = value
  253 + },
  254 + setWork (state, work) {
  255 + window.__work = work
  256 + work.pages = work.pages.map(page => {
  257 + page.elements = page.elements.map(element => new Element(element))
  258 + return new Page(page)
  259 + })
  260 + state.work = new Work(work)
  261 + },
  262 + previewWork (state, { type, value }) {},
  263 + deployWork (state, { type, value }) {},
  264 + formDetailOfWork (state, { type, value }) {
  265 + state.formDetailOfWork = value
  266 + }
  267 +}
front-end/h5/src/store/plugins/undo-redo/History.js renamed to front-end/h5/src/components/core/store/plugins/undo-redo/History.js
front-end/h5/src/store/plugins/undo-redo/index.js renamed to front-end/h5/src/components/core/store/plugins/undo-redo/index.js
front-end/h5/src/components/core/styles/index.scss
@@ -6,52 +6,6 @@ @@ -6,52 +6,6 @@
6 @import url("./page-manager.scss"); 6 @import url("./page-manager.scss");
7 @import url("./canvas-wrapper.scss"); 7 @import url("./canvas-wrapper.scss");
8 8
9 -#luban-editor-layout,  
10 -#luban-work-manager-layout {  
11 - .header {  
12 - padding: 0 10px;  
13 -  
14 - .logo {  
15 - width: 120px;  
16 - height: 31px;  
17 - // background: rgba(255,255,255,.2);  
18 - margin: 16px 28px 16px 0;  
19 - float: left;  
20 -  
21 - line-height: 31px;  
22 - text-align: center;  
23 - color: white;  
24 - font-size: 16px;  
25 - }  
26 -  
27 - .lang-select-activator,  
28 - .user-avatar-activator {  
29 - float: right;  
30 - background: transparent;  
31 - margin: 0 28px 16px 0;  
32 - cursor: pointer;  
33 -  
34 - .anticon {  
35 - color: white;  
36 - }  
37 - }  
38 - }  
39 -  
40 - #props-edit-form {  
41 - .ant-form-item {  
42 - margin-bottom: 12px;  
43 - }  
44 - }  
45 -  
46 - .card-cover-wrapper {  
47 - position: relative;  
48 - height: 300px;  
49 - border: 1px dashed #eee;  
50 - color: #aaa;  
51 - padding: 4px;  
52 - }  
53 -}  
54 -  
55 .hidden { 9 .hidden {
56 display: none !important; 10 display: none !important;
57 } 11 }
@@ -84,7 +38,7 @@ @@ -84,7 +38,7 @@
84 } 38 }
85 39
86 // 动画编辑面板定制 40 // 动画编辑面板定制
87 -#animation-edit-panel { 41 +#animation-right-panel {
88 .ant-collapse-header { 42 .ant-collapse-header {
89 padding: 6px 0 6px 40px; 43 padding: 6px 0 6px 40px;
90 } 44 }
@@ -180,7 +134,7 @@ $activeHoverColor: #1593ff; @@ -180,7 +134,7 @@ $activeHoverColor: #1593ff;
180 134
181 .adjust-line-wrapper-v { 135 .adjust-line-wrapper-v {
182 position: relative; 136 position: relative;
183 - height: 100%; 137 + height: 100vh;
184 cursor: ew-resize; 138 cursor: ew-resize;
185 139
186 .adjust-button { 140 .adjust-button {
front-end/h5/src/components/core/styles/props-config-panel.scss 0 → 100644
  1 +.props-config-form {
  2 + .ant-form-item {
  3 + margin-bottom: 12px;
  4 + }
  5 +}
0 \ No newline at end of file 6 \ No newline at end of file
front-end/h5/src/components/core/support/excel.js
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 */ 3 */
4 4
5 import Spreadsheet from 'x-data-spreadsheet' 5 import Spreadsheet from 'x-data-spreadsheet'
6 -import Parser from '../../../utils/excel-parser' 6 +import Parser from '@/utils/excel-parser'
7 import CsvImport from './csv-import' 7 import CsvImport from './csv-import'
8 // const getDefaultTableMatrix = () => [ 8 // const getDefaultTableMatrix = () => [
9 // [1, 2, 3, 4], 9 // [1, 2, 3, 4],
front-end/h5/src/components/core/support/image-gallery/tabs/personal.js
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 * https://github.com/ly525/luban-h5/issues/138 2 * https://github.com/ly525/luban-h5/issues/138
3 */ 3 */
4 import axios from 'axios' 4 import axios from 'axios'
5 -import ImageItem from '../components/image-item.js'  
6 -import Uploader from '../components/uploader.js' 5 +import ImageItem from 'core/support/image-gallery/components/image-item.js'
  6 +import Uploader from 'core/support/image-gallery/components/uploader.js'
7 7
8 export default { 8 export default {
9 data: () => ({ 9 data: () => ({