UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

1,259 lines (1,186 loc) 33.6 kB
const Item = require('mm_machine').Drive; const Excel = require('mm_excel'); /** * Sql操作驱动类 * @augments {Item} * @class */ class Drive extends Item { static config = { 'main': '', // 表名 {0} 代表可前端传参自定义查询的表 'table': '{0}', // 主键 用于水平连表查询时 例如:id 'key': '', // 排序 {0} 代表可前台传参自定义排序规则 格式: `name` asc, `id` desc 'orderby': '{0}', // 默认排序 `id` desc 'orderby_default': '', // 显示的字段 {0} 代表可前台传参自定义查询的字段, 例如: `id`,`username`,`name`,`email` 'field': '{0}', // 默认显示字段 例如: `id`,`username`,`name` 'field_default': '*', // 隐藏字段 有些字段即使前端请求也不能返回,这是通过隐藏字段将其过滤掉, 例如:password *表示包含匹配 'field_hide': ['*password*', '*token*', 'salt'], // 分页大小,默认一页显示条数 'page_size': 30, /* 过滤参数 */ 'filter': { /** * 表名 */ 'table': 'table', /** * 查询的页码 */ 'page': 'page', /** * 查询每页条数 */ 'size': 'size', /** * 操作方式: 传入参数method=add, 支持参数 add增、del删、set改、get查,为空则为get */ 'method': 'method', /** * 排序 */ 'orderby': 'orderby', /** * 查询显示的字段 */ 'field': 'field', /** * 统计结果: 统计符合条件的结果数,只有当page等于1或0时才会统计 */ 'count_ret': 'count_ret' }, // 分隔符 用于查询时的多条件处理 'separator': '|', // 支持的方法 add增、del删、set改、get查, 只填get表示只支持查询 // import export del_repeat", 'method': 'add del set get get_obj import export del_repeat avg sum count update', // sql查询语句 'query': {}, // 默认查询, 当查询条件中不包含该项时,默认添加该项。 例如: { "age": "`age` < 20" } , 当查询参含有age,不调用该项,不存在时,sql会增加该项 'query_default': {}, // sql更改语句 'update': {}, // 默认添加条件,当不包含该项时,默认添加该项。 例如: { "age": "`age` += 1" } , 当查询参含有age,不调用该项,不存在时,sql会增加该项 'body_default': {}, // 参数 [] 'params': null, // 格式 'format': [ /* { // 表名,当选择转换方式 表转换时需填写 "table": "mm_web_region", // 查询条件,用于加速转换 "query": { "group": "市" }, // 表标题名 "title": "所属省份", // 转换ID "id": "province_id", // 转换主键 "key": "province", // 取名 "name": "name", // 列表 "list": [{ "province_id": 1, "name": "广东省" }, { "province_id": 2, "name": "广西省" }, { "province_id": 3, "name": "湖南省" } ] }, { "title": "是否可见", "key": "show", "list": ["否", "是"] } */ ], /* 去重 */ 'del_repeat': { // 判断重复的字段,例如字段名 number 'groupBy': '', // 排序方式 例如: `diJia` ASC 'orderBy': '' }, /* 逻辑符 */ 'logic': {}, // 输出sql语句 'log': false }; /** * 构造函数 * @param {object} config 配置参数 * @param {object} parent 父对象 * @class */ constructor(config, parent) { super({ ...Drive.config, ...config }, parent); // 默认启用热更新 this.mode = 3; } } /** * 获取模板目录 * @returns {string} 模板目录 */ Drive.prototype._getTplDir = function () { return __dirname; }; /** * 预设 */ Drive.prototype._preset = function () { // 保存文件目录 this.save_dir = './static/file/'; // 读取文件目录 this.url_path = '/file/'; /* 通用项 */ this.params = null; }; /** * 执行前, 可用于过滤参数 * @param {object} params 参数对象 (object) 包含query和body 如{ query, body } * @param {object} db 数据库管理器 * @returns {object} 过滤后的参数 */ Drive.prototype.before = async function (params, db) { return params; }; /** * 验证, 用于判断是否执行 * @param {object} params 参数对象 (object) 包含query和body * @param {object} db 数据管理器 * @returns {boolean} 验证通过返回true, 失败返回false */ Drive.prototype.check = async function (params, db) { return true; }; /** * 执行后, 可用于附加执行 * @param {object} params 参数对象 (object) 包含query和body * @param {object} db 数据管理器 * @returns {object} 最终执行结果 */ Drive.prototype.after = async function (params, db) { return db.ret; }; /** * 更新缓存 * @param {string} table 表名 * @param {object} sql 缓存sql语句 */ Drive.prototype.updateCache = async function (table, sql) { }; /** * @ 执行修改 * @param {object} query 查询url参数 * @param {object} body 修改时置入body的参数 * @param {object} db 数据库管理器 * @returns {object} 返回执行结果 */ Drive.prototype.run = async function (query, body, db) { var params = { query, body }; params = await this.before(params, db); if (this.check(params, db)) { var ret = await this.main(params, db); if (!ret.error) { db.ret = ret; return await this.after(params, db); } else { return ret; } } return null; }; /** * SQL操作准备 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回准备参数 */ Drive.prototype.ready = function (db, query, body) { var cg = this.config; var qy = { ...query }; $.push(db.config.filter, cg.filter, true); db.filter(qy); return { cg, qy }; }; /** * 转为查询条件字符串 * @param {object} db 数据库管理器 * @param {object} query 查寻条件 * @param {object} method 方法 * @returns {string} 返回查询条件 */ Drive.prototype.toWhere = function (db, query, method) { var { cg, qy: originalQy } = this.ready(db, query, {}); // 创建 qy 对象的副本,避免修改原始参数 var qy = { ...originalQy }; this._setDbConfig(db, cg, query); qy = this._setQueryField(db, query, cg, method, qy); qy = this._setOrderBy(db, query, cg, qy); return this._buildQueryString(db, qy, cg); }; /** * 设置数据库配置 * @param {object} db 数据库管理器 * @param {object} cg 配置 * @param {object} query 查询条件 * @private */ Drive.prototype._setDbConfig = function (db, cg, query) { db.config.separator = cg.separator; if (!query.size && cg.page_size) { db.size = cg.page_size + 0; } if (db.size > 0 && db.page === 0) { db.page = 1; } }; /** * 设置查询字段 * @param {object} db 数据库管理器 * @param {object} query 查询条件 * @param {object} cg 配置 * @param {object} method 方法 * @param {object} qy 查询条件对象 * @returns {object} 更新后的查询条件对象 * @private */ Drive.prototype._setQueryField = function (db, query, cg, method, qy) { var f = db.config.filter; var field = query[f.field]; if (cg.field.has('*{0}*')) { if (field) { db.field = cg.field.replace('{0}', field); } else if (method === 'get_obj' && cg.field_obj) { db.field = cg.field_obj + ''; } else if (cg.field_default) { db.field = cg.field_default + ''; } } else { db.field = cg.field + ''; if (field) { return { ...qy, [f.field]: field }; } } return qy; }; /** * 设置排序方式 * @param {object} db 数据库管理器 * @param {object} query 查询条件 * @param {object} cg 配置 * @param {object} qy 查询条件对象 * @returns {object} 更新后的查询条件对象 * @private */ Drive.prototype._setOrderBy = function (db, query, cg, qy) { var f = db.config.filter; var orderby = query[f.orderby]; if (cg.orderby.has('*{0}*')) { if (orderby) { db.orderby = cg.orderby.replace('{0}', orderby); } else if (cg.orderby_default) { db.orderby = cg.orderby_default + ''; } } else { db.orderby = cg.orderby + ''; if (orderby) { return { ...qy, [f.orderby]: orderby }; } } return qy; }; /** * 构建查询字符串 * @param {object} db 数据库管理器 * @param {object} qy 查询条件对象 * @param {object} cg 配置 * @returns {string} 查询字符串 * @private */ Drive.prototype._buildQueryString = function (db, qy, cg) { var query_str = db.tplQuery(qy, cg.query); var qt = cg.query_default; if (Object.keys(qt).length > 0) { var id = $.dict.user_id; var id_key = '{' + id + '}'; var user_id = '0'; var user = db.user; if (user && user[id]) { user_id = user[id]; } for (var k in qt) { if (!qy[k]) { query_str += ' && ' + qt[k].replaceAll(id_key, user_id); } } if (query_str.startsWith(' && ')) { query_str = query_str.replace(' && ', ''); } } return query_str; }; /** * 查询(主要) * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} method 方法 * @returns {object} 返回查询结果 */ Drive.prototype.getMain = async function (db, query, method) { var ret; if (this.config.field.has('*{0}*')) { var field = query[db.config.filter.field]; if (field && this.config.field_hide.getMatch(field)) { return $.ret.error(70003, '不合法的查询参数'); } } var query_str = this.toWhere(db, query, method); // 查询 if (db.count_ret === 'true') { ret = $.ret.body(await db.getCountSql(query_str, db.orderby, db.field)); } else { ret = $.ret.list(await db.getSql(query_str, db.orderby, db.field)); } return ret; }; /** * 查询 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回查询结果 */ Drive.prototype.get = async function (db, query, body) { return await this.getMain(db, query); }; /** * 查询单条数据 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回查询结果 */ Drive.prototype.getObj = async function (db, query, body) { var qy = { ...query }; qy.page = 1; qy.size = 1; var ret = await this.getMain(db, qy, 'get_obj'); if (ret.result) { var list = ret.result.list; if (list.length > 0) { return $.ret.obj(list[0]); } else { return $.ret.obj(null); } } return ret; }; /** * 修改(主要) * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回修改结果 */ Drive.prototype.setMain = async function (db, query, body) { var ret; var { cg, qy } = this.ready(db, query, body); var key = cg.key; if (body[key]) { qy[key] = body[key]; } var query_str = db.tplQuery(qy, cg.query); var qt = cg.query_default; if (Object.keys(qt).length > 0) { var id = $.dict.user_id; var id_key = '{' + id + '}'; var user_id = '0'; var user = db.user; if (user && user[id]) { user_id = user[id]; } for (var k in qt) { if (!qy[k]) { query_str += ' && ' + qt[k].replace(id_key, user_id); } } if (query_str.startsWith(' && ')) { query_str = query_str.replace(' && ', ''); } } var n = await db.setSql(query_str, db.tplBody(body, cg.update)); if (n < 1) { ret = $.ret.error(500, '修改失败!\n' + db.error.message); } else { ret = $.ret.bl(true, '修改成功!'); } return ret; }; /** * 修改 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回查询结果 */ Drive.prototype.set = async function (db, query, body) { return await this.setMain(db, query, body); }; /** * 添加(主要) * @param {object} db 数据库操作类 * @param {object} body 添加项 * @returns {object} 返回查询结果 */ Drive.prototype.addMain = async function (db, body) { var ret; var cg = this.config; if (Object.keys(body).length > 0) { var bt = cg.body_default; if (Object.keys(bt).length > 0) { var id = $.dict.user_id; var id_key = '{' + id + '}'; var user_id = '0'; var user = db.user; if (user && user[id]) { user_id = user[id]; } for (var k in bt) { if (!body[k]) { var str = bt[k].replace(id_key, user_id); var key = str.left('=').trim('`'); body[key] = str.right('=').trim("'"); } } } var n = await db.add(body); if (n < 1) { ret = $.ret.error(500, '添加失败!\n' + db.error.message); } else { ret = $.ret.bl(true, '添加成功!'); } } else { ret = $.ret.error(30001, '参数不能为空'); } if (cg.log) { this.log('debug', '添加SQL语句', db.sql); } return ret; }; /** * 添加 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回添加结果 */ Drive.prototype.add = async function (db, query, body) { return await this.addMain(db, body); }; /** * 删除(主要) * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @returns {object} 返回查询结果 */ Drive.prototype.delMain = async function (db, query) { var ret; var { cg, qy } = this.ready(db, query, {}); var query_str = db.tplQuery(qy, cg.query); var bl = await db.delSql(query_str); if (bl < 1) { ret = $.ret.error(500, '删除失败!\n' + db.error.message); } else { ret = $.ret.bl(true, '删除成功!'); } if (cg.log) { this.log('debug', '删除SQL语句', db.sql); } return ret; }; /** * 删除 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回删除结果 */ Drive.prototype.del = async function (db, query, body = {}) { return await this.delMain(db, { ...query, ...body }); }; /** * 添加或修改(主要) * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回修改结果 */ Drive.prototype.addorsetMain = async function (db, query, body) { var ret; var { cg, qy } = this.ready(db, query, body); if (Object.keys(body).length > 0 && Object.keys(qy).length > 0) { var n = await db.addOrSet(qy, body); if (n < 1) { ret = $.ret.error(500, '操作失败!\n' + db.error.message); } else { ret = $.ret.bl(true, '操作成功!'); } } else { ret = $.ret.error(30001, '参数不能为空'); } if (cg.log) { this.log('debug', '添加或修改SQL语句', db.sql); } return ret; }; /** * 添加或修改 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回查询结果 */ Drive.prototype.addOrSet = async function (db, query, body) { return await this.addOrSetMain(db, query, body); }; /** * 获取数据类型 * @param {string} data_type 数据类型 * @returns {string} 返回数据类型 */ Drive.prototype.getType = function (data_type) { if (data_type.indexOf('int') !== -1) { return 'number'; } else { return 'string'; } }; /** * 获取数据 * @param {object} db 数据库操作类 * @param {string} field 要获取的字段 * @returns {Array} 返回参数信息列表 */ Drive.prototype.getParam = async function (db, field) { var cg = this.config; if (cg.params) { return cg.params; } if (this.params) { return this.params; } var lt = await this._getFieldsFromCache(cg); if (!lt.length) { lt = await this._getFieldsFromDb(db, cg); } return this._filterFields(lt, field, cg); }; /** * 从缓存获取字段列表 * @param {object} cg 配置 * @returns {Array} 字段列表 * @private */ Drive.prototype._getFieldsFromCache = function (cg) { var lt = []; if ($.pool.db) { var pool = $.pool.db['sys']; if (pool) { var dt = pool.get(cg.table); if (dt && dt.config) { var list = dt.config.fields; for (var i = 0; i < list.length; i++) { var name = list[i].replace(/`/g, ''); lt.push({ name, title: name }); } } } } return lt; }; /** * 从数据库获取字段列表 * @param {object} db 数据库操作类 * @param {object} cg 配置 * @returns {Array} 字段列表 * @private */ Drive.prototype._getFieldsFromDb = async function (db, cg) { var lt = []; db.table = cg.table; var list = await db.fields(); for (var i = 0; i < list.length; i++) { var o = list[i]; var name = o.name; var note = o.note ? o.note.replace(':', ':') : name; lt.push({ name, title: note.left(':', true), type: this.getType(o.type) }); } return lt; }; /** * 过滤字段 * @param {Array} lt 字段列表 * @param {string} field 字段筛选 * @param {object} cg 配置 * @returns {Array} 过滤后的字段列表 * @private */ Drive.prototype._filterFields = function (lt, field, cg) { var fields = field || cg.field_default; if (fields && fields !== '*') { var arr = fields.replace(/`/g, '').split(','); return arr.map(name => lt.getObj({ name })).filter(obj => obj); } return lt; }; /** * 获取导入导出格式 * @param {object} db 数据库操作类 * @returns {Array} 格式列表 */ Drive.prototype.getFormat = async function (db) { var dbs = { ...db }; dbs.size = 0; var fmt = this.config.format; for (var i = 0; i < fmt.length; i++) { var o = fmt[i]; if (o.table) { if (!o.list || o.list.length == 0) { dbs.table = o.table; if (!o.id) { o.id = o.key; } o.list = await dbs.getSql(o.where, null, o.id + ',' + o.name); if (o.id !== o.key) { for (var j = 0; j < o.list.length; j++) { var m = o.list[j]; m[o.key] = m[o.name]; } } } } } return fmt; }; /** * 导入数据(主要) * @param {object} db 数据库操作类 * @param {string} filename 文件名 * @returns {object} 返回导入结果 */ Drive.prototype.importMain = async function (db, filename) { var params = await this.getParam(db); var format = await this.getFormat(db); var file = this._processFilePath(filename); if (!file.hasFile()) { return $.ret.error(30001, file + '文件不存在!'); } var jarr = await this._loadImport(file, params, format); if (!jarr || !jarr.length) { return $.ret.error(10000, '要导入的数据不能为空!'); } var result = await this._importToDb(db, jarr); return this._buildImport(result); }; /** * 处理文件路径 * @param {string} filename 文件名 * @returns {string} 处理后的文件路径 * @private */ Drive.prototype._processFilePath = function (filename) { var file = filename; if (file.indexOf($.run_path) !== 0) { file = file.replace(this.url_path, this.save_dir); var path = this._getPath(); file = file.fullname(path); } return file; }; /** * 加载导入数据 * @param {string} file 文件路径 * @param {Array} params 参数列表 * @param {Array} format 格式列表 * @returns {Array} 数据数组 * @private */ Drive.prototype._loadImport = async function (file, params, format) { if (file.ends('.json')) { return file.loadJson(); } else if (file.ends('.xml')) { return file.loadXml(); } else { var excel = new Excel({ file, params, format }); try { return await excel.load(); } catch (e) { this.log('error', '导入文件', e); } finally { excel.clear(); excel = null; } } return []; }; /** * 导入数据到数据库 * @param {object} db 数据库操作类 * @param {Array} jarr 数据数组 * @returns {object} 导入结果 * @private */ Drive.prototype._importToDb = async function (db, jarr) { var list = []; var errors = []; var list_error = []; db.table = db.table || this.config.table; var key = this.config.key; if (jarr[0][key]) { for (var i = 0; i < jarr.length; i++) { var o = jarr[i]; var qy = {}; qy[key] = o[key]; var n = await db.addOrSet(qy, o); if (n < 1) { errors.push(db.error); list_error.push(o); } else { list.push(o); } } } else { for (var i = 0; i < jarr.length; i++) { var o = jarr[i]; var n = await db.add(o); if (n < 1) { errors.push(db.error); list_error.push(o); } else { list.push(o); } } } return { list, errors, list_error, total: jarr.length }; }; /** * 构建导入结果 * @param {object} result 导入结果数据 * @returns {object} 返回结果对象 * @private */ Drive.prototype._buildImport = function (result) { var bl = result.list.length === result.total; var body = $.ret.bl(bl, bl ? '导入成功!' : '导入失败!'); body.result.list = result.list; if (result.errors.length) { body.result.list_error = result.list_error; body.result.errors = result.errors; } return body; }; /** * 导入数据 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 导入设置 * @returns {object} 返回执行结果 */ Drive.prototype.import = async function (db, query, body) { var params = { ...query, ...body }; if (!params.file) { return $.ret.error(60000, '文件名(file)参数不能为空'); } return await this.importMain(db, params.file); }; /** * 导出数据(主要) * @param {object} db 数据库操作类 * @param {object} query 查询参数 * @param {object} body 正文参数(导出设置) * @property {string} body.fields 需要导出的字段 例如: `username`,`gm`,`vip` * @property {string} body.file 文件名 例如: 用户名.xlsx 、用户信息.csv 、用户账户.xls * @property {string} body.path 文件路径 例如: /static/download, 可不填写 * @returns {object} 返回执行结果 */ Drive.prototype.exportMain = async function (db, query, body) { var by = await this.getMain(db, query); if (db.error) { return $.ret.error(10000, db.error.message); } var config = this._prepareExportConfig(query, body); var params = await this.getParam(db, config.fields); var format = await this.getFormat(db); var file = await this._saveExportFile(config.file, params, format, by.result.list); return this._buildExport(file, config.name); }; /** * 准备导出配置 * @param {object} query 查询参数 * @param {object} body 正文参数 * @returns {object} 导出配置 * @private */ Drive.prototype._prepareExportConfig = function (query, body) { var path = body.path; var file = body.file; var fields = body.fields; var table = $.dict.table || this.config.table; if (!path) { path = this._getPath(); } if (!file) { var date = new Date(); file = this.save_dir + table + '_' + date.stamp() + '.xlsx'; } if (!fields) { fields = query.field || (this.config.field_default !== '*' ? this.config.field_default : ''); } return { path, file, fields, name: file.split('/').pop() }; }; /** * 获取路径 * @returns {string} 导出路径 * @private */ Drive.prototype._getPath = function () { return $.config.get('user_path') || $.config.get('static_path') || './static/'; }; /** * 保存导出文件 * @param {string} file 文件路径 * @param {Array} params 参数列表 * @param {Array} format 格式列表 * @param {Array} list 数据列表 * @returns {string} 保存后的文件路径 * @private */ Drive.prototype._saveExportFile = async function (file, params, format, list) { var export_path = this._getPath(); var save_file = file.fullname(export_path); save_file.addDir(); var excel = new Excel({ file: save_file, params, format }); try { return await excel.save(list); } catch (e) { this.log('error', '导出保存文件失败!', e); } finally { excel.clear(); excel = null; } return ''; }; /** * 构建导出结果 * @param {string} file 文件路径 * @param {string} name 文件名 * @returns {object} 导出结果 * @private */ Drive.prototype._buildExport = function (file, name) { var body = $.ret.bl(!!file, file ? '导出成功!' : '导出失败!'); body.result.file = file; body.result.url = this.url_path + name; return body; }; /** * 导出数据 * @param {object} db 数据库操作类 * @param {object} query 查询条件 * @param {object} body 修改项 * @returns {object} 返回执行结果 */ Drive.prototype.export = async function (db, query, body) { return await this.exportMain(db, query, body); }; /** * 删除重复项(主要) * @param {object} db 数据库管理器 * @param {object} params 查询参数 * @returns {object} 返回执行结果 */ Drive.prototype.delRepeatMain = async function (db, params) { var pm = { ...params }; var msg = ''; var cg = this.config.del_repeat; var order_by = pm.orderby || cg.orderBy; delete pm.orderby; var group_by = pm.groupby || cg.groupBy; delete pm.groupby; var f = db.config.filter; // 设置查询字段 var field = pm[f.field] || group_by; delete pm[f.field]; db.field = field; var sql = db.toGetSql(pm).replace(' * ', ' `' + field + '`, count(*) as len '); sql += ` GROUP BY ${group_by}`; sql = 'SELECT * FROM (' + sql + ') a WHERE len > 1'; var list = await db.run(sql); if (list.length) { db.page = 1; db.size = 1; var key = this.config.key; for (var i = 0; i < list.length; i++) { var o = list[i]; var len = o.len - 1; delete o.len; for (var n = 0; n < len; n++) { var obj = await db.getObj(o, order_by, key); if (obj) { await db.del(obj); } } } } else { msg = '没有重复项。'; } return $.ret.bl(!msg, msg ? '去重失败!原因:' + msg : '去重成功!'); }; /** * 删除重复项 * @param {object} db 数据库管理器 * @param {object} query 查询条件 * @param {object} body 正文参数 * @returns {object} 返回执行结果 */ Drive.prototype.delRepeat = async function (db, query, body) { var pm = { ...query, ...body }; return await this.delRepeatMain(db, pm); }; /** * 执行模板操作 * @param {object} params 参数对象 (object) 包含query和body * @param {object} db 数据管理器 * @returns {object} 返回执行结果 */ Drive.prototype.main = async function (params, db) { var { query, body } = params; var cg = this.config; var method = query.method; if (!method) { method = 'get'; } if (!cg.method.has('*' + method + '*')) { return $.ret.error(50001, '不支持的操作方式'); } method = this._getMethodName(method); var qy = { ...query }; delete qy.method; if (this[method]) { db.method = method; // 过滤查询参数 var f = cg.filter; var table = query[f.table]; // 设置操作的数据表 if (cg.table.has('*{0}*')) { if (table) { db.table = cg.table.replace('{0}', table); } else { return $.ret.error(30001, '表名不能为空'); } } else { db.table = cg.table + ''; } return await this[method](db, qy, { ...body }); } else { return $.ret.error(50001, '不支持的操作方式'); } }; /** * 获取方法名 * @param {string} method 方法名 * @returns {string} 方法名 * @private */ Drive.prototype._getMethodName = function (method) { if (!method) { return ''; } if (method.indexOf('_') == -1) { return method; } // 将小写蛇形改为小驼峰 let arr = method.split('_'); let new_name = arr[0].toLowerCase(); for (let i = 1; i < arr.length; i++) { let name = arr[i]; new_name += name.charAt(0).toUpperCase() + name.substring(1); } return new_name; }; /** * 总计 * @param {object} db 数据库管理器 * @param {object} param 查询条件 * @returns {object} 返回执行结果 */ Drive.prototype.sumMain = async function (db, param) { var pm = { ...param }; var ret; var orderby = pm.orderby || ''; delete pm.orderby; var groupby = pm.groupby; delete pm.groupby; var f = db.config.filter; var field = pm[f.field]; delete pm[f.field]; var query_str = this.toWhere(db, pm, 'get_list'); if (!groupby || !field) { ret = $.ret.error(30000, '参数groupby、field是必须的,且值不能为空!'); } else { var list = await db.groupSumSql(query_str, groupby, field, orderby); if (!list.length && db.error) { ret = $.ret.body(db.error); } else { ret = $.ret.list(list); } } return ret; }; /** * 总计 * @param {object} db 数据库管理器 * @param {object} query 查询条件 * @param {object} body 正文参数 * @returns {object} 返回执行结果 */ Drive.prototype.sum = async function (db, query, body) { var pm = { ...query, ...body }; return await this.sumMain(db, pm); }; /** * 平均值 * @param {object} db 数据库管理器 * @param {object} param 查询条件 * @returns {object} 返回执行结果 */ Drive.prototype.avgMain = async function (db, param) { var pm = { ...param }; var ret; var orderby = pm.orderby || ''; delete pm.orderby; var groupby = pm.groupby; delete pm.groupby; var f = db.config.filter; var field = pm[f.field]; delete pm[f.field]; var query_str = this.toWhere(db, pm, 'get_list'); if (!groupby || !field) { ret = $.ret.error(30000, '参数groupby、field是必须的,且值不能为空!'); } else { var list = await db.groupAvgSql(query_str, groupby, field, orderby); if (!list.length && db.error) { ret = $.ret.body(db.error); } else { ret = $.ret.list(list); } } return ret; }; /** * 平均值 * @param {object} db 数据库管理器 * @param {object} query 查询条件 * @param {object} body 正文参数 * @returns {object} 返回执行结果 */ Drive.prototype.avg = async function (db, query, body) { var pm = { ...query, ...body }; return await this.avgMain(db, pm); }; /** * 总计 * @param {object} db 数据库管理器 * @param {object} param 查询条件 * @returns {object} 返回执行结果 */ Drive.prototype.countMain = async function (db, param) { var pm = { ...param }; var ret; var orderby = pm.orderby || ''; delete pm.orderby; var groupby = pm.groupby; delete pm.groupby; var f = db.config.filter; var field = pm[f.field]; delete pm[f.field]; var query_str = this.toWhere(db, pm, 'get_list'); if (!groupby || !field) { ret = $.ret.error(30000, '参数groupby、field是必须的,且值不能为空!'); } else { var list = await db.groupCountSql(query_str, groupby, field, orderby); if (!list.length && db.error) { ret = $.ret.body(db.error); } else { ret = $.ret.list(list); } } return ret; }; /** * 总计 * @param {object} db 数据库管理器 * @param {object} query 查询条件 * @param {object} body 正文参数 * @returns {object} 返回执行结果 */ Drive.prototype.count = async function (db, query, body) { var pm = { ...query, ...body }; return await this.countMain(db, pm); }; /** * 获取模型 * @param {string} type 模型类型 * @returns {object} 返回获取到的模型 */ Drive.prototype.getModel = function (type) { let model = { ...this.config }; let dir = this.getDir(); let l = $.slash; let app_name = dir.between('app' + l, l); let plugin_name = dir.between('plugin' + l, l); let name = dir.basename(); model.app = app_name; model.plugin = plugin_name; model.name = model.name || app_name + '_' + name; return model; }; module.exports = Drive;