Commit 39d9f8fdcce6dcbaafd765986a55ffeaa58e4b6a
1 parent
1102fe32
feat(preview): build preview engine
Showing
9 changed files
with
230 additions
and
9 deletions
back-end/h5-api/api/work/config/routes.json
back-end/h5-api/api/work/controllers/Work.js
| ... | ... | @@ -5,4 +5,10 @@ |
| 5 | 5 | * to customize this controller |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | -module.exports = {}; | |
| 8 | +module.exports = { | |
| 9 | + // GET /previewOne | |
| 10 | + // strapi-hook-ejs: https://github.com/strapi/strapi/tree/master/packages/strapi-hook-ejs | |
| 11 | + previewOne: async (ctx) => { | |
| 12 | + return ctx.render('engine', {work: { page2: []}}); | |
| 13 | + } | |
| 14 | +}; | ... | ... |
back-end/h5-api/config/hook.json
| ... | ... | @@ -6,5 +6,13 @@ |
| 6 | 6 | "Define the hooks' load order by putting their names in this array in the right order" |
| 7 | 7 | ], |
| 8 | 8 | "after": [] |
| 9 | + }, | |
| 10 | + "ejs": { | |
| 11 | + "enabled": true, | |
| 12 | + "viewExt": "ejs", | |
| 13 | + "partial": true, | |
| 14 | + "cache": false, | |
| 15 | + "debug": true, | |
| 16 | + "layout": false | |
| 9 | 17 | } |
| 10 | 18 | } | ... | ... |
back-end/h5-api/package.json
| ... | ... | @@ -18,20 +18,22 @@ |
| 18 | 18 | "eslint-plugin-react": "^7.14.0" |
| 19 | 19 | }, |
| 20 | 20 | "dependencies": { |
| 21 | + "ejs": "^2.6.2", | |
| 22 | + "knex": "latest", | |
| 21 | 23 | "lodash": "^4.17.5", |
| 24 | + "sqlite3": "latest", | |
| 22 | 25 | "strapi": "3.0.0-beta.13", |
| 23 | 26 | "strapi-admin": "3.0.0-beta.13", |
| 24 | - "strapi-utils": "3.0.0-beta.13", | |
| 25 | - "strapi-plugin-settings-manager": "3.0.0-beta.13", | |
| 26 | - "strapi-plugin-content-type-builder": "3.0.0-beta.13", | |
| 27 | + "strapi-hook-bookshelf": "3.0.0-beta.13", | |
| 28 | + "strapi-hook-ejs": "^3.0.0-alpha.26.2", | |
| 29 | + "strapi-hook-knex": "3.0.0-beta.13", | |
| 27 | 30 | "strapi-plugin-content-manager": "3.0.0-beta.13", |
| 28 | - "strapi-plugin-users-permissions": "3.0.0-beta.13", | |
| 31 | + "strapi-plugin-content-type-builder": "3.0.0-beta.13", | |
| 29 | 32 | "strapi-plugin-email": "3.0.0-beta.13", |
| 33 | + "strapi-plugin-settings-manager": "3.0.0-beta.13", | |
| 30 | 34 | "strapi-plugin-upload": "3.0.0-beta.13", |
| 31 | - "strapi-hook-bookshelf": "3.0.0-beta.13", | |
| 32 | - "strapi-hook-knex": "3.0.0-beta.13", | |
| 33 | - "knex": "latest", | |
| 34 | - "sqlite3": "latest" | |
| 35 | + "strapi-plugin-users-permissions": "3.0.0-beta.13", | |
| 36 | + "strapi-utils": "3.0.0-beta.13" | |
| 35 | 37 | }, |
| 36 | 38 | "author": { |
| 37 | 39 | "name": "A Strapi developer" | ... | ... |
back-end/h5-api/views/engine-example.ejs
0 → 100644
front-end/h5/public/engine-example.html
0 → 100644
| 1 | +<!DOCTYPE html> | |
| 2 | +<html lang="en"> | |
| 3 | + <head> | |
| 4 | + <meta charset="utf-8"> | |
| 5 | + <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
| 6 | + <meta name="viewport" content="width=device-width,initial-scale=1.0"> | |
| 7 | + <title>work.html</title> | |
| 8 | + <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |
| 9 | + <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"> | |
| 10 | + <meta content="yes" name="apple-mobile-web-app-capable"> | |
| 11 | + <meta content="black" name="apple-mobile-web-app-status-bar-style"> | |
| 12 | + <meta content="telephone=no" name="format-detection"> | |
| 13 | + <meta content="email=no" name="format-detection"> | |
| 14 | + <script type="text/javascript" src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/flexible.js"></script> | |
| 15 | + <!-- <link rel="stylesheet" href="/be-static/be-static-luban-h5/engine/engine.css"> --> | |
| 16 | + <!-- <script src="/be-static/be-static-luban-h5/engine/engine.js"></script> --> | |
| 17 | + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/css/swiper.min.css"> | |
| 18 | + <link rel="stylesheet" href="https://meyerweb.com/eric/tools/css/reset/reset.css"> | |
| 19 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/js/swiper.min.js"></script> | |
| 20 | + <style> | |
| 21 | + .swiper-container { | |
| 22 | + width: 100%; | |
| 23 | + height: 100vh; | |
| 24 | + } | |
| 25 | + </style> | |
| 26 | + <script> | |
| 27 | + window.__work = {"id":12,"title":"default title","description":"default desc","cover_image_url":null,"is_publish":null,"create_time":"2019-07-21 06:07:44","update_time":"2019-07-21 06:07:44","pages":[{"elements":[{"name":"lbp-button","uuid":1563721976946,"pluginProps":{"text":"按钮","fontSize":14,"color":"black","backgroundColor":"#ffffff","borderColor":"#eeeeee","borderWidth":2,"borderRadius":0,"lineHeight":1,"textAlign":"center"},"commonStyle":{"top":208,"left":106,"width":100,"height":40,"zindex":1,"textAlign":"center","color":"#000000","backgroundColor":"#ffffff","fontSize":14},"events":[]}]},{"elements":[]},{"elements":[]},{"elements":[{"name":"lbp-button","uuid":1563721991112,"pluginProps":{"text":"按钮","fontSize":14,"color":"black","backgroundColor":"#ffffff","borderColor":"#eeeeee","borderWidth":2,"borderRadius":0,"lineHeight":1,"textAlign":"center"},"commonStyle":{"top":208,"left":106,"width":100,"height":40,"zindex":1,"textAlign":"center","color":"#000000","backgroundColor":"#ffffff","fontSize":14},"events":[]}]},{"elements":[{"name":"lbp-button","uuid":1563721995650,"pluginProps":{"text":"按钮","fontSize":14,"color":"black","backgroundColor":"#ffffff","borderColor":"#eeeeee","borderWidth":2,"borderRadius":0,"lineHeight":1,"textAlign":"center"},"commonStyle":{"top":208,"left":106,"width":100,"height":40,"zindex":1,"textAlign":"center","color":"#000000","backgroundColor":"#ffffff","fontSize":14},"events":[]}]}],"created_at":"2019-07-21T06:07:44.636Z","updated_at":"2019-07-21T06:07:44.636Z"} | |
| 28 | + </script> | |
| 29 | + </head> | |
| 30 | + <body> | |
| 31 | + <noscript> | |
| 32 | + <strong>We're sorry but luban-h5 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> | |
| 33 | + </noscript> | |
| 34 | + <div id="app"></div> | |
| 35 | + <!-- built files will be auto injected --> | |
| 36 | + <script> | |
| 37 | + var mySwiper = new Swiper('.swiper-container', { | |
| 38 | + // Optional parameters | |
| 39 | + direction: 'vertical', | |
| 40 | + loop: false, | |
| 41 | + // If we need pagination | |
| 42 | + pagination: { | |
| 43 | + el: '.swiper-pagination', | |
| 44 | + }, | |
| 45 | + // Navigation arrows | |
| 46 | + navigation: { | |
| 47 | + nextEl: '.swiper-button-next', | |
| 48 | + prevEl: '.swiper-button-prev', | |
| 49 | + }, | |
| 50 | + // And if we need scrollbar | |
| 51 | + scrollbar: { | |
| 52 | + el: '.swiper-scrollbar', | |
| 53 | + }, | |
| 54 | + }); | |
| 55 | + </script> | |
| 56 | + </body> | |
| 57 | +</html> | ... | ... |
front-end/h5/public/engine.html
0 → 100644
| 1 | +<!DOCTYPE html> | |
| 2 | +<html lang="en"> | |
| 3 | + <head> | |
| 4 | + <meta charset="utf-8"> | |
| 5 | + <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
| 6 | + <meta name="viewport" content="width=device-width,initial-scale=1.0"> | |
| 7 | + <title>work.html</title> | |
| 8 | + <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |
| 9 | + <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport"> | |
| 10 | + <meta content="yes" name="apple-mobile-web-app-capable"> | |
| 11 | + <meta content="black" name="apple-mobile-web-app-status-bar-style"> | |
| 12 | + <meta content="telephone=no" name="format-detection"> | |
| 13 | + <meta content="email=no" name="format-detection"> | |
| 14 | + <script type="text/javascript" src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/flexible.js"></script> | |
| 15 | + <!-- <link rel="stylesheet" href="/be-static/be-static-luban-h5/engine/engine.css"> --> | |
| 16 | + <!-- <script src="/be-static/be-static-luban-h5/engine/engine.js"></script> --> | |
| 17 | + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/css/swiper.min.css"> | |
| 18 | + <link rel="stylesheet" href="https://meyerweb.com/eric/tools/css/reset/reset.css"> | |
| 19 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.0/js/swiper.min.js"></script> | |
| 20 | + <style> | |
| 21 | + .swiper-container { | |
| 22 | + width: 100%; | |
| 23 | + height: 100vh; | |
| 24 | + } | |
| 25 | + </style> | |
| 26 | + <!-- <script> | |
| 27 | + window.__work = {"id":12,"title":"default title","description":"default desc","cover_image_url":null,"is_publish":null,"create_time":"2019-07-21 06:07:44","update_time":"2019-07-21 06:07:44","pages":[{"elements":[{"name":"lbp-button","uuid":1563721976946,"pluginProps":{"text":"按钮","fontSize":14,"color":"black","backgroundColor":"#ffffff","borderColor":"#eeeeee","borderWidth":2,"borderRadius":0,"lineHeight":1,"textAlign":"center"},"commonStyle":{"top":208,"left":106,"width":100,"height":40,"zindex":1,"textAlign":"center","color":"#000000","backgroundColor":"#ffffff","fontSize":14},"events":[]}]},{"elements":[]},{"elements":[]},{"elements":[{"name":"lbp-button","uuid":1563721991112,"pluginProps":{"text":"按钮","fontSize":14,"color":"black","backgroundColor":"#ffffff","borderColor":"#eeeeee","borderWidth":2,"borderRadius":0,"lineHeight":1,"textAlign":"center"},"commonStyle":{"top":208,"left":106,"width":100,"height":40,"zindex":1,"textAlign":"center","color":"#000000","backgroundColor":"#ffffff","fontSize":14},"events":[]}]},{"elements":[{"name":"lbp-button","uuid":1563721995650,"pluginProps":{"text":"按钮","fontSize":14,"color":"black","backgroundColor":"#ffffff","borderColor":"#eeeeee","borderWidth":2,"borderRadius":0,"lineHeight":1,"textAlign":"center"},"commonStyle":{"top":208,"left":106,"width":100,"height":40,"zindex":1,"textAlign":"center","color":"#000000","backgroundColor":"#ffffff","fontSize":14},"events":[]}]}],"created_at":"2019-07-21T06:07:44.636Z","updated_at":"2019-07-21T06:07:44.636Z"} | |
| 28 | + </script> --> | |
| 29 | + </head> | |
| 30 | + <body> | |
| 31 | + <noscript> | |
| 32 | + <strong>We're sorry but luban-h5 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> | |
| 33 | + </noscript> | |
| 34 | + <div id="app"></div> | |
| 35 | + <!-- built files will be auto injected --> | |
| 36 | + <script> | |
| 37 | + var mySwiper = new Swiper('.swiper-container', { | |
| 38 | + // Optional parameters | |
| 39 | + direction: 'vertical', | |
| 40 | + loop: false, | |
| 41 | + // If we need pagination | |
| 42 | + pagination: { | |
| 43 | + el: '.swiper-pagination', | |
| 44 | + }, | |
| 45 | + // Navigation arrows | |
| 46 | + navigation: { | |
| 47 | + nextEl: '.swiper-button-next', | |
| 48 | + prevEl: '.swiper-button-prev', | |
| 49 | + }, | |
| 50 | + // And if we need scrollbar | |
| 51 | + scrollbar: { | |
| 52 | + el: '.swiper-scrollbar', | |
| 53 | + }, | |
| 54 | + }); | |
| 55 | + </script> | |
| 56 | + </body> | |
| 57 | +</html> | ... | ... |
front-end/h5/src/components/core/editor/engine/index.js
0 → 100644
| 1 | +/** | |
| 2 | + * 作品预览的渲染引擎,其实就是简单遍历 pages 以及 elements,显示即可 | |
| 3 | + */ | |
| 4 | +import Vue from 'vue' | |
| 5 | +import Antd from 'ant-design-vue' | |
| 6 | +import 'ant-design-vue/dist/antd.css' | |
| 7 | +import 'font-awesome/css/font-awesome.min.css' | |
| 8 | +import loadPluginMixin from '../../../../mixins/load-plugins.js' | |
| 9 | +import Element from '../../models/element' | |
| 10 | + | |
| 11 | +Vue.config.productionTip = false | |
| 12 | +Vue.use(Antd) | |
| 13 | +const Engine = { | |
| 14 | + name: 'engine', | |
| 15 | + mixins: [loadPluginMixin], | |
| 16 | + methods: { | |
| 17 | + renderPreview (h, _elements) { | |
| 18 | + const elements = _elements.map(element => new Element(element)) | |
| 19 | + return ( | |
| 20 | + <div style={{ height: '100%', position: 'relative' }}> | |
| 21 | + { | |
| 22 | + elements.map((element, index) => { | |
| 23 | + const style = element.getStyle({ position: 'absolute' }) | |
| 24 | + const data = { | |
| 25 | + style, | |
| 26 | + props: element.getProps({ mode: 'preview' }) | |
| 27 | + } | |
| 28 | + return h(element.name, data) | |
| 29 | + }) | |
| 30 | + } | |
| 31 | + </div> | |
| 32 | + ) | |
| 33 | + } | |
| 34 | + }, | |
| 35 | + render (h) { | |
| 36 | + const work = window.__work | |
| 37 | + return ( | |
| 38 | + <div id="work-container" data-work-id={work.id}> | |
| 39 | + <div class="swiper-container"> | |
| 40 | + <div class="swiper-wrapper">{ | |
| 41 | + work.pages.map(page => { | |
| 42 | + return ( | |
| 43 | + <section class="swiper-slide flat"> | |
| 44 | + {/* this.walk(h, page.elements) */} | |
| 45 | + { this.renderPreview(h, page.elements) } | |
| 46 | + </section> | |
| 47 | + ) | |
| 48 | + }) | |
| 49 | + }</div> | |
| 50 | + <div class="swiper-pagination"></div> | |
| 51 | + </div> | |
| 52 | + </div> | |
| 53 | + ) | |
| 54 | + } | |
| 55 | +} | |
| 56 | + | |
| 57 | +new Vue({ | |
| 58 | + components: { | |
| 59 | + engine: Engine | |
| 60 | + }, | |
| 61 | + render: h => h('engine') | |
| 62 | +}).$mount('#app') | ... | ... |
front-end/h5/vue.config.js
| ... | ... | @@ -5,5 +5,16 @@ module.exports = { |
| 5 | 5 | : '/', |
| 6 | 6 | devServer: { |
| 7 | 7 | proxy: 'http://localhost:1337' |
| 8 | + }, | |
| 9 | + pages: { | |
| 10 | + index: { | |
| 11 | + entry: 'src/main.js', | |
| 12 | + template: 'public/index.html', | |
| 13 | + filename: 'index.html', | |
| 14 | + title: 'Index Page' | |
| 15 | + }, | |
| 16 | + engine: { | |
| 17 | + entry: 'src/components/core/editor/engine/index.js' | |
| 18 | + } | |
| 8 | 19 | } |
| 9 | 20 | } | ... | ... |