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 "./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