const _ = require('lodash'); const getModelType = (type, interf = false) => { let modelType = 'string'; if (type === 'Money' || type === 'money') { if (!interf) modelType = 'Decimal128'; else modelType = 'number'; } else if (type === 'ObjectId') modelType = 'ObjectId'; else if (type === 'Array') modelType = 'Array'; else modelType = _.lowerFirst(type); return modelType; }; const ModelContext = (data) => { const { name: table_name, columns } = data; const prefix = _.upperFirst(table_name); let fc = []; fc.push(`import { modelOptions, prop } from '@typegoose/typegoose';`); fc.push(`import { BaseModel } from 'free-midway-component';`); const has_money = columns.find((f) => f.type === 'Money' || f.type === 'money'); if (has_money) fc.push(`import { Decimal128 } from 'mongoose';`); // 添加secret需要isString函数 const has_secret = columns.find((f) => f.type === 'Secret' || f.type === 'secret'); if (has_secret) fc.push(`import { isString } from 'lodash';`); fc.push(`@modelOptions({`); fc.push(` schemaOptions: { collection: '${table_name}' },`); fc.push(`})`); fc.push(`export class ${prefix} extends BaseModel {`); // 处理字段 for (const col of columns) { const { type, title, def } = col; const prop = _.pick(col, ['required', 'index', 'zh', 'ref', 'remark', 'esType']); if (def) prop.default = def; const modelType = getModelType(type); switch (modelType) { case 'secret': prop.select = false; // 手动删除引号.变成方法.这里处理不了 prop.set = `(val) => { if (isString(val)) { return { secret: val }; } return val; }`; fc.push(` // 手动删除set前的大括号,处理太麻烦了.就手动删除吧`); fc.push(` @prop(${JSON.stringify(prop)})`); fc.push(` ${title}: object`); break; default: fc.push(` @prop(${JSON.stringify(prop)})`); fc.push(` ${title}: ${modelType}`); break; } } fc.push(`}`); // 最后换行转为字符串 const fileContext = fc.join('\n'); return fileContext; }; const ServiceContext = (data) => { const fc = []; const { name: table_name, getPath } = data; const prefix = _.upperFirst(table_name); const entityPath = getPath('entity'); fc.push(`import { Provide } from '@midwayjs/decorator';`); fc.push(`import { InjectEntityModel } from '@midwayjs/typegoose';`); fc.push(`import { ReturnModelType } from '@typegoose/typegoose';`); fc.push(`import { BaseService } from 'free-midway-component';`); fc.push(`import { ${prefix} } from '${entityPath}';`); fc.push(`type modelType = ReturnModelType;`); fc.push(`@Provide()`); fc.push(`export class ${prefix}Service extends BaseService {`); fc.push(` @InjectEntityModel(${prefix})`); fc.push(` model: modelType;`); fc.push(`}`); return fc.join('\n'); }; const ControllerContext = (data) => { const fc = []; const { name, name_zh, getPath } = data; const prefix = _.upperFirst(name); const servicePath = getPath('service'); const interfacePath = getPath('interface'); fc.push(`import { Body, Controller, Del, Get, Inject, Param, Post, Query } from '@midwayjs/decorator';`); fc.push(`import { BaseController } from 'free-midway-component';`); fc.push(`import { ${prefix}Service } from '${servicePath}';`); fc.push(`import { CDTO_${name}, CVO_${name}, FVO_${name},QDTO_${name}, QVO_${name}, UDTO_${name}, UVAO_${name} } from '${interfacePath}';`); fc.push(`import { ApiResponse, ApiTags, ApiQuery } from '@midwayjs/swagger';`); fc.push(`import { Validate } from '@midwayjs/validate';`); fc.push(`@ApiTags(['${name_zh}'])`); fc.push(`@Controller('/${name}')`); fc.push(`export class ${prefix}Controller extends BaseController {`); fc.push(` @Inject()`); fc.push(` service: ${prefix}Service;`); fc.push('\n'); // create fc.push(`@Post('/') @Validate() @ApiResponse({ type: CVO_${name} })`); fc.push(` async create(@Body() data: CDTO_${name}) {`); fc.push(` const dbData = await this.service.create(data);`); fc.push(` const result = new CVO_${name}(dbData);`); fc.push(` return result;`); fc.push(` }`); // query fc.push(`@Get('/')@ApiQuery({name:'query'})@ApiResponse({ type: QVO_${name} })`); fc.push(` async query(@Query() filter:QDTO_${name}, @Query('skip') skip: number,@Query('limit') limit: number){`); fc.push(` const list = await this.service.query(filter, { skip, limit });`); fc.push(` const data = [];`); fc.push(` for (const i of list) {`); fc.push(` const newData = new QVO_${name}(i);`); fc.push(` data.push(newData);`); fc.push(` }`); fc.push(` const total = await this.service.count(filter);`); fc.push(` return { data, total };`); fc.push(` }`); fc.push(`\n`); // fetch fc.push(`@Get('/:id')@ApiResponse({ type: FVO_${name} })`); fc.push(` async fetch(@Param('id') id: string) {`); fc.push(` const data = await this.service.fetch(id);`); fc.push(` const result = new FVO_${name}(data);`); fc.push(` return result;`); fc.push(` }`); fc.push(`\n`); // update fc.push(`@Post('/:id')@Validate()@ApiResponse({ type: UVAO_${name} })`); fc.push(` async update(@Param('id') id: string, @Body() body: UDTO_${name}) {`); fc.push(` const result = await this.service.updateOne(id, body);`); fc.push(` return result;`); fc.push(` }`); fc.push(`\n`); // delete fc.push(`@Del('/:id')@Validate()`); fc.push(` async delete(@Param('id') id: string) {`); fc.push(` await this.service.delete(id);`); fc.push(` return 'ok';`); fc.push(` }`); // other bat deal fc.push(` async createMany(...args: any[]) {`); fc.push(` throw new Error('Method not implemented.');`); fc.push(` }`); fc.push(`\n`); fc.push(` async updateMany(...args: any[]) {`); fc.push(` throw new Error('Method not implemented.');`); fc.push(` }`); fc.push(`\n`); fc.push(` async deleteMany(...args: any[]) {`); fc.push(` throw new Error('Method not implemented.');`); fc.push(` }`); fc.push(`}`); fc.push(`\n`); return fc.join(`\n`); }; /** * * @param {Object} col 字段 * @param {boolean} needReq 是否启用必须,针对post设置 * @returns */ const getInterfaceColumn = (col, needReq = false) => { const fc = []; const { type, zh, title, required } = col; const modelType = getModelType(type, true); fc.push(` @ApiProperty({ description: '${zh}' })`); if (needReq) { let ruleStr = ''; let rt = ''; if (type === 'Money' || type === 'money') rt = 'number'; else rt = _.lowerFirst(type); if (required) ruleStr = `@Rule(RuleType['${rt}']().required().error(new ServiceError('缺少${zh}',FrameworkErrorEnum.${needReq ? 'NEED_BODY' : 'NEED_QUERY'})))`; else ruleStr = `@Rule(RuleType['${rt}']().empty(''))`; fc.push(ruleStr); } fc.push(` '${title}': ${modelType} = undefined;`); return fc; }; const InterfaceContext = (data) => { const fc = []; const { columns = [], name } = data; const have_required = columns.find((f) => f.required); fc.push(`import { Rule, RuleType } from '@midwayjs/validate';`); fc.push(`import { ApiProperty } from '@midwayjs/swagger';`); if (have_required) fc.push(`import { FrameworkErrorEnum, SearchBase, ServiceError } from 'free-midway-component';`); else fc.push(`import { SearchBase } from 'free-midway-component';`); fc.push(`import get = require('lodash/get');`); fc.push(`const dealVO = (cla, data) => {`); fc.push(` for (const key in cla) {`); fc.push(` const val = get(data, key);`); fc.push(` if (val || val === 0) cla[key] = val;`); fc.push(` }`); fc.push(`};`); fc.push(`export class FVO_${name} {`); fc.push(` constructor(data: object) {`); fc.push(` dealVO(this, data);`); fc.push(` }`); fc.push(` @ApiProperty({ description: '数据id' })`); fc.push(` _id: string = undefined;`); for (const col of columns) { const cfc = getInterfaceColumn(col); fc.push(...cfc); } fc.push(`}`); fc.push(`\n`); const indexs = columns.filter((f) => f.index); const props = indexs.map((i) => `'${i.title}'`).join(', '); fc.push(`export class QDTO_${name} extends SearchBase {`); fc.push(` constructor() {`); fc.push(` const like_prop = [];`); fc.push(` const props = [${props}];`); fc.push(` const mapping = [];`); fc.push(` super({ like_prop, props, mapping });`); fc.push(` }`); for (const col of indexs) { const cfc = getInterfaceColumn(col); fc.push(...cfc); } fc.push(`}`); fc.push(`\n`); fc.push(`export class QVO_${name} extends FVO_${name} {`); fc.push(` constructor(data: object) {`); fc.push(` super(data);`); fc.push(` dealVO(this, data);`); fc.push(` }`); fc.push(`}`); fc.push(`\n`); fc.push(`export class CDTO_${name} {`); for (const col of columns) { const cfc = getInterfaceColumn(col, true); fc.push(...cfc); } fc.push(`}`); fc.push(`\n`); fc.push(`export class CVO_${name} extends FVO_${name} {`); fc.push(` constructor(data: object) {`); fc.push(` super(data);`); fc.push(` dealVO(this, data);`); fc.push(` }`); fc.push(`}`); fc.push(`\n`); fc.push(`export class UDTO_${name} extends CDTO_${name} { @ApiProperty({ description: '数据id' }) @Rule(RuleType['string']().empty('')) _id: string = undefined; }`); fc.push(`\n`); fc.push(`export class UVAO_${name} extends FVO_${name} {`); fc.push(` constructor(data: object) {`); fc.push(` super(data);`); fc.push(` dealVO(this, data);`); fc.push(` }`); fc.push(`}`); return fc.join('\n'); }; module.exports = (data) => { // let result = `\n========== Model ==========\n`; // result += ModelContext(data); // result += `\n========== Service ==========\n`; // result += ServiceContext(data); // result += `\n========== Controller ==========\n`; // result += ControllerContext(data); // result += `\n========== interface ==========\n`; // result += InterfaceContext(data); const result = {}; result.m = ModelContext(data); result.s = ServiceContext(data); result.c = ControllerContext(data); result.i = InterfaceContext(data); result.n = data.name; return result; };