UNPKG

chameleon-tool

Version:

chameleon 脚手架工具

921 lines (846 loc) 28 kB
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Chameleon Preview</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-touch-fullscreen" content="yes"> <meta name="format-detection" content="telephone=no, email=no"> <style> html, body { width: 100%; height: 100%; margin: 0; padding: 0; background-color: #f3f7fd } ul, li { padding: 0; margin: 0; list-style: none } .center { display: flex; align-items: center; justify-content: center; } #preview { width: 750px; height: 1250px; transform: scale(0.29); transform-origin: top left; } .phone { align-self: flex-end; background-color: #FFF; /* width: 320px; */ width: 260px; height: 610px; position: relative; } .mock-phone { position: absolute; left: 50%; transform: translate(-50%); width: 265px; min-width: 265px; height: 520px; background: url('./preview-assets/phone.png') center / cover no-repeat; } .mock-phone .inner { position: absolute; top: 65px; z-index: 26; left: 50%; transform: translate(-50%); width: 218px; height: 375px; overflow: hidden; } .mock-phone .inner iframe { width: 100%; height: 100%; margin: 0; } .mock-phone .camera { position: absolute; width: 4px; height: 4px; border-radius: 4px; background: #2d2d2d; border: 1px solid #a6a8a9; top: 30px; left: 105px; } .mock-phone .earpiece { position: absolute; width: 40px; height: 4px; border-radius: 4px; background: #2d2d2d; border: 1px solid #a6a8a9; top: 30px; left: 120px; } .mock-phone .home-btn { position: absolute; width: 40px; height: 40px; border-radius: 40px; background: #f3f3f4; border: 1px solid #b7b7b9; bottom: 15px; left: 50%; margin-left: -25px; } body { display: flex; flex-direction: column; } .header { height: 76px; flex-grow: 0; background-color: #19263E; display: flex; align-items: center; justify-content: space-between; } .header .result-preview { font-size: 14px; color: #D8D8D8; } .header .header-left { display: flex; align-items: center; } .header .cml-logo { margin-left: 30px; width:150px; } .header .line { display: inline-block; margin-left: 20px; margin-right: 20px; width: 2px; height: 25px; background-color: #D7D7D7; } .header .header-right { display: flex; align-items: center; margin-right: 80px; } .header .toggle-route { color: #FFF; font-size: 12px; margin-right: 15px; font-weight: 300; } .header .route-input { padding-left: 5px; padding-right: 5px; display: inline-block; width: 230px; height: 32px; line-height: 32px; border-radius: 2px; /* color: #FFF; */ font-size: 12px; font-weight: 300; border: 1px solid rgba(255, 255, 255, 0.8); padding-left: 5px; overflow: scroll; } .routes-container { width: 350px; background: #FFF; overflow-y: scroll; overflow-x: hidden; border-radius: 5px; position: absolute; right: 30px; top: 70px; z-index: 999; box-shadow: 0 2px 12px 0; padding-right: 15px; height:500px; } .routes-container-hide { /* display: none; width: 350px; background: #FFF; overflow: scroll; border-radius: 5px; position: absolute; right: 30px; top: 76px; z-index: 999; */ } .content { flex: 1; overflow: scroll; } .main { display: flex; flex-direction: row; justify-content: space-between; min-width: 980px; } .main .right{ height:600px; overflow:auto; } .main .qrcode-box { /* width: 400px; */ width: 690px; display: flex; flex-direction: row; align-items: stretch; flex-wrap: wrap; } .main .qrcode-box-bottom { margin-top:10px; } .main .qrcode-item { width: 220px; height: 200px; background-color: #FFF; margin-left: 10px; position: relative; } .qrcode-item .qrcode-content { width: 100%; position: absolute; left: 50%; top: 60%; transform: translate(-50%, -50%) } .qrcode-title img { width:30px; /* height:36px */ border-radius:50%; } .qrcode-item .qrcode-title { display: flex; height: 40px; align-items: center; justify-content: flex-start; } .qrcode-title span { font-family: PingFangSC-Regular; font-size: 14px; color: #19263E; margin-left: 10px; } .qrcode { width: 100%; } .qrcode>img { display: block; width: 120px; height: 120px; margin: 0 auto; } /* .blur-qrcode:hover { -webkit-filter: blur(10px); -moz-filter: blur(10px); -o-filter: blur(10px); -ms-filter: blur(10px); filter: blur(10px); } */ .qrcode-tips { text-align: center; margin: 5px; font-size: 12px; color: #888F9B; } .qrcode-tips a, .qrcode-tips a:link { color: #00B4FF; text-decoration: none; } .qrcode-tips a:hover, .qrcode-tips a:active { color: #238FFF; } .web-page-link { opacity: 0; cursor: pointer; z-index: 999; display: block; right: 10px; top: 10px; width: 30px; height: 30px; font-size: 14px; border-radius: 50%; background: #f5f5f5; border: 1px solid #ddd; transition: all .2s ease; position: absolute; } .web-page-link svg { margin: 5px; opacity: .5; } .inner:hover .web-page-link { opacity: 1; transition: all .2s ease; } .pages-box { max-height: 330px; overflow-y: auto; } .pages-box .page-item { display: inline-block; padding: 5px 8px; text-decoration: none; font-size: 14px; border-radius: 5px; margin: 10px 5px; color: #717171; border: 1px solid #ddd; transition: all .2s ease; } .pages-box .page-item:hover { border-color: #0088fb; background: #0088fb; color: #fff; } .pages-box .page-item.active { border-color: #0088fb; background: #0088fb; color: #fff; } .beatlesqrcode { margin-top: 20px; } #routeList { cursor: pointer; list-style-type: none; } #routeList li { position: relative; } #routeList li span { padding-top:7px; padding-bottom: 3px; padding-left: 25px; font-size:14px; } #routeList li img { position: absolute; left: 5px; top: 50%; transform: translate(0, -50%) } #routeList li span { display: inline-block; width: 60px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; width: 100%; box-sizing: border-box; } #routeList li:hover { background-color: rgba(25, 38, 62, 0.08); } /* 这里的样式控制dev构建的类型的显示和隐藏 */ .inner .web-dev { display: none } .inner .web-no-dev { height: 100%; display: flex; justify-content: center; align-items: center; } .weex-dev { display: none; } .sfc-dev { display: none; } .wx-dev { display: none; } .alipay-dev,.tt-dev,.qq-dev { display: none; } .baidu-dev { display: none; } .h5-dev { display: none; } .no-dev-content { font-family: PingFangSC-Regular; font-size: 14px; color: #19263E; letter-spacing: 0; text-align: center; } .route-input::-webkit-scrollbar { height: 0px; width: 0px; background-color: #19263E; /* border-radius: 5px; */ } .right-route{ margin-left:10px; width:330px; background: #FFF; height:600px; overflow-y: scroll; overflow-x: hidden; } /* .route-input::-webkit-scrollbar-track { width:5px; background-color: #19263E; } */ </style> </head> <body> <header class="header"> <div class="header-left"> <img class="cml-logo" src="./preview-assets/cml-logo.png" alt=""> <span class="line"></span> <span class="result-preview">效果预览</span> </div> <div class="header-right"> <span class="toggle-route">搜索路由地址</span> <input class="route-input center" id="routes-select" ></input> </div> </header> </div> <div class="content center" id="wrap-content"> <main class="main"> <div class="phone"> <div class="qrcode-title"> <img src="./preview-assets/cml-h5.png" alt=""> <span style="vertical-align: 10px;"> H5页面 效果预览</span> </div> <div class="mock-phone"> <!-- <div class="camera"></div> --> <!-- <div class="earpiece"></div> --> <div class="inner"> <div class="web-dev" id="web-dev"> <a class="web-page-link" href="" target="_blank" title="Open on new tab"> <svg t="1526896599773" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2499" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"> <defs> <style type="text/css"></style> </defs> <path d="M466 146c41.6 0 82.1 7.9 120.4 23.4 39.7 16.1 75.3 39.7 105.8 70.3 58.2 58.3 91.5 135.7 93.6 218 2.1 82-26.8 160.7-81.4 221.6l-11.9 13.3-13.3 11.9C620.7 757 544.9 786 465.9 786c-41.6 0-82.1-7.9-120.4-23.4-39.7-16.1-75.3-39.7-105.8-70.3-30.6-30.6-54.2-66.2-70.3-105.8-15.6-38.4-23.4-79-23.4-120.5 0-41.6 7.9-82.1 23.4-120.4 16.1-39.7 39.7-75.3 70.3-105.8 30.6-30.6 66.2-54.2 105.8-70.3C383.9 153.8 424.4 146 466 146m0-40c-92.1 0-184.3 35.1-254.6 105.4-140.6 140.6-140.6 368.5 0 509.1C281.7 790.8 373.8 826 465.9 826c85.9 0 171.8-30.6 240-91.7L889.8 918l28.3-28.3L734.3 706C861 564.7 856.4 347.3 720.5 211.4 650.2 141.1 558.1 106 466 106z" fill="" p-id="2500"></path> </svg> </a> <iframe id="preview" src="/" frameborder="0"></iframe> </div> <div class="web-no-dev" id="web-no-dev"> <div> <div style="text-align:center"><img src="./preview-assets/cml-forbidden.png" alt=""><br> </div> <p class="no-dev-content"> 未启动web端构建 </p> </div> </div> </div> <!-- <div class="home-btn"></div> --> </div> </div> <div class="right"> <div class="qrcode-box" id="qrcodeBox"> <div class='qrcode-item'> <div class="qrcode-title"> <img src="./preview-assets/cml-chameleon.png" alt=""> <span>Chameleon Playground App 效果预览</span> </div> <div class="qrcode-content sfc-dev blur-qrcode" id="sfc-dev"> <a class="qrcode beatlesqrcode" id="beatlesqrcode" target="_blank"></a> <p class="qrcode-tips"><a href="https://beatles-chameleon.github.io/playground/app-release.apk" target="_blank">Chameleon Playground App</a> 扫码 </p> </div> <div class="qrcode-content" id="sfc-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class="no-dev-content"> 未启动weex端构建 </p> </div> </div> <div class="qrcode-item"> <div class="qrcode-title"> <img src="./preview-assets/cml-weex.png" alt=""> <span> Weex Playground App 效果预览</span> </div> <div class="qrcode-content weex-dev blur-qrcode" id="weex-dev"> <a class="qrcode" id="qrcode" target="_blank"></a> <p class="qrcode-tips"><a target="_blank" href="https://weex-project.io/playground.html">Weex Playground App</a> 扫码</p> </div> <div class="qrcode-content" id="weex-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class="no-dev-content"> 未启动Weex端构建 </p> </div> </div> <div class="qrcode-item"> <div class="qrcode-title"> <img src="./preview-assets/cml-h5.png" alt=""> <span> H5端 效果预览</span> </div> <div class="qrcode-content h5-dev blur-qrcode" id="h5-dev"> <a class="qrcode" id="h5qrcode" target="_blank"></a> <p class="qrcode-tips">用 智能手机 扫码</p> </div> <div class="qrcode-content" id="h5-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class="no-dev-content"> 未启动web端构建 </p> </div> </div> </div> <div class="qrcode-box qrcode-box-bottom" id="qrcodeBox"> <div class='qrcode-item'> <div class="qrcode-title"> <img src="./preview-assets/cml-weixin.png" alt=""> <span> 微信小程序 效果预览</span> </div> <div class="qrcode-content wx-dev" id="wx-dev"> <p class="qrcode-tips"> 代码产出到:项目根目录 /dist/wx </p> <p class="qrcode-tips"> 下载 <a href="https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html">微信开发者工具</a> 进行预览</p> </div> <div class="qrcode-content" id="wx-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class="no-dev-content">未启动微信小程序构建</p> </div> </div> <div class='qrcode-item'> <div class="qrcode-title"> <img src="./preview-assets/cml-alipay.png" alt=""> <span> 支付宝小程序 效果预览</span> </div> <div class="qrcode-content alipay-dev" id="alipay-dev"> <p class="qrcode-tips"> 代码产出到:项目根目录 /dist/alipay </p> <p class="qrcode-tips"> 下载 <a href="https://docs.alipay.com/mini/developer/getting-started#%E4%B8%8B%E8%BD%BD">支付宝开发者工具</a> 进行预览</p> </div> <div class="qrcode-content" id="alipay-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class='no-dev-content'> 未启动支付宝小程序构建 </p> </div> </div> <div class='qrcode-item'> <div class="qrcode-title"> <img src="./preview-assets/cml-baidu.png" alt=""> <span> 百度小程序 效果预览</span> </div> <div class="qrcode-content baidu-dev" id="baidu-dev"> <p class="qrcode-tips"> 代码产出到:项目根目录 /dist/baidu </p> <p class="qrcode-tips"> 下载 <a href="https://smartprogram.baidu.com/developer/index.html">百度开发者工具</a> 进行预览</p> </div> <div class="qrcode-content" id="baidu-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class='no-dev-content'> 未启动百度小程序构建 </p> </div> </div> </div> <div class="qrcode-box qrcode-box-bottom" id="qrcodeBox"> <div class='qrcode-item'> <div class="qrcode-title"> <img src="./preview-assets/cml-tt.png" alt=""> <span> 字节跳动小程序 效果预览</span> </div> <div class="qrcode-content tt-dev" id="tt-dev"> <p class="qrcode-tips"> 代码产出到:项目根目录 /dist/tt </p> <p class="qrcode-tips"> 下载 <a href="https://microapp.bytedance.com/docs/devtool/versionUpdate.html">头条开发者工具</a> 进行预览</p> </div> <div class="qrcode-content" id="tt-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class="no-dev-content">未启动字节跳动小程序构建</p> </div> </div> <div class='qrcode-item'> <div class="qrcode-title"> <img src="./preview-assets/cml-qq.png" alt=""> <span> QQ小程序 效果预览</span> </div> <div class="qrcode-content qq-dev" id="qq-dev"> <p class="qrcode-tips"> 代码产出到:项目根目录 /dist/qq </p> <p class="qrcode-tips"> 下载 <a href="https://q.qq.com/wiki/#_3-%E5%88%9B%E5%BB%BA%E5%B0%8F%E7%A8%8B%E5%BA%8F">QQ开发者工具</a> 进行预览</p> </div> <div class="qrcode-content" id="qq-no-dev"> <div style="text-align:center"> <img src="./preview-assets/cml-forbidden.png" alt=""> </div> <p class='no-dev-content'> 未启动QQ小程序构建 </p> </div> </div> </div> </div> <div class="right-route" id="routes-container"></div> </main> </div> <script src="./preview-assets/qrcode.js"></script> <script> //注意:所有的全局变量声明在最顶部 (function () { var subpath = ''; var jsbundle = ''; var weexBundles = [];//[{bundle,paths},{bundle,paths}] var routerConfig = { mode: 'history', routes:[] }; var activeIndex = 0; var routeListDom; var selectInput = document.getElementById('routes-select'); var routesContainer = document.getElementById('routes-container'); var wrapContent = document.getElementById('wrap-content'); function isType(o, type) { return Object.prototype.toString.call(o).slice(8,-1) === type } //初始化全局参数值 function initParams(params){ subpath = params.subpath; weexBundles = params.weexBundles || []; jsbundle = params.weexBundles && weexBundles[0].bundle; } function activeBuildType(params){ var buildType = params.buildType; if (~buildType.indexOf('weex')) { Array.isArray(buildType) && buildType.push('sfc'); }; if (~buildType.indexOf('web')) { Array.isArray(buildType) && buildType.push('h5'); }; buildType.forEach(function (type) { var activeDom = document.getElementById(type + '-dev'); var hideDom = document.getElementById(type + '-no-dev'); if(activeDom){ activeDom.style.display = 'block'; } if(hideDom){ hideDom.style.display = 'none'; } }) } //创建weex二维码 function createQRCode(url, path) { var $QR = document.querySelector('#qrcode') var QR = qrcode(0, 'L') url += '?path=' + encodeURIComponent(path) $QR.setAttribute('href', url) QR.addData(url) QR.make() $QR.innerHTML = QR.createImgTag(6, 12) } function createH5QRCode(url) { var $QR = document.querySelector('#h5qrcode') var QR = qrcode(0, 'L') $QR.setAttribute('href', url) QR.addData(url) QR.make() $QR.innerHTML = QR.createImgTag(6, 12) } //创建beatles的二维码 function createBeatlesQRCode(url, path,subpath) { var $QR = document.querySelector('#beatlesqrcode') var QR = qrcode(0, 'L') var origin = location.origin; var pageUrl = origin; if(routerConfig.mode === 'history') { pageUrl += subpath } var beatlesUrl = pageUrl + '?wx_addr=' + encodeURIComponent(url + '?t=' + Date.now()); if (path) { beatlesUrl += '&path=' + encodeURIComponent(path); } if(routerConfig.mode === 'hash') { beatlesUrl += subpath } $QR.setAttribute('href', beatlesUrl) QR.addData(beatlesUrl) QR.make() $QR.innerHTML = QR.createImgTag(6, 12) } //设置页面的url function setPageUrl(subpath) { if(!subpath){ return } //创建h5链接 if (subpath[0] === '/') { subpath = subpath.slice(1); } if (subpath) { var $preview = document.querySelector('#preview') var $webPageLink = document.querySelector('.web-page-link') var origin = location.origin; var pageUrl = origin + '/' + subpath; console.log('subpath',pageUrl); createH5QRCode(pageUrl); $preview.src = pageUrl; $webPageLink.setAttribute('href', pageUrl); } } //设置搜索框事件 function setSelectEvent() { selectInput.addEventListener('keyup', function (e) { if(e.keyCode === 13){ //按下enter键进行搜索且存在搜索值 console.log(e,this.value); let searchValue = this.value var selectedRoutes = routerConfig.routes.filter(function(item){ return item.url && ~item.url.indexOf(searchValue) }); setRoutesList(selectedRoutes) } }) }; //设置点击外部区域隐藏路由列表 function setWrapContentEvent() { // wrapContent.addEventListener('click', function (e) { // routesContainer.className = 'routes-container-hide'; // }) }; function setRouteSelected(index,routeListDom) { var lis = routeListDom.children; for (var i = 0; i < lis.length; i++) { if (i == index) { lis[i].children[0].style.display = 'inline'; } else { lis[i].children[0].style.display = 'none' } } } //所点击路由在对应的weexjsbundle里面 function updateWeexBundle(routePath){ var bundle = location.origin + '/' + jsbundle; for(var i = 0; i < weexBundles.length; i++){ if(weexBundles[i].paths.indexOf(routePath) != -1){ bundle =location.origin + '/' + weexBundles[i].bundle; } } return bundle; } function setRoutesList(routes) { var bundleurl = location.origin + '/' + jsbundle; routesContainer.innerHTML = '';//先将该元素下面的所有子元素删除 if (routes && routes.length > 0) { var fragment = document.createDocumentFragment(); routeListDom = document.createElement('ul'); routeListDom.setAttribute('id','routeList') for (var i = 0; i < routes.length; i++) { let usedPlatforms = routes[i].usedPlatforms; let usedPlatformsString = '' if(usedPlatforms){ usedPlatformsString = '-' + usedPlatforms.toString(); } console.log('usedPlatformsString',usedPlatformsString) var li = document.createElement('li'); li.setAttribute('index', i); li.innerHTML = '<img style="display:none;padding-right:5px;" src="./preview-assets/cml-right.png" alt=""><span index=' + i + ' title=' + routes[i].path + usedPlatformsString + ' >' + routes[i].url+ '</span>'; routeListDom.appendChild(li); } fragment.appendChild(routeListDom) routesContainer.appendChild(fragment); var handlClick = function (e) { if (e.target.tagName.toLowerCase() === 'span') { selectInput.innerText = e.target.innerText; selectInput.setAttribute('title', e.target.innerText); var index = e.target.getAttribute('index'); activeIndex = index; var subpath; if (routerConfig.mode === 'history') { subpath = routes[index].url; } else if (routerConfig.mode === 'hash') { var mpa = routerConfig.mpa; if(mpa && mpa.webMpa && isType(mpa.webMpa,'Array') ){ var webMpa = mpa.webMpa; for (var j = 0; j < webMpa.length ; j++){ if(isType(webMpa[j].paths,"Array") && webMpa[j].paths.indexOf(routes[index].path) != -1){ if (typeof webMpa[j].name === 'string') { subpath = webMpa[j].name +'.html'+ '#' + routes[index].url; } else { subpath = routerConfig.entry+j +'.html'+ '#' + routes[index].url; } } } }else{ subpath = '#' + routes[index].url; } } bundleurl = updateWeexBundle(routes[index].path) setRouteSelected(index,routeListDom); setPageUrl(subpath); createQRCode(bundleurl, routes[index].path); createBeatlesQRCode(bundleurl, routes[index].path,subpath) } } routeListDom.addEventListener('click', handlClick); routeListDom.children[0] && routeListDom.children[0].children[1].click(); } }; function createWS() { // const ws = new WebSocket(`ws://${location.hostname}:${webport}`); var ws = new WebSocket('ws://' + location.host); ws.onopen = function () { console.log('@open'); }; ws.onmessage = function (e) { if(e.data == 'weex_refresh') { routeListDom.children[0] && routeListDom.children[activeIndex].children[1].click(); } else { routerConfig = JSON.parse(e.data); initParams(routerConfig); activeBuildType(routerConfig); setRoutesList(routerConfig.routes) } }; ws.onclose = function () { console.log('@close') }; ws.onerror = function () { console.log('@error') } } createWS(); setWrapContentEvent() setSelectEvent(); })(); </script> </body> </html>