import { Model2Object } from "./model2object"; /** * 模型转entity */ export class Model2Entity{ /** * 生成sql * @param modelPath - 模型路径 * @param dstPath - 目标路径 */ public genEntity(modelPath:string,dstPath:string,excludeHeads?:string[]){ const me = this; const fsMdl = require('fs'); const pathMdl = require('path'); //关系集合 {依赖表.字段:被依赖表.字段} const relations = {}; //create table 串数组 const sqlArr = []; if(!fsMdl.existsSync(modelPath)){ throw new Error('模型路径不存在') } if(!fsMdl.existsSync(dstPath)){ fsMdl.mkdirSync(dstPath,{recursive:true}) } //转换成model对象 const models = Model2Object.gen(modelPath); const prettier = require('prettier'); //遍历生成entity for(let key of Object.keys(models)){ if(excludeHeads){ let notDo = false; for(let h of excludeHeads){ if(key.startsWith(h)){ notDo = true; break; } } if(notDo){ continue; } } let str = this.genOne(models[key],relations); str = prettier.format(str,{tabWidth: 4, parser: "typescript",trailingComma:'none'}); //写文件 fsMdl.writeFileSync(pathMdl.resolve(dstPath,models[key].ref.toLowerCase()+'.ts'),str); } } /** * 生产一个model的sql * @param modelPath */ private genOne(modelCfg,relations):string{ const fieldArr:string[] = []; //import 串 const importArr = [`import {BaseEntity,Entity,Column,Id,JoinColumn,ManyToOne,OneToMany,EntityProxy} from 'relaen';`]; //constructor getter //构造器 const postArr = [` constructor(idValue?:number){ super(); this.${modelCfg.idProp.name} = idValue; } `]; //处理字段 for(let cfg of modelCfg.props){ const tblName = cfg.ref; let str = '\t'; let fieldName = cfg.name; let s=''; //column配置项 let fieldCfg; //join column配置项 let joinCfg; //ts类型 let type = cfg.type; if(cfg.isId){ s = '@Id()\r\n'; fieldCfg = { type:'int', nullable:false } }else{ //普通字段,处理数据类型 switch(cfg.type){ case 'string': let len = 128; if(cfg.validator){ for(let v of cfg.validator){ //有最长度 if(v.includes('maxLength:')){ const ds = v.substring(v.indexOf('maxLength:') + 10); try{ len = parseInt(ds); }catch(e){ throw 'maxLength 参数错误' } } } } fieldCfg = { type:'string', length:len, nullable:true } break; case 'int': fieldCfg = { type:'int', nullable:true } break; case 'bool': fieldCfg = { type:'int', nullable:true } break; case 'ref': s = 'bigint'; //引用实体名 let refEnt; //引用字段名 let refField; if(cfg.ref === 'MdlAmFile'){ //文件 refEnt = 'AmFile'; refField = 'FILE_ID'; relations[tblName + '.' + fieldName] = { tbl:'AM_FILE', field:'FILE_ID' } importArr.push(`import {AmFile} from '../base/amfile';`) }else if(cfg.ref === 'MdlAmDataImport'){ //导入批次 refEnt = 'AmDataImport'; refField = 'DATA_IMPORT_ID'; relations[tblName + '.' + fieldName] = { tbl:'AM_DATA_IMPORT', field:'DATA_IMPORT_ID' } fieldName = 'amDataImport'; importArr.push(`import {AmDataImport} from '../base/amdataimport';`) }else{ //其它 refEnt = cfg.ref.substring(3); refField = cfg.editOption.option.valueProp; relations[tblName + '.' + fieldName] = { tbl:refEnt.toUpperCase(), field:refField.toUpperCase() } importArr.push(`import { ${refEnt} } from './${refEnt.toLowerCase()}';`) } s = `@ManyToOne({entity:'${refEnt}'})` joinCfg = { name:fieldName.toUpperCase(), refName:refField.toUpperCase(), nullable:true } //属性首字母转大写 const upName = fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); postArr.push(` public async get${upName}():Promise<${refEnt}>{ return this['${fieldName}']?this['${fieldName}']:await EntityProxy.get(this,'${fieldName}'); } `); type = refEnt; break; default: fieldCfg = { type:cfg.type, nullable:true } } } str = s; //数字类型 if(['int','float','double'].includes(type)){ type = 'number'; } //简单字段 if(fieldCfg){ fieldCfg['name'] = fieldName.toUpperCase(); str += `@Column(${JSON.stringify(fieldCfg)})`; }else if(joinCfg){ //引用字段 str += `@JoinColumn(${JSON.stringify(joinCfg)})`; } fieldArr.push(str); fieldArr.push(`public ${fieldName} : ${type};`); } return ` ${importArr.join('\r\n')} @Entity("${modelCfg.ref.toUpperCase()}") export class ${modelCfg.ref} extends BaseEntity{ ${fieldArr.join('\r\n')} ${postArr.join('\r\n')} } ` } ß}