UNPKG

@lct/common

Version:
260 lines (243 loc) 8.32 kB
import modelHelper from "../helper/modelHelper"; const PrimaryKeyId = Symbol("$primaryKeys"); const TableNameId = Symbol("$tableName"); const TableFieldMapId = Symbol("$tableFieldMap"); /** * 数据model的基础类 * 构造函数可以接受DB查出的result * 属性跟DB中的字段规定为 加前缀F * 例如:属性名为firsName 会自动映射到_dbData中的Ffirst_name字段 * 以下划线为开头的属性名不会做映射 * 注: 所有需要支持json序列化的,请定义时指定默认值。如: firstName: string = ""; */ class BaseModel { /** * 根据参数实例化当前类 * @param {Object/String} data 如果传入object会当做DB表数据来映射,如果是model对象,则进行浅拷贝。如果是字符串只进行json转换 * @param {Object} map 字段跟属性的映射,一般不需要指定,除非需要特殊 格式:{property: field} */ constructor(data: any = "", map = {}) { this._dbData = {}; if(data) { if(typeof data == 'string') { data = JSON.parse(data); Object.assign(this, data);//浅拷贝 } //DB原数据 else if(typeof data == 'object' && data.constructor && data.constructor.name == 'RowDataPacket') { this._dbData = data; } else if(typeof data == 'object') { Object.assign(this, data);//浅拷贝 } } this._fieldMap = Object.assign(this._fieldMap||{}, map); //所有model采用代理方法,从DB中取值 return new Proxy<BaseModel>(this, { get: function (target, key, receiver) { if(typeof key == 'string' && !key.startsWith('_') && !key.startsWith('$')) { let pros = modelHelper.getPropertyNames(target); if(pros.includes(key)) { let v = target.getValue(key, receiver); if(typeof v != 'undefined') return v; } } return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { if(typeof key == 'string' && !key.startsWith('_') && !key.startsWith('$')) { let pros = modelHelper.getPropertyNames(target); if(pros.includes(key)) { target.setValue(key, value, receiver); return true; } } return Reflect.set(target, key, value, receiver); } }); } /** * DB原始数据对象 * @property _dbData * @type Object */ public _dbData: object; /** * 当前对应表的唯一健 * @property _primaryKeys * @type Array<string> */ public get _primaryKeys(): Array<string> { let proto = Object.getPrototypeOf(this); return proto[PrimaryKeyId]; } public set _primaryKeys(value: Array<string>) { let proto = Object.getPrototypeOf(this); proto[PrimaryKeyId] = value; } /** * 当前对应表的唯一健 * @static * @property _primaryKeys * @type Array<string> */ public static get _primaryKeys(): Array<string> { return this.prototype[PrimaryKeyId]; } public static set _primaryKeys(value) { this.prototype[PrimaryKeyId] = value; } /** * 对应的表名 * @property _tableName * @type string */ public get _tableName(): string { let proto = Object.getPrototypeOf(this); return proto[TableNameId]; } public set _tableName(value: string) { let proto = Object.getPrototypeOf(this); proto[TableNameId] = value; } /** * 对应的表名 * @static * @property tableName * @type string */ public static get _tableName(): string { return this.prototype[TableNameId]; } public static set _tableName(value) { this.prototype[TableNameId] = value; } /** * 表字段跟对象属性的映射 * 格式:{property: field} * @property _fieldMap * @type Map */ public get _fieldMap(): object { let proto = Object.getPrototypeOf(this); return proto[TableFieldMapId]; } public set _fieldMap(value: object) { let proto = Object.getPrototypeOf(this); proto[TableFieldMapId] = value; } /** * 表字段跟对象属性的映射 * 格式:{property: field} * @property _fieldMap * @type Map */ public static get _fieldMap(): object { return this.prototype[TableFieldMapId]; } public static set _fieldMap(value: object) { this.prototype[TableFieldMapId] = value; } /** * 从DB数据源中读取属性值 * @method getValue * @param {string} name 属性名,也可以是在DB中的字段名 */ public getValue(name: string, receiver?: any): any { if(!this._dbData) return null; let field = this.getFieldName(name); if(field) return this._dbData[field]; else { return Reflect.get(this, name, receiver); } } /** * 把数据写到DB原对象中 * @method getValue * @param {string} name 属性名 * @param {any} value 设置值 */ public setValue(name: string, value: any, receiver?: any): void { if(this._dbData) { let field = this.getFieldName(name); this._dbData[field] = value; } else { Reflect.set(this, name, value, receiver); } } /** * 根据属性名得到对应的表字段名,这里规定死为属性名前加一个F为字段名 * 并把大写字母转为_小写 * 如果传入了_或$开头的名称,则返回空 * @method getFieldName * @param {String} name 属性名 */ public getFieldName(name: string): string { return modelHelper.getFieldName(name, this); } /** * 转为json * @method toJSON * @returns object */ public toJSON(): object { let jsonObj = modelHelper.toJSON(this, (k: string) => !k.startsWith('$')); return jsonObj; } /** * 转为json串 * @method toString * @returns string */ public toString(): string { let obj = this.toJSON(); return JSON.stringify(obj); } /** * 表名装饰器 * @param {String} name 表名 */ static Table(name: string, primaryKeys: Array<string> = []) { return (constructor: Function) => { constructor.prototype[TableNameId] = name; if(primaryKeys && primaryKeys.length) { this.TablePrimaryKey(primaryKeys)(constructor); } }; } /** * 表字段装饰器 * @param {String} field 字段名 */ static TableField(field: string) { return (target: any, name: string): any => { if(!target[TableFieldMapId]) { target[TableFieldMapId] = {}; } target[TableFieldMapId][name] = field; } } /** * 表唯一健装饰器 * "experimentalDecorators": true, */ static TablePrimaryKey(name: string|Array<string>) { return (constructor: Function) => { if(!constructor.prototype[PrimaryKeyId]) { constructor.prototype[PrimaryKeyId] = []; } if(Array.isArray(name)) { constructor.prototype[PrimaryKeyId] = name; } else { let v = constructor.prototype[PrimaryKeyId]; if(!v.includes(name)) v.push(name); } }; } } export default BaseModel; export { BaseModel }