mirror of https://github.com/veops/cmdb.git
Merge branch 'master' into doc
This commit is contained in:
commit
42d20e5397
|
@ -26,6 +26,7 @@ Flask-Bcrypt = "==1.0.1"
|
||||||
Flask-Cors = ">=3.0.8"
|
Flask-Cors = ">=3.0.8"
|
||||||
ldap3 = "==2.9.1"
|
ldap3 = "==2.9.1"
|
||||||
pycryptodome = "==3.12.0"
|
pycryptodome = "==3.12.0"
|
||||||
|
cryptography = "==41.0.2"
|
||||||
# Caching
|
# Caching
|
||||||
Flask-Caching = ">=1.0.0"
|
Flask-Caching = ">=1.0.0"
|
||||||
# Environment variable parsing
|
# Environment variable parsing
|
||||||
|
|
|
@ -216,10 +216,9 @@ class InitDepartment(object):
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
app = acl.validate_app()
|
app = acl.validate_app()
|
||||||
if app:
|
if not app:
|
||||||
return acl
|
|
||||||
|
|
||||||
acl.create_app(payload)
|
acl.create_app(payload)
|
||||||
|
return acl
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
current_app.logger.error(e)
|
current_app.logger.error(e)
|
||||||
if '不存在' in str(e):
|
if '不存在' in str(e):
|
||||||
|
|
|
@ -60,10 +60,11 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_choice_values_from_other_ci(choice_other):
|
def _get_choice_values_from_other(choice_other):
|
||||||
from api.lib.cmdb.search import SearchError
|
from api.lib.cmdb.search import SearchError
|
||||||
from api.lib.cmdb.search.ci import search
|
from api.lib.cmdb.search.ci import search
|
||||||
|
|
||||||
|
if choice_other.get('type_ids'):
|
||||||
type_ids = choice_other.get('type_ids')
|
type_ids = choice_other.get('type_ids')
|
||||||
attr_id = choice_other.get('attr_id')
|
attr_id = choice_other.get('attr_id')
|
||||||
other_filter = choice_other.get('filter') or ''
|
other_filter = choice_other.get('filter') or ''
|
||||||
|
@ -77,6 +78,16 @@ class AttributeManager(object):
|
||||||
current_app.logger.error("get choice values from other ci failed: {}".format(e))
|
current_app.logger.error("get choice values from other ci failed: {}".format(e))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
elif choice_other.get('script'):
|
||||||
|
try:
|
||||||
|
x = compile(choice_other['script'], '', "exec")
|
||||||
|
exec(x)
|
||||||
|
res = locals()['ChoiceValue']().values() or []
|
||||||
|
return [[i, {}] for i in res]
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.error("get choice values from script: {}".format(e))
|
||||||
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_other,
|
def get_choice_values(cls, attr_id, value_type, choice_web_hook, choice_other,
|
||||||
choice_web_hook_parse=True, choice_other_parse=True):
|
choice_web_hook_parse=True, choice_other_parse=True):
|
||||||
|
@ -87,7 +98,7 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
elif choice_other:
|
elif choice_other:
|
||||||
if choice_other_parse and isinstance(choice_other, dict):
|
if choice_other_parse and isinstance(choice_other, dict):
|
||||||
return cls._get_choice_values_from_other_ci(choice_other)
|
return cls._get_choice_values_from_other(choice_other)
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -96,7 +107,8 @@ class AttributeManager(object):
|
||||||
return []
|
return []
|
||||||
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
choice_values = choice_table.get_by(fl=["value", "option"], attr_id=attr_id)
|
||||||
|
|
||||||
return [[choice_value['value'], choice_value['option']] for choice_value in choice_values]
|
return [[ValueTypeMap.serialize[value_type](choice_value['value']), choice_value['option']]
|
||||||
|
for choice_value in choice_values]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_choice_values(_id, value_type, choice_values):
|
def add_choice_values(_id, value_type, choice_values):
|
||||||
|
@ -218,9 +230,14 @@ class AttributeManager(object):
|
||||||
if name in BUILTIN_KEYWORDS:
|
if name in BUILTIN_KEYWORDS:
|
||||||
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
return abort(400, ErrFormat.attribute_name_cannot_be_builtin)
|
||||||
|
|
||||||
if kwargs.get('choice_other'):
|
while kwargs.get('choice_other'):
|
||||||
if (not isinstance(kwargs['choice_other'], dict) or not kwargs['choice_other'].get('type_ids') or
|
if isinstance(kwargs['choice_other'], dict):
|
||||||
not kwargs['choice_other'].get('attr_id')):
|
if kwargs['choice_other'].get('script'):
|
||||||
|
break
|
||||||
|
|
||||||
|
if kwargs['choice_other'].get('type_ids') and kwargs['choice_other'].get('attr_id'):
|
||||||
|
break
|
||||||
|
|
||||||
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
||||||
|
|
||||||
alias = kwargs.pop("alias", "")
|
alias = kwargs.pop("alias", "")
|
||||||
|
@ -232,6 +249,8 @@ class AttributeManager(object):
|
||||||
|
|
||||||
kwargs.get('is_computed') and cls.can_create_computed_attribute()
|
kwargs.get('is_computed') and cls.can_create_computed_attribute()
|
||||||
|
|
||||||
|
kwargs.get('choice_other') and kwargs['choice_other'].get('script') and cls.can_create_computed_attribute()
|
||||||
|
|
||||||
attr = Attribute.create(flush=True,
|
attr = Attribute.create(flush=True,
|
||||||
name=name,
|
name=name,
|
||||||
alias=alias,
|
alias=alias,
|
||||||
|
@ -337,9 +356,14 @@ class AttributeManager(object):
|
||||||
|
|
||||||
self._change_index(attr, attr.is_index, kwargs['is_index'])
|
self._change_index(attr, attr.is_index, kwargs['is_index'])
|
||||||
|
|
||||||
if kwargs.get('choice_other'):
|
while kwargs.get('choice_other'):
|
||||||
if (not isinstance(kwargs['choice_other'], dict) or not kwargs['choice_other'].get('type_ids') or
|
if isinstance(kwargs['choice_other'], dict):
|
||||||
not kwargs['choice_other'].get('attr_id')):
|
if kwargs['choice_other'].get('script'):
|
||||||
|
break
|
||||||
|
|
||||||
|
if kwargs['choice_other'].get('type_ids') and kwargs['choice_other'].get('attr_id'):
|
||||||
|
break
|
||||||
|
|
||||||
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
return abort(400, ErrFormat.attribute_choice_other_invalid)
|
||||||
|
|
||||||
existed2 = attr.to_dict()
|
existed2 = attr.to_dict()
|
||||||
|
|
|
@ -28,6 +28,7 @@ from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_NO_ATTR
|
||||||
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
|
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
|
||||||
from api.lib.cmdb.search.ci.db.query_sql import QUERY_UNION_CI_ATTRIBUTE_IS_NULL
|
from api.lib.cmdb.search.ci.db.query_sql import QUERY_UNION_CI_ATTRIBUTE_IS_NULL
|
||||||
from api.lib.cmdb.utils import TableMap
|
from api.lib.cmdb.utils import TableMap
|
||||||
|
from api.lib.cmdb.utils import ValueTypeMap
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
from api.lib.perm.acl.acl import is_app_admin
|
from api.lib.perm.acl.acl import is_app_admin
|
||||||
from api.lib.utils import handle_arg_list
|
from api.lib.utils import handle_arg_list
|
||||||
|
@ -524,15 +525,15 @@ class Search(object):
|
||||||
if k:
|
if k:
|
||||||
table_name = TableMap(attr=attr).table_name
|
table_name = TableMap(attr=attr).table_name
|
||||||
query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
|
query_sql = FACET_QUERY.format(table_name, self.query_sql, attr.id)
|
||||||
# current_app.logger.warning(query_sql)
|
|
||||||
result = db.session.execute(query_sql).fetchall()
|
result = db.session.execute(query_sql).fetchall()
|
||||||
facet[k] = result
|
facet[k] = result
|
||||||
|
|
||||||
facet_result = dict()
|
facet_result = dict()
|
||||||
for k, v in facet.items():
|
for k, v in facet.items():
|
||||||
if not k.startswith('_'):
|
if not k.startswith('_'):
|
||||||
a = getattr(AttributeCache.get(k), self.ret_key)
|
attr = AttributeCache.get(k)
|
||||||
facet_result[a] = [(f[0], f[1], a) for f in v]
|
a = getattr(attr, self.ret_key)
|
||||||
|
facet_result[a] = [(ValueTypeMap.serialize[attr.value_type](f[0]), f[1], a) for f in v]
|
||||||
|
|
||||||
return facet_result
|
return facet_result
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import api.models.cmdb as model
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
from api.lib.cmdb.cache import AttributeCache
|
||||||
from api.lib.cmdb.const import ValueTypeEnum
|
from api.lib.cmdb.const import ValueTypeEnum
|
||||||
|
|
||||||
TIME_RE = re.compile(r"^(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d$")
|
TIME_RE = re.compile(r"^20|21|22|23|[0-1]\d:[0-5]\d:[0-5]\d$")
|
||||||
|
|
||||||
|
|
||||||
def string2int(x):
|
def string2int(x):
|
||||||
|
@ -21,7 +21,7 @@ def string2int(x):
|
||||||
|
|
||||||
def str2datetime(x):
|
def str2datetime(x):
|
||||||
try:
|
try:
|
||||||
return datetime.datetime.strptime(x, "%Y-%m-%d")
|
return datetime.datetime.strptime(x, "%Y-%m-%d").date()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.FLOAT: float,
|
ValueTypeEnum.FLOAT: float,
|
||||||
ValueTypeEnum.TEXT: lambda x: x if isinstance(x, six.string_types) else str(x),
|
ValueTypeEnum.TEXT: lambda x: x if isinstance(x, six.string_types) else str(x),
|
||||||
ValueTypeEnum.TIME: lambda x: x if isinstance(x, six.string_types) else str(x),
|
ValueTypeEnum.TIME: lambda x: x if isinstance(x, six.string_types) else str(x),
|
||||||
ValueTypeEnum.DATE: lambda x: x.strftime("%Y-%m-%d"),
|
ValueTypeEnum.DATE: lambda x: x.strftime("%Y-%m-%d") if not isinstance(x, six.string_types) else x,
|
||||||
ValueTypeEnum.DATETIME: lambda x: x.strftime("%Y-%m-%d %H:%M:%S"),
|
ValueTypeEnum.DATETIME: lambda x: x.strftime("%Y-%m-%d %H:%M:%S") if not isinstance(x, six.string_types) else x,
|
||||||
ValueTypeEnum.JSON: lambda x: json.loads(x) if isinstance(x, six.string_types) and x else x,
|
ValueTypeEnum.JSON: lambda x: json.loads(x) if isinstance(x, six.string_types) and x else x,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.FLOAT: model.FloatChoice,
|
ValueTypeEnum.FLOAT: model.FloatChoice,
|
||||||
ValueTypeEnum.TEXT: model.TextChoice,
|
ValueTypeEnum.TEXT: model.TextChoice,
|
||||||
ValueTypeEnum.TIME: model.TextChoice,
|
ValueTypeEnum.TIME: model.TextChoice,
|
||||||
|
ValueTypeEnum.DATE: model.TextChoice,
|
||||||
|
ValueTypeEnum.DATETIME: model.TextChoice,
|
||||||
}
|
}
|
||||||
|
|
||||||
table = {
|
table = {
|
||||||
|
@ -97,7 +99,7 @@ class ValueTypeMap(object):
|
||||||
ValueTypeEnum.DATE: 'text',
|
ValueTypeEnum.DATE: 'text',
|
||||||
ValueTypeEnum.TIME: 'text',
|
ValueTypeEnum.TIME: 'text',
|
||||||
ValueTypeEnum.FLOAT: 'float',
|
ValueTypeEnum.FLOAT: 'float',
|
||||||
ValueTypeEnum.JSON: 'object'
|
ValueTypeEnum.JSON: 'object',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
from flask import abort
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from api.lib.common_setting.resp_format import ErrFormat
|
from api.lib.common_setting.resp_format import ErrFormat
|
||||||
|
from api.lib.perm.acl.app import AppCRUD
|
||||||
from api.lib.perm.acl.cache import RoleCache, AppCache
|
from api.lib.perm.acl.cache import RoleCache, AppCache
|
||||||
|
from api.lib.perm.acl.permission import PermissionCRUD
|
||||||
|
from api.lib.perm.acl.resource import ResourceTypeCRUD, ResourceCRUD
|
||||||
from api.lib.perm.acl.role import RoleCRUD, RoleRelationCRUD
|
from api.lib.perm.acl.role import RoleCRUD, RoleRelationCRUD
|
||||||
from api.lib.perm.acl.user import UserCRUD
|
from api.lib.perm.acl.user import UserCRUD
|
||||||
from api.lib.perm.acl.resource import ResourceTypeCRUD, ResourceCRUD
|
|
||||||
from api.lib.perm.acl.permission import PermissionCRUD
|
|
||||||
|
|
||||||
|
|
||||||
class ACLManager(object):
|
class ACLManager(object):
|
||||||
|
@ -133,3 +133,9 @@ class ACLManager(object):
|
||||||
|
|
||||||
def grant_resource(self, rid, resource_id, perms):
|
def grant_resource(self, rid, resource_id, perms):
|
||||||
PermissionCRUD.grant(rid, perms, resource_id=resource_id, group_id=None)
|
PermissionCRUD.grant(rid, perms, resource_id=resource_id, group_id=None)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_app(payload):
|
||||||
|
rt = AppCRUD.add(**payload)
|
||||||
|
|
||||||
|
return rt.to_dict()
|
||||||
|
|
|
@ -121,6 +121,19 @@ class EmployeeCRUD(object):
|
||||||
employee = CreateEmployee().create_single(**data)
|
employee = CreateEmployee().create_single(**data)
|
||||||
return employee.to_dict()
|
return employee.to_dict()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_employee_from_acl_created(**kwargs):
|
||||||
|
try:
|
||||||
|
kwargs['acl_uid'] = kwargs.pop('uid')
|
||||||
|
kwargs['acl_rid'] = kwargs.pop('rid')
|
||||||
|
kwargs['department_id'] = 0
|
||||||
|
|
||||||
|
Employee.create(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
abort(400, str(e))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add(**kwargs):
|
def add(**kwargs):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -8,6 +8,7 @@ from flask import current_app
|
||||||
from flask import request
|
from flask import request
|
||||||
from sqlalchemy.exc import InvalidRequestError
|
from sqlalchemy.exc import InvalidRequestError
|
||||||
from sqlalchemy.exc import OperationalError
|
from sqlalchemy.exc import OperationalError
|
||||||
|
from sqlalchemy.exc import PendingRollbackError
|
||||||
from sqlalchemy.exc import StatementError
|
from sqlalchemy.exc import StatementError
|
||||||
|
|
||||||
from api.extensions import db
|
from api.extensions import db
|
||||||
|
@ -98,7 +99,10 @@ def reconnect_db(func):
|
||||||
|
|
||||||
|
|
||||||
def _flush_db():
|
def _flush_db():
|
||||||
|
try:
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
except (StatementError, OperationalError, InvalidRequestError, PendingRollbackError):
|
||||||
|
db.session.rollback()
|
||||||
|
|
||||||
|
|
||||||
def flush_db(func):
|
def flush_db(func):
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import msgpack
|
import msgpack
|
||||||
|
|
||||||
from api.extensions import cache
|
from api.extensions import cache
|
||||||
from api.extensions import db
|
from api.lib.decorator import flush_db
|
||||||
from api.lib.utils import Lock
|
from api.lib.utils import Lock
|
||||||
from api.models.acl import App
|
from api.models.acl import App
|
||||||
from api.models.acl import Permission
|
from api.models.acl import Permission
|
||||||
|
@ -221,9 +221,9 @@ class RoleRelationCache(object):
|
||||||
return msgpack.loads(r_g, raw=False)
|
return msgpack.loads(r_g, raw=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@flush_db
|
||||||
def rebuild(cls, rid, app_id):
|
def rebuild(cls, rid, app_id):
|
||||||
cls.clean(rid, app_id)
|
cls.clean(rid, app_id)
|
||||||
db.session.remove()
|
|
||||||
|
|
||||||
cls.get_parent_ids(rid, app_id)
|
cls.get_parent_ids(rid, app_id)
|
||||||
cls.get_child_ids(rid, app_id)
|
cls.get_child_ids(rid, app_id)
|
||||||
|
@ -235,9 +235,9 @@ class RoleRelationCache(object):
|
||||||
cls.get_resources2(rid, app_id)
|
cls.get_resources2(rid, app_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@flush_db
|
||||||
def rebuild2(cls, rid, app_id):
|
def rebuild2(cls, rid, app_id):
|
||||||
cache.delete(cls.PREFIX_RESOURCES2.format(rid, app_id))
|
cache.delete(cls.PREFIX_RESOURCES2.format(rid, app_id))
|
||||||
db.session.remove()
|
|
||||||
cls.get_resources2(rid, app_id)
|
cls.get_resources2(rid, app_id)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -58,10 +58,14 @@ class UserCRUD(object):
|
||||||
kwargs['employee_id'] = '{0:04d}'.format(biggest_employee_id + 1)
|
kwargs['employee_id'] = '{0:04d}'.format(biggest_employee_id + 1)
|
||||||
user = User.create(**kwargs)
|
user = User.create(**kwargs)
|
||||||
|
|
||||||
RoleCRUD.add_role(user.username, uid=user.uid)
|
role = RoleCRUD.add_role(user.username, uid=user.uid)
|
||||||
AuditCRUD.add_role_log(None, AuditOperateType.create,
|
AuditCRUD.add_role_log(None, AuditOperateType.create,
|
||||||
AuditScope.user, user.uid, {}, user.to_dict(), {}, {}
|
AuditScope.user, user.uid, {}, user.to_dict(), {}, {}
|
||||||
)
|
)
|
||||||
|
from api.lib.common_setting.employee import EmployeeCRUD
|
||||||
|
payload = {column: getattr(user, column) for column in ['uid', 'username', 'nickname', 'email', 'block']}
|
||||||
|
payload['rid'] = role.id
|
||||||
|
EmployeeCRUD.add_employee_from_acl_created(**payload)
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,8 @@ class UserQuery(BaseQuery):
|
||||||
|
|
||||||
conn = Connection(server, user=who, password=password)
|
conn = Connection(server, user=who, password=password)
|
||||||
conn.bind()
|
conn.bind()
|
||||||
|
if conn.result['result'] != 0:
|
||||||
|
raise LDAPBindError
|
||||||
conn.unbind()
|
conn.unbind()
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
|
|
|
@ -30,6 +30,7 @@ more-itertools==5.0.0
|
||||||
msgpack-python==0.5.6
|
msgpack-python==0.5.6
|
||||||
Pillow==9.3.0
|
Pillow==9.3.0
|
||||||
pycryptodome==3.12.0
|
pycryptodome==3.12.0
|
||||||
|
cryptography==41.0.2
|
||||||
PyJWT==2.4.0
|
PyJWT==2.4.0
|
||||||
PyMySQL==1.1.0
|
PyMySQL==1.1.0
|
||||||
ldap3==2.9.1
|
ldap3==2.9.1
|
||||||
|
|
|
@ -111,10 +111,8 @@ export default {
|
||||||
},
|
},
|
||||||
async beforeMount() {
|
async beforeMount() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
await getOnDutyUser().then((res) => {
|
await this.getOnDutyUser()
|
||||||
this.onDutuUids = res.map((i) => i.uid)
|
|
||||||
this.search()
|
this.search()
|
||||||
})
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
|
@ -148,6 +146,11 @@ export default {
|
||||||
inject: ['reload'],
|
inject: ['reload'],
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
async getOnDutyUser() {
|
||||||
|
await getOnDutyUser().then((res) => {
|
||||||
|
this.onDutuUids = res.map((i) => i.uid)
|
||||||
|
})
|
||||||
|
},
|
||||||
search() {
|
search() {
|
||||||
searchUser({ page_size: 10000 }).then((res) => {
|
searchUser({ page_size: 10000 }).then((res) => {
|
||||||
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
|
const ret = res.users.filter((u) => this.onDutuUids.includes(u.uid))
|
||||||
|
@ -162,8 +165,9 @@ export default {
|
||||||
handleEdit(record) {
|
handleEdit(record) {
|
||||||
this.$refs.userForm.handleEdit(record)
|
this.$refs.userForm.handleEdit(record)
|
||||||
},
|
},
|
||||||
handleOk() {
|
async handleOk() {
|
||||||
this.searchName = ''
|
this.searchName = ''
|
||||||
|
await this.getOnDutyUser()
|
||||||
this.search()
|
this.search()
|
||||||
},
|
},
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
|
|
|
@ -940,10 +940,10 @@ export default {
|
||||||
),
|
),
|
||||||
onOk() {
|
onOk() {
|
||||||
const _tempTree = that.treeKeys[that.treeKeys.length - 1].split('%')
|
const _tempTree = that.treeKeys[that.treeKeys.length - 1].split('%')
|
||||||
const firstCIObj = JSON.parse(_tempTree[2])
|
const first_ci_id = Number(_tempTree[0])
|
||||||
batchDeleteCIRelation(
|
batchDeleteCIRelation(
|
||||||
that.selectedRowKeys.map((item) => item._id),
|
that.selectedRowKeys.map((item) => item._id),
|
||||||
firstCIObj
|
[first_ci_id]
|
||||||
).then((res) => {
|
).then((res) => {
|
||||||
that.$refs.xTable.clearCheckboxRow()
|
that.$refs.xTable.clearCheckboxRow()
|
||||||
that.$refs.xTable.clearCheckboxReserve()
|
that.$refs.xTable.clearCheckboxReserve()
|
||||||
|
|
Loading…
Reference in New Issue