2024-12-09 20:21:34 +08:00

252 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { DataSchema, DataSourceFieldType, DataSourceSchema } from '@tmagic/core';
import { CascaderOption, FormConfig, FormState } from '@tmagic/form';
import {
DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX,
dataSourceTemplateRegExp,
getKeysArray,
isNumber,
} from '@tmagic/utils';
import BaseFormConfig from './formConfigs/base';
import HttpFormConfig from './formConfigs/http';
const fillConfig = (config: FormConfig): FormConfig => [
...BaseFormConfig(),
...config,
{
type: 'tab',
items: [
{
title: '数据定义',
items: [
{
name: 'fields',
type: 'data-source-fields',
defaultValue: () => [],
},
],
},
{
title: '方法定义',
items: [
{
name: 'methods',
type: 'data-source-methods',
defaultValue: () => [],
},
],
},
{
title: '事件配置',
items: [
{
name: 'events',
src: 'datasource',
type: 'event-select',
},
],
},
{
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',
},
],
},
],
},
];
export const getFormConfig = (type: string, configs: Record<string, FormConfig>): FormConfig => {
switch (type) {
case 'base':
return fillConfig([]);
case 'http':
return fillConfig(HttpFormConfig);
default:
return fillConfig(configs[type] || []);
}
};
export const getFormValue = (type: string, values: Partial<DataSourceSchema>): Partial<DataSourceSchema> => {
if (type !== 'http') {
return values;
}
return {
beforeRequest: `(options, context) => {
/**
* 用户可以直接编写函数,在原始接口调用之前,会运行该函数,将这个函数的返回值作为该数据源接口的入参
*
* options: HttpOptions
*
* interface HttpOptions {
* // 请求链接
* url: string;
* // query参数
* params?: Record<string, string>;
* // body数据
* data?: Record<string, any>;
* // 请求头
* headers?: Record<string, string>;
* // 请求方法 GET/POST
* method?: Method;
* }
*
* context上下文对象
*
* interface Content {
* app: TMagicApp;
* dataSource: HttpDataSource;
* }
*
* return: HttpOptions
*/
// 此处的返回值会作为这个接口的入参
return options;
}`,
afterResponse: `(response, context) => {
/**
* 用户可以直接编写函数,在原始接口返回之后,会运行该函数,将这个函数的返回值作为该数据源接口的返回
* context上下文对象
*
* interface Content {
* app: TMagicApp;
* dataSource: HttpDataSource;
* }
*
*/
// 此处的返回值会作为这个接口的返回值
return response;
}`,
...values,
};
};
export const getDisplayField = (dataSources: DataSourceSchema[], key: string) => {
const displayState: { value: string; type: 'var' | 'text' }[] = [];
// 匹配es6字符串模块
const matches = key.matchAll(dataSourceTemplateRegExp);
let index = 0;
for (const match of matches) {
if (typeof match.index === 'undefined') break;
// 字符串常量
displayState.push({
type: 'text',
value: key.substring(index, match.index),
});
let dsText = '';
let ds: DataSourceSchema | undefined;
let fields: DataSchema[] | undefined;
// 将模块解析成数据源对应的值
getKeysArray(match[1]).forEach((item, index) => {
if (index === 0) {
ds = dataSources.find((ds) => ds.id === item);
dsText += ds?.title || item;
fields = ds?.fields;
return;
}
if (isNumber(item)) {
dsText += `[${item}]`;
} else {
const field = fields?.find((field) => field.name === item);
fields = field?.fields;
dsText += `.${field?.title || item}`;
}
});
displayState.push({
type: 'var',
value: dsText,
});
index = match.index + match[0].length;
}
if (index < key.length) {
displayState.push({
type: 'text',
value: key.substring(index),
});
}
return displayState;
};
export const getCascaderOptionsFromFields = (
fields: DataSchema[] = [],
dataSourceFieldType: DataSourceFieldType[] = ['any'],
): CascaderOption[] => {
const child: CascaderOption[] = [];
fields.forEach((field) => {
if (!dataSourceFieldType.length) {
dataSourceFieldType.push('any');
}
let children: CascaderOption[] = [];
if (field.type && ['any', 'array', 'object'].includes(field.type)) {
children = getCascaderOptionsFromFields(field.fields, dataSourceFieldType);
}
const item = {
label: `${field.title || field.name}(${field.type})`,
value: field.name,
children,
};
const fieldType = field.type || 'any';
if (dataSourceFieldType.includes('any') || dataSourceFieldType.includes(fieldType)) {
child.push(item);
return;
}
if (!dataSourceFieldType.includes(fieldType) && !['array', 'object', 'any'].includes(fieldType)) {
return;
}
if (!children.length && ['object', 'array', 'any'].includes(field.type || '')) {
return;
}
child.push(item);
});
return child;
};
export const removeDataSourceFieldPrefix = (id?: string) =>
id?.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, '') || '';