From 56baaba22535ab7a47676eef69a178173ec1af3a Mon Sep 17 00:00:00 2001 From: durant <826035498@qq.com> Date: Fri, 16 Aug 2024 11:11:37 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat(backend):=20=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20#6235?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/backend/db_meta/enums/comm.py | 8 +- .../migrations/0043_auto_20241015_2128.py | 84 +++++++++++++++ dbm-ui/backend/db_meta/models/cluster.py | 2 + dbm-ui/backend/db_meta/models/tag.py | 23 ++-- .../db_services/dbbase/resources/query.py | 13 ++- .../dbbase/resources/serializers.py | 1 + .../tag/__init__.py} | 0 dbm-ui/backend/db_services/tag/constants.py | 17 +++ dbm-ui/backend/db_services/tag/handlers.py | 100 ++++++++++++++++++ dbm-ui/backend/db_services/tag/serializers.py | 51 +++++++++ dbm-ui/backend/db_services/tag/urls.py | 19 ++++ dbm-ui/backend/db_services/tag/views.py | 91 ++++++++++++++++ .../tests/db_monitor/views/__init__.py | 10 ++ .../ticket/builders/mongodb/mongo_restore.py | 2 +- .../tendbcluster/tendb_fixpoint_rollback.py | 4 +- dbm-ui/backend/urls.py | 1 + dbm-ui/scripts/ci/code_quality.sh | 2 +- dbm-ui/scripts/ci/install.sh | 10 +- 18 files changed, 416 insertions(+), 22 deletions(-) create mode 100644 dbm-ui/backend/db_meta/migrations/0043_auto_20241015_2128.py rename dbm-ui/backend/{tests/db_monitor/views/__init_.py => db_services/tag/__init__.py} (100%) create mode 100644 dbm-ui/backend/db_services/tag/constants.py create mode 100644 dbm-ui/backend/db_services/tag/handlers.py create mode 100644 dbm-ui/backend/db_services/tag/serializers.py create mode 100644 dbm-ui/backend/db_services/tag/urls.py create mode 100644 dbm-ui/backend/db_services/tag/views.py create mode 100644 dbm-ui/backend/tests/db_monitor/views/__init__.py diff --git a/dbm-ui/backend/db_meta/enums/comm.py b/dbm-ui/backend/db_meta/enums/comm.py index 89a82b24f4..9a7b9f1660 100644 --- a/dbm-ui/backend/db_meta/enums/comm.py +++ b/dbm-ui/backend/db_meta/enums/comm.py @@ -26,14 +26,16 @@ class DBCCModule(str, StructuredEnum): class TagType(str, StructuredEnum): - CUSTOM = EnumField("custom", _("custom")) - SYSTEM = EnumField("system", _("system")) + CUSTOM = EnumField("custom", _("自定义标签")) + SYSTEM = EnumField("system", _("系统标签")) + BUILTIN = EnumField("builtin", _("内置标签")) class SystemTagEnum(str, StructuredEnum): """系统内置的tag名称""" - TEMPORARY = EnumField("temporary", _("temporary")) + TEMPORARY = EnumField("temporary", _("临时集群")) + RESOURCE_TAG = EnumField("resource", _("资源标签")) class RedisVerUpdateNodeType(str, StructuredEnum): diff --git a/dbm-ui/backend/db_meta/migrations/0043_auto_20241015_2128.py b/dbm-ui/backend/db_meta/migrations/0043_auto_20241015_2128.py new file mode 100644 index 0000000000..703ef66dbe --- /dev/null +++ b/dbm-ui/backend/db_meta/migrations/0043_auto_20241015_2128.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.25 on 2024-10-15 13:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("db_meta", "0042_auto_20240903_1138"), + ] + + operations = [ + migrations.AlterModelOptions( + name="bksubzone", + options={"verbose_name": "蓝鲸园区表(BKSubzone)", "verbose_name_plural": "蓝鲸园区表(BKSubzone)"}, + ), + migrations.AddField( + model_name="cluster", + name="tags", + field=models.ManyToManyField(blank=True, help_text="标签(外键)", to="db_meta.Tag"), + ), + migrations.AddField( + model_name="tag", + name="key", + field=models.CharField(default="", help_text="标签键", max_length=64), + ), + migrations.AddField( + model_name="tag", + name="value", + field=models.CharField(default="", help_text="标签值", max_length=255), + ), + migrations.AlterField( + model_name="spec", + name="cpu", + field=models.JSONField(help_text='cpu规格描述:{"min":1,"max":10}', null=True), + ), + migrations.AlterField( + model_name="spec", + name="device_class", + field=models.JSONField(help_text='实际机器机型: ["class1","class2"]', null=True), + ), + migrations.AlterField( + model_name="spec", + name="mem", + field=models.JSONField(help_text='mem规格描述:{"min":100,"max":1000}', null=True), + ), + migrations.AlterField( + model_name="spec", + name="qps", + field=models.JSONField(default=dict, help_text='qps规格描述:{"min": 1, "max": 100}'), + ), + migrations.AlterField( + model_name="spec", + name="storage_spec", + field=models.JSONField(help_text='存储磁盘需求配置:[{"mount_point":"/data","size":500,"type":"ssd"}]', null=True), + ), + migrations.AlterField( + model_name="tag", + name="bk_biz_id", + field=models.IntegerField(default=0, help_text="业务 ID"), + ), + migrations.AlterField( + model_name="tag", + name="type", + field=models.CharField( + choices=[("custom", "自定义标签"), ("system", "系统标签"), ("builtin", "内置标签")], + default="custom", + help_text="tag类型", + max_length=64, + ), + ), + migrations.AlterUniqueTogether( + name="tag", + unique_together={("bk_biz_id", "key", "value")}, + ), + migrations.RemoveField( + model_name="tag", + name="cluster", + ), + migrations.RemoveField( + model_name="tag", + name="name", + ), + ] diff --git a/dbm-ui/backend/db_meta/models/cluster.py b/dbm-ui/backend/db_meta/models/cluster.py index 5c380f687d..9794519139 100644 --- a/dbm-ui/backend/db_meta/models/cluster.py +++ b/dbm-ui/backend/db_meta/models/cluster.py @@ -44,6 +44,7 @@ ClusterSqlserverStatusFlags, ) from backend.db_meta.exceptions import ClusterExclusiveOperateException, DBMetaException +from backend.db_meta.models.tag import Tag from backend.db_services.version.constants import LATEST, PredixyVersion, TwemproxyVersion from backend.exceptions import ApiError from backend.flow.consts import DEFAULT_RIAK_PORT @@ -69,6 +70,7 @@ class Cluster(AuditedModel): max_length=128, help_text=_("容灾要求"), choices=AffinityEnum.get_choices(), default=AffinityEnum.NONE.value ) time_zone = models.CharField(max_length=16, default=DEFAULT_TIME_ZONE, help_text=_("集群所在的时区")) + tags = models.ManyToManyField(Tag, blank=True, help_text=_("标签(外键)")) class Meta: unique_together = [("bk_biz_id", "immute_domain", "cluster_type", "db_module_id"), ("immute_domain",)] diff --git a/dbm-ui/backend/db_meta/models/tag.py b/dbm-ui/backend/db_meta/models/tag.py index ecdd353bd5..aaacff121c 100644 --- a/dbm-ui/backend/db_meta/models/tag.py +++ b/dbm-ui/backend/db_meta/models/tag.py @@ -12,20 +12,29 @@ from django.utils.translation import ugettext_lazy as _ from backend.bk_web.models import AuditedModel +from backend.configuration.constants import PLAT_BIZ_ID from backend.db_meta.enums.comm import TagType -from backend.db_meta.models import Cluster class Tag(AuditedModel): - bk_biz_id = models.IntegerField(default=0) - name = models.CharField(max_length=64, default="", help_text=_("tag名称")) - type = models.CharField(max_length=64, help_text=_("tag类型"), choices=TagType.get_choices()) - cluster = models.ManyToManyField(Cluster, blank=True, help_text=_("关联集群")) + bk_biz_id = models.IntegerField(help_text=_("业务 ID"), default=0) + key = models.CharField(help_text=_("标签键"), default="", max_length=64) + value = models.CharField(help_text=_("标签值"), default="", max_length=255) + type = models.CharField( + help_text=_("tag类型"), max_length=64, choices=TagType.get_choices(), default=TagType.CUSTOM.value + ) class Meta: - unique_together = ["bk_biz_id", "name"] + unique_together = ["bk_biz_id", "key", "value"] @property def tag_desc(self): """仅返回tag的信息""" - return {"bk_biz_id": self.bk_biz_id, "name": self.name, "type": self.type} + return {"bk_biz_id": self.bk_biz_id, "key": self.key, "type": self.type} + + @classmethod + def get_or_create_system_tag(cls, key: str, value: str): + tag, created = cls.objects.get_or_create( + bk_biz_id=PLAT_BIZ_ID, key=key, value=value, type=TagType.SYSTEM.value + ) + return tag diff --git a/dbm-ui/backend/db_services/dbbase/resources/query.py b/dbm-ui/backend/db_services/dbbase/resources/query.py index 412796246d..efad1b7e89 100644 --- a/dbm-ui/backend/db_services/dbbase/resources/query.py +++ b/dbm-ui/backend/db_services/dbbase/resources/query.py @@ -213,7 +213,7 @@ def export_instance(cls, bk_biz_id: int, bk_host_ids: list) -> HttpResponse: @classmethod def get_temporary_cluster_info(cls, cluster, ticket_type): """如果当前集群是临时集群,则补充临时集群相关信息。""" - tags = [tag.name for tag in cluster.tag_set.all()] + tags = [tag.key for tag in cluster.tag_set.all()] if SystemTagEnum.TEMPORARY.value not in tags: return {} record = ClusterOperateRecord.objects.filter(cluster_id=cluster.id, ticket__ticket_type=ticket_type).first() @@ -401,8 +401,14 @@ def _list_clusters( for param in filter_params_map: if query_params.get(param): query_filters &= filter_params_map[param] + + # 对标签进行过滤,标签“且”查询,需以追加 filter 的方式实现 + cluster_queryset = Cluster.objects.filter(query_filters) + for tag_id in query_params.get("tag_ids", "").split(","): + cluster_queryset = cluster_queryset.filter(tags__id=tag_id) + # 一join多的一方会有重复的数据,去重 - cluster_queryset = Cluster.objects.filter(query_filters).distinct() + cluster_queryset = cluster_queryset.distinct() # 实例筛选 def filter_instance_func(_query_params, _cluster_queryset, _proxy_queryset, _storage_queryset): @@ -466,7 +472,7 @@ def _filter_cluster_hook( Prefetch("proxyinstance_set", queryset=proxy_queryset.select_related("machine"), to_attr="proxies"), Prefetch("storageinstance_set", queryset=storage_queryset.select_related("machine"), to_attr="storages"), Prefetch("clusterentry_set", to_attr="entries"), - "tag_set", + "tags", ) # 由于对 queryset 切片工作方式的模糊性,这里的values可能会获得非预期的排序,所以不要在切片后用values # cluster_ids = list(cluster_queryset.values_list("id", flat=True)) @@ -567,6 +573,7 @@ def _to_cluster_representation( "updater": cluster.updater, "create_at": datetime2str(cluster.create_at), "update_at": datetime2str(cluster.update_at), + "tags": [{tag.key: tag.value} for tag in cluster.tags.all()], } @classmethod diff --git a/dbm-ui/backend/db_services/dbbase/resources/serializers.py b/dbm-ui/backend/db_services/dbbase/resources/serializers.py index 9a7860af51..7effc153c0 100644 --- a/dbm-ui/backend/db_services/dbbase/resources/serializers.py +++ b/dbm-ui/backend/db_services/dbbase/resources/serializers.py @@ -32,6 +32,7 @@ class ListResourceSLZ(serializers.Serializer): bk_cloud_id = serializers.CharField(required=False, help_text=_("管控区域")) cluster_type = serializers.CharField(required=False, help_text=_("集群类型")) ordering = serializers.CharField(required=False, help_text=_("排序字段,非必填")) + tag_ids = serializers.CharField(required=False, help_text=_("标签")) class ListMySQLResourceSLZ(ListResourceSLZ): diff --git a/dbm-ui/backend/tests/db_monitor/views/__init_.py b/dbm-ui/backend/db_services/tag/__init__.py similarity index 100% rename from dbm-ui/backend/tests/db_monitor/views/__init_.py rename to dbm-ui/backend/db_services/tag/__init__.py diff --git a/dbm-ui/backend/db_services/tag/constants.py b/dbm-ui/backend/db_services/tag/constants.py new file mode 100644 index 0000000000..03be4ecf3b --- /dev/null +++ b/dbm-ui/backend/db_services/tag/constants.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +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. +""" +from django.utils.translation import gettext_lazy as _ + +from blue_krill.data_types.enum import EnumField, StructuredEnum + + +class TagResourceType(str, StructuredEnum): + DB_RESOURCE = EnumField("db_resource", _("资源池")) diff --git a/dbm-ui/backend/db_services/tag/handlers.py b/dbm-ui/backend/db_services/tag/handlers.py new file mode 100644 index 0000000000..8a0a7aa794 --- /dev/null +++ b/dbm-ui/backend/db_services/tag/handlers.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +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. +""" +from typing import Dict, List + +from django.db.models import ManyToManyRel +from django.utils.translation import gettext_lazy as _ + +from backend.db_meta.models import Tag +from backend.db_services.tag.constants import TagResourceType +from backend.exceptions import ValidationError + + +class TagHandler: + """标签的操作类""" + + def batch_set_tags(self, tag_ids: List[int]): + """ + 给资源批量设置标签 + """ + # 1. 判断标签中 key 是否允许多值 + + # 2. 批量设置标签 + pass + + @classmethod + def delete_tags(cls, bk_biz_id: int, ids: List[int]): + """ + 删除标签 + """ + # 1. 检查标签是否被引用 + related_resources = cls.query_related_resources(ids) + for related_resource in related_resources: + if related_resource["count"] > 0: + raise ValidationError(_("标签被引用,无法删除")) + + # 2. 批量删除标签 + Tag.objects.filter(bk_biz_id=bk_biz_id, id__in=ids).delete() + + @classmethod + def query_related_resources(cls, ids: List[int], resource_type: str = None): + """ + 查询关联资源 + """ + # 1. 查询外键关联资源 + data = [] + for tag_id in ids: + info = {"id": tag_id, "related_resources": []} + for field in Tag._meta.get_fields(): + if isinstance(field, ManyToManyRel) and (field.name == resource_type or resource_type is None): + related_objs = field.related_model.objects.prefetch_related("tags").filter(tags__id=tag_id) + info["related_resources"].append( + { + "resource_type": field.name, + "count": related_objs.count(), + } + ) + + # 2. 查询第三方服务关联资源(如资源池、后续可能扩展的别的服务) + if resource_type == TagResourceType.DB_RESOURCE.value or resource_type is None: + info["related_resources"].append( + { + "resource_type": TagResourceType.DB_RESOURCE.value, + # TODO 请求资源池接口得到统计数量 + "count": 0, + } + ) + data.append(info) + return data + + @classmethod + def batch_create(cls, bk_biz_id: int, tags: List[Dict[str, str]], creator: str = ""): + """ + 批量创建标签 + """ + duplicate_tags = cls.verify_duplicated(bk_biz_id, tags) + if duplicate_tags: + raise ValidationError(_("检查到重复的标签"), data=duplicate_tags) + + tag_models = [Tag(bk_biz_id=bk_biz_id, key=tag["key"], value=tag["value"], creator=creator) for tag in tags] + Tag.objects.bulk_create(tag_models) + + @classmethod + def verify_duplicated(cls, bk_biz_id: int, tags: List[Dict[str, str]]) -> List[Dict[str, str]]: + """ + 检查标签是否重复 + """ + biz_tags = [f"{tag.key}:{tag.value}" for tag in Tag.objects.filter(bk_biz_id=bk_biz_id)] + duplicate_tags = [] + for tag in tags: + if f'{tag["key"]}:{tag["value"]}' in biz_tags: + duplicate_tags.append(tag) + return duplicate_tags diff --git a/dbm-ui/backend/db_services/tag/serializers.py b/dbm-ui/backend/db_services/tag/serializers.py new file mode 100644 index 0000000000..564c001e98 --- /dev/null +++ b/dbm-ui/backend/db_services/tag/serializers.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +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. +""" + +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from backend.bk_web.serializers import AuditedSerializer +from backend.db_meta.models import Tag + + +class TagSerializer(AuditedSerializer, serializers.ModelSerializer): + """ + 标签序列化器 + """ + + class Meta: + model = Tag + fields = "__all__" + + +class BatchCreateTagsSerializer(serializers.Serializer): + class CreateTagSerializer(serializers.Serializer): + key = serializers.CharField(help_text=_("标签key")) + value = serializers.CharField(help_text=_("标签value")) + + bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) + tags = serializers.ListField(child=CreateTagSerializer()) + + +class UpdateTagSerializer(serializers.Serializer): + bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) + id = serializers.IntegerField(help_text=_("标签 ID")) + value = serializers.CharField(help_text=_("标签value")) + + +class DeleteTagsSerializer(serializers.Serializer): + bk_biz_id = serializers.IntegerField(help_text=_("业务ID")) + ids = serializers.ListSerializer(child=serializers.IntegerField(help_text=_("标签 ID")), help_text=_("标签 ID 列表")) + + +class QueryRelatedResourceSerializer(serializers.Serializer): + ids = serializers.ListSerializer(child=serializers.IntegerField(help_text=_("标签 ID")), help_text=_("标签 ID 列表")) + resource_type = serializers.CharField(help_text=_("资源类型"), required=False) diff --git a/dbm-ui/backend/db_services/tag/urls.py b/dbm-ui/backend/db_services/tag/urls.py new file mode 100644 index 0000000000..a0ebbfe221 --- /dev/null +++ b/dbm-ui/backend/db_services/tag/urls.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +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. +""" + +from rest_framework.routers import DefaultRouter + +from . import views + +routers = DefaultRouter(trailing_slash=True) +routers.register("", views.TagViewSet, basename="tag") + +urlpatterns = routers.urls diff --git a/dbm-ui/backend/db_services/tag/views.py b/dbm-ui/backend/db_services/tag/views.py new file mode 100644 index 0000000000..a79a98a6c9 --- /dev/null +++ b/dbm-ui/backend/db_services/tag/views.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +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. +""" +from django.utils.decorators import method_decorator +from django.utils.translation import ugettext as _ +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework import filters +from rest_framework.decorators import action +from rest_framework.response import Response + +from backend.bk_web.swagger import common_swagger_auto_schema +from backend.bk_web.viewsets import AuditedModelViewSet +from backend.db_meta.models import Tag +from backend.db_services.tag import serializers +from backend.db_services.tag.handlers import TagHandler + +SWAGGER_TAG = _("标签") + + +@method_decorator( + name="partial_update", + decorator=common_swagger_auto_schema( + operation_summary=_("更新标签"), tags=[SWAGGER_TAG], request_body=serializers.UpdateTagSerializer() + ), +) +@method_decorator( + name="list", + decorator=common_swagger_auto_schema(operation_summary=_("查询标签列表"), tags=[SWAGGER_TAG]), +) +class TagViewSet(AuditedModelViewSet): + """ + 标签视图 + """ + + queryset = Tag.objects.all() + serializer_class = serializers.TagSerializer + filter_backends = [filters.SearchFilter, DjangoFilterBackend] + filter_fields = ("bk_biz_id", "key", "value", "type") + + @common_swagger_auto_schema( + operation_summary=_("查询标签关联资源"), request_body=serializers.QueryRelatedResourceSerializer(), tags=[SWAGGER_TAG] + ) + @action(methods=["POST"], detail=False, serializer_class=serializers.QueryRelatedResourceSerializer) + def related_resources(self, request, *args, **kwargs): + """ + 查询标签关联资源 + """ + validated_data = self.params_validate(self.get_serializer_class()) + return Response(TagHandler.query_related_resources(validated_data["ids"], validated_data.get("resource_type"))) + + @common_swagger_auto_schema( + operation_summary=_("批量创建标签"), request_body=serializers.BatchCreateTagsSerializer(), tags=[SWAGGER_TAG] + ) + @action(methods=["POST"], detail=False, serializer_class=serializers.BatchCreateTagsSerializer) + def batch_create(self, request, *args, **kwargs): + """ + 创建标签 + """ + validated_data = self.params_validate(self.get_serializer_class()) + return Response( + TagHandler.batch_create(validated_data["bk_biz_id"], validated_data["tags"], request.user.username) + ) + + @common_swagger_auto_schema( + operation_summary=_("批量删除标签"), request_body=serializers.DeleteTagsSerializer(), tags=[SWAGGER_TAG] + ) + @action(methods=["DELETE"], detail=False, serializer_class=serializers.DeleteTagsSerializer) + def batch_delete(self, request, *args, **kwargs): + """ + 删除标签 + """ + validated_data = self.params_validate(self.get_serializer_class()) + return Response(TagHandler.delete_tags(validated_data["bk_biz_id"], validated_data["ids"])) + + @common_swagger_auto_schema( + operation_summary=_("校验标签是否重复"), request_body=serializers.BatchCreateTagsSerializer(), tags=[SWAGGER_TAG] + ) + @action(methods=["POST"], detail=False, serializer_class=serializers.BatchCreateTagsSerializer) + def verify_duplicated(self, request, *args, **kwargs): + """ + 校验 + """ + validated_data = self.params_validate(self.get_serializer_class()) + return Response(TagHandler.verify_duplicated(validated_data["bk_biz_id"], validated_data["tags"])) diff --git a/dbm-ui/backend/tests/db_monitor/views/__init__.py b/dbm-ui/backend/tests/db_monitor/views/__init__.py new file mode 100644 index 0000000000..aa5085c628 --- /dev/null +++ b/dbm-ui/backend/tests/db_monitor/views/__init__.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. +Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT +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. +""" diff --git a/dbm-ui/backend/ticket/builders/mongodb/mongo_restore.py b/dbm-ui/backend/ticket/builders/mongodb/mongo_restore.py index 0a885cc724..2edba3e791 100644 --- a/dbm-ui/backend/ticket/builders/mongodb/mongo_restore.py +++ b/dbm-ui/backend/ticket/builders/mongodb/mongo_restore.py @@ -120,7 +120,7 @@ def pre_callback(self): # 为临时集群添加临时标志和记录 temporary_tag, _ = Tag.objects.get_or_create( - bk_biz_id=bk_biz_id, name=SystemTagEnum.TEMPORARY.value, type=TagType.SYSTEM.value + bk_biz_id=bk_biz_id, key=SystemTagEnum.TEMPORARY.value, type=TagType.SYSTEM.value ) source_cluster_name__cluster: Dict[str, Cluster] = {} cluster_records: List[ClusterOperateRecord] = [] diff --git a/dbm-ui/backend/ticket/builders/tendbcluster/tendb_fixpoint_rollback.py b/dbm-ui/backend/ticket/builders/tendbcluster/tendb_fixpoint_rollback.py index 19f5c2a23b..df4c1d8ac3 100644 --- a/dbm-ui/backend/ticket/builders/tendbcluster/tendb_fixpoint_rollback.py +++ b/dbm-ui/backend/ticket/builders/tendbcluster/tendb_fixpoint_rollback.py @@ -98,9 +98,9 @@ def pre_callback(self): # 对临时集群记录变更 temporary_tag, _ = Tag.objects.get_or_create( - bk_biz_id=self.ticket.bk_biz_id, name=SystemTagEnum.TEMPORARY.value, type=TagType.SYSTEM.value + bk_biz_id=self.ticket.bk_biz_id, key=SystemTagEnum.TEMPORARY.value, value=True, type=TagType.SYSTEM.value ) - target_cluster.tag_set.add(temporary_tag) + target_cluster.tags.add(temporary_tag) ClusterOperateRecord.objects.get_or_create( cluster_id=target_cluster.id, ticket=self.ticket, flow=rollback_flow ) diff --git a/dbm-ui/backend/urls.py b/dbm-ui/backend/urls.py index 51f2d65164..6f475895e4 100644 --- a/dbm-ui/backend/urls.py +++ b/dbm-ui/backend/urls.py @@ -61,6 +61,7 @@ path("db_dirty/", include("backend.db_dirty.urls")), path("dbbase/", include("backend.db_services.dbbase.urls")), path("quick_search/", include("backend.db_services.quick_search.urls")), + path("tag/", include("backend.db_services.tag.urls")), path("plugin/", include("backend.db_services.plugin.urls")), path("legacy/", include("backend.legacy.urls")), ] diff --git a/dbm-ui/scripts/ci/code_quality.sh b/dbm-ui/scripts/ci/code_quality.sh index 5a9c5774c0..4e7e437d48 100755 --- a/dbm-ui/scripts/ci/code_quality.sh +++ b/dbm-ui/scripts/ci/code_quality.sh @@ -57,7 +57,7 @@ echo "未通过数: $TEST_NOT_SUCCESS_COUNT" if [[ $TEST_NOT_SUCCESS_COUNT -ne 0 ]]; then - echo -e "$TEST_LOGS" + echo -e "\033[1;31m $TEST_LOGS \033[0m" exit 1 fi diff --git a/dbm-ui/scripts/ci/install.sh b/dbm-ui/scripts/ci/install.sh index a25c698417..5c8cf76cea 100755 --- a/dbm-ui/scripts/ci/install.sh +++ b/dbm-ui/scripts/ci/install.sh @@ -23,7 +23,7 @@ poetry export --without-hashes -f requirements.txt --output requirements.txt pip install -r requirements.txt >> /tmp/pip_install.log if [[ $? -ne 0 ]]; then - echo "Error: pip install -r requirements.txt error!" + echo -e "\033[1;31m Error: pip install -r requirements.txt error! \033[0m" cat /tmp/pip_install.log FAILED_COUNT=$[$FAILED_COUNT+1] fi @@ -57,7 +57,7 @@ echo "开始执行 python manage.py migrate --database=report_db" python manage.py migrate --database=report_db >> /tmp/migrate_report_db.log if [[ $? -ne 0 ]]; then - echo "Error: python manage.py migrate --database=report_db 执行失败!请检查 migrations 文件" + echo -e "\033[1;31m Error: python manage.py migrate --database=report_db 执行失败!请检查 migrations 文件 \033[0m" cat /tmp/migrate_report_db.log FAILED_COUNT=$[$FAILED_COUNT+1] fi @@ -66,7 +66,7 @@ echo "开始执行 python manage.py migrate" python manage.py migrate >> /tmp/migrate.log if [[ $? -ne 0 ]]; then - echo "Error: python manage.py migrate 执行失败!请检查 migrations 文件" + echo -e "\033[1;31m Error: python manage.py migrate 执行失败!请检查 migrations 文件 \033[0m" cat /tmp/migrate.log FAILED_COUNT=$[$FAILED_COUNT+1] fi @@ -76,13 +76,13 @@ python manage.py createcachetable django_cache python manage.py language_finder -p backend/ -m error if [[ $? -ne 0 ]]; then - echo "Error: python manage.py language_finder -p backend/ -m error 执行失败!请检查中文是否已标记" + echo -e "\033[1;31m Error: python manage.py language_finder -p backend/ -m error 执行失败!请检查中文是否已标记 \033[0m" FAILED_COUNT=$[$FAILED_COUNT+1] fi if [[ $FAILED_COUNT -ne 0 ]]; then - echo "Error: 前置命令未通过! 前置命令执行失败数量: $FAILED_COUNT" + echo -e "\033[1;31m Error: 前置命令未通过! 前置命令执行失败数量: $FAILED_COUNT \033[0m" exit 1 else echo "前置命令已通过" From c5945084dc7cb513e973d1105f4d71b639f3d2dd Mon Sep 17 00:00:00 2001 From: jojo Date: Tue, 8 Oct 2024 15:03:43 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat(frontend):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=8F=8A=E4=B8=9A=E5=8A=A1=E4=B8=8B=E7=9A=84?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E6=A0=87=E7=AD=BE=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=20#7285?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dbm-ui/frontend/lib/bk-icon/demo.html | 30 + .../frontend/lib/bk-icon/fonts/iconcool.eot | Bin 52560 -> 53216 bytes .../frontend/lib/bk-icon/fonts/iconcool.svg | 453 +++++++------- .../frontend/lib/bk-icon/fonts/iconcool.ttf | Bin 52392 -> 53048 bytes .../frontend/lib/bk-icon/fonts/iconcool.woff | Bin 31228 -> 31676 bytes dbm-ui/frontend/lib/bk-icon/iconcool.js | 2 +- dbm-ui/frontend/lib/bk-icon/iconcool.json | 2 +- dbm-ui/frontend/lib/bk-icon/style.css | 9 + .../src/components/db-table/index.vue | 15 +- .../components/disk-pop-info/DiskPopInfo.vue | 7 +- dbm-ui/frontend/src/layout/Index.vue | 2 + .../src/layout/components/ConfigManage.vue | 32 +- .../src/layout/components/ResourceManage.vue | 12 + dbm-ui/frontend/src/locales/zh-cn.json | 81 ++- dbm-ui/frontend/src/router/index.ts | 2 + .../services/model/db-resource/DbResource.ts | 7 +- .../services/model/db-resource/ResourceTag.ts | 45 ++ .../function-controller/functionController.ts | 3 + .../src/services/source/dbresourceResource.ts | 6 +- dbm-ui/frontend/src/services/source/tag.ts | 75 +++ dbm-ui/frontend/src/stores/globalBizs.ts | 5 + .../resource-manage/pool/business/Index.vue | 106 ++++ .../pool/components/host-list/Index.vue | 583 ++++++++++++++++++ .../host-list/components/HostOperationTip.vue | 114 ++++ .../host-list/components/ImportHostBtn.vue | 0 .../host-list/components/RenderTable.vue | 2 + .../components/batch-assign/Index.vue | 148 +++++ .../batch-assign/components/FormPanel.vue | 176 ++++++ .../batch-assign/components/ListPanel.vue | 266 ++++++++ .../batch-convert-to-business/Index.vue | 78 +++ .../batch-covert-to-public/Index.vue | 77 +++ .../batch-move-to-fault-pool/Index.vue | 64 ++ .../batch-move-to-recycle-pool/Index.vue | 64 ++ .../components/batch-setting/Index.vue | 37 +- .../components/ResourceSpecStorage.vue | 0 .../components/batch-undo-import/Index.vue | 64 ++ .../components/import-host/Index.vue | 31 +- .../import-host/components/FormPanel.vue | 99 +-- .../components/select-host-panel/Index.vue | 4 +- .../components/HostEmpty.vue | 0 .../resource-search-selector/Index.vue | 132 ++++ .../components/review-data-dialog/Index.vue | 158 +++++ .../host-list/components/search-box/Index.vue | 0 .../components/com-factory/Index.vue | 2 + .../com-factory/components/AgentStatus.vue | 0 .../com-factory/components/BkCloudIds.vue | 0 .../com-factory/components/CitySubzones.vue | 0 .../components/com-factory/components/Cpu.vue | 0 .../com-factory/components/DeviceClass.vue | 0 .../com-factory/components/Disk.vue | 0 .../com-factory/components/DiskType.vue | 0 .../com-factory/components/ForBiz.vue | 0 .../com-factory/components/Hosts.vue | 0 .../com-factory/components/Label.vue | 84 +++ .../components/com-factory/components/Mem.vue | 0 .../com-factory/components/MountPoint.vue | 0 .../com-factory/components/OSType.vue | 0 .../com-factory/components/ResourceType.vue | 0 .../com-factory/components/SpecId.vue | 0 .../search-box/components/field-config.ts | 5 + .../components/field-input/Index.vue | 8 +- .../components/CollectSearchParams.vue | 0 .../search-box/components/field-tag/Index.vue | 0 .../components/field-tag/ValueTag.vue | 0 .../components/search-box/components/utils.ts | 0 .../components/tag-research/panel/Index.vue | 47 ++ .../tag-research/selector/Index.vue | 92 +++ .../components/tag-selector/Index.vue | 273 ++++++++ .../components/update-assign/Index.vue | 167 +++++ .../host-list/hooks/useTableSetting.ts | 0 .../{ => components}/summary-view/Index.vue | 0 .../summary-view/components/BarChart.vue | 0 .../components/DimensionSelect.vue | 0 .../summary-view/components/Export.vue | 0 .../summary-view/components/List.vue | 0 .../components/search-box/Index.vue | 0 .../components/search-box/components/Biz.vue | 0 .../components/search-box/components/Db.vue | 0 .../search-box/components/Region.vue | 0 .../components/search-box/components/Spec.vue | 0 .../pool/{ => global}/Index.vue | 44 +- .../resource-manage/pool/host-list/Index.vue | 346 ----------- .../src/views/resource-manage/pool/type.ts | 13 + .../src/views/resource-manage/routes.ts | 15 +- .../frontend/src/views/tag-manage/Index.vue | 432 +++++++++++++ .../components/BusinessSelector.vue | 160 +++++ .../views/tag-manage/components/CreateTag.vue | 178 ++++++ .../tag-manage/components/EditableCell.vue | 79 +++ .../frontend/src/views/tag-manage/routes.ts | 41 ++ 89 files changed, 4301 insertions(+), 676 deletions(-) create mode 100644 dbm-ui/frontend/src/services/model/db-resource/ResourceTag.ts create mode 100644 dbm-ui/frontend/src/services/source/tag.ts create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/ImportHostBtn.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/RenderTable.vue (99%) create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-fault-pool/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-recycle-pool/Index.vue rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/batch-setting/Index.vue (88%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/batch-setting/components/ResourceSpecStorage.vue (100%) create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-undo-import/Index.vue rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/import-host/Index.vue (81%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/import-host/components/FormPanel.vue (83%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/import-host/components/select-host-panel/Index.vue (97%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/import-host/components/select-host-panel/components/HostEmpty.vue (100%) create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/resource-search-selector/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/review-data-dialog/Index.vue rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/Index.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/Index.vue (98%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/AgentStatus.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/BkCloudIds.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/CitySubzones.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/Cpu.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/DeviceClass.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/Disk.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/DiskType.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/ForBiz.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/Hosts.vue (100%) create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/Mem.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/MountPoint.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/OSType.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/ResourceType.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/com-factory/components/SpecId.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/field-config.ts (98%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/field-input/Index.vue (96%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/field-input/components/CollectSearchParams.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/field-tag/Index.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/field-tag/ValueTag.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/components/search-box/components/utils.ts (100%) create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/panel/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/host-list/hooks/useTableSetting.ts (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/Index.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/BarChart.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/DimensionSelect.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/Export.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/List.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/search-box/Index.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/search-box/components/Biz.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/search-box/components/Db.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/search-box/components/Region.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => components}/summary-view/components/search-box/components/Spec.vue (100%) rename dbm-ui/frontend/src/views/resource-manage/pool/{ => global}/Index.vue (73%) delete mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/host-list/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/type.ts create mode 100644 dbm-ui/frontend/src/views/tag-manage/Index.vue create mode 100644 dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue create mode 100644 dbm-ui/frontend/src/views/tag-manage/components/CreateTag.vue create mode 100644 dbm-ui/frontend/src/views/tag-manage/components/EditableCell.vue create mode 100644 dbm-ui/frontend/src/views/tag-manage/routes.ts diff --git a/dbm-ui/frontend/lib/bk-icon/demo.html b/dbm-ui/frontend/lib/bk-icon/demo.html index b0a9502cfa..3482f60773 100644 --- a/dbm-ui/frontend/lib/bk-icon/demo.html +++ b/dbm-ui/frontend/lib/bk-icon/demo.html @@ -117,6 +117,10 @@

    +
  • + +

    tags

    +
  • check-circle-fill

    @@ -749,6 +753,10 @@

    backup-2

  • +
  • + +

    loading-tubiao

    +
  • host-select

    @@ -829,6 +837,10 @@

    dirty-host

  • +
  • + +

    tag-3

    +
  • saoba

    @@ -990,6 +1002,12 @@

    如何使用

    +
  • + + + +

    tags

    +
  • @@ -1938,6 +1956,12 @@

    如何使用

    backup-2

  • +
  • + + + +

    loading-tubiao

    +
  • @@ -2058,6 +2082,12 @@

    如何使用

    dirty-host

  • +
  • + + + +

    tag-3

    +
  • diff --git a/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.eot b/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.eot index 91666f38ebfed10c5f9ea5768f5724faad025361..f09ba9d708d55bfb9687a17c1e7bac69b64fd96a 100644 GIT binary patch delta 4438 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 diff --git a/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.svg b/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.svg index 65cf7f419b..f56e283c54 100644 --- a/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.svg +++ b/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.svg @@ -7,659 +7,680 @@ - + + + + - + - + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + - + \ No newline at end of file diff --git a/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.ttf b/dbm-ui/frontend/lib/bk-icon/fonts/iconcool.ttf index 58a61df889fb5a9a86d570fe00f6a63abc97e93a..4d291b35722bb9fe48b500da69d5b3474c28baf2 100644 GIT binary patch delta 4453 zcmYk93wTu36@}Nm^U8BFlMI=>NhTrT5n>WTfDn@KiUF)u3c&|e-bPA*f+!+oC?X;v zqM;U15h5yDK{P5n3ZQX%^VIo`L3svnWdVujZ<=%atd7{P&H;hF!1LRiW=@@PSxw)4 zy!SIw*~BjrU9op?%sfxR7$=%|>-IKKE!IPIk^b*_P&c&qDya6c5IFZ!bdm!S*;P=SG{#2^gD z5L6)^Ls5-ks6j32FapCd5~DC0^|%}j7=y960zW|jJMuEq7dv99g40e4}ZX69D#@X|2#Hv``s;N zF-uxXW9|<(MDqbS$>ZXSFgxTT=*Ka$#=xzHI23L=gvn;$_Cs6>69M8@m=cf}g~4FX-F@H$qgw~nC6fog$WPotuXZ= zeH1i=IWVCltOtk*H(_N!Ot=Ya1Y$x=SS=6}8N#}On8*-T5X3}=u$CYuGK5tHF_9sx zFNlc-VWmM#G{XE~(Lqc&2#X71qCr@Q5EBi;l7!SLEKZ1t0AZOzOk@ZP7Gk17Sh^4s z4Zt&6o^?J!4w|N>IhW^Vpd0}HxRQrLgj&& zmnGC7hw#LOoYM2MMB5N_tcTqIOUh`C6pmk@J}P&pyy z8li?l<|$N5$b5ym3NdpC6&7OV5Na*N%pp`=h?zsEzYxv|n-5Ac#7rVagv3lDlxK)J zClqRknM5er5Oa-CydmbCnB5d}POzLub51Dj5OYo_@(^=QxB%9_`GQa>As1l}fLw&# z0CExb1;|C%As}}v>=Y1lPNL&`I405Y8jcAHc)V9(Pl2p8n77N|;65cfUdJ(E%Yodl zu=zmND{MoMO$r+lLA+`Ha*Cb3fmv#DTR#?^0dO12-&W%Il{On1KT9zStZPl33*Oo?}Y47*hL{b z74}oe^9nmFWS7Do3wc3dw}rGR?7NVc6n0?9%L;ojWVZsd@I7Y#_wbFfdGe~lRtKe^r_ez_4l48#koOh33dmuF{sMADq0@jIC1HNhbU=%X8 zg+>JOkwQxXIj+#0Ku##MDUgp98WzYO699PXa}|6{oCG)*kDE-DDqj zI34AV3656B0cVwSsVmM^9dw|@eJJ+pxCwEc@mIue zia(W5op3hss5i@drFV<>d{RNuTA$lj;k&`N#GmC~;6I*Rn0#IGy5wESA19wnsZN=l zvN)wPFe=a(XbLP3Yz#abI2HJ=$MMwFsgdBE;ETb|G^Ew1eUR=s9x6=hQ`2W%pU%GSzE}2L()WvgmHn3WJ6T*`+}=Ob ze|G?&W5XMs>WB%s%jsaJao;_{ng&;8>-h>SlTI(c-}=vPL6 zQJ-AjTL0DM%Nr^iPLGKjGk8qvm_uU=#@3D9aMkJw8z!8eST%9g#P*378gm*~HoiG2 zVbZio4%T|h(m;Bcd)wXW*l+Kk*k)6$hZw(WxjkMh#|q|HwN{N)QDS@Cp~8w9tEZLP zBh^(=WEJ+aLhfuUHORXLl-F97Nwzg`fHlbS#9G0W$_gu{SGqUR@+M}C%5Wumz3CyR zGsT3|sMK21jk4|(yUfb) zh6+O73_Hzf2AN57J>KL*+iiPdW4_JoVYT>rXZ{%QMi#}z_xLiftarY3=QojsrPjvM z$jnHj+;a68(zYSc>$WhnySvy4M=@19X#TgcQW12+Q;4EU1ihAri>7fW#z`yB<%)cI@?_*wm&?jKx#gJCd2CDcbJ?{EY{#lulUF3wCthDWW{Pc(t9BIs z|IM7-bLFMmIcZhWipjH9IqU`3R*$poDPwA{Pi)(L@9Bi-OLjW8+Re14dB)xKVx&tf z4RwIAPOW652bT3Rn^9SwV|mJ4(d*^rS|I7tUQ`s7*%y3~cl?8cyMuW_zg6Wc@t^QT zviv1^c_n$4-(DKMI6ZB!kJo&MyeYn*|HJ^F?{nTf#Fv&Ad?h%P}ZBxf)%WoaAj#|fHE%q#$d-Le>(#p1>2llb@ TO9!`nd+mT(7-Jg<<026fmjQF28>FZ)D9sWOkaS#1L?rUiL_`z? zMy3N15oIEHVW@=Q1t%zSF(afR>LD^SG9oluB>w*AS=;CPzW?`}|9kmA@ALeg-`TM) zq2aNF6~(dT5LpOJym{v2IrVp3eG4SDg*FFnskv+V_1Smd2RZtF>)aXBCQt1*Gkufh z{!t8?p%2<5rOelOmnfMrbME}xDleYV^^QP7ST!*vCbCnHI9Z$=I_u8bax)J;iTQg=FW zRF{VM*F-mv5Fho?K2;ChKw@-W-Bn4K>7?4Em9bKK(~Cazr62tnz}FebWenmQ3}%SV z7|Jlp7|sYrayjKxFpAM!!Ie}}#TdTHRb-Px2?bouIIiJ3uH{>dr-jF<<2&4-88`BM+S8hwVvMCHljy)?rf@S;NoN|{t=vWpGnvB=`4P7> zmphoJ#mr{`cXAg$W+6Y}ZelFrr~1B@dsxi9+((!Ae=)Pk(|>0=v6TCHfaNUXK_22^ zRuEfB8nakMox=JxR`W9+;pepFQ68h7HLT@v){)N>tmjGEC?Xqpif7o!(`=%M2A*Xz z&#{FbyugcWqmk{r#LK+Gt8`}vzhEb?DS>wLI&bhM8Dw%PZ?T8BX&S&gT*6-7WgqX+ zmFL+?B1`DTev(Mx{rGwcIlw^<(Mm79Ro!*T3+gJ8AC8s8vj9HQKICXXIbkhOsgM1M`?kjI7$#q=^ThDSFm(PS%YOd${(z)qfElu zIm#(4%hAilIylNRtfLch)N&o=9+u}Q3$X%6`G|GZ{k1`R3-lNsoo-2`Xb6gb)i=0v19nR1;VTt59`dA*@1m zf`w=ZRSXuQAyhk9h=x!VVIdkq^@N282vrsqA|O;_ScpJO8oL_?@Ru@C{FQpG|9go+jm5fCb0EJQ%4kg*T}p^_$Ml{yfrZY)GVsLrtv z0ilY=#yYBfEJQ;{1+WkeAw9st>V%X53#$|H#e~HPsRb4mB%~WySmoGlTtLLDAeWR&Eq?1^fC#0xYm?xyISePfIvRIfWq_;ZtI`Q%S8jJXNnZ|-*?H_Q|O|S<8dP21o zY`GI3Kculxv%wyA)ON5Hjv5eF@2C}FYaBHtY^|gAggx%4QDN&GwJhujN6kwSTCa^z zAH$w>)X}gF4lA{P%2AWUHaco|*wc<0ANGu+7Km+fg2%81M{N;%)=`7RHaju(N^Fax zu8D1R)IYK39d%Od1xGyb?i+?4IX>TQLD%HIBNRX+YV31G-z_< z1h97;c>-*&BX@x9bL11ScO5wf>^(=`0o(7$MPTnc@)Otxj+_PdOGh39`%uKRk=?+4 z<;ZwoM;uuY?AMOW2zJzwEx|r=WKghUj;spy8%L%E`>iAUg8j~sk-?5TvNWpy-|Ilg z-C!r2V3h3-jvNnWj=T?c(vb_o{^Srse#((E!v5^YBVivqa!c4>9Qh{flQ@chcrTwi zGE>;!9Kvfk?Z{tYe|O}xu+JQMF6Bx~`XB~Mn>|c&t8g@?iw{u#3 z$okJ6SvTwpM1de z`osfCMM>8t)hC^A)vwi~t2wpGMh3#Yn$43OS@>h>Fr)=_i0u^R(aNptlF#tSyTHKSDUvZ?{ueQ&HdYOhCnohVH$om;xMcSi49dmrsHuFtkU&3&u; z4Zd_+|1Sr8GVt`EJ%eu;vS`SmAt#4?F?8I}4Z}JOyLQ;RVF$``$_AI!mo*O`F#N)Z z5hIq3I5cwb$SKt$A04@;Jh^;qdDG>omp@pMUQt`Ixnk$2jib(wE*!mf^#0N3uULA; z2Ukw7%&%;!JX2LrwX|ycnA9;n#w@sI*7ybEk5?B~*Hmw;J~1J2!mSe;CY+sEHF0O% zuAIEam)n=z*?8CT4plL!G~e{nGD{MTWKVK!j62NY%m$pHY{tqU1=oW<97kX7{=#_{i6 zU|oa+B@w|y>{ziRioJ_sSAq%=yQl9If86vrf* zSVvRH^WJCw@jo+@8Sl=AIeWSHcg}gw?=1`T0J_9QY50h?e`$WV(R#ldOSj(d z-gcIMU!Rrzxi8bHcJ)+m_0<3k)^Lr|SWVDmP1h{V(L62E>v~HcYe}f zm-?um25N{#Xtc&@qNZquW^1nIYq6xa^+~g>_4&{LYWSMgXEU~7D|TQQM=_OYJkA@9 z_Qs&bhK-FILmDF+f8!e$Hl{YFw?4nF?`jxdX3G!N-wtbN?WrH z+p?Wk+@2lTiJ|PwE?#|Cc4H6r2=-%t4xlG}`3n6R$+sEJ z!HnWSf8rnxp&uO_%I>VqVJy$#9Kn%{;Y+^eqdA7LKL2+Zf5147$$KD#5w0ux&_YY?u8W7GyG%%czXr*v&qLss0idG5dD_S+2 zxoEX;4x`n>*^Jf*=QSD>&TzD5IM>ly;jBk%hw~q;6Rrek-Ed7n>xHWW8XT?@Xh^tX zpiRTIe*uxXPhj!}SjB7Os3~_iznFdxWbY+A~}i(O%KI zm%YQa673VNnrPpk_RjF2_UVXlO-1_!b= z9UQLF=#X%=Mu&#$HaaX^!O`L2T8@qgS9Nq`wD$j)aHU5_1-0Lg4p)D4Ot=rAvEhz@ z#)W$WIyT%T&~f2@fsPM%4s=4eN1zkK-2|N!?knizaEC#sL`?!ZHQaU3Y2p5Z#z)m1 zf1MugNvJd2ozNNKK7}TPI~JN4?p^5Ya2G@8g!>sfH{99KdC|K5^TYiCb#bRaUEBdt z7xzNc#a$6y5>zd@G+M`(MeF$Tpz6dGLB(uRxSygcqjh{$xXYre!~GUb4r=WwL9KmV zQ0rYE)EYMgbA{3+nmb9`5+)j&ScscScQr zniif1&|Trl08J0i2xvxlT0nP)=LR%0sCs`-c$Pr-26f-Fg1Yb7LEZO#LEZP9pzeEa zQ1?AAJdvRJLB-&KpknY~P%(HYJh`BUqt#y?2`V;^1{Isff{MZ8LB;8bpyKpoe^9Ym z5L9nj7*w2|3QtGq>7ZivOi(d?eic-lejQXS ze-l*9ejA?3(C>nZ-|vI!doKkQ%a?MtgJ6jWXLIH=vGlX?71!$uxU}=VhAhL49wj@C;3}Bbf4E&?Qo3e*ge@oXoum zoLgnNIDDS>Y}vPyiup^X96;Ke+ zDySe(D=H{g$|#5hilXQRabvmO3kr%W2+iSp-gA;^W(r>JcfbGt_q93iS>E@&>$5-4 zdximqdH)S2&$t=FFqMMGe;smnF!+zh=U-sQ$o-6y31a?KW;(-wAle`VatH=t0E!tR z3ek9R0NTLo@$$t4#JeCW1i>p~sX~4b%60;!0#raWf-IGbV2Jr`R3tVRKTU*_)NWbWas#m=Pdw!^1kcDgCe`j*?#jX~S#^V|=7IN2 zrK5d+D~|6C#*8Cmzy=}?Yyc`5U=tO&A`|9Fjpu7ewDg5vOyM0d$jdwv?((_CdO2;U2GJa&Oid2ZtjEP4ndx-7({I#g}~#+ zg_J!?DPFD&0G5vnqDLu~33JyA9QVRqdfL>*r?OVBU$$Chf4|q--#4c(B*8q^7YcZx z)$eU%7tA8}jlXu+3p1Mgf2Y-JwR&4<0vn+(->*1ZB)cQp8l`%1*I~~5>H7~a zUb$r66a71HfBZCrX5wkyn*VlubWK(+e$nQ_w`nEe<743`Zh;_u{nP3zGsD0BNaJjV zl~yJ?an0oMH7h$3*+d2r3lbC*n}J1}oE1?R9_j7J3tf7{2O)63=CE6!p(K_@UO38E5D zl<-=?Opku2!4*xhzi!%T!c?KX+>XEQjgMxnHt@lcEG+Ta%=yPgMAwsG58D9-v*GL@ z=+}jm-3fEc<+%{aO|dypK{@It3rO*0INNAVOqg;JrUum~H1mu7ho!15J3nnGUo zirxW;cjFqw6Ct2DOTp)BzvsB$e@#o_Kwob!{ytW?B-LfeR?pa9u`?2`7Xy)~;BmUWg-E_!!ZiYC#5rM9Beg1}6J!k2+AtYaU#cEF zh(B_l%XT8GRwbjgQNqw1q#P6Ip*)F#i3u@L(TJir0TfN?Yp!YhCeo}&nsTr*Z46c9 zebsFc${9@TgX?STx84YT!Y7J0k0@H%rqb3PCv3BoFWA?3)&<0UrauedcfrNnP8`BiON7# zJ!o@{Xme84E~=v{Q$-?skbJ>Ji~8KOf2gnaIH8Y6a0cnL(hC?-tAtVUo%;AL)p#YY zPuxZsV8K~&7J$+qc3o|j$zdb{B;X(-G>*wh?gOLCWl#^RS1g4NSYnV|#yV|4TxR@8 z8J1vO$SIs|p$o~HphS>)IE&?8C>6^EKH`bc%mUIqHbmt702zdYja3lJ5ig4af25N4 zBA=E$73~Q-Vs|?2BTjp5tbRelIR1lnXH~sEG1!5WGdma!X5+F+n8mxKfL&5dHnTYx zlI#JK(ZbCJr_Eg zeJl1xM3|@8B{KoUFoj7lT}(GqU@A;6Gsp}vvzhtKVrD6`l37F7*BOZ+&czVpV%WP1 zJ>$_hH(ysi;P|lT^kB!1kFul3$5^Izc;`;osUC(U2S-O$$AJSQ)hZk~e|%VdwpztY z_3+5Zh<2s_uuyHR>3;l2w$?@|m@+%7^xxrXxpc2{+es5Yv^;0-|xpZjv)*L zk>AG{BzKbM1m@Y#{h^9K6!O=$ zd&2->FZ@BB3lD8qAA-5RsQr?(Z}UVV9`!+*lCz4w)>dD!)mJ;OvD^AY1CB6f`aCnM@~jh-B_f4Ok^4C*^?A=r)5 zgZ$2AJN~$qx#Y>eU%C3!)ph!=^D8^zLgoWzT0m}FM&!m*v5bwc&A49zU z1>!LSR3)KoB1mNboe7i*9&Kg|<;qkjmvZcwq;95sVY38EOB4w^GYX8&752HjVDY=* z7Nb$!X-C1if6T+1z~y~IqAuS7wT*O29D|T8ct5t zB>_)_a%{I(jtoG_St)ikBtH~6khdT;l(i|&mn)@Wg7Q3+#=Ye3wR?#A1C!NifJjx>$bOmSDrTF_T;W(#B<}UbBYK}{LQ)l*0{ieS2QyvWjXrjHlFl);vp0qs#&3M&?#slfcPEWRP+G zE7~Phn3Pfh`+`5JFf~6yl8G0X!+N}VRFF3Vojxab`|jd(Qxz^g);A|WqQu|X~uiCjIa>latH`XrCn<{kdT z!%t1mZ=XMP>fqXJ_51fu?O2*j55*Gu&QB!zP6#+m9*qmoOB2Eea?i2tz% z98Wl#!Dz%gBN$npGdQq+hCb-G+xwBa^P-LOdA)t$GMn73AREjrK@WgO(_K;=f5TF^ z@lz`mBgUCTnW=ag(Z-HL5XbQ9Z(e*+{SD7U~uAu6$^hNZL<&Qu}5|u#*?99G+@% zYh9=N3i}ZGW?c`Cp8!t}h2&C$RUjWn6;p90M7fe+cPFR1 zZ{584R`;Bhg#DM*9UX&930XR5B&=uG!UgBMIbs}GhMMp|yd$}=FC12{e;MdWU3p~+ zZc5rVjuJAuQQ9%zxcWj=R+bGK2bV#_Zl8B5z^U`>_DKEFV7PBVm$7SsdLN|JpH8K( z*X@yC!MQ(#I##4kTN#8}nVKZUXacWr1abV)#rDd0#^+uhZ%_!J)(sJ;zVDXnN~5=; zy;t!jkRHcz7RY;;jmN$T75227zdk%<}%i%69w&aOu@qte`s&A8&P}gd^&bI za*u#?h_YQA8rwt_CAzfuEFok_rC3234Of`N6LB$)?vehyol_v#y6~?Kn}OG5 zZbY~-(x=%}!%S+TO#+cxx2iS|nr&b@G77@zh9N!GO-q5MaUI$7ST_6E9xa9Y#tW9` zK3cb8!D3vZ#!tw-P0VQ9DccCyc8Zol zs!;+{^-vRIgGU-=Fdet!QFw5n&f3jPL+y#$I=yWaFi?-e6)z@aC5mgT8MlgYsi9Np z3U+}%ao-P`O#HiX^})oW`tY=_JP4nlbg8z4rmSW_qGlv=0FNY9BskKnNbEA?42B%b z!>=0eki$0De`v$@l*Ri4b$ot={VsU~;aNf5Z#{FqW(S~*)$LJ)1SM7jAhzmoPHh?p zv1hePF@)n2NmuTZnov7qk2`urtDxIu} z2R32mLme$=awgJQaeKs8x2uISB_PXUm7KB7z_WtUn5ejA0+)B3J;li8;x=m#hc%@r z*$8VVe_WOqY_86P$uO{D)u#u~Gt};kSy?XNbhio~X=;*1evR{Nz*Q^8BgH z4(0-8FLNpLDXP_#P@xkDHCMm)5!L`ml3bjdVBU>qs2 zTuzh|arQF%vue!ZgcLO!q`+YzH&~o@yjfX0M26LNx7#OMEEcmr)Yc+HgtaFSC&?DU+B*d49U z9DW&QKZ^tI|Jnn;0omUc@_P-EU2-_Re=Xq_ug=GHJ=3MpL8oTzq=tHgd{oIQPGoZh zO>^*4#~kVnl*QAfA#Ala3RQKiNqek)vSnv z4jg-yDe5hKkf9gb3{vZyq~N83%~RuH!!E;)P*JJb)QdgAnH{aVZ0ZPMYR|zE^)O2l zdQf9|v$dDLLoIBC!S17+R(-YFe?M+3`#pOx_L0h-32McPl}?!Bk)c*fy3|EQE^h_# zNT9sgqcMoam6vj_))D$oE$q9SgN!Z@j`P&XHvS2$vzbrUe?2ZVC4J2- z@e_^5m^SptQ z@WU3#CFh&u;X(qBhg8Ae>@yw0Qh9t9wJ%)7QOmM%ys2etza^fYmc+ ztR`eNq}xJs5=uB4QaZg`e++~ews<=gU!W)0Hm9u`nxnL(+ggK~tItC1$%!{mFVA!_Sj!0K8*wOaO4oA=?j+>|7_Kj;LH zPrT*caM4_QPt<@X_1$_MHdDjSe|a{08~O7@J0~SG zC)+vyMeRY=162_6l+C5y3l{aSe}${mJ@g=dlB~xcv`UhdtUmUSYu2n@Q}>Y|UTKgw zPP`CNA|+I8DG|f@*;%U_rC`YzjE%t(?T*|>%~mvr8ntQeODGXH`^H%0a~515%^qI@ zIZ=_tQI@GOW7}bLfBSG{Yq@2+c6n`iTUq0Y_iFE1k#Z%Frc_azSckekL!DDZ151>i z#A2MfJSnpppaxI32CP(-ka1Q#y1ffIUpy+fwO0`6$IIip)B{a4Q6)qWz;#&A-+`(* z81xtnri3#UaZGEIE51<3SCQMS2}d;Tj60(#=W8;xLT705e-m0N?n*_$F%=8x#Xp9; z-{1+gn&W0X2V2ceFOWW(7Yv#w*K|e9nT|Rpw>r%cNjbHa->#R-v~7sfE{fPiQ!wZ@ zi00n{zMwTOw`p_V@YlC6r4RJgH)M3ww5VmO?vhtDm%N7P9`8wh`7>xNL`%!GfMzhMPe|EyxwnLyZfWLpYx4LaO3WuX5?x()?auui(exeUG&Lp)siAZSxrNo?< z@(mLm8J6` z?Ci)+Y?5}@N|Bd#m!4~{k~8PeKa;2jUy!4+&uv2m&gRC>VoBOXyS3iMFIgQ~EQh7D ze;amsf4$COTdo`qmvasJq0h5Hg9_A)V!BZhG2BB9Sg3VSA72+BYm87s7wsE_so#~Y zvtpO+;3%?X4QCi~Q2ewmbR2FGe4~+&RjV_GQnplR`s%ni7k5{efSeBlwb3S$$Tf8c8DzwxU}w1X%TqflI!Sl3u}41beq zqmRbwbaYgcH>fXCL1~)$wdybJ~%Y;0JW}AtI5N z)GFSoPn{I2RheW}(0foUOH`}L08;w|f3=qgREsRLWc&4dCz zW3)vitix}&N{(>K7PPo|L!SY74?gisSk!;hL%YGb|;!=TzQReYmJk@c{&4+t&Nf1|h_ zOobhi)$Vt&L~Mx~eSuIW>h$0P4-YsR-fan<1%ZwL{w56R`1hOQz~FUL*yXWECSvip zPd~q4w}>XiEt%W`hXZ>$=r!{rZdye^Uo*A}Z&1lAMk7vutd-sy3_(9L zv5Z9HQDBS~K{&sMmQf$mVf`5Ee<1rA6lr*BSV!d00#}Bf8Mm79KeQEUba*}0GjiK6D zlnM`RRO+EBS|K9p@&Xkm*gffoOg>ZEWI9ddwfMgGPBY=H&-983rl%h=e;U&!zv(n2 z)yNZ0$IFz-^s>=cZ(}E!OZzRgK_!6{sge*6%zA#-og`d)>CRctLu%IZbM8Fr&N{b+se#lMwpA3k25z@`!xk=DvH-nngtlIJfb2B3Vnpvf}*j=Zh|LKGo2K5TO!rg z5leV{D^F#4lx~pu*VP(of3MLp1aBMh(8_Vl6sc$q9~U&p#X6N7+vM3H7jssZjpglD zbJoif8*qdpMw7#4w3~R|KtzklAON_fWM>QEtagJS5LB;u5fDy^K=8zKCN&WK()LrP zBfGOFP&N`%`{rHqkipDFzqDhhSF{R12=F|>%oQL1mcdMNf++GJf8t}7uz%bCEsp!v z{_DQYvfqZeR#vcZ9AS;IsWw}e(MSm4jW%Q*ED%93ne7IS2nM&;$#M>d3l$r|%DX!x zPBa>g4u>EZje=)KGznJOW8}haqv&!&fA@BgKNd-XA&@i^!f^%;gV7o8`)$Z&de<6d}?kXeV8a~ZlO0H*uOfR#NScg{8>8E-4g$GvJFDX zU&mXzBk7-YhCbwZ5Y!dX&S2+HI@+2`1V6L$vkzQ+*ZG?-e^6(2l*>!X<&Isho`pX9 zP|;TS<*>!+Suab(Caw3_ElVwS&w9y5Bze8ZX})^c?DS$LSfw-EcI#5B-F*fs94>ji z*I|Z$l~|msoMsDF;T@q>xX#e3uuRL`AFO;em&!%K8};H3PKn53R|177mo8hpfpff- zk(drvVQpXU_q0gAnLe7G1tV;Em~1iF{Mgr&2H41m2@&K62Z}{MtCQ z`H~mSzWjccj0zqhFoTrZ96m=|iLkS3w}FX`eCF(tn_>o&CuvEXUcBr+77AFHz5nvd z4zcW^V*AFlk zTh=%c5(V;$aNcs*@C|#XzpDqJr>mx3meJxhe< zCv1CgtyL?&rVn(v>sUQruuGFebxSu2gpC!E8`^rL;RdT{i^PsJY}`nV*AAUZpr`v& zTSEzeM5uO?e%|`2?j9hgT2Q>lA2~=)9V#t$f1ZmuS-k)~o$Fj&8alPX4=zK#g<^ax zn$V>2LIf$TAc8;`lTp203wR_)C6VO>^>$;*0HdNLnL#p1qB?5O#-qmxnW$bKLnIV+ zw;T;dQ^o^^2$Q}hy{Wn>eGOb+tDb?h<%HgVeA!h zrB=#2Me3l`tVja&`9%|yCE-mMXqTF+e-%552&p*>kc6?KrxL@1rF0ArseVmb9(4db zh==2gyje8xNU{wk{veWlgOM1GEc>W~fRp165n^XKPJGmv+P4q>b;pj|KelIg?X}%| z_Wa|r%kH>n&&A~VtwxCz*&lP<*(TSoB-0wRzySa+m{xD3e1?#%M%OP<2!auge}B$t zBp`5GO|@e)|8>^K`}Yrkb^45re+VS2C!iba5bAHjqai1@XgwC<3WDuvK@a(^Wk8z+Dmm|`Q;Hnd7wEC&CGbQ zy^|rK;4PPm2{G?R^=iV}Kl!P3f7y9we8zvuaL0tjenDMu3pr)zDsIm8*K74(Q;&0_ z_B4j~YMN>y7T3+jlHit6lBmSWMSK<&C3;Q6jZhKbu_JIu@&ouK^*2&Wi{SPd--DLH^3{TAbWzp(XzvGRWiD>qlzHB1m)h56Bf6FG*@z*?7 z)79n}Ev8>+xNtdpBYBWgqdJ%8O`U9nS26xU zThE2K^>gc{-U#gTWZq`=t#fxug@km$wAMA}LHyjU@7D9`^L!o7!!xLT1hjZ=`e>1i^YX2T}S3OWnkZTe}0CoNQ%)zmPwXra%hRKFS7AyD` zwM1%1XeJh#9>oP_Mo|@<9M7poxiXC?v_^a-j{rpDxTwjz5r5Y3189Nbqg54admm|; zW{o?MhiB?y(3H)puAd%e50D>eFqEkC5naS zi`8MVa~-DEfUCt~wm3{iHYTzU7rR!m4{vcAk>OnO@D_*2f1VYd64_n%6O7v!l!p6e1sJ{W}3x>7JG8hhsfxvyznYtJvA1+0~|^tGpY zdQy=-yI{2r_fGKn*cm^z9%r(emOcqyQC6V=DPp1`WoY~m4Mhc6l;}h4v0M%j(K8v8 z;g#jyd7D3Le_Nhj)+Xg7_3LeWV1WbFwNsa@{p{{}@^X1uX89W?p9>5pgSonGxr{H{ zmuHp%xWJ))V|NG^N;&o0Ju^OZI!-Ful{gCbIFB$sWPxh;|J(|cGV+G;V<+L6N%d zQDf8{(G_Z;jZ=@`iJdysf8x=dor${s7^Z?nfQ!RL*7dNj?W-u#fjt>^G3d^4U0 z;MTIjL-c}AbC~&{z^-Qj9?{|UVVaUu?OE5_Oo)OpyrvdUcgUtaH5g5nj3;2S4?%c*Q`Umj>brHJ>{4JeMyJhWfALwZ zVOzi&ve_i7#qKg@I6iH1+S`(0Yrq!E8ZBihEhNqy`5sC{FpoAo30N!wlW(Rx&^^QE=ye|O3Ij1y@? zMZ<|)nHuyciOqSC77S7`Ql?uz1?nfGVXJPDdbD%8p-@4ti+W)KM_>otnnYbu2p39J zEWk@q!CqZRF1wYT_LD1lcr^v#Q_>Lhb6r6|+M7tK=eJCq);X;L%TOy=wU7ip`NljF zzIXSY*H*ylw})$rdswD>iBa>Xfgv(TsLjG#3vN+4 zIDX3l@C~0$mMysT>|5~?e6?pumcIM`@%KA9j?E(1nuBySOQk!Je}-_BiWLc`48c7n zX+cgB5?QL8N}61x#IiY*``CD?I0!ME8#BcrUdBw3t&~|8vcEt7#o-RbNcRss5cPxe zA~Bo{i@QNWs_QsOZH0de={l4-V&6aQGYFnD7PFlTm=d*1f*v&tYimHt=Zjd^2e@#AgI3@ zHS4tE9`gjv#WZ66SXek*b{{p6UD_v)AQUAK-Y-!b~Nfe|Of1fGcD1j;UPib=uIL95D z2R;#FHFFb-dLIpFWChBrkQ&S0f)>xq(x5)JCbUZGo4d71yGZ>bPMYUvH^CY4*#G<| zy9YjoD&#$Gy3eh>;vg4(R{b)Zdhb)usTaT}Aqd2_ z_nxop{qlWqD!ixdb!wK=Lpomr84#$8ah5s-OA}(Gf7lWA04VCp6nv%X%G5^pezvg} znA}%YSES$`^;fWyhB;AfufdiMGP+$RWuWo(9@JR7nCZ*{W)*X8BaXuzBG|$J!70fQ zP*~(K1w<{-Y!do^USSg=tFQ&hi~Lk7$odIbEb5dBPK5@emm(!Cuq`G~HmgvvAf8|q zsUTG}e+!f%p7xI!GuIG*x;G+xC(@htYso?9n}xVd(W`h zPOt8%&N3TZ?8>=S*=n%O>3{E&e;Vk0YoO=XstR`X8?ZwCFV-wJ2el|tc%&g6*HxwaSlgDeYNxcQ0f5KyvT85{}*OzWD!@5#Qy%Qh)G?$)d zg7RxihEr1@UN57Sf2VYPSuK~hPwg6B@|yY-pNwTQkW%TZ#uRy!6#H1=tH;7*Q4j=qmW!y7V} z+>iVK+u$3{P?qAjq)DX`Dj{SJbPROhZ+0l@qrOh?B`t0AK?k`t88WC z$7S+7VKu)z)lM}-QKCY=^rbIl@3|+df2D*pt}w0R|0r2NwFDz1L?f`h>YTA5;Nd;8 zK%MoyA@x0YPm>>h#C{U{+pu+%^D=m~9k7);X`+_E5|w1&w$ynk;5r9ZsfJYpop7VC z-G{$r%gD%r1!~8lO@wS(1XY(TyME&G`CNOKY54t+winljTrR`pnX+bq)wOOtf3S3X zyKOI^{w<3FDq@(Rgp5){r5umdb=UgQO*bhKX6H@pTHavbYdthw%ii?yt5}X(Y6m0R zxKOWKlUPH3o>-Gmhl?|caMz6D%w>y6hP`R0`WsOw3Up(qc8cu0>5AJ~!#1AdZf8Z< z#&PGBW|U^&Zw#wQ;BR#E=818mfB&~^2=kr)8ymuWcm6|d2q$Q~U;A1Jjk0P3(1J_p zf7x5nrA1kT;sNlI>o;A?@yFKA&4B)&iWmYh&nKS7g#@Ih`B$ob3-v7kMfB3&~F{&#+ zl815rM{+QJ@}Kw@A^y?bi^EOc#fg6S)0vMkS2CaY|JV;t6?+ z&IxaHbeILr2Y=nS*@h3^CTK2rGIPcLhuQx-9{5&27jc8;fvQL#vz zBB;pc3&>owM>$0hsg(in4f-I4S*U8!;Nct=E)T+p7ocEwfO^ypYGCW zng+yZSCs)4l_jb-f9d3`NH*R%+X;6d|yoEMG&D3JvBWpdVmkCP>M>TT&iy;(#aCF@@Rpo6>1ZR+Oa$e z{1jtE6#9$tgvSOn`j_^cQe3T}jJEl=q<=4|qHhJ(YS1@ZeXoQVRGY|hOkV}9V~HY4In-ntiwa0qs0$yj=?UjV4zYvU=iO*$ig9h<6b%W`jIOv8 zg|djNfb-$;f0lDtOTL^?gbEgn4nm=vhzbdi?+lQ98v~K=GDi zN>tRcs5E+tKP}n)CV{sZO?HF9ib!X0a%K+Yg*J}ZcoSzvMCT2>$eB3mR^`9~q5)7u zVp*PgSq;3^#+eN^BTx4qazT46lk%F46321^vS5>ef8$x+U^EyV_%3j)K*^cG-YMA~ zev?V!ITon74oMbfV)K}3z_ZQaw+So@950x?m|<-(Tg;+?1(xH@l98uAUY>BVxQHzP zp~QmYSiBUxc0-HJByc=OM9$+hn^~kmE}LAAIa|%V$#2BIav~?XupK0qPO~fG!rE#J{OHH-ss@4IN>cGrvYb9_S!{*J!nr` zT3qft1p(QI$zU@Wc{%|` z2U&=<8gXy}4qgP_NGFe2Y(X5X4ZDqGmk{o&6#l+dnW)m?O?1psb()L!H11AZ)&-0?oX>%Bm6JgJ=J*^Ny zf1Y47IPrC-jT3M@yonchw}WLlixI2Oum;g?XX%>b81YrX=)%6+h*|KO93oC9hl3RI z$fK|_5qTo^6rc19R$Lsc)+~xZ;aA{rDWZ0BJSHXOSlrWTkETt6U=UnkhqV=F)ge0k z2&$sfW)N_eEyTcEjDi&>*qic74h2EaecjfH0e`#PR+1j&q_>mqmq5Cj;*e|ke$nQg1bc|;Hp{6iu z{;9-hTo`>qzxLo%O1vVAg^FBAR1}fy7wzWS_i2bc={5g_1|~ds%{A)$ZKI>x=FZ)= zZ{N1LtWPu_UtqGrF!8&{t1cfq46DHJu64Tou!dZ+=06^MaMLC{8ut8Sf9%J|{t3|; zrSV9uf|x)KfJ~OU?98|QkmG)M+hzB2-2IpBz1O(;@+;0V9=q$Y_ZhOE`@zjO|A3pq zefg40zRa7NemwqJf&fRTH7igj&m+p7F9+N|fY=mekcs zPp#_876l%B5R{fffha&Ue*j&-{`Er-5&DIiTD>UIRv_B)hd176p=Dag6L_xOb=Owd z0Sq%SCdI*cCi##eawWownvJ~KXa0FLd=QuYAgJGkmnM3{i+68>p>4fQ-w33;w|i;y z8=Uy)0Z!nFFC*{;kDH3j^!`K3XtP3P1Es{S3DWSd;HFLL?>24Hf3MYnnNHhJpY7^l zVamz5WG80O0+7PHL-DBpxeAoK{{2~-L}u#nv5EZ-`2)g7 zR@W%ns4SrA6K*?bpNj!W5xPOsZRDV%De`8|Pe4}wy&pi0{t<%XZCZw!aKPOVeUu*OlesYabHk<>G)cQH| z>`fhK4{qt$I&*X9=J^Jn;ne;)>Wt6Km=J5$IdL_4F`gLreF%!?9@K3;URkV6T;WsN z%d<}3N65a@mt5eMyf&L_aY5g=myO2`Ojz>6xpu&ESQ^&Ne=~6DGGHkz3%$W3(1pBH)?i5LGlCyB=sq;A5T!00_yFzRJ&mFS)0{&>KD&Jt4n=K z_O)WZtCeZQf9!n$=dq;0ZbaJw)Vv=!qjgh*OC3!M5#4l6ftMC2$AMxowPb5pOt*fs zE$aO}^I>JrA_5Dh!cx43`8`XQ+THLeJUF)n@Y-$n`KHb%IF4PP0=HfL8fM{nCCn$s z$f6!R_o(+zT>yn!t{7 zz4o2A!g#Ev=56t6aew0$dWDMT6$ytb$MtY~>XXtGYx-rDvZnLK;e3aOJ<56RfB*V$uaD-&ljNQVaWFCgGjv>}zzLK~^XtPKo@k5YeJK{+~sV!fn&9!LWE*#nQe zlBX&Fumu(tF9)z#&0eA6VTr?IZtt4Ds9ab(e*hl2yK9Qw=bWWJ{Oqzqt+3?Bq_-&c z73T&6J_o7&eamz3!2H3Vx*a?_U`Pn8!z?)F56+CWLtEVLa`Dpz`P;Qi@4S=jQ`eA0 zVlLRNG7FEX_cr#|jgb2o8xy3MO_d7G+^pksY2xjKxRVj?iBEm%3GU=nJ=pZ%*hRC} ze-W~7R{b=+0{6V;1mf_2cW|E_Lk#58QVjnU!=-?K@B@3EBJ&gR9ej?HCBz zEA!?gVGh}U99p$-OvdJ_lD_I$)ibNxe+O^KXZcd)KyQz$Yjt{Fa?ZSpJv5jo&!#^5 z_fy7EHifjPlc_SZnC11aHC)Hsz}(1unz^lc->i=0xb$)a*Sret2{`rfS?|8|#&r6vY17ivi=9J@Z@+bQ zZ?ZT$UHh-pf>gYFWAwBGu%z~vxp_9V=b2}&hUa(hR)4+c?%mycC{D{w>lj4oqJI-9 z^h#zkvzyt=T*h3*T+4ih`4;m8bBy^3^B>G>%$rP&#tNUjwtPgJd-^f32m+_J5;2)B z3}`Enujs4P*g=SEP_B3cF&6RY&kOqdpe<;mv8X6T^NPNN9xbZZQ{XA+P(cb=f|8&g zk3&^oplF;(C4={;}URK-d zS)z|*>fWQdFy1;noJh+`z0_rJ5){3A5tyu&vc;_C)Oe1}R2E(t-mCsHdg^7NeYFLH zgXT~LGFeNxI5JXLxUeG@>ws6)C%7{cEBUXuJb90F1Gz1!S-E#0zIiN=>dL{CoRVyPwyYk- zs&Bbq*_=^gExwyST6{A9UVriE(b|(I0qVO!pE00Zvgnk>(ZN~a>C;1tdJ<*zlY==D zJmj+HZLZH}_wCE>cX7o5)D27|A89G$awZCTu%{^K9h zFn90X>sR$ux9)^%AAa~@*lg^~KmFJaW%OsC$xV5~rg~NlSK*Gm>O*=fzsJfc z%=^b-e)6|;yO|ZtY0P$n{Vy{2F!wWGW4_6JpLvq`G4nI#x6JDZ{Yn@@<9Giq86s|!7b7zDGmwXs_b334@9;-bvHO`9DK^4mSAni zFuZPe6&;S3$>R+W|HuA!-~IW|=?mv?u>V;7qhZ$;TGb0Lyz`FwTXK&2D(yr;>&Yuc zm;H4Z?pO=(^vjM%)s5J*n{rUhsatZi*KBzL2!H=t=&2;8ei{#OZRNR&-FL+rtuNofS(?#i?D$0%6VTB<){wTDm;>oqtL;Yx}`@c}EAG#J-uw-V+ zCH{klD1YJQp8OwB{NqRS@mxNiOhwbnr}Xx%TVb=AVyGHetv_CKzOZM_85v)zb6zxQ z1LuhS?DUnX1=jU{G-cK2y1#0%mMoTg$lV{t3{>OMqiRB92;}-FpZrJ7+3L%9Y{}>y z#hA%vTd}UMcgpf~G?mQfbMd^! z-eZB`Wo1l*J}esNI=?pG-qIbnW<*1B zquG!V)bDoq@^S(gbsrSk+X`!TNjcLr^^Qmc&YYH(N`sq&vavOye(ZypN$%m(kewWQ z*nd%IYgeCvOH(-%sWv7JV#XTpZn4k*nscsE9R9d;@p`+EF{t0opN!NecnzmT^R=SZG>h55T)}*qd5HNAGsZm5 zyvqEZ`6Kfe@W2%4hv~2$&V>tLH}aYSN`JMW5%iOhSlcp2zpPprm#75#DP2($iYdlG zou|lgibe^aEcDV;%iPDp}Qq@YrP3rd3z!3^9gy zNVUPbJm#hbz9_yhP3{$#o6XulY6*^Lc;L zc<_75RiEJ43oq>6jxCHB+ZMJA$1IsMLT9P-3NV~k=N1}6FtA*HPRq~`d-Ww8ITt&< zgYcJLD2U-DEz7v@;nc<9&`nljF1|T9E43%sb})Bm@`lK5slMyvi!Wb#27jB|aGv@1 z?eW>O^UIcHbJk=Ma0KSw{&+h(IDrJb(Z5`MXZoS(Wd9@@fSj+#;Y1;L~38pQH zLPvktAWn~~Z-qh-w++nkl*66Dj58ey*UQW(zdZms4ubbMt$C~SuI%V&_6Db?C^^+P z7wz3WoE+MmIg*^xpH0j} zcv;;~TTM?-PKUH;2={js5|$Iab2@t3JLBs!M^gRmzJPGntVFhdO7ci%^H6el_ufU> zzFR-JeEBDPyFAVtXs7Pd`gczdxEu^T<&L6aB z!HXKg%k-o2Qi6Vmwp65rXdEQg;Kgh~)=<16jMt;fk-A7BYb>6v(}e=nj!tInw6DAy zDG_2?i6WL~9Fr-=dVk!CrjeDLb*#kq+yZ@qazKg7tumDa@e=2oH?@Dtr5z0K~aF`>W!KCku+!KLBFMsC_v{yR2l9gwmIM*Bv zOLyJ1_P5LLxZ~nbDKRBv+%&JM3QH%+_4I)+}JU) zaqZlUyQO<@m1pgc+>>K{kLQ+lcQ4JoI%|b*#WYwreSh1|q2%11Tj!|no?zb(Km24A zfTUp>nc~MbGWYBVU-;d({Un(O!TN{D%x|G6!M?yDg}T7Oxr%4y`@3aipVm zE2*s7v2vCyVOI(*?#$d%R?G@cTLCxkoSPilxovvaoF}y|Jnmz2JLHuwR!JI-k*7_#V& zDpq5%a+BE$dE+?ZoiKS78ip`9f%BTZOVq4jAB35)CZ?(j#T0M&6PJk-98=JEbb@9k z1gc6jPzrlQZ}~bl)5^y&I>Oh--5CFea@jYI9Dn&wY7YC)BS*-$KR}^;`=N_+Tejr$ zt;tX>JGGv-OiW(E;Z>5!9r^0Thl|$e45!$ z{dU8=w@NejsVh(5(tEVX>|(NK&8@dD9)IdAmOFE^_w8=Ubi{)e+Tu+0i>U>vq3&}# zigQBK4y5;a*>v%`o6?R0r$tv?{me6aQfz)MvF7xSV{-0?%eW1EX{+zkS;wqLS(pAj zi3^zB%*UDQnLAPL)p^}x%nz8Sbv&Wg3T-F%2Z^~KW*GTM@E)sUUZR14P12_H0e?mj z`F{=1M~)o-0X09IMhzw6y_4C>D<5nCdE~<(^}VwxAZgaV+PViGs9oG-e{t1NB!1XNU0-hU?$95Gr3#^ zivk08tyRATbDGPY@as#+bF{xGMK=>C#{HunEw+U2FxJ1n$`0ro+$vsyM$<*c(S+RF z=2HLS3c-!7DPXIRYW>?Ut>$|z)-x3c>;b#7N3?F*YBH!VLT4K}goQ|HgMX_HAS7)d znby5~gBi$MtX7M%Z|MqWS{U7}kSh}D5 z8uCMgAs>8pv}4X)PGMO<;d-qSZ%!5degU9{>=x98#3?+C%0HQBNQ`c(dxJK z&$3{r8E3x<-G<3R%6nzaiH~$#iIwU(J&49`vr z{7V0GV=($U-rLPnA?#Nd+RYHA&q$n>yx;1uo5>2yS6B2r+ylR}o7F952Z1491Pb)= zvpqWPII$O}i^e}Oa(`n(PV+Z5#Bq;qVSM*0VH%rn8k=zrKF4v-9n{jj|4(&a9w$X{ z_TNucAJaYEGkwfV@668ZTsz0!GdmXxyUTJ3D9Ry=q8L_GKrS&VUO`a_qOTeiF&arE zo)I+B81Z^ll&JA|6OtH@7>&_fKaKJI#JsPGahqRN^~|zpOn-jA&nN!`cB+r6KB}MU zs^_VGzTao@7ZKjFe96WB!?fck&mKYOh<@DpDM-)eMro36@n5`T`4)`6xVZlaghpmh zK3+SN7d<@ATd6_@q#*N!6)^L2X*ehC-8;${&XIcjIiGZVvgRN@V+d{9OWl#)cCJ5{ z=8X9w+|Ag{+kXz8y$wEd`mqZeNxB#94z-Y;AT;_eY}oE_Lu3{1n11{#U9TLEYHpTy zbT3Jf%1V)4Lx|hHlPqs{USs9pvPKRX@{;sWo~BQ6kz&#{9O5BEl$=>G?+{0r(Hmgi zEa%<^7tHq=W-vk88jTA>4Z-?XkTH*zO0Ch{E9s1prhj-IqZB7~cf)>3^$+PW*9Q&u z-+I^bq_a351lt2!}}n8KmXYKWP8u$&@OA5eCN=p8>37Zt3!Z!?F`W97a8|` zsTdOVWq)zIaS2@h*Pu~jOu1|zr~y+n>IylHNImEyA6*}(hM1pSgWKuTQUAuGMzinvm475ojs7PKqd1+U&X2>XRBtNvu(K4t zNq^`?L;K_tnvZ$S7(Je5_NE{*X=Q&s2E-El6ndXwh`Nd0HIqA*TgIJFo*HHpOzD(F zT9i#`A%sw^my!a4K;7gi-9dPSPGh9@+W12TN~>DsoQzK-8tPMG!xbbdfA44`THsP3RP0vGW6u2UW1o z0~6>9^2reRv5Gszz*VMd@0NXNHu8Ax_J8>BZ0bb*ESzhE#q*Hi{6$L`&Kk1uMGQJL zt4Vl$p&%x)w#MfKWC`A>TNSnxI-z1m6NYb4Zb?&`mNE@b@=StEF1tgqgtU7dHCx1%zW4BLL-z-pc&x?z;Ym9VIXXDnkYyB#{8=DOMj@g9pETi%3%|TzBGEKX~W?F%)^ts>~LvEA4noX z#Q{jrQq{K6jgy8+W0g>ElR5ekmN0#H_A**`=D*X4hsn63aiOu8tSjV zX`e(IZ_oU$wmW}= zfR6X*!MUG&<9mq?mTxH2f7#N(YnCnh{(|`n_AMLz{otw7 zj+zbJDPP~U>$atL?fS}9yKei!^2=O3;YDI&TtU_trx~Rr1p4uTl8sRF&?vb^C+W#p zyy~F?q^R>243U))_BRAW&Rdu}z`aO0#$fNzrUM)$z5$W~w`s^>+<#;4wf2$w-%dsW zFN?Qq;Uu;M@=IDda_6}k+P{ClGqQg_obT+~y&D$o{@;<2y(1&&I_Cz8$cB|e&a2L= zkiUceYqYn6Tw)QTizgWGRY;e_giHKpXA_dB+o43QstZO=kaCc$k(UDxTyn|f&etv{ zDJ(zXZ0Cn(uU~&Q^naece)NT{@buQLpgaG)6$ZAVQ^!hOe#yP0OrxYh@*g1OR&90m zkJW=f@aeWMjYV#vZJ&BXezxr=eC8jWs~ECBJNjn`wniV!UL(NSME9e}_z{PQ zUiXf^xli|^=e_!*(G8b2C14Vq4@+3U;7vnA98da%PW(3RVSoC5nVbF3^!+i)P^Q<1 zOsXXQU4`E!3jdVh(=k4Mc+u$yoxW)69*p;Fz3c&uAGqw;0Lle>POU!j5s&tMO*h15 z*64H)oiPGv}exhllBTNb0Pcy>QVP2%WKL;p~gN z-A&$bg#YM~oqzA9_~xX6+nhf<_6z3?G2Q|zb-xld(wV7ilX6Q;_H=AJrnj4o$?bd_ z>2nTpbrEg%GhAIn@jaBQEAT2r#r{6=wCZWsI$zsHm;IAPh`w^t@_}+)ttDQRmKE2Y;_XTJ^^2jpUEE#{(Z9Na20B zi|DmY%p(Ktx!Ayp(Mh+vKe z!AjSvHM}iS@s_VU);j6Q1%iLdt>3<;P7v~j z@7{CFg@5xR7ewaoc$&hfPLTQiH*Y>0_}r2_kFL2rZp=P8z?+@@_@qhY(DAcd&>8&X z_UA7-VPVT11M%aYe&XsSc=tu@L?m71+%|6>x_{8;eE3XrL}+dA*!c^!|5WE?zyG}R zeSTL@U4@@yws9YezD?@yhYt9x13O}Y%~BGzkbfv=1f#E~Gp}Prnd5!nb2ZmBzDiAL zwDza769{?4OwlSPN>(Y}YxTDBe0%f;&6rpws@1x}tbnW#bt??*&izaSdl#b~o?ktK z=PSP|i;{q+uaW*pwXnNiIy{NRR54I&DOu%YiJr>Kx3{3FhUPqOr6)xfRWQ-Zgkxv9 zihmk82=xeFe$@uV%`WH?{-nvAQ5cm8(iI z!x)!(TRx#!~U6(q=)JE&@9^^ySw!tYMSwi(PfN} zN!M17neO5$k`3U5K^bq|361h(Fd6^~HjYD*Xzmp^0Pbg&Im>mbDxq4u4S;hMYcV85 zn?-5#3p7+>P^>H99JIyZ^wBHqYs{!QQvY3JA2v#doCnvfLw_KpXcUO5#=uHiGE^Wt`8|Y-8^jlM3uy z+4aB!T`TY2yO)u$zJ)kv(h9n31w37!3v0x(;bagjylIqZ8W*6uohLUt`xx%_0(>iZ zw$$dCz)k0dx#is1+@;(NW7c5Mjek5d0IV~%#WVw?(td#jE(+1F{VkL`H{Fc~iDd9t zpoel6rw_&@VhX68b2WMzF^_5Vb}q{RxefiFs`$(ZIJlFdM-Lt)A@1CpF&s6u#l9;P zpLQhRo0}zB^_YcbuLgbE_ytMunZDI8sD`1wpy~P=)qiMeGFWn_ z?3d-RobXeSXjqBs=Sd#f*X2*hY^ld(ry}cdCG7E#A_-DdzCu(I{!X9lk;q|PKBAEq z@XhDWyC|dC)CRY;%tiChx%qwpJb^GqeqzN4$*7`wJ$cQxcmQv}Fufo>r}R_w8(n%l8-HbT&B)lbJ^ICB{q{sz_IK*>OUB=SM2_o?`M=HVeen^k zBf(|4UfRo1kABj5iP=NBTWF6Sv@4|?Gg}XVLM?wip6cy5z@2|HMz^BoaWN#nOBAW0 zO?#aaS6+(HWy??5%Hypcx=%SHj z7rTAY6Zjs+KSF1zxQrWBoy7ysu!#esgumiEl30*%9*MOLpeqL2oONaLZxBr^mq(we z&O~Ttth54pKRqYi&e+EeaEFWD(9;8M`~CM<=eK7Xsf>io(1Q?=iM8(!Y@ zGTJ$34j=M6Ck(A^z3;x(wL@^LKjggfW9RiBLuPC)eJlDe%3N$4Zn%DmfYGJkMq3b58Ql(78Y7t!?NxyID}87 znP^5`+yJ+XdVlUV;#tty>T*_a>D7~T+M?8$zbGA?$T)O{1E(q2o{~JJDT29V zNSv{h9&(!Qol5p3n?1+RCfmy(WS&9~IK>Q|Lyr#|<9}1MkBn^7Xg)k<*v>A{w67lE zd=^r*(?|)>Rs;Af(dWOz3|j}=^VLMIbbf`R?*inx_;{jhbPE-umJ#eirjX7F#PlgZ zssoHcVE_vF>fF%$g>zdJPki1n3#Yav;8ZxR$vGDx=Xsb269QXzw9K3_RE(jW(I5P} zZNZ%Bm48-ZLyN7I>2nse!4HI)GX(`|#Ee?x>~fY%E&1NQfy9?x{+9nB@7IfLUNphY zVpx)s-55J9b&x)r5X;u;ioH;&QpOO>W|vcG3i)r$Lu6g>Rjrb4u%1;z0_FK*7I2Bi zHcwWpa+azlfflI3GoJQpo6n9(UT6YU==V8qGk@%354yL5h93BW-n<1Nq2MzNpYyEG z@aye(yQv!i#5L*86%eNgD3aRI63DffjqP~6JC3$TVu?zp4|_dBGkFhA)|@<4^6eAw zzI{+@Yo7#)^SzLcaJS}Ls`>o-@wx_lmtTirQ$xN-gVAUZ2U}3g`CYjTU7?mJQOshj z4}X4w=$ZGDXVuEpNW0#^9gIUu8Rp%tvauYG7F+5jI7^o$Edi}@b~ zBA*|M7GPW`T16T0Sdxzyd61^Y!tImKJ0uou9;pby5h1ghM_wLKP7zvi5jcsLQNBuJ z(OPDhSF+H9V!0^qiF?T9WKX_g*$BRrKYzIKxd?s%fXoYvq(mfYaQRENr?D!FW$ z@rLJE^UP6-QEKRf?6jCmlLt!MVspUn##QeiZ z_Zx;^wZMFmti%kW>#Z{bc7n96_lzJ}+OPv%xU6z)Oy)(+PwBM*B`_IVKm#(Kj%@l6 zZ9ExYw!$F2CuyK(kQcYqJ*I_Z}b9wSVXCgx=}> zn@)2^U?=^d@5K1`?prYHIZf}sc<1fV>l{6B#sE9_>BO%25$Tr-G!|cmk~{l>4dFCm zBGn*WGuPyJYQVURDTCmKx(kHp!~QzC`@jCiclRA}NuOCmE`K!7>5 z&CmtXqo|vAAe3Nte>&-rV$40-;SR)=6;+qO~H6A-GR}D{&ZitB? zgz%g}=P%AnmsIA34}*;`t;gpFT|N9{g#0o8nRxR_KEI)!|1GSOA%M!Eg9qHnDO5WG zD-A^V=5kdtLqC`y376o!eNTWiG~+erO#$zR!+!+2fFJqljrZebXMb??*MZ>rmYBftAoHHkKR=5uyhG*eN@GJNY zybm9t8E7NghQ5b>f_{TO!5U8B5}tv-fY;#D@rC$ud;`82--92(`|u0+4g4$ofAELI zrW_*@B6aTJ>)b>=EO=iJB3f0TXuDy!*=Ryi-X&j>e29%zQc=v7BzB6)co5ZcWj31i zU^?iKF{fG+8-GV*JH#|<+UH6cN;1X*HINrCju-(G>4Hfv&lrpS?2IsoNe7(G*`XjM zwI$j(Jp&dG=DWm1HJjcJl-tXT<|Ng5F?Bz>&p+9&kMli@07xjY97Fv>SKfN(vE4 z*4ds|B7fB*UrF^kvQjR?`Z!S^Dq1>c$7r;u4{}4iOyJ~(|Gk8Jd)va!?j?m2o?NEb z)ANBqFxY-TUMWsCsNvQ;iZR7yJX`z6N{3^uN&zj z@_(e(!6UMVx6Z<(Gmv}<(<56_(4R2$R<8$Bt(4~}&yXUJ|FYFY>*x0be4^)vo+Db& ztfk_OQ^4%*oRpttDkH72Cg?=v5K`12Qgqr*BycWO-<&L6(2BP#7QVW$U%D_AfyzK4 zszZ?Xmhp_FissgEt9XmLCnDW+mw4@vIDceCamU3Qck%Nsl-0Y{XT48$;}eR){MqQs zs~{(y;Op(wnsC*xeNTu8JYU3zXCV@Mq8vW*R^>{;Gjq`2g*$nijH#mU*Z(>(50$Bu zy&`3kA}Wt!`%Fb*5+}Jt4dK(8-W<>nuMrswRL0Q(c<%4ZSW^&_aWLq$d!w2!)_+T6 z9Q0a5`$N2d#TzND6;H(1Z0Lrb33`KSpfy269Fcim`>qhl5dn)D5wJ)026G9`iKxw5 zG&XV5^b|!iOid=IZ0wIuiWPlvBQ=K#+UvE<^_kY$s3B@aR*3PH(9Kqr*bO4(ml7zK z7A9LwM9EbYD~xFqHar3C^?wt2pMTR_30X-a(c=rW)+|N#czi*TyqKa_#FP$;7udT) z+BA8}m?(UL?DvqDM2+b2HUoJ(2C`PjYpZ~Trb>%HZpaZ!HZ7S5EtAw^n(UQiMGz?U z76QGvCl(~HVzch?yx%fJUVkjTB^n8< zcDp5ejC`=uZc@XMm|wEvljF_gHbqfWB~w-Hj)2u_ntn-A6MDwVSZyJd+?KaFR_P8X zGHC^(sH#e!qe+cuPR~&T?Mk57e^_q0?9p|9tQ_=`y7xAfA~PvJpX6`$io`Mu`68;i zMmJ=SWm@EZGp6C&iAal6(|x2yzXA3SX z5-v}HObO-c8 zE52kVA8gOdOx_7!tn~Qj$va6bn7Au%Q}O6+b$LhY^47wdNMzkaWNlh$pGOt-WX8&x zZRF+dj>f7z0a+G2SbuUQU5Gd;>9nl;K)@^UA_{r6aDU3kSj)|Xzoir+twO+>c0@Qb zOCa5Xq(_L%d0zKZp|ACmzTLE_&=uJgI}EiK}omu8-^ICUaA{8Qd&x4uAVTxrkfLoxq*Ut>9L1 zYq|B@2JT$$OWZ}=X6{n%a_&m*8tw+}>)cN6UhaNwPn`o~Klc*%GE9MKa2R|8z6rO( zx8VEm61)n(fVbe+@LPBn{s{jA2T&8SA=aVo=-cRV^b~rAM(m)xEJe{S(v)Z)R=qJfJcyO_nrATCZKYFDn5DcKb%L!oF=CS*e~N38&%7^G@ijzzm6 zs-1}i1I zXnzJHpCzVfEmI;|U(JQoN;Q|~md%z`DKK5i3F%-Zoqx&&Dbzej36B`?mK0@pHAWmu z-SrGtL$1&nBO^^~>>_vF`j_hP1$sL!@GeMWuGJ_!mj=KwLM0mbwnA!U84Sr=lic%G z$mL6w1|m0DssnSSV4CiwcU}kSWplM03lh`-@VW@OM%4^lD3T{!VNXmT*%V?ykD}>8 z#P8pO@PF4_7=I0DelbH2O-m)nN?9TpOwmI1jR}F8Eyk8-JS5w=QH^*9iO%a_#N@aM<}hQJ|K1 z1g|WM(NgieQ-u!-(A9IQGI}=87f83c6VNBJ$di23I`1k?4`YOK#bR?h-C8UWk9QO_JxNB;37wixlV#0! z>~@dR+@k8S_Uu*~dL`)TdITq>5m3uelO>X@JB!1S66u9}L_=MFjc5Dcp7Z<6Y@uUWM=X=8MAP9QOfNq4(0@_W zjD@GnUf?YkOAmp!zdPF=)76${#k2jC&IuV^%bGsF7|(mvY}M$mT(3q7uqoBo<++AW zPs7-Zri0P`1>tj!oSTFlet&OQfAcx<_Gl&@Te765!(4WuQtVoFvfUkwgnCo5RD^T8 zXFSlda@H0#Kx&f849wjSfq^MoiGQA0{#$7r4k!7?--eo-Bhi+YCXeL&-UshkR)xrW z5gD`pvva2NDw;w>GJ30sn$8R#rF_ZYuTzw*rqRmd(VKd&BC7091lT5s;(EV9be{<( zX*?S=U4O^Z3t+vv8sAS;*o5<@%U}A*Z_uApMQe??8ChC zuEw8uz1N#gcXVXZxpLVI+;0XABj^_e;Sos`pXnVG1Q11Hz4{PVle%U#$B7=b*m|is zMq9c`uTScBr6?2xGK^axU#QE_d{>6U-Hrpud6gLw zYdS5b2@;+;Q)|(-a>0pO=W|Lyy+oA zip6l(U{|6|4=gHV!w9vsw)Z8ReXw9F&l|xHA3CZhk{<}iQi(iy8gf%}G1}F+!fLk9 z>ipn?PKKC!^wCFi0n0;;fVWl?edjdEshR*4O^4s-(wUBqP%>b?K!5MH`zFok3i-UG zE~2=t+j)f=zF6?b6cIedm#oFDQd^mw#3b&h2@Pr)*4MQ2yE*xZy)q+;QL ze5B{7hdOMSbb<4rdw>6bAa~!0iQr;&Jen>3- z<8FWV;fEidBXnd|ug-UkfcW#HTk@xVj7$@Kyt=Jr;c-1Pdw-(HkB{*^DA;NBT||8x@1YOd%Ze5sC(}?#q25dm`6y`w{t5f z^5-DN!eo(o>GU-jX2-*RY^lP&g;19o#5p_B-l6e~wto|!+#3#`^;oa+`Yk^6;?U?2 z=_TG8$96k%`z?p_aQ^CBe#UeEPuI&biVlhB8r4>K@6*@A!Ly$0*W@YhcON4SL-y}o z@o8nn$ss#4{MTOf@`c>NSin2#{3$f@6y+PB7-@@sE}&j<@(SmIQ_x4wUTb;Ra_2ZY zQ;!xbcYijWA`A_|{^eb#j9$=)Bj@6S+?dXjDaRs(D7iJDAB(NzK`0aRaA@$5)@w-f z8zHsmwhg-#6+l&-VMWuFL$*+nY?7U1gY7(I3wIuxG5XpeCqemtm|e#@;R|sW`+h-v zm<1yP8g!v-N)m_=XpCxsesRfAy4M`8I`_gnXMZa!cJ6e(g$_8YiRI>e(QAO>ft$#B z04_B^AASnXeiDplUwEP8cY^Rc(nUKN#Sq^k%FEl{5WHcjV= z{eSXQawAcVZ=THYl7VX29R}-owGz~^$Fu@?z1td{{qFJ>%{ahC(wN?+^QNjJa+lB3 z5SlMHz%0~1?*P~E=A+BE$X#Cm$?!sQ%QyMG*rOSvZ|#MvC;hU&;Ya1h<%kpeY$EeL z{O8ZG*S6?)3pbiuwq{i=T7>$-KYhZAbPs7&va?Gj#{NB$LX^;e*Q0LB-o)^#5P~l{g!i4S-w@1}2aw09@@1p#T5?c${NkWRp>I z6%z>nqyh(#c${Nl0D=?-1{Q`Ph?9A99Dnlbf96m;?tb+DKZ^#CKJ@<=t;3y=pP1`W z`2c#77M%b900000000aCd;p>V+yO)ZxB>VAXadj!1OqYyR0E;|#soS9d<6;xJOz>k zzy=BiXa=4K2nS*ZqzFa`hzVi|mI>|(R0`A!ObeO|+zdPn@D0)q91cznpbqvAB!3T# z5C#x55MB^^5gZY65!MnW5?T_D60j2367mx~6KWH96Vwz$6jl^y6o3?%6si>56!aC= z7Kj%97i<@@7t|O47)BV(83Y+L8HO3S8S)w^8eAHb8wwjp8?GDj95fuT9PAw|9dI4& z9ts|09{-iaWqO4m@5wj6Bpl_&r)Zx;^qfygvRvNcMdU^jMxsXQM}SB+NZv^bNjOQONzO_nN58NRQ6Rm zRfbi*RrppOR)ki@0&?7qZy;=HEZ<$*CJ-H7>lz6OEQzC zSejWZ!?G;L@~ps$ti;N!!m6ys>a4+1Y{k}W z!?tY4_Uu4HN?=SzPCO;xJ4*7w$R_Bq&3u6|;_i9QqgiT%d8#W@eLPJUxd)JfDy z>?_e{ni$nd)k)>0a#A^|b4aZZ)(7i@zJr{g-=N3b>VmGQsTN2z|Pe(5|)bxL*0 z_`j%A$*+IxtBQW(9*F;&v9_+3U(2uUuU4nF&sx34y2id5b(^>s;y%)UBfpW;sMAb& zA^u0L+*WRDAFX|~@>}QC%5CHRlHcmHlh^65lh?`bfJnMS(dU<`^Q})x_Pj5fH^Xh#cz5Of=>J91)>I`xRxr5vx?mxMMyovsY axKHIy;=b+dKN!cxY&7~87-cI}0002ZI#{#- delta 30922 zcmV)cK&ZdG_W}I#0Tg#nMn(Vu00000dHeti00000%&3tRKYxv5ZDDW#00Dpi00qYY z01eEVbxmhyY74G{|>g4lZ@@mP|WVq)$lmZK)N zM30FHxzF7BC;#a=p5yNMFtfw#{AQl_eeUxv&<*Hft65jyokGL+e`uTRM;pz@yD)$A z@vd!S{qyP!@bea=L+$FJUh1QM8mwU&snHsz37V?unyJ~Et9SH)zS6wTZu92(_d3*2 zclA_n^;Lfj(Qu8@7@e+(nx+|=r8#;{(uexGv#t63Z~xWsds>|h7|O%Kl`7{d;S&HtVo1>oJ7&{VE&!(+*`L zzt$#f%4TfA=6=mxbJf7c()68xAk9L+Ht&k3B! zNu10njP*KnFpg6>ji2ySPUj5H? zOSzmYn820v!-J@qs4DgE#B9tExf}~m+)RkU8DM3-NO4HwTC+ae{~P{1nLp)4%9Q;C#YArV^HsK z@1TXkU4#}6_Y>+9-r1;cxW~}qQQ4v;!hMJOg*y=S5BDNkCft>1K)65Avf)le%Y}Ou zEg$Y)G%(!9XoYY`qe0=`Mk|K99IX`YceHZ2^U*5d3_z=f(*Ug&&IL3$oDgV8I4jWl z;nYAIe+2cuHVo>s4h?4t+9;eZXyb6spiRPgf;J6j585o8LTK}F9-%G5$%M8HXB65h zoK|S-pw@qzpw@8Ppw@7^pw?~saK51(!byjA3}+tNDV%<2=Wq_9UBZcoc8%s|*)5!s zX!melqCLXNiH3zU6b%ojDcUQj>+c=Z8txO$e_Avms699`oWE#PIEm5z;Y>ycgwq)v z7}bS3D4f{n;Ba=ML&7PJ4h`oyIxL#||L}0eqa%Xa`$vXz9~~8*0BCf07N9ZVseq0S z&j)l&cv7Ha!!rXN7oHC2`0yM-Cxj;oIx#$3&`D8e0i7I`FFGYWdC=JK3_>lQMyMk^ zf0xi{;R%Jtg=ZCN@zg>so?ocNlMJL0#vDpkDjNpkD8$psqhD zsB7LF)OBtN>N>Xub)CuKX^w6SDyMG`e`+t>5uWwv&hXSncLg;ori4!d=0)JK=?d?rUzAz89~+Kp`hw9GpKsZ3aTEn!)FmRC#c#y z8dPl_3#vAchtDkNiD=H3CxfclQ$f}2>7Z)!Oi=ZEHmLeN7gWuj4{FZ55LEqMe+;UA zF9lV)}1AbK~bv%`Dg zvmtsvs5SW@s5SX8s5SX0s5SXGf2cM2TTnCn??J84Cqb>rr$MdNXF;vc=Rut>z6fex z|0AgV{?DktkMw0w8S_<8XOORhTIYX7{cWXx2X&tMCaCrQPc$>_ztPOJdEpZ zFr8h(r(!z0hR?@zb_?472h&zZy8w8c%)JSG8`ZTqJm=0PjdqQsku6J>e>9e4%aUyE ziB~1g;_Sg$Ndh=P$U*{vKxx7fvv1*%vK0!nX`wBYkfyYSmREvXC=C!=x;-e}SYF?Q z7FxPJC`7||?u_Kf4)pQ9_x=CB&z9~i_s(6bOhLl~x<_j*E}b_W0O z>VvK9IC+z?FfN7xJBT4re+HnO0X9)q$_il)Re8R8NKaqk;jsc-3OOR2~2<9~VTgS|}0b-WNIU#e0pkp^MLS+k8!m&89T@Z2f)1eIXgSdtaQ@*#CQMKAX+gOcU4$eYt+s)hs)l(N3o`5cdNFd~9*1KA!pP zt2iDP6UI5rF!PLgfAlC`kFOVeZRHY4#Mx*9JMAu)IK@XqA@T7ChW!bDh8N7- zb8yM3rSqTa-+uF_Av7Bg^Vj~jH$F`(2_GE~KXp3<>EoZ)UY#BO&Bq#N zBdoMA(aCG3OsrYSndnYrpcNoNL9r27^hy50;yu&OIh&OCf9&Yio-Q;yVH#4owZ0v!Gb66_Gqk@d>bF~RPmGH0r@;|+01S4A zy9dEI&!-$Nf0$P)&4X}f0pP9xeYg!eizO3rTeWTX;UC;;b+KZpz*ld@Cmh}M;lb{1 z{k$-uxRQQ+94pC2eai~<@$F&vks~@@OlM|Jo?%eEsyFY=7xP7xMc5F0G|P(smMhcI zqHcNx2657_~h4~9D0 zSg~+~x38}kPD_g2`HRvmr}u{)j_}}e;sfACMG+)h z{vtn=@VSvvown>}$H;!h!N|B?3`C-W*X8l$Be_x$*9cq@*Q8O6Rx6ZFka0|_BVjL%&DCkLNX&4$*<;MZ zUHUv&nGU4q48)@%2p*qNN5mB=;=}|&JvKZ2e~_nBq+(`Xzr}t+@=MxY$>Wz`yR=ke zprY-wyGQjospuz_F^#Dpk=;kWAkm_J4=w7iK1t~9QJg_Kt@H#&wF+T0e5N+OOL2UZ zlSJZn@F|dYm0fwDG>AQ^I!AJvi2w=MhX{>ha*_RDcDqg5LG6lV&<;yYvfEsv4T#H3 ze-l!MrC1ko3YSOdM6xER5o8{&La7&ug;Ji6cq243k93a>5hXW31|eZ*RfKZH%fbLD z=X?sTptr2wVMiS>k#~ZFEK4fckjDjh%y+Z#ER_cGp&L*E%Dh3U$(;PSBW12sN>L@CY z7#B-`!k${~v$Mj~GAVVaWD3;vcCf1$-+-Rp0Ge^w9K?rDYU zyM^cRAGYF+0$$e+b)K>f`}zmQh7`<$($s5VolCx`5ATt1Wb?%N1< zWAsaY@3tR(QqNra^nYEs=EOBM`fl(m2jW8JLuOh)Zd*d+#zUdh3OyomNZraUf@(e@y^P-1i9i9%q7c zP2Vu#2QIRkAngi(Tzwl;Xml5M8!J^E|SI6jFkW@ zXLNV3+oc`So`>!)vs~F?w_C~_D@EcyUp!*;nIQjvf3F|(M3%!$k> zvzgh3eL@v5+67b@R79!|A`at4UZKh%q77b@d8!)*b(ymmtCyx|C5x(2m_CM_oh_mG zRDUX==ns_Xqbkw}G4EAjk(|hR(li+js%o%8lO3L1e?rdF1Q@kP#SiTAE#|Q=_@N3@<1Hkac!D{s*Ox=C=B32Ej7ut_V(LXo>JyR4;X;=cU#VQk z5L`VJs58Ws6_-`s}`u zPd)m~%-mTErcWPS*IoJk1Jm1=CDTK(#P0JFe~G>mLeLz)x$2Cr>ju>f1=x$|DS+q$ zQ9^N)jCa0-58X_h$w{?SWG-PWQ*)HYp?pjDcQ|_hr6HOKLgX;LfVdCPXPuylB2FW*b%XTb^6LbFcOeioJ8YBT^%Dv0=x ze?8!M!r4t`GhUg&%<`PciTyM6LBGS%kJOzP?VR7|>jSq%^0a_rvNQ+10A5{pNpTEI z;id^!Nnpe{lPED|A0yh?2?*jCUiszpMMw2-gW-@cR{Kl zi>F1)8y0tfo`)rBwDE4l@qcB!C?S@ye7w3 zj2sjgO5yfVQD7fEtB}f+8``<+Y~0(tb1kMOcoQ6>4ltAt{S-<2ad)cU3<(bMl8wVd zHEyfvbYEc~A>XX&!SQ3@>7|fdth1baky=YALH8j^uk#~s9<>VOXL#8D2%$PpoNgA6!PrvOzOpy*m~yJkP@s^T2Y{ga_j7$whtPuy)NrPwL7m zQ*cYtzHy9@v5oTC3(RXSKxJk5pm}gPL>!L!Cjy)}-{FYVZViU}7IvCD7i#+th)w2T;d~)MzV%P^$=Ze>l+up5X}M_@RsKQ}BrQeLP;E5J0UPB2azbqtui} zUs->y>`Nd$j^iwl_cJHXZSTt6a$-+0w`ke3?{h1ww`NY9)$#4iW)5^OU-$GIWGQSf z%>y?`X1Phy{;TV>kSuHO&+Ne;-|&wU;t| z%X|Js1b;R`Z=B_Zc_rljlGG%dwf_nzned#j_71%Q$xZn@S!|kyUsIs1!EWS2d3gaH zI~}=KKsrR(E)I=tpo%hGTD+GKGNfE6ql|_tOyY^S7{}+-Qn{2z%7Uy0SDe_I0)D#< zTyAe{03@qD*kJiI@8oz;e?sw8AloiOe^)-Ccr7-Zf##No-^QLvLaD7Y`bwf8frIBP zrY1*|%Ld75NdZymmyPz)Gp&lF$&Co>QnSrVR0Yx9#JUt&un^Yg^5r|GL9k`f-<)<6 zZ^+z;aO0#;x2cAi)MT3kBDG;vZ5%XP$8=;AgfR?5MrxRr0uAFjf3)j~?(Qdc=_%}= zC|H{Jc+H9hOK^$mA1y21*wb^PsHao-lscJDHFl!0a|CtGk&&%LPY*RPqirW_BV^kN zdJ3s}2~4#E4U7#QtCzua!j4Db!Hqg=7c&F3Cu-~TwNk)9JqlO6kWkbpuCZ?1D#Ycw zPGu?fA1&M2Z=}Z;aNj@5I#leQgta!S>1p{%}8V~ev?#@;7Fq)vBQ)# znX)Vozpg(+4%*#gb=y-nUhl2p^JDCH$zur5D(Zggne%iz0A;KmuPP)cu^Ire#ej2a z(?Fm_uvJ0?;o5;yjs%sGEd}*KCEiKbKtO7cwG&DdumUO`f9YikSXmsO4Y9qEI zDWta&9?Lx~RX z_(;6S6B2B1N!VPz?p$TSB8{5dCL5|G;>=J}a_~Z!I~>bdogROpm6tkD$*~bw>T{Pn zScwNVVc|pVf6b?H66q*=ykd*T-ONb|=w`7>&fIF^S;1^hlsyW8%iGVGW@fW-yDf;r znpTkQgmn07jSu61g|_j$s)hTc{brZUxfPQcXWCF zMCNSfeC877Qsy?Q)fG{p6GWFv4QD9b=aDPa)b9bRe_F>`s^Z7>rJ%DvYhiTRW+t9w8r9va$== zTwd245bXy5^#;n~>CzCkQXPYeHr}8;R&VOrv)Lqhq;Cm?e^hj!uqA%|GGw;nWUPXP zf2uVV6Do%WE|g3KizMF4JA|+B#3B|%38ra(G-RO%u}=qd%UOekNU7N^DC{Iuwj4kN zU0)rrx!pGMJxmW!W5~VJ?w@wU4b#YjZfmvQ<^s%n!s@QxSXm9lkoEyUh>}=gV%$wg zB9`Y*k+Jg=VTR6RcxLbe-G<+8FrM4N{yyo>DJ<0v zvNWMzYAkQG_R?plg^e)SeU#HGuT}adY-N97FTy@j*)u_{Sh3`#A2t-A3B(ZBk0*OYUdc`<{?v*4_89?ESmvf6WWF z|4}bIdL0aOt?n8Coe6r?op(*KW zWQm`u-^R4=KiH4_D9;S)vSvAsaF`JFR7HX%sz1;ZY#nZ`gof4DbZd*+?%QIqoat?k&RajX zb*%pEtl5TrvTg&V{B@97LjA{+Z8h?gYnXbi)aa_7JLehfo#Zc*?VOa% z9B=3Rgw}(q2dW_C8M|A10Ib^I{svcRyXcqvS+*U0*e1(1vgXJ?u35WgZOuo5c%?($ z1o1*di4;+>r9=$pXM43~f0Tly<1juBOZ6+VpPH>`4mE1i+?P=zZuE_@$mguMKDs@= z2uh-?h+`~MWya5fv9m_XTT9Jn>8IC~wv}|A_<;VL4JlUwX-WmPiIY&*XQ*?E=wOM` zlURsTmnUUb1JvN@(Sen!5(>_W*RXdX=Zi-LkNyY({X}_umU^Ixe=e$o2m-hP3&t~0 zu>^x&lSxXrQW58jR;BC@h5Tiu)s}EZ)2_HHnsU9aP%CtXCO@I2;_g%woYS$8QT&t0 z`%T_ZizRNsW3a{2@BrzfdBLD%YE4(fTd83Z=Ews6MP>~7I6Cyrolg+a)tebh1~U(TxJei8iOx z24A*1wNV&F!mo?U6^@f4?Lmt*6n8u8<1paXkJ4OLm*8r=WlGm$HS=r)doNIeLuKh) z2s=Bv9h;=xf3;EMrQM~+>TBe*1q)6i+P)W+sN(n7QGv62u(Mc_cF|$0b@59!XE&C^ z(%pX_aru0%5qq{24wtfZ`eDqoNrwv5jADjS5;5FM4OpmkP#<3>AZv_JLl^BEgsI<^ zt+8Uaecu?eW#qA2>1m}xPf3OH+%Z~W--otSu2&YRe^(Fn1|#(@jMJJ}hSsX-jZr^% zWo)Znt6o1bTGQK|;uCjF=9e;x7n6M95v>B_lbqmM?7#7=%d~?i5~EO@pIp~?WgI_K zYNNNtYjku>mp7;{QblQ+`nMzOm^O|dsGzt9TdByWUokbG$oJS0ay#-d2B`341jbMy zzEoCef8+;hT%urTNhsnYJ);p3I;CPW4tMkH_RHVvE3F^9{Jnn86?U`fm1lmxt7G|= z^^cS*PPf~6mD2^pO?q6;Xj{oyI`z^k-s>-)dYQxRb}Wu#xvhs&?L({Gt$2Nn!&Qgn zH%WzTt*s$L0hF4^;|isqG#*8)pTKxcCm*cofAPkFq>SSiYq=lPj*RZKBQL`b=^2N#j0TRpiq*jR+9mw_6ce)5vUef%2Aa^qy`r{OOsaYMk9i&H<}3r z{N`x0NLXi+!zMe!DSOcB;Z1!e;JtXqJ84n>)d=mqh30rzxpt!HcS=YC{ko2EbT)=i;O6) zhf`svY;!a@St2$^&Hg|r6LoplcMm;Vz>_P=f7KYO zjYX;O&`PBqs-op1q9HF(VS?S2enj$1X-PU+2 z7V6jA%FJa(nG2a~nOmv-nu0VHf5mGD-2#kfUQrbVmEOX0LDgAg7r}$5n@$RbEs<*L zh$TEem7}seN;k;-YibR(*XS97ua$UdNPI{!YL659(YdDe*)1jopr)Y zWOt4P%0^;p_xx)fFS0#0z3~ed*!v?GFeDg5JetDyv-8!?|Z(*ao^f= z{kK{6+c3|@3RaFItT{H_Ztpak2_d}Mj;wbB5k3^DS3M4IraGc4DA_M0D=+A67@fU(1 z*>F@QY!`;0($zgk$Y6I@g%NQLpJgv4H!wk_ms!QEVNPZ?G3O$_WW7F7H|*;Xd;PVQ z)Q$Qmy8N@;GSXfBG6<6k6%aZVQ7PjmRwu+%tZqfBm?(?v7_@f$e>@%OYL5RV*$ScL zZ{p2ek@U|yLLYHI2-?bMN3i23?X8U^f}h#`*@rH=_q@&LYjfI5rKP1(`wn-{BEMs( zV9)<*#Om^{S7c(B*Lxk-WmboGy=*74vfk^mTs>lO`7je~@~Iw&ZJEvCITaNSx3b>n zv_QZ{tgh8AixsQze~r>A+^6bQSZ8D&43@u|O=Y9ti~8^bCqxvnGl4>s+mJ2Z#5vx| z$V@vkz|2S4qEJ!{Iy<4WX92lE2n;KWAzvZz#*C>%z9|?}X%uY$?=cG>xpQM~T^w5d z$qVOR{vb=n1g{X7MT)IXzq7SS*g4fZL1H7HIb-yem`U;`f31mA3YYC?A&-UG2QREOZ8Wop@q z&WVsHkY9##f7XMhZ#X)dI(qp*8+y=_HQ={pmD{hy7`xNDw(9?C> z)=&Z<5vtx|9Jk)q)dS>2D~k8{A^XUQL&YVob1Oe-SW5nDjO2O_fdQYv6`z1tnXSvAY-2dqk+dhqu3uTFIz3rVnn6X{gtNy3yol zWYv`~7P=tsQ{=o{8iYLR7|4x?V6TuX zwNTzEQU|4OMG~mbFPfk%2`@T9Kh<5W*il4C-C2Mnj1|4*7=Bqw$M7rH&Pns*PJoB; z>--{b5luXjY?H+AL$Yr&6SJ9RA9oUPaohny94yC)kGoR4cf-G&efC|S+_kg%`p#Xu zfBtdVWp`h=>mu^PR@W=3LvqX8>$7XAKR_oHY~TL)Q+0d-kkZHC^f=#LZu!=HX{rnD9iDSURkJ*XPMhIPQzZI(2;hl<0u>dTE^fATB0{picO4+o1?U#Dx}~o`33RnobyLpS0L7Y71{CCk$Q14c~BsUjH?kiT&UQJUe~{0g(X#ejh@Z3dy;@#vp0CGwcn-CXfF93{{8o)n znD$PX^W$dFwL&OI6!!WV<`!r5-=dz17YYe-O`-sxt^a`8H@>er9wwDA*|6AZ1OMXY zNc9lS#6mNpxWLR9s)AGFIgKb+rXGb>kFVqrfM^^SHJR7r&+2{vJy3kCf1+V+A0RE$ zt#QZl@JL+@y0Td@^wWdvUh*Ryh7vVCVrZKAnsA{jnPqnGn_IfBSa9LjeC}O4KJh}& z%)(1oT>cHOYu6`t{e8s<+$wDDodM*wox7guXghK1&P(j>uU&Teugitr4I@+ZxQP)R zzmEc?Qv{vK7VUd}!EwL1e@9QXpCfnCo|v?;r?;Mo=?}Cg(xBUr_y+t)F-2w`bHbFJ z1*k-ObcYy?=ke;MrGnu(%ja6580Tp~1x2Aep5URFMUgpQRJ|w{t1%-YY%*fO9noYa zXmh!meY`i?*6s^7S=~;bo0ql0p`lFA`md%@OX5~^A{Pbik1c8>f22&_ZSZ8US#?`& zPOF1!ms$euW~;^Ol+0{QWFIYbu4W(I;xZ${x%km7PLVx5JT0=bzBj6FV^AmSnN(UF z&_m3rx=vk8$awVKAC0qmw|I_Q5cyybiYFC=LDAehAIScOd9A*%Vh*r2*4o#W>gh>E z`W%AIHqtxE=i^|Sf3Wp9)2(aiQ{WY46&jEtCdzV##t+d@R8T~j-qdd^r4SLlQ$ZPC zUE!O*`Lp&F>E*3*R@T1Wx(gOML0dO{>AKJEoUg1L1b6Nguo&1 zN*KFnkicTc>D?H933KNU+0G7bX=3SSt-6ICJJakB@0@m5< zb2E13gpu}r*1d zGLm4mNCVW1e`-PyBgL3EQY3rNyMtx#I8RT%(b}bbwZN{%-&1_VLQg9p%yIM@Q@N3N+^5j&jCaovXWy)?Eg0u_}#Qph!@lu6xuN z4M%jDT4>|c<9BSQ4)vdS4QFSfray*h;14^7;I;1sf3uMuPV=ZYKO%7JIs6FUjOPHj zb*%6RJ>ksf%u47h!irX*F}*HJ<;+D=Y0j@os=&9S?>I6@Zk{6d!Hx*->z z%fS=IX>1P9&#}3?S(YpUp1}8@)X`C*U!86su^Q9uTvnWYgOg*Ag)sJ)r=fm0$&E|F z)9cY~e|y=mRtX~|y2iu(aZY6P?eT zfb`1FB(NL0u#N&84T(r(Wh(j7FN&a4o*2{vdU0Ce=jP^6vozBZXj|D9u$~nW zX@bjHJ>YbU)8X8cq7jSDW(g}TExrhO3nEQzf69%chtIJGgZ6U{kKU-XHASY-=ccL9 zMguc+qM|DhlcHoADK)gFwxs&kHD_)-aAT%<-DfMy30Ypz(@7LtD>gNGSN6;E(JDYcG)GX-)0Nj z1GbReF59dQw>iV{Y02eiO@?g&TiEHe+ieb)lqSf2|5|;p9-wnSe<(bR z>l@~fmg-q|O?{x!0G7Nqs&BlT(zlL}+c%cFSwB{v^xY*NuSb;{Us}h0mwdpukT#Tc zoXD1_L64HytQTp)AQdAOy5&=#eli-i>Jh0&J8KvURph#;7bb874lt}q)D?wrp+?0# zyc`uAl||&TJJ=aNxsr$1QV>2Ne+|JVt}_TodlO0RyyodMI%bq%Icf!~7m>hCZ_X#- z2X^jyeI=|};VHB@oj_JNqL!4k@asKkxbUk<&|cWEmJPRY;tX!aFn{q?9+^zL6u#qZ zHS_k^IcrpF3T}vg?J{oX1L4r@wV^BidOCQ#TtnQ$a>GlEnm-K;Q9wp*e-_?ec)P~I z(c2e-f8-3ZeBm8u+<~XyuRc$@>9Zdk{h)*6*ly%n!$?QFsdOjO5RPJ@EaQ|RxW{BY z$Vo;bOO;bumy6U`cNXP7HeM_YLJa4|LUD*!FjHj9CDx7X?=OFKdIB-h^#dUb-VVrf74EZQ%(oVIb-Ig zW)%4(?UY^juSL=yi>$r1Q=ha8wLjscc@K9HoDr|%FMoD; zapY{~une%@?PoiIf5<+ctR3xO)#i}=Bkg6;j0G&l6q-yBea_utsrkwt&}Ajcv%C`l z8*%D3%TLk3BSq>%VfV?luuWdDWkI*6rNyI#X$ng(fAn(rw_R3Qw(iQ$ots}9khL4+ zKtP5aa$xQ1OD?I~g+5RAP`ePQMH>|JIj@KAb89O*$pxR)f4&SSKJd&>we#U72m-NR za{pH@`SN}^5#HDLIyK7aA%m}h0tnQFI7^*^#Yr(z?5MUERBcrXzEW{#s$-XYw!Rmb z?5}7mQ*gibYuHZ1oT#=}XG{AS!!DCD(fE2VYOI~iOlBdonmMN)$KeSPY+-=llw=5~ zEb^ENq$&8k!^h$mQ8 z&dX)p0;P&4|6|tdwWKNC8xg(}=}kA`+54wd-s-LVxd$H8?t_KepMgOgwF!>)o@%$B zQrT6RV==keRr4x}&14_$fB&XG5A?o0(DNHj1Bdnve^{ygCu_Bvt^UgVRbVljtg|Z@ zR!*^lZGF#JKbskB;CGW&f@exM6z?j*NyVae58nJ)Ha%a0 z((6k{Qqv$_E2Ecxw|GNIE0xZg-Z`@Lb?q5G8SBnKN~4dOQ}o%IoSr5}aGtFwGsT%a zQ=zmue>NdGApxFrL8;EMoW=|I$Y;oc(mVol%b1e6+7@~-T+&lQ{^vRA`bh~&!=&*7 zE*&nF@z&fD!HdT8OO2Z9&oo@rV7k7SLz%jl<5-mS@q0Py`!qguCr3TU*vFyc4VgzC zM1Fv6@O5V>OL1J*rBWG{5Hbwy1MT>k8%p}Af3Fk#Noy;;(N6A2hD=(;69{-<+!RXI zaGAV7SlusAwNu?tlqi!ged$Zx_ut>Gr-ancFs>f8MfP`>iMx1iGZS&X&cXRcd;UD z9uGmcdx@H4h~^W?bE|64YM1+M>%4Pk*N_mMV)V>G@=e_IHRvT6m;gG=eZ z;wu}{qM}3b0Qkrao33MdqP_C;NhgI{;&Hqp*KJ%2!Ol>qGf4Kc*KhLst=exNe?0w^ zlg(xukn1;Nkstbk!Bo(QyFKP-4B)&iV^%V2nA7MU#@Ih`Bo_Zk-v7kM_`h*6YO6k$ zhjGEjaxmWXPyCAz|M>33kp}PLWIy~V%qN*EnNR(H?1!g{Jq^Y`-VG1lT16k?h5tY2 zgf~0eErRZYzy8~7-3MzVxdLxEesA|#R;Vc#|4Z^4oAn$O3cGv;r%-`eLf7^xGEIYd( zRG$QMrULoJ&14IZ?q%Uwk8d}NTi3Aj6QCUeb7D?zae$nyXU!fzM>zXrngdymA1ssd z40fQ0&G)lAN`q{rmxWpR{1BOb@;nGF%agX&rE3AYV96#xzD~NUq>Rm|W=xajk#DkMXErZ3p?yxQnur#E) zMqa3y21Q80mv1H1OfBZTiryoglhLrKPKXN$wV)qkn17DaF+r%IKSai^lts%Ene;y#`~mC6cyQ;!`|6`jFlYqd*?1 zCiWaFC?GMUoB4dG{fo%hu}P{}3v|CQ9b=(nG$7=$tDY#f6pbUUQXi*IU~!@-tf@u4 zUYWW?^@%LSj8)J(f0ihqltWFXv8aG#g}U(ZoE~saln^@zbXc@Ag}A=uJoS7UQvcuUV zNixr|K+SbXvM>{y$4nC*?an5K}Bf#W$Ma$c9k!XgcF+m%wx)nehLCNuVx6FJe1?I5{yS=8z?)e?a7lPyG`o4Tlf&YKw|ZSBoH@nk5KWGtBW-PV zdpcaK&4Gj(M=fb(PVze>FE;8l^T2tKM9&hi7HoiXe^kFgI|;yofb2su*-d7iPJr1- z7GbSs9GrlI7lAj^$s<;K5C?0=ZX?+xgnh)`>?9)3;fA`*IR8t2nuLB4=6 zAxI`ei`|Kngx%+P(e1K3O~{F`XV{)zh#*g} zn_T#~%gzZn9$w-F-s5Ch&T7W$GptE;I9R&oI7WO_FuSquc485Hl2gR#2)mlUmDEtZ>E=AN~iO1xme-ev(I~>upBnT$K9d_DUa8{k7vk5^} zblFV;&a#!5c&k~k;RO3qKG~@v=vhTG=k1g&ip3su;0T;JaV9}T#E>MxCQ^7{S&P-j zaUPiiY`m?-;gme)pjX6Y;CM&CWV2UaHEl%< zf8wyWX4_ug;+9w|PgsOWKv+R+GO=dP#5tUbSivfF3^SW8CIQQEoMdv~;LSLXIAM8~ z-omAIw7Lb(!uu%32(n3XTR4gq1gF|2m|8*tt|nev9Fu*j3e#G9>k^I4ufJ(7;>}OE z#Pcx}X;7yq0kTq8#3itKm#TmFp~7#xe+cCRW_xXO2yEA!`y4QiEM22p>tBYiRw{J+ z*20=FU#V2I`s@?&|Xn_>mDZVfZk5*e|lJ$nQgXbc}BPp{6iu{wc?3 zTo}DW-}c~Ai@d6c`LdEvlvR=J5gnH5_i2bc>9zco1|~dw%{AJBZDV8G=FQu-e|z_~ zd8}Ww99<~cV1zWe$!l&uI|8er$y4p{G{IVO@!EfX_~A{P@LRX%A7MX9_DqV-C{9Fb z<;4VY0A#Y%WoNnbhaC6AJ1={X;~u>1k_XJ2FTdh+^O1X>_<$jMxF6hl>kqhT+?OxD z_{$voxli77)80ehxo_Ib6EPrTe|n6DT8{>5d{<3`G81YoZ@9-RVlh!v>RM7~3q7=G ztD04K_+e0+4+NqB(ExP*<~NT#Lg*W6sQJH>|-QOXfk)NSOAKJ(9O;eEL5`#}3Hygb<(Ubt@?3~lRect;@Jf4$vHqu=1z zOAl}YkG&az&wD*oWTw|2Sw^1~DjTRpc5RS`e+4&f(tf{blX0#M%y!v-_Izg#3)7Cz zCEGEB7Jw999l)FF?AdDVbkp-T55R0FC&_P)&sCw+`ESqLWis1P#cCIyhLl;nVR*X@-~*nIkC?cLhRPoc%FJ)`(r zFyGz6)MNI(fb&??VK<`h0BYP1oYA|f!=-_y`G{eAn=ii_+T)jQq z2_)@_h*xuxe~lOZ;J9b?*~-M34AP+i;|&P76s<^Q^w35sG3x`v;iJ?ae^*hCPM}yX>#qlrfxh;@>nZ1` z3IJ@Lg(WKhtTu~JD0^Ar^jg|FXD%+~*A0MI>FS*3@Vn+{k3PRVU(GN5G3hOceT8|! zfZs`~|Fz|(@X&(6pLv`-J77u(tkWVm7YxphwLxp#;db*g1?Ah-OYgad?AF$jL}DH| zYzhlce`pWX_t%Y*{fwOnQp~1Gg>G&(@VPkoa#GyMDEHKDw>`xjpKALWZXCIA&Pjxv zG^chLpL_{nWA~b#*6e=rw07-!xK~^E&_nz8f0H>$*Yv)<<)YA?yK!($`fu$6AxC-s za1w^eo}7J{~%=^ zV^c_rI+zMGhgng3Tf_Ctjm*u=r9EF;RNR(?ux>VQE4jOQqE)t)F9^=)f{jOsCq zgfXTX6KH1M88f``Cgb?d``vI#v(qbNElo;VyK+SyuF%p%fOu}pmTWH28O)^zT9$O3 zbN}?^ts`Z4N~`t^N#UTPy+LFx0jFlie>S#_gcqvW&cT-1$;HsrGQ6N^-+Up+-4rZ*u zczdRK=kB@Lj{NM5);nBi&(2tqzP^xVeY?{e)9JTo%t+5HbPO%I>y9oXG^}F~rHc-v(5slu z%uePK<}&6g<~rsx%(s}Qm?O+jn15$pXWn9}G*HVL)Gr zT-jKq`VK-|gHqWmh_Q&*xSuzk2Yo>!^?yZ0DVkS}CG_f1z1}=eL5B)b$P&~9eR&+J z`YL_v7}gRgs&wlZ6?bZp68e3w5KSl)d=Q!3qg^AYb*M+pK*h^go$3fA17lLH7maG;ntHrZqwz}xb@Fm)>q9$71d9n)VcTT4ELd6}LC%m2V_>Ce^HVINO;DjBk#we4czd_jKWK z?!ChMN4uAw51$%)1*U0-*|VO0`sm@q@Bby|b$^9ll{k%qo*U)A#o8Aw%8!l~O4jZS zN^h3I!S)!5!%JDsf}OHy|CRmM=zr?nq01h-a*?{~l7aZ<@j$9G3)8Y{vgP@bb{MO^ z{ru&_W5iZ?FL$``bngAa;ltIZj|0^Af_`&Ay?F5nOQM5w!ZT-v7WX7d+D(I55YmEh?Qq?rk3I^U%^kUCpEz3``}t?G)86#D_t3gN@3!Y0?gK%R9em#9`R(G1 z)qvR_9P@?dl@dJ*=L|+?%v`x+ZimzRdNBAqmn*sC?d_?a)gu+S`x5ODqm@5k|}J90{oD#RYt2SA@uSTVrf-1 zx<=2Dpc?0$#ArA+1w$xYgAV4d2n{azDDdXahJtpa`WSt+`7dcg#(&`sZ6mq;@ZqCR zKMiZA0>50n6$0mdG*J@38ui(k+O&fDPlvGym^jxDsR7hin$UF~<|Ozkz=iM-yER|{^( z8!*zo4&d2WoR4c8v43Z`WTBANwq$9q+0rBs{{D5)Q%+3(G=9Ootq(zgB&GoM(I2OZ z?cHyrJ97fpVOEkBvDle@qr1I0qpb~WqoMCzukLu{_w7+rTSmLO4!GJj{gI+*Nh;nO7wp>i*?kGWTe%x@t*ei7;Mo6Osc23C|&qNwquArC_^7wG%eYM`aV>&K?myw00Z zIHPIV07bezEKxF8vFuV^`iUa&sz{9pI^>k;TO$ps{qe~-?HncL6mwz-nXbHx0<>-n zR`gfI;iagj#(ynVzX^GuBgfsAFyIshjD{;t8so3mFGX2vUkBT1`zuQG$3PF z;vYOh2`~5b|A68jJ)DbYbGc+HnqD!jx9_BtcDocq)xc)^@!Io*U29Lx_*-1_qe(ls zMjdCQuS_kpt^bqMt^Ks?t5#dlYQ3M__fgD1Gao*zC4Y2=KyG;Y>3>vRE&hzxo{ZjI zh)H()%9Hwfr>#gwQ^{N|8_$_-wsP^jwQG05S?g^JQ&*9 zTVbS;PXK%*b9ldjg^(*IVHtFsoZPT^J9+2h@C(cOi{xuZMDsk?*A_UMyW+NtXi9Fh zm@9o+IJh~em|G&+CqJB-WFI{l*~x)N zo%z-_?K!wKl|_+iW6~sMZ1JvU$AYi9=9$HjYvqg9JA{l$d(hwBolszOq5*B!hHFkf z8HUYDaPwgCl*qC=w~2ljhxxAt7If`Yq&~)LIDb8wuLZTHIm`y;3g*kqBg}W0app

    rtF$QWp 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 diff --git a/dbm-ui/frontend/lib/bk-icon/iconcool.js b/dbm-ui/frontend/lib/bk-icon/iconcool.js index d5655d4995..36b6216124 100644 --- a/dbm-ui/frontend/lib/bk-icon/iconcool.js +++ b/dbm-ui/frontend/lib/bk-icon/iconcool.js @@ -1,6 +1,6 @@ !(function () { var svgCode = - ''; + ''; if (document.body) { document.body.insertAdjacentHTML('afterbegin', svgCode); } else { diff --git a/dbm-ui/frontend/lib/bk-icon/iconcool.json b/dbm-ui/frontend/lib/bk-icon/iconcool.json index 407cdb5afe..22a64a58b3 100644 --- a/dbm-ui/frontend/lib/bk-icon/iconcool.json +++ b/dbm-ui/frontend/lib/bk-icon/iconcool.json @@ -1 +1 @@ -{"iconName":"bk-dbm","icons":[{"name":"check-circle-fill","svgCode":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n","codepoint":"\\e1a7"},{"name":"exclamation-fill","svgCode":"\n\n\n\n\n\n","codepoint":"\\e173"},{"name":"help","svgCode":"\n\n\n\n\n\t\n\t\n\t\n\n\n","codepoint":"\\e1f5"},{"name":"help-document","svgCode":"\n\n\n\n\n\t\n\t\n\t\n\n\n","codepoint":"\\e1fa"},{"name":"auth","svgCode":"","codepoint":"\\e152"},{"name":"apply","svgCode":"","codepoint":"\\e144"},{"name":"increase","svgCode":"","codepoint":"\\e1fb"},{"name":"close-circle-shape","svgCode":"","codepoint":"\\e1be"},{"name":"right-shape","svgCode":"","codepoint":"\\e1a3"},{"name":"bulk-edit","svgCode":"","codepoint":"\\e15f"},{"name":"funnel","svgCode":"","codepoint":"\\e1bd"},{"name":"copy-2","svgCode":"","codepoint":"\\e1e4"},{"name":"paste","svgCode":"","codepoint":"\\e1e5"},{"name":"keyboard","svgCode":"","codepoint":"\\e1ae"},{"name":"draft","svgCode":"","codepoint":"\\e145"},{"name":"todolist","svgCode":"","codepoint":"\\e146"},{"name":"file","svgCode":"","codepoint":"\\e136"},{"name":"script","svgCode":"","codepoint":"\\e137"},{"name":"fast-script","svgCode":"","codepoint":"\\e151"},{"name":"homepage","svgCode":"","codepoint":"\\e158"},{"name":"template","svgCode":"","codepoint":"\\e147"},{"name":"unlock-line","svgCode":"","codepoint":"\\e166"},{"name":"sync-failed","svgCode":"","codepoint":"\\e18c"},{"name":"sync-pending","svgCode":"","codepoint":"\\e18f"},{"name":"sync-success","svgCode":"","codepoint":"\\e18d"},{"name":"sync-default","svgCode":"","codepoint":"\\e18e"},{"name":"pulsar","svgCode":"","codepoint":"\\e1b8"},{"name":"abnormal","svgCode":"","codepoint":"\\e187"},{"name":"normal","svgCode":"","codepoint":"\\e188"},{"name":"unknown","svgCode":"","codepoint":"\\e189"},{"name":"code","svgCode":"","codepoint":"\\e139"},{"name":"download-line","svgCode":"","codepoint":"\\e1f2"},{"name":"invisible1","svgCode":"","codepoint":"\\e1ff"},{"name":"variable-manage","svgCode":"","codepoint":"\\e1f7"},{"name":"visible1","svgCode":"","codepoint":"\\e1c5"},{"name":"sync-waiting-01","svgCode":"","codepoint":"\\e18a"},{"name":"script-template","svgCode":"","codepoint":"\\e138"},{"name":"qiyeweixin","svgCode":"","codepoint":"\\e1d9"},{"name":"sql","svgCode":"","codepoint":"\\e1cb"},{"name":"daochu","svgCode":"","codepoint":"\\e1ed"},{"name":"version","svgCode":"","codepoint":"\\e156"},{"name":"copy","svgCode":"","codepoint":"\\e103"},{"name":"database","svgCode":"","codepoint":"\\e101"},{"name":"eyes","svgCode":"","codepoint":"\\e102"},{"name":"setting-fill","svgCode":"","codepoint":"\\e104"},{"name":"resource","svgCode":"","codepoint":"\\e105"},{"name":"ticket","svgCode":"","codepoint":"\\e106"},{"name":"pc","svgCode":"","codepoint":"\\e1e6"},{"name":"edit","svgCode":"","codepoint":"\\e108"},{"name":"loading","svgCode":"","codepoint":"\\e1a8"},{"name":"help-fill","svgCode":"","codepoint":"\\e109"},{"name":"unlock-line-2","svgCode":"","codepoint":"\\e10b"},{"name":"lock-fill","svgCode":"","codepoint":"\\e10c"},{"name":"un-full-screen","svgCode":"","codepoint":"\\e10f"},{"name":"full-screen","svgCode":"","codepoint":"\\e110"},{"name":"minus-fill","svgCode":"","codepoint":"\\e111"},{"name":"plus-fill","svgCode":"","codepoint":"\\e112"},{"name":"add","svgCode":"","codepoint":"\\e116"},{"name":"delete-fill","svgCode":"","codepoint":"\\e117"},{"name":"refresh","svgCode":"","codepoint":"\\e118"},{"name":"more","svgCode":"","codepoint":"\\e119"},{"name":"arrow-fill","svgCode":"","codepoint":"\\e11e"},{"name":"attention-fill","svgCode":"","codepoint":"\\e11f"},{"name":"attention","svgCode":"","codepoint":"\\e120"},{"name":"up-big","svgCode":"","codepoint":"\\e121"},{"name":"down-big","svgCode":"","codepoint":"\\e123"},{"name":"arrow-down","svgCode":"","codepoint":"\\e122"},{"name":"arrow-up","svgCode":"","codepoint":"\\e124"},{"name":"right-big","svgCode":"","codepoint":"\\e125"},{"name":"arrow-right","svgCode":"","codepoint":"\\e126"},{"name":"arrow-left","svgCode":"","codepoint":"\\e127"},{"name":"mysql","svgCode":"","codepoint":"\\e128"},{"name":"redis","svgCode":"","codepoint":"\\e129"},{"name":"mongo-db","svgCode":"","codepoint":"\\e12a"},{"name":"kafka","svgCode":"","codepoint":"\\e12b"},{"name":"approval-node","svgCode":"","codepoint":"\\e155"},{"name":"down-shape","svgCode":"","codepoint":"\\e12c"},{"name":"import","svgCode":"","codepoint":"\\e12d"},{"name":"master","svgCode":"","codepoint":"\\e13a"},{"name":"cluster","svgCode":"","codepoint":"\\e13b"},{"name":"host","svgCode":"","codepoint":"\\e13c"},{"name":"proxy","svgCode":"","codepoint":"\\e13e"},{"name":"node","svgCode":"","codepoint":"\\e13d"},{"name":"check","svgCode":"","codepoint":"\\e13f"},{"name":"deploy","svgCode":"","codepoint":"\\e140"},{"name":"switch","svgCode":"","codepoint":"\\e141"},{"name":"refresh-2","svgCode":"","codepoint":"\\e142"},{"name":"stop","svgCode":"","codepoint":"\\e143"},{"name":"dns","svgCode":"","codepoint":"\\e148"},{"name":"member","svgCode":"","codepoint":"\\e14c"},{"name":"spec","svgCode":"","codepoint":"\\e149"},{"name":"timed-task","svgCode":"","codepoint":"\\e14d"},{"name":"history","svgCode":"","codepoint":"\\e14a"},{"name":"backup","svgCode":"","codepoint":"\\e14f"},{"name":"account","svgCode":"","codepoint":"\\e14b"},{"name":"note","svgCode":"","codepoint":"\\e150"},{"name":"single-node","svgCode":"","codepoint":"\\e14e"},{"name":"dba-config","svgCode":"","codepoint":"\\e154"},{"name":"db-config","svgCode":"","codepoint":"\\e157"},{"name":"default-node","svgCode":"","codepoint":"\\e159"},{"name":"position","svgCode":"","codepoint":"\\e15c"},{"name":"plus-circle","svgCode":"","codepoint":"\\e15d"},{"name":"minus-circle","svgCode":"","codepoint":"\\e15e"},{"name":"rtx","svgCode":"","codepoint":"\\e160"},{"name":"expand-line","svgCode":"","codepoint":"\\e161"},{"name":"star","svgCode":"","codepoint":"\\e162"},{"name":"search","svgCode":"","codepoint":"\\e163"},{"name":"plus-8","svgCode":"","codepoint":"\\e164"},{"name":"star-fill","svgCode":"","codepoint":"\\e165"},{"name":"unlock","svgCode":"","codepoint":"\\e167"},{"name":"return","svgCode":"","codepoint":"\\e168"},{"name":"link","svgCode":"","codepoint":"\\e169"},{"name":"new","svgCode":"","codepoint":"\\e16b"},{"name":"drag","svgCode":"","codepoint":"\\e1a4"},{"name":"warning-2","svgCode":"","codepoint":"\\e18b"},{"name":"exclamation","svgCode":"","codepoint":"\\e16c"},{"name":"close","svgCode":"","codepoint":"\\e16d"},{"name":"check-line","svgCode":"","codepoint":"\\e16e"},{"name":"early-warning","svgCode":"","codepoint":"\\e16f"},{"name":"warning","svgCode":"","codepoint":"\\e170"},{"name":"spce","svgCode":"","codepoint":"\\e171"},{"name":"password","svgCode":"","codepoint":"\\e172"},{"name":"redis-2","svgCode":"","codepoint":"\\e176"},{"name":"mysql-2","svgCode":"","codepoint":"\\e174"},{"name":"es","svgCode":"","codepoint":"\\e177"},{"name":"hdfs","svgCode":"","codepoint":"\\e175"},{"name":"delete","svgCode":"","codepoint":"\\e178"},{"name":"excel","svgCode":"","codepoint":"\\e179"},{"name":"history-2","svgCode":"","codepoint":"\\e17a"},{"name":"migration","svgCode":"","codepoint":"\\e17d"},{"name":"switch-2","svgCode":"","codepoint":"\\e17e"},{"name":"remote","svgCode":"","codepoint":"\\e17f"},{"name":"clearing","svgCode":"","codepoint":"\\e180"},{"name":"alert","svgCode":"","codepoint":"\\e181"},{"name":"rebuild","svgCode":"","codepoint":"\\e182"},{"name":"clone","svgCode":"","codepoint":"\\e183"},{"name":"associated","svgCode":"","codepoint":"\\e184"},{"name":"rollback","svgCode":"","codepoint":"\\e185"},{"name":"aa","svgCode":"","codepoint":"\\e1f6"},{"name":"data","svgCode":"","codepoint":"\\e186"},{"name":"audit","svgCode":"","codepoint":"\\e190"},{"name":"yijinyong","svgCode":"","codepoint":"\\e19a"},{"name":"kuorongzhong","svgCode":"","codepoint":"\\e19d"},{"name":"zhongqizhong","svgCode":"","codepoint":"\\e19b"},{"name":"suorongzhong","svgCode":"","codepoint":"\\e19e"},{"name":"tihuanzong","svgCode":"","codepoint":"\\e19c"},{"name":"shanchuzhong","svgCode":"","codepoint":"\\e19f"},{"name":"jinyongzhong","svgCode":"","codepoint":"\\e1a0"},{"name":"qiyongzhong","svgCode":"","codepoint":"\\e1a1"},{"name":"help-fill-2","svgCode":"","codepoint":"\\e1a2"},{"name":"2-jiantou-you","svgCode":"","codepoint":"\\e1a5"},{"name":"2-jiantou-zuo","svgCode":"","codepoint":"\\e1a6"},{"name":"tools","svgCode":"","codepoint":"\\e1a9"},{"name":"todos","svgCode":"","codepoint":"\\e1aa"},{"name":"manual","svgCode":"","codepoint":"\\e1ac"},{"name":"minimap","svgCode":"","codepoint":"\\e1ad"},{"name":"backup-2","svgCode":"","codepoint":"\\e1af"},{"name":"host-select","svgCode":"","codepoint":"\\e1b0"},{"name":"batch-host-select","svgCode":"","codepoint":"\\e1b1"},{"name":"revoke","svgCode":"","codepoint":"\\e1b3"},{"name":"en","svgCode":"","codepoint":"\\e1b4"},{"name":"cn","svgCode":"","codepoint":"\\e1b5"},{"name":"list","svgCode":"","codepoint":"\\e1b7"},{"name":"influxdb","svgCode":"","codepoint":"\\e1ba"},{"name":"summation","svgCode":"","codepoint":"\\e1bb"},{"name":"folder-open","svgCode":"","codepoint":"\\e1bc"},{"name":"wenjian","svgCode":"","codepoint":"\\e1bf"},{"name":"drag","svgCode":"","codepoint":"\\e1c0"},{"name":"gaokeyong","svgCode":"","codepoint":"\\e1c2"},{"name":"fenbushijiqun","svgCode":"","codepoint":"\\e1c3"},{"name":"danjiedian","svgCode":"","codepoint":"\\e1c1"},{"name":"zhongkongji","svgCode":"","codepoint":"\\e1c4"},{"name":"wenjian","svgCode":"","codepoint":"\\e1c6"},{"name":"manual-2","svgCode":"","codepoint":"\\e1c7"},{"name":"clock","svgCode":"","codepoint":"\\e1c8"},{"name":"auto","svgCode":"","codepoint":"\\e1c9"},{"name":"dirty-host","svgCode":"","codepoint":"\\e1ca"},{"name":"saoba","svgCode":"","codepoint":"\\e1f4"},{"name":"dongzuo-xiazai","svgCode":"","codepoint":"\\e1f3"},{"name":"entry","svgCode":"","codepoint":"\\e1d0"},{"name":"gaojingcelve","svgCode":"","codepoint":"\\e1d1"},{"name":"lunzhi","svgCode":"","codepoint":"\\e1d5"},{"name":"gaojing","svgCode":"","codepoint":"\\e1d2"},{"name":"yonghuzu","svgCode":"","codepoint":"\\e1d3"},{"name":"pingbi","svgCode":"","codepoint":"\\e1d4"},{"name":"hongqi","svgCode":"","codepoint":"\\e1d6"},{"name":"jiankong","svgCode":"","codepoint":"\\e1d7"},{"name":"mimasuijihua","svgCode":"","codepoint":"\\e1d8"},{"name":"jiqiren","svgCode":"","codepoint":"\\e1da"},{"name":"qiyeweixin-2","svgCode":"","codepoint":"\\e1db"},{"name":"weixin-2","svgCode":"","codepoint":"\\e1dc"},{"name":"youjian","svgCode":"","codepoint":"\\e1dd"},{"name":"duanxin","svgCode":"","codepoint":"\\e1de"},{"name":"yuyin","svgCode":"","codepoint":"\\e1df"},{"name":"warn-lightning","svgCode":"","codepoint":"\\e1e1"},{"name":"unlink","svgCode":"","codepoint":"\\e1e2"},{"name":"mobanshili","svgCode":"","codepoint":"\\e1e3"},{"name":"qiangzhizhongzhi","svgCode":"","codepoint":"\\e1e7"},{"name":"sqlserver","svgCode":"","codepoint":"\\e1e8"},{"name":"qianyizhong","svgCode":"","codepoint":"\\e1ea"},{"name":"liucheng","svgCode":"","codepoint":"\\e1eb"},{"name":"kejian","svgCode":"","codepoint":"\\e1ec"},{"name":"doris","svgCode":"","codepoint":"\\e1ee"},{"name":"daochu-2","svgCode":"","codepoint":"\\e1f0"},{"name":"daoru","svgCode":"","codepoint":"\\e1ef"},{"name":"piliangluru","svgCode":"","codepoint":"\\e1f1"},{"name":"cluster-standardize","svgCode":"","codepoint":"\\e1f9"},{"name":"fill-1","svgCode":"","codepoint":"\\e1fc"},{"name":"kelong","svgCode":"","codepoint":"\\e1fe"},{"name":"yuandezhongjian","svgCode":"","codepoint":"\\e1fd"}]} +{"iconName":"bk-dbm","icons":[{"name":"tags","svgCode":"\n\n\n\n\n\n\n\t\n\t\n\n\n","codepoint":"\\e206"},{"name":"check-circle-fill","svgCode":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n\n\n\n\n\n\n\n\n\n\n\n\n\n","codepoint":"\\e1a7"},{"name":"exclamation-fill","svgCode":"\n\n\n\n\n\n","codepoint":"\\e173"},{"name":"help","svgCode":"\n\n\n\n\n\t\n\t\n\t\n\n\n","codepoint":"\\e1f5"},{"name":"help-document","svgCode":"\n\n\n\n\n\t\n\t\n\t\n\n\n","codepoint":"\\e1fa"},{"name":"check","svgCode":"\n\n\n\n\n\t\n\t\n\n\n","codepoint":"\\e205"},{"name":"auth","svgCode":"","codepoint":"\\e152"},{"name":"apply","svgCode":"","codepoint":"\\e144"},{"name":"increase","svgCode":"","codepoint":"\\e1fb"},{"name":"close-circle-shape","svgCode":"","codepoint":"\\e1be"},{"name":"right-shape","svgCode":"","codepoint":"\\e1a3"},{"name":"bulk-edit","svgCode":"","codepoint":"\\e15f"},{"name":"funnel","svgCode":"","codepoint":"\\e1bd"},{"name":"copy-2","svgCode":"","codepoint":"\\e1e4"},{"name":"paste","svgCode":"","codepoint":"\\e1e5"},{"name":"keyboard","svgCode":"","codepoint":"\\e1ae"},{"name":"draft","svgCode":"","codepoint":"\\e145"},{"name":"todolist","svgCode":"","codepoint":"\\e146"},{"name":"file","svgCode":"","codepoint":"\\e136"},{"name":"script","svgCode":"","codepoint":"\\e137"},{"name":"fast-script","svgCode":"","codepoint":"\\e151"},{"name":"homepage","svgCode":"","codepoint":"\\e158"},{"name":"template","svgCode":"","codepoint":"\\e147"},{"name":"unlock-line","svgCode":"","codepoint":"\\e166"},{"name":"sync-failed","svgCode":"","codepoint":"\\e18c"},{"name":"sync-pending","svgCode":"","codepoint":"\\e18f"},{"name":"sync-success","svgCode":"","codepoint":"\\e18d"},{"name":"sync-default","svgCode":"","codepoint":"\\e18e"},{"name":"pulsar","svgCode":"","codepoint":"\\e1b8"},{"name":"abnormal","svgCode":"","codepoint":"\\e187"},{"name":"normal","svgCode":"","codepoint":"\\e188"},{"name":"unknown","svgCode":"","codepoint":"\\e189"},{"name":"code","svgCode":"","codepoint":"\\e139"},{"name":"download-line","svgCode":"","codepoint":"\\e1f2"},{"name":"invisible1","svgCode":"","codepoint":"\\e1ff"},{"name":"variable-manage","svgCode":"","codepoint":"\\e1f7"},{"name":"visible1","svgCode":"","codepoint":"\\e1c5"},{"name":"sync-waiting-01","svgCode":"","codepoint":"\\e18a"},{"name":"script-template","svgCode":"","codepoint":"\\e138"},{"name":"qiyeweixin","svgCode":"","codepoint":"\\e1d9"},{"name":"sql","svgCode":"","codepoint":"\\e1cb"},{"name":"daochu","svgCode":"","codepoint":"\\e1ed"},{"name":"version","svgCode":"","codepoint":"\\e156"},{"name":"copy","svgCode":"","codepoint":"\\e103"},{"name":"database","svgCode":"","codepoint":"\\e101"},{"name":"eyes","svgCode":"","codepoint":"\\e102"},{"name":"setting-fill","svgCode":"","codepoint":"\\e104"},{"name":"resource","svgCode":"","codepoint":"\\e105"},{"name":"ticket","svgCode":"","codepoint":"\\e106"},{"name":"pc","svgCode":"","codepoint":"\\e1e6"},{"name":"edit","svgCode":"","codepoint":"\\e108"},{"name":"loading","svgCode":"","codepoint":"\\e1a8"},{"name":"help-fill","svgCode":"","codepoint":"\\e109"},{"name":"unlock-line-2","svgCode":"","codepoint":"\\e10b"},{"name":"lock-fill","svgCode":"","codepoint":"\\e10c"},{"name":"un-full-screen","svgCode":"","codepoint":"\\e10f"},{"name":"full-screen","svgCode":"","codepoint":"\\e110"},{"name":"minus-fill","svgCode":"","codepoint":"\\e111"},{"name":"plus-fill","svgCode":"","codepoint":"\\e112"},{"name":"add","svgCode":"","codepoint":"\\e116"},{"name":"delete-fill","svgCode":"","codepoint":"\\e117"},{"name":"refresh","svgCode":"","codepoint":"\\e118"},{"name":"more","svgCode":"","codepoint":"\\e119"},{"name":"arrow-fill","svgCode":"","codepoint":"\\e11e"},{"name":"attention-fill","svgCode":"","codepoint":"\\e11f"},{"name":"attention","svgCode":"","codepoint":"\\e120"},{"name":"up-big","svgCode":"","codepoint":"\\e121"},{"name":"down-big","svgCode":"","codepoint":"\\e123"},{"name":"arrow-down","svgCode":"","codepoint":"\\e122"},{"name":"arrow-up","svgCode":"","codepoint":"\\e124"},{"name":"right-big","svgCode":"","codepoint":"\\e125"},{"name":"arrow-right","svgCode":"","codepoint":"\\e126"},{"name":"arrow-left","svgCode":"","codepoint":"\\e127"},{"name":"mysql","svgCode":"","codepoint":"\\e128"},{"name":"redis","svgCode":"","codepoint":"\\e129"},{"name":"mongo-db","svgCode":"","codepoint":"\\e12a"},{"name":"kafka","svgCode":"","codepoint":"\\e12b"},{"name":"approval-node","svgCode":"","codepoint":"\\e155"},{"name":"down-shape","svgCode":"","codepoint":"\\e12c"},{"name":"import","svgCode":"","codepoint":"\\e12d"},{"name":"master","svgCode":"","codepoint":"\\e13a"},{"name":"cluster","svgCode":"","codepoint":"\\e13b"},{"name":"host","svgCode":"","codepoint":"\\e13c"},{"name":"proxy","svgCode":"","codepoint":"\\e13e"},{"name":"node","svgCode":"","codepoint":"\\e13d"},{"name":"check-search","svgCode":"","codepoint":"\\e13f"},{"name":"deploy","svgCode":"","codepoint":"\\e140"},{"name":"switch","svgCode":"","codepoint":"\\e141"},{"name":"refresh-2","svgCode":"","codepoint":"\\e142"},{"name":"stop","svgCode":"","codepoint":"\\e143"},{"name":"dns","svgCode":"","codepoint":"\\e148"},{"name":"member","svgCode":"","codepoint":"\\e14c"},{"name":"spec","svgCode":"","codepoint":"\\e149"},{"name":"timed-task","svgCode":"","codepoint":"\\e14d"},{"name":"history","svgCode":"","codepoint":"\\e14a"},{"name":"backup","svgCode":"","codepoint":"\\e14f"},{"name":"account","svgCode":"","codepoint":"\\e14b"},{"name":"note","svgCode":"","codepoint":"\\e150"},{"name":"single-node","svgCode":"","codepoint":"\\e14e"},{"name":"dba-config","svgCode":"","codepoint":"\\e154"},{"name":"db-config","svgCode":"","codepoint":"\\e157"},{"name":"default-node","svgCode":"","codepoint":"\\e159"},{"name":"position","svgCode":"","codepoint":"\\e15c"},{"name":"plus-circle","svgCode":"","codepoint":"\\e15d"},{"name":"minus-circle","svgCode":"","codepoint":"\\e15e"},{"name":"rtx","svgCode":"","codepoint":"\\e160"},{"name":"expand-line","svgCode":"","codepoint":"\\e161"},{"name":"star","svgCode":"","codepoint":"\\e162"},{"name":"search","svgCode":"","codepoint":"\\e163"},{"name":"plus-8","svgCode":"","codepoint":"\\e164"},{"name":"star-fill","svgCode":"","codepoint":"\\e165"},{"name":"unlock","svgCode":"","codepoint":"\\e167"},{"name":"return","svgCode":"","codepoint":"\\e168"},{"name":"link","svgCode":"","codepoint":"\\e169"},{"name":"new","svgCode":"","codepoint":"\\e16b"},{"name":"drag","svgCode":"","codepoint":"\\e1a4"},{"name":"warning-2","svgCode":"","codepoint":"\\e18b"},{"name":"exclamation","svgCode":"","codepoint":"\\e16c"},{"name":"close","svgCode":"","codepoint":"\\e16d"},{"name":"check-line","svgCode":"","codepoint":"\\e16e"},{"name":"early-warning","svgCode":"","codepoint":"\\e16f"},{"name":"warning","svgCode":"","codepoint":"\\e170"},{"name":"spce","svgCode":"","codepoint":"\\e171"},{"name":"password","svgCode":"","codepoint":"\\e172"},{"name":"redis-2","svgCode":"","codepoint":"\\e176"},{"name":"mysql-2","svgCode":"","codepoint":"\\e174"},{"name":"es","svgCode":"","codepoint":"\\e177"},{"name":"hdfs","svgCode":"","codepoint":"\\e175"},{"name":"delete","svgCode":"","codepoint":"\\e178"},{"name":"excel","svgCode":"","codepoint":"\\e179"},{"name":"history-2","svgCode":"","codepoint":"\\e17a"},{"name":"migration","svgCode":"","codepoint":"\\e17d"},{"name":"switch-2","svgCode":"","codepoint":"\\e17e"},{"name":"remote","svgCode":"","codepoint":"\\e17f"},{"name":"clearing","svgCode":"","codepoint":"\\e180"},{"name":"alert","svgCode":"","codepoint":"\\e181"},{"name":"rebuild","svgCode":"","codepoint":"\\e182"},{"name":"clone","svgCode":"","codepoint":"\\e183"},{"name":"associated","svgCode":"","codepoint":"\\e184"},{"name":"rollback","svgCode":"","codepoint":"\\e185"},{"name":"aa","svgCode":"","codepoint":"\\e1f6"},{"name":"data","svgCode":"","codepoint":"\\e186"},{"name":"audit","svgCode":"","codepoint":"\\e190"},{"name":"yijinyong","svgCode":"","codepoint":"\\e19a"},{"name":"kuorongzhong","svgCode":"","codepoint":"\\e19d"},{"name":"zhongqizhong","svgCode":"","codepoint":"\\e19b"},{"name":"suorongzhong","svgCode":"","codepoint":"\\e19e"},{"name":"tihuanzong","svgCode":"","codepoint":"\\e19c"},{"name":"shanchuzhong","svgCode":"","codepoint":"\\e19f"},{"name":"jinyongzhong","svgCode":"","codepoint":"\\e1a0"},{"name":"qiyongzhong","svgCode":"","codepoint":"\\e1a1"},{"name":"help-fill-2","svgCode":"","codepoint":"\\e1a2"},{"name":"2-jiantou-you","svgCode":"","codepoint":"\\e1a5"},{"name":"2-jiantou-zuo","svgCode":"","codepoint":"\\e1a6"},{"name":"tools","svgCode":"","codepoint":"\\e1a9"},{"name":"todos","svgCode":"","codepoint":"\\e1aa"},{"name":"manual","svgCode":"","codepoint":"\\e1ac"},{"name":"minimap","svgCode":"","codepoint":"\\e1ad"},{"name":"backup-2","svgCode":"","codepoint":"\\e1af"},{"name":"loading-tubiao","svgCode":"","codepoint":"\\e208"},{"name":"host-select","svgCode":"","codepoint":"\\e1b0"},{"name":"batch-host-select","svgCode":"","codepoint":"\\e1b1"},{"name":"revoke","svgCode":"","codepoint":"\\e1b3"},{"name":"en","svgCode":"","codepoint":"\\e1b4"},{"name":"cn","svgCode":"","codepoint":"\\e1b5"},{"name":"list","svgCode":"","codepoint":"\\e1b7"},{"name":"influxdb","svgCode":"","codepoint":"\\e1ba"},{"name":"summation","svgCode":"","codepoint":"\\e1bb"},{"name":"folder-open","svgCode":"","codepoint":"\\e1bc"},{"name":"wenjian","svgCode":"","codepoint":"\\e1bf"},{"name":"drag","svgCode":"","codepoint":"\\e1c0"},{"name":"gaokeyong","svgCode":"","codepoint":"\\e1c2"},{"name":"fenbushijiqun","svgCode":"","codepoint":"\\e1c3"},{"name":"danjiedian","svgCode":"","codepoint":"\\e1c1"},{"name":"zhongkongji","svgCode":"","codepoint":"\\e1c4"},{"name":"wenjian","svgCode":"","codepoint":"\\e1c6"},{"name":"manual-2","svgCode":"","codepoint":"\\e1c7"},{"name":"clock","svgCode":"","codepoint":"\\e1c8"},{"name":"auto","svgCode":"","codepoint":"\\e1c9"},{"name":"dirty-host","svgCode":"","codepoint":"\\e1ca"},{"name":"tag-3","svgCode":"","codepoint":"\\e207"},{"name":"saoba","svgCode":"","codepoint":"\\e1f4"},{"name":"dongzuo-xiazai","svgCode":"","codepoint":"\\e1f3"},{"name":"entry","svgCode":"","codepoint":"\\e1d0"},{"name":"gaojingcelve","svgCode":"","codepoint":"\\e1d1"},{"name":"lunzhi","svgCode":"","codepoint":"\\e1d5"},{"name":"gaojing","svgCode":"","codepoint":"\\e1d2"},{"name":"yonghuzu","svgCode":"","codepoint":"\\e1d3"},{"name":"pingbi","svgCode":"","codepoint":"\\e1d4"},{"name":"hongqi","svgCode":"","codepoint":"\\e1d6"},{"name":"jiankong","svgCode":"","codepoint":"\\e1d7"},{"name":"mimasuijihua","svgCode":"","codepoint":"\\e1d8"},{"name":"jiqiren","svgCode":"","codepoint":"\\e1da"},{"name":"qiyeweixin-2","svgCode":"","codepoint":"\\e1db"},{"name":"weixin-2","svgCode":"","codepoint":"\\e1dc"},{"name":"youjian","svgCode":"","codepoint":"\\e1dd"},{"name":"duanxin","svgCode":"","codepoint":"\\e1de"},{"name":"yuyin","svgCode":"","codepoint":"\\e1df"},{"name":"warn-lightning","svgCode":"","codepoint":"\\e1e1"},{"name":"unlink","svgCode":"","codepoint":"\\e1e2"},{"name":"mobanshili","svgCode":"","codepoint":"\\e1e3"},{"name":"qiangzhizhongzhi","svgCode":"","codepoint":"\\e1e7"},{"name":"sqlserver","svgCode":"","codepoint":"\\e1e8"},{"name":"qianyizhong","svgCode":"","codepoint":"\\e1ea"},{"name":"liucheng","svgCode":"","codepoint":"\\e1eb"},{"name":"kejian","svgCode":"","codepoint":"\\e1ec"},{"name":"doris","svgCode":"","codepoint":"\\e1ee"},{"name":"daochu-2","svgCode":"","codepoint":"\\e1f0"},{"name":"daoru","svgCode":"","codepoint":"\\e1ef"},{"name":"piliangluru","svgCode":"","codepoint":"\\e1f1"},{"name":"cluster-standardize","svgCode":"","codepoint":"\\e1f9"},{"name":"fill-1","svgCode":"","codepoint":"\\e1fc"},{"name":"kelong","svgCode":"","codepoint":"\\e1fe"},{"name":"yuandezhongjian","svgCode":"","codepoint":"\\e1fd"},{"name":"daihuishou-2","svgCode":"","codepoint":"\\e202"},{"name":"daihuishou","svgCode":"","codepoint":"\\e203"},{"name":"guzhangji","svgCode":"","codepoint":"\\e204"}]} \ No newline at end of file diff --git a/dbm-ui/frontend/lib/bk-icon/style.css b/dbm-ui/frontend/lib/bk-icon/style.css index 6b7f07362a..70c39a0a2b 100644 --- a/dbm-ui/frontend/lib/bk-icon/style.css +++ b/dbm-ui/frontend/lib/bk-icon/style.css @@ -23,6 +23,9 @@ url("fonts/iconcool.eot?#iefix") format("embedded-opentype"); -moz-osx-font-smoothing: grayscale; } +.db-icon-tags:before { + content: "\e206"; +} .db-icon-check-circle-fill:before { content: "\e1a7"; } @@ -497,6 +500,9 @@ url("fonts/iconcool.eot?#iefix") format("embedded-opentype"); .db-icon-backup-2:before { content: "\e1af"; } +.db-icon-loading-tubiao:before { + content: "\e208"; +} .db-icon-host-select:before { content: "\e1b0"; } @@ -557,6 +563,9 @@ url("fonts/iconcool.eot?#iefix") format("embedded-opentype"); .db-icon-dirty-host:before { content: "\e1ca"; } +.db-icon-tag-3:before { + content: "\e207"; +} .db-icon-saoba:before { content: "\e1f4"; } diff --git a/dbm-ui/frontend/src/components/db-table/index.vue b/dbm-ui/frontend/src/components/db-table/index.vue index e831c85e44..c95ca7b674 100644 --- a/dbm-ui/frontend/src/components/db-table/index.vue +++ b/dbm-ui/frontend/src/components/db-table/index.vue @@ -111,6 +111,7 @@ // 是否允许行点击选中 allowRowClickSelect?: boolean, remoteSort?: boolean, + sortType?: 'ordering' | 'default'; } interface Emits { @@ -145,6 +146,7 @@ remotePagination: true, allowRowClickSelect: false, remoteSort: false, + sortType: 'default', }); const emits = defineEmits(); @@ -517,9 +519,16 @@ desc: 0, asc: 1, }; - sortParams = { - [sortPayload.column.field]: valueMap[sortPayload.type as keyof typeof valueMap], - }; + if (props.sortType === 'ordering') { + sortParams = { + ordering: `${valueMap[sortPayload.type as keyof typeof valueMap] === 0 ? '-' : ''}${sortPayload.column.field}` + }; + } + else { + sortParams = { + [sortPayload.column.field]: valueMap[sortPayload.type as keyof typeof valueMap], + }; + } fetchListData(); }; diff --git a/dbm-ui/frontend/src/components/disk-pop-info/DiskPopInfo.vue b/dbm-ui/frontend/src/components/disk-pop-info/DiskPopInfo.vue index 74eb16d751..1e91969cc2 100644 --- a/dbm-ui/frontend/src/components/disk-pop-info/DiskPopInfo.vue +++ b/dbm-ui/frontend/src/components/disk-pop-info/DiskPopInfo.vue @@ -2,7 +2,7 @@ @@ -26,9 +26,12 @@ interface Props { data: DbResourceModel['storage_device']; + trigger?: 'hover' | 'click' | 'manual'; } - const props = defineProps(); + const props = withDefaults(defineProps(), { + trigger: 'hover', + }); const { t } = useI18n(); diff --git a/dbm-ui/frontend/src/layout/Index.vue b/dbm-ui/frontend/src/layout/Index.vue index 19c4ad3a4a..3158ab322f 100644 --- a/dbm-ui/frontend/src/layout/Index.vue +++ b/dbm-ui/frontend/src/layout/Index.vue @@ -138,6 +138,8 @@ ], [menuEnum.observableManage]: ['DBHASwitchEvents', 'inspectionManage'], [menuEnum.configManage]: [ + 'BizResourcePool', + 'BizResourceTag', 'DbConfigure', 'DBMonitorStrategy', 'DBMonitorAlarmGroup', diff --git a/dbm-ui/frontend/src/layout/components/ConfigManage.vue b/dbm-ui/frontend/src/layout/components/ConfigManage.vue index e6a675fdce..c4ba4938c5 100644 --- a/dbm-ui/frontend/src/layout/components/ConfigManage.vue +++ b/dbm-ui/frontend/src/layout/components/ConfigManage.vue @@ -9,6 +9,36 @@ :active-key="currentActiveKey" :opened-keys="[parentKey]" @click="handleMenuChange"> + + + + + {{ t('资源池') }} + + + + + + {{ t('资源标签') }} + + + >, 'DbConfigure'); + } = useActiveKey(menuRef as Ref>, 'BizResourcePool'); const styles = useMenuStyles(menuBoxRef); diff --git a/dbm-ui/frontend/src/layout/components/ResourceManage.vue b/dbm-ui/frontend/src/layout/components/ResourceManage.vue index d187047bf5..90efa287e7 100644 --- a/dbm-ui/frontend/src/layout/components/ResourceManage.vue +++ b/dbm-ui/frontend/src/layout/components/ResourceManage.vue @@ -41,6 +41,18 @@ {{ t('污点主机处理') }} + + + + {{ t('资源标签管理') }} + + diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index 69b778732e..e3afefcf5c 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -351,6 +351,7 @@ "访问DB": "访问 DB", "访问源预览": "访问源预览", "旧从库主机": "旧从库主机", + "新从库主机": "新从库主机", "备份源": "备份源", "目标从库实例": "目标从库实例", "请输入域名_集群名称_所属DB模块": "请输入域名,集群名称,所属DB模块", @@ -1201,7 +1202,7 @@ "Bookkeeper节点数至少为2台": "Bookkeeper 节点数至少为 2 台", "Zookeeper节点数需3台": "Zookeeper 节点数需 3 台", "Broker节点数至少为1台": "Broker节点数至少为 1 台", - "已选n台_共nGB": "已选{0}台,共{1}GB", + "已选n台_共nGB(目标容量:nG)": "已选{0}台,共{1}GB(目标容量:{2}G)", "(共n台_磁盘容量nG)": "(共{0}台,磁盘容量{1}G)", "(需n台_已选n台_少n台_共nG)": "(需{0}台,已选{1}台,少{2}台_共{3}G)", "确认扩容【name】集群": "确认扩容【{name}】集群?", @@ -1337,6 +1338,8 @@ "Client节点规格": "Client 节点规格", "冷_热节点": "冷/热节点", "NameNode_Zookeeper_JournalNode节点": "NameNode/Zookeeper/JournalNode 节点", + "冷_热节点规格": "冷/热节点规格", + "NameNode_Zookeeper_JournalNode节点规格": "NameNode/Zookeeper/JournalNode 节点规格", "确认删除以下规格": "确认删除以下规格?", "Pulsar集群管理": "【Pulsar】集群管理", "InfluxDB实例详情": "InfluxDB 实例详情", @@ -1433,6 +1436,7 @@ "请先返回列表选择要替换的节点 IP": "请先返回列表选择要替换的节点 IP", "xx节点规格": "{name}节点规格", "替换后原节点 IP 将不在可用,资源将会被释放": "替换后原节点 IP 将不在可用,资源将会被释放", + "已选n台_共nG_(目标容量:nG)": "已选{0}台,共{1}G(目标容量:{1}G)", "Client 节点": "Client 节点", "冷热节点至少扩容一种类型": "冷热节点至少扩容一种类型", "每台主机实例数量": "每台主机实例数量", @@ -2595,8 +2599,10 @@ "预计容量nG": "预计容量 {0} G", "所需主机数量": "所需主机数量", "Shard 节点数": "Shard 节点数", - "部署副本集数量": "部署副本集数量", "每组主机部署副本集数量": "每组主机部署副本集数量", + "主从节点数": "主从节点数", + "部署副本集数量": "部署副本集数量", + "每台主机部署副本集数量": "每台主机部署副本集数量", "共需n台": "共需 {0} 台", "计算规则": "计算规则", "集群ID重复": "集群ID重复", @@ -2687,6 +2693,7 @@ "保留索引": "保留索引", "删除索引": "删除索引", "索引处理": "索引处理", + "备份文件保存时间": "备份文件保存时间", "备份方式": "备份方式", "当前Shard节点规格": "当前 Shard 节点规格", "当前Shard节点数": "当前 Shard 节点数", @@ -2714,6 +2721,7 @@ "目标集群与构造设置": "目标集群与构造设置", "备份文件": "备份文件", "该操作将会修改对应DB的数据,请谨慎操作": "该操作将会修改对应 DB 的数据,请谨慎操作!", + "是否开启 Oplog": "是否开启 Oplog", "确认清档n个副本集集群": "确认清档 {n} 个副本集集群?", "确认执行变更脚本任务": "确认执行变更脚本任务?", "集群上的数据将会全部构造至指定的新机器": "集群上的数据将会全部构造至指定的新机器", @@ -3559,16 +3567,6 @@ "匹配的规则": "匹配的规则", "域名不能为空": "域名不能为空", "请选择或直接输入账号,Enter完成输入": "请选择或直接输入账号,Enter完成输入", - "后端存储": "后端存储", - "TendisCache后端存储": "TendisCache 后端存储", - "TendisSSD后端存储": "TendisSSD 后端存储", - "TendisPlus后端存储": "TendisPlus 后端存储", - "DataNode节点": "DataNode 节点", - "副本集/ShardSvr": "副本集/ShardSvr", - "必须要能除尽总分片数": "必须要能除尽总分片数", - "变更机器组数": "变更机器组数", - "CPU/内存": "CPU/内存", - "添加机型": "添加机型", "TendisCache/RedisCluster/Redis主从 后端存储": "TendisCache/RedisCluster/Redis主从 后端存储", "扩容数量(当前n台)": "扩容数量(当前 {0} 台)", "当前容量:nG": "当前容量:{0} G", @@ -3609,9 +3607,6 @@ "变更类型": "变更类型", "删除规则": "删除规则", "账户名称": "账户名称", - "编辑中": "编辑中", - "权限规则_t_任务正在进行中": "权限规则{t}任务正在进行中", - "修改": "修改", "变更规则": "变更规则", "修改成功后,不会影响已授权的实例,新增的授权将会按照最新的配置生效": "修改成功后,不会影响已授权的实例,新增的授权将会按照最新的配置生效", "差异确认": "差异确认", @@ -3654,5 +3649,61 @@ "每个分类最多显示 10 条记录,点击搜索可查看全部记录。": "每个分类最多显示 10 条记录,点击搜索可查看全部记录。", "全站搜索,支持多对象,Shift + Enter 换行,Enter键开启搜索": "全站搜索,支持多对象,Shift + Enter 换行,Enter键开启搜索", "全站搜索,支持多对象,Enter开启搜索": "全站搜索,支持多对象,Enter开启搜索", + "后端存储": "后端存储", + "TendisCache后端存储": "TendisCache 后端存储", + "TendisSSD后端存储": "TendisSSD 后端存储", + "TendisPlus后端存储": "TendisPlus 后端存储", + "DataNode节点": "DataNode 节点", + "副本集/ShardSvr": "副本集/ShardSvr", + "必须要能除尽总分片数": "必须要能除尽总分片数", + "变更机器组数": "变更机器组数", + "CPU/内存": "CPU/内存", + "添加机型": "添加机型", + "已选n台_共nGB": "已选{0}台,共{1}GB", + "编辑中": "编辑中", + "权限规则_t_任务正在进行中": "权限规则{t}任务正在进行中", + "删除操作将发起单据,单据获得审批后才会执行删除": "删除操作将发起单据,单据获得审批后才会执行删除", + "修改": "修改", + "确认将 {n} 台主机转为公共资源?": "确认将 {n} 台主机转为公共资源?", + "已选择以下n台主机": "已选择以下 {0} 台主机", + "资源监控": "资源监控", + "系统管理": "系统管理", + "撤销导入": "撤销导入", + "确认后,主机将从资源池移回原有模块": "确认后,主机将从资源池移回原有模块", + "所属DB": "所属DB", + "移入故障池": "移入故障池", + "移入待回收池": "移入待回收池", + "资源归属": "资源归属", + "确认批量将 {n} 台主机转入回收池?": "确认批量将 {n} 台主机转入回收池?", + "确认批量将 {n} 台主机转入故障池?": "确认批量将 {n} 台主机转入故障池?", + "确认批量撤销 {n} 台主机的导入?": "确认批量撤销 {n} 台主机的导入?", + "确认批量撤销 {n} 台主机的导入?": "确认批量撤销 {n} 台主机的导入?", + "资源标签": "资源标签", + "标签": "标签", + "仅支持同业务的主机": "仅支持同业务的主机", + "设置属性": "设置属性", + "添加资源归属": "添加资源归属", + "转为公共资源": "转为公共资源", + "共n台": "共{0}台", + "批量添加资源归属": "批量添加资源归属", + "为主机添加或更新所属 DB、标签设置,若设置不存在则添加,已存在则覆盖更新": "为主机添加或更新所属 DB、标签设置,若设置不存在则添加,已存在则覆盖更新", + "我的已办": "我的已办", + "操作系统": "操作系统", + "确认后,将主机标记为待回收,等待处理": "确认后,将主机标记为待回收,等待处理", + "确认后,将主机标记为故障,等待处理": "确认后,将主机标记为故障,等待处理", + "编辑资源归属": "编辑资源归属", + "资源标签管理": "资源标签管理", + "确认后,将主机清空已存在的资源归属设置,并设置为公共资源": "确认后,将主机清空已存在的资源归属设置,并设置为公共资源", + "确认后,主机将标记为待回收,等待处理": "确认后,主机将标记为待回收,等待处理", + "确认后,主机将标记为故障,等待处理": "确认后,主机将标记为故障,等待处理", + "确认后,主机将标记为业务专属": "确认后,主机将标记为业务专属", + "确认转入待回收池?": "确认转入待回收池?", + "确认批量将 {n} 台主机转入待回收池": "确认批量将 {n} 台主机转入待回收池", + "确认批量将 {n} 台主机转入业务资源池": "确认批量将 {n} 台主机转入业务资源池", + "确认撤销导入?": "确认撤销导入?", + "确认后,将主机将清空已存在的资源归属设置,并设置为公共资源": "确认后,将主机将清空已存在的资源归属设置,并设置为公共资源", + "确认批量将 {n} 台主机转入业务资源池?": "确认批量将 {n} 台主机转入业务资源池?", + "确认转入待故障池?": "确认转入待故障池?", + "跳转管理页": "跳转管理页", "这行勿动!新增翻译请在上一行添加!": "" } diff --git a/dbm-ui/frontend/src/router/index.ts b/dbm-ui/frontend/src/router/index.ts index d352355ce3..58bc61d57a 100644 --- a/dbm-ui/frontend/src/router/index.ts +++ b/dbm-ui/frontend/src/router/index.ts @@ -30,6 +30,7 @@ import getQuickSearchRoutes from '@views/quick-search/routes'; import getResourceManageRoutes from '@views/resource-manage/routes'; import getServiceApplyRoutes from '@views/service-apply/routes'; import getStaffManageRoutes from '@views/staff-manage/routes'; +import getResourceTagRoutes from '@views/tag-manage/routes'; import getTaskHistoryRoutes from '@views/task-history/routes'; import getTemporaryPasswordModify from '@views/temporary-paassword-modify/routes'; import getTicketFlowSettingBizRoutes from '@views/ticket-flow-setting-biz/routes'; @@ -113,6 +114,7 @@ export default () => { { path: `${rootPath}${currentBiz}`, children: [ + ...getResourceTagRoutes(), ...getDbManageRoutes(), ...getDbConfRoutes(), ...getDbhaSwitchEventsRouters(), diff --git a/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts b/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts index 30692db00f..c5917fa8a6 100644 --- a/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts +++ b/dbm-ui/frontend/src/services/model/db-resource/DbResource.ts @@ -38,7 +38,10 @@ export default class DbResource { bk_biz_name: string; }; ip: string; - label: string; + labels: { + name: string; + id: number; + }[]; net_device_id: string; os_bit: string; os_type: string; @@ -81,7 +84,7 @@ export default class DbResource { this.device_class = payload.device_class; this.for_biz = payload.for_biz; this.ip = payload.ip; - this.label = payload.label; + this.labels = payload.labels; this.net_device_id = payload.net_device_id; this.os_bit = payload.os_bit; this.os_type = payload.os_type; diff --git a/dbm-ui/frontend/src/services/model/db-resource/ResourceTag.ts b/dbm-ui/frontend/src/services/model/db-resource/ResourceTag.ts new file mode 100644 index 0000000000..f461debeeb --- /dev/null +++ b/dbm-ui/frontend/src/services/model/db-resource/ResourceTag.ts @@ -0,0 +1,45 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited; a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * 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. + */ +import dayjs from 'dayjs'; + +import { utcDisplayTime } from '@utils'; + +export default class ResourceTag { + create_at: string; // 创建时间 + creator: string; // 创建人 + id: number; // 标签ID + is_builtin: boolean; // 是否内置标签 + update_at: string; // 更新时间 + value: string; // 标签名 + + constructor(payload = {} as ResourceTag) { + this.create_at = payload.create_at || ''; + this.creator = payload.creator || ''; + this.id = payload.id || 0; + this.is_builtin = payload.is_builtin || false; + this.update_at = payload.update_at || ''; + this.value = payload.value || ''; + } + + get isNewCreated() { + return dayjs().isBefore(dayjs(this.create_at).add(24, 'hour')); + } + + get createAtDisplay() { + return utcDisplayTime(this.create_at); + } + + get updatedAtDisplay() { + return utcDisplayTime(this.update_at); + } +} diff --git a/dbm-ui/frontend/src/services/model/function-controller/functionController.ts b/dbm-ui/frontend/src/services/model/function-controller/functionController.ts index cd1e8a7c7b..fa854d06f7 100644 --- a/dbm-ui/frontend/src/services/model/function-controller/functionController.ts +++ b/dbm-ui/frontend/src/services/model/function-controller/functionController.ts @@ -72,8 +72,11 @@ interface ControllerData { 'resourceManage.resourceSpec': ControllerItem; 'resourceManage.resourcePool': ControllerItem; 'resourceManage.dirtyHostManage': ControllerItem; + 'resourceManage.resourceTagsManagement': ControllerItem; 'resourceManage.resourceOperationRecord': ControllerItem; bizConfigManage: ControllerItem; + 'bizConfigManage.businessResourcePool': ControllerItem; + 'bizConfigManage.businessResourceTag': ControllerItem; 'bizConfigManage.monitorStrategy': ControllerItem; 'bizConfigManage.alarmGroup': ControllerItem; 'bizConfigManage.dbConfigure': ControllerItem; diff --git a/dbm-ui/frontend/src/services/source/dbresourceResource.ts b/dbm-ui/frontend/src/services/source/dbresourceResource.ts index 1e7d81a36c..a97c52ae4b 100644 --- a/dbm-ui/frontend/src/services/source/dbresourceResource.ts +++ b/dbm-ui/frontend/src/services/source/dbresourceResource.ts @@ -25,7 +25,7 @@ const path = '/apis/dbresource/resource'; /** * 资源删除 */ -export function removeResource(params: { bk_host_ids: number[] }) { +export function removeResource(params: { bk_host_ids: number[]; event: 'to_recycle' | 'to_fault' | 'undo_import' }) { return http.post<{ bk_host_ids: number[] }>(`${path}/delete/`, params); } @@ -71,6 +71,7 @@ export function importResource(params: { host_id: number; bk_cloud_id: number; }>; + labels: number; }) { return http.post(`${path}/import/`, params); } @@ -175,7 +176,8 @@ export function getSpecResourceCount(params: { */ export function updateResource(params: { bk_host_ids: number[]; - for_biz?: number; + labels?: number[]; + for_biz: number; rack_id: string; resource_type?: string; storage_device: Record; diff --git a/dbm-ui/frontend/src/services/source/tag.ts b/dbm-ui/frontend/src/services/source/tag.ts new file mode 100644 index 0000000000..14c2f7a146 --- /dev/null +++ b/dbm-ui/frontend/src/services/source/tag.ts @@ -0,0 +1,75 @@ +import ResourceTagModel from '@services/model/db-resource/ResourceTag'; +import type { ListBase } from '@services/types/listBase'; + +import http from '../http'; + +const path = '/apis/tag/'; + +/** + * 查询资源标签 + */ +export function listTag(params: { + value?: string; + bind_ips?: string[]; + creator?: string; + bk_biz_id?: number; + limit?: number; + offset?: number; +}) { + return http.get>(`${path}`, params).then((res) => ({ + ...res, + results: res.results.map((item: ResourceTagModel) => new ResourceTagModel(item)), + })); +} + +/** + * 新增资源标签 + */ +export function createTag(params: { + bk_biz_id: number; + tags: { + key: string; // 固定为 dbresource + value: string; + }[]; +}) { + return http.post(`${path}batch_create/`, params); +} + +/** + * 批量删除资源标签 + */ +export function deleteTag(params: { bk_biz_id: number; ids: number[] }) { + return http.delete(`${path}batch_delete/`, params); +} + +/** + * 编辑资源标签 + */ +export function updateTag(params: { bk_biz_id: number; id: number; value: string }) { + return http.patch(`${path}${params.id}/`, params); +} + +/** + * 校验标签是否重复,并返回重复的标签值 + */ +export function validateTag(params: { + bk_biz_id: number; + tags: { + key: string; + value: string; + }[]; +}) { + return http.post<{ key: string; value: string }[]>(`${path}verify_duplicated/`, params); +} + +/** + * 根据标签id获取关联IP + */ +export function getTagRelatedResource(params: { bk_biz_id: number; ids: number[]; resource_type?: string }) { + return http.post< + { + id: number; + ip_count: number; + }[] + >(`${path}related_resources/`, params); +} diff --git a/dbm-ui/frontend/src/stores/globalBizs.ts b/dbm-ui/frontend/src/stores/globalBizs.ts index 90326f745e..9dc83e575d 100644 --- a/dbm-ui/frontend/src/stores/globalBizs.ts +++ b/dbm-ui/frontend/src/stores/globalBizs.ts @@ -29,6 +29,11 @@ export const useGlobalBizs = defineStore('GlobalBizs', { }), getters: { currentBizInfo: (state): BizItem | undefined => state.bizs.find((item) => item.bk_biz_id === state.currentBizId), + bizIdMap: (state) => + state.bizs.reduce>((map, biz) => { + map.set(biz.bk_biz_id, biz); + return map; + }, new Map()), }, actions: { /** diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue new file mode 100644 index 0000000000..8ad233dfd5 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/business/Index.vue @@ -0,0 +1,106 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue new file mode 100644 index 0000000000..a49fe2bfb6 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue @@ -0,0 +1,583 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue new file mode 100644 index 0000000000..0684e08802 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/HostOperationTip.vue @@ -0,0 +1,114 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/ImportHostBtn.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/ImportHostBtn.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/ImportHostBtn.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/ImportHostBtn.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/RenderTable.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/RenderTable.vue similarity index 99% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/RenderTable.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/RenderTable.vue index c9b237efc8..47f352f5cd 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/RenderTable.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/RenderTable.vue @@ -27,6 +27,7 @@ :pagination="pagination" :pagination-heihgt="60" remote-pagination + :row-class="rowCls" show-overflow-tooltip v-bind="$attrs" @column-sort="handleColumnSortChange" @@ -87,6 +88,7 @@ paginationExtra?: IPaginationExtra; selectable?: boolean; disableSelectMethod?: (data: any) => boolean | string; + rowCls?: string; // data 数据的主键 primaryKey?: string; } diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/Index.vue new file mode 100644 index 0000000000..bcc5d1fc10 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/Index.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue new file mode 100644 index 0000000000..5c4efa5a92 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue @@ -0,0 +1,176 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue new file mode 100644 index 0000000000..9915a0362b --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/ListPanel.vue @@ -0,0 +1,266 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue new file mode 100644 index 0000000000..9a20fd0f79 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-convert-to-business/Index.vue @@ -0,0 +1,78 @@ + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue new file mode 100644 index 0000000000..091ffa1bdb --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-covert-to-public/Index.vue @@ -0,0 +1,77 @@ + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-fault-pool/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-fault-pool/Index.vue new file mode 100644 index 0000000000..6cefab2c9c --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-fault-pool/Index.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-recycle-pool/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-recycle-pool/Index.vue new file mode 100644 index 0000000000..9a4d01ddb1 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-move-to-recycle-pool/Index.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/batch-setting/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue similarity index 88% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/batch-setting/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue index aab44ad364..11e93304dc 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/batch-setting/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/Index.vue @@ -23,6 +23,7 @@

    ({ - for_biz: '', + for_biz: undefined, rack_id: '', resource_type: '', storage_spec: [] as IStorageSpecItem[], @@ -109,32 +112,23 @@ const formRef = ref(); const isSubmiting = ref(false); - const bizList = shallowRef< - { - bk_biz_id: string; - display_name: string; - }[] - >([]); - const dbTypeList = shallowRef< - { - id: string; - name: string; - }[] - >([]); + const bizList = shallowRef>([]); + const dbTypeList = shallowRef>([]); + const formData = reactive(genDefaultData()); const isSubmitDisabled = computed( - () => !(formData.for_biz || formData.resource_type || formData.storage_spec.length > 0), + () => !(formData.for_biz !== '' || formData.resource_type || formData.storage_spec.length > 0), ); useRequest(getBizs, { onSuccess(data) { bizList.value = [ - { bk_biz_id: '0', display_name: t('公共资源池') }, - ...data.map((item) => ({ - bk_biz_id: `${item.bk_biz_id}`, - display_name: item.display_name, - })), + { + bk_biz_id: 0, + display_name: t('公共资源池'), + } as BizItem, + ...data, ]; }, }); @@ -155,7 +149,7 @@ formRef.value .validate() .then(() => { - const storageDevice = formData.storage_spec.reduce( + const storageDevice = formData.storage_spec.reduce>( (result, item) => ({ ...result, [item.mount_point]: { @@ -163,10 +157,11 @@ disk_type: item.type, }, }), - {} as Record, + {}, ); const params = { bk_host_ids: props.data.map((item) => ~~item), + for_biz: formData.for_biz, rack_id: formData.rack_id, storage_device: storageDevice, }; diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/batch-setting/components/ResourceSpecStorage.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/components/ResourceSpecStorage.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/batch-setting/components/ResourceSpecStorage.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-setting/components/ResourceSpecStorage.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-undo-import/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-undo-import/Index.vue new file mode 100644 index 0000000000..12250d2e10 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-undo-import/Index.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/import-host/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue similarity index 81% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/import-host/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue index 89e9255de8..389572c4a2 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/import-host/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue @@ -17,6 +17,7 @@ class="import-host-dialog" :esc-close="false" :quick-close="false" + render-directive="if" :width="width"> {{ t('确定') }} @@ -60,7 +62,8 @@ - + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/review-data-dialog/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/review-data-dialog/Index.vue new file mode 100644 index 0000000000..0a134f0da0 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/review-data-dialog/Index.vue @@ -0,0 +1,158 @@ + + + + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/Index.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/Index.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/Index.vue similarity index 98% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/Index.vue index 2977fe784e..b3630d1e4d 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/Index.vue @@ -52,6 +52,7 @@ import DiskType from './components/DiskType.vue'; import ForBiz from './components/ForBiz.vue'; import Hosts from './components/Hosts.vue'; + import Label from './components/Label.vue'; import Mem from './components/Mem.vue'; import MountPoint from './components/MountPoint.vue'; import OSType from './components/OSType.vue'; @@ -89,6 +90,7 @@ mount_point: MountPoint, cpu: Cpu, mem: Mem, + label: Label, disk: Disk, disk_type: DiskType, city: CitySubzones, diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/AgentStatus.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/AgentStatus.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/AgentStatus.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/AgentStatus.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/BkCloudIds.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/BkCloudIds.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/BkCloudIds.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/BkCloudIds.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/CitySubzones.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/CitySubzones.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/CitySubzones.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/CitySubzones.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Cpu.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Cpu.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Cpu.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Cpu.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/DeviceClass.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/DeviceClass.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/DeviceClass.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/DeviceClass.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Disk.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Disk.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Disk.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Disk.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/DiskType.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/DiskType.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/DiskType.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/DiskType.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/ForBiz.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/ForBiz.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/ForBiz.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/ForBiz.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Hosts.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Hosts.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Hosts.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Hosts.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue new file mode 100644 index 0000000000..2a1ca49b99 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Label.vue @@ -0,0 +1,84 @@ + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Mem.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Mem.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/Mem.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/Mem.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/MountPoint.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/MountPoint.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/MountPoint.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/MountPoint.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/OSType.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/OSType.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/OSType.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/OSType.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/ResourceType.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/ResourceType.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/ResourceType.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/ResourceType.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/SpecId.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/SpecId.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/com-factory/components/SpecId.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/com-factory/components/SpecId.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-config.ts b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-config.ts similarity index 98% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-config.ts rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-config.ts index bb728254d9..b807008e0c 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-config.ts +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-config.ts @@ -135,6 +135,11 @@ export default { return true; }, }, + label: { + label: t('标签'), + component: 'label', + type: 'string', + }, disk: { label: t('磁盘(G)'), component: 'disk', diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-input/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue similarity index 96% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-input/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue index 695d77fde0..f4cb42b674 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-input/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/Index.vue @@ -70,6 +70,11 @@ :model="localValueMemo" name="mem" @change="handleChange" /> +
    @@ -159,6 +164,7 @@ os_type: true, cpu: true, mem: true, + label: true, mount_point: true, disk: true, disk_type: true, @@ -183,7 +189,7 @@ // 提交搜索,更新外部值 const handleSubmit = _.debounce( () => { - Promise.all(Object.values(inputRef.value).map((inputItem) => inputItem.getValue())).then(() => { + Promise.all(Object.values(inputRef.value).map((inputItem) => inputItem?.getValue())).then(() => { emits('update:modelValue', { ...localValueMemo.value, }); diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-input/components/CollectSearchParams.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/components/CollectSearchParams.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-input/components/CollectSearchParams.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-input/components/CollectSearchParams.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-tag/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-tag/Index.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-tag/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-tag/Index.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-tag/ValueTag.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-tag/ValueTag.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/field-tag/ValueTag.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/field-tag/ValueTag.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/utils.ts b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/utils.ts similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/components/search-box/components/utils.ts rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/search-box/components/utils.ts diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/panel/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/panel/Index.vue new file mode 100644 index 0000000000..e39ba0c0ed --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/panel/Index.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue new file mode 100644 index 0000000000..3840ec85b4 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-research/selector/Index.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue new file mode 100644 index 0000000000..1fa30ebc9c --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/tag-selector/Index.vue @@ -0,0 +1,273 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue new file mode 100644 index 0000000000..06e0b090ce --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/update-assign/Index.vue @@ -0,0 +1,167 @@ + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/hooks/useTableSetting.ts b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/hooks/useTableSetting.ts similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/host-list/hooks/useTableSetting.ts rename to dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/hooks/useTableSetting.ts diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/Index.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/Index.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/BarChart.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/BarChart.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/BarChart.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/BarChart.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/DimensionSelect.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/DimensionSelect.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/DimensionSelect.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/DimensionSelect.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/Export.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/Export.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/Export.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/Export.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/List.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/List.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/List.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/List.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/Index.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/Index.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Biz.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Biz.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Biz.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Biz.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Db.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Db.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Db.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Db.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Region.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Region.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Region.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Region.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Spec.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Spec.vue similarity index 100% rename from dbm-ui/frontend/src/views/resource-manage/pool/summary-view/components/search-box/components/Spec.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/components/summary-view/components/search-box/components/Spec.vue diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue similarity index 73% rename from dbm-ui/frontend/src/views/resource-manage/pool/Index.vue rename to dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue index 5de41d126f..20f57ada7f 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/global/Index.vue @@ -12,21 +12,30 @@ --> @@ -35,8 +44,8 @@ import { useDebouncedRef } from '@hooks'; - import HostList from './host-list/Index.vue'; - import SummaryView from './summary-view/Index.vue'; + import HostList from '../components/host-list/Index.vue'; + import SummaryView from '../components/summary-view/Index.vue'; const { t } = useI18n(); const router = useRouter(); @@ -74,7 +83,6 @@ params: { page: value, }, - query: {}, }); }; diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/host-list/Index.vue deleted file mode 100644 index 6148e0a580..0000000000 --- a/dbm-ui/frontend/src/views/resource-manage/pool/host-list/Index.vue +++ /dev/null @@ -1,346 +0,0 @@ - - - - - diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/type.ts b/dbm-ui/frontend/src/views/resource-manage/pool/type.ts new file mode 100644 index 0000000000..53e363a426 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/type.ts @@ -0,0 +1,13 @@ +/** + * 资源池类型枚举值 + */ +export enum ResourcePool { + public = 'public', + global = 'global', + business = 'business', +} + +/** + * 资源池类型 + */ +export type ResourcePoolType = ResourcePool.business | ResourcePool.global | ResourcePool.public; diff --git a/dbm-ui/frontend/src/views/resource-manage/routes.ts b/dbm-ui/frontend/src/views/resource-manage/routes.ts index 6ab833b15c..4d8c87f2f8 100644 --- a/dbm-ui/frontend/src/views/resource-manage/routes.ts +++ b/dbm-ui/frontend/src/views/resource-manage/routes.ts @@ -23,7 +23,7 @@ const resourcePoolRoute = { navName: t('DB 资源池'), fullscreen: true, }, - component: () => import('@views/resource-manage/pool/Index.vue'), + component: () => import('@views/resource-manage/pool/global/Index.vue'), }; const resourcePoolOperationRecordRoute = { @@ -44,6 +44,15 @@ const resourcePoolDirtyMachinesRoute = { component: () => import('@views/resource-manage/dirty-machine/Index.vue'), }; +const resourceTagsManagementRoute = { + name: 'resourceTagsManagement', + path: 'tags-management', + meta: { + navName: t('资源标签管理'), + }, + component: () => import('@views/tag-manage/Index.vue'), +}; + const resourceSpecRoute = { name: 'resourceSpec', path: 'spec', @@ -82,6 +91,10 @@ export default function getRoutes() { mainRoute[0].children.push(resourcePoolDirtyMachinesRoute); } + if (checkDbConsole('resourceManage.resourceTagsManagement')) { + mainRoute[0].children.push(resourceTagsManagementRoute); + } + if (checkDbConsole('resourceManage.resourceOperationRecord')) { mainRoute[0].children.push(resourcePoolOperationRecordRoute); } diff --git a/dbm-ui/frontend/src/views/tag-manage/Index.vue b/dbm-ui/frontend/src/views/tag-manage/Index.vue new file mode 100644 index 0000000000..1e88a85779 --- /dev/null +++ b/dbm-ui/frontend/src/views/tag-manage/Index.vue @@ -0,0 +1,432 @@ + + + + + + + + + diff --git a/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue b/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue new file mode 100644 index 0000000000..118a478b7d --- /dev/null +++ b/dbm-ui/frontend/src/views/tag-manage/components/BusinessSelector.vue @@ -0,0 +1,160 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tag-manage/components/CreateTag.vue b/dbm-ui/frontend/src/views/tag-manage/components/CreateTag.vue new file mode 100644 index 0000000000..a4acc621f9 --- /dev/null +++ b/dbm-ui/frontend/src/views/tag-manage/components/CreateTag.vue @@ -0,0 +1,178 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tag-manage/components/EditableCell.vue b/dbm-ui/frontend/src/views/tag-manage/components/EditableCell.vue new file mode 100644 index 0000000000..fec0a7a1eb --- /dev/null +++ b/dbm-ui/frontend/src/views/tag-manage/components/EditableCell.vue @@ -0,0 +1,79 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/tag-manage/routes.ts b/dbm-ui/frontend/src/views/tag-manage/routes.ts new file mode 100644 index 0000000000..4200a67b34 --- /dev/null +++ b/dbm-ui/frontend/src/views/tag-manage/routes.ts @@ -0,0 +1,41 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * 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. + */ +import type { RouteRecordRaw } from 'vue-router'; + +import { checkDbConsole } from '@utils'; + +import { t } from '@locales/index'; + +const routes: RouteRecordRaw[] = [ + { + name: 'BizResourcePool', + path: 'pool/:page?', + meta: { + navName: t('资源池'), + fullscreen: true, + }, + component: () => import('@views/resource-manage/pool/business/Index.vue'), + }, + { + name: 'BizResourceTag', + path: 'business-resource-tag', + meta: { + navName: t('资源标签'), + }, + component: () => import('@views/tag-manage/Index.vue'), + }, +]; + +export default function getRoutes() { + return checkDbConsole('bizConfigManage.businessResourceTag') ? routes : []; +} From 590d184e10d5e8bb8394fab4f86522e0b5b3cfdf Mon Sep 17 00:00:00 2001 From: jojo Date: Tue, 8 Oct 2024 15:03:43 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat(frontend):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=95=85=E9=9A=9C=E6=B1=A0=E3=80=81=E5=BE=85=E5=9B=9E=E6=94=B6?= =?UTF-8?q?=E6=B1=A0=20#7881?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/db-popconfirm/index.vue | 20 +- .../src/components/db-table/index.vue | 4 +- .../src/layout/components/ResourceManage.vue | 24 ++ dbm-ui/frontend/src/locales/zh-cn.json | 18 + .../db-resource/FaultOrRecycleMachine.ts | 55 +++ .../function-controller/functionController.ts | 2 + .../frontend/src/services/source/dbdirty.ts | 22 + .../src/services/source/dbresourceResource.ts | 2 +- dbm-ui/frontend/src/services/source/tag.ts | 1 + .../fault-or-recycle-list/Index.vue | 398 ++++++++++++++++++ .../BatchImportResourcePool/Index.vue | 154 +++++++ .../components/FormPanel.vue | 151 +++++++ .../components/ListPanel.vue | 265 ++++++++++++ .../components/ImportResourcePool.vue | 205 +++++++++ .../components/search.vue | 79 ++++ .../pool/components/host-list/Index.vue | 9 +- .../batch-assign/components/FormPanel.vue | 2 +- .../components/import-host/Index.vue | 47 ++- .../import-host/components/FormPanel.vue | 2 +- .../resource-search-selector/Index.vue | 2 +- .../components/review-data-dialog/Index.vue | 20 +- .../components/com-factory/Index.vue | 2 +- .../search-box/components/field-config.ts | 4 +- .../components/field-input/Index.vue | 4 +- .../components/update-assign/Index.vue | 4 +- .../components => }/tag-selector/Index.vue | 28 +- .../src/views/resource-manage/routes.ts | 26 ++ .../frontend/src/views/tag-manage/Index.vue | 2 +- .../views/tag-manage/components/CreateTag.vue | 2 +- 29 files changed, 1490 insertions(+), 64 deletions(-) create mode 100644 dbm-ui/frontend/src/services/model/db-resource/FaultOrRecycleMachine.ts create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/Index.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/FormPanel.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/ListPanel.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/ImportResourcePool.vue create mode 100644 dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/search.vue rename dbm-ui/frontend/src/views/resource-manage/pool/components/{host-list/components => }/tag-selector/Index.vue (91%) diff --git a/dbm-ui/frontend/src/components/db-popconfirm/index.vue b/dbm-ui/frontend/src/components/db-popconfirm/index.vue index 2b645a42aa..643678f48b 100644 --- a/dbm-ui/frontend/src/components/db-popconfirm/index.vue +++ b/dbm-ui/frontend/src/components/db-popconfirm/index.vue @@ -21,19 +21,21 @@
    + :style="contentStyle">
    {{ title }}
    - {{ content }} + + {{ content }} +
    {{ $t('确认') }} @@ -51,15 +53,20 @@ interface Props { title: string; - content: string; + content?: string; placement?: Placement; + width?: number; confirmHandler: () => Promise | void; cancelHandler?: () => Promise | void; + theme?: 'primary' | 'danger'; } const props = withDefaults(defineProps(), { placement: 'top', + content: '', + width: 280, cancelHandler: () => Promise.resolve(), + theme: 'primary', }); defineOptions({ @@ -72,6 +79,11 @@ const popRef = ref(); const isConfirmLoading = ref(false); + const contentStyle = computed(() => ({ + width: `${props.width}px`, + padding: '15px 10px', + })); + const handleConfirm = () => { isConfirmLoading.value = true; Promise.resolve() diff --git a/dbm-ui/frontend/src/components/db-table/index.vue b/dbm-ui/frontend/src/components/db-table/index.vue index c95ca7b674..e305f69617 100644 --- a/dbm-ui/frontend/src/components/db-table/index.vue +++ b/dbm-ui/frontend/src/components/db-table/index.vue @@ -606,8 +606,8 @@ getAllData: fetchAllData, // 清空选择 clearSelected() { - // bkTableRef.value?.clearSelection(); - handleClearWholeSelect(); + rowSelectMemo.value = {}; + bkTableRef.value?.clearSelection(); }, updateTableKey() { tableKey.value = Date.now().toString(); diff --git a/dbm-ui/frontend/src/layout/components/ResourceManage.vue b/dbm-ui/frontend/src/layout/components/ResourceManage.vue index 90efa287e7..e5fbc94aa3 100644 --- a/dbm-ui/frontend/src/layout/components/ResourceManage.vue +++ b/dbm-ui/frontend/src/layout/components/ResourceManage.vue @@ -29,6 +29,30 @@ {{ t('DB 资源池管理') }} + + + + {{ t('待回收池') }} + + + + + + {{ t('故障池') }} + + diff --git a/dbm-ui/frontend/src/locales/zh-cn.json b/dbm-ui/frontend/src/locales/zh-cn.json index e3afefcf5c..43559a4aff 100644 --- a/dbm-ui/frontend/src/locales/zh-cn.json +++ b/dbm-ui/frontend/src/locales/zh-cn.json @@ -3705,5 +3705,23 @@ "确认批量将 {n} 台主机转入业务资源池?": "确认批量将 {n} 台主机转入业务资源池?", "确认转入待故障池?": "确认转入待故障池?", "跳转管理页": "跳转管理页", + "确认批量回收 {n} 台主机?": "确认批量回收 {n} 台主机?", + "回收": "回收", + "导入资源池": "导入资源池", + "确认回收该机器?": "确认回收该机器?", + "待回收池": "待回收池", + "故障池": "故障池", + "磁盘总容量(G)": "磁盘总容量(G)", + "确认后,主机将从系统中删除": "确认后,主机将从系统中删除", + "批量导入资源池": "批量导入资源池", + "批量回收": "批量回收", + "故障资源池": "故障资源池", + "确认后,主机将从系统中删除,请谨慎操作!": "确认后,主机将从系统中删除,请谨慎操作!", + "确认批量将 {n} 台主机转入待回收池?": "确认批量将 {n} 台主机转入待回收池?", + "批量转入回收池": "批量转入回收池", + "转入回收池": "转入回收池", + "新建标签": "新建标签", + "所有 IP": "所有 IP", + "已选 IP": "已选 IP", "这行勿动!新增翻译请在上一行添加!": "" } diff --git a/dbm-ui/frontend/src/services/model/db-resource/FaultOrRecycleMachine.ts b/dbm-ui/frontend/src/services/model/db-resource/FaultOrRecycleMachine.ts new file mode 100644 index 0000000000..3d1d32b51e --- /dev/null +++ b/dbm-ui/frontend/src/services/model/db-resource/FaultOrRecycleMachine.ts @@ -0,0 +1,55 @@ +/* + * TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-DB管理系统(BlueKing-BK-DBM) available. + * + * Copyright (C) 2017-2023 THL A29 Limited; a Tencent company. All rights reserved. + * + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at https://opensource.org/licenses/MIT + * + * 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 default class FaultOrRecycleMachine { + agent_status: number; + bk_biz_id: number; + bk_cloud_id: number; + bk_cpu: number; + bk_disk: number; + bk_host_id: number; + bk_mem: number; + city: string; + create_at: string; + creator: string; + device_class: string; + ip: string; + os_name: string; + pool: string; + rack_id: string; + sub_zone: string; + ticket: string; + update_at: string; + updater: string; + + constructor(payload = {} as FaultOrRecycleMachine) { + this.agent_status = payload.agent_status; + this.bk_biz_id = payload.bk_biz_id; + this.bk_cloud_id = payload.bk_cloud_id; + this.bk_cpu = payload.bk_cpu; + this.bk_disk = payload.bk_disk; + this.bk_host_id = payload.bk_host_id; + this.bk_mem = payload.bk_mem; + this.city = payload.city; + this.create_at = payload.create_at; + this.creator = payload.creator; + this.device_class = payload.device_class; + this.ip = payload.ip; + this.os_name = payload.os_name; + this.pool = payload.pool; + this.rack_id = payload.rack_id; + this.sub_zone = payload.sub_zone; + this.ticket = payload.ticket; + this.update_at = payload.update_at; + this.updater = payload.updater; + } +} diff --git a/dbm-ui/frontend/src/services/model/function-controller/functionController.ts b/dbm-ui/frontend/src/services/model/function-controller/functionController.ts index fa854d06f7..4122f9f843 100644 --- a/dbm-ui/frontend/src/services/model/function-controller/functionController.ts +++ b/dbm-ui/frontend/src/services/model/function-controller/functionController.ts @@ -214,6 +214,8 @@ export default class FunctionController { resourceManage: ControllerItem; 'resourceManage.resourceSpec': ControllerItem; 'resourceManage.resourcePool': ControllerItem; + 'resourceManage.faultPool': ControllerItem; + 'resourceManage.toRecyclePool': ControllerItem; 'resourceManage.dirtyHostManage': ControllerItem; 'resourceManage.resourceOperationRecord': ControllerItem; bizConfigManage: ControllerItem; diff --git a/dbm-ui/frontend/src/services/source/dbdirty.ts b/dbm-ui/frontend/src/services/source/dbdirty.ts index 27f937abee..1d8fdf07f0 100644 --- a/dbm-ui/frontend/src/services/source/dbdirty.ts +++ b/dbm-ui/frontend/src/services/source/dbdirty.ts @@ -12,6 +12,7 @@ */ import DirtyMachinesModel from '@services/model/db-resource/dirtyMachines'; +import FaultOrRecycleMachineModel from '@services/model/db-resource/FaultOrRecycleMachine'; import type { ListBase } from '@services/types'; import http from '../http'; @@ -52,3 +53,24 @@ export function transferDirtyMachines(params: { bk_host_ids: number[] }) { export function deleteDirtyRecords(params: { bk_host_ids: number[] }) { return http.delete(`${path}/delete_dirty_records/`, params); } + +/** + * 故障池、待回收池列表 + */ +export function getMachinePool(params: { limit?: number; offset?: number; ips?: string; pool: 'fault' | 'recycle' }) { + return http.get>(`${path}/query_machine_pool/`, params).then((res) => ({ + ...res, + results: res.results.map((item: FaultOrRecycleMachineModel) => new FaultOrRecycleMachineModel(item)), + })); +} + +/** + * 将主机转移至待回收/故障池模块 + */ +export function transferMachinePool(params: { + bk_host_ids: number[]; + source: 'fault' | 'recycle'; + target: 'fault' | 'recycle' | 'recycled'; +}) { + return http.post(`${path}/transfer_hosts_to_pool/`, params); +} diff --git a/dbm-ui/frontend/src/services/source/dbresourceResource.ts b/dbm-ui/frontend/src/services/source/dbresourceResource.ts index a97c52ae4b..5454cd464a 100644 --- a/dbm-ui/frontend/src/services/source/dbresourceResource.ts +++ b/dbm-ui/frontend/src/services/source/dbresourceResource.ts @@ -71,7 +71,7 @@ export function importResource(params: { host_id: number; bk_cloud_id: number; }>; - labels: number; + labels: number[]; }) { return http.post(`${path}/import/`, params); } diff --git a/dbm-ui/frontend/src/services/source/tag.ts b/dbm-ui/frontend/src/services/source/tag.ts index 14c2f7a146..649ace1376 100644 --- a/dbm-ui/frontend/src/services/source/tag.ts +++ b/dbm-ui/frontend/src/services/source/tag.ts @@ -15,6 +15,7 @@ export function listTag(params: { bk_biz_id?: number; limit?: number; offset?: number; + ordering?: string; }) { return http.get>(`${path}`, params).then((res) => ({ ...res, diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue new file mode 100644 index 0000000000..61a43cc329 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/Index.vue @@ -0,0 +1,398 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/Index.vue new file mode 100644 index 0000000000..baf9c0eef7 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/Index.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/FormPanel.vue new file mode 100644 index 0000000000..ad176c0e19 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/FormPanel.vue @@ -0,0 +1,151 @@ + + + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/ListPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/ListPanel.vue new file mode 100644 index 0000000000..6233c7064d --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/BatchImportResourcePool/components/ListPanel.vue @@ -0,0 +1,265 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/ImportResourcePool.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/ImportResourcePool.vue new file mode 100644 index 0000000000..449263c269 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/ImportResourcePool.vue @@ -0,0 +1,205 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/search.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/search.vue new file mode 100644 index 0000000000..b172dc2d70 --- /dev/null +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/fault-or-recycle-list/components/search.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue index a49fe2bfb6..2baef51252 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/Index.vue @@ -224,7 +224,7 @@ ...params, }); - const searchParams: Record = {}; + let searchParams: Record = {}; let selectionListWholeDataMemo: DbResourceModel[] = []; const tableColumn = [ { @@ -252,10 +252,10 @@
    {t('所属业务')} : {data.for_biz_display} + theme={(data.for_biz.bk_biz_id === 0 || !data.for_biz.bk_biz_name) ? 'success' : undefined}>{t('所属业务')} : {data.forBizDisplay} {t('所属DB')} : {data.resource_type_display} + theme={(!data.resource_type || data.resource_type === 'PUBLIC') ? 'success' : undefined}>{t('所属DB')} : {data.resourceTypeDisplay} { data.labels && Array.isArray(data.labels) && ( @@ -393,7 +393,8 @@ }; const handleSearch = (params: Record) => { - tableRef.value.fetchData(params); + searchParams = {...searchParams, ...params}; + tableRef.value.fetchData(searchParams); }; // 导入主机 diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue index 5c4efa5a92..8632b86401 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/batch-assign/components/FormPanel.vue @@ -74,7 +74,7 @@ import { listTag } from '@services/source/tag'; import type { BizItem } from '@services/types'; - import TagSelector from '../../tag-selector/Index.vue'; + import TagSelector from '@views/resource-manage/pool/components/tag-selector/Index.vue'; interface Props { bizId: number; diff --git a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue index 389572c4a2..09d9f055c5 100644 --- a/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue +++ b/dbm-ui/frontend/src/views/resource-manage/pool/components/host-list/components/import-host/Index.vue @@ -39,20 +39,14 @@