59 changed files with 1239 additions and 298 deletions
@ -1,129 +0,0 @@ |
|||||
import { HttpClient, HttpParams } from "@angular/common/http"; |
|
||||
import { Injectable } from "@angular/core"; |
|
||||
import { AnyObject, ResponseType } from "@cdk/types"; |
|
||||
import { Utils } from "@cdk/utils"; |
|
||||
import { Observable, map, of, tap } from "rxjs"; |
|
||||
import { PermItemDTO, UserDTO, UserRoleDTO, GlobalEnum, OrgDTO } from "@cdk/public-api"; |
|
||||
|
|
||||
@Injectable({ |
|
||||
providedIn: "root", |
|
||||
}) |
|
||||
export class ApiService { |
|
||||
constructor(private http: HttpClient) {} |
|
||||
|
|
||||
globalEnum!: GlobalEnum; |
|
||||
|
|
||||
page(v: {}, q: {}) { |
|
||||
return this.http.get<any>("https://jsonplaceholder.typicode.com/users", v).pipe( |
|
||||
map((r) => { |
|
||||
return { |
|
||||
total: 10, |
|
||||
content: r, |
|
||||
}; |
|
||||
}) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
getAllEnum(force?: boolean): Observable<GlobalEnum> { |
|
||||
if (this.globalEnum && !force) { |
|
||||
return of(this.globalEnum); |
|
||||
} |
|
||||
return this.http.get<ResponseType<GlobalEnum>>("/api/basic/enum").pipe( |
|
||||
map((res) => { |
|
||||
return res.body; |
|
||||
}), |
|
||||
tap((r) => { |
|
||||
this.globalEnum = r; |
|
||||
}) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
login(v: {}) { |
|
||||
const params = Utils.objectToHttpParams(v); |
|
||||
return this.http.get<ResponseType>("/api/login", { params }); |
|
||||
} |
|
||||
|
|
||||
logout() { |
|
||||
return this.http.get<ResponseType>("/api/logout"); |
|
||||
} |
|
||||
|
|
||||
getRoleList() { |
|
||||
return this.http.get<ResponseType<UserRoleDTO[]>>("/api/role"); |
|
||||
} |
|
||||
|
|
||||
deleteRole(roleId: string) { |
|
||||
const params = new HttpParams().set("roleId", roleId); |
|
||||
return this.http.delete<ResponseType>("/api/role", { |
|
||||
params, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
updateRole(rule: AnyObject) { |
|
||||
const body = Utils.objectToFormData(rule); |
|
||||
const method = rule["roleId"] ? "post" : "put"; |
|
||||
return this.http[method]<ResponseType>("/api/role", body); |
|
||||
} |
|
||||
|
|
||||
getRolePerms() { |
|
||||
return this.http.get<ResponseType<PermItemDTO[]>>("/api/role/item"); |
|
||||
} |
|
||||
|
|
||||
getUserList() { |
|
||||
return this.http.get<ResponseType<UserDTO[]>>("/api/user"); |
|
||||
} |
|
||||
|
|
||||
checkUid(uid: string) { |
|
||||
const params = new HttpParams().set("uid", uid); |
|
||||
return this.http.delete<ResponseType>("/api/user/check", { |
|
||||
params, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
saveUser(user: AnyObject, edit: boolean) { |
|
||||
const body = Utils.objectToFormData(user); |
|
||||
const method = edit ? "post" : "put"; |
|
||||
return this.http[method]<ResponseType>("/api/user", body); |
|
||||
} |
|
||||
|
|
||||
deleteUser(uid: string) { |
|
||||
const params = new HttpParams().set("uid", uid); |
|
||||
return this.http.delete<ResponseType>("/api/user", { |
|
||||
params, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
getOrgList() { |
|
||||
return this.http.get<ResponseType<OrgDTO[]>>("/api/vender"); |
|
||||
} |
|
||||
|
|
||||
checkOrgAccount(account: string) { |
|
||||
const params = new HttpParams().set("account", account); |
|
||||
return this.http.get<ResponseType<boolean>>("/api/vender/check/account", { |
|
||||
params, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
checkOrgName(name: string) { |
|
||||
const params = new HttpParams().set("name", name); |
|
||||
return this.http.get<ResponseType<boolean>>("/api/vender/check/name", { |
|
||||
params, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
deleteOrg(id: number) { |
|
||||
const params = new HttpParams().set("vender", id); |
|
||||
return this.http.delete<ResponseType>("/api/vender", { |
|
||||
params, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
saveOrg(org: AnyObject) { |
|
||||
const body = Utils.objectToFormData(org); |
|
||||
const method = org["id"] ? "post" : "put"; |
|
||||
return this.http[method]<ResponseType>("/api/vender", body); |
|
||||
} |
|
||||
|
|
||||
// getOrgConfig() {
|
|
||||
// return this.http.get<ResponseType>("/api/vender/config");
|
|
||||
// }
|
|
||||
} |
|
||||
@ -1 +1 @@ |
|||||
export * from "./api.service"; |
export * from "../../../../cdk/src/services/api.service"; |
||||
|
|||||
@ -0,0 +1,234 @@ |
|||||
|
import { HttpClient, HttpParams } from "@angular/common/http"; |
||||
|
import { Inject, Injectable, InjectionToken } from "@angular/core"; |
||||
|
import { AnyObject, PageResult, ResponseType } from "@cdk/types"; |
||||
|
import { Utils } from "@cdk/utils"; |
||||
|
import { Observable, map, of, tap } from "rxjs"; |
||||
|
import { |
||||
|
PermItemDTO, |
||||
|
UserDTO, |
||||
|
UserRoleDTO, |
||||
|
GlobalEnum, |
||||
|
OrgDTO, |
||||
|
ClientAccountDTO, |
||||
|
AdminAccountDTO, |
||||
|
OrgConfigDTO, |
||||
|
} from "@cdk/public-api"; |
||||
|
|
||||
|
export const PROJECT_NAME = new InjectionToken<string>("projectName"); |
||||
|
|
||||
|
@Injectable({ |
||||
|
providedIn: "root", |
||||
|
}) |
||||
|
export class ApiService { |
||||
|
constructor(private http: HttpClient, @Inject(PROJECT_NAME) public project: string) { |
||||
|
this.initAccount(); |
||||
|
} |
||||
|
|
||||
|
public account!: ClientAccountDTO; |
||||
|
|
||||
|
public adminAccount!: AdminAccountDTO; |
||||
|
|
||||
|
public accountKey = this.project === "admin" ? "CATERING_ADMIN_ACCOUNT" : "CATERING_CLIENT_ACCOUNT"; |
||||
|
|
||||
|
globalEnum!: GlobalEnum; |
||||
|
|
||||
|
page(v: {}, q: {}) { |
||||
|
return this.http.get<any>("https://jsonplaceholder.typicode.com/users", v).pipe( |
||||
|
map((r) => { |
||||
|
return { |
||||
|
total: 10, |
||||
|
content: r, |
||||
|
}; |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
initAccount() { |
||||
|
try { |
||||
|
const stragedAccount = localStorage.getItem(this.accountKey); |
||||
|
if (stragedAccount) { |
||||
|
if (this.project === "admin") { |
||||
|
this.adminAccount = JSON.parse(stragedAccount); |
||||
|
} else { |
||||
|
this.account = JSON.parse(stragedAccount); |
||||
|
} |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error("获取用户信息失败", error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
getAllEnum(force?: boolean): Observable<GlobalEnum> { |
||||
|
if (this.globalEnum && !force) { |
||||
|
return of(this.globalEnum); |
||||
|
} |
||||
|
return this.http.get<ResponseType<GlobalEnum>>("/api/basic/enum").pipe( |
||||
|
map((res) => { |
||||
|
return res.body; |
||||
|
}), |
||||
|
tap((r) => { |
||||
|
this.globalEnum = r; |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
login(v: {}) { |
||||
|
const params = Utils.objectToHttpParams(v); |
||||
|
return this.http.get<ResponseType>("/api/login", { params }).pipe( |
||||
|
tap((res) => { |
||||
|
localStorage.setItem(this.accountKey, JSON.stringify(res.body)); |
||||
|
this.initAccount(); |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
logout() { |
||||
|
return this.http.get<ResponseType>("/api/logout").pipe( |
||||
|
tap((res) => { |
||||
|
if (res.success) { |
||||
|
localStorage.removeItem(this.accountKey); |
||||
|
} |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
getOrgConfig() { |
||||
|
return this.http.get<ResponseType<OrgConfigDTO>>("/api/vender/config"); |
||||
|
} |
||||
|
|
||||
|
saveOrgConfig(config: AnyObject) { |
||||
|
const body = Utils.objectToFormData(config); |
||||
|
return this.http.post<ResponseType>("/api/vender/config", body); |
||||
|
} |
||||
|
|
||||
|
updatePassword(v: {}) { |
||||
|
const body = Utils.objectToFormData(v); |
||||
|
return this.http.post<ResponseType>("/api/basic/user", body); |
||||
|
} |
||||
|
|
||||
|
getRoleList() { |
||||
|
return this.http.get<ResponseType<UserRoleDTO[]>>("/api/role"); |
||||
|
} |
||||
|
|
||||
|
deleteRole(roleId: string) { |
||||
|
const params = new HttpParams().set("roleId", roleId); |
||||
|
return this.http.delete<ResponseType>("/api/role", { |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
updateRole(rule: AnyObject) { |
||||
|
const body = Utils.objectToFormData(rule); |
||||
|
const method = rule["roleId"] ? "post" : "put"; |
||||
|
return this.http[method]<ResponseType>("/api/role", body); |
||||
|
} |
||||
|
|
||||
|
getRolePerms() { |
||||
|
return this.http.get<ResponseType<PermItemDTO[]>>("/api/role/item"); |
||||
|
} |
||||
|
|
||||
|
getUserList() { |
||||
|
return this.http.get<ResponseType<UserDTO[]>>("/api/user"); |
||||
|
} |
||||
|
|
||||
|
checkUid(uid: string) { |
||||
|
const params = new HttpParams().set("uid", uid); |
||||
|
return this.http.delete<ResponseType>("/api/user/check", { |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
saveUser(user: AnyObject, edit: boolean) { |
||||
|
const body = Utils.objectToFormData(user); |
||||
|
const method = edit ? "post" : "put"; |
||||
|
return this.http[method]<ResponseType>("/api/user", body); |
||||
|
} |
||||
|
|
||||
|
deleteUser(uid: string) { |
||||
|
const params = new HttpParams().set("uid", uid); |
||||
|
return this.http.delete<ResponseType>("/api/user", { |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
getOrgList() { |
||||
|
return this.http.get<ResponseType<OrgDTO[]>>("/api/vender"); |
||||
|
} |
||||
|
|
||||
|
checkOrgAccount(account: string) { |
||||
|
const params = new HttpParams().set("account", account); |
||||
|
return this.http.get<ResponseType<boolean>>("/api/vender/check/account", { |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
checkOrgName(name: string) { |
||||
|
const params = new HttpParams().set("name", name); |
||||
|
return this.http.get<ResponseType<boolean>>("/api/vender/check/name", { |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
deleteOrg(id: number) { |
||||
|
const params = new HttpParams().set("vender", id); |
||||
|
return this.http.delete<ResponseType>("/api/vender", { |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
saveOrg(org: AnyObject) { |
||||
|
const body = Utils.objectToFormData(org); |
||||
|
const method = org["id"] ? "post" : "put"; |
||||
|
return this.http[method]<ResponseType>("/api/vender", body); |
||||
|
} |
||||
|
|
||||
|
// getOrgConfig() {
|
||||
|
// return this.http.get<ResponseType>("/api/vender/config");
|
||||
|
// }
|
||||
|
|
||||
|
getFoodPage(p: {}, q: {}) { |
||||
|
const params = Utils.objectStringify({ ...p, ...q }); |
||||
|
return this.http.get<ResponseType<PageResult>>(`/api/ingredient?${params}`).pipe( |
||||
|
map((r) => { |
||||
|
if (Array.isArray(r.body.content)) { |
||||
|
r.body.content = r.body.content.map((o) => { |
||||
|
return { |
||||
|
...o, |
||||
|
nutrientArr: Object.entries(o.nutrient).map(([k, v]) => { |
||||
|
const nutrient = this.globalEnum.nutrient.find((f) => f.key === k); |
||||
|
return { |
||||
|
key: k, |
||||
|
value: v, |
||||
|
label: nutrient?.value, |
||||
|
measurement: nutrient?.measurement, |
||||
|
}; |
||||
|
}), |
||||
|
}; |
||||
|
}); |
||||
|
} |
||||
|
return r; |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
saveFood(food: AnyObject) { |
||||
|
const body = Utils.objectToFormData(food); |
||||
|
const method = food["id"] ? "post" : "put"; |
||||
|
return this.http[method]<ResponseType>("/api/ingredient", body); |
||||
|
} |
||||
|
|
||||
|
deleteFoods(ids: number[]) { |
||||
|
const params = Utils.objectStringify({ nutrients: ids }); |
||||
|
console.log("params", params, { nutrients: ids }); |
||||
|
return this.http.delete<ResponseType>(`/api/ingredient?${params}`); |
||||
|
} |
||||
|
|
||||
|
importFood(f: FormData) { |
||||
|
return this.http.put<ResponseType>("/api/ingredient/mark", f); |
||||
|
} |
||||
|
markFood(mark: string, nutrient: string) { |
||||
|
const params = Utils.objectToFormData({ mark, nutrient }, false); |
||||
|
|
||||
|
return this.http.put<ResponseType>("/api/ingredient/mark", params); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
export * from "./api.service"; |
||||
@ -1,2 +1,4 @@ |
|||||
export * from "./app-layout/app-layout.component"; |
export * from "./app-layout/app-layout.component"; |
||||
export * from "./org-form/org-form.component"; |
export * from "./org-form/org-form.component"; |
||||
|
export * from "./user-list/user-list.component"; |
||||
|
export * from "./role-permission/role-permission.component"; |
||||
|
|||||
@ -0,0 +1,25 @@ |
|||||
|
<div class="pb-10"> |
||||
|
<nz-card *ngFor="let group of permissions | keyvalue : returenZero;" nzType="inner" [nzTitle]="group.key" |
||||
|
class="mb-4"> |
||||
|
<div nz-row [nzGutter]="[12,12]"> |
||||
|
<div nz-col nzSpan="8" *ngFor="let perm of group.value"> |
||||
|
<label nz-checkbox |
||||
|
[nzChecked]="hasPermissions.has(perm.value)" |
||||
|
(nzCheckedChange)="onPermissionChange($event,perm.value)"> |
||||
|
{{perm.label}} |
||||
|
</label> |
||||
|
</div> |
||||
|
</div> |
||||
|
</nz-card> |
||||
|
|
||||
|
<div class="fixed-footter bg-white py-2 absolute left-0 bottom-0 right-0"> |
||||
|
<div class="flex pl-16"> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit()" [nzLoading]="loading"> |
||||
|
保存 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
@ -0,0 +1,82 @@ |
|||||
|
import { PermItemDTO, UserRoleDTO } from "@cdk/dtos/user.dto"; |
||||
|
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from "@angular/core"; |
||||
|
import { ActivatedRoute } from "@angular/router"; |
||||
|
import { AnyObject } from "@cdk/types"; |
||||
|
import { NzMessageService } from "ng-zorro-antd/message"; |
||||
|
import { finalize } from "rxjs"; |
||||
|
import { ApiService } from "@cdk/services"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-role-permission", |
||||
|
templateUrl: "./role-permission.component.html", |
||||
|
styleUrls: ["./role-permission.component.less"], |
||||
|
}) |
||||
|
export class RolePermissionComponent implements OnChanges { |
||||
|
constructor(private api: ApiService, private route: ActivatedRoute, private msg: NzMessageService) {} |
||||
|
|
||||
|
@Input() perms: PermItemDTO[] = []; |
||||
|
|
||||
|
@Input() role!: UserRoleDTO; |
||||
|
|
||||
|
@Output() onReload = new EventEmitter(); |
||||
|
|
||||
|
loading = false; |
||||
|
|
||||
|
ngOnChanges(changes: SimpleChanges): void { |
||||
|
if (changes["perms"]?.currentValue) { |
||||
|
const perms: PermItemDTO[] = changes["perms"].currentValue; |
||||
|
this.permissions = perms.reduce((a, c) => { |
||||
|
const key = c["category"]; |
||||
|
const o = { ...c, label: c.itemName, value: c.id }; |
||||
|
if (a[key]) { |
||||
|
a[key].push(o); |
||||
|
} else { |
||||
|
a[key] = [o]; |
||||
|
} |
||||
|
return a; |
||||
|
}, {} as Record<string, Array<{ label: string; value: number } & AnyObject>>); |
||||
|
} |
||||
|
if (changes["role"]?.currentValue) { |
||||
|
const role: UserRoleDTO = changes["role"].currentValue; |
||||
|
let perms: number[] = role.roleItems ?? []; |
||||
|
this.hasPermissions.clear(); |
||||
|
perms.forEach((p) => { |
||||
|
this.hasPermissions.add(p); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
permissions = {}; |
||||
|
|
||||
|
hasPermissions = new Set<number>(); |
||||
|
|
||||
|
ngOnInit(): void {} |
||||
|
|
||||
|
returenZero() { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
onPermissionChange(checked: boolean, key: number) { |
||||
|
if (!checked && this.hasPermissions.has(key)) { |
||||
|
this.hasPermissions.delete(key); |
||||
|
} else { |
||||
|
this.hasPermissions.add(key); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onSubmit() { |
||||
|
const role = { ...this.role, roleId: this.role.id, items: Array.from(this.hasPermissions) }; |
||||
|
this.loading = true; |
||||
|
this.api |
||||
|
.updateRole(role) |
||||
|
.pipe( |
||||
|
finalize(() => { |
||||
|
this.loading = false; |
||||
|
}) |
||||
|
) |
||||
|
.subscribe((res) => { |
||||
|
this.msg.success(res.desc); |
||||
|
this.onReload.emit(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
<ng-template #searchTpl> |
||||
|
|
||||
|
</ng-template> |
||||
|
|
||||
|
<div class="flex items-center justify-between"> |
||||
|
<div> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<nz-input-group [nzSuffix]="suffixIconSearch"> |
||||
|
<input nz-input placeholder="请输入用户" [(ngModel)]="searchValue" (ngModelChange)="onSearch($event)" /> |
||||
|
</nz-input-group> |
||||
|
<ng-template #suffixIconSearch> |
||||
|
<span nz-icon nzType="search"></span> |
||||
|
</ng-template> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</div> |
||||
|
<div> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="primary" (click)="openForm()"> |
||||
|
<i nz-icon nzType="plus"></i> |
||||
|
新增用户 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<nz-table #table [nzData]="visibledUsers"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>账号</th> |
||||
|
<th>姓名</th> |
||||
|
<th>角色</th> |
||||
|
<th>添加时间</th> |
||||
|
<th>操作</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr *ngFor="let data of table.data"> |
||||
|
<td>{{data.uid}}</td> |
||||
|
<td>{{data.name}}</td> |
||||
|
<td>{{data.roleName}}</td> |
||||
|
<td>{{data.time | date:'yyyy-MM-dd HH:mm:ss'}}</td> |
||||
|
<td> |
||||
|
<a (click)="openForm(data)">编辑</a> |
||||
|
<nz-divider nzType="vertical"></nz-divider> |
||||
|
<a (click)="deleteItem(data.uid)">删除</a> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</nz-table> |
||||
|
|
||||
|
|
||||
|
<ng-template #userFormTpl> |
||||
|
<form nz-form [formGroup]="userFrom"> |
||||
|
|
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="6" nzRequired> |
||||
|
姓名 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="12" [nzErrorTip]="formErrorTipsTpl"> |
||||
|
<input nz-input placeholder="请输入用户姓名" formControlName="name" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="6" nzRequired> |
||||
|
账号 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="12" [nzErrorTip]="formErrorTipsTpl"> |
||||
|
<input nz-input placeholder="请输入用户账号" formControlName="uid" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="6" nzRequired> |
||||
|
密码 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="12" [nzErrorTip]="formErrorTipsTpl"> |
||||
|
<input nz-input placeholder="请输入用户密码" type="password" formControlName="password" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</form> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #formErrorTipsTpl let-control> |
||||
|
<form-error-tips [control]="control"></form-error-tips> |
||||
|
</ng-template> |
||||
@ -0,0 +1,122 @@ |
|||||
|
import { UserDTO, UserRoleDTO } from "@cdk/dtos/user.dto"; |
||||
|
import { |
||||
|
Component, |
||||
|
EventEmitter, |
||||
|
Input, |
||||
|
OnChanges, |
||||
|
OnInit, |
||||
|
Output, |
||||
|
SimpleChanges, |
||||
|
TemplateRef, |
||||
|
ViewChild, |
||||
|
} from "@angular/core"; |
||||
|
import { FormControl, FormGroup } from "@angular/forms"; |
||||
|
import { ActivatedRoute } from "@angular/router"; |
||||
|
import { AnyObject, FormValidators, TableListOption, Utils } from "@cdk/public-api"; |
||||
|
import { MD5 } from "crypto-js"; |
||||
|
import { NzMessageService } from "ng-zorro-antd/message"; |
||||
|
import { NzModalService } from "ng-zorro-antd/modal"; |
||||
|
import { lastValueFrom } from "rxjs"; |
||||
|
import { ApiService } from "@cdk/services"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-user-list", |
||||
|
templateUrl: "./user-list.component.html", |
||||
|
styleUrls: ["./user-list.component.less"], |
||||
|
}) |
||||
|
export class UserListComponent implements OnChanges { |
||||
|
constructor( |
||||
|
private api: ApiService, |
||||
|
private route: ActivatedRoute, |
||||
|
private modal: NzModalService, |
||||
|
private msg: NzMessageService |
||||
|
) {} |
||||
|
|
||||
|
@ViewChild("userFormTpl") public userFormTpl!: TemplateRef<void>; |
||||
|
|
||||
|
@Input() users: UserDTO[] = []; |
||||
|
|
||||
|
@Input() role!: UserRoleDTO; |
||||
|
|
||||
|
@Output() onReload = new EventEmitter(); |
||||
|
|
||||
|
searchValue = ""; |
||||
|
|
||||
|
visibledUsers: UserDTO[] = []; |
||||
|
|
||||
|
public userFrom = new FormGroup({ |
||||
|
uid: new FormControl("", [FormValidators.required("请输入账号")]), |
||||
|
name: new FormControl("", [FormValidators.required("请输入姓名")]), |
||||
|
password: new FormControl("", [FormValidators.required("请输入密码")]), |
||||
|
}); |
||||
|
|
||||
|
ngOnInit(): void {} |
||||
|
|
||||
|
ngOnChanges(changes: SimpleChanges): void { |
||||
|
const u = changes["users"]?.currentValue; |
||||
|
if (Array.isArray(u)) { |
||||
|
this.onSearch(this.searchValue); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onSearch(kw: string) { |
||||
|
this.visibledUsers = this.users.filter((f) => f.name.includes(kw) || f.uid.includes(kw)); |
||||
|
} |
||||
|
|
||||
|
deleteItem(uid: string) { |
||||
|
this.modal.confirm({ |
||||
|
nzTitle: "警告", |
||||
|
nzContent: "是否要删除该用户?", |
||||
|
nzOkDanger: true, |
||||
|
nzOnOk: async () => { |
||||
|
const res = await lastValueFrom(this.api.deleteUser(uid)); |
||||
|
if (res.success) { |
||||
|
this.msg.success(res.desc); |
||||
|
this.onReload.emit(); |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
resetUserForm() { |
||||
|
this.userFrom.reset(); |
||||
|
} |
||||
|
|
||||
|
openForm(item?: any) { |
||||
|
if (item) { |
||||
|
this.userFrom.patchValue(item); |
||||
|
} |
||||
|
this.modal.create({ |
||||
|
nzTitle: item ? "编辑用户" : "新增用户", |
||||
|
nzContent: this.userFormTpl, |
||||
|
nzOnCancel: () => { |
||||
|
this.resetUserForm(); |
||||
|
}, |
||||
|
nzOnOk: async () => { |
||||
|
if (Utils.validateFormGroup(this.userFrom)) { |
||||
|
const user = { ...this.userFrom.value, roleId: this.role.id }; |
||||
|
user["password"] = MD5(user.password!).toString().substring(16).toUpperCase(); |
||||
|
let notExist = true; |
||||
|
if ((item && item.uid !== user.uid) || !item) { |
||||
|
const check = await lastValueFrom(this.api.checkUid(user.uid!)); |
||||
|
notExist = check.body; |
||||
|
} |
||||
|
|
||||
|
if (notExist) { |
||||
|
const res = await lastValueFrom(this.api.saveUser(user, Boolean(item))); |
||||
|
this.msg.success(res.desc); |
||||
|
this.onReload.emit(); |
||||
|
this.resetUserForm(); |
||||
|
return true; |
||||
|
} else { |
||||
|
this.msg.error("账号重复"); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,92 @@ |
|||||
|
<app-page [scroll]="false"> |
||||
|
|
||||
|
<div nz-row class="h-full overflow-hidden bg-white rounded-lg"> |
||||
|
<div nz-col nzFlex="220px" class="user-type"> |
||||
|
<nz-card |
||||
|
class="h-full " |
||||
|
[nzBordered]="false" |
||||
|
nzTitle="用户角色" |
||||
|
[nzBodyStyle]="{padding:'1px 0 0 0'}"> |
||||
|
|
||||
|
<ul nz-menu nzMode="inline"> |
||||
|
<li |
||||
|
*ngFor="let item of roleList" |
||||
|
nz-menu-item |
||||
|
(click)="onRoleChange(item.id)" |
||||
|
[nzSelected]="role?.id === item.id" |
||||
|
class="flex items-center justify-between role-item"> |
||||
|
<span> |
||||
|
{{item.roleName}} |
||||
|
</span> |
||||
|
<nz-space nzSize="small" class="options"> |
||||
|
<a *nzSpaceItem nz-button nzType="link" nzSize="small" |
||||
|
(click)="openForm(roleFormTpl,$event,item)"> |
||||
|
<span nz-icon nzType="edit"></span> |
||||
|
</a> |
||||
|
<a *nzSpaceItem nz-button nzType="link" nzSize="small" |
||||
|
(click)="deleteItem($event,item.id)"> |
||||
|
<span nz-icon nzType="delete"></span> |
||||
|
</a> |
||||
|
</nz-space> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<div class="px-4 py-2"> |
||||
|
<button nz-button nzType="dashed" nzBlock (click)="openForm(roleFormTpl,$event)"> |
||||
|
<i nz-icon nzType="plus"></i> |
||||
|
<span> |
||||
|
新增角色 |
||||
|
</span> |
||||
|
</button> |
||||
|
</div> |
||||
|
</nz-card> |
||||
|
</div> |
||||
|
<div nz-col nzFlex="1" class="flex-1 h-full overflow-hidden bg-white "> |
||||
|
|
||||
|
<nz-card [nzBordered]="false" |
||||
|
class="h-full scroll-card-body "> |
||||
|
<nz-card-tab> |
||||
|
<nz-tabset nzSize="large" [nzSelectedIndex]="tab" (nzSelectedIndexChange)="onTabChange($event)"> |
||||
|
<nz-tab nzTitle="用户列表"></nz-tab> |
||||
|
<nz-tab nzTitle="权限管理"></nz-tab> |
||||
|
</nz-tabset> |
||||
|
</nz-card-tab> |
||||
|
<div class="p-4"> |
||||
|
<app-user-list |
||||
|
*ngIf="role && tab.toString() === '0'" |
||||
|
[users]="currentUserList" |
||||
|
[role]="role" |
||||
|
(onReload)="reloadUserList()"> |
||||
|
|
||||
|
</app-user-list> |
||||
|
<app-role-permission |
||||
|
*ngIf="role && tab.toString() === '1'" |
||||
|
[perms]="allPerms" |
||||
|
[role]="role" |
||||
|
(onReload)="getRoleList()"> |
||||
|
</app-role-permission> |
||||
|
</div> |
||||
|
</nz-card> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</app-page> |
||||
|
|
||||
|
|
||||
|
<ng-template #roleFormTpl> |
||||
|
<form nz-form [formGroup]="roleForm"> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="6" nzRequired> |
||||
|
角色名称 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="12" [nzErrorTip]="formErrorTipsTpl"> |
||||
|
<input nz-input placeholder="请输入角色名称" formControlName="roleName" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</form> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #formErrorTipsTpl let-control> |
||||
|
<div class="text-left"> |
||||
|
<form-error-tips [control]="control"></form-error-tips> |
||||
|
</div> |
||||
|
</ng-template> |
||||
@ -0,0 +1,29 @@ |
|||||
|
.user-type { |
||||
|
border-right: 1px solid #e8e8e8; |
||||
|
|
||||
|
::ng-deep { |
||||
|
.ant-menu-inline { |
||||
|
border-right: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.role-head { |
||||
|
::ng-deep { |
||||
|
.ant-card-extra { |
||||
|
padding: 10px 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.role-item { |
||||
|
.options { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
&:hover { |
||||
|
.options { |
||||
|
display: flex; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,147 @@ |
|||||
|
import { PermItemDTO, UserDTO, UserRoleDTO } from "@cdk/dtos/user.dto"; |
||||
|
import { Component, OnChanges, OnInit, SimpleChanges, TemplateRef, ViewChild } from "@angular/core"; |
||||
|
import { FormControl, FormGroup, FormGroupName } from "@angular/forms"; |
||||
|
import { ActivatedRoute, Router } from "@angular/router"; |
||||
|
import { AnyObject, FormValidators, TableListOption, Utils } from "@cdk/public-api"; |
||||
|
import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; |
||||
|
import { NzMessageService } from "ng-zorro-antd/message"; |
||||
|
import { NzModalService } from "ng-zorro-antd/modal"; |
||||
|
import { lastValueFrom } from "rxjs"; |
||||
|
import { ApiService } from "@cdk/services"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-client-user-manage", |
||||
|
templateUrl: "./user-manage.component.html", |
||||
|
styleUrls: ["./user-manage.component.less"], |
||||
|
}) |
||||
|
export class ClientUserManageComponent { |
||||
|
constructor( |
||||
|
private route: ActivatedRoute, |
||||
|
private api: ApiService, |
||||
|
private router: Router, |
||||
|
private modal: NzModalService, |
||||
|
private msg: NzMessageService |
||||
|
) {} |
||||
|
|
||||
|
public tab = 0; |
||||
|
|
||||
|
public role: UserRoleDTO | null = null; |
||||
|
|
||||
|
public roleForm = new FormGroup({ |
||||
|
roleId: new FormControl(""), |
||||
|
roleName: new FormControl("", [FormValidators.required("请输入角色名称")]), |
||||
|
items: new FormControl([]), |
||||
|
}); |
||||
|
|
||||
|
public allPerms: PermItemDTO[] = []; |
||||
|
|
||||
|
public userList: UserDTO[] = []; |
||||
|
|
||||
|
public currentUserList: UserDTO[] = []; |
||||
|
|
||||
|
roleList: UserRoleDTO[] = []; |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.tab = Number(this.route.snapshot.queryParamMap.get("tab")) || 0; |
||||
|
this.api.getRolePerms().subscribe((res) => { |
||||
|
this.allPerms = res.body; |
||||
|
}); |
||||
|
this.getRoleList(); |
||||
|
this.getUserList(); |
||||
|
} |
||||
|
|
||||
|
getUserList(reload?: boolean) { |
||||
|
this.api.getUserList().subscribe((res) => { |
||||
|
this.userList = res.body; |
||||
|
this.currentUserList = this.userList.filter((f) => Number(f.roleId) === Number(this.role!.id)); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
reloadUserList() { |
||||
|
this.getUserList(true); |
||||
|
} |
||||
|
|
||||
|
getRoleList() { |
||||
|
this.api.getRoleList().subscribe((res) => { |
||||
|
this.roleList = res.body.map((i) => ({ ...i, id: i.id.toString() })); |
||||
|
const roleId = this.route.snapshot.queryParamMap.get("roleId"); |
||||
|
const role = this.roleList.find((f) => f.id === roleId); |
||||
|
if (role) { |
||||
|
this.role = role; |
||||
|
this.onRoleChange(role.id); |
||||
|
return; |
||||
|
} |
||||
|
if (this.roleList.length > 0) { |
||||
|
this.onRoleChange(this.roleList[0].id); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
onRoleChange(roleId: string) { |
||||
|
const role = this.roleList.find((f) => f.id === roleId); |
||||
|
if (role) { |
||||
|
this.router |
||||
|
.navigate(["/system/user"], { |
||||
|
queryParams: { |
||||
|
roleId, |
||||
|
}, |
||||
|
queryParamsHandling: "merge", |
||||
|
}) |
||||
|
.then(() => { |
||||
|
this.role = role; |
||||
|
this.currentUserList = this.userList.filter((f) => Number(f.roleId) === Number(role.id)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onTabChange(index: number) { |
||||
|
this.tab = index; |
||||
|
this.router.navigate(["/system/user"], { |
||||
|
queryParams: { |
||||
|
tab: index, |
||||
|
}, |
||||
|
queryParamsHandling: "merge", |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
openForm(nzContent: TemplateRef<{}>, event: MouseEvent, role?: UserRoleDTO) { |
||||
|
event.stopPropagation(); |
||||
|
if (role) { |
||||
|
this.roleForm.patchValue({ |
||||
|
...role, |
||||
|
roleId: role.id, |
||||
|
}); |
||||
|
} |
||||
|
this.modal.create({ |
||||
|
nzTitle: role ? "编辑角色" : "新增角色", |
||||
|
nzContent, |
||||
|
nzOnCancel: () => { |
||||
|
this.roleForm.reset(); |
||||
|
}, |
||||
|
nzOnOk: async () => { |
||||
|
if (Utils.validateFormGroup(this.roleForm)) { |
||||
|
const res = await lastValueFrom(this.api.updateRole(this.roleForm.value)); |
||||
|
this.msg.success(res.desc); |
||||
|
this.roleForm.reset(); |
||||
|
this.getRoleList(); |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
deleteItem(event: MouseEvent, id: string) { |
||||
|
event.stopPropagation(); |
||||
|
this.modal.confirm({ |
||||
|
nzTitle: "警告", |
||||
|
nzContent: "是否要删除该角色?", |
||||
|
nzOkDanger: true, |
||||
|
nzOnOk: async () => { |
||||
|
const res = await lastValueFrom(this.api.deleteRole(id)); |
||||
|
this.msg.success(res.desc); |
||||
|
this.getRoleList(); |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -1 +1 @@ |
|||||
export * from "./client-api.service"; |
export * from "./auth.guard"; |
||||
|
|||||
Loading…
Reference in new issue