# Waveform Analysis 基于 Vue 3、TypeScript 和 D3 的响应式 SVG 波形图组件。适合展示单通道、多通道和大规模采样 数据,内置缩放、tooltip、图例、误差棒、标注、分页和多 Y 轴叠加。 当前稳定版本:`v0.1.15`。 组件使用不可变数据模型:替换 `data` 引用后会重新计算数据域和视口;大数据会按当前可见范围 和屏幕像素自动保峰降采样,而 tooltip、最近点查询和标注仍使用完整原始数据。 ## 在线示例 最新稳定版 Demo: 本地运行 `pnpm dev` 后,可通过 查看固定振幅上下限示例。 ## 特性 - Vue 3 Composition API + TypeScript,支持按需导入 `WaveformChart` - 采样值、显式坐标点和多系列数据模型 - `independent`、`separated`、`compact` 三种布局模式 - 曲线、阶梯线、点符号和对称/非对称误差棒 - 实线、虚线和点划线,可按系列独立配置 - 缩放过程事件、缩放结束按可视区间加载和视口重置 - 可选的空格拖拽平移,默认关闭并隔离多图表实例 - 多系列图例、受控显隐、网格分页和最多四根 Y 轴 - 自动 Y 轴范围,以及全局、按轨道或按系列配置的固定振幅范围 - 按轨道控制水平/垂直网格线的显隐与颜色 - 受控标注、右键编辑、拖拽避让和自定义颜色 - 标题、图框、坐标轴、零值参考线、净图和渲染参数可配置 ## 安装 组件库将 Vue、D3、Ant Design Vue 和 vue3-colorpicker 作为 peer dependency;直接安装到业务项目时请一并 安装这些依赖: ```bash pnpm add waveform-analysis vue d3 ant-design-vue vue3-colorpicker ``` ### 运行时版本要求 组件库支持以下运行时版本: | 依赖 | 支持版本 | | ---------------- | ------------- | | Vue | `>=3.2.33 <4` | | Ant Design Vue | `>=3.2.20 <4` | | D3 | `>=7.9.0 <8` | | vue3-colorpicker | `>=2.3.0 <3` | 安装时请确保业务项目中的 peer dependency 版本均满足上述范围。 ## 发布 发布由推送版本 tag 触发。`package.json` 的 `version` 必须与 tag 去掉 `v` 后完全一致。 稳定版使用 `vX.Y.Z`,预发布版使用 `vX.Y.Z-rc.1`;稳定版发布为 npm `latest`,预发布版发布为 `next`。流水线会创建 Gitea Release,并上传包文件与 SHA-256 校验文件。 ## 最小示例 ```vue ``` 父容器需要有明确高度;未指定 `width` 或 `height` 时,组件会填充父容器,并保持最小高度 `180px`。`WaveformChart` 的正式入口为 `src/index.ts`,样式入口为 `waveform-analysis/style.css`。 ## API 速查 ### Props | Prop | 类型 | 默认值 | 说明 | | --------------------------------- | ------------------------------------------- | ------------------------------------------------------- | --------------------------------- | | `data` | `WaveformData` | 必填 | 波形数据 | | `displayMode` | `'independent' \| 'separated' \| 'compact'` | `'independent'` | 图框布局 | | `overlayMode` | `'single-axis' \| 'multi-axis'` | `'single-axis'` | 叠加曲线的 Y 轴模式 | | `timeUnit` | `'s' \| 'ms'` | `'ms'` | 坐标轴和 tooltip 展示单位 | | `xLabel` / `yLabel` | `string` | `时间(timeUnit)` / `'幅值'` | 坐标轴名称 | | `lineColor` | `string` | `'#0960bd'` | 单波形默认颜色 | | `width` / `height` | `number` | 自适应 | 组件总尺寸,单位为 CSS 像素 | | `zoomable` / `showTooltip` | `boolean` | `true` / `true` | 缩放和数值 tooltip 开关 | | `pannable` | `boolean` | `false` | 空格拖拽平移开关 | | `minZoomSpan` | `number` | 未设置 | 最小缩放跨度,使用原始 X 数据单位 | | `minVisiblePoints` | `number` | `0` | 缩放后至少保留的不同 X 坐标数 | | `initialXDomain` | `[number, number]` | 未设置 | 所有图框的初始 X 范围 | | `initialXDomains` | `Record` | 未设置 | 按 track/series ID 配置初始范围 | | `yDomain` | `[number, number]` | 未设置 | 所有波形的固定 Y 轴范围 | | `yDomains` | `Record` | 未设置 | 按 track/series ID 配置固定范围 | | `grid` | `WaveformGridOptions` | `{ rowCount: 2, columnCount: 1, showPagination: true }` | 网格和分页 | | `axes` | `WaveformAxesOptions` | 轴线均显示 | X/Y 轴基线显隐 | | `rendering` | `WaveformRenderingOptions` | `{}` | 降采样与点/误差棒间距 | | `title` / `legend` / `frameStyle` | 对应公开类型 | 未设置 | 标题、图例和图框样式 | | `frameNumber` | `string \| number` | 未设置 | 图框水印内容 | | `zeroLine` | `WaveformZeroLineOptions` | `{ visible: false }` | 零值参考线显隐与样式 | | `cleanView` | `boolean` | `false` | 保留波形、图框和刻度的净图模式 | | `presentationMode` | `boolean` | `false` | 禁用绘图区交互的展示模式 | | `annotations` | `WaveformAnnotation[]` | `[]` | 受控标注数据 | | `annotationsVisible` | `boolean` | `true` | 标注图层显隐 | | `interactionMode` | `'zoom' \| 'annotation'` | `'zoom'` | 左键交互模式 | | `hiddenSeriesIds` | `string[]` | 未设置 | 受控隐藏系列 ID | | `defaultHiddenSeriesIds` | `string[]` | `[]` | 非受控模式的初始隐藏系列 | 所有公开类型均可从包入口导入,例如 `WaveformData`、`WaveformSeries`、 `WaveformAnnotation`、`WaveformLineStyle`、`WaveformRenderingOptions`、 `WaveformAxesOptions`、`WaveformZeroLineOptions`、`WaveformGridOptions` 和 `WaveformGridTrackLines`。 ### 数据结构 单通道可以使用采样值(`sampleRate` 为每秒采样数)或显式坐标点: ```ts import type { WaveformData } from 'waveform-analysis' const samples: WaveformData = { kind: 'samples', values: [0.2, 0.4, 0.1], sampleRate: 1000, startTime: 0, } const points: WaveformData = { kind: 'points', points: [ { x: 0, y: 12 }, { x: 0.001, y: 15, lowerError: 0.4, upperError: 0.8 }, ], } ``` 多通道使用 `kind: 'series'`。同一个 `trackId` 的系列会绘制在同一图框中;没有 `trackId` 的系列默认各占一个图框。建议为每个系列提供全图唯一且稳定的 `id`。 ```ts const chartData: WaveformData = { kind: 'series', series: [ { id: 'ch-a', name: '通道 A', trackId: 'group-1', data: samples }, { id: 'ch-b', name: '通道 B', trackId: 'group-1', data: points }, ], } ``` ## 波形图 组件内置缩放、悬浮取点和 tooltip。调用方只需要提供波形数据: ```vue ``` ### 固定振幅上下限 未传入 Y 轴范围时,组件继续根据当前可见系列及其误差棒自动计算范围。传入 `yDomain` 后,所有波形使用同一个固定范围;超出范围的部分只在绘图区裁剪,不会过滤或修改原始数据: ```vue ``` 多通道可以通过 `yDomains` 按稳定的 `trackId` 或 `seriesId` 分别配置: ```vue ``` 范围优先级为 `trackId` 配置、`seriesId` 配置、全局 `yDomain`、数据自动范围。上下限必须 是两个有限且不相等的数字;倒序范围会自动调整为升序,无效配置会回退到下一优先级。 固定范围会精确作为坐标域使用,不会经过 D3 的 `nice()` 扩展。 单值轴叠加模式会合并同一根轴上所有可见系列的有效范围;多值轴模式按系列分别使用配置, 超过四根轴后复用第 4 根轴的系列会取范围并集。隐藏系列不参与公共范围合并。 固定范围存在时,对应图框的 Y 轴不会被平移或视口重置覆盖;X 轴缩放、平移和重置保持原有 行为。运行时更新或移除 `yDomain` / `yDomains` 会立即重新布局,移除后恢复自动范围。 ### 缩放后按可视区间加载数据 组件支持 Plotly 风格的矩形框选缩放:在 zoom 模式下按住鼠标左键拖拽,松开后同时缩放 X/Y 轴;设置 `pannable` 后,指针位于图表内时按住空格键拖拽可平移当前视口。 鼠标滚轮可放大和缩小,双击恢复完整视口。 组件会在滚轮或框选缩放结束后触发 `zoom-end`,调用方可以使用端点请求后端,再通过 `data` 传回新数据。独立分图模式还会包含 `trackIndex` 和稳定的 `seriesIds`。 ```vue ``` `zoom-change` 会在滚轮、框选和平移过程中触发,适合更新外部状态;后端请求应使用 `zoom-end`,或在 `zoom-change` 上自行防抖。标注数据应由父组件独立持有,替换波形数据时 不要清空标注,组件会根据当前数据域自动隐藏或恢复对应标注。 `zoom-end.gesture` 用于区分 `wheel` 和 `box`。单轨道 payload 使用 `yStart/yEnd`;共享 X 轴且包含多个轨道时使用按稳定 track ID 索引的 `yRanges`。平移不会触发 `zoom-end`, 因此不会自动发起新的区间加载请求。 调用方应处理加载失败的情况(网络错误、超时等),并保持旧数据或显示加载状态。生产环境建议使用 `AbortController` 取消过时的请求。 `initialXDomain` 固定首次完整数据的 X 轴缩放边界,不要将它改成后端返回的当前窗口;独立图框有不同时间范围时,可通过 `initialXDomains` 按 track ID 或 series ID 分别配置。`minZoomSpan` 使用原始 X 数据单位, 可防止每次区间数据回填后重新累计放大。双击图框会 重置组件内部缩放并触发 `zoom-reset`;调用方应在事件中取消区间请求并恢复首次完整数据。 外部重置按钮也可以通过模板引用调用组件公开的 `resetViewport()` 方法,然后执行相同的数据恢复逻辑。 独立坐标模式下,回填响应应只替换 `seriesIds` 对应的系列,并调用 `resetViewport(trackIndex)`;其他图框的数据和缩放状态应保持不变。 多通道数据应为每个 `WaveformSeries` 提供稳定的 `id`。内部时间坐标始终使用秒, `timeUnit` 只控制坐标轴和 tooltip 的显示单位。 ### 线型、点型与误差棒 每条序列可以独立设置连线方式、数据点符号和误差棒: ```ts const series = { id: 'temperature', name: '温度', lineType: 'step-end', lineStyle: 'dashed', pointType: 'circle', errorBar: { visible: true, width: 1.5, capWidth: 8 }, data: { kind: 'points', points: [ { x: 0, y: 12, error: 0.5 }, { x: 1, y: 15, lowerError: 0.4, upperError: 0.8 }, ], }, } satisfies WaveformSeries ``` `lineType` 支持 `none`、`linear`、`step-start`、`step-middle` 和 `step-end`;它控制连接线的几何形态,兼容值 `step-after` 与 `step-end` 等价。三个阶梯值分别在区间起点、中点和终点跳变。`pointType` 支持 `none`、`circle`、`square`、`triangle` 和 `diamond`。默认使用普通直线且不显示数据点; `lineStyle` 控制连接线的描边样式,支持 `solid`、`dashed` 和 `dash-dot`,默认值为 `solid`; 设置 `lineType: 'none'` 可以隐藏数据点之间的连接线,只保留点符号和误差棒;将其改为 `linear` 或阶梯类型即可同时显示对应连接线。误差棒仅在 `errorBar.visible` 为 `true` 时显示, 并参与 Y 轴范围计算;当误差棒可见时,`lineType` 和 `pointType` 可以同时为 `none`,用于展示 纯误差棒。只有连接线、点符号和误差棒全部关闭时才会回退为普通直线。`lowerError`、 `upperError` 分别覆盖对称的 `error`,图例会同步显示实际线型、点型和误差棒样式。 ### 叠加与多值轴 为多条曲线设置相同的 `trackId`,可将它们叠加到同一图框。`overlayMode` 控制叠加 曲线共享一根 Y 轴还是使用独立值轴: ```vue ``` `overlayMode` 对应公开类型 `WaveformOverlayMode`,可选值为 `single-axis` 和 `multi-axis`,默认值为 `single-axis`。多值轴最多渲染四根 Y 轴;超过四条曲线时, 后续曲线复用第 4 根轴,该轴的范围覆盖绑定到它的全部曲线。轴顺序依次为左侧、 右侧;三轴时第 3 根位于右侧外部,四轴时顺序为左侧、左侧外部、右侧、右侧外部。 `overlayMode` 与 `displayMode` 相互独立。`displayMode` 仍可使用 `independent`、 `separated` 或 `compact` 控制图框布局和 X 轴共享方式;未共享 `trackId` 的单曲线 图框不会因为切换叠加方式而改变。 ### 绘图区域尺寸 `width` 和 `height` 接收像素数值,并且可以独立设置。指定的维度使用固定尺寸,未指定的 维度自适应填满父容器: ```vue
``` 自适应高度要求父容器具有明确高度;父容器未定高时,组件使用最低 `180px` 高度。 显式高度同样保留 `180px` 下限。非有限尺寸按未指定处理,负宽度归零。 ### 图表标题 `title` 在整个波形网格上方渲染一次,支持显隐、对齐、字体样式和旋转: ```vue ``` 对应的公开类型为 `WaveformTitleOptions` 和 `WaveformTitleTextStyle`。未传 `title`、 `visible` 为 `false`,或 `text` 去除首尾空格后为空时,标题不渲染且不占高度。标题默认 居中、字号 `14px`、颜色 `#1f2937`、微软雅黑、常规字重且不旋转。标题区域高度按文字及旋转角度 在 `44px` 至 `160px` 之间计算;超长文字会省略,悬浮可查看完整内容。 `width` 和 `height` 始终表示组件总尺寸。标题显示后会从总高度中扣除标题区域,剩余高度 用于 SVG 绘图区,因此启用标题不会扩大组件或破坏父容器布局。 Demo 左侧控制面板提供标题实时预览,可配置标题名称、显隐、对齐、字体、字号、粗体、 斜体、下划线、旋转和颜色。字号范围为 `8–72px`,旋转范围为 `-180–180°`;样式栏中的 `A` 用于恢复常规字重、非斜体和无下划线,关闭标题不会清除已经填写的配置。 ### 图框样式 `frameStyle` 统一设置所有非空图框的边框和背景,颜色支持带 alpha 的 CSS 颜色值: ```vue ``` `frameStyle.borderStyle` 支持 `solid`(实线)、`dashed`(虚线)和 `dotted`(点虚线)。 对应的公开类型为 `WaveformFrameStyle`。默认边框颜色为 `#1f2937`、线宽为 `1`、线型为 `solid`,背景透明。`borderWidth` 为 `0` 时隐藏边框;非有限值或负数会回退到默认线宽。 ### 图例与曲线显隐 `legend.backgroundColor` 设置多曲线图例的背景颜色。该字段接受任意有效 CSS 颜色值, 可通过 `rgba(...)` 或 `hsla(...)` 中的 alpha 通道调整透明度: ```vue ``` `legend.trackPositions` 按图框 ID 单独覆盖图例位置;同一个 `trackId` 组成的图框以该 `trackId` 为键,未设置 `trackId` 时以规范化后的 `series.id` 为键。未命中的图框继续使用 `legend.position`,两者都未配置时使用 `top-right`。当 `orientation` 为 `auto` 时,每个图框 会根据最终位置独立选择排列方向:`top`、`bottom` 为水平排列,其余位置为垂直排列。 未配置或传入空字符串时,图例背景默认使用 `rgba(255, 255, 255, 0.7)`。 `legend.interactive` 默认为 `false`;开启后可以单击或使用键盘操作图例项切换曲线显隐。 调用方可通过 `hiddenSeriesIds` 和 `update:hidden-series-ids` 控制状态,也可使用 `defaultHiddenSeriesIds` 设置非受控模式的初始隐藏项。隐藏状态同步作用于坐标轴、tooltip、 悬浮点和标注交互;允许隐藏全部曲线,并可通过保留的图例恢复显示。 显隐状态以规范化后的 `series.id` 为键。要在数据刷新和重新排序后稳定保留状态,每个系列都应 提供全图唯一且稳定的显式 `id`;自动生成的索引 ID 或重复 ID 添加的后缀不保证跨排序稳定。 ### 零值参考线与净图 `zeroLine` 用于绘制 `y = 0` 的水平参考线,默认隐藏。参考线只在对应 Y 轴的当前 domain 包含 0 时渲染,不会为了显示参考线而扩展数据范围。多值轴模式下,每根可见 Y 轴分别按自身 scale 定位零线: ```vue ``` `dash` 直接对应 SVG 的 `stroke-dasharray`;传入空字符串可显示实线。无效或非正数的 `width` 会回退到 `1`。 设置 `cleanView` 后,组件保留波形、图框边框、X/Y 轴刻度及刻度值,并隐藏标题内容、图例、 网格、轴标签、图框背景、帧水印、零值参考线、标注和分页器。原图的标题区域、边距和波形 尺寸保持不变;缩放、悬浮、十字线和 tooltip 仍然可用,切换回普通模式后原有配置和标注 不会丢失: ```vue ``` ### 网格、分页与交互模式 `grid` 控制独立图框的行列数(范围 `1–10`)以及是否显示分页器。默认值为 `2` 行、 `1` 列并开启分页;当图框数量超过网格容量时,分页器会显示在图表右下角。 还可以通过 `trackLines` 按轨道 ID 分别控制水平/垂直网格线的显隐和颜色。颜色未配置时, 继续使用组件默认的主/次网格颜色: ```vue ``` `axes` 可以分别隐藏 X/Y 轴的基线,同时保留刻度短线、刻度数字、科学计数倍率、单位和轴标题。 与关闭网格线、设置 `frameStyle` 组合后,可以只使用图框边框围住绘图区: ```vue ``` `interactionMode` 可选 `zoom` 或 `annotation`,默认使用缩放模式。右键绘图区可直接打开 标注编辑器,无需切换交互模式。`zoomable`、`pannable` 和 `showTooltip` 可分别控制缩放、 空格拖拽平移和 tooltip;平移默认关闭。 展示场景可启用 `presentationMode`,统一禁用绘图区的 tooltip、缩放、平移、双击复位和 标注交互。该模式不会隐藏任何图形内容,也不会禁用图例切换或分页;关闭后恢复原交互配置。 ```vue ``` 空数据或过滤后没有有效点时,组件会保留图框布局并显示“暂无有效波形数据”。 ## 大数据渲染 组件按不可变数据处理:替换 `data` 引用会重新过滤、排序和缓存坐标域,并重置视口; 原地修改已有数组不会触发缓存刷新。建议通过 `shallowRef` 保存大数据并整体替换引用。 规范化始终保留所有有效点,坐标域、误差棒、tooltip 和标注均使用完整数据;绘制路径会根据 当前视口和 `rendering` 配置自动降采样。调用方如需在传入组件前主动压缩数据,应自行保留 原始数据,以免影响 tooltip、标注和误差范围的精度。 默认在可见点超过 2,000 时进行降采样,每个像素最多渲染 4 个保峰点。可按业务调整: ```vue ``` 全量视图只绘制均匀分布的真实数据点,放大后会自动恢复更多源标记。`pointMinSpacing` 和 `errorBarMinSpacing` 分别控制点符号和误差棒的最小水平间距,单位为 CSS 像素。两者同时 显示时共用一批采样点,并采用两个间距中的较大值,确保误差棒与对应点符号保持共心;仅显示 一类装饰时仍使用各自的间距。仅显示一类装饰时可将对应间距设为 `0`;两者同时显示时需将 两个间距都设为 `0` 才会关闭共同限制。设置 `downsample: false` 会关闭曲线和装饰的全部降采样。 降采样仅作用于 SVG 中的曲线、点符号和误差棒。点符号和误差棒在每个系列中分别合并为 单个 SVG path;最近点查询、tooltip、标注插值、Y 轴误差范围和受控数据不会损失精度。 ## 采样点标注 标注由父组件通过 `v-model:annotations` 持有,标注使用 `seriesId` 和 `x/y` 数据坐标, 不依赖数组下标: ```vue ``` 标注默认显示。右键绘图区任意位置即可弹出居中编辑器,标注会吸附到当前 X 位置最近的真实采样点,右键已有标注可以编辑或删除。 标注框可以直接拖动进行手动避让,拖动只改变标签框位置,不会改变 `x/y` 数据锚点;偏移会以 `labelOffsetX/labelOffsetY` 像素字段保存在标注中。标注文本最多 40 个字符,边框色、文字色和背景色均支持取色与透明度调整。组件只负责内存中的受控数据, 业务层负责会话或后端持久化。 标注可以序列化为带版本号的 JSON,并在解析成功后整体替换当前数据: ```ts const exportedJson = serializeWaveformAnnotations(annotations.value) async function importAnnotationFile(file: File) { annotations.value = parseWaveformAnnotations(await file.text()) } ``` 导出格式为 `{ version: 1, annotations: [...] }`。解析会验证全部标注;文件格式、版本或任意 字段无效时会抛出 `TypeError`,不会返回部分结果。导入包含未知 `seriesId` 的标注是允许的, 对应曲线加载后会恢复显示。文件选择、错误提示和下载由业务层实现。 X 轴刻度和左右端点先按 `timeUnit` 转换为秒或毫秒,再四舍五入为不带分组符的普通整数,不使用科学计数法。Y 轴会根据完整显示域选择格式:最大绝对值在 `[0.01, 100)` 时显示两位普通小数;大于等于 `100`,或大于 `0` 且小于 `0.01` 时,刻度显示两位缩放值,并在轴末端单独显示共享倍率 `E±NN`,多 Y 轴分别计算倍率。tooltip 使用最多 4 位小数的本地化普通数字并省略无意义尾零;标注编辑器的 X 坐标跟随 `timeUnit` 并固定 3 位小数,Y 坐标显示完整普通十进制。所有格式化都只发生在展示层,内部坐标值保持原始精度。 标注框默认布局在采样点正上方,只做绘图区边界裁剪;文本框通过连接箭头指向标注位置,多个标注重叠时可通过拖动手动避让。 ## 事件 组件提供以下事件,名称与 Vue 模板写法一致: | 事件 | 说明 | | --------------------------------------------------------------- | -------------------------------------------------------------- | | `point-hover` | 当前最近点变化时触发,离开图表时传入 `null` | | `zoom-change` | 缩放过程中触发,参数为 `[start, end]` | | `zoom-end` | 滚轮或框选结束后触发;`gesture` 区分二者,独立模式附带轨道信息 | | `zoom-reset` | 双击重置视口时触发,调用方应恢复首次完整数据 | | `page-change` | 分页变化,参数为当前页和总页数 | | `series-visibility-change` | 图例切换曲线显隐时触发 | | `annotation-create` / `annotation-update` / `annotation-delete` | 标注新增、更新或删除 | `annotations` 和 `hidden-series-ids` 支持 `v-model`;`annotations-visible` 与 `interaction-mode` 是受控输入属性。业务层应负责将标注和显隐状态持久化。 ## 项目结构 - `src/index.ts`:组件库公开入口和工具函数导出 - `src/components/WaveformChart.vue`:图表容器、缩放、tooltip、图例和标注编排 - `src/components/{core,data,rendering,interaction,annotation}`:数据、布局、渲染和交互模块 - `src/App.vue`:综合可交互 demo,`src/data` 中提供示例波形数据 - `src/router.ts`:Demo 路由;`src/views/FixedYDomainDemo.vue` 为固定振幅范围示例 ## 本地开发 开发环境要求 Node.js 22 和 pnpm: ```bash pnpm install pnpm dev ``` 常用质量检查和构建命令: ```bash pnpm typecheck pnpm lint pnpm test pnpm test:coverage pnpm build ``` `pnpm build` 同时生成 `dist/` 组件库产物和 `dist-demo/` 演示应用。正式公开入口为 `src/index.ts`,样式入口为 `src/styles.css`;`dist/` 和 `dist-demo/` 均为生成目录,不要手工编辑。 ## 发布流程 发布由推送版本 tag 触发。先将 `package.json` 的 `version` 更新为目标版本并提交,再创建同版本 tag: ```bash git tag -a v0.1.15 -m "Release v0.1.15" git push origin main --follow-tags ``` 支持稳定版 `vX.Y.Z` 与预发布版 `vX.Y.Z-rc.1`。tag 去掉 `v` 后必须与 `package.json` 的 `version` 完全一致。稳定版发布为 npm `latest`,预发布版发布为 npm `next`。流水线会创建 Gitea Release,并上传 `.tgz` 与 SHA-256 校验文件。