307 lines
7.9 KiB
Vue
307 lines
7.9 KiB
Vue
<template>
|
||
<div class="api-doc-page">
|
||
<header class="doc-nav">
|
||
<button type="button" @click="goBack">
|
||
<i class="el-icon-arrow-left"></i>
|
||
返回
|
||
</button>
|
||
<span>API文档</span>
|
||
</header>
|
||
|
||
<main class="doc-container">
|
||
<el-alert
|
||
v-if="errorMessage"
|
||
class="doc-alert"
|
||
:title="errorMessage"
|
||
type="warning"
|
||
show-icon
|
||
:closable="false"
|
||
></el-alert>
|
||
|
||
<section class="doc-hero">
|
||
<h1>{{ apiDoc.model_name }} API 文档</h1>
|
||
<p>{{ heroDescription }}</p>
|
||
<!-- <div class="quick-tabs">
|
||
<span v-for="item in quickTabs" :key="item">{{ item }}</span>
|
||
</div> -->
|
||
</section>
|
||
|
||
<section v-loading="loading" class="doc-section">
|
||
<h2>1. 接口地址</h2>
|
||
<p>统一使用 HTTPS 请求,所有接口都需要携带平台签发的 API Key。</p>
|
||
<pre><code>{{ apiUrlText }}</code></pre>
|
||
</section>
|
||
|
||
|
||
|
||
|
||
|
||
<section class="doc-section">
|
||
<h2>2. 请求示例</h2>
|
||
<pre><code>{{ apiDoc.curl_code || requestExample }}</code></pre>
|
||
</section>
|
||
|
||
<section class="doc-section">
|
||
<h2>3. Python 示例</h2>
|
||
<pre><code>{{ apiDoc.python_code || pythonExample }}</code></pre>
|
||
</section>
|
||
|
||
<section class="doc-section">
|
||
<h2>4. 错误码</h2>
|
||
<el-table :data="errorCodes" border size="small">
|
||
<el-table-column prop="code" label="错误码" width="140"></el-table-column>
|
||
<el-table-column prop="message" label="说明"></el-table-column>
|
||
<el-table-column prop="suggestion" label="处理建议"></el-table-column>
|
||
</el-table>
|
||
</section>
|
||
</main>
|
||
|
||
<footer class="doc-footer">© 2026 开元云科技 · API 文档中心</footer>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { reqModelApiDocument } from '@/api/model/model'
|
||
|
||
export default {
|
||
name: 'ApiDocument',
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
errorMessage: '',
|
||
apiDoc: {
|
||
id: '',
|
||
api_url: '',
|
||
model_id: '',
|
||
curl_code: '',
|
||
python_code: '',
|
||
model_name: '模型'
|
||
},
|
||
quickTabs: ['API概览', '认证方式', '请求参数', '代码示例', '错误码'],
|
||
capabilityTable: [
|
||
{ name: '文本对话', value: '支持单轮和多轮对话生成', status: '支持' },
|
||
{ name: '流式输出', value: '通过 stream=true 开启 SSE 增量返回', status: '支持' },
|
||
{ name: 'Function Call', value: '支持工具调用和结构化参数', status: '支持' },
|
||
{ name: '图像输入', value: '可在 messages 中传入图片内容', status: '支持' },
|
||
{ name: '私有化部署', value: '当前公共服务暂不支持私有化', status: '暂不支持' }
|
||
],
|
||
requestParams: [
|
||
{ name: 'model', type: 'string', required: '是', desc: '模型 ID,例如 minimax-m2.5' },
|
||
{ name: 'messages', type: 'array', required: '是', desc: '对话消息列表,包含 role 和 content' },
|
||
{ name: 'temperature', type: 'number', required: '否', desc: '采样温度,数值越高输出越随机' },
|
||
{ name: 'stream', type: 'boolean', required: '否', desc: '是否开启流式返回' },
|
||
{ name: 'max_tokens', type: 'number', required: '否', desc: '限制模型最大输出长度' }
|
||
],
|
||
errorCodes: [
|
||
{ code: '401', message: '认证失败', suggestion: '检查 API Key 是否正确或过期' },
|
||
{ code: '429', message: '请求过于频繁', suggestion: '降低并发或等待限流恢复' },
|
||
{ code: '500', message: '服务异常', suggestion: '稍后重试或联系平台支持' }
|
||
],
|
||
requestExample: `curl https://api.kboss.example.com/v2/chat/completions \\
|
||
-H "Content-Type: application/json" \\
|
||
-H "Authorization: Bearer $KBOSS_API_KEY" \\
|
||
-d '{
|
||
"model": "minimax-m2.5",
|
||
"messages": [
|
||
{
|
||
"role": "user",
|
||
"content": "帮我写一段模型上架介绍"
|
||
}
|
||
],
|
||
"temperature": 0.7,
|
||
"stream": false
|
||
}'`,
|
||
pythonExample: `import requests
|
||
|
||
url = "https://api.kboss.example.com/v2/chat/completions"
|
||
headers = {
|
||
"Content-Type": "application/json",
|
||
"Authorization": "Bearer $KBOSS_API_KEY"
|
||
}
|
||
data = {
|
||
"model": "minimax-m2.5",
|
||
"messages": [{"role": "user", "content": "Hello!"}],
|
||
"stream": False
|
||
}
|
||
response = requests.post(url, headers=headers, json=data)
|
||
print(response.json())`
|
||
}
|
||
},
|
||
computed: {
|
||
apiUrlText() {
|
||
const curlUrl = this.getUrlFromCurl(this.apiDoc.curl_code)
|
||
const url = this.apiDoc.api_url || curlUrl
|
||
return url ? `POST ${url}` : '接口地址以后端返回为准'
|
||
},
|
||
heroDescription() {
|
||
const modelName = this.apiDoc.model_name || '当前模型'
|
||
return `${modelName} 接口调用示例,包含 curl 与 Python 两种接入方式。`
|
||
}
|
||
},
|
||
created() {
|
||
this.fetchApiDocument()
|
||
},
|
||
watch: {
|
||
'$route.query.id'() {
|
||
this.fetchApiDocument()
|
||
}
|
||
},
|
||
methods: {
|
||
// 通过路由传入的 id 获取模型 API 文档数据。
|
||
async fetchApiDocument() {
|
||
const id = this.$route.query.id || this.$route.query.model_id
|
||
if (!id) {
|
||
this.errorMessage = '缺少模型ID,无法获取 API 文档'
|
||
return
|
||
}
|
||
|
||
this.loading = true
|
||
this.errorMessage = ''
|
||
try {
|
||
const res = await reqModelApiDocument({ id })
|
||
if (res && res.status && res.data) {
|
||
this.apiDoc = {
|
||
...this.apiDoc,
|
||
...res.data,
|
||
model_name: res.data.model_name || this.apiDoc.model_name
|
||
}
|
||
return
|
||
}
|
||
this.errorMessage = (res && res.msg) || 'API 文档数据获取失败'
|
||
} catch (error) {
|
||
console.error('[API文档] 获取模型 API 文档失败', error)
|
||
this.errorMessage = 'API 文档数据获取失败,请稍后重试'
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
getUrlFromCurl(curlCode) {
|
||
if (!curlCode) return ''
|
||
const match = String(curlCode).match(/https?:\/\/[^\s\\]+/)
|
||
return match ? match[0] : ''
|
||
},
|
||
goBack() {
|
||
if (this.$route.query.from === 'tokenMarket') {
|
||
if (this.$route.query.single === '1') {
|
||
this.$router.push({ path: '/tokenMarket', query: { category: 'TOKEN市集', single: '1' } })
|
||
return
|
||
}
|
||
this.$router.push({ path: '/product', query: { category: 'TOKEN市集' } })
|
||
return
|
||
}
|
||
this.$router.back()
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.api-doc-page {
|
||
height: 100vh;
|
||
color: #1f2d3d;
|
||
background: #f6f8fb;
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
.doc-nav {
|
||
display: flex;
|
||
align-items: center;
|
||
height: 48px;
|
||
padding: 0 28px;
|
||
color: #667085;
|
||
background: #ffffff;
|
||
border-bottom: 1px solid #edf1f7;
|
||
|
||
button {
|
||
padding: 0;
|
||
margin-right: 16px;
|
||
color: #667085;
|
||
cursor: pointer;
|
||
background: transparent;
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
.doc-container {
|
||
width: 920px;
|
||
margin: 28px auto 0;
|
||
}
|
||
|
||
.doc-alert {
|
||
margin-bottom: 18px;
|
||
}
|
||
|
||
.doc-hero,
|
||
.doc-section {
|
||
padding: 24px;
|
||
margin-bottom: 18px;
|
||
background: #ffffff;
|
||
border: 1px solid #edf1f7;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
.doc-hero {
|
||
h1 {
|
||
margin: 0 0 10px;
|
||
font-size: 28px;
|
||
}
|
||
|
||
p {
|
||
margin: 0 0 18px;
|
||
color: #667085;
|
||
}
|
||
}
|
||
|
||
.quick-tabs {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
|
||
span {
|
||
padding: 6px 12px;
|
||
color: #2f6bff;
|
||
background: #eef4ff;
|
||
border-radius: 999px;
|
||
font-size: 13px;
|
||
}
|
||
}
|
||
|
||
.doc-section {
|
||
h2 {
|
||
margin: 0 0 16px;
|
||
padding-left: 10px;
|
||
color: #1f2d3d;
|
||
font-size: 18px;
|
||
border-left: 3px solid #2f6bff;
|
||
}
|
||
|
||
p {
|
||
color: #667085;
|
||
line-height: 1.8;
|
||
}
|
||
}
|
||
|
||
pre {
|
||
margin: 0;
|
||
padding: 16px;
|
||
color: #e6edf3;
|
||
overflow-x: auto;
|
||
background: #1f2329;
|
||
border-radius: 8px;
|
||
line-height: 1.7;
|
||
}
|
||
|
||
code {
|
||
font-family: Consolas, Monaco, monospace;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.doc-footer {
|
||
padding: 32px 0;
|
||
color: #98a2b3;
|
||
text-align: center;
|
||
font-size: 12px;
|
||
}
|
||
</style>
|