插件优化,增加FTP上传进度监控.
This commit is contained in:
parent
46b65e4f9c
commit
99ec923ebc
@ -2,6 +2,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const FileUtil = require('./FileUtils');
|
const FileUtil = require('./FileUtils');
|
||||||
const Client = require("ftp");
|
const Client = require("ftp");
|
||||||
|
const logger = require('./logger');
|
||||||
|
|
||||||
class FileUploader {
|
class FileUploader {
|
||||||
ftps = {};
|
ftps = {};
|
||||||
@ -13,7 +14,7 @@ class FileUploader {
|
|||||||
lastIdleState = true;
|
lastIdleState = true;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.loopId = setInterval(this.loop.bind(this), 200);
|
this.loopId = setInterval(this.loop.bind(this), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
setOption(options, maxThread) {
|
setOption(options, maxThread) {
|
||||||
@ -25,6 +26,10 @@ class FileUploader {
|
|||||||
this.idleCallback = callback;
|
this.idleCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restart(tName) {
|
||||||
|
this.ftps[tName] && this.ftps[tName].restart();
|
||||||
|
}
|
||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
const currLen = Object.keys(this.ftps).length;
|
const currLen = Object.keys(this.ftps).length;
|
||||||
logger.info('准备创建上传线程:', this.maxClients, currLen);
|
logger.info('准备创建上传线程:', this.maxClients, currLen);
|
||||||
@ -52,6 +57,7 @@ class FileUploader {
|
|||||||
const curState = this.checkState();
|
const curState = this.checkState();
|
||||||
if (curState != this.lastIdleState) {
|
if (curState != this.lastIdleState) {
|
||||||
this.lastIdleState = curState;
|
this.lastIdleState = curState;
|
||||||
|
logger.info('当前状态:', curState);
|
||||||
this.idleCallback && this.idleCallback(curState);
|
this.idleCallback && this.idleCallback(curState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,6 +71,29 @@ class FileUploader {
|
|||||||
return idleState;
|
return idleState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检测所有线程运行状态
|
||||||
|
checkThreads() {
|
||||||
|
let str = [];
|
||||||
|
for (let i in this.ftps) {
|
||||||
|
let p = 0;
|
||||||
|
if (this.ftps[i].totalTasks && !this.ftps[i].idleState) {
|
||||||
|
p = (this.ftps[i].totalTasks - this.ftps[i].queue.length) / this.ftps[i].totalTasks;
|
||||||
|
}
|
||||||
|
p = Math.floor(p * 10000) / 100;
|
||||||
|
str.push({
|
||||||
|
name: i,
|
||||||
|
idle: this.ftps[i].idleState,
|
||||||
|
remain: this.ftps[i].queue.length,
|
||||||
|
hasError: this.ftps[i].hasError,
|
||||||
|
totalTasks: this.ftps[i].totalTasks,
|
||||||
|
curTaskPath: this.ftps[i].curTaskPath,
|
||||||
|
taskStartTime: this.ftps[i].taskStartTime,
|
||||||
|
progress: p
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传文件、目录到ftp服务器。
|
* 上传文件、目录到ftp服务器。
|
||||||
* @param source
|
* @param source
|
||||||
@ -105,6 +134,12 @@ class UploadThread {
|
|||||||
stopped = false;
|
stopped = false;
|
||||||
options = null;
|
options = null;
|
||||||
idleState = true;
|
idleState = true;
|
||||||
|
hasError = false;
|
||||||
|
|
||||||
|
// 总任务数量, 所有任务上传完成时,total清零.
|
||||||
|
totalTasks = 0;
|
||||||
|
curTaskPath = "";// 显示当前任务.
|
||||||
|
taskStartTime = 0; // 显示任务用时.
|
||||||
|
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
@ -117,6 +152,7 @@ class UploadThread {
|
|||||||
if (this.stopped) {
|
if (this.stopped) {
|
||||||
this.ftp = this.newConnection();
|
this.ftp = this.newConnection();
|
||||||
}
|
}
|
||||||
|
this.totalTasks += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
newConnection() {
|
newConnection() {
|
||||||
@ -124,6 +160,10 @@ class UploadThread {
|
|||||||
const ftp = new Client();
|
const ftp = new Client();
|
||||||
ftp.on('ready', () => {
|
ftp.on('ready', () => {
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
|
if (this.hasError) {
|
||||||
|
this.hasError = false;
|
||||||
|
logger.success('连接恢复,当前剩余任务:', this.queue.length);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
ftp.on('close', () => {
|
ftp.on('close', () => {
|
||||||
this.ready = false;
|
this.ready = false;
|
||||||
@ -138,47 +178,78 @@ class UploadThread {
|
|||||||
return ftp;
|
return ftp;
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
getTaskLength() {
|
||||||
this.stopped = true;
|
return this.queue.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
async sleep(ms) {
|
destroy() {
|
||||||
|
this.stopped = true;
|
||||||
|
this.ftp.destroy();
|
||||||
|
this.totalTasks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(ms) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定时循环.直到destroy()执行.
|
// 定时循环.直到destroy()执行.
|
||||||
async run() {
|
async run() {
|
||||||
while (!this.stopped) {
|
while (!this.stopped) {
|
||||||
if (!this.ready || this.queue.length <= 0) {
|
if (this.hasError || !this.ready) {
|
||||||
await this.sleep(500);
|
await this.sleep(1000);
|
||||||
|
let ts = new Date().getTime();
|
||||||
|
if (this.hasError && ts - this.taskStartTime > 60000) {
|
||||||
|
this.taskStartTime = ts;
|
||||||
|
this.ftp.destroy();
|
||||||
|
this.ftp = this.newConnection();
|
||||||
|
logger.log('线程异常超时,尝试重启线程');
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (this.queue.length <= 0) {
|
||||||
this.idleState = true;
|
this.idleState = true;
|
||||||
|
this.totalTasks = 0;
|
||||||
|
await this.sleep(1000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.idleState = false;
|
this.idleState = false;
|
||||||
const once = this.queue[0];
|
const once = this.queue[0];
|
||||||
|
this.curTaskPath = once;
|
||||||
|
this.taskStartTime = new Date().getTime();
|
||||||
const err = await this.uploadOnce(this.ftp, once);
|
const err = await this.uploadOnce(this.ftp, once);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
this.queue.shift();
|
this.queue.shift();
|
||||||
logger.info('上传完成:', once.src);
|
this.curTaskPath = "";
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
logger.warn('上传失败,准备重试:', once.src);
|
logger.warn('上传失败,准备重试:', once.src);
|
||||||
this.ftp.end();
|
this.ftp.logout();
|
||||||
|
this.ftp.destroy();
|
||||||
// 上传失败有可能是线程强制结束导致的上传失败.
|
// 上传失败有可能是线程强制结束导致的上传失败.
|
||||||
if (!this.stopped) {
|
if (!this.stopped) {
|
||||||
|
this.hasError = true;
|
||||||
this.ftp = this.newConnection();
|
this.ftp = this.newConnection();
|
||||||
|
await this.sleep(5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.ftp.end();
|
this.ftp.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadOnce(ftp, once) {
|
uploadOnce(ftp, once) {
|
||||||
return new Promise(resolve => {
|
return Promise.race([new Promise(function (resolve) {
|
||||||
ftp.put(once.src, once.dst, false, resolve)
|
ftp.put(once.src, once.dst, false, resolve)
|
||||||
});
|
}), this.sleep(20000)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
restart() {
|
||||||
|
this.hasError = true;
|
||||||
|
this.ready = false;
|
||||||
|
this.ftp.destroy();
|
||||||
|
this.ftp = null;
|
||||||
|
this.ftp = this.newConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,6 @@
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
// console adapter.
|
|
||||||
global.logger = global.logger || {};
|
|
||||||
logger.log = (Editor && Editor.log) || console.log;
|
|
||||||
logger.info = (Editor && Editor.info) || console.info;
|
|
||||||
logger.warn = (Editor && Editor.warn) || console.warn;
|
|
||||||
logger.error = (Editor && Editor.error) || console.error;
|
|
||||||
logger.success = (Editor && Editor.success) || (Editor && Editor.info) || console.log;
|
|
||||||
|
|
||||||
class FileUtil {
|
class FileUtil {
|
||||||
/*
|
/*
|
||||||
* 获取window上的文件目录以及文件列表信息
|
* 获取window上的文件目录以及文件列表信息
|
||||||
|
12
packages/update-manager/js/logger.js
Normal file
12
packages/update-manager/js/logger.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const logger = (global && global.Editor) || (global && global.console) || (window && window.console);
|
||||||
|
/**
|
||||||
|
* 适配不同Logger 对象.
|
||||||
|
* @type {{warn: (message?: any, ...optionalParams: any[]) => void, log: (message?: any, ...optionalParams: any[]) => void, success: any | ((message?: any, ...optionalParams: any[]) => void), error: (message?: any, ...optionalParams: any[]) => void, info: (message?: any, ...optionalParams: any[]) => void}}
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
log: logger.log,
|
||||||
|
info: logger.info,
|
||||||
|
warn: logger.warn,
|
||||||
|
error: logger.error,
|
||||||
|
success: logger.success
|
||||||
|
}
|
@ -3,6 +3,7 @@ const fs = require('fs');
|
|||||||
const {join} = require('path');
|
const {join} = require('path');
|
||||||
const FileUtil = require('./js/FileUtils');
|
const FileUtil = require('./js/FileUtils');
|
||||||
const FileUpload = require('./js/FileUploader');
|
const FileUpload = require('./js/FileUploader');
|
||||||
|
const logger = require('./js/logger');
|
||||||
|
|
||||||
// 生成更新文件.
|
// 生成更新文件.
|
||||||
const doMakeUpdatePackage = function (opt, cb) {
|
const doMakeUpdatePackage = function (opt, cb) {
|
||||||
@ -70,10 +71,12 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onUploadStateChange(state) {
|
onUploadStateChange(state) {
|
||||||
|
logger.log('当前任务执行器状态:', state);
|
||||||
if (!state) {
|
if (!state) {
|
||||||
Editor.info('开始上传更新包');
|
this.startUploadTime = new Date().getTime();
|
||||||
|
logger.info('开始上传更新包', this.startUploadTime);
|
||||||
} else {
|
} else {
|
||||||
Editor.success('所有文件上传完成!');
|
logger.success(`所有文件上传完成,耗时:${Math.floor((new Date().getTime() - this.startUploadTime) / 1000)}秒`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -95,6 +98,15 @@ module.exports = {
|
|||||||
'getProjectPath'(event) {
|
'getProjectPath'(event) {
|
||||||
event.reply(Editor.Project.path);
|
event.reply(Editor.Project.path);
|
||||||
},
|
},
|
||||||
|
"checkThreads"(event) {
|
||||||
|
event.reply(this.ftp.checkThreads());
|
||||||
|
},
|
||||||
|
'queryThreadStates'(event) {
|
||||||
|
event.reply(this.ftp.checkState());
|
||||||
|
},
|
||||||
|
'restartThread'(event, name) {
|
||||||
|
this.ftp.restart(name);
|
||||||
|
},
|
||||||
'uploadStop'() {
|
'uploadStop'() {
|
||||||
if (this.ftp) {
|
if (this.ftp) {
|
||||||
this.ftp.destroy();
|
this.ftp.destroy();
|
||||||
|
@ -13,8 +13,9 @@
|
|||||||
"main": "panel/index.html",
|
"main": "panel/index.html",
|
||||||
"type": "simple",
|
"type": "simple",
|
||||||
"title": "热更新配置",
|
"title": "热更新配置",
|
||||||
"width": 500,
|
"width": 600,
|
||||||
"height": 600
|
"height": 800,
|
||||||
|
"resizable": false
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ftp": "^0.3.10"
|
"ftp": "^0.3.10"
|
||||||
|
@ -4,24 +4,14 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<!-- import CSS -->
|
<!-- import CSS -->
|
||||||
<link rel="stylesheet" href="./element-ui/index.css">
|
<link rel="stylesheet" href="./element-ui/index.css">
|
||||||
<style>
|
<link rel="stylesheet" href="./main.css">
|
||||||
#app {
|
<title>热更新配置</title>
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #3646ea;
|
|
||||||
background-color: #fafcfc;
|
|
||||||
padding: 35px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body style="height: 1000px;">
|
<body style="height: 1000px;">
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<el-tabs v-model="tabName">
|
<el-tabs v-model="tabName">
|
||||||
<el-tab-pane label="版本配置" name="versionConfig" style="height: 400px;">
|
<el-tab-pane label="版本配置" name="versionConfig" class="tab-content">
|
||||||
<el-form ref="version" :model="versionCfg" label-width="100px">
|
<el-form ref="version" :model="versionCfg" label-width="80px">
|
||||||
<el-tooltip effect="dark" :content="tip.versionCode" open-delay=500 placement="top">
|
<el-tooltip effect="dark" :content="tip.versionCode" open-delay=500 placement="top">
|
||||||
<el-form-item label="新版本号:">
|
<el-form-item label="新版本号:">
|
||||||
<el-input type="number" v-model="versionCfg.versionCode" placeholder="1"></el-input>
|
<el-input type="number" v-model="versionCfg.versionCode" placeholder="1"></el-input>
|
||||||
@ -38,6 +28,21 @@
|
|||||||
<el-input v-model="versionCfg.versionType" placeholder="dev"></el-input>
|
<el-input v-model="versionCfg.versionType" placeholder="dev"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
<!--<el-form-item label="其他设置:">-->
|
||||||
|
<!--<el-tooltip content="开启时将强制更新用户端版本" placement="top">-->
|
||||||
|
<!--<el-switch v-model="versionCfg.forceUpdate"-->
|
||||||
|
<!--:active-text="versionCfg.forceUpdate?'强制静默更新':'用户决定更新'"-->
|
||||||
|
<!--active-color="#13ce66" inactive-color="#ff4949"-->
|
||||||
|
<!--style="margin-right: 20px;"></el-switch>-->
|
||||||
|
<!--</el-tooltip>-->
|
||||||
|
|
||||||
|
<!--<el-tooltip placement="top">-->
|
||||||
|
<!--<div slot="content">开启时将在每次启动时直接请求更新信息<br/>否则将在进入游戏后才请求更新信息</div>-->
|
||||||
|
<!--<el-switch v-model="versionCfg.updateMoment"-->
|
||||||
|
<!--:active-text="versionCfg.updateMoment?'每次启动时更新':'二次启动时更新'"-->
|
||||||
|
<!--active-color="#13ce66" inactive-color="#ff4949"></el-switch>-->
|
||||||
|
<!--</el-tooltip>-->
|
||||||
|
<!--</el-form-item>-->
|
||||||
<el-tooltip effect="dark" :content="tip.baseUrl" open-delay=500 placement="top">
|
<el-tooltip effect="dark" :content="tip.baseUrl" open-delay=500 placement="top">
|
||||||
<el-form-item label="热更地址:">
|
<el-form-item label="热更地址:">
|
||||||
<el-input v-model="versionCfg.baseUrl"
|
<el-input v-model="versionCfg.baseUrl"
|
||||||
@ -52,8 +57,8 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="上传配置" name="ftpConfig" style="height: 400px;">
|
<el-tab-pane label="上传配置" name="ftpConfig" class="tab-content">
|
||||||
<el-form ref="ftpCfg" :model="ftpCfg" label-width="100px">
|
<el-form ref="ftpCfg" :model="ftpCfg" label-width="80px">
|
||||||
<el-tooltip effect="dark" :content="tip.ip" placement="top" open-delay=500>
|
<el-tooltip effect="dark" :content="tip.ip" placement="top" open-delay=500>
|
||||||
<el-form-item label="IP:">
|
<el-form-item label="IP:">
|
||||||
<el-col :span="15">
|
<el-col :span="15">
|
||||||
@ -103,27 +108,72 @@
|
|||||||
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="使用帮助" name="help" style="height: 400px;">
|
<el-tab-pane label="使用帮助" name="help" class="tab-content">
|
||||||
<div style="height: 300px;">
|
<el-alert :closable="false"
|
||||||
<el-alert :closable="false"
|
title="如不需要发布新版本,可无需做任何操作,以正常步骤打包发布即可"
|
||||||
title="如不需要发布新版本,可无需做任何操作,以正常步骤打包发布即可"
|
type="info">
|
||||||
type="info">
|
</el-alert>
|
||||||
</el-alert>
|
<el-divider content-position="left"></el-divider>
|
||||||
<el-divider content-position="left"></el-divider>
|
<el-steps direction="vertical" :active="1" space="100px">
|
||||||
<el-steps direction="vertical" :active="1" space="100px">
|
<el-step title="版本配置"
|
||||||
<el-step title="版本配置"
|
description="使用前需要先配置版本信息,并点击保存配置."></el-step>
|
||||||
description="使用前需要先配置版本信息,并点击保存配置."></el-step>
|
<el-step title="构建版本"
|
||||||
<el-step title="构建版本"
|
description="开始构建版本,构建完成后会在构建目录中生成remote文件夹以及update-dev.json更新描述文件
|
||||||
description="开始构建版本,构建完成后会在构建目录中生成remote文件夹以及update-dev.json更新描述文件
|
|
||||||
注:不需要设置Bundle为远程包,插件将自动调整远程包设置"></el-step>
|
注:不需要设置Bundle为远程包,插件将自动调整远程包设置"></el-step>
|
||||||
<el-step title="上传更新包"
|
<el-step title="上传更新包"
|
||||||
description="构建完成时,如需发布新版本,则需要点击[上传更新包],更新包会向游戏代码中注入热更逻辑."></el-step>
|
description="构建完成时,如需发布新版本,则需要点击[上传更新包],更新包会向游戏代码中注入热更逻辑."></el-step>
|
||||||
</el-steps>
|
</el-steps>
|
||||||
</div>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="任务状态" name="states" class="tab-content">
|
||||||
|
<template v-if="states.length>0">
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col v-for="(value,index) in states" :key="index" :span="24" style="margin-bottom:10px">
|
||||||
|
<el-card :body-style="{ padding: '0px' }">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<el-col :span="16">
|
||||||
|
<h3 style="line-height: 5px;">{{index+1}}-线程:{{value.name}}</h3>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-button :loading="!value.idle" size="small"
|
||||||
|
:type="value.idle?'success':'danger'">
|
||||||
|
{{value.idle?"空闲中":"正忙"}}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip effect="dark" content="如果任务长时间卡住,点击重试即可" placement="top" open-delay=500>
|
||||||
|
<el-button icon="el-icon-refresh-right" size="small" circle type="warning"
|
||||||
|
@click="onRestart(value.name)"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
</el-col>
|
||||||
|
</div>
|
||||||
|
<el-form label-position="right" label-width="80px">
|
||||||
|
<el-form-item label="剩余任务:" style="margin-bottom: 5px;">
|
||||||
|
<span>{{value.totalTasks-value.remain}}/{{value.totalTasks}}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否异常:" style="margin-bottom: 5px;">
|
||||||
|
<span>{{value.hasError?"正在重试中...":"线程正常"}}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="当前上传:" style="margin-bottom: 5px;">
|
||||||
|
<span>{{value.curTaskPath?value.curTaskPath.dst.substring(value.curTaskPath.dst.length>>1):"无目标"}}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上传用时:" style="margin-bottom: 5px;">
|
||||||
|
<span>{{(!value.idle && value.taskStartTime)? Math.floor(new Date().getTime()-value.taskStartTime):0}} 毫秒</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="任务进度:" style="margin-bottom: 5px;">
|
||||||
|
<el-progress :text-inside="true" :stroke-width="22"
|
||||||
|
style="width: 90%; line-height: unset;"
|
||||||
|
:percentage="value.progress" :color="customColors"></el-progress>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<h1 style="text-align: center; vertical-align: center;line-height: 15;">无任务</h1>
|
||||||
|
</template>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<el-row>
|
<el-row style="margin-top: 20px;">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-button type="success" @click="onSave">保存配置信息</el-button>
|
<el-button type="success" @click="onSave">保存配置信息</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -138,6 +188,7 @@
|
|||||||
</body>
|
</body>
|
||||||
<!-- import Vue before Element -->
|
<!-- import Vue before Element -->
|
||||||
<script src="../js/vue.2.5.16.js"></script>
|
<script src="../js/vue.2.5.16.js"></script>
|
||||||
|
<script src="../js/logger.js"></script>
|
||||||
<!-- import JavaScript -->
|
<!-- import JavaScript -->
|
||||||
<script src="./element-ui/index.js"></script>
|
<script src="./element-ui/index.js"></script>
|
||||||
<script>
|
<script>
|
||||||
@ -155,7 +206,9 @@
|
|||||||
versionName: "1.0.0",
|
versionName: "1.0.0",
|
||||||
versionType: "dev",
|
versionType: "dev",
|
||||||
versionLog: "",
|
versionLog: "",
|
||||||
baseUrl: ""
|
baseUrl: "",
|
||||||
|
// forceUpdate: true, // 强制静默更新.
|
||||||
|
// updateMoment: true // 启动时直接请求更新.
|
||||||
},
|
},
|
||||||
ftpCfg: {
|
ftpCfg: {
|
||||||
host: "127.0.0.1",
|
host: "127.0.0.1",
|
||||||
@ -177,7 +230,10 @@
|
|||||||
port: "FTP端口号,默认21",
|
port: "FTP端口号,默认21",
|
||||||
user: "FTP登录验证帐号及密码",
|
user: "FTP登录验证帐号及密码",
|
||||||
rootPath: "FTP文件上传根目录"
|
rootPath: "FTP文件上传根目录"
|
||||||
}
|
},
|
||||||
|
states: [],
|
||||||
|
refreshTimer: 0,
|
||||||
|
uploadState: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
@ -192,8 +248,25 @@
|
|||||||
self.projectPath = arg;
|
self.projectPath = arg;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.refreshTimer = setInterval(this.checkThreads.bind(this), 200);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
if (this.refreshTimer) {
|
||||||
|
clearInterval(this.refreshTimer);
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
customColors(p) {
|
||||||
|
return `#${this.getR(0x90, 0x67, p)}${this.getR(0x93, 0xc2, p)}${this.getR(0x99, 0x3a, p)}`;
|
||||||
|
},
|
||||||
|
getR(from, to, percent) {
|
||||||
|
return Math.floor(from + (to - from) * percent / 100).toString(16)
|
||||||
|
},
|
||||||
|
|
||||||
|
onRestart(id) {
|
||||||
|
Editor.Ipc.sendToMain('update-manager:restartThread', id);
|
||||||
|
},
|
||||||
onSave() {
|
onSave() {
|
||||||
if (!this.versionCfg.baseUrl.endsWith('/') && this.versionCfg.baseUrl.length > 0) {
|
if (!this.versionCfg.baseUrl.endsWith('/') && this.versionCfg.baseUrl.length > 0) {
|
||||||
this.versionCfg.baseUrl += "/";
|
this.versionCfg.baseUrl += "/";
|
||||||
@ -207,7 +280,14 @@
|
|||||||
this.$message({message: "配置保存成功!", type: "success"});
|
this.$message({message: "配置保存成功!", type: "success"});
|
||||||
},
|
},
|
||||||
onUpload() {
|
onUpload() {
|
||||||
Editor.info("准备上传更新包");
|
if (this.uploadState) {
|
||||||
|
this.$message('上传正在进行中,请勿重复点击哦~');
|
||||||
|
logger.warn('上传正在进行中,请勿重复点击哦~');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.uploadState = true;
|
||||||
|
|
||||||
|
logger.info("准备上传更新包");
|
||||||
this.$message("准备上传更新包");
|
this.$message("准备上传更新包");
|
||||||
if (!this.versionCfg.baseUrl.endsWith('/') && this.versionCfg.baseUrl.length > 0) {
|
if (!this.versionCfg.baseUrl.endsWith('/') && this.versionCfg.baseUrl.length > 0) {
|
||||||
this.versionCfg.baseUrl += "/";
|
this.versionCfg.baseUrl += "/";
|
||||||
@ -226,7 +306,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.ftpCfg.onlyJson) {
|
if (this.ftpCfg.onlyJson) {
|
||||||
Editor.warn('当前仅上传JSON文件,请手动上传remote目录');
|
logger.warn('当前仅上传JSON文件,请手动上传remote目录');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 上传更新描述文件.
|
// 上传更新描述文件.
|
||||||
@ -241,6 +321,16 @@
|
|||||||
onStopUpload() {
|
onStopUpload() {
|
||||||
Editor.Ipc.sendToMain('update-manager:uploadStop');
|
Editor.Ipc.sendToMain('update-manager:uploadStop');
|
||||||
},
|
},
|
||||||
|
checkThreads() {
|
||||||
|
const self = this;
|
||||||
|
Editor.Ipc.sendToMain('update-manager:checkThreads', function (args) {
|
||||||
|
self.states = args;
|
||||||
|
});
|
||||||
|
// 检测是否空闲中.
|
||||||
|
Editor.Ipc.sendToMain('update-manager:queryThreadStates', function (args) {
|
||||||
|
self.uploadState = !args;
|
||||||
|
});
|
||||||
|
},
|
||||||
notifyMainJs(updateUrl, serverUrl) {
|
notifyMainJs(updateUrl, serverUrl) {
|
||||||
this.$message.info("notifyMainJs");
|
this.$message.info("notifyMainJs");
|
||||||
const filePath = path.join(this.projectPath, 'build/jsb-link/main.js');
|
const filePath = path.join(this.projectPath, 'build/jsb-link/main.js');
|
||||||
|
33
packages/update-manager/panel/main.css
Normal file
33
packages/update-manager/panel/main.css
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#app {
|
||||||
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: center;
|
||||||
|
color: #3646ea;
|
||||||
|
background-color: #fafcfc;
|
||||||
|
padding: 35px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix:before,
|
||||||
|
.clearfix:after {
|
||||||
|
display: table;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix:after {
|
||||||
|
clear: both
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-item {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
height: 600px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-scrolling: auto;
|
||||||
|
}
|
@ -11,62 +11,41 @@ window.beforeBoot = function () {
|
|||||||
window.boot();
|
window.boot();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
url += `?_t=${Math.random()}`;
|
|
||||||
cc.log("请求更新地址:", url);
|
|
||||||
|
|
||||||
get(url, function (err, asset) {
|
// 请求缓存信息,判断是否需要更新.
|
||||||
cc.log("请求更新信息:", url, err && err.toLocaleString(), JSON.stringify(asset));
|
let assetStr = window.localStorage.getItem('version_data');
|
||||||
if (err || !asset) {
|
if (!assetStr) {
|
||||||
window.boot();
|
window.boot();
|
||||||
return;
|
} else {
|
||||||
}
|
let asset = JSON.parse(assetStr);
|
||||||
window.mergeVersion(asset);
|
window.mergeVersion(asset);
|
||||||
window.boot();
|
window.boot();
|
||||||
cc.log("游戏已启动.");
|
}
|
||||||
|
// 游戏启动后再请求更新,避免影响启动速度.
|
||||||
|
url += `?_t=${Math.random()}`;
|
||||||
|
cc.log("请求更新地址:", url);
|
||||||
|
get(url, function (err, asset) {
|
||||||
|
if (err || !asset) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.localStorage.setItem('version_data', asset);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
window.mergeVersion = function (updateInfo) {
|
window.mergeVersion = function (updateInfo) {
|
||||||
const currentVer = cc.sys.localStorage.getItem("currentVer");
|
|
||||||
let isFirstRun = false;
|
|
||||||
let newVerFlag = false;
|
|
||||||
if (!currentVer) {
|
|
||||||
isFirstRun = true;
|
|
||||||
cc.log("当前为首次运行");
|
|
||||||
} else {
|
|
||||||
const oldVerInfo = JSON.parse(currentVer);
|
|
||||||
if (oldVerInfo && oldVerInfo.versionCode != updateInfo.versionCode) {
|
|
||||||
newVerFlag = true;
|
|
||||||
cc.log("发现新版本信息:", updateInfo.versionCode, oldVerInfo.versionCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const settings = window._CCSettings;
|
const settings = window._CCSettings;
|
||||||
if (updateInfo.server) {
|
const bundleVers = updateInfo.bundles;
|
||||||
settings.server = updateInfo.server;
|
|
||||||
cc.log("更新远程资源地址:", updateInfo.server);
|
|
||||||
}
|
|
||||||
const bundleVers = updateInfo.bundles
|
|
||||||
if (bundleVers) {
|
if (bundleVers) {
|
||||||
let changed = false;
|
|
||||||
for (let b in bundleVers) {
|
for (let b in bundleVers) {
|
||||||
if (bundleVers[b] != settings.bundleVers[b]) {
|
if (bundleVers[b] != settings.bundleVers[b]) {
|
||||||
// 配置中的bundleVer版本不一致,则添加到remote列表中去,以供远程加载.
|
// 配置中的bundleVer版本不一致,则添加到remote列表中去,以供远程加载.
|
||||||
if (settings.remoteBundles.indexOf(b) < 0) {
|
if (settings.remoteBundles.indexOf(b) < 0) {
|
||||||
settings.remoteBundles.push(b);
|
settings.remoteBundles.push(b);
|
||||||
}
|
}
|
||||||
changed = true;
|
|
||||||
cc.log("发现更新Bundle:", b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settings.bundleVers = bundleVers;
|
settings.bundleVers = bundleVers;
|
||||||
// 如果首次运行,但检测版本有差异,则标记有更新.
|
|
||||||
if (isFirstRun && changed) {
|
|
||||||
newVerFlag = true;
|
|
||||||
cc.log("标记为新版本.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cc.sys.localStorage.setItem('newVerFlag', newVerFlag ? 1 : 0);
|
return;
|
||||||
cc.sys.localStorage.setItem('firstRunFlag', isFirstRun ? 1 : 0);
|
|
||||||
cc.sys.localStorage.setItem('currentVer', JSON.stringify(updateInfo));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ajax 请求.
|
// ajax 请求.
|
||||||
@ -77,8 +56,8 @@ function get(url, cb) {
|
|||||||
ajax.onreadystatechange = function () {
|
ajax.onreadystatechange = function () {
|
||||||
if (ajax.readyState == 4) {
|
if (ajax.readyState == 4) {
|
||||||
if (ajax.status == 200) {
|
if (ajax.status == 200) {
|
||||||
var response = JSON.parse(ajax.responseText)
|
// var response = JSON.parse(ajax.responseText)
|
||||||
cb && cb(null, response);
|
cb && cb(null, ajax.responseText);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
cb && cb("request error!");
|
cb && cb("request error!");
|
||||||
@ -87,4 +66,3 @@ function get(url, cb) {
|
|||||||
}
|
}
|
||||||
ajax.send(null);
|
ajax.send(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user