From 30d4c8a9da997efc3fe07222d9487783c05d5b84 Mon Sep 17 00:00:00 2001 From: zhangguoyun Date: Tue, 16 Dec 2025 17:36:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(ApifoxService):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=B0=86=E6=97=A5=E5=BF=97=E5=86=99=E5=85=A5=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=B9=B6=E5=88=9B=E5=BB=BA=E6=97=A5=E5=BF=97=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apifox.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/apifox.js b/apifox.js index 0f257df..b4ff793 100644 --- a/apifox.js +++ b/apifox.js @@ -1,15 +1,17 @@ import axios from "axios"; import NodeCache from 'node-cache'; -// import fs from 'fs' +import fs from 'fs'; +import path from 'path'; const APIFOX_API_BASE = "https://apifox.gzmiyuan.com/api/v1"; export class ApifoxService { constructor(config = {}) { - const { projectId, token, baseUrl } = config; + const { projectId, token, baseUrl, logFilePath } = config; this.projectId = projectId; this.branchId = null; this.apiTreeList = null; + this.logFilePath = logFilePath || path.join(process.cwd(), 'apifox-service.log'); this.http = axios.create({ baseURL: baseUrl || APIFOX_API_BASE, headers: { @@ -43,6 +45,50 @@ export class ApifoxService { } } + /** + * 写入日志到文件 + * @param {string} level - 日志级别 (INFO, ERROR, WARN, DEBUG) + * @param {string} message - 日志消息 + * @param {object} data - 可选的额外数据 + */ + logToFile(level, message, data = null) { + try { + const timestamp = new Date().toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }); + + let logLine = `[${timestamp}] ${level.toUpperCase()}: ${message}`; + + if (data) { + if (typeof data === 'object') { + logLine += `\n 数据: ${JSON.stringify(data, null, 2)}`; + } else { + logLine += `\n 数据: ${data}`; + } + } + + logLine += '\n'; + + // 确保日志目录存在 + const logDir = path.dirname(this.logFilePath); + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir, { recursive: true }); + } + + // 追加写入日志文件 + fs.appendFileSync(this.logFilePath, logLine); + + // 同时输出到控制台 + } catch (error) { + console.error('写入日志失败:', error); + } + } + /** * 初始化服务,获取branchId * @returns {Promise} @@ -264,14 +310,33 @@ export class ApifoxService { const requestSchemaId = this.getSchemaRefId(apiDetail.requestBody.jsonSchema); const responseSchema = Array.isArray(apiDetail.responses) ? apiDetail.responses[0].jsonSchema : apiDetail.responses.jsonSchema; const responseSchemaId = this.getSchemaRefId(responseSchema); - const respDataSchemaId = this.getSchemaRefId(dataSchema.find((item) => item.id.toString() === responseSchemaId).jsonSchema.properties.data) + const responseDataSchema = dataSchema.find((item) => item.id.toString() === responseSchemaId).jsonSchema.properties.data; + + let respDataSchemaId; + const isArray = responseDataSchema.type === 'array'; + // 处理数组和对象两种情况 + if (isArray && responseDataSchema.items && responseDataSchema.items.$ref) { + // 数组情况:从 items.$ref 中提取 schema ID + respDataSchemaId = this.getSchemaRefId(responseDataSchema.items); + } else if (responseDataSchema.$ref) { + // 对象情况:直接从 $ref 中提取 schema ID + respDataSchemaId = this.getSchemaRefId(responseDataSchema); + } else { + // 如果都没有 $ref,记录警告并返回 null + this.logToFile('WARN', `无法从 responseDataSchema 中提取 schema ID`, responseDataSchema); + respDataSchemaId = null; + } + return { path: apiDetail.path, name: apiDetail.name, method: apiDetail.method, url: apiDetail.url, requestSchema: await this.getSchemaById(requestSchemaId), - responseSchema: await this.getSchemaById(respDataSchemaId), + responseSchema: isArray ? { + type: 'array', + items: respDataSchemaId ? await this.getSchemaById(respDataSchemaId) : null, + } : await this.getSchemaById(respDataSchemaId), }; }