@lct/common
Version:
260 lines (243 loc) • 8.32 kB
text/typescript
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
}