/* ========================================================================== API 文档版式(docs/content/api/**) -------------------------------------------------------------------------- 三处视觉缺口,对应下面三段: 1. 端点标题 `## `POST` `/data/page`` 与 `## 基础约定` 长得一样 → 方法徽章 2. 参数表是裸 markdown 表格(必填列原来是 emoji)→ G3ApiParams 面板 3. 请求体 / 响应体是两块一模一样的灰底 JSON → G3ApiPayload 面板(按 code 着色) 两条自我约束: - 只用 --vp-c-* 变量,不引第三方样式表。站点其余部分是逐像素对齐 Docus 的 (见 custom.css),API 页必须留在同一套设计语言里。 - 一律逻辑属性(inline-* / block-*),站内已有 RTL 支持(见 content/ui/usage/rtl)。 ========================================================================== */ /* ========================================================================== 1. 端点标题 -------------------------------------------------------------------------- 写法:## `POST` `/data/page` 用 :has(> code:first-child) 把端点标题与普通 H2 区分开 —— 这既是样式的需要, 也是「为什么不用组件渲染标题」的答案:标题一旦交给 Vue 组件渲染,就不再进 markdown 的 heading token 流,右侧目录(G3DocAside)会丢掉全部条目、锚点 一并消失。所以标题仍是 markdown H2,只在 CSS 上做文章。 代价:方法徽章的颜色没法按 GET/POST 区分(CSS 不能按文本匹配)。当前 /api/** 下全部是 POST,所以是准确的;将来出现混合方法时,在 config.mts 的 markdown.config 里加一个「把首词换成 」的 小插件即可,slug 由文本 token 决定,不受影响。 作用域:三张 API 页都带 frontmatter `pageClass: g3-api`(VitePress 把该 class 落到根
上,见主题 Layout.vue:34),下面全部规则都由 .g3-api 兜住,不会漏到组件页去。 ========================================================================== */ .g3-api .vp-doc h2:has(> code:first-child) { /* 覆盖 VitePress 的 .vp-doc h2(上边框 + padding-top):端点标题改为 「下方一条分隔线」,与紧随其后的参数面板构成一组,读起来是一个接口一节。 */ margin-block: 56px 20px; padding-block: 0 14px; border-block-start: 0; border-block-end: 1px solid var(--vp-c-divider); font-size: 20px; line-height: 28px; } /* 方法徽章:第一个 code */ .g3-api .vp-doc h2:has(> code:first-child) > code:first-child { padding: 2px 8px; border-radius: 6px; background-color: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); font-family: var(--vp-font-family-mono); font-size: 12px; font-weight: 700; line-height: 18px; letter-spacing: 0.06em; } /* 路径:第二个 code(nth-of-type 只数 code,不受中间的空格文本与 末尾 header-anchor 的 影响) */ .g3-api .vp-doc h2:has(> code:first-child) > code:nth-of-type(2) { padding: 0; background-color: transparent; color: var(--vp-c-text-1); font-family: var(--vp-font-family-mono); font-size: 18px; font-weight: 600; letter-spacing: -0.01em; } /* ========================================================================== 2 & 3. 面板(G3ApiParams / G3ApiPayload) -------------------------------------------------------------------------- 结构:标题栏 + 内容两段式。三个语气走同一组自定义变量,默认中性、 ok / warn / error 分别取 success / warning / danger。 ⚠ 语气语义是 **body.code**,不是 HTTP 状态码 —— 这正是通用 OpenAPI 渲染器做不到的地方(它们的颜色模型绑死 HTTP 状态码,会把这里的 失败响应渲染成绿色成功块)。 ========================================================================== */ .g3-api-panel { --g3-api-accent: var(--vp-c-text-3); --g3-api-accent-soft: var(--vp-c-bg-alt); margin: 16px 0; border: 1px solid var(--vp-c-divider); border-radius: 8px; /* 圆角要裁掉子元素底色(标题栏、代码块),但横向滚动不能裁 —— 滚动交给 __body,见下。 */ overflow: hidden; } .g3-api-panel--ok { --g3-api-accent: var(--vp-c-success-1, var(--vp-c-green-1)); --g3-api-accent-soft: var(--vp-c-success-soft, var(--vp-c-green-soft)); } .g3-api-panel--warn { --g3-api-accent: var(--vp-c-warning-1, var(--vp-c-yellow-1)); --g3-api-accent-soft: var(--vp-c-warning-soft, var(--vp-c-yellow-soft)); } .g3-api-panel--error { --g3-api-accent: var(--vp-c-danger-1, var(--vp-c-red-1)); --g3-api-accent-soft: var(--vp-c-danger-soft, var(--vp-c-red-soft)); } .g3-api-panel__head { display: flex; align-items: center; gap: 8px; padding: 8px 14px; background-color: var(--vp-c-bg-soft); border-block-end: 1px solid var(--vp-c-divider); color: var(--vp-c-text-2); font-size: 12px; font-weight: 600; line-height: 20px; } /* 语气点:与语气同色。文字标签(成功/失败)与它并存, 不让颜色成为唯一的区分手段。 */ .g3-api-panel__dot { flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background-color: var(--g3-api-accent); } .g3-api-panel--ok .g3-api-panel__head, .g3-api-panel--warn .g3-api-panel__head, .g3-api-panel--error .g3-api-panel__head { color: var(--g3-api-accent); } .g3-api-panel__tone { font-weight: 500; opacity: 0.9; } /* code 徽章:仅 G3ApiPayload 传了 code 时出现 */ .g3-api-panel__code { padding: 1px 7px; border-radius: 9999px; background-color: var(--g3-api-accent-soft); color: inherit; font-family: var(--vp-font-family-mono); font-size: 11px; font-weight: 600; } .g3-api-panel__body { /* 宽表横向滚动由这一层承担:VitePress 给 .vp-doc table 设了 display:block + overflow-x:auto,那会让 table 自己成为滚动容器 (custom.css 里已记录过它导致 sticky 表头失效的问题)。 */ overflow-x: auto; } /* --- 参数表:去掉 .vp-doc 给 markdown 表格画的四边框与上下留白 ------ */ .g3-api-panel__body table { display: table; width: 100%; margin: 0; } .g3-api-panel__body table th, .g3-api-panel__body table td { border: 0; border-block-end: 1px solid var(--vp-c-divider); padding: 8px 14px; background-color: transparent; } .g3-api-panel__body table tr:nth-child(2n) { background-color: transparent; } .g3-api-panel__body table tr:last-child td { border-block-end: 0; } .g3-api-panel__body table th { color: var(--vp-c-text-3); font-size: 12px; font-weight: 600; text-align: start; white-space: nowrap; } /* 列序约定:参数 / 类型 / 必填 / 说明。这两条按位置定样式,所以要两重限定: 1) variant="params" —— 参数表才有这个形状。bare 的表(错误码:code / 含义 / 典型原因 / 定位)若套上,散文列会被当成「类型」套等宽、被当成「必填」染成品牌色。 2) :has(td:nth-child(4)) —— 同一个 params 变体下,「字段 / 说明」两列表(如 /data/page 的 data 字段)第 2 列是散文,也不该套等宽小字。 第 1 列两种表都是标识符(参数名 / 字段名 / code),所以不加限定。 */ .g3-api-panel__body table td:first-child { color: var(--vp-c-text-1); font-family: var(--vp-font-family-mono); font-size: 13px; } .g3-api-panel--params .g3-api-panel__body:has(td:nth-child(4)) table td:nth-child(2) { color: var(--vp-c-text-3); font-family: var(--vp-font-family-mono); font-size: 12px; white-space: nowrap; } .g3-api-panel--params .g3-api-panel__body:has(td:nth-child(4)) table td:nth-child(3) { color: var(--vp-c-brand-1); font-weight: 500; white-space: nowrap; } /* --- 报文里的代码块:贴边(VitePress 默认 margin:20px 0 + 圆角 8px)- */ .g3-api-panel__body div[class*='language-'] { margin: 0; border-radius: 0; } /* ========================================================================== 4. 表格列宽:短中文列不被压扁 -------------------------------------------------------------------------- 现象:/api/getting-started 的「接口一览」里「板块」列被压成一列一个字 (「数据查询」折成两行)。 原因不是这列太长,而是**太短**:CJK 没有「词」的边界,可以逐字换行,于是 该列的 min-content 宽度只有 1 个字。table-layout: auto 按 min-content 分配 空间时,浏览器会把这列压到最小、把余量让给旁边的长路径与长文案 —— 越短的列 越容易被牺牲,与直觉相反。 nowrap 把该列的 min-content 抬到「整格文字的宽度」,即不可再压。 API 页各表的首列都是短键(板块 / 项 / code / 字段 / 参数名),nowrap 安全; 长文案列(说明、触发场景)不带这条规则,照常换行。 ========================================================================== */ .g3-api .vp-doc table th:first-child, .g3-api .vp-doc table td:first-child { white-space: nowrap; }