This is an automated email from the ASF dual-hosted git repository.

gongchao pushed a commit to branch new-alarm
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/new-alarm by this push:
     new 9224d3160 [alarm] combine common labels and update ui (#2944)
9224d3160 is described below

commit 9224d31604b7566966ecccc819eb632f3c44adf3
Author: tomsun28 <[email protected]>
AuthorDate: Fri Jan 3 17:18:21 2025 +0800

    [alarm] combine common labels and update ui (#2944)
    
    Signed-off-by: tomsun28 <[email protected]>
---
 .../apache/hertzbeat/alert/dto/AlertDefineDTO.java |  4 -
 .../impl/AlertDefineExcelImExportServiceImpl.java  | 21 +----
 .../controller/NoticeConfigControllerTest.java     |  5 --
 .../AlertDefineExcelImExportServiceTest.java       | 10 ---
 .../common/constants/CommonConstants.java          |  5 ++
 .../hertzbeat/common/entity/manager/Bulletin.java  |  6 --
 .../entity/manager/JsonTagAttributeConverter.java  | 43 ----------
 .../manager/JsonTagListAttributeConverter.java     | 58 -------------
 .../common/entity/manager/StatusPageComponent.java | 13 ++-
 .../hertzbeat/common/entity/manager/TagItem.java   | 41 ----------
 .../apache/hertzbeat/common/util/JsonUtilTest.java | 21 ++---
 .../manager/component/status/CalculateStatus.java  | 58 ++++++-------
 .../app/layout/basic/widgets/notify.component.ts   |  2 +-
 web-app/src/app/pojo/Alert.ts                      | 38 ---------
 web-app/src/app/pojo/AlertDefine.ts                |  6 +-
 web-app/src/app/pojo/AlertSilence.ts               |  5 +-
 web-app/src/app/pojo/Monitor.ts                    |  3 -
 web-app/src/app/pojo/NoticeRule.ts                 |  1 +
 web-app/src/app/pojo/StatusPageComponent.ts        |  2 +-
 .../alert/alert-center/alert-center.component.html |  8 +-
 .../alert/alert-notice/alert-notice.component.html | 40 +--------
 .../alert-setting/alert-setting.component.html     | 53 ++++++------
 .../alert/alert-setting/alert-setting.component.ts | 16 ++--
 .../alert-silence/alert-silence.component.html     | 52 +-----------
 .../alert/alert-silence/alert-silence.component.ts | 85 -------------------
 .../app/routes/dashboard/dashboard.component.html  | 12 +--
 .../app/routes/dashboard/dashboard.component.ts    |  3 +-
 .../monitor/monitor-edit/monitor-edit.component.ts |  3 -
 .../monitor-form/monitor-form.component.html       | 20 +++--
 .../monitor/monitor-form/monitor-form.component.ts |  3 +-
 .../monitor-list/monitor-list.component.html       | 10 +--
 .../monitor/monitor-list/monitor-list.component.ts | 16 +++-
 .../monitor/monitor-new/monitor-new.component.ts   |  1 -
 web-app/src/app/routes/setting/setting.module.ts   |  6 +-
 .../routes/setting/status/status.component.html    | 22 +----
 .../app/routes/setting/status/status.component.ts  | 75 +++--------------
 .../app/routes/setting/tags/tags.component.html    | 95 +++++++---------------
 .../app/routes/setting/tags/tags.component.less    | 80 ++++++++++++++++++
 .../src/app/routes/setting/tags/tags.component.ts  | 13 ++-
 .../key-value-input/key-value-input.component.html |  6 +-
 .../key-value-input/key-value-input.component.less |  2 +-
 .../labels-input/labels-input.component.html       |  7 +-
 .../labels-input/labels-input.component.less       |  2 +-
 .../labels-input/labels-input.component.ts         | 12 ++-
 .../tags-select/tags-select.component.html         |  2 +-
 web-app/src/assets/i18n/en-US.json                 |  6 +-
 web-app/src/assets/i18n/zh-CN.json                 | 16 ++--
 web-app/src/assets/i18n/zh-TW.json                 |  6 +-
 48 files changed, 318 insertions(+), 696 deletions(-)

diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
index 0cf72feda..290f3781f 100644
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/AlertDefineDTO.java
@@ -21,9 +21,7 @@ import cn.afterturn.easypoi.excel.annotation.Excel;
 import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
-import java.util.List;
 import lombok.Data;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
 
 /**
  * Data transfer object for alert configuration
@@ -48,8 +46,6 @@ public class AlertDefineDTO {
     private Byte priority;
     @Excel(name = "Times")
     private Integer times;
-    @Excel(name = "Tags")
-    private List<TagItem> tags;
     @Excel(name = "Enable")
     private Boolean enable;
     @Excel(name = "RecoverNotice")
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
index 50540042e..4c2ba2e6f 100644
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertDefineExcelImExportServiceImpl.java
@@ -19,7 +19,6 @@ package org.apache.hertzbeat.alert.service.impl;
 
 import static 
org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.FILE_SUFFIX;
 import static 
org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.TYPE;
-import com.fasterxml.jackson.core.type.TypeReference;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -29,8 +28,6 @@ import java.util.Objects;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.alert.dto.AlertDefineDTO;
 import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
-import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.common.util.export.ExcelExportUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.ss.usermodel.Cell;
@@ -97,15 +94,6 @@ public class AlertDefineExcelImExportServiceImpl extends 
AlertDefineAbstractImEx
         }
     }
 
-    private List<TagItem> extractTagDataFromRow(Cell cell) {
-        String jsonStr = getCellValueAsString(cell);
-        if (StringUtils.hasText(jsonStr)) {
-            return JsonUtil.fromJson(jsonStr, new TypeReference<>() {
-            });
-        }
-        return null;
-    }
-
 
     private String getCellValueAsString(Cell cell) {
         if (cell == null) {
@@ -161,7 +149,7 @@ public class AlertDefineExcelImExportServiceImpl extends 
AlertDefineAbstractImEx
         alertDefineDTO.setExpr(getCellValueAsString(row.getCell(4)));
         alertDefineDTO.setPriority(getCellValueAsByte(row.getCell(5)));
         alertDefineDTO.setTimes(getCellValueAsInteger(row.getCell(6)));
-        alertDefineDTO.setTags(extractTagDataFromRow(row.getCell(7)));
+        // todo labels
         alertDefineDTO.setEnable(getCellValueAsBoolean(row.getCell(8)));
         alertDefineDTO.setRecoverNotice(getCellValueAsBoolean(row.getCell(9)));
         alertDefineDTO.setTemplate(getCellValueAsString(row.getCell(10)));
@@ -211,12 +199,7 @@ public class AlertDefineExcelImExportServiceImpl extends 
AlertDefineAbstractImEx
                 priorityCell.setCellStyle(cellStyle);
                 Cell timesCell = row.createCell(6);
                 timesCell.setCellValue(alertDefineDTO.getTimes());
-                Cell tagCell = row.createCell(7);
-                // get tags
-                List<TagItem> tagList = alertDefineDTO.getTags();
-                String tagValue = tagList == null || tagList.isEmpty() ? "" : 
JsonUtil.toJson(tagList);
-                tagCell.setCellValue(tagValue);
-                tagCell.setCellStyle(cellStyle);
+                // todo labels
                 Cell enableCell = row.createCell(8);
                 enableCell.setCellValue(alertDefineDTO.getEnable() != null
                         && alertDefineDTO.getEnable());
diff --git 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
index 59001a5fb..5ced52af7 100644
--- 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
+++ 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/NoticeConfigControllerTest.java
@@ -36,7 +36,6 @@ import org.apache.hertzbeat.common.constants.CommonConstants;
 import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
 import org.apache.hertzbeat.common.entity.alerter.NoticeRule;
 import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -66,10 +65,6 @@ class NoticeConfigControllerTest {
 
 
     public NoticeRule getNoticeRule() {
-        TagItem tagItem = new TagItem();
-        tagItem.setName("key1");
-        tagItem.setValue("value1");
-
         NoticeRule noticeRule = new NoticeRule();
         noticeRule.setId(87584674384L);
         noticeRule.setName("dispatch-1");
diff --git 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
index dd46b3e22..e775baea7 100644
--- 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
+++ 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertDefineExcelImExportServiceTest.java
@@ -27,7 +27,6 @@ import java.util.List;
 import org.apache.hertzbeat.alert.dto.AlertDefineDTO;
 import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
 import 
org.apache.hertzbeat.alert.service.impl.AlertDefineExcelImExportServiceImpl;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
 import org.apache.hertzbeat.common.util.export.ExcelExportUtils;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
@@ -91,9 +90,6 @@ public class AlertDefineExcelImExportServiceTest {
             assertTrue(alertDefineDTO.getPreset());
             assertEquals("expr1", alertDefineDTO.getExpr());
             assertEquals(10, alertDefineDTO.getTimes());
-            assertEquals(1, alertDefineDTO.getTags().size());
-            assertEquals("tag1", alertDefineDTO.getTags().get(0).getName());
-            assertEquals("value1", alertDefineDTO.getTags().get(0).getValue());
             assertTrue(alertDefineDTO.getEnable());
             assertTrue(alertDefineDTO.getRecoverNotice());
             assertEquals("template1", alertDefineDTO.getTemplate());
@@ -113,12 +109,6 @@ public class AlertDefineExcelImExportServiceTest {
         alertDefineDTO.setExpr("expr1");
         alertDefineDTO.setPriority((byte) 1);
         alertDefineDTO.setTimes(10);
-        List<TagItem> tags = new ArrayList<>();
-        TagItem tagItem = new TagItem();
-        tagItem.setName("tag1");
-        tagItem.setValue("value1");
-        tags.add(tagItem);
-        alertDefineDTO.setTags(tags);
         alertDefineDTO.setEnable(true);
         alertDefineDTO.setRecoverNotice(true);
         alertDefineDTO.setTemplate("template1");
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
index 062adacb4..f4bdb3cbe 100644
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/constants/CommonConstants.java
@@ -101,6 +101,11 @@ public interface CommonConstants {
      * Alarm severity label key
      */
     String LABEL_ALERT_SEVERITY = "severity";
+
+    /**
+     * Alarm severity fatal level
+     */
+    String LABEL_ALERT_FATAL = "fatal";
     
     /**
      * alarm severity emergency level
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
index b0d724dd8..b98082296 100644
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/Bulletin.java
@@ -74,12 +74,6 @@ public class Bulletin {
     @Convert(converter = JsonMapListAttributeConverter.class)
     private Map<String, List<String>> fields;
 
-    @Schema(description = "Tags(status:success,env:prod)", example = "{name: 
key1, value: value1}",
-            accessMode = READ_WRITE)
-    @Convert(converter = JsonTagListAttributeConverter.class)
-    @Column(length = 2048)
-    private List<TagItem> tags;
-
     @Schema(title = "The creator of this record", example = "tom", accessMode 
= READ_WRITE)
     @CreatedBy
     private String creator;
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagAttributeConverter.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagAttributeConverter.java
deleted file mode 100644
index b3e21460a..000000000
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagAttributeConverter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.common.entity.manager;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import jakarta.persistence.AttributeConverter;
-import jakarta.persistence.Converter;
-import org.apache.hertzbeat.common.util.JsonUtil;
-import org.springframework.stereotype.Component;
-
-/**
- * json str to tag item
- */
-@Converter
-@Component
-public class JsonTagAttributeConverter implements AttributeConverter<TagItem, 
String> {
-
-    @Override
-    public String convertToDatabaseColumn(TagItem attribute) {
-        return JsonUtil.toJson(attribute);
-    }
-
-    @Override
-    public TagItem convertToEntityAttribute(String dbData) {
-        TypeReference<TagItem> typeReference = new TypeReference<>() {};
-        return JsonUtil.fromJson(dbData, typeReference);
-    }
-}
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagListAttributeConverter.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagListAttributeConverter.java
deleted file mode 100644
index 50ea299ff..000000000
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/JsonTagListAttributeConverter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.common.entity.manager;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import jakarta.persistence.AttributeConverter;
-import jakarta.persistence.Converter;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import org.apache.hertzbeat.common.util.JsonUtil;
-import org.springframework.stereotype.Component;
-
-/**
- * json str to tag list
- */
-@Converter
-@Component
-public class JsonTagListAttributeConverter implements 
AttributeConverter<List<TagItem>, String> {
-
-    @Override
-    public String convertToDatabaseColumn(List<TagItem> attribute) {
-        return JsonUtil.toJson(attribute);
-    }
-
-    @Override
-    public List<TagItem> convertToEntityAttribute(String dbData) {
-        TypeReference<List<TagItem>> typeReference = new TypeReference<>() {};
-        List<TagItem> tagItems = JsonUtil.fromJson(dbData, typeReference);
-        if (tagItems == null) {
-            TypeReference<Map<String, String>> mapTypeReference = new 
TypeReference<>() {};
-            Map<String, String> map = JsonUtil.fromJson(dbData, 
mapTypeReference);
-            if (map != null) {
-                return map.entrySet().stream().map(entry -> new 
TagItem(entry.getKey(), entry.getValue())).collect(Collectors.toList());
-            } else {
-                return null;
-            }
-        } else {
-            return tagItems;
-        }
-
-    }
-}
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
index 5fe82560c..0bf6d57dd 100644
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/StatusPageComponent.java
@@ -17,7 +17,9 @@
 
 package org.apache.hertzbeat.common.entity.manager;
 
+import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.persistence.Column;
 import jakarta.persistence.Convert;
 import jakarta.persistence.Entity;
 import jakarta.persistence.EntityListeners;
@@ -27,10 +29,12 @@ import jakarta.persistence.Id;
 import jakarta.persistence.Table;
 import jakarta.validation.constraints.NotBlank;
 import java.time.LocalDateTime;
+import java.util.Map;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.apache.hertzbeat.common.entity.alerter.JsonMapAttributeConverter;
 import org.springframework.data.annotation.CreatedBy;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.LastModifiedBy;
@@ -64,10 +68,11 @@ public class StatusPageComponent {
 
     @Schema(title = "component desc", example = "TanCloud Gateway")
     private String description;
-    
-    @Schema(title = "component match single tag", example = 
"{labelName:labelValue}")
-    @Convert(converter = JsonTagAttributeConverter.class)
-    private TagItem tag;
+
+    @Schema(title = "component label", example = "{env:test}", accessMode = 
READ_WRITE)
+    @Convert(converter = JsonMapAttributeConverter.class)
+    @Column(length = 4096)
+    private Map<String, String> labels;
 
     @Schema(title = "calculate status method: 0-auto 1-manual", example = "0")
     private byte method;
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/TagItem.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/TagItem.java
deleted file mode 100644
index dbd9c8a4a..000000000
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/manager/TagItem.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.common.entity.manager;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * tag item
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Data
-public class TagItem {
-
-    @Schema(title = "Tag Name")
-    @NotBlank
-    private String name;
-
-    @Schema(title = "Tag Value")
-    private String value;
-
-}
diff --git 
a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
 
b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
index a43989b2c..8908485ca 100644
--- 
a/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
+++ 
b/hertzbeat-common/src/test/java/org/apache/hertzbeat/common/util/JsonUtilTest.java
@@ -20,13 +20,10 @@ package org.apache.hertzbeat.common.util;
 import static org.apache.hertzbeat.common.util.JsonUtil.isJsonStr;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import com.fasterxml.jackson.core.type.TypeReference;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
+import java.util.Map;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -36,23 +33,16 @@ class JsonUtilTest {
 
     @Test
     void toJson() {
-        List<TagItem> tagList = new ArrayList<>(4);
-        TagItem proTag = new TagItem("test", "pro");
-        tagList.add(proTag);
-        tagList.add(new TagItem("test", "dev"));
-
-        
assertEquals("[{\"name\":\"test\",\"value\":\"pro\"},{\"name\":\"test\",\"value\":\"dev\"}]",
-                JsonUtil.toJson(tagList));
+        Map<String, String> map = Map.of("test", "pro");
+        
+        assertEquals("{\"test\":\"pro\"}",
+                JsonUtil.toJson(map));
 
         assertNull(JsonUtil.toJson(null));
     }
 
     @Test
     void testFromJson() {
-        String jsonStr = 
"[{\"name\":\"test\",\"value\":\"pro\"},{\"name\":\"test\",\"value\":\"dev\"}]";
-        List<TagItem> tagItems = JsonUtil.fromJson(jsonStr, new 
TypeReference<>() {
-        });
-        assertEquals("[TagItem(name=test, value=pro), TagItem(name=test, 
value=dev)]", tagItems.toString());
         assertNull(JsonUtil.fromJson("", new TypeReference<>() {
         }));
         assertNull(JsonUtil.fromJson(null, new TypeReference<>() {
@@ -62,7 +52,6 @@ class JsonUtilTest {
         assertNull(JsonUtil.fromJson(" ", String.class));
         assertNull(JsonUtil.fromJson(" "));
         assertNull(JsonUtil.fromJson(null));
-        assertNotNull(JsonUtil.fromJson(jsonStr));
         assertNull(JsonUtil.fromJson("invalid"));
     }
 
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
index ec37ea966..94a0d7ca0 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/component/status/CalculateStatus.java
@@ -18,8 +18,6 @@
 package org.apache.hertzbeat.manager.component.status;
 
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import jakarta.persistence.criteria.JoinType;
-import jakarta.persistence.criteria.ListJoin;
 import jakarta.persistence.criteria.Predicate;
 import java.time.Duration;
 import java.time.Instant;
@@ -37,14 +35,11 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.hertzbeat.common.constants.CommonConstants;
 import org.apache.hertzbeat.common.entity.manager.Monitor;
 import org.apache.hertzbeat.common.entity.manager.StatusPageComponent;
 import org.apache.hertzbeat.common.entity.manager.StatusPageHistory;
 import org.apache.hertzbeat.common.entity.manager.StatusPageOrg;
-import org.apache.hertzbeat.common.entity.manager.Tag;
-import org.apache.hertzbeat.common.entity.manager.TagItem;
 import org.apache.hertzbeat.manager.config.StatusProperties;
 import org.apache.hertzbeat.manager.dao.MonitorDao;
 import org.apache.hertzbeat.manager.dao.StatusPageComponentDao;
@@ -104,37 +99,34 @@ public class CalculateStatus {
                     List<StatusPageComponent> pageComponentList = 
statusPageComponentDao.findByOrgId(orgId);
                     Set<Byte> stateSet = new HashSet<>(8);
                     for (StatusPageComponent component : pageComponentList) {
-                        byte state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
+                        byte state;
                         if (component.getMethod() == 
CommonConstants.STATUS_PAGE_CALCULATE_METHOD_MANUAL) {
                             state = component.getConfigState();
                         } else {
-                            TagItem tagItem = component.getTag();
-                            if (tagItem != null) {
-                                Specification<Monitor> specification = (root, 
query, criteriaBuilder) -> {
-                                    List<Predicate> andList = new 
ArrayList<>();
-                                    ListJoin<Monitor, Tag> tagJoin = root
-                                            .join(root.getModel()
-                                                    .getList("tags", 
Tag.class), JoinType.LEFT);
-                                    if 
(StringUtils.isNotBlank(tagItem.getValue())) {
-                                        
andList.add(criteriaBuilder.equal(tagJoin.get("name"), tagItem.getName()));
-                                        
andList.add(criteriaBuilder.equal(tagJoin.get("tagValue"), tagItem.getValue()));
-                                    } else {
-                                        
andList.add(criteriaBuilder.equal(tagJoin.get("name"), tagItem.getName()));
-                                    }
-                                    Predicate[] andPredicates = new 
Predicate[andList.size()];
-                                    Predicate andPredicate = 
criteriaBuilder.and(andList.toArray(andPredicates));
-                                    return 
query.where(andPredicate).getRestriction();
-                                };
-                                List<Monitor> monitorList = 
monitorDao.findAll(specification);
-                                state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN;
-                                for (Monitor monitor : monitorList) {
-                                    if (monitor.getStatus() == 
CommonConstants.MONITOR_DOWN_CODE) {
-                                        state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL;
-                                        break;
-                                    } else if (monitor.getStatus() == 
CommonConstants.MONITOR_UP_CODE) {
-                                        state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
-                                    }
-                                }   
+                            Map<String, String> labels = component.getLabels();
+                            if (labels == null || labels.isEmpty()) {
+                                continue;
+                            }
+                            Specification<Monitor> specification = (root, 
query, criteriaBuilder) -> {
+                                List<Predicate> predicates = new ArrayList<>();
+                                // create every label condition
+                                labels.forEach((key, value) -> {
+                                    String pattern = 
String.format("%%\"%s\":\"%s\"%%", key, value);
+                                    
predicates.add(criteriaBuilder.like(root.get("labels"), pattern));
+                                });
+
+                                // use or connect them
+                                return 
criteriaBuilder.or(predicates.toArray(new Predicate[0]));
+                            };
+                            List<Monitor> monitorList = 
monitorDao.findAll(specification);
+                            state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_UNKNOWN;
+                            for (Monitor monitor : monitorList) {
+                                if (monitor.getStatus() == 
CommonConstants.MONITOR_DOWN_CODE) {
+                                    state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_ABNORMAL;
+                                    break;
+                                } else if (monitor.getStatus() == 
CommonConstants.MONITOR_UP_CODE) {
+                                    state = 
CommonConstants.STATUS_PAGE_COMPONENT_STATE_NORMAL;
+                                }
                             }
                         }
                         stateSet.add(state);
diff --git a/web-app/src/app/layout/basic/widgets/notify.component.ts 
b/web-app/src/app/layout/basic/widgets/notify.component.ts
index 2a45af50a..b65ee7662 100644
--- a/web-app/src/app/layout/basic/widgets/notify.component.ts
+++ b/web-app/src/app/layout/basic/widgets/notify.component.ts
@@ -206,7 +206,7 @@ export class HeaderNotifyComponent implements OnInit, 
OnDestroy {
               let item = {
                 id: alert.id,
                 avatar: '/assets/img/notification.svg',
-                // title: 
`${alert.tags?.monitorName}--${this.i18nSvc.fanyi(`alert.priority.${alert.priority}`)}`,
+                // title: 
`${alert.tags?.monitorName}--${this.i18nSvc.fanyi(`alert.severity.${alert.severity}`)}`,
                 title: alert.content,
                 datetime: new Date(alert.activeAt).toLocaleString(),
                 color: 'blue',
diff --git a/web-app/src/app/pojo/Alert.ts b/web-app/src/app/pojo/Alert.ts
deleted file mode 100644
index b342ce8e7..000000000
--- a/web-app/src/app/pojo/Alert.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-export class Alert {
-  id!: number;
-  target!: string;
-  monitorId!: number;
-  monitorName!: string;
-  // alert level -- 0:high-emergency-red 1:medium-critical-orange 
2:low-warning-yellow
-  priority: number = 2;
-  // alert status-- 0-to be processed 1-not reached the threshold 2-recover 
3-processed
-  status!: number;
-  content!: string;
-  // alarm times
-  times!: number;
-  firstAlarmTime!: number;
-  lastAlarmTime!: number;
-  tags!: Record<string, string>;
-  gmtCreate!: number;
-  gmtUpdate!: number;
-  tmp!: any;
-}
diff --git a/web-app/src/app/pojo/AlertDefine.ts 
b/web-app/src/app/pojo/AlertDefine.ts
index 93b0021b8..bfaf6dbf0 100644
--- a/web-app/src/app/pojo/AlertDefine.ts
+++ b/web-app/src/app/pojo/AlertDefine.ts
@@ -17,8 +17,6 @@
  * under the License.
  */
 
-import { TagItem } from './NoticeRule';
-
 export class AlertDefine {
   id!: number;
   name!: string;
@@ -30,7 +28,9 @@ export class AlertDefine {
   // unit second
   period: number = 300;
   times: number = 3;
-  tags!: TagItem[];
+  // severity: info, warning, critical, emergency, fatal
+  labels!: Record<string, string>;
+  annotations!: Record<string, string>;
   enable: boolean = true;
   template!: string;
   creator!: string;
diff --git a/web-app/src/app/pojo/AlertSilence.ts 
b/web-app/src/app/pojo/AlertSilence.ts
index d5d75dce3..444f4f180 100644
--- a/web-app/src/app/pojo/AlertSilence.ts
+++ b/web-app/src/app/pojo/AlertSilence.ts
@@ -17,8 +17,6 @@
  * under the License.
  */
 
-import { TagItem } from './NoticeRule';
-
 export class AlertSilence {
   id!: number;
   name!: string;
@@ -26,8 +24,7 @@ export class AlertSilence {
   matchAll: boolean = true;
   type: number = 0;
   times!: number;
-  priorities!: number[];
-  tags!: TagItem[];
+  labels!: Record<string, string>;
   days!: number[];
   periodStart: Date = new Date();
   periodEnd: Date = new Date();
diff --git a/web-app/src/app/pojo/Monitor.ts b/web-app/src/app/pojo/Monitor.ts
index 649bb67e8..2f42c7053 100644
--- a/web-app/src/app/pojo/Monitor.ts
+++ b/web-app/src/app/pojo/Monitor.ts
@@ -17,8 +17,6 @@
  * under the License.
  */
 
-import { Tag } from './Tag';
-
 export class Monitor {
   id!: number;
   name!: string;
@@ -34,5 +32,4 @@ export class Monitor {
   modifier!: string;
   gmtCreate!: number;
   gmtUpdate!: number;
-  tags!: Tag[];
 }
diff --git a/web-app/src/app/pojo/NoticeRule.ts 
b/web-app/src/app/pojo/NoticeRule.ts
index 65585b7cc..efdf73831 100644
--- a/web-app/src/app/pojo/NoticeRule.ts
+++ b/web-app/src/app/pojo/NoticeRule.ts
@@ -27,6 +27,7 @@ export class NoticeRule {
   enable: boolean = true;
   // forward all or not
   filterAll: boolean = true;
+  labels!: Record<string, string>;
   // filter alert level
   priorities!: number[];
   tags!: TagItem[];
diff --git a/web-app/src/app/pojo/StatusPageComponent.ts 
b/web-app/src/app/pojo/StatusPageComponent.ts
index ac5552958..6afe004cb 100644
--- a/web-app/src/app/pojo/StatusPageComponent.ts
+++ b/web-app/src/app/pojo/StatusPageComponent.ts
@@ -24,7 +24,7 @@ export class StatusPageComponent {
   orgId!: number;
   name!: string;
   description!: string;
-  tag!: TagItem;
+  labels!: Record<string, string>;
   // calculate status method: 0-auto 1-manual
   method: number = 0;
   // config state when use manual method: 0-Normal 1-Abnormal 2-unknown
diff --git 
a/web-app/src/app/routes/alert/alert-center/alert-center.component.html 
b/web-app/src/app/routes/alert/alert-center/alert-center.component.html
index 8870e4e26..c141e8c60 100644
--- a/web-app/src/app/routes/alert/alert-center/alert-center.component.html
+++ b/web-app/src/app/routes/alert/alert-center/alert-center.component.html
@@ -40,10 +40,10 @@
       [(ngModel)]="filterPriority"
       (ngModelChange)="loadAlertsTable()"
     >
-      <nz-option [nzLabel]="'alert.priority.all' | i18n" 
[nzValue]="9"></nz-option>
-      <nz-option [nzLabel]="'alert.priority.2' | i18n" 
[nzValue]="2"></nz-option>
-      <nz-option [nzLabel]="'alert.priority.1' | i18n" 
[nzValue]="1"></nz-option>
-      <nz-option [nzLabel]="'alert.priority.0' | i18n" 
[nzValue]="0"></nz-option>
+      <nz-option [nzLabel]="'alert.severity.all' | i18n" 
[nzValue]="9"></nz-option>
+      <nz-option [nzLabel]="'alert.severity.2' | i18n" 
[nzValue]="2"></nz-option>
+      <nz-option [nzLabel]="'alert.severity.1' | i18n" 
[nzValue]="1"></nz-option>
+      <nz-option [nzLabel]="'alert.severity.0' | i18n" 
[nzValue]="0"></nz-option>
     </nz-select>
     <nz-select
       class="mobile-hide"
diff --git 
a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html 
b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
index f81609c4e..436b7a37d 100644
--- a/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
+++ b/web-app/src/app/routes/alert/alert-notice/alert-notice.component.html
@@ -436,45 +436,9 @@
         </nz-form-control>
       </nz-form-item>
       <nz-form-item *ngIf="!rule.filterAll">
-        <nz-form-label nzFor="tags" nzSpan="7">{{ 'alert.notice.rule.tag' | 
i18n }}</nz-form-label>
+        <nz-form-label nzFor="labels" nzSpan="7">{{ 'alert.notice.rule.tag' | 
i18n }}</nz-form-label>
         <nz-form-control nzSpan="12">
-          <nz-select
-            (nzOpenChange)="loadTagsOption()"
-            [(ngModel)]="filterTags"
-            [nzDisabled]="rule.filterAll"
-            [nzMaxTagCount]="5"
-            [nzOptions]="tagsOption"
-            id="tags"
-            name="tags"
-            nzAllowClear
-            nzMode="multiple"
-            [nzPlaceHolder]="'alert.notice.rule.tag.placeholder' | i18n"
-            nzShowSearch
-            required
-          >
-          </nz-select>
-        </nz-form-control>
-      </nz-form-item>
-      <nz-form-item *ngIf="!rule.filterAll">
-        <nz-form-label nzFor="priorities" nzSpan="7">{{ 
'alert.notice.rule.priority' | i18n }}</nz-form-label>
-        <nz-form-control nzSpan="12">
-          <nz-select
-            (ngModelChange)="onPrioritiesChange()"
-            [(ngModel)]="rule.priorities"
-            [nzDisabled]="rule.filterAll"
-            id="priorities"
-            name="priorities"
-            nzAllowClear
-            nzMode="multiple"
-            [nzPlaceHolder]="'alert.notice.rule.priority.placeholder' | i18n"
-            nzShowSearch
-            required
-          >
-            <nz-option [nzLabel]="'alert.priority.all' | i18n" 
[nzValue]="9"></nz-option>
-            <nz-option [nzLabel]="'alert.priority.0' | i18n" 
[nzValue]="0"></nz-option>
-            <nz-option [nzLabel]="'alert.priority.1' | i18n" 
[nzValue]="1"></nz-option>
-            <nz-option [nzLabel]="'alert.priority.2' | i18n" 
[nzValue]="2"></nz-option>
-          </nz-select>
+          <app-labels-input [(ngModel)]="rule.labels" name="labels" 
required></app-labels-input>
         </nz-form-control>
       </nz-form-item>
       <nz-form-item>
diff --git 
a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html 
b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
index 8b51f5bca..a0ed89183 100644
--- a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
+++ b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.html
@@ -96,7 +96,7 @@
       <th nzAlign="center" nzWidth="8%">{{ 'alert.setting.type' | i18n }}</th>
       <th nzAlign="center" nzWidth="24%">{{ 'alert.setting.expr' | i18n }}</th>
       <th nzAlign="center" nzWidth="20%">{{ 'alert.setting.template' | i18n 
}}</th>
-      <th nzAlign="center" nzWidth="8%">{{ 'alert.priority' | i18n }}</th>
+      <th nzAlign="center" nzWidth="8%">{{ 'alert.severity' | i18n }}</th>
       <th nzAlign="center" nzWidth="8%">{{ 'alert.setting.enable' | i18n 
}}</th>
       <th nzAlign="center" nzWidth="8%">{{ 'common.edit' | i18n }}</th>
     </tr>
@@ -120,17 +120,17 @@
       </td>
       <td nzAlign="center">{{ data.template }}</td>
       <td nzAlign="center">
-        <nz-tag *ngIf="data.priority == 0" nzColor="red">
+        <nz-tag *ngIf="severity == 'emergency'" nzColor="red">
           <i nz-icon nzType="bell" nzTheme="outline"></i>
-          <span>{{ 'alert.priority.0' | i18n }}</span>
+          <span>{{ 'alert.severity.0' | i18n }}</span>
         </nz-tag>
-        <nz-tag *ngIf="data.priority == 1" nzColor="orange">
+        <nz-tag *ngIf="severity == 'critical'" nzColor="orange">
           <i nz-icon nzType="bell" nzTheme="outline"></i>
-          <span>{{ 'alert.priority.1' | i18n }}</span>
+          <span>{{ 'alert.severity.1' | i18n }}</span>
         </nz-tag>
-        <nz-tag *ngIf="data.priority == 2" nzColor="yellow">
+        <nz-tag *ngIf="severity == 'warning'" nzColor="yellow">
           <i nz-icon nzType="bell" nzTheme="outline"></i>
-          <span>{{ 'alert.priority.2' | i18n }}</span>
+          <span>{{ 'alert.severity.2' | i18n }}</span>
         </nz-tag>
       </td>
       <td nzAlign="center">
@@ -481,19 +481,20 @@
         </nz-form-control>
       </nz-form-item>
       <nz-form-item>
-        <nz-form-label nzSpan="7" nzRequired="true" nzFor="priority" 
[nzTooltipTitle]="'alert.setting.priority.tip' | i18n">
-          {{ 'alert.priority' | i18n }}
+        <nz-form-label nzSpan="7" nzRequired="true" nzFor="severity" 
[nzTooltipTitle]="'alert.setting.priority.tip' | i18n">
+          {{ 'alert.severity' | i18n }}
         </nz-form-label>
         <nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' | 
i18n">
           <nz-select
-            [(ngModel)]="define.priority"
+            [(ngModel)]="severity"
+            (ngModelChange)="onSeverityChange()"
             [nzPlaceHolder]="'alert.notice.rule.priority.placeholder' | i18n"
-            name="priority"
-            id="priority"
+            name="severity"
+            id="severity"
           >
-            <nz-option [nzValue]="0" [nzLabel]="'alert.priority.0' | 
i18n"></nz-option>
-            <nz-option [nzValue]="1" [nzLabel]="'alert.priority.1' | 
i18n"></nz-option>
-            <nz-option [nzValue]="2" [nzLabel]="'alert.priority.2' | 
i18n"></nz-option>
+            <nz-option [nzValue]="'emergency'" [nzLabel]="'alert.severity.0' | 
i18n"></nz-option>
+            <nz-option [nzValue]="'critical'" [nzLabel]="'alert.severity.1' | 
i18n"></nz-option>
+            <nz-option [nzValue]="'warning'" [nzLabel]="'alert.severity.2' | 
i18n"></nz-option>
           </nz-select>
         </nz-form-control>
       </nz-form-item>
@@ -542,17 +543,17 @@
         </nz-form-control>
       </nz-form-item>
       <nz-form-item>
-        <nz-form-label nzSpan="7" [nzFor]="'tags'" 
[nzTooltipTitle]="'tag.bind.tip' | i18n">{{ 'tag.bind' | i18n }} 
</nz-form-label>
-        <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' | 
i18n">
-          <app-form-field
-            [item]="{
-              field: 'tags',
-              type: 'tags-selection'
-            }"
-            [extra]="{ tag_mode: 'closeable' }"
-            [name]="'tags'"
-            [(ngModel)]="define.tags"
-          />
+        <nz-form-label nzSpan="7" [nzFor]="'labels'" 
[nzTooltipTitle]="'label.bind.tip' | i18n">{{ 'label.bind' | i18n }} 
</nz-form-label>
+        <nz-form-control nzSpan="12">
+          <app-labels-input [(ngModel)]="define.labels" 
name="labels"></app-labels-input>
+        </nz-form-control>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label nzSpan="7" [nzFor]="'annotations'" 
[nzTooltipTitle]="'annotation.bind.tip' | i18n"
+          >{{ 'annotation.bind' | i18n }}
+        </nz-form-label>
+        <nz-form-control nzSpan="12">
+          <app-labels-input [(ngModel)]="define.annotations" 
name="annotations"></app-labels-input>
         </nz-form-control>
       </nz-form-item>
       <nz-form-item>
diff --git 
a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts 
b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
index 41f69ea16..b6b3cb1d7 100644
--- a/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
+++ b/web-app/src/app/routes/alert/alert-setting/alert-setting.component.ts
@@ -247,7 +247,6 @@ export class AlertSettingComponent implements OnInit {
     this.isSelectTypeModalVisible = false;
     this.define = new AlertDefine();
     this.define.type = type;
-    this.define.tags = [];
     this.userExpr = '';
     this.selectedMonitorIds = new Set<number>();
     // Set default period for periodic alert
@@ -469,6 +468,7 @@ export class AlertSettingComponent implements OnInit {
   currentMetrics: any[] = [];
   isExpr = false;
   userExpr!: string;
+  severity!: string;
 
   editAlertDefine(alertDefineId: number) {
     if (this.isLoadingEdit !== -1) return;
@@ -489,6 +489,9 @@ export class AlertSettingComponent implements OnInit {
         message => {
           if (message.code === 0) {
             this.define = message.data;
+            if (this.define.labels && this.define.labels['severity']) {
+              this.severity = this.define.labels['severity'];
+            }
             // Set default period for periodic alert if not set
             if (this.define.type === 'periodic' && !this.define.period) {
               this.define.period = 300;
@@ -512,10 +515,6 @@ export class AlertSettingComponent implements OnInit {
                 }
               });
             }
-            // Initialize tags array if undefined
-            if (this.define.tags == undefined) {
-              this.define.tags = [];
-            }
           } else {
             
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.monitor-fail'), 
message.msg);
           }
@@ -853,6 +852,13 @@ export class AlertSettingComponent implements OnInit {
     }
   }
 
+  onSeverityChange() {
+    if (!this.define.labels) {
+      this.define.labels = {};
+    }
+    this.define.labels['severity'] = this.severity;
+  }
+
   onManageModalCancel() {
     this.cascadeValues = [];
     this.isExpr = false;
diff --git 
a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html 
b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
index c57f5e7d0..68ccef7a7 100755
--- a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
+++ b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.html
@@ -79,7 +79,6 @@
       <th nzAlign="center" nzLeft nzWidth="3%" [(nzChecked)]="checkedAll" 
(nzCheckedChange)="onAllChecked($event)"></th>
       <th nzAlign="center" nzWidth="8%">{{ 'alert.silence.name' | i18n }}</th>
       <th nzAlign="center" nzWidth="14%">{{ 'alert.silence.type' | i18n }}</th>
-      <th nzAlign="center" nzWidth="14%">{{ 'alert.silence.tags' | i18n }}</th>
       <th nzAlign="center" nzWidth="8%">{{ 'alert.silence.times' | i18n }}</th>
       <th nzAlign="center" nzWidth="8%">{{ 'alert.silence.enable' | i18n 
}}</th>
       <th nzAlign="center" nzWidth="15%">{{ 'common.edit' | i18n }}</th>
@@ -101,16 +100,6 @@
           <span>{{ 'alert.silence.type.cyc' | i18n }}</span>
         </nz-tag>
       </td>
-      <td nzAlign="center" *ngIf="!data.matchAll">
-        <nz-tag nzColor="processing" style="margin-top: 2px" *ngFor="let tag 
of data.tags; let i = index">
-          {{ sliceTagName(tag) }}
-        </nz-tag>
-      </td>
-      <td nzAlign="center" *ngIf="data.matchAll">
-        <nz-tag nzColor="warning">
-          {{ 'alert.silence.match-all' | i18n }}
-        </nz-tag>
-      </td>
       <td nzAlign="center">
         <nz-tag nzColor="processing">
           <i nz-icon nzType="audio-muted" nzTheme="outline"></i>
@@ -182,46 +171,9 @@
         </nz-form-control>
       </nz-form-item>
       <nz-form-item *ngIf="!silence.matchAll">
-        <nz-form-label nzSpan="7" nzFor="tags" nzRequired="true">{{ 
'alert.silence.tags' | i18n }}</nz-form-label>
-        <nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' | 
i18n">
-          <nz-select
-            [(ngModel)]="matchTags"
-            [nzDisabled]="silence.matchAll"
-            (nzOpenChange)="loadTagsOption()"
-            [nzOptions]="tagsOption"
-            [nzMaxTagCount]="5"
-            [nzDropdownMatchSelectWidth]="false"
-            nzShowSearch
-            nzMode="multiple"
-            nzAllowClear
-            [nzPlaceHolder]="'alert.notice.rule.tag.placeholder' | i18n"
-            required
-            name="tags"
-            id="tags"
-          >
-          </nz-select>
-        </nz-form-control>
-      </nz-form-item>
-      <nz-form-item *ngIf="!silence.matchAll">
-        <nz-form-label nzSpan="7" nzFor="priorities" nzRequired="true">{{ 
'alert.silence.priority' | i18n }}</nz-form-label>
+        <nz-form-label nzSpan="7" nzFor="labels" nzRequired="true">{{ 
'alert.silence.labels' | i18n }}</nz-form-label>
         <nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' | 
i18n">
-          <nz-select
-            [(ngModel)]="silence.priorities"
-            [nzDisabled]="silence.matchAll"
-            (ngModelChange)="onPrioritiesChange()"
-            nzShowSearch
-            nzMode="multiple"
-            nzAllowClear
-            [nzPlaceHolder]="'alert.notice.rule.priority.placeholder' | i18n"
-            required
-            name="priorities"
-            id="priorities"
-          >
-            <nz-option [nzLabel]="'alert.priority.all' | i18n" 
[nzValue]="9"></nz-option>
-            <nz-option [nzLabel]="'alert.priority.0' | i18n" 
[nzValue]="0"></nz-option>
-            <nz-option [nzLabel]="'alert.priority.1' | i18n" 
[nzValue]="1"></nz-option>
-            <nz-option [nzLabel]="'alert.priority.2' | i18n" 
[nzValue]="2"></nz-option>
-          </nz-select>
+          <app-labels-input [(ngModel)]="silence.labels" name="labels" 
required></app-labels-input>
         </nz-form-control>
       </nz-form-item>
       <nz-form-item>
diff --git 
a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts 
b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
index b25f33577..baf32d84d 100644
--- a/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
+++ b/web-app/src/app/routes/alert/alert-silence/alert-silence.component.ts
@@ -29,7 +29,6 @@ import { finalize } from 'rxjs/operators';
 import { AlertSilence } from '../../../pojo/AlertSilence';
 import { TagItem } from '../../../pojo/NoticeRule';
 import { AlertSilenceService } from '../../../service/alert-silence.service';
-import { TagService } from '../../../service/tag.service';
 
 @Component({
   selector: 'app-alert-silence',
@@ -41,7 +40,6 @@ export class AlertSilenceComponent implements OnInit {
     private modal: NzModalService,
     private notifySvc: NzNotificationService,
     private alertSilenceService: AlertSilenceService,
-    private tagService: TagService,
     @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
   ) {}
 
@@ -208,8 +206,6 @@ export class AlertSilenceComponent implements OnInit {
   isManageModalOkLoading = false;
   isManageModalAdd = true;
   silence: AlertSilence = new AlertSilence();
-  searchTag!: string;
-  tagsOption: any[] = [];
   matchTags: string[] = [];
   silenceDates!: Date[];
   dayCheckOptions = [
@@ -269,19 +265,6 @@ export class AlertSilenceComponent implements OnInit {
             this.isManageModalVisible = true;
             this.isManageModalAdd = false;
             this.matchTags = [];
-            if (this.silence.tags != undefined) {
-              this.silence.tags.forEach(item => {
-                let tag = `${item.name}`;
-                if (item.value != undefined) {
-                  tag = `${tag}:${item.value}`;
-                }
-                this.matchTags.push(tag);
-                this.tagsOption.push({
-                  value: tag,
-                  label: tag
-                });
-              });
-            }
           } else {
             
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.edit-fail'), 
message.msg);
           }
@@ -301,22 +284,6 @@ export class AlertSilenceComponent implements OnInit {
       });
       return;
     }
-    this.silence.tags = [];
-    this.matchTags.forEach(tag => {
-      let tmp: string[] = tag.split(':');
-      let tagItem = new TagItem();
-      if (tmp.length == 1) {
-        tagItem.name = tmp[0];
-        this.silence.tags.push(tagItem);
-      } else if (tmp.length == 2) {
-        tagItem.name = tmp[0];
-        tagItem.value = tmp[1];
-        this.silence.tags.push(tagItem);
-      }
-    });
-    if (this.silence.priorities != undefined) {
-      this.silence.priorities = this.silence.priorities.filter(item => item != 
null && item != 9);
-    }
     if (this.silence.type === 0) {
       this.silence.periodStart = this.silenceDates[0];
       this.silence.periodEnd = this.silenceDates[1];
@@ -375,56 +342,4 @@ export class AlertSilenceComponent implements OnInit {
         );
     }
   }
-
-  onPrioritiesChange() {
-    if (this.silence.priorities != undefined) {
-      let isAll = false;
-      this.silence.priorities.forEach(item => {
-        if (item == 9) {
-          isAll = true;
-        }
-      });
-      if (isAll) {
-        this.silence.priorities = [9, 0, 1, 2];
-      }
-    }
-  }
-
-  loadTagsOption() {
-    let tagsInit$ = this.tagService.loadTags(this.searchTag, undefined, 0, 
1000).subscribe(
-      message => {
-        if (message.code === 0) {
-          let page = message.data;
-          this.tagsOption = [];
-          if (page.content != undefined) {
-            page.content.forEach(item => {
-              let tag = `${item.name}`;
-              if (item.tagValue != undefined) {
-                tag = `${tag}:${item.tagValue}`;
-              }
-              this.tagsOption.push({
-                value: tag,
-                label: tag
-              });
-            });
-          }
-        } else {
-          console.warn(message.msg);
-        }
-        tagsInit$.unsubscribe();
-      },
-      error => {
-        tagsInit$.unsubscribe();
-        console.error(error.msg);
-      }
-    );
-  }
-
-  sliceTagName(tag: any): string {
-    if (tag.value != undefined && tag.value.trim() != '') {
-      return `${tag.name}:${tag.value}`;
-    } else {
-      return tag.name;
-    }
-  }
 }
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.html 
b/web-app/src/app/routes/dashboard/dashboard.component.html
index a6e226f64..59e37eddd 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.html
+++ b/web-app/src/app/routes/dashboard/dashboard.component.html
@@ -398,17 +398,17 @@
         <nz-timeline nzMode="left">
           <nz-timeline-item *ngFor="let alert of alerts; let i = index" 
[nzLabel]="(alert.activeAt | date : 'YYYY-MM-dd HH:mm:ss')?.trim()">
             <p style="font-weight: 400">
-              <!--              <nz-tag *ngIf="alert.priority == 0" 
nzColor="red">-->
+              <!--              <nz-tag *ngIf="alert.severity == 0" 
nzColor="red">-->
               <!--                <i nz-icon nzType="bell" 
nzTheme="outline"></i>-->
-              <!--                <span>{{ 'alert.priority.0' | i18n 
}}</span>-->
+              <!--                <span>{{ 'alert.severity.0' | i18n 
}}</span>-->
               <!--              </nz-tag>-->
-              <!--              <nz-tag *ngIf="alert.priority == 1" 
nzColor="orange">-->
+              <!--              <nz-tag *ngIf="alert.severity == 1" 
nzColor="orange">-->
               <!--                <i nz-icon nzType="bell" 
nzTheme="outline"></i>-->
-              <!--                <span>{{ 'alert.priority.1' | i18n 
}}</span>-->
+              <!--                <span>{{ 'alert.severity.1' | i18n 
}}</span>-->
               <!--              </nz-tag>-->
-              <!--              <nz-tag *ngIf="alert.priority == 2" 
nzColor="yellow">-->
+              <!--              <nz-tag *ngIf="alert.severity == 2" 
nzColor="yellow">-->
               <!--                <i nz-icon nzType="bell" 
nzTheme="outline"></i>-->
-              <!--                <span>{{ 'alert.priority.2' | i18n 
}}</span>-->
+              <!--                <span>{{ 'alert.severity.2' | i18n 
}}</span>-->
               <!--              </nz-tag>-->
               <!--              <span>[{{ alert.tags.monitorName }}] </span>-->
               {{ alert.content }}
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.ts 
b/web-app/src/app/routes/dashboard/dashboard.component.ts
index 575fc6503..0c60e8688 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.ts
+++ b/web-app/src/app/routes/dashboard/dashboard.component.ts
@@ -27,7 +27,6 @@ import { NzMessageService } from 'ng-zorro-antd/message';
 import { fromEvent } from 'rxjs';
 import { finalize } from 'rxjs/operators';
 
-import { Alert } from '../../pojo/Alert';
 import { AppCount } from '../../pojo/AppCount';
 import { CollectorSummary } from '../../pojo/CollectorSummary';
 import { SingleAlert } from '../../pojo/SingleAlert';
@@ -299,7 +298,7 @@ export class DashboardComponent implements OnInit, 
OnDestroy {
       },
       xAxis: {
         type: 'category',
-        data: [this.i18nSvc.fanyi('alert.priority.2'), 
this.i18nSvc.fanyi('alert.priority.1'), this.i18nSvc.fanyi('alert.priority.0')]
+        data: [this.i18nSvc.fanyi('alert.severity.2'), 
this.i18nSvc.fanyi('alert.severity.1'), this.i18nSvc.fanyi('alert.severity.0')]
       },
       yAxis: {
         type: 'value'
diff --git 
a/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts 
b/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
index bd313128f..5eae28f83 100644
--- a/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-edit/monitor-edit.component.ts
@@ -92,9 +92,6 @@ export class MonitorEditComponent implements OnInit {
               });
               this.paramValueMap = paramValueMap;
             }
-            if (this.monitor.tags == undefined) {
-              this.monitor.tags = [];
-            }
           } else {
             console.warn(message.msg);
             this.notifySvc.error(this.i18nSvc.fanyi('monitors.not-found'), 
message.msg);
diff --git 
a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html 
b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
index d721ff16d..601688714 100644
--- a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
+++ b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.html
@@ -129,16 +129,18 @@
       </nz-form-item>
 
       <nz-form-item>
-        <nz-form-label nzSpan="7" [nzFor]="'tags'" 
[nzTooltipTitle]="'tag.bind.tip' | i18n">{{ 'tag.bind' | i18n }} 
</nz-form-label>
+        <nz-form-label nzSpan="7" [nzFor]="'labels'" 
[nzTooltipTitle]="'label.bind.tip' | i18n">{{ 'label.bind' | i18n }} 
</nz-form-label>
         <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' | 
i18n">
-          <app-form-field
-            [item]="{
-              field: 'tags',
-              type: 'tags-selection'
-            }"
-            [name]="'tags'"
-            [(ngModel)]="monitor.tags"
-          />
+          <app-labels-input [(ngModel)]="monitor.labels" 
name="labels"></app-labels-input>
+        </nz-form-control>
+      </nz-form-item>
+
+      <nz-form-item>
+        <nz-form-label nzSpan="7" [nzFor]="'annotation'" 
[nzTooltipTitle]="'annotation.bind.tip' | i18n"
+          >{{ 'annotation.bind' | i18n }}
+        </nz-form-label>
+        <nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' | 
i18n">
+          <app-labels-input [(ngModel)]="monitor.annotations" 
name="annotation"></app-labels-input>
         </nz-form-control>
       </nz-form-item>
 
diff --git 
a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts 
b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
index e08653f57..b301f713d 100644
--- a/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-form/monitor-form.component.ts
@@ -24,6 +24,7 @@ import { ALAIN_I18N_TOKEN } from '@delon/theme';
 import { NzNotificationService } from 'ng-zorro-antd/notification';
 
 import { Collector } from '../../../pojo/Collector';
+import { Monitor } from '../../../pojo/Monitor';
 import { Param } from '../../../pojo/Param';
 import { ParamDefine } from '../../../pojo/ParamDefine';
 
@@ -33,7 +34,7 @@ import { ParamDefine } from '../../../pojo/ParamDefine';
   styleUrls: ['./monitor-form.component.less']
 })
 export class MonitorFormComponent implements OnChanges {
-  @Input() monitor!: any;
+  @Input() monitor!: Monitor;
   @Input() grafanaDashboard!: any;
   @Input() loading!: boolean;
   @Input() loadingTip!: string;
diff --git 
a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html 
b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
index 35cba1480..84620da17 100644
--- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
+++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.html
@@ -150,7 +150,7 @@
       <th nzAlign="center" nzWidth="10%" nzColumnKey="status" 
[nzSortFn]="true">{{ 'monitor.status' | i18n }}</th>
       <th nzAlign="center" nzWidth="12%">{{ 'monitor.host' | i18n }}</th>
       <th nzAlign="center" nzWidth="10%">{{ 'monitor.app' | i18n }}</th>
-      <th nzAlign="center" nzWidth="21%">{{ 'tag' | i18n }}</th>
+      <th nzAlign="center" nzWidth="21%">{{ 'label' | i18n }}</th>
       <th nzAlign="center" nzWidth="14%" nzColumnKey="gmtUpdate" 
[nzSortFn]="true">{{ 'common.edit-time' | i18n }}</th>
       <th nzAlign="center" nzWidth="10%">{{ 'common.edit' | i18n }}</th>
     </tr>
@@ -201,11 +201,9 @@
         </a>
       </td>
       <td nzAlign="left">
-        <a *ngFor="let tag of data?.tags; let i = index" 
routerLink="/monitors" [queryParams]="{ tag: sliceTagName(tag) }">
-          <nz-tag style="margin-top: 2px" [nzColor]="tag?.color" 
class="hoverClass">
-            {{ sliceTagName(tag) }}
-          </nz-tag>
-        </a>
+        <nz-tag *ngFor="let label of data.labels | keyvalue" 
style="margin-top: 2px" [nzColor]="getLabelColor(label.key)">
+          {{ label.key }}:{{ label.value }}
+        </nz-tag>
       </td>
       <td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate : 
data.gmtCreate) | date : 'YYYY-MM-dd HH:mm:ss' }}</td>
       <td nzAlign="center">
diff --git 
a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts 
b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
index 1184a6bbd..79781adb7 100644
--- a/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-list/monitor-list.component.ts
@@ -594,5 +594,19 @@ export class MonitorListComponent implements OnInit, 
OnDestroy {
     );
   }
 
-  protected readonly sliceTagName = formatTagName;
+  getLabelColor(key: string): string {
+    const colors = ['blue', 'green', 'orange', 'purple', 'cyan'];
+    const index = Math.abs(this.hashString(key)) % colors.length;
+    return colors[index];
+  }
+
+  private hashString(str: string): number {
+    let hash = 0;
+    for (let i = 0; i < str.length; i++) {
+      const char = str.charCodeAt(i);
+      hash = (hash << 5) - hash + char;
+      hash = hash & hash;
+    }
+    return hash;
+  }
 }
diff --git 
a/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts 
b/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
index 03a20449a..e626afa4d 100644
--- a/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
+++ b/web-app/src/app/routes/monitor/monitor-new/monitor-new.component.ts
@@ -64,7 +64,6 @@ export class MonitorNewComponent implements OnInit {
     private collectorSvc: CollectorService
   ) {
     this.monitor = new Monitor();
-    this.monitor.tags = [];
     this.grafanaDashboard = new GrafanaDashboard();
   }
 
diff --git a/web-app/src/app/routes/setting/setting.module.ts 
b/web-app/src/app/routes/setting/setting.module.ts
index 08d23546e..108221d3b 100644
--- a/web-app/src/app/routes/setting/setting.module.ts
+++ b/web-app/src/app/routes/setting/setting.module.ts
@@ -26,8 +26,10 @@ import { NzCascaderModule } from 'ng-zorro-antd/cascader';
 import { NzCodeEditorModule } from 'ng-zorro-antd/code-editor';
 import { NzCollapseModule } from 'ng-zorro-antd/collapse';
 import { NzDividerModule } from 'ng-zorro-antd/divider';
+import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
 import { NzLayoutModule } from 'ng-zorro-antd/layout';
 import { NzListModule } from 'ng-zorro-antd/list';
+import { NzPaginationComponent } from 'ng-zorro-antd/pagination';
 import { NzRadioModule } from 'ng-zorro-antd/radio';
 import { NzSwitchModule } from 'ng-zorro-antd/switch';
 import { NzTagModule } from 'ng-zorro-antd/tag';
@@ -74,7 +76,9 @@ const COMPONENTS: Array<Type<void>> = [
     ClipboardModule,
     NzBadgeModule,
     NzRadioModule,
-    NzUploadComponent
+    NzUploadComponent,
+    NzPaginationComponent,
+    NzDropDownModule
   ],
   declarations: COMPONENTS
 })
diff --git a/web-app/src/app/routes/setting/status/status.component.html 
b/web-app/src/app/routes/setting/status/status.component.html
index 06962fd73..5aee1e288 100644
--- a/web-app/src/app/routes/setting/status/status.component.html
+++ b/web-app/src/app/routes/setting/status/status.component.html
@@ -194,11 +194,9 @@
             </nz-tag>
           </td>
           <td nzAlign="center">
-            <a routerLink="/monitors" [queryParams]="{ tag: 
sliceTagName(data.tag) }">
-              <nz-tag class="hoverClass">
-                {{ sliceTagName(data.tag) }}
-              </nz-tag>
-            </a>
+            <nz-tag *ngFor="let label of data.labels | keyvalue" 
style="margin-top: 2px" [nzColor]="getLabelColor(label.key)">
+              {{ label.key }}:{{ label.value }}
+            </nz-tag>
           </td>
           <td nzAlign="center">{{ data.gmtUpdate | date : 'YYYY-MM-dd 
HH:mm:ss' }}</td>
           <td nzAlign="center">
@@ -375,19 +373,7 @@
           'status.component.tag' | i18n
         }}</nz-form-label>
         <nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | 
i18n">
-          <nz-select
-            [(ngModel)]="matchTag"
-            (nzOpenChange)="loadTagsOption()"
-            [nzOptions]="tagsOption"
-            [nzMaxTagCount]="5"
-            [nzDropdownMatchSelectWidth]="false"
-            nzShowSearch
-            [nzPlaceHolder]="'alert.notice.rule.tag.placeholder' | i18n"
-            required
-            name="tag"
-            id="tag"
-          >
-          </nz-select>
+          <app-labels-input [(ngModel)]="currentStatusComponent.labels" 
name="sourceLabels" required></app-labels-input>
         </nz-form-control>
       </nz-form-item>
       <nz-form-item *ngIf="currentStatusComponent.method == 1">
diff --git a/web-app/src/app/routes/setting/status/status.component.ts 
b/web-app/src/app/routes/setting/status/status.component.ts
index 1258c2c00..d7128996b 100644
--- a/web-app/src/app/routes/setting/status/status.component.ts
+++ b/web-app/src/app/routes/setting/status/status.component.ts
@@ -26,13 +26,11 @@ import { NzNotificationService } from 
'ng-zorro-antd/notification';
 import { switchMap } from 'rxjs';
 
 import { Message } from '../../../pojo/Message';
-import { TagItem } from '../../../pojo/NoticeRule';
 import { StatusPageComponent } from '../../../pojo/StatusPageComponent';
 import { StatusPageIncident } from '../../../pojo/StatusPageIncident';
 import { StatusPageIncidentContent } from 
'../../../pojo/StatusPageIncidentContent';
 import { StatusPageOrg } from '../../../pojo/StatusPageOrg';
 import { StatusPageService } from '../../../service/status-page.service';
-import { TagService } from '../../../service/tag.service';
 
 @Component({
   selector: 'app-status',
@@ -44,7 +42,6 @@ export class StatusComponent implements OnInit {
     private notifySvc: NzNotificationService,
     private modal: NzModalService,
     private statusPageService: StatusPageService,
-    private tagService: TagService,
     @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
   ) {}
 
@@ -70,8 +67,6 @@ export class StatusComponent implements OnInit {
   isIncidentModalAdd: boolean = true;
 
   search!: string;
-  tagsOption: any[] = [];
-  matchTag: string = '';
 
   ngOnInit(): void {
     this.loadStatusPageConfig();
@@ -182,7 +177,6 @@ export class StatusComponent implements OnInit {
   onNewStatusComponent() {
     this.isComponentModalAdd = true;
     this.currentStatusComponent = new StatusPageComponent();
-    this.matchTag = '';
     this.currentComponentVisible = true;
   }
 
@@ -220,13 +214,6 @@ export class StatusComponent implements OnInit {
   onEditOneComponent(data: StatusPageComponent) {
     this.isComponentModalAdd = false;
     this.currentStatusComponent = { ...data };
-    if (this.currentStatusComponent.tag != undefined) {
-      this.matchTag = this.sliceTagName(this.currentStatusComponent.tag);
-      this.tagsOption.push({
-        value: this.matchTag,
-        label: this.matchTag
-      });
-    }
     this.currentComponentVisible = true;
   }
 
@@ -304,17 +291,6 @@ export class StatusComponent implements OnInit {
       });
       return;
     }
-    if (this.matchTag != undefined && this.matchTag.trim() != '') {
-      let tmp: string[] = this.matchTag.split(':');
-      let tagItem = new TagItem();
-      if (tmp.length == 1) {
-        tagItem.name = tmp[0];
-      } else if (tmp.length == 2) {
-        tagItem.name = tmp[0];
-        tagItem.value = tmp[1];
-      }
-      this.currentStatusComponent.tag = tagItem;
-    }
     if (this.statusOrg.id == undefined) {
       
this.notifySvc.warning(this.i18nSvc.fanyi('status.component.notify.need-org'), 
'');
       return;
@@ -479,36 +455,6 @@ export class StatusComponent implements OnInit {
     });
   }
 
-  loadTagsOption() {
-    let tagsInit$ = this.tagService.loadTags(undefined, undefined, 0, 
1000).subscribe(
-      message => {
-        if (message.code === 0) {
-          let page = message.data;
-          this.tagsOption = [];
-          if (page.content != undefined) {
-            page.content.forEach(item => {
-              let tag = `${item.name}`;
-              if (item.tagValue != undefined) {
-                tag = `${tag}:${item.tagValue}`;
-              }
-              this.tagsOption.push({
-                value: tag,
-                label: tag
-              });
-            });
-          }
-        } else {
-          console.warn(message.msg);
-        }
-        tagsInit$.unsubscribe();
-      },
-      error => {
-        tagsInit$.unsubscribe();
-        console.error(error.msg);
-      }
-    );
-  }
-
   getLatestIncidentContentMsg(incidents: StatusPageIncidentContent[]): string {
     if (incidents == undefined || incidents.length == 0) {
       return '';
@@ -533,14 +479,19 @@ export class StatusComponent implements OnInit {
     }
   }
 
-  sliceTagName(tag: TagItem): string {
-    if (tag == undefined) {
-      return '';
-    }
-    if (tag.value != undefined && tag.value.trim() != '') {
-      return `${tag.name}:${tag.value}`;
-    } else {
-      return tag.name;
+  getLabelColor(key: string): string {
+    const colors = ['blue', 'green', 'orange', 'purple', 'cyan'];
+    const index = Math.abs(this.hashString(key)) % colors.length;
+    return colors[index];
+  }
+
+  private hashString(str: string): number {
+    let hash = 0;
+    for (let i = 0; i < str.length; i++) {
+      const char = str.charCodeAt(i);
+      hash = (hash << 5) - hash + char;
+      hash = hash & hash;
     }
+    return hash;
   }
 }
diff --git a/web-app/src/app/routes/setting/tags/tags.component.html 
b/web-app/src/app/routes/setting/tags/tags.component.html
index 75683c288..9de6b5ca5 100644
--- a/web-app/src/app/routes/setting/tags/tags.component.html
+++ b/web-app/src/app/routes/setting/tags/tags.component.html
@@ -60,73 +60,38 @@
   </ng-template>
 </app-toolbar>
 
-<nz-table
-  #fixedTable
-  [nzData]="tags"
-  [nzPageIndex]="pageIndex"
-  [nzPageSize]="pageSize"
-  [nzTotal]="total"
-  nzFrontPagination="false"
-  [nzLoading]="tableLoading"
-  nzShowSizeChanger
-  [nzShowTotal]="rangeTemplate"
-  [nzPageSizeOptions]="[8, 15, 25]"
-  (nzQueryParams)="onTablePageChange($event)"
-  nzShowPagination="true"
-  [nzScroll]="{ x: '1240px' }"
->
-  <thead>
-    <tr>
-      <th nzAlign="center" nzLeft nzWidth="3%" [(nzChecked)]="checkedAll" 
(nzCheckedChange)="onAllChecked($event)"></th>
-      <th nzAlign="center" nzWidth="15%">{{ 'tag' | i18n }}</th>
-      <th nzAlign="center" nzWidth="15%">{{ 'tag.name' | i18n }}</th>
-      <th nzAlign="center" nzWidth="15%">{{ 'tag.value' | i18n }}</th>
-      <th nzAlign="center" nzWidth="15%">{{ 'tag.description' | i18n }}</th>
-      <th nzAlign="center" nzWidth="20%">{{ 'tag.update-time' | i18n }}</th>
-      <th nzAlign="center" nzWidth="17%">{{ 'common.edit' | i18n }}</th>
-    </tr>
-  </thead>
-  <tbody>
-    <tr *ngFor="let data of fixedTable.data">
-      <td nzAlign="center" nzLeft [nzChecked]="checkedTagIds.has(data.id)" 
(nzCheckedChange)="onItemChecked(data.id, $event)"></td>
-      <td nzAlign="center">
-        <a routerLink="/monitors" [queryParams]="{ tag: formatTagName(data) }">
-          <nz-tag [nzColor]="data.color" style="font-weight: bold; font-size: 
larger" class="hoverClass">
-            {{ formatTagName(data) }}
-          </nz-tag>
-        </a>
-      </td>
-      <td nzAlign="center">{{ data.name }}</td>
-      <td nzAlign="center">{{ data.tagValue }}</td>
-      <td nzAlign="center">{{ data.description }}</td>
-      <td nzAlign="center">{{ data.gmtUpdate | date : 'YYYY-MM-dd HH:mm:ss' 
}}</td>
-      <td nzAlign="center">
-        <div class="actions">
-          <button nz-button nzType="primary" (click)="onEditOneTag(data)" 
nz-tooltip [nzTooltipTitle]="'tag.edit' | i18n">
-            <i nz-icon nzType="edit" nzTheme="outline"></i>
-          </button>
-          <button nz-button nz-dropdown [nzDropdownMenu]="more_menu">
-            <span nz-icon nzType="ellipsis"></span>
-          </button>
-          <nz-dropdown-menu #more_menu="nzDropdownMenu">
-            <ul nz-menu>
-              <li nz-menu-item>
-                <button nz-button nzDanger (click)="onDeleteOneTag(data.id)">
-                  <i nz-icon nzType="delete" nzTheme="outline"></i>
-                  {{ 'common.button.delete' | i18n }}
-                </button>
-              </li>
-            </ul>
-          </nz-dropdown-menu>
+<div class="tag-cards-container">
+  <nz-row [nzGutter]="[12, 12]">
+    <nz-col [nzXs]="12" [nzSm]="8" [nzMd]="6" [nzLg]="4" *ngFor="let data of 
tags">
+      <nz-card [nzActions]="[editAction, deleteAction]" [nzBorderless]="true" 
class="tag-card">
+        <div class="tag-header">
+          <a routerLink="/monitors" [queryParams]="{ tag: formatTagName(data) 
}">
+            <nz-tag [nzColor]="data.color" class="tag-name">
+              {{ formatTagName(data) }}
+            </nz-tag>
+          </a>
         </div>
-      </td>
-    </tr>
-  </tbody>
-</nz-table>
 
-<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }} 
</ng-template>
+        <div class="tag-description" *ngIf="data.description">
+          {{ data.description }}
+        </div>
+
+        <ng-template #editAction>
+          <span nz-tooltip [nzTooltipTitle]="'tag.edit' | i18n" 
(click)="onEditOneTag(data)">
+            <i nz-icon nzType="edit" nzTheme="outline"></i>
+          </span>
+        </ng-template>
+
+        <ng-template #deleteAction>
+          <span nz-tooltip [nzTooltipTitle]="'common.button.delete' | i18n" 
(click)="onDeleteOneTag(data.id)">
+            <i nz-icon nzType="delete" nzTheme="outline"></i>
+          </span>
+        </ng-template>
+      </nz-card>
+    </nz-col>
+  </nz-row>
+</div>
 
-<!-- new or update TAG pop-up box -->
 <nz-modal
   [(nzVisible)]="isManageModalVisible"
   [nzTitle]="isManageModalAdd ? ('tag.new' | i18n) : ('tag.edit' | i18n)"
@@ -184,3 +149,5 @@
     </form>
   </div>
 </nz-modal>
+
+<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }} 
</ng-template>
diff --git a/web-app/src/app/routes/setting/tags/tags.component.less 
b/web-app/src/app/routes/setting/tags/tags.component.less
new file mode 100644
index 000000000..192b580e2
--- /dev/null
+++ b/web-app/src/app/routes/setting/tags/tags.component.less
@@ -0,0 +1,80 @@
+.tag-cards-container {
+  padding: 24px 0;
+
+  .tag-card {
+    transition: all 0.3s;
+    border-radius: 8px;
+    background: #fff;
+    
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+    }
+
+    ::ng-deep {
+      .ant-card-body {
+        padding: 12px;
+        min-height: 80px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+      }
+
+      .ant-card-actions {
+        border-radius: 0 0 8px 8px;
+        background: #fafafa;
+        border-top: 1px solid #f0f0f0;
+        min-height: 32px;
+        
+        > li {
+          margin: 0;
+          
+          > span {
+            padding: 4px 0;
+            
+            &:hover {
+              color: #1890ff;
+            }
+
+            i {
+              font-size: 14px;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .tag-header {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 8px;
+
+    .tag-name {
+      font-size: 16px;
+      padding: 4px 16px;
+      border-radius: 4px;
+      margin: 0;
+      font-weight: 500;
+      line-height: 1.4;
+      text-align: center;
+    }
+  }
+
+  .tag-description {
+    color: rgba(0, 0, 0, 0.65);
+    font-size: 14px;
+    line-height: 1.5;
+    margin: 0;
+    min-height: 32px;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    text-align: center;
+    width: 100%;
+  }
+} 
\ No newline at end of file
diff --git a/web-app/src/app/routes/setting/tags/tags.component.ts 
b/web-app/src/app/routes/setting/tags/tags.component.ts
index e3aee2fe4..928d800f7 100644
--- a/web-app/src/app/routes/setting/tags/tags.component.ts
+++ b/web-app/src/app/routes/setting/tags/tags.component.ts
@@ -32,7 +32,8 @@ import { formatTagName } from 
'../../../shared/utils/common-util';
 
 @Component({
   selector: 'app-setting-tags',
-  templateUrl: './tags.component.html'
+  templateUrl: './tags.component.html',
+  styleUrls: ['./tags.component.less']
 })
 export class SettingTagsComponent implements OnInit {
   @ViewChild('tagForm', { static: false }) tagForm: NgForm | undefined;
@@ -253,4 +254,14 @@ export class SettingTagsComponent implements OnInit {
   }
   // end 新增修改告警定义model
   protected readonly formatTagName = formatTagName;
+
+  onPageIndexChange(index: number): void {
+    this.pageIndex = index;
+    this.loadTagsTable();
+  }
+
+  onPageSizeChange(size: number): void {
+    this.pageSize = size;
+    this.loadTagsTable();
+  }
 }
diff --git 
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
 
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
index a366b9f0c..9b5b0823a 100644
--- 
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
+++ 
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.html
@@ -17,14 +17,14 @@
   ~ under the License.
 -->
 
-<div *ngFor="let item of keyValues; let i = index" nz-row>
+<div style="margin-bottom: 2px; margin-top: 2px" *ngFor="let item of 
keyValues; let i = index" nz-row>
   <div nz-col nzSpan="10">
     <input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key" 
(ngModelChange)="onChange()" />
   </div>
-  <div nz-col nzSpan="11">
+  <div nz-col nzSpan="10">
     <input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value" 
(ngModelChange)="onChange()" />
   </div>
-  <div nz-col nzSpan="3">
+  <div nz-col nzSpan="4">
     <i nz-icon nzType="plus-circle" class="dynamic-button" *ngIf="i === 0" 
(click)="addNew($event)"></i>
     <i nz-icon nzType="minus-circle" class="dynamic-button" 
(click)="removeCurrent(i, $event)"></i>
   </div>
diff --git 
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
 
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
index 6d29b59af..953c4f9f9 100644
--- 
a/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
+++ 
b/web-app/src/app/shared/components/key-value-input/key-value-input.component.less
@@ -8,5 +8,5 @@
 }
 
 .dynamic-button:hover {
-  font-size: 26px;
+  font-size: 18px;
 }
diff --git 
a/web-app/src/app/shared/components/labels-input/labels-input.component.html 
b/web-app/src/app/shared/components/labels-input/labels-input.component.html
index d1d0e7fc4..70c842dbd 100644
--- a/web-app/src/app/shared/components/labels-input/labels-input.component.html
+++ b/web-app/src/app/shared/components/labels-input/labels-input.component.html
@@ -17,11 +17,14 @@
   ~ under the License.
 -->
 
-<div *ngFor="let item of keyValues; let i = index" nz-row>
+<div style="margin-bottom: 2px; margin-top: 2px" *ngFor="let item of 
keyValues; let i = index" nz-row>
   <div nz-col nzSpan="10">
     <input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key" 
(ngModelChange)="emitChange()" />
   </div>
-  <div nz-col nzSpan="11">
+  <div style="text-align: center; font-weight: bolder" nz-col nzSpan="1">
+    <span>:</span>
+  </div>
+  <div nz-col nzSpan="10">
     <input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value" 
(ngModelChange)="emitChange()" />
   </div>
   <div nz-col nzSpan="3">
diff --git 
a/web-app/src/app/shared/components/labels-input/labels-input.component.less 
b/web-app/src/app/shared/components/labels-input/labels-input.component.less
index 6d29b59af..953c4f9f9 100644
--- a/web-app/src/app/shared/components/labels-input/labels-input.component.less
+++ b/web-app/src/app/shared/components/labels-input/labels-input.component.less
@@ -8,5 +8,5 @@
 }
 
 .dynamic-button:hover {
-  font-size: 26px;
+  font-size: 18px;
 }
diff --git 
a/web-app/src/app/shared/components/labels-input/labels-input.component.ts 
b/web-app/src/app/shared/components/labels-input/labels-input.component.ts
index ce5676af7..e1f88002d 100644
--- a/web-app/src/app/shared/components/labels-input/labels-input.component.ts
+++ b/web-app/src/app/shared/components/labels-input/labels-input.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, Output, OnInit, forwardRef } from 
'@angular/core';
+import { Component, Input, OnInit, forwardRef } from '@angular/core';
 import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
 
 interface KeyValuePair {
@@ -26,7 +26,7 @@ export class LabelsInputComponent implements OnInit, 
ControlValueAccessor {
 
   keyValues: KeyValuePair[] = [];
 
-  // ControlValueAccessor 接口实现
+  // ControlValueAccessor
   private onChange: any = () => {};
   private onTouched: any = () => {};
 
@@ -50,7 +50,7 @@ export class LabelsInputComponent implements OnInit, 
ControlValueAccessor {
   }
 
   setDisabledState(isDisabled: boolean): void {
-    // 如果需要处理禁用状态,可以在这里实现
+    // set disabled state here
   }
 
   ngOnInit(): void {
@@ -86,7 +86,11 @@ export class LabelsInputComponent implements OnInit, 
ControlValueAccessor {
         result[item.key] = item.value || '';
       }
     });
-    this.onChange(result);
+    if (Object.keys(result).length === 0 || Object.values(result).every(v => v 
=== '')) {
+      this.onChange(null);
+    } else {
+      this.onChange(result);
+    }
     this.onTouched();
   }
 }
diff --git 
a/web-app/src/app/shared/components/tags-select/tags-select.component.html 
b/web-app/src/app/shared/components/tags-select/tags-select.component.html
index ff8b3f7c5..c888672d3 100644
--- a/web-app/src/app/shared/components/tags-select/tags-select.component.html
+++ b/web-app/src/app/shared/components/tags-select/tags-select.component.html
@@ -36,7 +36,7 @@
 
 <nz-modal
   [(nzVisible)]="isManageModalVisible"
-  [nzTitle]="'tag.bind' | i18n"
+  [nzTitle]="'label.bind' | i18n"
   (nzOnCancel)="onManageModalCancel()"
   (nzOnOk)="onManageModalOk()"
   nzMaskClosable="false"
diff --git a/web-app/src/assets/i18n/en-US.json 
b/web-app/src/assets/i18n/en-US.json
index 64a7f0ed5..2174fea8e 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -225,7 +225,7 @@
   "alert.silence.type.once": "One Time Silence",
   "alert.silence.type.cyc": "Periodic Silence",
   "alert.silence.type": "Silence Type",
-  "alert.silence.tags": "Tag Match",
+  "alert.silence.labels": "Tag Match",
   "alert.silence.time": "Silence Period",
   "alert.silence.times": "Silenced Alerts Num",
   "alert.silence.enable": "Enable Silence",
@@ -572,8 +572,8 @@
   "tag.description": "Description",
   "tag.update-time": "Update Time",
   "tag.display": "Display",
-  "tag.bind": "Bind Tags",
-  "tag.bind.tip": "You can use tags for classification management.eg: assign 
tags to resources in production environment and test environment.",
+  "label.bind": "Bind Tags",
+  "label.bind.tip": "You can use tags for classification management.eg: assign 
tags to resources in production environment and test environment.",
   "tag.help": "Tags are everywhere in HertzBeat. We can apply tags in resource 
grouping, tag matching under rules and others. [Tag Manage] is used for unified 
management of tags, including adding, deleting, editing, etc. <br>You can use 
tags to classify and manage monitoring resources, such as binding labels for 
production and testing environments separately.",
   "tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/";,
   "plugin.help": "In HertzBeat, we can use the plugin mechanism to perform 
some other operations after the alarm except notification. Plugin management is 
used for unified management of plugins, including upload and enable/disable 
operations.<br>For example, you can use the plugin mechanism to execute 
specific scripts or SQL after the alarm occurs.",
diff --git a/web-app/src/assets/i18n/zh-CN.json 
b/web-app/src/assets/i18n/zh-CN.json
index 83098a1dc..7cdda7224 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -130,7 +130,7 @@
       "2": "已恢复",
       "3": "已处理"
     },
-    "priority": {
+    "severity": {
       "": "告警级别",
       "all": "全部级别",
       "0": "紧急告警",
@@ -226,7 +226,7 @@
   "alert.silence.type.once": "一次性静默",
   "alert.silence.type.cyc": "周期性静默",
   "alert.silence.type": "静默类型",
-  "alert.silence.tags": "匹配标签",
+  "alert.silence.labels": "匹配标签",
   "alert.silence.time": "静默时段",
   "alert.silence.times": "已静默告警数",
   "alert.silence.enable": "启用静默策略",
@@ -571,10 +571,14 @@
   "tag.description": "标签描述",
   "tag.update-time": "更新时间",
   "tag.display": "效果",
-  "tag.bind": "绑定标签",
-  "tag.bind.tip": "您可以使用标签进行监控资源的分类管理, 例如给资源分别绑定生产环境、测试环境的标签。",
+  "label": "标签",
+  "label.bind": "绑定标签",
+  "label.bind.tip": "您可以使用标签进行监控资源的分类管理, 例如给资源分别绑定生产环境、测试环境的标签。",
   "tag.help": "标签在 HertzBeat 
中无处不在,我们可以应用标签在资源分组,规则下的标签匹配等场景。标签管理用于对标签的统一管理维护,包含新增,删除,编辑等操作。<br>例如:您可以使用标签对监控资源进行分类管理,给资源分别绑定生产环境、测试环境的标签,在告警通知时通过标签匹配不同的通知人。",
   "tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/";,
+  "annotation": "注解",
+  "annotation.bind": "绑定注解",
+  "annotation.bind.tip": "您可以使用注解对实体信息进行标记,例如给资源绑定重要事件的注解。",
   "plugin.help": 
"在HertzBeat中,我们可以通过插件机制在告警后执行一些除通知以外的其他操作。插件管理用于对插件的统一管理,包括上传和,启用禁用等操作。<br>例如:您可以通过插件机制实现在告警出现后,执行特定的脚本或SQL等操作。",
   "plugin.help.link": "https://hertzbeat.apache.org/zh-cn/docs/help/plugin";,
   "plugin.upload": "上传插件",
@@ -824,7 +828,7 @@
   "alert.group-converge.group-labels.input": "输入自定义标签后按回车",
   "alert.group-converge.group-labels.placeholder": "请输入标签",
   "alert.group-converge.name.tip": "标识此分组策略的名称,需要唯一",
-  "alert.group-converge.group-labels.tip": "根据告警标签对告警消息进行分组,支持配置多个标签,如 
alertname、severity、instance 等",
+  "alert.group-converge.group-labels.tip": "根据告警标签Key对告警消息进行分组,支持配置多个标签Key,如 
alertname、severity、instance 等",
   "alert.group-converge.group-wait.tip": "新告警产生后等待时间,在此时间内收到的相同告警将被分组,默认30秒",
   "alert.group-converge.group-interval.tip": 
"发送分组告警通知的最小时间间隔,避免告警通知过于频繁,默认5分钟",
   "alert.group-converge.repeat-interval.tip": 
"重复告警的最小通知间隔,对于持续触发的告警,避免重复发送通知,默认4小时",
@@ -833,7 +837,7 @@
   "alert.inhibit.target_labels": "目标标签",
   "alert.inhibit.target_labels.tip": "匹配这些标签的告警将被抑制",
   "alert.inhibit.equal_labels": "相等标签",
-  "alert.inhibit.equal_labels.tip": "源告警和目标告警这些标签值必须相等,常用标签如 
alertname、instance、severity 等",
+  "alert.inhibit.equal_labels.tip": "源告警和目标告警这些标签Key和对应值必须相等,常用标签Key如 
alertname、instance、severity 等",
   "alert.inhibit.equal_labels.placeholder": "输入标签名称后按回车,或从下拉列表选择",
   "alert.inhibit.equal_labels.more": "还有 {{count}} 个标签",
   "alert.inhibit.equal_labels.common": "常用标签",
diff --git a/web-app/src/assets/i18n/zh-TW.json 
b/web-app/src/assets/i18n/zh-TW.json
index fcf5851de..7c8ac3464 100644
--- a/web-app/src/assets/i18n/zh-TW.json
+++ b/web-app/src/assets/i18n/zh-TW.json
@@ -238,7 +238,7 @@
   "alert.silence.type.once": "一次性靜默",
   "alert.silence.type.cyc": "週期性靜默",
   "alert.silence.type": "靜默類型",
-  "alert.silence.tags": "匹配標籤",
+  "alert.silence.labels": "匹配標籤",
   "alert.silence.time": "靜默時段",
   "alert.silence.times": "已靜默告警數",
   "alert.silence.enable": "啟用靜默策略",
@@ -582,8 +582,8 @@
   "tag.description": "標簽描述",
   "tag.update-time": "更新時間",
   "tag.display": "效果",
-  "tag.bind": "綁定標簽",
-  "tag.bind.tip": "您可以使用標簽進行監控資源的分類管理, 例如給資源分別綁定生産環境、測試環境的標簽。",
+  "label.bind": "綁定標簽",
+  "label.bind.tip": "您可以使用標簽進行監控資源的分類管理, 例如給資源分別綁定生産環境、測試環境的標簽。",
   "tag.help": "標簽在 HertzBeat 
中無處不在,我們可以應用標簽在資源分組,規則下的標簽匹配等場景。標簽管理用于對標簽的統壹管理維護,包含新增,刪除,編輯等操作。<br>例如:您可以使用標簽對監控資源進行分類管理,給資源分別綁定生産環境、測試環境的標簽,在告警通知時通過標簽匹配不同的通知人。",
   "tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/";,
   "plugin.help": 
"在HertzBeat中,我們可以透過外掛機制在警告後執行一些除通知以外的其他操作。外掛程式管理用於對外掛程式的統一管理,包括上傳和,啟用停用等操作。<br>例如:您可以透過外掛機制實現在警告出現後,執行特定的腳本或SQL等操作。",


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to