feat: Apifox风格API文档页面,替代MarkdownViewer平铺展示

This commit is contained in:
yumoqing 2026-06-01 13:26:46 +08:00
parent d65629afb2
commit afdbb2ed37
2 changed files with 936 additions and 27 deletions

932
wwwroot/api_doc.html Normal file
View File

@ -0,0 +1,932 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>元境 API 文档</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--bg-main: #1a1a2e;
--bg-sidebar: #16213e;
--bg-card: #1e2a47;
--bg-code: #0d1117;
--bg-table-row: #162038;
--bg-table-header: #1a2744;
--border: #2a3a5c;
--text-primary: #e0e6ed;
--text-secondary: #8899aa;
--text-muted: #5a6a7a;
--accent-blue: #4fc3f7;
--accent-green: #66bb6a;
--accent-orange: #ffa726;
--accent-red: #ef5350;
--accent-purple: #ab47bc;
--method-post: #66bb6a;
--method-get: #4fc3f7;
--hover-bg: #1e2d4a;
--sidebar-width: 280px;
}
html, body { height: 100%; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; background: var(--bg-main); color: var(--text-primary); font-size: 14px; }
/* Layout */
.app { display: flex; height: 100vh; overflow: hidden; }
/* Sidebar */
.sidebar { width: var(--sidebar-width); min-width: var(--sidebar-width); background: var(--bg-sidebar); border-right: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; }
.sidebar-header { padding: 20px; border-bottom: 1px solid var(--border); }
.sidebar-header h1 { font-size: 16px; font-weight: 600; color: var(--accent-blue); }
.sidebar-header .base-url { font-size: 11px; color: var(--text-muted); margin-top: 4px; font-family: monospace; }
.sidebar-nav { flex: 1; overflow-y: auto; padding: 8px 0; }
.sidebar-nav::-webkit-scrollbar { width: 4px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
.nav-group { margin-bottom: 4px; }
.nav-group-title { padding: 8px 16px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); cursor: pointer; display: flex; align-items: center; gap: 6px; user-select: none; }
.nav-group-title:hover { color: var(--text-secondary); }
.nav-group-title .arrow { transition: transform 0.2s; font-size: 10px; }
.nav-group.collapsed .arrow { transform: rotate(-90deg); }
.nav-group.collapsed .nav-items { display: none; }
.nav-item { padding: 7px 16px 7px 24px; cursor: pointer; display: flex; align-items: center; gap: 8px; transition: background 0.15s; border-left: 3px solid transparent; }
.nav-item:hover { background: var(--hover-bg); }
.nav-item.active { background: var(--hover-bg); border-left-color: var(--accent-blue); }
.nav-item .method { font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 3px; min-width: 36px; text-align: center; font-family: monospace; }
.nav-item .method.post { background: rgba(102,187,106,0.15); color: var(--method-post); }
.nav-item .method.get { background: rgba(79,195,247,0.15); color: var(--method-get); }
.nav-item .path { font-size: 12px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-item.active .path { color: var(--text-primary); }
/* Content */
.content { flex: 1; overflow-y: auto; padding: 0; }
.content::-webkit-scrollbar { width: 6px; }
.content::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.api-section { display: none; padding: 32px 40px; max-width: 960px; }
.api-section.active { display: block; }
.api-title { font-size: 22px; font-weight: 600; margin-bottom: 8px; display: flex; align-items: center; gap: 12px; }
.api-title .method-badge { font-size: 13px; font-weight: 700; padding: 4px 10px; border-radius: 4px; font-family: monospace; }
.api-title .method-badge.post { background: rgba(102,187,106,0.2); color: var(--method-post); }
.api-title .method-badge.get { background: rgba(79,195,247,0.2); color: var(--method-get); }
.api-title .endpoint { font-family: monospace; color: var(--text-primary); }
.api-desc { color: var(--text-secondary); margin-bottom: 24px; font-size: 14px; line-height: 1.6; }
/* Sections */
.section-title { font-size: 14px; font-weight: 600; color: var(--text-primary); margin: 24px 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.subsection-title { font-size: 13px; font-weight: 600; color: var(--accent-blue); margin: 20px 0 10px; }
/* Parameter Table */
.param-table { width: 100%; border-collapse: collapse; margin-bottom: 16px; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.param-table th { background: var(--bg-table-header); padding: 10px 14px; text-align: left; font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.3px; }
.param-table td { padding: 10px 14px; border-top: 1px solid var(--border); font-size: 13px; vertical-align: top; }
.param-table tr:nth-child(even) td { background: var(--bg-table-row); }
.param-table .param-name { font-family: monospace; color: var(--accent-orange); font-weight: 500; }
.param-table .param-type { color: var(--accent-purple); font-family: monospace; font-size: 12px; }
.param-table .param-required { color: var(--accent-red); font-size: 11px; font-weight: 600; }
.param-table .param-optional { color: var(--text-muted); font-size: 11px; }
/* Code Blocks */
.code-block { margin: 12px 0 16px; border-radius: 8px; overflow: hidden; border: 1px solid var(--border); }
.code-header { background: #0d1117; padding: 8px 14px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); }
.code-header .lang { font-size: 11px; color: var(--text-muted); text-transform: uppercase; font-weight: 600; }
.code-header .copy-btn { background: none; border: 1px solid var(--border); color: var(--text-muted); padding: 3px 10px; border-radius: 4px; cursor: pointer; font-size: 11px; transition: all 0.15s; }
.code-header .copy-btn:hover { color: var(--text-primary); border-color: var(--text-secondary); }
.code-block pre { margin: 0; padding: 16px; background: var(--bg-code); overflow-x: auto; }
.code-block code { font-family: "SF Mono", "Fira Code", "Consolas", monospace; font-size: 13px; line-height: 1.5; }
/* Info Box */
.info-box { padding: 12px 16px; border-radius: 6px; margin: 12px 0; font-size: 13px; line-height: 1.5; }
.info-box.note { background: rgba(79,195,247,0.1); border-left: 3px solid var(--accent-blue); color: var(--text-secondary); }
.info-box.warn { background: rgba(255,167,38,0.1); border-left: 3px solid var(--accent-orange); color: var(--text-secondary); }
/* Welcome page */
.welcome { padding: 60px 40px; max-width: 700px; }
.welcome h2 { font-size: 28px; font-weight: 700; margin-bottom: 12px; }
.welcome p { color: var(--text-secondary); line-height: 1.7; margin-bottom: 16px; }
.welcome .feature-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 24px; }
.welcome .feature-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 16px; }
.welcome .feature-card h4 { font-size: 13px; margin-bottom: 6px; color: var(--accent-blue); }
.welcome .feature-card p { font-size: 12px; color: var(--text-muted); margin: 0; }
/* Model sub-nav */
.model-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0; }
.model-tab { padding: 5px 12px; border-radius: 4px; font-size: 12px; cursor: pointer; background: var(--bg-card); border: 1px solid var(--border); color: var(--text-secondary); transition: all 0.15s; }
.model-tab:hover { border-color: var(--accent-blue); color: var(--text-primary); }
.model-tab.active { background: rgba(79,195,247,0.15); border-color: var(--accent-blue); color: var(--accent-blue); }
.model-detail { display: none; }
.model-detail.active { display: block; }
</style>
</head>
<body>
<div class="app">
<!-- Sidebar -->
<div class="sidebar">
<div class="sidebar-header">
<h1>元境 API</h1>
<div class="base-url">https://token.opencomputing.cn</div>
</div>
<div class="sidebar-nav" id="sidebarNav"></div>
</div>
<!-- Content -->
<div class="content" id="contentArea"></div>
</div>
<script>
// ===== API Data =====
const apiData = [
{
group: "大模型 API",
items: [
{
id: "chat-completions",
method: "POST",
path: "/llmage/v1/chat/completions",
title: "文本生成",
desc: "文本生成接口,兼容 OpenAI 格式。支持流式和非流式输出。",
params: [
{ section: "必填参数", rows: [
{ name: "model", type: "string", required: true, desc: "模型名称,如 \"qwen3-max\"" },
{ name: "messages / prompt", type: "array / string", required: true, desc: "对话消息数组或文本提示" }
]},
{ section: "可选参数", rows: [
{ name: "catelogid", type: "string", required: false, desc: "目录类型ID默认 \"t2t\"" },
{ name: "stream", type: "boolean", required: false, desc: "是否启用流式输出" },
{ name: "off_peak", type: "boolean", required: false, desc: "是否使用非高峰时段" },
{ name: "transno", type: "string", required: false, desc: "交易流水号(不传则自动生成)" }
]}
],
requestExample: {
lang: "json",
code: `{
"model": "qwen3-max",
"messages": [
{"role": "user", "content": "Hello"}
],
"stream": false
}`
},
responseExamples: [
{
title: "非流式响应",
lang: "json",
code: `{
"id": "luid_xxx",
"object": "chat.completion",
"model": "qwen3-max",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Hi there!"},
"finish_reason": "stop"
}],
"usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15}
}`
},
{
title: "流式响应 (SSE)",
lang: "text",
code: `data: {"choices": [{"delta": {"content": "Hi"}, "index": 0}]}
data: {"choices": [{"delta": {"content": " there!"}, "index": 0}]}
data: [DONE]`
}
],
errors: [
{ code: "400", desc: "缺少必填参数或模型不存在" },
{ code: "403", desc: "未登录" },
{ code: "429", desc: "账户余额不足" }
]
},
{
id: "video-generations",
method: "POST",
path: "/llmage/v1/video/generations",
title: "视频生成",
desc: "视频生成接口。支持文生视频、图生视频、参考生视频等多种模式。异步任务,需通过 /v1/tasks 查询状态。",
params: [
{ section: "必填参数", rows: [
{ name: "model", type: "string", required: true, desc: "模型名称,如 \"keling-2.1\"" },
{ name: "catelogid", type: "string", required: true, desc: "目录类型IDt2v / i2v / r2v" },
{ name: "prompt", type: "string", required: true, desc: "生成提示词" }
]},
{ section: "可选参数", rows: [
{ name: "image_url", type: "string", required: false, desc: "图生视频时提供参考图 URL" },
{ name: "duration", type: "string", required: false, desc: "视频时长,如 \"5s\"" },
{ name: "resolution", type: "string", required: false, desc: "分辨率,如 \"1080p\"" },
{ name: "n", type: "integer", required: false, desc: "生成数量" },
{ name: "transno", type: "string", required: false, desc: "交易流水号" }
]}
],
requestExample: {
lang: "json",
code: `{
"model": "keling-2.1",
"catelogid": "t2v",
"prompt": "A beautiful sunset over the ocean",
"duration": "5s",
"resolution": "1080p"
}`
},
responseExamples: [
{
title: "异步任务响应",
lang: "json",
code: `{
"id": "luid_xxx",
"object": "video.generation",
"model": "keling-2.1",
"status": "submitted",
"taskid": "task_xxx",
"created": 1716912000
}`
}
],
models: [
{
name: "Vidu - T2V 文生视频",
params: [
{ name: "model", type: "string", required: true, desc: "viduq3-pro, viduq3-turbo" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "duration", type: "integer", required: false, desc: "视频长度1-16秒默认 10" },
{ name: "ratio", type: "string", required: false, desc: "长宽比16:9, 9:16, 4:3, 3:4, 1:1" },
{ name: "resolution", type: "string", required: false, desc: "分辨率540p, 720p, 1080p" }
]
},
{
name: "Vidu - I2V 图生视频",
params: [
{ name: "model", type: "string", required: true, desc: "viduq3-pro, viduq3-turbo" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "image_file", type: "image", required: true, desc: "首帧图片" },
{ name: "duration", type: "integer", required: false, desc: "视频长度1-16秒" },
{ name: "ratio", type: "string", required: false, desc: "长宽比" },
{ name: "resolution", type: "string", required: false, desc: "分辨率" }
]
},
{
name: "Vidu - Ref2V 参考生视频 v2主体模式",
params: [
{ name: "model", type: "string", required: true, desc: "viduq3-turbo/q3/q2-pro/q2/q1/2.0" },
{ name: "subjects", type: "array", required: true, desc: "主体列表最多7个图片/文字主体每个最多3张图" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "duration", type: "integer", required: false, desc: "视频时长" },
{ name: "aspect_ratio", type: "string", required: false, desc: "画面比例" },
{ name: "resolution", type: "string", required: false, desc: "分辨率" },
{ name: "audio", type: "boolean", required: false, desc: "音视频直出" }
]
},
{
name: "Vidu - Ref2V 参考生视频 v2非主体模式",
params: [
{ name: "model", type: "string", required: true, desc: "viduq3-mix/q3-turbo/q3/q2-pro/q2/q1/2.0" },
{ name: "images", type: "array", required: true, desc: "参考图片URL列表1-7张" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "duration", type: "integer", required: false, desc: "视频时长" },
{ name: "aspect_ratio", type: "string", required: false, desc: "画面比例" },
{ name: "resolution", type: "string", required: false, desc: "分辨率" }
]
},
{
name: "Seedance - T2V 文生视频",
params: [
{ name: "model", type: "string", required: true, desc: "doubao-seedance-2-0-260128, doubao-seedance-2-0-fast-260128" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "resolution", type: "string", required: false, desc: "尺寸480p, 720p, 1080p" },
{ name: "duration", type: "integer", required: false, desc: "视频长度,默认 8" },
{ name: "ratio", type: "string", required: false, desc: "宽高比1:1, 16:9, 9:16, 4:3, 3:4, 21:9, 9:21" }
]
},
{
name: "Seedance - TI2V 文图生视频",
params: [
{ name: "model", type: "string", required: true, desc: "doubao-seedance-2-0-260128, doubao-seedance-2-0-fast-260128" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "image1_file", type: "image", required: true, desc: "首帧图片" },
{ name: "image2_file", type: "image", required: false, desc: "尾帧图片" },
{ name: "resolution", type: "string", required: false, desc: "尺寸" },
{ name: "duration", type: "integer", required: false, desc: "视频长度,默认 8" },
{ name: "ratio", type: "string", required: false, desc: "宽高比" }
]
},
{
name: "通义万象 - T2V 文生视频",
params: [
{ name: "model", type: "string", required: true, desc: "模型名称(如 wan2.6-t2v" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "negative_prompt", type: "string", required: false, desc: "反向提示词" },
{ name: "audio_file", type: "audio", required: false, desc: "配音文件" },
{ name: "size", type: "string", required: false, desc: "视频尺寸,默认 1920*1080" },
{ name: "duration", type: "string", required: false, desc: "视频时长5, 10, 15" }
]
},
{
name: "通义万象 - I2V 图生视频",
params: [
{ name: "model", type: "string", required: true, desc: "wan2.6-i2v, wan2.6-i2v-flash" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "image_file", type: "image", required: true, desc: "首帧图片" },
{ name: "size", type: "string", required: false, desc: "视频尺寸" },
{ name: "duration", type: "string", required: false, desc: "视频时长" }
]
},
{
name: "通义万象 - Ref2V 角色参考生视频",
params: [
{ name: "model", type: "string", required: true, desc: "模型名称(如 wan2.6-r2v" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "video1_file", type: "video", required: true, desc: "角色一视频" },
{ name: "video2_file", type: "video", required: false, desc: "角色二视频" },
{ name: "video3_file", type: "video", required: false, desc: "角色三视频" },
{ name: "size", type: "string", required: false, desc: "视频尺寸" },
{ name: "duration", type: "string", required: false, desc: "视频时长10, 15" }
]
},
{
name: "可灵 Kling - T2V 文生视频",
params: [
{ name: "model", type: "string", required: true, desc: "kling-v2-1-master, kling-v2-master, kling-v1-6, kling-v1" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "negative_prompt", type: "string", required: false, desc: "反向提示词" }
]
},
{
name: "海螺 MiniMax - TI2V 图生视频",
params: [
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "image_file", type: "image", required: false, desc: "首帧图片" },
{ name: "image_file1", type: "image", required: false, desc: "尾帧图片" },
{ name: "resolution", type: "string", required: false, desc: "尺寸768P, 1080P" },
{ name: "duration", type: "integer", required: false, desc: "视频长度66秒, 1010秒" }
]
}
]
},
{
id: "image-generations",
method: "POST",
path: "/llmage/v1/image/generations",
title: "图像生成",
desc: "图像生成接口。支持文生图和图生图。",
params: [
{ section: "必填参数", rows: [
{ name: "model", type: "string", required: true, desc: "模型名称,如 \"jimeng-4.0\"" },
{ name: "catelogid", type: "string", required: true, desc: "目录类型ID文生图固定为 \"t2i\"" },
{ name: "prompt", type: "string", required: true, desc: "生成提示词" }
]},
{ section: "可选参数", rows: [
{ name: "image_url", type: "string", required: false, desc: "图生图时提供参考图 URL" },
{ name: "size", type: "string", required: false, desc: "尺寸,如 \"1024x1024\"" },
{ name: "n", type: "integer", required: false, desc: "生成数量" },
{ name: "style", type: "string", required: false, desc: "风格参数" },
{ name: "quality", type: "string", required: false, desc: "质量参数" },
{ name: "transno", type: "string", required: false, desc: "交易流水号" }
]}
],
requestExample: {
lang: "json",
code: `{
"model": "jimeng-4.0",
"catelogid": "t2i",
"prompt": "A beautiful sunset over the ocean",
"size": "1024x1024",
"n": 1
}`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"id": "luid_xxx",
"object": "image.generation",
"model": "jimeng-4.0",
"status": "submitted",
"taskid": "task_xxx",
"created": 1716912000
}`
}
],
models: [
{
name: "百炼-万象文生图(异步)",
params: [
{ name: "model", type: "string", required: true, desc: "wan2.2-t2i-plus / wan2.5-t2i-preview / wan2.2-t2i-flash" },
{ name: "catelogid", type: "string", required: true, desc: "文生图固定 t2i" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "size", type: "string", required: false, desc: "尺寸512*512, 1024*1024, 2048*2048 等" },
{ name: "n", type: "integer", required: false, desc: "生成数量 1-4" }
],
responseExample: {
lang: "json",
code: `// 提交响应
{"status": "ok", "data": {"taskid": "task_xxx", "status": "PENDING"}}
// 查询结果(/v1/tasks?taskid=task_xxx
{"status": "ok", "data": {"status": "SUCCEEDED", "output": [{"url": "https://..."}], "usage": {"image_count": 1}}}`
}
},
{
name: "智谱 CogView-3-Flash同步/免费)",
params: [
{ name: "model", type: "string", required: true, desc: "cogview-3-flash" },
{ name: "catelogid", type: "string", required: true, desc: "文生图固定 t2i" },
{ name: "prompt", type: "string", required: true, desc: "提示词" },
{ name: "size", type: "string", required: false, desc: "尺寸512x512, 1024x1024, 2048x2048" }
],
responseExample: {
lang: "json",
code: `{"status": "ok", "data": {"image": "https://...", "usage": {"image_count": 1}}}`
}
}
]
},
{
id: "tasks",
method: "GET",
path: "/llmage/v1/tasks",
title: "查询异步任务",
desc: "查询异步任务状态。用于视频生成、图像生成等异步接口返回任务进度。",
params: [
{ section: "必填参数", rows: [
{ name: "taskid", type: "string", required: true, desc: "任务 ID" }
]}
],
requestExample: {
lang: "bash",
code: `GET /llmage/v1/tasks?taskid=task_xxx`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"status": "ok",
"data": {
"status": "SUCCEEDED",
"output": [...]
}
}`
}
],
note: "任务状态值: UNKNOWN / SUCCEEDED / FAILED"
},
{
id: "models",
method: "GET",
path: "/llmage/v1/models",
title: "模型列表",
desc: "列出可用模型列表。",
params: [
{ section: "可选参数", rows: [
{ name: "catelogid", type: "string", required: false, desc: "按目录类型过滤" },
{ name: "orderby", type: "string", required: false, desc: "排序字段" }
]}
],
requestExample: {
lang: "bash",
code: `GET /llmage/v1/models`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"object": "list",
"data": [
{
"id": "qwen3-max",
"object": "model",
"created": 1748044800,
"owned_by": "opencomputing.ai"
}
]
}`
}
]
}
]
},
{
group: "真人素材 API",
items: [
{
id: "rl-verify",
method: "POST",
path: "/reallife_asset/api/rl_verify.dspy",
title: "真人认证",
desc: "获取真人认证链接H5。终端用户通过 H5 页面完成人脸识别。",
params: [
{ section: "请求参数", rows: [
{ name: "vendor", type: "string", required: true, desc: "供应商标识" },
{ name: "project_name", type: "string", required: false, desc: "项目名称,默认 default" },
{ name: "name", type: "string", required: false, desc: "认证名称,方便识别" }
]}
],
requestExample: {
lang: "bash",
code: `curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_verify.dspy' \\
-H 'Authorization: Bearer *** \\
-H 'Content-Type: application/json' \\
-d '{
"vendor": "volcengine",
"project_name": "default",
"name": "张三"
}'`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"status": "ok",
"data": {
"id": "local_group_id_xxx",
"h5_link": "https://... (H5页面链接120秒有效)",
"byted_token": "..."
}
}`
}
],
note: "user_id 和 org_id 由 Bearer Token 自动获取"
},
{
id: "rl-query-groups",
method: "POST",
path: "/reallife_asset/api/rl_query_groups.dspy",
title: "查询已认证组合",
desc: "查询当前机构下所有已认证的组合 ID用于上传素材时选择有效的 vendor_group_id。",
params: [
{ section: "请求参数", rows: [
{ name: "(无)", type: "-", required: false, desc: "系统自动从 Bearer Token 获取 org_id" }
]}
],
requestExample: {
lang: "bash",
code: `curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_query_groups.dspy' \\
-H 'Authorization: Bearer ***`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"status": "ok",
"data": {
"groups": [
{
"vendor_group_id": "volc-asset-group-xxx",
"vendor": "volcengine",
"name": "模特张三",
"status": "active",
"create_time": "2026-05-28 15:30:00"
}
]
}
}`
}
]
},
{
id: "rl-upload",
method: "POST",
path: "/reallife_asset/api/rl_upload.dspy",
title: "上传素材",
desc: "上传素材到已认证的组合。支持图片和视频。上传为异步操作,需轮询 rl_status 获取处理状态。",
params: [
{ section: "请求参数", rows: [
{ name: "vendor_group_id", type: "string", required: true, desc: "已认证的组合 ID" },
{ name: "source_url", type: "string", required: true, desc: "素材 URL 或 data: base64 编码" },
{ name: "asset_type", type: "string", required: false, desc: "Image默认或 Video" },
{ name: "name", type: "string", required: false, desc: "素材名称" }
]}
],
requestExample: {
lang: "bash",
code: `curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_upload.dspy' \\
-H 'Authorization: Bearer *** \\
-H 'Content-Type: application/json' \\
-d '{
"vendor_group_id": "volc-asset-group-xxx",
"source_url": "https://bucket.oss.com/photo.jpg",
"asset_type": "Image",
"name": "模特A"
}'`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"status": "ok",
"data": {
"id": "asset_record_id_xxx",
"vendor_asset_id": "asset-2026...",
"status": "Processing"
}
}`
}
],
note: "上传是异步操作,需调用 rl_status 轮询状态。"
},
{
id: "rl-status",
method: "POST",
path: "/reallife_asset/api/rl_status.dspy",
title: "查询素材状态",
desc: "查询素材处理状态。素材永久存储url 过期后可再次调用获取新链接。",
params: [
{ section: "请求参数", rows: [
{ name: "asset_id", type: "string", required: true, desc: "上传时返回的记录 ID" }
]}
],
requestExample: {
lang: "bash",
code: `curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_status.dspy' \\
-H 'Authorization: Bearer *** \\
-H 'Content-Type: application/json' \\
-d '{
"asset_id": "asset_record_id_xxx"
}'`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"status": "ok",
"data": {
"status": "Active",
"url": "https://... (临时下载链接12小时有效)"
}
}`
}
]
},
{
id: "rl-assets",
method: "POST",
path: "/reallife_asset/api/rl_assets.dspy",
title: "查询组合素材",
desc: "查询组合下所有素材列表。",
params: [
{ section: "请求参数", rows: [
{ name: "vendor_group_id", type: "string", required: true, desc: "已认证的组合 ID" }
]}
],
requestExample: {
lang: "bash",
code: `curl -X POST 'https://token.opencomputing.cn/reallife_asset/api/rl_assets.dspy' \\
-H 'Authorization: Bearer *** \\
-H 'Content-Type: application/json' \\
-d '{
"vendor_group_id": "volc-asset-group-xxx"
}'`
},
responseExamples: [
{
title: "响应示例",
lang: "json",
code: `{
"status": "ok",
"data": {
"assets": [
{
"id": "asset_record_id_xxx",
"vendor_asset_id": "asset-2026...",
"name": "模特A",
"asset_type": "Image",
"status": "Active",
"url": "https://...",
"create_time": "2026-05-28 15:30:00"
}
],
"total": 3
}
}`
}
]
}
]
},
{
group: "参考信息",
items: [
{
id: "catelogid",
method: "GET",
path: "",
title: "catelogid 对照表",
desc: "catelogid 目录类型ID对照表。所有 v1 接口统一使用此参数标识目录类型。",
isReference: true,
refTable: [
{ id: "t2t", name: "文生文", desc: "文本生成(默认)" },
{ id: "t2i", name: "文生图", desc: "图像生成" },
{ id: "t2v", name: "文生视频", desc: "文本生成视频" },
{ id: "i2v", name: "图生视频", desc: "图像生成视频" },
{ id: "r2v", name: "参考生视频", desc: "参考图像生成视频" },
{ id: "tts", name: "语音合成", desc: "文本转语音" },
{ id: "asr", name: "语音识别", desc: "语音转文本" },
{ id: "vision", name: "图理解", desc: "图像理解" },
{ id: "ai_search", name: "AI搜索", desc: "AI搜索" },
{ id: "digital_human", name: "数字人", desc: "数字人" },
{ id: "music_gen", name: "音乐生成", desc: "音乐生成" },
{ id: "text_cls", name: "文本分类", desc: "文本分类" },
{ id: "3d_gen", name: "3D生成", desc: "3D模型生成" },
{ id: "video_tool", name: "视频工具", desc: "视频处理工具" },
{ id: "translate", name: "翻译", desc: "文本翻译" }
]
}
]
}
];
// ===== Render Functions =====
function renderSidebar() {
const nav = document.getElementById('sidebarNav');
let html = '';
apiData.forEach((group, gi) => {
html += `<div class="nav-group" data-group="${gi}">`;
html += `<div class="nav-group-title" onclick="toggleGroup(${gi})"><span class="arrow"></span>${group.group}</div>`;
html += `<div class="nav-items">`;
group.items.forEach(item => {
const methodClass = item.method.toLowerCase();
const pathDisplay = item.path ? item.path.replace('/llmage/v1/', '/v1/').replace('/reallife_asset/api/', '') : item.title;
html += `<div class="nav-item" data-id="${item.id}" onclick="selectApi('${item.id}')">`;
if (item.path) {
html += `<span class="method ${methodClass}">${item.method}</span>`;
}
html += `<span class="path">${item.path ? pathDisplay : item.title}</span>`;
html += `</div>`;
});
html += `</div></div>`;
});
nav.innerHTML = html;
}
function renderContent() {
const content = document.getElementById('contentArea');
let html = `<div class="api-section active" id="welcome-section">
<div class="welcome">
<h2>元境 API 文档</h2>
<p>统一的 AI 模型 API 网关,兼容 OpenAI 格式。支持文本生成、图像生成、视频生成、真人素材等能力。</p>
<p>所有接口通过 Bearer Token 认证。Base URL: <code style="color:var(--accent-blue)">https://token.opencomputing.cn</code></p>
<div class="feature-grid">
<div class="feature-card"><h4>🤖 文本生成</h4><p>兼容 OpenAI Chat Completions 格式,支持流式输出</p></div>
<div class="feature-card"><h4>🎬 视频生成</h4><p>多平台视频模型Vidu、Seedance、通义万象、可灵、海螺</p></div>
<div class="feature-card"><h4>🎨 图像生成</h4><p>百炼万象、智谱CogView 等文生图/图生图模型</p></div>
<div class="feature-card"><h4>👤 真人素材</h4><p>真人认证、素材上传、素材管理全流程</p></div>
</div>
</div>
</div>`;
apiData.forEach(group => {
group.items.forEach(item => {
html += `<div class="api-section" id="section-${item.id}">`;
// Title
if (item.path) {
const methodClass = item.method.toLowerCase();
html += `<div class="api-title"><span class="method-badge ${methodClass}">${item.method}</span><span class="endpoint">${item.path}</span></div>`;
} else {
html += `<div class="api-title"><span class="endpoint">${item.title}</span></div>`;
}
html += `<div class="api-desc">${item.desc}</div>`;
// Reference table (catelogid)
if (item.isReference && item.refTable) {
html += `<table class="param-table"><thead><tr><th>ID</th><th>中文名</th><th>说明</th></tr></thead><tbody>`;
item.refTable.forEach(r => {
html += `<tr><td class="param-name">${r.id}</td><td>${r.name}</td><td>${r.desc}</td></tr>`;
});
html += `</tbody></table>`;
html += `<div class="info-box note" style="margin-top:16px">向后兼容catelogid 参数同时支持新ID如 "t2v")和旧中文名(如 "文生视频"推荐使用新ID。</div>`;
html += `</div>`;
return;
}
// Note
if (item.note) {
html += `<div class="info-box note">${item.note}</div>`;
}
// Parameters
if (item.params) {
html += `<div class="section-title">请求参数</div>`;
item.params.forEach(p => {
if (item.params.length > 1) html += `<div class="subsection-title">${p.section}</div>`;
html += renderParamTable(p.rows);
});
}
// Request Example
if (item.requestExample) {
html += `<div class="section-title">请求示例</div>`;
html += renderCodeBlock(item.requestExample.lang, item.requestExample.code);
}
// Response Examples
if (item.responseExamples) {
html += `<div class="section-title">响应示例</div>`;
item.responseExamples.forEach(r => {
if (item.responseExamples.length > 1) html += `<div class="subsection-title">${r.title}</div>`;
html += renderCodeBlock(r.lang, r.code);
});
}
// Errors
if (item.errors) {
html += `<div class="section-title">错误响应</div>`;
html += `<table class="param-table"><thead><tr><th>状态码</th><th>说明</th></tr></thead><tbody>`;
item.errors.forEach(e => {
html += `<tr><td><span style="color:var(--accent-red);font-weight:600">${e.code}</span></td><td>${e.desc}</td></tr>`;
});
html += `</tbody></table>`;
}
// Model details
if (item.models) {
html += `<div class="section-title">各模型参数明细</div>`;
html += `<div class="info-box note">调用时通过 model + catelogid 自动路由到对应供应商</div>`;
html += `<div class="model-tabs" id="tabs-${item.id}">`;
item.models.forEach((m, mi) => {
html += `<div class="model-tab${mi === 0 ? ' active' : ''}" onclick="switchModelTab('${item.id}', ${mi})">${m.name}</div>`;
});
html += `</div>`;
item.models.forEach((m, mi) => {
html += `<div class="model-detail${mi === 0 ? ' active' : ''}" id="model-${item.id}-${mi}">`;
html += renderParamTable(m.params);
if (m.responseExample) {
html += `<div class="subsection-title">响应示例</div>`;
html += renderCodeBlock(m.responseExample.lang, m.responseExample.code);
}
html += `</div>`;
});
}
html += `</div>`;
});
});
content.innerHTML = html;
}
function renderParamTable(rows) {
let html = `<table class="param-table"><thead><tr><th>参数</th><th>类型</th><th>必填</th><th>说明</th></tr></thead><tbody>`;
rows.forEach(r => {
const reqClass = r.required ? 'param-required' : 'param-optional';
const reqText = r.required ? '是' : '否';
html += `<tr><td class="param-name">${r.name}</td><td class="param-type">${r.type}</td><td class="${reqClass}">${reqText}</td><td>${r.desc}</td></tr>`;
});
html += `</tbody></table>`;
return html;
}
function renderCodeBlock(lang, code) {
const escaped = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return `<div class="code-block">
<div class="code-header"><span class="lang">${lang}</span><button class="copy-btn" onclick="copyCode(this)">复制</button></div>
<pre><code class="language-${lang}">${escaped}</code></pre>
</div>`;
}
// ===== Interactions =====
function selectApi(id) {
document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active'));
document.querySelector(`.nav-item[data-id="${id}"]`)?.classList.add('active');
document.querySelectorAll('.api-section').forEach(el => el.classList.remove('active'));
const section = document.getElementById(`section-${id}`);
if (section) {
section.classList.add('active');
document.getElementById('contentArea').scrollTop = 0;
}
// Highlight code
section?.querySelectorAll('pre code').forEach(block => hljs.highlightElement(block));
}
function toggleGroup(gi) {
const group = document.querySelector(`.nav-group[data-group="${gi}"]`);
group.classList.toggle('collapsed');
}
function switchModelTab(apiId, index) {
const tabs = document.querySelectorAll(`#tabs-${apiId} .model-tab`);
tabs.forEach((t, i) => t.classList.toggle('active', i === index));
const details = document.querySelectorAll(`[id^="model-${apiId}-"]`);
details.forEach((d, i) => d.classList.toggle('active', i === index));
}
function copyCode(btn) {
const code = btn.closest('.code-block').querySelector('code').textContent;
navigator.clipboard.writeText(code).then(() => {
btn.textContent = '已复制';
setTimeout(() => btn.textContent = '复制', 1500);
});
}
// ===== Init =====
renderSidebar();
renderContent();
</script>
</body>
</html>

View File

@ -7,35 +7,12 @@
},
"subwidgets": [
{
"widgettype": "HBox",
"widgettype": "urlwidget",
"options": {
"url": "{{entire_url('/dashboard_for_sage/api_doc.html')}}",
"width": "100%",
"alignItems": "center",
"marginBottom": "16px"
},
"subwidgets": [
{
"widgettype": "Title2",
"options": {
"text": "大模型 API 文档"
}
}
]
},
{
"widgettype": "VScrollPanel",
"options": {
"css": "filler"
},
"subwidgets": [
{
"widgettype": "MarkdownViewer",
"options": {
"md_url": "{{entire_url('/dashboard_for_sage/api_doc.md')}}",
"width": "100%"
}
}
]
"height": "100%"
}
}
]
}