aiot-toolkit 2.0.2-beta.10 → 2.0.2-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bin.js +21 -29
- package/lib/builder/UxBuilder.d.ts +12 -5
- package/lib/builder/UxBuilder.js +22 -15
- package/lib/builder/XtsBuilder.js +9 -12
- package/lib/starter/AndroidUxStart.d.ts +39 -0
- package/lib/starter/AndroidUxStart.js +170 -0
- package/lib/starter/IStarter.d.ts +2 -1
- package/lib/starter/IStarter.js +5 -1
- package/lib/starter/UxStarter.d.ts +3 -2
- package/lib/starter/UxStarter.js +50 -46
- package/lib/starter/XtsStarter.d.ts +2 -2
- package/lib/starter/androidRouter/LinkMode.d.ts +9 -0
- package/lib/starter/androidRouter/LinkMode.js +12 -0
- package/lib/starter/androidRouter/PackageRouter.d.ts +55 -0
- package/lib/starter/androidRouter/PackageRouter.js +152 -0
- package/lib/starter/androidRouter/h5/index.css +167 -0
- package/lib/starter/androidRouter/h5/index.html +58 -0
- package/lib/starter/androidRouter/h5/index.js +66 -0
- package/lib/utils/AdbUtils.js +3 -3
- package/lib/utils/DeviceUtil.js +37 -24
- package/lib/utils/RequestUtils.js +5 -5
- package/lib/utils/VelaAvdUtils.js +70 -62
- package/package.json +15 -10
- package/lib/utils/UxBuilderUtils.d.ts +0 -8
- package/lib/utils/UxBuilderUtils.js +0 -51
package/lib/starter/UxStarter.js
CHANGED
|
@@ -1,27 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -35,10 +12,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
13
|
};
|
|
37
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
const
|
|
15
|
+
const aiotpack_1 = require("@aiot-toolkit/aiotpack");
|
|
39
16
|
const emulator_1 = require("@aiot-toolkit/emulator");
|
|
40
17
|
const constants_1 = require("@aiot-toolkit/emulator/lib/static/constants");
|
|
41
|
-
const
|
|
18
|
+
const index_1 = require("@aiot-toolkit/emulator/lib/utils/index");
|
|
19
|
+
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
42
20
|
const prompts_1 = require("@inquirer/prompts");
|
|
43
21
|
const os_1 = __importDefault(require("os"));
|
|
44
22
|
const path_1 = __importDefault(require("path"));
|
|
@@ -47,6 +25,7 @@ const UxBuilder_1 = __importDefault(require("../builder/UxBuilder"));
|
|
|
47
25
|
const VelaAvdUtils_1 = __importDefault(require("../utils/VelaAvdUtils"));
|
|
48
26
|
const IStarter_1 = __importDefault(require("./IStarter"));
|
|
49
27
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
28
|
+
const ws_1 = __importDefault(require("ws"));
|
|
50
29
|
/**
|
|
51
30
|
* UxStarter
|
|
52
31
|
* ux快应用启动器
|
|
@@ -54,7 +33,14 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
54
33
|
class UxStarter extends IStarter_1.default {
|
|
55
34
|
constructor() {
|
|
56
35
|
super(...arguments);
|
|
57
|
-
this.builder = new UxBuilder_1.default(
|
|
36
|
+
this.builder = new UxBuilder_1.default({
|
|
37
|
+
onBuildSuccess: () => {
|
|
38
|
+
var _a;
|
|
39
|
+
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify({
|
|
40
|
+
type: 'restart'
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
58
44
|
this.params = [
|
|
59
45
|
{
|
|
60
46
|
name: 'disableNSH',
|
|
@@ -81,30 +67,43 @@ class UxStarter extends IStarter_1.default {
|
|
|
81
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
82
68
|
// 获取已经创建的模拟器列表
|
|
83
69
|
const avdList = VelaAvdUtils_1.default.velaAvdCls.getVelaAvdList();
|
|
70
|
+
let avdName;
|
|
84
71
|
if (avdList.length === 0) {
|
|
85
|
-
|
|
72
|
+
shared_utils_1.ColorConsole.error('no vela emulator available, please create it first.');
|
|
86
73
|
VelaAvdUtils_1.default.createVelaAvdByInquire();
|
|
87
74
|
return;
|
|
88
75
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
})
|
|
94
|
-
|
|
76
|
+
else if (avdList.length === 1) {
|
|
77
|
+
const needtoRun = yield (0, prompts_1.confirm)({
|
|
78
|
+
message: 'there is only one emulator, need to Run?',
|
|
79
|
+
default: true
|
|
80
|
+
});
|
|
81
|
+
if (!needtoRun) {
|
|
82
|
+
VelaAvdUtils_1.default.createVelaAvdByInquire();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
avdName = avdList[0].avdName;
|
|
86
|
+
shared_utils_1.ColorConsole.warn(`Start run by :${avdName} `);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
avdName = yield (0, prompts_1.select)({
|
|
90
|
+
message: 'name of the avd to start',
|
|
91
|
+
choices: avdList.map((item) => {
|
|
92
|
+
return { value: item.avdName };
|
|
93
|
+
})
|
|
94
|
+
});
|
|
95
|
+
}
|
|
95
96
|
// 检查选择的模拟器是否符合要求
|
|
96
|
-
if (!this.isAvailableEmulator(avdName)) {
|
|
97
|
-
|
|
97
|
+
if (avdName && !this.isAvailableEmulator(avdName)) {
|
|
98
|
+
shared_utils_1.ColorConsole.throw(`this emulator is unavailable, please create a new emulator.`);
|
|
98
99
|
return;
|
|
99
100
|
}
|
|
100
101
|
let serverPort;
|
|
101
102
|
// watch模型下开启server
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
(0, JavascriptDefaultCompileOption_1.setServerPort)(serverPort);
|
|
107
|
-
}
|
|
103
|
+
serverPort = yield portfinder_1.default.getPortPromise({
|
|
104
|
+
port: aiotpack_1.JavascriptDefaultCompileOption.serverPort
|
|
105
|
+
});
|
|
106
|
+
(0, aiotpack_1.setServerPort)(serverPort);
|
|
108
107
|
// build
|
|
109
108
|
const compilerOption = this.builder.getCompilerOption(projectPath, options);
|
|
110
109
|
yield this.builder.build(projectPath, options);
|
|
@@ -119,16 +118,20 @@ class UxStarter extends IStarter_1.default {
|
|
|
119
118
|
const goldfishInstance = (0, emulator_1.findInstance)(avdName, params);
|
|
120
119
|
if (!goldfishInstance)
|
|
121
120
|
return;
|
|
122
|
-
let
|
|
121
|
+
let grpcPort;
|
|
123
122
|
// 设置vncPort
|
|
124
123
|
if (options.openVNC) {
|
|
125
|
-
|
|
124
|
+
grpcPort = yield portfinder_1.default.getPortPromise({
|
|
126
125
|
port: constants_1.defaultVncPort,
|
|
127
126
|
stopPort: constants_1.defaultVncPort + 100
|
|
128
127
|
});
|
|
129
128
|
}
|
|
130
129
|
// 设置adbPort
|
|
131
|
-
const adbPort = yield
|
|
130
|
+
const adbPort = yield (0, index_1.getEvenPort)();
|
|
131
|
+
if (!adbPort) {
|
|
132
|
+
shared_utils_1.ColorConsole.throw(`${adbPort},5555和5585之间的端口号已全部不占用,请解决端口冲突,再启动模拟器`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
132
135
|
// 设置debugPort
|
|
133
136
|
let debugPort;
|
|
134
137
|
if (options.devtool) {
|
|
@@ -139,11 +142,12 @@ class UxStarter extends IStarter_1.default {
|
|
|
139
142
|
devtool: options.devtool,
|
|
140
143
|
disableNSH: options.disableNSH,
|
|
141
144
|
serverPort,
|
|
142
|
-
|
|
145
|
+
grpcPort,
|
|
143
146
|
adbPort,
|
|
144
147
|
debugPort
|
|
145
148
|
};
|
|
146
|
-
goldfishInstance.start(startOptions);
|
|
149
|
+
yield goldfishInstance.start(startOptions);
|
|
150
|
+
this.ws = new ws_1.default(`ws://localhost:${serverPort}`);
|
|
147
151
|
// waiter
|
|
148
152
|
// const startWaiter: PersistentCommand = new PersistentCommand({
|
|
149
153
|
// description: 'aiot-toolkit start 的常驻命令',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IParam } from '@aiot-toolkit/commander';
|
|
2
2
|
import XtsBuilder from '../builder/XtsBuilder';
|
|
3
3
|
import IStarter from './IStarter';
|
|
4
4
|
declare class XtsStarter extends IStarter {
|
|
5
5
|
builder: XtsBuilder;
|
|
6
|
-
params:
|
|
6
|
+
params: IParam[];
|
|
7
7
|
start(projectPath: string, options: any): void;
|
|
8
8
|
}
|
|
9
9
|
export default XtsStarter;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* 连接类型
|
|
5
|
+
*/
|
|
6
|
+
var LinkMode;
|
|
7
|
+
(function (LinkMode) {
|
|
8
|
+
LinkMode[LinkMode["NULL"] = 0] = "NULL";
|
|
9
|
+
LinkMode[LinkMode["WIFI"] = 1] = "WIFI";
|
|
10
|
+
LinkMode[LinkMode["ADB"] = 2] = "ADB";
|
|
11
|
+
})(LinkMode || (LinkMode = {}));
|
|
12
|
+
exports.default = LinkMode;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { IJavascriptCompileOption } from '@aiot-toolkit/aiotpack';
|
|
2
|
+
import { IRouteItem, IRouter } from '@aiot-toolkit/shared-utils';
|
|
3
|
+
interface IPackageRouter {
|
|
4
|
+
projectPath: string;
|
|
5
|
+
options: IJavascriptCompileOption;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* 打包相关的路由配置
|
|
9
|
+
* 用于开发机的httpServer
|
|
10
|
+
*/
|
|
11
|
+
declare class PackageRouter implements IRouter<IPackageRouter> {
|
|
12
|
+
readonly param: IPackageRouter;
|
|
13
|
+
constructor(param: IPackageRouter);
|
|
14
|
+
routeList: IRouteItem<any, {}>[];
|
|
15
|
+
/**
|
|
16
|
+
* 下载 rpk 包
|
|
17
|
+
* @param ctx
|
|
18
|
+
* @param next
|
|
19
|
+
*/
|
|
20
|
+
private handlerDownLoadRpk;
|
|
21
|
+
private handlerQrCode;
|
|
22
|
+
/**
|
|
23
|
+
* 记录设备信息
|
|
24
|
+
*
|
|
25
|
+
* 获取请求的 ip 和端口,记录到本机中,最多记录5个
|
|
26
|
+
*
|
|
27
|
+
* 文件内容的格式为:
|
|
28
|
+
* ```
|
|
29
|
+
* records: {
|
|
30
|
+
* "快应用项目路径":[
|
|
31
|
+
* {ip:"", port:""},
|
|
32
|
+
* {ip:"", port:""},
|
|
33
|
+
* {ip:"", port:""}
|
|
34
|
+
* ]
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
*
|
|
39
|
+
* 此记录的作用是:当重新打包后,获取已连接的设备列表
|
|
40
|
+
* @param ctx
|
|
41
|
+
* @param next
|
|
42
|
+
*/
|
|
43
|
+
private recordDevice;
|
|
44
|
+
private getClientFromRequest;
|
|
45
|
+
/**
|
|
46
|
+
* http 请求中,用于返回下载文件
|
|
47
|
+
*
|
|
48
|
+
* 调用此方法后,仍需调用 next()
|
|
49
|
+
*
|
|
50
|
+
* @param filePath 文件绝对路径
|
|
51
|
+
* @param ctx 请求上下文
|
|
52
|
+
*/
|
|
53
|
+
private download;
|
|
54
|
+
}
|
|
55
|
+
export default PackageRouter;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const qr_image_1 = __importDefault(require("qr-image"));
|
|
19
|
+
const LinkMode_1 = __importDefault(require("./LinkMode"));
|
|
20
|
+
const CLIENT_PORT = 39517;
|
|
21
|
+
/**
|
|
22
|
+
* 打包相关的路由配置
|
|
23
|
+
* 用于开发机的httpServer
|
|
24
|
+
*/
|
|
25
|
+
class PackageRouter {
|
|
26
|
+
constructor(param) {
|
|
27
|
+
this.param = param;
|
|
28
|
+
this.routeList = [
|
|
29
|
+
{
|
|
30
|
+
path: '/qrcode',
|
|
31
|
+
handler: (ctx, next) => {
|
|
32
|
+
return this.handlerQrCode(ctx, next);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
path: '/bundle',
|
|
37
|
+
handler: (ctx, next) => {
|
|
38
|
+
this.recordDevice(ctx);
|
|
39
|
+
return this.handlerDownLoadRpk(ctx, next);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
/**
|
|
44
|
+
* 下载 rpk 包
|
|
45
|
+
* @param ctx
|
|
46
|
+
* @param next
|
|
47
|
+
*/
|
|
48
|
+
this.handlerDownLoadRpk = (ctx, next) => {
|
|
49
|
+
const { projectPath, options } = this.param;
|
|
50
|
+
const dist = path_1.default.join(projectPath, options.releasePath);
|
|
51
|
+
const files = fs_extra_1.default.readdirSync(dist).filter((item) => path_1.default.extname(item) === '.rpk');
|
|
52
|
+
const filePath = files.length ? path_1.default.join(dist, files[0]) : '';
|
|
53
|
+
this.download(filePath, ctx);
|
|
54
|
+
return next();
|
|
55
|
+
};
|
|
56
|
+
this.handlerQrCode = (ctx, next) => {
|
|
57
|
+
const qrText = ctx.origin;
|
|
58
|
+
const image = qr_image_1.default.image(qrText, {
|
|
59
|
+
size: 9
|
|
60
|
+
});
|
|
61
|
+
ctx.type = 'image/png';
|
|
62
|
+
ctx.body = image;
|
|
63
|
+
return next();
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* 记录设备信息
|
|
67
|
+
*
|
|
68
|
+
* 获取请求的 ip 和端口,记录到本机中,最多记录5个
|
|
69
|
+
*
|
|
70
|
+
* 文件内容的格式为:
|
|
71
|
+
* ```
|
|
72
|
+
* records: {
|
|
73
|
+
* "快应用项目路径":[
|
|
74
|
+
* {ip:"", port:""},
|
|
75
|
+
* {ip:"", port:""},
|
|
76
|
+
* {ip:"", port:""}
|
|
77
|
+
* ]
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
*
|
|
82
|
+
* 此记录的作用是:当重新打包后,获取已连接的设备列表
|
|
83
|
+
* @param ctx
|
|
84
|
+
* @param next
|
|
85
|
+
*/
|
|
86
|
+
this.recordDevice = (ctx) => __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const clientInfo = this.getClientFromRequest(ctx);
|
|
88
|
+
if (!(clientInfo === null || clientInfo === void 0 ? void 0 : clientInfo.clientIp)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (clientInfo.linkMode === LinkMode_1.default.WIFI) {
|
|
92
|
+
const max = 5;
|
|
93
|
+
const filePath = this.param.options.clientRecordPath;
|
|
94
|
+
const projectPath = this.param.projectPath;
|
|
95
|
+
const data = {
|
|
96
|
+
sn: clientInfo.sn,
|
|
97
|
+
ip: clientInfo.clientIp,
|
|
98
|
+
port: CLIENT_PORT
|
|
99
|
+
};
|
|
100
|
+
const json = fs_extra_1.default.readJSONSync(filePath, { throws: false }) || {};
|
|
101
|
+
if (!json.records) {
|
|
102
|
+
json.records = {};
|
|
103
|
+
}
|
|
104
|
+
if (!json.records[projectPath]) {
|
|
105
|
+
json.records[projectPath] = [];
|
|
106
|
+
}
|
|
107
|
+
const deviceList = json.records[projectPath];
|
|
108
|
+
if (deviceList.findIndex((item) => item.ip === data.ip) < 0) {
|
|
109
|
+
deviceList.push(data);
|
|
110
|
+
if (deviceList.length > max) {
|
|
111
|
+
deviceList.splice(0, deviceList.length - max);
|
|
112
|
+
}
|
|
113
|
+
fs_extra_1.default.ensureDirSync(path_1.default.dirname(filePath));
|
|
114
|
+
fs_extra_1.default.writeJSONSync(filePath, json, { spaces: 2 });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
getClientFromRequest(ctx) {
|
|
120
|
+
const clientIp = shared_utils_1.NetworkUtil.getClientIp(ctx);
|
|
121
|
+
const serverIp = shared_utils_1.NetworkUtil.getIPv4IPAddress();
|
|
122
|
+
const sn = ctx.request.header['device-serial-number'];
|
|
123
|
+
let linkMode = LinkMode_1.default.NULL;
|
|
124
|
+
if (clientIp === '127.0.0.1' && sn) {
|
|
125
|
+
linkMode = LinkMode_1.default.ADB;
|
|
126
|
+
}
|
|
127
|
+
else if (clientIp !== '127.0.0.1' && clientIp !== serverIp) {
|
|
128
|
+
linkMode = LinkMode_1.default.WIFI;
|
|
129
|
+
}
|
|
130
|
+
return { clientIp, sn, linkMode };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* http 请求中,用于返回下载文件
|
|
134
|
+
*
|
|
135
|
+
* 调用此方法后,仍需调用 next()
|
|
136
|
+
*
|
|
137
|
+
* @param filePath 文件绝对路径
|
|
138
|
+
* @param ctx 请求上下文
|
|
139
|
+
*/
|
|
140
|
+
download(filePath, ctx) {
|
|
141
|
+
if (filePath && fs_extra_1.default.existsSync(filePath)) {
|
|
142
|
+
ctx.set('Content-Type', 'application/octet-stream');
|
|
143
|
+
ctx.set('Content-Transfer-Encoding', 'binary');
|
|
144
|
+
ctx.set('Content-Disposition', `attachment; filename=${path_1.default.basename(filePath)}`);
|
|
145
|
+
ctx.body = fs_extra_1.default.createReadStream(filePath);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
ctx.throw('404', 404);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.default = PackageRouter;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
.alert-warning {
|
|
2
|
+
color: #8a6d3b;
|
|
3
|
+
background-color: #fcf8e3;
|
|
4
|
+
border-color: #faebcc;
|
|
5
|
+
text-align: left;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.alert {
|
|
9
|
+
padding: 8px;
|
|
10
|
+
margin: 10px auto;
|
|
11
|
+
width: 400px;
|
|
12
|
+
min-width: 350px;
|
|
13
|
+
border: 1px solid transparent;
|
|
14
|
+
border-radius: 6px;
|
|
15
|
+
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.alert p {
|
|
19
|
+
margin: 6px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.panel-default {
|
|
23
|
+
border-color: #ddd;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.panel {
|
|
27
|
+
margin-bottom: 20px;
|
|
28
|
+
background-color: #fff;
|
|
29
|
+
border-radius: 4px;
|
|
30
|
+
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
|
31
|
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
|
32
|
+
margin: 10px auto;
|
|
33
|
+
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15);
|
|
34
|
+
width: 400px;
|
|
35
|
+
min-width: 350px;
|
|
36
|
+
padding: 8px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.panel-default > .panel-heading {
|
|
40
|
+
color: #333;
|
|
41
|
+
border-color: #ddd;
|
|
42
|
+
text-align: left;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.panel-heading {
|
|
46
|
+
padding: 8px 15px;
|
|
47
|
+
border-bottom: 1px solid transparent;
|
|
48
|
+
border-top-left-radius: 3px;
|
|
49
|
+
border-top-right-radius: 3px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.table {
|
|
53
|
+
width: 100%;
|
|
54
|
+
max-width: 100%;
|
|
55
|
+
margin: 6px;
|
|
56
|
+
background-color: transparent;
|
|
57
|
+
border-spacing: 0;
|
|
58
|
+
border-collapse: collapse;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.table td {
|
|
62
|
+
color: black;
|
|
63
|
+
text-shadow: none;
|
|
64
|
+
text-align: left;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.table td.tname {
|
|
68
|
+
width: 70%;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
body {
|
|
72
|
+
margin: 0;
|
|
73
|
+
display: block;
|
|
74
|
+
position: absolute;
|
|
75
|
+
top: 0;
|
|
76
|
+
bottom: 0;
|
|
77
|
+
left: 0;
|
|
78
|
+
right: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.hide {
|
|
82
|
+
display: none !important;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.qr-code-panel {
|
|
86
|
+
text-align: center;
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-direction: column;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.qr-code-panel .qr-img {
|
|
92
|
+
margin: 10px 200px;
|
|
93
|
+
min-width: 350px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.bd-bg {
|
|
97
|
+
position: relative;
|
|
98
|
+
padding: 40px 0;
|
|
99
|
+
color: black;
|
|
100
|
+
text-align: center;
|
|
101
|
+
background: #eee;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.updatetip-link {
|
|
105
|
+
padding: 0 5px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
table.tunning tr {
|
|
109
|
+
padding: 8px 15px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.btn {
|
|
113
|
+
display: inline-block;
|
|
114
|
+
padding: 6px 12px;
|
|
115
|
+
margin-bottom: 0;
|
|
116
|
+
font-size: 14px;
|
|
117
|
+
font-weight: 400;
|
|
118
|
+
line-height: 1.42857143;
|
|
119
|
+
text-align: center;
|
|
120
|
+
white-space: nowrap;
|
|
121
|
+
vertical-align: middle;
|
|
122
|
+
-ms-touch-action: manipulation;
|
|
123
|
+
touch-action: manipulation;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
-webkit-user-select: none;
|
|
126
|
+
-moz-user-select: none;
|
|
127
|
+
-ms-user-select: none;
|
|
128
|
+
user-select: none;
|
|
129
|
+
background-image: none;
|
|
130
|
+
border: 1px solid transparent;
|
|
131
|
+
border-radius: 4px;
|
|
132
|
+
margin-left: 5px;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.btn-default {
|
|
136
|
+
color: #333;
|
|
137
|
+
background-color: #fff;
|
|
138
|
+
border-color: #ccc;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.label {
|
|
142
|
+
display: inline;
|
|
143
|
+
padding: 0.7em;
|
|
144
|
+
font-size: 75%;
|
|
145
|
+
font-weight: 700;
|
|
146
|
+
line-height: 1;
|
|
147
|
+
color: #fff;
|
|
148
|
+
text-align: center;
|
|
149
|
+
text-decoration: none;
|
|
150
|
+
white-space: nowrap;
|
|
151
|
+
vertical-align: baseline;
|
|
152
|
+
border-radius: 0.25em;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.label-info {
|
|
156
|
+
background-color: #5bc0de;
|
|
157
|
+
}
|
|
158
|
+
.block {
|
|
159
|
+
width: 420px;
|
|
160
|
+
}
|
|
161
|
+
.block .block-title {
|
|
162
|
+
font-size: 16px;
|
|
163
|
+
margin: 0.5em 0;
|
|
164
|
+
}
|
|
165
|
+
.block a {
|
|
166
|
+
color: #0055ff;
|
|
167
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>调试器</title>
|
|
6
|
+
<link href="./index.css" rel="stylesheet" />
|
|
7
|
+
</head>
|
|
8
|
+
<body class="bd-bg">
|
|
9
|
+
<section class="qr-code-wrapper">
|
|
10
|
+
<div>
|
|
11
|
+
<div class="qr-code-panel">
|
|
12
|
+
<div class="qr-img">
|
|
13
|
+
<img src="" id="j-qr-icon" class="qr-icon" />
|
|
14
|
+
</div>
|
|
15
|
+
<div class="block alert alert-warning updatetip">
|
|
16
|
+
<div class="block">
|
|
17
|
+
<h2 class="block-title" title="在设备上预览">手机预览</h2>
|
|
18
|
+
<p>1. 扫码安装rpk包</p>
|
|
19
|
+
<p>
|
|
20
|
+
2. 在手机的调试器上点击
|
|
21
|
+
<button class="btn btn-default">开始调试</button> ,启动调试界面
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
24
|
+
<!-- <div class="block">
|
|
25
|
+
<h2 class="block-title" title="在浏览器中预览">web 预览</h2>
|
|
26
|
+
<p><a href="/preview" target="_blank">打开 web 预览</a></p>
|
|
27
|
+
</div> -->
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</section>
|
|
32
|
+
<section class="inform-tip-wrapper"></section>
|
|
33
|
+
<section class="result inspector-link-panel hide">
|
|
34
|
+
<div class="panel panel-default">
|
|
35
|
+
<div class="panel-heading">调试</div>
|
|
36
|
+
<div class="panel-body">
|
|
37
|
+
<table class="table tunning">
|
|
38
|
+
<tbody></tbody>
|
|
39
|
+
</table>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</section>
|
|
43
|
+
<script type="text/template" id="j-tpl-appinfo">
|
|
44
|
+
<tr>
|
|
45
|
+
<td class="tname">{{data_app_name}}</td>
|
|
46
|
+
<td class="tlink"><a href='{{data_href_value}}' target='_blank' class="label label-info">{{data_href_name}}</a>
|
|
47
|
+
</td>
|
|
48
|
+
</tr>
|
|
49
|
+
</script>
|
|
50
|
+
<script src="./index.js"></script>
|
|
51
|
+
<script type="text/template" id="j-tpl-updatetip">
|
|
52
|
+
<div class="alert alert-warning updatetip">
|
|
53
|
+
<p>调试器已有重要更新,请更新调试器</p>
|
|
54
|
+
</div>
|
|
55
|
+
</script>
|
|
56
|
+
<script src="/socket.io/socket.io.js"></script>
|
|
57
|
+
</body>
|
|
58
|
+
</html>
|