This commit is contained in:
oneao committed 2026-10-12 22:25:41 +08:00
1 parent ae3ca3cfa1
commit 7bd5f1dde9
45 files changed
+3414 -229

No files matched your search

@@ -0,0 +1,240 @@
/* ==========================================================================
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 里加一个「把首词换成 <span class="g3-api-method--get">」的
小插件即可,slug 由文本 token 决定,不受影响。
作用域:三张 API 页都带 frontmatter `pageClass: g3-api`(VitePress 把该 class
落到根 <div class="Layout"> 上,见主题 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 的 <a> 影响) */
.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;
}