跳转至

Orca UI 样式指南

这是 Orca 的 UI/视觉设计 文档 —— 涵盖颜色令牌、排版、组件选型与 UX 规则。它 不是 架构文档;系统级设计请参阅代码与行内注释。令牌值以 src/renderer/src/assets/main.css 为权威来源;本文件记录的是使用它们的 角色与规则。

概述

Orca 是一款 Electron 桌面应用,用于跨 git worktree 编排编码代理(coding agents)。其视觉身份是 单色而安静 —— 中性灰承载界面框架,颜色只留给状态(选中环、破坏性操作、git 装饰)。产品大部分时间都在承载他人的工具(Monaco、xterm、Markdown 预览),因此 Orca 自身的 UI 应当退居幕后,起到衬托与框定作用。

拿不准时:

  • 优先使用 muted/accent/border,而不是直接上颜色。
  • 优先使用 CSS 变量,而不是硬编码 hex 值。
  • 优先匹配最接近的 shadcn 基础组件(primitive),而不是手写自定义 CSS。

权威来源

事项 权威位置
颜色令牌 src/renderer/src/assets/main.css(:root、.dark)
Tailwind 主题绑定 同一文件,@theme inline { … } 块
基础组件(primitives) src/renderer/src/components/ui/(shadcn 风格)
应用排版 / 滚动条 / 标题栏框架 同一个 main.css

如果已有变量覆盖了某个场景,绝不要在组件代码中硬编码 hex 值。若确实需要新令牌,先将其添加到 main.css(:root 与 .dark 都要加),在 @theme inline 块中暴露出来,然后再使用。

颜色角色

令牌成对出现:一个 surface(表面色)搭配一个能与它形成足够对比度的 foreground(前景色)。务必成对使用。

角色 用途 不要用于
background / foreground 应用画布、默认文本 卡片、弹出层、侧边栏(它们有自己的令牌)
card / card-foreground 从画布上浮起的面板 画布本身
popover / popover-foreground 浮动菜单、下拉框、悬停卡片 内联 UI
primary / primary-foreground 流程中唯一的肯定性操作(保存、确认) 装饰性强调;悬停状态;次要操作
secondary / secondary-foreground 主操作旁边的低强调操作 肯定性操作本身
muted / muted-foreground 弱化文本、说明文字、占位符、禁用状态的界面框架 正文;主要操作
accent / accent-foreground 幽灵按钮和列表行的悬停/激活背景 实心填充按钮(请改用 secondary)
destructive / destructive-foreground 删除、放弃、不可逆操作按钮;错误状态 取消按钮(取消并非破坏性操作)
border 所有细线:分隔线、输入框轮廓、卡片边缘 重度强调;那是 ring 的职责
input 仅限表单字段背景 表单字段之外的任何地方
ring 焦点可见轮廓、激活选中光晕 持续性装饰
sidebar(及变体) worktree 侧边栏及其子元素 其他面板
editor-surface Monaco / Markdown 编辑器面板的背景 应用界面框架

sidebar 家族会展开为 --sidebar、--sidebar-foreground、--sidebar-primary、--sidebar-primary-foreground、--sidebar-accent、--sidebar-accent-foreground、--sidebar-border 和 --sidebar-ring —— 请在 worktree 侧边栏内部使用它们,使其悬停/选中/聚焦状态保持一致,且不会扩散到其他面板。editor-surface 是一个独立令牌(而不只是 background),因为 Monaco 和 Markdown 编辑器在深色模式下表面色略深,以贴合 VS Code 的惯例;只要渲染编辑器面板,就应该使用它。

Git 装饰颜色

对于 diff 状态、文件树装饰和更改视图,请使用 git 装饰令牌(与 VS Code 的调色板保持一致,这样从 VS Code 迁移过来的用户不会感到意外):

令牌 状态
--git-decoration-added 已添加 / 新增
--git-decoration-modified 已修改
--git-decoration-deleted 已删除
--git-decoration-renamed 已重命名
--git-decoration-untracked 未跟踪
--git-decoration-copied 已复制
--git-decoration-ignored 被 git 忽略

这些令牌 只能 用于 git 状态。不要将它们复用于无关的状态颜色 —— 那会破坏约定。

列表行:悬停、选中、当前

这是常见的偏离点。对于任何列表式行(worktree、命令面板条目、设置导航),请遵循以下约定:

  • 空闲(Idle): 透明背景。
  • 悬停(Hover): 使用 bg-accent(在 worktree 侧边栏中为 bg-sidebar-accent)。
  • 键盘选中(cmdk 高亮): 在浅色 popover/dialog 表面,不要仅靠纯色的 bg-accent —— --accent(#f5f5f5)与 --background(#fff)几乎相同,选中光标会因此消失。请使用 main.css 中的跳转面板(jump palette)配方(.jump-palette-item[data-selected='true']):用 color-mix 将前景色以约 12% 的比例混入背景色,再加上内嵌 ring。当嵌套的镂空元素(如状态小圆点)需要匹配时,请将该混合结果暴露为 --jump-palette-selection-surface。data-selected 属性由 cmdk 自动设置。
  • 持久性的"当前"/"激活"行(例如用户正在查看的 worktree):同样使用 bg-accent,并且 加上 data-current="true" 属性,以便 CSS 或未来的样式能将其与 cmdk 高亮区分开。
  • 不要: 硬编码 bg-[#ededed] / bg-[#333333],也不要自创一种"选中"颜色。请从现有令牌(foreground/background/accent)混合而来,以保证浅色/深色模式保持一致。

颜色混合

当你需要一种色调(例如 hover 时 12% 的主色覆盖层),请使用 color-mix 基于现有 token 进行混合,而不是新写一个 hex 值:

background: color-mix(in srgb, var(--primary) 12%, var(--background));

这样能自动保持明暗模式的一致性。

字体排印

  • 字体家族: Geist 以单个可变 woff2 文件加载(字重范围 100–900)。无衬线字体始终使用 Geist,不要使用 Inter 或系统无衬线字体。
  • 等宽字体: var(--font-mono) —— 用于路径、终端相关界面、代码,以及任何等宽字体能传达“这是字面内容”的场景。
  • 正文字距: 0.01em(在 body 上全局设置)。不要在每个组件里覆盖。
  • 字号: 使用 Tailwind 默认字号体系。本仓库常用字号:
  • 11px(大写元信息、侧边栏标题、说明文字)—— 搭配 font-weight: 600、text-transform: uppercase 和 letter-spacing: 0.05em,用于分类标签。
  • 12px(次要文本、路径、辅助内容)
  • 13px(侧边栏条目、紧凑列表行)
  • 14px(默认正文,default 尺寸按钮文本)

圆角

--radius: 0.625rem(10px)是基础值;其余圆角由它计算得出(--radius-sm = 0.6×、--radius-md = 0.8×、--radius-lg = 1×、--radius-xl = 1.4×,等等)。按钮和输入框使用 rounded-md;Card 原语使用 rounded-xl;徽章使用 rounded-full。尽量匹配现有原语的圆角,而不是引入新的圆角值。

层级与阴影

Orca 很少使用阴影。实际使用中分三个层级:

  1. 内嵌发丝线 —— border + border token。默认层级。几乎一切都处在这一层。
  2. 轻微浮起 —— shadow-xs + 单 token 边框。用于描边按钮、嵌入式卡片。
  3. 浮动 —— shadow-floating(0 10px 24px rgba(0, 0, 0, 0.18))。用于弹出框、脱离编辑器表面的弹窗。需谨慎使用。

不要再添加第四层。如果某个元素需要的强调程度超过“浮动”,那很可能应该改用焦点 ring。

组件

在编写任何自定义组件之前,请优先使用 src/renderer/src/components/ui/ 中的 shadcn 原语。该目录下的 shadcn 风格包装器遵循一致的模式:

  • 大多数包装器在根元素上带有 data-slot="<name>" 属性,供 CSS 选择器定位——不要移除它。(此目录中的非 shadcn 辅助组件——sonner 和 repo-multi-combobox——不遵循此模式,在添加需要遵循该模式的新原语时,不应模仿它们。)
  • 使用 cn() 进行类名合并。将用户传入的 className 放在最后,以便调用方覆盖。
  • 当存在多个变体时,使用 class-variance-authority(CVA)管理变体。

按钮 (button.tsx)

按优先级排序的变体:

变体 使用场景
default 流程中唯一的确认性操作。
secondary 与 default 相邻、强调程度较低的兄弟按钮。
outline 工具栏 / 独立操作,实心按钮显得太重时使用。
ghost 图标按钮、列表行触发器,以及任何需要让界面框架隐藏起来的场景。
link 段落内的行内文本操作。
destructive 删除、丢弃、不可逆操作。绝不能用于“取消”。

尺寸:default(36px)、sm(32px)、xs(24px)、lg(40px),另有 icon、icon-xs、icon-sm、icon-lg。尺寸要与所在行高匹配——不要把 default 按钮放进 28px 的工具栏里。

本仓库中的其他原语

完整列表请浏览 src/renderer/src/components/ui/。大多数包装了 Radix UI 原语——例外是 command(包装 cmdk)、sonner(包装 sonner),以及仅负责视觉的包装器(badge、button-group、card、input),它们直接应用 token 和 Tailwind 工具类。永远不要重新实现 headless 行为;应在现有包装器的基础上扩展。

选择合适的原语

当一个控件存在多个看似可用的原语时,请参考以下分支:

你的需求… 使用 不要使用
图标按钮的悬停提示标签 Tooltip HoverCard(过重)、title 属性
悬停预览更丰富的内容(头像 + 摘要) HoverCard Tooltip(不支持丰富内容)
点击展开的带操作菜单 DropdownMenu 用手写列表的 Popover
右键上下文操作 ContextMenu DropdownMenu(触发方式不同)
点击展开的任意内容面板(表单、选择器) Popover Dialog(会锁定焦点并使背景变暗)
需要先做出决定才能继续的模态框 Dialog Popover、内联覆盖层
从屏幕边缘滑入的抽屉 / 面板 Sheet 居中显示的 Dialog
从已知列表中选择单个选项 Select 自定义 listbox
带搜索 / 模糊过滤的单项选择 Popover 内的 Command Select(不支持搜索)
带搜索的多选 repo-multi-combobox(模仿其模式) 新写一个
转瞬即逝的确认提示(“已保存”“已复制”) sonner toast Dialog、内联横幅
持续存在的内联状态(“3 个错误”) 内联文本 + Badge toast(toast 会消失)
当你想要…… 选用 不要使用

如果你发现自己在用样式绕过某个基础组件(例如让 <Popover> 表现得像 <Dialog>,或反过来),请停下来重新考虑——焦点管理语义不同,未来的贡献者会被这种不一致误导。

工具提示

工具提示用于_命名_一个仅凭外观无法明确其含义的控件。它们不是用来教学、说服或警告的地方——用户在操作过程中需要阅读的内容应放在可见 UI 中。

  • 使用工具提示的情况: 仅图标按钮或紧凑标签需要文本标签时。工具栏图标、带缩写的徽章、被截断的路径。
  • 不要使用工具提示的情况: 控件已有可见标签、内容可交互(链接、按钮),或消息很关键(错误、阻断性警告——这些应内联显示)。
  • 挂载: 全局 <TooltipProvider delayDuration={400}> 位于 App 根节点。除非需要为范围较窄的界面使用不同的延迟,否则不要嵌套第二个 TooltipProvider。
  • 触发器模式: 使用 <TooltipTrigger asChild> 包裹触发元素,使工具提示的无障碍属性附加到按钮上(而不是包裹用的 span)。这是键盘焦点能够显示工具提示的必要条件。
  • 位置: 默认 side="top" sideOffset={4}——与 sidebar/SidebarToolbar.tsx 中的工具栏模式保持一致。只有当默认位置会被视口裁剪时,才选择其他方向。
  • 工具提示中的快捷键标签: 如果操作有键盘快捷键,请追加 <ShortcutKeyCombo />,而不是把按键硬编码到标签字符串中。这些标签会按平台正确渲染;硬编码字符串容易漂移。
<Tooltip>
  <TooltipTrigger asChild>
    <Button variant="ghost" size="icon-sm" onClick={openSettings}>
      <Settings />
    </Button>
  </TooltipTrigger>
  <TooltipContent side="top" sideOffset={4}>
    Settings
  </TooltipContent>
</Tooltip>

图标

图标来自 lucide-react。不要引入第二个图标库。

  • 默认尺寸: size-4(16px)。Button 会通过 [&_svg:not([class*='size-'])]:size-4 自动为其包含的任何 <svg> 应用该尺寸,因此大多数调用点无需为图标设置尺寸。
  • size-3 / size-3.5: 用于元数据、说明文字以及 16px 过于醒目的密集列表行。
  • size-7+: 仅用于特色/空状态的主图标。
  • 描边宽度: lucide 默认 2px。不要按图标覆盖。
  • 颜色: 继承自周围文本——次要内容用 text-muted-foreground,破坏性操作用 text-destructive,等等。当父元素已经带有正确颜色时,不要直接对 SVG 应用颜色 token。
  • 加载指示器: 规范的加载图标是 <Loader2 className="size-4 animate-spin" />。对于 3 秒以上的多步骤任务,优先使用标明阶段的标签(“克隆中…” → “安装中…”),而不是无标签的加载指示器。参见 UX 规则 1。

键盘快捷键标签

使用来自 src/renderer/src/components/ShortcutKeyCombo.tsx 的 <ShortcutKeyCombo />。它会渲染一致的按键帽样式,并在 Windows/Linux 上插入 + 分隔符(Mac 显示相邻符号,无分隔符)。它不转换按键字符串——由_调用方_选择适合平台的标签并传入:

const isMac = navigator.userAgent.includes('Mac')
const mod = isMac ? '⌘' : 'Ctrl'
const shift = isMac ? '⇧' : 'Shift'
<ShortcutKeyCombo keys={[mod, shift, 'N']} />

参见 Landing.tsx 中的规范模式。不要临时写一个 <kbd>——如果每个人都自行样式化,kbd 标签的形状和颜色会很快在整个应用中漂移。

快捷键在 UI 中呈现的位置:

  • 图标按钮上的工具提示——在标签末尾追加该标签。
  • 下拉菜单 / 上下文菜单项——使用 <DropdownMenuShortcut>(或其上下文菜单等价组件)作为右对齐的标签;不要自行定位。
  • 绝不要用于取消、关闭或 link 变体的内联操作——参见 UX 规则 3。

标签必须与平台上的实际绑定一致。 如果键盘处理器在 Mac 上读取 metaKey,在其他平台读取 ctrlKey,则标签必须在 Mac 上显示 ⌘,在其他平台显示 Ctrl。不一致的标签比没有标签更糟。

表单结构

src/renderer/src/components/settings/SettingsFormControls.tsx 中的模式是任何“标签 + 控件 + 辅助文本”的规范样式。新表单应与其保持一致:

  • 外层堆叠: 完整分区表单(ThemePicker)使用 space-y-3;紧凑的单控件字段(ColorField、NumberField)使用 space-y-2。根据密度选择,而不是凭偏好。
  • 标签组: 使用 space-y-1,包含 <Label> 和一段 text-xs text-muted-foreground 的说明文字。
  • 控件: shadcn 基础组件(<Input>、<Select> 等)。错误通过 aria-invalid 呈现;输入基础组件已将其映射为破坏性边框——不要自行绘制。
  • 后置元数据: 在控件下方使用 text-[11px] text-muted-foreground(例如“当前:14px · 默认:13px”),而不是放在标签旁边。

滚动条

main.css 中全局定义了三个滚动条类:

  • .scrollbar-sleek——侧边栏、列表、弹出层默认使用的细窄中性滚动条。如果希望滑块仅在父元素悬停时淡入,请在悬停目标祖先元素上搭配 .scrollbar-sleek-parent。
  • .scrollbar-editor——稍重一些,用于 Monaco 相邻界面内部。
  • .worktree-sidebar-scrollbar——不预留滚动槽:与 overflow-y-auto 搭配时,滚动条(及其宽度)仅在内容实际溢出时存在,因此短列表会与固定头部控件齐平,经典滚动条的 Windows 在空列表上不会显示箭头按钮。滑块保持不可见,直到父元素(.scrollbar-sleek-parent)被悬停。仅用于 worktree 侧边栏。

将其中一种应用于溢出容器;不要编写第四种样式。

UX 规则

这些是贡献者在独立工作时最容易出错的规则。它们适用于所有 UI 更改。

UI 文案不得过度声称。 除非代码拥有真实的状态或结果数据作为支撑,否则不要暗示应用已经执行了某个操作、做出了某个决定,或观察到了某个事实。在工作待处理时,使用中性的过程性语言;将“已跳过”“已保护”“已找到”“已验证”或“已删除”等结果动词保留给实际结果。

屏幕 UX 评审标准

在评审任何 Orca IDE 屏幕、截图或原型时,使用本标准。一次好的评审应先指出影响最大的摩擦点,然后给出实现者可以执行的具体更改。

评审输出格式

  1. 首要修复: 最能改善该屏幕的 3 项更改。
  2. 摩擦点说明: 具体的杂乱、对齐、文案、焦点或流程问题,并指明受影响的 UI 元素。
  3. 建议更改: 对布局、层级、控件、文案、空/错误状态和展开/收起方式的具体更改。
  4. 键盘与速度检查: 在适当情况下,主要工作流能否在 1-2 个操作内完成,并具有良好的默认焦点以及 Enter/Esc 行为。
  5. 后续链接或状态: 用户需要恢复时缺失的外部链接、获取或配置操作,或持久错误。

评审要点

  • 渐进式披露: 保持高频操作可见且突出。将低频操作移出常见指针路径,放入菜单、溢出控件、详情抽屉或高级部分。不要让菜单长到用户必须扫描无关操作;当菜单增长时,应分组或拆分。
  • 操作层级: 主要操作必须通过位置、大小和 default 按钮样式变得明显。将高频操作放在菜单顶部以及最易触及的工具栏位置。次要操作和罕见操作不应与主要操作竞争。
  • 点击次数: 移除不必要的中间步骤。当应用已有足够信息可以继续时,常见工作流应在 1-2 个操作内完成。
  • 默认焦点: 对话框、弹出层和命令界面应聚焦到用户最可能使用的字段或主要操作。如果 Enter 提交,焦点必须落在 Enter 会触发预期主要操作的位置。Esc 应能退出,且不要给“取消/关闭”增加视觉噪音。
  • 键盘导航: 对于较长的选项列表,优先使用可搜索的命令界面。当用户需要从列表中找到仓库、分支、工作树、代理、命令、设置、文件或提供商时,添加搜索字段。
  • 快捷键标签: 仅为实际已实现且在该位置有用的快捷键显示快捷键芯片。标签必须与平台绑定匹配。如果快捷键策略尚未确定,不要在产品 UI 中暴露占位标签。
  • 对齐: 行和列必须对齐到可见网格。为便于扫描,文本和标签左对齐;当比较重要时,数字、计数、快捷键和尾部元数据右对齐;仅紧凑图标控件、空状态以及对称性最清晰的表格单元格居中对齐。
  • 文案质量: 显示文本必须无错别字、简洁且具体。优先使用直接动词和具体名词。移除“请”“只需”“仅仅”“你可以”等填充词,以及没有状态支撑的泛化成功语言。
  • 对话框和覆盖层: 选择与输入量匹配的对话框大小。简短确认保持紧凑;包含多行文本、路径选择器、提供商设置或评审内容的表单需要更大的对话框或 sheet。浮动界面必须使用文档中规定的阴影/高程和背景处理,使其看起来位于页面之上。
  • 空状态和错误状态: 当数据缺失时,显示一个直接操作来获取或配置该数据。对临时失败或确认使用 toast 提示;当用户需要阅读、重试、复制或处理消息时,将错误持久显示在行内。
  • 外部链接: 当用户可能需要提供商文档、token 设置、计费/设置页面、Git 提供商资源或故障排查上下文时,添加直接链接。将链接放在相关空状态、错误、辅助文本或设置步骤附近,而不是埋在通用菜单中。
  • 可供性: 用户应能在没有侵入式教育的情况下发现可用功能。使用熟悉的图标、可见的悬停/焦点状态、必要时清晰的标签,以及仅图标控件的工具提示。优先使用附近已使用的简单 lucide 图标,而不是晦涩的替代项。
  • 布局密度: 避免将控件挤在一起。在主要工作流周围保留呼吸空间,减少相互竞争的按钮,并保持工具栏组在视觉上可区分。只有当分组、对齐和层级使扫描更快时,密集屏幕才可接受。
  • 卡片和容器: 卡片必须通过现有的 card/border 处理与其父表面在视觉上区分开。避免在卡片内嵌套卡片。如果某个部分不是重复项、模态框或带框工具,考虑使用无边框布局或全宽条带。
  • 并排布局: 对于复杂工作流,默认使用逐行布局,因为它们更容易对齐和扫描。仅在空间受限或比较是重点时使用并排布局,然后仔细打磨列宽、基线和换行状态。
  • 动画: 使用细微动画来柔化展开/折叠内容,并防止布局跳动。动画应阐明连续性,而不是装饰。尊重减少动态效果设置。
  • SSH 和延迟: 假设操作可能远程执行。立即禁用提交控件,在适当时延迟可见加载反馈,并在远程数据到达期间保持焦点稳定。

1. 将进行中反馈与感知时长匹配

正确的问题不是 “这个控件在工作时是否应该改变?” — 而是 “这个操作需要多长时间,以及在此期间用户需要知道什么?”

| 时长 | 反馈 |

持续时间 反馈
------------------ ---------------------------------------------
0–100 ms 无。任何可见内容都会显得像故障。
100 ms–1 s 仅禁用状态。
1 s–3 s 禁用 + 加载指示器或标签切换。
3 s+ 或多步骤 阶段标签、进度、可选的安抚提示。

两个推论:

  • 预先保留你稍后会占用的空间。 如果控件可能会切换到更长的标签或增加图标,请提前固定其占位尺寸(使用 width,而不是 min-width)。一个在操作中途改变尺寸的控件,即使操作成功,也会显得损坏。
  • 不要为所有人选择最坏情况的反馈。 如果操作在本地很快、在远程很慢(SSH),请将可见加载状态延迟约 200ms。本地用户看不到任何内容;远程用户获得适当的反馈。立即绑定 禁用 状态(这样双击不会重复提交),并在计时器上绑定 可见 状态。

2. 在孤立设计之前先寻找同级组件

如果你的组件有一个同级组件——同一领域、行为重叠、且常常在同一流程的相邻时刻可见——两者应读起来像一个设计。相同的图标、相同的快捷键约定、相同的提交语义。用户在它们之间移动时不应感知到接缝。

这 并非 “匹配所有现有模式。” 一些仓库模式是技术债务,复制它们会扩散债务。更精确的说法是关于 相邻 组件。与同级组件偏离需要理由:要么同级组件是错的(两者都修复),要么新组件在角色上有真实差异(坚持它)。

当没有同级组件时,匹配周围的界面元素——按钮尺寸、图标粗细、文案语气——并且不要从一个用户永远不会与此关联的屏幕中制造一个同级组件。

3. 不要过度加重退出路径

destructive 用于会丢失数据或无法撤销的操作。Cancel、Dismiss、Close 和 Discard 不是破坏性操作 — 它们让用户退出进行中的操作,应保持低调(默认幽灵按钮,无颜色,无键盘提示标签,无动画提示)。把视觉权重留给肯定操作,使两者不竞争。键盘处理器仍可以响应 Esc;保持最小化的是可见装饰。

跨平台

Orca 运行在 macOS、Linux 和 Windows 上。每个 UI 更改都必须在这三个平台上可靠,并且在浅色和深色模式下都可靠。

  • 修饰键: 永远不要硬编码 e.metaKey。使用 navigator.userAgent.includes('Mac') 在 Mac 上选择 metaKey,在 Linux/Windows 上选择 ctrlKey。Electron 菜单加速器应使用 CmdOrCtrl。
  • 快捷键标签: 在 Mac 上显示 ⌘ / ⇧;在其他平台上显示 Ctrl+ / Shift+。标签必须反映该平台的实际绑定。
  • 窗口装饰: macOS 显示交通灯;标题栏保留 80px 的边距(titlebar-traffic-light-pad),以免它们与内容重叠。在 Mac 上不要在该区域放置可点击目标。
  • SSH: 许多用户在远程机器上运行 Orca。加载状态、焦点管理和动画必须在额外 50–200 ms 延迟下保持可靠。在模拟延迟(或实际 SSH)下测试——仅本地验证是不够的。参见 UX 规则 → 1。

当本指南未说明时

如果你有一个本文件未回答的 UI 问题:

  1. 查看 src/renderer/src/components/ 中相邻代码,找到最接近的同级组件,并遵循它的做法。
  2. 检查 src/renderer/src/components/ui/ 中是否已有编码该模式的原语。
  3. 如果是 token 问题,main.css 是权威来源——使用其中已有的,或在浅色和深色中都添加一个新的。
  4. 如果以上都无法解决,先询问用户,不要自行发明。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 orca48/orca