ts-template.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. const _ = require('lodash');
  2. const getModelType = (type, interf = false) => {
  3. let modelType = 'string';
  4. if (type === 'Money' || type === 'money') {
  5. if (!interf) modelType = 'Decimal128';
  6. else modelType = 'number';
  7. } else if (type === 'ObjectId') modelType = 'ObjectId';
  8. else if (type === 'Array') modelType = 'Array<any>';
  9. else modelType = _.lowerFirst(type);
  10. return modelType;
  11. };
  12. const ModelContext = (data) => {
  13. const { name: table_name, columns } = data;
  14. const prefix = _.upperFirst(table_name);
  15. let fc = [];
  16. fc.push(`import { modelOptions, prop } from '@typegoose/typegoose';`);
  17. fc.push(`import { BaseModel } from 'free-midway-component';`);
  18. const has_money = columns.find((f) => f.type === 'Money' || f.type === 'money');
  19. if (has_money) fc.push(`import { Decimal128 } from 'mongoose';`);
  20. fc.push(`@modelOptions({`);
  21. fc.push(` schemaOptions: { collection: '${table_name}' },`);
  22. fc.push(`})`);
  23. fc.push(`export class ${prefix} extends BaseModel {`);
  24. // 处理字段
  25. for (const col of columns) {
  26. const { type, title, def } = col;
  27. const prop = _.pick(col, ['required', 'index', 'zh', 'ref', 'remark']);
  28. if (def) prop.default = def;
  29. const modelType = getModelType(type);
  30. fc.push(` @prop(${JSON.stringify(prop)})`);
  31. fc.push(` ${title}: ${modelType}`);
  32. }
  33. fc.push(`}`);
  34. // 最后换行转为字符串
  35. const fileContext = fc.join('\n');
  36. return fileContext;
  37. };
  38. const ServiceContext = (data) => {
  39. const fc = [];
  40. const { name: table_name, getPath } = data;
  41. const prefix = _.upperFirst(table_name);
  42. const entityPath = getPath('entity');
  43. fc.push(`import { Provide } from '@midwayjs/decorator';`);
  44. fc.push(`import { InjectEntityModel } from '@midwayjs/typegoose';`);
  45. fc.push(`import { ReturnModelType } from '@typegoose/typegoose';`);
  46. fc.push(`import { BaseService } from 'free-midway-component';`);
  47. fc.push(`import { ${prefix} } from '${entityPath}';`);
  48. fc.push(`type modelType = ReturnModelType<typeof ${prefix}>;`);
  49. fc.push(`@Provide()`);
  50. fc.push(`export class ${prefix}Service extends BaseService<modelType> {`);
  51. fc.push(` @InjectEntityModel(${prefix})`);
  52. fc.push(` model: modelType;`);
  53. fc.push(`}`);
  54. return fc.join('\n');
  55. };
  56. const ControllerContext = (data) => {
  57. const fc = [];
  58. const { name, name_zh, getPath } = data;
  59. const prefix = _.upperFirst(name);
  60. const servicePath = getPath('service');
  61. const interfacePath = getPath('interface');
  62. fc.push(`import { Body, Controller, Del, Get, Inject, Param, Post, Query } from '@midwayjs/decorator';`);
  63. fc.push(`import { BaseController } from 'free-midway-component';`);
  64. fc.push(`import { ${prefix}Service } from '${servicePath}';`);
  65. fc.push(`import { CDTO_${name}, CVO_${name}, FVO_${name},QDTO_${name}, QVO_${name}, UDTO_${name}, UVAO_${name} } from '${interfacePath}';`);
  66. fc.push(`import { ApiResponse, ApiTags, ApiQuery } from '@midwayjs/swagger';`);
  67. fc.push(`import { Validate } from '@midwayjs/validate';`);
  68. fc.push(`@ApiTags(['${name_zh}'])`);
  69. fc.push(`@Controller('/${name}')`);
  70. fc.push(`export class ${prefix}Controller extends BaseController {`);
  71. fc.push(` @Inject()`);
  72. fc.push(` service: ${prefix}Service;`);
  73. fc.push('\n');
  74. // create
  75. fc.push(`@Post('/') @Validate() @ApiResponse({ type: CVO_${name} })`);
  76. fc.push(` async create(@Body() data: CDTO_${name}) {`);
  77. fc.push(` const dbData = await this.service.create(data);`);
  78. fc.push(` const result = new CVO_${name}(dbData);`);
  79. fc.push(` return result;`);
  80. fc.push(` }`);
  81. // query
  82. fc.push(`@Get('/')@ApiQuery({name:'query'})@ApiResponse({ type: QVO_${name} })`);
  83. fc.push(` async query(@Query() filter:QDTO_${name}, @Query('skip') skip: number,@Query('limit') limit: number){`);
  84. fc.push(` const list = await this.service.query(filter, { skip, limit });`);
  85. fc.push(` const data = [];`);
  86. fc.push(` for (const i of list) {`);
  87. fc.push(` const newData = new QVO_${name}(i);`);
  88. fc.push(` data.push(newData);`);
  89. fc.push(` }`);
  90. fc.push(` const total = await this.service.count(filter);`);
  91. fc.push(` return { data, total };`);
  92. fc.push(` }`);
  93. fc.push(`\n`);
  94. // fetch
  95. fc.push(`@Get('/:id')@ApiResponse({ type: FVO_${name} })`);
  96. fc.push(` async fetch(@Param('id') id: string) {`);
  97. fc.push(` const data = await this.service.fetch(id);`);
  98. fc.push(` const result = new FVO_${name}(data);`);
  99. fc.push(` return result;`);
  100. fc.push(` }`);
  101. fc.push(`\n`);
  102. // update
  103. fc.push(`@Post('/:id')@Validate()@ApiResponse({ type: UVAO_${name} })`);
  104. fc.push(` async update(@Param('id') id: string, @Body() body: UDTO_${name}) {`);
  105. fc.push(` const result = await this.service.updateOne(id, body);`);
  106. fc.push(` return result;`);
  107. fc.push(` }`);
  108. fc.push(`\n`);
  109. // delete
  110. fc.push(`@Del('/:id')@Validate()`);
  111. fc.push(` async delete(@Param('id') id: string) {`);
  112. fc.push(` await this.service.delete(id);`);
  113. fc.push(` return 'ok';`);
  114. fc.push(` }`);
  115. // other bat deal
  116. fc.push(` async createMany(...args: any[]) {`);
  117. fc.push(` throw new Error('Method not implemented.');`);
  118. fc.push(` }`);
  119. fc.push(`\n`);
  120. fc.push(` async updateMany(...args: any[]) {`);
  121. fc.push(` throw new Error('Method not implemented.');`);
  122. fc.push(` }`);
  123. fc.push(`\n`);
  124. fc.push(` async deleteMany(...args: any[]) {`);
  125. fc.push(` throw new Error('Method not implemented.');`);
  126. fc.push(` }`);
  127. fc.push(`}`);
  128. fc.push(`\n`);
  129. return fc.join(`\n`);
  130. };
  131. /**
  132. *
  133. * @param {Object} col 字段
  134. * @param {boolean} needReq 是否启用必须,针对post设置
  135. * @returns
  136. */
  137. const getInterfaceColumn = (col, needReq = false) => {
  138. const fc = [];
  139. const { type, zh, title, required } = col;
  140. const modelType = getModelType(type, true);
  141. fc.push(` @ApiProperty({ description: '${zh}' })`);
  142. if (needReq) {
  143. let ruleStr = '';
  144. let rt = '';
  145. if (type === 'Money' || type === 'money') rt = 'number';
  146. else rt = _.lowerFirst(type);
  147. if (required) ruleStr = `@Rule(RuleType['${rt}']().required().error(new ServiceError('缺少${zh}',FrameworkErrorEnum.${needReq ? 'NEED_BODY' : 'NEED_QUERY'})))`;
  148. else ruleStr = `@Rule(RuleType['${rt}']().empty(''))`;
  149. fc.push(ruleStr);
  150. }
  151. fc.push(` '${title}': ${modelType} = undefined;`);
  152. return fc;
  153. };
  154. const interfaceContext = (data) => {
  155. const fc = [];
  156. const { columns = [], name } = data;
  157. const have_required = columns.find((f) => f.required);
  158. fc.push(`import { Rule, RuleType } from '@midwayjs/validate';`);
  159. fc.push(`import { ApiProperty } from '@midwayjs/swagger';`);
  160. if (have_required) fc.push(`import { FrameworkErrorEnum, SearchBase, ServiceError } from 'free-midway-component';`);
  161. else fc.push(`import { SearchBase } from 'free-midway-component';`);
  162. fc.push(`import get = require('lodash/get');`);
  163. fc.push(`const dealVO = (cla, data) => {`);
  164. fc.push(` for (const key in cla) {`);
  165. fc.push(` const val = get(data, key);`);
  166. fc.push(` if (val || val === 0) cla[key] = val;`);
  167. fc.push(` }`);
  168. fc.push(`};`);
  169. fc.push(`export class FVO_${name} {`);
  170. fc.push(` constructor(data: object) {`);
  171. fc.push(` dealVO(this, data);`);
  172. fc.push(` }`);
  173. fc.push(` @ApiProperty({ description: '数据id' })`);
  174. fc.push(` _id: string = undefined;`);
  175. for (const col of columns) {
  176. const cfc = getInterfaceColumn(col);
  177. fc.push(...cfc);
  178. }
  179. fc.push(`}`);
  180. fc.push(`\n`);
  181. const indexs = columns.filter((f) => f.index);
  182. const props = indexs.map((i) => `'${i.title}'`).join(', ');
  183. fc.push(`export class QDTO_${name} extends SearchBase {`);
  184. fc.push(` constructor() {`);
  185. fc.push(` const like_prop = [];`);
  186. fc.push(` const props = [${props}];`);
  187. fc.push(` const mapping = [];`);
  188. fc.push(` super({ like_prop, props, mapping });`);
  189. fc.push(` }`);
  190. for (const col of indexs) {
  191. const cfc = getInterfaceColumn(col);
  192. fc.push(...cfc);
  193. }
  194. fc.push(`}`);
  195. fc.push(`\n`);
  196. fc.push(`export class QVO_${name} extends FVO_${name} {`);
  197. fc.push(` constructor(data: object) {`);
  198. fc.push(` super(data);`);
  199. fc.push(` dealVO(this, data);`);
  200. fc.push(` }`);
  201. fc.push(`}`);
  202. fc.push(`\n`);
  203. fc.push(`export class CDTO_${name} {`);
  204. for (const col of columns) {
  205. const cfc = getInterfaceColumn(col, true);
  206. fc.push(...cfc);
  207. }
  208. fc.push(`}`);
  209. fc.push(`\n`);
  210. fc.push(`export class CVO_${name} extends FVO_${name} {`);
  211. fc.push(` constructor(data: object) {`);
  212. fc.push(` super(data);`);
  213. fc.push(` dealVO(this, data);`);
  214. fc.push(` }`);
  215. fc.push(`}`);
  216. fc.push(`\n`);
  217. fc.push(`export class UDTO_${name} extends CDTO_${name} {
  218. @ApiProperty({ description: '数据id' })
  219. @Rule(RuleType['string']().empty(''))
  220. _id: string = undefined;
  221. }`);
  222. fc.push(`\n`);
  223. fc.push(`export class UVAO_${name} extends FVO_${name} {`);
  224. fc.push(` constructor(data: object) {`);
  225. fc.push(` super(data);`);
  226. fc.push(` dealVO(this, data);`);
  227. fc.push(` }`);
  228. fc.push(`}`);
  229. return fc.join('\n');
  230. };
  231. module.exports = (data) => {
  232. let result = `\n========== Model ==========\n`;
  233. result += ModelContext(data);
  234. result += `\n========== Service ==========\n`;
  235. result += ServiceContext(data);
  236. result += `\n========== Controller ==========\n`;
  237. result += ControllerContext(data);
  238. result += `\n========== interface ==========\n`;
  239. result += interfaceContext(data);
  240. return result;
  241. };