基础输入与操作

标签输入 AsamInputTag

将自由输入转换为字符串标签,支持上限、分隔、拖动与折叠。

使用场景 ​

适合关键词、标签等自由文本集合。v-model 使用 string[] 或 undefined;按 trigger 指定的按键或 delimiter 分隔符生成标签。

新增、删除与数量上限 ​

默认按 Enter 添加标签。max 限制数量,clearable 提供整体清空;事件分别记录添加和删除的内容。

新增、删除与数量上限

展开源码

分隔、拖动与折叠 ​

逗号生成标签;saveOnBlur 保存失焦时尚未提交的文字。拖动改变顺序,折叠只改变显示。

分隔、拖动与折叠

展开源码

标签插槽与实例操作 ​

tag 插槽携带 value、index,prefix/suffix 用于输入装饰。实例公开 focus、blur。

标签插槽与实例操作

展开源码

四档密度与继承 ​

large / big / default / small 分别为四档密度。显式 size 覆盖继承;省略 size 时按组件、组、表单、ConfigProvider 到 default 解析。通过切换 provider 验证继承响应。

四档密度与继承

展开源码

ASAM 扩展与迁移 ​

四档密度属于 ASAM 扩展。自由字符串标签使用本组件;从固定选项选择多个值请使用 Select。迁移时将单行字符串模型改为标签数组;add-tag 可能为单字符串或字符串数组,不能只按单值处理。

标签编辑完整用法 ​

trigger 选择 Enter 或 Space,saveOnBlur 控制失焦保存。 完整说明。

触发、上限、折叠与拖拽

展开源码

readonly 和 disabled 原样委托原生。底层组件 的 readonly 模式仍可能响应 Backspace 删除标签并触发模型、change、remove-tag;ASAM 原样转发这些通知,不额外过滤。需要限制业务变更时,由应用控制父级模型的接受策略。

API 阅读方式 ​

下方 API 来自当前公开类型与运行默认值。默认值标为“未知 / 未声明”时,不代表 false、空值或未支持。省略 size 保留祖先上下文继承。省略 disabled 保留表单禁用继承;validateEvent 控制校验事件,不用 disabled 代替。

五入口表单继承与校验 ​

本完整 TS/JS 组合实际实例化单行、密码、多行、建议和标签五个入口。省略各入口 disabled 以继承表单状态;validateEvent 控制各自 change/blur 自动校验。切换禁用不会清空模型,关闭自动校验不影响编辑。五页注册同一组合源码的自包含副本,复制当前示例即可运行,无需从其他组件页补齐文件。

五入口表单继承与校验

展开源码

原生委托与事件记录 ​

下方完整 TS/JS 示例记录模型及事件顺序,并可切换禁用、只读和自动校验状态。 完整说明。

原生委托与事件记录

展开源码

API

属性 AsamInputTagProps

属性名说明类型默认值
modelValue输入值string[] | undefined—
max可添加标签的最大数量number | undefined—
tagType标签类型enum"primary" | "success" | "danger" | "warning" | "info"完整类型:"primary" | "success" | "danger" | "warning" | "info" | undefined—
tagEffect标签效果enum"light" | "dark" | "plain"完整类型:"light" | "dark" | "plain" | undefined—
effectTooltip 主题,内置了 dark / light 两种enum"light" | "dark"完整类型:(AsamInputTagProps)["effect"]—
trigger触发输入标签的按键enum"Enter" | "Space"完整类型:"Enter" | "Space" | undefined—
draggable是否可以拖动标签boolean | undefinedfalse
delimiter在匹配分隔符时添加标签string | RegExp | undefined—
size显式控件密度;省略时继承按钮组、表单和配置提供器。enum"large" | "big" | "default" | "small"完整类型:AsamControlSize | undefined—
clearable是否显示清除按钮boolean | undefinedfalse
clearIcon自定义清除图标(AsamInputTagProps)["clearIcon"]—
disabled是否禁用boolean | undefinedfalse
validateEvent是否触发表单验证boolean | undefinedfalse
readonly原生输入的只读状态。boolean | undefinedfalse
autofocus原生输入自动聚焦。boolean | undefinedfalse
id等价于原生 input id 属性string | undefined—
tabindex等价于原生 tabindex 属性string | number | undefined—
maxlength等价于原生 maxlength 属性string | number | undefined—
minlength等价于原生 minlength 属性string | number | undefined—
placeholder输入框占位文本string | undefined—
autocomplete原生输入自动完成;联合类型包含大量字面量时可能触发 TS2590,详见 Vue 问题 10514。string | undefined—
saveOnBlur当输入失去焦点时是否保存输入值boolean | undefinedfalse
collapseTags是否将多个标签折叠为文字。boolean | undefinedfalse
collapseTagsTooltip当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。要使用此功能,collapse-tags的值必须为trueboolean | undefinedfalse
maxCollapseTags需要显示的 Tag 的最大数量。只有当 collapse-tags 设置为 true 时才会生效。number | undefined—
ariaLabel原生 aria-label属性string | undefined—

事件 AsamInputTagEmits

属性名说明类型默认值
update:modelValue—[value?: string[] | undefined]—
change—[value?: string[] | undefined]—
input—[value: string]—
add-tag—[value: string | string[]]—
remove-tag—[value: string, index: number]—
drag-tag—[oldIndex: number, newIndex: number, value: string]—
focus—[event: FocusEvent]—
blur—[event: FocusEvent]—
clear—(AsamInputTagEmits)["clear"]—

插槽 AsamInputTagSlots

属性名说明类型默认值
prefix—(() => unknown) | undefined—
suffix—(() => unknown) | undefined—
tag—((props: { value: string; index: number; }) => unknown) | undefined—

实例方法与状态 AsamInputTagExpose

属性名说明类型默认值
focus—() => void—
blur—() => void—

用法与契约补充说明 ​

标签编辑完整用法 ​

trigger 选择 Enter 或 Space,saveOnBlur 控制失焦保存。max 限制标签数,draggable 允许重排并提供 oldIndex/newIndex/value。collapseTags 配合 maxCollapseTags 折叠,collapseTagsTooltip 通过悬停展示其余标签。clearIcon 配置清空标记;tagType/tagEffect/effect 配置标签及提示样式。只读保留显示,禁用阻止编辑;自定义 tag/prefix/suffix 见已有插槽示例。

原生委托与事件记录 ​

下方完整 TS/JS 示例记录模型及事件顺序,并可切换禁用、只读和自动校验状态。省略的基础参数使用原生 defaults;显式 undefined/null/false 原样传入,合法值范围见 API。四档 size 是 ASAM 的视觉桥接;Password 额外固定 type=password,并在省略 showPassword 时启用显隐入口。

参数与事件补充说明

参数与事件说明

modelValue

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)

max

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

tagType

必填:否;声明来源:ASAM 声明。

tagType 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"primary" / "success" / "danger" / "warning" / "info"

默认值与来源
未知 / 未声明

固定上游文档默认:info(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

tagEffect

必填:否;声明来源:ASAM 声明。

tagEffect 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"light" / "dark" / "plain"

默认值与来源
未知 / 未声明

固定上游文档默认:light(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

effect

必填:否;声明来源:ASAM 声明。

effect 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"light" / "dark"

默认值与来源
未知 / 未声明

固定上游文档默认:light(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:'light'(2.14.7;源码事实,未作为 ASAM 运行实测)

trigger

必填:否;声明来源:ASAM 声明。

trigger 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"Enter" / "Space"

默认值与来源
未知 / 未声明

固定上游文档默认:Enter(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:EVENT_CODE.enter(2.14.7;源码事实,未作为 ASAM 运行实测)

draggable

必填:否;声明来源:ASAM 声明。

draggable 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

delimiter

必填:否;声明来源:ASAM 声明。

delimiter 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

  • delimiter.exec: (string: string) => RegExpExecArray | null — 依赖声明

    使用正则表达式检索字符串,返回匹配结果数组。

    事件参数:(string: string): RegExpExecArray | null

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.test: (string: string) => boolean — 依赖声明

    返回布尔值,表示被检索字符串是否包含匹配模式。

    事件参数:(string: string): boolean

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.source: string — 依赖声明

    返回正则表达式模式文本的只读副本;regExp 参数为正则对象,可以使用变量或字面量。

  • delimiter.global: boolean — 依赖声明

    返回正则表达式 global(g)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.ignoreCase: boolean — 依赖声明

    返回正则表达式 ignoreCase(i)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.multiline: boolean — 依赖声明

    返回正则表达式 multiline(m)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.lastIndex: number — 依赖声明
  • delimiter.compile: (pattern: string, flags?: string) => RegExp — 依赖声明

    事件参数:(pattern: string, flags?: string | undefined): RegExp

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.flags: string — 依赖声明

    返回正则表达式标志的只读字符串,按 g(全局)、i(忽略大小写)、m(多行)、u(Unicode)、y(粘连)顺序排列;未设置标志时为空字符串。

  • delimiter.sticky: boolean — 依赖声明

    返回正则表达式 sticky(y)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.unicode: boolean — 依赖声明

    返回正则表达式 Unicode(u)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.dotAll: boolean — 依赖声明

    返回正则表达式 dotAll(s)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.hasIndices: boolean — 依赖声明

    返回正则表达式 hasIndices(d)标志的只读布尔状态,默认为 false。

    枚举:false / true

  • delimiter.__@match@8899: (string: string) => RegExpMatchArray | null — 依赖声明

    使用此正则表达式匹配字符串,并返回包含匹配结果的数组。

    事件参数:(string: string): RegExpMatchArray | null

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.__@replace@8901: { (string: string, replaceValue: string): string; (string: string, replacer: (substring: string, ...args: any[]) => string): string; } — 依赖声明

    使用此正则表达式替换字符串中的文本。

    事件参数:(string: string, replaceValue: string): string

    事件参数:(string: string, replacer: (substring: string, ...args: any[]) => string): string

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.__@search@8904: (string: string) => number — 依赖声明

    返回使用此正则表达式检索时,首个匹配子串的起始位置。

    事件参数:(string: string): number

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.__@split@8906: (string: string, limit?: number) => string[] — 依赖声明

    使用与此正则匹配的内容分隔原始字符串,返回子串数组;若含捕获组,每次匹配的捕获结果也会插入数组,包括 undefined 结果。

    事件参数:(string: string, limit?: number | undefined): string[]

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

  • delimiter.__@matchAll@8908: (str: string) => RegExpStringIterator<RegExpExecArray> — 依赖声明

    使用此正则表达式匹配字符串,并返回包含匹配结果的可迭代对象。

    事件参数:(str: string): RegExpStringIterator<RegExpExecArray>

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:''(2.14.7;源码事实,未作为 ASAM 运行实测)

size

必填:否;声明来源:ASAM 声明。

size 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"large" / "big" / "default" / "small"

clearable

必填:否;声明来源:ASAM 声明。

clearable 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

clearIcon

必填:否;声明来源:ASAM 声明。

clearIcon 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(props: any, ctx: Parameters<Extract<NonNullable<(AsamInputTagProps)["clearIcon"]>, (...args: never[]) => unknown>>[1]): any

  • clearIcon.__isFragment: undefined — 依赖声明
  • clearIcon.__isTeleport: undefined — 依赖声明
  • clearIcon.__isSuspense: undefined — 依赖声明
默认值与来源
未知 / 未声明

固定上游文档默认:CircleClose(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:CircleClose(2.14.7;源码事实,未作为 ASAM 运行实测)

disabled

必填:否;声明来源:ASAM 声明。

disabled 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:undefined(2.14.7;源码事实,未作为 ASAM 运行实测)

validateEvent

必填:否;声明来源:ASAM 声明。

validateEvent 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:true(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:true(2.14.7;源码事实,未作为 ASAM 运行实测)

readonly

必填:否;声明来源:ASAM 声明。

readonly 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

autofocus

必填:否;声明来源:ASAM 声明。

autofocus 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

id

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:undefined(2.14.7;源码事实,未作为 ASAM 运行实测)

tabindex

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:0(2.14.7;源码事实,未作为 ASAM 运行实测)

maxlength

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)

minlength

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码未声明 default(2.14.7;源码事实,未作为 ASAM 运行实测)

placeholder

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

autocomplete

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:off(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:'off'(2.14.7;源码事实,未作为 ASAM 运行实测)

saveOnBlur

必填:否;声明来源:ASAM 声明。

saveOnBlur 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:true(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:true(2.14.7;源码事实,未作为 ASAM 运行实测)

collapseTags

必填:否;声明来源:ASAM 声明。

collapseTags 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

collapseTagsTooltip

必填:否;声明来源:ASAM 声明。

collapseTagsTooltip 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(隐式 Boolean 默认;已安装组件)

固定上游文档默认:false(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

maxCollapseTags

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:1(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

固定上游源码默认表达式:1(2.14.7;源码事实,未作为 ASAM 运行实测)

ariaLabel

必填:否;声明来源:ASAM 声明。

默认值与来源
未知 / 未声明

固定上游文档默认:未声明(2.14.7;文档事实,实际默认以 ASAM 源码 / 安装包为准)

AsamInputTagProps 公开类型视图
ts
import type { Attrs } from 'vue';
import type { AsamInputTagProps, AsamControlSize } from '@asam-ui/ui';

type PublicMember<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ? T[K] : never : never;

// AsamInputTagProps
type PublicContract = {
	readonly "modelValue"?: string[] | undefined;
	readonly "max"?: number | undefined;
	readonly "tagType"?: "primary" | "success" | "danger" | "warning" | "info" | undefined;
	readonly "tagEffect"?: "light" | "dark" | "plain" | undefined;
	readonly "effect"?: (AsamInputTagProps)["effect"];
	readonly "trigger"?: "Enter" | "Space" | undefined;
	readonly "draggable"?: boolean | undefined;
	readonly "delimiter"?: string | RegExp | undefined;
	readonly "size"?: AsamControlSize | undefined;
	readonly "clearable"?: boolean | undefined;
	readonly "clearIcon"?: (AsamInputTagProps)["clearIcon"];
	readonly "disabled"?: boolean | undefined;
	readonly "validateEvent"?: boolean | undefined;
	readonly "readonly"?: boolean | undefined;
	readonly "autofocus"?: boolean | undefined;
	readonly "id"?: string | undefined;
	readonly "tabindex"?: string | number | undefined;
	readonly "maxlength"?: string | number | undefined;
	readonly "minlength"?: string | number | undefined;
	readonly "placeholder"?: string | undefined;
	readonly "autocomplete"?: string | undefined;
	readonly "saveOnBlur"?: boolean | undefined;
	readonly "collapseTags"?: boolean | undefined;
	readonly "collapseTagsTooltip"?: boolean | undefined;
	readonly "maxCollapseTags"?: number | undefined;
	readonly "ariaLabel"?: string | undefined;
};

参数与事件说明

update:modelValue

必填:是;声明来源:ASAM 声明。

change

必填:是;声明来源:ASAM 声明。

input

必填:是;声明来源:ASAM 声明。

add-tag

必填:是;声明来源:ASAM 声明。

remove-tag

必填:是;声明来源:ASAM 声明。

drag-tag

必填:是;声明来源:ASAM 声明。

focus

必填:是;声明来源:ASAM 声明。

blur

必填:是;声明来源:ASAM 声明。

clear

必填:是;声明来源:ASAM 声明。

AsamInputTagEmits 公开类型视图
ts
import type { AsamInputTagEmits } from '@asam-ui/ui';

// AsamInputTagEmits
type PublicContract = {
	"update:modelValue": [value?: string[] | undefined];
	"change": [value?: string[] | undefined];
	"input": [value: string];
	"add-tag": [value: string | string[]];
	"remove-tag": [value: string, index: number];
	"drag-tag": [oldIndex: number, newIndex: number, value: string];
	"focus": [event: FocusEvent];
	"blur": [event: FocusEvent];
	"clear": (AsamInputTagEmits)["clear"];
};

参数与事件说明

prefix

必填:否;声明来源:ASAM 声明。

prefix 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): unknown

suffix

必填:否;声明来源:ASAM 声明。

suffix 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): unknown

tag

必填:否;声明来源:ASAM 声明。

tag 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(props: { value: string; index: number; }): unknown

AsamInputTagSlots 公开类型视图
ts
import type { AsamInputTagSlots } from '@asam-ui/ui';

// AsamInputTagSlots
type PublicContract = {
	"prefix"?: (() => unknown) | undefined;
	"suffix"?: (() => unknown) | undefined;
	"tag"?: ((props: { value: string; index: number; }) => unknown) | undefined;
};

参数与事件说明

focus

必填:是;声明来源:ASAM 声明。

focus 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): void

blur

必填:是;声明来源:ASAM 声明。

blur 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): void

AsamInputTagExpose 公开类型视图
ts
import type { AsamInputTagExpose } from '@asam-ui/ui';

// AsamInputTagExpose
type PublicContract = {
	"focus": () => void;
	"blur": () => void;
};

搜索文档

Tab 选择结果 Enter 打开 Esc 关闭