# @dkachko/angular2-toaster 中文文档

规范地址：https://npmcn.com/package/%40dkachko/angular2-toaster/

版本：15\.0\.1
npm 元数据更新时间：2023-04-26T21:27:44.180Z
中文译文更新时间：2026-11-12T12:29:39.062Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40dkachko/angular2-toaster
原文对照：https://npmcn.com/package/%40dkachko/angular2-toaster/?lang=original
项目主页：https://github.com/stabzs/Angular2-Toaster#readme
源码仓库：https://github.com/stabzs/Angular2-Toaster

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

- 包体积（解压后）：323 kB，36 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：@angular/common ^15\.0\.0，@angular/compiler ^15\.0\.0，@angular/core ^15\.0\.0，rxjs ^7\.5\.0
- 首次发布：2022-10-06T20:16:51.231Z
- 最新版本发布：2023-04-26T21:27:44.062Z
- 近 30 天下载量：7481（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：4（近 12 个月 0 个）

## 中文简介

基于 AngularJS- Toaster 的 Angular Toaster 通知库

## 安装

```sh
npm install @dkachko/angular2-toaster
```

也可以使用：`pnpm add @dkachko/angular2-toaster`、`yarn add @dkachko/angular2-toaster`、`bun add @dkachko/angular2-toaster`

## README

# 角2号烤面包机

**角2-托盘** 是一个同步的、非屏蔽的、 时间前期汇编支持的 Angular Toaster 通知库 主要基于 [角形JS- Toaster 图像](https://github.com/jirikavi/AngularJS-Toaster)。 。 。 .

[![npm](https://img.shields.io/npm/v/angular2-toaster.svg?maxAge=3600?800=true)](https://www.npmjs.com/package/angular2-toaster) [![npm](https://img.shields.io/npm/dt/angular2-toaster.svg?cache=true)](https://www.npmjs.com/package/angular2-toaster) [![Build Status](https://travis-ci.org/Stabzs/Angular2-Toaster.svg?branch=master)](https://travis-ci.org/Stabzs/Angular2-Toaster) [![Coverage Status](https://coveralls.io/repos/github/Stabzs/Angular2-Toaster/badge.svg?branch=master&b=11.0.0)](https://coveralls.io/github/Stabzs/Angular2-Toaster?branch=master)

^11.0.0版本有一些新特征,类型定义,以及断裂变化. 请审查 [变化](https://npmcn.com/package/%40dkachko/angular2-toaster/CHANGELOG.md/#11.0.0) 用于在升级前列出特性和打破更改.

^ 5. 0. 0. 版本要求任一 `.forRoot()` 或者说 `.forChild()` `ToasterModule` 列入。 请 读取 5.x.x 发布注释和 `Getting Started` 在升级前.

^4.0.0版本现在支持@angular/动画,这是一个突破性的更改. 请在升级前同时阅读“开始”和“动画”两个部分.

# 演示

可在下列地点找到动态角和打字演示 [这个平板电脑](http://plnkr.co/edit/hkENUhos6q9fhiOHprXO?p=preview)。 。 。 .

# 开始

## 安装 :

```bash
npm install angular2-toaster
```

## 导入 CSS

### 复制或链接 CSS

```html
<link rel="stylesheet" type="text/css" href="/node_modules/angular2-toaster/toaster.css" />
```

或者说

```html
<link rel="stylesheet" type="text/css" href="/node_modules/angular2-toaster/toaster.min.css" />
```

### 以 Sass 或 小于 SSS 导入 CSS

```scss
@import 'node_modules/angular2-toaster/toaster';
```

### 汇编图书馆的SCSS

```scss
@import 'node_modules/angular2-toaster/toaster';
```

## 导入库

### 通过系统JS导入

内部 `map` 财产的财产 `systemjs.config` 文件,为角、 rxjs 添加映射 (这是一个依赖), 和 angular2-toaster 捆绑 umd 文件:

```javascript
map: {
      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      // ...
      // other libraries
      'rxjs':  'npm:rxjs',
      'angular2-toaster': 'npm:angular2-toaster/bundles/angular2-toaster.umd.js'
```

### 通过 Webpack 导入

只要跟随 `Getting Started` 命令导入库.

## 以默认配置开始 - NgModule( 建议) :

```typescript
import {NgModule, Component} from '@angular/core';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {ToasterModule, ToasterService} from 'angular2-toaster';
import {Root} from './root.component'

@NgModule({
    imports: [BrowserAnimationsModule, ToasterModule.forRoot()],
    declarations: [Root],
    bootstrap: [Root]
})

@Component({
    selector: 'root',
    template: `
            <toaster-container></toaster-container>
            <button (click)="popToast()">pop toast</button>`
})

export class Root {
    private toasterService: ToasterService;

    constructor(toasterService: ToasterService) {
        this.toasterService = toasterService;
    }

    popToast() {
        this.toasterService.pop('success', 'Args Title', 'Args Body');
    }
}
```

`ToasterModule.forRoot()` 它将保证一个单一的托斯特服务实例,确保所有接收容器都遵守同样的托斯特服务事件.

用于以后的列入,使用 `ToasterModule.forChild()` 提供 `ToasterContainerComponent` 只有,确保 `ToasterService` 仍作为根部单子持有.

## 启动默认配置 - 手动组件包含( 过时 QQ 5. 0.0 ):

```typescript
import {Component} from '@angular/core';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {ToasterContainerComponent, ToasterService} from 'angular2-toaster';

@Component({
    selector: 'root',
    imports: [BrowserAnimationsModule],
    directives: [ToasterContainerComponent],
    providers: [ToasterService],
    template: `
        <toaster-container></toaster-container>
        <button (click)="popToast()">pop toast</button>`
})

class Root {
    private toasterService: ToasterService;
    
    constructor(toasterService: ToasterService) {
        this.toasterService = toasterService;    
    }
    
    popToast() {
        this.toasterService.pop('success', 'Args Title', 'Args Body');
    }
}

bootstrap(Root);
```

## 以配置覆盖开始 :

```typescript
import {Component} from '@angular/core';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {ToasterModule, ToasterService, ToasterConfig} from 'angular2-toaster';

@Component({
    selector: 'root',
    imports: [BrowserAnimationsModule, ToasterModule.forRoot()],
    template: `
        <toaster-container [toasterconfig]="config">
        </toaster-container>
        <button (click)="popToast()">pop toast</button>`
})

class Root {
    private toasterService: ToasterService;
    
    constructor(toasterService: ToasterService) {
        this.toasterService = toasterService;    
    }
    
    public config: ToasterConfig = 
        new ToasterConfig({
            showCloseButton: true, 
            tapToDismiss: false, 
            timeout: 0
        });
    
    popToast() {
        this.toasterService.pop('success', 'Args Title', 'Args Body');
    }
}

bootstrap(Root);
```

## 同步对同步烤面包机服务

`ToasterService` 以下列形式暴露出同步和同步的流行方法: `pop()` 财务报告和审定财务报表 `popAsync()` 页:1.

`pop()` 返回混凝土 `Toast` 土司的地产被水化 所有接收集装箱都添加了土司.

`popAsync()` 返回热量 `Observable<Toast>` 可能签署接受多份祝酒 更新.

## 自定义 在流行中提示参数

```typescript

var toast: Toast = {
    type: 'success',
    title: 'close button',
    showCloseButton: true
};

this.toasterService.pop(toast);

```

## 清除已存在的吐司

`ToasterService` 暴露一个 `clear` 函数接受两个可选参数: `toastId` 财务报告和审定财务报表 `toastContainerId`。 。 。 .

这些参数可以用来通过特定的id来清除吐司,通过容器id, 两者,或两者皆然。 如果省去这两个参数,所有容器中的所有土司都将是 已删除.

```typescript
var toast = this.toasterService.pop('success', 'title', 'body');
this.toasterService.clear(toast.toastId, toast.toastContainerId);
```

## 动画

从版本开始 `4.0.0` 需要更大的动画配置,如 `Getting Started` 节.

要添加动画 :

-   安装 `@angular/animations` npm 软件包通过 `npm install @angular/animations`。 。 。 .
    
-   添加数据 `BrowserAnimationsModule` 转到您的根模块
    
    ```typescript
    import {NgModule, Component} from '@angular/core';
    import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
    import {ToasterModule} from 'angular2-toaster';
    
    @NgModule({
        imports: [BrowserAnimationsModule, ToasterModule],
        ...
    ```
    

如果你想避免仅仅为了动画而增加一个模块,你可以 明确配置 `angular2-toaster` 忽略动画。 为此,导入 `NoopAnimationsModule` 相反:

```typescript
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {ToasterModule} from 'angular2-toaster';
    
@NgModule({
    imports: [NoopAnimationsModule, ToasterModule],
    ...
```

需要角动画 [浏览器](http://caniuse.com/#feat=web-animation) 支持 [Web 动画标准](https://w3c.github.io/web-animations/)。 。 。 .

如果您需要瞄准一个非支持的浏览器, a [多边填充](https://github.com/web-animations/web-animations-js) 需要时间.

# 可配置选项

### 托拉斯类型

默认情况下,5个土司类型是通过 `ToastType` 类型 : “ error” 、 “info” 、 “等待” 、 “ 成功” 和 “ 警告” .

现有的土司类型配置可以通过通过一个使用 相同类型名称, 但覆盖样式类 :

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({typeClasses: {
      error: 'custom-toast-error',
      info: 'custom-toast-info',
      wait: 'custom-toast-wait',
      success: 'custom-toast-success',
      warning: 'custom-toast-warning'
    }});
```

此外,默认选项还可以被推翻、替换或扩展,方法是用一个 自定义类型并将映射对象传递到配置中,其中密钥对应了土司类型和 值对应自定义类 :

**注:在提供自定义类型时,必须更新类型Classes和图标Classes两个对象. 如果两者均不提供,则土司类型将回落到 `defaultToastType` 哪个 默认为 `info`。 。 。 .**

```typescript
import {DefaultTypeClasses, DefaultIconClasses} from 'angular2-toaster';
type ExtendedToastType = ('partial-success') & ToastType;

template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

extendedTypeClasses = { ...DefaultTypeClasses, ...{ 'partial-success': 'toast-partial-success' }};
extendedIconClasses = { ...DefaultIconClasses, ...{ 'partial-success': 'icon-partial-success' }};

public config: ToasterConfig = 
    new ToasterConfig({
        typeClasses: <ExtendedToastType>this.extendedTypeClasses,
        iconClasses: <ExtendedToastType>this.extendedIconClasses
    });
```

### 动画

有五种动画风格可以通过烤面包机配置应用 `animation` 属性 : 平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平起平 其他任何值都会禁用动画.

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({animation: 'fade'});
```

### 限制

限制默认为无效, 也就是说没有定义最多多的土司 在吐司容器开始去除吐司之前... ...当一个新的吐司被添加.

要改变这个行为, 请通过“ 限制” 选项到配置 :

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({limit: 5});
```

### 拨打解散

默认情况下 `tapToDismiss` 选项设置为正,这意味着如果在任何地方单击了祝酒词 在吐司身体上, 吐司将被解雇。 此行为可在配置中被覆盖 如果设置为虚假, 只有关闭按钮被定义并点击时, 土司才会被删除 :

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({tapToDismiss: false});
```

### 集装箱位置

预建有9个烤面包机集装箱位置配置:

```
'toast-top-full-width', 'toast-bottom-full-width', 'toast-center',
'toast-top-left', 'toast-top-center', 'toast-top-right',
'toast-bottom-left', 'toast-bottom-center', 'toast-bottom-right'
```

默认, `'toast-top-right'` 将被使用。 您可以通过 `positionClass` 属性 :

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({positionClass: 'toast-top-left'});
```

### 关闭按钮

Close按钮的能见度可以配置在三个不同的级别:

-   从全球来看,所有土司类型都有:
    
    ```typescript
    template: 
        `<toaster-container [toasterconfig]="config"></toaster-container>`
    
    public config: ToasterConfig = 
        new ToasterConfig({showCloseButton: true});
    ```
    
-   每个信息类类型 : 通过将关闭按钮配置作为对象而不是布尔来传递,可以指定信息类类型的全局行为.
    
    ```typescript
    template: 
        `<toaster-container [toasterconfig]="config"></toaster-container>`
    
    public config: ToasterConfig = 
        new ToasterConfig({
            showCloseButton: { 'warning': true, 'error': false }
        });
    ```
    
    如果没有定义和指定一个类型,该类型的默认行为是虚假的.
    
-   通过 Toast 对象创建构建的每个土司 :
    
    ```typescript
    var toast : Toast = {
        type: 'error',
        title: 'Title text',
        body: 'Body text',
        showCloseButton: true
    };
    
    this.toasterService.pop(toast);
    
    ```
    
    这个选项最受重视,并且将取代全球的土司配置。 然而,它不会继续留在其他此类的土司上,也不会改变或污染全球布局.
    

### 关闭 Html

关闭的按钮html可以被全球覆盖,也可以被每个土司调用.

-   全球:
    
    ```typescript
    template: 
        `<toaster-container [toasterconfig]="config"></toaster-container>`
    
    public config: ToasterConfig = 
        new ToasterConfig({
            closeHtml: '<button>Close</button>'
        });
    ```
    
-   每个土司:
    
    ```typescript
    var toast : Toast = {
        type: 'error',
        title: 'Title text',
        body: 'Body text',
        showCloseButton: true,
        closeHtml: '<button>Close</button>'
    };
    
    this.toasterService.pop(toast);
    ```
    

### 顶上最新的烤面包

这个 `newestOnTop` 选项默认为真,在其它已有的土司上添加新的土司. 如果通过配置更改为虚假,会将土司添加到其他现存土司的底部.

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({newestOnTop: false});
```

### 超时

默认情况下,土司的超时设置为5000个,也就是说它们会在5000个之后被移除 毫秒长.

如果超时设定为超过0的,则会考虑吐司 "粘"而不会自动辞退.

超时可以配置在三个不同的级别:

-   从全球来看,所有土司类型都有:
    
    ```typescript
    template: 
      `<toaster-container [toasterconfig]="config"></toaster-container>`
    
    public config: ToasterConfig = 
          new ToasterConfig({timeout: 2000});
    ```
    
-   每个信息类类型 : 通过将超时配置选项传递为对象而不是数字,您可以指定全局 信息类的行为应该有.
    
    ```
    template: 
      `<toaster-container [toasterconfig]="config"></toaster-container>`
    
    public config: ToasterConfig = 
        new ToasterConfig({timeout: {error:1000});
    ```
    

如果一个类型没有定义和指定,则不会应用超时,使吐司"粘".

-   每道土司通过烤面包机. pop('success',"title","text")构造:
    
    ```typescript
    var toast : Toast = {
        type: 'error',
        title: 'Title text',
        body: 'Body text',
        showCloseButton: true,
        closeHtml: '<button>Close</button>'
    };
          
    this.toasterService.pop(toast);
    ```
    

### 防止鼠标超时

默认情况下,所有土司在计时器过期时都会被解职, 即使你鼠标在土司上.  
这可以通过容器的配置来覆盖.

```typescript
template: 
    `<toaster-container [toasterconfig]="config"></toaster-container>`

public config: ToasterConfig = 
    new ToasterConfig({mouseoverTimerStop: false});
```

### 车体输出类型

有三种不同的身体渲染方式可以通过 `toast.bodyOutputType` 参数 : “ 默认 ” 、 “ 信任 Html ” 和 “ 组件 ”。 如果有的话 `bodyOutputType` 未提供,它将默认为“ 默认 ” .

-   默认: `body` 参数将作为文本内容直接插入。 如果通过html 输入 `body` 参数,它将被编码成文本.
    
-   信任的 Httml : 该 `body` 参数将作为 html 内容解析和提供.
    
    ```typescript
    import {BodyOutputType} from 'angular2-toaster';
    var toast : Toast = {
        type: 'error',
        title: 'Title text',
        body: '<h4>Body text</h4>',
        bodyOutputType: BodyOutputType.TrustedHtml
    };
              
    this.toasterService.pop(toast);
    ```
    
-   构成部分: `body` 参数是用作内容的组件类的名称 祝酒词.
    
    ```typescript
    import {BodyOutputType} from 'angular2-toaster';
    
    @Component({
      selector: 'dynamic-component',
      template: `<div>loaded via component</div>`
    })
    class DynamicComponent { }
    
    var toast : Toast = {
        type: 'error',
        title: 'Title text',
        body: DynamicComponent,
        bodyOutputType: BodyOutputType.Component
    };
              
    this.toasterService.pop(toast);
    ```
    
    构成部分 " 体积输出Type " 提供了额外的灵活性,即将土司实例附于 你的组件。 建议您在您的部件上曝光一个公共财产类型 如果你需要用在你的组件内的话 可以安全进入烤面包箱.  
    不建议改变吐司的情况.
    

### 进度栏

每个土司都可通过 `progressBar` 属性。 如果设置为对, 则会有一个进度栏 显示在土司被自动解除之前 还有多少时间.

进步栏有两个方向: `decreasing` 或从左到右 `increasing`,或从左到右. 默认时 改为 `decreasing`每个土司都会被推翻:

```typescript
var toast: Toast = {
  type: 'success',
  progressBar: true,
  progressBarDirection: 'increasing'  
};

this.toasterService.pop(toast);
```

### 显示回调时

每个土司实例可附加一个 onShow回调功能. 吐司加起来后,将使用回调.

```typescript
var toast: Toast = {
  type: 'success',
  title: 'parent',
  onShowCallback: (toast) => this.toasterService.pop('success', 'invoked from ' + toast.title + ' onShow callback')  
};

this.toasterService.pop(toast);
```

### 隐藏回调

每个土司实例可附带一个在线回调功能。 吐司撤走时,将援引回调.

```typescript
var toast: Toast = {
  type: 'success',
  title: 'parent',
  onHideCallback: (toast) => this.toasterService.pop('success', 'invoked from ' + toast.title + ' onHide callback')  
};

this.toasterService.pop(toast);
```

### 点击回拨

每个土司实例都可以附加一个 onClick回调功能. 敬酒时,将使用回调 已点击,即使点击是关闭按钮。 在去除吐司之前,会引用回调.

```typescript
var toast: Toast = {
  type: 'success',
  title: 'parent',
  onClickCallback: (toast) => this.toasterService.pop('success', 'invoked from ' + toast.title + ' onClick callback')  
};

this.toasterService.pop(toast);
```

# 构建源

为了建造Angular2-Toaster以促进发展,需要安装Git和Node.js.

切除回转的复制件:

```bash
git clone https://github.com/stabzs/Angular2-Toaster.git
```

在克隆目录中, 运行 :

```bash
npm install
```

运行角 AoT 编译器 :

```bash
npm run build
```

使用覆盖报告运行 Karma 测试实例 :

```bash
ng test angular2-toaster --code-coverage
```

# 经常被问到的问题

## 我得到这个 `No Toaster Containers have been initialized to receive toasts.` 错误

在尝试发布祝酒词之前,你没有适当地初始化一个烤面包机容器实例. 确定你已经完成了 `toaster-container` 组件和正在导入的组件 页:1 `ToasterModule` 与 `ToasterModule.forRoot()`。 。 。 .

## 从错误处理器跳出时不显示托拉斯

这个 `handleError` 函数被执行到角区域以外的大小。 你必须要 明确告诉Angular在一个区的背景范围内运行流行调用.

```TypeScript
export class AppErrorHandler implements ErrorHandler {
    constructor(
        private toasterService: ToasterService,
        private ngZone : NgZone) { }

    handleError(error: any): void {
        this.ngZone.run(() => {
            this.toasterService.pop('error', "Error", error);
        });  
    }
}
```

(看见这个伟大的) [堆叠过量流答覆](https://stackoverflow.com/questions/44975477/angular2-ng-toasty-errorhandler) 详情请查阅.

## 作者

[刺杀](https://npmcn.com/package/%40dkachko/angular2-toaster/stabzssoftware@gmail.com)

## 贷项

重写自 [https://github.com/jirikavi/AngularJS- Toaster 互联网档案馆的存檔,存档日期2013-12-02](https://github.com/jirikavi/AngularJS-Toaster)

灵感来自 [http://codevii.github.io/toastr/demo.html 互联网档案馆的存檔,存档日期2013-12-12](http://codeseven.github.io/toastr/demo.html)。 。 。 .

## 版权

版权所有 2016-2020 Stabzs.

## 许可证

这个项目根据麻省理工学院的许可证获得许可。 见 [自由主义](https://npmcn.com/package/%40dkachko/angular2-toaster/LICENSE) 需要更多信息的文件.

## 常见问题

### @dkachko/angular2-toaster 是什么？

基于 AngularJS- Toaster 的 Angular Toaster 通知库

### 如何安装 @dkachko/angular2-toaster？

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

### @dkachko/angular2-toaster 支持 TypeScript 吗？

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

### @dkachko/angular2-toaster 支持 ESM 还是 CommonJS？

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

### @dkachko/angular2-toaster 可以商用吗？

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

### @dkachko/angular2-toaster 的下载量有多少？

根据 npm 官方下载统计，@dkachko/angular2-toaster 在 2026/10/13 – 2026/11/11 这 30 天内被下载 7,481 次，日均约 249 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @dkachko/angular2-toaster 还在维护吗？

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

