mm_machine
Version:
这是超级美眉框架机制构建辅助模块,用于快速构建一个机制
560 lines (529 loc) • 12.2 kB
JavaScript
/**
* @fileOverview 机制构建帮助类函数
* @author <a href="http://qww.elins.cn">邱文武</a>
* @version 1.5
*/
const util = require('util');
const ph = require('path');
const Item = require('./item.js');
/**
* @class Index索引类
*/
class Index {
/**
* 构造函数
* @param {Object} scope 作用域
* @param {String} dir_base 模块目录
* @constructor
*/
constructor(scope, dir_base) {
// 作用域(同时作为检索的后缀名)
this.scope;
if (scope) {
this.scope = scope;
} else {
this.scope = $.val.scope + '';
}
// Index接口列表
this.list = [];
/**
* 机制类型
*/
this.type = "";
/**
* 排序项
*/
this.sort_key = "sort";
/**
* 模块目录
*/
this.dir_base = dir_base;
/**
* 模式
* 1.生产模式,改变文件不会重新加载
* 2.热更新模式,改变配置文件会重新加载配置,不重新加载脚本
* 3.热重载模式,改变配置文件都会加载配置和脚本
* 4.重载模式,执行完后重新加载脚本,避免变量污染
* 5.热更新+重载模式,改变配置文件重新加载配置和脚本,执行完后重新加载脚本
*/
this.mode = 1;
}
}
/**
* 清除接口缓存
*/
Index.prototype.clear = function() {
this.list = [];
};
/**
* 默认驱动
*/
Index.prototype.Drive = Item;
/**
* 加载项
* @param {String} dir 文件路径
* @param {Object} cg 配置参数
* @param {String} file 配置文件
*/
Index.prototype.load_item = async function(dir, cg, file) {
if (this.Drive) {
var drive = new this.Drive(dir, this.dir_base.fullname());
drive.mode = this.mode;
if (cg) {
await drive.exec('load_config', file, cg.name);
await drive.exec('set_config', cg);
} else {
await drive.exec('load_config', file);
}
this.list.push(drive);
return drive;
} else {
var json = file.loadJson();
if (!json) {
var fl = this.dir_base + "/config.tpl.json";
if (fl.hasFile()) {
fl.copyFile(file);
json = file.loadJson();
}
}
if (json) {
this.list.push(json);
}
return json;
}
};
/**
* 加载列表
* @param {Array} list 文件列表
*/
Index.prototype.load_list = async function(list) {
// 遍历文件路径
for (var i = 0; i < list.length; i++) {
var file = list[i];
await this.load_file(file, true);
}
};
/**
* 排序
*/
Index.prototype.sort = function() {
var _this = this;
this.list.sort(function(o1, o2) {
var p1 = o1.config[_this.sort_key];
var p2 = o2.config[_this.sort_key];
return p2 - p1;
});
};
/**
* 更新前
*/
Index.prototype.update_before = async function(dir) {
// console.log("更新前")
}
/**
* 更新后
*/
Index.prototype.update_after = async function(dir) {
// console.log("更新后")
}
/**
* 更新所有配置
* @param {String} path 检索路径
* @param {Boolean} accurate 精准路径,默认为false
*/
Index.prototype.update_config_all = async function(path, accurate) {
if (path) {
if (!ph.isAbsolute(path)) {
path = ph.join('app', path);
}
} else {
path = './app/';
}
var list_scope = [];
try {
if (!accurate) {
// 获取所有应用路径
var search_dir;
if (this.scope && this.scope !== $.val.scope) {
search_dir = this.type + '_' + this.scope;
} else {
search_dir = this.type;
}
list_scope = $.dir.getAll(path, search_dir);
} else {
list_scope = $.dir.getAll(path);
}
} catch (err) {
console.error("检索目录失败!", err);
}
for (var i = 0; i < list_scope.length; i++) {
var f = list_scope[i];
// 获取所有配置文件
var list_file = $.file.getAll(f, "*" + this.type + ".json");
await this.load_list(list_file);
}
};
/**
* 更新配置
* @param {Object} dir
*/
Index.prototype.update_config_have = async function(dir) {
var list = this.list;
for (var i = 0; i < list.length; i++) {
var o = list[i];
var file = o.filename;
if (file) {
var config = file.loadJson();
if (config) {
if (Array.isArray(config)) {
var lt = config;
for (var n = 0; n < lt.length; n++) {
var cg = lt[n];
if (cg.name == o.config.name) {
await o.exec('set_config', cg);
continue;
}
}
} else {
await o.exec('set_config', config);
}
}
}
}
}
/**
* 更新配置
* @param {Object} dir
*/
Index.prototype.update_config = async function(dir, accurate = false, clear = false) {
if (clear) {
this.clear();
await this.update_config_all(dir, accurate);
} else {
// 如果没有指定目录,则更新已有的配置文件
await this.update_config_have();
}
this.sort();
}
/**
* 更新JS
*/
Index.prototype.update_script = async function() {
var list = this.list;
for (var i = 0; i < list.length; i++) {
var o = list[i];
if (o.config.state === 1) {
await o.exec('load');
}
}
}
/**
* 更新
* @param {String} dir 检索的路径
* @param {Boolean} loadJS 是否加载JS
*/
Index.prototype.update_main = async function(dir, accurate = false, loadJS = true, clear = true) {
await this.update_config(dir, accurate, clear);
if (loadJS) {
await this.update_script();
}
}
/**
* 更新配置
* @param {String} dir 检索的路径
* @param {Boolean} loadJS 是否加载JS
*/
Index.prototype.update = async function(dir, accurate = false, loadJS = true, clear = true) {
await this.update_before(dir);
await this.update_main(dir, accurate, loadJS, clear);
await this.update_after(dir);
};
/**
* 查询配置项
* @param {String} name 名称
* @return {Object} 返回单项配置
*/
Index.prototype.get = function(name) {
var obj;
var lt = this.list;
var len = lt.length;
for (var i = 0; i < len; i++) {
var o = lt[i];
if (name === o.config.name) {
obj = o;
break;
}
}
return obj;
};
/**
* 查询配置项
* @param {String} name 名称
* @return {Object} 返回单项配置
*/
Index.prototype.set = function(cg) {
var bl = false;
var lt = this.list;
var len = lt.length;
for (var i = 0; i < len; i++) {
var o = lt[i];
if (cg.name === o.config.name) {
$.push(lt[i].config, cg);
bl = true;
break;
}
}
return bl;
};
/**
* 保存配置
* @param {String} name 保存的配置
*/
Index.prototype.save = function(name) {
var item = this.get(name);
if (item) {
item.save();
return true;
} else {
return false;
}
};
/**
* 添加
* @param {Object} obj 配置参数
* @return {String} 失败返回错误提示,成功返回null
*/
Index.prototype.add = async function(obj) {
var f = obj.filename;
if (!f) {
return "文件保存路径不能为空";
}
var name = obj.config.name;
var item = this.get(name);
if (item) {
return "配置已存在";
}
if (f.hasFile()) {
var jobj = f.loadJson(obj.dir);
if (jobj) {
if (jobj.constructor == Array) {
var has = false;
for (var i = 0; i < jobj.length; i++) {
var o = jobj[i];
if (o.name === name) {
has = true;
break;
}
}
if (has) {
return "配置文件已存在";
} else {
jobj.push(obj.config);
f.saveText(JSON.stringify(jobj, null, 4));
}
} else {
var list = [];
list.push(jobj);
list.push(obj.config);
f.saveText(JSON.stringify(list, null, 4));
}
} else {
f.saveText(JSON.stringify(obj.config, null, 4));
}
} else {
await this.load_item(f.dirname(), obj.config, f);
this.save(name);
}
return null;
};
/**
* 删除
* @param {String} name 保存的配置名
* @param {Boolean} remove 是否删除配置文件
* @return {String} 失败返回null,成功返回文件路径
*/
Index.prototype.del = function(name, remove) {
var lt = this.list;
var obj = null;
var len = lt.length;
for (var i = 0; i < len; i++) {
var o = lt[i];
if (name === o.config.name) {
obj = o;
// 删除成员
lt.splice(i, 1);
break;
}
}
return obj;
};
/**
* 加载模块
* @param {String} name 模块名称
* @return {String} 失败返回null,成功返回文件路径
*/
Index.prototype.load = async function(name) {
var o = this.get(name);
var file = null;
if (o) {
await o.exec('load');
file = o.filename;
}
return file;
}
/**
* 卸载模块
* @param {String} name 模块名称
* @param {Boolean} remove 是否删除配置文件
* @return {String} 失败返回null,成功返回文件路径
*/
Index.prototype.unload = async function(name, remove) {
var o = this.del(name, remove);
var file = null;
if (o) {
await o.exec('unload', remove);
file = o.filename;
}
return file;
}
/**
* 重载脚本和配置
* @param {String} file 文件名
* @return {String} 重载失败返回错误提示,重载成功返回null
*/
Index.prototype.reload = async function(name) {
var o = this.get(name);
if (o) {
await o.exec('reload');
return o.filename;
}
return '没有找到模块';
}
/**
* 通过文件加载配置
* @param {String} file 文件名
* @param {Boolean} create 不存在则进行创建
* @return {String} 加载失败返回错误提示,加载成功返回null
*/
Index.prototype.load_file = async function(file, create = false) {
var _this = this;
var dir = file.dirname();
// 载入文件
var obj = file.loadJson();
if (obj) {
if (obj.constructor == Array) {
for (var i = 0; i < obj.length; i++) {
var o = obj[i];
// 实例化一个驱动
await _this.load_item(dir, o, file);
}
} else {
return await _this.load_item(dir, null, file);
}
} else if (create) {
return await _this.load_item(dir, null, file);
} else {
return file + "文件不存在";
}
return null;
};
/**
* 调用函数
* @param {String} name 模块名
* @param {String} method 函数名
* @param {Object} params 参数集合
* @return {Object} 执行结果
*/
Index.prototype.run = async function(name, method, ...params) {
var result;
if (name) {
var o = await this.get(name);
if (o && o.config.state === 1) {
if (!o.complete) {
await o.exec('load');
}
var ret = o.exec(method, ...params);
if (util.types.isPromise(ret)) {
result = await ret;
} else {
result = ret;
}
if (this.mode >= 4) {
o.exec('reload');
}
}
} else if (name === null) {
var lt = this.list;
for (var i = 0; i < lt.length; i++) {
var o = lt[i];
if (o.config.state === 1) {
if (!o.complete) {
await o.exec('load');
}
var ret = o.exec(method, ...params);
if (util.types.isPromise(ret)) {
result = await ret;
} else {
result = ret;
}
if (this.mode >= 4) {
o.exec('reload');
}
if (result && o.config.end) {
break;
}
}
}
}
return result;
};
/**
* 执行方法
* @param {String} name 插件名称
* @param {String} method 方法名称
* @param {Object} option 配置参数
* @return {String} 执行结果
*/
Index.prototype.exec = async function(name, method, ...params) {
var result;
if (name) {
var o = await this.get(name);
if (o) {
if (!o.complete) {
await o.exec('load');
}
var ret = o.exec(method, ...params);
if (util.types.isPromise(ret)) {
result = await ret;
} else {
result = ret;
}
if (this.mode >= 4) {
await o.exec('reload');
}
}
} else if (name === null) {
var lt = this.list;
for (var i = 0; i < lt.length; i++) {
var o = lt[i];
if (!o.complete) {
await o.exec('load');
}
var ret = o.exec(method, ...params);
if (util.types.isPromise(ret)) {
result = await ret;
} else {
result = ret;
}
if (this.mode >= 4) {
await o.exec('reload');
}
}
}
return result;
};
/**
* @module 导出Index类
*/
exports.Index = Index;
exports.Item = Item;