From 186ae319ee00a212dd6f01d748352a4b5c29ba03 Mon Sep 17 00:00:00 2001 From: lhzzforever Date: Mon, 26 Feb 2024 17:27:43 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=E6=9D=83=E9=99=90=E4=BA=A4=E6=8E=A5?= =?UTF-8?q?=E2=80=94>=E7=94=A8=E6=88=B7=E7=BB=84=E6=9D=83=E9=99=90?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=B7=A8=E9=A1=B5=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/transfer/group.vue | 88 ++++++++++++++++++++------- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/frontend/src/views/transfer/group.vue b/frontend/src/views/transfer/group.vue index 1ecee85f2..1cfe6ca02 100644 --- a/frontend/src/views/transfer/group.vue +++ b/frontend/src/views/transfer/group.vue @@ -17,7 +17,7 @@ { + this.groupList.splice(0, this.groupList.length, ...groupList); + this.isEmpty = groupList.length < 1; + this.emptyData = formatCodeData(code, this.emptyData, this.isEmpty); + const selectGroup = this.groupSelectData.length + ? this.groupSelectData.map(item => String(item.id)) : []; + this.groupList.forEach(item => { if (String(item.department_id) !== '0' || item.expired_at < this.user.timestamp) { this.groupNotTransferCount += 1; item.canNotTransfer = true; } + setTimeout(() => { + if (selectGroup.includes(String(item.id))) { + this.$refs.groupTableRef && this.$refs.groupTableRef.toggleRowSelection(item, true); + } + if (this.groupSelectData.length < 1) { + this.$refs.groupTableRef && this.$refs.groupTableRef.clearSelection(); + } + }, 0); }); - this.groupList.splice(0, this.groupList.length, ...groupList); - this.isEmpty = groupList.length < 1; - this.emptyData = formatCodeData(code, this.emptyData, this.isEmpty); + this.fetchSelectedGroupCount(); } catch (e) { console.error(e); this.emptyData = formatCodeData(e.code, this.emptyData); @@ -186,26 +197,61 @@ } }, - handleSelectAll (selection) { - this.isSelectAllChecked = !!selection.length; - if (this.isSelectAllChecked) { - const validGroupList = this.groupList.filter(item => !item.canNotTransfer); - this.groupSelectData.splice( - 0, - this.groupSelectData.length, - ...validGroupList - ); - } else { - this.groupSelectData.splice(0, this.groupSelectData.length, ...[]); - } + fetchSelectedGroupCount () { + setTimeout(() => { + const selectionCount = document.getElementsByClassName('bk-page-selection-count'); + console.log(this.groupSelectData); + if (this.$refs.groupTableRef && selectionCount && selectionCount.length && selectionCount[0].children) { + selectionCount[0].children[0].innerHTML = this.groupSelectData.length; + } + }, 0); + }, + fetchSelectedGroups (type, payload, row) { + const typeMap = { + multiple: () => { + const isChecked = payload.length && payload.indexOf(row) !== -1; + if (isChecked) { + this.groupSelectData.push(row); + } else { + this.groupSelectData = this.groupSelectData.filter((item) => item.id !== row.id); + } + this.fetchSelectedGroupCount(); + }, + all: () => { + const validGroupList = payload.filter(item => !item.canNotTransfer); + const selectGroups = this.groupSelectData.filter((item) => + !this.groupList.map((v) => v.id).includes(item.id)); + console.log(selectGroups, validGroupList); + this.groupSelectData = [...selectGroups, ...validGroupList]; + // this.isSelectAllChecked = !!payload.length; + // if (this.isSelectAllChecked) { + // const validGroupList = this.groupList.filter(item => !item.canNotTransfer); + // this.groupSelectData.splice( + // 0, + // this.groupSelectData.length, + // ...validGroupList + // ); + // } else { + // this.groupSelectData.splice(0, this.groupSelectData.length, ...[]); + // } + console.log(this.groupSelectData); + this.fetchSelectedGroupCount(); + } + }; + return typeMap[type](); + }, + + handleSelectAll (selection) { + // this.isSelectAllChecked = !!selection.length; + this.fetchSelectedGroups('all', selection); this.$emit('group-selection-change', this.groupSelectData); }, - handleSelect (selection) { - const validGroupList = this.groupList.filter(item => !item.canNotTransfer); - this.isSelectAllChecked = selection.length === validGroupList.length; - this.groupSelectData.splice(0, this.groupSelectData.length, ...selection); + handleSelect (selection, row) { + // const validGroupList = this.groupList.filter(item => !item.canNotTransfer); + // this.isSelectAllChecked = selection.length === validGroupList.length; + this.fetchSelectedGroups('multiple', selection, row); this.$emit('group-selection-change', this.groupSelectData); }, From 860440aa9046eabdca5ebf3dcdd67401bc947f36 Mon Sep 17 00:00:00 2001 From: lhzzforever Date: Wed, 28 Feb 2024 16:43:48 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feture:=20=E6=9D=83=E9=99=90=E4=BA=A4?= =?UTF-8?q?=E6=8E=A5=E2=80=94>=E7=AE=A1=E7=90=86=E5=91=98=E4=BA=A4?= =?UTF-8?q?=E6=8E=A5=E5=A2=9E=E5=8A=A0=E8=B7=A8=E9=A1=B5=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/transfer/group.vue | 26 ++++------ frontend/src/views/transfer/manager.vue | 68 +++++++++++++++++++------ 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/frontend/src/views/transfer/group.vue b/frontend/src/views/transfer/group.vue index 1cfe6ca02..9167d5ab5 100644 --- a/frontend/src/views/transfer/group.vue +++ b/frontend/src/views/transfer/group.vue @@ -177,6 +177,9 @@ handleGroupExpanded () { this.groupExpanded = !this.groupExpanded; + if (this.groupExpanded) { + this.fetchData(); + } }, handleGroupShowAll () { @@ -199,10 +202,12 @@ fetchSelectedGroupCount () { setTimeout(() => { - const selectionCount = document.getElementsByClassName('bk-page-selection-count'); - console.log(this.groupSelectData); - if (this.$refs.groupTableRef && selectionCount && selectionCount.length && selectionCount[0].children) { - selectionCount[0].children[0].innerHTML = this.groupSelectData.length; + const paginationWrapper = this.$refs.groupTableRef.$refs.paginationWrapper; + if (paginationWrapper && paginationWrapper.getElementsByClassName('bk-page-selection-count')) { + const selectCount = paginationWrapper.getElementsByClassName('bk-page-selection-count'); + if (selectCount.length && selectCount[0].children && selectCount[0].children.length) { + selectCount[0].children[0].innerHTML = this.groupSelectData.length; + } } }, 0); }, @@ -222,20 +227,7 @@ const validGroupList = payload.filter(item => !item.canNotTransfer); const selectGroups = this.groupSelectData.filter((item) => !this.groupList.map((v) => v.id).includes(item.id)); - console.log(selectGroups, validGroupList); this.groupSelectData = [...selectGroups, ...validGroupList]; - // this.isSelectAllChecked = !!payload.length; - // if (this.isSelectAllChecked) { - // const validGroupList = this.groupList.filter(item => !item.canNotTransfer); - // this.groupSelectData.splice( - // 0, - // this.groupSelectData.length, - // ...validGroupList - // ); - // } else { - // this.groupSelectData.splice(0, this.groupSelectData.length, ...[]); - // } - console.log(this.groupSelectData); this.fetchSelectedGroupCount(); } }; diff --git a/frontend/src/views/transfer/manager.vue b/frontend/src/views/transfer/manager.vue index 08deeb059..1f7dae360 100644 --- a/frontend/src/views/transfer/manager.vue +++ b/frontend/src/views/transfer/manager.vue @@ -10,11 +10,12 @@
String(item.id)) : []; + setTimeout(() => { + this.managerList.forEach(item => { + if (selectGroup.includes(String(item.id))) { + this.$refs.manageTableRef && this.$refs.manageTableRef.toggleRowSelection(item, true); + } + if (this.managerSelectData.length < 1) { + this.$refs.manageTableRef && this.$refs.manageTableRef.clearSelection(); + } + }); + }, 0); + this.fetchSelectedGroupCount(); } catch (e) { console.error(e); const { code } = e; @@ -139,6 +153,9 @@ handleRateExpanded () { this.rateExpanded = !this.rateExpanded; + if (this.rateExpanded) { + this.fetchData(); + } }, handleManagerShowAll () { @@ -159,25 +176,44 @@ } }, - handleSelectAll (selection) { - this.isSelectAllChecked = !!selection.length; - if (this.isSelectAllChecked) { - this.managerSelectData.splice( - 0, - this.managerSelectData.length, - ...this.managerList - ); - } else { - this.managerSelectData.splice(0, this.managerSelectData.length, ...[]); - } + fetchSelectedGroupCount () { + setTimeout(() => { + const paginationWrapper = this.$refs.manageTableRef.$refs.paginationWrapper; + const selectCount = paginationWrapper.getElementsByClassName('bk-page-selection-count'); + if (selectCount.length && selectCount[0].children && selectCount[0].children.length) { + selectCount[0].children[0].innerHTML = this.managerSelectData.length; + } + }, 0); + }, - this.$emit('manager-selection-change', this.managerSelectData); + fetchSelectedGroups (type, payload, row) { + const typeMap = { + multiple: () => { + const isChecked = payload.length && payload.indexOf(row) !== -1; + if (isChecked) { + this.managerSelectData.push(row); + } else { + this.managerSelectData = this.managerSelectData.filter((item) => item.id !== row.id); + } + this.fetchSelectedGroupCount(); + }, + all: () => { + const selectGroups = this.managerSelectData.filter((item) => + !this.managerList.map((v) => v.id).includes(item.id)); + this.managerSelectData = [...selectGroups, ...payload]; + this.fetchSelectedGroupCount(); + } + }; + return typeMap[type](); }, - handleSelect (selection) { - this.isSelectAllChecked = selection.length === this.managerList.length; - this.managerSelectData.splice(0, this.managerSelectData.length, ...selection); + handleSelectAll (selection) { + this.fetchSelectedGroups('all', selection); + this.$emit('manager-selection-change', this.managerSelectData); + }, + handleSelect (selection, row) { + this.fetchSelectedGroups('multiple', selection, row); this.$emit('manager-selection-change', this.managerSelectData); }, From 9ab24452de5d5a7c9e6e4efbb741d8fa47fc3a4e Mon Sep 17 00:00:00 2001 From: lhzzforever Date: Wed, 28 Feb 2024 17:04:58 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=E8=B7=91=E9=A9=AC=E7=81=AF=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=8D=87=E7=BA=A7=E5=88=B02.0.3=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 7fab8f1d6..196869130 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -86,7 +86,7 @@ "@babel/preset-env": "~7.4.5", "@babel/register": "~7.4.4", "@babel/runtime": "~7.4.5", - "@blueking/notice-component-vue2": "^2.0.1", + "@blueking/notice-component-vue2": "^2.0.3", "@blueking/user-selector": "^1.0.11", "@commitlint/cli": "~13.1.0", "@commitlint/config-conventional": "~13.1.0", From 0127447d485fde8aef08f2c249bab51b0ae0ceb0 Mon Sep 17 00:00:00 2001 From: lhzzforever Date: Thu, 29 Feb 2024 10:01:01 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=B1=95=E5=BC=80?= =?UTF-8?q?=E6=97=B6=E5=80=99=E4=B8=8D=E9=9C=80=E8=A6=81=E8=B0=83=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/transfer/group.vue | 40 ++++++++++++++----------- frontend/src/views/transfer/manager.vue | 32 +++++++++++--------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/frontend/src/views/transfer/group.vue b/frontend/src/views/transfer/group.vue index 9167d5ab5..d58584b90 100644 --- a/frontend/src/views/transfer/group.vue +++ b/frontend/src/views/transfer/group.vue @@ -144,23 +144,7 @@ this.groupList.splice(0, this.groupList.length, ...groupList); this.isEmpty = groupList.length < 1; this.emptyData = formatCodeData(code, this.emptyData, this.isEmpty); - const selectGroup = this.groupSelectData.length - ? this.groupSelectData.map(item => String(item.id)) : []; - this.groupList.forEach(item => { - if (String(item.department_id) !== '0' || item.expired_at < this.user.timestamp) { - this.groupNotTransferCount += 1; - item.canNotTransfer = true; - } - setTimeout(() => { - if (selectGroup.includes(String(item.id))) { - this.$refs.groupTableRef && this.$refs.groupTableRef.toggleRowSelection(item, true); - } - if (this.groupSelectData.length < 1) { - this.$refs.groupTableRef && this.$refs.groupTableRef.clearSelection(); - } - }, 0); - }); - this.fetchSelectedGroupCount(); + this.handleGetCheckData(); } catch (e) { console.error(e); this.emptyData = formatCodeData(e.code, this.emptyData); @@ -170,6 +154,26 @@ } }, + handleGetCheckData () { + const selectGroup = this.groupSelectData.length + ? this.groupSelectData.map(item => String(item.id)) : []; + this.groupList.forEach(item => { + if (String(item.department_id) !== '0' || item.expired_at < this.user.timestamp) { + this.groupNotTransferCount += 1; + item.canNotTransfer = true; + } + setTimeout(() => { + if (selectGroup.includes(String(item.id))) { + this.$refs.groupTableRef && this.$refs.groupTableRef.toggleRowSelection(item, true); + } + if (this.groupSelectData.length < 1) { + this.$refs.groupTableRef && this.$refs.groupTableRef.clearSelection(); + } + }, 0); + }); + this.fetchSelectedGroupCount(); + }, + handleEmptyRefresh () { this.pagination = Object.assign(this.pagination, { current: 1, limit: 10 }); this.fetchData(); @@ -178,7 +182,7 @@ handleGroupExpanded () { this.groupExpanded = !this.groupExpanded; if (this.groupExpanded) { - this.fetchData(); + this.handleGetCheckData(); } }, diff --git a/frontend/src/views/transfer/manager.vue b/frontend/src/views/transfer/manager.vue index 1f7dae360..5ebc116b4 100644 --- a/frontend/src/views/transfer/manager.vue +++ b/frontend/src/views/transfer/manager.vue @@ -128,19 +128,7 @@ this.managerList.splice(0, this.managerList.length, ...managerList); this.isEmpty = managerList.length < 1; this.emptyData = formatCodeData(0, this.emptyData, this.isEmpty); - const selectGroup = this.managerSelectData.length - ? this.managerSelectData.map(item => String(item.id)) : []; - setTimeout(() => { - this.managerList.forEach(item => { - if (selectGroup.includes(String(item.id))) { - this.$refs.manageTableRef && this.$refs.manageTableRef.toggleRowSelection(item, true); - } - if (this.managerSelectData.length < 1) { - this.$refs.manageTableRef && this.$refs.manageTableRef.clearSelection(); - } - }); - }, 0); - this.fetchSelectedGroupCount(); + this.handleGetCheckData(); } catch (e) { console.error(e); const { code } = e; @@ -151,10 +139,26 @@ } }, + handleGetCheckData () { + const selectGroup = this.managerSelectData.length + ? this.managerSelectData.map(item => String(item.id)) : []; + setTimeout(() => { + this.managerList.forEach(item => { + if (selectGroup.includes(String(item.id))) { + this.$refs.manageTableRef && this.$refs.manageTableRef.toggleRowSelection(item, true); + } + if (this.managerSelectData.length < 1) { + this.$refs.manageTableRef && this.$refs.manageTableRef.clearSelection(); + } + }); + }, 0); + this.fetchSelectedGroupCount(); + }, + handleRateExpanded () { this.rateExpanded = !this.rateExpanded; if (this.rateExpanded) { - this.fetchData(); + this.handleGetCheckData(); } }, From 79761a88cf7dbf026cf8421ef854db464212f546 Mon Sep 17 00:00:00 2001 From: Timmy Date: Thu, 29 Feb 2024 19:34:05 +0800 Subject: [PATCH 5/5] feat: add group member batch renew api (#2544) --- saas/backend/apps/group/serializers.py | 10 ++++++ saas/backend/apps/group/urls.py | 5 +++ saas/backend/apps/group/views.py | 42 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/saas/backend/apps/group/serializers.py b/saas/backend/apps/group/serializers.py index a86f5c321..a499f9eed 100644 --- a/saas/backend/apps/group/serializers.py +++ b/saas/backend/apps/group/serializers.py @@ -276,6 +276,16 @@ class GroupMemberUpdateExpiredAtSLZ(serializers.Serializer): members = serializers.ListField(label="成员列表", child=GroupMemberExpiredAtSLZ(label="成员"), allow_empty=False) +class GroupMemberExpiredAtItemSLZ(GroupMemberExpiredAtSLZ): + group_id = serializers.IntegerField(label="用户组ID") + + +class BatchGroupMemberUpdateExpiredAtSLZ(serializers.Serializer): + group_members = serializers.ListField( + label="成员列表", child=GroupMemberExpiredAtItemSLZ(label="成员"), allow_empty=False + ) + + class GroupPolicyUpdateSLZ(serializers.Serializer): system_id = serializers.CharField(label="系统ID") template_id = serializers.IntegerField(label="模板ID", required=False, default=0) diff --git a/saas/backend/apps/group/urls.py b/saas/backend/apps/group/urls.py index 91c416339..3b5603042 100644 --- a/saas/backend/apps/group/urls.py +++ b/saas/backend/apps/group/urls.py @@ -24,6 +24,11 @@ views.GroupsMemberViewSet.as_view({"post": "destroy"}), name="group.members_delete", ), + path( + "members/renew/", + views.GroupsMemberRenewViewSet.as_view({"post": "create"}), + name="group.members_renew", + ), path("transfer/", views.GroupTransferView.as_view(), name="group.transfer"), path("search/", views.GroupSearchViewSet.as_view({"post": "search"}), name="group.search"), # 用户组详情 diff --git a/saas/backend/apps/group/views.py b/saas/backend/apps/group/views.py index 94c69e08e..0f59c3d99 100644 --- a/saas/backend/apps/group/views.py +++ b/saas/backend/apps/group/views.py @@ -68,6 +68,7 @@ from .filters import GroupFilter, GroupSubjectTemplateFilter, GroupTemplateSystemFilter from .serializers import ( BatchGroupDeleteMemberSLZ, + BatchGroupMemberUpdateExpiredAtSLZ, GradeManagerGroupTransferSLZ, GroupAddMemberSLZ, GroupAuthorizationSLZ, @@ -561,6 +562,47 @@ def destroy(self, request, *args, **kwargs): raise error_codes.ACTIONS_PARTIAL_FAILED.format(failed_info) +class GroupsMemberRenewViewSet(GenericViewSet): + + group_biz = GroupBiz() + + @swagger_auto_schema( + operation_description="批量用户组添加成员", + request_body=BatchGroupMemberUpdateExpiredAtSLZ(label="成员"), + responses={status.HTTP_200_OK: serializers.Serializer()}, + tags=["group"], + ) + def create(self, request, *args, **kwargs): + serializer = BatchGroupMemberUpdateExpiredAtSLZ(data=request.data) + serializer.is_valid(raise_exception=True) + + data = serializer.validated_data + + role_checker = RoleObjectRelationChecker(request.role) + for group_member in data["group_members"]: + group = Group.objects.filter(id=group_member["group_id"]).first() + if not group: + continue + + if not role_checker.check_group(group): + self.permission_denied(request, message=f"{request.role.type} role can not access group {group.id}") + + if group_member["type"] != GroupMemberType.TEMPLATE.value: + member = parse_obj_as(GroupMemberExpiredAtBean, group_member) + self.group_biz.update_members_expired_at(group.id, [member]) + + # 处理人员模版的续期 + if group_member["type"] == GroupMemberType.TEMPLATE.value: + self.group_biz.update_subject_template_expired_at( + group.id, int(group_member["id"]), group_member["expired_at"] + ) + + # 写入审计上下文 + audit_context_setter(group=group, members=data["members"]) + + return Response({}) + + class GroupMemberUpdateExpiredAtViewSet(GroupPermissionMixin, GenericViewSet): permission_classes = [role_perm_class(PermissionCodeEnum.MANAGE_GROUP.value)]