Commit 722031c925351e82ea30a93d90ddc3f462f4084f
1 parent
d21296a7
feat: support long page mode(alpha);
#!zh: 支持长页面(alpha)
Showing
12 changed files
with
266 additions
and
19 deletions
back-end/h5-api/api/work/documentation/1.0.0/work.json
| ... | ... | @@ -1002,6 +1002,18 @@ |
| 1002 | 1002 | }, |
| 1003 | 1003 | "is_template": { |
| 1004 | 1004 | "type": "boolean" |
| 1005 | + }, | |
| 1006 | + "mode": { | |
| 1007 | + "type": "string", | |
| 1008 | + "enum": [ | |
| 1009 | + "h5_swipper", | |
| 1010 | + "h5_long_page", | |
| 1011 | + "h5_form" | |
| 1012 | + ] | |
| 1013 | + }, | |
| 1014 | + "height": { | |
| 1015 | + "type": "integer", | |
| 1016 | + "default": 568 | |
| 1005 | 1017 | } |
| 1006 | 1018 | } |
| 1007 | 1019 | }, |
| ... | ... | @@ -1024,6 +1036,18 @@ |
| 1024 | 1036 | }, |
| 1025 | 1037 | "is_template": { |
| 1026 | 1038 | "type": "boolean" |
| 1039 | + }, | |
| 1040 | + "mode": { | |
| 1041 | + "type": "string", | |
| 1042 | + "enum": [ | |
| 1043 | + "h5_swipper", | |
| 1044 | + "h5_long_page", | |
| 1045 | + "h5_form" | |
| 1046 | + ] | |
| 1047 | + }, | |
| 1048 | + "height": { | |
| 1049 | + "type": "integer", | |
| 1050 | + "default": 568 | |
| 1027 | 1051 | } |
| 1028 | 1052 | } |
| 1029 | 1053 | } | ... | ... |
back-end/h5-api/api/work/models/Work.settings.json
| ... | ... | @@ -31,6 +31,18 @@ |
| 31 | 31 | }, |
| 32 | 32 | "is_template": { |
| 33 | 33 | "type": "boolean" |
| 34 | + }, | |
| 35 | + "mode": { | |
| 36 | + "type": "enumeration", | |
| 37 | + "enum": [ | |
| 38 | + "h5_swipper", | |
| 39 | + "h5_long_page", | |
| 40 | + "h5_form" | |
| 41 | + ] | |
| 42 | + }, | |
| 43 | + "height": { | |
| 44 | + "type": "integer", | |
| 45 | + "default": 568 | |
| 34 | 46 | } |
| 35 | 47 | } |
| 36 | -} | |
| 37 | 48 | \ No newline at end of file |
| 49 | +} | ... | ... |
back-end/h5-api/api/workform/documentation/1.0.0/workform.json
back-end/h5-api/extensions/documentation/documentation/1.0.0/full_documentation.json
| 1 | 1 | { |
| 2 | 2 | "openapi": "3.0.0", |
| 3 | 3 | "info": { |
| 4 | - "version": "0.0.1", | |
| 5 | - "title": "#!zh: 鲁班H5-后端API 文档", | |
| 6 | - "description": "#!zh: 鲁班H5-后端API 文档(#!en: API docs for luban-h5)", | |
| 4 | + "version": "1.0.0", | |
| 5 | + "title": "DOCUMENTATION", | |
| 6 | + "description": "", | |
| 7 | + "termsOfService": "YOUR_TERMS_OF_SERVICE_URL", | |
| 7 | 8 | "contact": { |
| 8 | - "name": "Feedback", | |
| 9 | - "url": "https://github.com/ly525/luban-h5/issues/new?title=[api-docs-feedback]" | |
| 9 | + "name": "TEAM", | |
| 10 | + "email": "contact-email@something.io", | |
| 11 | + "url": "mywebsite.io" | |
| 10 | 12 | }, |
| 11 | - "x-generation-date": "01/26/2020 5:36:49 PM" | |
| 13 | + "license": { | |
| 14 | + "name": "Apache 2.0", | |
| 15 | + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" | |
| 16 | + }, | |
| 17 | + "x-generation-date": "05/10/2020 10:31:59 PM" | |
| 12 | 18 | }, |
| 13 | 19 | "x-strapi-config": { |
| 14 | 20 | "path": "/documentation", |
| ... | ... | @@ -29,8 +35,8 @@ |
| 29 | 35 | } |
| 30 | 36 | ], |
| 31 | 37 | "externalDocs": { |
| 32 | - "description": "#!zh 鲁班H5完整文档(#!en Full Docs for Luban-H5)", | |
| 33 | - "url": "https://ly525.github.io/luban-h5/" | |
| 38 | + "description": "Find out more", | |
| 39 | + "url": "https://strapi.io/documentation/3.0.0-beta.x/" | |
| 34 | 40 | }, |
| 35 | 41 | "security": [ |
| 36 | 42 | { |
| ... | ... | @@ -3706,6 +3712,18 @@ |
| 3706 | 3712 | }, |
| 3707 | 3713 | "is_template": { |
| 3708 | 3714 | "type": "boolean" |
| 3715 | + }, | |
| 3716 | + "mode": { | |
| 3717 | + "type": "string", | |
| 3718 | + "enum": [ | |
| 3719 | + "h5_swipper", | |
| 3720 | + "h5_long_page", | |
| 3721 | + "h5_form" | |
| 3722 | + ] | |
| 3723 | + }, | |
| 3724 | + "height": { | |
| 3725 | + "type": "integer", | |
| 3726 | + "default": 568 | |
| 3709 | 3727 | } |
| 3710 | 3728 | } |
| 3711 | 3729 | }, |
| ... | ... | @@ -3728,6 +3746,18 @@ |
| 3728 | 3746 | }, |
| 3729 | 3747 | "is_template": { |
| 3730 | 3748 | "type": "boolean" |
| 3749 | + }, | |
| 3750 | + "mode": { | |
| 3751 | + "type": "string", | |
| 3752 | + "enum": [ | |
| 3753 | + "h5_swipper", | |
| 3754 | + "h5_long_page", | |
| 3755 | + "h5_form" | |
| 3756 | + ] | |
| 3757 | + }, | |
| 3758 | + "height": { | |
| 3759 | + "type": "integer", | |
| 3760 | + "default": 568 | |
| 3731 | 3761 | } |
| 3732 | 3762 | } |
| 3733 | 3763 | }, |
| ... | ... | @@ -3767,6 +3797,12 @@ |
| 3767 | 3797 | }, |
| 3768 | 3798 | "is_template": { |
| 3769 | 3799 | "type": "boolean" |
| 3800 | + }, | |
| 3801 | + "mode": { | |
| 3802 | + "type": "string" | |
| 3803 | + }, | |
| 3804 | + "height": { | |
| 3805 | + "type": "integer" | |
| 3770 | 3806 | } |
| 3771 | 3807 | } |
| 3772 | 3808 | } | ... | ... |
front-end/h5/src/components/core/editor/canvas/edit.js
| ... | ... | @@ -10,7 +10,7 @@ export default { |
| 10 | 10 | contextmenuPos: [] |
| 11 | 11 | }), |
| 12 | 12 | computed: { |
| 13 | - ...mapState('editor', ['editingElement']) | |
| 13 | + ...mapState('editor', ['editingElement', 'work']) | |
| 14 | 14 | }, |
| 15 | 15 | methods: { |
| 16 | 16 | ...mapActions('editor', [ |
| ... | ... | @@ -18,7 +18,8 @@ export default { |
| 18 | 18 | 'setElementPosition', |
| 19 | 19 | 'setElementShape', |
| 20 | 20 | 'recordElementRect', |
| 21 | - 'elementManager' | |
| 21 | + 'elementManager', | |
| 22 | + 'updateWork' | |
| 22 | 23 | ]), |
| 23 | 24 | // TODO #!zh: 优化代码 |
| 24 | 25 | // generate vertical line |
| ... | ... | @@ -142,6 +143,43 @@ export default { |
| 142 | 143 | } |
| 143 | 144 | }, |
| 144 | 145 | /** |
| 146 | + * 更新作品高度 | |
| 147 | + * @param {Number} height | |
| 148 | + */ | |
| 149 | + updateWorkHeight (height) { | |
| 150 | + this.updateWork({ height }) | |
| 151 | + }, | |
| 152 | + /** | |
| 153 | + * TODO 封装 adjust editor scale 组件 | |
| 154 | + * scale: height/width | |
| 155 | + * @param {MouseEvent} e | |
| 156 | + */ | |
| 157 | + mousedownForAdjustLine (e) { | |
| 158 | + let startY = e.clientY | |
| 159 | + let startHeight = this.work.height | |
| 160 | + | |
| 161 | + const canvasOuterWrapper = document.querySelector('#canvas-outer-wrapper') | |
| 162 | + | |
| 163 | + let move = moveEvent => { | |
| 164 | + // !#zh 移动的时候,不需要向后代元素传递事件,只需要单纯的移动就OK | |
| 165 | + moveEvent.stopPropagation() | |
| 166 | + moveEvent.preventDefault() | |
| 167 | + | |
| 168 | + let currY = moveEvent.clientY | |
| 169 | + let currentHeight = currY - startY + startHeight | |
| 170 | + this.updateWorkHeight(currentHeight) | |
| 171 | + // 交互效果:滚动条同步滚动至底部 | |
| 172 | + canvasOuterWrapper && (canvasOuterWrapper.scrollTop = canvasOuterWrapper.scrollHeight) | |
| 173 | + } | |
| 174 | + | |
| 175 | + let up = moveEvent => { | |
| 176 | + document.removeEventListener('mousemove', move, true) | |
| 177 | + document.removeEventListener('mouseup', up, true) | |
| 178 | + } | |
| 179 | + document.addEventListener('mousemove', move, true) | |
| 180 | + document.addEventListener('mouseup', up, true) | |
| 181 | + }, | |
| 182 | + /** | |
| 145 | 183 | * #!zh: renderCanvas 渲染中间画布 |
| 146 | 184 | * elements |
| 147 | 185 | * @param {*} h |
| ... | ... | @@ -251,6 +289,26 @@ export default { |
| 251 | 289 | onHideMenu={this.hideContextMenu} |
| 252 | 290 | /> : null |
| 253 | 291 | } |
| 292 | + <div style={{ | |
| 293 | + position: 'absolute', | |
| 294 | + top: `${this.work.height}px`, | |
| 295 | + width: '100%' | |
| 296 | + }}> | |
| 297 | + <div class="long-page-adjust"> | |
| 298 | + <div class="adjust-line"></div> | |
| 299 | + <div class="adjust-button" onMousedown={this.mousedownForAdjustLine}><div class="indicator"></div></div> | |
| 300 | + <div class="adjust-tip"> | |
| 301 | + <span>320 x</span> | |
| 302 | + <a-input-number | |
| 303 | + size="small" | |
| 304 | + style="margin: 0 4px; width:60px;" | |
| 305 | + value={this.work.height} | |
| 306 | + onChange={height => { this.updateWork({ height }) }} | |
| 307 | + /> | |
| 308 | + <span>px</span> | |
| 309 | + </div> | |
| 310 | + </div> | |
| 311 | + </div> | |
| 254 | 312 | </div> |
| 255 | 313 | ) |
| 256 | 314 | } | ... | ... |
front-end/h5/src/components/core/editor/edit-panel/props.js
| 1 | 1 | import Vue from 'vue' |
| 2 | 2 | import { mapState, mapActions } from 'vuex' |
| 3 | 3 | import { getVM, getComponentsForPropsEditor } from '../../../../utils/element' |
| 4 | +import RenderGlobalWorkPropsEditor from './props/global-work.vue' | |
| 4 | 5 | |
| 5 | 6 | export default { |
| 6 | 7 | data: () => ({ |
| ... | ... | @@ -141,11 +142,14 @@ export default { |
| 141 | 142 | } |
| 142 | 143 | </a-form> |
| 143 | 144 | ) |
| 145 | + }, | |
| 146 | + renderWorkGlobalPropsPanel (h) { | |
| 147 | + return <RenderGlobalWorkPropsEditor /> | |
| 144 | 148 | } |
| 145 | 149 | }, |
| 146 | 150 | render (h) { |
| 147 | 151 | const ele = this.editingElement |
| 148 | - if (!ele) return (<span>{this.$t('editor.editPanel.common.empty')}</span>) | |
| 152 | + if (!ele) return this.renderWorkGlobalPropsPanel(h) | |
| 149 | 153 | this.mixinEnhancedPropsEditor(ele) |
| 150 | 154 | return this.renderPropsEditorPanel(h, ele) |
| 151 | 155 | }, | ... | ... |
front-end/h5/src/components/core/editor/edit-panel/props/global-work.vue
0 → 100644
| 1 | +<!-- | |
| 2 | + * @Author: ly525 | |
| 3 | + * @Date: 2020-05-10 23:10:52 | |
| 4 | + * @LastEditors: ly525 | |
| 5 | + * @LastEditTime: 2020-05-10 23:20:22 | |
| 6 | + * @FilePath: /luban-h5/front-end/h5/src/components/core/editor/edit-panel/props/global-work.vue | |
| 7 | + * @Github: https://github.com/ly525/luban-h5 | |
| 8 | + * @Description: Do not edit | |
| 9 | + * @Copyright 2018 - 2019 luban-h5. All Rights Reserved | |
| 10 | + --> | |
| 11 | +<template> | |
| 12 | + <a-form :layout="formLayout"> | |
| 13 | + <a-form-item | |
| 14 | + label="H5类型" | |
| 15 | + > | |
| 16 | + <a-radio-group default-value="h5_swipper" @change="handleChangeMode" size="small"> | |
| 17 | + <a-radio-button value="h5_swipper"> | |
| 18 | + 翻页H5 | |
| 19 | + </a-radio-button> | |
| 20 | + <a-radio-button value="h5_long_page"> | |
| 21 | + 长页面H5 | |
| 22 | + </a-radio-button> | |
| 23 | + </a-radio-group> | |
| 24 | + </a-form-item> | |
| 25 | + </a-form> | |
| 26 | +</template> | |
| 27 | + | |
| 28 | +<script> | |
| 29 | +import { mapActions } from 'vuex' | |
| 30 | +export default { | |
| 31 | + data () { | |
| 32 | + return { | |
| 33 | + formLayout: 'vertical' | |
| 34 | + } | |
| 35 | + }, | |
| 36 | + methods: { | |
| 37 | + ...mapActions('editor', [ | |
| 38 | + 'updateWork' | |
| 39 | + ]), | |
| 40 | + handleModeChange (e) { | |
| 41 | + this.updateWork({ mode: e.target.value }) | |
| 42 | + } | |
| 43 | + } | |
| 44 | +} | |
| 45 | +</script> | ... | ... |
front-end/h5/src/components/core/editor/index.js
| ... | ... | @@ -311,7 +311,7 @@ export default { |
| 311 | 311 | <a-layout-sider width="240" theme='light' style={{ background: '#fff', padding: '12px' }}> |
| 312 | 312 | { this._renderMenuContent() } |
| 313 | 313 | </a-layout-sider> |
| 314 | - <a-layout> | |
| 314 | + <a-layout id="canvas-outer-wrapper"> | |
| 315 | 315 | <div class="mode-toggle-wrapper"> |
| 316 | 316 | <a-radio-group |
| 317 | 317 | size="small" |
| ... | ... | @@ -330,7 +330,9 @@ export default { |
| 330 | 330 | </a-radio-group> |
| 331 | 331 | </div> |
| 332 | 332 | <a-layout-content style={{ transform: `scale(${this.scaleRate})`, 'transform-origin': 'center top' }}> |
| 333 | - <div class='canvas-wrapper'> | |
| 333 | + <div class='canvas-wrapper' style={{ | |
| 334 | + height: `${this.work.height}px` | |
| 335 | + }}> | |
| 334 | 336 | {/* { this.isPreviewMode ? this.renderPreview(h, this.elements) : this.renderCanvas(h, this.elements) } */} |
| 335 | 337 | { this.isPreviewMode |
| 336 | 338 | ? <RenderPreviewCanvas elements={this.elements}/> | ... | ... |
front-end/h5/src/components/core/models/work.js
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | * @Author: ly525 |
| 3 | 3 | * @Date: 2019-11-24 18:51:58 |
| 4 | 4 | * @LastEditors: ly525 |
| 5 | - * @LastEditTime: 2019-12-15 16:24:33 | |
| 5 | + * @LastEditTime: 2020-05-10 23:23:40 | |
| 6 | 6 | * @FilePath: /luban-h5/front-end/h5/src/components/core/models/work.js |
| 7 | 7 | * @Github: https://github.com/ly525/luban-h5 |
| 8 | 8 | * @Description: work model |
| ... | ... | @@ -12,6 +12,7 @@ import Page from './page.js' |
| 12 | 12 | |
| 13 | 13 | class Work { |
| 14 | 14 | constructor (work = {}) { |
| 15 | + this.id = work.id | |
| 15 | 16 | this.title = work.title || '标题' |
| 16 | 17 | this.description = work.description || '描述' |
| 17 | 18 | this.pages = work.pages || [new Page()] |
| ... | ... | @@ -30,6 +31,13 @@ class Work { |
| 30 | 31 | |
| 31 | 32 | this.is_publish = false |
| 32 | 33 | this.is_template = false |
| 34 | + this.height = work.height || 568 | |
| 35 | + /** | |
| 36 | + * 页面模式,枚举值 | |
| 37 | + * h5_swipper 翻页H5 | |
| 38 | + * h5_long_page 长页面H5 | |
| 39 | + */ | |
| 40 | + this.mode = work.mode || 'h5_swipper' | |
| 33 | 41 | } |
| 34 | 42 | } |
| 35 | 43 | ... | ... |
front-end/h5/src/components/core/styles/canvas-wrapper.scss
| ... | ... | @@ -11,7 +11,8 @@ $designerWidthHalf: $designerWidth / 2; |
| 11 | 11 | position: relative; |
| 12 | 12 | top: 60px; |
| 13 | 13 | width: $designerWidth; |
| 14 | - height: $designerHeight; | |
| 14 | + // height: $designerHeight; | |
| 15 | + min-height: $designerHeight; | |
| 15 | 16 | margin: 0 auto; |
| 16 | 17 | background: #fff; |
| 17 | 18 | border: 1px solid #e7e7e7; |
| ... | ... | @@ -33,3 +34,41 @@ $designerWidthHalf: $designerWidth / 2; |
| 33 | 34 | left: calc(50% - 120px); |
| 34 | 35 | text-align: center; |
| 35 | 36 | } |
| 37 | + | |
| 38 | + | |
| 39 | +.long-page-adjust { | |
| 40 | + .adjust-line { | |
| 41 | + width: 100%; | |
| 42 | + height: 1px; | |
| 43 | + background-color: #1593ff; | |
| 44 | + } | |
| 45 | + | |
| 46 | + .adjust-button { | |
| 47 | + margin: 0 auto; | |
| 48 | + width: 30px; | |
| 49 | + height: 10px; | |
| 50 | + border-radius: 2px; | |
| 51 | + padding-top: 4px; | |
| 52 | + cursor: ns-resize; | |
| 53 | + background-color: #1593ff; | |
| 54 | + | |
| 55 | + .indicator { | |
| 56 | + margin: 0 auto; | |
| 57 | + width: 10px; | |
| 58 | + height: 1px; | |
| 59 | + background-color: #ccd5db; | |
| 60 | + } | |
| 61 | + } | |
| 62 | + | |
| 63 | + .adjust-tip { | |
| 64 | + letter-spacing: 1px; | |
| 65 | + padding: 0; | |
| 66 | + height: 24px; | |
| 67 | + margin: 2px auto 0; | |
| 68 | + text-align: center; | |
| 69 | + line-height: 24px; | |
| 70 | + font-size: 12px; | |
| 71 | + color: #868484; | |
| 72 | + vertical-align: middle; | |
| 73 | + } | |
| 74 | +} | |
| 36 | 75 | \ No newline at end of file | ... | ... |
front-end/h5/src/engine-entry.js
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | * @Author: ly525 |
| 3 | 3 | * @Date: 2019-11-24 18:51:58 |
| 4 | 4 | * @LastEditors: ly525 |
| 5 | - * @LastEditTime: 2019-12-15 17:09:51 | |
| 5 | + * @LastEditTime: 2020-05-10 23:43:42 | |
| 6 | 6 | * @FilePath: /luban-h5/front-end/h5/src/engine-entry.js |
| 7 | 7 | * @Github: https://github.com/ly525/luban-h5 |
| 8 | 8 | * @Description: |
| ... | ... | @@ -32,9 +32,22 @@ const Engine = { |
| 32 | 32 | }, |
| 33 | 33 | methods: { |
| 34 | 34 | renderPreview (h, _elements) { |
| 35 | + const isLongPage = window.__work.mode === 'h5_long_page' | |
| 35 | 36 | const elements = _elements.map(element => new Element(element)) |
| 37 | + let pageWrapperStyle = { | |
| 38 | + height: '100%', | |
| 39 | + position: 'relative' | |
| 40 | + } | |
| 41 | + | |
| 42 | + if (isLongPage) { | |
| 43 | + pageWrapperStyle = { | |
| 44 | + ...pageWrapperStyle, | |
| 45 | + 'overflow-y': 'scroll' | |
| 46 | + } | |
| 47 | + } | |
| 48 | + | |
| 36 | 49 | return ( |
| 37 | - <div style={{ height: '100%', position: 'relative' }}> | |
| 50 | + <div style={pageWrapperStyle}> | |
| 38 | 51 | { |
| 39 | 52 | elements.map((element, index) => { |
| 40 | 53 | // const style = element.getStyle({ position: 'absolute', isRem: true }) | ... | ... |
front-end/h5/src/store/modules/work.js
| ... | ... | @@ -257,7 +257,7 @@ export const mutations = { |
| 257 | 257 | page.elements = page.elements.map(element => new Element(element)) |
| 258 | 258 | return new Page(page) |
| 259 | 259 | }) |
| 260 | - state.work = work | |
| 260 | + state.work = new Work(work) | |
| 261 | 261 | }, |
| 262 | 262 | previewWork (state, { type, value }) {}, |
| 263 | 263 | deployWork (state, { type, value }) {}, | ... | ... |