Commit 722031c925351e82ea30a93d90ddc3f462f4084f

Authored by ly525
1 parent d21296a7

feat: support long page mode(alpha);

#!zh: 支持长页面(alpha)
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
... ... @@ -550,6 +550,12 @@
550 550 },
551 551 "is_template": {
552 552 "type": "boolean"
  553 + },
  554 + "mode": {
  555 + "type": "string"
  556 + },
  557 + "height": {
  558 + "type": "integer"
553 559 }
554 560 }
555 561 }
... ...
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 &#39;./page.js&#39;
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 }) {},
... ...