# @lovince/ui-vue 中文文档

规范地址：https://npmcn.com/package/%40lovince/ui-vue/

版本：0\.5\.0
npm 元数据更新时间：2026-11-01T18:05:05.159Z
中文译文更新时间：2026-11-01T18:56:39.404Z
软件包许可：MIT

本文由上游 README 机器翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40lovince/ui-vue
原文对照：https://npmcn.com/package/%40lovince/ui-vue/?lang=original
项目主页：https://github.com/Mac254/Lovince_product_journey#readme
源码仓库：https://github.com/Mac254/Lovince_product_journey

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：739 kB，87 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18
- 运行依赖：2 个
- peer 依赖：vue ^3\.5\.0，@lovince/icons ^1\.3\.1
- 首次发布：2026-10-15T18:45:46.337Z
- 最新版本发布：2026-11-01T18:05:05.008Z
- 已发布版本数：11（近 12 个月 11 个）

## 中文简介

可访问的无头Vue 3组件为Lovince UI -披露，复选框，选项卡和对话框，无样式。

## 安装

```sh
npm install @lovince/ui-vue
```

也可以使用：`pnpm add @lovince/ui-vue`、`yarn add @lovince/ui-vue`、`bun add @lovince/ui-vue`

## README

# @lovince / ui-vue

可访问的，无样式的Vue 3组件为Lovince UI。每个组件都是 状态机来自 [`@lovince/ui-headless`](https://npmcn.com/package/%40lovince/ui-headless);它的浏览器 效果贯穿始终 [`@lovince/ui-dom`](https://npmcn.com/package/%40lovince/ui-dom)． 这个套餐订阅 机器，输入道具，并呈现什么 `connect()` 的回报。它不存在 它自己的行为。

> **状态: `0.5.0`、实验。** API之前可能会更改 `1.0`.

```bash
bun add @lovince/ui-vue
```

需要v3.5 +（用于ssr稳定） `useId`）. 包中没有CSS。风格 它与类和 `data-*` 状态属性，或使用 [`@lovince/themes`](https://npmcn.com/package/%40lovince/themes) 令牌。

每个组件导出都带有 `Lv` 前缀(`LvButton`， `LvDialogRoot`),所以 名称永远不会与您自己的组件或本地元素冲突。

## 组件

| 集团 | 组件 | 部分 |
| --- | --- | --- |
| 原语 | 文本，标题，标签，链接，代码，Kbd，框，对比度，视觉隐藏，分隔符 |  |
|  | 图标 | `LvIcon`，从分离 `@lovince/ui-vue/icon` 条目 |
| 信息披露 | 信息披露 | `LvDisclosureRoot`， `LvDisclosureTrigger`， `LvDisclosureContent` |
|  | 手风琴 | `LvAccordionRoot`， `LvAccordionItem`， `LvAccordionHeader`， `LvAccordionTrigger`， `LvAccordionContent` |
|  | 选项卡 | `LvTabsRoot`， `LvTabsList`， `LvTabsTrigger`， `LvTabsContent` |
| 覆盖 | 对话框 | `LvDialogRoot`， `LvDialogTrigger`， `LvDialogPortal`， `LvDialogOverlay`， `LvDialogContent`， `LvDialogTitle`， `LvDialogDescription`， `LvDialogClose` |
|  | Lightbox | `LvLightboxRoot`， `LvLightboxTrigger`， `LvLightboxPortal`， `LvLightboxOverlay`， `LvLightboxContent`， `LvLightboxTitle`， `LvLightboxItem`， `LvLightboxPrevious`， `LvLightboxNext`， `LvLightboxCounter`， `LvLightboxClose` |
|  | 弹出窗口 | `LvPopoverRoot`， `LvPopoverTrigger`， `LvPopoverAnchor`， `LvPopoverPortal`， `LvPopoverContent`， `LvPopoverClose` |
|  | 工具提示 | `LvTooltipRoot`， `LvTooltipTrigger`， `LvTooltipPortal`， `LvTooltipContent` |
|  | 悬停卡 | `LvHoverCardRoot`， `LvHoverCardTrigger`， `LvHoverCardPortal`， `LvHoverCardContent` |
|  | 菜单 | `LvDropdownMenuRoot`， `LvDropdownMenuTrigger`， `LvDropdownMenuContent`， `LvDropdownMenuItem`， `LvDropdownMenuCheckboxItem`， `LvDropdownMenuRadioGroup`， `LvDropdownMenuRadioItem`， `LvDropdownMenuItemIndicator`， `LvDropdownMenuLabel`， `LvDropdownMenuGroup`， `LvDropdownMenuSeparator`， `LvContextMenuTrigger` |
|  | 导航菜单 | `LvNavigationMenuRoot`， `LvNavigationMenuList`， `LvNavigationMenuItem`， `LvNavigationMenuTrigger`， `LvNavigationMenuContent`， `LvNavigationMenuLink` |
|  | 烤面包 | `LvToastViewport`， `LvToastRoot`， `LvToastTitle`， `LvToastDescription`， `LvToastAction`， `LvToastClose`,再加上 `toast()` |
| 选择 | 复选框,切换 | `LvCheckboxRoot`， `LvCheckboxIndicator`， `LvSwitchRoot`， `LvSwitchThumb` |
|  | 广播组 | `LvRadioGroupRoot`， `LvRadioGroupItem`， `LvRadioGroupIndicator` |
|  | 切换，切换组 | `LvToggleRoot`， `LvToggleGroupRoot`， `LvToggleGroupItem` |
|  | 选择 | `LvSelectRoot`， `LvSelectTrigger`， `LvSelectValue`， `LvSelectContent`， `LvSelectItem`， `LvSelectItemText`， `LvSelectItemIndicator`， `LvSelectGroup`， `LvSelectLabel`， `LvSelectSeparator` |
|  | 组合框 | `LvComboboxRoot`， `LvComboboxAnchor`， `LvComboboxInput`， `LvComboboxTrigger`， `LvComboboxClear`， `LvComboboxContent`， `LvComboboxItem`， `LvComboboxItemIndicator`， `LvComboboxEmpty` |
|  | 命令面板 | `LvCommandRoot`， `LvCommandInput`， `LvCommandList`， `LvCommandGroup`， `LvCommandItem`， `LvCommandEmpty`， `LvCommandSeparator` |
|  | Emoji选择器 | `LvEmojiPickerRoot`， `LvEmojiPickerSearch`， `LvEmojiPickerList`， `LvEmojiPickerGroup`， `LvEmojiPickerItem`， `LvEmojiPickerNav`… |
| 输入 | 滑块 | `LvSliderRoot`， `LvSliderTrack`， `LvSliderRange`， `LvSliderThumb` |
|  | 角滑块 | `LvAngleSliderRoot`， `LvAngleSliderTrack`， `LvAngleSliderMarkers`， `LvAngleSliderIndicator`， `LvAngleSliderThumb`， `LvAngleSliderValue` |
|  | 数域 | `LvNumberFieldRoot`， `LvNumberFieldInput`， `LvNumberFieldIncrement`， `LvNumberFieldDecrement` |
|  | 销的输入 | `LvPinInputRoot`， `LvPinInputInput` |
|  | 日历 | `LvCalendarRoot`， `LvCalendarHeading`， `LvCalendarPrev`， `LvCalendarNext`， `LvCalendarGrid`， `LvCalendarHeadCell`， `LvCalendarCell`， `LvCalendarDay` |
| 形式 | 字段，输入，文本区域，表单，TagsInput, FileUpload, TimeField, PhoneInput | `LvFieldRoot`， `LvFieldLabel`， `LvTagsInputRoot`， `LvTagsInputInput`， `LvTagsInputItem`， `LvTagsInputRemove`， `LvFileUploadRoot`， `LvFileUploadInput`， `LvFileUploadItem`， `LvFileUploadRemove`， `LvTimeFieldRoot`， `LvTimeFieldInput`， `LvPhoneInputRoot`， `LvPhoneInputInput`， `LvPhoneInputCountrySelect` |
|  | 时钟选择器 | `LvClockPickerRoot`， `LvClockPickerViewTrigger`， `LvClockPickerMeridiem`， `LvClockPickerDial`， `LvClockPickerHand` |
| 布局 | ScrollArea | `LvScrollAreaRoot`， `LvScrollAreaViewport`， `LvScrollAreaScrollbar`， `LvScrollAreaThumb` |
|  | 分配器 | `LvSplitterGroup`， `LvSplitterPanel`， `LvSplitterHandle` |
|  | 树 | `LvTreeRoot`， `LvTreeItem`， `LvTreeGroup` |
|  | 旋转木马 | `LvCarouselRoot`， `LvCarouselViewport`， `LvCarouselSlide`， `LvCarouselPrevious`， `LvCarouselNext`， `LvCarouselIndicators`， `LvCarouselIndicator` |
|  | 可分类的 | `LvSortableRoot`， `LvSortableItem`， `LvSortableHandle` |
|  | 部分 | `LvSectionRoot`， `LvSectionHeader`， `LvSectionEyebrow`， `LvSectionTitle`， `LvSectionDescription`， `LvSectionContent` |
| 显示 | 《阿凡达》,进步 | `LvAvatarRoot`， `LvAvatarImage`， `LvAvatarFallback`， `LvProgressRoot`， `LvProgressIndicator` |
|  | 计,倒计时 | `LvGauge`， `LvCountdownRoot`， `LvCountdownSegment` |
|  | 表格 | `LvTableContainer`， `LvTableRoot`， `LvTableCaption`， `LvTableHeader`， `LvTableBody`， `LvTableFooter`， `LvTableRow`， `LvTableHead`， `LvTableCell`,再加上 `LvDataTable` |

### 原语

这些原语提供了语义HTML和稳定的样式挂钩，而不会强加于人 CSS。 `LvText` 和 `LvHeading` 公开 `data-text-role` 匹配排版 角色 `@lovince/tokens`;标题级别控制语义独立于 视觉的大小。

```vue
<script setup lang="ts">
import { LvAspectRatio, LvCode, LvHeading, LvKbd, LvLabel, LvLink, LvSeparator, LvText, LvVisuallyHidden } from '@lovince/ui-vue'
</script>

<template>
  <LvHeading :level="1" size="display-md">Workspace</LvHeading>
  <LvText variant="body-md">Manage projects and members.</LvText>
  <LvLabel for="query">Search</LvLabel>
  <LvLink href="/guide">Read the guide</LvLink>
  <LvCode>bun test</LvCode>
  <LvKbd>Ctrl+K</LvKbd>
  <LvAspectRatio :ratio="16 / 9">
    <img src="/product.webp" alt="Product detail" />
  </LvAspectRatio>
  <LvVisuallyHidden>Search projects</LvVisuallyHidden>
  <LvSeparator :decorative="false" />
</template>
```

`LvBox`， `LvAspectRatio`， `LvText`， `LvHeading`， `LvLabel`， `LvLink`， `LvCode`， `LvKbd`, `LvVisuallyHidden` 支持 `as` 和 `asChild`. `LvAspectRatio` 默认为1:1 框架;集 `ratio` 到一个正有限数，例如 `16 / 9` 来衡量它的大小 内容区域。 `LvLink` 默认为锚，并留下导航属性 如 `href`， `target`, `rel` 在来电者的控制之下。 `LvCode` 和 `LvKbd` 默认为它们对应的语义元素。当 `LvHeading` 呈现一个非标题元素，它保持其语义级别 `role="heading"` 和 `aria-level`. `LvVisuallyHidden` 应用最小的内联 剪辑风格需要保持辅助技术的可用性。一个 non-decorative `LvSeparator` 公开分隔符语义及其方向； 装饰性分隔符隐藏在可访问性树中。

### 按钮

`LvButton` 是命名设计决策的部分： `variant` （`solid`， `subtle`， `outline`， `ghost`， `danger`), `size` （`sm`， `md`， `lg`， `icon`)成为 `data-variant` 和 `data-size`，而样式表决定了什么 他们每个人看起来都像。组件所拥有的是手写的标记 按钮出错了。

```vue
<script setup lang="ts">
import { LvButton } from '@lovince/ui-vue'
</script>

<template>
  <LvButton @click="save">Save</LvButton>
  <LvButton type="submit" variant="solid" size="lg" :loading="saving">Save</LvButton>
  <LvButton as="a" href="/settings" variant="ghost" size="sm">Settings</LvButton>
  <LvButton :disabled="!valid" variant="outline">Publish</LvButton>
</template>
```

-   `type` 默认为 `button`，因此表单中的按钮永远不会提交 事故;问......为...... `submit` 或者 `reset` 明确。
-   `disabled` 当元素为实元素时，设置native属性 `button`, `aria-disabled` 当它不是，因为锚不能被禁用。
-   `loading` 集合 `aria-busy` 并将控件保持在TAB顺序中——这是一个请求 从键盘开始，在吞咽时保持键盘可见 单击以使处理程序不能触发两次。
-   这两个状态也显示为 `data-disabled` 和 `data-loading`，两者都没有 运行 `onClick` 这是给定的。与 `asChild` 元素是你的，点击 处理包括;状态属性仍然到达。

### 图标

`LvIcon` 从中绘制一个象形符号 `@lovince/icons` 在注册表的共享24单元上 画布。它是它自己的条目，因为icon注册表是一个可选的peer： 进口 `@lovince/ui-vue` 没有加载图标数据，一个应用程序带来了自己的 icon不需要额外的东西。

```vue
<script setup lang="ts">
import { LvIcon } from '@lovince/ui-vue/icon'
</script>

<template>
  <LvIcon name="arrowRight" />
  <LvIcon name="success" :size="16" :stroke-width="1.5" label="Completed" />
</template>
```

图标是装饰性的 `aria-hidden="true"` -除非给出 `label`， 也就是说 `role="img"` 用那个通俗易懂的名字。 `absoluteStrokeWidth` 使渲染的描边厚度恒定为 `size` 生长; `fill` 取0到 1用于部分洗涤； `rotate` 和 `flip` 围绕画布中心转动。大小和 笔画退回到注册表自己的默认值，并且未知 `name` 呈现一个 空框而不是破坏布局。

### 形式

`LvFieldRoot` 提供一个稳定的输入id，并连接标签、描述和 误差为 `LvInput` 或者 `LvTextarea`． 描述和错误副本可以作为参数传递 道具或命名槽。集 `invalid` 暴露一个错误槽，或通过 `error` 来 自动将该字段标记为无效。 `required` 和 `disabled` 传播 对现场进行控制；每个控件都可以覆盖它们。

```vue
<script setup lang="ts">
import { LvFieldLabel, LvFieldRoot, LvForm, LvInput, LvTextarea } from '@lovince/ui-vue'
</script>

<template>
  <LvForm @submit.prevent="save">
    <LvFieldRoot required description="Use your work email.">
      <LvFieldLabel>Email</LvFieldLabel>
      <LvInput type="email" name="email" autocomplete="email" />
    </LvFieldRoot>

    <LvFieldRoot :invalid="Boolean(message)" :error="message">
      <LvFieldLabel>Project summary</LvFieldLabel>
      <LvTextarea name="summary" />
    </LvFieldRoot>

    <button type="submit">Save</button>
  </LvForm>
</template>
```

`LvInput` 和 `LvTextarea` 支持 `modelValue` / `defaultValue` 并发出 `update:modelValue`. `LvTextarea` 使用基于内容的字段大小 浏览器支持它，并保留了一个本机 `rows` 回退。 `LvForm` 是本地人 表单包装器：浏览器约束验证和提交事件保留在 控制。集 `submitting` 暴露 `aria-busy` 和 `data-submitting`，或者 `noValidate` 在其他地方处理验证时。

`TagsInput` 和 `FileUpload` 公开它们的当前值和被拒绝的条目 通过根节点的默认槽位。他们纯粹的规则和拒绝的理由依然存在 `@lovince/ui-headless`.

```vue
<script setup lang="ts">
import {
  LvFileUploadInput,
  LvFileUploadItem,
  LvFileUploadRemove,
  LvFileUploadRoot,
  LvTagsInputInput,
  LvTagsInputItem,
  LvTagsInputRemove,
  LvTagsInputRoot,
} from '@lovince/ui-vue'
</script>

<LvTagsInputRoot v-model="emails" :max="5" :validate="isEmail" name="emails">
  <LvTagsInputItem v-for="(email, index) in emails" :key="email" :index="index">
    {{ email }} <LvTagsInputRemove />
  </LvTagsInputItem>
  <LvTagsInputInput label="Add email address" />
</LvTagsInputRoot>

<LvFileUploadRoot v-model="files" accept="image/*,.pdf" :max-files="4" :max-size="5000000">
  <LvFileUploadInput />
  <LvFileUploadItem v-for="(file, index) in files" :key="file.name" :index="index">
    <template #default="{ file, size }">
      {{ file.name }} ({{ size }}) <LvFileUploadRemove />
    </template>
  </LvFileUploadItem>
</LvFileUploadRoot>
```

使用Enter或配置的分隔符创建标签；粘贴separator-delimited 文本被分割，并产生重复、无效和超出限制的值 `rejected`. 文件选择和删除共享相同的类型、每个文件大小、计数和总数 尺寸检查。 `LvFileUploadRoot` 发出接受 `File[]` 值和被拒绝的文件 用他们的理性； `LvFileUploadItem` 还暴露了kind， extension和localized 大小到它的槽。

`TimeField` 接受人工输入的时间并进行规范化存储 `HH:mm` 值。 它验证了可选 `min` 和 `max` 模糊或回车键的边界，并曝光 `invalid` 解析或范围验证失败时。 `PhoneInput` 格式一个 国家号码模糊，识别支持的国际前缀，还有 发出E.164值。它包含一个国家选择器，并接受一个可选的 自定义国家列表。

```vue
<LvTimeFieldRoot v-model="appointment" min="09:00" max="17:00" required name="appointment">
  <LvTimeFieldInput label="Appointment time" />
</LvTimeFieldRoot>

<LvPhoneInputRoot v-model="phone" country="KE" name="phone">
  <LvPhoneInputCountrySelect />
  <LvPhoneInputInput label="Mobile number" />
</LvPhoneInputRoot>
```

`ScrollArea` 保持滚动原生，同时暴露自定义，键盘可操作 滚动条的部分。从其容器中调整根的大小，然后渲染viewport和 滚动条/拇指部分在其中。根槽位报告当前溢出 指标;样式跟踪和拇指与他们的 `data-scroll-area-*` 属性。 视口保持其原生滚动行为和用途 `scrollbar-width: none` 支持该属性的地方。

```vue
<LvScrollAreaRoot class="results">
  <LvScrollAreaViewport>
    <div v-for="result in results" :key="result.id">{{ result.title }}</div>
  </LvScrollAreaViewport>
  <LvScrollAreaScrollbar>
    <LvScrollAreaThumb />
  </LvScrollAreaScrollbar>
</LvScrollAreaRoot>
```

可组合: `useDataTable`， `useVirtualList`， `useInView`， `useScrollEdges`， `useActiveSection`， `useClipboard`，再加上下面的积木。

包裹是 `sideEffects: false`． 只能导入应用程序 `LvDialogRoot` 船只 没有菜单、选择或表代码，测试强制执行这一点。

## 共同的约定

-   **`as` 和 `asChild`.** 每个部分都是一个合理的元素 `as` 去改变它。与 `asChild`，部分呈现你的独生子女， 将其属性和处理程序合并到。
-   **控制与否。** 离开 `v-model` 关闭，组件拥有自己的状态。 把它和你的价值结合起来，就是真理的源泉。每一个被接受的改变 发出，并将模型设置为 `undefined` 清除它。
-   **你的身份受到尊重。** 给任何部分 `id` 和ARIA参考文献 其他地方也一样。
-   **退出动画播放。** 关闭内容保持安装状态，使用 `data-state="closed"`，直到它的CSS动画结束。没有动画，或者 减少运动，它立即卸载。
-   **Hydration-safe门户。** 只在挂载后覆盖传送，所以服务器和 客户端呈现总是同意。
-   **可删除的解雇。** 覆盖发出 `escapeKeyDown` 和 `pointerDownOutside` (对话框也 `focusOutside`)。呼叫 `event.preventDefault()` 让它们保持开放。

## Lovince-specific行为

以下两种行为与Doitrix组件不同：

-   **披露内容和选项卡面板留在DOM中** 与 `hidden` 而 关闭了，所以在页面中找到 `aria-controls` 继续工作。
-   **Tabs选择第一个启用的选项卡** 当没有给出值时，包括during 服务器呈现。

模态对话框也构成了页面的其余部分 `inert`而不仅仅是专注。

## 构建块

这个包中的每个组件都是以同样的方式构建的：

```ts
const machine = useMachine(dialogMachine, initialContext, {
  controlled: { open: () => props.open },          // a v-model, synced in
  onChange: (next, previous) => emit(…),           // accepted changes, never echoes of props
  beforeSend: dismiss.filter,                      // e.g. cancellable dismissal
})
const api = computed(() => connectDialog(machine.snapshot.value, machine.send))
// h(Primitive, normalizeProps(api.value.contentProps), slots)
```

-   `useMachine` 在挂载时启动效果（在服务器上没有），在挂载时停止效果 卸载，保持一个受控值的来源的真理，并提供 `query` 那 `connect` 通读整页。组件永远不会接触 DOM。
-   `normalizeProps` 转动引擎的中性支柱(`onKeyDown`)到Vue's （`onKeydown`）. React适配器将在相同的机器上发布自己的适配器。
-   `useListEnv` 以视觉顺序从DOM中读取机器的列表项 导航列表。
-   `Primitive`， `Slot`， `Portal`， `usePresence`， `useIdWatch` 处理 呈现的问题: `as`/`asChild`水合安全的入口，出口动画， 消费者的id。

## 状态属性

| 属性 | 值 |
| --- | --- |
| `data-state` | `open` / `closed`， `checked` / `unchecked` / `indeterminate`， `active` / `inactive` |
| `data-disabled`， `data-readonly` | 设定时呈现 |
| `data-orientation` | `horizontal` / `vertical` |
| `data-side`， `data-align` | 碰撞处理后，浮动内容放置在哪里 |

浮动内容载体 `data-anchor-hidden` 当它的锚滚动时 看，又暴露 `--lovince-floating-available-height`， `--lovince-floating-available-width` 和 `--lovince-anchor-width`． 信息披露 内容公开 `--lovince-collapsible-height` 和 `-width` 用于高度动画。

## 已知的限制

-   定位是引擎自己的(参见 [`@lovince/ui-headless`](https://npmcn.com/package/%40lovince/ui-headless#positioning)): 它尊重滚动容器和转换后的祖先，并隐藏内容 谁的锚已经卷走(`data-anchor-hidden`）. 箭头不是内置的。
-   看到 [`@lovince/ui-dom`](https://npmcn.com/package/%40lovince/ui-dom#known-limitations) 用于 `inert` 滚动锁浏览器警告。

## 许可证

麻省理工学院

## 常见问题

### @lovince/ui-vue 是什么？

可访问的无头Vue 3组件为Lovince UI -披露，复选框，选项卡和对话框，无样式。

### 如何安装 @lovince/ui-vue？

在项目目录运行 npm install @lovince/ui-vue，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：vue（^3\.5\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @lovince/ui-vue 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @lovince/ui-vue 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @lovince/ui-vue 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @lovince/ui-vue 可以商用吗？

@lovince/ui-vue 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @lovince/ui-vue 还在维护吗？

最新版本 0\.5\.0 发布于 2026/11/02（1 天前）；至今共发布 11 个版本，其中过去 12 个月发布了 11 个；首次发布于 2026/10/16。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

