mirror of https://github.com/veops/cmdb.git
feat: dynamic attribute (#534)
This commit is contained in:
parent
1a774490ac
commit
fa737e75c3
|
@ -383,12 +383,12 @@ class CIManager(object):
|
||||||
computed_attrs.append(attr.to_dict())
|
computed_attrs.append(attr.to_dict())
|
||||||
elif attr.is_password:
|
elif attr.is_password:
|
||||||
if attr.name in ci_dict:
|
if attr.name in ci_dict:
|
||||||
password_dict[attr.id] = ci_dict.pop(attr.name)
|
password_dict[attr.id] = (ci_dict.pop(attr.name), attr.is_dynamic)
|
||||||
elif attr.alias in ci_dict:
|
elif attr.alias in ci_dict:
|
||||||
password_dict[attr.id] = ci_dict.pop(attr.alias)
|
password_dict[attr.id] = (ci_dict.pop(attr.alias), attr.is_dynamic)
|
||||||
|
|
||||||
if attr.re_check and password_dict.get(attr.id):
|
if attr.re_check and password_dict.get(attr.id):
|
||||||
value_manager.check_re(attr.re_check, password_dict[attr.id])
|
value_manager.check_re(attr.re_check, password_dict[attr.id][0])
|
||||||
|
|
||||||
if computed_attrs:
|
if computed_attrs:
|
||||||
value_manager.handle_ci_compute_attributes(ci_dict, computed_attrs, ci)
|
value_manager.handle_ci_compute_attributes(ci_dict, computed_attrs, ci)
|
||||||
|
@ -421,7 +421,8 @@ class CIManager(object):
|
||||||
operate_type = OperateType.UPDATE if ci is not None else OperateType.ADD
|
operate_type = OperateType.UPDATE if ci is not None else OperateType.ADD
|
||||||
try:
|
try:
|
||||||
ci = ci or CI.create(type_id=ci_type.id, is_auto_discovery=is_auto_discovery)
|
ci = ci or CI.create(type_id=ci_type.id, is_auto_discovery=is_auto_discovery)
|
||||||
record_id = value_manager.create_or_update_attr_value(ci, ci_dict, key2attr, ticket_id=ticket_id)
|
record_id, has_dynamic = value_manager.create_or_update_attr_value(
|
||||||
|
ci, ci_dict, key2attr, ticket_id=ticket_id)
|
||||||
except BadRequest as e:
|
except BadRequest as e:
|
||||||
if existed is None:
|
if existed is None:
|
||||||
cls.delete(ci.id)
|
cls.delete(ci.id)
|
||||||
|
@ -431,7 +432,7 @@ class CIManager(object):
|
||||||
for attr_id in password_dict:
|
for attr_id in password_dict:
|
||||||
record_id = cls.save_password(ci.id, attr_id, password_dict[attr_id], record_id, ci_type.id)
|
record_id = cls.save_password(ci.id, attr_id, password_dict[attr_id], record_id, ci_type.id)
|
||||||
|
|
||||||
if record_id: # has change
|
if record_id or has_dynamic: # has change
|
||||||
ci_cache.apply_async(args=(ci.id, operate_type, record_id), queue=CMDB_QUEUE)
|
ci_cache.apply_async(args=(ci.id, operate_type, record_id), queue=CMDB_QUEUE)
|
||||||
|
|
||||||
if ref_ci_dict: # add relations
|
if ref_ci_dict: # add relations
|
||||||
|
@ -440,7 +441,6 @@ class CIManager(object):
|
||||||
return ci.id
|
return ci.id
|
||||||
|
|
||||||
def update(self, ci_id, _is_admin=False, ticket_id=None, __sync=False, **ci_dict):
|
def update(self, ci_id, _is_admin=False, ticket_id=None, __sync=False, **ci_dict):
|
||||||
current_app.logger.info((ci_id, ci_dict, __sync))
|
|
||||||
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
ci = self.confirm_ci_existed(ci_id)
|
ci = self.confirm_ci_existed(ci_id)
|
||||||
|
|
||||||
|
@ -465,12 +465,12 @@ class CIManager(object):
|
||||||
computed_attrs.append(attr.to_dict())
|
computed_attrs.append(attr.to_dict())
|
||||||
elif attr.is_password:
|
elif attr.is_password:
|
||||||
if attr.name in ci_dict:
|
if attr.name in ci_dict:
|
||||||
password_dict[attr.id] = ci_dict.pop(attr.name)
|
password_dict[attr.id] = (ci_dict.pop(attr.name), attr.is_dynamic)
|
||||||
elif attr.alias in ci_dict:
|
elif attr.alias in ci_dict:
|
||||||
password_dict[attr.id] = ci_dict.pop(attr.alias)
|
password_dict[attr.id] = (ci_dict.pop(attr.alias), attr.is_dynamic)
|
||||||
|
|
||||||
if attr.re_check and password_dict.get(attr.id):
|
if attr.re_check and password_dict.get(attr.id):
|
||||||
value_manager.check_re(attr.re_check, password_dict[attr.id])
|
value_manager.check_re(attr.re_check, password_dict[attr.id][0])
|
||||||
|
|
||||||
if computed_attrs:
|
if computed_attrs:
|
||||||
value_manager.handle_ci_compute_attributes(ci_dict, computed_attrs, ci)
|
value_manager.handle_ci_compute_attributes(ci_dict, computed_attrs, ci)
|
||||||
|
@ -495,7 +495,8 @@ class CIManager(object):
|
||||||
ci_dict.pop(k)
|
ci_dict.pop(k)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
record_id = value_manager.create_or_update_attr_value(ci, ci_dict, key2attr, ticket_id=ticket_id)
|
record_id, has_dynamic = value_manager.create_or_update_attr_value(
|
||||||
|
ci, ci_dict, key2attr, ticket_id=ticket_id)
|
||||||
except BadRequest as e:
|
except BadRequest as e:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
@ -503,25 +504,25 @@ class CIManager(object):
|
||||||
for attr_id in password_dict:
|
for attr_id in password_dict:
|
||||||
record_id = self.save_password(ci.id, attr_id, password_dict[attr_id], record_id, ci.type_id)
|
record_id = self.save_password(ci.id, attr_id, password_dict[attr_id], record_id, ci.type_id)
|
||||||
|
|
||||||
if record_id: # has change
|
if record_id or has_dynamic: # has change
|
||||||
if not __sync:
|
if not __sync:
|
||||||
ci_cache.apply_async(args=(ci_id, OperateType.UPDATE, record_id), queue=CMDB_QUEUE)
|
ci_cache.apply_async(args=(ci_id, OperateType.UPDATE, record_id), queue=CMDB_QUEUE)
|
||||||
else:
|
else:
|
||||||
ci_cache((ci_id, OperateType.UPDATE, record_id))
|
ci_cache(ci_id, OperateType.UPDATE, record_id)
|
||||||
|
|
||||||
ref_ci_dict = {k: v for k, v in ci_dict.items() if k.startswith("$") and "." in k}
|
ref_ci_dict = {k: v for k, v in ci_dict.items() if k.startswith("$") and "." in k}
|
||||||
if ref_ci_dict:
|
if ref_ci_dict:
|
||||||
if not __sync:
|
if not __sync:
|
||||||
ci_relation_add.apply_async(args=(ref_ci_dict, ci.id), queue=CMDB_QUEUE)
|
ci_relation_add.apply_async(args=(ref_ci_dict, ci.id), queue=CMDB_QUEUE)
|
||||||
else:
|
else:
|
||||||
ci_relation_add((ref_ci_dict, ci.id))
|
ci_relation_add(ref_ci_dict, ci.id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_unique_value(ci_id, unique_name, unique_value):
|
def update_unique_value(ci_id, unique_name, unique_value):
|
||||||
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
ci = CI.get_by_id(ci_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(ci_id)))
|
||||||
|
|
||||||
key2attr = {unique_name: AttributeCache.get(unique_name)}
|
key2attr = {unique_name: AttributeCache.get(unique_name)}
|
||||||
record_id = AttributeValueManager().create_or_update_attr_value(ci, {unique_name: unique_value}, key2attr)
|
record_id, _ = AttributeValueManager().create_or_update_attr_value(ci, {unique_name: unique_value}, key2attr)
|
||||||
|
|
||||||
ci_cache.apply_async(args=(ci_id, OperateType.UPDATE, record_id), queue=CMDB_QUEUE)
|
ci_cache.apply_async(args=(ci_id, OperateType.UPDATE, record_id), queue=CMDB_QUEUE)
|
||||||
|
|
||||||
|
@ -761,6 +762,7 @@ class CIManager(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def save_password(cls, ci_id, attr_id, value, record_id, type_id):
|
def save_password(cls, ci_id, attr_id, value, record_id, type_id):
|
||||||
|
value, is_dynamic = value
|
||||||
changed = None
|
changed = None
|
||||||
encrypt_value = None
|
encrypt_value = None
|
||||||
value_table = ValueTypeMap.table[ValueTypeEnum.PASSWORD]
|
value_table = ValueTypeMap.table[ValueTypeEnum.PASSWORD]
|
||||||
|
@ -777,13 +779,17 @@ class CIManager(object):
|
||||||
if existed is None:
|
if existed is None:
|
||||||
if value:
|
if value:
|
||||||
value_table.create(ci_id=ci_id, attr_id=attr_id, value=encrypt_value)
|
value_table.create(ci_id=ci_id, attr_id=attr_id, value=encrypt_value)
|
||||||
|
if not is_dynamic:
|
||||||
changed = [(ci_id, attr_id, OperateType.ADD, '', PASSWORD_DEFAULT_SHOW, type_id)]
|
changed = [(ci_id, attr_id, OperateType.ADD, '', PASSWORD_DEFAULT_SHOW, type_id)]
|
||||||
elif existed.value != encrypt_value:
|
elif existed.value != encrypt_value:
|
||||||
if value:
|
if value:
|
||||||
existed.update(ci_id=ci_id, attr_id=attr_id, value=encrypt_value)
|
existed.update(ci_id=ci_id, attr_id=attr_id, value=encrypt_value)
|
||||||
changed = [(ci_id, attr_id, OperateType.UPDATE, PASSWORD_DEFAULT_SHOW, PASSWORD_DEFAULT_SHOW, type_id)]
|
if not is_dynamic:
|
||||||
|
changed = [(ci_id, attr_id, OperateType.UPDATE, PASSWORD_DEFAULT_SHOW,
|
||||||
|
PASSWORD_DEFAULT_SHOW, type_id)]
|
||||||
else:
|
else:
|
||||||
existed.delete()
|
existed.delete()
|
||||||
|
if not is_dynamic:
|
||||||
changed = [(ci_id, attr_id, OperateType.DELETE, PASSWORD_DEFAULT_SHOW, '', type_id)]
|
changed = [(ci_id, attr_id, OperateType.DELETE, PASSWORD_DEFAULT_SHOW, '', type_id)]
|
||||||
|
|
||||||
if current_app.config.get('SECRETS_ENGINE') == 'vault':
|
if current_app.config.get('SECRETS_ENGINE') == 'vault':
|
||||||
|
|
|
@ -856,7 +856,9 @@ class CITypeRelationManager(object):
|
||||||
if ci_type is None:
|
if ci_type is None:
|
||||||
return nodes, edges
|
return nodes, edges
|
||||||
|
|
||||||
nodes.append(ci_type.to_dict())
|
ci_type_dict = ci_type.to_dict()
|
||||||
|
ci_type_dict.setdefault('level', [0])
|
||||||
|
nodes.append(ci_type_dict)
|
||||||
node_ids.add(ci_type.id)
|
node_ids.add(ci_type.id)
|
||||||
|
|
||||||
def _find(_id, lv):
|
def _find(_id, lv):
|
||||||
|
|
|
@ -172,6 +172,7 @@ class TopologyViewManager(object):
|
||||||
_type = CITypeCache.get(central_node_type)
|
_type = CITypeCache.get(central_node_type)
|
||||||
if not _type:
|
if not _type:
|
||||||
return dict(nodes=nodes, links=links)
|
return dict(nodes=nodes, links=links)
|
||||||
|
type2meta = {_type.id: _type.icon}
|
||||||
root_ids = []
|
root_ids = []
|
||||||
show_key = AttributeCache.get(_type.show_id or _type.unique_id)
|
show_key = AttributeCache.get(_type.show_id or _type.unique_id)
|
||||||
|
|
||||||
|
@ -192,7 +193,6 @@ class TopologyViewManager(object):
|
||||||
prefix = REDIS_PREFIX_CI_RELATION
|
prefix = REDIS_PREFIX_CI_RELATION
|
||||||
key = list(map(str, root_ids))
|
key = list(map(str, root_ids))
|
||||||
id2node = {}
|
id2node = {}
|
||||||
type2meta = {}
|
|
||||||
for level in sorted([i for i in path.keys() if int(i) > 0]):
|
for level in sorted([i for i in path.keys() if int(i) > 0]):
|
||||||
type_ids = {int(i) for i in path[level]}
|
type_ids = {int(i) for i in path[level]}
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,9 @@ def is_app_admin(app=None):
|
||||||
if app is None:
|
if app is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if hasattr(current_user, 'username') and current_user.username == 'worker':
|
||||||
|
return True
|
||||||
|
|
||||||
app_id = app.id
|
app_id = app.id
|
||||||
if 'acl_admin' in session.get("acl", {}).get("parentRoles", []):
|
if 'acl_admin' in session.get("acl", {}).get("parentRoles", []):
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -79,7 +79,8 @@ class PermissionCRUD(object):
|
||||||
return r and cls.get_all(r.id)
|
return r and cls.get_all(r.id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def grant(rid, perms, resource_id=None, group_id=None, rebuild=True, source=AuditOperateSource.acl):
|
def grant(rid, perms, resource_id=None, group_id=None, rebuild=True,
|
||||||
|
source=AuditOperateSource.acl, force_update=False):
|
||||||
app_id = None
|
app_id = None
|
||||||
rt_id = None
|
rt_id = None
|
||||||
|
|
||||||
|
@ -106,8 +107,23 @@ class PermissionCRUD(object):
|
||||||
if not perms:
|
if not perms:
|
||||||
perms = [i.get('name') for i in ResourceTypeCRUD.get_perms(group.resource_type_id)]
|
perms = [i.get('name') for i in ResourceTypeCRUD.get_perms(group.resource_type_id)]
|
||||||
|
|
||||||
_role_permissions = []
|
if force_update:
|
||||||
|
revoke_role_permissions = []
|
||||||
|
existed_perms = RolePermission.get_by(rid=rid,
|
||||||
|
app_id=app_id,
|
||||||
|
group_id=group_id,
|
||||||
|
resource_id=resource_id,
|
||||||
|
to_dict=False)
|
||||||
|
for role_perm in existed_perms:
|
||||||
|
perm = PermissionCache.get(role_perm.perm_id, rt_id)
|
||||||
|
if perm and perm.name not in perms:
|
||||||
|
role_perm.soft_delete()
|
||||||
|
revoke_role_permissions.append(role_perm)
|
||||||
|
|
||||||
|
AuditCRUD.add_permission_log(app_id, AuditOperateType.revoke, rid, rt_id,
|
||||||
|
revoke_role_permissions, source=source)
|
||||||
|
|
||||||
|
_role_permissions = []
|
||||||
for _perm in set(perms):
|
for _perm in set(perms):
|
||||||
perm = PermissionCache.get(_perm, rt_id)
|
perm = PermissionCache.get(_perm, rt_id)
|
||||||
if not perm:
|
if not perm:
|
||||||
|
|
|
@ -51,12 +51,12 @@ def _auth_with_key():
|
||||||
user, authenticated = User.query.authenticate_with_key(key, secret, req_args, path)
|
user, authenticated = User.query.authenticate_with_key(key, secret, req_args, path)
|
||||||
if user and authenticated:
|
if user and authenticated:
|
||||||
login_user(user)
|
login_user(user)
|
||||||
reset_session(user)
|
# reset_session(user)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
role, authenticated = Role.query.authenticate_with_key(key, secret, req_args, path)
|
role, authenticated = Role.query.authenticate_with_key(key, secret, req_args, path)
|
||||||
if role and authenticated:
|
if role and authenticated:
|
||||||
reset_session(None, role=role.name)
|
# reset_session(None, role=role.name)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -104,6 +104,7 @@ class Attribute(Model):
|
||||||
is_link = db.Column(db.Boolean, default=False)
|
is_link = db.Column(db.Boolean, default=False)
|
||||||
is_password = db.Column(db.Boolean, default=False)
|
is_password = db.Column(db.Boolean, default=False)
|
||||||
is_sortable = db.Column(db.Boolean, default=False)
|
is_sortable = db.Column(db.Boolean, default=False)
|
||||||
|
is_dynamic = db.Column(db.Boolean, default=False)
|
||||||
|
|
||||||
default = db.Column(db.JSON) # {"default": None}
|
default = db.Column(db.JSON) # {"default": None}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,9 @@ const cmdb_en = {
|
||||||
show: 'show attribute',
|
show: 'show attribute',
|
||||||
setAsShow: 'Set as show attribute',
|
setAsShow: 'Set as show attribute',
|
||||||
cancelSetAsShow: 'Cancel show attribute',
|
cancelSetAsShow: 'Cancel show attribute',
|
||||||
showTips: 'The names of nodes in the service tree and topology view'
|
showTips: 'The names of nodes in the service tree and topology view',
|
||||||
|
isDynamic: 'Dynamic',
|
||||||
|
dynamicTips: 'For example, for monitoring data and frequently updated data, it is recommended to set it as a dynamic attribute, so that the change history of the attribute will not be recorded.',
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
unselectAttributes: 'Unselected',
|
unselectAttributes: 'Unselected',
|
||||||
|
@ -538,7 +540,7 @@ if __name__ == "__main__":
|
||||||
rollbackSuccess: 'Rollback successfully',
|
rollbackSuccess: 'Rollback successfully',
|
||||||
rollbackingTips: 'Rollbacking',
|
rollbackingTips: 'Rollbacking',
|
||||||
batchRollbacking: 'Deleting {total} items in total, {successNum} items successful, {errorNum} items failed',
|
batchRollbacking: 'Deleting {total} items in total, {successNum} items successful, {errorNum} items failed',
|
||||||
baselineTips: 'Changes at this point in time will also be rollbacked, Unique ID and password attributes do not support',
|
baselineTips: 'Changes at this point in time will also be rollbacked, Unique ID, password and dynamic attributes do not support',
|
||||||
},
|
},
|
||||||
serviceTree: {
|
serviceTree: {
|
||||||
remove: 'Remove',
|
remove: 'Remove',
|
||||||
|
|
|
@ -78,7 +78,7 @@ const cmdb_zh = {
|
||||||
password: '密码',
|
password: '密码',
|
||||||
link: '链接',
|
link: '链接',
|
||||||
list: '多值',
|
list: '多值',
|
||||||
listTips: '字段的值是1个或者多个,接口返回的值的类型是list',
|
listTips: '属性的值是1个或者多个,接口返回的值的类型是list',
|
||||||
computeForAllCITips: '所有CI触发计算',
|
computeForAllCITips: '所有CI触发计算',
|
||||||
confirmcomputeForAllCITips: '确认触发所有CI的计算?',
|
confirmcomputeForAllCITips: '确认触发所有CI的计算?',
|
||||||
isUnique: '是否唯一',
|
isUnique: '是否唯一',
|
||||||
|
@ -89,7 +89,7 @@ const cmdb_zh = {
|
||||||
isSortable: '可排序',
|
isSortable: '可排序',
|
||||||
isIndex: '是否索引',
|
isIndex: '是否索引',
|
||||||
index: '索引',
|
index: '索引',
|
||||||
indexTips: '字段可被用于检索,加速查询',
|
indexTips: '属性可被用于全文检索,加速查询',
|
||||||
confirmDelete: '确认删除【{name}】?',
|
confirmDelete: '确认删除【{name}】?',
|
||||||
confirmDelete2: '确认删除?',
|
confirmDelete2: '确认删除?',
|
||||||
computeSuccess: '触发成功!',
|
computeSuccess: '触发成功!',
|
||||||
|
@ -200,7 +200,9 @@ const cmdb_zh = {
|
||||||
show: '展示属性',
|
show: '展示属性',
|
||||||
setAsShow: '设置为展示属性',
|
setAsShow: '设置为展示属性',
|
||||||
cancelSetAsShow: '取消设置为展示属性',
|
cancelSetAsShow: '取消设置为展示属性',
|
||||||
showTips: '服务树和拓扑视图里节点的名称'
|
showTips: '服务树和拓扑视图里节点的名称',
|
||||||
|
isDynamic: '动态属性',
|
||||||
|
dynamicTips: '譬如监控类的数据, 频繁更新的数据, 建议设置为动态属性, 则不会记录该属性的变更历史',
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
unselectAttributes: '未选属性',
|
unselectAttributes: '未选属性',
|
||||||
|
@ -538,7 +540,7 @@ if __name__ == "__main__":
|
||||||
rollbackSuccess: '回滚成功',
|
rollbackSuccess: '回滚成功',
|
||||||
rollbackingTips: '正在批量回滚中',
|
rollbackingTips: '正在批量回滚中',
|
||||||
batchRollbacking: '正在回滚,共{total}个,成功{successNum}个,失败{errorNum}个',
|
batchRollbacking: '正在回滚,共{total}个,成功{successNum}个,失败{errorNum}个',
|
||||||
baselineTips: '该时间点的变更也会被回滚, 唯一标识、密码属性不支持回滚',
|
baselineTips: '该时间点的变更也会被回滚, 唯一标识、密码属性、动态属性不支持回滚',
|
||||||
},
|
},
|
||||||
serviceTree: {
|
serviceTree: {
|
||||||
remove: '移除',
|
remove: '移除',
|
||||||
|
|
|
@ -163,6 +163,12 @@ export default {
|
||||||
width: 110,
|
width: 110,
|
||||||
help: this.$t('cmdb.ci.tips10'),
|
help: this.$t('cmdb.ci.tips10'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'is_dynamic',
|
||||||
|
title: this.$t('cmdb.ciType.isDynamic'),
|
||||||
|
width: 110,
|
||||||
|
help: this.$t('cmdb.ciType.dynamicTips'),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -180,6 +180,10 @@ export default {
|
||||||
label: this.$t('cmdb.ciType.isIndex'),
|
label: this.$t('cmdb.ciType.isIndex'),
|
||||||
property: 'is_index',
|
property: 'is_index',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: this.$t('cmdb.ciType.isDynamic'),
|
||||||
|
property: 'is_dynamic',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
inherited() {
|
inherited() {
|
||||||
|
|
|
@ -157,33 +157,6 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
|
||||||
<a-col :span="6">
|
|
||||||
<a-form-item
|
|
||||||
:label-col="horizontalFormItemLayout.labelCol"
|
|
||||||
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
|
||||||
:label="$t('required')"
|
|
||||||
>
|
|
||||||
<a-switch
|
|
||||||
@change="(checked) => onChange(checked, 'is_required')"
|
|
||||||
name="is_required"
|
|
||||||
v-decorator="['is_required', { rules: [], valuePropName: 'checked' }]"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
|
|
||||||
<a-form-item
|
|
||||||
:label-col="{ span: 8 }"
|
|
||||||
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
|
||||||
:label="$t('cmdb.ciType.unique')"
|
|
||||||
>
|
|
||||||
<a-switch
|
|
||||||
:disabled="isShowComputedArea"
|
|
||||||
@change="onChange"
|
|
||||||
name="is_unique"
|
|
||||||
v-decorator="['is_unique', { rules: [], valuePropName: 'checked' }]"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
|
<a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:hidden="currentValueType === '2' ? false : true"
|
:hidden="currentValueType === '2' ? false : true"
|
||||||
|
@ -196,7 +169,7 @@
|
||||||
>{{ $t('cmdb.ciType.index') }}
|
>{{ $t('cmdb.ciType.index') }}
|
||||||
<a-tooltip :title="$t('cmdb.ciType.indexTips')">
|
<a-tooltip :title="$t('cmdb.ciType.indexTips')">
|
||||||
<a-icon
|
<a-icon
|
||||||
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
style="position:absolute;top:2px;left:-17px;color:#2f54eb;"
|
||||||
type="question-circle"
|
type="question-circle"
|
||||||
theme="filled"
|
theme="filled"
|
||||||
@click="
|
@click="
|
||||||
|
@ -217,10 +190,37 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="6">
|
<a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
|
:label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
|
||||||
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
|
:label="$t('cmdb.ciType.unique')"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
:disabled="isShowComputedArea"
|
||||||
|
@change="onChange"
|
||||||
|
name="is_unique"
|
||||||
|
v-decorator="['is_unique', { rules: [], valuePropName: 'checked' }]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item
|
||||||
|
:label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 8 } : horizontalFormItemLayout.labelCol"
|
||||||
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
|
:label="$t('required')"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
@change="(checked) => onChange(checked, 'is_required')"
|
||||||
|
name="is_required"
|
||||||
|
v-decorator="['is_required', { rules: [], valuePropName: 'checked' }]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item
|
||||||
|
:label-col="currentValueType === '2' ? { span: 12 } : horizontalFormItemLayout.labelCol"
|
||||||
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
>
|
>
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<span
|
<span
|
||||||
|
@ -228,7 +228,7 @@
|
||||||
>{{ $t('cmdb.ciType.defaultShow') }}
|
>{{ $t('cmdb.ciType.defaultShow') }}
|
||||||
<a-tooltip :title="$t('cmdb.ciType.defaultShowTips')">
|
<a-tooltip :title="$t('cmdb.ciType.defaultShowTips')">
|
||||||
<a-icon
|
<a-icon
|
||||||
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
style="position:absolute;top:2px;left:-17px;color:#2f54eb;"
|
||||||
type="question-circle"
|
type="question-circle"
|
||||||
theme="filled"
|
theme="filled"
|
||||||
@click="
|
@click="
|
||||||
|
@ -295,6 +295,37 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
<a-col span="6">
|
||||||
|
<a-form-item
|
||||||
|
:label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 12 } : horizontalFormItemLayout.labelCol"
|
||||||
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
|
>
|
||||||
|
<template slot="label">
|
||||||
|
<span
|
||||||
|
style="position:relative;white-space:pre;"
|
||||||
|
>{{ $t('cmdb.ciType.isDynamic') }}
|
||||||
|
<a-tooltip :title="$t('cmdb.ciType.dynamicTips')">
|
||||||
|
<a-icon
|
||||||
|
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
||||||
|
type="question-circle"
|
||||||
|
theme="filled"
|
||||||
|
@click="
|
||||||
|
(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<a-switch
|
||||||
|
@change="(checked) => onChange(checked, 'is_dynamic')"
|
||||||
|
name="is_dynamic"
|
||||||
|
v-decorator="['is_dynamic', { rules: [], valuePropName: 'checked' }]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-divider style="font-size:14px;margin-top:6px;">{{ $t('cmdb.ciType.advancedSettings') }}</a-divider>
|
<a-divider style="font-size:14px;margin-top:6px;">{{ $t('cmdb.ciType.advancedSettings') }}</a-divider>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="24" v-if="!['6'].includes(currentValueType)">
|
<a-col :span="24" v-if="!['6'].includes(currentValueType)">
|
||||||
|
@ -534,6 +565,7 @@ export default {
|
||||||
is_index: _record.is_index,
|
is_index: _record.is_index,
|
||||||
is_sortable: _record.is_sortable,
|
is_sortable: _record.is_sortable,
|
||||||
is_computed: _record.is_computed,
|
is_computed: _record.is_computed,
|
||||||
|
is_dynamic: _record.is_dynamic,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
console.log(_record)
|
console.log(_record)
|
||||||
|
|
|
@ -150,42 +150,19 @@
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|
||||||
<a-col :span="6">
|
<a-col :span="currentValueType === '2' ? 6 : 0" v-if="currentValueType !== '6'">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
:hidden="currentValueType === '2' ? false : true"
|
||||||
:label-col="horizontalFormItemLayout.labelCol"
|
:label-col="horizontalFormItemLayout.labelCol"
|
||||||
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
:label="$t('required')"
|
|
||||||
>
|
>
|
||||||
<a-switch
|
|
||||||
@change="(checked) => onChange(checked, 'is_required')"
|
|
||||||
name="is_required"
|
|
||||||
v-decorator="['is_required', { rules: [], valuePropName: 'checked' }]"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
|
|
||||||
<a-form-item
|
|
||||||
:label-col="{ span: 8 }"
|
|
||||||
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
|
||||||
:label="$t('cmdb.ciType.unique')"
|
|
||||||
>
|
|
||||||
<a-switch
|
|
||||||
:disabled="isShowComputedArea"
|
|
||||||
@change="onChange"
|
|
||||||
name="is_unique"
|
|
||||||
v-decorator="['is_unique', { rules: [], valuePropName: 'checked' }]"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="6" v-if="currentValueType === '2'">
|
|
||||||
<a-form-item :label-col="horizontalFormItemLayout.labelCol" :wrapper-col="horizontalFormItemLayout.wrapperCol">
|
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<span
|
<span
|
||||||
style="position:relative;white-space:pre;"
|
style="position:relative;white-space:pre;"
|
||||||
>{{ $t('cmdb.ciType.index') }}
|
>{{ $t('cmdb.ciType.index') }}
|
||||||
<a-tooltip :title="$t('cmdb.ciType.indexTips')">
|
<a-tooltip :title="$t('cmdb.ciType.indexTips')">
|
||||||
<a-icon
|
<a-icon
|
||||||
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
style="position:absolute;top:2px;left:-17px;color:#2f54eb;"
|
||||||
type="question-circle"
|
type="question-circle"
|
||||||
theme="filled"
|
theme="filled"
|
||||||
@click="
|
@click="
|
||||||
|
@ -206,10 +183,37 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="6">
|
<a-col :span="6" v-if="currentValueType !== '6' && currentValueType !== '7'">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
:label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
|
:label-col="currentValueType === '2' ? { span: 8 } : horizontalFormItemLayout.labelCol"
|
||||||
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
|
:label="$t('cmdb.ciType.unique')"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
:disabled="isShowComputedArea"
|
||||||
|
@change="onChange"
|
||||||
|
name="is_unique"
|
||||||
|
v-decorator="['is_unique', { rules: [], valuePropName: 'checked' }]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item
|
||||||
|
:label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 8 } : horizontalFormItemLayout.labelCol"
|
||||||
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
|
:label="$t('required')"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
@change="(checked) => onChange(checked, 'is_required')"
|
||||||
|
name="is_required"
|
||||||
|
v-decorator="['is_required', { rules: [], valuePropName: 'checked' }]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item
|
||||||
|
:label-col="currentValueType === '2' ? { span: 12 } : horizontalFormItemLayout.labelCol"
|
||||||
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
>
|
>
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<span
|
<span
|
||||||
|
@ -217,7 +221,7 @@
|
||||||
>{{ $t('cmdb.ciType.defaultShow') }}
|
>{{ $t('cmdb.ciType.defaultShow') }}
|
||||||
<a-tooltip :title="$t('cmdb.ciType.defaultShowTips')">
|
<a-tooltip :title="$t('cmdb.ciType.defaultShowTips')">
|
||||||
<a-icon
|
<a-icon
|
||||||
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
style="position:absolute;top:2px;left:-17px;color:#2f54eb;"
|
||||||
type="question-circle"
|
type="question-circle"
|
||||||
theme="filled"
|
theme="filled"
|
||||||
@click="
|
@click="
|
||||||
|
@ -284,6 +288,37 @@
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
|
<a-col span="6">
|
||||||
|
<a-form-item
|
||||||
|
:label-col="['2', '6', '7'].findIndex(i => currentValueType === i) === -1 ? { span: 12 } : horizontalFormItemLayout.labelCol"
|
||||||
|
:wrapper-col="horizontalFormItemLayout.wrapperCol"
|
||||||
|
>
|
||||||
|
<template slot="label">
|
||||||
|
<span
|
||||||
|
style="position:relative;white-space:pre;"
|
||||||
|
>{{ $t('cmdb.ciType.isDynamic') }}
|
||||||
|
<a-tooltip :title="$t('cmdb.ciType.dynamicTips')">
|
||||||
|
<a-icon
|
||||||
|
style="position:absolute;top:3px;left:-17px;color:#2f54eb;"
|
||||||
|
type="question-circle"
|
||||||
|
theme="filled"
|
||||||
|
@click="
|
||||||
|
(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<a-switch
|
||||||
|
@change="(checked) => onChange(checked, 'is_dynamic')"
|
||||||
|
name="is_dynamic"
|
||||||
|
v-decorator="['is_dynamic', { rules: [], valuePropName: 'checked', initialValue: currentValueType === '6' ? true: false }]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-divider style="font-size:14px;margin-top:6px;">{{ $t('cmdb.ciType.advancedSettings') }}</a-divider>
|
<a-divider style="font-size:14px;margin-top:6px;">{{ $t('cmdb.ciType.advancedSettings') }}</a-divider>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="24" v-if="!['6'].includes(currentValueType)">
|
<a-col :span="24" v-if="!['6'].includes(currentValueType)">
|
||||||
|
@ -404,8 +439,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(values)
|
console.log(values)
|
||||||
const { is_required, default_show, default_value } = values
|
const { is_required, default_show, default_value, is_dynamic } = values
|
||||||
const data = { is_required, default_show }
|
const data = { is_required, default_show, is_dynamic }
|
||||||
delete values.is_required
|
delete values.is_required
|
||||||
delete values.default_show
|
delete values.default_show
|
||||||
if (values.value_type === '0' && default_value) {
|
if (values.value_type === '0' && default_value) {
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
<a-tab-pane key="2" :tab="$t('cmdb.ciType.relation')">
|
<a-tab-pane key="2" :tab="$t('cmdb.ciType.relation')">
|
||||||
<RelationTable :CITypeId="CITypeId" :CITypeName="CITypeName"></RelationTable>
|
<RelationTable :CITypeId="CITypeId" :CITypeName="CITypeName"></RelationTable>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="3" :tab="$t('cmdb.ciType.trigger')">
|
<a-tab-pane key="3" :tab="$t('cmdb.ciType.attributeAD')">
|
||||||
<TriggerTable ref="triggerTable" :CITypeId="CITypeId"></TriggerTable>
|
|
||||||
</a-tab-pane>
|
|
||||||
<a-tab-pane key="4" :tab="$t('cmdb.ciType.attributeAD')">
|
|
||||||
<AttrAD :CITypeId="CITypeId"></AttrAD>
|
<AttrAD :CITypeId="CITypeId"></AttrAD>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="5" :tab="$t('cmdb.ciType.relationAD')">
|
<a-tab-pane key="4" :tab="$t('cmdb.ciType.relationAD')">
|
||||||
<RelationAD :CITypeId="CITypeId"></RelationAD>
|
<RelationAD :CITypeId="CITypeId"></RelationAD>
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="5" :tab="$t('cmdb.ciType.trigger')">
|
||||||
|
<TriggerTable ref="triggerTable" :CITypeId="CITypeId"></TriggerTable>
|
||||||
|
</a-tab-pane>
|
||||||
<a-tab-pane key="6" :tab="$t('cmdb.ciType.grant')">
|
<a-tab-pane key="6" :tab="$t('cmdb.ciType.grant')">
|
||||||
<GrantComp :CITypeId="CITypeId" resourceType="CIType" :resourceTypeName="CITypeName"></GrantComp>
|
<GrantComp :CITypeId="CITypeId" resourceType="CIType" :resourceTypeName="CITypeName"></GrantComp>
|
||||||
<div class="citype-detail-title">{{ $t('cmdb.components.relationGrant') }}</div>
|
<div class="citype-detail-title">{{ $t('cmdb.components.relationGrant') }}</div>
|
||||||
|
@ -67,7 +67,7 @@ export default {
|
||||||
if (activeKey === '1') {
|
if (activeKey === '1') {
|
||||||
this.$refs.attributesTable.getCITypeGroupData()
|
this.$refs.attributesTable.getCITypeGroupData()
|
||||||
}
|
}
|
||||||
if (activeKey === '3') {
|
if (activeKey === '5') {
|
||||||
this.$refs.triggerTable.getTableData()
|
this.$refs.triggerTable.getTableData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -91,7 +91,7 @@
|
||||||
show-search
|
show-search
|
||||||
>
|
>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="attr in commonAttributes.filter((attr) => !attr.is_password)"
|
v-for="attr in commonAttributes.filter((attr) => !attr.is_password && attr.value_type !== '6')"
|
||||||
:key="attr.id"
|
:key="attr.id"
|
||||||
:value="attr.id"
|
:value="attr.id"
|
||||||
>{{ attr.alias || attr.name }}</a-select-option
|
>{{ attr.alias || attr.name }}</a-select-option
|
||||||
|
|
Loading…
Reference in New Issue