diff --git a/src/components/ApiTest/index.vue b/src/components/ApiTest/index.vue
index 9fab685..33260ce 100644
--- a/src/components/ApiTest/index.vue
+++ b/src/components/ApiTest/index.vue
@@ -742,7 +742,7 @@
console.log('ApiTest: 当前映射关系: 1=xml, 2=form-urlencoded, 3=json, 4=form-data');
console.log('ApiTest: 如果不对,请告诉我接口明细显示什么和应该映射到什么!');
} else {
- // 如果没有contentType,默认设置为json,因为我们有inParams数据
+ // 如果没有contentType,默认设置为json
newBodyType = 'json';
console.log('ApiTest: no contentType found, defaulting bodyType to json');
}
@@ -766,93 +766,7 @@
}, 100);
});
- // 4. 设置请求容器的Demo数据(从接口对象的 inParams 中读取)
- console.log('ApiTest: checking for inParams in interface...');
- console.log('ApiTest: newInterface has inParams:', !!newInterface.inParams);
- console.log('ApiTest: newInterface.inParams type:', typeof newInterface.inParams);
- console.log('ApiTest: current bodyType:', bodyConfig.bodyType);
-
- if (newInterface.inParams) {
- console.log('ApiTest: found inParams in interface, processing...');
- console.log('ApiTest: inParams length:', newInterface.inParams.length);
- console.log('ApiTest: inParams preview:', newInterface.inParams.substring(0, 200));
-
- // 始终将处理后的inParams数据显示在CodeMirror中(用于显示demo数据)
- const processedInParams = processInParamsData(newInterface.inParams);
- bodyConfig.body = processedInParams;
- console.log('ApiTest: always set bodyConfig.body with processed inParams for display, length:', processedInParams.length);
-
- // 根据不同的bodyType设置相应的容器数据(用于请求发送)
- if (bodyConfig.bodyType === 'x-www-form-urlencoded') {
- // 对于x-www-form-urlencoded,将JSON数据转换为表格数据
- console.log('ApiTest: processing for x-www-form-urlencoded bodyType');
- try {
- const rawData = newInterface.inParams.replace(/\\r\\n/g, '\n').replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/\\t/g, '\t').replace(/\\\\/g, '\\').replace(/\\"/g, '"');
- console.log('ApiTest: processed raw data length:', rawData.length);
-
- const parsedData = JSON5.parse(rawData);
- console.log('ApiTest: parsed JSON successfully');
-
- const flattenedData = flattenJsonToKeyValuePairs(parsedData);
- console.log('ApiTest: flattened to', flattenedData.length, 'key-value pairs');
-
- const tableData = flattenedData.map(item => ({
- id: random(0, 2099999999),
- name: item.key,
- type: 1, // string类型
- value: String(item.value),
- description: item.description || ''
- }));
-
- urlEncodedTableProps.data = tableData;
-
- console.log('ApiTest: set urlEncoded table data with', urlEncodedTableProps.data.length, 'items');
- console.log('ApiTest: first 3 items:', urlEncodedTableProps.data.slice(0, 3));
- console.log('ApiTest: urlEncodedTableProps.data is reactive:', isReactive(urlEncodedTableProps.data));
- console.log('ApiTest: current urlEncodedTableProps.data:', urlEncodedTableProps.data);
-
- // 强制更新UI
- nextTick(() => {
- console.log('ApiTest: nextTick - table data should be updated');
- });
- } catch (error) {
- console.warn('ApiTest: failed to parse inParams for urlEncoded:', error);
- console.warn('ApiTest: error details:', error instanceof Error ? error.message : String(error));
- }
-
- } else if (bodyConfig.bodyType === 'form-data') {
- // 对于form-data,将JSON数据转换为表格数据
- console.log('ApiTest: processing for form-data bodyType');
- try {
- const rawData = newInterface.inParams.replace(/\\r\\n/g, '\n').replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/\\t/g, '\t').replace(/\\\\/g, '\\').replace(/\\"/g, '"');
- const parsedData = JSON5.parse(rawData);
- const flattenedData = flattenJsonToKeyValuePairs(parsedData);
-
- formDataTableProps.data = flattenedData.map(item => ({
- id: random(0, 2099999999),
- name: item.key,
- type: 1, // string类型
- value: String(item.value),
- description: item.description || ''
- }));
-
- console.log('ApiTest: set formData table data with', formDataTableProps.data.length, 'items');
- } catch (error) {
- console.warn('ApiTest: failed to parse inParams for formData:', error);
- }
-
- } else if (bodyConfig.bodyType === 'raw') {
- // 对于raw类型,直接显示处理后的数据
- console.log('ApiTest: processing for raw bodyType');
- bodyConfig.rawBody = processedInParams;
- console.log('ApiTest: set bodyConfig.rawBody with processed inParams');
- } else {
- console.log('ApiTest: bodyType is json/xml/raw, using CodeMirror display');
- }
- } else {
- console.log('ApiTest: no inParams found in interface');
- console.log('ApiTest: available fields in newInterface:', Object.keys(newInterface));
- }
+ // 4. 不再从接口明细的 inParams/curl 示例加载 body 数据,body 仅通过「导入cURL」或「调试」按钮导入的 cURL 的 --data-raw 显示
// 5. 设置 Header 和 Query 的默认值(只在启用默认值且为空时设置)
console.log('ApiTest: in watch, enableDefaults:', props.enableDefaults);
@@ -958,22 +872,17 @@
}
- // 导入 cURL
- const importCurl = () => {
- // 使用Modal显示输入框让用户输入cURL命令
- const curlInput = ref('');
- const modalVisible = ref(true);
-
- const parseCurl = (curlCommand: string) => {
+ // 解析并导入 cURL 命令(可被外部调用)
+ function parseCurlCommand(curlCommand: string) {
try {
console.log('Parsing cURL command:', curlCommand);
// 清理命令,但保留数据部分的多行结构
let cleanCurl = curlCommand.trim();
- // 先处理多行命令的连接(反斜杠+换行符)
- // 注意:要先处理 \r\n,再处理 \n;这里统一用 \r?\n
+ // 先处理多行命令的连接:Linux/Mac 用 \,Windows 用 ^
cleanCurl = cleanCurl.replace(/\\\s*\r?\n\s*/g, ' ');
+ cleanCurl = cleanCurl.replace(/\^\s*\r?\n\s*/g, ' ');
// 移除多余的空格,但保留数据部分
cleanCurl = cleanCurl.replace(/\s+/g, ' ');
@@ -1086,39 +995,52 @@
}
}
- // 查找--data-raw
- const dataRawIndex = cleanCurl.indexOf('--data-raw');
-
- if (dataRawIndex !== -1) {
- // 找到--data-raw的位置
- const dataPart = cleanCurl.substring(dataRawIndex + '--data-raw'.length).trim();
- console.log('Found --data-raw part:', dataPart.substring(0, 200) + '...');
-
- // 检查是否有引号包围
- if (dataPart.startsWith("'") || dataPart.startsWith('"')) {
- const quote = dataPart.charAt(0);
- const endQuoteIndex = dataPart.indexOf(quote, 1);
- if (endQuoteIndex !== -1) {
- bodyData = dataPart.substring(1, endQuoteIndex);
- console.log('Extracted quoted data-raw:', bodyData.substring(0, 100) + '...');
+ // 查找--data-raw(支持双引号/单引号内含转义 \" 的 JSON,逐字符解析确保正确匹配结束引号)
+ function extractDataRawValue(str: string): string | null {
+ const idx = str.indexOf('--data-raw');
+ if (idx === -1) return null;
+ let part = str.substring(idx + '--data-raw'.length).trim();
+ if (!part) return null;
+ if (part.startsWith('"')) {
+ let result = '';
+ for (let i = 1; i < part.length; i++) {
+ if (part[i] === '\\' && i + 1 < part.length) {
+ result += part[i] + part[i + 1];
+ i++;
+ continue;
+ }
+ if (part[i] === '"') return result;
+ result += part[i];
}
- } else {
- // 没有引号,找到下一个--或行尾
- const nextFlagIndex = dataPart.search(/\s--/);
- if (nextFlagIndex !== -1) {
- bodyData = dataPart.substring(0, nextFlagIndex).trim();
- } else {
- bodyData = dataPart.trim();
- }
- console.log('Extracted unquoted data-raw:', bodyData.substring(0, 100) + '...');
+ return null;
}
- } else {
- // 检查是否有--data
+ if (part.startsWith("'")) {
+ let result = '';
+ for (let i = 1; i < part.length; i++) {
+ if (part[i] === '\\' && i + 1 < part.length) {
+ result += part[i] + part[i + 1];
+ i++;
+ continue;
+ }
+ if (part[i] === "'") return result;
+ result += part[i];
+ }
+ return null;
+ }
+ const nextFlag = part.search(/\s--/);
+ return (nextFlag !== -1 ? part.substring(0, nextFlag) : part).trim() || null;
+ }
+ const extracted = extractDataRawValue(cleanCurl);
+ if (extracted !== null) {
+ bodyData = extracted.replace(/\\"/g, '"');
+ console.log('Extracted data-raw:', bodyData.substring(0, 100) + '...');
+ }
+
+ // 若仍未解析到 body,尝试 --data(非 --data-raw)
+ if (!bodyData && !cleanCurl.includes('--data-raw')) {
const dataIndex = cleanCurl.indexOf('--data');
if (dataIndex !== -1) {
const dataPart = cleanCurl.substring(dataIndex + '--data'.length).trim();
- console.log('Found --data part:', dataPart.substring(0, 50) + '...');
-
if (dataPart.startsWith("'") || dataPart.startsWith('"')) {
const quote = dataPart.charAt(0);
const endQuoteIndex = dataPart.indexOf(quote, 1);
@@ -1126,7 +1048,6 @@
bodyData = dataPart.substring(1, endQuoteIndex);
}
}
- console.log('Extracted data:', bodyData.substring(0, 100) + '...');
}
}
@@ -1175,15 +1096,48 @@
urlEncodedTableProps.data = formData;
console.log('Set as form-urlencoded from --data-urlencode with', formData.length, 'params');
} else if (bodyData) {
- // 根据Content-Type设置bodyType
+ // 根据 Content-Type 或内容推断 bodyType
+ let inferredType: 'json' | 'xml' | 'x-www-form-urlencoded' | 'form-data' | 'raw' = 'raw';
if (contentType.includes('application/json')) {
- bodyConfig.bodyType = 'json';
- // 对JSON数据进行格式化
- bodyConfig.body = processInParamsData(bodyData);
- console.log('Set as formatted JSON body');
+ inferredType = 'json';
+ } else if (contentType.includes('application/xml') || contentType.includes('text/xml')) {
+ inferredType = 'xml';
} else if (contentType.includes('application/x-www-form-urlencoded')) {
+ inferredType = 'x-www-form-urlencoded';
+ } else if (contentType.includes('multipart/form-data')) {
+ inferredType = 'form-data';
+ } else {
+ // 无 Content-Type 时根据内容推断
+ const trimmed = bodyData.trim();
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
+ try {
+ JSON5.parse(trimmed);
+ inferredType = 'json';
+ } catch {
+ inferredType = 'raw';
+ }
+ } else if (trimmed.startsWith(']/.test(trimmed))) {
+ inferredType = 'xml';
+ } else if (trimmed.includes('=') && !trimmed.startsWith('<')) {
+ try {
+ const params = new URLSearchParams(trimmed);
+ if (params.toString()) inferredType = 'x-www-form-urlencoded';
+ } catch {
+ /* keep raw */
+ }
+ }
+ }
+
+ if (inferredType === 'json') {
+ bodyConfig.bodyType = 'json';
+ bodyConfig.body = processInParamsData(bodyData);
+ console.log('Set as JSON body (from Content-Type or inferred)');
+ } else if (inferredType === 'xml') {
+ bodyConfig.bodyType = 'xml';
+ bodyConfig.body = bodyData;
+ console.log('Set as XML body (from Content-Type or inferred)');
+ } else if (inferredType === 'x-www-form-urlencoded') {
bodyConfig.bodyType = 'x-www-form-urlencoded';
- // 解析form data
try {
const formData: any[] = [];
const params = new URLSearchParams(bodyData);
@@ -1203,7 +1157,7 @@
bodyConfig.bodyType = 'raw';
bodyConfig.rawBody = bodyData;
}
- } else if (contentType.includes('multipart/form-data')) {
+ } else if (inferredType === 'form-data') {
bodyConfig.bodyType = 'form-data';
bodyConfig.body = bodyData;
console.log('Set as form-data');
@@ -1236,10 +1190,12 @@
console.error('cURL parsing error:', error);
Message.error(`cURL命令解析失败: ${error instanceof Error ? error.message : String(error)}`);
}
- };
+ }
- // 显示Modal
- const modal = Modal.confirm({
+ // 导入 cURL(打开 Modal 让用户粘贴)
+ const importCurl = () => {
+ const curlInput = ref('');
+ Modal.confirm({
title: '导入 cURL 命令',
content: () => h('div', [
h('p', { style: 'margin-bottom: 16px' }, '请粘贴完整的 cURL 命令:'),
@@ -1269,7 +1225,7 @@
Message.warning('请输入 cURL 命令');
return false;
}
- parseCurl(curlInput.value.trim());
+ parseCurlCommand(curlInput.value.trim());
return true;
},
onCancel: () => {
@@ -1633,6 +1589,12 @@
});
return formatted.substring(1, formatted.length - 3);
}
+
+ defineExpose({
+ importCurlFromString: (curl: string) => {
+ if (curl && curl.trim()) parseCurlCommand(curl.trim());
+ },
+ });
diff --git a/src/components/InterfaceDetail/index.vue b/src/components/InterfaceDetail/index.vue
index f3af015..a8f0081 100644
--- a/src/components/InterfaceDetail/index.vue
+++ b/src/components/InterfaceDetail/index.vue
@@ -1,6 +1,6 @@
@@ -789,7 +790,11 @@
:interface-id="tableForm.id"
:service-provider-id="tableForm.serviceProviderId"
@update:basic-form-data="(val) => Object.assign(tableForm, val)"
- />
+ >
+
+