Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3b84687f89 | ||
|
dc2f6ba957 | ||
|
93bcafda9b | ||
|
676b326fc6 | ||
|
42c82ff790 | ||
|
c1a6adc32c | ||
|
7f49ae3dfb |
@@ -32,7 +32,7 @@ from api.lib.perm.acl.resource import ResourceCRUD
|
|||||||
from api.lib.perm.acl.resource import ResourceTypeCRUD
|
from api.lib.perm.acl.resource import ResourceTypeCRUD
|
||||||
from api.lib.perm.acl.role import RoleCRUD
|
from api.lib.perm.acl.role import RoleCRUD
|
||||||
from api.lib.secrets.inner import KeyManage
|
from api.lib.secrets.inner import KeyManage
|
||||||
from api.lib.secrets.inner import global_key_threshold
|
from api.lib.secrets.inner import global_key_threshold, secrets_shares
|
||||||
from api.lib.secrets.secrets import InnerKVManger
|
from api.lib.secrets.secrets import InnerKVManger
|
||||||
from api.models.acl import App
|
from api.models.acl import App
|
||||||
from api.models.acl import ResourceType
|
from api.models.acl import ResourceType
|
||||||
@@ -55,12 +55,9 @@ def cmdb_init_cache():
|
|||||||
for cr in ci_relations:
|
for cr in ci_relations:
|
||||||
relations.setdefault(cr.first_ci_id, {}).update({cr.second_ci_id: cr.second_ci.type_id})
|
relations.setdefault(cr.first_ci_id, {}).update({cr.second_ci_id: cr.second_ci.type_id})
|
||||||
if cr.ancestor_ids:
|
if cr.ancestor_ids:
|
||||||
relations2.setdefault('{},{}'.format(cr.ancestor_ids, cr.first_ci_id), {}).update(
|
relations2.setdefault(cr.ancestor_ids, {}).update({cr.second_ci_id: cr.second_ci.type_id})
|
||||||
{cr.second_ci_id: cr.second_ci.type_id})
|
|
||||||
for i in relations:
|
for i in relations:
|
||||||
relations[i] = json.dumps(relations[i])
|
relations[i] = json.dumps(relations[i])
|
||||||
for i in relations2:
|
|
||||||
relations2[i] = json.dumps(relations2[i])
|
|
||||||
if relations:
|
if relations:
|
||||||
rd.create_or_update(relations, REDIS_PREFIX_CI_RELATION)
|
rd.create_or_update(relations, REDIS_PREFIX_CI_RELATION)
|
||||||
if relations2:
|
if relations2:
|
||||||
|
@@ -6,7 +6,6 @@ from werkzeug.datastructures import MultiDict
|
|||||||
from api.lib.common_setting.acl import ACLManager
|
from api.lib.common_setting.acl import ACLManager
|
||||||
from api.lib.common_setting.employee import EmployeeAddForm, GrantEmployeeACLPerm
|
from api.lib.common_setting.employee import EmployeeAddForm, GrantEmployeeACLPerm
|
||||||
from api.lib.common_setting.resp_format import ErrFormat
|
from api.lib.common_setting.resp_format import ErrFormat
|
||||||
from api.lib.common_setting.utils import CheckNewColumn
|
|
||||||
from api.models.common_setting import Employee, Department
|
from api.models.common_setting import Employee, Department
|
||||||
|
|
||||||
|
|
||||||
@@ -210,7 +209,57 @@ def common_check_new_columns():
|
|||||||
"""
|
"""
|
||||||
add new columns to tables
|
add new columns to tables
|
||||||
"""
|
"""
|
||||||
CheckNewColumn().run()
|
from api.extensions import db
|
||||||
|
from sqlalchemy import inspect, text
|
||||||
|
|
||||||
|
def get_model_by_table_name(_table_name):
|
||||||
|
registry = getattr(db.Model, 'registry', None)
|
||||||
|
class_registry = getattr(registry, '_class_registry', None)
|
||||||
|
for _model in class_registry.values():
|
||||||
|
if hasattr(_model, '__tablename__') and _model.__tablename__ == _table_name:
|
||||||
|
return _model
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_new_column(target_table_name, new_column):
|
||||||
|
column_type = new_column.type.compile(engine.dialect)
|
||||||
|
default_value = new_column.default.arg if new_column.default else None
|
||||||
|
|
||||||
|
sql = "ALTER TABLE " + target_table_name + " ADD COLUMN " + f"`{new_column.name}`" + " " + column_type
|
||||||
|
if new_column.comment:
|
||||||
|
sql += f" comment '{new_column.comment}'"
|
||||||
|
|
||||||
|
if column_type == 'JSON':
|
||||||
|
pass
|
||||||
|
elif default_value:
|
||||||
|
if column_type.startswith('VAR') or column_type.startswith('Text'):
|
||||||
|
if default_value is None or len(default_value) == 0:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
sql += f" DEFAULT {default_value}"
|
||||||
|
|
||||||
|
sql = text(sql)
|
||||||
|
db.session.execute(sql)
|
||||||
|
|
||||||
|
engine = db.get_engine()
|
||||||
|
inspector = inspect(engine)
|
||||||
|
table_names = inspector.get_table_names()
|
||||||
|
for table_name in table_names:
|
||||||
|
existed_columns = inspector.get_columns(table_name)
|
||||||
|
existed_column_name_list = [c['name'] for c in existed_columns]
|
||||||
|
|
||||||
|
model = get_model_by_table_name(table_name)
|
||||||
|
if model is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
model_columns = getattr(getattr(getattr(model, '__table__'), 'columns'), '_all_columns')
|
||||||
|
for column in model_columns:
|
||||||
|
if column.name not in existed_column_name_list:
|
||||||
|
try:
|
||||||
|
add_new_column(table_name, column)
|
||||||
|
current_app.logger.info(f"add new column [{column.name}] in table [{table_name}] success.")
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error(f"add new column [{column.name}] in table [{table_name}] err:")
|
||||||
|
current_app.logger.error(e)
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
|
@@ -92,9 +92,6 @@ class CITypeManager(object):
|
|||||||
for type_dict in ci_types:
|
for type_dict in ci_types:
|
||||||
attr = AttributeCache.get(type_dict["unique_id"])
|
attr = AttributeCache.get(type_dict["unique_id"])
|
||||||
type_dict["unique_key"] = attr and attr.name
|
type_dict["unique_key"] = attr and attr.name
|
||||||
if type_dict.get('show_id'):
|
|
||||||
attr = AttributeCache.get(type_dict["show_id"])
|
|
||||||
type_dict["show_name"] = attr and attr.name
|
|
||||||
type_dict['parent_ids'] = CITypeInheritanceManager.get_parents(type_dict['id'])
|
type_dict['parent_ids'] = CITypeInheritanceManager.get_parents(type_dict['id'])
|
||||||
if resources is None or type_dict['name'] in resources:
|
if resources is None or type_dict['name'] in resources:
|
||||||
res.append(type_dict)
|
res.append(type_dict)
|
||||||
@@ -195,7 +192,7 @@ class CITypeManager(object):
|
|||||||
CITypeAttributeManager.update(type_id, [attr])
|
CITypeAttributeManager.update(type_id, [attr])
|
||||||
|
|
||||||
ci_type2 = ci_type.to_dict()
|
ci_type2 = ci_type.to_dict()
|
||||||
new = ci_type.update(**kwargs, filter_none=False)
|
new = ci_type.update(**kwargs)
|
||||||
|
|
||||||
CITypeCache.clean(type_id)
|
CITypeCache.clean(type_id)
|
||||||
|
|
||||||
@@ -683,9 +680,6 @@ class CITypeAttributeManager(object):
|
|||||||
|
|
||||||
CITypeAttributeCache.clean(type_id, attr_id)
|
CITypeAttributeCache.clean(type_id, attr_id)
|
||||||
|
|
||||||
if ci_type.show_id == attr_id:
|
|
||||||
ci_type.update(show_id=None, filter_none=False)
|
|
||||||
|
|
||||||
CITypeHistoryManager.add(CITypeOperateType.DELETE_ATTRIBUTE, type_id, attr_id=attr.id,
|
CITypeHistoryManager.add(CITypeOperateType.DELETE_ATTRIBUTE, type_id, attr_id=attr.id,
|
||||||
change=attr and attr.to_dict())
|
change=attr and attr.to_dict())
|
||||||
|
|
||||||
@@ -1233,10 +1227,7 @@ class CITypeTemplateManager(object):
|
|||||||
def _import_ci_types(self, ci_types, attr_id_map):
|
def _import_ci_types(self, ci_types, attr_id_map):
|
||||||
for i in ci_types:
|
for i in ci_types:
|
||||||
i.pop("unique_key", None)
|
i.pop("unique_key", None)
|
||||||
i.pop("show_name", None)
|
|
||||||
i['unique_id'] = attr_id_map.get(i['unique_id'], i['unique_id'])
|
i['unique_id'] = attr_id_map.get(i['unique_id'], i['unique_id'])
|
||||||
if i.get('show_id'):
|
|
||||||
i['show_id'] = attr_id_map.get(i['show_id'], i['show_id'])
|
|
||||||
i['uid'] = current_user.uid
|
i['uid'] = current_user.uid
|
||||||
|
|
||||||
return self.__import(CIType, ci_types)
|
return self.__import(CIType, ci_types)
|
||||||
|
@@ -297,10 +297,6 @@ class PreferenceManager(object):
|
|||||||
|
|
||||||
for type_id in id2type:
|
for type_id in id2type:
|
||||||
id2type[type_id] = CITypeCache.get(type_id).to_dict()
|
id2type[type_id] = CITypeCache.get(type_id).to_dict()
|
||||||
id2type[type_id]['unique_name'] = AttributeCache.get(id2type[type_id]['unique_id']).name
|
|
||||||
if id2type[type_id]['show_id']:
|
|
||||||
show_attr = AttributeCache.get(id2type[type_id]['show_id'])
|
|
||||||
id2type[type_id]['show_name'] = show_attr and show_attr.name
|
|
||||||
|
|
||||||
return result, id2type, sorted(name2id, key=lambda x: x[1])
|
return result, id2type, sorted(name2id, key=lambda x: x[1])
|
||||||
|
|
||||||
|
@@ -8,8 +8,6 @@ from flask import current_app
|
|||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
|
||||||
from api.extensions import rd
|
from api.extensions import rd
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
|
||||||
from api.lib.cmdb.cache import CITypeCache
|
|
||||||
from api.lib.cmdb.ci import CIRelationManager
|
from api.lib.cmdb.ci import CIRelationManager
|
||||||
from api.lib.cmdb.ci_type import CITypeRelationManager
|
from api.lib.cmdb.ci_type import CITypeRelationManager
|
||||||
from api.lib.cmdb.const import ConstraintEnum
|
from api.lib.cmdb.const import ConstraintEnum
|
||||||
@@ -20,8 +18,6 @@ from api.lib.cmdb.perms import CIFilterPermsCRUD
|
|||||||
from api.lib.cmdb.resp_format import ErrFormat
|
from api.lib.cmdb.resp_format import ErrFormat
|
||||||
from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB
|
from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB
|
||||||
from api.lib.cmdb.search.ci.es.search import Search as SearchFromES
|
from api.lib.cmdb.search.ci.es.search import Search as SearchFromES
|
||||||
from api.lib.cmdb.utils import TableMap
|
|
||||||
from api.lib.cmdb.utils import ValueTypeMap
|
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
from api.lib.perm.acl.acl import is_app_admin
|
from api.lib.perm.acl.acl import is_app_admin
|
||||||
from api.models.cmdb import CI
|
from api.models.cmdb import CI
|
||||||
@@ -240,7 +236,7 @@ class Search(object):
|
|||||||
type2filter_perms = CIFilterPermsCRUD().get_by_ids(list(map(int, [i['name'] for i in res2])))
|
type2filter_perms = CIFilterPermsCRUD().get_by_ids(list(map(int, [i['name'] for i in res2])))
|
||||||
|
|
||||||
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
||||||
_tmp, tmp_res = [], []
|
_tmp = []
|
||||||
level2ids = {}
|
level2ids = {}
|
||||||
for lv in range(1, self.level + 1):
|
for lv in range(1, self.level + 1):
|
||||||
level2ids[lv] = []
|
level2ids[lv] = []
|
||||||
@@ -307,26 +303,25 @@ class Search(object):
|
|||||||
if key:
|
if key:
|
||||||
res = [json.loads(x).items() for x in [i or '{}' for i in rd.get(key, prefix) or []]]
|
res = [json.loads(x).items() for x in [i or '{}' for i in rd.get(key, prefix) or []]]
|
||||||
if type_ids and lv == self.level:
|
if type_ids and lv == self.level:
|
||||||
tmp_res = [[i for i in x if i[1] in type_ids and
|
__tmp = [[i for i in x if i[1] in type_ids and
|
||||||
(not id_filter_limit or (
|
(not id_filter_limit or (
|
||||||
key[idx] not in id_filter_limit or
|
key[idx] not in id_filter_limit or
|
||||||
int(i[0]) in id_filter_limit[key[idx]]) or
|
int(i[0]) in id_filter_limit[key[idx]]) or
|
||||||
int(i[0]) in id_filter_limit)] for idx, x in enumerate(res)]
|
int(i[0]) in id_filter_limit)] for idx, x in enumerate(res)]
|
||||||
else:
|
else:
|
||||||
tmp_res = [[i for i in x if (not id_filter_limit or (
|
__tmp = [[i for i in x if (not id_filter_limit or (
|
||||||
key[idx] not in id_filter_limit or
|
key[idx] not in id_filter_limit or
|
||||||
int(i[0]) in id_filter_limit[key[idx]]) or
|
int(i[0]) in id_filter_limit[key[idx]]) or
|
||||||
int(i[0]) in id_filter_limit)] for idx, x in
|
int(i[0]) in id_filter_limit)] for idx, x in enumerate(res)]
|
||||||
enumerate(res)]
|
|
||||||
|
|
||||||
if ci_filter_limit:
|
if ci_filter_limit:
|
||||||
tmp_res = [[j for j in i if j[1] not in ci_filter_limit or
|
__tmp = [[j for j in i if j[1] not in ci_filter_limit or
|
||||||
int(j[0]) in ci_filter_limit[j[1]]] for i in tmp_res]
|
int(j[0]) in ci_filter_limit[j[1]]] for i in __tmp]
|
||||||
else:
|
else:
|
||||||
tmp_res = []
|
__tmp = []
|
||||||
|
|
||||||
if tmp_res:
|
if __tmp:
|
||||||
_tmp[idx] = [j for i in tmp_res for j in i]
|
_tmp[idx] = [j for i in __tmp for j in i]
|
||||||
else:
|
else:
|
||||||
_tmp[idx] = []
|
_tmp[idx] = []
|
||||||
level2ids[lv].append([])
|
level2ids[lv].append([])
|
||||||
@@ -337,84 +332,3 @@ class Search(object):
|
|||||||
detail={str(_id): dict(Counter([i[1] for i in _tmp[idx]]).items()) for idx, _id in enumerate(ids)})
|
detail={str(_id): dict(Counter([i[1] for i in _tmp[idx]]).items()) for idx, _id in enumerate(ids)})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def search_full(self, type_ids):
|
|
||||||
def _get_id2name(_type_id):
|
|
||||||
ci_type = CITypeCache.get(_type_id)
|
|
||||||
|
|
||||||
attr = AttributeCache.get(ci_type.unique_id)
|
|
||||||
value_table = TableMap(attr=attr).table
|
|
||||||
serializer = ValueTypeMap.serialize[attr.value_type]
|
|
||||||
unique_value = {i.ci_id: serializer(i.value) for i in value_table.get_by(attr_id=attr.id, to_dict=False)}
|
|
||||||
|
|
||||||
attr = AttributeCache.get(ci_type.show_id)
|
|
||||||
if attr:
|
|
||||||
value_table = TableMap(attr=attr).table
|
|
||||||
serializer = ValueTypeMap.serialize[attr.value_type]
|
|
||||||
show_value = {i.ci_id: serializer(i.value) for i in value_table.get_by(attr_id=attr.id, to_dict=False)}
|
|
||||||
else:
|
|
||||||
show_value = unique_value
|
|
||||||
|
|
||||||
return show_value, unique_value
|
|
||||||
|
|
||||||
self.level = int(self.level)
|
|
||||||
|
|
||||||
acl = ACLManager('cmdb')
|
|
||||||
|
|
||||||
type2filter_perms = dict()
|
|
||||||
if not self.is_app_admin:
|
|
||||||
res2 = acl.get_resources(ResourceTypeEnum.CI_FILTER)
|
|
||||||
if res2:
|
|
||||||
type2filter_perms = CIFilterPermsCRUD().get_by_ids(list(map(int, [i['name'] for i in res2])))
|
|
||||||
|
|
||||||
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
|
||||||
|
|
||||||
level_ids = [str(i) for i in ids]
|
|
||||||
result = []
|
|
||||||
id2children = {}
|
|
||||||
id2name = _get_id2name(type_ids[0])
|
|
||||||
for i in level_ids:
|
|
||||||
item = dict(id=int(i),
|
|
||||||
type_id=type_ids[0],
|
|
||||||
isLeaf=False,
|
|
||||||
title=id2name[0].get(int(i)),
|
|
||||||
uniqueValue=id2name[1].get(int(i)),
|
|
||||||
children=[])
|
|
||||||
result.append(item)
|
|
||||||
id2children[str(i)] = item['children']
|
|
||||||
|
|
||||||
for lv in range(1, self.level):
|
|
||||||
|
|
||||||
if len(type_ids or []) >= lv and type2filter_perms.get(type_ids[lv]):
|
|
||||||
id_filter_limit, _ = self._get_ci_filter(type2filter_perms[type_ids[lv]])
|
|
||||||
else:
|
|
||||||
id_filter_limit = {}
|
|
||||||
|
|
||||||
if self.has_m2m and lv != 1:
|
|
||||||
key, prefix = [i for i in level_ids], REDIS_PREFIX_CI_RELATION2
|
|
||||||
else:
|
|
||||||
key, prefix = [i.split(',')[-1] for i in level_ids], REDIS_PREFIX_CI_RELATION
|
|
||||||
res = [json.loads(x).items() for x in [i or '{}' for i in rd.get(key, prefix) or []]]
|
|
||||||
res = [[i for i in x if (not id_filter_limit or (key[idx] not in id_filter_limit or
|
|
||||||
int(i[0]) in id_filter_limit[key[idx]]) or
|
|
||||||
int(i[0]) in id_filter_limit)] for idx, x in enumerate(res)]
|
|
||||||
_level_ids = []
|
|
||||||
type_id = type_ids[lv]
|
|
||||||
id2name = _get_id2name(type_id)
|
|
||||||
for idx, node_path in enumerate(level_ids):
|
|
||||||
for child_id, _ in (res[idx] or []):
|
|
||||||
item = dict(id=int(child_id),
|
|
||||||
type_id=type_id,
|
|
||||||
isLeaf=True if lv == self.level - 1 else False,
|
|
||||||
title=id2name[0].get(int(child_id)),
|
|
||||||
uniqueValue=id2name[1].get(int(child_id)),
|
|
||||||
children=[])
|
|
||||||
id2children[node_path].append(item)
|
|
||||||
|
|
||||||
_node_path = "{},{}".format(node_path, child_id)
|
|
||||||
_level_ids.append(_node_path)
|
|
||||||
id2children[_node_path] = item['children']
|
|
||||||
|
|
||||||
level_ids = _level_ids
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
@@ -1,10 +1,5 @@
|
|||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import current_app
|
|
||||||
from sqlalchemy import inspect, text
|
|
||||||
from sqlalchemy.dialects.mysql import ENUM
|
|
||||||
|
|
||||||
from api.extensions import db
|
|
||||||
|
|
||||||
|
|
||||||
def get_cur_time_str(split_flag='-'):
|
def get_cur_time_str(split_flag='-'):
|
||||||
@@ -28,115 +23,3 @@ class BaseEnum(object):
|
|||||||
if not attr.startswith("_") and not callable(getattr(cls, attr))
|
if not attr.startswith("_") and not callable(getattr(cls, attr))
|
||||||
}
|
}
|
||||||
return cls._ALL_
|
return cls._ALL_
|
||||||
|
|
||||||
|
|
||||||
class CheckNewColumn(object):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.engine = db.get_engine()
|
|
||||||
self.inspector = inspect(self.engine)
|
|
||||||
self.table_names = self.inspector.get_table_names()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_model_by_table_name(_table_name):
|
|
||||||
registry = getattr(db.Model, 'registry', None)
|
|
||||||
class_registry = getattr(registry, '_class_registry', None)
|
|
||||||
for _model in class_registry.values():
|
|
||||||
if hasattr(_model, '__tablename__') and _model.__tablename__ == _table_name:
|
|
||||||
return _model
|
|
||||||
return None
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
for table_name in self.table_names:
|
|
||||||
self.check_by_table(table_name)
|
|
||||||
|
|
||||||
def check_by_table(self, table_name):
|
|
||||||
existed_columns = self.inspector.get_columns(table_name)
|
|
||||||
enum_columns = []
|
|
||||||
existed_column_name_list = []
|
|
||||||
for c in existed_columns:
|
|
||||||
if isinstance(c['type'], ENUM):
|
|
||||||
enum_columns.append(c['name'])
|
|
||||||
existed_column_name_list.append(c['name'])
|
|
||||||
|
|
||||||
model = self.get_model_by_table_name(table_name)
|
|
||||||
if model is None:
|
|
||||||
return
|
|
||||||
model_columns = getattr(getattr(getattr(model, '__table__'), 'columns'), '_all_columns')
|
|
||||||
for column in model_columns:
|
|
||||||
if column.name not in existed_column_name_list:
|
|
||||||
add_res = self.add_new_column(table_name, column)
|
|
||||||
if not add_res:
|
|
||||||
continue
|
|
||||||
|
|
||||||
current_app.logger.info(f"add new column [{column.name}] in table [{table_name}] success.")
|
|
||||||
|
|
||||||
if column.name in enum_columns:
|
|
||||||
enum_columns.remove(column.name)
|
|
||||||
|
|
||||||
self.add_new_index(table_name, column)
|
|
||||||
|
|
||||||
if len(enum_columns) > 0:
|
|
||||||
self.check_enum_column(enum_columns, existed_columns, model_columns, table_name)
|
|
||||||
|
|
||||||
def add_new_column(self, target_table_name, new_column):
|
|
||||||
try:
|
|
||||||
column_type = new_column.type.compile(self.engine.dialect)
|
|
||||||
default_value = new_column.default.arg if new_column.default else None
|
|
||||||
|
|
||||||
sql = "ALTER TABLE " + target_table_name + " ADD COLUMN " + f"`{new_column.name}`" + " " + column_type
|
|
||||||
if new_column.comment:
|
|
||||||
sql += f" comment '{new_column.comment}'"
|
|
||||||
|
|
||||||
if column_type == 'JSON':
|
|
||||||
pass
|
|
||||||
elif default_value:
|
|
||||||
if column_type.startswith('VAR') or column_type.startswith('Text'):
|
|
||||||
if default_value is None or len(default_value) == 0:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
sql += f" DEFAULT {default_value}"
|
|
||||||
|
|
||||||
sql = text(sql)
|
|
||||||
db.session.execute(sql)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
err = f"add_new_column [{new_column.name}] to table [{target_table_name}] err: {e}"
|
|
||||||
current_app.logger.error(err)
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def add_new_index(target_table_name, new_column):
|
|
||||||
try:
|
|
||||||
if new_column.index:
|
|
||||||
index_name = f"{target_table_name}_{new_column.name}"
|
|
||||||
sql = "CREATE INDEX " + f"{index_name}" + " ON " + target_table_name + " (" + new_column.name + ")"
|
|
||||||
db.session.execute(sql)
|
|
||||||
current_app.logger.info(f"add new index [{index_name}] in table [{target_table_name}] success.")
|
|
||||||
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
err = f"add_new_index [{new_column.name}] to table [{target_table_name}] err: {e}"
|
|
||||||
current_app.logger.error(err)
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def check_enum_column(enum_columns, existed_columns, model_columns, table_name):
|
|
||||||
for column_name in enum_columns:
|
|
||||||
try:
|
|
||||||
enum_column = list(filter(lambda x: x['name'] == column_name, existed_columns))[0]
|
|
||||||
old_enum_value = enum_column.get('type', {}).enums
|
|
||||||
target_column = list(filter(lambda x: x.name == column_name, model_columns))[0]
|
|
||||||
new_enum_value = target_column.type.enums
|
|
||||||
|
|
||||||
if set(old_enum_value) == set(new_enum_value):
|
|
||||||
continue
|
|
||||||
|
|
||||||
enum_values_str = ','.join(["'{}'".format(value) for value in new_enum_value])
|
|
||||||
sql = f"ALTER TABLE {table_name} MODIFY COLUMN" + f"`{column_name}`" + f" enum({enum_values_str})"
|
|
||||||
db.session.execute(sql)
|
|
||||||
current_app.logger.info(
|
|
||||||
f"modify column [{column_name}] ENUM: {new_enum_value} in table [{table_name}] success.")
|
|
||||||
except Exception as e:
|
|
||||||
current_app.logger.error(
|
|
||||||
f"modify column ENUM [{column_name}] in table [{table_name}] err: {e}")
|
|
||||||
|
@@ -46,17 +46,13 @@ class CIType(Model):
|
|||||||
name = db.Column(db.String(32), nullable=False)
|
name = db.Column(db.String(32), nullable=False)
|
||||||
alias = db.Column(db.String(32), nullable=False)
|
alias = db.Column(db.String(32), nullable=False)
|
||||||
unique_id = db.Column(db.Integer, db.ForeignKey("c_attributes.id"), nullable=False)
|
unique_id = db.Column(db.Integer, db.ForeignKey("c_attributes.id"), nullable=False)
|
||||||
show_id = db.Column(db.Integer, db.ForeignKey("c_attributes.id"))
|
|
||||||
enabled = db.Column(db.Boolean, default=True, nullable=False)
|
enabled = db.Column(db.Boolean, default=True, nullable=False)
|
||||||
is_attached = db.Column(db.Boolean, default=False, nullable=False)
|
is_attached = db.Column(db.Boolean, default=False, nullable=False)
|
||||||
icon = db.Column(db.Text)
|
icon = db.Column(db.Text)
|
||||||
order = db.Column(db.SmallInteger, default=0, nullable=False)
|
order = db.Column(db.SmallInteger, default=0, nullable=False)
|
||||||
default_order_attr = db.Column(db.String(33))
|
default_order_attr = db.Column(db.String(33))
|
||||||
|
|
||||||
unique_key = db.relationship("Attribute", backref="c_ci_types.unique_id",
|
unique_key = db.relationship("Attribute", backref="c_ci_types.unique_id")
|
||||||
primaryjoin="Attribute.id==CIType.unique_id", foreign_keys=[unique_id])
|
|
||||||
show_key = db.relationship("Attribute", backref="c_ci_types.show_id",
|
|
||||||
primaryjoin="Attribute.id==CIType.show_id", foreign_keys=[show_id])
|
|
||||||
|
|
||||||
uid = db.Column(db.Integer, index=True)
|
uid = db.Column(db.Integer, index=True)
|
||||||
|
|
||||||
|
@@ -30,7 +30,6 @@ class CIRelationSearchView(APIView):
|
|||||||
level: default is 1
|
level: default is 1
|
||||||
facet: statistic
|
facet: statistic
|
||||||
"""
|
"""
|
||||||
|
|
||||||
page = get_page(request.values.get("page", 1))
|
page = get_page(request.values.get("page", 1))
|
||||||
count = get_page_size(request.values.get("count") or request.values.get("page_size"))
|
count = get_page_size(request.values.get("count") or request.values.get("page_size"))
|
||||||
|
|
||||||
@@ -87,26 +86,6 @@ class CIRelationStatisticsView(APIView):
|
|||||||
return self.jsonify(result)
|
return self.jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
class CIRelationSearchFullView(APIView):
|
|
||||||
url_prefix = "/ci_relations/search/full"
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
root_ids = list(map(int, handle_arg_list(request.values.get('root_ids'))))
|
|
||||||
level = request.values.get('level', 1)
|
|
||||||
type_ids = list(map(int, handle_arg_list(request.values.get('type_ids', []))))
|
|
||||||
has_m2m = request.values.get("has_m2m") in current_app.config.get('BOOL_TRUE')
|
|
||||||
|
|
||||||
start = time.time()
|
|
||||||
s = Search(root_ids, level, has_m2m=has_m2m)
|
|
||||||
try:
|
|
||||||
result = s.search_full(type_ids)
|
|
||||||
except SearchError as e:
|
|
||||||
return abort(400, str(e))
|
|
||||||
current_app.logger.debug("search time is :{0}".format(time.time() - start))
|
|
||||||
|
|
||||||
return self.jsonify(result)
|
|
||||||
|
|
||||||
|
|
||||||
class GetSecondCIsView(APIView):
|
class GetSecondCIsView(APIView):
|
||||||
url_prefix = "/ci_relations/<int:first_ci_id>/second_cis"
|
url_prefix = "/ci_relations/<int:first_ci_id>/second_cis"
|
||||||
|
|
||||||
|
@@ -42,11 +42,9 @@
|
|||||||
"relation-graph": "^1.1.0",
|
"relation-graph": "^1.1.0",
|
||||||
"snabbdom": "^3.5.1",
|
"snabbdom": "^3.5.1",
|
||||||
"sortablejs": "1.9.0",
|
"sortablejs": "1.9.0",
|
||||||
"style-resources-loader": "^1.5.0",
|
|
||||||
"viser-vue": "^2.4.8",
|
"viser-vue": "^2.4.8",
|
||||||
"vue": "2.6.11",
|
"vue": "2.6.11",
|
||||||
"vue-clipboard2": "^0.3.3",
|
"vue-clipboard2": "^0.3.3",
|
||||||
"vue-cli-plugin-style-resources-loader": "^0.1.5",
|
|
||||||
"vue-codemirror": "^4.0.6",
|
"vue-codemirror": "^4.0.6",
|
||||||
"vue-cropper": "^0.6.2",
|
"vue-cropper": "^0.6.2",
|
||||||
"vue-grid-layout": "2.3.12",
|
"vue-grid-layout": "2.3.12",
|
||||||
|
@@ -54,24 +54,6 @@
|
|||||||
<div class="content unicode" style="display: block;">
|
<div class="content unicode" style="display: block;">
|
||||||
<ul class="icon_lists dib-box">
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<span class="icon iconfont"></span>
|
|
||||||
<div class="name">veops-show</div>
|
|
||||||
<div class="code-name">&#xe914;</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<span class="icon iconfont"></span>
|
|
||||||
<div class="name">itsm-duration</div>
|
|
||||||
<div class="code-name">&#xe913;</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<span class="icon iconfont"></span>
|
|
||||||
<div class="name">itsm-workload (1)</div>
|
|
||||||
<div class="code-name">&#xe912;</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
<li class="dib">
|
||||||
<span class="icon iconfont"></span>
|
<span class="icon iconfont"></span>
|
||||||
<div class="name">VPC</div>
|
<div class="name">VPC</div>
|
||||||
@@ -4806,9 +4788,9 @@
|
|||||||
<pre><code class="language-css"
|
<pre><code class="language-css"
|
||||||
>@font-face {
|
>@font-face {
|
||||||
font-family: 'iconfont';
|
font-family: 'iconfont';
|
||||||
src: url('iconfont.woff2?t=1713335725699') format('woff2'),
|
src: url('iconfont.woff2?t=1711963254221') format('woff2'),
|
||||||
url('iconfont.woff?t=1713335725699') format('woff'),
|
url('iconfont.woff?t=1711963254221') format('woff'),
|
||||||
url('iconfont.ttf?t=1713335725699') format('truetype');
|
url('iconfont.ttf?t=1711963254221') format('truetype');
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||||
@@ -4834,33 +4816,6 @@
|
|||||||
<div class="content font-class">
|
<div class="content font-class">
|
||||||
<ul class="icon_lists dib-box">
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<span class="icon iconfont veops-show"></span>
|
|
||||||
<div class="name">
|
|
||||||
veops-show
|
|
||||||
</div>
|
|
||||||
<div class="code-name">.veops-show
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<span class="icon iconfont itsm-duration"></span>
|
|
||||||
<div class="name">
|
|
||||||
itsm-duration
|
|
||||||
</div>
|
|
||||||
<div class="code-name">.itsm-duration
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<span class="icon iconfont a-itsm-workload1"></span>
|
|
||||||
<div class="name">
|
|
||||||
itsm-workload (1)
|
|
||||||
</div>
|
|
||||||
<div class="code-name">.a-itsm-workload1
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
<li class="dib">
|
||||||
<span class="icon iconfont caise-VPC"></span>
|
<span class="icon iconfont caise-VPC"></span>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
@@ -11962,30 +11917,6 @@
|
|||||||
<div class="content symbol">
|
<div class="content symbol">
|
||||||
<ul class="icon_lists dib-box">
|
<ul class="icon_lists dib-box">
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<svg class="icon svg-icon" aria-hidden="true">
|
|
||||||
<use xlink:href="#veops-show"></use>
|
|
||||||
</svg>
|
|
||||||
<div class="name">veops-show</div>
|
|
||||||
<div class="code-name">#veops-show</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<svg class="icon svg-icon" aria-hidden="true">
|
|
||||||
<use xlink:href="#itsm-duration"></use>
|
|
||||||
</svg>
|
|
||||||
<div class="name">itsm-duration</div>
|
|
||||||
<div class="code-name">#itsm-duration</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
|
||||||
<svg class="icon svg-icon" aria-hidden="true">
|
|
||||||
<use xlink:href="#a-itsm-workload1"></use>
|
|
||||||
</svg>
|
|
||||||
<div class="name">itsm-workload (1)</div>
|
|
||||||
<div class="code-name">#a-itsm-workload1</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dib">
|
<li class="dib">
|
||||||
<svg class="icon svg-icon" aria-hidden="true">
|
<svg class="icon svg-icon" aria-hidden="true">
|
||||||
<use xlink:href="#caise-VPC"></use>
|
<use xlink:href="#caise-VPC"></use>
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 3857903 */
|
font-family: "iconfont"; /* Project id 3857903 */
|
||||||
src: url('iconfont.woff2?t=1713335725699') format('woff2'),
|
src: url('iconfont.woff2?t=1711963254221') format('woff2'),
|
||||||
url('iconfont.woff?t=1713335725699') format('woff'),
|
url('iconfont.woff?t=1711963254221') format('woff'),
|
||||||
url('iconfont.ttf?t=1713335725699') format('truetype');
|
url('iconfont.ttf?t=1711963254221') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@@ -13,18 +13,6 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
.veops-show:before {
|
|
||||||
content: "\e914";
|
|
||||||
}
|
|
||||||
|
|
||||||
.itsm-duration:before {
|
|
||||||
content: "\e913";
|
|
||||||
}
|
|
||||||
|
|
||||||
.a-itsm-workload1:before {
|
|
||||||
content: "\e912";
|
|
||||||
}
|
|
||||||
|
|
||||||
.caise-VPC:before {
|
.caise-VPC:before {
|
||||||
content: "\e910";
|
content: "\e910";
|
||||||
}
|
}
|
||||||
|
@@ -5,27 +5,6 @@
|
|||||||
"css_prefix_text": "",
|
"css_prefix_text": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
{
|
|
||||||
"icon_id": "39948814",
|
|
||||||
"name": "veops-show",
|
|
||||||
"font_class": "veops-show",
|
|
||||||
"unicode": "e914",
|
|
||||||
"unicode_decimal": 59668
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "39926816",
|
|
||||||
"name": "itsm-duration",
|
|
||||||
"font_class": "itsm-duration",
|
|
||||||
"unicode": "e913",
|
|
||||||
"unicode_decimal": 59667
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "39926833",
|
|
||||||
"name": "itsm-workload (1)",
|
|
||||||
"font_class": "a-itsm-workload1",
|
|
||||||
"unicode": "e912",
|
|
||||||
"unicode_decimal": 59666
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"icon_id": "39782649",
|
"icon_id": "39782649",
|
||||||
"name": "VPC",
|
"name": "VPC",
|
||||||
|
14
cmdb-ui/src/assets/icons/ops-default_show.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 0H2.5V1.25H1.25V2.5H0V1C0 0.447715 0.447715 0 1 0ZM0 7.5V9C0 9.55229 0.447715 10 1 10H2.5V8.75H1.25V7.5H0ZM8.75 7.5V8.75H7.5V10H9C9.55229 10 10 9.55228 10 9V7.5H8.75ZM10 2.5V1C10 0.447715 9.55228 0 9 0H7.5V1.25H8.75V2.5H10Z" fill="url(#paint0_linear_124_16807)"/>
|
||||||
|
<rect x="2.5" y="3.125" width="5" height="3.75" fill="url(#paint1_linear_124_16807)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16807" x1="5" y1="0" x2="5" y2="10" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#4F84FF"/>
|
||||||
|
<stop offset="1" stop-color="#85CBFF"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_124_16807" x1="5" y1="3.125" x2="5" y2="6.875" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#4F84FF"/>
|
||||||
|
<stop offset="1" stop-color="#85CBFF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 916 B |
14
cmdb-ui/src/assets/icons/ops-is_choice.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="2.5" y="2.5" width="5" height="5" rx="0.5" fill="url(#paint0_linear_124_16808)"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 0C0.447715 0 0 0.447715 0 1V9C0 9.55229 0.447715 10 1 10H9C9.55229 10 10 9.55228 10 9V1C10 0.447715 9.55228 0 9 0H1ZM8.75 1.25H1.25V8.75H8.75V1.25Z" fill="url(#paint1_linear_124_16808)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16808" x1="5" y1="2.5" x2="5" y2="7.5" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#5187FF"/>
|
||||||
|
<stop offset="1" stop-color="#84C9FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_124_16808" x1="5" y1="0" x2="5" y2="10" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#5187FF"/>
|
||||||
|
<stop offset="1" stop-color="#84C9FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 840 B |
9
cmdb-ui/src/assets/icons/ops-is_index.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5.56845 8.8409C3.06335 8.78963 1.86719 8.05799 2.06279 6.48243C2.1538 5.75105 2.64549 5.3214 3.34457 5.16041C3.67173 5.08909 4.00806 5.06954 4.34128 5.10247C4.40203 5.10811 4.44843 5.11401 4.47689 5.11837L4.51586 5.12631C4.64379 5.15574 4.77263 5.18104 4.90218 5.20219C5.26786 5.2651 5.63914 5.28941 6.0099 5.27474C6.8046 5.23219 7.21015 4.97429 7.23092 4.41672C7.25424 3.79429 6.76332 3.29619 5.86659 2.91832C5.52815 2.77793 5.17843 2.66645 4.82117 2.58506C4.70325 2.55755 4.58482 2.53328 4.46587 2.51226C4.30323 2.94847 3.9867 3.31016 3.57591 3.5292C3.16512 3.74824 2.68841 3.80952 2.23557 3.70149C1.90324 3.61651 1.60053 3.44214 1.36029 3.1973C1.12004 2.95245 0.951447 2.64649 0.872793 2.3126C0.794138 1.97872 0.808429 1.62967 0.914116 1.30333C1.0198 0.976995 1.21285 0.685836 1.4723 0.461451C1.73176 0.237065 2.04771 0.0880244 2.38588 0.0305017C2.72404 -0.0270211 3.07151 0.00917138 3.39056 0.135152C3.70961 0.261132 3.98807 0.472088 4.19571 0.745127C4.40335 1.01817 4.53225 1.34286 4.56841 1.68397C4.6812 1.70269 4.83374 1.73217 5.01524 1.77421C5.42003 1.86601 5.81625 1.99216 6.1996 2.15131C7.38191 2.64966 8.1156 3.39463 8.07638 4.4462C8.03639 5.53187 7.23425 6.04253 6.0563 6.10533C5.62418 6.12373 5.19132 6.09614 4.76503 6.02304C4.61925 5.99997 4.47398 5.9716 4.32923 5.93793C4.30731 5.93532 4.28534 5.9331 4.26335 5.93127C4.02033 5.90687 3.77501 5.92018 3.53606 5.97075C3.15153 6.05893 2.94311 6.24146 2.90056 6.58267C2.78725 7.49504 3.47915 7.94443 5.42694 8.00416C5.44492 7.65558 5.5586 7.3187 5.75548 7.03049C5.95237 6.74229 6.22485 6.51389 6.54303 6.37039C6.8612 6.22689 7.21277 6.17383 7.55912 6.21703C7.90548 6.26023 8.23323 6.39802 8.50641 6.61528C8.77959 6.83254 8.98763 7.12086 9.10769 7.4486C9.22775 7.77634 9.25519 8.13082 9.187 8.47314C9.11881 8.81545 8.95763 9.13235 8.72114 9.38907C8.48465 9.64578 8.18201 9.83237 7.84643 9.92836C7.39921 10.0556 6.92094 10.0153 6.50129 9.81515C6.08164 9.61495 5.74941 9.26855 5.56691 8.8409H5.56845Z" fill="url(#paint0_linear_124_16804)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16804" x1="5.02318" y1="0.00390625" x2="5.02318" y2="10.0013" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#497DFF"/>
|
||||||
|
<stop offset="1" stop-color="#8CD5FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
9
cmdb-ui/src/assets/icons/ops-is_link.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4.01211 4.50621L2.7769 5.74077C2.712 5.80565 2.66051 5.88268 2.62538 5.96747C2.59025 6.05225 2.57217 6.14313 2.57217 6.2349C2.57217 6.32668 2.59025 6.41755 2.62538 6.50234C2.66051 6.58712 2.712 6.66416 2.7769 6.72904L3.27085 7.223C3.33573 7.28791 3.41276 7.3394 3.49754 7.37453C3.58232 7.40966 3.67319 7.42774 3.76496 7.42774C3.85674 7.42774 3.94761 7.40966 4.03239 7.37453C4.11717 7.3394 4.1942 7.28791 4.25908 7.223L5.49394 5.98775C5.6237 6.1175 5.72663 6.27155 5.79686 6.44109C5.86708 6.61063 5.90323 6.79234 5.90323 6.97585C5.90323 7.15935 5.86708 7.34106 5.79686 7.5106C5.72663 7.68014 5.6237 7.83419 5.49394 7.96394L3.76479 9.69316C3.56827 9.88963 3.30176 10 3.02387 10C2.74599 10 2.47948 9.88963 2.28296 9.69316L0.306832 7.71696C0.110368 7.52043 0 7.25391 0 6.97602C0 6.69813 0.110368 6.43161 0.306832 6.23508L2.03599 4.50586C2.16574 4.3761 2.31978 4.27317 2.48931 4.20294C2.65884 4.13271 2.84055 4.09657 3.02405 4.09657C3.20755 4.09657 3.38925 4.13271 3.55879 4.20294C3.72832 4.27317 3.88236 4.3761 4.01211 4.50586V4.50621ZM5.98789 5.49414L7.2231 4.25923C7.288 4.19435 7.33949 4.11732 7.37462 4.03253C7.40975 3.94775 7.42783 3.85687 7.42783 3.7651C7.42783 3.67332 7.40975 3.58245 7.37462 3.49766C7.33949 3.41288 7.288 3.33584 7.2231 3.27096L6.72915 2.777C6.66428 2.71209 6.58724 2.6606 6.50246 2.62547C6.41768 2.59034 6.32681 2.57226 6.23504 2.57226C6.14326 2.57226 6.05239 2.59034 5.96761 2.62547C5.88283 2.6606 5.8058 2.71209 5.74092 2.777L4.50606 4.01225C4.3763 3.8825 4.27337 3.72845 4.20314 3.55891C4.13292 3.38937 4.09677 3.20766 4.09677 3.02415C4.09677 2.84065 4.13292 2.65894 4.20314 2.4894C4.27337 2.31986 4.3763 2.16581 4.50606 2.03606L6.23521 0.306843C6.43173 0.110371 6.69824 0 6.97613 0C7.25401 0 7.52052 0.110371 7.71704 0.306843L9.69317 2.28304C9.88963 2.47957 10 2.74609 10 3.02398C10 3.30187 9.88963 3.56839 9.69317 3.76492L7.96401 5.49414C7.83426 5.6239 7.68022 5.72683 7.51069 5.79706C7.34116 5.86729 7.15945 5.90343 6.97595 5.90343C6.79245 5.90343 6.61075 5.86729 6.44121 5.79706C6.27168 5.72683 6.11764 5.6239 5.98789 5.49414ZM3.51817 5.9881L5.98789 3.51829C6.05339 3.45274 6.14225 3.4159 6.23491 3.41586C6.32758 3.41583 6.41646 3.45261 6.48201 3.51812C6.54755 3.58362 6.5844 3.67248 6.58443 3.76515C6.58446 3.85782 6.54768 3.9467 6.48218 4.01225L4.01211 6.48206C3.94661 6.54761 3.85775 6.58445 3.76509 6.58449C3.67242 6.58452 3.58354 6.54774 3.51799 6.48223C3.45245 6.41673 3.4156 6.32787 3.41557 6.2352C3.41554 6.14253 3.45232 6.05365 3.51782 5.9881H3.51817Z" fill="url(#paint0_linear_124_16775)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16775" x1="5" y1="0" x2="5" y2="10" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#5A85FF"/>
|
||||||
|
<stop offset="1" stop-color="#8DD8FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
9
cmdb-ui/src/assets/icons/ops-is_password.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1.31822 4.16667H2.54549V2.5C2.54549 1.11458 3.63981 0 5.00003 0C6.36026 0 7.45458 1.11458 7.45458 2.5V4.16667H8.68185C8.90685 4.16667 9.09094 4.35417 9.09094 4.58333V9.58333C9.09094 9.8125 8.90685 10 8.68185 10H1.31822C1.09322 10 0.909124 9.8125 0.909124 9.58333V4.58333C0.909124 4.35417 1.09322 4.16667 1.31822 4.16667ZM5.00003 7.91667C5.45003 7.91667 5.81822 7.54167 5.81822 7.08333C5.81822 6.625 5.45003 6.25 5.00003 6.25C4.55003 6.25 4.18185 6.625 4.18185 7.08333C4.18185 7.54167 4.55003 7.91667 5.00003 7.91667ZM3.36367 4.16667H6.6364V2.5C6.6364 1.58333 5.90003 0.833333 5.00003 0.833333C4.10003 0.833333 3.36367 1.58333 3.36367 2.5V4.16667Z" fill="url(#paint0_linear_124_16805)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16805" x1="5.00003" y1="0" x2="5.00003" y2="10" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#4D82FF"/>
|
||||||
|
<stop offset="1" stop-color="#88CFFF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1022 B |
9
cmdb-ui/src/assets/icons/ops-is_sortable.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.91242 9.46382C3.91242 9.57428 3.82288 9.66382 3.71242 9.66382H2.35075C2.2403 9.66382 2.15075 9.57428 2.15075 9.46382V3.55962C2.15075 3.44916 2.06121 3.35962 1.95075 3.35962H0.539905C0.354312 3.35962 0.268806 3.12879 0.40961 3.00788L3.58212 0.283626C3.71182 0.172253 3.91242 0.264405 3.91242 0.43536V9.46382ZM6.08758 0.567715C6.08758 0.457258 6.17712 0.367716 6.28758 0.367716H7.64925C7.7597 0.367716 7.84925 0.457259 7.84925 0.567716V6.4411C7.84925 6.55156 7.93879 6.6411 8.04925 6.6411H9.46001C9.64561 6.6411 9.73111 6.87195 9.59029 6.99285L6.41786 9.71645C6.28816 9.8278 6.08758 9.73565 6.08758 9.5647V0.567715Z" fill="url(#paint0_linear_124_16806)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16806" x1="5" y1="0" x2="5" y2="10" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#5A85FF"/>
|
||||||
|
<stop offset="1" stop-color="#8DD8FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 979 B |
9
cmdb-ui/src/assets/icons/ops-is_unique.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="1em" height="1em" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5.51961 6.8937V10H4.48V6.8937H1.76732C1.65823 6.8937 1.56223 6.85372 1.48369 6.77237C1.40522 6.69504 1.3621 6.5915 1.36369 6.48421C1.36369 5.95891 1.52769 5.48566 1.85895 5.06411C2.18986 4.64428 2.56258 4.43334 2.97893 4.43334V1.64277C2.75966 1.64277 2.57167 1.56142 2.41022 1.39873C2.25355 1.24349 2.16738 1.0362 2.17022 0.821384C2.17022 0.598718 2.25022 0.407762 2.41022 0.244037C2.56912 0.0827244 2.7593 0 2.97893 0H7.01959C7.23885 0 7.42685 0.0813456 7.5883 0.244037C7.74721 0.406728 7.82866 0.598718 7.82866 0.821384C7.82866 1.04405 7.74866 1.23501 7.58867 1.39873C7.4283 1.5628 7.23885 1.64277 7.01959 1.64277V4.43196C7.43594 4.43196 7.81012 4.64291 8.13956 5.06273C8.46631 5.47151 8.64098 5.97137 8.63628 6.48421C8.63628 6.59486 8.59701 6.6924 8.51665 6.77237C8.43665 6.85234 8.34211 6.8937 8.23302 6.8937H5.51998H5.51961Z" fill="url(#paint0_linear_124_16803)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_124_16803" x1="5.00001" y1="0" x2="5.00001" y2="10" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#5A85FF"/>
|
||||||
|
<stop offset="1" stop-color="#8DD8FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@@ -69,6 +69,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.custom-drawer-close {
|
.custom-drawer-close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@@ -230,6 +230,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
.employee-transfer {
|
.employee-transfer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.vue-treeselect__multi-value-item-container {
|
.vue-treeselect__multi-value-item-container {
|
||||||
@@ -262,6 +263,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.employee-transfer {
|
.employee-transfer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@@ -146,6 +146,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.regex-select {
|
.regex-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
|
@@ -126,6 +126,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.role-transfer {
|
.role-transfer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@@ -60,6 +60,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.sidebar-list-item {
|
.sidebar-list-item {
|
||||||
.ops_popover_item();
|
.ops_popover_item();
|
||||||
margin: 2px 0;
|
margin: 2px 0;
|
||||||
|
@@ -52,6 +52,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.two-column-layout {
|
.two-column-layout {
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
|
@@ -4,22 +4,34 @@
|
|||||||
@click="jumpTo"
|
@click="jumpTo"
|
||||||
v-if="showTitle && !collapsed"
|
v-if="showTitle && !collapsed"
|
||||||
style="width: 100%; height: 100%; cursor: pointer"
|
style="width: 100%; height: 100%; cursor: pointer"
|
||||||
:src="require('@/assets/logo_VECMDB.png')"
|
:src="file_name ? `/api/common-setting/v1/file/${file_name}` : require('@/assets/logo_VECMDB.png')"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
@click="jumpTo"
|
@click="jumpTo"
|
||||||
v-else
|
v-else
|
||||||
style="width: 32px; height: 32px; margin-left: 24px; cursor: pointer"
|
style="width: 32px; height: 32px; margin-left: 24px; cursor: pointer"
|
||||||
:src="require('@/assets/logo.png')"
|
:src="small_file_name ? `/api/common-setting/v1/file/${small_file_name}` : require('@/assets/logo.png')"
|
||||||
/>
|
/>
|
||||||
|
<!-- <logo-svg/> -->
|
||||||
|
<!-- <img v-if="showTitle" style="width:92px;height: 32px" src="@/assets/OneOps.png" /> -->
|
||||||
|
<!-- <h1 v-if="showTitle">{{ title }}</h1> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// import LogoSvg from '@/assets/logo.svg?inline'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
name: 'Logo',
|
name: 'Logo',
|
||||||
components: {},
|
components: {
|
||||||
computed: {},
|
// LogoSvg,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
file_name: (state) => state.logo.file_name,
|
||||||
|
small_file_name: (state) => state.logo.small_file_name,
|
||||||
|
}),
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@@ -96,6 +96,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
.color {
|
.color {
|
||||||
color: #custom_colors[color_1];
|
color: #custom_colors[color_1];
|
||||||
background-color: #custom_colors[color_2];
|
background-color: #custom_colors[color_2];
|
||||||
|
@@ -9,11 +9,25 @@
|
|||||||
import gridSvg from '@/assets/icons/grid.svg?inline'
|
import gridSvg from '@/assets/icons/grid.svg?inline'
|
||||||
import top_agent from '@/assets/icons/top_agent.svg?inline'
|
import top_agent from '@/assets/icons/top_agent.svg?inline'
|
||||||
import top_acl from '@/assets/icons/top_acl.svg?inline'
|
import top_acl from '@/assets/icons/top_acl.svg?inline'
|
||||||
|
import ops_default_show from '@/assets/icons/ops-default_show.svg?inline'
|
||||||
|
import ops_is_choice from '@/assets/icons/ops-is_choice.svg?inline'
|
||||||
|
import ops_is_index from '@/assets/icons/ops-is_index.svg?inline'
|
||||||
|
import ops_is_link from '@/assets/icons/ops-is_link.svg?inline'
|
||||||
|
import ops_is_password from '@/assets/icons/ops-is_password.svg?inline'
|
||||||
|
import ops_is_sortable from '@/assets/icons/ops-is_sortable.svg?inline'
|
||||||
|
import ops_is_unique from '@/assets/icons/ops-is_unique.svg?inline'
|
||||||
import ops_move_icon from '@/assets/icons/ops-move-icon.svg?inline'
|
import ops_move_icon from '@/assets/icons/ops-move-icon.svg?inline'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
gridSvg,
|
gridSvg,
|
||||||
top_agent,
|
top_agent,
|
||||||
top_acl,
|
top_acl,
|
||||||
|
ops_default_show,
|
||||||
|
ops_is_choice,
|
||||||
|
ops_is_index,
|
||||||
|
ops_is_link,
|
||||||
|
ops_is_password,
|
||||||
|
ops_is_sortable,
|
||||||
|
ops_is_unique,
|
||||||
ops_move_icon
|
ops_move_icon
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
import './highlight.less'
|
|
||||||
|
|
||||||
const highlight = (el, binding) => {
|
|
||||||
if (binding.value.value) {
|
|
||||||
let testValue = `${binding.value.value}`
|
|
||||||
if (['(', ')', '$'].includes(testValue)) {
|
|
||||||
testValue = `\\${testValue}`
|
|
||||||
}
|
|
||||||
const regex = new RegExp(`(${testValue})`, 'gi')
|
|
||||||
el.innerHTML = el.innerText.replace(regex, `<span class='${binding.value.class ?? 'ops-text-highlight'}'>$1</span>`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default highlight
|
|
@@ -1,5 +0,0 @@
|
|||||||
@import '~@/style/static.less';
|
|
||||||
|
|
||||||
.ops-text-highlight {
|
|
||||||
background-color: @primary-color_3;
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
import hightlight from './highlight'
|
|
||||||
|
|
||||||
const install = function (Vue) {
|
|
||||||
Vue.directive('hightlight', hightlight)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window.hightlight = hightlight
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
hightlight.install = install
|
|
||||||
export default hightlight
|
|
@@ -1,13 +0,0 @@
|
|||||||
import waves from './waves'
|
|
||||||
|
|
||||||
const install = function (Vue) {
|
|
||||||
Vue.directive('waves', waves)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.Vue) {
|
|
||||||
window.waves = waves
|
|
||||||
Vue.use(install); // eslint-disable-line
|
|
||||||
}
|
|
||||||
|
|
||||||
waves.install = install
|
|
||||||
export default waves
|
|
@@ -1,26 +0,0 @@
|
|||||||
.waves-ripple {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.15);
|
|
||||||
background-clip: padding-box;
|
|
||||||
pointer-events: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-transform: scale(0);
|
|
||||||
-ms-transform: scale(0);
|
|
||||||
transform: scale(0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.waves-ripple.z-active {
|
|
||||||
opacity: 0;
|
|
||||||
-webkit-transform: scale(2);
|
|
||||||
-ms-transform: scale(2);
|
|
||||||
transform: scale(2);
|
|
||||||
-webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
|
|
||||||
transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
|
|
||||||
transition: opacity 1.2s ease-out, transform 0.6s ease-out;
|
|
||||||
transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
|
|
||||||
}
|
|
@@ -1,72 +0,0 @@
|
|||||||
import './waves.css'
|
|
||||||
|
|
||||||
const context = '@@wavesContext'
|
|
||||||
|
|
||||||
function handleClick(el, binding) {
|
|
||||||
function handle(e) {
|
|
||||||
const customOpts = Object.assign({}, binding.value)
|
|
||||||
const opts = Object.assign({
|
|
||||||
ele: el, // 波纹作用元素
|
|
||||||
type: 'hit', // hit 点击位置扩散 center中心点扩展
|
|
||||||
color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
|
||||||
},
|
|
||||||
customOpts
|
|
||||||
)
|
|
||||||
const target = opts.ele
|
|
||||||
if (target) {
|
|
||||||
target.style.position = 'relative'
|
|
||||||
target.style.overflow = 'hidden'
|
|
||||||
const rect = target.getBoundingClientRect()
|
|
||||||
let ripple = target.querySelector('.waves-ripple')
|
|
||||||
if (!ripple) {
|
|
||||||
ripple = document.createElement('span')
|
|
||||||
ripple.className = 'waves-ripple'
|
|
||||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
|
|
||||||
target.appendChild(ripple)
|
|
||||||
} else {
|
|
||||||
ripple.className = 'waves-ripple'
|
|
||||||
}
|
|
||||||
switch (opts.type) {
|
|
||||||
case 'center':
|
|
||||||
ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px'
|
|
||||||
ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px'
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
ripple.style.top =
|
|
||||||
(e.pageY - rect.top - ripple.offsetHeight / 2 - document.documentElement.scrollTop ||
|
|
||||||
document.body.scrollTop) + 'px'
|
|
||||||
ripple.style.left =
|
|
||||||
(e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft ||
|
|
||||||
document.body.scrollLeft) + 'px'
|
|
||||||
}
|
|
||||||
ripple.style.backgroundColor = opts.color
|
|
||||||
ripple.className = 'waves-ripple z-active'
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!el[context]) {
|
|
||||||
el[context] = {
|
|
||||||
removeHandle: handle
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
el[context].removeHandle = handle
|
|
||||||
}
|
|
||||||
|
|
||||||
return handle
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
bind(el, binding) {
|
|
||||||
el.addEventListener('click', handleClick(el, binding), false)
|
|
||||||
},
|
|
||||||
update(el, binding) {
|
|
||||||
el.removeEventListener('click', el[context].removeHandle, false)
|
|
||||||
el.addEventListener('click', handleClick(el, binding), false)
|
|
||||||
},
|
|
||||||
unbind(el) {
|
|
||||||
el.removeEventListener('click', el[context].removeHandle, false)
|
|
||||||
el[context] = null
|
|
||||||
delete el[context]
|
|
||||||
}
|
|
||||||
}
|
|
@@ -31,6 +31,7 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
store.dispatch("loadAllUsers")
|
store.dispatch("loadAllUsers")
|
||||||
store.dispatch("loadAllEmployees")
|
store.dispatch("loadAllEmployees")
|
||||||
store.dispatch("loadAllDepartments")
|
store.dispatch("loadAllDepartments")
|
||||||
|
store.dispatch("getCompanyInfo")
|
||||||
store.dispatch('GenerateRoutes', { roles }).then(() => {
|
store.dispatch('GenerateRoutes', { roles }).then(() => {
|
||||||
router.addRoutes(store.getters.appRoutes)
|
router.addRoutes(store.getters.appRoutes)
|
||||||
const redirect = decodeURIComponent(from.query.redirect || to.path)
|
const redirect = decodeURIComponent(from.query.redirect || to.path)
|
||||||
|
@@ -233,6 +233,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-history {
|
.acl-history {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -32,6 +32,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-operation-history {
|
.acl-operation-history {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -189,6 +189,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-resource-types {
|
.acl-resource-types {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -352,6 +352,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-resources {
|
.acl-resources {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -285,6 +285,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-roles {
|
.acl-roles {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -88,6 +88,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-secret-key {
|
.acl-secret-key {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
@@ -320,6 +320,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-trigger {
|
.acl-trigger {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -188,6 +188,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.acl-users {
|
.acl-users {
|
||||||
border-radius: @border-radius-box;
|
border-radius: @border-radius-box;
|
||||||
|
@@ -73,11 +73,3 @@ export function deleteCIRelationView(firstCiId, secondCiId, data) {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function searchCIRelationFull(params) {
|
|
||||||
return axios({
|
|
||||||
url: `/v0.1/ci_relations/search/full`,
|
|
||||||
method: 'GET',
|
|
||||||
params,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@@ -221,6 +221,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-transfer {
|
.cmdb-transfer {
|
||||||
.ant-transfer-list {
|
.ant-transfer-list {
|
||||||
|
@@ -311,6 +311,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.cmdb-grant {
|
.cmdb-grant {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
@@ -323,6 +324,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-grant {
|
.cmdb-grant {
|
||||||
.grant-button {
|
.grant-button {
|
||||||
|
@@ -59,6 +59,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.read-checkbox {
|
.read-checkbox {
|
||||||
.read-checkbox-half-checked {
|
.read-checkbox-half-checked {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
@@ -112,6 +112,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.notice-content {
|
.notice-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
& &-main {
|
& &-main {
|
||||||
@@ -185,6 +186,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.notice-content {
|
.notice-content {
|
||||||
.w-e-bar {
|
.w-e-bar {
|
||||||
|
@@ -95,12 +95,12 @@
|
|||||||
isFocusExpression = false
|
isFocusExpression = false
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
:class="{ 'ci-searchform-expression': true, 'ci-searchform-expression-has-value': expression }"
|
class="ci-searchform-expression"
|
||||||
:style="{ width }"
|
:style="{ width }"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
@keyup.enter="emitRefresh"
|
@keyup.enter="emitRefresh"
|
||||||
>
|
>
|
||||||
<a-icon slot="suffix" type="check-circle" @click="handleCopyExpression" />
|
<ops-icon slot="suffix" type="veops-copy" @click="handleCopyExpression" />
|
||||||
</a-input>
|
</a-input>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</a-space>
|
</a-space>
|
||||||
@@ -264,6 +264,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
@import '../../views/index.less';
|
@import '../../views/index.less';
|
||||||
.ci-searchform-expression {
|
.ci-searchform-expression {
|
||||||
> input {
|
> input {
|
||||||
@@ -284,9 +285,6 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ci-searchform-expression-has-value .ant-input-suffix {
|
|
||||||
color: @func-color_3;
|
|
||||||
}
|
|
||||||
.cmdb-search-form {
|
.cmdb-search-form {
|
||||||
.ant-form-item-label {
|
.ant-form-item-label {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -297,6 +295,8 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.search-form-bar {
|
.search-form-bar {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -244,6 +244,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-subscribe-drawer {
|
.cmdb-subscribe-drawer {
|
||||||
.cmdb-subscribe-drawer-container {
|
.cmdb-subscribe-drawer-container {
|
||||||
@@ -314,6 +315,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
.cmdb-subscribe-drawer {
|
.cmdb-subscribe-drawer {
|
||||||
.ant-tabs-bar {
|
.ant-tabs-bar {
|
||||||
background-color: #custom_colors[color_2];
|
background-color: #custom_colors[color_2];
|
||||||
|
@@ -194,10 +194,7 @@ const cmdb_en = {
|
|||||||
attributeAssociationTip3: 'Two Attributes must be selected',
|
attributeAssociationTip3: 'Two Attributes must be selected',
|
||||||
attributeAssociationTip4: 'Please select a attribute from Source CIType',
|
attributeAssociationTip4: 'Please select a attribute from Source CIType',
|
||||||
attributeAssociationTip5: 'Please select a attribute from Target CIType',
|
attributeAssociationTip5: 'Please select a attribute from Target CIType',
|
||||||
show: 'show attribute',
|
|
||||||
setAsShow: 'Set as show attribute',
|
|
||||||
cancelSetAsShow: 'Cancel show attribute',
|
|
||||||
showTips: 'The names of nodes in the service tree and topology view'
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
unselectAttributes: 'Unselected',
|
unselectAttributes: 'Unselected',
|
||||||
@@ -533,8 +530,7 @@ if __name__ == "__main__":
|
|||||||
peopleHasRead: 'Personnel authorized to read:',
|
peopleHasRead: 'Personnel authorized to read:',
|
||||||
authorizationPolicy: 'CI Authorization Policy:',
|
authorizationPolicy: 'CI Authorization Policy:',
|
||||||
idAuthorizationPolicy: 'Authorized by node:',
|
idAuthorizationPolicy: 'Authorized by node:',
|
||||||
view: 'View permissions',
|
view: 'View permissions'
|
||||||
searchTips: 'Search in service tree'
|
|
||||||
},
|
},
|
||||||
tree: {
|
tree: {
|
||||||
tips1: 'Please go to Preference page first to complete your subscription!',
|
tips1: 'Please go to Preference page first to complete your subscription!',
|
||||||
|
@@ -194,10 +194,6 @@ const cmdb_zh = {
|
|||||||
attributeAssociationTip3: '属性关联必须选择两个属性',
|
attributeAssociationTip3: '属性关联必须选择两个属性',
|
||||||
attributeAssociationTip4: '请选择原模型属性',
|
attributeAssociationTip4: '请选择原模型属性',
|
||||||
attributeAssociationTip5: '请选择目标模型属性',
|
attributeAssociationTip5: '请选择目标模型属性',
|
||||||
show: '展示属性',
|
|
||||||
setAsShow: '设置为展示属性',
|
|
||||||
cancelSetAsShow: '取消设置为展示属性',
|
|
||||||
showTips: '服务树和拓扑视图里节点的名称'
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
unselectAttributes: '未选属性',
|
unselectAttributes: '未选属性',
|
||||||
@@ -533,8 +529,7 @@ if __name__ == "__main__":
|
|||||||
peopleHasRead: '当前有查看权限的人员:',
|
peopleHasRead: '当前有查看权限的人员:',
|
||||||
authorizationPolicy: '实例授权策略:',
|
authorizationPolicy: '实例授权策略:',
|
||||||
idAuthorizationPolicy: '按节点授权的:',
|
idAuthorizationPolicy: '按节点授权的:',
|
||||||
view: '查看权限',
|
view: '查看权限'
|
||||||
searchTips: '在服务树中筛选'
|
|
||||||
},
|
},
|
||||||
tree: {
|
tree: {
|
||||||
tips1: '请先到 我的订阅 页面完成订阅!',
|
tips1: '请先到 我的订阅 页面完成订阅!',
|
||||||
|
@@ -147,6 +147,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
@import '../index.less';
|
@import '../index.less';
|
||||||
.cmdb-batch-upload-label {
|
.cmdb-batch-upload-label {
|
||||||
color: @text-color_1;
|
color: @text-color_1;
|
||||||
@@ -158,6 +159,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-batch-upload {
|
.cmdb-batch-upload {
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
|
@@ -113,6 +113,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-batch-upload-table {
|
.cmdb-batch-upload-table {
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
@@ -83,6 +83,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-batch-upload-dragger {
|
.cmdb-batch-upload-dragger {
|
||||||
height: auto;
|
height: auto;
|
||||||
@@ -111,6 +112,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-batch-upload-dragger {
|
.cmdb-batch-upload-dragger {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@@ -101,6 +101,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.cmdb-batch-upload-result {
|
.cmdb-batch-upload-result {
|
||||||
.cmdb-batch-upload-result-content {
|
.cmdb-batch-upload-result-content {
|
||||||
|
@@ -55,6 +55,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.ci-detail-header {
|
.ci-detail-header {
|
||||||
border-left: 3px solid @primary-color;
|
border-left: 3px solid @primary-color;
|
||||||
|
@@ -992,6 +992,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.cmdb-ci {
|
.cmdb-ci {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
@@ -150,11 +150,11 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
topoData() {
|
topoData() {
|
||||||
const ci_types_list = this.ci_types()
|
const ci_types_list = this.ci_types()
|
||||||
const _findCiType = ci_types_list.find((item) => item.id === this.typeId)
|
const unique_id = this.attributes().unique_id
|
||||||
const unique_id = _findCiType.show_id || this.attributes().unique_id
|
const unique_name = this.attributes().unique
|
||||||
const unique_name = _findCiType.show_name || this.attributes().unique
|
|
||||||
const _findUnique = this.attrList().find((attr) => attr.id === unique_id)
|
const _findUnique = this.attrList().find((attr) => attr.id === unique_id)
|
||||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
||||||
|
const _findCiType = ci_types_list.find((item) => item.id === this.typeId)
|
||||||
const nodes = {
|
const nodes = {
|
||||||
isRoot: true,
|
isRoot: true,
|
||||||
id: `Root_${this.typeId}`,
|
id: `Root_${this.typeId}`,
|
||||||
@@ -183,10 +183,6 @@ export default {
|
|||||||
this.parentCITypes.forEach((parent) => {
|
this.parentCITypes.forEach((parent) => {
|
||||||
const _findCiType = ci_types_list.find((item) => item.id === parent.id)
|
const _findCiType = ci_types_list.find((item) => item.id === parent.id)
|
||||||
if (this.firstCIs[parent.name]) {
|
if (this.firstCIs[parent.name]) {
|
||||||
const unique_id = _findCiType.show_id || _findCiType.unique_id
|
|
||||||
const _findUnique = parent.attributes.find((attr) => attr.id === unique_id)
|
|
||||||
const unique_name = _findUnique?.name
|
|
||||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
|
||||||
this.firstCIs[parent.name].forEach((parentCi) => {
|
this.firstCIs[parent.name].forEach((parentCi) => {
|
||||||
nodes.children.push({
|
nodes.children.push({
|
||||||
id: `${parentCi._id}`,
|
id: `${parentCi._id}`,
|
||||||
@@ -194,9 +190,9 @@ export default {
|
|||||||
title: parent.alias || parent.name,
|
title: parent.alias || parent.name,
|
||||||
name: parent.name,
|
name: parent.name,
|
||||||
side: 'left',
|
side: 'left',
|
||||||
unique_alias,
|
unique_alias: parentCi.unique_alias,
|
||||||
unique_name,
|
unique_name: parentCi.unique,
|
||||||
unique_value: parentCi[unique_name],
|
unique_value: parentCi[parentCi.unique],
|
||||||
children: [],
|
children: [],
|
||||||
icon: _findCiType?.icon || '',
|
icon: _findCiType?.icon || '',
|
||||||
endpoints: [
|
endpoints: [
|
||||||
@@ -226,10 +222,6 @@ export default {
|
|||||||
this.childCITypes.forEach((child) => {
|
this.childCITypes.forEach((child) => {
|
||||||
const _findCiType = ci_types_list.find((item) => item.id === child.id)
|
const _findCiType = ci_types_list.find((item) => item.id === child.id)
|
||||||
if (this.secondCIs[child.name]) {
|
if (this.secondCIs[child.name]) {
|
||||||
const unique_id = _findCiType.show_id || _findCiType.unique_id
|
|
||||||
const _findUnique = child.attributes.find((attr) => attr.id === unique_id)
|
|
||||||
const unique_name = _findUnique?.name
|
|
||||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
|
||||||
this.secondCIs[child.name].forEach((childCi) => {
|
this.secondCIs[child.name].forEach((childCi) => {
|
||||||
nodes.children.push({
|
nodes.children.push({
|
||||||
id: `${childCi._id}`,
|
id: `${childCi._id}`,
|
||||||
@@ -237,9 +229,9 @@ export default {
|
|||||||
title: child.alias || child.name,
|
title: child.alias || child.name,
|
||||||
name: child.name,
|
name: child.name,
|
||||||
side: 'right',
|
side: 'right',
|
||||||
unique_alias,
|
unique_alias: childCi.unique_alias,
|
||||||
unique_name,
|
unique_name: childCi.unique,
|
||||||
unique_value: childCi[unique_name],
|
unique_value: childCi[childCi.unique],
|
||||||
children: [],
|
children: [],
|
||||||
icon: _findCiType?.icon || '',
|
icon: _findCiType?.icon || '',
|
||||||
endpoints: [
|
endpoints: [
|
||||||
@@ -268,24 +260,6 @@ export default {
|
|||||||
})
|
})
|
||||||
return { nodes, edges }
|
return { nodes, edges }
|
||||||
},
|
},
|
||||||
exsited_ci() {
|
|
||||||
const _exsited_ci = [this.typeId]
|
|
||||||
this.parentCITypes.forEach((parent) => {
|
|
||||||
if (this.firstCIs[parent.name]) {
|
|
||||||
this.firstCIs[parent.name].forEach((parentCi) => {
|
|
||||||
_exsited_ci.push(parentCi._id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.childCITypes.forEach((child) => {
|
|
||||||
if (this.secondCIs[child.name]) {
|
|
||||||
this.secondCIs[child.name].forEach((childCi) => {
|
|
||||||
_exsited_ci.push(childCi._id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return _exsited_ci
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
inject: {
|
inject: {
|
||||||
attrList: { from: 'attrList' },
|
attrList: { from: 'attrList' },
|
||||||
@@ -304,7 +278,6 @@ export default {
|
|||||||
await Promise.all([this.getParentCITypes(), this.getChildCITypes()])
|
await Promise.all([this.getParentCITypes(), this.getChildCITypes()])
|
||||||
Promise.all([this.getFirstCIs(), this.getSecondCIs()]).then(() => {
|
Promise.all([this.getFirstCIs(), this.getSecondCIs()]).then(() => {
|
||||||
if (isFirst && this.$refs.ciDetailRelationTopo) {
|
if (isFirst && this.$refs.ciDetailRelationTopo) {
|
||||||
this.$refs.ciDetailRelationTopo.exsited_ci = this.exsited_ci
|
|
||||||
this.$refs.ciDetailRelationTopo.setTopoData(this.topoData)
|
this.$refs.ciDetailRelationTopo.setTopoData(this.topoData)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -341,6 +314,7 @@ export default {
|
|||||||
secondCIs[item.ci_type] = [item]
|
secondCIs[item.ci_type] = [item]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
console.log(_.cloneDeep(secondCIs))
|
||||||
this.secondCIs = secondCIs
|
this.secondCIs = secondCIs
|
||||||
})
|
})
|
||||||
.catch((e) => {})
|
.catch((e) => {})
|
||||||
@@ -440,7 +414,6 @@ export default {
|
|||||||
handleChangeActiveKey(e) {
|
handleChangeActiveKey(e) {
|
||||||
if (e.target.value === '1') {
|
if (e.target.value === '1') {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.ciDetailRelationTopo.exsited_ci = this.exsited_ci
|
|
||||||
this.$refs.ciDetailRelationTopo.setTopoData(this.topoData)
|
this.$refs.ciDetailRelationTopo.setTopoData(this.topoData)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
border-radius: 2px;
|
border-radius: 10px;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -74,11 +74,13 @@
|
|||||||
}
|
}
|
||||||
.root {
|
.root {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
border-color: @primary-color;
|
background: #2f54eb;
|
||||||
font-weight: 700;
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: 500;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
.title {
|
.title {
|
||||||
color: @primary-color;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { TreeCanvas } from 'butterfly-dag'
|
import { TreeCanvas } from 'butterfly-dag'
|
||||||
import { searchCIRelation } from '@/modules/cmdb/api/CIRelation'
|
import { searchCIRelation } from '@/modules/cmdb/api/CIRelation'
|
||||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
|
||||||
import Node from './node.js'
|
import Node from './node.js'
|
||||||
|
|
||||||
import 'butterfly-dag/dist/index.css'
|
import 'butterfly-dag/dist/index.css'
|
||||||
@@ -88,7 +87,7 @@ export default {
|
|||||||
this.canvas.focusCenterWithAnimate()
|
this.canvas.focusCenterWithAnimate()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async redrawData(res, sourceNode, side) {
|
redrawData(res, sourceNode, side) {
|
||||||
const newNodes = []
|
const newNodes = []
|
||||||
const newEdges = []
|
const newEdges = []
|
||||||
if (!res.result.length) {
|
if (!res.result.length) {
|
||||||
@@ -96,24 +95,18 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const ci_types_list = this.ci_types()
|
const ci_types_list = this.ci_types()
|
||||||
for (let i = 0; i < res.result.length; i++) {
|
res.result.forEach((r) => {
|
||||||
const r = res.result[i]
|
|
||||||
if (!this.exsited_ci.includes(r._id)) {
|
if (!this.exsited_ci.includes(r._id)) {
|
||||||
const _findCiType = ci_types_list.find((item) => item.id === r._type)
|
const _findCiType = ci_types_list.find((item) => item.id === r._type)
|
||||||
const { attributes } = await getCITypeAttributesById(_findCiType.id)
|
|
||||||
const unique_id = _findCiType.show_id || _findCiType.unique_id
|
|
||||||
const _findUnique = attributes.find((attr) => attr.id === unique_id)
|
|
||||||
const unique_name = _findUnique?.name
|
|
||||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
|
||||||
newNodes.push({
|
newNodes.push({
|
||||||
id: `${r._id}`,
|
id: `${r._id}`,
|
||||||
Class: Node,
|
Class: Node,
|
||||||
title: r.ci_type_alias || r.ci_type,
|
title: r.ci_type_alias || r.ci_type,
|
||||||
name: r.ci_type,
|
name: r.ci_type,
|
||||||
side: side,
|
side: side,
|
||||||
unique_alias,
|
unique_alias: r.unique_alias,
|
||||||
unique_name,
|
unique_name: r.unique,
|
||||||
unique_value: r[unique_name],
|
unique_value: r[r.unique],
|
||||||
children: [],
|
children: [],
|
||||||
icon: _findCiType?.icon || '',
|
icon: _findCiType?.icon || '',
|
||||||
endpoints: [
|
endpoints: [
|
||||||
@@ -138,8 +131,7 @@ export default {
|
|||||||
targetNode: side === 'right' ? `${r._id}` : sourceNode,
|
targetNode: side === 'right' ? `${r._id}` : sourceNode,
|
||||||
type: 'endpoint',
|
type: 'endpoint',
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
|
||||||
const { nodes, edges } = this.canvas.getDataMap()
|
const { nodes, edges } = this.canvas.getDataMap()
|
||||||
// 删除原节点和边
|
// 删除原节点和边
|
||||||
this.canvas.removeNodes(nodes.map((node) => node.id))
|
this.canvas.removeNodes(nodes.map((node) => node.id))
|
||||||
|
@@ -204,6 +204,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
.attr-ad {
|
.attr-ad {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
:class="{ 'attribute-card': true, 'attribute-card-add': isAdd, 'attribute-card-inherited': inherited }"
|
:class="{ 'attribute-card': true, 'attribute-card-add': isAdd, 'attribute-card-inherited': inherited }"
|
||||||
>
|
>
|
||||||
<div class="attribute-card-uniqueKey" v-if="isUnique">{{ $t('cmdb.ciType.uniqueKey') }}</div>
|
<div class="attribute-card-uniqueKey" v-if="isUnique">{{ $t('cmdb.ciType.uniqueKey') }}</div>
|
||||||
<div class="attribute-card-uniqueKey" v-if="isShowId">{{ $t('cmdb.ciType.show') }}</div>
|
|
||||||
<template v-if="!isAdd">
|
<template v-if="!isAdd">
|
||||||
<a-tooltip :title="inherited ? $t('cmdb.ciType.inheritFrom', { name: property.inherited_from }) : ''">
|
<a-tooltip :title="inherited ? $t('cmdb.ciType.inheritFrom', { name: property.inherited_from }) : ''">
|
||||||
<div class="attribute-card-content">
|
<div class="attribute-card-content">
|
||||||
@@ -28,7 +27,6 @@
|
|||||||
<div
|
<div
|
||||||
class="attribute-card-trigger"
|
class="attribute-card-trigger"
|
||||||
v-if="(property.value_type === '3' || property.value_type === '4') && !isStore"
|
v-if="(property.value_type === '3' || property.value_type === '4') && !isStore"
|
||||||
:style="{ top: isShowId ? '18px' : '' }"
|
|
||||||
>
|
>
|
||||||
<a @click="openTrigger"><ops-icon type="ops-trigger"/></a>
|
<a @click="openTrigger"><ops-icon type="ops-trigger"/></a>
|
||||||
</div>
|
</div>
|
||||||
@@ -66,24 +64,12 @@
|
|||||||
</a-space>
|
</a-space>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
|
|
||||||
<a-space class="attribute-card-operation">
|
<a-space class="attribute-card-operation" v-if="!inherited">
|
||||||
<a v-if="!isStore && !inherited"><a-icon type="edit" @click="handleEdit"/></a>
|
<a v-if="!isStore"><a-icon type="edit" @click="handleEdit"/></a>
|
||||||
<a-tooltip
|
<a-tooltip :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||||
v-if="
|
<a v-if="!isStore && property.is_computed"><a-icon type="redo" @click="handleCalcComputed"/></a>
|
||||||
!isStore &&
|
|
||||||
!isUnique &&
|
|
||||||
!['6'].includes(property.value_type) &&
|
|
||||||
!property.is_password &&
|
|
||||||
!property.is_list
|
|
||||||
"
|
|
||||||
:title="$t(isShowId ? 'cmdb.ciType.cancelSetAsShow' : 'cmdb.ciType.setAsShow')"
|
|
||||||
>
|
|
||||||
<a><ops-icon type="veops-show" @click="setAsShow"/></a>
|
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip v-if="!isStore && property.is_computed" :title="$t('cmdb.ciType.computeForAllCITips')">
|
<a v-if="!isUnique" style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
||||||
<a><a-icon type="redo" @click="handleCalcComputed"/></a>
|
|
||||||
</a-tooltip>
|
|
||||||
<a v-if="!isUnique && !inherited" style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
||||||
@@ -98,9 +84,17 @@
|
|||||||
<script>
|
<script>
|
||||||
import { deleteCITypeAttributesById, deleteAttributesById, calcComputedAttribute } from '@/modules/cmdb/api/CITypeAttr'
|
import { deleteCITypeAttributesById, deleteAttributesById, calcComputedAttribute } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
import ValueTypeIcon from '@/components/CMDBValueTypeMapIcon'
|
import ValueTypeIcon from '@/components/CMDBValueTypeMapIcon'
|
||||||
|
import {
|
||||||
|
ops_default_show,
|
||||||
|
ops_is_choice,
|
||||||
|
ops_is_index,
|
||||||
|
ops_is_link,
|
||||||
|
ops_is_password,
|
||||||
|
ops_is_sortable,
|
||||||
|
ops_is_unique,
|
||||||
|
} from '@/core/icons'
|
||||||
import { valueTypeMap } from '../../utils/const'
|
import { valueTypeMap } from '../../utils/const'
|
||||||
import TriggerForm from './triggerForm.vue'
|
import TriggerForm from './triggerForm.vue'
|
||||||
import { updateCIType } from '@/modules/cmdb/api/CIType'
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AttributeCard',
|
name: 'AttributeCard',
|
||||||
inject: {
|
inject: {
|
||||||
@@ -108,14 +102,17 @@ export default {
|
|||||||
from: 'unique',
|
from: 'unique',
|
||||||
default: () => undefined,
|
default: () => undefined,
|
||||||
},
|
},
|
||||||
show_id: {
|
|
||||||
from: 'show_id',
|
|
||||||
default: () => undefined,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
ValueTypeIcon,
|
ValueTypeIcon,
|
||||||
TriggerForm,
|
TriggerForm,
|
||||||
|
ops_default_show,
|
||||||
|
ops_is_choice,
|
||||||
|
ops_is_index,
|
||||||
|
ops_is_link,
|
||||||
|
ops_is_password,
|
||||||
|
ops_is_sortable,
|
||||||
|
ops_is_unique,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
property: {
|
property: {
|
||||||
@@ -149,12 +146,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
isShowId() {
|
|
||||||
if (this.show_id) {
|
|
||||||
return this.property?.id === this.show_id()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
valueTypeMap() {
|
valueTypeMap() {
|
||||||
return valueTypeMap()
|
return valueTypeMap()
|
||||||
},
|
},
|
||||||
@@ -226,16 +217,12 @@ export default {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setAsShow() {
|
|
||||||
updateCIType(this.CITypeId, { show_id: this.isShowId ? null : this.property?.id }).then((res) => {
|
|
||||||
this.$emit('ok')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.attribute-card {
|
.attribute-card {
|
||||||
width: 182px;
|
width: 182px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
@@ -164,6 +164,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.attrbute-store-search {
|
.attrbute-store-search {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
|
@@ -186,7 +186,6 @@ import {
|
|||||||
createCITypeGroupById,
|
createCITypeGroupById,
|
||||||
updateCITypeGroupById,
|
updateCITypeGroupById,
|
||||||
getTriggerList,
|
getTriggerList,
|
||||||
getCIType,
|
|
||||||
} from '@/modules/cmdb/api/CIType'
|
} from '@/modules/cmdb/api/CIType'
|
||||||
import {
|
import {
|
||||||
getCITypeAttributesById,
|
getCITypeAttributesById,
|
||||||
@@ -232,7 +231,6 @@ export default {
|
|||||||
newGroupName: '',
|
newGroupName: '',
|
||||||
attrTypeFilter: [],
|
attrTypeFilter: [],
|
||||||
unique: '',
|
unique: '',
|
||||||
show_id: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -252,31 +250,20 @@ export default {
|
|||||||
unique: () => {
|
unique: () => {
|
||||||
return this.unique
|
return this.unique
|
||||||
},
|
},
|
||||||
show_id: () => {
|
|
||||||
return this.show_id
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeCreate() {},
|
beforeCreate() {},
|
||||||
created() {},
|
created() {},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init()
|
this.getCITypeGroupData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getPropertyIcon,
|
getPropertyIcon,
|
||||||
init() {
|
|
||||||
getCIType(this.CITypeId).then((res) => {
|
|
||||||
if (res?.ci_types && res.ci_types.length) {
|
|
||||||
this.show_id = res.ci_types[0]?.show_id ?? null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.getCITypeGroupData()
|
|
||||||
},
|
|
||||||
handleEditProperty(property) {
|
handleEditProperty(property) {
|
||||||
this.$refs.attributeEditForm.handleEdit(property, this.attributes)
|
this.$refs.attributeEditForm.handleEdit(property, this.attributes)
|
||||||
},
|
},
|
||||||
handleOk() {
|
handleOk() {
|
||||||
this.init()
|
this.getCITypeGroupData()
|
||||||
},
|
},
|
||||||
setOtherGroupAttributes() {
|
setOtherGroupAttributes() {
|
||||||
const orderMap = this.attributes.reduce(function(map, obj) {
|
const orderMap = this.attributes.reduce(function(map, obj) {
|
||||||
@@ -604,6 +591,8 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.fold {
|
.fold {
|
||||||
width: calc(100% - 216px);
|
width: calc(100% - 216px);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@@ -77,6 +77,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.citype-detail-title {
|
.citype-detail-title {
|
||||||
border-left: 4px solid @primary-color;
|
border-left: 4px solid @primary-color;
|
||||||
|
@@ -53,10 +53,11 @@
|
|||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="1">
|
<a-menu-item key="1">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a href="/api/v0.1/ci_types/template/export/file">
|
<a
|
||||||
<a-icon type="download" /> {{ $t('download') }}
|
href="/api/v0.1/ci_types/template/export/file"
|
||||||
</a></a-space
|
><a-icon type="download" /> {{ $t('download') }}</a
|
||||||
>
|
>
|
||||||
|
</a-space>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</a-dropdown>
|
</a-dropdown>
|
||||||
@@ -261,7 +262,6 @@
|
|||||||
'default_order_attr',
|
'default_order_attr',
|
||||||
{ rules: [{ required: false, message: $t('cmdb.ciType.selectDefaultOrderAttr') }] },
|
{ rules: [{ required: false, message: $t('cmdb.ciType.selectDefaultOrderAttr') }] },
|
||||||
]"
|
]"
|
||||||
:placeholder="$t('placeholder2')"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
:key="item.name"
|
:key="item.name"
|
||||||
@@ -299,7 +299,6 @@
|
|||||||
filterInput = ''
|
filterInput = ''
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@change="handleChangeUnique"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -314,40 +313,6 @@
|
|||||||
<a-divider type="vertical" />
|
<a-divider type="vertical" />
|
||||||
<a @click="handleCreatNewAttr">{{ $t('cmdb.ciType.notfound') }}</a>
|
<a @click="handleCreatNewAttr">{{ $t('cmdb.ciType.notfound') }}</a>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
|
||||||
:help="$t('cmdb.ciType.showTips')"
|
|
||||||
:label="$t('cmdb.ciType.show')"
|
|
||||||
v-if="drawerTitle === $t('cmdb.ciType.editCIType')"
|
|
||||||
>
|
|
||||||
<el-select
|
|
||||||
size="small"
|
|
||||||
filterable
|
|
||||||
clearable
|
|
||||||
name="show_id"
|
|
||||||
:filter-method="
|
|
||||||
(input) => {
|
|
||||||
showIdFilterInput = input
|
|
||||||
}
|
|
||||||
"
|
|
||||||
v-decorator="['show_id', { rules: [{ required: false }] }]"
|
|
||||||
:placeholder="$t('placeholder2')"
|
|
||||||
@visible-change="
|
|
||||||
() => {
|
|
||||||
showIdFilterInput = ''
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.id"
|
|
||||||
v-for="item in showIdSelectOptions"
|
|
||||||
:label="item.alias || item.name"
|
|
||||||
>
|
|
||||||
<span> {{ item.alias || item.name }}</span>
|
|
||||||
<span :title="item.name" style="font-size: 10px; color: #afafaf"> {{ item.name }}</span>
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</a-form-item>
|
|
||||||
<div v-if="newAttrAreaVisible" :style="{ padding: '15px 8px 0 8px', backgroundColor: '#fafafa' }">
|
<div v-if="newAttrAreaVisible" :style="{ padding: '15px 8px 0 8px', backgroundColor: '#fafafa' }">
|
||||||
<create-new-attribute
|
<create-new-attribute
|
||||||
ref="createNewAttribute"
|
ref="createNewAttribute"
|
||||||
@@ -453,17 +418,14 @@ export default {
|
|||||||
addId: null,
|
addId: null,
|
||||||
|
|
||||||
filterInput: '',
|
filterInput: '',
|
||||||
showIdFilterInput: '',
|
|
||||||
|
|
||||||
currentTypeAttrs: [],
|
orderSelectionOptions: [],
|
||||||
default_order_asc: '1',
|
default_order_asc: '1',
|
||||||
|
|
||||||
allTreeDepAndEmp: [],
|
allTreeDepAndEmp: [],
|
||||||
|
|
||||||
editCiType: null,
|
editCiType: null,
|
||||||
isInherit: false,
|
isInherit: false,
|
||||||
|
|
||||||
unique_id: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -520,22 +482,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return _attributes
|
return _attributes
|
||||||
},
|
},
|
||||||
orderSelectionOptions() {
|
|
||||||
return this.currentTypeAttrs.filter((item) => item.is_required)
|
|
||||||
},
|
|
||||||
showIdSelectOptions() {
|
|
||||||
const _showIdSelectOptions = this.currentTypeAttrs.filter(
|
|
||||||
(item) => item.id !== this.unique_id && !['6'].includes(item.value_type) && !item.is_password && !item.is_list
|
|
||||||
)
|
|
||||||
if (this.showIdFilterInput) {
|
|
||||||
return _showIdSelectOptions.filter(
|
|
||||||
(item) =>
|
|
||||||
item.name.toLowerCase().includes(this.showIdFilterInput.toLowerCase()) ||
|
|
||||||
item.alias.toLowerCase().includes(this.showIdFilterInput.toLowerCase())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return _showIdSelectOptions
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
@@ -713,7 +659,6 @@ export default {
|
|||||||
delete values.parent_ids
|
delete values.parent_ids
|
||||||
await this.updateCIType(values.id, {
|
await this.updateCIType(values.id, {
|
||||||
...values,
|
...values,
|
||||||
show_id: values.show_id || null,
|
|
||||||
icon,
|
icon,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -919,8 +864,7 @@ export default {
|
|||||||
this.drawerTitle = this.$t('cmdb.ciType.editCIType')
|
this.drawerTitle = this.$t('cmdb.ciType.editCIType')
|
||||||
this.drawerVisible = true
|
this.drawerVisible = true
|
||||||
await getCITypeAttributesById(record.id).then((res) => {
|
await getCITypeAttributesById(record.id).then((res) => {
|
||||||
this.currentTypeAttrs = res.attributes
|
this.orderSelectionOptions = res.attributes.filter((item) => item.is_required)
|
||||||
this.unique_id = res.unique_id
|
|
||||||
})
|
})
|
||||||
await getCIType(record.id).then((res) => {
|
await getCIType(record.id).then((res) => {
|
||||||
const ci_type = res.ci_types[0]
|
const ci_type = res.ci_types[0]
|
||||||
@@ -933,9 +877,6 @@ export default {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.form.setFieldsValue({
|
|
||||||
show_id: ci_type.show_id ?? null,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.default_order_asc = record.default_order_attr && record.default_order_attr.startsWith('-') ? '2' : '1'
|
this.default_order_asc = record.default_order_attr && record.default_order_attr.startsWith('-') ? '2' : '1'
|
||||||
@@ -1000,18 +941,13 @@ export default {
|
|||||||
this.$message.error({ content: this.$t('cmdb.ciType.uploadFailed'), key, duration: 2 })
|
this.$message.error({ content: this.$t('cmdb.ciType.uploadFailed'), key, duration: 2 })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleChangeUnique(value) {
|
|
||||||
this.unique_id = value
|
|
||||||
const show_id = this.form.getFieldValue('show_id')
|
|
||||||
if (show_id === value) {
|
|
||||||
this.form.setFieldsValue({ show_id: '' })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.ci-types-wrap {
|
.ci-types-wrap {
|
||||||
margin: 0 0 -24px 0;
|
margin: 0 0 -24px 0;
|
||||||
.ci-types-empty {
|
.ci-types-empty {
|
||||||
|
@@ -634,6 +634,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.auto-complete-wrapper {
|
.auto-complete-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@@ -142,6 +142,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.setting-discovery {
|
.setting-discovery {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
@@ -313,6 +313,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.cmdb-adc {
|
.cmdb-adc {
|
||||||
.cmdb-adc-group {
|
.cmdb-adc-group {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
@@ -308,6 +308,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.model-relation {
|
.model-relation {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
@@ -393,6 +393,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.cmdb-preference {
|
.cmdb-preference {
|
||||||
margin: -24px;
|
margin: -24px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
@@ -11,14 +11,6 @@
|
|||||||
<template #one>
|
<template #one>
|
||||||
<div class="relation-views-left" :style="{ height: `${windowHeight - 115}px` }">
|
<div class="relation-views-left" :style="{ height: `${windowHeight - 115}px` }">
|
||||||
<div class="relation-views-left-header" :title="$route.meta.name">{{ $route.meta.name }}</div>
|
<div class="relation-views-left-header" :title="$route.meta.name">{{ $route.meta.name }}</div>
|
||||||
<a-input
|
|
||||||
:placeholder="$t('cmdb.serviceTree.searchTips')"
|
|
||||||
class="relation-views-left-input"
|
|
||||||
@pressEnter="handleSearchFull"
|
|
||||||
v-model="fullSearchValue"
|
|
||||||
>
|
|
||||||
<a-icon slot="prefix" type="search" />
|
|
||||||
</a-input>
|
|
||||||
<div
|
<div
|
||||||
class="ops-list-batch-action"
|
class="ops-list-batch-action"
|
||||||
:style="{ marginBottom: '10px' }"
|
:style="{ marginBottom: '10px' }"
|
||||||
@@ -55,7 +47,6 @@
|
|||||||
<span>{{ $t('selectRows', { rows: batchTreeKey.length }) }}</span>
|
<span>{{ $t('selectRows', { rows: batchTreeKey.length }) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<a-tree
|
<a-tree
|
||||||
v-if="!isFullSearch"
|
|
||||||
:selectedKeys="selectedKeys"
|
:selectedKeys="selectedKeys"
|
||||||
:loadData="onLoadData"
|
:loadData="onLoadData"
|
||||||
:treeData="treeData"
|
:treeData="treeData"
|
||||||
@@ -64,10 +55,13 @@
|
|||||||
@drop="onDrop"
|
@drop="onDrop"
|
||||||
:expandedKeys="expandedKeys"
|
:expandedKeys="expandedKeys"
|
||||||
>
|
>
|
||||||
<template #title="treeNodeData">
|
<template #title="{ key: treeKey, title,number, isLeaf }">
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
:treeNodeData="treeNodeData"
|
:title="title"
|
||||||
|
:number="number"
|
||||||
|
:treeKey="treeKey"
|
||||||
:levels="levels"
|
:levels="levels"
|
||||||
|
:isLeaf="isLeaf"
|
||||||
:currentViews="relationViews.views[viewName]"
|
:currentViews="relationViews.views[viewName]"
|
||||||
:id2type="relationViews.id2type"
|
:id2type="relationViews.id2type"
|
||||||
@onContextMenuClick="onContextMenuClick"
|
@onContextMenuClick="onContextMenuClick"
|
||||||
@@ -80,30 +74,6 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</a-tree>
|
</a-tree>
|
||||||
<a-tree
|
|
||||||
v-else
|
|
||||||
:treeData="filterFullTreeData"
|
|
||||||
defaultExpandAll
|
|
||||||
:selectedKeys="selectedKeys"
|
|
||||||
:expandedKeys="expandedKeys"
|
|
||||||
>
|
|
||||||
<template #title="treeNodeData">
|
|
||||||
<ContextMenu
|
|
||||||
:treeNodeData="treeNodeData"
|
|
||||||
:levels="levels"
|
|
||||||
:currentViews="relationViews.views[viewName]"
|
|
||||||
:id2type="relationViews.id2type"
|
|
||||||
@onContextMenuClick="onContextMenuClick"
|
|
||||||
@onNodeClick="onNodeClick"
|
|
||||||
:ciTypeIcons="ciTypeIcons"
|
|
||||||
:showBatchLevel="showBatchLevel"
|
|
||||||
:batchTreeKey="batchTreeKey"
|
|
||||||
@clickCheckbox="clickCheckbox"
|
|
||||||
@updateTreeData="updateTreeData"
|
|
||||||
:fullSearchValue="fullSearchValue"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</a-tree>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #two>
|
<template #two>
|
||||||
@@ -372,6 +342,7 @@
|
|||||||
total,
|
total,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
|
:style="{ alignSelf: 'flex-end', marginRight: '12px' }"
|
||||||
>
|
>
|
||||||
<template slot="buildOptionText" slot-scope="props">
|
<template slot="buildOptionText" slot-scope="props">
|
||||||
<span v-if="props.value !== '100000'">{{ props.value }}{{ $t('cmdb.history.itemsPerPage') }}</span>
|
<span v-if="props.value !== '100000'">{{ props.value }}{{ $t('cmdb.history.itemsPerPage') }}</span>
|
||||||
@@ -421,7 +392,6 @@ import {
|
|||||||
batchDeleteCIRelation,
|
batchDeleteCIRelation,
|
||||||
batchUpdateCIRelationChildren,
|
batchUpdateCIRelationChildren,
|
||||||
addCIRelationView,
|
addCIRelationView,
|
||||||
searchCIRelationFull,
|
|
||||||
} from '@/modules/cmdb/api/CIRelation'
|
} from '@/modules/cmdb/api/CIRelation'
|
||||||
|
|
||||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||||
@@ -519,13 +489,9 @@ export default {
|
|||||||
|
|
||||||
statisticsObj: {},
|
statisticsObj: {},
|
||||||
viewOption: {},
|
viewOption: {},
|
||||||
loadRootStatisticsParams: {},
|
|
||||||
fullSearchValue: '',
|
|
||||||
isFullSearch: false,
|
|
||||||
fullTreeData: [],
|
|
||||||
filterFullTreeData: [],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
windowHeight() {
|
windowHeight() {
|
||||||
return this.$store.state.windowHeight
|
return this.$store.state.windowHeight
|
||||||
@@ -534,6 +500,9 @@ export default {
|
|||||||
return this.windowHeight - 244
|
return this.windowHeight - 244
|
||||||
},
|
},
|
||||||
selectedKeys() {
|
selectedKeys() {
|
||||||
|
if (this.treeKeys.length <= 1) {
|
||||||
|
return this.treeKeys.map((item) => `@^@${item}`)
|
||||||
|
}
|
||||||
return [this.treeKeys.join('@^@')]
|
return [this.treeKeys.join('@^@')]
|
||||||
},
|
},
|
||||||
isLeaf() {
|
isLeaf() {
|
||||||
@@ -607,7 +576,7 @@ export default {
|
|||||||
this.reload()
|
this.reload()
|
||||||
},
|
},
|
||||||
pageNo: function(newPage, oldPage) {
|
pageNo: function(newPage, oldPage) {
|
||||||
this.loadData({ params: { pageNo: newPage }, refreshType: undefined, sortByTable: this.sortByTable })
|
this.loadData({ pageNo: newPage }, undefined, this.sortByTable)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -635,7 +604,7 @@ export default {
|
|||||||
this.loadData()
|
this.loadData()
|
||||||
},
|
},
|
||||||
|
|
||||||
async loadData({ parameter, refreshType = undefined, sortByTable = undefined } = {}) {
|
async loadData(parameter, refreshType = undefined, sortByTable = undefined) {
|
||||||
// refreshType='refreshNumber' 树图只更新number
|
// refreshType='refreshNumber' 树图只更新number
|
||||||
const params = Object.assign(parameter || {}, (this.$refs.search || {}).queryParam)
|
const params = Object.assign(parameter || {}, (this.$refs.search || {}).queryParam)
|
||||||
let q = ''
|
let q = ''
|
||||||
@@ -655,6 +624,8 @@ export default {
|
|||||||
|
|
||||||
const exp = expression.match(regQ) ? expression.match(regQ)[0] : null
|
const exp = expression.match(regQ) ? expression.match(regQ)[0] : null
|
||||||
if (exp) {
|
if (exp) {
|
||||||
|
// exp = exp.replace(/(\:)/g, '$1*')
|
||||||
|
// exp = exp.replace(/(\,)/g, '*$1')
|
||||||
q = `${q},${exp}`
|
q = `${q},${exp}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,9 +656,38 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.treeKeys.length === 0) {
|
if (this.treeKeys.length === 0) {
|
||||||
if (!refreshType && !this.isFullSearch) {
|
// await this.judgeCITypes(q)
|
||||||
|
if (!refreshType) {
|
||||||
await this.loadRoot()
|
await this.loadRoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const fuzzySearch = (this.$refs['search'] || {}).fuzzySearch || ''
|
||||||
|
// if (fuzzySearch) {
|
||||||
|
// q = `q=_type:${this.currentTypeId[0]},*${fuzzySearch}*,` + q
|
||||||
|
// } else {
|
||||||
|
// q = `q=_type:${this.currentTypeId[0]},` + q
|
||||||
|
// }
|
||||||
|
// if (this.currentTypeId[0] && this.treeData && this.treeData.length) {
|
||||||
|
// // default select first node
|
||||||
|
// this.onNodeClick(this.treeData[0].key)
|
||||||
|
// const res = await searchCI2(q)
|
||||||
|
// const root_id = this.treeData.map((item) => item.id).join(',')
|
||||||
|
// q += `&root_id=${root_id}`
|
||||||
|
|
||||||
|
// this.pageNo = res.page
|
||||||
|
// this.numfound = res.numfound
|
||||||
|
// res.result.forEach((item, index) => (item.key = item._id))
|
||||||
|
// const jsonAttrList = this.preferenceAttrList.filter((attr) => attr.value_type === '6')
|
||||||
|
// console.log(jsonAttrList)
|
||||||
|
// this.instanceList = res['result'].map((item) => {
|
||||||
|
// jsonAttrList.forEach(
|
||||||
|
// (jsonAttr) => (item[jsonAttr.name] = item[jsonAttr.name] ? JSON.stringify(item[jsonAttr.name]) : '')
|
||||||
|
// )
|
||||||
|
// return { ..._.cloneDeep(item) }
|
||||||
|
// })
|
||||||
|
// this.initialInstanceList = _.cloneDeep(this.instanceList)
|
||||||
|
// this.calcColumns()
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
q += `&root_id=${this.treeKeys[this.treeKeys.length - 1].split('%')[0]}`
|
q += `&root_id=${this.treeKeys[this.treeKeys.length - 1].split('%')[0]}`
|
||||||
|
|
||||||
@@ -726,7 +726,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
q += `&level=${this.topo_flatten.includes(this.currentTypeId[0]) ? 1 : level.join(',')}`
|
q += `&level=${this.topo_flatten.includes(this.currentTypeId[0]) ? 1 : level.join(',')}`
|
||||||
if (!refreshType && !this.isFullSearch) {
|
if (!refreshType) {
|
||||||
this.loadNoRoot(this.treeKeys[this.treeKeys.length - 1], level)
|
this.loadNoRoot(this.treeKeys[this.treeKeys.length - 1], level)
|
||||||
}
|
}
|
||||||
const fuzzySearch = (this.$refs['search'] || {}).fuzzySearch || ''
|
const fuzzySearch = (this.$refs['search'] || {}).fuzzySearch || ''
|
||||||
@@ -812,6 +812,9 @@ export default {
|
|||||||
this.selectedRowKeys = []
|
this.selectedRowKeys = []
|
||||||
this.currentTypeId = [typeId]
|
this.currentTypeId = [typeId]
|
||||||
this.loadColumns()
|
this.loadColumns()
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.refreshTable()
|
||||||
|
// })
|
||||||
},
|
},
|
||||||
|
|
||||||
async judgeCITypes() {
|
async judgeCITypes() {
|
||||||
@@ -851,6 +854,64 @@ export default {
|
|||||||
this.currentTypeId = [this.showTypeIds[0]]
|
this.currentTypeId = [this.showTypeIds[0]]
|
||||||
await this.loadColumns()
|
await this.loadColumns()
|
||||||
}
|
}
|
||||||
|
// const showTypeIds = []
|
||||||
|
// let _showTypes = []
|
||||||
|
// let _showTypeIds = []
|
||||||
|
|
||||||
|
// if (this.treeKeys.length) {
|
||||||
|
// const typeId = parseInt(this.treeKeys[this.treeKeys.length - 1].split('%')[1])
|
||||||
|
|
||||||
|
// _showTypes = this.node2ShowTypes[typeId + '']
|
||||||
|
// _showTypes.forEach((item) => {
|
||||||
|
// _showTypeIds.push(item.id)
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// _showTypeIds = JSON.parse(JSON.stringify(this.origShowTypeIds))
|
||||||
|
// _showTypes = JSON.parse(JSON.stringify(this.origShowTypes))
|
||||||
|
// }
|
||||||
|
// const promises = _showTypeIds.map((typeId) => {
|
||||||
|
// let _q = (`q=_type:${typeId},` + q).replace(/count=\d*/, 'count=1')
|
||||||
|
// if (Object.values(this.level2constraint).includes('2')) {
|
||||||
|
// _q = _q + `&has_m2m=1`
|
||||||
|
// }
|
||||||
|
// if (this.root_parent_path) {
|
||||||
|
// _q = _q + `&root_parent_path=${this.root_parent_path}`
|
||||||
|
// }
|
||||||
|
// // if (this.treeKeys.length === 0) {
|
||||||
|
// // return searchCI2(_q).then((res) => {
|
||||||
|
// // if (res.numfound !== 0) {
|
||||||
|
// // showTypeIds.push(typeId)
|
||||||
|
// // }
|
||||||
|
// // })
|
||||||
|
// // } else {
|
||||||
|
// _q = _q + `&descendant_ids=${this.descendant_ids}`
|
||||||
|
// return searchCIRelation(_q).then((res) => {
|
||||||
|
// if (res.numfound !== 0) {
|
||||||
|
// showTypeIds.push(typeId)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// // }
|
||||||
|
// })
|
||||||
|
// await Promise.all(promises).then(async () => {
|
||||||
|
// if (showTypeIds.length && showTypeIds.sort().join(',') !== this.showTypeIds.sort().join(',')) {
|
||||||
|
// const showTypes = []
|
||||||
|
// _showTypes.forEach((item) => {
|
||||||
|
// if (showTypeIds.includes(item.id)) {
|
||||||
|
// showTypes.push(item)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// console.log(showTypes)
|
||||||
|
// this.showTypes = showTypes
|
||||||
|
// this.showTypeIds = showTypeIds
|
||||||
|
// if (
|
||||||
|
// !this.currentTypeId.length ||
|
||||||
|
// (this.currentTypeId.length && !this.showTypeIds.includes(this.currentTypeId[0]))
|
||||||
|
// ) {
|
||||||
|
// this.currentTypeId = [this.showTypeIds[0]]
|
||||||
|
// await this.loadColumns()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
},
|
},
|
||||||
|
|
||||||
async loadRoot() {
|
async loadRoot() {
|
||||||
@@ -858,41 +919,29 @@ export default {
|
|||||||
const facet = []
|
const facet = []
|
||||||
const ciIds = []
|
const ciIds = []
|
||||||
res.result.forEach((item) => {
|
res.result.forEach((item) => {
|
||||||
const showName = this.relationViews.id2type[item._type]?.show_name ?? null
|
facet.push([item[item.unique], 0, item._id, item._type, item.unique])
|
||||||
facet.push({
|
|
||||||
showName,
|
|
||||||
showNameValue: item[showName] ?? null,
|
|
||||||
uniqueValue: item[item.unique],
|
|
||||||
number: 0,
|
|
||||||
ciId: item._id,
|
|
||||||
typeId: item._type,
|
|
||||||
unique: item.unique,
|
|
||||||
})
|
|
||||||
ciIds.push(item._id)
|
ciIds.push(item._id)
|
||||||
})
|
})
|
||||||
|
const promises = this.leaf.map((leafId) => {
|
||||||
const leafId = this.leaf[0]
|
let level = 0
|
||||||
let level = 0
|
this.levels.forEach((item, idx) => {
|
||||||
this.levels.forEach((item, idx) => {
|
if (item.includes(leafId)) {
|
||||||
if (item.includes(leafId)) {
|
level = idx + 1
|
||||||
level = idx + 1
|
}
|
||||||
}
|
})
|
||||||
})
|
return statisticsCIRelation({
|
||||||
const params = {
|
root_ids: ciIds.join(','),
|
||||||
level,
|
level: level,
|
||||||
root_ids: ciIds.join(','),
|
type_ids: this.leaf2showTypes[this.leaf[0]].join(','),
|
||||||
has_m2m: Number(Object.values(this.level2constraint).includes('2')),
|
has_m2m: Number(Object.values(this.level2constraint).includes('2')),
|
||||||
}
|
descendant_ids: this.descendant_ids_for_statistics,
|
||||||
this.loadRootStatisticsParams = params
|
}).then((num) => {
|
||||||
await statisticsCIRelation({
|
facet.forEach((item, idx) => {
|
||||||
...params,
|
item[1] += num[ciIds[idx] + '']
|
||||||
type_ids: this.leaf2showTypes[this.leaf[0]].join(','),
|
})
|
||||||
descendant_ids: this.descendant_ids_for_statistics,
|
|
||||||
}).then((num) => {
|
|
||||||
facet.forEach((item, idx) => {
|
|
||||||
item.number += num[ciIds[idx] + '']
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
await Promise.all(promises)
|
||||||
this.wrapTreeData(facet)
|
this.wrapTreeData(facet)
|
||||||
// default select first node
|
// default select first node
|
||||||
this.onNodeClick(this.treeData[0].key)
|
this.onNodeClick(this.treeData[0].key)
|
||||||
@@ -927,16 +976,7 @@ export default {
|
|||||||
const facet = []
|
const facet = []
|
||||||
const ciIds = []
|
const ciIds = []
|
||||||
res.result.forEach((item) => {
|
res.result.forEach((item) => {
|
||||||
const showName = this.relationViews.id2type[item._type]?.show_name ?? null
|
facet.push([item[item.unique], 0, item._id, item._type, item.unique])
|
||||||
facet.push({
|
|
||||||
showName,
|
|
||||||
showNameValue: item[showName] ?? null,
|
|
||||||
uniqueValue: item[item.unique],
|
|
||||||
number: 0,
|
|
||||||
ciId: item._id,
|
|
||||||
typeId: item._type,
|
|
||||||
unique: item.unique,
|
|
||||||
})
|
|
||||||
ciIds.push(item._id)
|
ciIds.push(item._id)
|
||||||
})
|
})
|
||||||
let ancestor_ids
|
let ancestor_ids
|
||||||
@@ -958,7 +998,7 @@ export default {
|
|||||||
descendant_ids: this.descendant_ids_for_statistics,
|
descendant_ids: this.descendant_ids_for_statistics,
|
||||||
}).then((num) => {
|
}).then((num) => {
|
||||||
facet.forEach((item, idx) => {
|
facet.forEach((item, idx) => {
|
||||||
item.number += num[ciIds[idx] + '']
|
item[1] += num[ciIds[idx] + '']
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -969,7 +1009,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onNodeClick(keys, callback = undefined) {
|
onNodeClick(keys) {
|
||||||
this.triggerSelect = true
|
this.triggerSelect = true
|
||||||
if (keys) {
|
if (keys) {
|
||||||
const _tempKeys = keys.split('@^@').filter((item) => item !== '')
|
const _tempKeys = keys.split('@^@').filter((item) => item !== '')
|
||||||
@@ -988,9 +1028,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.refreshTable()
|
this.refreshTable()
|
||||||
if (callback && typeof callback === 'function') {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
wrapTreeData(facet) {
|
wrapTreeData(facet) {
|
||||||
if (this.triggerSelect) {
|
if (this.triggerSelect) {
|
||||||
@@ -998,15 +1035,12 @@ export default {
|
|||||||
}
|
}
|
||||||
const treeData = []
|
const treeData = []
|
||||||
facet.forEach((item) => {
|
facet.forEach((item) => {
|
||||||
const _treeKeys = _.cloneDeep(this.treeKeys)
|
|
||||||
_treeKeys.push(item.ciId + '%' + item.typeId + '%' + `{"${item.unique}":"${item.uniqueValue}"}`)
|
|
||||||
treeData.push({
|
treeData.push({
|
||||||
title: item.showName ? item.showNameValue : item.uniqueValue,
|
title: item[0],
|
||||||
number: item.number,
|
number: item[1],
|
||||||
key: _treeKeys.join('@^@'),
|
key: this.treeKeys.join('@^@') + '@^@' + item[2] + '%' + item[3] + '%' + `{"${item[4]}":"${item[0]}"}`,
|
||||||
isLeaf: this.leaf.includes(item.typeId),
|
isLeaf: this.leaf.includes(item[3]),
|
||||||
id: item.ciId,
|
id: item[2],
|
||||||
showName: item.showName,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (this.treeNode === null) {
|
if (this.treeNode === null) {
|
||||||
@@ -1026,6 +1060,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.treeKeys = treeNode.eventKey.split('@^@').filter((item) => item !== '')
|
this.treeKeys = treeNode.eventKey.split('@^@').filter((item) => item !== '')
|
||||||
this.treeNode = treeNode
|
this.treeNode = treeNode
|
||||||
|
// this.refreshTable()
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -1193,7 +1228,7 @@ export default {
|
|||||||
that.$refs.xTable.clearCheckboxRow()
|
that.$refs.xTable.clearCheckboxRow()
|
||||||
that.$refs.xTable.clearCheckboxReserve()
|
that.$refs.xTable.clearCheckboxReserve()
|
||||||
that.selectedRowKeys = []
|
that.selectedRowKeys = []
|
||||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
that.loadData({}, 'refreshNumber')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -1206,7 +1241,9 @@ export default {
|
|||||||
const _splitTargetKey = targetKey.split('@^@').filter((item) => item !== '')
|
const _splitTargetKey = targetKey.split('@^@').filter((item) => item !== '')
|
||||||
if (_splitDragKey.length - 1 === _splitTargetKey.length) {
|
if (_splitDragKey.length - 1 === _splitTargetKey.length) {
|
||||||
const dragId = _splitDragKey[_splitDragKey.length - 1].split('%')[0]
|
const dragId = _splitDragKey[_splitDragKey.length - 1].split('%')[0]
|
||||||
|
// const targetObj = JSON.parse(_splitTargetKey[_splitTargetKey.length - 1].split('%')[2])
|
||||||
const targetId = _splitTargetKey[_splitTargetKey.length - 1].split('%')[0]
|
const targetId = _splitTargetKey[_splitTargetKey.length - 1].split('%')[0]
|
||||||
|
// TODO 拖拽这里不造咋弄 等等再说吧
|
||||||
batchUpdateCIRelationChildren([dragId], [targetId]).then((res) => {
|
batchUpdateCIRelationChildren([dragId], [targetId]).then((res) => {
|
||||||
this.reload()
|
this.reload()
|
||||||
})
|
})
|
||||||
@@ -1241,7 +1278,7 @@ export default {
|
|||||||
this.sortByTable = sortByTable
|
this.sortByTable = sortByTable
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.pageNo === 1) {
|
if (this.pageNo === 1) {
|
||||||
this.loadData({ params: {}, refreshType: undefined, sortByTable })
|
this.loadData({}, undefined, sortByTable)
|
||||||
} else {
|
} else {
|
||||||
this.pageNo = 1
|
this.pageNo = 1
|
||||||
}
|
}
|
||||||
@@ -1400,7 +1437,7 @@ export default {
|
|||||||
onOk() {
|
onOk() {
|
||||||
deleteCI(record.ci_id || record._id).then((res) => {
|
deleteCI(record.ci_id || record._id).then((res) => {
|
||||||
that.$message.success(that.$t('deleteSuccess'))
|
that.$message.success(that.$t('deleteSuccess'))
|
||||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
that.loadData({}, 'refreshNumber')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -1420,7 +1457,7 @@ export default {
|
|||||||
}
|
}
|
||||||
addCIRelationView(first_ci_id, ci_id, { ancestor_ids }).then((res) => {
|
addCIRelationView(first_ci_id, ci_id, { ancestor_ids }).then((res) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loadData({ params: {}, refreshType: 'refreshNumber' })
|
this.loadData({}, 'refreshNumber')
|
||||||
}, 500)
|
}, 500)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -1458,7 +1495,7 @@ export default {
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
that.loading = false
|
that.loading = false
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
that.loadData({ params: {} })
|
that.loadData({})
|
||||||
}, 800)
|
}, 800)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -1521,7 +1558,7 @@ export default {
|
|||||||
that.selectedRowKeys = []
|
that.selectedRowKeys = []
|
||||||
that.$refs.xTable.clearCheckboxRow()
|
that.$refs.xTable.clearCheckboxRow()
|
||||||
that.$refs.xTable.clearCheckboxReserve()
|
that.$refs.xTable.clearCheckboxReserve()
|
||||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
that.loadData({}, 'refreshNumber')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -1531,6 +1568,7 @@ export default {
|
|||||||
},
|
},
|
||||||
jsonEditorOk(row, column, jsonData) {
|
jsonEditorOk(row, column, jsonData) {
|
||||||
// 后端写数据有快慢,不拉接口直接修改table的数据
|
// 后端写数据有快慢,不拉接口直接修改table的数据
|
||||||
|
// this.reloadData()
|
||||||
this.instanceList.forEach((item) => {
|
this.instanceList.forEach((item) => {
|
||||||
if (item._id === row._id) {
|
if (item._id === row._id) {
|
||||||
item[column.property] = JSON.stringify(jsonData)
|
item[column.property] = JSON.stringify(jsonData)
|
||||||
@@ -1539,7 +1577,7 @@ export default {
|
|||||||
this.$refs.xTable.refreshColumn()
|
this.$refs.xTable.refreshColumn()
|
||||||
},
|
},
|
||||||
relationViewRefreshNumber() {
|
relationViewRefreshNumber() {
|
||||||
this.loadData({ params: {}, refreshType: 'refreshNumber' })
|
this.loadData({}, 'refreshNumber')
|
||||||
},
|
},
|
||||||
onShowSizeChange(current, pageSize) {
|
onShowSizeChange(current, pageSize) {
|
||||||
this.pageSize = pageSize
|
this.pageSize = pageSize
|
||||||
@@ -1716,9 +1754,11 @@ export default {
|
|||||||
return node[i]
|
return node[i]
|
||||||
}
|
}
|
||||||
if (node[i].children && node[i].children.length) {
|
if (node[i].children && node[i].children.length) {
|
||||||
const found = this.findNode(node[i].children, target)
|
for (let i = 0; i < node[i].children.length; i++) {
|
||||||
if (found) {
|
const found = this.findNode(node[i].children, target)
|
||||||
return found
|
if (found) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1731,85 +1771,13 @@ export default {
|
|||||||
}
|
}
|
||||||
this.refreshTable()
|
this.refreshTable()
|
||||||
},
|
},
|
||||||
handleSearchFull(e) {
|
|
||||||
const value = e.target.value
|
|
||||||
this.treeKeys = []
|
|
||||||
this.expandedKeys = []
|
|
||||||
if (!value) {
|
|
||||||
this.reload()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.isFullSearch) {
|
|
||||||
this.calcFilterFullTreeData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
searchCIRelationFull({
|
|
||||||
...this.loadRootStatisticsParams,
|
|
||||||
type_ids: this.topo_flatten.join(','),
|
|
||||||
}).then((res) => {
|
|
||||||
this.isFullSearch = true
|
|
||||||
this.fullTreeData = this.formatTreeData(res)
|
|
||||||
this.calcFilterFullTreeData()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
calcFilterFullTreeData() {
|
|
||||||
const _expandedKeys = []
|
|
||||||
const predicateCiIds = []
|
|
||||||
const filterTree = (node, predicate) => {
|
|
||||||
if (predicate(node)) {
|
|
||||||
predicateCiIds.push(node.id)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
node.children = node.children.filter((child) => {
|
|
||||||
if (predicateCiIds.some((id) => child.key.includes(String(id)))) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return filterTree(child, predicate)
|
|
||||||
})
|
|
||||||
if (node.children.length && !predicateCiIds.some((id) => node.key.includes(String(id)))) {
|
|
||||||
_expandedKeys.push(node.key)
|
|
||||||
}
|
|
||||||
return node.children.length > 0
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const predicate = (node) =>
|
|
||||||
String(node.title)
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(this.fullSearchValue.toLowerCase())
|
|
||||||
const _fullTreeData = _.cloneDeep(this.fullTreeData)
|
|
||||||
this.filterFullTreeData = _fullTreeData.filter((item) => filterTree(item, predicate))
|
|
||||||
if (this.filterFullTreeData && this.filterFullTreeData.length) {
|
|
||||||
this.onNodeClick(this.filterFullTreeData[0].key, () => {
|
|
||||||
this.expandedKeys = _expandedKeys
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.treeKeys = []
|
|
||||||
this.instanceList = []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatTreeData(array, parentKey = '') {
|
|
||||||
array.forEach((item) => {
|
|
||||||
const showName = this.relationViews.id2type[item.type_id]?.show_name ?? null
|
|
||||||
const uniqueName = this.relationViews.id2type[item.type_id]?.unique_name ?? null
|
|
||||||
const keyList = parentKey.split('@^@').filter((item) => !!item)
|
|
||||||
keyList.push(item.id + '%' + item.type_id + '%' + `{"${uniqueName}":"${item.uniqueValue}"}`)
|
|
||||||
const key = keyList.join('@^@')
|
|
||||||
item.key = key
|
|
||||||
item.showName = showName
|
|
||||||
if (!item.isLeaf && item.children && item.children.length) {
|
|
||||||
item.children = this.formatTreeData(item.children, key)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return array
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@import '../index.less';
|
@import '../index.less';
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.relation-views-wrapper {
|
.relation-views-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -1852,18 +1820,6 @@ export default {
|
|||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.relation-views-left-input {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
input {
|
|
||||||
background-color: transparent;
|
|
||||||
border-top: none;
|
|
||||||
border-right: none;
|
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
.ant-input:focus {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.relation-views-right {
|
.relation-views-right {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@@ -27,13 +27,7 @@
|
|||||||
/>
|
/>
|
||||||
<span class="relation-views-node-icon" v-else>{{ icon ? icon[0].toUpperCase() : 'i' }}</span>
|
<span class="relation-views-node-icon" v-else>{{ icon ? icon[0].toUpperCase() : 'i' }}</span>
|
||||||
</template>
|
</template>
|
||||||
<span
|
<span class="relation-views-node-title" v-if="!isEditNodeName" :title="title">{{ title }}</span>
|
||||||
class="relation-views-node-title"
|
|
||||||
v-if="!isEditNodeName"
|
|
||||||
:title="title"
|
|
||||||
v-highlight="{ value: fullSearchValue, class: 'relation-views-node-title-highlight' }"
|
|
||||||
>{{ title }}
|
|
||||||
</span>
|
|
||||||
<a-input
|
<a-input
|
||||||
ref="input"
|
ref="input"
|
||||||
@blur="changeNodeName"
|
@blur="changeNodeName"
|
||||||
@@ -73,7 +67,10 @@
|
|||||||
key="editNodeName"
|
key="editNodeName"
|
||||||
><ops-icon type="icon-xianxing-edit" />{{ $t('cmdb.serviceTree.editNodeName') }}</a-menu-item
|
><ops-icon type="icon-xianxing-edit" />{{ $t('cmdb.serviceTree.editNodeName') }}</a-menu-item
|
||||||
>
|
>
|
||||||
<a-menu-item key="batch"><ops-icon type="veops-copy" />{{ $t('cmdb.serviceTree.batch') }}</a-menu-item>
|
<a-menu-item
|
||||||
|
key="batch"
|
||||||
|
><ops-icon type="veops-copy" />{{ $t('cmdb.serviceTree.batch') }}</a-menu-item
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-menu-item
|
<a-menu-item
|
||||||
@@ -106,17 +103,20 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { updateCI } from '../../../api/ci.js'
|
import { updateCI } from '../../../api/ci.js'
|
||||||
import highlight from '@/directive/highlight'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ContextMenu',
|
name: 'ContextMenu',
|
||||||
directives: {
|
|
||||||
highlight,
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
treeNodeData: {
|
title: {
|
||||||
type: Object,
|
type: String,
|
||||||
default: () => {},
|
default: '',
|
||||||
|
},
|
||||||
|
number: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
treeKey: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
},
|
},
|
||||||
levels: {
|
levels: {
|
||||||
type: Array,
|
type: Array,
|
||||||
@@ -130,6 +130,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
isLeaf: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => false,
|
||||||
|
},
|
||||||
ciTypeIcons: {
|
ciTypeIcons: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
@@ -142,10 +146,6 @@ export default {
|
|||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
fullSearchValue: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -201,21 +201,6 @@ export default {
|
|||||||
showCheckbox() {
|
showCheckbox() {
|
||||||
return this.showBatchLevel === this.treeKey.split('@^@').filter((item) => !!item).length - 1
|
return this.showBatchLevel === this.treeKey.split('@^@').filter((item) => !!item).length - 1
|
||||||
},
|
},
|
||||||
title() {
|
|
||||||
return this.treeNodeData.title
|
|
||||||
},
|
|
||||||
number() {
|
|
||||||
return this.treeNodeData.number
|
|
||||||
},
|
|
||||||
treeKey() {
|
|
||||||
return this.treeNodeData.key
|
|
||||||
},
|
|
||||||
isLeaf() {
|
|
||||||
return this.treeNodeData.isLeaf
|
|
||||||
},
|
|
||||||
showName() {
|
|
||||||
return this.treeNodeData.showName
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onContextMenuClick(treeKey, menuKey) {
|
onContextMenuClick(treeKey, menuKey) {
|
||||||
@@ -245,11 +230,8 @@ export default {
|
|||||||
.split('%')
|
.split('%')
|
||||||
const unique = Object.keys(JSON.parse(ci[2]))[0]
|
const unique = Object.keys(JSON.parse(ci[2]))[0]
|
||||||
const ciId = Number(ci[0])
|
const ciId = Number(ci[0])
|
||||||
let editAttrName = unique
|
|
||||||
if (this.showName) {
|
updateCI(ciId, { [unique]: value }).then((res) => {
|
||||||
editAttrName = this.showName
|
|
||||||
}
|
|
||||||
updateCI(ciId, { [editAttrName]: value }).then((res) => {
|
|
||||||
this.$message.success(this.$t('updateSuccess'))
|
this.$message.success(this.$t('updateSuccess'))
|
||||||
this.$emit('updateTreeData', ciId, value)
|
this.$emit('updateTreeData', ciId, value)
|
||||||
})
|
})
|
||||||
@@ -262,6 +244,8 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.relation-views-node {
|
.relation-views-node {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -330,9 +314,7 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.relation-views-node-title-highlight {
|
@import '~@/style/static.less';
|
||||||
color: @func-color_1;
|
|
||||||
}
|
|
||||||
.relation-views-left {
|
.relation-views-left {
|
||||||
ul:has(.relation-views-node-checkbox) > li > ul {
|
ul:has(.relation-views-node-checkbox) > li > ul {
|
||||||
margin-left: 26px;
|
margin-left: 26px;
|
||||||
|
@@ -535,6 +535,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.resource-search {
|
.resource-search {
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
|
@@ -50,6 +50,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.tree-views-node {
|
.tree-views-node {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
33
cmdb-ui/src/store/global/logo.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { getCompanyInfo } from '@/api/company'
|
||||||
|
|
||||||
|
const logo = {
|
||||||
|
state: {
|
||||||
|
file_name: '',
|
||||||
|
small_file_name: ''
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
SET_FILENAME: (state, name) => {
|
||||||
|
state.file_name = name
|
||||||
|
},
|
||||||
|
SET_SMALL_FILENAME: (state, name) => {
|
||||||
|
state.small_file_name = name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
getCompanyInfo({ commit }) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getCompanyInfo().then(res => {
|
||||||
|
if (res.info) {
|
||||||
|
commit('SET_FILENAME', res.info.logoName)
|
||||||
|
commit('SET_SMALL_FILENAME', res.info.smallLogoName)
|
||||||
|
resolve(res.info)
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.log('获取失败', err)
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default logo
|
@@ -5,6 +5,7 @@ import Vuex from 'vuex'
|
|||||||
import app from './global/app'
|
import app from './global/app'
|
||||||
import user from './global/user'
|
import user from './global/user'
|
||||||
import routes from './global/routes'
|
import routes from './global/routes'
|
||||||
|
import logo from './global/logo'
|
||||||
import notice from './global/notice'
|
import notice from './global/notice'
|
||||||
import getters from './global/getters'
|
import getters from './global/getters'
|
||||||
import appConfig from '@/config/app'
|
import appConfig from '@/config/app'
|
||||||
@@ -16,6 +17,7 @@ const store = new Vuex.Store({
|
|||||||
app,
|
app,
|
||||||
user,
|
user,
|
||||||
routes,
|
routes,
|
||||||
|
logo,
|
||||||
notice
|
notice
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
|
@@ -1352,11 +1352,3 @@ body {
|
|||||||
.ant-tree li .ant-tree-node-content-wrapper:hover {
|
.ant-tree li .ant-tree-node-content-wrapper:hover {
|
||||||
background-color: @primary-color_3;
|
background-color: @primary-color_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-pagination-options-size-changer.ant-select {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-form-explain{
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
@@ -130,30 +130,22 @@ export const isEmptySubDepartments = (item) => {
|
|||||||
|
|
||||||
// format部门员工树
|
// format部门员工树
|
||||||
export const formatOption = (data, idType = 1, isDisabledAllCompany, departmentKey = 'department_id', employeeKey = 'employee_id') => {
|
export const formatOption = (data, idType = 1, isDisabledAllCompany, departmentKey = 'department_id', employeeKey = 'employee_id') => {
|
||||||
// idType 1 表示 员工id为`${departmentKey}-${employeeKey}`
|
// idType 1 表示 员工id为`${department_id}-${employee_id}`
|
||||||
// 2 表示 department-${departmentKey} employee-${employeeKey}
|
// 2 表示 department-${department_id} employee-${employee_id}
|
||||||
// 3 表示 departmentKey employeeKey
|
|
||||||
let _data = _.cloneDeep(data)
|
let _data = _.cloneDeep(data)
|
||||||
_data = _data.filter((item) => {
|
_data = _data.filter((item) => {
|
||||||
return item.employees.length || (item.sub_departments.length && !isEmptySubDepartments(item))
|
return item.employees.length || (item.sub_departments.length && !isEmptySubDepartments(item))
|
||||||
})
|
})
|
||||||
const switchEmployeeIdType = (item, employee) => {
|
|
||||||
switch (idType) {
|
|
||||||
case 1: return `${item[departmentKey]}-${employee[employeeKey]}`
|
|
||||||
case 2: return `employee-${employee[employeeKey]}`
|
|
||||||
case 3: return `${employee[employeeKey]}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_data.forEach((item) => {
|
_data.forEach((item) => {
|
||||||
if (isDisabledAllCompany) {
|
if (isDisabledAllCompany) {
|
||||||
item.isDisabled = !item.department_id
|
item.isDisabled = !item.department_id
|
||||||
}
|
}
|
||||||
item.id = [1, 3].includes(idType) ? item[departmentKey] : `department-${item[departmentKey]}`
|
item.id = idType === 1 ? item[departmentKey] : `department-${item[departmentKey]}`
|
||||||
item.label = item.department_name
|
item.label = item.department_name
|
||||||
item.children = [
|
item.children = [
|
||||||
...formatOption(
|
...formatOption(
|
||||||
item.sub_departments.map((dep) => {
|
item.sub_departments.map((dep) => {
|
||||||
return { ...dep, id: [1, 3].includes(idType) ? dep[departmentKey] : `department-${dep[departmentKey]}`, label: dep.department_name }
|
return { ...dep, id: idType === 1 ? dep[departmentKey] : `department-${dep[departmentKey]}`, label: dep.department_name }
|
||||||
}),
|
}),
|
||||||
idType,
|
idType,
|
||||||
isDisabledAllCompany,
|
isDisabledAllCompany,
|
||||||
@@ -161,7 +153,7 @@ export const formatOption = (data, idType = 1, isDisabledAllCompany, departmentK
|
|||||||
employeeKey
|
employeeKey
|
||||||
),
|
),
|
||||||
...item.employees.map((employee) => {
|
...item.employees.map((employee) => {
|
||||||
return { ...employee, id: switchEmployeeIdType(item, employee), label: employee.nickname }
|
return { ...employee, id: idType === 1 ? `${item[departmentKey]}-${employee[employeeKey]}` : `employee-${employee[employeeKey]}`, label: employee.nickname }
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
@@ -284,6 +284,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
|
|
||||||
.notice-center-left {
|
.notice-center-left {
|
||||||
color: rgba(0, 0, 0, 0.7);
|
color: rgba(0, 0, 0, 0.7);
|
||||||
|
@@ -3,62 +3,140 @@
|
|||||||
<a-form-model ref="infoData" :model="infoData" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rule">
|
<a-form-model ref="infoData" :model="infoData" :label-col="labelCol" :wrapper-col="wrapperCol" :rules="rule">
|
||||||
<SpanTitle>{{ $t('cs.companyInfo.spanCompany') }}</SpanTitle>
|
<SpanTitle>{{ $t('cs.companyInfo.spanCompany') }}</SpanTitle>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.name')" prop="name">
|
<a-form-model-item :label="$t('cs.companyInfo.name')" prop="name">
|
||||||
<a-input v-model="infoData.name" :disabled="!isEditable" />
|
<a-input v-model="infoData.name" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.description')">
|
<a-form-model-item :label="$t('cs.companyInfo.description')">
|
||||||
<a-input v-model="infoData.description" type="textarea" :disabled="!isEditable" />
|
<a-input v-model="infoData.description" type="textarea" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<SpanTitle>{{ $t('cs.companyInfo.spanAddress') }}</SpanTitle>
|
<SpanTitle>{{ $t('cs.companyInfo.spanAddress') }}</SpanTitle>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.country')">
|
<a-form-model-item :label="$t('cs.companyInfo.country')">
|
||||||
<a-input v-model="infoData.country" :disabled="!isEditable" />
|
<a-input v-model="infoData.country" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.city')">
|
<a-form-model-item :label="$t('cs.companyInfo.city')">
|
||||||
<a-input v-model="infoData.city" :disabled="!isEditable" />
|
<a-input v-model="infoData.city" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.address')">
|
<a-form-model-item :label="$t('cs.companyInfo.address')">
|
||||||
<a-input v-model="infoData.address" :disabled="!isEditable" />
|
<a-input v-model="infoData.address" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.postcode')">
|
<a-form-model-item :label="$t('cs.companyInfo.postcode')">
|
||||||
<a-input v-model="infoData.postCode" :disabled="!isEditable" />
|
<a-input v-model="infoData.postCode" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<SpanTitle>{{ $t('cs.companyInfo.spanContract') }}</SpanTitle>
|
<SpanTitle>{{ $t('cs.companyInfo.spanContract') }}</SpanTitle>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.website')">
|
<a-form-model-item :label="$t('cs.companyInfo.website')">
|
||||||
<a-input v-model="infoData.website" :disabled="!isEditable" />
|
<a-input v-model="infoData.website" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.phone')" prop="phone">
|
<a-form-model-item :label="$t('cs.companyInfo.phone')" prop="phone">
|
||||||
<a-input v-model="infoData.phone" :disabled="!isEditable" />
|
<a-input v-model="infoData.phone" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.faxCode')" prop="faxCode">
|
<a-form-model-item :label="$t('cs.companyInfo.faxCode')" prop="faxCode">
|
||||||
<a-input v-model="infoData.faxCode" :disabled="!isEditable" />
|
<a-input v-model="infoData.faxCode" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.email')" prop="email">
|
<a-form-model-item :label="$t('cs.companyInfo.email')" prop="email">
|
||||||
<a-input v-model="infoData.email" :disabled="!isEditable" />
|
<a-input v-model="infoData.email" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<SpanTitle>{{ $t('cs.companyInfo.spanLogo') }}</SpanTitle>
|
<SpanTitle>{{ $t('cs.companyInfo.spanLogo') }}</SpanTitle>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.messenger')" prop="messenger">
|
<a-form-model-item :label="$t('cs.companyInfo.messenger')" prop="messenger">
|
||||||
<a-input v-model="infoData.messenger" :disabled="!isEditable" />
|
<a-input v-model="infoData.messenger" :disabled="!isEditable"/>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :label="$t('cs.companyInfo.domainName')" prop="domainName">
|
<a-form-model-item :label="$t('cs.companyInfo.domainName')" prop="domainName">
|
||||||
<a-input v-model="infoData.domainName" :disabled="!isEditable" />
|
<a-input v-model="infoData.domainName" :disabled="!isEditable"/>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item :label="$t('cs.companyInfo.logo')">
|
||||||
|
<a-space>
|
||||||
|
<a-upload
|
||||||
|
:disabled="!isEditable"
|
||||||
|
name="avatar"
|
||||||
|
list-type="picture-card"
|
||||||
|
class="avatar-uploader"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="customRequest"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:style="{ width: '400px', height: '80px' }"
|
||||||
|
accept=".png,.jpg,.jpeg"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ops-setting-companyinfo-upload-show"
|
||||||
|
v-if="infoData.logoName"
|
||||||
|
:style="{ width: '400px', height: '80px' }"
|
||||||
|
@click="eidtImageOption.type = 'Logo'"
|
||||||
|
>
|
||||||
|
<img :src="`/api/common-setting/v1/file/${infoData.logoName}`" alt="avatar"/>
|
||||||
|
<a-icon
|
||||||
|
v-if="isEditable"
|
||||||
|
type="minus-circle"
|
||||||
|
theme="filled"
|
||||||
|
class="delete-icon"
|
||||||
|
@click.stop="deleteLogo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else @click="eidtImageOption.type = 'Logo'">
|
||||||
|
<a-icon type="plus"/>
|
||||||
|
<div class="ant-upload-text">{{ $t('cs.companyInfo.upload') }}</div>
|
||||||
|
</div>
|
||||||
|
</a-upload>
|
||||||
|
|
||||||
|
<a-upload
|
||||||
|
:disabled="!isEditable"
|
||||||
|
name="avatar"
|
||||||
|
list-type="picture-card"
|
||||||
|
class="avatar-uploader"
|
||||||
|
:show-upload-list="false"
|
||||||
|
:customRequest="customRequest"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:style="{ width: '82px', height: '82px' }"
|
||||||
|
accept=".png,.jpg,.jpeg"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="ops-setting-companyinfo-upload-show"
|
||||||
|
v-if="infoData.smallLogoName"
|
||||||
|
:style="{ width: '82px', height: '82px' }"
|
||||||
|
@click="eidtImageOption.type = 'SmallLogo'"
|
||||||
|
>
|
||||||
|
<img :src="`/api/common-setting/v1/file/${infoData.smallLogoName}`" alt="avatar"/>
|
||||||
|
<a-icon
|
||||||
|
v-if="isEditable"
|
||||||
|
type="minus-circle"
|
||||||
|
theme="filled"
|
||||||
|
class="delete-icon"
|
||||||
|
@click.stop="deleteSmallLogo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else @click="eidtImageOption.type = 'SmallLogo'">
|
||||||
|
<a-icon type="plus"/>
|
||||||
|
<div class="ant-upload-text">{{ $t('cs.companyInfo.upload') }}</div>
|
||||||
|
</div>
|
||||||
|
</a-upload>
|
||||||
|
</a-space>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item :wrapper-col="{ span: 14, offset: 3 }" v-if="isEditable">
|
<a-form-model-item :wrapper-col="{ span: 14, offset: 3 }" v-if="isEditable">
|
||||||
<a-button type="primary" @click="onSubmit"> {{ $t('save') }}</a-button>
|
<a-button type="primary" @click="onSubmit"> {{ $t('save') }}</a-button>
|
||||||
<a-button ghost type="primary" style="margin-left: 28px" @click="resetForm"> {{ $t('reset') }}</a-button>
|
<a-button ghost type="primary" style="margin-left: 28px" @click="resetForm"> {{ $t('reset') }}</a-button>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-form-model>
|
</a-form-model>
|
||||||
|
<edit-image
|
||||||
|
v-if="showEditImage"
|
||||||
|
:show="showEditImage"
|
||||||
|
:image="editImage"
|
||||||
|
:title="eidtImageOption.title"
|
||||||
|
:eidtImageOption="eidtImageOption"
|
||||||
|
@save="submitImage"
|
||||||
|
@close="showEditImage = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getCompanyInfo, postCompanyInfo, putCompanyInfo } from '@/api/company'
|
import { getCompanyInfo, postCompanyInfo, putCompanyInfo } from '@/api/company'
|
||||||
import { mapState } from 'vuex'
|
import { postImageFile } from '@/api/file'
|
||||||
|
import { mapMutations, mapState } from 'vuex'
|
||||||
import SpanTitle from '../components/spanTitle.vue'
|
import SpanTitle from '../components/spanTitle.vue'
|
||||||
|
import EditImage from '../components/EditImage.vue'
|
||||||
import { mixinPermissions } from '@/utils/mixin'
|
import { mixinPermissions } from '@/utils/mixin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CompanyInfo',
|
name: 'CompanyInfo',
|
||||||
mixins: [mixinPermissions],
|
mixins: [mixinPermissions],
|
||||||
components: { SpanTitle },
|
components: { SpanTitle, EditImage },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
labelCol: { span: 3 },
|
labelCol: { span: 3 },
|
||||||
@@ -74,10 +152,14 @@ export default {
|
|||||||
phone: '',
|
phone: '',
|
||||||
faxCode: '',
|
faxCode: '',
|
||||||
email: '',
|
email: '',
|
||||||
|
logoName: '',
|
||||||
|
smallLogoName: '',
|
||||||
messenger: '',
|
messenger: '',
|
||||||
domainName: '',
|
domainName: '',
|
||||||
},
|
},
|
||||||
getId: -1,
|
getId: -1,
|
||||||
|
showEditImage: false,
|
||||||
|
editImage: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@@ -128,8 +210,26 @@ export default {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
eidtImageOption () {
|
||||||
|
return {
|
||||||
|
type: 'Logo',
|
||||||
|
fixedNumber: [15, 4],
|
||||||
|
title: this.$t('cs.companyInfo.editCompanyLogo'),
|
||||||
|
previewWidth: '200px',
|
||||||
|
previewHeight: '40px',
|
||||||
|
autoCropWidth: 200,
|
||||||
|
autoCropHeight: 40,
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapMutations(['SET_FILENAME', 'SET_SMALL_FILENAME']),
|
||||||
|
deleteLogo() {
|
||||||
|
this.infoData.logoName = ''
|
||||||
|
},
|
||||||
|
deleteSmallLogo() {
|
||||||
|
this.infoData.smallLogoName = ''
|
||||||
|
},
|
||||||
async onSubmit() {
|
async onSubmit() {
|
||||||
this.$refs.infoData.validate(async (valid) => {
|
this.$refs.infoData.validate(async (valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -138,6 +238,8 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
await putCompanyInfo(this.getId, this.infoData)
|
await putCompanyInfo(this.getId, this.infoData)
|
||||||
}
|
}
|
||||||
|
this.SET_FILENAME(this.infoData.logoName)
|
||||||
|
this.SET_SMALL_FILENAME(this.infoData.smallFileName)
|
||||||
this.$message.success(this.$t('saveSuccess'))
|
this.$message.success(this.$t('saveSuccess'))
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning(this.$t('cs.companyInfo.checkInputCorrect'))
|
this.$message.warning(this.$t('cs.companyInfo.checkInputCorrect'))
|
||||||
@@ -157,10 +259,70 @@ export default {
|
|||||||
phone: '',
|
phone: '',
|
||||||
faxCode: '',
|
faxCode: '',
|
||||||
email: '',
|
email: '',
|
||||||
|
logoName: '',
|
||||||
|
smallLogoName: '',
|
||||||
messenger: '',
|
messenger: '',
|
||||||
domainName: '',
|
domainName: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
customRequest(file) {
|
||||||
|
const reader = new FileReader()
|
||||||
|
var self = this
|
||||||
|
if (this.eidtImageOption.type === 'Logo') {
|
||||||
|
this.eidtImageOption = {
|
||||||
|
type: 'Logo',
|
||||||
|
fixedNumber: [20, 4],
|
||||||
|
title: this.$t('cs.companyInfo.editCompanyLogo'),
|
||||||
|
previewWidth: '200px',
|
||||||
|
previewHeight: '40px',
|
||||||
|
autoCropWidth: 200,
|
||||||
|
autoCropHeight: 40,
|
||||||
|
}
|
||||||
|
} else if (this.eidtImageOption.type === 'SmallLogo') {
|
||||||
|
this.eidtImageOption = {
|
||||||
|
type: 'SmallLogo',
|
||||||
|
fixedNumber: [4, 4],
|
||||||
|
title: this.$t('cs.companyInfo.editCompanyLogoSmall'),
|
||||||
|
previewWidth: '80px',
|
||||||
|
previewHeight: '80px',
|
||||||
|
autoCropWidth: 250,
|
||||||
|
autoCropHeight: 250,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.onload = function (e) {
|
||||||
|
let result
|
||||||
|
if (typeof e.target.result === 'object') {
|
||||||
|
// 把Array Buffer转化为blob 如果是base64不需要
|
||||||
|
result = window.URL.createObjectURL(new Blob([e.target.result]))
|
||||||
|
} else {
|
||||||
|
result = e.target.result
|
||||||
|
}
|
||||||
|
|
||||||
|
self.editImage = result
|
||||||
|
self.showEditImage = true
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(file.file)
|
||||||
|
},
|
||||||
|
submitImage(file) {
|
||||||
|
postImageFile(file).then((res) => {
|
||||||
|
if (res.file_name) {
|
||||||
|
if (this.eidtImageOption.type === 'Logo') {
|
||||||
|
this.infoData.logoName = res.file_name
|
||||||
|
} else if (this.eidtImageOption.type === 'SmallLogo') {
|
||||||
|
this.infoData.smallLogoName = res.file_name
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeUpload(file) {
|
||||||
|
const isLt2M = file.size / 1024 / 1024 < 2
|
||||||
|
if (!isLt2M) {
|
||||||
|
this.$message.error(this.$t('cs.companyInfo.imageSizeLimit2MB'))
|
||||||
|
}
|
||||||
|
return isLt2M
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -169,7 +331,7 @@ export default {
|
|||||||
.ops-setting-companyinfo {
|
.ops-setting-companyinfo {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
.ops-setting-companyinfo-upload-show {
|
.ops-setting-companyinfo-upload-show {
|
||||||
|
@@ -155,6 +155,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@import '~@/style/static.less';
|
||||||
ul,
|
ul,
|
||||||
li {
|
li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
@@ -862,13 +862,14 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.ops-setting-structure {
|
.ops-setting-structure {
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
.ops-setting-structure-sidebar {
|
.ops-setting-structure-sidebar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
&:hover {
|
&:hover {
|
||||||
overflow-y: overlay;
|
overflow-y: overlay;
|
||||||
@@ -1025,7 +1026,7 @@ export default {
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
.ops-setting-structure-main-controller {
|
.ops-setting-structure-main-controller {
|
||||||
// height: 70px;
|
// height: 70px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
@@ -64,6 +64,7 @@ name: 'SearchForm',
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.search-form-bar-filter {
|
.search-form-bar-filter {
|
||||||
background-color: rgb(240, 245, 255);
|
background-color: rgb(240, 245, 255);
|
||||||
.ops_display_wrapper();
|
.ops_display_wrapper();
|
||||||
|
@@ -137,7 +137,7 @@ export default {
|
|||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
.notice-dingding-wrapper-tips {
|
.notice-dingding-wrapper-tips {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: #ffdfdf;
|
background-color: #ffdfdf;
|
||||||
|
@@ -117,7 +117,7 @@ export default {
|
|||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
.notice-feishu-wrapper-tips {
|
.notice-feishu-wrapper-tips {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: #ffdfdf;
|
background-color: #ffdfdf;
|
||||||
|
@@ -138,7 +138,7 @@ export default {
|
|||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
margin-bottom: -24px;
|
margin-bottom: -24px;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
.notice-wx-wrapper-tips {
|
.notice-wx-wrapper-tips {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: #ffdfdf;
|
background-color: #ffdfdf;
|
||||||
|
@@ -354,6 +354,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@import '~@/style/static.less';
|
||||||
.setting-person {
|
.setting-person {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -362,7 +363,7 @@ export default {
|
|||||||
height: 400px;
|
height: 400px;
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
.setting-person-left-item {
|
.setting-person-left-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -387,7 +388,7 @@ export default {
|
|||||||
width: 800px;
|
width: 800px;
|
||||||
height: 700px;
|
height: 700px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: @border-radius-box;
|
border-radius: 15px;
|
||||||
padding: 24px 48px;
|
padding: 24px 48px;
|
||||||
.setting-person-right-disabled {
|
.setting-person-right-disabled {
|
||||||
background-color: #custom_colors[color_2];
|
background-color: #custom_colors[color_2];
|
||||||
|
@@ -91,12 +91,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pluginOptions: {
|
|
||||||
'style-resources-loader': {
|
|
||||||
preProcessor: 'less',
|
|
||||||
patterns: [path.resolve(__dirname, './src/style/static.less')],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
devServer: {
|
devServer: {
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
port: process.env.DEV_PORT || 8000,
|
port: process.env.DEV_PORT || 8000,
|
||||||
|
@@ -32,8 +32,6 @@ services:
|
|||||||
container_name: cmdb-cache
|
container_name: cmdb-cache
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
volumes:
|
|
||||||
- cache-data:/data
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
@@ -45,7 +43,7 @@ services:
|
|||||||
- redis
|
- redis
|
||||||
|
|
||||||
cmdb-api:
|
cmdb-api:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-api:2.4.3
|
image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-api:2.4.2
|
||||||
# build:
|
# build:
|
||||||
# context: .
|
# context: .
|
||||||
# target: cmdb-api
|
# target: cmdb-api
|
||||||
@@ -68,6 +66,9 @@ services:
|
|||||||
flask common-check-new-columns
|
flask common-check-new-columns
|
||||||
gunicorn --workers=4 autoapp:app -b 0.0.0.0:5000 -D
|
gunicorn --workers=4 autoapp:app -b 0.0.0.0:5000 -D
|
||||||
|
|
||||||
|
#nohup celery -A celery_worker.celery worker -E -Q one_cmdb_async --autoscale=2,5 > one_cmdb_async.log 2>&1 &
|
||||||
|
#nohup celery -A celery_worker.celery worker -E -Q acl_async --concurrency=2 > one_acl_async.log 2>&1 &
|
||||||
|
#
|
||||||
celery -A celery_worker.celery worker -E -Q one_cmdb_async --autoscale=4,1 --logfile=one_cmdb_async.log -D
|
celery -A celery_worker.celery worker -E -Q one_cmdb_async --autoscale=4,1 --logfile=one_cmdb_async.log -D
|
||||||
celery -A celery_worker.celery worker -E -Q acl_async --logfile=one_acl_async.log --autoscale=2,1 -D
|
celery -A celery_worker.celery worker -E -Q acl_async --logfile=one_acl_async.log --autoscale=2,1 -D
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ services:
|
|||||||
- cmdb-api
|
- cmdb-api
|
||||||
|
|
||||||
cmdb-ui:
|
cmdb-ui:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-ui:2.4.3
|
image: registry.cn-hangzhou.aliyuncs.com/veops/cmdb-ui:2.4.2
|
||||||
# build:
|
# build:
|
||||||
# context: .
|
# context: .
|
||||||
# target: cmdb-ui
|
# target: cmdb-ui
|
||||||
@@ -112,9 +113,6 @@ volumes:
|
|||||||
db-data:
|
db-data:
|
||||||
driver: local
|
driver: local
|
||||||
name: cmdb_db-data
|
name: cmdb_db-data
|
||||||
cache-data:
|
|
||||||
driver: local
|
|
||||||
name: cmdb_cache-data
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
new:
|
new:
|
||||||
|