diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py
index 3500862e5..69e64ceaf 100644
--- a/apps/assets/forms/asset.py
+++ b/apps/assets/forms/asset.py
@@ -33,11 +33,16 @@ class AssetCreateForm(OrgModelForm):
             return
         nodes_field = self.fields['nodes']
         if self.instance:
-            nodes_field.choices = ((n.id, n.full_value) for n in
-                                   self.instance.nodes.all())
+            nodes_field.choices = [(n.id, n.full_value) for n in
+                                   self.instance.nodes.all()]
         else:
             nodes_field.choices = []
 
+    def add_nodes_initial(self, node):
+        nodes_field = self.fields['nodes']
+        nodes_field.choices.append((node.id, node.full_value))
+        nodes_field.initial = [node]
+
     class Meta:
         model = Asset
         fields = [
diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py
index 37ebbd6d3..243c352a7 100644
--- a/apps/assets/models/node.py
+++ b/apps/assets/models/node.py
@@ -37,19 +37,22 @@ class TreeMixin:
     def tree(cls):
         from ..utils import TreeService
         tree_updated_time = cache.get(cls.tree_updated_time_cache_key, 0)
+        now = time.time()
+        # 什么时候重新初始化 _tree_service
         if not cls.tree_created_time or \
                 tree_updated_time > cls.tree_created_time:
             logger.debug("Create node tree")
             tree = TreeService.new()
-            cls.tree_created_time = time.time()
-            cls.tree_assets_created_time = time.time()
+            cls.tree_created_time = now
+            cls.tree_assets_created_time = now
             cls._tree_service = tree
             return tree
+        # 是否要重新初始化节点资产
         node_assets_updated_time = cache.get(cls.tree_assets_cache_key, 0)
         if not cls.tree_assets_created_time or \
                 node_assets_updated_time > cls.tree_assets_created_time:
-            cls._tree_service.init_assets_async()
-            cls.tree_assets_created_time = time.time()
+            cls._tree_service.init_assets()
+            cls.tree_assets_created_time = now
             logger.debug("Refresh node tree assets")
         return cls._tree_service
 
diff --git a/apps/assets/templates/assets/_asset_list_modal.html b/apps/assets/templates/assets/_asset_list_modal.html
index beafa9ae1..06aa4a707 100644
--- a/apps/assets/templates/assets/_asset_list_modal.html
+++ b/apps/assets/templates/assets/_asset_list_modal.html
@@ -15,11 +15,11 @@
     text-align: center;
 }
 
-#assetTree2.ztree * {
-    background-color: #f8fafb;
+#asset_modal_tree.ztree * {
+    background-color: white;
 }
-#assetTree2.ztree {
-    background-color: #f8fafb;
+#asset_modal_tree.ztree {
+    background-color: white;
 }
 </style>
 
@@ -29,7 +29,8 @@
            <div class="ibox float-e-margins">
                <div class="ibox-content mailbox-content" style="padding-top: 0;padding-left: 1px">
                    <div class="file-manager ">
-                       <div id="assetTree2" class="ztree">
+                       <div id="asset_modal_tree" class="ztree">
+                           {% trans 'Loading' %} ...
                        </div>
                        <div class="clearfix"></div>
                    </div>
@@ -55,12 +56,77 @@
 </div>
 
 <script>
-var zTree2, asset_table2 = 0;
-function initTable2() {
-    if(asset_table2){
-        return
+function syncTableSelectedAssetToSelect2(table) {
+    var assets = table.selected;
+    var options = [];
+    var select2Id = assetModalOption.select2Id;
+    $(select2Id + ' option').each(function (i, v) {
+        options.push(v.value)
+    });
+    table.selected_rows.forEach(function (i) {
+        var name = i.hostname + '(' + i.ip + ')';
+        var option = new Option(name, i.id, false, true);
+
+        if (options.indexOf(i.id) === -1) {
+            $(select2Id).append(option).trigger('change');
+        }
+    });
+    $(select2Id).val(assets).trigger('change');
+}
+
+
+
+// 解决input框中的资产和弹出表格中资产的显示不一致
+function syncSelectedAssetsToModalTable(assetModalTable) {
+    var select2Id = assetModalOption.select2Id;
+    var inputAssets = $(select2Id).val();
+    var selectedAssets = assetModalTable.selected.concat();
+
+    // input assets无,table assets选中,则取消勾选(再次click)
+    if (selectedAssets.length !== 0) {
+        $.each(selectedAssets, function (index, assetId) {
+            if ($.inArray(assetId, inputAssets) === -1) {
+                $('#' + assetId).trigger('click');  // 取消勾选
+            }
+        });
     }
 
+    // input assets有,table assets没选,则选中(click)
+    if (inputAssets !== null) {
+        assetModalTable.selected = inputAssets;
+        $.each(inputAssets, function (index, assetId) {
+            var dom = document.getElementById(assetId);
+            if (dom !== null) {
+                var selected = dom.parentElement.parentElement.className.indexOf('selected')
+            }
+            if (selected === -1) {
+                $('#' + assetId).trigger('click');
+            }
+        });
+    }
+}
+
+defaultOnAssetModalConfirm = syncTableSelectedAssetToSelect2;
+defaultOnModalTableDone = syncSelectedAssetsToModalTable;
+
+
+var assetModalOption = {
+    selectStyle: 'multi',
+    select2Id: '#id_assets',
+    onModalTableDone: defaultOnModalTableDone,
+    onModalTreeDone: null,
+    onModalConfirm: defaultOnAssetModalConfirm,
+};
+
+var assetModalTable, assetModalTree = null;
+
+function initAssetModalTable() {
+    if(assetModalTable){
+        return
+    }
+    if (assetModalOption.selectStyle === 'single') {
+        $('.ipt_check_all').addClass('hidden')
+    }
     var options = {
         ele: $('#asset_list_modal_table'),
         ajax_url: '{% url "api-assets:asset-list" %}?show_current_asset=1',
@@ -68,22 +134,26 @@ function initTable2() {
             {data: "id"}, {data: "hostname" }, {data: "ip" }
         ],
         lengthMenu: [[10, 25, 50], [10, 25, 50]],
-        pageLength: 10
+        pageLength: 10,
+        select_style: assetModalOption.selectStyle
     };
-    asset_table2 = jumpserver.initServerSideDataTable(options);
-    return asset_table2
+    assetModalTable = jumpserver.initServerSideDataTable(options);
+    if (assetModalOption.onModalTableDone) {
+        assetModalOption.onModalTableDone(assetModalTable);
+    }
+    return assetModalTable
 }
 
-function onNodeSelected2(event, treeNode) {
-    var url = asset_table2.ajax.url();
+function onModalTreeNodeSelected(event, treeNode) {
+    var url = assetModalTable.ajax.url();
     url = setUrlParam(url, "node_id", treeNode.meta.node.id);
     url = setUrlParam(url, "show_current_asset", "");
-    asset_table2.ajax.url(url);
-    asset_table2.ajax.reload();
+    assetModalTable.ajax.url(url);
+    assetModalTable.ajax.reload();
 }
 
 
-function initTree2() {
+function initModalTree() {
     var url = '{% url 'api-assets:node-children-tree' %}?assets=0';
     var setting = {
         view: {
@@ -102,17 +172,34 @@ function initTree2() {
             type: 'get'
 		},
         callback: {
-            onSelected: onNodeSelected2
+            onSelected: onModalTreeNodeSelected
         }
     };
-    zTree2 = $.fn.zTree.init($("#assetTree2"), setting);
+    $.get(url, function(data, status){
+        $.fn.zTree.init($("#asset_modal_tree"), setting);
+        assetModalTree = $.fn.zTree.getZTreeObj("assetTree2");
+        if (assetModalOption.onModalTreeDone) {
+            assetModalOption.onModalTreeDone(assetModalTree);
+        }
+        return assetModalTree;
+    });
+}
+
+function setAssetModalOptions(options) {
+    assetModalOption = options;
 }
 
 
 $(document).ready(function(){
+
 }).on('show.bs.modal', function () {
-    initTable2();
-    initTree2();
+    initAssetModalTable();
+    initModalTree();
+}).on('click', '#btn_asset_modal_confirm', function () {
+    if (assetModalOption.onModalConfirm) {
+        assetModalOption.onModalConfirm(assetModalTable, assetModalTree);
+    }
+    $("#asset_list_modal").modal('hide');
 })
 </script>
 {% endblock %}
diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html
index 58e0d86e5..fcd0f79ff 100644
--- a/apps/assets/templates/assets/asset_list.html
+++ b/apps/assets/templates/assets/asset_list.html
@@ -226,6 +226,33 @@ function onNodeSelected(event, treeNode) {
     asset_table.ajax.reload();
 }
 
+function onAssetModalConfirmAddAssetToNode(table) {
+    var assets_selected = table.selected;
+    if (!current_node_id) {
+        return
+    }
+
+    var data = {'assets': assets_selected};
+    var success = function () {
+        table.selected = [];
+        table.ajax.reload()
+    };
+
+    var url = '';
+    if (update_node_action === "move") {
+        url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
+    } else {
+        url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
+    }
+
+    requestApi({
+        'url': url,
+        'method': 'PUT',
+        'body': JSON.stringify(data),
+        'success': success
+    })
+}
+
 $(document).ready(function(){
     initTable();
     initTree();
@@ -236,6 +263,12 @@ $(document).ready(function(){
     else{
         $('#show_current_asset').css('display', 'inline-block');
     }
+
+    var modalOption = {
+        onModalConfirm: onAssetModalConfirmAddAssetToNode,
+        onModalTableDone: null
+    };
+    setAssetModalOptions(modalOption);
 })
 .on('click', '.labels li', function () {
     var val = $(this).text();
@@ -429,7 +462,6 @@ $(document).ready(function(){
      }
 
     function doRemove() {
-       var nodes = zTree.getSelectedNodes();
        if (!current_node_id) {
            return
        }
@@ -472,32 +504,7 @@ $(document).ready(function(){
     }
     $(".ipt_check_all").prop("checked", false)
 })
-.on('click', '#btn_asset_modal_confirm', function () {
-    var assets_selected = asset_table2.selected;
-    if (!current_node_id) {
-        return
-    }
-
-    var data = {'assets': assets_selected};
-    var success = function () {
-        asset_table2.selected = [];
-        asset_table2.ajax.reload()
-    };
-
-    var url = '';
-    if (update_node_action === "move") {
-        url = "{% url 'api-assets:node-replace-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
-    } else {
-        url = "{% url 'api-assets:node-add-assets' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id);
-    }
-
-    requestApi({
-        'url': url,
-        'method': 'PUT',
-        'body': JSON.stringify(data),
-        'success': success
-    })
-}).on('hidden.bs.modal', '#asset_list_modal', function () {
+.on('hidden.bs.modal', '#asset_list_modal', function () {
     window.location.reload();
 }).on('click', '#menu_asset_add', function () {
     update_node_action = "add"
diff --git a/apps/assets/templates/assets/domain_create_update.html b/apps/assets/templates/assets/domain_create_update.html
index 399b38011..96bfd02aa 100644
--- a/apps/assets/templates/assets/domain_create_update.html
+++ b/apps/assets/templates/assets/domain_create_update.html
@@ -28,25 +28,6 @@ $(document).ready(function () {
 }).on('click', '.select2-selection__rendered', function (e) {
     e.preventDefault();
     $("#asset_list_modal").modal();
-    initSelectedAssets2Table();
-})
-.on('click', '#btn_asset_modal_confirm', function () {
-    var assets = asset_table2.selected;
-    var options = [];
-    $('#id_assets option').each(function (i, v) {
-        options.push(v.value)
-    });
-    asset_table2.selected_rows.forEach(function (i) {
-        var name = i.hostname + '(' + i.ip + ')';
-        var option = new Option(name, i.id, false, true);
-
-        if (options.indexOf(i.id) === -1) {
-            $('#id_assets').append(option).trigger('change');
-        }
-    });
-    $('.select2').val(assets).trigger('change');
-    $("#asset_list_modal").modal('hide');
-
 })
 .on("submit", "form", function (evt) {
     evt.preventDefault();
diff --git a/apps/assets/templates/assets/label_create_update.html b/apps/assets/templates/assets/label_create_update.html
index a6b9582a5..41646003c 100644
--- a/apps/assets/templates/assets/label_create_update.html
+++ b/apps/assets/templates/assets/label_create_update.html
@@ -32,24 +32,6 @@ $(document).ready(function () {
 }).on('click', '.select2-selection__rendered', function (e) {
     e.preventDefault();
     $("#asset_list_modal").modal();
-    initSelectedAssets2Table();
-})
-.on('click', '#btn_asset_modal_confirm', function () {
-    var assets = asset_table2.selected;
-    var options = [];
-    $('#id_assets option').each(function (i, v) {
-        options.push(v.value)
-    });
-    asset_table2.selected_rows.forEach(function (i) {
-        var name = i.hostname + '(' + i.ip + ')';
-        var option = new Option(name, i.id, false, true);
-
-        if (options.indexOf(i.id) === -1) {
-            $('#id_assets').append(option).trigger('change');
-        }
-    });
-    $('#id_assets').val(assets).trigger('change');
-    $("#asset_list_modal").modal('hide');
 })
 .on("submit", "form", function (evt) {
     evt.preventDefault();
diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py
index 257691fa4..f08c08db8 100644
--- a/apps/assets/views/asset.py
+++ b/apps/assets/views/asset.py
@@ -86,7 +86,7 @@ class AssetCreateView(PermissionsMixin, FormMixin, TemplateView):
             node = get_object_or_none(Node, id=node_id)
         else:
             node = Node.org_root()
-        form["nodes"].initial = node
+        form.add_nodes_initial(node)
         return form
 
     def get_protocol_formset(self):
diff --git a/apps/audits/templates/audits/ftp_log_list.html b/apps/audits/templates/audits/ftp_log_list.html
index 91ea6c49d..a5e3fceec 100644
--- a/apps/audits/templates/audits/ftp_log_list.html
+++ b/apps/audits/templates/audits/ftp_log_list.html
@@ -11,6 +11,9 @@
         #search_btn {
             margin-bottom: 0;
         }
+        .form-control {
+            height: 30px;
+        }
     </style>
 {% endblock %}
 
diff --git a/apps/audits/templates/audits/login_log_list.html b/apps/audits/templates/audits/login_log_list.html
index c855db1c1..6a3bae989 100644
--- a/apps/audits/templates/audits/login_log_list.html
+++ b/apps/audits/templates/audits/login_log_list.html
@@ -8,6 +8,12 @@
         #search_btn {
             margin-bottom: 0;
         }
+        .form-control {
+            height: 30px;
+        }
+        .select2-selection__rendered span.select2-selection, .select2-container .select2-selection--single {
+            height: 30px !important;
+        }
     </style>
 {% endblock %}
 
diff --git a/apps/audits/templates/audits/operate_log_list.html b/apps/audits/templates/audits/operate_log_list.html
index 736c4f7ac..ae072187d 100644
--- a/apps/audits/templates/audits/operate_log_list.html
+++ b/apps/audits/templates/audits/operate_log_list.html
@@ -11,6 +11,12 @@
         #search_btn {
             margin-bottom: 0;
         }
+        .form-control {
+            height: 30px;
+        }
+        .select2-selection__rendered span.select2-selection, .select2-container .select2-selection--single {
+            height: 30px !important;
+        }
     </style>
 {% endblock %}
 
diff --git a/apps/audits/templates/audits/password_change_log_list.html b/apps/audits/templates/audits/password_change_log_list.html
index a8a2f818d..1440dca2d 100644
--- a/apps/audits/templates/audits/password_change_log_list.html
+++ b/apps/audits/templates/audits/password_change_log_list.html
@@ -11,6 +11,12 @@
         #search_btn {
             margin-bottom: 0;
         }
+        .form-control {
+            height: 30px;
+        }
+        .select2-selection__rendered span.select2-selection, .select2-container .select2-selection--single {
+            height: 30px !important;
+        }
     </style>
 {% endblock %}
 
diff --git a/apps/common/mixins/api.py b/apps/common/mixins/api.py
index ae92e3e97..21f0394ce 100644
--- a/apps/common/mixins/api.py
+++ b/apps/common/mixins/api.py
@@ -44,8 +44,10 @@ class IDInCacheFilterMixin(object):
             return queryset
         cache_key = KEY_CACHE_RESOURCES_ID.format(spm)
         resources_id = cache.get(cache_key)
-        if resources_id and isinstance(resources_id, list):
-            queryset = queryset.filter(id__in=resources_id)
+        if not resources_id or not isinstance(resources_id, list):
+            queryset = queryset.none()
+            return queryset
+        queryset = queryset.filter(id__in=resources_id)
         return queryset
 
 
diff --git a/apps/common/signals_handlers.py b/apps/common/signals_handlers.py
index 91901676d..e7dd728c3 100644
--- a/apps/common/signals_handlers.py
+++ b/apps/common/signals_handlers.py
@@ -14,7 +14,7 @@ from .local import thread_local
 
 pattern = re.compile(r'FROM `(\w+)`')
 logger = get_logger(__name__)
-DEBUG_DB_QUERY = os.environ.get('DEBUG_DB_QUERY', '0') == '1'
+DEBUG_DB = os.environ.get('DEBUG_DB', '0') == '1'
 
 
 class Counter:
@@ -58,7 +58,7 @@ def on_request_finished_release_local(sender, **kwargs):
     thread_local.__release_local__()
 
 
-if settings.DEBUG and DEBUG_DB_QUERY:
+if settings.DEBUG and DEBUG_DB:
     request_finished.connect(on_request_finished_logging_db_query)
 
 
diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py
index 27df6314f..f211eef82 100644
--- a/apps/jumpserver/settings.py
+++ b/apps/jumpserver/settings.py
@@ -609,6 +609,7 @@ SWAGGER_SETTINGS = {
     },
 }
 
+
 # Default email suffix
 EMAIL_SUFFIX = CONFIG.EMAIL_SUFFIX
 LOGIN_LOG_KEEP_DAYS = CONFIG.LOGIN_LOG_KEEP_DAYS
diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo
index 3ec0085d8..7e3bfc87f 100644
Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ
diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po
index 8a804450c..7962b471b 100644
--- a/apps/locale/zh/LC_MESSAGES/django.po
+++ b/apps/locale/zh/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Jumpserver 0.3.3\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-08-28 18:19+0800\n"
+"POT-Creation-Date: 2019-09-12 18:01+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: ibuler <ibuler@qq.com>\n"
 "Language-Team: Jumpserver team<ibuler@qq.com>\n"
@@ -84,9 +84,9 @@ msgstr "运行参数"
 #: assets/templates/assets/domain_list.html:26
 #: assets/templates/assets/label_list.html:16
 #: assets/templates/assets/system_user_list.html:55 audits/models.py:19
-#: audits/templates/audits/ftp_log_list.html:41
-#: audits/templates/audits/ftp_log_list.html:71
-#: perms/forms/asset_permission.py:69 perms/models/asset_permission.py:78
+#: audits/templates/audits/ftp_log_list.html:44
+#: audits/templates/audits/ftp_log_list.html:74
+#: perms/forms/asset_permission.py:79 perms/models/asset_permission.py:78
 #: perms/templates/perms/asset_permission_create_update.html:45
 #: perms/templates/perms/asset_permission_list.html:52
 #: perms/templates/perms/asset_permission_list.html:121
@@ -95,8 +95,8 @@ msgstr "运行参数"
 #: terminal/templates/terminal/command_list.html:66
 #: terminal/templates/terminal/session_list.html:28
 #: terminal/templates/terminal/session_list.html:72
-#: xpack/plugins/change_auth_plan/forms.py:64
-#: xpack/plugins/change_auth_plan/models.py:416
+#: xpack/plugins/change_auth_plan/forms.py:121
+#: xpack/plugins/change_auth_plan/models.py:413
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:46
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13
@@ -112,11 +112,10 @@ msgstr "资产"
 #: applications/templates/applications/remote_app_detail.html:61
 #: applications/templates/applications/remote_app_list.html:23
 #: applications/templates/applications/user_remote_app_list.html:19
-#: assets/models/user.py:168 assets/templates/assets/user_asset_list.html:53
-#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49
-#: audits/templates/audits/ftp_log_list.html:72
-#: perms/forms/asset_permission.py:75 perms/models/asset_permission.py:80
-#: perms/models/asset_permission.py:115
+#: assets/models/user.py:168 assets/templates/assets/user_asset_list.html:52
+#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:52
+#: audits/templates/audits/ftp_log_list.html:75
+#: perms/forms/asset_permission.py:85 perms/models/asset_permission.py:80
 #: perms/templates/perms/asset_permission_detail.html:140
 #: perms/templates/perms/asset_permission_list.html:54
 #: perms/templates/perms/asset_permission_list.html:75
@@ -160,7 +159,7 @@ msgstr "系统用户"
 #: perms/templates/perms/remote_app_permission_remote_app.html:53
 #: perms/templates/perms/remote_app_permission_user.html:53
 #: settings/models.py:29
-#: settings/templates/settings/_ldap_list_users_modal.html:38
+#: settings/templates/settings/_ldap_list_users_modal.html:31
 #: settings/templates/settings/command_storage_create.html:41
 #: settings/templates/settings/replay_storage_create.html:44
 #: settings/templates/settings/terminal_setting.html:83
@@ -174,8 +173,8 @@ msgstr "系统用户"
 #: users/templates/users/user_list.html:35
 #: users/templates/users/user_profile.html:51
 #: users/templates/users/user_pubkey_update.html:57
-#: xpack/plugins/change_auth_plan/forms.py:47
-#: xpack/plugins/change_auth_plan/models.py:64
+#: xpack/plugins/change_auth_plan/forms.py:104
+#: xpack/plugins/change_auth_plan/models.py:61
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12
 #: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:144
@@ -215,12 +214,12 @@ msgstr "参数"
 #: assets/templates/assets/domain_detail.html:72
 #: assets/templates/assets/system_user_detail.html:100
 #: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:14
-#: perms/models/asset_permission.py:118 perms/models/base.py:54
+#: perms/models/base.py:54
 #: perms/templates/perms/asset_permission_detail.html:98
 #: perms/templates/perms/remote_app_permission_detail.html:90
 #: users/models/user.py:371 users/serializers/v1.py:119
 #: users/templates/users/user_detail.html:111
-#: xpack/plugins/change_auth_plan/models.py:109
+#: xpack/plugins/change_auth_plan/models.py:106
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
 #: xpack/plugins/cloud/models.py:80 xpack/plugins/cloud/models.py:179
 msgid "Created by"
@@ -238,8 +237,7 @@ msgstr "创建者"
 #: assets/templates/assets/domain_detail.html:68
 #: assets/templates/assets/system_user_detail.html:96
 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
-#: orgs/models.py:15 perms/models/asset_permission.py:119
-#: perms/models/base.py:55
+#: orgs/models.py:15 perms/models/base.py:55
 #: perms/templates/perms/asset_permission_detail.html:94
 #: perms/templates/perms/remote_app_permission_detail.html:86
 #: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
@@ -273,8 +271,7 @@ msgstr "创建日期"
 #: assets/templates/assets/domain_list.html:28
 #: assets/templates/assets/system_user_detail.html:104
 #: assets/templates/assets/system_user_list.html:59 ops/models/adhoc.py:43
-#: orgs/models.py:16 perms/models/asset_permission.py:120
-#: perms/models/base.py:56
+#: orgs/models.py:16 perms/models/base.py:56
 #: perms/templates/perms/asset_permission_detail.html:102
 #: perms/templates/perms/remote_app_permission_detail.html:94
 #: settings/models.py:34 terminal/models.py:32
@@ -283,7 +280,7 @@ msgstr "创建日期"
 #: users/templates/users/user_group_detail.html:67
 #: users/templates/users/user_group_list.html:37
 #: users/templates/users/user_profile.html:138
-#: xpack/plugins/change_auth_plan/models.py:105
+#: xpack/plugins/change_auth_plan/models.py:102
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:117
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19
 #: xpack/plugins/cloud/models.py:77 xpack/plugins/cloud/models.py:173
@@ -355,7 +352,7 @@ msgstr "重置"
 #: assets/templates/assets/domain_create_update.html:17
 #: assets/templates/assets/gateway_create_update.html:59
 #: assets/templates/assets/label_create_update.html:19
-#: audits/templates/audits/login_log_list.html:89
+#: audits/templates/audits/login_log_list.html:95
 #: perms/templates/perms/asset_permission_create_update.html:84
 #: perms/templates/perms/remote_app_permission_create_update.html:84
 #: settings/templates/settings/basic_setting.html:65
@@ -404,7 +401,7 @@ msgstr "提交"
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:20
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:17
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:106
-#: xpack/plugins/change_auth_plan/views.py:91
+#: xpack/plugins/change_auth_plan/views.py:88
 msgid "Detail"
 msgstr "详情"
 
@@ -526,8 +523,8 @@ msgstr "创建远程应用"
 #: assets/templates/assets/domain_list.html:29
 #: assets/templates/assets/label_list.html:17
 #: assets/templates/assets/system_user_list.html:60 audits/models.py:38
-#: audits/templates/audits/operate_log_list.html:41
-#: audits/templates/audits/operate_log_list.html:67
+#: audits/templates/audits/operate_log_list.html:47
+#: audits/templates/audits/operate_log_list.html:73
 #: authentication/templates/authentication/_access_key_modal.html:30
 #: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
 #: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34
@@ -619,25 +616,25 @@ msgstr "未知"
 msgid "Port"
 msgstr "端口"
 
-#: assets/forms/asset.py:50 assets/models/asset.py:145
+#: assets/forms/asset.py:55 assets/models/asset.py:145
 #: assets/models/user.py:110 assets/templates/assets/asset_detail.html:190
 #: assets/templates/assets/asset_detail.html:198
 #: assets/templates/assets/system_user_assets.html:83
 #: perms/models/asset_permission.py:79
-#: xpack/plugins/change_auth_plan/models.py:75
+#: xpack/plugins/change_auth_plan/models.py:72
 msgid "Nodes"
 msgstr "节点"
 
-#: assets/forms/asset.py:53 assets/forms/asset.py:99 assets/models/asset.py:149
-#: assets/models/cluster.py:19 assets/models/user.py:68
-#: assets/templates/assets/asset_detail.html:76 templates/_nav.html:24
-#: xpack/plugins/cloud/models.py:161
+#: assets/forms/asset.py:58 assets/forms/asset.py:104
+#: assets/models/asset.py:149 assets/models/cluster.py:19
+#: assets/models/user.py:68 assets/templates/assets/asset_detail.html:76
+#: templates/_nav.html:24 xpack/plugins/cloud/models.py:161
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:68
 #: xpack/plugins/orgs/templates/orgs/org_list.html:18
 msgid "Admin user"
 msgstr "管理用户"
 
-#: assets/forms/asset.py:56 assets/forms/asset.py:102 assets/forms/asset.py:141
+#: assets/forms/asset.py:61 assets/forms/asset.py:107 assets/forms/asset.py:146
 #: assets/templates/assets/asset_create.html:48
 #: assets/templates/assets/asset_create.html:50
 #: assets/templates/assets/asset_list.html:85
@@ -645,23 +642,22 @@ msgstr "管理用户"
 msgid "Label"
 msgstr "标签"
 
-#: assets/forms/asset.py:59 assets/forms/asset.py:105
+#: assets/forms/asset.py:64 assets/forms/asset.py:110
 #: assets/models/asset.py:144 assets/models/domain.py:26
 #: assets/models/domain.py:52 assets/templates/assets/asset_detail.html:80
-#: assets/templates/assets/user_asset_list.html:54
+#: assets/templates/assets/user_asset_list.html:53
 #: xpack/plugins/orgs/templates/orgs/org_list.html:17
 msgid "Domain"
 msgstr "网域"
 
-#: assets/forms/asset.py:63 assets/forms/asset.py:96 assets/forms/asset.py:109
-#: assets/forms/asset.py:144 assets/models/node.py:369
+#: assets/forms/asset.py:68 assets/forms/asset.py:101 assets/forms/asset.py:114
+#: assets/forms/asset.py:149 assets/models/node.py:393
 #: assets/templates/assets/asset_create.html:42
-#: perms/forms/asset_permission.py:72 perms/forms/asset_permission.py:79
-#: perms/models/asset_permission.py:113
+#: perms/forms/asset_permission.py:82 perms/forms/asset_permission.py:89
 #: perms/templates/perms/asset_permission_list.html:53
 #: perms/templates/perms/asset_permission_list.html:74
 #: perms/templates/perms/asset_permission_list.html:124
-#: xpack/plugins/change_auth_plan/forms.py:65
+#: xpack/plugins/change_auth_plan/forms.py:122
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15
 #: xpack/plugins/cloud/models.py:157
@@ -670,7 +666,7 @@ msgstr "网域"
 msgid "Node"
 msgstr "节点"
 
-#: assets/forms/asset.py:67 assets/forms/asset.py:113
+#: assets/forms/asset.py:72 assets/forms/asset.py:118
 msgid ""
 "root or other NOPASSWD sudo privilege user existed in asset,If asset is "
 "windows or other set any one, more see admin user left menu"
@@ -678,20 +674,20 @@ msgstr ""
 "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一"
 "个, 更多信息查看左侧 `管理用户` 菜单"
 
-#: assets/forms/asset.py:70 assets/forms/asset.py:116
+#: assets/forms/asset.py:75 assets/forms/asset.py:121
 msgid "Windows 2016 RDP protocol is different, If is window 2016, set it"
 msgstr "Windows 2016的RDP协议与之前不同,如果是请设置"
 
-#: assets/forms/asset.py:71 assets/forms/asset.py:117
+#: assets/forms/asset.py:76 assets/forms/asset.py:122
 msgid ""
 "If your have some network not connect with each other, you can set domain"
 msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录"
 
-#: assets/forms/asset.py:124 assets/forms/asset.py:128
+#: assets/forms/asset.py:129 assets/forms/asset.py:133
 #: assets/forms/domain.py:17 assets/forms/label.py:15
 #: perms/templates/perms/asset_permission_asset.html:78
-#: xpack/plugins/change_auth_plan/forms.py:55
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:74
+#: xpack/plugins/change_auth_plan/forms.py:112
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:84
 msgid "Select assets"
 msgstr "选择资产"
 
@@ -717,20 +713,20 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC"
 #: assets/templates/assets/domain_gateway_list.html:71
 #: assets/templates/assets/system_user_detail.html:62
 #: assets/templates/assets/system_user_list.html:52 audits/models.py:80
-#: audits/templates/audits/login_log_list.html:51 authentication/forms.py:13
+#: audits/templates/audits/login_log_list.html:57 authentication/forms.py:13
 #: authentication/templates/authentication/login.html:65
 #: authentication/templates/authentication/new_login.html:92
 #: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:70
 #: perms/templates/perms/asset_permission_user.html:55
 #: perms/templates/perms/remote_app_permission_user.html:54
-#: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:14
+#: settings/templates/settings/_ldap_list_users_modal.html:30 users/forms.py:14
 #: users/models/user.py:328 users/templates/users/_select_user_modal.html:14
 #: users/templates/users/user_detail.html:67
 #: users/templates/users/user_list.html:36
 #: users/templates/users/user_profile.html:47
-#: xpack/plugins/change_auth_plan/forms.py:49
-#: xpack/plugins/change_auth_plan/models.py:66
-#: xpack/plugins/change_auth_plan/models.py:412
+#: xpack/plugins/change_auth_plan/forms.py:106
+#: xpack/plugins/change_auth_plan/models.py:63
+#: xpack/plugins/change_auth_plan/models.py:409
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:65
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12
@@ -756,8 +752,8 @@ msgstr "密码或密钥密码"
 #: users/templates/users/user_profile_update.html:41
 #: users/templates/users/user_pubkey_update.html:41
 #: users/templates/users/user_update.html:20
-#: xpack/plugins/change_auth_plan/models.py:96
-#: xpack/plugins/change_auth_plan/models.py:267
+#: xpack/plugins/change_auth_plan/models.py:93
+#: xpack/plugins/change_auth_plan/models.py:264
 msgid "Password"
 msgstr "密码"
 
@@ -805,31 +801,31 @@ msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig"
 
 #: assets/models/asset.py:135 assets/models/domain.py:49
 #: assets/serializers/asset_user.py:28
-#: assets/templates/assets/_asset_list_modal.html:46
+#: assets/templates/assets/_asset_list_modal.html:47
 #: assets/templates/assets/_asset_user_list.html:15
 #: assets/templates/assets/asset_detail.html:64
 #: assets/templates/assets/asset_list.html:97
 #: assets/templates/assets/domain_gateway_list.html:68
-#: assets/templates/assets/user_asset_list.html:50
-#: audits/templates/audits/login_log_list.html:54
+#: assets/templates/assets/user_asset_list.html:49
+#: audits/templates/audits/login_log_list.html:60
 #: perms/templates/perms/asset_permission_asset.html:58 settings/forms.py:140
 #: users/templates/users/_granted_assets.html:26
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:54
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:51
 msgid "IP"
 msgstr "IP"
 
 #: assets/models/asset.py:136 assets/serializers/asset_user.py:27
-#: assets/templates/assets/_asset_list_modal.html:45
+#: assets/templates/assets/_asset_list_modal.html:46
 #: assets/templates/assets/_asset_user_auth_update_modal.html:9
 #: assets/templates/assets/_asset_user_auth_view_modal.html:15
 #: assets/templates/assets/_asset_user_list.html:14
 #: assets/templates/assets/asset_detail.html:60
 #: assets/templates/assets/asset_list.html:96
-#: assets/templates/assets/user_asset_list.html:49
+#: assets/templates/assets/user_asset_list.html:48
 #: perms/templates/perms/asset_permission_asset.html:57
 #: perms/templates/perms/asset_permission_list.html:73 settings/forms.py:139
 #: users/templates/users/_granted_assets.html:25
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:53
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:50
 msgid "Hostname"
 msgstr "主机名"
 
@@ -844,13 +840,13 @@ msgstr "协议"
 
 #: assets/models/asset.py:142 assets/serializers/asset.py:63
 #: assets/templates/assets/asset_create.html:24
-#: assets/templates/assets/user_asset_list.html:51
+#: assets/templates/assets/user_asset_list.html:50
 #: perms/serializers/user_permission.py:38
 msgid "Protocols"
 msgstr "协议组"
 
 #: assets/models/asset.py:143 assets/templates/assets/asset_detail.html:104
-#: assets/templates/assets/user_asset_list.html:52
+#: assets/templates/assets/user_asset_list.html:51
 msgid "Platform"
 msgstr "系统平台"
 
@@ -946,13 +942,13 @@ msgstr "版本"
 msgid "AuthBook"
 msgstr ""
 
-#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:100
-#: xpack/plugins/change_auth_plan/models.py:274
+#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:97
+#: xpack/plugins/change_auth_plan/models.py:271
 msgid "SSH private key"
 msgstr "ssh密钥"
 
-#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:103
-#: xpack/plugins/change_auth_plan/models.py:270
+#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:100
+#: xpack/plugins/change_auth_plan/models.py:267
 msgid "SSH public key"
 msgstr "ssh公钥"
 
@@ -1024,7 +1020,7 @@ msgid "Regex"
 msgstr "正则表达式"
 
 #: assets/models/cmd_filter.py:39 ops/models/command.py:21
-#: ops/templates/ops/command_execution_list.html:61 terminal/models.py:161
+#: ops/templates/ops/command_execution_list.html:64 terminal/models.py:161
 #: terminal/templates/terminal/command_list.html:28
 #: terminal/templates/terminal/command_list.html:68
 #: terminal/templates/terminal/session_detail.html:48
@@ -1046,7 +1042,7 @@ msgstr "过滤器"
 
 #: assets/models/cmd_filter.py:50
 #: assets/templates/assets/cmd_filter_rule_list.html:58
-#: audits/templates/audits/login_log_list.html:52
+#: audits/templates/audits/login_log_list.html:58
 #: perms/templates/perms/remote_app_permission_remote_app.html:54
 #: settings/templates/settings/command_storage_create.html:31
 #: settings/templates/settings/replay_storage_create.html:31
@@ -1094,15 +1090,15 @@ msgid "Default asset group"
 msgstr "默认资产组"
 
 #: assets/models/label.py:15 audits/models.py:17 audits/models.py:37
-#: audits/models.py:50 audits/templates/audits/ftp_log_list.html:33
-#: audits/templates/audits/ftp_log_list.html:70
-#: audits/templates/audits/operate_log_list.html:33
-#: audits/templates/audits/operate_log_list.html:66
-#: audits/templates/audits/password_change_log_list.html:33
-#: audits/templates/audits/password_change_log_list.html:50
-#: ops/templates/ops/command_execution_list.html:35
-#: ops/templates/ops/command_execution_list.html:60
-#: perms/forms/asset_permission.py:63 perms/forms/remote_app_permission.py:31
+#: audits/models.py:50 audits/templates/audits/ftp_log_list.html:36
+#: audits/templates/audits/ftp_log_list.html:73
+#: audits/templates/audits/operate_log_list.html:39
+#: audits/templates/audits/operate_log_list.html:72
+#: audits/templates/audits/password_change_log_list.html:39
+#: audits/templates/audits/password_change_log_list.html:56
+#: ops/templates/ops/command_execution_list.html:38
+#: ops/templates/ops/command_execution_list.html:63
+#: perms/forms/asset_permission.py:73 perms/forms/remote_app_permission.py:31
 #: perms/models/base.py:49
 #: perms/templates/perms/asset_permission_create_update.html:41
 #: perms/templates/perms/asset_permission_list.html:50
@@ -1123,7 +1119,7 @@ msgstr "默认资产组"
 msgid "User"
 msgstr "用户"
 
-#: assets/models/label.py:19 assets/models/node.py:360
+#: assets/models/label.py:19 assets/models/node.py:384
 #: assets/templates/assets/label_list.html:15 settings/models.py:30
 msgid "Value"
 msgstr "值"
@@ -1132,19 +1128,19 @@ msgstr "值"
 msgid "Category"
 msgstr "分类"
 
-#: assets/models/node.py:198
+#: assets/models/node.py:222
 msgid "New node"
 msgstr "新节点"
 
-#: assets/models/node.py:284 perms/api/mixin.py:146
+#: assets/models/node.py:308 perms/api/mixin.py:146
 msgid "ungrouped"
 msgstr "未分组"
 
-#: assets/models/node.py:286 perms/api/mixin.py:151
+#: assets/models/node.py:310 perms/api/mixin.py:151
 msgid "empty"
 msgstr "空"
 
-#: assets/models/node.py:359
+#: assets/models/node.py:383
 msgid "Key"
 msgstr "键"
 
@@ -1175,7 +1171,7 @@ msgstr "手动登录"
 #: assets/views/label.py:27 assets/views/label.py:45 assets/views/label.py:73
 #: assets/views/system_user.py:29 assets/views/system_user.py:46
 #: assets/views/system_user.py:63 assets/views/system_user.py:79
-#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:71
+#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:68
 msgid "Assets"
 msgstr "资产管理"
 
@@ -1322,30 +1318,30 @@ msgstr "测试系统用户可连接性: {} => {}"
 msgid "Test system user connectivity period: {}"
 msgstr "定期测试系统用户可连接性: {}"
 
-#: assets/tasks.py:478 assets/tasks.py:564
-#: xpack/plugins/change_auth_plan/models.py:525
+#: assets/tasks.py:487 assets/tasks.py:573
+#: xpack/plugins/change_auth_plan/models.py:522
 msgid "The asset {} system platform {} does not support run Ansible tasks"
 msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务"
 
-#: assets/tasks.py:490
+#: assets/tasks.py:499
 msgid ""
 "Push system user task skip, auto push not enable or protocol is not ssh or "
 "rdp: {}"
 msgstr "推送系统用户任务跳过,自动推送没有打开,或协议不是ssh或rdp: {}"
 
-#: assets/tasks.py:497
+#: assets/tasks.py:506
 msgid "For security, do not push user {}"
 msgstr "为了安全,禁止推送用户 {}"
 
-#: assets/tasks.py:525 assets/tasks.py:539
+#: assets/tasks.py:534 assets/tasks.py:548
 msgid "Push system users to assets: {}"
 msgstr "推送系统用户到入资产: {}"
 
-#: assets/tasks.py:531
+#: assets/tasks.py:540
 msgid "Push system users to asset: {} => {}"
 msgstr "推送系统用户到入资产: {} => {}"
 
-#: assets/tasks.py:611
+#: assets/tasks.py:620
 msgid "Test asset user connectivity: {}"
 msgstr "测试资产用户可连接性: {}"
 
@@ -1389,10 +1385,18 @@ msgid "Import assets"
 msgstr "导入资产"
 
 #: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:38
-#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:118
+#: templates/_nav.html:22 xpack/plugins/change_auth_plan/views.py:115
 msgid "Asset list"
 msgstr "资产列表"
 
+#: assets/templates/assets/_asset_list_modal.html:33
+#: assets/templates/assets/_node_tree.html:40
+#: users/templates/users/_granted_assets.html:7
+#: users/templates/users/_granted_assets.html:83
+#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66
+msgid "Loading"
+msgstr "加载中"
+
 #: assets/templates/assets/_asset_update_modal.html:4
 msgid "Update assets"
 msgstr "更新资产"
@@ -1402,7 +1406,7 @@ msgid "Update asset user auth"
 msgstr "更新资产用户认证信息"
 
 #: assets/templates/assets/_asset_user_auth_update_modal.html:23
-#: xpack/plugins/change_auth_plan/forms.py:51
+#: xpack/plugins/change_auth_plan/forms.py:108
 msgid "Please input password"
 msgstr "请输入密码"
 
@@ -1430,14 +1434,14 @@ msgstr "获取认证信息错误"
 #: assets/templates/assets/_user_asset_detail_modal.html:23
 #: authentication/templates/authentication/_access_key_modal.html:143
 #: authentication/templates/authentication/_mfa_confirm_modal.html:53
-#: settings/templates/settings/_ldap_list_users_modal.html:99
+#: settings/templates/settings/_ldap_list_users_modal.html:92
 #: templates/_modal.html:22
 msgid "Close"
 msgstr "关闭"
 
 #: assets/templates/assets/_asset_user_list.html:19
-#: audits/templates/audits/operate_log_list.html:71
-#: audits/templates/audits/password_change_log_list.html:53
+#: audits/templates/audits/operate_log_list.html:77
+#: audits/templates/audits/password_change_log_list.html:59
 #: ops/templates/ops/task_adhoc.html:63
 #: terminal/templates/terminal/command_list.html:33
 #: terminal/templates/terminal/session_detail.html:50
@@ -1480,12 +1484,6 @@ msgstr "SSH端口"
 msgid "If use nat, set the ssh real port"
 msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口"
 
-#: assets/templates/assets/_node_tree.html:40
-#: users/templates/users/_granted_assets.html:7
-#: users/templates/users/_granted_assets.html:83
-msgid "Loading"
-msgstr "加载中..."
-
 #: assets/templates/assets/_node_tree.html:50
 msgid "Add node"
 msgstr "新建节点"
@@ -1498,19 +1496,19 @@ msgstr "重命名节点"
 msgid "Delete node"
 msgstr "删除节点"
 
-#: assets/templates/assets/_node_tree.html:161
+#: assets/templates/assets/_node_tree.html:166
 msgid "Create node failed"
 msgstr "创建节点失败"
 
-#: assets/templates/assets/_node_tree.html:173
+#: assets/templates/assets/_node_tree.html:178
 msgid "Have child node, cancel"
 msgstr "存在子节点,不能删除"
 
-#: assets/templates/assets/_node_tree.html:175
+#: assets/templates/assets/_node_tree.html:180
 msgid "Have assets, cancel"
 msgstr "存在资产,不能删除"
 
-#: assets/templates/assets/_node_tree.html:250
+#: assets/templates/assets/_node_tree.html:255
 msgid "Rename success"
 msgstr "重命名成功"
 
@@ -1592,14 +1590,14 @@ msgstr "替换资产的管理员"
 
 #: assets/templates/assets/admin_user_detail.html:91
 #: perms/templates/perms/asset_permission_asset.html:103
-#: xpack/plugins/change_auth_plan/forms.py:59
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:99
+#: xpack/plugins/change_auth_plan/forms.py:116
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:109
 msgid "Select nodes"
 msgstr "选择节点"
 
 #: assets/templates/assets/admin_user_detail.html:100
 #: assets/templates/assets/asset_detail.html:204
-#: assets/templates/assets/asset_list.html:385
+#: assets/templates/assets/asset_list.html:418
 #: assets/templates/assets/cmd_filter_detail.html:106
 #: assets/templates/assets/system_user_assets.html:97
 #: assets/templates/assets/system_user_detail.html:182
@@ -1637,7 +1635,7 @@ msgstr "Jumpserver 使用该用户来 `推送系统用户`、`获取资产硬件
 #: assets/templates/assets/admin_user_list.html:16
 #: assets/templates/assets/asset_list.html:68
 #: assets/templates/assets/system_user_list.html:23
-#: audits/templates/audits/login_log_list.html:85
+#: audits/templates/audits/login_log_list.html:91
 #: users/templates/users/user_group_list.html:10
 #: users/templates/users/user_list.html:10
 #: xpack/plugins/vault/templates/vault/vault.html:55
@@ -1647,7 +1645,7 @@ msgstr "导出"
 #: assets/templates/assets/admin_user_list.html:21
 #: assets/templates/assets/asset_list.html:73
 #: assets/templates/assets/system_user_list.html:28
-#: settings/templates/settings/_ldap_list_users_modal.html:100
+#: settings/templates/settings/_ldap_list_users_modal.html:93
 #: users/templates/users/user_group_list.html:15
 #: users/templates/users/user_list.html:15
 #: xpack/plugins/license/templates/license/license_detail.html:110
@@ -1662,8 +1660,8 @@ msgstr "创建管理用户"
 
 #: assets/templates/assets/admin_user_list.html:162
 #: assets/templates/assets/admin_user_list.html:193
-#: assets/templates/assets/asset_list.html:266
-#: assets/templates/assets/asset_list.html:303
+#: assets/templates/assets/asset_list.html:299
+#: assets/templates/assets/asset_list.html:336
 #: assets/templates/assets/system_user_list.html:192
 #: assets/templates/assets/system_user_list.html:223
 #: users/templates/users/user_group_list.html:164
@@ -1720,7 +1718,7 @@ msgstr "创建日期"
 
 #: assets/templates/assets/asset_detail.html:150 authentication/models.py:15
 #: authentication/templates/authentication/_access_key_modal.html:28
-#: perms/models/asset_permission.py:116 perms/models/base.py:51
+#: perms/models/base.py:51
 #: perms/templates/perms/asset_permission_create_update.html:55
 #: perms/templates/perms/asset_permission_detail.html:120
 #: perms/templates/perms/remote_app_permission_create_update.html:54
@@ -1805,7 +1803,7 @@ msgstr "仅显示当前节点资产"
 msgid "Displays all child node assets"
 msgstr "显示所有子节点资产"
 
-#: assets/templates/assets/asset_list.html:379
+#: assets/templates/assets/asset_list.html:412
 #: assets/templates/assets/system_user_list.html:133
 #: users/templates/users/user_detail.html:386
 #: users/templates/users/user_detail.html:412
@@ -1816,11 +1814,11 @@ msgstr "显示所有子节点资产"
 msgid "Are you sure?"
 msgstr "你确认吗?"
 
-#: assets/templates/assets/asset_list.html:380
+#: assets/templates/assets/asset_list.html:413
 msgid "This will delete the selected assets !!!"
 msgstr "删除选择资产"
 
-#: assets/templates/assets/asset_list.html:383
+#: assets/templates/assets/asset_list.html:416
 #: assets/templates/assets/system_user_list.html:137
 #: settings/templates/settings/terminal_setting.html:166
 #: users/templates/users/user_detail.html:390
@@ -1834,16 +1832,16 @@ msgstr "删除选择资产"
 msgid "Cancel"
 msgstr "取消"
 
-#: assets/templates/assets/asset_list.html:396
+#: assets/templates/assets/asset_list.html:429
 msgid "Asset Deleted."
 msgstr "已被删除"
 
-#: assets/templates/assets/asset_list.html:397
-#: assets/templates/assets/asset_list.html:401
+#: assets/templates/assets/asset_list.html:430
+#: assets/templates/assets/asset_list.html:434
 msgid "Asset Delete"
 msgstr "删除"
 
-#: assets/templates/assets/asset_list.html:400
+#: assets/templates/assets/asset_list.html:433
 msgid "Asset Deleting failed."
 msgstr "删除失败"
 
@@ -2133,27 +2131,27 @@ msgid "System user asset"
 msgstr "系统用户资产"
 
 #: audits/models.py:18 audits/models.py:41 audits/models.py:52
-#: audits/templates/audits/ftp_log_list.html:73
-#: audits/templates/audits/operate_log_list.html:70
-#: audits/templates/audits/password_change_log_list.html:52
+#: audits/templates/audits/ftp_log_list.html:76
+#: audits/templates/audits/operate_log_list.html:76
+#: audits/templates/audits/password_change_log_list.html:58
 #: terminal/models.py:158 terminal/templates/terminal/session_list.html:30
 #: terminal/templates/terminal/session_list.html:74
 #: terminal/templates/terminal/terminal_detail.html:47
 msgid "Remote addr"
 msgstr "远端地址"
 
-#: audits/models.py:21 audits/templates/audits/ftp_log_list.html:74
+#: audits/models.py:21 audits/templates/audits/ftp_log_list.html:77
 msgid "Operate"
 msgstr "操作"
 
-#: audits/models.py:22 audits/templates/audits/ftp_log_list.html:56
-#: audits/templates/audits/ftp_log_list.html:75
+#: audits/models.py:22 audits/templates/audits/ftp_log_list.html:59
+#: audits/templates/audits/ftp_log_list.html:78
 msgid "Filename"
 msgstr "文件名"
 
 #: audits/models.py:23 audits/models.py:76
-#: audits/templates/audits/ftp_log_list.html:76
-#: ops/templates/ops/command_execution_list.html:65
+#: audits/templates/audits/ftp_log_list.html:79
+#: ops/templates/ops/command_execution_list.html:68
 #: ops/templates/ops/task_list.html:31
 #: users/templates/users/user_detail.html:462
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:14
@@ -2167,16 +2165,16 @@ msgstr "成功"
 msgid "Create"
 msgstr "创建"
 
-#: audits/models.py:39 audits/templates/audits/operate_log_list.html:49
-#: audits/templates/audits/operate_log_list.html:68
+#: audits/models.py:39 audits/templates/audits/operate_log_list.html:55
+#: audits/templates/audits/operate_log_list.html:74
 msgid "Resource Type"
 msgstr "资源类型"
 
-#: audits/models.py:40 audits/templates/audits/operate_log_list.html:69
+#: audits/models.py:40 audits/templates/audits/operate_log_list.html:75
 msgid "Resource"
 msgstr "资源"
 
-#: audits/models.py:51 audits/templates/audits/password_change_log_list.html:51
+#: audits/models.py:51 audits/templates/audits/password_change_log_list.html:57
 msgid "Change by"
 msgstr "修改者"
 
@@ -2214,22 +2212,22 @@ msgstr "登录城市"
 msgid "User agent"
 msgstr "Agent"
 
-#: audits/models.py:85 audits/templates/audits/login_log_list.html:56
+#: audits/models.py:85 audits/templates/audits/login_log_list.html:62
 #: authentication/templates/authentication/_mfa_confirm_modal.html:14
 #: users/forms.py:175 users/models/user.py:352
 #: users/templates/users/first_login.html:45
 msgid "MFA"
 msgstr "MFA"
 
-#: audits/models.py:86 audits/templates/audits/login_log_list.html:57
-#: xpack/plugins/change_auth_plan/models.py:420
+#: audits/models.py:86 audits/templates/audits/login_log_list.html:63
+#: xpack/plugins/change_auth_plan/models.py:417
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15
 #: xpack/plugins/cloud/models.py:281
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:69
 msgid "Reason"
 msgstr "原因"
 
-#: audits/models.py:87 audits/templates/audits/login_log_list.html:58
+#: audits/models.py:87 audits/templates/audits/login_log_list.html:64
 #: xpack/plugins/cloud/models.py:278 xpack/plugins/cloud/models.py:313
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:70
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:65
@@ -2240,33 +2238,33 @@ msgstr "状态"
 msgid "Date login"
 msgstr "登录日期"
 
-#: audits/templates/audits/ftp_log_list.html:77
+#: audits/templates/audits/ftp_log_list.html:80
 #: ops/templates/ops/adhoc_history.html:52
 #: ops/templates/ops/adhoc_history_detail.html:61
-#: ops/templates/ops/command_execution_list.html:66
+#: ops/templates/ops/command_execution_list.html:69
 #: ops/templates/ops/task_history.html:58 perms/models/base.py:52
 #: perms/templates/perms/asset_permission_detail.html:86
 #: perms/templates/perms/remote_app_permission_detail.html:78
 #: terminal/models.py:165 terminal/templates/terminal/session_list.html:34
-#: xpack/plugins/change_auth_plan/models.py:253
-#: xpack/plugins/change_auth_plan/models.py:423
+#: xpack/plugins/change_auth_plan/models.py:250
+#: xpack/plugins/change_auth_plan/models.py:420
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17
 msgid "Date start"
 msgstr "开始日期"
 
-#: audits/templates/audits/login_log_list.html:28
+#: audits/templates/audits/login_log_list.html:34
 #: perms/templates/perms/asset_permission_user.html:88
 #: perms/templates/perms/remote_app_permission_user.html:87
 msgid "Select user"
 msgstr "选择用户"
 
-#: audits/templates/audits/login_log_list.html:35
-#: audits/templates/audits/login_log_list.html:40
-#: audits/templates/audits/operate_log_list.html:58
-#: audits/templates/audits/password_change_log_list.html:42
-#: ops/templates/ops/command_execution_list.html:43
-#: ops/templates/ops/command_execution_list.html:48
+#: audits/templates/audits/login_log_list.html:41
+#: audits/templates/audits/login_log_list.html:46
+#: audits/templates/audits/operate_log_list.html:64
+#: audits/templates/audits/password_change_log_list.html:48
+#: ops/templates/ops/command_execution_list.html:46
+#: ops/templates/ops/command_execution_list.html:51
 #: ops/templates/ops/task_list.html:13 ops/templates/ops/task_list.html:18
 #: templates/_base_list.html:41
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:52
@@ -2274,7 +2272,7 @@ msgstr "选择用户"
 msgid "Search"
 msgstr "搜索"
 
-#: audits/templates/audits/login_log_list.html:50
+#: audits/templates/audits/login_log_list.html:56
 #: authentication/templates/authentication/_access_key_modal.html:26
 #: ops/templates/ops/adhoc_detail.html:49
 #: ops/templates/ops/adhoc_history_detail.html:49
@@ -2285,15 +2283,15 @@ msgstr "搜索"
 msgid "ID"
 msgstr "ID"
 
-#: audits/templates/audits/login_log_list.html:53
+#: audits/templates/audits/login_log_list.html:59
 msgid "UA"
 msgstr "Agent"
 
-#: audits/templates/audits/login_log_list.html:55
+#: audits/templates/audits/login_log_list.html:61
 msgid "City"
 msgstr "城市"
 
-#: audits/templates/audits/login_log_list.html:59
+#: audits/templates/audits/login_log_list.html:65
 #: authentication/templates/authentication/_access_key_modal.html:29
 #: ops/templates/ops/task_list.html:32
 msgid "Date"
@@ -2672,16 +2670,16 @@ msgstr ""
 msgid "Encrypt field using Secret Key"
 msgstr ""
 
-#: common/mixins/api.py:62
+#: common/mixins/api.py:63
 #, python-format
 msgid "%(name)s was %(action)s successfully"
 msgstr "%(name)s %(action)s成功"
 
-#: common/mixins/api.py:63
+#: common/mixins/api.py:64
 msgid "create"
 msgstr "创建"
 
-#: common/mixins/api.py:63
+#: common/mixins/api.py:64
 msgid "update"
 msgstr "更新"
 
@@ -2757,7 +2755,7 @@ msgid "Options"
 msgstr "选项"
 
 #: ops/models/adhoc.py:161 ops/templates/ops/adhoc_detail.html:53
-#: ops/templates/ops/command_execution_list.html:59
+#: ops/templates/ops/command_execution_list.html:62
 #: ops/templates/ops/task_adhoc.html:59 ops/templates/ops/task_list.html:30
 #: settings/templates/settings/command_storage_create.html:49
 msgid "Hosts"
@@ -2802,8 +2800,8 @@ msgstr "完成时间"
 
 #: ops/models/adhoc.py:327 ops/templates/ops/adhoc_history.html:57
 #: ops/templates/ops/task_history.html:63 ops/templates/ops/task_list.html:33
-#: xpack/plugins/change_auth_plan/models.py:256
-#: xpack/plugins/change_auth_plan/models.py:426
+#: xpack/plugins/change_auth_plan/models.py:253
+#: xpack/plugins/change_auth_plan/models.py:423
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16
 msgid "Time"
@@ -2859,7 +2857,7 @@ msgstr "执行历史"
 
 #: ops/templates/ops/adhoc_detail.html:72
 #: ops/templates/ops/adhoc_detail.html:77
-#: ops/templates/ops/command_execution_list.html:62
+#: ops/templates/ops/command_execution_list.html:65
 #: ops/templates/ops/task_adhoc.html:61
 msgid "Run as"
 msgstr "运行用户"
@@ -2922,7 +2920,7 @@ msgid "Run history detail"
 msgstr "执行历史详情"
 
 #: ops/templates/ops/adhoc_history_detail.html:22
-#: ops/templates/ops/command_execution_list.html:63
+#: ops/templates/ops/command_execution_list.html:66
 #: terminal/backends/command/models.py:16
 msgid "Output"
 msgstr "输出"
@@ -2988,7 +2986,7 @@ msgstr "没有选择系统用户"
 msgid "Pending"
 msgstr "等待"
 
-#: ops/templates/ops/command_execution_list.html:64
+#: ops/templates/ops/command_execution_list.html:67
 msgid "Finished"
 msgstr "结束"
 
@@ -3078,9 +3076,8 @@ msgstr "未分组"
 msgid "Empty"
 msgstr "空"
 
-#: perms/forms/asset_permission.py:66 perms/forms/remote_app_permission.py:34
-#: perms/models/asset_permission.py:114 perms/models/base.py:50
-#: perms/templates/perms/asset_permission_list.html:51
+#: perms/forms/asset_permission.py:76 perms/forms/remote_app_permission.py:34
+#: perms/models/base.py:50 perms/templates/perms/asset_permission_list.html:51
 #: perms/templates/perms/asset_permission_list.html:71
 #: perms/templates/perms/asset_permission_list.html:118
 #: perms/templates/perms/remote_app_permission_list.html:16
@@ -3092,17 +3089,17 @@ msgstr "空"
 msgid "User group"
 msgstr "用户组"
 
-#: perms/forms/asset_permission.py:82
+#: perms/forms/asset_permission.py:92
 msgid ""
 "Tips: The RDP protocol does not support separate controls for uploading or "
 "downloading files"
 msgstr "提示:RDP 协议不支持单独控制上传或下载文件"
 
-#: perms/forms/asset_permission.py:92 perms/forms/remote_app_permission.py:47
+#: perms/forms/asset_permission.py:102 perms/forms/remote_app_permission.py:47
 msgid "User or group at least one required"
 msgstr "用户和用户组至少选一个"
 
-#: perms/forms/asset_permission.py:101
+#: perms/forms/asset_permission.py:111
 msgid "Asset or group at least one required"
 msgstr "资产和节点至少选一个"
 
@@ -3122,16 +3119,15 @@ msgstr "下载文件"
 msgid "Upload download"
 msgstr "上传下载"
 
-#: perms/models/asset_permission.py:82
+#: perms/models/asset_permission.py:81
 msgid "Actions"
 msgstr "动作"
 
-#: perms/models/asset_permission.py:86 perms/models/asset_permission.py:126
-#: templates/_nav.html:44
+#: perms/models/asset_permission.py:85 templates/_nav.html:44
 msgid "Asset permission"
 msgstr "资产授权"
 
-#: perms/models/asset_permission.py:117 perms/models/base.py:53
+#: perms/models/base.py:53
 #: perms/templates/perms/asset_permission_detail.html:90
 #: perms/templates/perms/remote_app_permission_detail.html:82
 #: users/models/user.py:368 users/templates/users/user_detail.html:107
@@ -3175,7 +3171,7 @@ msgstr "添加资产"
 #: settings/templates/settings/terminal_setting.html:98
 #: settings/templates/settings/terminal_setting.html:120
 #: users/templates/users/user_group_detail.html:95
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:80
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:90
 #: xpack/plugins/orgs/templates/orgs/org_detail.html:93
 #: xpack/plugins/orgs/templates/orgs/org_detail.html:130
 msgid "Add"
@@ -3185,9 +3181,9 @@ msgstr "添加"
 msgid "Add node to this permission"
 msgstr "添加节点"
 
-#: perms/templates/perms/asset_permission_asset.html:112
+#: perms/templates/perms/asset_permission_asset.html:109
 #: users/templates/users/user_detail.html:234
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:105
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:115
 msgid "Join"
 msgstr "加入"
 
@@ -3242,7 +3238,7 @@ msgstr "刷新授权缓存"
 msgid "Validity"
 msgstr "有效"
 
-#: perms/templates/perms/asset_permission_list.html:245
+#: perms/templates/perms/asset_permission_list.html:244
 msgid "Refresh success"
 msgstr "刷新成功"
 
@@ -3687,13 +3683,13 @@ msgstr "LDAP 用户列表"
 msgid "Please submit the LDAP configuration before import"
 msgstr "请先提交LDAP配置再进行导入"
 
-#: settings/templates/settings/_ldap_list_users_modal.html:39
+#: settings/templates/settings/_ldap_list_users_modal.html:32
 #: users/models/user.py:332 users/templates/users/user_detail.html:71
 #: users/templates/users/user_profile.html:59
 msgid "Email"
 msgstr "邮件"
 
-#: settings/templates/settings/_ldap_list_users_modal.html:40
+#: settings/templates/settings/_ldap_list_users_modal.html:33
 msgid "Existing"
 msgstr "已存在"
 
@@ -4529,7 +4525,7 @@ msgstr "生成重置密码链接,通过邮件发送给用户"
 msgid "Set password"
 msgstr "设置密码"
 
-#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:89
+#: users/forms.py:133 xpack/plugins/change_auth_plan/models.py:86
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:51
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:69
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57
@@ -5416,7 +5412,21 @@ msgstr "MFA 解绑成功,返回登录页面"
 msgid "Password length"
 msgstr "密码长度"
 
-#: xpack/plugins/change_auth_plan/forms.py:66
+#: xpack/plugins/change_auth_plan/forms.py:51
+#: xpack/plugins/change_auth_plan/models.py:213
+msgid "* For security, do not change {} user's password"
+msgstr "* 为了安全,禁止更改 {} 用户的密码"
+
+#: xpack/plugins/change_auth_plan/forms.py:61
+msgid "* Please enter custom password"
+msgstr "* 请输入自定义密码"
+
+#: xpack/plugins/change_auth_plan/forms.py:70
+#: xpack/plugins/cloud/serializers.py:73
+msgid "* Please enter a valid crontab expression"
+msgstr "* 请输入有效的 crontab 表达式"
+
+#: xpack/plugins/change_auth_plan/forms.py:123
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:60
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:81
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17
@@ -5427,7 +5437,7 @@ msgstr "密码长度"
 msgid "Periodic perform"
 msgstr "定时执行"
 
-#: xpack/plugins/change_auth_plan/forms.py:70
+#: xpack/plugins/change_auth_plan/forms.py:127
 msgid ""
 "Tips: The username of the user on the asset to be modified. if the user "
 "exists, change the password; If the user does not exist, create the user."
@@ -5435,11 +5445,11 @@ msgstr ""
 "提示:用户名为将要修改的资产上的用户的用户名。如果用户存在,则修改密码;如果"
 "用户不存在,则创建用户。"
 
-#: xpack/plugins/change_auth_plan/forms.py:74 xpack/plugins/cloud/forms.py:90
+#: xpack/plugins/change_auth_plan/forms.py:131 xpack/plugins/cloud/forms.py:90
 msgid "Tips: (Units: hour)"
 msgstr "提示:(单位: 时)"
 
-#: xpack/plugins/change_auth_plan/forms.py:75 xpack/plugins/cloud/forms.py:91
+#: xpack/plugins/change_auth_plan/forms.py:132 xpack/plugins/cloud/forms.py:91
 msgid ""
 "eg: Every Sunday 03:05 run <5 3 * * 0> <br> Tips: Using 5 digits linux "
 "crontab expressions <min hour day month week> (<a href='https://tool.lu/"
@@ -5451,113 +5461,88 @@ msgstr ""
 "具</a>) <br>注意: 如果同时设置了定期执行和周期执行,优先使用定期执行"
 
 #: xpack/plugins/change_auth_plan/meta.py:9
-#: xpack/plugins/change_auth_plan/models.py:117
-#: xpack/plugins/change_auth_plan/models.py:260
+#: xpack/plugins/change_auth_plan/models.py:114
+#: xpack/plugins/change_auth_plan/models.py:257
 #: xpack/plugins/change_auth_plan/views.py:33
 #: xpack/plugins/change_auth_plan/views.py:50
-#: xpack/plugins/change_auth_plan/views.py:74
-#: xpack/plugins/change_auth_plan/views.py:90
-#: xpack/plugins/change_auth_plan/views.py:117
-#: xpack/plugins/change_auth_plan/views.py:132
-#: xpack/plugins/change_auth_plan/views.py:147
+#: xpack/plugins/change_auth_plan/views.py:72
+#: xpack/plugins/change_auth_plan/views.py:87
+#: xpack/plugins/change_auth_plan/views.py:114
+#: xpack/plugins/change_auth_plan/views.py:129
+#: xpack/plugins/change_auth_plan/views.py:144
 msgid "Change auth plan"
 msgstr "改密计划"
 
-#: xpack/plugins/change_auth_plan/models.py:58
+#: xpack/plugins/change_auth_plan/models.py:55
 msgid "Custom password"
 msgstr "自定义密码"
 
-#: xpack/plugins/change_auth_plan/models.py:59
+#: xpack/plugins/change_auth_plan/models.py:56
 msgid "All assets use the same random password"
 msgstr "所有资产使用相同的随机密码"
 
-#: xpack/plugins/change_auth_plan/models.py:60
+#: xpack/plugins/change_auth_plan/models.py:57
 msgid "All assets use different random password"
 msgstr "所有资产使用不同的随机密码"
 
-#: xpack/plugins/change_auth_plan/models.py:79
-#: xpack/plugins/change_auth_plan/models.py:148
+#: xpack/plugins/change_auth_plan/models.py:76
+#: xpack/plugins/change_auth_plan/models.py:145
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:100
 #: xpack/plugins/cloud/models.py:165 xpack/plugins/cloud/models.py:219
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:91
 msgid "Cycle perform"
 msgstr "周期执行"
 
-#: xpack/plugins/change_auth_plan/models.py:84
-#: xpack/plugins/change_auth_plan/models.py:146
+#: xpack/plugins/change_auth_plan/models.py:81
+#: xpack/plugins/change_auth_plan/models.py:143
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:92
 #: xpack/plugins/cloud/models.py:170 xpack/plugins/cloud/models.py:217
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:83
 msgid "Regularly perform"
 msgstr "定期执行"
 
-#: xpack/plugins/change_auth_plan/models.py:93
+#: xpack/plugins/change_auth_plan/models.py:90
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:74
 msgid "Password rules"
 msgstr "密码规则"
 
-#: xpack/plugins/change_auth_plan/models.py:216
-msgid "* For security, do not change {} user's password"
-msgstr "* 为了安全,禁止更改 {} 用户的密码"
-
-#: xpack/plugins/change_auth_plan/models.py:220
+#: xpack/plugins/change_auth_plan/models.py:217
 msgid "Assets is empty, please add the asset"
 msgstr "资产为空,请添加资产"
 
-#: xpack/plugins/change_auth_plan/models.py:264
+#: xpack/plugins/change_auth_plan/models.py:261
 msgid "Change auth plan snapshot"
 msgstr "改密计划快照"
 
-#: xpack/plugins/change_auth_plan/models.py:279
-#: xpack/plugins/change_auth_plan/models.py:430
+#: xpack/plugins/change_auth_plan/models.py:276
+#: xpack/plugins/change_auth_plan/models.py:427
 msgid "Change auth plan execution"
 msgstr "改密计划执行"
 
-#: xpack/plugins/change_auth_plan/models.py:439
+#: xpack/plugins/change_auth_plan/models.py:436
 msgid "Change auth plan execution subtask"
 msgstr "改密计划执行子任务"
 
-#: xpack/plugins/change_auth_plan/models.py:457
+#: xpack/plugins/change_auth_plan/models.py:454
 msgid "Authentication failed"
 msgstr "认证失败"
 
-#: xpack/plugins/change_auth_plan/models.py:459
+#: xpack/plugins/change_auth_plan/models.py:456
 msgid "Connection timeout"
 msgstr "连接超时"
 
-#: xpack/plugins/change_auth_plan/serializers.py:58
-msgid "* For security, do not change {}'s password"
-msgstr "* 为了安全,禁止更改 {} 的密码"
-
-#: xpack/plugins/change_auth_plan/serializers.py:65
-msgid "* Please enter custom password"
-msgstr "* 请输入自定义密码"
-
-#: xpack/plugins/change_auth_plan/serializers.py:75
-msgid "* Please enter the correct password length"
-msgstr "* 请输入正确的密码长度"
-
-#: xpack/plugins/change_auth_plan/serializers.py:78
-msgid "* Password length range 6-30 bits"
-msgstr "* 密码长度范围 6-30 位"
-
-#: xpack/plugins/change_auth_plan/serializers.py:94
-#: xpack/plugins/cloud/serializers.py:73
-msgid "* Please enter a valid crontab expression"
-msgstr "* 请输入有效的 crontab 表达式"
-
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:23
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:26
 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:23
-#: xpack/plugins/change_auth_plan/views.py:133
+#: xpack/plugins/change_auth_plan/views.py:130
 msgid "Plan execution list"
 msgstr "执行列表"
 
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:66
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:76
 msgid "Add asset to this plan"
 msgstr "添加资产"
 
-#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:91
+#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:101
 msgid "Add node to this plan"
 msgstr "添加节点"
 
@@ -5616,11 +5601,11 @@ msgstr "创建计划"
 msgid "Plan list"
 msgstr "计划列表"
 
-#: xpack/plugins/change_auth_plan/views.py:75
+#: xpack/plugins/change_auth_plan/views.py:73
 msgid "Update plan"
 msgstr "更新计划"
 
-#: xpack/plugins/change_auth_plan/views.py:148
+#: xpack/plugins/change_auth_plan/views.py:145
 msgid "Plan execution task list"
 msgstr "执行任务列表"
 
@@ -5776,10 +5761,6 @@ msgstr "地域 & 实例"
 msgid "Node & AdminUser"
 msgstr "节点 & 管理用户"
 
-#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66
-msgid "Loading..."
-msgstr "加载中..."
-
 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:67
 msgid "Load failed"
 msgstr "加载失败"
@@ -6087,6 +6068,18 @@ msgstr "密码匣子"
 msgid "vault create"
 msgstr "创建"
 
+#~ msgid "* For security, do not change {}'s password"
+#~ msgstr "* 为了安全,禁止更改 {} 的密码"
+
+#~ msgid "* Please enter the correct password length"
+#~ msgstr "* 请输入正确的密码长度"
+
+#~ msgid "* Password length range 6-30 bits"
+#~ msgstr "* 密码长度范围 6-30 位"
+
+#~ msgid "Loading..."
+#~ msgstr "加载中..."
+
 #~ msgid "You do not have permission."
 #~ msgstr "你没有权限"
 
diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py
index 64d979c25..d2f55f623 100644
--- a/apps/ops/tasks.py
+++ b/apps/ops/tasks.py
@@ -40,7 +40,7 @@ def run_ansible_task(tid, callback=None, **kwargs):
         logger.error("No task found")
 
 
-@shared_task(soft_time_limit=60)
+@shared_task(soft_time_limit=60, queue="ansible")
 def run_command_execution(cid, **kwargs):
     execution = get_object_or_none(CommandExecution, id=cid)
     if execution:
diff --git a/apps/ops/templates/ops/command_execution_list.html b/apps/ops/templates/ops/command_execution_list.html
index fe8b7122c..81e9635c6 100644
--- a/apps/ops/templates/ops/command_execution_list.html
+++ b/apps/ops/templates/ops/command_execution_list.html
@@ -9,6 +9,9 @@
     <link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
     <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
     <style>
+        .form-control {
+            height: 30px;
+        }
 
         #search_btn {
             margin-bottom: 0;
@@ -88,13 +91,6 @@
 <script src="{% static "js/plugins/footable/footable.all.min.js" %}"></script>
 <script>
 $(document).ready(function() {
-    {#$('table').DataTable({#}
-    {#    "searching": false,#}
-    {#    "paging": false,#}
-    {#    "bInfo" : false,#}
-    {#    "order": []#}
-    {# });#}
-    {#$('.footable').footable();#}
     $('.select2').select2({
         dropdownAutoWidth : true,
         width: 'auto'
@@ -116,7 +112,14 @@ $(document).ready(function() {
         var html = createPopover(data_list);
         $(this).html(html);
     });
-    $('[data-toggle="popover"]').popover();
+    $('[data-toggle="popover"]').popover({
+        html: true,
+        placement: 'bottom',
+        trigger: 'click',
+        container: 'body'
+    }).on('click', function (e) {
+        $('[data-toggle="popover"]').not(this).popover('hide');
+    });
 })
 </script>
 {% endblock %}
diff --git a/apps/orgs/mixins/api.py b/apps/orgs/mixins/api.py
index 1537982a0..d36360f51 100644
--- a/apps/orgs/mixins/api.py
+++ b/apps/orgs/mixins/api.py
@@ -35,6 +35,10 @@ class OrgBulkModelViewSet(IDInCacheFilterMixin, BulkModelViewSet):
         return queryset
 
     def allow_bulk_destroy(self, qs, filtered):
+        if qs.count() <= filtered.count():
+            return False
+        if self.request.query_params.get('spm', ''):
+            return True
         return False
 
 
diff --git a/apps/perms/api/asset_permission.py b/apps/perms/api/asset_permission.py
index 810ae5ac9..3e7f4a078 100644
--- a/apps/perms/api/asset_permission.py
+++ b/apps/perms/api/asset_permission.py
@@ -97,6 +97,8 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
         inherit_nodes_keys = assets.all().values_list('nodes__key', flat=True)
 
         for key in inherit_nodes_keys:
+            if key is None:
+                continue
             ancestor_keys = Node.get_nodes_ancestor_keys_by_key(key, with_self=True)
             inherit_all_nodes.update(ancestor_keys)
         queryset = queryset.filter(
diff --git a/apps/perms/forms/asset_permission.py b/apps/perms/forms/asset_permission.py
index 1d80258d4..6fdaee30b 100644
--- a/apps/perms/forms/asset_permission.py
+++ b/apps/perms/forms/asset_permission.py
@@ -53,6 +53,16 @@ class AssetPermissionForm(OrgModelForm):
             assets_field.queryset = Asset.objects.none()
             nodes_field.queryset = Node.objects.none()
 
+    def set_nodes_initial(self, nodes):
+        field = self.fields['nodes']
+        field.choices = [(n.id, n.full_value) for n in nodes]
+        field.initial = nodes
+
+    def set_assets_initial(self, assets):
+        field = self.fields['assets']
+        field.choices = [(a.id, a.hostname) for a in assets]
+        field.initial = assets
+
     class Meta:
         model = AssetPermission
         exclude = (
diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py
index e23bc1f8c..8066ce5ca 100644
--- a/apps/perms/signals_handler.py
+++ b/apps/perms/signals_handler.py
@@ -47,7 +47,7 @@ def on_permission_nodes_changed(sender, instance=None, action='', **kwargs):
     if isinstance(instance, AssetPermission):
         logger.debug("Asset permission nodes change signal received")
         nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
-        system_users = instance.system_users.all().values_list('id', flat=True)
+        system_users = instance.system_users.all()
         for system_user in system_users:
             system_user.nodes.add(*tuple(nodes))
 
@@ -59,7 +59,7 @@ def on_permission_assets_changed(sender, instance=None, action='', **kwargs):
     if isinstance(instance, AssetPermission):
         logger.debug("Asset permission assets change signal received")
         assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
-        system_users = instance.system_users.all().values_list('id', flat=True)
+        system_users = instance.system_users.all()
         for system_user in system_users:
             system_user.assets.add(*tuple(assets))
 
diff --git a/apps/perms/templates/perms/asset_permission_asset.html b/apps/perms/templates/perms/asset_permission_asset.html
index ccb1b7f90..093ab39a8 100644
--- a/apps/perms/templates/perms/asset_permission_asset.html
+++ b/apps/perms/templates/perms/asset_permission_asset.html
@@ -100,10 +100,7 @@
                                         <form>
                                             <tr>
                                                 <td colspan="2" class="no-borders">
-                                                    <select data-placeholder="{% trans 'Select nodes' %}" class="select2" id="node_select2" style="width: 100%" multiple="" tabindex="4">
-                                                        {% for node in nodes_remain %}
-                                                        <option value="{{ node.id }}" id="opt_{{ node.id }}">{{ node.full_value }}</option>
-                                                        {% endfor %}
+                                                    <select data-placeholder="{% trans 'Select nodes' %}" class="nodes-select2" id="nodes_select2" style="width: 100%" multiple="" tabindex="4">
                                                     </select>
                                                 </td>
                                             </tr>
@@ -202,35 +199,22 @@ function initAssetTable() {
     return table
 }
 
+
 $(document).ready(function () {
     $('.select2').select2();
     table = initAssetTable();
+
+    var nodeListUrl = "{% url 'api-assets:node-list' %}";
+    nodesSelect2Init(".nodes-select2", nodeListUrl);
+
     $("#asset_select2").parent().find(".select2-selection").on('click', function (e) {
         if ($(e.target).attr('class') !== 'select2-selection__choice__remove'){
             e.preventDefault();
             e.stopPropagation();
             $("#asset_list_modal").modal();
-            initSelectedAssets2Table('#asset_select2');
         }
     })
 })
-.on('click', '#btn_asset_modal_confirm', function () {
-    var assets = asset_table2.selected;
-    var options = [];
-    $('#asset_select2 option').each(function (i, v) {
-        options.push(v.value)
-    });
-    asset_table2.selected_rows.forEach(function (i) {
-        var name = i.hostname + '(' + i.ip + ')';
-        var option = new Option(name, i.id, false, true);
-
-        if (options.indexOf(i.id) === -1) {
-            $('#asset_select2').append(option).trigger('change');
-        }
-    });
-    $('#asset_select2').val(assets).trigger('change');
-    $("#asset_list_modal").modal('hide');
-})
 .on('click', '.btn-add-assets', function () {
     var assets_selected = $("#asset_select2 option:selected").map(function () {
         return $(this).attr('value');
@@ -250,7 +234,7 @@ $(document).ready(function () {
 })
 .on('click', '#btn-add-node', function () {
     var nodes_selected = {};
-    $("#node_select2 option:selected").each(function (i, data) {
+    $("#nodes_select2 option:selected").each(function (i, data) {
         nodes_selected[$(data).attr('value')] = $(data).text();
     });
     if (Object.keys(nodes_selected).length === 0) {
diff --git a/apps/perms/templates/perms/asset_permission_create_update.html b/apps/perms/templates/perms/asset_permission_create_update.html
index 5b69f7b4c..02d51e220 100644
--- a/apps/perms/templates/perms/asset_permission_create_update.html
+++ b/apps/perms/templates/perms/asset_permission_create_update.html
@@ -111,42 +111,25 @@ var dateOptions = {
     }
 };
 var api_action =  "{{ api_action }}";
+
 $(document).ready(function () {
     $('.select2').select2({
         closeOnSelect: false
     });
     var url = "{% url 'api-assets:node-list' %}";
     nodesSelect2Init(".nodes-select2", url);
+
     $('#date_start').daterangepicker(dateOptions);
     $('#date_expired').daterangepicker(dateOptions);
+
     $("#id_assets").parent().find(".select2-selection").on('click', function (e) {
         if ($(e.target).attr('class') !== 'select2-selection__choice__remove'){
             e.preventDefault();
             e.stopPropagation();
             $("#asset_list_modal").modal();
-            initSelectedAssets2Table();
         }
     })
 })
-.on('click', '#btn_asset_modal_confirm', function () {
-    var assets = asset_table2.selected;
-
-    var options = [];
-    $('#id_assets option').each(function (i, v) {
-        options.push(v.value)
-    });
-    asset_table2.selected_rows.forEach(function (i) {
-        var name = i.hostname + '(' + i.ip + ')';
-        var option = new Option(name, i.id, false, true);
-
-        if (options.indexOf(i.id) === -1) {
-            $('#id_assets').append(option).trigger('change');
-        }
-    });
-
-    $('#id_assets').val(assets).trigger('change');
-    $("#asset_list_modal").modal('hide');
-})
 .on("submit", "form", function (evt) {
     evt.preventDefault();
     var the_url = '{% url 'api-perms:asset-permission-list' %}';
diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html
index 95a92f16b..2a493e16b 100644
--- a/apps/perms/templates/perms/asset_permission_list.html
+++ b/apps/perms/templates/perms/asset_permission_list.html
@@ -227,7 +227,6 @@ function toggle() {
 $(document).ready(function(){
     initTable();
     initTree();
-
 })
 .on('click', '.btn-del', function () {
     var $this = $(this);
@@ -247,17 +246,19 @@ $(document).ready(function(){
 })
 .on('click', '.btn-create-permission', function () {
     var url = "{% url 'perms:asset-permission-create' %}";
-    var nodes = zTree.getSelectedNodes();
-    var _nodes = [];
-    var _assets = [];
-    $.each(nodes, function (id, node) {
-        if (node.meta.type === 'node') {
-            _nodes.push(node.meta.node.id)
-        } else {
-            _assets.push(node.meta.asset.id)
-        }
-    });
-    url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(",");
+    if (zTree) {
+        var nodes = zTree.getSelectedNodes();
+        var _nodes = [];
+        var _assets = [];
+        $.each(nodes, function (id, node) {
+            if (node.meta.type === 'node') {
+                _nodes.push(node.meta.node.id)
+            } else {
+                _assets.push(node.meta.asset.id)
+            }
+        });
+        url += "?assets=" + _assets.join(",") + "&nodes=" + _nodes.join(",");
+    }
     window.open(url, '_self');
 }).on('click', '.toggle', function (e) {
     e.preventDefault();
@@ -283,7 +284,6 @@ $(document).ready(function(){
             detailRows.push(tr.attr('id'));
         }
     }
-
 }).on('click', '#permission_list_table_filter input', function (e) {
     e.preventDefault();
     e.stopPropagation();
diff --git a/apps/perms/views/asset_permission.py b/apps/perms/views/asset_permission.py
index e7d2f155b..94c7c8c62 100644
--- a/apps/perms/views/asset_permission.py
+++ b/apps/perms/views/asset_permission.py
@@ -53,11 +53,11 @@ class AssetPermissionCreateView(PermissionsMixin, CreateView):
             nodes_id = nodes_id.split(",")
             nodes = Node.objects.filter(id__in=nodes_id)\
                 .exclude(id=Node.org_root().id)
-            form['nodes'].initial = nodes
+            form.set_nodes_initial(nodes)
         if assets_id:
             assets_id = assets_id.split(",")
             assets = Asset.objects.filter(id__in=assets_id)
-            form['assets'].initial = assets
+            form.set_assets_initial(assets)
         return form
 
     def get_context_data(self, **kwargs):
diff --git a/apps/settings/templates/settings/_ldap_list_users_modal.html b/apps/settings/templates/settings/_ldap_list_users_modal.html
index c0d062714..dd839eb5b 100644
--- a/apps/settings/templates/settings/_ldap_list_users_modal.html
+++ b/apps/settings/templates/settings/_ldap_list_users_modal.html
@@ -17,13 +17,6 @@
     padding: 10px 10px;
     text-align: center;
 }
-
-#assetTree2.ztree * {
-    background-color: #f8fafb;
-}
-#assetTree2.ztree {
-    background-color: #f8fafb;
-}
 </style>
 
 <div class="wrapper wrapper-content">
diff --git a/apps/static/js/inspinia.js b/apps/static/js/inspinia.js
index ed8c1c6ba..979f41005 100644
--- a/apps/static/js/inspinia.js
+++ b/apps/static/js/inspinia.js
@@ -76,10 +76,9 @@ $(document).ready(function () {
         if(!$("body").hasClass('body-small')) {
             fix_height();
         }
-    })
+    });
 
-    $("[data-toggle=popover]")
-        .popover();
+    $("[data-toggle=popover]").popover();
 });
 
 
diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js
index 400fd637e..127529a73 100644
--- a/apps/static/js/jumpserver.js
+++ b/apps/static/js/jumpserver.js
@@ -1,7 +1,8 @@
 //jumpserver 自定义js 2015-01-29
 
 //此函数用于checkbox的全选和反选
-var checked=false;
+var checked = false;
+
 function check_all(form) {
     var checkboxes = document.getElementById(form);
     if (checked === false) {
@@ -16,26 +17,23 @@ function check_all(form) {
     }
 }
 
-function checkAll(id, name){
+function checkAll(id, name) {
     var checklist = document.getElementsByName(name);
-    if(document.getElementById(id).checked)
-        {
-        for(var i=0;i<checklist.length;i++)
-        {
-          checklist[i].checked = 1;
+    if (document.getElementById(id).checked) {
+        for (var i = 0; i < checklist.length; i++) {
+            checklist[i].checked = 1;
         }
-    }else{
-        for(var j=0;j<checklist.length;j++)
-        {
-         checklist[j].checked = 0;
+    } else {
+        for (var j = 0; j < checklist.length; j++) {
+            checklist[j].checked = 0;
         }
     }
 }
 
 //提取指定行的数据,JSON格式
-function GetRowData(row){
+function GetRowData(row) {
     var rowData = {};
-    for(var j=0;j<row.cells.length; j++) {
+    for (var j = 0; j < row.cells.length; j++) {
         name = row.parentNode.rows[0].cells[j].getAttribute("Name");
         if (name) {
             var value = row.cells[j].getAttribute("Value");
@@ -56,16 +54,16 @@ function GetTableDataBox() {
     var checkboxes = document.getElementById("contents_form");
     var id_list = [];
     len = checkboxes.elements.length;
-    for (var i=0; i < len; i++) {
+    for (var i = 0; i < len; i++) {
         if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked === true && checkboxes.elements[i].value != "checkall") {
             id_list.push(i);
-         }
         }
+    }
     for (i in id_list) {
         tableData.push(GetRowData(tabProduct.rows[id_list[i]]));
     }
 
-    if (id_list.length === 0){
+    if (id_list.length === 0) {
         alert('请至少选择一行!');
     }
     returnData.push(tableData);
@@ -77,8 +75,8 @@ function move(from, to, from_o, to_o) {
     $("#" + from + " option").each(function () {
         if ($(this).prop("selected") === true) {
             $("#" + to).append(this);
-            if( typeof from_o !== 'undefined'){
-                $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']"));
+            if (typeof from_o !== 'undefined') {
+                $("#" + to_o).append($("#" + from_o + " option[value='" + this.value + "']"));
             }
         }
     });
@@ -88,18 +86,18 @@ function move_left(from, to, from_o, to_o) {
     $("#" + from + " option").each(function () {
         if ($(this).prop("selected") === true) {
             $("#" + to).append(this);
-            if( typeof from_o !== 'undefined'){
-                $("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']"));
+            if (typeof from_o !== 'undefined') {
+                $("#" + to_o).append($("#" + from_o + " option[value='" + this.value + "']"));
             }
         }
-        $(this).attr("selected",'true');
+        $(this).attr("selected", 'true');
     });
 }
 
 
-function selectAll(){
+function selectAll() {
     // Select all check box
-    $('option').each(function(){
+    $('option').each(function () {
         $(this).attr('selected', true);
     });
 }
@@ -131,7 +129,7 @@ function setAjaxCSRFToken() {
     var sessionid = getCookie('sessionid');
 
     $.ajaxSetup({
-        beforeSend: function(xhr, settings) {
+        beforeSend: function (xhr, settings) {
             if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                 xhr.setRequestHeader("X-CSRFToken", csrftoken);
             }
@@ -143,19 +141,16 @@ function activeNav() {
     var url_array = document.location.pathname.split("/");
     var app = url_array[1];
     var resource = url_array[2];
-    if (app === ''){
+    if (app === '') {
         $('#index').addClass('active');
-    }
-    else if (app === 'xpack' && resource === 'cloud') {
+    } else if (app === 'xpack' && resource === 'cloud') {
         var item = url_array[3];
         $("#" + app).addClass('active');
         $('#' + app + ' #' + resource).addClass('active');
         $('#' + app + ' #' + resource + ' #' + item + ' a').css('color', '#ffffff');
-    }
-    else if (app === 'settings'){
+    } else if (app === 'settings') {
         $("#" + app).addClass('active');
-    }
-    else {
+    } else {
         $("#" + app).addClass('active');
         $('#' + app + ' #' + resource).addClass('active');
     }
@@ -186,14 +181,14 @@ function formSubmit(props) {
     }).done(function (data, textState, jqXHR) {
         if (redirect_to) {
             if (props.message) {
-                var messages="ed65330a45559c87345a0eb6ac7812d18d0d8976$[[\"__json_message\"\0540\05425\054\"asdfasdf \\u521b\\u5efa\\u6210\\u529f\"]]"
+                var messages = "ed65330a45559c87345a0eb6ac7812d18d0d8976$[[\"__json_message\"\0540\05425\054\"asdfasdf \\u521b\\u5efa\\u6210\\u529f\"]]"
                 setCookie("messages", messages)
             }
             location.href = redirect_to;
         } else if (typeof props.success === 'function') {
             return props.success(data, textState, jqXHR);
         }
-    }).fail(function(jqXHR, textStatus, errorThrown) {
+    }).fail(function (jqXHR, textStatus, errorThrown) {
         if (typeof props.error === 'function') {
             return props.error(jqXHR, textStatus, errorThrown)
         }
@@ -233,7 +228,7 @@ function formSubmit(props) {
                 }
                 if (fieldRef.length === 1 && formGroupRef.length === 1) {
                     formGroupRef.addClass('has-error');
-                    var help_msg = v.join("<br/>") ;
+                    var help_msg = v.join("<br/>");
                     helpBlockRef.html(help_msg);
                 } else {
                     $.each(v, function (kk, vv) {
@@ -241,7 +236,7 @@ function formSubmit(props) {
                             $.each(vv, function (kkk, vvv) {
                                 noneFieldErrorMsg += " " + vvv + '<br/>';
                             })
-                        } else{
+                        } else {
                             noneFieldErrorMsg += vv + '<br/>';
                         }
                     })
@@ -264,7 +259,7 @@ function requestApi(props) {
     var user_fail_message = props.fail_message;
     var default_failed_message = gettext('An unknown error occurred while updating..');
     var flash_message = props.flash_message || true;
-    if (props.flash_message === false){
+    if (props.flash_message === false) {
         flash_message = false;
     }
 
@@ -274,7 +269,7 @@ function requestApi(props) {
         data: props.body,
         contentType: props.content_type || "application/json; charset=utf-8",
         dataType: props.data_type || "json"
-    }).done(function(data, textStatue, jqXHR) {
+    }).done(function (data, textStatue, jqXHR) {
         if (flash_message) {
             var msg = "";
             if (user_success_message) {
@@ -287,7 +282,7 @@ function requestApi(props) {
         if (typeof props.success === 'function') {
             return props.success(data);
         }
-    }).fail(function(jqXHR, textStatus, errorThrown) {
+    }).fail(function (jqXHR, textStatus, errorThrown) {
         if (flash_message) {
             var msg = "";
             if (user_fail_message) {
@@ -308,24 +303,24 @@ function requestApi(props) {
             return props.error(jqXHR.responseText, jqXHR.status);
         }
     });
-  // return true;
+    // return true;
 }
 
 // Sweet Alert for Delete
 function objectDelete(obj, name, url, redirectTo) {
     function doDelete() {
         var body = {};
-        var success = function() {
+        var success = function () {
             // swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success");
             if (!redirectTo) {
                 $(obj).parent().parent().remove();
             } else {
-                window.location.href=redirectTo;
+                window.location.href = redirectTo;
             }
         };
-        var fail = function() {
+        var fail = function () {
             // swal("错误", "删除"+"[ "+name+" ]"+"遇到错误", "error");
-            swal(gettext('Error'), "[ "+name+" ]" + gettext("Being used by the asset, please unbind the asset first."), "error");
+            swal(gettext('Error'), "[ " + name + " ]" + gettext("Being used by the asset, please unbind the asset first."), "error");
         };
         requestApi({
             url: url,
@@ -336,6 +331,7 @@ function objectDelete(obj, name, url, redirectTo) {
             error: fail
         });
     }
+
     swal({
         title: gettext('Are you sure about deleting it?'),
         text: " [" + name + "] ",
@@ -350,22 +346,21 @@ function objectDelete(obj, name, url, redirectTo) {
     });
 }
 
-function orgDelete(obj, name, url, redirectTo){
+function orgDelete(obj, name, url, redirectTo) {
     function doDelete() {
         var body = {};
-        var success = function() {
+        var success = function () {
             if (!redirectTo) {
                 $(obj).parent().parent().remove();
             } else {
-                window.location.href=redirectTo;
+                window.location.href = redirectTo;
             }
         };
-        var fail = function(responseText, status) {
-            if (status === 400){
-                swal(gettext("Error"),  "[ " + name + " ] " + gettext("The organization contains undeleted information. Please try again after deleting"), "error");
-            }
-            else if (status === 405){
-                swal(gettext("Error"), " [ "+ name + " ] " + gettext("Do not perform this operation under this organization. Try again after switching to another organization"), "error");
+        var fail = function (responseText, status) {
+            if (status === 400) {
+                swal(gettext("Error"), "[ " + name + " ] " + gettext("The organization contains undeleted information. Please try again after deleting"), "error");
+            } else if (status === 405) {
+                swal(gettext("Error"), " [ " + name + " ] " + gettext("Do not perform this operation under this organization. Try again after switching to another organization"), "error");
             }
         };
         requestApi({
@@ -377,6 +372,7 @@ function orgDelete(obj, name, url, redirectTo){
             error: fail
         });
     }
+
     swal({
         title: gettext("Please ensure that the following information in the organization has been deleted"),
         text: gettext("User list、User group、Asset list、Domain list、Admin user、System user、Labels、Asset permission"),
@@ -391,11 +387,10 @@ function orgDelete(obj, name, url, redirectTo){
     });
 }
 
-$.fn.serializeObject = function()
-{
+$.fn.serializeObject = function () {
     var o = {};
     var a = this.serializeArray();
-    $.each(a, function() {
+    $.each(a, function () {
         if (o[this.name] !== undefined) {
             if (!o[this.name].push) {
                 o[this.name] = [o[this.name]];
@@ -413,16 +408,15 @@ function makeLabel(data) {
 }
 
 
-
 var jumpserver = {};
 jumpserver.checked = false;
 jumpserver.selected = {};
 jumpserver.language = {
-    processing: gettext('Loading ...'),
+    processing: gettext('Loading') + '...',
     search: gettext('Search'),
     select: {
         rows: {
-            _:  gettext("Selected item %d"),
+            _: gettext("Selected item %d"),
             0: ""
         }
     },
@@ -440,36 +434,40 @@ jumpserver.language = {
     }
 };
 jumpserver.initDataTable = function (options) {
-  // options = {
-  //    ele *: $('#dataTable_id'),
-  //    ajax_url *: '{% url 'users:user-list-api' %}',
-  //    columns *: [{data: ''}, ....],
-  //    dom: 'fltip',
-  //    i18n_url: '{% static "js/...../en-us.json" %}',
-  //    order: [[1, 'asc'], [2, 'asc'], ...],
-  //    buttons: ['excel', 'pdf', 'print'],
-  //    columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
-  //    uc_html: '<a>header button</a>',
-  //    op_html: 'div.btn-group?',
-  //    paging: true
-  // }
-  var ele = options.ele || $('.dataTable');
-  var columnDefs = [
-      {
-          targets: 0,
-          orderable: false,
-          createdCell: function (td, cellData) {
-              $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData));
-          }
-      },
-      {className: 'text-center', render: $.fn.dataTable.render.text(), targets: '_all'}
-  ];
-  columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs;
-  var select = {
-      style: 'multi',
-      selector: 'td:first-child'
-  };
-  var table = ele.DataTable({
+    // options = {
+    //    ele *: $('#dataTable_id'),
+    //    ajax_url *: '{% url 'users:user-list-api' %}',
+    //    columns *: [{data: ''}, ....],
+    //    dom: 'fltip',
+    //    i18n_url: '{% static "js/...../en-us.json" %}',
+    //    order: [[1, 'asc'], [2, 'asc'], ...],
+    //    buttons: ['excel', 'pdf', 'print'],
+    //    columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
+    //    uc_html: '<a>header button</a>',
+    //    op_html: 'div.btn-group?',
+    //    paging: true
+    // }
+    var ele = options.ele || $('.dataTable');
+    var columnDefs = [
+        {
+            targets: 0,
+            orderable: false,
+            createdCell: function (td, cellData) {
+                $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData));
+            }
+        },
+        {
+            className: 'text-center',
+            render: $.fn.dataTable.render.text(),
+            targets: '_all'
+        }
+    ];
+    columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs;
+    var select = {
+        style: 'multi',
+        selector: 'td:first-child'
+    };
+    var table = ele.DataTable({
         pageLength: options.pageLength || 15,
         dom: options.dom || '<"#uc.pull-left"><"pull-right"<"inline"l><"#fb.inline"><"inline"f><"#fa.inline">>tr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
         order: options.order || [],
@@ -486,15 +484,15 @@ jumpserver.initDataTable = function (options) {
         language: jumpserver.language,
         lengthMenu: [[10, 15, 25, 50, -1], [10, 15, 25, 50, "All"]]
     });
-    table.on('select', function(e, dt, type, indexes) {
-        var $node = table[ type ]( indexes ).nodes().to$();
+    table.on('select', function (e, dt, type, indexes) {
+        var $node = table[type](indexes).nodes().to$();
         $node.find('input.ipt_check').prop('checked', true);
         jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true
-    }).on('deselect', function(e, dt, type, indexes) {
-        var $node = table[ type ]( indexes ).nodes().to$();
+    }).on('deselect', function (e, dt, type, indexes) {
+        var $node = table[type](indexes).nodes().to$();
         $node.find('input.ipt_check').prop('checked', false);
         jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false
-    }).on('draw', function(){
+    }).on('draw', function () {
         $('#op').html(options.op_html || '');
         $('#uc').html(options.uc_html || '');
         $('[data-toggle="popover"]').popover({
@@ -506,16 +504,16 @@ jumpserver.initDataTable = function (options) {
             $('[data-toggle="popover"]').not(this).popover('hide');
         });
     });
-    $('.ipt_check_all').on('click', function() {
-      if ($(this).prop("checked")) {
-          $(this).closest('table').find('.ipt_check').prop('checked', true);
-          jumpserver.checked = true;
-          table.rows({search:'applied', page:'current'}).select();
-      } else {
-          $(this).closest('table').find('.ipt_check').prop('checked', false);
-          jumpserver.checked = false;
-          table.rows({search:'applied', page:'current'}).deselect();
-      }
+    $('.ipt_check_all').on('click', function () {
+        if ($(this).prop("checked")) {
+            $(this).closest('table').find('.ipt_check').prop('checked', true);
+            jumpserver.checked = true;
+            table.rows({search: 'applied', page: 'current'}).select();
+        } else {
+            $(this).closest('table').find('.ipt_check').prop('checked', false);
+            jumpserver.checked = false;
+            table.rows({search: 'applied', page: 'current'}).deselect();
+        }
     });
 
     return table;
@@ -532,40 +530,42 @@ jumpserver.initStaticTable = function (selector) {
 };
 
 jumpserver.initServerSideDataTable = function (options) {
-  // options = {
-  //    ele *: $('#dataTable_id'),
-  //    ajax_url *: '{% url 'users:user-list-api' %}',
-  //    columns *: [{data: ''}, ....],
-  //    dom: 'fltip',
-  //    i18n_url: '{% static "js/...../en-us.json" %}',
-  //    order: [[1, 'asc'], [2, 'asc'], ...],
-  //    buttons: ['excel', 'pdf', 'print'],
-  //    columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
-  //    uc_html: '<a>header button</a>',
-  //    op_html: 'div.btn-group?',
-  //    paging: true
-  // }
-  var ele = options.ele || $('.dataTable');
-  var columnDefs = [
-      {
-          targets: 0,
-          orderable: false,
-          createdCell: function (td, cellData) {
-              $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData));
-          }
-      },
-      {
-          targets: '_all',
-          className: 'text-center',
-          render: $.fn.dataTable.render.text()
-      }
-  ];
-  columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs;
-  var select = {
-            style: 'multi',
-            selector: 'td:first-child'
-      };
-  var table = ele.DataTable({
+    // options = {
+    //    ele *: $('#dataTable_id'),
+    //    ajax_url *: '{% url 'users:user-list-api' %}',
+    //    select_style: 'multi',
+    //    columns *: [{data: ''}, ....],
+    //    dom: 'fltip',
+    //    i18n_url: '{% static "js/...../en-us.json" %}',
+    //    order: [[1, 'asc'], [2, 'asc'], ...],
+    //    buttons: ['excel', 'pdf', 'print'],
+    //    columnDefs: [{target: 0, createdCell: ()=>{}}, ...],
+    //    uc_html: '<a>header button</a>',
+    //    op_html: 'div.btn-group?',
+    //    paging: true
+    // }
+    var ele = options.ele || $('.dataTable');
+    var columnDefs = [
+        {
+            targets: 0,
+            orderable: false,
+            createdCell: function (td, cellData) {
+                $(td).html('<input type="checkbox" class="text-center ipt_check" id=99991937>'.replace('99991937', cellData));
+            }
+        },
+        {
+            targets: '_all',
+            className: 'text-center',
+            render: $.fn.dataTable.render.text()
+        }
+    ];
+    var select_style = options.select_style || 'multi';
+    columnDefs = options.columnDefs ? options.columnDefs.concat(columnDefs) : columnDefs;
+    var select = {
+        style: select_style,
+        selector: 'td:first-child'
+    };
+    var table = ele.DataTable({
         pageLength: options.pageLength || 15,
         // dom: options.dom || '<"#uc.pull-left">fltr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
         dom: options.dom || '<"#uc.pull-left"><"pull-right"<"inline"l><"#fb.inline"><"inline"f><"#fa.inline">>tr<"row m-t"<"col-md-8"<"#op.col-md-6"><"col-md-6 text-center"i>><"col-md-4"p>>',
@@ -576,8 +576,8 @@ jumpserver.initServerSideDataTable = function (options) {
         processing: true,
         searchDelay: 800,
         ajax: {
-            url: options.ajax_url ,
-            error: function(jqXHR, textStatus, errorThrown) {
+            url: options.ajax_url,
+            error: function (jqXHR, textStatus, errorThrown) {
                 var msg = gettext("Unknown error occur");
                 if (jqXHR.responseJSON) {
                     if (jqXHR.responseJSON.error) {
@@ -590,7 +590,7 @@ jumpserver.initServerSideDataTable = function (options) {
             },
             data: function (data) {
                 delete data.columns;
-                if (data.length !== null){
+                if (data.length !== null) {
                     data.limit = data.length;
                     delete data.length;
                 }
@@ -605,15 +605,15 @@ jumpserver.initServerSideDataTable = function (options) {
                     var search_raw = [];
 
                     search_list.map(function (val, index) {
-                       var kv = val.split(":");
-                       if (kv.length === 2) {
-                           var value = kv[1];
-                           var key = kv[0].trim();
-                           value = value.replace("+", " ").trim();
-                           search_attr[key] = value
-                       } else {
-                           search_raw.push(kv)
-                       }
+                        var kv = val.split(":");
+                        if (kv.length === 2) {
+                            var value = kv[1];
+                            var key = kv[0].trim();
+                            value = value.replace("+", " ").trim();
+                            search_attr[key] = value
+                        } else {
+                            search_raw.push(kv)
+                        }
                     });
                     data.search = search_raw.join("");
                     $.each(search_attr, function (k, v) {
@@ -629,8 +629,8 @@ jumpserver.initServerSideDataTable = function (options) {
                     data.order = order;
                 }
             },
-            dataFilter: function(data){
-                var json = jQuery.parseJSON( data );
+            dataFilter: function (data) {
+                var json = jQuery.parseJSON(data);
                 json.recordsTotal = json.count;
                 json.recordsFiltered = json.count;
                 return JSON.stringify(json); // return JSON string
@@ -644,35 +644,36 @@ jumpserver.initServerSideDataTable = function (options) {
     });
     table.selected = [];
     table.selected_rows = [];
-    table.on('select', function(e, dt, type, indexes) {
-        var $node = table[ type ]( indexes ).nodes().to$();
+    table.on('select', function (e, dt, type, indexes) {
+        var $node = table[type](indexes).nodes().to$();
         $node.find('input.ipt_check').prop('checked', true);
         jumpserver.selected[$node.find('input.ipt_check').prop('id')] = true;
         if (type === 'row') {
             var rows = table.rows(indexes).data();
             $.each(rows, function (id, row) {
-                table.selected_rows.push(row);
-                if (row.id && $.inArray(row.id, table.selected) === -1){
-                    table.selected.push(row.id)
+                if (row.id && $.inArray(row.id, table.selected) === -1) {
+                    table.selected.push(row.id);
+                    table.selected_rows.push(row);
                 }
             })
         }
-    }).on('deselect', function(e, dt, type, indexes) {
-        var $node = table[ type ]( indexes ).nodes().to$();
+    }).on('deselect', function (e, dt, type, indexes) {
+        var $node = table[type](indexes).nodes().to$();
         $node.find('input.ipt_check').prop('checked', false);
         jumpserver.selected[$node.find('input.ipt_check').prop('id')] = false;
         if (type === 'row') {
             var rows = table.rows(indexes).data();
             $.each(rows, function (id, row) {
-                if (row.id){
+                if (row.id) {
                     var index = table.selected.indexOf(row.id);
-                    if (index > -1){
-                        table.selected.splice(index, 1)
+                    if (index > -1) {
+                        table.selected.splice(index, 1);
+                        table.selected_rows.splice(index, 1);
                     }
                 }
             })
         }
-    }).on('draw', function(){
+    }).on('draw', function () {
         $('[data-toggle="popover"]').popover({
             html: true,
             placement: 'bottom',
@@ -690,7 +691,7 @@ jumpserver.initServerSideDataTable = function (options) {
 
         $.each(table.selected, function (id, data) {
             var index = table_data.indexOf(data);
-            if (index > -1){
+            if (index > -1) {
                 table.rows(index).select()
             }
         });
@@ -701,13 +702,16 @@ jumpserver.initServerSideDataTable = function (options) {
         $('#fa').html(options.fa_html || '');
     });
     var table_id = table.settings()[0].sTableId;
-    $('#' + table_id + ' .ipt_check_all').on('click', function() {
+    $('#' + table_id + ' .ipt_check_all').on('click', function () {
+        if (select_style !== 'multi') {
+            return
+        }
         if ($(this).prop("checked")) {
             $(this).closest('table').find('.ipt_check').prop('checked', true);
-            table.rows({search:'applied', page:'current'}).select();
+            table.rows({search: 'applied', page: 'current'}).select();
         } else {
             $(this).closest('table').find('.ipt_check').prop('checked', false);
-            table.rows({search:'applied', page:'current'}).deselect();
+            table.rows({search: 'applied', page: 'current'}).deselect();
         }
     });
 
@@ -728,7 +732,7 @@ String.prototype.replaceAll = function (exp, newStr) {
  * 原型:字符串格式化
  * @param args 格式化参数值
  */
-String.prototype.format = function(args) {
+String.prototype.format = function (args) {
     var result = this;
     if (arguments.length < 1) {
         return result;
@@ -738,7 +742,7 @@ String.prototype.format = function(args) {
     if (arguments.length == 1 && typeof (args) == "object") {
         data = args;
     }
-    for ( var key in data) {
+    for (var key in data) {
         var value = data[key];
         if (undefined != value) {
             result = result.replaceAll("\\{" + key + "\\}", value);
@@ -750,7 +754,7 @@ String.prototype.format = function(args) {
 function setCookie(key, value, time) {
     var expires = new Date();
     if (!time) {
-        time =  expires.getTime() + (24 * 60 * 60 * 1000);
+        time = expires.getTime() + (24 * 60 * 60 * 1000);
     }
     expires.setTime(time);
     document.cookie = key + '=' + value + ';expires=' + expires.toUTCString() + ';path=/';
@@ -767,26 +771,26 @@ function delCookie(key) {
 }
 
 function createPopover(dataset, title, callback) {
-    if (callback !== undefined){
+    if (callback !== undefined) {
         var new_dataset = [];
         $.each(dataset, function (index, value) {
             new_dataset.push(callback(value))
         });
         dataset = new_dataset;
     }
-    var data_content = dataset.join("</br>");
-
+    var data_content = dataset.join("<br>");
     var html = "<a data-toggle='popover' data-content='" + data_content + "'>" + dataset.length + "</a>";
     return html;
 }
 
 
- $(function () {
+$(function () {
     (function ($) {
         $.getUrlParam = function (name) {
             var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
             var r = window.location.search.substr(1).match(reg);
-            if (r != null) return unescape(r[2]); return null;
+            if (r != null) return unescape(r[2]);
+            return null;
         }
     })(jQuery);
 });
@@ -794,12 +798,13 @@ function createPopover(dataset, title, callback) {
 function getUrlParam(name) {
     var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
     var r = window.location.search.substr(1).match(reg);
-    if (r != null) return unescape(r[2]); return null;
+    if (r != null) return unescape(r[2]);
+    return null;
 }
 
 function setUrlParam(url, name, value) {
     var urlArray = url.split("?");
-    if (urlArray.length===1){
+    if (urlArray.length === 1) {
         url += "?" + name + "=" + value;
     } else {
         var oriParam = urlArray[1].split("&");
@@ -836,12 +841,11 @@ var rules_id_map_label = {
     'id_security_password_special_char': gettext('Must contain special characters')
 };
 
-function getRuleLabel(rule){
+function getRuleLabel(rule) {
     var label = '';
-    if (rule.key === rules_short_map_id['min']){
+    if (rule.key === rules_short_map_id['min']) {
         label = rules_id_map_label[rule.key].replace('{N}', rule.value)
-    }
-    else{
+    } else {
         label = rules_id_map_label[rule.key]
     }
     return label
@@ -850,38 +854,33 @@ function getRuleLabel(rule){
 // 校验密码-改变规则颜色
 function checkPasswordRules(password, minLength) {
     if (wordMinLength(password, minLength)) {
-        $('#'+rules_short_map_id['min']).css('color', 'green')
-    }
-    else {
-        $('#'+rules_short_map_id['min']).css('color', '#908a8a')
+        $('#' + rules_short_map_id['min']).css('color', 'green')
+    } else {
+        $('#' + rules_short_map_id['min']).css('color', '#908a8a')
     }
 
     if (wordUpperCase(password)) {
-        $('#'+rules_short_map_id['upper']).css('color', 'green')
-    }
-    else {
-        $('#'+rules_short_map_id['upper']).css('color', '#908a8a')
+        $('#' + rules_short_map_id['upper']).css('color', 'green')
+    } else {
+        $('#' + rules_short_map_id['upper']).css('color', '#908a8a')
     }
 
     if (wordLowerCase(password)) {
-        $('#'+rules_short_map_id['lower']).css('color', 'green')
-    }
-    else {
-        $('#'+rules_short_map_id['lower']).css('color', '#908a8a')
+        $('#' + rules_short_map_id['lower']).css('color', 'green')
+    } else {
+        $('#' + rules_short_map_id['lower']).css('color', '#908a8a')
     }
 
     if (wordNumber(password)) {
-        $('#'+rules_short_map_id['number']).css('color', 'green')
-    }
-    else {
-        $('#'+rules_short_map_id['number']).css('color', '#908a8a')
+        $('#' + rules_short_map_id['number']).css('color', 'green')
+    } else {
+        $('#' + rules_short_map_id['number']).css('color', '#908a8a')
     }
 
     if (wordSpecialChar(password)) {
-        $('#'+rules_short_map_id['special']).css('color', 'green')
-    }
-    else {
-        $('#'+rules_short_map_id['special']).css('color', '#908a8a')
+        $('#' + rules_short_map_id['special']).css('color', 'green')
+    } else {
+        $('#' + rules_short_map_id['special']).css('color', '#908a8a')
     }
 }
 
@@ -891,18 +890,22 @@ function wordMinLength(word, minLength) {
     var re = new RegExp("^(.{" + minLength + ",})$");
     return word.match(re)
 }
+
 // 大写字母
 function wordUpperCase(word) {
     return word.match(/([A-Z]+)/)
 }
+
 // 小写字母
 function wordLowerCase(word) {
     return word.match(/([a-z]+)/)
 }
+
 // 数字字符
 function wordNumber(word) {
     return word.match(/([\d]+)/)
 }
+
 // 特殊字符
 function wordSpecialChar(word) {
     return word.match(/[`,~,!,@,#,\$,%,\^,&,\*,\(,\),\-,_,=,\+,\{,\},\[,\],\|,\\,;,',:,",\,,\.,<,>,\/,\?]+/)
@@ -920,7 +923,7 @@ function popoverPasswordRules(password_check_rules, $el) {
 }
 
 // 初始化弹窗popover
-function initPopover($container, $progress, $idPassword, $el, password_check_rules, i18n_fallback){
+function initPopover($container, $progress, $idPassword, $el, password_check_rules, i18n_fallback) {
     options = {};
     // User Interface
     options.ui = {
@@ -944,37 +947,6 @@ function initPopover($container, $progress, $idPassword, $el, password_check_rul
     popoverPasswordRules(password_check_rules, $el);
 }
 
-// 解决input框中的资产和弹出表格中资产的显示不一致
-function initSelectedAssets2Table(id){
-    if (!id) {
-        id = "#id_assets"
-    }
-    var inputAssets = $(id).val();
-    var selectedAssets = asset_table2.selected.concat();
-
-    // input assets无,table assets选中,则取消勾选(再次click)
-    if (selectedAssets.length !== 0){
-        $.each(selectedAssets, function (index, assetId){
-            if ($.inArray(assetId, inputAssets) === -1){
-                $('#'+assetId).trigger('click');  // 取消勾选
-            }
-        });
-    }
-
-    // input assets有,table assets没选,则选中(click)
-    if (inputAssets !== null){
-        asset_table2.selected = inputAssets;
-        $.each(inputAssets, function(index, assetId){
-            var dom = document.getElementById(assetId);
-            if (dom !== null){
-                var selected = dom.parentElement.parentElement.className.indexOf('selected')
-            }
-            if (selected === -1){
-                $('#'+assetId).trigger('click');
-            }
-        });
-    }
-}
 
 
 function rootNodeAddDom(ztree, callback) {
@@ -1002,7 +974,7 @@ function APIExportData(props) {
             var params = props.params || {};
             params['format'] = props.format;
             params['spm'] = data.spm;
-            for (var k in params){
+            for (var k in params) {
                 export_url = setUrlParam(export_url, k, params[k])
             }
             window.open(export_url);
@@ -1013,7 +985,7 @@ function APIExportData(props) {
     })
 }
 
-function APIImportData(props){
+function APIImportData(props) {
     props = props || {};
     $.ajax({
         url: props.url,
@@ -1022,12 +994,12 @@ function APIImportData(props){
         data: props.body,
         contentType: props.content_type || 'text/csv',
         success: function (data) {
-            if(props.method === 'POST'){
+            if (props.method === 'POST') {
                 $('#created_failed').html('');
                 $('#created_failed_detail').html('');
                 $('#success_created').html(gettext("Import Success"));
                 $('#success_created_detail').html("Count" + ": " + data.length);
-            }else{
+            } else {
                 $('#updated_failed').html('');
                 $('#updated_failed_detail').html('');
                 $('#success_updated').html(gettext("Update Success"));
@@ -1038,11 +1010,11 @@ function APIImportData(props){
         },
         error: function (error) {
             var data = error.responseJSON;
-            if (data instanceof Array){
+            if (data instanceof Array) {
                 var html = '';
                 var li = '';
                 var err = '';
-                $.each(data, function (index, item){
+                $.each(data, function (index, item) {
                     err = '';
                     for (var prop in item) {
                         err += prop + ": " + item[prop][0] + " "
@@ -1053,16 +1025,15 @@ function APIImportData(props){
                     }
                 });
                 html = "<ul>" + html + "</ul>"
-            }
-            else {
+            } else {
                 html = error.responseText
             }
-            if(props.method === 'POST'){
+            if (props.method === 'POST') {
                 $('#success_created').html('');
                 $('#success_created_detail').html('');
                 $('#created_failed').html(gettext("Import failed"));
                 $('#created_failed_detail').html(html);
-            }else{
+            } else {
                 $('#success_updated').html('');
                 $('#success_updated_detail').html('');
                 $('#updated_failed').html(gettext("Update failed"));
@@ -1073,7 +1044,7 @@ function APIImportData(props){
 }
 
 
-function htmlEscape ( d ) {
+function htmlEscape(d) {
     return typeof d === 'string' ?
         d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
         d;
@@ -1081,10 +1052,9 @@ function htmlEscape ( d ) {
 
 function objectAttrsIsList(obj, attrs) {
     attrs.forEach(function (attr) {
-        if (!obj[attr]){
+        if (!obj[attr]) {
             obj[attr] = []
-        }
-        else if (obj[attr] && !(obj[attr] instanceof Array)){
+        } else if (obj[attr] && !(obj[attr] instanceof Array)) {
             obj[attr] = [obj[attr]]
         }
     })
@@ -1107,8 +1077,8 @@ function objectAttrsIsBool(obj, attrs) {
 }
 
 function cleanDateStr(d) {
-    for (var i=0;i<3;i++) {
-        if (!isNaN(Date.parse(d))){
+    for (var i = 0; i < 3; i++) {
+        if (!isNaN(Date.parse(d))) {
             return d;
         }
         if (!isNaN(Number(d))) {
@@ -1145,7 +1115,7 @@ function toSafeLocalDateStr(d) {
 function getUrlParams(url) {
     url = url.split("?");
     var params = "";
-    if (url.length === 2){
+    if (url.length === 2) {
         params = url[1];
     }
     return params
@@ -1167,7 +1137,7 @@ function getTimeUnits(u) {
 function timeOffset(a, b) {
     var start = safeDate(a);
     var end = safeDate(b);
-    var offset = (end - start)/1000;
+    var offset = (end - start) / 1000;
 
     var days = offset / 3600 / 24;
     var hours = offset / 3600;
@@ -1192,7 +1162,7 @@ function readFile(ref) {
     if (hasFile) {
         var reader = new FileReader();//新建一个FileReader
         reader.readAsText(files[0], "UTF-8");//读取文件
-        reader.onload = function(evt){ //读取完文件之后会回来这里
+        reader.onload = function (evt) { //读取完文件之后会回来这里
             ref.trigger("onload", evt.target.result);
         };
     } else {
@@ -1210,9 +1180,9 @@ function nodesSelect2Init(selector, url) {
             data: function (params) {
                 var page = params.page || 1;
                 var query = {
-                   search: params.term,
-                   offset: (page -1) * 10,
-                   limit: 10
+                    search: params.term,
+                    offset: (page - 1) * 10,
+                    limit: 10
                 };
                 return query
             },
@@ -1221,7 +1191,7 @@ function nodesSelect2Init(selector, url) {
                     return {id: v.id, text: v.full_value}
                 });
                 var more = !!data.next;
-                return {results: results, pagination: {"more": more }}
+                return {results: results, pagination: {"more": more}}
             }
         },
     })