Commit 0bd23421a802bb762764e0fbbfbeb8edd50a3e62

Authored by ly525
1 parent a34f5f11

feat(preview): add preview modal

back-end/h5-api/views/engine.ejs
@@ -17,6 +17,9 @@ @@ -17,6 +17,9 @@
17 <script>window.__work = <%- JSON.stringify(work) %></script> 17 <script>window.__work = <%- JSON.stringify(work) %></script>
18 <script src="/engine-assets/engine.js"></script> 18 <script src="/engine-assets/engine.js"></script>
19 <style> 19 <style>
  20 + * {
  21 + outline: none;
  22 + }
20 .swiper-container { 23 .swiper-container {
21 width: 100%; 24 width: 100%;
22 height: 100vh; 25 height: 100vh;
@@ -26,7 +29,9 @@ @@ -26,7 +29,9 @@
26 29
27 <body> 30 <body>
28 <div id="app"> 31 <div id="app">
29 - <engine /> 32 + <button class="swiper-button-next" style="position: fixed;left: 1000px">Next</button>
  33 + <button class="swiper-button-prev" style="position: fixed;left: 1000px">Prev</button>
  34 + <engine />
30 </div> 35 </div>
31 <script> 36 <script>
32 // Vue.component('engine', window.Engine) 37 // Vue.component('engine', window.Engine)
@@ -59,6 +64,18 @@ @@ -59,6 +64,18 @@
59 el: '.swiper-scrollbar', 64 el: '.swiper-scrollbar',
60 }, 65 },
61 }); 66 });
  67 +
  68 + function displayMessage ({ origin, data }) {
  69 + if (data && origin === "http://localhost:8080") {
  70 + document.querySelector(`.swiper-button-${data}`).click()
  71 + }
  72 + }
  73 +
  74 + if (window.addEventListener) {
  75 + window.addEventListener("message", displayMessage, false);
  76 + } else {
  77 + window.attachEvent("onmessage", displayMessage);
  78 + }
62 </script> 79 </script>
63 <!-- build:js scripts/vendor.js --> 80 <!-- build:js scripts/vendor.js -->
64 <!-- endbuild --> 81 <!-- endbuild -->
front-end/h5/package.json
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 "core-js": "^2.6.5", 15 "core-js": "^2.6.5",
16 "element-ui": "^2.9.1", 16 "element-ui": "^2.9.1",
17 "font-awesome": "4.7.0", 17 "font-awesome": "4.7.0",
  18 + "qrcode": "^1.4.1",
18 "register-service-worker": "^1.6.2", 19 "register-service-worker": "^1.6.2",
19 "strapi-sdk-javascript": "^0.3.1", 20 "strapi-sdk-javascript": "^0.3.1",
20 "vue": "^2.6.10", 21 "vue": "^2.6.10",
front-end/h5/public/index.html
@@ -6,6 +6,11 @@ @@ -6,6 +6,11 @@
6 <meta name="viewport" content="width=device-width,initial-scale=1.0"> 6 <meta name="viewport" content="width=device-width,initial-scale=1.0">
7 <link rel="icon" href="<%= BASE_URL %>favicon.ico"> 7 <link rel="icon" href="<%= BASE_URL %>favicon.ico">
8 <title>鲁班-H5</title> 8 <title>鲁班-H5</title>
  9 + <style>
  10 + * {
  11 + outline: none;
  12 + }
  13 + </style>
9 </head> 14 </head>
10 <body> 15 <body>
11 <noscript> 16 <noscript>
front-end/h5/src/components/core/editor/index.js
@@ -10,6 +10,7 @@ import RenderPropsEditor from &#39;./edit-panel/props&#39; @@ -10,6 +10,7 @@ import RenderPropsEditor from &#39;./edit-panel/props&#39;
10 import RenderScriptEditor from './edit-panel/script' 10 import RenderScriptEditor from './edit-panel/script'
11 import RenderActoionEditor from './edit-panel/action' 11 import RenderActoionEditor from './edit-panel/action'
12 import RenderShortcutsPanel from './shortcuts-panel/index' 12 import RenderShortcutsPanel from './shortcuts-panel/index'
  13 +import PreviewDialog from './modals/preview.vue'
13 14
14 const sidebarMenus = [ 15 const sidebarMenus = [
15 { 16 {
@@ -34,7 +35,8 @@ export default { @@ -34,7 +35,8 @@ export default {
34 data: () => ({ 35 data: () => ({
35 activeMenuKey: 'pluginList', 36 activeMenuKey: 'pluginList',
36 isPreviewMode: false, 37 isPreviewMode: false,
37 - activeTabKey: '属性' 38 + activeTabKey: '属性',
  39 + previewVisible: false
38 }), 40 }),
39 computed: { 41 computed: {
40 ...mapState('editor', { 42 ...mapState('editor', {
@@ -109,7 +111,7 @@ export default { @@ -109,7 +111,7 @@ export default {
109 <a-button class="transparent-bg" style={{ color: 'white' }} type="dashed" size="small" onClick={() => undoRedoHistory.redo()}><i class={['shortcut-icon', 'fa', `fa-mail-forward`]} aria-hidden='true'/> 重做</a-button> 111 <a-button class="transparent-bg" style={{ color: 'white' }} type="dashed" size="small" onClick={() => undoRedoHistory.redo()}><i class={['shortcut-icon', 'fa', `fa-mail-forward`]} aria-hidden='true'/> 重做</a-button>
110 </a-button-group> 112 </a-button-group>
111 </a-menu-item> 113 </a-menu-item>
112 - <a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small">预览</a-button></a-menu-item> 114 + <a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small" onClick={() => { this.previewVisible = true }}>预览</a-button></a-menu-item>
113 <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()}>保存</a-button></a-menu-item> 115 <a-menu-item key="2" class="transparent-bg"><a-button size="small" onClick={() => this.saveWork()}>保存</a-button></a-menu-item>
114 <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item> 116 <a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item>
115 </a-menu> 117 </a-menu>
@@ -185,6 +187,7 @@ export default { @@ -185,6 +187,7 @@ export default {
185 </a-tabs> 187 </a-tabs>
186 </a-layout-sider> 188 </a-layout-sider>
187 </a-layout> 189 </a-layout>
  190 + <PreviewDialog visible={this.previewVisible} handleClose={() => { this.previewVisible = false }} />
188 </a-layout> 191 </a-layout>
189 ) 192 )
190 }, 193 },
front-end/h5/src/components/core/editor/modals/preview.vue 0 → 100644
  1 +<script>
  2 +import { mapActions, mapState } from 'vuex'
  3 +import QRCode from 'qrcode'
  4 +export default {
  5 + props: {
  6 + visible: {
  7 + type: Boolean,
  8 + default: false
  9 + },
  10 + handleClose: {
  11 + type: Function,
  12 + default: () => {}
  13 + }
  14 + },
  15 + computed: {
  16 + ...mapState('editor', {
  17 + work: state => state.work,
  18 + }),
  19 + releaseUrl () {
  20 + return `//localhost:1337/works/preview/${this.work.id}`
  21 + }
  22 + },
  23 + data() {
  24 + return {
  25 + confirmLoading: false,
  26 + qrcodeSize: 500,
  27 + }
  28 + },
  29 + watch: {
  30 + visible (val) {
  31 + if (!val) return;
  32 + this.$nextTick(() => this.drawQRcode());
  33 + },
  34 + },
  35 + methods: {
  36 + ...mapActions('editor', [
  37 + 'saveWork',
  38 + 'updateWork'
  39 + ]),
  40 + handleOk(e) {
  41 + this.confirmLoading = true;
  42 + this.saveWork().then(res => {
  43 + this.handleClose()
  44 + this.confirmLoading = false;
  45 + })
  46 + // setTimeout(() => {
  47 + // }, 2000);
  48 + },
  49 + handleCancel(e) {
  50 + console.log('Clicked cancel button');
  51 + this.handleClose()
  52 + },
  53 + drawQRcode () {
  54 + var canvas = document.getElementById('qrcode-container');
  55 + QRCode.toCanvas(canvas, this.releaseUrl, { scale: 4 }, err => {
  56 + console.log(err);
  57 + });
  58 + },
  59 + postMessage2Iframe (message) {
  60 + let iframeWin = document.getElementById('iframe-for-preview').contentWindow
  61 + // iframeWin.postMessage('next', window.location.origin);
  62 + iframeWin.postMessage(message, 'http://localhost:1337');
  63 + }
  64 + },
  65 + render (h) {
  66 + return (
  67 + <div>
  68 + <a-modal
  69 + title="作品设置"
  70 + visible={this.visible}
  71 + confirmLoading={this.confirmLoading}
  72 + onOk={this.handleOk}
  73 + onCancel={this.handleCancel}
  74 + width="70%"
  75 + okText="保存"
  76 + >
  77 + <div class="preview-wrapper">
  78 + <a-row gutter={20}>
  79 + <a-col span={8}>
  80 + <div class="phone-wrapper">
  81 + <div class="phone">
  82 + <div class="float-ctrl-panel">
  83 + <a class="page-controller" onClick={(e) => { this.postMessage2Iframe('prev') }}>上一页</a>
  84 + <a class="page-controller" onClick={(e) => { this.postMessage2Iframe('next') }}>下一页</a>
  85 + {/**
  86 + <a-button icon="up" shape="circle" onClick={() => { this.postMessage2Iframe('prev') }}></a-button>
  87 + <a-button icon="down" shape="circle" onClick={() => { this.postMessage2Iframe('next') }}></a-button>
  88 + <a-icon type="up" class="page-controller" onClick={() => { this.postMessage2Iframe('prev') }}/>
  89 + <a-icon type="down" class="page-controller" onClick={() => { this.postMessage2Iframe('next') }}/>
  90 + */}
  91 + </div>
  92 + <iframe
  93 + id="iframe-for-preview"
  94 + src="http://localhost:1337/works/preview/12"
  95 + frameborder="0"
  96 + style="height: 100%;width: 100%;"
  97 + ></iframe>
  98 + {/** <engine :work="editingWork" :map-config="{}" /> */}
  99 + </div>
  100 + </div>
  101 + </a-col>
  102 + <a-col span={12} offset={4}>
  103 + <div class="setting">
  104 + <div class="info">
  105 + <div class="label">设置作品信息</div>
  106 + <a-input
  107 + class="input"
  108 + value={this.work.title}
  109 + onChange={e => this.updateWork({ title: e.target.value})}
  110 + // onBlur={this.saveTitle}
  111 + placeholder="请输入标题"
  112 + ></a-input>
  113 + <a-input
  114 + class="input"
  115 + value={this.work.description}
  116 + onChange={e => this.updateWork({ description: e.target.value})}
  117 + // v-model="description"
  118 + // onBlur={this.saveDescription}
  119 + placeholder="请输入描述"
  120 + type="textarea"
  121 + ></a-input>
  122 + </div>
  123 + <div class="qrcode my-4">
  124 + <div class="label">手机扫码分享给好友</div>
  125 + <div class="code">
  126 + <canvas style="float: left" id="qrcode-container"></canvas>
  127 + <a-radio-group class="radios" value={this.qrcodeSize} onChange={e => {this.qrcodeSize = e.target.value}}>
  128 + <a-radio label={500} value={500}>500x500</a-radio>
  129 + <a-radio label={1000} value={1000}>1000x1000</a-radio>
  130 + <a-radio label={2000} value={2000}>2000x2000</a-radio>
  131 + </a-radio-group>
  132 + </div>
  133 + </div>
  134 + </div>
  135 + </a-col>
  136 + </a-row>
  137 + </div>
  138 + </a-modal>
  139 + </div>
  140 + )
  141 + },
  142 + mounted () {
  143 + }
  144 +}
  145 +</script>
  146 +
  147 +
  148 +<style lang="scss">
  149 +.preview-wrapper {
  150 + position: relative;
  151 + min-height: 600px;
  152 + min-width: 800px;
  153 +
  154 + .phone-wrapper {
  155 + position: absolute;
  156 + // margin-top: -300px;
  157 + left: 10px;
  158 + top: 50%;
  159 + width: 320px;
  160 + height: 600px;
  161 + box-sizing: content-box;
  162 + .phone {
  163 + position: absolute;
  164 + // left: 40px;
  165 + width: 100%;
  166 + height: calc(638px - 70px);
  167 + display: inline-block;
  168 + background: #fff;
  169 + box-sizing: content-box;
  170 + border-top: 10px solid #f6f6f6;
  171 + border-left: 10px solid #f6f6f6;
  172 + border-right: 10px solid #f6f6f6;
  173 + border-bottom: 20px solid #f6f6f6;
  174 + border-radius: 20px;
  175 + -webkit-transform-origin: 100% 0;
  176 + transform-origin: 100% 0;
  177 + -webkit-transform: scale(1);
  178 + transform: scale(1);
  179 +
  180 + .float-ctrl-panel {
  181 + position: absolute;
  182 + top: 100px;
  183 + right: -40px;
  184 +
  185 + .page-controller {
  186 + display: block;
  187 + cursor: pointer;
  188 + width: 30px;
  189 + height: 80px;
  190 + border-top-right-radius: 5px;
  191 + border-bottom-right-radius: 5px;
  192 + background: #2096f9;
  193 + font-size: 12px;
  194 + text-align: center;
  195 + border: 1px solid #2096f9;
  196 + color: #fff;
  197 + // position: absolute;
  198 + padding: 14px 8px;
  199 + margin-top: 12px;
  200 + // margin-top: -50px;
  201 + }
  202 +
  203 + }
  204 + }
  205 + }
  206 + .setting {
  207 + color: #4a4a4a;
  208 + font-size: 14px;
  209 + float: right;
  210 + width: 380px;
  211 + .info {
  212 + .input {
  213 + margin-top: 10px;
  214 + }
  215 + }
  216 + .qrcode {
  217 + margin-top: 20px;
  218 + }
  219 + .code {
  220 + // !#zh 防止浮动塌陷
  221 + overflow: hidden;
  222 + .radios {
  223 + width: 80px;
  224 + margin-top: 5px;
  225 + margin-left: 30px;
  226 + label {
  227 + margin-left: 0px;
  228 + margin-top: 10px;
  229 + }
  230 + button {
  231 + margin-top: 15px;
  232 + }
  233 + }
  234 + }
  235 + .link {
  236 + width: 100%;
  237 + display: block;
  238 + }
  239 + .edit {
  240 + text-align: center;
  241 + margin-top: 20px;
  242 + }
  243 + }
  244 +}
  245 +
  246 +</style>
0 \ No newline at end of file 247 \ No newline at end of file
front-end/h5/src/components/core/models/element.js
  1 +import { parsePx } from '../../../utils/element.js'
  2 +
1 const clone = (value) => JSON.parse(JSON.stringify(value)) 3 const clone = (value) => JSON.parse(JSON.stringify(value))
2 4
3 const defaultProps = { 5 const defaultProps = {
@@ -56,14 +58,14 @@ class Element { @@ -56,14 +58,14 @@ class Element {
56 return pluginProps 58 return pluginProps
57 } 59 }
58 60
59 - getStyle ({ position = 'static' }) { 61 + getStyle ({ position = 'static', isRem = false }) {
60 const pluginProps = this.pluginProps 62 const pluginProps = this.pluginProps
61 const commonStyle = this.commonStyle 63 const commonStyle = this.commonStyle
62 let style = { 64 let style = {
63 - top: `${pluginProps.top || commonStyle.top}px`,  
64 - left: `${pluginProps.left || commonStyle.left}px`,  
65 - width: `${pluginProps.width || commonStyle.width}px`,  
66 - height: `${pluginProps.height || commonStyle.height}px`, 65 + top: parsePx(pluginProps.top || commonStyle.top),
  66 + left: parsePx(pluginProps.left || commonStyle.left),
  67 + width: parsePx(pluginProps.width || commonStyle.width),
  68 + height: parsePx(pluginProps.height || commonStyle.height),
67 fontSize: `${pluginProps.fontSize || commonStyle.fontSize}px`, 69 fontSize: `${pluginProps.fontSize || commonStyle.fontSize}px`,
68 color: pluginProps.color || commonStyle.color, 70 color: pluginProps.color || commonStyle.color,
69 // backgroundColor: pluginProps.backgroundColor || commonStyle.backgroundColor, 71 // backgroundColor: pluginProps.backgroundColor || commonStyle.backgroundColor,
front-end/h5/src/store/modules/work.js
@@ -18,9 +18,21 @@ export const actions = { @@ -18,9 +18,21 @@ export const actions = {
18 // commit('pageManager', { type: 'add' }) 18 // commit('pageManager', { type: 'add' })
19 // commit('setEditingPage') 19 // commit('setEditingPage')
20 }, 20 },
  21 + updateWork ({ commit, state }, payload = {}) {
  22 + // update work with strapi
  23 + const work = {
  24 + ...state.work,
  25 + ...payload
  26 + }
  27 + commit('setWork', work)
  28 + },
21 saveWork ({ commit, state }, payload = {}) { 29 saveWork ({ commit, state }, payload = {}) {
22 // update work with strapi 30 // update work with strapi
23 - strapi.updateEntry('works', state.work.id, state.work) 31 + const work = {
  32 + ...state.work,
  33 + ...payload
  34 + }
  35 + strapi.updateEntry('works', state.work.id, work)
24 }, 36 },
25 fetchWork ({ commit, state }, workId) { 37 fetchWork ({ commit, state }, workId) {
26 strapi.getEntry('works', workId).then(entry => { 38 strapi.getEntry('works', workId).then(entry => {
front-end/h5/src/utils/element.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 2
  3 +const DESIGN_DRAFT_WIDTH = 320
  4 +const styleKey = 'commonStyle'
  5 +
3 export function getEditorConfigForEditingElement (elementName) { 6 export function getEditorConfigForEditingElement (elementName) {
4 const Ctor = Vue.component(elementName) 7 const Ctor = Vue.component(elementName)
5 // TODO 为何直接 return new Ctor() 并将其赋值给 vuex 的 state 会报错:Cannot convert a Symbol value to a string 8 // TODO 为何直接 return new Ctor() 并将其赋值给 vuex 的 state 会报错:Cannot convert a Symbol value to a string
6 return new Ctor().$options.editorConfig 9 return new Ctor().$options.editorConfig
7 } 10 }
8 11
9 -const styleKey = 'commonStyle'  
10 export function swapZindex (x, y) { 12 export function swapZindex (x, y) {
11 const tmp = y[styleKey].zindex 13 const tmp = y[styleKey].zindex
12 y[styleKey].zindex = x[styleKey].zindex 14 y[styleKey].zindex = x[styleKey].zindex
13 x[styleKey].zindex = tmp 15 x[styleKey].zindex = tmp
14 } 16 }
  17 +
  18 +/**
  19 + * !#zh 将 px 转换为 rem
  20 + * @param {Number} px
  21 + */
  22 +function px2Rem (px) {
  23 + const number = Math.pow(10, 6)
  24 + const val = (px / (DESIGN_DRAFT_WIDTH / 10)) * number
  25 + const rem = Math.round(val) / number + 'rem'
  26 + return rem
  27 +}
  28 +
  29 +/**
  30 + *
  31 + * @param {Number} px 元素的某个属性的像素值,比如 height
  32 + * @param {Boolean} isToRem 是否将 px 转换为 rem
  33 + */
  34 +export function parsePx (px, isRem = false) {
  35 + if (isRem) return px2Rem(px)
  36 + return `${px}px`
  37 +}
front-end/h5/vue.config.js
@@ -12,9 +12,9 @@ module.exports = { @@ -12,9 +12,9 @@ module.exports = {
12 template: 'public/index.html', 12 template: 'public/index.html',
13 filename: 'index.html', 13 filename: 'index.html',
14 title: 'Index Page' 14 title: 'Index Page'
15 - },  
16 - engine: {  
17 - entry: 'src/components/core/editor/engine/index.js'  
18 } 15 }
  16 + // engine: {
  17 + // entry: 'src/engine-entry.js'
  18 + // }
19 } 19 }
20 } 20 }
front-end/h5/yarn.lock
@@ -3399,6 +3399,11 @@ diffie-hellman@^5.0.0: @@ -3399,6 +3399,11 @@ diffie-hellman@^5.0.0:
3399 miller-rabin "^4.0.0" 3399 miller-rabin "^4.0.0"
3400 randombytes "^2.0.0" 3400 randombytes "^2.0.0"
3401 3401
  3402 +dijkstrajs@^1.0.1:
  3403 + version "1.0.1"
  3404 + resolved "https://registry.npm.taobao.org/dijkstrajs/download/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b"
  3405 + integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs=
  3406 +
3402 dir-glob@^2.0.0, dir-glob@^2.2.2: 3407 dir-glob@^2.0.0, dir-glob@^2.2.2:
3403 version "2.2.2" 3408 version "2.2.2"
3404 resolved "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" 3409 resolved "https://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
@@ -5760,6 +5765,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: @@ -5760,6 +5765,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
5760 resolved "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 5765 resolved "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
5761 integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 5766 integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
5762 5767
  5768 +isarray@^2.0.1:
  5769 + version "2.0.5"
  5770 + resolved "https://registry.npm.taobao.org/isarray/download/isarray-2.0.5.tgz?cache=0&sync_timestamp=1562592096220&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fisarray%2Fdownload%2Fisarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
  5771 + integrity sha1-ivHkwSISRMxiRZ+vOJQNTmRKVyM=
  5772 +
5763 isemail@3.x.x: 5773 isemail@3.x.x:
5764 version "3.2.0" 5774 version "3.2.0"
5765 resolved "https://registry.npm.taobao.org/isemail/download/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c" 5775 resolved "https://registry.npm.taobao.org/isemail/download/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c"
@@ -7920,6 +7930,11 @@ pn@^1.1.0: @@ -7920,6 +7930,11 @@ pn@^1.1.0:
7920 resolved "https://registry.npm.taobao.org/pn/download/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" 7930 resolved "https://registry.npm.taobao.org/pn/download/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
7921 integrity sha1-4vTO8OIZ9GPBeas3Rj5OHs3Muvs= 7931 integrity sha1-4vTO8OIZ9GPBeas3Rj5OHs3Muvs=
7922 7932
  7933 +pngjs@^3.3.0:
  7934 + version "3.4.0"
  7935 + resolved "https://registry.npm.taobao.org/pngjs/download/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
  7936 + integrity sha1-mcp9clll+2VYFOr2XzjxK72/VV8=
  7937 +
7923 portfinder@^1.0.20: 7938 portfinder@^1.0.20:
7924 version "1.0.20" 7939 version "1.0.20"
7925 resolved "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" 7940 resolved "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a"
@@ -8440,6 +8455,16 @@ q@^1.1.2: @@ -8440,6 +8455,16 @@ q@^1.1.2:
8440 resolved "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" 8455 resolved "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
8441 integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= 8456 integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
8442 8457
  8458 +qrcode@^1.4.1:
  8459 + version "1.4.1"
  8460 + resolved "https://registry.npm.taobao.org/qrcode/download/qrcode-1.4.1.tgz#2126814985d0dbbd9aee050fc523d319c6a7dc3b"
  8461 + integrity sha1-ISaBSYXQ272a7gUPxSPTGcan3Ds=
  8462 + dependencies:
  8463 + dijkstrajs "^1.0.1"
  8464 + isarray "^2.0.1"
  8465 + pngjs "^3.3.0"
  8466 + yargs "^13.2.4"
  8467 +
8443 qs@6.7.0, qs@^6.5.2: 8468 qs@6.7.0, qs@^6.5.2:
8444 version "6.7.0" 8469 version "6.7.0"
8445 resolved "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" 8470 resolved "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
@@ -10895,6 +10920,14 @@ yargs-parser@^13.1.0: @@ -10895,6 +10920,14 @@ yargs-parser@^13.1.0:
10895 camelcase "^5.0.0" 10920 camelcase "^5.0.0"
10896 decamelize "^1.2.0" 10921 decamelize "^1.2.0"
10897 10922
  10923 +yargs-parser@^13.1.1:
  10924 + version "13.1.1"
  10925 + resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-13.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
  10926 + integrity sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA=
  10927 + dependencies:
  10928 + camelcase "^5.0.0"
  10929 + decamelize "^1.2.0"
  10930 +
10898 yargs-parser@^9.0.2: 10931 yargs-parser@^9.0.2:
10899 version "9.0.2" 10932 version "9.0.2"
10900 resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-9.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" 10933 resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-9.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
@@ -10955,6 +10988,22 @@ yargs@^13.0.0: @@ -10955,6 +10988,22 @@ yargs@^13.0.0:
10955 y18n "^4.0.0" 10988 y18n "^4.0.0"
10956 yargs-parser "^13.1.0" 10989 yargs-parser "^13.1.0"
10957 10990
  10991 +yargs@^13.2.4:
  10992 + version "13.3.0"
  10993 + resolved "https://registry.npm.taobao.org/yargs/download/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83"
  10994 + integrity sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM=
  10995 + dependencies:
  10996 + cliui "^5.0.0"
  10997 + find-up "^3.0.0"
  10998 + get-caller-file "^2.0.1"
  10999 + require-directory "^2.1.1"
  11000 + require-main-filename "^2.0.0"
  11001 + set-blocking "^2.0.0"
  11002 + string-width "^3.0.0"
  11003 + which-module "^2.0.0"
  11004 + y18n "^4.0.0"
  11005 + yargs-parser "^13.1.1"
  11006 +
10958 yauzl@2.10.0: 11007 yauzl@2.10.0:
10959 version "2.10.0" 11008 version "2.10.0"
10960 resolved "https://registry.npm.taobao.org/yauzl/download/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" 11009 resolved "https://registry.npm.taobao.org/yauzl/download/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"