桌面 GUI 外链修复 + 主题顺序调整(含结构扁平化进行中的工作区基线)

- 集成 tauri-plugin-opener:Cargo/lib.rs/capabilities/npm 四处接线,新增 src/openExternal.ts(桌面走 opener,浏览器回退 window.open,相对路径绝对化)
- 关于页 4 个链接、活动栏官网菜单、代理错误横幅 2 处健康检查链接全部改走 openExternal,桌面端可正常跳转
- 设置→外观 主题顺序调整为 深色/浅色/跟随系统
- release 二进制重编并验证(浏览器实测关于页链接可开文档页)
- 附带工作区中未提交的扁平化重构现状(另一会话进行中)
- homepage 落地页与文档终检通过(8787 / 与 /docs 双 200)
This commit is contained in:
logan committed 2026-10-16 03:03:36 +08:00
1 parent 6452026fd6
commit 2bb4ef7a95
299 files changed
+6059 -3322

No files matched your search

+282
View File
@@ -0,0 +1,282 @@
/* OpsxAPI 官网 —— 营销单页样式 */
:root {
--blue: #2563eb;
--blue-dark: #1d4ed8;
--blue-soft: rgba(37, 99, 235, 0.08);
--bg: #ffffff;
--bg-alt: #f6f8fc;
--border: #e4e9f1;
--text: #111827;
--text-2: #5b6880;
--text-3: #98a2b3;
--green: #059669;
--amber: #d97706;
--radius: 14px;
--shadow: 0 1px 3px rgba(16,24,40,.06), 0 12px 32px rgba(16,24,40,.07);
--mono: "JetBrains Mono", SFMono-Regular, Menlo, monospace;
}
* { box-sizing: border-box; scroll-behavior: smooth; }
body {
margin: 0; font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif;
color: var(--text); background: var(--bg); font-size: 15px; line-height: 1.75;
}
a { color: var(--blue); text-decoration: none; }
h1,h2,h3 { letter-spacing: -0.015em; }
section[id] { scroll-margin-top: 76px; }
.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.wrap.narrow { max-width: 820px; }
/* ---------- SVG 图标(lucide sprite) ---------- */
.i { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vertical-align: -2px; }
.i-lg { width: 28px; height: 28px; vertical-align: middle; }
code { font-family: var(--mono); font-size: 13px; background: var(--blue-soft); color: var(--blue-dark); border-radius: 5px; padding: 1px 6px; }
/* ---------- 按钮 ---------- */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
border-radius: 10px; padding: 9px 20px; font-size: 14.5px; font-weight: 600; cursor: pointer;
transition: all .18s; border: 1px solid transparent; white-space: nowrap;
}
.btn-lg { padding: 12px 26px; font-size: 15.5px; }
.btn-primary { background: var(--blue); color: #fff !important; box-shadow: 0 6px 18px rgba(37,99,235,.28); }
.btn-primary:hover { background: var(--blue-dark); transform: translateY(-1px); }
.btn-ghost { border-color: var(--border); color: var(--text) !important; background: #fff; }
.btn-ghost:hover { border-color: var(--blue); color: var(--blue) !important; }
.btn-inverse { background: #fff; color: var(--blue) !important; }
.btn-inverse:hover { transform: translateY(-1px); }
.btn-outline { border-color: rgba(255,255,255,.5); color: #fff !important; }
.btn-outline:hover { border-color: #fff; background: rgba(255,255,255,.1); }
/* ---------- 导航 ---------- */
.nav {
position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,.9);
backdrop-filter: blur(10px); border-bottom: 1px solid var(--border);
}
.nav-inner { max-width: 1120px; margin: 0 auto; padding: 0 24px; height: 60px; display: flex; align-items: center; gap: 28px; }
.brand { display: flex; align-items: center; gap: 9px; }
.brand-logo { display: inline-flex; }
.brand-logo svg { display: block; border-radius: 8px; }
.brand-name { font-size: 17px; font-weight: 800; color: var(--text) !important; }
.nav-links { display: flex; gap: 22px; }
.nav-links a { font-size: 14px; font-weight: 500; color: var(--text-2) !important; }
.nav-links a:hover { color: var(--blue) !important; }
.nav-cta { margin-left: auto; }
/* ---------- Hero ---------- */
.hero {
position: relative; overflow: hidden;
background:
radial-gradient(1200px 500px at 85% -10%, rgba(37,99,235,.14), transparent 60%),
radial-gradient(800px 400px at -10% 10%, rgba(5,150,105,.08), transparent 55%),
linear-gradient(180deg, #f8faff 0%, #fff 100%);
border-bottom: 1px solid var(--border);
}
.hero-inner {
max-width: 1120px; margin: 0 auto; padding: 72px 24px 64px;
display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 48px; align-items: center;
}
.hero-badge {
display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--blue-dark);
background: #fff; border: 1px solid rgba(37,99,235,.25); border-radius: 999px; padding: 4px 14px;
box-shadow: 0 2px 8px rgba(37,99,235,.1); margin-bottom: 18px;
}
.hero h1 { font-size: 44px; line-height: 1.22; font-weight: 800; margin: 0 0 16px; }
.hero h1 em { font-style: normal; color: var(--blue); }
.hero-sub { color: var(--text-2); font-size: 16px; margin: 0 0 26px; }
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; }
.hero-actions.center { justify-content: center; }
.hero-pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
.hero-pills span {
font-size: 12px; color: var(--text-2); background: #fff; border: 1px solid var(--border);
padding: 3px 12px; border-radius: 999px;
}
/* ---------- Mock 界面 ---------- */
.mock {
border-radius: 14px; overflow: hidden; box-shadow: var(--shadow); border: 1px solid #1e2b45;
background: #0d1526; transform: perspective(1400px) rotateY(-4deg) rotateX(1.5deg);
}
.mock-titlebar {
display: flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
background: #101a30; border-bottom: 1px solid #1e2b45;
}
.mock-titlebar i { width: 11px; height: 11px; border-radius: 50%; background: #3a4a6b; }
.mock-titlebar i:nth-child(1) { background: #f87171; } .mock-titlebar i:nth-child(2) { background: #fbbf24; } .mock-titlebar i:nth-child(3) { background: #34d399; }
.mock-titlebar span { margin-left: 8px; color: #8b99b0; font-size: 11px; }
.mock-body { display: grid; grid-template-columns: 158px minmax(0,1fr); min-height: 320px; }
.mock-side { border-right: 1px solid #1e2b45; padding: 10px 8px; background: #0c1322; }
.mock-search { height: 22px; border-radius: 6px; background: #16213a; margin-bottom: 10px; }
.mock-group { color: #8b99b0; font-size: 11px; padding: 6px 6px 3px; }
.mock-item { display: flex; align-items: center; gap: 6px; color: #aab8d0; font-size: 11.5px; padding: 4px 6px; border-radius: 6px; }
.mock-item.active { background: rgba(37,99,235,.18); color: #93c5fd; }
.mi { width: 11px; height: 11px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; opacity: .8; }
.m-get { color: #34d399; font-style: normal; font-size: 9.5px; min-width: 30px; }
.m-post { color: #fbbf24; font-style: normal; font-size: 9.5px; min-width: 30px; }
.mock-main { padding: 10px 12px; display: flex; flex-direction: column; gap: 9px; }
.mock-urlbar { display: flex; align-items: center; gap: 8px; }
.mock-url {
flex: 1; background: #0a1120; border: 1px solid #22304f; border-radius: 7px; color: #cbd5e1;
font-family: var(--mono); font-size: 11px; padding: 6px 10px;
}
.mock-send {
background: var(--blue); color: #fff; font-size: 11px; font-weight: 600;
border-radius: 7px; padding: 6px 14px;
}
.mock-req, .mock-resp { border: 1px solid #1e2b45; border-radius: 9px; padding: 8px 10px; background: #0c1322; }
.mock-req .tab, .mock-resp .tab { color: #5c6a83; font-size: 10.5px; margin-right: 12px; }
.mock-req .tab.on { color: #93c5fd; border-bottom: 2px solid var(--blue); padding-bottom: 2px; }
.mock-resp .tab.on { color: #6ee7b7; border-bottom: 2px solid var(--green); padding-bottom: 2px; }
.mock-status { float: right; color: #34d399; font-size: 10px; font-family: var(--mono); }
.mock pre {
margin: 8px 0 2px; font-family: var(--mono); font-size: 11px; line-height: 1.6; color: #cbd5e1;
white-space: pre-wrap;
}
.mock pre i { font-style: normal; color: #7dd3fc; }
.mock pre u { text-decoration: none; color: #86efac; }
/* ---------- 通用 Section ---------- */
.section { padding: 72px 0; }
.section.alt { background: var(--bg-alt); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.sec-title { font-size: 30px; font-weight: 800; text-align: center; margin: 0 0 8px; }
.sec-sub { text-align: center; color: var(--text-2); margin: 0 0 40px; }
.grid { display: grid; gap: 18px; }
.g3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
/* ---------- 卡片 ---------- */
.card {
background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
padding: 22px; box-shadow: 0 1px 2px rgba(16,24,40,.04); transition: all .18s;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: rgba(37,99,235,.35); }
.card h3 { font-size: 16px; margin: 0 0 6px; }
.card p { color: var(--text-2); font-size: 13.5px; margin: 0; }
.card-icon { color: var(--blue); margin-bottom: 10px; }
.card-icon .i-lg { width: 30px; height: 30px; }
.card.row { display: flex; gap: 14px; align-items: flex-start; }
.card.row .card-icon { margin: 2px 0 0; }
.card.mini h3 { font-size: 15px; display: flex; align-items: center; gap: 8px; }
.card.mini h3 .i-lg { width: 20px; height: 20px; color: var(--blue); }
.card.mini p { font-size: 13px; }
/* ---------- 协议 ---------- */
.proto {
background: #fff; border: 1px solid var(--border); border-left: 3px solid var(--blue);
border-radius: 12px; padding: 18px 20px;
}
.proto h3 { margin: 0 0 6px; font-size: 15.5px; display: flex; align-items: center; gap: 8px; }
.proto h3 .i { color: var(--blue); width: 17px; height: 17px; }
.proto p { margin: 0; color: var(--text-2); font-size: 13.5px; }
/* ---------- 导入导出 ---------- */
.badges { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-bottom: 18px; }
.badges span {
background: #fff; border: 1px solid var(--border); border-radius: 999px;
padding: 6px 16px; font-size: 13px; font-weight: 500; color: var(--text);
}
.badges span.more { border-style: dashed; color: var(--text-2); }
.footnote { text-align: center; color: var(--text-3); font-size: 12.5px; margin: 10px 0 0; }
.exchange-actions { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; margin-top: 26px; }
.chip {
display: inline-flex; align-items: center; gap: 6px;
background: #fff; border: 1px solid var(--border); border-radius: 10px; padding: 8px 16px;
font-size: 13px; font-weight: 600; color: var(--text-2);
}
.chip.big { background: var(--blue); border-color: var(--blue); color: #fff; padding: 10px 22px; }
.exchange-arrow { color: var(--text-3); font-size: 15px; }
/* ---------- 对比表 ---------- */
.table-wrap { overflow-x: auto; }
.cmp { border-collapse: collapse; width: 100%; background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 0 0 1px var(--border); font-size: 14px; }
.cmp th, .cmp td { padding: 12px 16px; text-align: left; border-bottom: 1px solid var(--border); }
.cmp th { background: #f9fbfe; font-size: 13.5px; }
.cmp tr:last-child td { border-bottom: none; }
.cmp td.hl { background: rgba(37,99,235,.05); color: var(--blue-dark); }
.cmp th.hl { background: var(--blue); color: #fff; }
/* ---------- 定价 ---------- */
.pricing { display: grid; grid-template-columns: repeat(2, minmax(0, 380px)); gap: 22px; justify-content: center; }
.pricing.three { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 1080px; margin: 0 auto; }
.price-card {
position: relative; background: #fff; border: 1px solid var(--border); border-radius: 16px;
padding: 30px 28px 26px; box-shadow: 0 1px 2px rgba(16,24,40,.04); display: flex; flex-direction: column;
}
.price-card.featured { border: 2px solid var(--blue); box-shadow: 0 12px 36px rgba(37,99,235,.16); }
.price-card.enterprise {
background: linear-gradient(160deg, #101a30 0%, #0d1526 70%);
border: 1px solid #2a3b5e; box-shadow: 0 14px 40px rgba(13,21,38,.4);
}
.price-card.enterprise .plan { color: #8b99b0; }
.price-card.enterprise .price b { color: #fff; font-size: 36px; }
.price-card.enterprise .price span { color: #8b99b0; }
.price-card.enterprise .plan-sub { color: #8b99b0; }
.price-card.enterprise li { color: #aab8d0; border-bottom-color: #22304f; }
.price-card.enterprise .deal-note {
margin-top: 14px; font-size: 11.5px; line-height: 1.7; color: #8b99b0;
background: rgba(255,255,255,.05); border: 1px dashed #2a3b5e; border-radius: 9px; padding: 9px 12px;
}
.price-card.enterprise .deal-note b { color: #93c5fd; }
.btn-dark { background: #fff; color: #0d1526 !important; }
.btn-dark:hover { transform: translateY(-1px); background: #e8eefc; }
.plan-tag {
position: absolute; top: -13px; left: 50%; transform: translateX(-50%);
background: var(--blue); color: #fff; font-size: 12px; font-weight: 700;
padding: 3px 14px; border-radius: 999px; white-space: nowrap;
}
.plan-tag.dark { background: #0d1526; border: 1px solid #2a3b5e; }
.plan { font-size: 16px; font-weight: 700; color: var(--text-2); }
.price { margin: 8px 0 2px; }
.price b { font-size: 44px; font-weight: 800; letter-spacing: -.02em; color: var(--text); }
.price span { color: var(--text-3); font-size: 14px; margin-left: 4px; }
.plan-sub { color: var(--text-3); font-size: 13px; margin-bottom: 18px; }
.price-card ul { list-style: none; padding: 0; margin: 0 0 22px; flex: 1; }
.price-card li { font-size: 13.5px; color: var(--text-2); padding: 6px 0; border-bottom: 1px dashed var(--border); }
.price-card li:last-child { border-bottom: none; }
.price-card .btn { width: 100%; }
.growth-title { text-align: center; font-size: 20px; font-weight: 700; margin: 52px 0 22px; }
/* ---------- FAQ ---------- */
.faq details {
background: #fff; border: 1px solid var(--border); border-radius: 12px;
padding: 16px 20px; margin-bottom: 12px;
}
.faq summary { font-weight: 600; cursor: pointer; font-size: 15px; list-style: none; display: flex; justify-content: space-between; }
.faq summary::after { content: "+"; color: var(--text-3); font-weight: 400; }
.faq details[open] summary::after { content: "-"; }
.faq details p { margin: 10px 0 0; color: var(--text-2); font-size: 14px; }
/* ---------- CTA ---------- */
.cta {
background: linear-gradient(135deg, #1d4ed8 0%, #2563eb 55%, #3b82f6 100%);
color: #fff; text-align: center; padding: 72px 24px;
}
.cta h2 { font-size: 32px; font-weight: 800; margin: 0 0 10px; }
.cta p { color: rgba(255,255,255,.85); margin: 0 0 28px; }
/* ---------- Footer ---------- */
.footer { background: #0d1526; color: #8b99b0; padding: 52px 0 0; font-size: 13.5px; }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 32px; padding-bottom: 36px; }
.footer .brand-name { color: #fff !important; }
.footer .f-logo { display: block; border-radius: 8px; }
.footer .brand { display: flex; align-items: center; gap: 9px; }
.footer-desc { margin: 12px 0 0; font-size: 13px; line-height: 1.8; }
.footer h4 { color: #fff; font-size: 13.5px; margin: 4px 0 12px; }
.footer a { display: block; color: #8b99b0 !important; padding: 4px 0; font-size: 13px; }
.footer a:hover { color: #fff !important; }
.footer-bar { border-top: 1px solid #1e2b45; text-align: center; padding: 18px; font-size: 12px; color: #5c6a83; }
/* ---------- 响应式 ---------- */
@media (max-width: 1020px) {
.hero-inner { grid-template-columns: 1fr; padding-top: 52px; }
.mock { transform: none; }
.g4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.g3 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.pricing, .pricing.three { grid-template-columns: minmax(0, 420px); }
.footer-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 680px) {
.nav-links { display: none; }
.hero h1 { font-size: 32px; }
.sec-title { font-size: 24px; }
.g3, .g4 { grid-template-columns: 1fr; }
.footer-grid { grid-template-columns: 1fr; }
}
+80
View File
@@ -0,0 +1,80 @@
// Package site 在 /home(及 /)提供产品官网单页(SSR,资源嵌入二进制)。
package site
import (
"embed"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
//go:embed template.html terms.html assets
var files embed.FS
// Handler 官网服务
type Handler struct {
html string
terms string
}
func New() *Handler {
raw, err := files.ReadFile("template.html")
if err != nil {
panic("site: template.html 缺失: " + err.Error())
}
terms, err := files.ReadFile("terms.html")
if err != nil {
panic("site: terms.html 缺失: " + err.Error())
}
return &Handler{html: string(raw), terms: string(terms)}
}
// Register 注册路由:/ 与 /home 均渲染官网
func (h *Handler) Register(r *gin.Engine) {
r.GET("/", h.Page)
r.GET("/home", h.Page)
r.GET("/index.html", h.Page)
r.GET("/site/assets/*file", h.Asset)
r.GET("/terms", h.Terms)
}
// Terms 渲染服务条款
func (h *Handler) Terms(c *gin.Context) {
c.Header("Content-Type", "text/html; charset=utf-8")
c.Header("Cache-Control", "no-cache")
_, _ = c.Writer.WriteString(h.terms)
}
// Page 渲染官网
func (h *Handler) Page(c *gin.Context) {
c.Header("Content-Type", "text/html; charset=utf-8")
c.Header("Cache-Control", "no-cache")
_, _ = c.Writer.WriteString(h.html)
}
// Asset 静态资源
func (h *Handler) Asset(c *gin.Context) {
name := strings.TrimPrefix(c.Param("file"), "/")
if strings.Contains(name, "..") {
c.Status(http.StatusBadRequest)
return
}
data, err := files.ReadFile("assets/" + name)
if err != nil {
c.Status(http.StatusNotFound)
return
}
switch {
case strings.HasSuffix(name, ".css"):
c.Header("Content-Type", "text/css; charset=utf-8")
case strings.HasSuffix(name, ".js"):
c.Header("Content-Type", "application/javascript; charset=utf-8")
case strings.HasSuffix(name, ".svg"):
c.Header("Content-Type", "image/svg+xml")
default:
c.Header("Content-Type", "application/octet-stream")
}
c.Header("Cache-Control", "public, max-age=3600")
c.Data(http.StatusOK, "", data)
}
+63
View File
@@ -0,0 +1,63 @@
package site
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gin-gonic/gin"
)
func newTestRouter(t *testing.T) *gin.Engine {
t.Helper()
gin.SetMode(gin.TestMode)
r := gin.New()
New().Register(r)
return r
}
func TestSitePageRender(t *testing.T) {
r := newTestRouter(t)
for _, path := range []string{"/", "/home", "/index.html"} {
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, path, nil))
if w.Code != http.StatusOK {
t.Fatalf("%s: expect 200, got %d", path, w.Code)
}
body := w.Body.String()
for _, want := range []string{
"<title>OpsxAPI", // 标题
`id="features"`, // 功能区
`id="pricing"`, // 定价区
"¥99", // 入门价
"¥8,000", // 企业档标价
"¥30,000", // 买断标价
"¥5,000–8,000", // 成交区间
"永久买断", // 买断 FAQ
"早鸟创始价", // 让利策略
"Socket.IO", // 协议覆盖
"hello@opsxapi.dev", // 联系方式
`href="/docs"`, // 文档互链
`href="/site/assets/site.css"`, // 样式资源
} {
if !strings.Contains(body, want) {
t.Fatalf("%s: missing %q", path, want)
}
}
}
}
func TestSiteAsset(t *testing.T) {
r := newTestRouter(t)
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/site/assets/site.css", nil))
if w.Code != http.StatusOK || !strings.Contains(w.Header().Get("Content-Type"), "text/css") {
t.Fatalf("css: %d %s", w.Code, w.Header().Get("Content-Type"))
}
w = httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/site/assets/../template.html", nil))
if w.Code != http.StatusBadRequest && w.Code != http.StatusNotFound {
t.Fatalf("path traversal should be rejected, got %d", w.Code)
}
}
+357
View File
@@ -0,0 +1,357 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OpsxAPI — 本地优先的全协议接口工作台</title>
<meta name="description" content="OpsxAPI:HTTP、GraphQL、WebSocket、SSE、Socket.IO、MQTT 一站式调试。本地优先数据主权,OpenAPI/Postman/cURL 全格式导入导出。个人版 ¥99/年,团队版 ¥99/人/年。">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%232563eb'/%3E%3Ctext x='16' y='22' font-size='18' font-weight='bold' fill='%23fff' text-anchor='middle' font-family='sans-serif'%3EO%3C/text%3E%3C/svg%3E">
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22g%22%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%2264%22%20y2%3D%2264%22%20gradientUnits%3D%22userSpaceOnUse%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%232563EB%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%2306B6D4%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22url%28%23g%29%22%2F%3E%3Cg%20stroke%3D%22%23fff%22%20stroke-width%3D%225%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20fill%3D%22none%22%3E%3Cpath%20d%3D%22M17%2025h26%22%2F%3E%3Cpath%20d%3D%22M37%2019l6%206-6%206%22%2F%3E%3Cpath%20d%3D%22M47%2039H21%22%2F%3E%3Cpath%20d%3D%22M27%2033l-6%206%206%206%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E">
<link rel="stylesheet" href="/site/assets/site.css">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">
<symbol id="i-rocket" viewBox="0 0 24 24"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5" /> <path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09" /> <path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z" /> <path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05" /></symbol>
<symbol id="i-shield-check" viewBox="0 0 24 24"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" /> <path d="m9 12 2 2 4-4" /></symbol>
<symbol id="i-arrow-left-right" viewBox="0 0 24 24"><path d="M8 3 4 7l4 4" /> <path d="M4 7h16" /> <path d="m16 21 4-4-4-4" /> <path d="M20 17H4" /></symbol>
<symbol id="i-plug-zap" viewBox="0 0 24 24"><path d="M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z" /> <path d="m2 22 3-3" /> <path d="M7.5 13.5 10 11" /> <path d="M10.5 16.5 13 14" /> <path d="m18 3-4 4h6l-4 4" /></symbol>
<symbol id="i-package" viewBox="0 0 24 24"><path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z" /> <path d="M12 22V12" /> <polyline points="3.29 7 12 12 20.71 7" /> <path d="m7.5 4.27 9 5.15" /></symbol>
<symbol id="i-folder-tree" viewBox="0 0 24 24"><path d="M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z" /> <path d="M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z" /> <path d="M3 5a2 2 0 0 0 2 2h3" /> <path d="M3 3v13a2 2 0 0 0 2 2h3" /></symbol>
<symbol id="i-globe" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" /> <path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" /> <path d="M2 12h20" /></symbol>
<symbol id="i-hexagon" viewBox="0 0 24 24"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" /></symbol>
<symbol id="i-zap" viewBox="0 0 24 24"><path d="M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z" /></symbol>
<symbol id="i-radio" viewBox="0 0 24 24"><path d="M16.247 7.761a6 6 0 0 1 0 8.478" /> <path d="M19.075 4.933a10 10 0 0 1 0 14.134" /> <path d="M4.925 19.067a10 10 0 0 1 0-14.134" /> <path d="M7.753 16.239a6 6 0 0 1 0-8.478" /> <circle cx="12" cy="12" r="2" /></symbol>
<symbol id="i-mailbox" viewBox="0 0 24 24"><path d="M22 17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9.5C2 7 4 5 6.5 5H18c2.2 0 4 1.8 4 4v8Z" /> <polyline points="15,9 18,9 18,11" /> <path d="M6.5 5C9 5 11 7 11 9.5V17a2 2 0 0 1-2 2" /> <line x1="6" x2="7" y1="10" y2="10" /></symbol>
<symbol id="i-code" viewBox="0 0 24 24"><path d="m16 18 6-6-6-6" /> <path d="m8 6-6 6 6 6" /></symbol>
<symbol id="i-book-open" viewBox="0 0 24 24"><path d="M12 5v16" /> <path d="M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z" /></symbol>
<symbol id="i-sprout" viewBox="0 0 24 24"><path d="M14 9.536V7a4 4 0 0 1 4-4h1.5a.5.5 0 0 1 .5.5V5a4 4 0 0 1-4 4 4 4 0 0 0-4 4c0 2 1 3 1 5a5 5 0 0 1-1 3" /> <path d="M4 9a5 5 0 0 1 8 4 5 5 0 0 1-8-4" /> <path d="M5 21h14" /></symbol>
<symbol id="i-graduation-cap" viewBox="0 0 24 24"><path d="M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z" /> <path d="M22 10v6" /> <path d="M6 12.5V16a6 3 0 0 0 12 0v-3.5" /></symbol>
<symbol id="i-credit-card" viewBox="0 0 24 24"><rect width="20" height="14" x="2" y="5" rx="2" /> <line x1="2" x2="22" y1="10" y2="10" /> <path d="M6 14h2" /></symbol>
<symbol id="i-megaphone" viewBox="0 0 24 24"><path d="M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z" /> <path d="M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14" /> <path d="M8 6v8" /></symbol>
<symbol id="i-download" viewBox="0 0 24 24"><path d="M12 15V3" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> <path d="m7 10 5 5 5-5" /></symbol>
<symbol id="i-upload" viewBox="0 0 24 24"><path d="M12 3v12" /> <path d="m17 8-5-5-5 5" /> <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /></symbol>
<symbol id="i-library" viewBox="0 0 24 24"><path d="m16 6 4 14" /> <path d="M12 6v14" /> <path d="M8 8v12" /> <path d="M4 4v16" /></symbol>
</svg>
<!-- ===================== 导航 ===================== -->
<header class="nav">
<div class="nav-inner">
<a class="brand" href="/home">
<span class="brand-logo"><svg width="30" height="30" viewBox="0 0 64 64" aria-label="OpsxAPI"><defs><linearGradient id="lg-site" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2563EB"/><stop offset="1" stop-color="#06B6D4"/></linearGradient></defs><rect width="64" height="64" rx="14" fill="url(#lg-site)"/><g stroke="#fff" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" fill="none"><path d="M17 25h26"/><path d="M37 19l6 6-6 6"/><path d="M47 39H21"/><path d="M27 33l-6 6 6 6"/></g></svg></span>
<span class="brand-name">OpsxAPI</span>
</a>
<nav class="nav-links">
<a href="#features">功能</a>
<a href="#protocols">协议</a>
<a href="#exchange">导入导出</a>
<a href="#pricing">定价</a>
<a href="/docs" target="_blank" rel="noopener">文档</a>
</nav>
<div class="nav-cta">
<a class="btn btn-primary" href="/" target="_blank" rel="noopener">打开工作台 ↗</a>
</div>
</div>
</header>
<!-- ===================== Hero ===================== -->
<section class="hero">
<div class="hero-inner">
<div class="hero-copy">
<div class="hero-badge"><svg class="i"><use href="#i-rocket"/></svg> v1.0 正式发布 · 数据 100% 本地</div>
<h1>一个工作台,<br>调完<em>六种协议</em>的接口</h1>
<p class="hero-sub">
HTTP · GraphQL · WebSocket · SSE · Socket.IO · MQTT。<br>
集合管理、多环境变量、全格式导入导出、代码生成、内置文档站 —— 运维与开发的自托管接口利器。
</p>
<div class="hero-actions">
<a class="btn btn-primary btn-lg" href="/" target="_blank" rel="noopener">立即开始(免费体验)</a>
<a class="btn btn-ghost btn-lg" href="/docs/quickstart" target="_blank" rel="noopener">快速开始 →</a>
</div>
<div class="hero-pills">
<span>本地优先</span><span>自定义 WS 握手头</span><span>SSE 断点续传</span><span>OpenAPI 双向同步</span>
</div>
</div>
<!-- 产品界面示意(纯 CSS 绘制) -->
<div class="mock" aria-hidden="true">
<div class="mock-titlebar"><i></i><i></i><i></i><span>OpsxAPI · 示例集合</span></div>
<div class="mock-body">
<div class="mock-side">
<div class="mock-search"></div>
<div class="mock-group"><svg class="mi"><use href="#i-library"/></svg> 示例集合</div>
<div class="mock-item"><b class="m-get">GET</b>获取请求回显</div>
<div class="mock-item"><b class="m-post">POST</b>提交 JSON</div>
<div class="mock-item"><b class="m-get">GET</b>Bearer 鉴权示例</div>
<div class="mock-group"><svg class="mi"><use href="#i-radio"/></svg> 实时协议</div>
<div class="mock-item active"><svg class="mi"><use href="#i-zap"/></svg> WebSocket · echo</div>
<div class="mock-item"><svg class="mi"><use href="#i-mailbox"/></svg> MQTT · EMQX</div>
<div class="mock-group"><svg class="mi"><use href="#i-hexagon"/></svg> GraphQL</div>
<div class="mock-item">国家查询 · countries</div>
</div>
<div class="mock-main">
<div class="mock-urlbar">
<b class="m-post">POST</b>
<span class="mock-url">{{baseUrl}}/v1/orders</span>
<span class="mock-send">发送</span>
</div>
<div class="mock-req">
<span class="tab on">Body</span><span class="tab">Params</span><span class="tab">Headers</span><span class="tab">Auth</span>
<pre>{
<i>"sku"</i>: <u>"A-1"</u>,
<i>"qty"</i>: <u>2</u>
}</pre>
</div>
<div class="mock-resp">
<span class="tab on">响应体</span>
<span class="mock-status">200 · 87ms · 274B</span>
<pre>{
<i>"orderId"</i>: <u>"ord_9f2a"</u>,
<i>"status"</i>: <u>"created"</u>,
<i>"paid"</i>: <u>false</u>
}</pre>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ===================== 为什么选 ===================== -->
<section class="section">
<div class="wrap">
<h2 class="sec-title">为什么团队选择 OpsxAPI</h2>
<p class="sec-sub">不追赶云端协作的花活,专注把「调试接口」这件事做到极致。</p>
<div class="grid g4">
<div class="card">
<div class="card-icon"><svg class="i-lg"><use href="#i-shield-check"/></svg></div>
<h3>本地优先,数据主权</h3>
<p>集合、环境、历史全部保存在本机,不经过任何第三方服务器。内网、涉密项目放心用。</p>
</div>
<div class="card">
<div class="card-icon"><svg class="i-lg"><use href="#i-arrow-left-right"/></svg></div>
<h3>六协议一个窗口</h3>
<p>HTTP / GraphQL / WebSocket / SSE / Socket.IO / MQTT 统一工作台,实时消息分色日志。</p>
</div>
<div class="card">
<div class="card-icon"><svg class="i-lg"><use href="#i-plug-zap"/></svg></div>
<h3>浏览器也能带握手头</h3>
<p>内置 WebSocket 隧道与流式代理,突破浏览器 CORS 与 Header 限制,调试网关级接口。</p>
</div>
<div class="card">
<div class="card-icon"><svg class="i-lg"><use href="#i-package"/></svg></div>
<h3>生态互通</h3>
<p>Apifox / Postman / Swagger / cURL / HAR 一键导入导出,迁移零成本,文档即代码。</p>
</div>
</div>
</div>
</section>
<!-- ===================== 功能 ===================== -->
<section class="section alt" id="features">
<div class="wrap">
<h2 class="sec-title">开箱即用的专业能力</h2>
<p class="sec-sub">从单人调试到团队交付,该有的都有。</p>
<div class="grid g3">
<div class="card row"><div class="card-icon"><svg class="i-lg"><use href="#i-folder-tree"/></svg></div><div><h3>集合与多标签</h3><p>目录树、搜索、右键菜单、拖拽移动;多标签并行调试。</p></div></div>
<div class="card row"><div class="card-icon"><svg class="i-lg"><use href="#i-globe"/></svg></div><div><h3>多环境变量</h3><p><code>{{baseUrl}}</code> 全局替换,正式 / 测试 / 本地一键切换。</p></div></div>
<div class="card row"><div class="card-icon"><svg class="i-lg"><use href="#i-shield-check"/></svg></div><div><h3>鉴权管理</h3><p>Bearer / Basic / API Key,token 走变量,一处配置全局生效。</p></div></div>
<div class="card row"><div class="card-icon"><svg class="i-lg"><use href="#i-zap"/></svg></div><div><h3>实时协议调试</h3><p>WS 握手头、SSE 断点续传、Socket.IO 事件收发、MQTT 通配符订阅。</p></div></div>
<div class="card row"><div class="card-icon"><svg class="i-lg"><use href="#i-code"/></svg></div><div><h3>代码生成</h3><p>任意请求一键生成 cURL / fetch / Python / Go,直接进脚本与 CI。</p></div></div>
<div class="card row"><div class="card-icon"><svg class="i-lg"><use href="#i-book-open"/></svg></div><div><h3>内置文档站</h3><p>随服务自带 /docs 用户文档与 Markdown 接口文档导出,交付即完整。</p></div></div>
</div>
</div>
</section>
<!-- ===================== 协议 ===================== -->
<section class="section" id="protocols">
<div class="wrap">
<h2 class="sec-title">六种协议,全覆盖</h2>
<p class="sec-sub">每个协议都有为它定制的编辑器,而不是塞进同一个表单。</p>
<div class="grid g3">
<div class="proto"><h3><svg class="i"><use href="#i-globe"/></svg> HTTP / REST</h3><p>7 种方法 · 6 种请求体 · 响应 Pretty 高亮 · 历史回跳</p></div>
<div class="proto"><h3><svg class="i"><use href="#i-hexagon"/></svg> GraphQL</h3><p>Query + Variables 编辑 · errors 高亮 · 生成 cURL 报文</p></div>
<div class="proto"><h3><svg class="i"><use href="#i-zap"/></svg> WebSocket</h3><p>自定义握手 Header(本地隧道)· 子协议 · 分色消息日志</p></div>
<div class="proto"><h3><svg class="i"><use href="#i-radio"/></svg> SSE</h3><p>直连失败自动切代理 · Last-Event-ID 续传 · 事件按名称归类</p></div>
<div class="proto"><h3><svg class="i"><use href="#i-plug-zap"/></svg> Socket.IO</h3><p>事件监听(onAny)· emit 参数 JSON · path / auth 配置</p></div>
<div class="proto"><h3><svg class="i"><use href="#i-mailbox"/></svg> MQTT</h3><p>wss Broker · 通配符订阅 · QoS 0/1/2 · 断线自动重连</p></div>
</div>
</div>
</section>
<!-- ===================== 导入导出 ===================== -->
<section class="section alt" id="exchange">
<div class="wrap">
<h2 class="sec-title">导入导出,迁移零成本</h2>
<p class="sec-sub">粘贴、文件、URL 三种来源,格式自动识别。</p>
<div class="badges">
<span>OpenAPI 3.0 / 3.1</span><span>Swagger 2.0</span><span>Apifox</span><span>Postman v2.1</span>
<span>Apipost</span><span>cURL</span><span>HAR</span><span>Insomnia</span><span>Hoppscotch</span><span>Markdown</span>
<span class="more">YApi / Apidoc / Apizza / Eolink ①</span>
</div>
<p class="footnote">① 经 OpenAPI / Postman 格式中转导入。导入自动:tag 建目录、路径参数转变量、schema 生成示例体、security 映射鉴权。</p>
<div class="exchange-actions">
<div class="chip"><svg class="i"><use href="#i-download"/></svg> 导入</div><div class="exchange-arrow">──→</div><div class="chip big">OpsxAPI</div><div class="exchange-arrow">──→</div>
<div class="chip"><svg class="i"><use href="#i-upload"/></svg> OpenAPI / Postman</div><div class="chip"><svg class="i"><use href="#i-upload"/></svg> Markdown 文档</div><div class="chip"><svg class="i"><use href="#i-upload"/></svg> 代码生成</div><div class="chip"><svg class="i"><use href="#i-upload"/></svg> 全量备份</div>
</div>
</div>
</section>
<!-- ===================== 对比 ===================== -->
<section class="section" id="compare">
<div class="wrap">
<h2 class="sec-title">与主流工具的对比</h2>
<p class="sec-sub">价格为各官网公开标价(2026-09 整理),以官方为准。</p>
<div class="table-wrap">
<table class="cmp">
<thead><tr><th>能力</th><th class="hl">OpsxAPI</th><th>Apifox</th><th>Apipost</th></tr></thead>
<tbody>
<tr><td>入门付费价格</td><td class="hl"><b>¥99/年</b>(个人)</td><td>¥99/人/年②</td><td>免费 + 商业版</td></tr>
<tr><td>专业档价格</td><td class="hl"><b>¥99/人/年</b>(团队)</td><td>¥199/人/年</td><td>按席位订阅</td></tr>
<tr><td>数据存储位置</td><td class="hl"><b>100% 本地</b></td><td>云端 / 私有化</td><td>云端 / 私有化</td></tr>
<tr><td>调试协议</td><td class="hl">HTTP · GraphQL · WS · SSE · Socket.IO · MQTT</td><td>HTTP · WS · GraphQL</td><td>HTTP · WS · gRPC 等</td></tr>
<tr><td>WS 自定义握手 Header(Web)</td><td class="hl"><b>✓ 内置隧道</b></td><td>桌面端支持</td><td>桌面端支持</td></tr>
<tr><td>自托管部署</td><td class="hl"><b>单二进制 + 静态页</b></td><td>私有化付费</td><td>私有化付费</td></tr>
<tr><td>私有化 / 买断参考价</td><td class="hl"><b>¥8,000/年起 · ¥30,000 买断</b></td><td>询价</td><td>询价</td></tr>
<tr><td>内置用户文档站</td><td class="hl"><b>✓ /docs</b></td><td>—</td><td>—</td></tr>
</tbody>
</table>
</div>
<p class="footnote">② Apifox 免费版即含大部分调试能力,付费档面向团队协作;对比仅帮助按需选型,各有所长。</p>
</div>
</section>
<!-- ===================== 定价 ===================== -->
<section class="section alt" id="pricing">
<div class="wrap">
<h2 class="sec-title">简单透明的定价</h2>
<p class="sec-sub">先在工作台免费用起来,需要授权与服务时再付费。</p>
<div class="pricing three">
<div class="price-card">
<div class="plan">个人版</div>
<div class="price"><b>¥99</b><span>/ 年</span></div>
<div class="plan-sub">单设备授权 · 全功能</div>
<ul>
<li>✓ 六种协议全部调试能力</li>
<li>✓ 集合 / 环境 / 历史无限量</li>
<li>✓ 全格式导入导出 + 代码生成</li>
<li>✓ 桌面端 + Web 双形态</li>
<li>✓ 1 年免费升级</li>
</ul>
<a class="btn btn-primary" href="#contact">购买咨询</a>
</div>
<div class="price-card featured">
<div class="plan-tag">高性价比之选</div>
<div class="plan">团队版</div>
<div class="price"><b>¥99</b><span>/ 人 / 年</span></div>
<div class="plan-sub">按席位授权 · 5 席起</div>
<ul>
<li>✓ 个人版全部能力</li>
<li>✓ 集合批量导入分发</li>
<li>✓ 内网自托管(单二进制)</li>
<li>✓ 优先技术支持</li>
<li>✓ 1 年免费升级</li>
</ul>
<a class="btn btn-primary" href="#contact">联系商务</a>
</div>
<div class="price-card enterprise">
<div class="plan-tag dark">私有化 · 单法人不限席位</div>
<div class="plan">企业私有化版</div>
<div class="price"><b>¥8,000</b><span>/ 年 · 标价</span></div>
<div class="plan-sub">或 ¥30,000 一次性永久买断(标价)</div>
<ul>
<li>✓ 整机 / 内网部署,数据不出企业</li>
<li>✓ 不限席位,团队版全部能力</li>
<li>✓ 远程部署协助 + 专属支持</li>
<li>✓ 定制开发通道(另行报价)</li>
<li>✓ 买断可选:永久使用 + 1 年升级</li>
</ul>
<a class="btn btn-dark" href="#contact">获取报价</a>
<div class="deal-note">
标价透明,成交灵活:经早鸟 / 教育 / 多年预付 / 案例合作,常见成交区间 <b>¥5,000–8,000/年</b>、买断 <b>¥15,000–30,000</b>。
</div>
</div>
</div>
<!-- 让利策略 -->
<h3 class="growth-title">早鸟与让利计划 —— 把优惠变成共同成长</h3>
<div class="grid g4">
<div class="card mini">
<h3><svg class="i-lg"><use href="#i-sprout"/></svg> 早鸟创始价</h3>
<p>前 20 个付费席位享 <b>5-7 折永久优惠</b>,并进入创始客户名单,参与需求优先排期。</p>
</div>
<div class="card mini">
<h3><svg class="i-lg"><use href="#i-graduation-cap"/></svg> 教育 / 开源</h3>
<p>高校师生、开源维护者凭证享 <b>6-8 折</b>。教育用途可申请批量授权。</p>
</div>
<div class="card mini">
<h3><svg class="i-lg"><use href="#i-credit-card"/></svg> 多年预付</h3>
<p>一次预付 2 年 <b>9 折</b>、3 年 <b>8 折</b>,锁定当期价格,改善双方现金流。</p>
</div>
<div class="card mini">
<h3><svg class="i-lg"><use href="#i-megaphone"/></svg> 案例换授权</h3>
<p>愿意公开使用案例、撰写评测或作为推荐客户的,可获 <b>额外折扣或免费席位</b>。</p>
</div>
</div>
<p class="footnote">以上为官网标价机制;最终成交价支持按规模与场景商务沟通,多年预付 / 服务范围(部署协助、定制开发)可组合。</p>
</div>
</section>
<!-- ===================== FAQ ===================== -->
<section class="section" id="faq">
<div class="wrap narrow">
<h2 class="sec-title">购买常见问题</h2>
<div class="faq">
<details open><summary>授权如何交付?包含哪些内容?</summary><p>邮件交付授权码与部署包(单二进制 + Web 静态资源),含使用文档。团队版附内网部署指南。</p></details>
<details><summary>一年后不续费还能用吗?</summary><p>可以。授权期内下载的版本可 <b>永久使用</b>,续费获得后续升级与支持。</p></details>
<details><summary>团队版怎么计费?人员变动怎么办?</summary><p>按启用席位每年计费,5 席起。人员变动可在授权期内置换席位,无需额外费用。</p></details>
<details><summary>可以开发票吗?</summary><p>支持增值税普通发票与专票,对公转账或线上支付均可。</p></details>
<details><summary>我们能自己部署吗?安全吗?</summary><p>完全可以,这正是 OpsxAPI 的设计初衷:数据 100% 本地,服务仅监听本机回环,内网部署无外联。</p></details>
<details><summary>可以永久买断吗?</summary><p>可以。企业私有化版支持一次性买断(标价 ¥30,000,含 1 年免费升级与支持),买断版本<b>永久使用</b>,续费仅用于继续获得升级。订阅档同理:授权期内下载的版本永久可用。</p></details>
<details><summary>预算有限,有优惠空间吗?</summary><p>我们不直接降价,但提供四种「让利换增长」机制:<b>早鸟创始价</b>(前 20 席 5–7 折永久)、<b>教育 / 开源</b> 6–8 折、<b>多年预付</b> 8–9 折、<b>以案例 / 评测换折扣</b>。相比按年订阅的 SaaS,5 人以上团队通常 1–2 年即可回本;可自行部署(我们提供文档)或以案例分享换取创始价。</p></details>
<details><summary>先试用再决定可以吗?</summary><p>欢迎。工作台全部调试能力可直接体验;授权版差异主要在商业支持与升级服务。</p></details>
</div>
</div>
</section>
<!-- ===================== CTA / 联系 ===================== -->
<section class="cta" id="contact">
<div class="wrap">
<h2>把接口调试收回自己手里</h2>
<p>现在打开工作台,30 秒发出第一个请求;采购事宜邮件联系,当天回复。</p>
<div class="hero-actions center">
<a class="btn btn-inverse btn-lg" href="/" target="_blank" rel="noopener">打开工作台 ↗</a>
<a class="btn btn-outline btn-lg" href="mailto:hello@opsxapi.dev?subject=OpsxAPI%20购买咨询">hello@opsxapi.dev</a>
</div>
</div>
</section>
<!-- ===================== Footer ===================== -->
<footer class="footer">
<div class="wrap footer-grid">
<div>
<div class="brand"><span class="brand-logo"><svg width="30" height="30" viewBox="0 0 64 64" aria-label="OpsxAPI"><defs><linearGradient id="lg-site" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2563EB"/><stop offset="1" stop-color="#06B6D4"/></linearGradient></defs><rect width="64" height="64" rx="14" fill="url(#lg-site)"/><g stroke="#fff" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" fill="none"><path d="M17 25h26"/><path d="M37 19l6 6-6 6"/><path d="M47 39H21"/><path d="M27 33l-6 6 6 6"/></g></svg></span><span class="brand-name">OpsxAPI</span></div>
<p class="footer-desc">本地优先的全协议接口工作台。<br>数据在自己手里,才是真的效率工具。</p>
</div>
<div>
<h4>产品</h4>
<a href="#features">功能特性</a>
<a href="#pricing">定价与让利</a>
<a href="#compare">工具对比</a>
</div>
<div>
<h4>资源</h4>
<a href="/docs" target="_blank" rel="noopener">用户文档</a>
<a href="/docs/server-api" target="_blank" rel="noopener">服务端 API</a>
<a href="/docs/faq" target="_blank" rel="noopener">常见问题</a>
</div>
<div>
<h4>支持</h4>
<a href="mailto:hello@opsxapi.dev">hello@opsxapi.dev</a>
<a href="/docs/quickstart" target="_blank" rel="noopener">快速开始</a>
</div>
</div>
<div class="footer-bar">© 2026 OpsxAPI · <a href="/terms" target="_blank">服务条款</a> · 本页由单二进制内置提供(/home)</div>
</footer>
</body>
</html>
+77
View File
@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>服务条款 · OpsxAPI</title>
<meta name="description" content="OpsxAPI 服务条款:使用规范、频率限制与禁止滥用条款" />
<link rel="icon" type="image/svg+xml" href="/site/assets/favicon.svg" />
<link rel="stylesheet" href="/site/assets/site.css" />
<style>
.terms-wrap { max-width: 820px; margin: 0 auto; padding: 48px 24px 80px; }
.terms-wrap h1 { font-size: 30px; margin-bottom: 8px; }
.terms-meta { color: var(--muted, #6b7280); font-size: 13px; margin-bottom: 32px; }
.terms-wrap h2 { font-size: 18px; margin: 32px 0 12px; }
.terms-wrap p, .terms-wrap li { line-height: 1.9; font-size: 14px; color: var(--text, #374151); }
.terms-wrap ul { padding-left: 20px; }
.terms-box { border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px 20px; margin: 12px 0; background: #f9fafb; }
.terms-box strong { color: #111827; }
table.limits { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; }
table.limits th, table.limits td { border: 1px solid #e5e7eb; padding: 8px 12px; text-align: left; }
table.limits th { background: #f9fafb; }
.back-home { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 24px; color: #2563eb; text-decoration: none; font-size: 14px; }
</style>
</head>
<body>
<main class="terms-wrap">
<a class="back-home" href="/home">← 返回官网</a>
<h1>服务条款</h1>
<div class="terms-meta">最近更新:2026 年 9 月 17 日 · 生效范围:OpsxAPI 本地服务(含官网 /docs、/home、/mock 及 /api)</div>
<h2>一、服务说明</h2>
<p>OpsxAPI 是运行在你本机的接口调试与 Mock 服务。官网(/home)、文档(/docs)、账号与云端空间(/api)及本地 Mock 服务(/mock)默认仅监听 127.0.0.1,供个人与团队内部开发联调使用。</p>
<h2>二、账号与安全</h2>
<ul>
<li>注册需提供有效邮箱,密码经加盐哈希后存储;请妥善保管凭据,退出登录即作废令牌。</li>
<li>团队成员凭邮箱邀请加入,共享空间内数据对全体成员可见;仅团队创建者可管理成员。</li>
<li>冒用他人身份注册、批量恶意注册账号的行为将被禁止。</li>
</ul>
<h2>三、频率限制</h2>
<p>为保障本地服务稳定,Mock 接口(/mock)实施以下默认限流,超限返回 <strong>HTTP 429</strong> 与 <code>Retry-After</code>:</p>
<table class="limits">
<tr><th>类别</th><th>阈值</th><th>超出行为</th></tr>
<tr><td>通用 API 请求频率</td><td>60 QPM(每分钟 60 次)或 20 QPS(每秒 20 次)</td><td>返回 429 错误</td></tr>
<tr><td>单空间 Mock 接口数</td><td>200 个</td><td>发布请求被拒绝(400)</td></tr>
<tr><td>云端空间数据体积</td><td>20 MB</td><td>保存请求被拒绝(413)</td></tr>
</table>
<h2>四、禁止滥用</h2>
<div class="terms-box">
<p><strong>若账户或使用行为存在「未经授权或滥用」情形,平台有权采取限流、暂停服务等措施。</strong>通过技术手段规避限流(如频繁更换来源地址、伪造标识等)本身即属于违规行为。</p>
</div>
<ul>
<li>不得将本地 Mock 服务长期暴露到公网对外提供流量服务,或用于任何压测 / 攻击 / 爬虫目标;</li>
<li>不得利用服务存储违法违规内容,或侵害第三方(含任何第三方接口、服务)权益;</li>
<li>不得逆向、干扰、破坏服务及其组件,或绕过任何使用限制与安全措施;</li>
<li>对违反上述条款的行为,我们有权不经通知采取限流、下线 Mock 接口、停用账号等措施。</li>
</ul>
<h2>五、数据与隐私</h2>
<ul>
<li>所有数据(账号、团队空间、Mock 接口)默认存储于本机 SQLite(data/opsxapi.db),不经任何第三方中转、不上传外部服务器;</li>
<li>AI 功能直连你自己配置的模型供应商,密钥仅存本机;</li>
<li>请自行做好数据备份(客户端支持全量备份导出);对未备份的数据丢失不承担责任。</li>
</ul>
<h2>六、免责声明</h2>
<p>本软件按「现状」提供,不承诺适销性或特定用途适用性。因不可抗力、系统维护或依本条款采取措施导致的服务中断,不视为违约。在法律允许范围内,对间接损失不承担赔偿责任。</p>
<h2>七、条款变更</h2>
<p>我们可能随版本更新修订本条款,修订后在官网公示并更新日期;继续使用即视为接受修订后的条款。</p>
<p class="terms-meta" style="margin-top:40px">如有疑问,请通过官网页脚的联系方式反馈。</p>
</main>
</body>
</html>