openapi-ts-request icon indicating copy to clipboard operation
openapi-ts-request copied to clipboard

apifox 返回的类型名称带数字,请教一下是什么原因,应该是apifox的问题

Open eamd-wq opened this issue 6 months ago • 5 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Current Behavior

apifox 返回的 json 中,类型被自带了一个数字,而且后端每次重新同步这个接口,数字还会变化 请教下这种问题是否有遇到,能否通过openapi-ts-request来解决

Image

Expected Behavior

No response

Steps To Reproduce

使用apifox的方式,并且使用includesPaths来控制生成哪些接口

Environment

windows macos

Additional context

No response

eamd-wq avatar Oct 16 '25 11:10 eamd-wq

理论上是可以的

apifox返回的数据,到openapi-ts-request是可以修改的,你可以看看下面两个api,https://github.com/openapi-ui/openapi-ts-request?tab=readme-ov-file#Custom-Hook

  • hook.afterOpenApiDataInited 直接改openapi.json文件
  • hook.customRenderTemplateData 直接改最后渲染模板的数据

rookie-luochao avatar Oct 17 '25 01:10 rookie-luochao

我本地通过pnpm patch做了补丁;解决方式就是把apifox的结尾数字给去掉,然后重复的类型自己再去做一个索引数字,这个数字起码是稳定的,待我用一段稳定的情况下提交一个pr

patch文件如下:

diff --git a/dist/generator/serviceGenarator.js b/dist/generator/serviceGenarator.js
index 57ea7e712cf57373caf58734fd67aba3be35e524..fe1fa6efee07fd2ed259c767d19390df672e1fbf 100644
--- a/dist/generator/serviceGenarator.js
+++ b/dist/generator/serviceGenarator.js
@@ -181,6 +181,10 @@ class ServiceGenerator {
         // 处理重复的 typeName
         this.interfaceTPConfigs = this.getInterfaceTPConfigs();
         (0, util_2.handleDuplicateTypeNames)(this.interfaceTPConfigs);
+
+        // 处理apifox生成的数字
+        (0, util_2.handleApifoxTypeNamesIndex)(this.interfaceTPConfigs);
+
         // 生成 ts 类型声明
         if (!isGenJavaScript) {
             this.genFileFromTemplate(`${config_2.interfaceFileName}.ts`, config_2.TypescriptFileType.interface, {
diff --git a/dist/generator/util.d.ts b/dist/generator/util.d.ts
index e12c174adff041eb22bbe367a6c89c3a1d4dde81..3d9761517348707e0d59326c13f7604fdfdc7157 100644
--- a/dist/generator/util.d.ts
+++ b/dist/generator/util.d.ts
@@ -7,6 +7,7 @@ export declare function getLastRefName(refPath?: string): string;
 export declare function getDefaultType(schemaObject?: ISchemaObject | string, namespace?: string, schemas?: ComponentsObject['schemas']): string;
 export declare function getDefaultFileTag(operationObject: OperationObject, apiPath: string): string[];
 export declare function handleDuplicateTypeNames(interfaceTPConfigs: Array<Pick<ITypeItem, 'typeName' | 'displayLabelFuncName'>>): void;
+export declare function handleApifoxTypeNamesIndex(interfaceTPConfigs: Array<Pick<ITypeItem, 'typeName' | 'displayLabelFuncName'>>): void;
 export declare function getBasePrefix(paths: string[]): string;
 export declare function genDefaultFunctionName(path: string, pathBasePrefix: string): string;
 export declare function getFinalFileName(s: string): string;
diff --git a/dist/generator/util.js b/dist/generator/util.js
index 0d3d1a80d7072fc99e73718f4a4180e4723bbbc4..639f7c02b4a067a40368981a5814766e3add73f2 100644
--- a/dist/generator/util.js
+++ b/dist/generator/util.js
@@ -8,6 +8,7 @@ exports.getLastRefName = getLastRefName;
 exports.getDefaultType = getDefaultType;
 exports.getDefaultFileTag = getDefaultFileTag;
 exports.handleDuplicateTypeNames = handleDuplicateTypeNames;
+exports.handleApifoxTypeNamesIndex = handleApifoxTypeNamesIndex;
 exports.getBasePrefix = getBasePrefix;
 exports.genDefaultFunctionName = genDefaultFunctionName;
 exports.getFinalFileName = getFinalFileName;
@@ -229,7 +230,7 @@ function findDuplicateTypeNames(arr) {
     return duplicates;
 }
 function handleDuplicateTypeNames(interfaceTPConfigs) {
-    const duplicateTypeNames = findDuplicateTypeNames((0, lodash_1.map)(interfaceTPConfigs, (item) => item.typeName));
+    const duplicateTypeNames = findDuplicateTypeNames((0, lodash_1.map)(interfaceTPConfigs, (item) => item.typeName.replace(/\d+$/, '')));
     if (!(0, lodash_1.isEmpty)(duplicateTypeNames)) {
         (0, lodash_1.forEach)(duplicateTypeNames, (typeName) => {
             const selectInterfaceTPConfigs = (0, lodash_1.filter)(interfaceTPConfigs, (interfaceTP) => interfaceTP.typeName === typeName);
@@ -244,6 +245,41 @@ function handleDuplicateTypeNames(interfaceTPConfigs) {
         });
     }
 }
+// 处理Apifox类型有数字的问题
+function handleApifoxTypeNamesIndex(interfaceTPConfigs) {
+    // 更改typeName并收集映射关系
+    const typeNameMap = {}
+    interfaceTPConfigs.forEach((interfaceTP) => {
+        if(!/\d+$/.test(interfaceTP.typeName)) return
+        const typeName = interfaceTP.typeName.replace(/\d+$/, '');
+        const selectInterfaceTPConfigs = interfaceTPConfigs.filter((interfaceTP) => interfaceTP.typeName.replace(/\d+$/, '') === typeName);
+        
+        if(selectInterfaceTPConfigs.length <= 1){
+            typeNameMap[interfaceTP.typeName] = typeName
+            interfaceTP.typeName = typeNameMap[interfaceTP.typeName];
+            return
+        }
+        selectInterfaceTPConfigs.sort()
+        selectInterfaceTPConfigs.forEach((interfaceTP, index) => {
+            if (index >= 1) {
+                typeNameMap[interfaceTP.typeName] = `${typeName}${index + 1}`
+                interfaceTP.typeName = typeNameMap[interfaceTP.typeName];
+            }
+        });
+    });
+    // 替换引用时的对应类型
+    interfaceTPConfigs.forEach((interfaceTP) => {
+        if(interfaceTP.props?.length){
+            interfaceTP.props.flat().forEach((propsItem) => {
+                Object.keys(typeNameMap).forEach((key) => {
+                    if(propsItem.type?.includes(key)){
+                        propsItem.type = propsItem.type.replace(key, typeNameMap[key]);
+                    }
+                })
+            });
+        }
+    });
+}
 // 检测所有path重复区域(prefix)
 function getBasePrefix(paths) {
     const arr = [];

eamd-wq avatar Oct 17 '25 08:10 eamd-wq

apifox的数据类型错误怕是要自己处理哦,而不是丢给工具?

你确定是apifox的返回的类型带数字?

有可能type重复了,工具对重复type做了索引自增

rookie-luochao avatar Oct 17 '25 10:10 rookie-luochao

你这个type类型带数字的问题确实是apifox的问题,不是openapi-ts-request的

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: shuang @.> 发送时间: 2025年10月17日 16:05 收件人: openapi-ui/openapi-ts-request @.> 抄送: 故城 @.>, Comment @.> 主题: Re: [openapi-ui/openapi-ts-request] apifox 返回的类型名称带数字,请教一下是什么原因,应该是apifox的问题 (Issue #529)

eamd-wq left a comment (openapi-ui/openapi-ts-request#529)

我本地通过pnpm patch做了补丁;解决方式就是把apifox的结尾数字给去掉,然后重复的类型自己再去做一个索引数字,这个数字起码是稳定的,待我用一段稳定的情况下提交一个pr

patch文件如下: diff --git a/dist/generator/serviceGenarator.js b/dist/generator/serviceGenarator.js index 57ea7e712cf57373caf58734fd67aba3be35e524..fe1fa6efee07fd2ed259c767d19390df672e1fbf 100644 --- a/dist/generator/serviceGenarator.js +++ b/dist/generator/serviceGenarator.js @@ -181,6 +181,10 @@ class ServiceGenerator { // 处理重复的 typeName this.interfaceTPConfigs = this.getInterfaceTPConfigs(); (0, util_2.handleDuplicateTypeNames)(this.interfaceTPConfigs); + + // 处理apifox生成的数字 + (0, util_2.handleApifoxTypeNamesIndex)(this.interfaceTPConfigs); + // 生成 ts 类型声明 if (!isGenJavaScript) { this.genFileFromTemplate(${config_2.interfaceFileName}.ts, config_2.TypescriptFileType.interface, { diff --git a/dist/generator/util.d.ts b/dist/generator/util.d.ts index e12c174adff041eb22bbe367a6c89c3a1d4dde81..3d9761517348707e0d59326c13f7604fdfdc7157 100644 --- a/dist/generator/util.d.ts +++ b/dist/generator/util.d.ts @@ -7,6 +7,7 @@ export declare function getLastRefName(refPath?: string): string; export declare function getDefaultType(schemaObject?: ISchemaObject | string, namespace?: string, schemas?: ComponentsObject['schemas']): string; export declare function getDefaultFileTag(operationObject: OperationObject, apiPath: string): string[]; export declare function handleDuplicateTypeNames(interfaceTPConfigs: Array<Pick<ITypeItem, 'typeName' | 'displayLabelFuncName'>>): void; +export declare function handleApifoxTypeNamesIndex(interfaceTPConfigs: Array<Pick<ITypeItem, 'typeName' | 'displayLabelFuncName'>>): void; export declare function getBasePrefix(paths: string[]): string; export declare function genDefaultFunctionName(path: string, pathBasePrefix: string): string; export declare function getFinalFileName(s: string): string; diff --git a/dist/generator/util.js b/dist/generator/util.js index 0d3d1a80d7072fc99e73718f4a4180e4723bbbc4..639f7c02b4a067a40368981a5814766e3add73f2 100644 --- a/dist/generator/util.js +++ b/dist/generator/util.js @@ -8,6 +8,7 @@ exports.getLastRefName = getLastRefName; exports.getDefaultType = getDefaultType; exports.getDefaultFileTag = getDefaultFileTag; exports.handleDuplicateTypeNames = handleDuplicateTypeNames; +exports.handleApifoxTypeNamesIndex = handleApifoxTypeNamesIndex; exports.getBasePrefix = getBasePrefix; exports.genDefaultFunctionName = genDefaultFunctionName; exports.getFinalFileName = getFinalFileName; @@ -229,7 +230,7 @@ function findDuplicateTypeNames(arr) { return duplicates; } function handleDuplicateTypeNames(interfaceTPConfigs) { - const duplicateTypeNames = findDuplicateTypeNames((0, lodash_1.map)(interfaceTPConfigs, (item) => item.typeName)); + const duplicateTypeNames = findDuplicateTypeNames((0, lodash_1.map)(interfaceTPConfigs, (item) => item.typeName.replace(/\d+$/, ''))); if (!(0, lodash_1.isEmpty)(duplicateTypeNames)) { (0, lodash_1.forEach)(duplicateTypeNames, (typeName) => { const selectInterfaceTPConfigs = (0, lodash_1.filter)(interfaceTPConfigs, (interfaceTP) => interfaceTP.typeName === typeName); @@ -244,6 +245,41 @@ function handleDuplicateTypeNames(interfaceTPConfigs) { }); } } +// 处理Apifox类型有数字的问题 +function handleApifoxTypeNamesIndex(interfaceTPConfigs) { + // 更改typeName并收集映射关系 + const typeNameMap = {} + interfaceTPConfigs.forEach((interfaceTP) => { + if(!/\d+$/.test(interfaceTP.typeName)) return + const typeName = interfaceTP.typeName.replace(/\d+$/, ''); + const selectInterfaceTPConfigs = interfaceTPConfigs.filter((interfaceTP) => interfaceTP.typeName.replace(/\d+$/, '') === typeName); + + if(selectInterfaceTPConfigs.length <= 1){ + typeNameMap[interfaceTP.typeName] = typeName + interfaceTP.typeName = typeNameMap[interfaceTP.typeName]; + return + } + selectInterfaceTPConfigs.sort() + selectInterfaceTPConfigs.forEach((interfaceTP, index) => { + if (index >= 1) { + typeNameMap[interfaceTP.typeName] = ${typeName}${index + 1} + interfaceTP.typeName = typeNameMap[interfaceTP.typeName]; + } + }); + }); + // 替换引用时的对应类型 + interfaceTPConfigs.forEach((interfaceTP) => { + if(interfaceTP.props?.length){ + interfaceTP.props.flat().forEach((propsItem) => { + Object.keys(typeNameMap).forEach((key) => { + if(propsItem.type?.includes(key)){ + propsItem.type = propsItem.type.replace(key, typeNameMap[key]); + } + }) + }); + } + }); +} // 检测所有path重复区域(prefix) function getBasePrefix(paths) { const arr = [];
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

rookie-luochao avatar Oct 17 '25 10:10 rookie-luochao

是apifox的问题,我是请教看你有没有遇到,我通过工具做了处理兜底;但apifox这点确实不合理,数字的生成规则有问题;

我已经用patch做了处理,但觉得这种apifox的问题,工具做逻辑用来避免,也合理

eamd-wq avatar Oct 17 '25 10:10 eamd-wq