chameleon-tool
Version:
chameleon 脚手架工具
921 lines (846 loc) • 28 kB
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>