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.role import RoleCRUD
|
||||
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.models.acl import App
|
||||
from api.models.acl import ResourceType
|
||||
@@ -55,12 +55,9 @@ def cmdb_init_cache():
|
||||
for cr in ci_relations:
|
||||
relations.setdefault(cr.first_ci_id, {}).update({cr.second_ci_id: cr.second_ci.type_id})
|
||||
if cr.ancestor_ids:
|
||||
relations2.setdefault('{},{}'.format(cr.ancestor_ids, cr.first_ci_id), {}).update(
|
||||
{cr.second_ci_id: cr.second_ci.type_id})
|
||||
relations2.setdefault(cr.ancestor_ids, {}).update({cr.second_ci_id: cr.second_ci.type_id})
|
||||
for i in relations:
|
||||
relations[i] = json.dumps(relations[i])
|
||||
for i in relations2:
|
||||
relations2[i] = json.dumps(relations2[i])
|
||||
if relations:
|
||||
rd.create_or_update(relations, REDIS_PREFIX_CI_RELATION)
|
||||
if relations2:
|
||||
|
@@ -6,7 +6,6 @@ from werkzeug.datastructures import MultiDict
|
||||
from api.lib.common_setting.acl import ACLManager
|
||||
from api.lib.common_setting.employee import EmployeeAddForm, GrantEmployeeACLPerm
|
||||
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
|
||||
|
||||
|
||||
@@ -210,7 +209,57 @@ def common_check_new_columns():
|
||||
"""
|
||||
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()
|
||||
|
@@ -92,9 +92,6 @@ class CITypeManager(object):
|
||||
for type_dict in ci_types:
|
||||
attr = AttributeCache.get(type_dict["unique_id"])
|
||||
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'])
|
||||
if resources is None or type_dict['name'] in resources:
|
||||
res.append(type_dict)
|
||||
@@ -195,7 +192,7 @@ class CITypeManager(object):
|
||||
CITypeAttributeManager.update(type_id, [attr])
|
||||
|
||||
ci_type2 = ci_type.to_dict()
|
||||
new = ci_type.update(**kwargs, filter_none=False)
|
||||
new = ci_type.update(**kwargs)
|
||||
|
||||
CITypeCache.clean(type_id)
|
||||
|
||||
@@ -683,9 +680,6 @@ class CITypeAttributeManager(object):
|
||||
|
||||
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,
|
||||
change=attr and attr.to_dict())
|
||||
|
||||
@@ -1233,10 +1227,7 @@ class CITypeTemplateManager(object):
|
||||
def _import_ci_types(self, ci_types, attr_id_map):
|
||||
for i in ci_types:
|
||||
i.pop("unique_key", None)
|
||||
i.pop("show_name", None)
|
||||
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
|
||||
|
||||
return self.__import(CIType, ci_types)
|
||||
|
@@ -297,10 +297,6 @@ class PreferenceManager(object):
|
||||
|
||||
for type_id in id2type:
|
||||
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])
|
||||
|
||||
|
@@ -8,8 +8,6 @@ from flask import current_app
|
||||
from flask_login import current_user
|
||||
|
||||
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_type import CITypeRelationManager
|
||||
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.search.ci.db.search import Search as SearchFromDB
|
||||
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 is_app_admin
|
||||
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])))
|
||||
|
||||
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
||||
_tmp, tmp_res = [], []
|
||||
_tmp = []
|
||||
level2ids = {}
|
||||
for lv in range(1, self.level + 1):
|
||||
level2ids[lv] = []
|
||||
@@ -307,26 +303,25 @@ class Search(object):
|
||||
if key:
|
||||
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:
|
||||
tmp_res = [[i for i in x if i[1] in type_ids and
|
||||
(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)]
|
||||
__tmp = [[i for i in x if i[1] in type_ids and
|
||||
(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)]
|
||||
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
|
||||
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)]
|
||||
|
||||
if ci_filter_limit:
|
||||
tmp_res = [[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]
|
||||
__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]
|
||||
else:
|
||||
tmp_res = []
|
||||
__tmp = []
|
||||
|
||||
if tmp_res:
|
||||
_tmp[idx] = [j for i in tmp_res for j in i]
|
||||
if __tmp:
|
||||
_tmp[idx] = [j for i in __tmp for j in i]
|
||||
else:
|
||||
_tmp[idx] = []
|
||||
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)})
|
||||
|
||||
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 -*-
|
||||
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='-'):
|
||||
@@ -28,115 +23,3 @@ class BaseEnum(object):
|
||||
if not attr.startswith("_") and not callable(getattr(cls, attr))
|
||||
}
|
||||
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)
|
||||
alias = db.Column(db.String(32), 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)
|
||||
is_attached = db.Column(db.Boolean, default=False, nullable=False)
|
||||
icon = db.Column(db.Text)
|
||||
order = db.Column(db.SmallInteger, default=0, nullable=False)
|
||||
default_order_attr = db.Column(db.String(33))
|
||||
|
||||
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])
|
||||
unique_key = db.relationship("Attribute", backref="c_ci_types.unique_id")
|
||||
|
||||
uid = db.Column(db.Integer, index=True)
|
||||
|
||||
|
@@ -30,7 +30,6 @@ class CIRelationSearchView(APIView):
|
||||
level: default is 1
|
||||
facet: statistic
|
||||
"""
|
||||
|
||||
page = get_page(request.values.get("page", 1))
|
||||
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)
|
||||
|
||||
|
||||
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):
|
||||
url_prefix = "/ci_relations/<int:first_ci_id>/second_cis"
|
||||
|
||||
|
@@ -42,11 +42,9 @@
|
||||
"relation-graph": "^1.1.0",
|
||||
"snabbdom": "^3.5.1",
|
||||
"sortablejs": "1.9.0",
|
||||
"style-resources-loader": "^1.5.0",
|
||||
"viser-vue": "^2.4.8",
|
||||
"vue": "2.6.11",
|
||||
"vue-clipboard2": "^0.3.3",
|
||||
"vue-cli-plugin-style-resources-loader": "^0.1.5",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-cropper": "^0.6.2",
|
||||
"vue-grid-layout": "2.3.12",
|
||||
|
@@ -54,24 +54,6 @@
|
||||
<div class="content unicode" style="display: block;">
|
||||
<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">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">VPC</div>
|
||||
@@ -4806,9 +4788,9 @@
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.woff2?t=1713335725699') format('woff2'),
|
||||
url('iconfont.woff?t=1713335725699') format('woff'),
|
||||
url('iconfont.ttf?t=1713335725699') format('truetype');
|
||||
src: url('iconfont.woff2?t=1711963254221') format('woff2'),
|
||||
url('iconfont.woff?t=1711963254221') format('woff'),
|
||||
url('iconfont.ttf?t=1711963254221') format('truetype');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
@@ -4834,33 +4816,6 @@
|
||||
<div class="content font-class">
|
||||
<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">
|
||||
<span class="icon iconfont caise-VPC"></span>
|
||||
<div class="name">
|
||||
@@ -11962,30 +11917,6 @@
|
||||
<div class="content symbol">
|
||||
<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">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#caise-VPC"></use>
|
||||
|
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 3857903 */
|
||||
src: url('iconfont.woff2?t=1713335725699') format('woff2'),
|
||||
url('iconfont.woff?t=1713335725699') format('woff'),
|
||||
url('iconfont.ttf?t=1713335725699') format('truetype');
|
||||
src: url('iconfont.woff2?t=1711963254221') format('woff2'),
|
||||
url('iconfont.woff?t=1711963254221') format('woff'),
|
||||
url('iconfont.ttf?t=1711963254221') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@@ -13,18 +13,6 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.veops-show:before {
|
||||
content: "\e914";
|
||||
}
|
||||
|
||||
.itsm-duration:before {
|
||||
content: "\e913";
|
||||
}
|
||||
|
||||
.a-itsm-workload1:before {
|
||||
content: "\e912";
|
||||
}
|
||||
|
||||
.caise-VPC:before {
|
||||
content: "\e910";
|
||||
}
|
||||
|
@@ -5,27 +5,6 @@
|
||||
"css_prefix_text": "",
|
||||
"description": "",
|
||||
"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",
|
||||
"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>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.custom-drawer-close {
|
||||
position: absolute;
|
||||
|
@@ -230,6 +230,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
.employee-transfer {
|
||||
width: 100%;
|
||||
.vue-treeselect__multi-value-item-container {
|
||||
@@ -262,6 +263,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.employee-transfer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@@ -146,6 +146,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.regex-select {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
|
@@ -126,6 +126,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.role-transfer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@@ -60,6 +60,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.sidebar-list-item {
|
||||
.ops_popover_item();
|
||||
margin: 2px 0;
|
||||
|
@@ -52,6 +52,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.two-column-layout {
|
||||
margin-bottom: -24px;
|
||||
|
@@ -4,22 +4,34 @@
|
||||
@click="jumpTo"
|
||||
v-if="showTitle && !collapsed"
|
||||
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
|
||||
@click="jumpTo"
|
||||
v-else
|
||||
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>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import LogoSvg from '@/assets/logo.svg?inline'
|
||||
import { mapState } from 'vuex'
|
||||
export default {
|
||||
name: 'Logo',
|
||||
components: {},
|
||||
computed: {},
|
||||
components: {
|
||||
// LogoSvg,
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
file_name: (state) => state.logo.file_name,
|
||||
small_file_name: (state) => state.logo.small_file_name,
|
||||
}),
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
|
@@ -96,6 +96,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
.color {
|
||||
color: #custom_colors[color_1];
|
||||
background-color: #custom_colors[color_2];
|
||||
|
@@ -9,11 +9,25 @@
|
||||
import gridSvg from '@/assets/icons/grid.svg?inline'
|
||||
import top_agent from '@/assets/icons/top_agent.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'
|
||||
|
||||
export {
|
||||
gridSvg,
|
||||
top_agent,
|
||||
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
|
||||
}
|
||||
|
@@ -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("loadAllEmployees")
|
||||
store.dispatch("loadAllDepartments")
|
||||
store.dispatch("getCompanyInfo")
|
||||
store.dispatch('GenerateRoutes', { roles }).then(() => {
|
||||
router.addRoutes(store.getters.appRoutes)
|
||||
const redirect = decodeURIComponent(from.query.redirect || to.path)
|
||||
|
@@ -233,6 +233,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-history {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -32,6 +32,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-operation-history {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -189,6 +189,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-resource-types {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -352,6 +352,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-resources {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -285,6 +285,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-roles {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -88,6 +88,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-secret-key {
|
||||
background-color: #fff;
|
||||
|
@@ -320,6 +320,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-trigger {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -188,6 +188,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.acl-users {
|
||||
border-radius: @border-radius-box;
|
||||
|
@@ -73,11 +73,3 @@ export function deleteCIRelationView(firstCiId, secondCiId, 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>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-transfer {
|
||||
.ant-transfer-list {
|
||||
|
@@ -311,6 +311,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.cmdb-grant {
|
||||
position: relative;
|
||||
padding: 0 20px;
|
||||
@@ -323,6 +324,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-grant {
|
||||
.grant-button {
|
||||
|
@@ -59,6 +59,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.read-checkbox {
|
||||
.read-checkbox-half-checked {
|
||||
width: 16px;
|
||||
|
@@ -112,6 +112,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.notice-content {
|
||||
width: 100%;
|
||||
& &-main {
|
||||
@@ -185,6 +186,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.notice-content {
|
||||
.w-e-bar {
|
||||
|
@@ -95,12 +95,12 @@
|
||||
isFocusExpression = false
|
||||
}
|
||||
"
|
||||
:class="{ 'ci-searchform-expression': true, 'ci-searchform-expression-has-value': expression }"
|
||||
class="ci-searchform-expression"
|
||||
:style="{ width }"
|
||||
:placeholder="placeholder"
|
||||
@keyup.enter="emitRefresh"
|
||||
>
|
||||
<a-icon slot="suffix" type="check-circle" @click="handleCopyExpression" />
|
||||
<ops-icon slot="suffix" type="veops-copy" @click="handleCopyExpression" />
|
||||
</a-input>
|
||||
<slot></slot>
|
||||
</a-space>
|
||||
@@ -264,6 +264,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
@import '../../views/index.less';
|
||||
.ci-searchform-expression {
|
||||
> input {
|
||||
@@ -284,9 +285,6 @@ export default {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.ci-searchform-expression-has-value .ant-input-suffix {
|
||||
color: @func-color_3;
|
||||
}
|
||||
.cmdb-search-form {
|
||||
.ant-form-item-label {
|
||||
overflow: hidden;
|
||||
@@ -297,6 +295,8 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.search-form-bar {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
|
@@ -244,6 +244,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-subscribe-drawer {
|
||||
.cmdb-subscribe-drawer-container {
|
||||
@@ -314,6 +315,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
.cmdb-subscribe-drawer {
|
||||
.ant-tabs-bar {
|
||||
background-color: #custom_colors[color_2];
|
||||
|
@@ -194,10 +194,7 @@ const cmdb_en = {
|
||||
attributeAssociationTip3: 'Two Attributes must be selected',
|
||||
attributeAssociationTip4: 'Please select a attribute from Source 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: {
|
||||
unselectAttributes: 'Unselected',
|
||||
@@ -533,8 +530,7 @@ if __name__ == "__main__":
|
||||
peopleHasRead: 'Personnel authorized to read:',
|
||||
authorizationPolicy: 'CI Authorization Policy:',
|
||||
idAuthorizationPolicy: 'Authorized by node:',
|
||||
view: 'View permissions',
|
||||
searchTips: 'Search in service tree'
|
||||
view: 'View permissions'
|
||||
},
|
||||
tree: {
|
||||
tips1: 'Please go to Preference page first to complete your subscription!',
|
||||
|
@@ -194,10 +194,6 @@ const cmdb_zh = {
|
||||
attributeAssociationTip3: '属性关联必须选择两个属性',
|
||||
attributeAssociationTip4: '请选择原模型属性',
|
||||
attributeAssociationTip5: '请选择目标模型属性',
|
||||
show: '展示属性',
|
||||
setAsShow: '设置为展示属性',
|
||||
cancelSetAsShow: '取消设置为展示属性',
|
||||
showTips: '服务树和拓扑视图里节点的名称'
|
||||
},
|
||||
components: {
|
||||
unselectAttributes: '未选属性',
|
||||
@@ -533,8 +529,7 @@ if __name__ == "__main__":
|
||||
peopleHasRead: '当前有查看权限的人员:',
|
||||
authorizationPolicy: '实例授权策略:',
|
||||
idAuthorizationPolicy: '按节点授权的:',
|
||||
view: '查看权限',
|
||||
searchTips: '在服务树中筛选'
|
||||
view: '查看权限'
|
||||
},
|
||||
tree: {
|
||||
tips1: '请先到 我的订阅 页面完成订阅!',
|
||||
|
@@ -147,6 +147,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
@import '../index.less';
|
||||
.cmdb-batch-upload-label {
|
||||
color: @text-color_1;
|
||||
@@ -158,6 +159,7 @@ export default {
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-batch-upload {
|
||||
margin-bottom: -24px;
|
||||
|
@@ -113,6 +113,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-batch-upload-table {
|
||||
height: 200px;
|
||||
|
@@ -83,6 +83,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-batch-upload-dragger {
|
||||
height: auto;
|
||||
@@ -111,6 +112,7 @@ export default {
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-batch-upload-dragger {
|
||||
position: relative;
|
||||
|
@@ -101,6 +101,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.cmdb-batch-upload-result {
|
||||
.cmdb-batch-upload-result-content {
|
||||
|
@@ -55,6 +55,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.ci-detail-header {
|
||||
border-left: 3px solid @primary-color;
|
||||
|
@@ -992,6 +992,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.cmdb-ci {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
|
@@ -150,11 +150,11 @@ export default {
|
||||
computed: {
|
||||
topoData() {
|
||||
const ci_types_list = this.ci_types()
|
||||
const _findCiType = ci_types_list.find((item) => item.id === this.typeId)
|
||||
const unique_id = _findCiType.show_id || this.attributes().unique_id
|
||||
const unique_name = _findCiType.show_name || this.attributes().unique
|
||||
const unique_id = this.attributes().unique_id
|
||||
const unique_name = this.attributes().unique
|
||||
const _findUnique = this.attrList().find((attr) => attr.id === unique_id)
|
||||
const unique_alias = _findUnique?.alias || _findUnique?.name || ''
|
||||
const _findCiType = ci_types_list.find((item) => item.id === this.typeId)
|
||||
const nodes = {
|
||||
isRoot: true,
|
||||
id: `Root_${this.typeId}`,
|
||||
@@ -183,10 +183,6 @@ export default {
|
||||
this.parentCITypes.forEach((parent) => {
|
||||
const _findCiType = ci_types_list.find((item) => item.id === parent.id)
|
||||
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) => {
|
||||
nodes.children.push({
|
||||
id: `${parentCi._id}`,
|
||||
@@ -194,9 +190,9 @@ export default {
|
||||
title: parent.alias || parent.name,
|
||||
name: parent.name,
|
||||
side: 'left',
|
||||
unique_alias,
|
||||
unique_name,
|
||||
unique_value: parentCi[unique_name],
|
||||
unique_alias: parentCi.unique_alias,
|
||||
unique_name: parentCi.unique,
|
||||
unique_value: parentCi[parentCi.unique],
|
||||
children: [],
|
||||
icon: _findCiType?.icon || '',
|
||||
endpoints: [
|
||||
@@ -226,10 +222,6 @@ export default {
|
||||
this.childCITypes.forEach((child) => {
|
||||
const _findCiType = ci_types_list.find((item) => item.id === child.id)
|
||||
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) => {
|
||||
nodes.children.push({
|
||||
id: `${childCi._id}`,
|
||||
@@ -237,9 +229,9 @@ export default {
|
||||
title: child.alias || child.name,
|
||||
name: child.name,
|
||||
side: 'right',
|
||||
unique_alias,
|
||||
unique_name,
|
||||
unique_value: childCi[unique_name],
|
||||
unique_alias: childCi.unique_alias,
|
||||
unique_name: childCi.unique,
|
||||
unique_value: childCi[childCi.unique],
|
||||
children: [],
|
||||
icon: _findCiType?.icon || '',
|
||||
endpoints: [
|
||||
@@ -268,24 +260,6 @@ export default {
|
||||
})
|
||||
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: {
|
||||
attrList: { from: 'attrList' },
|
||||
@@ -304,7 +278,6 @@ export default {
|
||||
await Promise.all([this.getParentCITypes(), this.getChildCITypes()])
|
||||
Promise.all([this.getFirstCIs(), this.getSecondCIs()]).then(() => {
|
||||
if (isFirst && this.$refs.ciDetailRelationTopo) {
|
||||
this.$refs.ciDetailRelationTopo.exsited_ci = this.exsited_ci
|
||||
this.$refs.ciDetailRelationTopo.setTopoData(this.topoData)
|
||||
}
|
||||
})
|
||||
@@ -341,6 +314,7 @@ export default {
|
||||
secondCIs[item.ci_type] = [item]
|
||||
}
|
||||
})
|
||||
console.log(_.cloneDeep(secondCIs))
|
||||
this.secondCIs = secondCIs
|
||||
})
|
||||
.catch((e) => {})
|
||||
@@ -440,7 +414,6 @@ export default {
|
||||
handleChangeActiveKey(e) {
|
||||
if (e.target.value === '1') {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.ciDetailRelationTopo.exsited_ci = this.exsited_ci
|
||||
this.$refs.ciDetailRelationTopo.setTopoData(this.topoData)
|
||||
})
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
border-radius: 10px;
|
||||
padding: 4px 8px;
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
@@ -74,11 +74,13 @@
|
||||
}
|
||||
.root {
|
||||
width: 100px;
|
||||
border-color: @primary-color;
|
||||
font-weight: 700;
|
||||
background: #2f54eb;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-weight: 500;
|
||||
padding: 4px 8px;
|
||||
.title {
|
||||
color: @primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@
|
||||
import _ from 'lodash'
|
||||
import { TreeCanvas } from 'butterfly-dag'
|
||||
import { searchCIRelation } from '@/modules/cmdb/api/CIRelation'
|
||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||
import Node from './node.js'
|
||||
|
||||
import 'butterfly-dag/dist/index.css'
|
||||
@@ -88,7 +87,7 @@ export default {
|
||||
this.canvas.focusCenterWithAnimate()
|
||||
})
|
||||
},
|
||||
async redrawData(res, sourceNode, side) {
|
||||
redrawData(res, sourceNode, side) {
|
||||
const newNodes = []
|
||||
const newEdges = []
|
||||
if (!res.result.length) {
|
||||
@@ -96,24 +95,18 @@ export default {
|
||||
return
|
||||
}
|
||||
const ci_types_list = this.ci_types()
|
||||
for (let i = 0; i < res.result.length; i++) {
|
||||
const r = res.result[i]
|
||||
res.result.forEach((r) => {
|
||||
if (!this.exsited_ci.includes(r._id)) {
|
||||
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({
|
||||
id: `${r._id}`,
|
||||
Class: Node,
|
||||
title: r.ci_type_alias || r.ci_type,
|
||||
name: r.ci_type,
|
||||
side: side,
|
||||
unique_alias,
|
||||
unique_name,
|
||||
unique_value: r[unique_name],
|
||||
unique_alias: r.unique_alias,
|
||||
unique_name: r.unique,
|
||||
unique_value: r[r.unique],
|
||||
children: [],
|
||||
icon: _findCiType?.icon || '',
|
||||
endpoints: [
|
||||
@@ -138,8 +131,7 @@ export default {
|
||||
targetNode: side === 'right' ? `${r._id}` : sourceNode,
|
||||
type: 'endpoint',
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
const { nodes, edges } = this.canvas.getDataMap()
|
||||
// 删除原节点和边
|
||||
this.canvas.removeNodes(nodes.map((node) => node.id))
|
||||
|
@@ -204,6 +204,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
.attr-ad {
|
||||
position: relative;
|
||||
padding: 0 20px;
|
||||
|
@@ -10,7 +10,6 @@
|
||||
: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="isShowId">{{ $t('cmdb.ciType.show') }}</div>
|
||||
<template v-if="!isAdd">
|
||||
<a-tooltip :title="inherited ? $t('cmdb.ciType.inheritFrom', { name: property.inherited_from }) : ''">
|
||||
<div class="attribute-card-content">
|
||||
@@ -28,7 +27,6 @@
|
||||
<div
|
||||
class="attribute-card-trigger"
|
||||
v-if="(property.value_type === '3' || property.value_type === '4') && !isStore"
|
||||
:style="{ top: isShowId ? '18px' : '' }"
|
||||
>
|
||||
<a @click="openTrigger"><ops-icon type="ops-trigger"/></a>
|
||||
</div>
|
||||
@@ -66,24 +64,12 @@
|
||||
</a-space>
|
||||
</a-popover>
|
||||
|
||||
<a-space class="attribute-card-operation">
|
||||
<a v-if="!isStore && !inherited"><a-icon type="edit" @click="handleEdit"/></a>
|
||||
<a-tooltip
|
||||
v-if="
|
||||
!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-space class="attribute-card-operation" v-if="!inherited">
|
||||
<a v-if="!isStore"><a-icon type="edit" @click="handleEdit"/></a>
|
||||
<a-tooltip :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||
<a v-if="!isStore && property.is_computed"><a-icon type="redo" @click="handleCalcComputed"/></a>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-if="!isStore && property.is_computed" :title="$t('cmdb.ciType.computeForAllCITips')">
|
||||
<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 v-if="!isUnique" style="color:red;"><a-icon type="delete" @click="handleDelete"/></a>
|
||||
</a-space>
|
||||
</div>
|
||||
<TriggerForm ref="triggerForm" :CITypeId="CITypeId" />
|
||||
@@ -98,9 +84,17 @@
|
||||
<script>
|
||||
import { deleteCITypeAttributesById, deleteAttributesById, calcComputedAttribute } from '@/modules/cmdb/api/CITypeAttr'
|
||||
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 TriggerForm from './triggerForm.vue'
|
||||
import { updateCIType } from '@/modules/cmdb/api/CIType'
|
||||
export default {
|
||||
name: 'AttributeCard',
|
||||
inject: {
|
||||
@@ -108,14 +102,17 @@ export default {
|
||||
from: 'unique',
|
||||
default: () => undefined,
|
||||
},
|
||||
show_id: {
|
||||
from: 'show_id',
|
||||
default: () => undefined,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
ValueTypeIcon,
|
||||
TriggerForm,
|
||||
ops_default_show,
|
||||
ops_is_choice,
|
||||
ops_is_index,
|
||||
ops_is_link,
|
||||
ops_is_password,
|
||||
ops_is_sortable,
|
||||
ops_is_unique,
|
||||
},
|
||||
props: {
|
||||
property: {
|
||||
@@ -149,12 +146,6 @@ export default {
|
||||
}
|
||||
return false
|
||||
},
|
||||
isShowId() {
|
||||
if (this.show_id) {
|
||||
return this.property?.id === this.show_id()
|
||||
}
|
||||
return false
|
||||
},
|
||||
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>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.attribute-card {
|
||||
width: 182px;
|
||||
height: 80px;
|
||||
|
@@ -164,6 +164,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.attrbute-store-search {
|
||||
width: 300px;
|
||||
|
@@ -186,7 +186,6 @@ import {
|
||||
createCITypeGroupById,
|
||||
updateCITypeGroupById,
|
||||
getTriggerList,
|
||||
getCIType,
|
||||
} from '@/modules/cmdb/api/CIType'
|
||||
import {
|
||||
getCITypeAttributesById,
|
||||
@@ -232,7 +231,6 @@ export default {
|
||||
newGroupName: '',
|
||||
attrTypeFilter: [],
|
||||
unique: '',
|
||||
show_id: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -252,31 +250,20 @@ export default {
|
||||
unique: () => {
|
||||
return this.unique
|
||||
},
|
||||
show_id: () => {
|
||||
return this.show_id
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeCreate() {},
|
||||
created() {},
|
||||
mounted() {
|
||||
this.init()
|
||||
this.getCITypeGroupData()
|
||||
},
|
||||
methods: {
|
||||
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) {
|
||||
this.$refs.attributeEditForm.handleEdit(property, this.attributes)
|
||||
},
|
||||
handleOk() {
|
||||
this.init()
|
||||
this.getCITypeGroupData()
|
||||
},
|
||||
setOtherGroupAttributes() {
|
||||
const orderMap = this.attributes.reduce(function(map, obj) {
|
||||
@@ -604,6 +591,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.fold {
|
||||
width: calc(100% - 216px);
|
||||
display: inline-block;
|
||||
|
@@ -77,6 +77,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.citype-detail-title {
|
||||
border-left: 4px solid @primary-color;
|
||||
|
@@ -53,10 +53,11 @@
|
||||
</a-menu-item>
|
||||
<a-menu-item key="1">
|
||||
<a-space>
|
||||
<a href="/api/v0.1/ci_types/template/export/file">
|
||||
<a-icon type="download" /> {{ $t('download') }}
|
||||
</a></a-space
|
||||
>
|
||||
<a
|
||||
href="/api/v0.1/ci_types/template/export/file"
|
||||
><a-icon type="download" /> {{ $t('download') }}</a
|
||||
>
|
||||
</a-space>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
@@ -261,7 +262,6 @@
|
||||
'default_order_attr',
|
||||
{ rules: [{ required: false, message: $t('cmdb.ciType.selectDefaultOrderAttr') }] },
|
||||
]"
|
||||
:placeholder="$t('placeholder2')"
|
||||
>
|
||||
<el-option
|
||||
:key="item.name"
|
||||
@@ -299,7 +299,6 @@
|
||||
filterInput = ''
|
||||
}
|
||||
"
|
||||
@change="handleChangeUnique"
|
||||
>
|
||||
<el-option
|
||||
:key="item.id"
|
||||
@@ -314,40 +313,6 @@
|
||||
<a-divider type="vertical" />
|
||||
<a @click="handleCreatNewAttr">{{ $t('cmdb.ciType.notfound') }}</a>
|
||||
</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' }">
|
||||
<create-new-attribute
|
||||
ref="createNewAttribute"
|
||||
@@ -453,17 +418,14 @@ export default {
|
||||
addId: null,
|
||||
|
||||
filterInput: '',
|
||||
showIdFilterInput: '',
|
||||
|
||||
currentTypeAttrs: [],
|
||||
orderSelectionOptions: [],
|
||||
default_order_asc: '1',
|
||||
|
||||
allTreeDepAndEmp: [],
|
||||
|
||||
editCiType: null,
|
||||
isInherit: false,
|
||||
|
||||
unique_id: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -520,22 +482,6 @@ export default {
|
||||
}
|
||||
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() {
|
||||
return {
|
||||
@@ -713,7 +659,6 @@ export default {
|
||||
delete values.parent_ids
|
||||
await this.updateCIType(values.id, {
|
||||
...values,
|
||||
show_id: values.show_id || null,
|
||||
icon,
|
||||
})
|
||||
} else {
|
||||
@@ -919,8 +864,7 @@ export default {
|
||||
this.drawerTitle = this.$t('cmdb.ciType.editCIType')
|
||||
this.drawerVisible = true
|
||||
await getCITypeAttributesById(record.id).then((res) => {
|
||||
this.currentTypeAttrs = res.attributes
|
||||
this.unique_id = res.unique_id
|
||||
this.orderSelectionOptions = res.attributes.filter((item) => item.is_required)
|
||||
})
|
||||
await getCIType(record.id).then((res) => {
|
||||
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.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 })
|
||||
}
|
||||
},
|
||||
handleChangeUnique(value) {
|
||||
this.unique_id = value
|
||||
const show_id = this.form.getFieldValue('show_id')
|
||||
if (show_id === value) {
|
||||
this.form.setFieldsValue({ show_id: '' })
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.ci-types-wrap {
|
||||
margin: 0 0 -24px 0;
|
||||
.ci-types-empty {
|
||||
|
@@ -634,6 +634,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.auto-complete-wrapper {
|
||||
position: relative;
|
||||
|
@@ -142,6 +142,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.setting-discovery {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
|
@@ -313,6 +313,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.cmdb-adc {
|
||||
.cmdb-adc-group {
|
||||
margin-bottom: 20px;
|
||||
|
@@ -308,6 +308,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.model-relation {
|
||||
background-color: #fff;
|
||||
|
@@ -393,6 +393,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.cmdb-preference {
|
||||
margin: -24px;
|
||||
overflow: auto;
|
||||
|
@@ -11,14 +11,6 @@
|
||||
<template #one>
|
||||
<div class="relation-views-left" :style="{ height: `${windowHeight - 115}px` }">
|
||||
<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
|
||||
class="ops-list-batch-action"
|
||||
:style="{ marginBottom: '10px' }"
|
||||
@@ -55,7 +47,6 @@
|
||||
<span>{{ $t('selectRows', { rows: batchTreeKey.length }) }}</span>
|
||||
</div>
|
||||
<a-tree
|
||||
v-if="!isFullSearch"
|
||||
:selectedKeys="selectedKeys"
|
||||
:loadData="onLoadData"
|
||||
:treeData="treeData"
|
||||
@@ -64,10 +55,13 @@
|
||||
@drop="onDrop"
|
||||
:expandedKeys="expandedKeys"
|
||||
>
|
||||
<template #title="treeNodeData">
|
||||
<template #title="{ key: treeKey, title,number, isLeaf }">
|
||||
<ContextMenu
|
||||
:treeNodeData="treeNodeData"
|
||||
:title="title"
|
||||
:number="number"
|
||||
:treeKey="treeKey"
|
||||
:levels="levels"
|
||||
:isLeaf="isLeaf"
|
||||
:currentViews="relationViews.views[viewName]"
|
||||
:id2type="relationViews.id2type"
|
||||
@onContextMenuClick="onContextMenuClick"
|
||||
@@ -80,30 +74,6 @@
|
||||
/>
|
||||
</template>
|
||||
</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>
|
||||
</template>
|
||||
<template #two>
|
||||
@@ -372,6 +342,7 @@
|
||||
total,
|
||||
})
|
||||
"
|
||||
:style="{ alignSelf: 'flex-end', marginRight: '12px' }"
|
||||
>
|
||||
<template slot="buildOptionText" slot-scope="props">
|
||||
<span v-if="props.value !== '100000'">{{ props.value }}{{ $t('cmdb.history.itemsPerPage') }}</span>
|
||||
@@ -421,7 +392,6 @@ import {
|
||||
batchDeleteCIRelation,
|
||||
batchUpdateCIRelationChildren,
|
||||
addCIRelationView,
|
||||
searchCIRelationFull,
|
||||
} from '@/modules/cmdb/api/CIRelation'
|
||||
|
||||
import { getCITypeAttributesById } from '@/modules/cmdb/api/CITypeAttr'
|
||||
@@ -519,13 +489,9 @@ export default {
|
||||
|
||||
statisticsObj: {},
|
||||
viewOption: {},
|
||||
loadRootStatisticsParams: {},
|
||||
fullSearchValue: '',
|
||||
isFullSearch: false,
|
||||
fullTreeData: [],
|
||||
filterFullTreeData: [],
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
windowHeight() {
|
||||
return this.$store.state.windowHeight
|
||||
@@ -534,6 +500,9 @@ export default {
|
||||
return this.windowHeight - 244
|
||||
},
|
||||
selectedKeys() {
|
||||
if (this.treeKeys.length <= 1) {
|
||||
return this.treeKeys.map((item) => `@^@${item}`)
|
||||
}
|
||||
return [this.treeKeys.join('@^@')]
|
||||
},
|
||||
isLeaf() {
|
||||
@@ -607,7 +576,7 @@ export default {
|
||||
this.reload()
|
||||
},
|
||||
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()
|
||||
},
|
||||
|
||||
async loadData({ parameter, refreshType = undefined, sortByTable = undefined } = {}) {
|
||||
async loadData(parameter, refreshType = undefined, sortByTable = undefined) {
|
||||
// refreshType='refreshNumber' 树图只更新number
|
||||
const params = Object.assign(parameter || {}, (this.$refs.search || {}).queryParam)
|
||||
let q = ''
|
||||
@@ -655,6 +624,8 @@ export default {
|
||||
|
||||
const exp = expression.match(regQ) ? expression.match(regQ)[0] : null
|
||||
if (exp) {
|
||||
// exp = exp.replace(/(\:)/g, '$1*')
|
||||
// exp = exp.replace(/(\,)/g, '*$1')
|
||||
q = `${q},${exp}`
|
||||
}
|
||||
|
||||
@@ -685,9 +656,38 @@ export default {
|
||||
}
|
||||
|
||||
if (this.treeKeys.length === 0) {
|
||||
if (!refreshType && !this.isFullSearch) {
|
||||
// await this.judgeCITypes(q)
|
||||
if (!refreshType) {
|
||||
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 {
|
||||
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(',')}`
|
||||
if (!refreshType && !this.isFullSearch) {
|
||||
if (!refreshType) {
|
||||
this.loadNoRoot(this.treeKeys[this.treeKeys.length - 1], level)
|
||||
}
|
||||
const fuzzySearch = (this.$refs['search'] || {}).fuzzySearch || ''
|
||||
@@ -812,6 +812,9 @@ export default {
|
||||
this.selectedRowKeys = []
|
||||
this.currentTypeId = [typeId]
|
||||
this.loadColumns()
|
||||
// this.$nextTick(() => {
|
||||
// this.refreshTable()
|
||||
// })
|
||||
},
|
||||
|
||||
async judgeCITypes() {
|
||||
@@ -851,6 +854,64 @@ export default {
|
||||
this.currentTypeId = [this.showTypeIds[0]]
|
||||
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() {
|
||||
@@ -858,41 +919,29 @@ export default {
|
||||
const facet = []
|
||||
const ciIds = []
|
||||
res.result.forEach((item) => {
|
||||
const showName = this.relationViews.id2type[item._type]?.show_name ?? null
|
||||
facet.push({
|
||||
showName,
|
||||
showNameValue: item[showName] ?? null,
|
||||
uniqueValue: item[item.unique],
|
||||
number: 0,
|
||||
ciId: item._id,
|
||||
typeId: item._type,
|
||||
unique: item.unique,
|
||||
})
|
||||
facet.push([item[item.unique], 0, item._id, item._type, item.unique])
|
||||
ciIds.push(item._id)
|
||||
})
|
||||
|
||||
const leafId = this.leaf[0]
|
||||
let level = 0
|
||||
this.levels.forEach((item, idx) => {
|
||||
if (item.includes(leafId)) {
|
||||
level = idx + 1
|
||||
}
|
||||
})
|
||||
const params = {
|
||||
level,
|
||||
root_ids: ciIds.join(','),
|
||||
has_m2m: Number(Object.values(this.level2constraint).includes('2')),
|
||||
}
|
||||
this.loadRootStatisticsParams = params
|
||||
await statisticsCIRelation({
|
||||
...params,
|
||||
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] + '']
|
||||
const promises = this.leaf.map((leafId) => {
|
||||
let level = 0
|
||||
this.levels.forEach((item, idx) => {
|
||||
if (item.includes(leafId)) {
|
||||
level = idx + 1
|
||||
}
|
||||
})
|
||||
return statisticsCIRelation({
|
||||
root_ids: ciIds.join(','),
|
||||
level: level,
|
||||
type_ids: this.leaf2showTypes[this.leaf[0]].join(','),
|
||||
has_m2m: Number(Object.values(this.level2constraint).includes('2')),
|
||||
descendant_ids: this.descendant_ids_for_statistics,
|
||||
}).then((num) => {
|
||||
facet.forEach((item, idx) => {
|
||||
item[1] += num[ciIds[idx] + '']
|
||||
})
|
||||
})
|
||||
})
|
||||
await Promise.all(promises)
|
||||
this.wrapTreeData(facet)
|
||||
// default select first node
|
||||
this.onNodeClick(this.treeData[0].key)
|
||||
@@ -927,16 +976,7 @@ export default {
|
||||
const facet = []
|
||||
const ciIds = []
|
||||
res.result.forEach((item) => {
|
||||
const showName = this.relationViews.id2type[item._type]?.show_name ?? null
|
||||
facet.push({
|
||||
showName,
|
||||
showNameValue: item[showName] ?? null,
|
||||
uniqueValue: item[item.unique],
|
||||
number: 0,
|
||||
ciId: item._id,
|
||||
typeId: item._type,
|
||||
unique: item.unique,
|
||||
})
|
||||
facet.push([item[item.unique], 0, item._id, item._type, item.unique])
|
||||
ciIds.push(item._id)
|
||||
})
|
||||
let ancestor_ids
|
||||
@@ -958,7 +998,7 @@ export default {
|
||||
descendant_ids: this.descendant_ids_for_statistics,
|
||||
}).then((num) => {
|
||||
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
|
||||
if (keys) {
|
||||
const _tempKeys = keys.split('@^@').filter((item) => item !== '')
|
||||
@@ -988,9 +1028,6 @@ export default {
|
||||
}
|
||||
|
||||
this.refreshTable()
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
wrapTreeData(facet) {
|
||||
if (this.triggerSelect) {
|
||||
@@ -998,15 +1035,12 @@ export default {
|
||||
}
|
||||
const treeData = []
|
||||
facet.forEach((item) => {
|
||||
const _treeKeys = _.cloneDeep(this.treeKeys)
|
||||
_treeKeys.push(item.ciId + '%' + item.typeId + '%' + `{"${item.unique}":"${item.uniqueValue}"}`)
|
||||
treeData.push({
|
||||
title: item.showName ? item.showNameValue : item.uniqueValue,
|
||||
number: item.number,
|
||||
key: _treeKeys.join('@^@'),
|
||||
isLeaf: this.leaf.includes(item.typeId),
|
||||
id: item.ciId,
|
||||
showName: item.showName,
|
||||
title: item[0],
|
||||
number: item[1],
|
||||
key: this.treeKeys.join('@^@') + '@^@' + item[2] + '%' + item[3] + '%' + `{"${item[4]}":"${item[0]}"}`,
|
||||
isLeaf: this.leaf.includes(item[3]),
|
||||
id: item[2],
|
||||
})
|
||||
})
|
||||
if (this.treeNode === null) {
|
||||
@@ -1026,6 +1060,7 @@ export default {
|
||||
}
|
||||
this.treeKeys = treeNode.eventKey.split('@^@').filter((item) => item !== '')
|
||||
this.treeNode = treeNode
|
||||
// this.refreshTable()
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
@@ -1193,7 +1228,7 @@ export default {
|
||||
that.$refs.xTable.clearCheckboxRow()
|
||||
that.$refs.xTable.clearCheckboxReserve()
|
||||
that.selectedRowKeys = []
|
||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
that.loadData({}, 'refreshNumber')
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -1206,7 +1241,9 @@ export default {
|
||||
const _splitTargetKey = targetKey.split('@^@').filter((item) => item !== '')
|
||||
if (_splitDragKey.length - 1 === _splitTargetKey.length) {
|
||||
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]
|
||||
// TODO 拖拽这里不造咋弄 等等再说吧
|
||||
batchUpdateCIRelationChildren([dragId], [targetId]).then((res) => {
|
||||
this.reload()
|
||||
})
|
||||
@@ -1241,7 +1278,7 @@ export default {
|
||||
this.sortByTable = sortByTable
|
||||
this.$nextTick(() => {
|
||||
if (this.pageNo === 1) {
|
||||
this.loadData({ params: {}, refreshType: undefined, sortByTable })
|
||||
this.loadData({}, undefined, sortByTable)
|
||||
} else {
|
||||
this.pageNo = 1
|
||||
}
|
||||
@@ -1400,7 +1437,7 @@ export default {
|
||||
onOk() {
|
||||
deleteCI(record.ci_id || record._id).then((res) => {
|
||||
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) => {
|
||||
setTimeout(() => {
|
||||
this.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
this.loadData({}, 'refreshNumber')
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
@@ -1458,7 +1495,7 @@ export default {
|
||||
.finally(() => {
|
||||
that.loading = false
|
||||
setTimeout(() => {
|
||||
that.loadData({ params: {} })
|
||||
that.loadData({})
|
||||
}, 800)
|
||||
})
|
||||
},
|
||||
@@ -1521,7 +1558,7 @@ export default {
|
||||
that.selectedRowKeys = []
|
||||
that.$refs.xTable.clearCheckboxRow()
|
||||
that.$refs.xTable.clearCheckboxReserve()
|
||||
that.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
that.loadData({}, 'refreshNumber')
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -1531,6 +1568,7 @@ export default {
|
||||
},
|
||||
jsonEditorOk(row, column, jsonData) {
|
||||
// 后端写数据有快慢,不拉接口直接修改table的数据
|
||||
// this.reloadData()
|
||||
this.instanceList.forEach((item) => {
|
||||
if (item._id === row._id) {
|
||||
item[column.property] = JSON.stringify(jsonData)
|
||||
@@ -1539,7 +1577,7 @@ export default {
|
||||
this.$refs.xTable.refreshColumn()
|
||||
},
|
||||
relationViewRefreshNumber() {
|
||||
this.loadData({ params: {}, refreshType: 'refreshNumber' })
|
||||
this.loadData({}, 'refreshNumber')
|
||||
},
|
||||
onShowSizeChange(current, pageSize) {
|
||||
this.pageSize = pageSize
|
||||
@@ -1716,9 +1754,11 @@ export default {
|
||||
return node[i]
|
||||
}
|
||||
if (node[i].children && node[i].children.length) {
|
||||
const found = this.findNode(node[i].children, target)
|
||||
if (found) {
|
||||
return found
|
||||
for (let i = 0; i < node[i].children.length; i++) {
|
||||
const found = this.findNode(node[i].children, target)
|
||||
if (found) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1731,85 +1771,13 @@ export default {
|
||||
}
|
||||
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>
|
||||
|
||||
<style lang="less">
|
||||
@import '../index.less';
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.relation-views-wrapper {
|
||||
width: 100%;
|
||||
@@ -1852,18 +1820,6 @@ export default {
|
||||
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 {
|
||||
width: 100%;
|
||||
|
@@ -27,13 +27,7 @@
|
||||
/>
|
||||
<span class="relation-views-node-icon" v-else>{{ icon ? icon[0].toUpperCase() : 'i' }}</span>
|
||||
</template>
|
||||
<span
|
||||
class="relation-views-node-title"
|
||||
v-if="!isEditNodeName"
|
||||
:title="title"
|
||||
v-highlight="{ value: fullSearchValue, class: 'relation-views-node-title-highlight' }"
|
||||
>{{ title }}
|
||||
</span>
|
||||
<span class="relation-views-node-title" v-if="!isEditNodeName" :title="title">{{ title }}</span>
|
||||
<a-input
|
||||
ref="input"
|
||||
@blur="changeNodeName"
|
||||
@@ -73,7 +67,10 @@
|
||||
key="editNodeName"
|
||||
><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 v-else>
|
||||
<a-menu-item
|
||||
@@ -106,17 +103,20 @@
|
||||
|
||||
<script>
|
||||
import { updateCI } from '../../../api/ci.js'
|
||||
import highlight from '@/directive/highlight'
|
||||
|
||||
export default {
|
||||
name: 'ContextMenu',
|
||||
directives: {
|
||||
highlight,
|
||||
},
|
||||
props: {
|
||||
treeNodeData: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
number: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
treeKey: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
levels: {
|
||||
type: Array,
|
||||
@@ -130,6 +130,10 @@ export default {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
isLeaf: {
|
||||
type: Boolean,
|
||||
default: () => false,
|
||||
},
|
||||
ciTypeIcons: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
@@ -142,10 +146,6 @@ export default {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
fullSearchValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -201,21 +201,6 @@ export default {
|
||||
showCheckbox() {
|
||||
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: {
|
||||
onContextMenuClick(treeKey, menuKey) {
|
||||
@@ -245,11 +230,8 @@ export default {
|
||||
.split('%')
|
||||
const unique = Object.keys(JSON.parse(ci[2]))[0]
|
||||
const ciId = Number(ci[0])
|
||||
let editAttrName = unique
|
||||
if (this.showName) {
|
||||
editAttrName = this.showName
|
||||
}
|
||||
updateCI(ciId, { [editAttrName]: value }).then((res) => {
|
||||
|
||||
updateCI(ciId, { [unique]: value }).then((res) => {
|
||||
this.$message.success(this.$t('updateSuccess'))
|
||||
this.$emit('updateTreeData', ciId, value)
|
||||
})
|
||||
@@ -262,6 +244,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.relation-views-node {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
@@ -330,9 +314,7 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.relation-views-node-title-highlight {
|
||||
color: @func-color_1;
|
||||
}
|
||||
@import '~@/style/static.less';
|
||||
.relation-views-left {
|
||||
ul:has(.relation-views-node-checkbox) > li > ul {
|
||||
margin-left: 26px;
|
||||
|
@@ -535,6 +535,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.resource-search {
|
||||
margin-bottom: -24px;
|
||||
|
@@ -50,6 +50,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.tree-views-node {
|
||||
width: 100%;
|
||||
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 user from './global/user'
|
||||
import routes from './global/routes'
|
||||
import logo from './global/logo'
|
||||
import notice from './global/notice'
|
||||
import getters from './global/getters'
|
||||
import appConfig from '@/config/app'
|
||||
@@ -16,6 +17,7 @@ const store = new Vuex.Store({
|
||||
app,
|
||||
user,
|
||||
routes,
|
||||
logo,
|
||||
notice
|
||||
},
|
||||
state: {
|
||||
|
@@ -1352,11 +1352,3 @@ body {
|
||||
.ant-tree li .ant-tree-node-content-wrapper:hover {
|
||||
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部门员工树
|
||||
export const formatOption = (data, idType = 1, isDisabledAllCompany, departmentKey = 'department_id', employeeKey = 'employee_id') => {
|
||||
// idType 1 表示 员工id为`${departmentKey}-${employeeKey}`
|
||||
// 2 表示 department-${departmentKey} employee-${employeeKey}
|
||||
// 3 表示 departmentKey employeeKey
|
||||
// idType 1 表示 员工id为`${department_id}-${employee_id}`
|
||||
// 2 表示 department-${department_id} employee-${employee_id}
|
||||
let _data = _.cloneDeep(data)
|
||||
_data = _data.filter((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) => {
|
||||
if (isDisabledAllCompany) {
|
||||
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.children = [
|
||||
...formatOption(
|
||||
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,
|
||||
isDisabledAllCompany,
|
||||
@@ -161,7 +153,7 @@ export const formatOption = (data, idType = 1, isDisabledAllCompany, departmentK
|
||||
employeeKey
|
||||
),
|
||||
...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>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
|
||||
.notice-center-left {
|
||||
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">
|
||||
<SpanTitle>{{ $t('cs.companyInfo.spanCompany') }}</SpanTitle>
|
||||
<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 :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>
|
||||
<SpanTitle>{{ $t('cs.companyInfo.spanAddress') }}</SpanTitle>
|
||||
<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 :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 :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 :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>
|
||||
<SpanTitle>{{ $t('cs.companyInfo.spanContract') }}</SpanTitle>
|
||||
<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 :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 :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 :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>
|
||||
<SpanTitle>{{ $t('cs.companyInfo.spanLogo') }}</SpanTitle>
|
||||
<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 :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 :wrapper-col="{ span: 14, offset: 3 }" v-if="isEditable">
|
||||
<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-form-model-item>
|
||||
</a-form-model>
|
||||
<edit-image
|
||||
v-if="showEditImage"
|
||||
:show="showEditImage"
|
||||
:image="editImage"
|
||||
:title="eidtImageOption.title"
|
||||
:eidtImageOption="eidtImageOption"
|
||||
@save="submitImage"
|
||||
@close="showEditImage = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
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 EditImage from '../components/EditImage.vue'
|
||||
import { mixinPermissions } from '@/utils/mixin'
|
||||
|
||||
export default {
|
||||
name: 'CompanyInfo',
|
||||
mixins: [mixinPermissions],
|
||||
components: { SpanTitle },
|
||||
components: { SpanTitle, EditImage },
|
||||
data() {
|
||||
return {
|
||||
labelCol: { span: 3 },
|
||||
@@ -74,10 +152,14 @@ export default {
|
||||
phone: '',
|
||||
faxCode: '',
|
||||
email: '',
|
||||
logoName: '',
|
||||
smallLogoName: '',
|
||||
messenger: '',
|
||||
domainName: '',
|
||||
},
|
||||
getId: -1,
|
||||
showEditImage: false,
|
||||
editImage: null
|
||||
}
|
||||
},
|
||||
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: {
|
||||
...mapMutations(['SET_FILENAME', 'SET_SMALL_FILENAME']),
|
||||
deleteLogo() {
|
||||
this.infoData.logoName = ''
|
||||
},
|
||||
deleteSmallLogo() {
|
||||
this.infoData.smallLogoName = ''
|
||||
},
|
||||
async onSubmit() {
|
||||
this.$refs.infoData.validate(async (valid) => {
|
||||
if (valid) {
|
||||
@@ -138,6 +238,8 @@ export default {
|
||||
} else {
|
||||
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'))
|
||||
} else {
|
||||
this.$message.warning(this.$t('cs.companyInfo.checkInputCorrect'))
|
||||
@@ -157,10 +259,70 @@ export default {
|
||||
phone: '',
|
||||
faxCode: '',
|
||||
email: '',
|
||||
logoName: '',
|
||||
smallLogoName: '',
|
||||
messenger: '',
|
||||
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>
|
||||
@@ -169,7 +331,7 @@ export default {
|
||||
.ops-setting-companyinfo {
|
||||
padding-top: 15px;
|
||||
background-color: #fff;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
overflow: auto;
|
||||
margin-bottom: -24px;
|
||||
.ops-setting-companyinfo-upload-show {
|
||||
|
@@ -155,6 +155,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '~@/style/static.less';
|
||||
ul,
|
||||
li {
|
||||
list-style: none;
|
||||
|
@@ -862,13 +862,14 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.ops-setting-structure {
|
||||
margin-bottom: -24px;
|
||||
width: 100%;
|
||||
.ops-setting-structure-sidebar {
|
||||
height: 100%;
|
||||
padding: 15px;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
overflow-y: hidden;
|
||||
&:hover {
|
||||
overflow-y: overlay;
|
||||
@@ -1025,7 +1026,7 @@ export default {
|
||||
padding: 12px;
|
||||
background-color: #fff;
|
||||
overflow-y: auto;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
.ops-setting-structure-main-controller {
|
||||
// height: 70px;
|
||||
margin-bottom: 12px;
|
||||
|
@@ -64,6 +64,7 @@ name: 'SearchForm',
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.search-form-bar-filter {
|
||||
background-color: rgb(240, 245, 255);
|
||||
.ops_display_wrapper();
|
||||
|
@@ -137,7 +137,7 @@ export default {
|
||||
padding-top: 15px;
|
||||
overflow: auto;
|
||||
margin-bottom: -24px;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
.notice-dingding-wrapper-tips {
|
||||
display: inline-block;
|
||||
background-color: #ffdfdf;
|
||||
|
@@ -117,7 +117,7 @@ export default {
|
||||
padding-top: 15px;
|
||||
overflow: auto;
|
||||
margin-bottom: -24px;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
.notice-feishu-wrapper-tips {
|
||||
display: inline-block;
|
||||
background-color: #ffdfdf;
|
||||
|
@@ -138,7 +138,7 @@ export default {
|
||||
padding-top: 15px;
|
||||
overflow: auto;
|
||||
margin-bottom: -24px;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
.notice-wx-wrapper-tips {
|
||||
display: inline-block;
|
||||
background-color: #ffdfdf;
|
||||
|
@@ -354,6 +354,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~@/style/static.less';
|
||||
.setting-person {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -362,7 +363,7 @@ export default {
|
||||
height: 400px;
|
||||
margin-right: 24px;
|
||||
background-color: #fff;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
padding-top: 15px;
|
||||
.setting-person-left-item {
|
||||
cursor: pointer;
|
||||
@@ -387,7 +388,7 @@ export default {
|
||||
width: 800px;
|
||||
height: 700px;
|
||||
background-color: #fff;
|
||||
border-radius: @border-radius-box;
|
||||
border-radius: 15px;
|
||||
padding: 24px 48px;
|
||||
.setting-person-right-disabled {
|
||||
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: {
|
||||
disableHostCheck: true,
|
||||
port: process.env.DEV_PORT || 8000,
|
||||
|
@@ -32,8 +32,6 @@ services:
|
||||
container_name: cmdb-cache
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
volumes:
|
||||
- cache-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
@@ -45,7 +43,7 @@ services:
|
||||
- redis
|
||||
|
||||
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:
|
||||
# context: .
|
||||
# target: cmdb-api
|
||||
@@ -68,6 +66,9 @@ services:
|
||||
flask common-check-new-columns
|
||||
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 acl_async --logfile=one_acl_async.log --autoscale=2,1 -D
|
||||
|
||||
@@ -84,7 +85,7 @@ services:
|
||||
- cmdb-api
|
||||
|
||||
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:
|
||||
# context: .
|
||||
# target: cmdb-ui
|
||||
@@ -112,9 +113,6 @@ volumes:
|
||||
db-data:
|
||||
driver: local
|
||||
name: cmdb_db-data
|
||||
cache-data:
|
||||
driver: local
|
||||
name: cmdb_cache-data
|
||||
|
||||
networks:
|
||||
new:
|
||||
|