/** * 将管理端 / 开放鉴权接口合并进 swagger.json(运行: node _docs/merge_biz_into_swagger.js) */ const fs = require("fs"); const path = require("path"); const swaggerPath = path.join(__dirname, "swagger.json"); const doc = JSON.parse(fs.readFileSync(swaggerPath, "utf8")); const TAG_ADMIN = ["管理端-业务订阅"]; const TAG_OPEN_AUTH = ["开放接口-鉴权"]; function res200() { return { 200: { description: "框架统一包装;成功时 code=0,业务数据在 data" } }; } function post(summary, ref, tags = TAG_ADMIN) { const params = [ { in: "body", name: "body", schema: ref ? { $ref: `#/definitions/${ref}` } : { type: "object", description: "JSON 请求体" }, }, ]; return { post: { tags, summary, parameters: params, responses: res200() } }; } function postEmpty(summary, tags = TAG_ADMIN) { return { post: { tags, summary, parameters: [], responses: res200() } }; } function get(summary, queryList, tags = TAG_ADMIN) { return { get: { tags, summary, parameters: queryList.map((q) => ({ in: "query", name: q.n, type: q.t || "string", required: q.req !== false, description: q.d || "", })), responses: res200(), }, }; } const definitions = { BizAdminPageRequest: { type: "object", title: "BizAdminPageRequest", description: "通用分页/筛选:body 可直接为 param,或形如 { param: { pageOption, seachOption } }", properties: { param: { type: "object", properties: { pageOption: { type: "object", properties: { page: { type: "integer", example: 1 }, pageSize: { type: "integer", example: 20 }, }, }, seachOption: { type: "object", properties: { key: { type: "string", description: "与模型字段名一致,如 user_id、status" }, value: { type: "string" }, }, }, }, }, }, }, BizIdRequest: { type: "object", title: "BizIdRequest", properties: { id: { type: "integer", format: "int64" } }, }, BizUserRevokeTokensRequest: { type: "object", title: "BizUserRevokeTokensRequest", properties: { user_id: { type: "integer", format: "int64", description: "与 id 二选一" }, id: { type: "integer", format: "int64" }, }, }, BizUserAddRequest: { type: "object", title: "BizUserAddRequest", description: "写入字段见 biz_user 模型;可选自动创建 Token", properties: { name: { type: "string" }, mobile: { type: "string" }, email: { type: "string" }, company_name: { type: "string" }, status: { type: "string", enum: ["active", "disabled"] }, auto_create_token: { type: "boolean", default: true }, initial_token_name: { type: "string" }, initial_token_expire_at: { type: "string", description: "如 2026-12-31 23:59:59" }, }, }, BizUserEditRequest: { type: "object", title: "BizUserEditRequest", properties: { id: { type: "integer", format: "int64" }, name: { type: "string" }, mobile: { type: "string" }, email: { type: "string" }, company_name: { type: "string" }, status: { type: "string", enum: ["active", "disabled"] }, }, required: ["id"], }, BizSubscriptionOpenRequest: { type: "object", title: "BizSubscriptionOpenRequest", required: ["user_id", "plan_id", "start_time", "end_time"], properties: { user_id: { type: "integer", format: "int64" }, plan_id: { type: "integer", format: "int64" }, start_time: { type: "string" }, end_time: { type: "string" }, status: { type: "string", enum: ["pending", "active", "expired", "cancelled"] }, renew_mode: { type: "string", enum: ["manual", "auto"] }, payment_channel: { type: "string", enum: ["offline", "pay_link"] }, payment_ref: { type: "string" }, }, }, BizSubscriptionUpgradeRequest: { type: "object", title: "BizSubscriptionUpgradeRequest", required: ["subscription_id", "new_plan_id"], properties: { subscription_id: { type: "integer", format: "int64" }, new_plan_id: { type: "integer", format: "int64" }, start_time: { type: "string" }, end_time: { type: "string" }, }, }, BizSubscriptionRenewRequest: { type: "object", title: "BizSubscriptionRenewRequest", required: ["subscription_id", "end_time"], properties: { subscription_id: { type: "integer", format: "int64" }, end_time: { type: "string" }, }, }, BizSubscriptionCancelRequest: { type: "object", title: "BizSubscriptionCancelRequest", required: ["subscription_id"], properties: { subscription_id: { type: "integer", format: "int64" } }, }, BizPaymentConfirmRequest: { type: "object", title: "BizPaymentConfirmRequest", required: ["subscription_id"], properties: { subscription_id: { type: "integer", format: "int64" }, payment_ref: { type: "string" }, }, }, BizTokenCreateRequest: { type: "object", title: "BizTokenCreateRequest", required: ["user_id", "expire_at"], properties: { user_id: { type: "integer", format: "int64" }, key: { type: "string", description: "账号唯一标识,可选" }, token_name: { type: "string" }, expire_at: { type: "string" }, }, }, BizTokenEditRequest: { type: "object", title: "BizTokenEditRequest", required: ["id"], properties: { id: { type: "integer", format: "int64" }, key: { type: "string", description: "可空表示清空" }, token_name: { type: "string" }, expire_at: { type: "string" }, }, }, BizTokenIdRequest: { type: "object", title: "BizTokenIdRequest", required: ["id"], properties: { id: { type: "integer", format: "int64" } }, }, BizApiStatsByUserRequest: { type: "object", title: "BizApiStatsByUserRequest", required: ["user_id"], properties: { user_id: { type: "integer", format: "int64" }, start_date: { type: "string", description: "DATEONLY YYYY-MM-DD" }, end_date: { type: "string" }, }, }, BizApiStatsByApiRequest: { type: "object", title: "BizApiStatsByApiRequest", required: ["api_path"], properties: { api_path: { type: "string" }, start_date: { type: "string" }, end_date: { type: "string" }, }, }, BizApiStatsSummaryRequest: { type: "object", title: "BizApiStatsSummaryRequest", properties: { start_date: { type: "string" }, end_date: { type: "string" }, top_limit: { type: "integer", example: 10 }, }, }, BizUsageWriteRequest: { type: "object", title: "BizUsageWriteRequest", description: "月度用量 biz_usage_monthly 字段", properties: { id: { type: "integer", format: "int64", description: "edit 必填" }, user_id: { type: "integer", format: "int64" }, plan_id: { type: "integer", format: "int64" }, stat_month: { type: "string", example: "2026-04" }, msg_count: { type: "integer" }, mass_count: { type: "integer" }, friend_count: { type: "integer" }, sns_count: { type: "integer" }, active_user_count: { type: "integer" }, api_call_count: { type: "integer" }, }, }, BizAuthVerifyRequest: { type: "object", title: "BizAuthVerifyRequest", required: ["token"], properties: { token: { type: "string", description: "明文 API Token" }, feature: { type: "string", description: "swagger 路径对应 tags[0],用于套餐功能点" }, api_path: { type: "string", description: "请求的接口 path,用于 allowed_apis 校验" }, usage_delta: { type: "object", description: "可选用量上报", properties: { msg: { type: "integer" }, mass: { type: "integer" }, friend: { type: "integer" }, sns: { type: "integer" }, active_user: { type: "integer" }, }, }, }, }, BizPlanWriteRequest: { type: "object", title: "BizPlanWriteRequest", description: "biz_plan 表字段;add 不需 id,edit 需 id", properties: { id: { type: "integer", format: "int64" }, plan_code: { type: "string" }, plan_name: { type: "string" }, monthly_price: { type: "number" }, auth_fee: { type: "number" }, account_limit: { type: "integer" }, active_user_limit: { type: "integer" }, msg_quota: { type: "integer" }, mass_quota: { type: "integer" }, friend_quota: { type: "integer" }, sns_quota: { type: "integer" }, allowed_apis: { description: "JSON:路径字符串数组", type: "array", items: { type: "string" } }, api_call_quota: { type: "integer" }, enabled_features: { type: "object", description: "JSON 功能点开关" }, status: { type: "string", enum: ["active", "inactive"] }, }, }, }; const paths = {}; paths["/admin_api/biz_api_call_log/page"] = post("API 调用明细分页", "BizAdminPageRequest"); paths["/admin_api/biz_api_call_log/export"] = post("API 调用明细导出", "BizAdminPageRequest"); paths["/admin_api/biz_api_stats/by_user"] = post("按用户统计接口调用", "BizApiStatsByUserRequest"); paths["/admin_api/biz_api_stats/by_api"] = post("按接口路径统计调用", "BizApiStatsByApiRequest"); paths["/admin_api/biz_api_stats/summary"] = post("调用量汇总与趋势", "BizApiStatsSummaryRequest"); paths["/admin_api/biz_audit_log/page"] = post("审计日志分页", "BizAdminPageRequest"); paths["/admin_api/biz_audit_log/export"] = post("审计日志导出", "BizAdminPageRequest"); paths["/admin_api/biz_dashboard/summary"] = get("订阅/用户/Token 看板汇总", [], TAG_ADMIN); paths["/admin_api/biz_payment/confirm-offline"] = post("确认线下支付(订阅置 active)", "BizPaymentConfirmRequest"); paths["/admin_api/biz_payment/confirm-link"] = post("确认链接支付", "BizPaymentConfirmRequest"); paths["/admin_api/biz_plan/page"] = post("套餐分页", "BizAdminPageRequest"); paths["/admin_api/biz_plan/add"] = post("新增套餐", "BizPlanWriteRequest"); paths["/admin_api/biz_plan/edit"] = post("编辑套餐", "BizPlanWriteRequest"); paths["/admin_api/biz_plan/del"] = post("删除套餐", "BizIdRequest"); paths["/admin_api/biz_plan/detail"] = get("套餐详情", [{ n: "id", req: true, d: "套餐 id" }]); paths["/admin_api/biz_plan/all"] = get("套餐列表(下拉,最多 2000 条)", []); paths["/admin_api/biz_plan/toggle"] = post("上下线切换", "BizIdRequest"); paths["/admin_api/biz_plan/export"] = post("套餐导出", "BizAdminPageRequest"); paths["/admin_api/biz_plan/proxy_api_catalog"] = postEmpty("转发接口目录(配置 allowed_apis)"); paths["/admin_api/biz_subscription/page"] = post("订阅分页(含 user_name、plan_name)", "BizAdminPageRequest"); paths["/admin_api/biz_subscription/detail"] = get("订阅详情", [{ n: "id", req: true }]); paths["/admin_api/biz_subscription/by_user"] = get("某用户订阅列表", [ { n: "user_id", req: true, d: "业务用户 id" }, ]); paths["/admin_api/biz_subscription/open"] = post("开通订阅", "BizSubscriptionOpenRequest"); paths["/admin_api/biz_subscription/upgrade"] = post("变更套餐/时间", "BizSubscriptionUpgradeRequest"); paths["/admin_api/biz_subscription/renew"] = post("续费(更新结束时间)", "BizSubscriptionRenewRequest"); paths["/admin_api/biz_subscription/cancel"] = post("取消订阅", "BizSubscriptionCancelRequest"); paths["/admin_api/biz_subscription/export"] = post("订阅导出 CSV 数据", "BizAdminPageRequest"); paths["/admin_api/biz_token/page"] = post("API Token 分页(不含 secret_cipher)", "BizAdminPageRequest"); paths["/admin_api/biz_token/create"] = post("创建 Token,返回 plain_token", "BizTokenCreateRequest"); paths["/admin_api/biz_token/edit"] = post("编辑 Token(名称/key/过期时间,不改密钥)", "BizTokenEditRequest"); paths["/admin_api/biz_token/revoke"] = post("吊销 Token", "BizTokenIdRequest"); paths["/admin_api/biz_token/regenerate"] = post("重新生成密钥(返回新 plain_token)", "BizTokenIdRequest"); paths["/admin_api/biz_token/export"] = post("Token 导出", "BizAdminPageRequest"); paths["/admin_api/biz_usage/page"] = post("月度用量分页", "BizAdminPageRequest"); paths["/admin_api/biz_usage/add"] = post("新增用量记录", "BizUsageWriteRequest"); paths["/admin_api/biz_usage/edit"] = post("编辑用量记录", "BizUsageWriteRequest"); paths["/admin_api/biz_usage/del"] = post("删除用量记录", "BizIdRequest"); paths["/admin_api/biz_usage/detail"] = get("用量详情", [{ n: "id", req: true }]); paths["/admin_api/biz_usage/export"] = post("用量导出", "BizAdminPageRequest"); paths["/admin_api/biz_user/page"] = post("业务用户分页(含 token_count)", "BizAdminPageRequest"); paths["/admin_api/biz_user/add"] = post("新增用户(可选自动创建 Token)", "BizUserAddRequest"); paths["/admin_api/biz_user/edit"] = post("编辑用户", "BizUserEditRequest"); paths["/admin_api/biz_user/del"] = post("删除用户", "BizIdRequest"); paths["/admin_api/biz_user/detail"] = get("用户详情(含 subscriptions、tokens[].plain_token)", [{ n: "id", req: true }]); paths["/admin_api/biz_user/all"] = get("全部用户(下拉)", []); paths["/admin_api/biz_user/disable"] = post("禁用用户", "BizIdRequest"); paths["/admin_api/biz_user/enable"] = post("启用用户", "BizIdRequest"); paths["/admin_api/biz_user/export"] = post("用户导出", "BizAdminPageRequest"); paths["/admin_api/biz_user/revoke_all_tokens"] = post("吊销用户下全部 Token", "BizUserRevokeTokensRequest"); paths["/admin_api/sys_file/upload_img"] = { post: { tags: TAG_ADMIN, summary: "本地上传图片(multipart/form-data)", consumes: ["multipart/form-data"], parameters: [], responses: res200(), }, }; paths["/admin_api/sys_file/upload_oos_img"] = { post: { tags: TAG_ADMIN, summary: "上传图片到 OSS(multipart)", consumes: ["multipart/form-data"], parameters: [], responses: res200(), }, }; paths["/api/auth/verify"] = { post: { tags: TAG_OPEN_AUTH, summary: "对外开放:Token 鉴权校验(含订阅/套餐/用量等)", parameters: [ { in: "body", name: "body", schema: { $ref: "#/definitions/BizAuthVerifyRequest" }, }, ], responses: res200(), }, }; Object.assign(doc.definitions, definitions); Object.assign(doc.paths, paths); const extraTags = [ { name: "管理端-业务订阅", description: "Base URL + /admin_api,需管理端登录" }, { name: "开放接口-鉴权", description: "Base URL + /api,如 /api/auth/verify" }, ]; for (const t of extraTags) { if (!doc.tags.some((x) => x.name === t.name)) { doc.tags.push(t); } } fs.writeFileSync(swaggerPath, JSON.stringify(doc, null, 4) + "\n", "utf8"); console.log("merged admin biz paths + definitions into swagger.json");