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';`); 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']); if (def) prop.default = def; const modelType = getModelType(type); fc.push(` @prop(${JSON.stringify(prop)})`); fc.push(` ${title}: ${modelType}`); } fc.push(`}`); // 最后换行转为字符串 const fileContext = fc.join('\n'); return fileContext; }; const ServiceContext = (data) => { const fc = []; const { name: table_name } = data; const prefix = _.upperFirst(table_name); 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 '../entity/${_.lowerFirst(table_name)}.entity';`); 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 } = data; const prefix = _.upperFirst(name); 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 '../service/${_.lowerFirst(name)}.service';`); fc.push(`import { CDTO_${name}, CVO_${name}, FVO_${name},QDTO_${name}, QVO_${name}, UDTO_${name}, UVAO_${name} } from '../interface/${_.lowerFirst(name)}.interface';`); 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 result = await this.service.create(data);`); 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 data = await this.service.query(filter, { skip, limit });`); 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); return result; };