UNPKG

@lct/common

Version:
166 lines (154 loc) 6.02 kB
import BaseModel from '../model/base'; /** * TS 反射的一些封装 */ class modelHelper { /** * 获取对象的属性名称集合 * 如果继承自 BaseModel ,则到BaseModel后不会再往上查找 * * @param target {class} 需要获取属性的实例 * @returns {Array<string>} 属性名称数组 */ static getPropertyNames(target: any): Array<string> { let proto = Object.getPrototypeOf(target); let names = Object.getOwnPropertyNames(target); while(proto) { //如果到了基类object,则不再查找 if(proto.constructor.name === 'Object') break; let tmp = Object.getOwnPropertyNames(proto); //过滤掉不可读和函数属性 tmp.forEach(k => { if(k === '__proto__') return; let desc = Object.getOwnPropertyDescriptor(proto, k); let hasGetter = desc && typeof desc.get === 'function'; if(hasGetter && names.indexOf(k) === -1) { names.push(k); } }); proto = proto.__proto__; } return names; } /** * 把原始数据组转为当前model数组 * @param {Array} data 原始数据数组 * @static * @returns {Array<Model>} */ static toArray<T>(data: Array<object|string>, type: { new(data: any): T ;}): Array<T> { if(!data || !data.length) return []; return Array.from(data, (d) => { return new type(d); }); } /** * 获取model类型中属性对应的表字段名 * 根据属性名得到对应的表字段名,这里规定死为属性名前加一个F为字段名 * 并把大写字母转为_小写 * 如果传入了_或$开头的名称,则返回空 * @param name model中的属性名 * @param type model的class类 */ static getFieldName<T extends BaseModel>(name: string, type: { new(): T, _fieldMap: object;}|BaseModel): string { if(!type) return name; if(name.startsWith('_') || name.startsWith('$')) return ""; //映射是 field: property //如果从映射中找到,则直接返回即可 if(type && type._fieldMap && type._fieldMap[name]) return type._fieldMap[name]; let field = name; //当不是以F开头时,认为属性名,则需要转为字段名 if(!/^F/.test(name)) { //把类似于 firstName 这种命名转为 first_name field = name.replace(/([A-Z])/g, p => '_' + p.toLowerCase()); field = 'F' + field; type && type._fieldMap && (type._fieldMap[name] = field); //缓存映射 } return field; } /** * 把属性集合转为字段集合 * @param columns 属性的集合 */ static convertFields(columns: Array<string>, type: { new(): BaseModel, _fieldMap: object;}|BaseModel): Array<string> { if(!type) return columns; let ret = new Array<string>(); for(let i=0;i<columns.length;i++) { let c = this.getFieldName(columns[i], type) || columns[i]; ret.push(c); } return ret; } /** * 获取model中的主健和其值 * @param target model实例 */ static getPrimaryKeysWhere(target: BaseModel): object { let obj = {}; let keys = target._primaryKeys; if(keys && keys.length) { for(var i=0;i<keys.length;i++) { let f = target.getFieldName(keys[i]) || keys[i]; obj[f] = target[keys[i]]; } } return obj; } /** * 生成SQL参数语句 * 默认会返回 * { where: "", params: new Array<any>() }; * @param obj sql条件参数 * @param type {model class} 指定类型,如果不指定则字段按属性名,指定了就会去取映射的字段名 */ static createSqlWhere(obj: object, type?: { new(): BaseModel, _fieldMap: object;}|BaseModel): {where: string, params: Array<any>} { let result = { where: "", params: new Array<any>() }; if(!obj) return result; let ps = this.getPropertyNames(obj); //组合更新条件 for(let i=0; i<ps.length; i++) { let c = type? this.getFieldName(ps[i], type): ps[i]; result.where += `\`${c}\`=? and `; result.params.push(obj[ps[i]]); } if(result.where.endsWith(' and ')) result.where = result.where.replace(/\s*and\s*$/, ''); return result; } /** * 把原数据对象转为映射为表字段的对象 * 例如: {id:1} 转为 {Fid:1} * @param obj 原值对象 * @param type 对应的model类 */ static objectToFieldValues(obj: object, type: { new(): BaseModel, _fieldMap: object;}|BaseModel): object { let ret = {}; for(var k in obj) { let f = this.getFieldName(k, type) || k; ret[f] = obj[k]; } return ret; } /** * 转为json * @method toJSON * @param target {class} 需要转为json的实例 * @param filter {Function} 需要对属性过滤的函数,返回false则不处理此属性 * @returns object */ static toJSON(target: any, filter: Function = ()=>{}): object { let jsonObj = {}; let pros = this.getPropertyNames(target); for (let key of pros) { if(filter && filter(key) === false) continue; jsonObj[key] = target[key]; } return jsonObj; } } export default modelHelper;