diff --git a/cmdb-api/api/lib/cmdb/ci.py b/cmdb-api/api/lib/cmdb/ci.py
index 2594a08..88530d0 100644
--- a/cmdb-api/api/lib/cmdb/ci.py
+++ b/cmdb-api/api/lib/cmdb/ci.py
@@ -485,7 +485,7 @@ class CIRelationManager(object):
return numfound, len(first_ci_ids), result
@classmethod
- def add(cls, first_ci_id, second_ci_id, more=None, relation_type_id=None):
+ def add(cls, first_ci_id, second_ci_id, more=None, relation_type_id=None, many_to_one=False):
first_ci = CIManager.confirm_ci_existed(first_ci_id)
second_ci = CIManager.confirm_ci_existed(second_ci_id)
@@ -495,7 +495,7 @@ class CIRelationManager(object):
to_dict=False,
first=True)
if existed is not None:
- if existed.relation_type_id != relation_type_id:
+ if existed.relation_type_id != relation_type_id and relation_type_id is not None:
existed.update(relation_type_id=relation_type_id)
CIRelationHistoryManager().add(existed, OperateType.UPDATE)
@@ -509,6 +509,16 @@ class CIRelationManager(object):
relation_type_id or abort(404, "Relation {0} <-> {1} is not found".format(
first_ci.ci_type.name, second_ci.ci_type.name))
+ if many_to_one:
+ for item in CIRelation.get_by(second_ci_id=second_ci_id,
+ relation_type_id=relation_type_id,
+ to_dict=False):
+ item.soft_delete()
+ his_manager = CIRelationHistoryManager()
+ his_manager.add(item, operate_type=OperateType.DELETE)
+
+ ci_relation_delete.apply_async(args=(item.first_ci_id, item.second_ci_id), queue=CMDB_QUEUE)
+
existed = CIRelation.create(first_ci_id=first_ci_id,
second_ci_id=second_ci_id,
relation_type_id=relation_type_id)
@@ -544,3 +554,25 @@ class CIRelationManager(object):
ci_relation_delete.apply_async(args=(first_ci_id, second_ci_id), queue=CMDB_QUEUE)
return cls.delete(cr.id)
+
+ @classmethod
+ def batch_update(cls, ci_ids, parents):
+ """
+ only for many to one
+ :param ci_ids:
+ :param parents:
+ :return:
+ """
+ from api.lib.cmdb.utils import TableMap
+
+ if parents is not None and isinstance(parents, dict):
+ for attr_name in parents:
+ if parents[attr_name]:
+ attr = AttributeCache.get(attr_name)
+ value_table = TableMap(attr_name=attr.name).table
+ parent = value_table.get_by(attr_id=attr.id, value=parents[attr_name], first=True, to_dict=False)
+ if not parent:
+ return abort(404, "{0}: {1} is not found".format(attr_name, parents[attr_name]))
+ parent_id = parent.ci_id
+ for ci_id in ci_ids:
+ cls.add(parent_id, ci_id, many_to_one=True)
diff --git a/cmdb-api/api/tasks/cmdb.py b/cmdb-api/api/tasks/cmdb.py
index 7560b5e..5210567 100644
--- a/cmdb-api/api/tasks/cmdb.py
+++ b/cmdb-api/api/tasks/cmdb.py
@@ -11,7 +11,7 @@ from api.extensions import celery
from api.extensions import db
from api.extensions import es
from api.extensions import rd
-from api.lib.cmdb.cache import CITypeAttributeCache
+from api.lib.cmdb.cache import CITypeAttributesCache
from api.lib.cmdb.const import CMDB_QUEUE
from api.lib.cmdb.const import REDIS_PREFIX_CI
from api.lib.cmdb.const import REDIS_PREFIX_CI_RELATION
@@ -81,7 +81,7 @@ def ci_type_attribute_order_rebuild(type_id):
from api.lib.cmdb.ci_type import CITypeAttributeGroupManager
- attrs = CITypeAttributeCache.get(type_id)
+ attrs = CITypeAttributesCache.get(type_id)
id2attr = {attr.attr_id: attr for attr in attrs}
res = CITypeAttributeGroupManager.get_by_type_id(type_id, True)
diff --git a/cmdb-api/api/views/cmdb/ci_relation.py b/cmdb-api/api/views/cmdb/ci_relation.py
index 38ed735..e0fa467 100644
--- a/cmdb-api/api/views/cmdb/ci_relation.py
+++ b/cmdb-api/api/views/cmdb/ci_relation.py
@@ -11,6 +11,7 @@ from api.lib.cmdb.cache import RelationTypeCache
from api.lib.cmdb.ci import CIRelationManager
from api.lib.cmdb.search import SearchError
from api.lib.cmdb.search.ci_relation.search import Search
+from api.lib.decorator import args_required
from api.lib.perm.auth import auth_abandoned
from api.lib.utils import get_page
from api.lib.utils import get_page_size
@@ -122,11 +123,13 @@ class CIRelationView(APIView):
def post(self, first_ci_id, second_ci_id):
manager = CIRelationManager()
res = manager.add(first_ci_id, second_ci_id)
+
return self.jsonify(cr_id=res)
def delete(self, first_ci_id, second_ci_id):
manager = CIRelationManager()
manager.delete_2(first_ci_id, second_ci_id)
+
return self.jsonify(message="CIType Relation is deleted")
@@ -136,4 +139,24 @@ class DeleteCIRelationView(APIView):
def delete(self, cr_id):
manager = CIRelationManager()
manager.delete(cr_id)
+
return self.jsonify(message="CIType Relation is deleted")
+
+
+class BatchCreateOrUpdateCIRelationView(APIView):
+ url_prefix = "/ci_relations/batch"
+
+ @args_required('ci_ids')
+ @args_required('parents')
+ def post(self):
+ ci_ids = request.values.get('ci_ids')
+ parents = request.values.get('parents')
+
+ CIRelationManager.batch_update(ci_ids, parents)
+
+ return self.jsonify(code=200)
+
+ @args_required('ci_ids')
+ @args_required('parents')
+ def put(self):
+ return self.post()
diff --git a/cmdb-ui/package.json b/cmdb-ui/package.json
index 1adca4b..9d0ee54 100644
--- a/cmdb-ui/package.json
+++ b/cmdb-ui/package.json
@@ -15,7 +15,7 @@
"@antv/data-set": "^0.10.2",
"@handsontable-pro/vue": "^3.1.1",
"@handsontable/vue": "^4.1.1",
- "ant-design-vue": "1.5.0-beta.1",
+ "ant-design-vue": "1.5.0",
"axios": "^0.19.0",
"core-js": "^3.1.2",
"enquire.js": "^2.1.6",
diff --git a/cmdb-ui/src/App.vue b/cmdb-ui/src/App.vue
index ff0f9cd..5b48756 100644
--- a/cmdb-ui/src/App.vue
+++ b/cmdb-ui/src/App.vue
@@ -1,9 +1,9 @@
-
+
-
+
diff --git a/cmdb-ui/yarn.lock b/cmdb-ui/yarn.lock
index 9e0602e..0fce044 100644
--- a/cmdb-ui/yarn.lock
+++ b/cmdb-ui/yarn.lock
@@ -2017,10 +2017,10 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
-ant-design-vue@1.5.0-beta.1:
- version "1.5.0-beta.1"
- resolved "https://registry.yarnpkg.com/ant-design-vue/-/ant-design-vue-1.5.0-beta.1.tgz#9396e1bb4435c9bc5dc224e2bd888a000144a8f9"
- integrity sha512-Fv5vxO+qHakbjsswgZ70/bjiZK4FphdFxv31VjBJKfhA5Ud7K6sNqC0BVpYS8nL0BwxGCVG8I30efNdU3VifnA==
+ant-design-vue@1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/ant-design-vue/-/ant-design-vue-1.5.0.tgz#2e2c5658cf1211be06fbee95a18eee02965e089f"
+ integrity sha512-12+mTowYNZZhsXFR848BZRWGtZrWGayJx9j8Dv3gpgPBU4Abi86tz0hUSbnp8RXL6wb7xNcE9JoawNeE9Y83+Q==
dependencies:
"@ant-design/icons" "^2.1.1"
"@ant-design/icons-vue" "^2.0.0"