user role & group & accounts

This commit is contained in:
MaxKey 2022-05-24 17:13:07 +08:00
parent 9ab56c7803
commit 3cabc8a790
34 changed files with 985 additions and 165 deletions

View File

@ -38,6 +38,8 @@ public interface GroupMemberMapper extends IJpaBaseMapper<GroupMember> {
public List<GroupMember> memberNotInGroup(GroupMember entity); public List<GroupMember> memberNotInGroup(GroupMember entity);
public List<GroupMember> groupMemberInGroup(GroupMember entity); public List<GroupMember> groupMemberInGroup(GroupMember entity);
public List<Groups> groupsNoMember(GroupMember entity);
public int addDynamicGroupMember(Groups dynamicGroup); public int addDynamicGroupMember(Groups dynamicGroup);
public int deleteDynamicGroupMember(Groups dynamicGroup); public int deleteDynamicGroupMember(Groups dynamicGroup);

View File

@ -37,6 +37,8 @@ public interface RoleMemberMapper extends IJpaBaseMapper<RoleMember> {
public List<RoleMember> memberNotInRole(RoleMember entity); public List<RoleMember> memberNotInRole(RoleMember entity);
public List<RoleMember> roleMemberInRole(RoleMember entity); public List<RoleMember> roleMemberInRole(RoleMember entity);
public List<Roles> rolesNoMember(RoleMember entity);
public int addDynamicRoleMember(Roles dynamicRole); public int addDynamicRoleMember(Roles dynamicRole);
public int deleteDynamicRoleMember(Roles dynamicRole); public int deleteDynamicRoleMember(Roles dynamicRole);

View File

@ -20,14 +20,18 @@ package org.maxkey.persistence.service;
import java.util.List; import java.util.List;
import org.apache.mybatis.jpa.persistence.JpaBaseService; import org.apache.mybatis.jpa.persistence.JpaBaseService;
import org.apache.mybatis.jpa.persistence.JpaPageResults;
import org.maxkey.entity.GroupMember; import org.maxkey.entity.GroupMember;
import org.maxkey.entity.Groups; import org.maxkey.entity.Groups;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.mapper.GroupMemberMapper; import org.maxkey.persistence.mapper.GroupMemberMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
public class GroupMemberService extends JpaBaseService<GroupMember>{ public class GroupMemberService extends JpaBaseService<GroupMember>{
final static Logger _logger = LoggerFactory.getLogger(GroupMemberService.class);
public GroupMemberService() { public GroupMemberService() {
super(GroupMemberMapper.class); super(GroupMemberMapper.class);
@ -57,4 +61,29 @@ public class GroupMemberService extends JpaBaseService<GroupMember>{
return getMapper().queryMemberByGroupId(groupId); return getMapper().queryMemberByGroupId(groupId);
} }
public JpaPageResults<Groups> groupsNoMember(GroupMember entity) {
entity.setPageResultSelectUUID(entity.generateId());
entity.setStartRow(calculateStartRow(entity.getPageNumber() ,entity.getPageSize()));
entity.setPageable(true);
List<Groups> resultslist = null;
try {
resultslist = getMapper().groupsNoMember(entity);
} catch (Exception e) {
_logger.error("queryPageResults Exception " , e);
}
entity.setPageable(false);
Integer totalPage = resultslist.size();
Integer totalCount = 0;
if(entity.getPageNumber() == 1 && totalPage < entity.getPageSize()) {
totalCount = totalPage;
}else {
totalCount = parseCount(getMapper().queryPageResultsCount(entity));
}
return new JpaPageResults<Groups>(entity.getPageNumber(),entity.getPageSize(),totalPage,totalCount,resultslist);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,15 +17,22 @@
package org.maxkey.persistence.service; package org.maxkey.persistence.service;
import java.util.List;
import org.apache.mybatis.jpa.persistence.JpaBaseService; import org.apache.mybatis.jpa.persistence.JpaBaseService;
import org.apache.mybatis.jpa.persistence.JpaPageResults;
import org.maxkey.entity.RoleMember; import org.maxkey.entity.RoleMember;
import org.maxkey.entity.Roles; import org.maxkey.entity.Roles;
import org.maxkey.persistence.mapper.RoleMemberMapper; import org.maxkey.persistence.mapper.RoleMemberMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
public class RoleMemberService extends JpaBaseService<RoleMember>{ public class RoleMemberService extends JpaBaseService<RoleMember>{
final static Logger _logger = LoggerFactory.getLogger(RoleMemberService.class);
public RoleMemberService() { public RoleMemberService() {
super(RoleMemberMapper.class); super(RoleMemberMapper.class);
} }
@ -50,4 +57,28 @@ public class RoleMemberService extends JpaBaseService<RoleMember>{
public int deleteByRoleId(String roleId) { public int deleteByRoleId(String roleId) {
return getMapper().deleteByRoleId(roleId); return getMapper().deleteByRoleId(roleId);
} }
public JpaPageResults<Roles> rolesNoMember(RoleMember entity) {
entity.setPageResultSelectUUID(entity.generateId());
entity.setStartRow(calculateStartRow(entity.getPageNumber() ,entity.getPageSize()));
entity.setPageable(true);
List<Roles> resultslist = null;
try {
resultslist = getMapper().rolesNoMember(entity);
} catch (Exception e) {
_logger.error("queryPageResults Exception " , e);
}
entity.setPageable(false);
Integer totalPage = resultslist.size();
Integer totalCount = 0;
if(entity.getPageNumber() == 1 && totalPage < entity.getPageSize()) {
totalCount = totalPage;
}else {
totalCount = parseCount(getMapper().queryPageResultsCount(entity));
}
return new JpaPageResults<Roles>(entity.getPageNumber(),entity.getPageSize(),totalPage,totalCount,resultslist);
}
} }

View File

@ -139,6 +139,28 @@
</if> </if>
</select> </select>
<select id="groupsNoMember" parameterType="GroupMember" resultType="Groups">
select distinct
g.*
from
mxk_groups g
where
g.id not in(
select
gm.groupid
from mxk_group_member gm,mxk_userinfo u
where gm.memberid = u.id
<if test="username != null and username != ''">
and u.username = #{username}
</if>
<if test="memberId != null and memberId != ''">
and gm.memberid = #{memberid}
</if>
)
<if test="groupName != null and groupName != ''">
and g.name = #{groupName}
</if>
</select>
<!-- GROUP_MEMBER Group Member--> <!-- GROUP_MEMBER Group Member-->
<select id="groupMemberInGroup" parameterType="GroupMember" resultType="Groups"> <select id="groupMemberInGroup" parameterType="GroupMember" resultType="Groups">

View File

@ -142,6 +142,29 @@
</select> </select>
<select id="rolesNoMember" parameterType="RoleMember" resultType="Roles">
select distinct
r.*
from
mxk_roles r
where
r.id not in(
select
rm.roleid
from mxk_role_member rm,mxk_userinfo u
where rm.memberid = u.id
<if test="username != null and username != ''">
and u.username = #{username}
</if>
<if test="memberId != null and memberId != ''">
and rm.memberid = #{memberid}
</if>
)
<if test="roleName != null and roleName != ''">
and r.name = #{roleName}
</if>
</select>
<!-- ROLE_MEMBER Roles Member--> <!-- ROLE_MEMBER Roles Member-->
<select id="roleMemberInRole" parameterType="RoleMember" resultType="Roles"> <select id="roleMemberInRole" parameterType="RoleMember" resultType="Roles">
select distinct select distinct

View File

@ -29,6 +29,7 @@ import { SessionsComponent } from './sessions/sessions.component';
import { SelectGroupsComponent } from './groups/select-groups/select-groups.component'; import { SelectGroupsComponent } from './groups/select-groups/select-groups.component';
import { GroupMembersEditerComponent } from './group-members/group-members-editer/group-members-editer.component'; import { GroupMembersEditerComponent } from './group-members/group-members-editer/group-members-editer.component';
import { PrivilegesEditerComponent } from './privileges/privileges-editer/privileges-editer.component'; import { PrivilegesEditerComponent } from './privileges/privileges-editer/privileges-editer.component';
import { MemberGroupsEditerComponent } from './group-members/member-groups-editer/member-groups-editer.component';
const routes: Routes = [ const routes: Routes = [
{ {
@ -52,7 +53,7 @@ const routes: Routes = [
const COMPONENTS = [SessionsComponent, GroupsComponent, GroupMembersComponent, PrivilegesComponent, GroupEditerComponent]; const COMPONENTS = [SessionsComponent, GroupsComponent, GroupMembersComponent, PrivilegesComponent, GroupEditerComponent];
@NgModule({ @NgModule({
declarations: [...COMPONENTS, PrivilegesComponent, SelectGroupsComponent, GroupMembersEditerComponent, PrivilegesEditerComponent], declarations: [...COMPONENTS, PrivilegesComponent, SelectGroupsComponent, GroupMembersEditerComponent, PrivilegesEditerComponent, MemberGroupsEditerComponent],
imports: [NzIconModule, SharedModule, CommonModule, RouterModule.forChild(routes)], imports: [NzIconModule, SharedModule, CommonModule, RouterModule.forChild(routes)],
exports: [RouterModule] exports: [RouterModule]
}) })

View File

@ -3,7 +3,7 @@
<nz-card [nzBordered]="false"> <nz-card [nzBordered]="false">
<form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form"> <form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form">
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 24, lg: 24, xl: 48, xxl: 48 }"> <div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 24, lg: 24, xl: 48, xxl: 48 }">
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="8" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.groups.name' | i18n }}</nz-form-label> <nz-form-label nzFor="name">{{ 'mxk.groups.name' | i18n }}</nz-form-label>
<nz-form-control> <nz-form-control>
@ -18,7 +18,7 @@
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="8" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.users.username' | i18n }}</nz-form-label> <nz-form-label nzFor="name">{{ 'mxk.users.username' | i18n }}</nz-form-label>
<nz-form-control> <nz-form-control>
@ -27,11 +27,10 @@
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col [nzSpan]="query.expandForm ? 24 : 4" [class.text-right]="query.expandForm"> <div nz-col [nzSpan]="query.expandForm ? 24 : 8" [class.text-right]="query.expandForm">
<button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{ 'mxk.text.query' | <button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{ 'mxk.text.query' |
i18n }}</button> i18n }}</button>
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{ 'mxk.text.reset' | <button nz-button type="reset" (click)="onReset()" class="mx-sm">{{ 'mxk.text.reset' | i18n }}</button>
i18n }}</button>
<button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none"> <button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none">
{{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button> {{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button>
</div> </div>

View File

@ -1,22 +1,22 @@
/* /*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { _HttpClient } from '@delon/theme'; import { _HttpClient } from '@delon/theme';
import { format, addDays } from 'date-fns'; import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types'; import { NzSafeAny } from 'ng-zorro-antd/core/types';
@ -30,6 +30,7 @@ import { GroupMembersService } from '../../../service/group-members.service';
import { set2String } from '../../../shared/index'; import { set2String } from '../../../shared/index';
import { SelectGroupsComponent } from '../groups/select-groups/select-groups.component'; import { SelectGroupsComponent } from '../groups/select-groups/select-groups.component';
import { GroupMembersEditerComponent } from './group-members-editer/group-members-editer.component'; import { GroupMembersEditerComponent } from './group-members-editer/group-members-editer.component';
import { MemberGroupsEditerComponent } from './member-groups-editer/member-groups-editer.component';
@Component({ @Component({
selector: 'app-group-members', selector: 'app-group-members',
@ -99,10 +100,14 @@ export class GroupMembersComponent implements OnInit {
private viewContainerRef: ViewContainerRef, private viewContainerRef: ViewContainerRef,
private fb: FormBuilder, private fb: FormBuilder,
private msg: NzMessageService, private msg: NzMessageService,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
if (this.route.snapshot.queryParams['username']) {
this.query.params.username = this.route.snapshot.queryParams['username'];
}
this.query.tableInitialize = false; this.query.tableInitialize = false;
} }
@ -118,7 +123,12 @@ export class GroupMembersComponent implements OnInit {
this.fetch(); this.fetch();
} }
onReset(): void { } onReset(): void {
this.query.params.username = '';
this.query.params.groupId = '';
this.query.params.name = '';
this.fetch();
}
onBatchDelete(e: MouseEvent): void { onBatchDelete(e: MouseEvent): void {
e.preventDefault(); e.preventDefault();
@ -135,22 +145,40 @@ export class GroupMembersComponent implements OnInit {
onAdd(e: MouseEvent): void { onAdd(e: MouseEvent): void {
e.preventDefault(); e.preventDefault();
const modal = this.modalService.create({ if (this.query.params.username != '') {
nzContent: GroupMembersEditerComponent, const modal = this.modalService.create({
nzViewContainerRef: this.viewContainerRef, nzContent: MemberGroupsEditerComponent,
nzComponentParams: { nzViewContainerRef: this.viewContainerRef,
isEdit: false, nzComponentParams: {
groupId: this.query.params.groupId username: this.query.params.username
}, },
nzWidth: 700, nzWidth: 700,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000)) nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
}); });
// Return a result when closed // Return a result when closed
modal.afterClose.subscribe(result => { modal.afterClose.subscribe(result => {
if (result.refresh) { if (result.refresh) {
this.fetch(); this.fetch();
} }
}); });
} else if (this.query.params.groupId != '') {
const modal = this.modalService.create({
nzContent: GroupMembersEditerComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: false,
groupId: this.query.params.groupId
},
nzWidth: 700,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
} }
onSelect(e: MouseEvent): void { onSelect(e: MouseEvent): void {

View File

@ -0,0 +1,56 @@
<div *nzModalTitle> {{ 'mxk.text.add' | i18n }} </div>
<nz-card [nzBordered]="false">
<form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form">
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }">
<div nz-col nzMd="14" nzSm="24">
<nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.groups.name' | i18n }}</nz-form-label>
<nz-form-control>
<input nz-input [(ngModel)]="query.params.groupName" [ngModelOptions]="{ standalone: true }"
name="groupName" placeholder="" id="groupName" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="query.expandForm ? 24 : 10" [class.text-right]="query.expandForm">
<button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{
'mxk.text.query' | i18n }}</button>
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{
'mxk.text.reset' | i18n }}</button>
<button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none">
{{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.confirm' | i18n }}</button>
</div>
</div>
</form>
<nz-table #dynamicTable nzTableLayout="auto" nzBordered nzShowSizeChanger [nzData]="query.results.rows"
[nzFrontPagination]="false" [nzTotal]="query.results.records" [nzPageSizeOptions]="query.params.pageSizeOptions"
[nzPageSize]="query.params.pageSize" [nzPageIndex]="query.params.pageNumber"
[nzLoading]="this.query.tableLoading" (nzQueryParams)="onQueryParamsChange($event)" nzWidth="100%">
<thead>
<tr>
<th></th>
<th nzAlign="center" style="display: none">Id</th>
<th nzAlign="center">{{ 'mxk.groups.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.groups.dynamic' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of query.results.rows">
<td [nzChecked]="query.tableCheckedId.has(data.id)" [nzDisabled]="data.disabled"
(nzCheckedChange)="onTableItemChecked(data.id, $event)"></td>
<td nzAlign="left" style="display: none">
<span>{{ data.id }}</span>
</td>
<td nzAlign="left"> {{ data.name }}</td>
<td nzAlign="center"> <i *ngIf="data.dynamic == 1" nz-icon nzType="check-circle" nzTheme="fill"
style="color: green"></i></td>
</tr>
</tbody>
</nz-table>
</nz-card>
<div *nzModalFooter style="display: none">
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MemberGroupsEditerComponent } from './member-groups-editer.component';
describe('MemberGroupsEditerComponent', () => {
let component: MemberGroupsEditerComponent;
let fixture: ComponentFixture<MemberGroupsEditerComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MemberGroupsEditerComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MemberGroupsEditerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,170 @@
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit, Input } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { _HttpClient } from '@delon/theme';
import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { GroupMembersService } from '../../../../service/group-members.service';
@Component({
selector: 'app-member-groups-editer',
templateUrl: './member-groups-editer.component.html',
styleUrls: ['./member-groups-editer.component.less']
})
export class MemberGroupsEditerComponent implements OnInit {
@Input() username?: String;
query: {
params: {
groupName: String;
username: String;
protocol: String;
startDate: String;
endDate: String;
startDatePicker: Date;
endDatePicker: Date;
pageSize: number;
pageNumber: number;
pageSizeOptions: number[];
};
results: {
records: number;
rows: NzSafeAny[];
};
expandForm: Boolean;
submitLoading: boolean;
tableLoading: boolean;
tableCheckedId: Set<String>;
indeterminate: boolean;
checked: boolean;
} = {
params: {
groupName: '',
username: '',
protocol: '',
startDate: '',
endDate: '',
startDatePicker: addDays(new Date(), -30),
endDatePicker: new Date(),
pageSize: 5,
pageNumber: 1,
pageSizeOptions: [5, 15, 50]
},
results: {
records: 0,
rows: []
},
expandForm: false,
submitLoading: false,
tableLoading: false,
tableCheckedId: new Set<String>(),
indeterminate: false,
checked: false
};
constructor(
private modalRef: NzModalRef,
private groupMembersService: GroupMembersService,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder,
private msg: NzMessageService,
private cdr: ChangeDetectorRef
) { }
ngOnInit(): void {
if (this.username) {
this.query.params.username = this.username;
}
this.fetch();
}
onQueryParamsChange(tableQueryParams: NzTableQueryParams): void {
this.query.params.pageNumber = tableQueryParams.pageIndex;
this.query.params.pageSize = tableQueryParams.pageSize;
this.fetch();
}
onSearch(): void {
this.fetch();
}
onReset(): void { }
fetch(): void {
this.query.submitLoading = true;
this.query.tableLoading = true;
this.query.indeterminate = false;
this.query.checked = true;
this.query.tableCheckedId.clear();
if (this.query.expandForm) {
this.query.params.endDate = format(this.query.params.endDatePicker, 'yyyy-MM-dd HH:mm:ss');
this.query.params.startDate = format(this.query.params.startDatePicker, 'yyyy-MM-dd HH:mm:ss');
} else {
this.query.params.endDate = '';
this.query.params.startDate = '';
}
this.groupMembersService.groupsNoMember(this.query.params).subscribe(res => {
this.query.results = res.data;
this.query.submitLoading = false;
this.query.tableLoading = false;
this.cdr.detectChanges();
});
}
updateTableCheckedSet(id: String, checked: boolean): void {
if (checked) {
this.query.tableCheckedId.add(id);
} else {
this.query.tableCheckedId.delete(id);
}
}
refreshTableCheckedStatus(): void {
const listOfEnabledData = this.query.results.rows.filter(({ disabled }) => !disabled);
this.query.checked = listOfEnabledData.every(({ id }) => this.query.tableCheckedId.has(id));
this.query.indeterminate = listOfEnabledData.some(({ id }) => this.query.tableCheckedId.has(id)) && !this.query.checked;
}
onTableItemChecked(id: String, checked: boolean): void {
//this.onTableAllChecked(false);
this.updateTableCheckedSet(id, checked);
this.refreshTableCheckedStatus();
}
onTableAllChecked(checked: boolean): void {
this.query.results.rows.filter(({ disabled }) => !disabled).forEach(({ id }) => this.updateTableCheckedSet(id, checked));
this.refreshTableCheckedStatus();
}
onSubmit(e: MouseEvent): void {
e.preventDefault();
const listOfEnabledData = this.query.results.rows.filter(({ disabled }) => !disabled);
let selectedData = listOfEnabledData.filter(({ id, name }) => {
return this.query.tableCheckedId.has(id);
});
let groupIds = '';
let groupNames = '';
for (let i = 0; i < selectedData.length; i++) {
groupIds = `${groupIds},${selectedData[i].id}`;
groupNames = `${groupNames},${selectedData[i].name}`;
}
this.groupMembersService.addMember2Groups({ username: this.username, groupId: groupIds, groupName: groupNames }).subscribe(res => {
this.query.results = res.data;
this.query.submitLoading = false;
this.query.tableLoading = false;
if (res.code == 0) {
this.msg.success(`提交成功`);
this.fetch();
} else {
this.msg.success(`提交失败`);
}
this.cdr.detectChanges();
});
}
onClose(e: MouseEvent): void {
e.preventDefault();
}
}

View File

@ -4,140 +4,119 @@
<nz-form-item style="display: none"> <nz-form-item style="display: none">
<nz-form-label [nzMd]="6" nzFor="id">{{ 'mxk.text.id' | i18n }}</nz-form-label> <nz-form-label [nzMd]="6" nzFor="id">{{ 'mxk.text.id' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!"> <nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.id" disabled="{{ isEdit }}" [ngModelOptions]="{ standalone: true }" nz-input name="id" id="id" /> <input [(ngModel)]="form.model.id" disabled="{{ isEdit }}" [ngModelOptions]="{ standalone: true }" nz-input
name="id" id="id" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item style="display: none"> <nz-form-item style="display: none">
<nz-form-label [nzSm]="6" [nzXs]="24" readonly nzRequired nzFor="userId">{{ 'mxk.users.id' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" readonly nzRequired nzFor="userId">{{ 'mxk.users.id' | i18n }}
</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid minLength!"> <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid minLength!">
<input [(ngModel)]="form.model.userId" [ngModelOptions]="{ standalone: true }" nz-input name="userId" id="userId" /> <input [(ngModel)]="form.model.userId" [ngModelOptions]="{ standalone: true }" nz-input name="userId"
id="userId" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item *ngIf="!isEdit && username == ''">
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="displayName">{{ 'mxk.users.displayName' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="displayName">{{ 'mxk.users.displayName' | i18n }}
</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid displayName!"> <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid displayName!">
<nz-input-group nzSearch [nzAddOnAfter]="suffixButton"> <nz-input-group nzSearch [nzAddOnAfter]="suffixButton">
<input <input [(ngModel)]="form.model.displayName" readonly [ngModelOptions]="{ standalone: true }" nz-input
[(ngModel)]="form.model.displayName" name="displayName" id="displayName" />
readonly
[ngModelOptions]="{ standalone: true }"
nz-input
name="displayName"
id="displayName"
/>
</nz-input-group> </nz-input-group>
<ng-template #suffixButton> <ng-template #suffixButton>
<button nz-button nzType="primary" nzSearch (click)="onSelectUser($event)">{{ 'mxk.text.select' | i18n }}</button> <button nz-button nzType="primary" nzSearch (click)="onSelectUser($event)">{{ 'mxk.text.select' | i18n
}}</button>
</ng-template> </ng-template>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item *ngIf="isEdit || username !== ''">
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="displayName">{{ 'mxk.users.displayName' | i18n }}
</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid displayName!">
<nz-input-group>
<input [(ngModel)]="form.model.displayName" disabled [ngModelOptions]="{ standalone: true }" nz-input
name="displayName" id="displayName" />
</nz-input-group>
</nz-form-control>
</nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="username">{{ 'mxk.users.username' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="username">{{ 'mxk.users.username' | i18n }}
</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid username!"> <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid username!">
<input <input [(ngModel)]="form.model.username" disabled="true" [ngModelOptions]="{ standalone: true }" nz-input
[(ngModel)]="form.model.username" name="username" id="username" />
disabled="true"
[ngModelOptions]="{ standalone: true }"
nz-input
name="username"
id="username"
/>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item style="display: none"> <nz-form-item style="display: none">
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="strategyId">{{ 'mxk.accountsstrategy.id' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="strategyId">{{ 'mxk.accountsstrategy.id' | i18n }}
</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid strategyId!"> <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid strategyId!">
<input <input [(ngModel)]="form.model.strategyId" readonly [ngModelOptions]="{ standalone: true }" nz-input
[(ngModel)]="form.model.strategyId" name="strategyId" id="strategyId" />
readonly
[ngModelOptions]="{ standalone: true }"
nz-input
name="strategyId"
id="strategyId"
/>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="strategyName">{{ 'mxk.accountsstrategy.name' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="strategyName">{{ 'mxk.accountsstrategy.name' | i18n }}
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid strategyName!"> </nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48"
nzErrorTip="The input is not valid strategyName!">
<nz-input-group nzSearch [nzAddOnAfter]="suffixStrategyButton"> <nz-input-group nzSearch [nzAddOnAfter]="suffixStrategyButton">
<input <input [(ngModel)]="form.model.strategyName" [ngModelOptions]="{ standalone: true }" nz-input readonly
[(ngModel)]="form.model.strategyName" name="strategyName" id="strategyName" />
[ngModelOptions]="{ standalone: true }"
nz-input
readonly
name="strategyName"
id="strategyName"
/>
</nz-input-group> </nz-input-group>
<ng-template #suffixStrategyButton> <ng-template #suffixStrategyButton>
<button nz-button nzType="primary" nzSearch (click)="onSelectStrategy($event)">{{ 'mxk.text.select' | i18n }}</button> <button nz-button nzType="primary" nzSearch (click)="onSelectStrategy($event)">{{ 'mxk.text.select' | i18n
}}</button>
</ng-template> </ng-template>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item style="display: none"> <nz-form-item style="display: none">
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="appId">{{ 'mxk.apps.id' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="appId">{{ 'mxk.apps.id' | i18n }}</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid appId!"> <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid appId!">
<input [(ngModel)]="form.model.appId" readonly [ngModelOptions]="{ standalone: true }" nz-input name="appId" id="appId" /> <input [(ngModel)]="form.model.appId" readonly [ngModelOptions]="{ standalone: true }" nz-input name="appId"
id="appId" />
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="appName">{{ 'mxk.apps.name' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="appName">{{ 'mxk.apps.name' | i18n }}</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid appName!"> <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid appName!">
<input <input [(ngModel)]="form.model.appName" disabled="true" [ngModelOptions]="{ standalone: true }" nz-input
[(ngModel)]="form.model.appName" name="appName" id="appName" />
disabled="true"
[ngModelOptions]="{ standalone: true }"
nz-input
name="appName"
id="appName"
/>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="relatedUsername">{{ 'mxk.accounts.relatedUsername' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="relatedUsername">{{ 'mxk.accounts.relatedUsername' | i18n
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid relatedUsername!"> }}</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48"
nzErrorTip="The input is not valid relatedUsername!">
<nz-input-group nzSearch [nzAddOnAfter]="suffixUserButton"> <nz-input-group nzSearch [nzAddOnAfter]="suffixUserButton">
<input <input [(ngModel)]="form.model.relatedUsername" [ngModelOptions]="{ standalone: true }" nz-input
[(ngModel)]="form.model.relatedUsername" disabled="{{ isEdit }}" name="relatedUsername" id="relatedUsername" />
[ngModelOptions]="{ standalone: true }"
nz-input
disabled="{{ isEdit }}"
name="relatedUsername"
id="relatedUsername"
/>
</nz-input-group> </nz-input-group>
<ng-template #suffixUserButton> <ng-template #suffixUserButton>
<button <button nz-button nzType="primary" style="{{ isEdit ? 'display:none' : 'display:block' }}" nzSearch
nz-button (click)="onGenerate($event)">{{ 'mxk.text.generate' | i18n }}</button>
nzType="primary"
style="{{ isEdit ? 'display:none' : 'display:block' }}"
nzSearch
(click)="onGenerate($event)"
>{{ 'mxk.text.generate' | i18n }}</button
>
</ng-template> </ng-template>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
<nz-form-item> <nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="relatedPassword">{{ 'mxk.accounts.relatedPassword' | i18n }}</nz-form-label> <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="relatedPassword">{{ 'mxk.accounts.relatedPassword' | i18n
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid relatedPassword!"> }}</nz-form-label>
<nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48"
nzErrorTip="The input is not valid relatedPassword!">
<nz-input-group nzSearch [nzSuffix]="suffixTemplate" [nzAddOnAfter]="suffixPasswordButton"> <nz-input-group nzSearch [nzSuffix]="suffixTemplate" [nzAddOnAfter]="suffixPasswordButton">
<input <input [(ngModel)]="form.model.relatedPassword" [ngModelOptions]="{ standalone: true }" nz-input
[(ngModel)]="form.model.relatedPassword" [type]="passwordVisible ? 'text' : 'password'" name="relatedPassword" id="relatedPassword" />
[ngModelOptions]="{ standalone: true }"
nz-input
[type]="passwordVisible ? 'text' : 'password'"
name="relatedPassword"
id="relatedPassword"
/>
</nz-input-group> </nz-input-group>
<ng-template #suffixTemplate> <ng-template #suffixTemplate>
<i nz-icon [nzType]="passwordVisible ? 'eye-invisible' : 'eye'" (click)="passwordVisible = !passwordVisible"></i> <i nz-icon [nzType]="passwordVisible ? 'eye-invisible' : 'eye'"
(click)="passwordVisible = !passwordVisible"></i>
</ng-template> </ng-template>
<ng-template #suffixPasswordButton> <ng-template #suffixPasswordButton>
<button nz-button nzType="primary" nzSearch (click)="onPassword($event)">{{ 'mxk.text.generate' | i18n }}</button> <button nz-button nzType="primary" nzSearch (click)="onPassword($event)">{{ 'mxk.text.generate' | i18n
}}</button>
</ng-template> </ng-template>
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
@ -147,4 +126,4 @@
<div *nzModalFooter> <div *nzModalFooter>
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button> <button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button> <button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div> </div>

View File

@ -1,19 +1,18 @@
/* /*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
@ -25,9 +24,8 @@ describe('AccountEditerComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ AccountEditerComponent ] declarations: [AccountEditerComponent]
}) }).compileComponents();
.compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,19 +1,18 @@
/* /*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { Component, ChangeDetectorRef, ViewContainerRef, Input, OnInit } from '@angular/core'; import { Component, ChangeDetectorRef, ViewContainerRef, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@ -42,6 +41,7 @@ import { SelectUserComponent } from '../../users/select-user/select-user.compone
}) })
export class AccountEditerComponent implements OnInit { export class AccountEditerComponent implements OnInit {
@Input() id?: String; @Input() id?: String;
@Input() username?: String;
@Input() isEdit?: boolean; @Input() isEdit?: boolean;
passwordVisible = false; passwordVisible = false;
@ -74,6 +74,15 @@ export class AccountEditerComponent implements OnInit {
this.cdr.detectChanges(); this.cdr.detectChanges();
}); });
} }
if (this.username) {
this.usersService.getByUsername(`${this.username}`).subscribe(res => {
this.form.model.userId = res.data.id;
this.form.model.username = res.data.username;
this.form.model.displayName = res.data.displayName;
this.cdr.detectChanges();
});
}
} }
onSelectUser(e: MouseEvent): void { onSelectUser(e: MouseEvent): void {

View File

@ -16,6 +16,7 @@
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { _HttpClient } from '@delon/theme'; import { _HttpClient } from '@delon/theme';
import { format, addDays } from 'date-fns'; import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types'; import { NzSafeAny } from 'ng-zorro-antd/core/types';
@ -34,6 +35,7 @@ import { AccountEditerComponent } from './account-editer/account-editer.componen
styleUrls: ['./accounts.component.less'] styleUrls: ['./accounts.component.less']
}) })
export class AccountsComponent implements OnInit { export class AccountsComponent implements OnInit {
userId: String = '';
query: { query: {
params: { params: {
username: String; username: String;
@ -90,10 +92,18 @@ export class AccountsComponent implements OnInit {
private accountsService: AccountsService, private accountsService: AccountsService,
private fb: FormBuilder, private fb: FormBuilder,
private msg: NzMessageService, private msg: NzMessageService,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
if (this.route.snapshot.queryParams['username']) {
this.query.params.username = this.route.snapshot.queryParams['username'];
}
if (this.route.snapshot.queryParams['userId']) {
this.userId = this.route.snapshot.queryParams['userId'];
}
this.fetch(); this.fetch();
} }
@ -149,6 +159,7 @@ export class AccountsComponent implements OnInit {
nzViewContainerRef: this.viewContainerRef, nzViewContainerRef: this.viewContainerRef,
nzComponentParams: { nzComponentParams: {
isEdit: false, isEdit: false,
username: this.query.params.username,
id: '' id: ''
}, },
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000)) nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))

View File

@ -29,6 +29,7 @@ import { RolesComponent } from './roles/roles.component';
import { ResourceEditerComponent } from './resources/resource-editer/resource-editer.component'; import { ResourceEditerComponent } from './resources/resource-editer/resource-editer.component';
import { SelectRolesComponent } from './roles/select-roles/select-roles.component'; import { SelectRolesComponent } from './roles/select-roles/select-roles.component';
import { RoleMembersEditerComponent } from './role-members/role-members-editer/role-members-editer.component'; import { RoleMembersEditerComponent } from './role-members/role-members-editer/role-members-editer.component';
import { MemberRolesEditerComponent } from './role-members/member-roles-editer/member-roles-editer.component';
const routes: Routes = [ const routes: Routes = [
{ {
path: 'roles', path: 'roles',
@ -51,7 +52,7 @@ const routes: Routes = [
const COMPONENTS = [RolesComponent]; const COMPONENTS = [RolesComponent];
@NgModule({ @NgModule({
declarations: [...COMPONENTS, RoleEditerComponent, RoleMembersComponent, ResourcesComponent, PrivilegesComponent, ResourceEditerComponent, SelectRolesComponent, RoleMembersEditerComponent], declarations: [...COMPONENTS, RoleEditerComponent, RoleMembersComponent, ResourcesComponent, PrivilegesComponent, ResourceEditerComponent, SelectRolesComponent, RoleMembersEditerComponent, MemberRolesEditerComponent],
imports: [NzIconModule, SharedModule, CommonModule, RouterModule.forChild(routes)], imports: [NzIconModule, SharedModule, CommonModule, RouterModule.forChild(routes)],
exports: [RouterModule] exports: [RouterModule]
}) })

View File

@ -0,0 +1,56 @@
<div *nzModalTitle> {{ 'mxk.text.add' | i18n }} </div>
<nz-card [nzBordered]="false">
<form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form">
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }">
<div nz-col nzMd="14" nzSm="24">
<nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.roles.name' | i18n }}</nz-form-label>
<nz-form-control>
<input nz-input [(ngModel)]="query.params.roleName" [ngModelOptions]="{ standalone: true }"
name="roleName" placeholder="" id="roleName" />
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzSpan]="query.expandForm ? 24 : 10" [class.text-right]="query.expandForm">
<button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{
'mxk.text.query' | i18n }}</button>
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{
'mxk.text.reset' | i18n }}</button>
<button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none">
{{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.confirm' | i18n }}</button>
</div>
</div>
</form>
<nz-table #dynamicTable nzTableLayout="auto" nzBordered nzShowSizeChanger [nzData]="query.results.rows"
[nzFrontPagination]="false" [nzTotal]="query.results.records" [nzPageSizeOptions]="query.params.pageSizeOptions"
[nzPageSize]="query.params.pageSize" [nzPageIndex]="query.params.pageNumber"
[nzLoading]="this.query.tableLoading" (nzQueryParams)="onQueryParamsChange($event)" nzWidth="100%">
<thead>
<tr>
<th></th>
<th nzAlign="center" style="display: none">Id</th>
<th nzAlign="center">{{ 'mxk.roles.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.roles.dynamic' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of query.results.rows">
<td [nzChecked]="query.tableCheckedId.has(data.id)" [nzDisabled]="data.disabled"
(nzCheckedChange)="onTableItemChecked(data.id, $event)"></td>
<td nzAlign="left" style="display: none">
<span>{{ data.id }}</span>
</td>
<td nzAlign="left"> {{ data.name }}</td>
<td nzAlign="center"> <i *ngIf="data.dynamic == 1" nz-icon nzType="check-circle" nzTheme="fill"
style="color: green"></i></td>
</tr>
</tbody>
</nz-table>
</nz-card>
<div *nzModalFooter style="display: none">
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MemberRolesEditerComponent } from './member-roles-editer.component';
describe('MemberRolesEditerComponent', () => {
let component: MemberRolesEditerComponent;
let fixture: ComponentFixture<MemberRolesEditerComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MemberRolesEditerComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MemberRolesEditerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,169 @@
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit, Input } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { _HttpClient } from '@delon/theme';
import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { RoleMembersService } from '../../../../service/role-members.service';
@Component({
selector: 'app-member-roles-editer',
templateUrl: './member-roles-editer.component.html',
styleUrls: ['./member-roles-editer.component.less']
})
export class MemberRolesEditerComponent implements OnInit {
@Input() username?: String;
query: {
params: {
roleName: String;
username: String;
protocol: String;
startDate: String;
endDate: String;
startDatePicker: Date;
endDatePicker: Date;
pageSize: number;
pageNumber: number;
pageSizeOptions: number[];
};
results: {
records: number;
rows: NzSafeAny[];
};
expandForm: Boolean;
submitLoading: boolean;
tableLoading: boolean;
tableCheckedId: Set<String>;
indeterminate: boolean;
checked: boolean;
} = {
params: {
roleName: '',
username: '',
protocol: '',
startDate: '',
endDate: '',
startDatePicker: addDays(new Date(), -30),
endDatePicker: new Date(),
pageSize: 5,
pageNumber: 1,
pageSizeOptions: [5, 15, 50]
},
results: {
records: 0,
rows: []
},
expandForm: false,
submitLoading: false,
tableLoading: false,
tableCheckedId: new Set<String>(),
indeterminate: false,
checked: false
};
constructor(
private modalRef: NzModalRef,
private roleMembersService: RoleMembersService,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder,
private msg: NzMessageService,
private cdr: ChangeDetectorRef
) { }
ngOnInit(): void {
if (this.username) {
this.query.params.username = this.username;
}
this.fetch();
}
onQueryParamsChange(tableQueryParams: NzTableQueryParams): void {
this.query.params.pageNumber = tableQueryParams.pageIndex;
this.query.params.pageSize = tableQueryParams.pageSize;
this.fetch();
}
onSearch(): void {
this.fetch();
}
onReset(): void { }
fetch(): void {
this.query.submitLoading = true;
this.query.tableLoading = true;
this.query.indeterminate = false;
this.query.checked = true;
this.query.tableCheckedId.clear();
if (this.query.expandForm) {
this.query.params.endDate = format(this.query.params.endDatePicker, 'yyyy-MM-dd HH:mm:ss');
this.query.params.startDate = format(this.query.params.startDatePicker, 'yyyy-MM-dd HH:mm:ss');
} else {
this.query.params.endDate = '';
this.query.params.startDate = '';
}
this.roleMembersService.rolesNoMember(this.query.params).subscribe(res => {
this.query.results = res.data;
this.query.submitLoading = false;
this.query.tableLoading = false;
this.cdr.detectChanges();
});
}
updateTableCheckedSet(id: String, checked: boolean): void {
if (checked) {
this.query.tableCheckedId.add(id);
} else {
this.query.tableCheckedId.delete(id);
}
}
refreshTableCheckedStatus(): void {
const listOfEnabledData = this.query.results.rows.filter(({ disabled }) => !disabled);
this.query.checked = listOfEnabledData.every(({ id }) => this.query.tableCheckedId.has(id));
this.query.indeterminate = listOfEnabledData.some(({ id }) => this.query.tableCheckedId.has(id)) && !this.query.checked;
}
onTableItemChecked(id: String, checked: boolean): void {
//this.onTableAllChecked(false);
this.updateTableCheckedSet(id, checked);
this.refreshTableCheckedStatus();
}
onTableAllChecked(checked: boolean): void {
this.query.results.rows.filter(({ disabled }) => !disabled).forEach(({ id }) => this.updateTableCheckedSet(id, checked));
this.refreshTableCheckedStatus();
}
onSubmit(e: MouseEvent): void {
e.preventDefault();
const listOfEnabledData = this.query.results.rows.filter(({ disabled }) => !disabled);
let selectedData = listOfEnabledData.filter(({ id, name }) => {
return this.query.tableCheckedId.has(id);
});
let roleIds = '';
let roleNames = '';
for (let i = 0; i < selectedData.length; i++) {
roleIds = `${roleIds},${selectedData[i].id}`;
roleNames = `${roleNames},${selectedData[i].name}`;
}
this.roleMembersService.addMember2Roles({ username: this.username, roleId: roleIds, roleName: roleNames }).subscribe(res => {
this.query.results = res.data;
this.query.submitLoading = false;
this.query.tableLoading = false;
if (res.code == 0) {
this.msg.success(`提交成功`);
this.fetch();
} else {
this.msg.success(`提交失败`);
}
this.cdr.detectChanges();
});
}
onClose(e: MouseEvent): void {
e.preventDefault();
}
}

View File

@ -3,7 +3,7 @@
<nz-card [nzBordered]="false"> <nz-card [nzBordered]="false">
<form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form"> <form nz-form [nzLayout]="'inline'" (ngSubmit)="onSearch()" class="search__form">
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 24, lg: 24, xl: 48, xxl: 48 }"> <div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 24, lg: 24, xl: 48, xxl: 48 }">
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="8" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.roles.name' | i18n }}</nz-form-label> <nz-form-label nzFor="name">{{ 'mxk.roles.name' | i18n }}</nz-form-label>
<nz-form-control> <nz-form-control>
@ -18,7 +18,7 @@
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col nzMd="10" nzSm="24"> <div nz-col nzMd="8" nzSm="24">
<nz-form-item> <nz-form-item>
<nz-form-label nzFor="name">{{ 'mxk.users.username' | i18n }}</nz-form-label> <nz-form-label nzFor="name">{{ 'mxk.users.username' | i18n }}</nz-form-label>
<nz-form-control> <nz-form-control>
@ -27,11 +27,10 @@
</nz-form-control> </nz-form-control>
</nz-form-item> </nz-form-item>
</div> </div>
<div nz-col [nzSpan]="query.expandForm ? 24 : 4" [class.text-right]="query.expandForm"> <div nz-col [nzSpan]="query.expandForm ? 24 : 8" [class.text-right]="query.expandForm">
<button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{ 'mxk.text.query' | <button nz-button type="submit" [nzType]="'primary'" [nzLoading]="query.submitLoading">{{ 'mxk.text.query' |
i18n }}</button> i18n }}</button>
<button nz-button type="reset" (click)="onReset()" class="mx-sm" style="display: none">{{ 'mxk.text.reset' | <button nz-button type="reset" (click)="onReset()" class="mx-sm">{{ 'mxk.text.reset' | i18n }}</button>
i18n }}</button>
<button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none"> <button nz-button (click)="query.expandForm = !query.expandForm" class="mx-sm" style="display: none">
{{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button> {{ query.expandForm ? ('mxk.text.collapse' | i18n) : ('mxk.text.expand' | i18n) }}</button>
</div> </div>

View File

@ -1,22 +1,22 @@
/* /*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { _HttpClient } from '@delon/theme'; import { _HttpClient } from '@delon/theme';
import { format, addDays } from 'date-fns'; import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types'; import { NzSafeAny } from 'ng-zorro-antd/core/types';
@ -29,6 +29,7 @@ import { NzFormatEmitEvent, NzTreeNode, NzTreeNodeOptions } from 'ng-zorro-antd/
import { RoleMembersService } from '../../../service/role-members.service'; import { RoleMembersService } from '../../../service/role-members.service';
import { set2String } from '../../../shared/index'; import { set2String } from '../../../shared/index';
import { SelectRolesComponent } from '../roles/select-roles/select-roles.component'; import { SelectRolesComponent } from '../roles/select-roles/select-roles.component';
import { MemberRolesEditerComponent } from './member-roles-editer/member-roles-editer.component';
import { RoleMembersEditerComponent } from './role-members-editer/role-members-editer.component'; import { RoleMembersEditerComponent } from './role-members-editer/role-members-editer.component';
@Component({ @Component({
@ -101,10 +102,14 @@ export class RoleMembersComponent implements OnInit {
private viewContainerRef: ViewContainerRef, private viewContainerRef: ViewContainerRef,
private fb: FormBuilder, private fb: FormBuilder,
private msg: NzMessageService, private msg: NzMessageService,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
if (this.route.snapshot.queryParams['username']) {
this.query.params.username = this.route.snapshot.queryParams['username'];
}
this.query.tableInitialize = false; this.query.tableInitialize = false;
} }
@ -120,7 +125,13 @@ export class RoleMembersComponent implements OnInit {
this.fetch(); this.fetch();
} }
onReset(): void { } onReset(): void {
this.query.params.username = '';
this.query.params.name = '';
this.query.params.roleId = '';
this.query.params.roleName = '';
this.fetch();
}
onBatchDelete(e: MouseEvent): void { onBatchDelete(e: MouseEvent): void {
e.preventDefault(); e.preventDefault();
@ -137,22 +148,40 @@ export class RoleMembersComponent implements OnInit {
onAdd(e: MouseEvent): void { onAdd(e: MouseEvent): void {
e.preventDefault(); e.preventDefault();
const modal = this.modalService.create({ if (this.query.params.username != '') {
nzContent: RoleMembersEditerComponent, const modal = this.modalService.create({
nzViewContainerRef: this.viewContainerRef, nzContent: MemberRolesEditerComponent,
nzComponentParams: { nzViewContainerRef: this.viewContainerRef,
isEdit: false, nzComponentParams: {
roleId: this.query.params.roleId username: this.query.params.username
}, },
nzWidth: 700, nzWidth: 700,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000)) nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
}); });
// Return a result when closed // Return a result when closed
modal.afterClose.subscribe(result => { modal.afterClose.subscribe(result => {
if (result.refresh) { if (result.refresh) {
this.fetch(); this.fetch();
} }
}); });
} else if (this.query.params.roleId != '') {
const modal = this.modalService.create({
nzContent: RoleMembersEditerComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: false,
roleId: this.query.params.roleId
},
nzWidth: 700,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
} }
onSelect(e: MouseEvent): void { onSelect(e: MouseEvent): void {

View File

@ -110,6 +110,18 @@
</button> </button>
<nz-dropdown-menu #menuMoreAction="nzDropdownMenu"> <nz-dropdown-menu #menuMoreAction="nzDropdownMenu">
<ul nz-menu> <ul nz-menu>
<li nz-menu-item *ngIf="data.status == 1"
(click)="onNavToUrl($event, data.id, data.username, 'accounts')">{{
'mxk.text.accounts' | i18n
}}</li>
<li nz-menu-item *ngIf="data.status == 1"
(click)="onNavToUrl($event, data.id, data.username, 'groups')">{{
'mxk.text.groups' | i18n
}}</li>
<li nz-menu-item *ngIf="data.status == 1"
(click)="onNavToUrl($event, data.id, data.username, 'roles')">{{
'mxk.text.roles' | i18n
}}</li>
<li nz-menu-item *ngIf="data.status == 1" (click)="changePasswordById($event, data.id)">{{ <li nz-menu-item *ngIf="data.status == 1" (click)="changePasswordById($event, data.id)">{{
'mxk.text.changepassword' | i18n 'mxk.text.changepassword' | i18n
}}</li> }}</li>

View File

@ -16,6 +16,7 @@
import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, ViewContainerRef, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { _HttpClient } from '@delon/theme'; import { _HttpClient } from '@delon/theme';
import { format, addDays } from 'date-fns'; import { format, addDays } from 'date-fns';
import { NzSafeAny } from 'ng-zorro-antd/core/types'; import { NzSafeAny } from 'ng-zorro-antd/core/types';
@ -94,6 +95,7 @@ export class UsersComponent implements OnInit {
private orgsService: OrganizationsService, private orgsService: OrganizationsService,
private fb: FormBuilder, private fb: FormBuilder,
private msg: NzMessageService, private msg: NzMessageService,
private router: Router,
private cdr: ChangeDetectorRef private cdr: ChangeDetectorRef
) { } ) { }
@ -213,6 +215,17 @@ export class UsersComponent implements OnInit {
}); });
} }
onNavToUrl(e: MouseEvent, userId: String, username: String, navType: String) {
e.preventDefault();
if (navType === 'accounts') {
this.router.navigateByUrl(`/accounts?username=${username}&userId=${userId}`);
} else if (navType === 'groups') {
this.router.navigateByUrl(`/access/groupmembers?username=${username}&userId=${userId}`);
} else if (navType === 'roles') {
this.router.navigateByUrl(`/permissions/rolemembers?username=${username}&userId=${userId}`);
}
}
onUpdateStatus(e: MouseEvent, userId: String, status: number): void { onUpdateStatus(e: MouseEvent, userId: String, status: number): void {
e.preventDefault(); e.preventDefault();
this.usersService.updateStatus({ id: userId, status: status }).subscribe(res => { this.usersService.updateStatus({ id: userId, status: status }).subscribe(res => {

View File

@ -1,19 +1,18 @@
/* /*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
@ -22,6 +21,7 @@ import { Observable } from 'rxjs';
import { GroupMembers } from '../entity/GroupMembers'; import { GroupMembers } from '../entity/GroupMembers';
import { Message } from '../entity/Message'; import { Message } from '../entity/Message';
import { PageResults } from '../entity/PageResults';
import { BaseService } from './base.service'; import { BaseService } from './base.service';
@Injectable({ @Injectable({
@ -33,4 +33,14 @@ export class GroupMembersService extends BaseService<GroupMembers> {
this.server.urls.member = '/memberInGroup'; this.server.urls.member = '/memberInGroup';
this.server.urls.memberOut = '/memberNotInGroup'; this.server.urls.memberOut = '/memberNotInGroup';
} }
groupsNoMember(params: NzSafeAny): Observable<Message<PageResults>> {
return this.http.get<Message<PageResults>>(`${this.server.urls.base}/groupsNoMember`, {
params: this.parseParams(params)
});
}
addMember2Groups(body: any): Observable<Message<PageResults>> {
return this.http.post<Message<PageResults>>(`${`${this.server.urls.base}/addMember2Groups`}`, body);
}
} }

View File

@ -1,19 +1,18 @@
/* /*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
@ -21,9 +20,9 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Message } from '../entity/Message'; import { Message } from '../entity/Message';
import { PageResults } from '../entity/PageResults';
import { RoleMembers } from '../entity/RoleMembers'; import { RoleMembers } from '../entity/RoleMembers';
import { BaseService } from './base.service'; import { BaseService } from './base.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@ -33,4 +32,14 @@ export class RoleMembersService extends BaseService<RoleMembers> {
this.server.urls.member = '/memberInRole'; this.server.urls.member = '/memberInRole';
this.server.urls.memberOut = '/memberNotInRole'; this.server.urls.memberOut = '/memberNotInRole';
} }
rolesNoMember(params: NzSafeAny): Observable<Message<PageResults>> {
return this.http.get<Message<PageResults>>(`${this.server.urls.base}/rolesNoMember`, {
params: this.parseParams(params)
});
}
addMember2Roles(body: any): Observable<Message<PageResults>> {
return this.http.post<Message<PageResults>>(`${`${this.server.urls.base}/addMember2Roles`}`, body);
}
} }

View File

@ -37,6 +37,12 @@ export class UsersService extends BaseService<Users> {
}); });
} }
getByUsername(params: NzSafeAny): Observable<Message<Users>> {
return this.http.get<Message<Users>>(`${this.server.urls.base}/getByUsername/${params}`, {
params: this.parseParams(params)
});
}
updateStatus(params: NzSafeAny): Observable<Message<Users>> { updateStatus(params: NzSafeAny): Observable<Message<Users>> {
return this.http.get<Message<Users>>(`${this.server.urls.base}/updateStatus`, { return this.http.get<Message<Users>>(`${this.server.urls.base}/updateStatus`, {
params: this.parseParams(params) params: this.parseParams(params)

View File

@ -652,6 +652,9 @@
"disable":"Disable", "disable":"Disable",
"lock":"Lock", "lock":"Lock",
"unlock":"UnLock", "unlock":"UnLock",
"accounts":"Accounts",
"roles":"Roles",
"groups":"Groups",
"moreaction":"More", "moreaction":"More",
"submit":"Submit", "submit":"Submit",
"generate":"Generate", "generate":"Generate",

View File

@ -551,7 +551,7 @@
"password":{ "password":{
"id": "用户编码", "id": "用户编码",
"displayName": "姓名", "displayName": "姓名",
"username": "账号", "username": "登录账号",
"oldPassword": "当前密码", "oldPassword": "当前密码",
"password": "新密码", "password": "新密码",
"confirmPassword": "确认密码", "confirmPassword": "确认密码",
@ -651,6 +651,9 @@
"disable":"禁用", "disable":"禁用",
"lock":"锁定", "lock":"锁定",
"unlock":"解锁", "unlock":"解锁",
"accounts":"账号",
"roles":"角色",
"groups":"用户组",
"submit":"提交", "submit":"提交",
"moreaction":"更多", "moreaction":"更多",
"generate":"生成", "generate":"生成",

View File

@ -1,5 +1,5 @@
/* /*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top] * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,15 +20,17 @@ package org.maxkey.web.access.contorller;
import org.apache.mybatis.jpa.persistence.JpaPageResults; import org.apache.mybatis.jpa.persistence.JpaPageResults;
import org.maxkey.authn.annotation.CurrentUser; import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.entity.GroupMember; import org.maxkey.entity.GroupMember;
import org.maxkey.entity.Groups;
import org.maxkey.entity.Message; import org.maxkey.entity.Message;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.service.GroupMemberService; import org.maxkey.persistence.service.GroupMemberService;
import org.maxkey.persistence.service.GroupsService; import org.maxkey.persistence.service.GroupsService;
import org.maxkey.persistence.service.UserInfoService;
import org.maxkey.util.StringUtils;
import org.maxkey.web.WebContext; import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -45,13 +47,14 @@ public class GroupMemberController {
final static Logger _logger = LoggerFactory.getLogger(GroupMemberController.class); final static Logger _logger = LoggerFactory.getLogger(GroupMemberController.class);
@Autowired @Autowired
@Qualifier("groupMemberService")
GroupMemberService groupMemberService; GroupMemberService groupMemberService;
@Autowired @Autowired
@Qualifier("groupsService")
GroupsService groupsService; GroupsService groupsService;
@Autowired
UserInfoService userInfoService;
@RequestMapping(value = { "/fetch" }, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value = { "/fetch" }, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody @ResponseBody
public ResponseEntity<?> fetch( public ResponseEntity<?> fetch(
@ -82,6 +85,13 @@ public class GroupMemberController {
groupMemberService.queryPageResults("memberNotInGroup",groupMember)).buildResponse(); groupMemberService.queryPageResults("memberNotInGroup",groupMember)).buildResponse();
} }
@RequestMapping(value = { "/groupsNoMember" })
@ResponseBody
public ResponseEntity<?> groupsNoMember(@ModelAttribute GroupMember groupMember,@CurrentUser UserInfo currentUser) {
groupMember.setInstId(currentUser.getInstId());
return new Message<JpaPageResults<Groups>>(
groupMemberService.groupsNoMember(groupMember)).buildResponse();
}
@RequestMapping(value = {"/add"}) @RequestMapping(value = {"/add"})
@ResponseBody @ResponseBody
@ -118,6 +128,41 @@ public class GroupMemberController {
return new Message<GroupMember>(Message.FAIL).buildResponse(); return new Message<GroupMember>(Message.FAIL).buildResponse();
} }
@RequestMapping(value = {"/addMember2Groups"})
@ResponseBody
public ResponseEntity<?> addMember2Groups(@RequestBody GroupMember groupMember,@CurrentUser UserInfo currentUser) {
if (groupMember == null || StringUtils.isBlank(groupMember.getUsername())) {
return new Message<GroupMember>(Message.FAIL).buildResponse();
}
UserInfo userInfo = userInfoService.findByUsername(groupMember.getUsername());
boolean result = true;
String groupIds = groupMember.getGroupId();
String groupNames = groupMember.getGroupName();
if (groupIds != null && userInfo != null) {
String[] arrGroupIds = groupIds.split(",");
String[] arrGroupNames = groupNames.split(",");
for (int i = 0; i < arrGroupIds.length; i++) {
GroupMember newGroupMember =
new GroupMember(
arrGroupIds[i],
arrGroupNames[i],
userInfo.getId(),
userInfo.getDisplayName(),
"USER",
currentUser.getInstId());
newGroupMember.setId(WebContext.genId());
result = groupMemberService.insert(newGroupMember);
}
if(result) {
return new Message<GroupMember>(Message.SUCCESS).buildResponse();
}
}
return new Message<GroupMember>(Message.FAIL).buildResponse();
}
@ResponseBody @ResponseBody
@RequestMapping(value={"/delete"}, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value={"/delete"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> delete(@RequestParam("ids") String ids,@CurrentUser UserInfo currentUser) { public ResponseEntity<?> delete(@RequestParam("ids") String ids,@CurrentUser UserInfo currentUser) {

View File

@ -107,6 +107,13 @@ public class UserInfoController {
return new Message<UserInfo>(userInfo).buildResponse(); return new Message<UserInfo>(userInfo).buildResponse();
} }
@RequestMapping(value = { "/getByUsername/{username}" }, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> getByUsername(@PathVariable("username") String username) {
UserInfo userInfo=userInfoService.findByUsername(username);
userInfo.trans();
return new Message<UserInfo>(userInfo).buildResponse();
}
@ResponseBody @ResponseBody
@RequestMapping(value={"/add"}, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value={"/add"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> insert(@RequestBody UserInfo userInfo,@CurrentUser UserInfo currentUser) { public ResponseEntity<?> insert(@RequestBody UserInfo userInfo,@CurrentUser UserInfo currentUser) {

View File

@ -21,9 +21,12 @@ import org.apache.mybatis.jpa.persistence.JpaPageResults;
import org.maxkey.authn.annotation.CurrentUser; import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.entity.Message; import org.maxkey.entity.Message;
import org.maxkey.entity.RoleMember; import org.maxkey.entity.RoleMember;
import org.maxkey.entity.Roles;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.service.RoleMemberService; import org.maxkey.persistence.service.RoleMemberService;
import org.maxkey.persistence.service.RolesService; import org.maxkey.persistence.service.RolesService;
import org.maxkey.persistence.service.UserInfoService;
import org.maxkey.util.StringUtils;
import org.maxkey.web.WebContext; import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -49,6 +52,9 @@ public class RoleMemberController {
@Autowired @Autowired
RolesService rolesService; RolesService rolesService;
@Autowired
UserInfoService userInfoService;
@RequestMapping(value = { "/fetch" }, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value = { "/fetch" }, produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody @ResponseBody
public ResponseEntity<?> fetch( public ResponseEntity<?> fetch(
@ -85,7 +91,7 @@ public class RoleMemberController {
if (roleMember == null || roleMember.getRoleId() == null) { if (roleMember == null || roleMember.getRoleId() == null) {
return new Message<RoleMember>(Message.FAIL).buildResponse(); return new Message<RoleMember>(Message.FAIL).buildResponse();
} }
String groupId = roleMember.getRoleId(); String roleId = roleMember.getRoleId();
boolean result = true; boolean result = true;
String memberIds = roleMember.getMemberId(); String memberIds = roleMember.getMemberId();
@ -97,7 +103,7 @@ public class RoleMemberController {
for (int i = 0; i < arrMemberIds.length; i++) { for (int i = 0; i < arrMemberIds.length; i++) {
RoleMember newRoleMember = RoleMember newRoleMember =
new RoleMember( new RoleMember(
groupId, roleId,
roleMember.getRoleName(), roleMember.getRoleName(),
arrMemberIds[i], arrMemberIds[i],
arrMemberNames[i], arrMemberNames[i],
@ -113,6 +119,48 @@ public class RoleMemberController {
return new Message<RoleMember>(Message.FAIL).buildResponse(); return new Message<RoleMember>(Message.FAIL).buildResponse();
} }
@RequestMapping(value = { "/rolesNoMember" })
@ResponseBody
public ResponseEntity<?> rolesNoMember(@ModelAttribute RoleMember roleMember,@CurrentUser UserInfo currentUser) {
roleMember.setInstId(currentUser.getInstId());
return new Message<JpaPageResults<Roles>>(
roleMemberService.rolesNoMember(roleMember)).buildResponse();
}
@RequestMapping(value = {"/addMember2Roles"})
@ResponseBody
public ResponseEntity<?> addMember2Roles(@RequestBody RoleMember roleMember,@CurrentUser UserInfo currentUser) {
if (roleMember == null || StringUtils.isBlank(roleMember.getUsername())) {
return new Message<RoleMember>(Message.FAIL).buildResponse();
}
UserInfo userInfo = userInfoService.findByUsername(roleMember.getUsername());
boolean result = true;
String roleIds = roleMember.getRoleId();
String roleNames = roleMember.getRoleName();
if (roleIds != null) {
String[] arrRoleIds = roleIds.split(",");
String[] arrRoleNames = roleNames.split(",");
for (int i = 0; i < arrRoleIds.length; i++) {
RoleMember newRoleMember =
new RoleMember(
arrRoleIds[i],
arrRoleNames[i],
userInfo.getId(),
userInfo.getDisplayName(),
"USER",
currentUser.getInstId());
newRoleMember.setId(WebContext.genId());
result = roleMemberService.insert(newRoleMember);
}
if(result) {
return new Message<RoleMember>(Message.SUCCESS).buildResponse();
}
}
return new Message<RoleMember>(Message.FAIL).buildResponse();
}
@ResponseBody @ResponseBody
@RequestMapping(value={"/delete"}, produces = {MediaType.APPLICATION_JSON_VALUE}) @RequestMapping(value={"/delete"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> delete(@RequestParam("ids") String ids,@CurrentUser UserInfo currentUser) { public ResponseEntity<?> delete(@RequestParam("ids") String ids,@CurrentUser UserInfo currentUser) {