Commit c784e56d9c7ae9b91a524b1ad3b1a8c28f0f8d9e
1 parent
abd9e622
feat(page): support copy, delete page
Showing
7 changed files
with
33 additions
and
11 deletions
README.en.md
| ... | ... | @@ -15,8 +15,11 @@ English | [简体中文](./README.md) |
| 15 | 15 | - [x] Edit Element (Canvas) |
| 16 | 16 | - [x] Copy Element (Canvas) |
| 17 | 17 | - [x] Delete Element (Canvas) |
| 18 | - - [ ] Page: add, copy, delete | |
| 19 | - - [x] Preview | |
| 18 | + - [x] Edit Page | |
| 19 | + - [x] Copy Page | |
| 20 | + - [x] Delete Page | |
| 21 | + - [x] Quick Preview | |
| 22 | + - [x] Undo、Redo | |
| 20 | 23 | |
| 21 | 24 | 2. Plugin System |
| 22 | 25 | ... | ... |
README.md
front-end/h5/src/components/core/editor/index.js
| ... | ... | @@ -79,8 +79,8 @@ export default { |
| 79 | 79 | </a> |
| 80 | 80 | <a-menu slot="overlay" onClick={({ key }) => { this.pageManager({ type: key }) }}> |
| 81 | 81 | <a-menu-item key="add"><a-icon type="user" />新增页面</a-menu-item> |
| 82 | - {/* <a-menu-item key="copy"><a-icon type="user" />复制页面</a-menu-item> */} | |
| 83 | - {/* <a-menu-item key="delete"><a-icon type="user" />删除页面</a-menu-item> */} | |
| 82 | + <a-menu-item key="copy"><a-icon type="user" />复制页面</a-menu-item> | |
| 83 | + <a-menu-item key="delete"><a-icon type="user" />删除页面</a-menu-item> | |
| 84 | 84 | </a-menu> |
| 85 | 85 | </a-dropdown> |
| 86 | 86 | </span> | ... | ... |
front-end/h5/src/components/core/models/element.js
| 1 | +const clone = (value) => JSON.parse(JSON.stringify(value)) | |
| 1 | 2 | |
| 2 | 3 | const defaultProps = { |
| 3 | 4 | top: 100, |
| ... | ... | @@ -16,14 +17,18 @@ class Element { |
| 16 | 17 | this.name = ele.name |
| 17 | 18 | this.uuid = +new Date() |
| 18 | 19 | /** |
| 20 | + * #!zh: | |
| 19 | 21 | * 之前版本代码:https://github.com/ly525/luban-h5/blob/a7875cbc73c0d18bc2459985ca3ce1d4dc44f141/front-end/h5/src/components/core/models/element.js#L21 |
| 20 | 22 | * 1.之前的版本为:this.pluginProps = {}, 改为下面的版本 |
| 21 | 23 | * 是因为要支持[复制画布上的元素],所以需要先使用 ele.pluginProps 进行初始化(也就是拷贝之前的元素的值) |
| 22 | 24 | * |
| 23 | 25 | * 2. 移除 this.init() 原因是:如果是 复制元素,则 init 会把 copy 的值重新覆盖为初始值,copy 无效 |
| 26 | + * | |
| 27 | + * 3. 为何需要 clone,因为会有 element.clone() 以及 page.clone(), | |
| 28 | + * element.pluginProps 和 elementcommonStyle 是引用类型,如果不做 deep_clone 可能会出现意外错误 | |
| 24 | 29 | */ |
| 25 | - this.pluginProps = ele.pluginProps || this.getDefaultPluginProps(ele.editorConfig || {}) | |
| 26 | - this.commonStyle = ele.commonStyle || this.getDefaultCommonStyle() | |
| 30 | + this.pluginProps = clone(ele.pluginProps) || this.getDefaultPluginProps(ele.editorConfig || {}) | |
| 31 | + this.commonStyle = clone(ele.commonStyle) || this.getDefaultCommonStyle() | |
| 27 | 32 | this.events = [] |
| 28 | 33 | } |
| 29 | 34 | |
| ... | ... | @@ -74,7 +79,7 @@ class Element { |
| 74 | 79 | clone () { |
| 75 | 80 | return new Element({ |
| 76 | 81 | name: this.name, |
| 77 | - pluginProps: JSON.parse(JSON.stringify(this.pluginProps)), | |
| 82 | + pluginProps: this.pluginProps, | |
| 78 | 83 | commonStyle: { |
| 79 | 84 | ...this.commonStyle, |
| 80 | 85 | top: this.commonStyle.top + 20, | ... | ... |
front-end/h5/src/components/core/models/page.js
| 1 | +import Element from '../models/element' | |
| 2 | + | |
| 1 | 3 | class Page { |
| 2 | 4 | constructor (page = {}) { |
| 5 | + this.uuid = +new Date() | |
| 3 | 6 | this.elements = page.elements || [] |
| 4 | 7 | } |
| 8 | + | |
| 9 | + clone () { | |
| 10 | + const elements = this.elements.map(element => new Element(element)) | |
| 11 | + return new Page({ elements }) | |
| 12 | + } | |
| 5 | 13 | } |
| 6 | 14 | |
| 7 | 15 | export default Page | ... | ... |
front-end/h5/src/store/modules/page.js
| ... | ... | @@ -26,10 +26,12 @@ export const mutations = { |
| 26 | 26 | state.work.pages.push(state.editingPage.clone()) |
| 27 | 27 | break |
| 28 | 28 | case 'delete': |
| 29 | + if (state.work.pages.length === 1) return // #!zh: 作品中至少需要保留一个页面,TODO 需要在页面中提示用户此信息 | |
| 30 | + | |
| 29 | 31 | const { work, editingPage } = state |
| 30 | - let index = work.pages.findIndex(e => e.uuid === editingPage.uuid) | |
| 32 | + let index = work.pages.findIndex(page => page.uuid === editingPage.uuid) | |
| 31 | 33 | if (index !== -1) { |
| 32 | - let newPages = work.slice() | |
| 34 | + let newPages = work.pages.slice() | |
| 33 | 35 | newPages.splice(index, 1) |
| 34 | 36 | state.work.pages = newPages |
| 35 | 37 | } | ... | ... |
front-end/h5/src/store/modules/work.js
| 1 | 1 | // import Work from '../../components/core/models/work' |
| 2 | 2 | import Element from '../../components/core/models/element' |
| 3 | 3 | import strapi from '../../utils/strapi' |
| 4 | +import Page from '../../components/core/models/page' | |
| 4 | 5 | |
| 5 | 6 | export const actions = { |
| 6 | 7 | previewWork ({ commit }, payload = {}) { |
| ... | ... | @@ -32,8 +33,9 @@ export const actions = { |
| 32 | 33 | // mutations |
| 33 | 34 | export const mutations = { |
| 34 | 35 | setWork (state, work) { |
| 35 | - work.pages.forEach(page => { | |
| 36 | + work.pages = work.pages.map(page => { | |
| 36 | 37 | page.elements = page.elements.map(element => new Element(element)) |
| 38 | + return new Page(page) | |
| 37 | 39 | }) |
| 38 | 40 | state.work = work |
| 39 | 41 | }, | ... | ... |