feat(portal): i18n-ify DocsView + auth narrative panels
Extract all Chinese from DocsView.vue into docs.* namespace and add auth.narrative.* sub-namespace for LoginView/RegisterView narrative slots. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -499,7 +499,39 @@ export default {
|
|||||||
invalidResetLink: 'Invalid Reset Link',
|
invalidResetLink: 'Invalid Reset Link',
|
||||||
invalidResetLinkHint: 'This password reset link is invalid or has expired. Please request a new one.',
|
invalidResetLinkHint: 'This password reset link is invalid or has expired. Please request a new one.',
|
||||||
requestNewResetLink: 'Request New Reset Link',
|
requestNewResetLink: 'Request New Reset Link',
|
||||||
invalidOrExpiredToken: 'The password reset link is invalid or has expired. Please request a new one.'
|
invalidOrExpiredToken: 'The password reset link is invalid or has expired. Please request a new one.',
|
||||||
|
narrative: {
|
||||||
|
common: {
|
||||||
|
statusLive: 'live',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
|
kicker: '// you already paid for your subscriptions',
|
||||||
|
headlineN: 'N',
|
||||||
|
headlineOne: '1',
|
||||||
|
headlineSep: 'subscriptions →',
|
||||||
|
headlineSuffix: 'key',
|
||||||
|
sub1: 'No more juggling accounts,',
|
||||||
|
sub2: 'no more paying twice for overlapping subscriptions.',
|
||||||
|
tagline: 'PURO — AI calls, back to basics.',
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
kicker: '// up and running in 5 minutes',
|
||||||
|
headlineN: 'N',
|
||||||
|
headlineOne: '1',
|
||||||
|
headlineSep: 'subscriptions →',
|
||||||
|
headlineSuffix: 'key',
|
||||||
|
sub1: 'No more juggling accounts,',
|
||||||
|
sub2: 'no more paying twice for overlapping subscriptions.',
|
||||||
|
tagline: 'PURO — AI calls, back to basics.',
|
||||||
|
stepsTitle: '// next steps',
|
||||||
|
step1Title: 'Create account',
|
||||||
|
step1Desc: 'Email + password, or LinuxDO OAuth',
|
||||||
|
step2Title: 'Connect subscription',
|
||||||
|
step2Desc: 'OAuth into your existing Claude Pro / ChatGPT Plus',
|
||||||
|
step3Title: 'Get your API key',
|
||||||
|
step3Desc: 'Grab your sk-puro-… and swap the SDK\'s base_url',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
@@ -5680,4 +5712,61 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
docs: {
|
||||||
|
nav: {
|
||||||
|
products: 'Product',
|
||||||
|
pricing: 'Pricing',
|
||||||
|
docs: 'Docs',
|
||||||
|
login: 'Sign in',
|
||||||
|
signup: 'Sign up',
|
||||||
|
},
|
||||||
|
hero: {
|
||||||
|
title: 'Quickstart — PURO AI',
|
||||||
|
subtitle: 'Three steps: get a key → set base_url → send a request',
|
||||||
|
},
|
||||||
|
sections: {
|
||||||
|
getKey: {
|
||||||
|
heading: '1. Get your API key',
|
||||||
|
desc: 'PURO AI is currently invite-only. Contact the admin to get access:',
|
||||||
|
note: 'Subscription self-purchase via the iShare portal is coming soon.',
|
||||||
|
},
|
||||||
|
codex: {
|
||||||
|
heading: '2. Codex CLI setup',
|
||||||
|
configIntro: 'Edit ~/.codex/config.toml:',
|
||||||
|
authIntro: 'Then ~/.codex/auth.json:',
|
||||||
|
verifyIntro: 'Verify:',
|
||||||
|
copy: 'Copy',
|
||||||
|
copied: 'Copied',
|
||||||
|
},
|
||||||
|
claudeCode: {
|
||||||
|
heading: '3. Claude Code setup',
|
||||||
|
configIntro: 'Edit ~/.claude/settings.json:',
|
||||||
|
note: 'Claude Code calls the Anthropic-compatible API via the /v1/messages endpoint.',
|
||||||
|
copy: 'Copy',
|
||||||
|
copied: 'Copied',
|
||||||
|
},
|
||||||
|
curl: {
|
||||||
|
heading: '4. curl quick test',
|
||||||
|
openaiIntro: 'OpenAI Responses API:',
|
||||||
|
anthropicIntro: 'Anthropic Messages API:',
|
||||||
|
copy: 'Copy',
|
||||||
|
copied: 'Copied',
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
heading: '5. Available models',
|
||||||
|
colModel: 'Model',
|
||||||
|
colPlatform: 'Platform / source',
|
||||||
|
colContext: 'Context',
|
||||||
|
colStatus: 'Status',
|
||||||
|
codexDedicated: 'OpenAI Codex dedicated',
|
||||||
|
note: 'Pricing is tracked live from model-price-repo. Full list available in the dashboard after signing in.',
|
||||||
|
noteConsole: 'dashboard',
|
||||||
|
},
|
||||||
|
feedback: {
|
||||||
|
heading: '6. Feedback',
|
||||||
|
desc: 'Run into an issue or want a new platform added:',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -505,6 +505,38 @@ export default {
|
|||||||
puroRegisterTitle: '创建账户',
|
puroRegisterTitle: '创建账户',
|
||||||
puroRegisterSub: '5 分钟开始用 PURO AI',
|
puroRegisterSub: '5 分钟开始用 PURO AI',
|
||||||
confirmPasswordLabel: '确认密码',
|
confirmPasswordLabel: '确认密码',
|
||||||
|
narrative: {
|
||||||
|
common: {
|
||||||
|
statusLive: 'live',
|
||||||
|
},
|
||||||
|
login: {
|
||||||
|
kicker: '// 你的订阅,已经付过钱了',
|
||||||
|
headlineN: 'N',
|
||||||
|
headlineOne: '1',
|
||||||
|
headlineSep: '个订阅 →',
|
||||||
|
headlineSuffix: '个 key',
|
||||||
|
sub1: '省去切换账号的繁琐,',
|
||||||
|
sub2: '省去为多个高昂订阅重复买单。',
|
||||||
|
tagline: 'PURO(纯粹)—— 让 AI 调用回归本质。',
|
||||||
|
},
|
||||||
|
register: {
|
||||||
|
kicker: '// 5 分钟开始用',
|
||||||
|
headlineN: 'N',
|
||||||
|
headlineOne: '1',
|
||||||
|
headlineSep: '个订阅 →',
|
||||||
|
headlineSuffix: '个 key',
|
||||||
|
sub1: '省去切换账号的繁琐,',
|
||||||
|
sub2: '省去为多个高昂订阅重复买单。',
|
||||||
|
tagline: 'PURO(纯粹)—— 让 AI 调用回归本质。',
|
||||||
|
stepsTitle: '// 下一步',
|
||||||
|
step1Title: '创建账户',
|
||||||
|
step1Desc: '邮箱 + 密码,或用 LinuxDO OAuth',
|
||||||
|
step2Title: '绑定订阅',
|
||||||
|
step2Desc: 'OAuth 接入你现有的 Claude Pro / ChatGPT Plus',
|
||||||
|
step3Title: '生成 key',
|
||||||
|
step3Desc: '拿到 sk-puro-…,换掉 SDK 的 base_url',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
@@ -5873,4 +5905,61 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
docs: {
|
||||||
|
nav: {
|
||||||
|
products: '产品',
|
||||||
|
pricing: '定价',
|
||||||
|
docs: '文档',
|
||||||
|
login: '登录',
|
||||||
|
signup: '注册',
|
||||||
|
},
|
||||||
|
hero: {
|
||||||
|
title: '快速接入 PURO AI',
|
||||||
|
subtitle: '三步走:拿 key → 配 base_url → 发请求',
|
||||||
|
},
|
||||||
|
sections: {
|
||||||
|
getKey: {
|
||||||
|
heading: '1. 获取 API key',
|
||||||
|
desc: '当前 PURO AI 不开放自助注册付费。联系管理员获取:',
|
||||||
|
note: '未来通过 iShare 入口开放订阅购买。',
|
||||||
|
},
|
||||||
|
codex: {
|
||||||
|
heading: '2. Codex CLI 接入',
|
||||||
|
configIntro: '修改 ~/.codex/config.toml:',
|
||||||
|
authIntro: '然后 ~/.codex/auth.json:',
|
||||||
|
verifyIntro: '验证:',
|
||||||
|
copy: '复制',
|
||||||
|
copied: '已复制',
|
||||||
|
},
|
||||||
|
claudeCode: {
|
||||||
|
heading: '3. Claude Code 接入',
|
||||||
|
configIntro: '修改 ~/.claude/settings.json:',
|
||||||
|
note: 'Claude Code 通过 /v1/messages endpoint 调用 Anthropic 兼容 API。',
|
||||||
|
copy: '复制',
|
||||||
|
copied: '已复制',
|
||||||
|
},
|
||||||
|
curl: {
|
||||||
|
heading: '4. curl 直连测试',
|
||||||
|
openaiIntro: 'OpenAI Responses API:',
|
||||||
|
anthropicIntro: 'Anthropic Messages API:',
|
||||||
|
copy: '复制',
|
||||||
|
copied: '已复制',
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
heading: '5. 支持的模型',
|
||||||
|
colModel: '模型',
|
||||||
|
colPlatform: '平台 / 来源',
|
||||||
|
colContext: '上下文',
|
||||||
|
colStatus: '状态',
|
||||||
|
codexDedicated: 'OpenAI Codex 专用',
|
||||||
|
note: '后端 pricing 表实时跟进 model-price-repo,完整清单登录后在控制台查看。',
|
||||||
|
noteConsole: '控制台',
|
||||||
|
},
|
||||||
|
feedback: {
|
||||||
|
heading: '6. 问题反馈',
|
||||||
|
desc: '遇到问题或希望补接某个平台:',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,15 +11,17 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="n-kicker">// 你的订阅,已经付过钱了</div>
|
<div class="n-kicker">{{ t('auth.narrative.login.kicker') }}</div>
|
||||||
<div class="auth-narrative-headline" style="margin-top: 12px;">
|
<div class="auth-narrative-headline" style="margin-top: 12px;">
|
||||||
<span class="num-n">N</span> 个订阅<br>
|
<span class="num-n">{{ t('auth.narrative.login.headlineN') }}</span>
|
||||||
→ <span class="num-1">1</span> 个 key
|
{{ ' ' + t('auth.narrative.login.headlineSep') + ' ' }}
|
||||||
|
<span class="num-1">{{ t('auth.narrative.login.headlineOne') }}</span>
|
||||||
|
{{ ' ' + t('auth.narrative.login.headlineSuffix') }}
|
||||||
</div>
|
</div>
|
||||||
<p class="auth-narrative-sub">
|
<p class="auth-narrative-sub">
|
||||||
省去切换账号的繁琐,<br>
|
{{ t('auth.narrative.login.sub1') }}<br>
|
||||||
省去为多个高昂订阅重复买单。<br>
|
{{ t('auth.narrative.login.sub2') }}<br>
|
||||||
<span class="auth-narrative-tagline">PURO(纯粹)—— 让 AI 调用回归本质。</span>
|
<span class="auth-narrative-tagline">{{ t('auth.narrative.login.tagline') }}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -11,31 +11,33 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="n-kicker">// 5 分钟开始用</div>
|
<div class="n-kicker">{{ t('auth.narrative.register.kicker') }}</div>
|
||||||
<div class="auth-narrative-headline" style="margin-top: 12px;">
|
<div class="auth-narrative-headline" style="margin-top: 12px;">
|
||||||
<span class="num-n">N</span> 个订阅<br>
|
<span class="num-n">{{ t('auth.narrative.register.headlineN') }}</span>
|
||||||
→ <span class="num-1">1</span> 个 key
|
{{ ' ' + t('auth.narrative.register.headlineSep') + ' ' }}
|
||||||
|
<span class="num-1">{{ t('auth.narrative.register.headlineOne') }}</span>
|
||||||
|
{{ ' ' + t('auth.narrative.register.headlineSuffix') }}
|
||||||
</div>
|
</div>
|
||||||
<p class="auth-narrative-sub">
|
<p class="auth-narrative-sub">
|
||||||
省去切换账号的繁琐,<br>
|
{{ t('auth.narrative.register.sub1') }}<br>
|
||||||
省去为多个高昂订阅重复买单。<br>
|
{{ t('auth.narrative.register.sub2') }}<br>
|
||||||
<span class="auth-narrative-tagline">PURO(纯粹)—— 让 AI 调用回归本质。</span>
|
<span class="auth-narrative-tagline">{{ t('auth.narrative.register.tagline') }}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="steps">
|
<div class="steps">
|
||||||
<div class="steps-title">// 下一步</div>
|
<div class="steps-title">{{ t('auth.narrative.register.stepsTitle') }}</div>
|
||||||
<div class="step active">
|
<div class="step active">
|
||||||
<div class="step-num">1</div>
|
<div class="step-num">1</div>
|
||||||
<div class="step-text"><b>创建账户</b> · 邮箱 + 密码,或用 LinuxDO OAuth</div>
|
<div class="step-text"><b>{{ t('auth.narrative.register.step1Title') }}</b> · {{ t('auth.narrative.register.step1Desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="step">
|
<div class="step">
|
||||||
<div class="step-num">2</div>
|
<div class="step-num">2</div>
|
||||||
<div class="step-text"><b>绑定订阅</b> · OAuth 接入你现有的 Claude Pro / ChatGPT Plus</div>
|
<div class="step-text"><b>{{ t('auth.narrative.register.step2Title') }}</b> · {{ t('auth.narrative.register.step2Desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="step">
|
<div class="step">
|
||||||
<div class="step-num">3</div>
|
<div class="step-num">3</div>
|
||||||
<div class="step-text"><b>生成 key</b> · 拿到 <span class="k">sk-puro-…</span>,换掉 SDK 的 <span class="k">base_url</span></div>
|
<div class="step-text"><b>{{ t('auth.narrative.register.step3Title') }}</b> · {{ t('auth.narrative.register.step3Desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -11,36 +11,36 @@
|
|||||||
<span>PURO AI</span>
|
<span>PURO AI</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div class="nav-links">
|
<div class="nav-links">
|
||||||
<router-link to="/">产品</router-link>
|
<router-link to="/">{{ $t('docs.nav.products') }}</router-link>
|
||||||
<router-link to="/pricing">定价</router-link>
|
<router-link to="/pricing">{{ $t('docs.nav.pricing') }}</router-link>
|
||||||
<router-link to="/docs" class="active">文档</router-link>
|
<router-link to="/docs" class="active">{{ $t('docs.nav.docs') }}</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-cta">
|
<div class="nav-cta">
|
||||||
<PuroLocaleSwitcher />
|
<PuroLocaleSwitcher />
|
||||||
<router-link to="/login" class="btn btn-ghost">登录</router-link>
|
<router-link to="/login" class="btn btn-ghost">{{ $t('docs.nav.login') }}</router-link>
|
||||||
<router-link to="/register" class="btn btn-primary">注册</router-link>
|
<router-link to="/register" class="btn btn-primary">{{ $t('docs.nav.signup') }}</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<section class="docs-hero container">
|
<section class="docs-hero container">
|
||||||
<h1>快速接入 PURO AI</h1>
|
<h1>{{ $t('docs.hero.title') }}</h1>
|
||||||
<p class="subtitle">三步走:拿 key → 配 base_url → 发请求</p>
|
<p class="subtitle">{{ $t('docs.hero.subtitle') }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="container docs-body">
|
<div class="container docs-body">
|
||||||
<section id="get-key" class="docs-section">
|
<section id="get-key" class="docs-section">
|
||||||
<h2>1. 获取 API key</h2>
|
<h2>{{ $t('docs.sections.getKey.heading') }}</h2>
|
||||||
<p>当前 PURO AI 不开放自助注册付费。联系管理员获取:</p>
|
<p>{{ $t('docs.sections.getKey.desc') }}</p>
|
||||||
<div class="callout">
|
<div class="callout">
|
||||||
<a href="mailto:admin@puro.im">admin@puro.im</a>
|
<a href="mailto:admin@puro.im">admin@puro.im</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="note">未来通过 iShare 入口开放订阅购买。</p>
|
<p class="note">{{ $t('docs.sections.getKey.note') }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="codex" class="docs-section">
|
<section id="codex" class="docs-section">
|
||||||
<h2>2. Codex CLI 接入</h2>
|
<h2>{{ $t('docs.sections.codex.heading') }}</h2>
|
||||||
<p>修改 <code class="mono">~/.codex/config.toml</code>:</p>
|
<p>{{ $t('docs.sections.codex.configIntro') }}</p>
|
||||||
<div class="code-panel">
|
<div class="code-panel">
|
||||||
<div class="code-head">
|
<div class="code-head">
|
||||||
<div class="traffic">
|
<div class="traffic">
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
复制
|
{{ $t('docs.sections.codex.copy') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="mono"><code>model_provider = <span class="str">"OpenAI"</span>
|
<pre class="mono"><code>model_provider = <span class="str">"OpenAI"</span>
|
||||||
@@ -67,7 +67,7 @@ base_url = <span class="str">"https://ai.puro.im"</span>
|
|||||||
wire_api = <span class="str">"responses"</span>
|
wire_api = <span class="str">"responses"</span>
|
||||||
requires_openai_auth = <span class="kw">true</span></code></pre>
|
requires_openai_auth = <span class="kw">true</span></code></pre>
|
||||||
</div>
|
</div>
|
||||||
<p>然后 <code class="mono">~/.codex/auth.json</code>:</p>
|
<p>{{ $t('docs.sections.codex.authIntro') }}</p>
|
||||||
<div class="code-panel">
|
<div class="code-panel">
|
||||||
<div class="code-head">
|
<div class="code-head">
|
||||||
<div class="traffic">
|
<div class="traffic">
|
||||||
@@ -81,14 +81,14 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
复制
|
{{ $t('docs.sections.codex.copy') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="mono"><code>{
|
<pre class="mono"><code>{
|
||||||
<span class="str">"OPENAI_API_KEY"</span>: <span class="str">"sk-xxxxxxxxxxxxxxxx"</span>
|
<span class="str">"OPENAI_API_KEY"</span>: <span class="str">"sk-xxxxxxxxxxxxxxxx"</span>
|
||||||
}</code></pre>
|
}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
<p>验证:</p>
|
<p>{{ $t('docs.sections.codex.verifyIntro') }}</p>
|
||||||
<div class="code-panel">
|
<div class="code-panel">
|
||||||
<div class="code-head">
|
<div class="code-head">
|
||||||
<div class="traffic">
|
<div class="traffic">
|
||||||
@@ -102,7 +102,7 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
复制
|
{{ $t('docs.sections.codex.copy') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="mono"><code><span class="cm">$</span> codex exec --sandbox read-only <span class="str">"say hi"</span></code></pre>
|
<pre class="mono"><code><span class="cm">$</span> codex exec --sandbox read-only <span class="str">"say hi"</span></code></pre>
|
||||||
@@ -110,8 +110,8 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="claude-code" class="docs-section">
|
<section id="claude-code" class="docs-section">
|
||||||
<h2>3. Claude Code 接入</h2>
|
<h2>{{ $t('docs.sections.claudeCode.heading') }}</h2>
|
||||||
<p>修改 <code class="mono">~/.claude/settings.json</code>:</p>
|
<p>{{ $t('docs.sections.claudeCode.configIntro') }}</p>
|
||||||
<div class="code-panel">
|
<div class="code-panel">
|
||||||
<div class="code-head">
|
<div class="code-head">
|
||||||
<div class="traffic">
|
<div class="traffic">
|
||||||
@@ -125,7 +125,7 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
复制
|
{{ $t('docs.sections.claudeCode.copy') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="mono"><code>{
|
<pre class="mono"><code>{
|
||||||
@@ -133,12 +133,12 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
<span class="str">"api_key"</span>: <span class="str">"sk-xxxxxxxxxxxxxxxx"</span>
|
<span class="str">"api_key"</span>: <span class="str">"sk-xxxxxxxxxxxxxxxx"</span>
|
||||||
}</code></pre>
|
}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
<p class="note">Claude Code 通过 <code class="mono">/v1/messages</code> endpoint 调用 Anthropic 兼容 API。</p>
|
<p class="note">{{ $t('docs.sections.claudeCode.note') }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="curl" class="docs-section">
|
<section id="curl" class="docs-section">
|
||||||
<h2>4. curl 直连测试</h2>
|
<h2>{{ $t('docs.sections.curl.heading') }}</h2>
|
||||||
<p>OpenAI Responses API:</p>
|
<p>{{ $t('docs.sections.curl.openaiIntro') }}</p>
|
||||||
<div class="code-panel">
|
<div class="code-panel">
|
||||||
<div class="code-head">
|
<div class="code-head">
|
||||||
<div class="traffic">
|
<div class="traffic">
|
||||||
@@ -152,7 +152,7 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
复制
|
{{ $t('docs.sections.curl.copy') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="mono"><code><span class="cm">$</span> curl https://ai.puro.im/responses \
|
<pre class="mono"><code><span class="cm">$</span> curl https://ai.puro.im/responses \
|
||||||
@@ -160,7 +160,7 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
-H <span class="str">"Content-Type: application/json"</span> \
|
-H <span class="str">"Content-Type: application/json"</span> \
|
||||||
-d <span class="str">'{"model":"gpt-5.4","input":"hello"}'</span></code></pre>
|
-d <span class="str">'{"model":"gpt-5.4","input":"hello"}'</span></code></pre>
|
||||||
</div>
|
</div>
|
||||||
<p>Anthropic Messages API:</p>
|
<p>{{ $t('docs.sections.curl.anthropicIntro') }}</p>
|
||||||
<div class="code-panel">
|
<div class="code-panel">
|
||||||
<div class="code-head">
|
<div class="code-head">
|
||||||
<div class="traffic">
|
<div class="traffic">
|
||||||
@@ -174,7 +174,7 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
<path d="M4 1.5h5a.5.5 0 0 1 .5.5v1h1V2a1.5 1.5 0 0 0-1.5-1.5H4A1.5 1.5 0 0 0 2.5 2v8A1.5 1.5 0 0 0 4 11.5h1v-1H4a.5.5 0 0 1-.5-.5V2a.5.5 0 0 1 .5-.5z"/>
|
||||||
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
<path d="M7 4.5A1.5 1.5 0 0 1 8.5 3h5A1.5 1.5 0 0 1 15 4.5v9a1.5 1.5 0 0 1-1.5 1.5h-5A1.5 1.5 0 0 1 7 13.5v-9z"/>
|
||||||
</svg>
|
</svg>
|
||||||
复制
|
{{ $t('docs.sections.curl.copy') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<pre class="mono"><code><span class="cm">$</span> curl https://ai.puro.im/v1/messages \
|
<pre class="mono"><code><span class="cm">$</span> curl https://ai.puro.im/v1/messages \
|
||||||
@@ -186,15 +186,15 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="models" class="docs-section">
|
<section id="models" class="docs-section">
|
||||||
<h2>5. 支持的模型</h2>
|
<h2>{{ $t('docs.sections.models.heading') }}</h2>
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<table class="models-table mono">
|
<table class="models-table mono">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>模型</th>
|
<th>{{ $t('docs.sections.models.colModel') }}</th>
|
||||||
<th>平台 / 来源</th>
|
<th>{{ $t('docs.sections.models.colPlatform') }}</th>
|
||||||
<th>上下文</th>
|
<th>{{ $t('docs.sections.models.colContext') }}</th>
|
||||||
<th>状态</th>
|
<th>{{ $t('docs.sections.models.colStatus') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -206,7 +206,7 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>gpt-5.4-codex</code></td>
|
<td><code>gpt-5.4-codex</code></td>
|
||||||
<td><span class="provider gpt"><span class="dot"></span>OpenAI Codex 专用</span></td>
|
<td><span class="provider gpt"><span class="dot"></span>{{ $t('docs.sections.models.codexDedicated') }}</span></td>
|
||||||
<td>272K</td>
|
<td>272K</td>
|
||||||
<td><span class="badge-ok">OK</span></td>
|
<td><span class="badge-ok">OK</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -237,12 +237,12 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<p class="note">后端 pricing 表实时跟进 <code class="mono">model-price-repo</code>,完整清单登录后在 <router-link to="/dashboard">控制台</router-link> 查看。</p>
|
<p class="note">{{ $t('docs.sections.models.note') }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="feedback" class="docs-section">
|
<section id="feedback" class="docs-section">
|
||||||
<h2>6. 问题反馈</h2>
|
<h2>{{ $t('docs.sections.feedback.heading') }}</h2>
|
||||||
<p>遇到问题或希望补接某个平台:</p>
|
<p>{{ $t('docs.sections.feedback.desc') }}</p>
|
||||||
<div class="callout">
|
<div class="callout">
|
||||||
<a href="mailto:admin@puro.im">admin@puro.im</a>
|
<a href="mailto:admin@puro.im">admin@puro.im</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -252,8 +252,11 @@ requires_openai_auth = <span class="kw">true</span></code></pre>
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
import PuroLocaleSwitcher from '@/components/puro/PuroLocaleSwitcher.vue'
|
import PuroLocaleSwitcher from '@/components/puro/PuroLocaleSwitcher.vue'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
async function copyCode(ev: MouseEvent) {
|
async function copyCode(ev: MouseEvent) {
|
||||||
const button = ev.currentTarget as HTMLButtonElement
|
const button = ev.currentTarget as HTMLButtonElement
|
||||||
const panel = button.closest('.code-panel')
|
const panel = button.closest('.code-panel')
|
||||||
@@ -262,7 +265,7 @@ async function copyCode(ev: MouseEvent) {
|
|||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(codeEl.innerText)
|
await navigator.clipboard.writeText(codeEl.innerText)
|
||||||
const original = button.innerHTML
|
const original = button.innerHTML
|
||||||
button.innerHTML = '<svg viewBox="0 0 16 16" width="12" height="12" fill="currentColor"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/></svg> 已复制'
|
button.innerHTML = `<svg viewBox="0 0 16 16" width="12" height="12" fill="currentColor"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/></svg> ${t('docs.sections.codex.copied')}`
|
||||||
button.classList.add('copied')
|
button.classList.add('copied')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
button.innerHTML = original
|
button.innerHTML = original
|
||||||
|
|||||||
Reference in New Issue
Block a user