Commit cbea4adce501421098256fff897a8da488801347
Committed by
GitHub
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
front-end/h5/src/components/common/header/LangSelect.vue
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
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
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
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
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 'echarts/lib/component/legend' | @@ -8,7 +8,7 @@ import 'echarts/lib/component/legend' | ||
| 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
front-end/h5/src/components/core/router/index.js
0 → 100644
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
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: () => ({ |