Unverified Commit c75fd3c1 authored by 老广's avatar 老广 Committed by GitHub

Bugfix (#3286)

* [Update] 用户资产页面链接是 新窗口打开

* [Bugfix] 修复切换组织时, refer为空导致的bug

* [Update] 修复执行命令时报错

* [Bugfix] 修复用户树节点资产数量不对的问题

* [Update] 修改初始化tree
parent f87db2f4
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
# #
from functools import reduce
from treelib import Tree from treelib import Tree
from treelib.exceptions import NodeIDAbsentError
from collections import defaultdict from collections import defaultdict
from copy import deepcopy from copy import deepcopy
import threading
from django.db.models import Q
from common.utils import get_object_or_none, get_logger, timeit from common.utils import get_object_or_none, get_logger, timeit
from .models import SystemUser, Label, Asset from .models import SystemUser, Asset
logger = get_logger(__file__) logger = get_logger(__file__)
...@@ -31,6 +29,7 @@ class TreeService(Tree): ...@@ -31,6 +29,7 @@ class TreeService(Tree):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.nodes_assets_map = defaultdict(set) self.nodes_assets_map = defaultdict(set)
self.all_nodes_assets_map = {} self.all_nodes_assets_map = {}
self._invalid_assets = frozenset()
@classmethod @classmethod
@timeit @timeit
...@@ -47,25 +46,34 @@ class TreeService(Tree): ...@@ -47,25 +46,34 @@ class TreeService(Tree):
key = node["key"] key = node["key"]
value = node["value"] value = node["value"]
parent_key = ":".join(key.split(":")[:-1]) parent_key = ":".join(key.split(":")[:-1])
tree.create_node( tree.safe_create_node(
tag=value, identifier=key, tag=value, identifier=key,
parent=parent_key, parent=parent_key,
) )
tree.init_assets() tree.init_assets()
return tree return tree
@timeit
def init_assets(self): def init_assets(self):
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
self.all_nodes_assets_map = {} self.all_nodes_assets_map = {}
self.nodes_assets_map = defaultdict(set) self.nodes_assets_map = defaultdict(set)
logger.debug('Init tree assets')
with tmp_to_root_org(): with tmp_to_root_org():
queryset = Asset.objects.all().values_list('id', 'nodes__key') queryset = Asset.objects.all().values_list('id', 'nodes__key')
invalid_assets = Asset.objects.filter(is_active=False)\
.values_list('id', flat=True)
self._invalid_assets = frozenset(invalid_assets)
for asset_id, key in queryset: for asset_id, key in queryset:
if not key: if not key:
continue continue
self.nodes_assets_map[key].add(asset_id) self.nodes_assets_map[key].add(asset_id)
def safe_create_node(self, **kwargs):
parent = kwargs.get("parent")
if not self.contains(parent):
kwargs['parent'] = self.root
self.create_node(**kwargs)
def all_children_ids(self, nid, with_self=True): def all_children_ids(self, nid, with_self=True):
children_ids = self.expand_tree(nid) children_ids = self.expand_tree(nid)
if not with_self: if not with_self:
...@@ -93,6 +101,11 @@ class TreeService(Tree): ...@@ -93,6 +101,11 @@ class TreeService(Tree):
children = self.all_children(nid, with_self=False) children = self.all_children(nid, with_self=False)
return ancestors + [self[nid]] + children return ancestors + [self[nid]] + children
@staticmethod
def is_parent(child, parent):
parent_id = child.bpointer
return parent_id == parent.identifier
def root_node(self): def root_node(self):
return self.get_node(self.root) return self.get_node(self.root)
...@@ -108,12 +121,15 @@ class TreeService(Tree): ...@@ -108,12 +121,15 @@ class TreeService(Tree):
parent = self.copy_node(parent) parent = self.copy_node(parent)
return parent return parent
def set_assets(self, nid, assets):
self.nodes_assets_map[nid] = set(assets)
def assets(self, nid): def assets(self, nid):
assets = self.nodes_assets_map[nid] assets = self.nodes_assets_map[nid]
return assets return assets
def set_assets(self, nid, assets): def valid_assets(self, nid):
self.nodes_assets_map[nid] = assets return set(self.assets(nid)) - set(self._invalid_assets)
def all_assets(self, nid): def all_assets(self, nid):
assets = self.all_nodes_assets_map.get(nid) assets = self.all_nodes_assets_map.get(nid)
...@@ -123,41 +139,55 @@ class TreeService(Tree): ...@@ -123,41 +139,55 @@ class TreeService(Tree):
children = self.children(nid) children = self.children(nid)
for child in children: for child in children:
assets.update(self.all_assets(child.identifier)) assets.update(self.all_assets(child.identifier))
self.all_nodes_assets_map[nid] = assets
return assets return assets
def all_valid_assets(self, nid):
return set(self.all_assets(nid)) - set(self._invalid_assets)
def assets_amount(self, nid): def assets_amount(self, nid):
return len(self.all_assets(nid)) return len(self.all_assets(nid))
def valid_assets_amount(self, nid):
return len(self.all_valid_assets(nid))
@staticmethod @staticmethod
def copy_node(node): def copy_node(node):
new_node = deepcopy(node) new_node = deepcopy(node)
new_node.fpointer = None new_node.fpointer = None
return new_node return new_node
def safe_add_ancestors(self, ancestors): def safe_add_ancestors(self, node, ancestors):
# 如果祖先节点为1个,那么添加该节点, 父节点是root node # 如果没有祖先节点,那么添加该节点, 父节点是root node
if len(ancestors) == 1: if len(ancestors) == 0:
node = ancestors[0]
parent = self.root_node() parent = self.root_node()
else: else:
node, ancestors = ancestors[0], ancestors[1:] parent = ancestors[0]
parent_id = ancestors[0].identifier
# 如果父节点不存在, 则先添加父节点
if not self.contains(parent_id):
self.safe_add_ancestors(ancestors)
parent = self.get_node(parent_id)
# 如果当前节点已再树中,则移动当前节点到父节点中 # 如果当前节点已再树中,则移动当前节点到父节点中
# 这个是由于 当前节点放到了二级节点中 # 这个是由于 当前节点放到了二级节点中
if not self.contains(parent.identifier):
# logger.debug('Add parent: {}'.format(parent.identifier))
self.safe_add_ancestors(parent, ancestors[1:])
if self.contains(node.identifier): if self.contains(node.identifier):
# msg = 'Move node to parent: {} => {}'.format(
# node.identifier, parent.identifier
# )
# logger.debug(msg)
self.move_node(node.identifier, parent.identifier) self.move_node(node.identifier, parent.identifier)
else: else:
# logger.debug('Add node: {}'.format(node.identifier))
self.add_node(node, parent) self.add_node(node, parent)
# #
# def __getstate__(self): # def __getstate__(self):
# self.mutex = None # self.mutex = None
# return self.__dict__ # return self.__dict__
# #
# def __setstate__(self, state):
# self.__dict__ = state def __setstate__(self, state):
self.__dict__ = state
if '_invalid_assets' not in state:
self._invalid_assets = frozenset()
# self.mutex = threading.Lock() # self.mutex = threading.Lock()
...@@ -194,7 +194,7 @@ def timeit(func): ...@@ -194,7 +194,7 @@ def timeit(func):
now = time.time() now = time.time()
result = func(*args, **kwargs) result = func(*args, **kwargs)
using = (time.time() - now) * 1000 using = (time.time() - now) * 1000
msg = "Call {} end, using: {:.1f}ms".format(func.__name__, using) msg = "End call {}, using: {:.1f}ms".format(func.__name__, using)
logger.debug(msg) logger.debug(msg)
return result return result
return wrapper return wrapper
......
...@@ -33,7 +33,7 @@ class UserNodeTreeMixin: ...@@ -33,7 +33,7 @@ class UserNodeTreeMixin:
_queryset = [] _queryset = []
for node in nodes: for node in nodes:
assets_amount = self.tree.assets_amount(node.key) assets_amount = self.tree.valid_assets_amount(node.key)
if assets_amount == 0 and node.key != Node.empty_key: if assets_amount == 0 and node.key != Node.empty_key:
continue continue
node.assets_amount = assets_amount node.assets_amount = assets_amount
......
# coding: utf-8 # coding: utf-8
import time
import pickle import pickle
from collections import defaultdict from collections import defaultdict
from functools import reduce from functools import reduce
from hashlib import md5
import json
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Q from django.db.models import Q
...@@ -94,6 +91,7 @@ class AssetPermissionUtilCacheMixin: ...@@ -94,6 +91,7 @@ class AssetPermissionUtilCacheMixin:
user_tree = pickle.loads(data) user_tree = pickle.loads(data)
return user_tree return user_tree
@timeit
def get_user_tree_from_cache_if_need(self): def get_user_tree_from_cache_if_need(self):
if not self.user_tree_cache_enable: if not self.user_tree_cache_enable:
return None return None
...@@ -278,9 +276,9 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): ...@@ -278,9 +276,9 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
) )
if not ancestors: if not ancestors:
continue continue
parent_id = ancestors[0].identifier user_tree.safe_add_ancestors(child, ancestors)
user_tree.safe_add_ancestors(ancestors) # parent_id = ancestors[0].identifier
user_tree.move_node(child.identifier, parent_id) # user_tree.move_node(child.identifier, parent_id)
@staticmethod @staticmethod
def add_empty_node_if_need(user_tree): def add_empty_node_if_need(user_tree):
...@@ -315,6 +313,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): ...@@ -315,6 +313,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin):
self.set_user_tree_to_local(user_tree) self.set_user_tree_to_local(user_tree)
return user_tree return user_tree
user_tree = TreeService() user_tree = TreeService()
user_tree._invalid_assets = self.full_tree._invalid_assets
full_tree_root = self.full_tree.root_node() full_tree_root = self.full_tree.root_node()
user_tree.create_node( user_tree.create_node(
tag=full_tree_root.tag, tag=full_tree_root.tag,
......
...@@ -103,6 +103,7 @@ function onSelected(event, treeNode) { ...@@ -103,6 +103,7 @@ function onSelected(event, treeNode) {
function initTree(refresh) { function initTree(refresh) {
var asyncUrl = setUrlParam(treeUrl, 'cache_policy', '1');
var setting = { var setting = {
view: { view: {
dblClickExpand: false, dblClickExpand: false,
...@@ -115,7 +116,7 @@ function initTree(refresh) { ...@@ -115,7 +116,7 @@ function initTree(refresh) {
}, },
async: { async: {
enable: true, enable: true,
url: treeUrl, url: asyncUrl,
autoParam: ["id=key", "name=n", "level=lv"], autoParam: ["id=key", "name=n", "level=lv"],
type: 'get' type: 'get'
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment