380 lines
8.1 KiB
Vue
380 lines
8.1 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>元境 API 文档</h1>
|
|
<p>统一展示大模型、视频、图像、音频、任务查询等接口说明。</p>
|
|
</section>
|
|
|
|
<section v-loading="loading" class="doc-section markdown-section">
|
|
<div v-html="renderedMarkdown"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer class="doc-footer">© 2026 开元云科技 · API 文档中心</footer>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'ApiDocument',
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
errorMessage: '',
|
|
markdownText: '',
|
|
markdownUrl: 'https://token.opencomputing.cn/docs/api_doc_zh.md'
|
|
}
|
|
},
|
|
computed: {
|
|
renderedMarkdown() {
|
|
return this.renderMarkdown(this.markdownText)
|
|
}
|
|
},
|
|
created() {
|
|
this.fetchMarkdownDocument()
|
|
},
|
|
methods: {
|
|
async fetchMarkdownDocument() {
|
|
this.loading = true
|
|
this.errorMessage = ''
|
|
try {
|
|
const response = await fetch(this.markdownUrl)
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}`)
|
|
}
|
|
this.markdownText = await response.text()
|
|
} catch (error) {
|
|
console.error('[API文档] 获取 Markdown 文档失败', error)
|
|
this.errorMessage = 'API 文档加载失败,请稍后重试'
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
escapeHtml(text = '') {
|
|
return String(text)
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
},
|
|
renderInline(text = '') {
|
|
return this.escapeHtml(text)
|
|
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
|
},
|
|
renderTable(lines) {
|
|
const rows = lines
|
|
.filter(line => line.trim().startsWith('|'))
|
|
.map(line => line.trim().replace(/^\||\|$/g, '').split('|').map(cell => this.renderInline(cell.trim())))
|
|
if (!rows.length) return ''
|
|
const header = rows[0] || []
|
|
const bodyRows = rows.slice(2)
|
|
return `<div class="md-table-wrap"><table><thead><tr>${header.map(cell => `<th>${cell}</th>`).join('')}</tr></thead><tbody>${bodyRows.map(row => `<tr>${row.map(cell => `<td>${cell}</td>`).join('')}</tr>`).join('')}</tbody></table></div>`
|
|
},
|
|
renderMarkdown(markdown = '') {
|
|
const lines = markdown.replace(/\r\n/g, '\n').split('\n')
|
|
const html = []
|
|
let index = 0
|
|
|
|
while (index < lines.length) {
|
|
const line = lines[index]
|
|
const trimmed = line.trim()
|
|
|
|
if (!trimmed) {
|
|
index += 1
|
|
continue
|
|
}
|
|
|
|
if (trimmed.startsWith('```')) {
|
|
const lang = trimmed.replace(/```/, '').trim()
|
|
const code = []
|
|
index += 1
|
|
while (index < lines.length && !lines[index].trim().startsWith('```')) {
|
|
code.push(lines[index])
|
|
index += 1
|
|
}
|
|
html.push(`<pre><code class="language-${this.escapeHtml(lang)}">${this.escapeHtml(code.join('\n'))}</code></pre>`)
|
|
index += 1
|
|
continue
|
|
}
|
|
|
|
if (trimmed.startsWith('|')) {
|
|
const tableLines = []
|
|
while (index < lines.length && lines[index].trim().startsWith('|')) {
|
|
tableLines.push(lines[index])
|
|
index += 1
|
|
}
|
|
html.push(this.renderTable(tableLines))
|
|
continue
|
|
}
|
|
|
|
if (/^---+$/.test(trimmed)) {
|
|
html.push('<hr>')
|
|
index += 1
|
|
continue
|
|
}
|
|
|
|
const heading = trimmed.match(/^(#{1,6})\s+(.*)$/)
|
|
if (heading) {
|
|
const level = heading[1].length
|
|
html.push(`<h${level}>${this.renderInline(heading[2])}</h${level}>`)
|
|
index += 1
|
|
continue
|
|
}
|
|
|
|
if (/^[-*]\s+/.test(trimmed)) {
|
|
const items = []
|
|
while (index < lines.length && /^[-*]\s+/.test(lines[index].trim())) {
|
|
items.push(lines[index].trim().replace(/^[-*]\s+/, ''))
|
|
index += 1
|
|
}
|
|
html.push(`<ul>${items.map(item => `<li>${this.renderInline(item)}</li>`).join('')}</ul>`)
|
|
continue
|
|
}
|
|
|
|
if (/^\d+\.\s+/.test(trimmed)) {
|
|
const items = []
|
|
while (index < lines.length && /^\d+\.\s+/.test(lines[index].trim())) {
|
|
items.push(lines[index].trim().replace(/^\d+\.\s+/, ''))
|
|
index += 1
|
|
}
|
|
html.push(`<ol>${items.map(item => `<li>${this.renderInline(item)}</li>`).join('')}</ol>`)
|
|
continue
|
|
}
|
|
|
|
html.push(`<p>${this.renderInline(trimmed)}</p>`)
|
|
index += 1
|
|
}
|
|
|
|
return html.join('')
|
|
},
|
|
goBack() {
|
|
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: 1180px;
|
|
max-width: calc(100vw - 48px);
|
|
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;
|
|
}
|
|
}
|
|
|
|
.markdown-section {
|
|
line-height: 1.8;
|
|
|
|
::v-deep h1 {
|
|
margin: 0 0 24px;
|
|
color: #111827;
|
|
font-size: 30px;
|
|
font-weight: 800;
|
|
}
|
|
|
|
::v-deep h2 {
|
|
margin: 34px 0 16px;
|
|
padding-left: 10px;
|
|
color: #1f2d3d;
|
|
font-size: 22px;
|
|
border-left: 3px solid #2f6bff;
|
|
}
|
|
|
|
::v-deep h3 {
|
|
margin: 26px 0 12px;
|
|
color: #1f2937;
|
|
font-size: 18px;
|
|
}
|
|
|
|
::v-deep h4,
|
|
::v-deep h5 {
|
|
margin: 20px 0 10px;
|
|
color: #334155;
|
|
font-size: 16px;
|
|
}
|
|
|
|
::v-deep p,
|
|
::v-deep li {
|
|
color: #475569;
|
|
font-size: 14px;
|
|
}
|
|
|
|
::v-deep ul,
|
|
::v-deep ol {
|
|
padding-left: 22px;
|
|
}
|
|
|
|
::v-deep hr {
|
|
height: 1px;
|
|
margin: 28px 0;
|
|
background: #e5e7eb;
|
|
border: 0;
|
|
}
|
|
|
|
::v-deep code {
|
|
padding: 2px 6px;
|
|
color: #d6336c;
|
|
background: #fff1f2;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
::v-deep pre code {
|
|
padding: 0;
|
|
color: inherit;
|
|
background: transparent;
|
|
border-radius: 0;
|
|
}
|
|
|
|
::v-deep .md-table-wrap {
|
|
width: 100%;
|
|
margin: 16px 0 24px;
|
|
overflow-x: auto;
|
|
border: 1px solid #e5e7eb;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
::v-deep table {
|
|
width: 100%;
|
|
min-width: 680px;
|
|
border-collapse: collapse;
|
|
background: #fff;
|
|
}
|
|
|
|
::v-deep th,
|
|
::v-deep td {
|
|
padding: 10px 12px;
|
|
color: #475569;
|
|
font-size: 13px;
|
|
text-align: left;
|
|
border-bottom: 1px solid #e5e7eb;
|
|
border-right: 1px solid #e5e7eb;
|
|
}
|
|
|
|
::v-deep th {
|
|
color: #1f2937;
|
|
font-weight: 700;
|
|
background: #f8fafc;
|
|
}
|
|
}
|
|
|
|
pre {
|
|
margin: 14px 0 24px;
|
|
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>
|