app-lib-progress
Version:
app-lib-progress
282 lines (246 loc) • 9.35 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("app-lib-log"));
else if(typeof define === 'function' && define.amd)
define(["app-lib-log"], factory);
else {
var a = typeof exports === 'object' ? factory(require("app-lib-log")) : factory(root["app-lib-log"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(this, (__WEBPACK_EXTERNAL_MODULE_app_lib_log__) => {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/***/ ((module, exports, __webpack_require__) => {
/*************************************************************************************
*
* 支持已知进度和未知进度打印
*
**************************************************************************************/
const { log } = __webpack_require__(/*! app-lib-log */ "app-lib-log");
const MODULE_NAME = "app-lib-progress";
const defaultOption = {
stream: process.stderr, // 输出
total: -1, // 总进度数量 // 没有总数的时候 表示没有君度的显示
current: 0, // 当前进度
loopText: ["—", "\\", "|", "/"], // 未知进度的旋转文本
currentLoopTextIndex: 0, // 轮询显示位置
loopTime: 1000, // 动画切换时间
cChar: "=", // 进度完成的显示
ucChar: "-", // 未完成的显示
output: ":flag (:current)", // 输出内容格式化
startTime: 0, // 开始时间
clear: () => true, // 结束是否清空控控制台
success: () => true, // 每次完成回调 true 清空控制太 false 不清空 默认不清空
throttle: 10, // 防抖时间
cusField: [], // 自定义需要格式化的字段
data: null, // 每次动态显示的数据 按照对象的key进行output对应即可,
isComplete: false,
};
const type = any => Object.prototype.toString.call(any).split(' ')[1].split(']')[0].toLowerCase();
class Progress {
/**
* 初始化参数
*
* @param {oobject} option
*/
constructor(option) {
this.lastContent = ""; // 上一次打印内容
this.allContent = []; // 全部打印内容
this.option = { ...defaultOption, ...option }
}
/**
* 设置属性值
*
* @param {string} key 属性值
* @param {any} value 值
* @returns {object} 框架对象
*/
set(key, value) {
this.option[key] = value;
return this;
}
/**
* 获取属性
* @param {string} key 属性键
* @returns {any} 属性键对应的值
*/
get(key) {
return this.option[key];
}
/**
* 开始统计
*
* @param {num} length 长度 相对total
* @param {object} data 自定义数据
* @param {boolean} isForce 是否强制执行
* @returns 进度对象
*/
count(length, data, isForce) {
if (!isForce && this.option.isComplete) return;
let len = void 0 === length ? 1 : 1 * length;
if (isNaN(len)) {
len = 1;
log.mwn(MODULE_NAME, `length require number type`);
}
// 开始时间
if (0 == this.option.current) this.option.startTime = + new Date;
this.option.current += len;
this.option.data = data;
return this.output();
}
/**
* 格式化输出字段内容
* @returns {string} 格式化的内容
*/
formatStr() {
let { stream, total, current, startTime, loopText, currentLoopTextIndex,
loopTime, cChar, ucChar, output, data, cusField } = this.option;
// 消耗时间
let useTime = (((+ new Date) - startTime) / 1000).toFixed(1); // 秒
let percent = 0;
let flag = loopText[currentLoopTextIndex % loopText.length];
if (total == -1) { // 没有总数 只是数量
} else { // 进度
// 进度百分比
var ratio = this.curr / this.total;
ratio = Math.min(Math.max(ratio, 0), 1);
percent = Math.floor(ratio * 100);
}
let str = output
.replace(":total", total) // 总数
.replace(":current", current) // 当前数量
.replace(":flag", flag) // 无总数的旋转标识
.replace(":useTime", useTime) // 消耗时间
.replace(":percent", percent) // 百分比
// TODO 后续需要进度在进行添加
// 格式化用户自定义数据
if (cusField.length) {
cusField.forEach(diyFiled => {
let value = data?.[diyFiled];
str = str.replace(`:${diyFiled}`, void 0 == value ? '-' : value) // 总数
});
}
return str;
}
// 设置完成
complate(length = 0, data = null) {
this.option.isComplete = true;
this.count(length, data || this.option.data, true);
}
// 当前是否处于完成状态
isComplete() {
if (this.option.isComplete) return true;
if (this.option.total == -1) return this.option.isComplete;
return this.option.total <= this.option.current;
}
/**
* 输出内容
*
*/
output() {
if (!this.option.stream.isTTY) return;
this.option.currentLoopTextIndex += 1;
let outputString = this.formatStr();
this._log(outputString);
if (this.isComplete()) {
if (this.option?.success()) {
this.over();
}
}
}
/**
* 结束时是否清空输出
* @returns {object} 进度对象
*/
over() {
if (this.option?.clear) {
if (this.option.clear(log)) {
this.option.stream?.clearLine();
this.option.stream?.cursorTo(0);
}
}
// this.option.stream?.write('\n');
return this;
}
// 输出到控制太
_log(str) {
if (this.lastContent === str) return;
let stream = this.option.stream;
stream.cursorTo(0);
stream.write(str);
stream.clearLine(1);
this.lastContent = str;
this.allContent.push(str) // 记录用于获取全部内容
}
/**
* 向上插入信息打印
* @param {string/function} message function 标识回调函数外部进行打印
*/
log(fn, ...message) {
let stream = this.option.stream;
// clear the current line
stream.clearLine();
// move the cursor to the start of the line
stream.cursorTo(0);
// write the message text
if (type(fn) == "function") {
fn.apply(log,message);
} else {
log.i(...[fn,...message]);
stream.write('\n');
}
stream.write(this.lastContent);
}
}
exports = module.exports = Progress;
/***/ }),
/***/ "app-lib-log":
/*!******************************!*\
!*** external "app-lib-log" ***!
\******************************/
/***/ ((module) => {
"use strict";
module.exports = __WEBPACK_EXTERNAL_MODULE_app_lib_log__;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module is referenced by other modules so it can't be inlined
/******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
/******/
/******/ return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=index.js.map