diff --git a/packages/data-source/src/data-sources/Http.ts b/packages/data-source/src/data-sources/Http.ts index dd5af19a..8e93a98c 100644 --- a/packages/data-source/src/data-sources/Http.ts +++ b/packages/data-source/src/data-sources/Http.ts @@ -126,21 +126,29 @@ export default class HttpDataSource extends DataSource { public async request(options: Partial = {}) { this.isLoading = true; + let reqOptions = { + ...this.httpOptions, + ...options, + }; + try { for (const method of this.#beforeRequest) { - await method({ options, params: {}, dataSource: this, app: this.app }); + await method({ options: reqOptions, params: {}, dataSource: this, app: this.app }); + } + + if (typeof this.schema.beforeRequest === 'function') { + reqOptions = this.schema.beforeRequest(reqOptions, { app: this.app, dataSource: this }); } // 注意:在编辑器中mockData不会为空,至少是默认值,不会发起请求 - const res = this.mockData - ? this.mockData - : await this.#fetch?.({ - ...this.httpOptions, - ...options, - }); + let res = this.mockData ? this.mockData : await this.#fetch?.(reqOptions); for (const method of this.#afterRequest) { - await method({ res, options, params: {}, dataSource: this, app: this.app }); + await method({ res, options: reqOptions, params: {}, dataSource: this, app: this.app }); + } + + if (typeof this.schema.afterResponse === 'function') { + res = this.schema.afterResponse(res, { app: this.app, dataSource: this }); } if (this.schema.responseOptions?.dataPath) { diff --git a/packages/data-source/src/types.ts b/packages/data-source/src/types.ts index 2538fa3d..e7305592 100644 --- a/packages/data-source/src/types.ts +++ b/packages/data-source/src/types.ts @@ -1,5 +1,7 @@ import type { AppCore, DataSourceSchema, HttpOptions, RequestFunction } from '@tmagic/schema'; +import HttpDataSource from './data-sources/Http'; + export interface DataSourceOptions { schema: DataSourceSchema; app: AppCore; @@ -13,6 +15,10 @@ export interface HttpDataSourceSchema extends DataSourceSchema { dataPath?: string; }; autoFetch?: boolean; + beforeRequest: + | string + | ((options: HttpOptions, content: { app: AppCore; dataSource: HttpDataSource }) => HttpOptions); + afterResponse: string | ((response: any, content: { app: AppCore; dataSource: HttpDataSource }) => any); } export interface HttpDataSourceOptions extends DataSourceOptions { diff --git a/packages/editor/src/services/dataSource.ts b/packages/editor/src/services/dataSource.ts index 3adbc197..9889463d 100644 --- a/packages/editor/src/services/dataSource.ts +++ b/packages/editor/src/services/dataSource.ts @@ -7,7 +7,7 @@ import type { DataSourceSchema } from '@tmagic/schema'; import { guid } from '@tmagic/utils'; import type { DatasourceTypeOption } from '@editor/type'; -import { getFormConfig } from '@editor/utils/data-source'; +import { getFormConfig, getFormValue } from '@editor/utils/data-source'; import BaseService from './BaseService'; @@ -50,7 +50,7 @@ class DataSource extends BaseService { } public getFormValue(type = 'base') { - return this.get('values')[type]; + return getFormValue(type, this.get('values')[type]); } public setFormValue(type: string, value: Partial) { diff --git a/packages/editor/src/utils/data-source/index.ts b/packages/editor/src/utils/data-source/index.ts index 8e004f70..ac1c76ac 100644 --- a/packages/editor/src/utils/data-source/index.ts +++ b/packages/editor/src/utils/data-source/index.ts @@ -1,4 +1,4 @@ -import { FormConfig } from '@tmagic/form'; +import { FormConfig, FormState } from '@tmagic/form'; import { DataSchema, DataSourceSchema } from '@tmagic/schema'; import BaseFormConfig from './formConfigs/base'; @@ -8,47 +8,72 @@ const fillConfig = (config: FormConfig): FormConfig => [ ...BaseFormConfig(), ...config, { - type: 'panel', - title: '数据定义', + type: 'tab', items: [ { - name: 'fields', - type: 'data-source-fields', - defaultValue: () => [], + title: '数据定义', + items: [ + { + name: 'fields', + type: 'data-source-fields', + defaultValue: () => [], + }, + ], }, - ], - }, - { - type: 'panel', - title: '方法定义', - items: [ { - name: 'methods', - type: 'data-source-methods', - defaultValue: () => [], + title: '方法定义', + items: [ + { + name: 'methods', + type: 'data-source-methods', + defaultValue: () => [], + }, + ], }, - ], - }, - { - type: 'panel', - title: '事件配置', - display: false, - items: [ { - name: 'events', - src: 'datasource', - type: 'event-select', + title: '事件配置', + display: false, + items: [ + { + name: 'events', + src: 'datasource', + type: 'event-select', + }, + ], }, - ], - }, - { - type: 'panel', - title: 'mock数据', - items: [ { - name: 'mocks', - type: 'data-source-mocks', - defaultValue: () => [], + title: 'mock数据', + items: [ + { + name: 'mocks', + type: 'data-source-mocks', + defaultValue: () => [], + }, + ], + }, + { + title: '请求参数裁剪', + display: (formState: FormState, { model }: any) => model.type === 'http', + items: [ + { + name: 'beforeRequest', + type: 'vs-code', + parse: true, + height: '600px', + }, + ], + }, + { + title: '响应数据裁剪', + display: (formState: FormState, { model }: any) => model.type === 'http', + items: [ + { + name: 'afterResponse', + type: 'vs-code', + parse: true, + height: '600px', + }, + ], }, ], }, @@ -65,6 +90,64 @@ export const getFormConfig = (type: string, configs: Record) } }; +export const getFormValue = (type: string, values: Partial): Partial => { + if (type !== 'http') { + return values; + } + + return { + beforeRequest: `(options, context) => { + /** + * 用户可以直接编写函数,在原始接口调用之前,会运行该函数,将这个函数的返回值作为该数据源接口的入参 + * + * options: HttpOptions + * + * interface HttpOptions { + * // 请求链接 + * url: string; + * // query参数 + * params?: Record; + * // body数据 + * data?: Record; + * // 请求头 + * headers?: Record; + * // 请求方法 GET/POST + * method?: Method; + * } + * + * context:上下文对象 + * + * interface Content { + * app: AppCore; + * dataSource: HttpDataSource; + * } + * + * return: HttpOptions + */ + + // 此处的返回值会作为这个接口的入参 + return options; +}`, + afterResponse: `(response, context) => { + /** + * 用户可以直接编写函数,在原始接口返回之后,会运行该函数,将这个函数的返回值作为该数据源接口的返回 + + * context:上下文对象 + * + * interface Content { + * app: AppCore; + * dataSource: HttpDataSource; + * } + * + */ + + // 此处的返回值会作为这个接口的返回值 + return response; +}`, + ...values, + }; +}; + export const getDisplayField = (dataSources: DataSourceSchema[], key: string) => { const displayState: { value: string; type: 'var' | 'text' }[] = []; diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index 4a064c4f..38c361d9 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -18,10 +18,15 @@ export type Method = 'get' | 'GET' | 'delete' | 'DELETE' | 'post' | 'POST' | 'put' | 'PUT'; export interface HttpOptions { + /** 请求链接 */ url: string; + /** query参数 */ params?: Record; + /** body数据 */ data?: Record; + /** 请求头 */ headers?: Record; + /** 请求方法 GET/POST */ method?: Method; [key: string]: any; }