diff --git a/core/src/controller/base.ts b/core/src/controller/base.ts index f679c5d..9f7500a 100644 --- a/core/src/controller/base.ts +++ b/core/src/controller/base.ts @@ -12,6 +12,7 @@ import { BaseService } from '../service/base'; import { IMidwayApplication } from '@midwayjs/core'; import { Context } from '@midwayjs/koa'; import { TypeORMDataSourceManager } from '@midwayjs/typeorm'; +import { CoolValidateException } from '../exception/validate'; /** * 控制器基类 @@ -48,6 +49,41 @@ export abstract class BaseController { await this.setService(curdOption); // 设置实体 await this.setEntity(curdOption); + // 创建动态方法 + await this.createDynamicMethods(curdOption); + } + + /** + * 创建动态方法 + * @param curdOption 配置 + */ + private async createDynamicMethods(curdOption: CurdOption) { + if (!curdOption.serviceApis) { + return; + } + // 过滤出非标准方法 + const customMethods = curdOption.serviceApis; + + // 为每个自定义方法创建对应的控制器方法 + for (const api of customMethods) { + const methodName = typeof api === 'string' ? api : api.method; + if (this[methodName]) { + continue; // 如果方法已存在则跳过 + } + + this[methodName] = async function () { + const { body } = this.baseCtx.request; + const serviceMethod = this.service[methodName]; + + if (typeof serviceMethod !== 'function') { + throw new CoolValidateException( + `Service method ${methodName} not found` + ); + } + + return this.ok(await serviceMethod.call(this.service, body)); + }; + } } private async before(curdOption: CurdOption) { diff --git a/core/src/decorator/controller.ts b/core/src/decorator/controller.ts index 57a8bc1..ab6e1b5 100644 --- a/core/src/decorator/controller.ts +++ b/core/src/decorator/controller.ts @@ -14,13 +14,23 @@ import * as _ from 'lodash'; import location from '../util/location'; export type ApiTypes = 'add' | 'delete' | 'update' | 'page' | 'info' | 'list'; -// Crud配置 +/** 服务映射接口 */ +export type ServiceApis = { + /** 方法 */ + method: string; + /** 描述 */ + summary: string; +}; + +// Crud配置 export interface CurdOption { // 路由前缀,不配置默认是按Controller下的文件夹路径 prefix?: string; // curd api接口 - api: ApiTypes[]; + api?: ApiTypes[]; + // 服务映射接口 + serviceApis?: (ServiceApis | string)[]; // 分页查询配置 pageQueryOp?: QueryOp | Function; // 非分页查询配置 @@ -32,7 +42,7 @@ export interface CurdOption { // info 忽略返回属性 infoIgnoreProperty?: string[]; // 实体 - entity: any; + entity?: any; // 服务 service?: any; // api标签 @@ -206,12 +216,28 @@ function saveMetadata(prefix, routerOptions, target, curdOption, module) { path: `/${path}`, requestMethod: path == 'info' ? 'get' : 'post', method: path, - summary: apiDesc[path], + summary: apiDesc[path] || path, description: '', }, target ); }); - Scope(ScopeEnum.Request)(target); } + if (!_.isEmpty(curdOption?.serviceApis)) { + curdOption.serviceApis.forEach(api => { + const methodName = typeof api === 'string' ? api : api.method; + attachClassMetadata( + WEB_ROUTER_KEY, + { + path: `/${methodName}`, + requestMethod: 'post', + method: methodName, + summary: typeof api === 'string' ? api : api.summary, + description: '', + }, + target + ); + }); + } + Scope(ScopeEnum.Request)(target); } diff --git a/core/src/service/base.ts b/core/src/service/base.ts index dd0bbcd..9101060 100644 --- a/core/src/service/base.ts +++ b/core/src/service/base.ts @@ -153,7 +153,7 @@ export abstract class BaseService { * @param autoSort 是否自动排序 * @param connectionName 连接名称 */ - async sqlRenderPage(sql, query, autoSort = true, connectionName?) { + async sqlRenderPage(sql, query = {}, autoSort = true, connectionName?) { return await this.service.sqlRenderPage( sql, query, diff --git a/typeorm/query-builder/SelectQueryBuilder.js b/typeorm/query-builder/SelectQueryBuilder.js index f8f5d67..c812b02 100644 --- a/typeorm/query-builder/SelectQueryBuilder.js +++ b/typeorm/query-builder/SelectQueryBuilder.js @@ -42,7 +42,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder { this.orderBys = []; this.relationMetadatas = []; this.broadcaster = new Broadcaster_1.Broadcaster(this.queryRunner); - this.broadcaster.broadcastAfterQueryBuilder(this, "select"); + } // ------------------------------------------------------------------------- @@ -52,6 +52,7 @@ class SelectQueryBuilder extends QueryBuilder_1.QueryBuilder { * Gets generated SQL query without parameters being replaced. */ getQuery() { + this.broadcaster.broadcastAfterQueryBuilder(this, "select"); let sql = this.createComment(); sql += this.createCteExpression(); sql += this.createSelectExpression();