65 changed files with 407 additions and 2479 deletions
@ -1,12 +0,0 @@ |
|||
<form nz-form [formGroup]="formGroup"> |
|||
<nz-form-item> |
|||
<nz-form-label> 部门名称 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入部门名称" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
|
|||
<ng-template #formErrorTipsTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
@ -1,38 +0,0 @@ |
|||
import { Component, OnInit, inject } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { FormValidators } from 'app/utils' |
|||
import { NZ_MODAL_DATA } from 'ng-zorro-antd/modal' |
|||
|
|||
@Component({ |
|||
selector: 'app-contact-group-form', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './contact-group-form.component.html', |
|||
styleUrl: './contact-group-form.component.less', |
|||
}) |
|||
export class ContactGroupFormComponent implements OnInit { |
|||
constructor() {} |
|||
|
|||
data = inject(NZ_MODAL_DATA) |
|||
|
|||
formGroup = new FormGroup({ |
|||
id: new FormControl(), |
|||
name: new FormControl('', [FormValidators.required('请输入部门名称'), FormValidators.maxLength(30)]), |
|||
parentId: new FormControl(), |
|||
}) |
|||
|
|||
ngOnInit(): void { |
|||
if (this.data) { |
|||
this.formGroup.patchValue(this.data) |
|||
} |
|||
} |
|||
|
|||
public getValues() { |
|||
let values = null |
|||
if (FormValidators.validateFormGroup(this.formGroup)) { |
|||
values = this.formGroup.value |
|||
} |
|||
return values |
|||
} |
|||
} |
@ -1,31 +0,0 @@ |
|||
<div class="data-tree"> |
|||
<nz-tree |
|||
nzBlockNode |
|||
[nzSelectedKeys]="contact.selecedKeys" |
|||
[nzExpandedKeys]="contact.expandedKeys" |
|||
[nzData]="nodes" |
|||
(nzClick)="activeNode($event)" |
|||
(nzExpandChange)="handleExpandedKeysChange($event)" |
|||
[nzTreeTemplate]="nzTreeTemplate" |
|||
> |
|||
</nz-tree> |
|||
</div> |
|||
|
|||
<ng-template #nzTreeTemplate let-node let-origin="origin"> |
|||
<div class="flex items-center justify-between overflow-hidden"> |
|||
<span class="flex-1 overflow-hidden text-ellipsis">{{ node.title }}</span> |
|||
|
|||
@if (origin.id !== '1') { |
|||
<button nz-button nzType="text" nz-dropdown [nzDropdownMenu]="menu" (click)="$event.stopPropagation()"> |
|||
<i nz-icon nzType="more"></i> |
|||
</button> |
|||
} |
|||
<nz-dropdown-menu #menu="nzDropdownMenu"> |
|||
<ul nz-menu> |
|||
<!-- <li nz-menu-item (click)="createGroup(node)">新增下级部门</li> --> |
|||
<li nz-menu-item (click)="editGroup(node)">编辑</li> |
|||
<li nz-menu-item (click)="deleteGroup(node)">删除</li> |
|||
</ul> |
|||
</nz-dropdown-menu> |
|||
</div> |
|||
</ng-template> |
@ -1,83 +0,0 @@ |
|||
import { Component, EventEmitter, Input, Output, OnChanges, OnInit, SimpleChanges } from '@angular/core' |
|||
|
|||
import { NzContextMenuService, NzDropdownMenuComponent } from 'ng-zorro-antd/dropdown' |
|||
import { NzFormatEmitEvent, NzTreeNode, NzTreeNodeOptions } from 'ng-zorro-antd/tree' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { Persist } from 'app/utils' |
|||
import { ContactService } from '../contact.service' |
|||
|
|||
@Component({ |
|||
selector: 'app-contact-group', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
providers: [ContactService], |
|||
templateUrl: './contact-group.component.html', |
|||
styleUrl: './contact-group.component.less', |
|||
}) |
|||
export class ContactGroupComponent implements OnInit, OnChanges { |
|||
constructor( |
|||
private nzContextMenuService: NzContextMenuService, |
|||
public contact: ContactService, |
|||
) {} |
|||
|
|||
@Input() nodes: NzTreeNodeOptions[] = [] |
|||
|
|||
@Input() active!: Persist |
|||
|
|||
@Output() onSelect = new EventEmitter() |
|||
|
|||
@Output() onCreate = new EventEmitter() |
|||
|
|||
@Output() onEdit = new EventEmitter() |
|||
|
|||
@Output() onDelete = new EventEmitter() |
|||
|
|||
ngOnInit(): void {} |
|||
|
|||
ngOnChanges(changes: SimpleChanges) {} |
|||
|
|||
openFolder(data: NzTreeNode | NzFormatEmitEvent): void { |
|||
if (data instanceof NzTreeNode) { |
|||
data.isExpanded = !data.isExpanded |
|||
} else { |
|||
const node = data.node |
|||
if (node) { |
|||
node.isExpanded = !node.isExpanded |
|||
} |
|||
} |
|||
} |
|||
|
|||
activeNode(data: NzFormatEmitEvent): void { |
|||
this.contact.contactGroup.update((state) => { |
|||
return { |
|||
...state, |
|||
selecedKeys: [data.node!.key], |
|||
} |
|||
}) |
|||
this.onSelect.emit() |
|||
} |
|||
|
|||
handleExpandedKeysChange(expanded: NzFormatEmitEvent) { |
|||
this.contact.contactGroup.update((state) => { |
|||
return { |
|||
...state, |
|||
expandedKeys: expanded?.keys ?? [], |
|||
} |
|||
}) |
|||
} |
|||
|
|||
contextMenu($event: MouseEvent, menu: NzDropdownMenuComponent): void { |
|||
this.nzContextMenuService.create($event, menu) |
|||
} |
|||
|
|||
createGroup(node: NzTreeNode): void { |
|||
this.onCreate.emit(node.origin) |
|||
} |
|||
|
|||
editGroup(node: NzTreeNode): void { |
|||
this.onEdit.emit(node.origin) |
|||
} |
|||
deleteGroup(node: NzTreeNode): void { |
|||
this.onDelete.emit(node.origin.key) |
|||
} |
|||
} |
@ -1,97 +0,0 @@ |
|||
<nz-card [nzBordered]="false" [nzBodyStyle]="{ padding: 0, height }"> |
|||
<div class="flex contacts h-full"> |
|||
<div class="group w-56 h-full flex flex-col"> |
|||
<div> |
|||
<h3 class="px-4 pt-4 flex items-center justify-between"> |
|||
<span>部门</span> |
|||
<button nz-button nzType="text" (click)="showGroupForm()"> |
|||
<i nz-icon nzType="plus"></i> |
|||
</button> |
|||
</h3> |
|||
</div> |
|||
|
|||
<div class="flex-1 overflow-y-auto"> |
|||
<app-contact-group |
|||
[nodes]="groups" |
|||
(onSelect)="handleGroupSelect()" |
|||
(onCreate)="showGroupForm($event)" |
|||
(onEdit)="showGroupForm($event, true)" |
|||
(onDelete)="deleteUserGroup($event)" |
|||
> |
|||
</app-contact-group> |
|||
</div> |
|||
</div> |
|||
<div class="flex-1 p-4 overflow-auto"> |
|||
<app-server-paginated-table |
|||
[formGroup]="queryForm" |
|||
[renderColumn]="renderColumnTpl" |
|||
[options]="tableOption" |
|||
> |
|||
<div *appTableForm nz-row [nzGutter]="[24, 24]"> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px">用户名</nz-form-label> |
|||
<nz-form-control nzFlex="1"> |
|||
<input nz-input placeholder="请输入用户名" formControlName="userName" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px">姓名</nz-form-label> |
|||
<nz-form-control nzFlex="1"> |
|||
<input nz-input placeholder="请输入姓名" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px">状态</nz-form-label> |
|||
<nz-form-control nzFlex="1"> |
|||
<nz-select nzPlaceHolder="请选择状态" formControlName="enable" nzAllowClear> |
|||
<nz-option [nzValue]="true" nzLabel="启用"></nz-option> |
|||
<nz-option [nzValue]="false" nzLabel="禁用"></nz-option> |
|||
</nz-select> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px">创建时间</nz-form-label> |
|||
<nz-form-control nzFlex="1"> |
|||
<!-- <nz-range-picker formControlName="createTime"></nz-range-picker> --> |
|||
<app-range-picker [showTime]="true" formControlName="createTime"></app-range-picker> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
</div> |
|||
<div *appTableAction> |
|||
<nz-space> |
|||
<button nz-button nzType="primary" (click)="handleCreateUser()">添加用户</button> |
|||
</nz-space> |
|||
</div> |
|||
<ng-template #renderColumnTpl let-data let-key="key"> |
|||
@switch (key) { |
|||
@case ('enable') { |
|||
@if (data) { |
|||
<nz-badge nzStatus="success" nzText="启用"></nz-badge> |
|||
} @else { |
|||
<nz-badge nzStatus="error" nzText="禁用"></nz-badge> |
|||
} |
|||
} |
|||
@case ('roleName') { |
|||
@if (data) { |
|||
<nz-tag>{{ data }}</nz-tag> |
|||
} @else { |
|||
- |
|||
} |
|||
} |
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
</app-server-paginated-table> |
|||
</div> |
|||
</div> |
|||
</nz-card> |
@ -1,3 +0,0 @@ |
|||
.group { |
|||
border-right: 1px solid var(--border-color); |
|||
} |
@ -1,223 +0,0 @@ |
|||
import { Component, HostListener, OnInit, OnDestroy } from '@angular/core' |
|||
import { lastValueFrom } from 'rxjs' |
|||
import { NzTreeNodeOptions } from 'ng-zorro-antd/tree' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { format } from 'date-fns' |
|||
import { ApiService, UserGroupTreeItem } from 'app/services' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { ContactGroupComponent } from '../contact-group/contact-group.component' |
|||
import { ContactGroupFormComponent } from '../contact-group-form/contact-group-form.component' |
|||
import { AnyObject, TableOption } from 'app/components/server-paginated-table' |
|||
import { UserFormComponent } from 'app/components/user-form/user-form.component' |
|||
import { RoleListDTO, UserDTO } from 'app/services/api.dto' |
|||
import { ContactService } from '../contact.service' |
|||
|
|||
@Component({ |
|||
selector: 'app-contact-list', |
|||
standalone: true, |
|||
imports: [SharedModule, ContactGroupComponent, ContactGroupFormComponent], |
|||
templateUrl: './contact-list.component.html', |
|||
styleUrl: './contact-list.component.less', |
|||
providers: [ContactService], |
|||
}) |
|||
export class ContactListComponent implements OnInit, OnDestroy { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
private contact: ContactService, |
|||
) {} |
|||
|
|||
height = 'auto' |
|||
|
|||
groups: NzTreeNodeOptions[] = [] |
|||
|
|||
tableOption = new TableOption(this.fetchData.bind(this), { |
|||
manual: true, |
|||
}) |
|||
|
|||
queryForm = new FormGroup({ |
|||
userName: new FormControl(), |
|||
enable: new FormControl(), |
|||
name: new FormControl(), |
|||
createTime: new FormControl(), |
|||
}) |
|||
|
|||
roleList: RoleListDTO[] = [] |
|||
|
|||
ngOnInit(): void { |
|||
this.initTableOption() |
|||
this.onResize() |
|||
this.getUserGroupTree() |
|||
this.getRoleList() |
|||
} |
|||
|
|||
ngOnDestroy(): void {} |
|||
|
|||
initTableOption() { |
|||
this.tableOption |
|||
.setColumn([ |
|||
{ key: 'username', title: '用户名' }, |
|||
{ key: 'name', title: '姓名' }, |
|||
{ key: 'enable', title: '状态' }, |
|||
{ key: 'roleName', title: '角色' }, |
|||
{ key: 'remark', title: '说明' }, |
|||
{ key: 'createTime', title: '创建时间' }, |
|||
]) |
|||
.setRowOperate([ |
|||
{ title: '启用', onClick: this.updateStatus.bind(this), visible: (v) => v.id !== '1' && !v.enable }, |
|||
{ title: '禁用', onClick: this.updateStatus.bind(this), visible: (v) => v.id !== '1' && v.enable }, |
|||
{ |
|||
title: '重置密码', |
|||
onClick: this.resetPassword.bind(this), |
|||
premissions: [], |
|||
visible: (v) => v.id !== '1', |
|||
}, |
|||
{ |
|||
title: '编辑', |
|||
onClick: this.handleCreateUser.bind(this), |
|||
premissions: [], |
|||
visible: (v) => v.id !== '1', |
|||
}, |
|||
{ |
|||
title: '删除', |
|||
onClick: this.deleteUser.bind(this), |
|||
premissions: [], |
|||
visible: (v) => v.id !== '1', |
|||
}, |
|||
]) |
|||
} |
|||
|
|||
@HostListener('window:resize') |
|||
onResize() { |
|||
this.height = innerHeight - 100 + 'px' |
|||
} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
let query = Object.create(null) |
|||
const activeGroup = this.contact.contactGroup.value |
|||
if (Array.isArray(q['createTime'])) { |
|||
const createTimeStart = q['createTime']?.[0] |
|||
const createTimeEnd = q['createTime']?.[1] |
|||
|
|||
q['createTimeStart'] = createTimeStart ? format(new Date(createTimeStart), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
q['createTimeEnd'] = createTimeEnd ? format(new Date(createTimeEnd), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
} |
|||
query = { ...q, groupId: activeGroup?.selecedKeys[0] } |
|||
return this.api.getUserPage(p, query) |
|||
} |
|||
|
|||
handleGroupSelect() { |
|||
this.tableOption.ref?.search() |
|||
} |
|||
|
|||
updateStatus(v: UserDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: `是否要${v.enable ? '禁用' : '启用'}该用户?`, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.updateUserStatus(v.id)) |
|||
this.msg.success('操作成功') |
|||
this.tableOption.ref.reload() |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
getUserGroupTree() { |
|||
this.api.getUserGroupTree().subscribe((res) => { |
|||
this.groups = res |
|||
this.contact.initState(res) |
|||
if (res.length > 0) { |
|||
this.tableOption.ref?.reload() |
|||
} |
|||
}) |
|||
} |
|||
|
|||
getRoleList() { |
|||
this.api.getAllRole().subscribe((res) => { |
|||
this.roleList = res.data |
|||
}) |
|||
} |
|||
|
|||
showGroupForm(group?: UserGroupTreeItem, edit = false) { |
|||
this.modal.create({ |
|||
nzTitle: edit ? '编辑部门' : '新增部门', |
|||
nzContent: ContactGroupFormComponent, |
|||
nzData: edit ? group : { parentId: group?.id }, |
|||
nzOnOk: async (e) => { |
|||
const vals = e.getValues() |
|||
if (vals) { |
|||
await lastValueFrom(this.api.saveUserGroup(vals as UserGroupTreeItem)) |
|||
this.msg.success('保存成功') |
|||
this.getUserGroupTree() |
|||
return true |
|||
} |
|||
return false |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
deleteUserGroup(id: string) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要删除该分组?', |
|||
nzOkDanger: true, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.deleteUserGroup(id)) |
|||
this.msg.success('删除成功') |
|||
this.getUserGroupTree() |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
deleteUser(v: UserDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要删除该用户?', |
|||
nzOkDanger: true, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.deleteUser(v.id)) |
|||
this.msg.success('删除成功') |
|||
this.getUserGroupTree() |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
resetPassword(v: UserDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要将该用户的密码重置为jwkj?', |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.changeUserPassword(v.id, 'jwkj')) |
|||
this.msg.success('重置成功') |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
handleCreateUser(user?: UserDTO) { |
|||
this.modal.create({ |
|||
nzTitle: user ? '编辑用户' : '添加用户', |
|||
nzContent: UserFormComponent, |
|||
nzWidth: 720, |
|||
nzData: { |
|||
roleList: this.roleList, |
|||
value: user, |
|||
}, |
|||
nzOnOk: async (e) => { |
|||
const vals = e.getValues() |
|||
if (vals) { |
|||
const activeGroup = this.contact.contactGroup.value |
|||
await lastValueFrom( |
|||
this.api.saveUser({ ...(user ?? {}), ...vals, groupId: activeGroup.selecedKeys[0] }), |
|||
) |
|||
this.tableOption.ref?.reload() |
|||
this.msg.success('保存成功') |
|||
return true |
|||
} |
|||
return false |
|||
}, |
|||
}) |
|||
} |
|||
} |
@ -1,59 +0,0 @@ |
|||
import { Injectable, OnDestroy } from '@angular/core' |
|||
import { Persist, Utils } from 'app/utils' |
|||
import { NzTreeNodeOptions } from 'ng-zorro-antd/tree' |
|||
|
|||
@Injectable() |
|||
export class ContactService implements OnDestroy { |
|||
constructor() {} |
|||
|
|||
ngOnDestroy(): void { |
|||
this.contactGroup.clear() |
|||
} |
|||
|
|||
contactGroup = new Persist<{ selecedKeys: string[]; expandedKeys: string[] }>(sessionStorage, 'contactGroup', { |
|||
selecedKeys: [], |
|||
expandedKeys: [], |
|||
}) |
|||
|
|||
public get selecedKeys(): string[] { |
|||
return this.contactGroup.value.selecedKeys |
|||
} |
|||
|
|||
public get expandedKeys(): string[] { |
|||
return this.contactGroup.value.expandedKeys |
|||
} |
|||
|
|||
initState(treeData: NzTreeNodeOptions[]) { |
|||
if (treeData.length === 0) { |
|||
return |
|||
} |
|||
let selecedKeys = this.selecedKeys |
|||
let expandedKeys = this.expandedKeys |
|||
const flatData: NzTreeNodeOptions[] = Utils.treeToFlatList(treeData) |
|||
if (!flatData.some((s) => selecedKeys.includes(s.key))) { |
|||
selecedKeys = [] |
|||
} |
|||
if (selecedKeys.length === 0) { |
|||
selecedKeys = [treeData[0].key] as string[] |
|||
} else { |
|||
expandedKeys = this.setExpandedKeysBySelecedKeys(treeData, selecedKeys) |
|||
} |
|||
this.contactGroup.update(() => { |
|||
return { |
|||
expandedKeys: [...new Set(expandedKeys)], |
|||
selecedKeys, |
|||
} |
|||
}) |
|||
} |
|||
|
|||
setExpandedKeysBySelecedKeys(flatData: NzTreeNodeOptions[], selecedKeys: string[]) { |
|||
const res: string[] = [] |
|||
|
|||
let parentId = flatData.find((f) => selecedKeys.includes(f.key))?.['parentId'] |
|||
while (parentId) { |
|||
res.push(parentId) |
|||
parentId = flatData.find((f) => f.key === parentId)?.['parentId'] |
|||
} |
|||
return this.expandedKeys.concat(res) |
|||
} |
|||
} |
@ -1,83 +0,0 @@ |
|||
<nz-card [nzBordered]="false"> |
|||
<form nz-form class="w-[800px]" [formGroup]="formGroup" (ngSubmit)="onSubmit()"> |
|||
<nz-form-item> |
|||
<nz-form-label nzRequired nzSpan="4"> 角色名称 </nz-form-label> |
|||
<nz-form-control> |
|||
<input nz-input placeholder="请输入角色名称" formControlName="roleName" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
|
|||
<nz-form-item> |
|||
<nz-form-label nzRequired nzSpan="4"> 权限 </nz-form-label> |
|||
<nz-form-control> |
|||
<nz-spin [nzSpinning]="permissionsLoading"> |
|||
<div class="bordered min-h-[20px]"> |
|||
<ul class="permissions"> |
|||
@for (p of permissions; track $index) { |
|||
<li> |
|||
<div |
|||
nz-checkbox |
|||
[nzChecked]="checked.has(p.id)" |
|||
(nzCheckedChange)="onPermissionChange($event, p.id)" |
|||
[nzValue]="p.id" |
|||
> |
|||
{{ p.name }} |
|||
</div> |
|||
</li> |
|||
} |
|||
</ul> |
|||
<!-- <nz-collapse nzGhost> |
|||
@for (item of permissions; track $index) { |
|||
<nz-collapse-panel [nzHeader]="item.name" [nzExtra]="nzExtraTpl"> |
|||
<ng-template #nzExtraTpl> |
|||
<label |
|||
nz-checkbox |
|||
[nzIndeterminate]="checkedAll.get(item.id)?.nzIndeterminate" |
|||
[nzChecked]="checkedAll.get(item.id)?.nzChecked" |
|||
(click)="$event.stopPropagation()" |
|||
(nzCheckedChange)="checkAllChange($event, item)" |
|||
> |
|||
全选 |
|||
</label> |
|||
</ng-template> |
|||
<div nz-row [nzGutter]="[12, 12]"> |
|||
@for (p of item.children; track $index) { |
|||
<div nz-col nzSpan="8"> |
|||
<label |
|||
nz-checkbox |
|||
[nzChecked]="checked.has(p.id)" |
|||
[nzValue]="p.id" |
|||
(nzCheckedChange)="onPermissionChange($event, p.id, item)" |
|||
> |
|||
{{ p.name }} |
|||
</label> |
|||
</div> |
|||
} @empty { |
|||
<div nz-col nzSpan="24"> |
|||
<nz-empty></nz-empty> |
|||
</div> |
|||
} |
|||
</div> |
|||
</nz-collapse-panel> |
|||
} |
|||
</nz-collapse> --> |
|||
</div> |
|||
</nz-spin> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4"> 说明 </nz-form-label> |
|||
<nz-form-control> |
|||
<textarea nz-input formControlName="remark" placeholder="请输入说明"></textarea> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-control nzOffset="4"> |
|||
<nz-space> |
|||
<button nz-button nzType="primary" *nzSpaceItem>保存</button> |
|||
<button nz-button *nzSpaceItem [routerLink]="['/', 'role']">取消</button> |
|||
</nz-space> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</nz-card> |
@ -1,11 +0,0 @@ |
|||
.permissions { |
|||
li { |
|||
display: flex; |
|||
padding: 8px 24px; |
|||
|
|||
&:not(:last-child) { |
|||
|
|||
border-bottom: 1px solid var(--border-color); |
|||
} |
|||
} |
|||
} |
@ -1,146 +0,0 @@ |
|||
import { finalize } from 'rxjs' |
|||
import { Component, OnInit } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { ActivatedRoute, Router } from '@angular/router' |
|||
import { ApiService } from 'app/services' |
|||
import { PermissionDTO } from 'app/services/api.dto' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { FormValidators } from 'app/utils' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
|
|||
@Component({ |
|||
selector: 'app-role-form', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './role-form.component.html', |
|||
styleUrl: './role-form.component.less', |
|||
}) |
|||
export class RoleFormComponent implements OnInit { |
|||
constructor( |
|||
private api: ApiService, |
|||
private msg: NzMessageService, |
|||
private route: ActivatedRoute, |
|||
private router: Router, |
|||
// private modal: NzModalService,
|
|||
) {} |
|||
|
|||
id: string | null = null |
|||
|
|||
permissions: PermissionDTO[] = [] |
|||
|
|||
formGroup = new FormGroup({ |
|||
roleName: new FormControl('', [FormValidators.required('请输入角色名称'), FormValidators.maxLength(30)]), |
|||
remark: new FormControl('', [FormValidators.maxLength(30)]), |
|||
}) |
|||
|
|||
checkedAll = new Map<string, { nzIndeterminate: boolean; nzChecked: boolean }>() |
|||
|
|||
checked = new Set<string>() |
|||
|
|||
permissionsLoading = false |
|||
|
|||
ngOnInit(): void { |
|||
this.getPermissions() |
|||
const id = this.route.snapshot.paramMap.get('id') |
|||
if (id && id !== 'create') { |
|||
this.id = id |
|||
this.getRoleInfo() |
|||
} |
|||
} |
|||
|
|||
getPermissions() { |
|||
this.permissionsLoading = true |
|||
this.api |
|||
.getAllPermission() |
|||
.pipe( |
|||
finalize(() => { |
|||
this.permissionsLoading = false |
|||
}), |
|||
) |
|||
.subscribe((res) => { |
|||
this.permissions = res.data |
|||
this.updateCheckedAll() |
|||
}) |
|||
} |
|||
|
|||
getRoleInfo() { |
|||
this.api.getRoleById(this.id!).subscribe((res) => { |
|||
this.formGroup.patchValue(res.data) |
|||
this.checked = new Set(res.data.authorityId) |
|||
this.updateCheckedAll() |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 权限之间的联动 |
|||
*/ |
|||
roleLinkage = new Map<string, string[]>([ |
|||
// ['2', ['2', '9', '15']],
|
|||
// ['9', ['2', '9', '15']],
|
|||
// ['15', ['2', '9', '15']],
|
|||
// ['20', ['20', '25']],
|
|||
// ['25', ['20', '25']],
|
|||
]) |
|||
|
|||
onPermissionChange(checked: boolean, id: string) { |
|||
const checkedIds = this.roleLinkage.get(id) ?? [id] |
|||
checkedIds.forEach((i) => { |
|||
if (checked) { |
|||
this.checked.add(i) |
|||
} else { |
|||
this.checked.delete(i) |
|||
} |
|||
}) |
|||
this.updateCheckedAll() |
|||
} |
|||
|
|||
checkAllChange(checked: boolean, p: PermissionDTO) { |
|||
p.children?.forEach((permission) => { |
|||
if (checked) { |
|||
this.checked.add(permission.id) |
|||
} else { |
|||
this.checked.delete(permission.id) |
|||
} |
|||
}) |
|||
this.updateCheckedAll() |
|||
} |
|||
|
|||
updateCheckedAll() { |
|||
this.permissions.forEach((g) => { |
|||
let nzChecked = true |
|||
let nzIndeterminate = false |
|||
g.children?.forEach((permission) => { |
|||
if (this.checked.has(permission.id)) { |
|||
nzIndeterminate = true |
|||
} else { |
|||
nzChecked = false |
|||
} |
|||
}) |
|||
this.checkedAll.set(g.id, { |
|||
nzChecked, |
|||
nzIndeterminate: nzChecked ? false : nzIndeterminate, |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
onSubmit() { |
|||
if (FormValidators.validateFormGroup(this.formGroup)) { |
|||
if (this.checked.size === 0) { |
|||
this.msg.error('请选择权限') |
|||
return |
|||
} |
|||
const { value } = this.formGroup |
|||
this.api |
|||
.saveRole({ |
|||
id: this.id, |
|||
roleName: value.roleName!, |
|||
remark: value.remark as string, |
|||
authorityId: Array.from(this.checked), |
|||
}) |
|||
.subscribe(() => { |
|||
this.msg.success('保存成功') |
|||
this.router.navigate(['/role/list']) |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -1,27 +0,0 @@ |
|||
<nz-card [nzBordered]="false"> |
|||
<app-server-paginated-table [options]="tableOption" [formGroup]="queryForm"> |
|||
<div *appTableAction class="flex items-center justify-between"> |
|||
<div class="flex-1"> |
|||
<nz-space> |
|||
<button |
|||
nz-button |
|||
nzType="primary" |
|||
type="button" |
|||
[routerLink]="['/', 'role', 'form', 'create']" |
|||
*nzSpaceItem |
|||
> |
|||
添加角色 |
|||
</button> |
|||
</nz-space> |
|||
</div> |
|||
<!-- <div> |
|||
<nz-input-group nzSearch [nzSuffix]="suffixIconSearch"> |
|||
<input type="text" nz-input placeholder="请输入角色名称" formControlName="roleName" /> |
|||
</nz-input-group> |
|||
<ng-template #suffixIconSearch> |
|||
<span nz-icon nzType="search"></span> |
|||
</ng-template> |
|||
</div> --> |
|||
</div> |
|||
</app-server-paginated-table> |
|||
</nz-card> |
@ -1,72 +0,0 @@ |
|||
import { lastValueFrom } from 'rxjs' |
|||
import { Component, OnInit } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { Router } from '@angular/router' |
|||
import { TableOption } from 'app/components/server-paginated-table' |
|||
import { ApiService } from 'app/services' |
|||
import { RoleListDTO } from 'app/services/api.dto' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
|
|||
@Component({ |
|||
selector: 'app-role-list', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './role-list.component.html', |
|||
styleUrl: './role-list.component.less', |
|||
}) |
|||
export class RoleListComponent implements OnInit { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private router: Router, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
tableOption = new TableOption(this.fetchData.bind(this)) |
|||
|
|||
queryForm = new FormGroup({ |
|||
roleName: new FormControl(), |
|||
}) |
|||
|
|||
permissions = [] |
|||
|
|||
ngOnInit(): void { |
|||
this.initTable() |
|||
} |
|||
|
|||
initTable() { |
|||
this.tableOption |
|||
.setColumn([ |
|||
{ key: 'roleName', title: '角色名称' }, |
|||
{ key: 'remark', title: '说明' }, |
|||
{ key: 'createTime', title: '创建时间' }, |
|||
]) |
|||
.setRowOperate([ |
|||
{ title: '编辑', onClick: this.edit.bind(this), visible: (v) => v.id !== '1' }, |
|||
{ title: '删除', onClick: this.deleteItem.bind(this), visible: (v) => v.id !== '1' }, |
|||
]) |
|||
} |
|||
|
|||
fetchData(p: {}, q: {}) { |
|||
return this.api.getRolePage(p, q) |
|||
} |
|||
|
|||
edit(role: RoleListDTO) { |
|||
this.router.navigate(['/', 'role', 'form', role.id]) |
|||
} |
|||
|
|||
deleteItem(role: RoleListDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要删除该角色?', |
|||
nzOkDanger: true, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.deleteRole(role.id)) |
|||
this.msg.success('删除成功') |
|||
this.tableOption.ref?.reload() |
|||
}, |
|||
}) |
|||
} |
|||
} |
@ -1,63 +0,0 @@ |
|||
<div nz-row nzGutter="12"> |
|||
<div nz-col nzSpan="6"> |
|||
<nz-card [nzBordered]="false"> |
|||
<div> |
|||
<nz-statistic [nzValue]="counter.totalClient" [nzTitle]="'今日预约'"></nz-statistic> |
|||
</div> |
|||
</nz-card> |
|||
</div> |
|||
<div nz-col nzSpan="18"> |
|||
<nz-card [nzBordered]="false"> |
|||
<div nz-row nzGutter="24"> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-statistic [nzValue]="counter.totalClient" [nzTitle]="'会员'"></nz-statistic> |
|||
</div> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-statistic [nzValue]="counter.totalProduct" [nzTitle]="'会员卡'"></nz-statistic> |
|||
</div> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-statistic [nzValue]="counter.totalLicense" [nzTitle]="'教练'"></nz-statistic> |
|||
</div> |
|||
</div> |
|||
</nz-card> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="mt-4"> |
|||
<nz-card [nzBordered]="false" nzTitle="近30天办卡"> |
|||
<div class="h-80" #chart1Tpl></div> |
|||
</nz-card> |
|||
</div> |
|||
|
|||
<div class="mt-4 mb-4"> |
|||
<nz-card [nzBordered]="false" nzTitle="近30天到期会员"> |
|||
<nz-table nzTemplateMode nzSize="small" [nzBordered]="true"> |
|||
<thead> |
|||
<tr> |
|||
<th>实体</th> |
|||
<th>产品</th> |
|||
<!-- <th>版本</th> --> |
|||
<th>到期时间</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
@for (p of expiringSoon; track $index) { |
|||
<tr> |
|||
<td>{{ p.clientName }}</td> |
|||
<td>{{ p.productName }}</td> |
|||
<!-- <td></td> --> |
|||
<td> |
|||
{{ p.endTime * 1000 | date: 'yyyy-MM-dd HH:mm:ss' }} |
|||
</td> |
|||
</tr> |
|||
} @empty { |
|||
<tr> |
|||
<td [colSpan]="4"> |
|||
<nz-empty nzNotFoundContent="没有近30天到期的授权"></nz-empty> |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</nz-table> |
|||
</nz-card> |
|||
</div> |
@ -1,195 +0,0 @@ |
|||
import { AfterViewInit, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core' |
|||
import { init, EChartsType } from 'echarts' |
|||
import { SharedModule } from '../../shared/shared.module' |
|||
import { ApiService } from 'app/services' |
|||
import { ConsoleClientTopDTO, ConsoleCountDTO, ConsoleExpireDTO } from 'app/services/api.dto' |
|||
|
|||
const antvColor = [ |
|||
'#5B8FF9', |
|||
'#61DDAA', |
|||
'#65789B', |
|||
'#F6BD16', |
|||
'#7262FD', |
|||
'#78D3F8', |
|||
'#9661BC', |
|||
'#F6903D', |
|||
'#008685', |
|||
'#F08BB4', |
|||
] |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
selector: 'app-dashboard', |
|||
templateUrl: './dashboard.component.html', |
|||
styleUrls: ['./dashboard.component.less'], |
|||
}) |
|||
export class DashboardComponent implements OnInit, AfterViewInit { |
|||
constructor(private api: ApiService) {} |
|||
|
|||
@ViewChild('chart1Tpl') chart1!: ElementRef<HTMLDivElement> |
|||
|
|||
@ViewChild('chart2Tpl') chart2!: ElementRef<HTMLDivElement> |
|||
|
|||
echartRef1?: EChartsType |
|||
|
|||
echartRef2?: EChartsType |
|||
|
|||
counter: ConsoleCountDTO = { totalClient: 0, totalLicense: 0, totalProduct: 0 } |
|||
|
|||
expiringSoon: ConsoleExpireDTO[] = [] |
|||
|
|||
clientTopTen: ConsoleClientTopDTO[] = [] |
|||
|
|||
@HostListener('window:resize') |
|||
onResize() { |
|||
// this.echartRef1?.resize();
|
|||
this.echartRef2?.resize() |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
// this.api.getDashboardCounter().subscribe((res) => {
|
|||
// this.counter = res.data
|
|||
// })
|
|||
// this.api.getDashboardExpire().subscribe((res) => {
|
|||
// this.expiringSoon = res.data
|
|||
// })
|
|||
// this.api.getDashboardClientTop().subscribe((res) => {
|
|||
// this.clientTopTen = res.data
|
|||
// this.initChart2()
|
|||
// })
|
|||
} |
|||
|
|||
ngAfterViewInit(): void { |
|||
// this.initChart1();
|
|||
} |
|||
|
|||
initChart1() { |
|||
const el = this.chart1.nativeElement |
|||
if (el) { |
|||
this.echartRef1 = init(el) |
|||
this.echartRef1.setOption({ |
|||
color: antvColor, |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
axisPointer: { |
|||
type: 'cross', |
|||
label: { |
|||
backgroundColor: '#6a7985', |
|||
}, |
|||
}, |
|||
}, |
|||
legend: { |
|||
data: ['晶未智慧安全平台', 'NG-WAF', 'DLP', 'API'], |
|||
}, |
|||
|
|||
grid: { |
|||
left: '10px', |
|||
right: '10px', |
|||
bottom: '3%', |
|||
containLabel: true, |
|||
}, |
|||
xAxis: [ |
|||
{ |
|||
type: 'category', |
|||
boundaryGap: false, |
|||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
|||
}, |
|||
], |
|||
yAxis: [ |
|||
{ |
|||
type: 'value', |
|||
}, |
|||
], |
|||
series: [ |
|||
{ |
|||
name: '晶未智慧安全平台', |
|||
type: 'line', |
|||
smooth: true, |
|||
areaStyle: { |
|||
opacity: 0.2, |
|||
}, |
|||
emphasis: { |
|||
focus: 'series', |
|||
}, |
|||
data: [620, 332, 401, 534, 190, 330, 410], |
|||
}, |
|||
{ |
|||
name: 'NG-WAF', |
|||
type: 'line', |
|||
smooth: true, |
|||
areaStyle: { |
|||
opacity: 0.2, |
|||
}, |
|||
emphasis: { |
|||
focus: 'series', |
|||
}, |
|||
data: [220, 182, 191, 234, 290, 330, 310], |
|||
}, |
|||
{ |
|||
name: 'API', |
|||
type: 'line', |
|||
smooth: true, |
|||
areaStyle: { |
|||
opacity: 0.2, |
|||
}, |
|||
emphasis: { |
|||
focus: 'series', |
|||
}, |
|||
data: [55, 612, 491, 34, 90, 200, 411], |
|||
}, |
|||
{ |
|||
name: 'DLP', |
|||
type: 'line', |
|||
smooth: true, |
|||
areaStyle: { |
|||
opacity: 0.2, |
|||
}, |
|||
emphasis: { |
|||
focus: 'series', |
|||
}, |
|||
data: [20, 162, 291, 134, 390, 300, 10], |
|||
}, |
|||
], |
|||
}) |
|||
} |
|||
} |
|||
initChart2() { |
|||
const el = this.chart2.nativeElement |
|||
if (el) { |
|||
this.echartRef2 = init(el) |
|||
this.echartRef2.setOption({ |
|||
color: antvColor, |
|||
tooltip: { |
|||
trigger: 'axis', |
|||
axisPointer: { |
|||
type: 'cross', |
|||
label: { |
|||
backgroundColor: '#6a7985', |
|||
}, |
|||
}, |
|||
}, |
|||
|
|||
grid: { |
|||
left: '10px', |
|||
right: '10px', |
|||
bottom: '3%', |
|||
containLabel: true, |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
data: this.clientTopTen.map((i) => i.clientName), |
|||
}, |
|||
yAxis: { |
|||
type: 'value', |
|||
}, |
|||
series: [ |
|||
{ |
|||
data: this.clientTopTen.map((i) => i.count), |
|||
type: 'bar', |
|||
}, |
|||
], |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -1,101 +0,0 @@ |
|||
@if (entity) { |
|||
<div class="mb-4"> |
|||
<nz-card [nzBordered]="false" nzTitle="实体详情" [nzExtra]="nzExtraTpl"> |
|||
<ng-template #nzExtraTpl> |
|||
<nz-space> |
|||
<button *nzSpaceItem nz-button [routerLink]="['/', 'entity']">返回</button> |
|||
</nz-space> |
|||
</ng-template> |
|||
|
|||
<nz-descriptions [nzColumn]="3" class="ml-16"> |
|||
<nz-descriptions-item nzTitle="实体名称"> |
|||
{{ entity.name }} |
|||
</nz-descriptions-item> |
|||
<nz-descriptions-item nzTitle="联系方式"> |
|||
{{ entity.contact ?? '-' }} |
|||
</nz-descriptions-item> |
|||
<!-- <nz-descriptions-item nzTitle="地址"> |
|||
{{ entity.address ?? '-' }} |
|||
</nz-descriptions-item> --> |
|||
<nz-descriptions-item nzTitle="说明">{{ entity.remark || '-' }}</nz-descriptions-item> |
|||
</nz-descriptions> |
|||
</nz-card> |
|||
</div> |
|||
} |
|||
|
|||
<div class="mb-4"> |
|||
<nz-card [nzBordered]="false" nzTitle="授权记录" [nzExtra]="licenseExtraTpl"> |
|||
<ng-template #licenseExtraTpl> |
|||
<nz-space> |
|||
<button *nzSpaceItem nz-button nzType="primary" (click)="authorize()">新增授权</button> |
|||
</nz-space> |
|||
</ng-template> |
|||
<div> |
|||
<div class="mb-3"> |
|||
<nz-space nzAlign="center"> |
|||
<div *nzSpaceItem>状态:</div> |
|||
<div *nzSpaceItem> |
|||
<nz-select |
|||
nzPlaceHolder="请选择状态" |
|||
class="w-64" |
|||
[(ngModel)]="status" |
|||
(ngModelChange)="onStatusChange()" |
|||
> |
|||
<nz-option [nzValue]="-1" nzLabel="全部"></nz-option> |
|||
<nz-option [nzValue]="0" nzLabel="无效"></nz-option> |
|||
<nz-option [nzValue]="1" nzLabel="生效中"></nz-option> |
|||
</nz-select> |
|||
</div> |
|||
</nz-space> |
|||
</div> |
|||
<nz-table #table [nzData]="visibleList" [nzShowPagination]="false"> |
|||
<thead> |
|||
<tr> |
|||
<th>授权产品</th> |
|||
<th>操作人</th> |
|||
<th>生效时间</th> |
|||
<th>失效时间</th> |
|||
<th>状态</th> |
|||
<th>创建时间</th> |
|||
<th>操作</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
@for (item of table.data; track $index) { |
|||
<tr> |
|||
<td> |
|||
{{ item.productName }} |
|||
</td> |
|||
<td> |
|||
{{ item.username }} |
|||
</td> |
|||
<td> |
|||
{{ item.startTime * 1000 | date: 'yyyy-MM-dd HH:mm:ss' }} |
|||
</td> |
|||
<td> |
|||
{{ item.endTime ? (item.endTime * 1000 | date: 'yyyy-MM-dd HH:mm:ss') : '永久' }} |
|||
</td> |
|||
<td> |
|||
@if (item.status) { |
|||
<nz-badge nzStatus="processing" nzText="生效中"> </nz-badge> |
|||
} @else { |
|||
<nz-badge nzStatus="default" nzText="无效"></nz-badge> |
|||
} |
|||
</td> |
|||
<td> |
|||
{{ item.createTime }} |
|||
</td> |
|||
<td> |
|||
<nz-space> |
|||
<button *nzSpaceItem nz-button nzType="link" (click)="copy(item.license)"> |
|||
复制授权码 |
|||
</button> |
|||
</nz-space> |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</nz-table> |
|||
</div> |
|||
</nz-card> |
|||
</div> |
@ -1,105 +0,0 @@ |
|||
import { Component, OnInit } from '@angular/core' |
|||
import { ActivatedRoute } from '@angular/router' |
|||
import { ApiService } from 'app/services' |
|||
import { AuthorizeItemDTO, EntityDTO, EntityDetailDTO } from 'app/services/api.dto' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { Clipboard } from '@angular/cdk/clipboard' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { AuthorizeComponent } from 'app/components/authorize/authorize.component' |
|||
|
|||
@Component({ |
|||
selector: 'app-entity-detail', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './entity-detail.component.html', |
|||
styleUrl: './entity-detail.component.less', |
|||
}) |
|||
export class EntityDetailComponent implements OnInit { |
|||
constructor( |
|||
private api: ApiService, |
|||
private route: ActivatedRoute, |
|||
private clipboard: Clipboard, |
|||
private msg: NzMessageService, |
|||
private modal: NzModalService, |
|||
) {} |
|||
|
|||
entity?: EntityDetailDTO |
|||
|
|||
authorizeData: AuthorizeItemDTO[] = [] |
|||
|
|||
visibleList: AuthorizeItemDTO[] = [] |
|||
|
|||
product: { id: string; name: string }[] = [] |
|||
|
|||
id: string = '' |
|||
|
|||
status = -1 |
|||
|
|||
ngOnInit(): void { |
|||
const id = this.route.snapshot.paramMap.get('id') |
|||
if (id) { |
|||
this.id = id |
|||
this.api.getEntityDetail(id).subscribe((res) => { |
|||
this.entity = res.data |
|||
}) |
|||
this.getEntityAuthorizeList() |
|||
} |
|||
this.api.getAllProduct().subscribe((res) => { |
|||
this.product = res.data |
|||
}) |
|||
} |
|||
|
|||
getEntityAuthorizeList() { |
|||
this.api.getEntityAuthorizeList(this.id).subscribe((res) => { |
|||
this.authorizeData = res.data.map((i) => ({ |
|||
...i, |
|||
status: this.between(i.startTime, i.endTime) ? 1 : 0, |
|||
})) |
|||
this.onStatusChange() |
|||
}) |
|||
} |
|||
|
|||
onStatusChange() { |
|||
this.visibleList = this.authorizeData.filter((f) => (this.status === -1 ? true : f.status === this.status)) |
|||
} |
|||
|
|||
copy(license: string) { |
|||
const pending = this.clipboard.beginCopy(license) |
|||
let remainingAttempts = 3 |
|||
const attempt = () => { |
|||
const result = pending.copy() |
|||
if (!result && --remainingAttempts) { |
|||
setTimeout(attempt) |
|||
} else { |
|||
this.msg.success('复制成功') |
|||
pending.destroy() |
|||
} |
|||
} |
|||
attempt() |
|||
} |
|||
|
|||
between(start: number, end: number): boolean { |
|||
if (end === 0) { |
|||
return true |
|||
} |
|||
const now = Date.now() |
|||
return start * 1000 <= now && now <= end * 1000 |
|||
} |
|||
|
|||
authorize() { |
|||
const ref = this.modal.create({ |
|||
nzTitle: '添加授权', |
|||
nzContent: AuthorizeComponent, |
|||
nzWidth: 800, |
|||
nzData: { |
|||
product: this.product, |
|||
entity: this.entity, |
|||
}, |
|||
nzFooter: null, |
|||
}) |
|||
ref.afterClose.subscribe(() => { |
|||
this.getEntityAuthorizeList() |
|||
}) |
|||
} |
|||
} |
@ -1,83 +0,0 @@ |
|||
<nz-card [nzBordered]="false"> |
|||
<app-server-paginated-table |
|||
#tableTpl |
|||
[renderColumn]="renderColumnsTpl" |
|||
[formGroup]="queryForm" |
|||
[simpleSearch]="true" |
|||
[options]="table" |
|||
> |
|||
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row"> |
|||
@switch (key) { |
|||
@case ('name') { |
|||
<a [routerLink]="['/', 'entity', row.id, 'detail']">{{ data }}</a> |
|||
} |
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
|
|||
<div *appTableForm nz-row [nzGutter]="[24, 24]"> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px"> 实体名称 </nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<input nz-input placeholder="请输入实体名称" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
<div nz-col nzSpan="12"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px"> 创建时间 </nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<!-- <nz-range-picker nzShowTime formControlName="createTime"></nz-range-picker> --> |
|||
<app-range-picker [showTime]="true" formControlName="createTime"></app-range-picker> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
</div> |
|||
<div *appTableAction class="flex"> |
|||
<div> |
|||
<nz-space> |
|||
<button *nzSpaceItem nzType="primary" nz-button (click)="create()">添加实体</button> |
|||
</nz-space> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- <div action>Custom Modal action</div> --> |
|||
</app-server-paginated-table> |
|||
</nz-card> |
|||
|
|||
<ng-template #entityFormTpl> |
|||
<form [formGroup]="createForm" nz-form [nzLayout]="'vertical'"> |
|||
<nz-form-item> |
|||
<nz-form-label nzRequired> 实体名称 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入实体名称" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
|
|||
<nz-form-item> |
|||
<nz-form-label> 联系方式 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入联系方式" formControlName="contact" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<!-- <nz-form-item> |
|||
<nz-form-label> 地址 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入地址" formControlName="address" /> |
|||
</nz-form-control> |
|||
</nz-form-item> --> |
|||
<nz-form-item> |
|||
<nz-form-label> 说明 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<textarea nz-input placeholder="请输入说明" formControlName="remark"></textarea> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #formErrorTipsTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
@ -1,132 +0,0 @@ |
|||
import { Component, ElementRef, OnInit, TemplateRef, ViewChild } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { ApiService } from 'app/services' |
|||
import { AnyObject, ServerPaginatedTableComponent, TableOption } from 'app/components/server-paginated-table' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { FormValidators } from 'app/utils' |
|||
import { lastValueFrom } from 'rxjs' |
|||
import { EntityDTO, ProductDTO } from 'app/services/api.dto' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { format } from 'date-fns' |
|||
import { AuthorizeComponent } from 'app/components/authorize/authorize.component' |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
selector: 'app-entity-list', |
|||
templateUrl: './entity-list.component.html', |
|||
styleUrls: ['./entity-list.component.less'], |
|||
}) |
|||
export class EntityListComponent implements OnInit { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
@ViewChild('entityFormTpl') entityFormTpl!: TemplateRef<{}> |
|||
|
|||
table = new TableOption(this.fetchData.bind(this), [{ key: 'name', title: '实体名称' }], [], { |
|||
cacheUrls: ['/dashboard'], |
|||
}) |
|||
|
|||
queryForm = new FormGroup({ |
|||
name: new FormControl(''), |
|||
createTime: new FormControl(), |
|||
}) |
|||
|
|||
createForm = new FormGroup({ |
|||
name: new FormControl('', [FormValidators.required('请输入实体名称'), FormValidators.maxLength(30)]), |
|||
// secretKey: new FormControl('', [FormValidators.required('请输入序列号')]),
|
|||
contact: new FormControl('', FormValidators.maxLength(30)), |
|||
// address: new FormControl('', FormValidators.maxLength(200)),
|
|||
remark: new FormControl('', FormValidators.maxLength(200)), |
|||
}) |
|||
|
|||
product: { id: string; name: string }[] = [] |
|||
|
|||
ngOnInit(): void { |
|||
this.table |
|||
.setColumn([ |
|||
{ key: 'name', title: '实体名称' }, |
|||
{ key: 'contact', title: '联系方式' }, |
|||
// { key: 'address', title: '地址' },
|
|||
{ key: 'remark', title: '说明' }, |
|||
{ key: 'createTime', title: '创建时间' }, |
|||
]) |
|||
.setRowOperate([ |
|||
{ title: '添加授权', premissions: [], onClick: this.authorize.bind(this) }, |
|||
{ title: '编辑', onClick: this.create.bind(this) }, |
|||
{ title: '删除', onClick: this.deleteItem.bind(this) }, |
|||
]) |
|||
this.api.getAllProduct().subscribe((res) => { |
|||
this.product = res.data |
|||
}) |
|||
} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
if (Array.isArray(q['createTime'])) { |
|||
const createTimeStart = q['createTime']?.[0] |
|||
const createTimeEnd = q['createTime']?.[1] |
|||
|
|||
q['createTimeStart'] = createTimeStart ? format(new Date(createTimeStart), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
q['createTimeEnd'] = createTimeEnd ? format(new Date(createTimeEnd), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
} |
|||
return this.api.getEntityPage(p, q) |
|||
} |
|||
|
|||
onSearch() {} |
|||
|
|||
authorize(v: EntityDTO) { |
|||
this.modal.create({ |
|||
nzTitle: '添加授权', |
|||
nzContent: AuthorizeComponent, |
|||
nzWidth: 800, |
|||
nzData: { |
|||
product: this.product, |
|||
entity: v, |
|||
}, |
|||
nzFooter: null, |
|||
}) |
|||
} |
|||
|
|||
create(entity?: EntityDTO) { |
|||
if (entity) { |
|||
this.createForm.patchValue(entity) |
|||
this.createForm.get('secretKey')?.disable() |
|||
} else { |
|||
this.createForm.get('secretKey')?.enable() |
|||
} |
|||
this.modal.create({ |
|||
nzTitle: entity ? '编辑实体' : '添加实体', |
|||
nzContent: this.entityFormTpl, |
|||
nzOnOk: async () => { |
|||
if (FormValidators.validateFormGroup(this.createForm)) { |
|||
await lastValueFrom(this.api.saveEntity({ ...(entity ?? {}), ...this.createForm.value })) |
|||
this.msg.success('保存成功') |
|||
this.table.ref?.reload() |
|||
this.createForm.reset() |
|||
return true |
|||
} |
|||
return false |
|||
}, |
|||
nzOnCancel: () => { |
|||
this.createForm.reset() |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
deleteItem(entity: EntityDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要删除该实体?', |
|||
nzOkDanger: true, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.deleteEntity(entity.id)) |
|||
this.msg.success('删除成功') |
|||
this.table.ref?.reload() |
|||
}, |
|||
}) |
|||
} |
|||
} |
@ -1,5 +0,0 @@ |
|||
<nz-card [nzBordered]="false" class="h-screen"> |
|||
<div class="flex items-center justify-center"> |
|||
<nz-result nzStatus="403"></nz-result> |
|||
</div> |
|||
</nz-card> |
@ -1,11 +0,0 @@ |
|||
import { Component } from '@angular/core' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
|
|||
@Component({ |
|||
selector: 'app-forbidden', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './forbidden.component.html', |
|||
styleUrl: './forbidden.component.less', |
|||
}) |
|||
export class ForbiddenComponent {} |
@ -1,82 +0,0 @@ |
|||
<nz-card [nzBordered]="false"> |
|||
<app-server-paginated-table |
|||
#tableTpl |
|||
[options]="tableOption" |
|||
[formGroup]="queryForm" |
|||
[simpleSearch]="false" |
|||
[renderColumn]="renderColumnsTpl" |
|||
> |
|||
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row"> |
|||
@switch (key) { |
|||
@case ('content') { |
|||
<span> |
|||
@switch (row.operation) { |
|||
@case ('insert') { |
|||
<nz-tag nzColor="success">新增</nz-tag> |
|||
} |
|||
@case ('update') { |
|||
<nz-tag nzColor="blue">编辑</nz-tag> |
|||
} |
|||
@case ('delete') { |
|||
<nz-tag nzColor="error">删除</nz-tag> |
|||
} |
|||
@case ('login') { |
|||
<nz-tag nzColor="gold">登录</nz-tag> |
|||
} |
|||
} |
|||
</span> |
|||
<span> {{ data }} </span> |
|||
} |
|||
|
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
<div *appTableForm nz-row [nzGutter]="[24, 24]"> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="6"> 操作人 </nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<input nz-input placeholder="请输入操作人" formControlName="username" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
|
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="6"> 操作类型 </nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<nz-select nzPlaceHolder="请选择操作类型" formControlName="operation" nzAllowClear> |
|||
<nz-option [nzValue]="'insert'" [nzLabel]="'新增'"></nz-option> |
|||
<nz-option [nzValue]="'update'" [nzLabel]="'编辑'"></nz-option> |
|||
<nz-option [nzValue]="'delete'" [nzLabel]="'删除'"></nz-option> |
|||
<nz-option [nzValue]="'login'" [nzLabel]="'登录'"></nz-option> |
|||
</nz-select> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
|
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="6"> 操作内容 </nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<input nz-input placeholder="请输入操作内容" formControlName="content" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
|
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="6"> 创建时间 </nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<!-- <nz-range-picker class="w-full" formControlName="createTime"></nz-range-picker> --> |
|||
<app-range-picker [showTime]="true" formControlName="createTime"></app-range-picker> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
</div> |
|||
</app-server-paginated-table> |
|||
</nz-card> |
|||
|
|||
<ng-template #createTpl> </ng-template> |
@ -1,87 +0,0 @@ |
|||
import { AfterViewInit, Component, ElementRef, OnInit, TemplateRef, ViewChild } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { ApiService } from 'app/services/api.service' |
|||
import { |
|||
AnyObject, |
|||
ServerPaginatedTableComponent, |
|||
ServerPaginatedTableService, |
|||
TableOption, |
|||
} from 'app/components/server-paginated-table' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { format } from 'date-fns' |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
selector: 'app-log', |
|||
templateUrl: './log.component.html', |
|||
styleUrls: ['./log.component.less'], |
|||
}) |
|||
export class LogComponent implements OnInit, AfterViewInit { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private table: ServerPaginatedTableService, |
|||
) {} |
|||
|
|||
@ViewChild('shadowLineTpl') shadowLineRef!: ElementRef<HTMLCanvasElement> |
|||
|
|||
tableOption = new TableOption(this.fetchData.bind(this)) |
|||
|
|||
queryForm = new FormGroup({ |
|||
operation: new FormControl(), |
|||
username: new FormControl(), |
|||
content: new FormControl(), |
|||
|
|||
createTime: new FormControl(), |
|||
}) |
|||
|
|||
ngOnInit(): void { |
|||
// this.table.run();
|
|||
this.tableOption.setConfig({ |
|||
cacheUrls: ['/dashboard'], |
|||
}) |
|||
this.tableOption.setColumn([ |
|||
{ |
|||
key: 'username', |
|||
title: '操作人', |
|||
}, |
|||
{ |
|||
key: 'content', |
|||
title: '操作内容', |
|||
}, |
|||
|
|||
{ |
|||
key: 'createTime', |
|||
title: '创建时间', |
|||
}, |
|||
]) |
|||
} |
|||
|
|||
ngAfterViewInit(): void {} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
if (Array.isArray(q['createTime'])) { |
|||
const createTimeStart = q['createTime']?.[0] |
|||
const createTimeEnd = q['createTime']?.[1] |
|||
|
|||
q['createTimeStart'] = createTimeStart ? format(new Date(createTimeStart), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
q['createTimeEnd'] = createTimeEnd ? format(new Date(createTimeEnd), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
} |
|||
return this.api.getSysLog(p, q) |
|||
} |
|||
|
|||
create(nzContent: TemplateRef<{}>) { |
|||
this.modal.create({ |
|||
nzTitle: '添加授权', |
|||
nzContent, |
|||
nzWidth: 720, |
|||
nzOnOk: async () => { |
|||
this.tableOption.ref?.reload() |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
onSearch() {} |
|||
} |
@ -1,54 +0,0 @@ |
|||
<div class="flex items-center justify-center fixed inset-0 z-10 login-page"> |
|||
<div class="bg fixed inset-0"></div> |
|||
<div class="w-[450px] relative z-10 login-form p-8 bg-white rounded-md shadow-2xl"> |
|||
<div class="px-4"> |
|||
<div class="text-center"> |
|||
<h1>Back to sea</h1> |
|||
<p class="text-lg mb-6">登录</p> |
|||
</div> |
|||
<form nz-form [formGroup]="loginForm" class="mt-12"> |
|||
<nz-form-item> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<nz-input-group [nzPrefix]="prefixTemplateUser" nzSize="large"> |
|||
<input nz-input nzSize="large" placeholder="用户名" formControlName="username" /> |
|||
</nz-input-group> |
|||
<ng-template #prefixTemplateUser> |
|||
<span nz-icon nzType="user"></span> |
|||
<nz-divider nzType="vertical"></nz-divider> |
|||
</ng-template> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<nz-input-group [nzPrefix]="prefixTemplatePassword" nzSize="large"> |
|||
<input nz-input type="password" placeholder="密码" formControlName="password" /> |
|||
</nz-input-group> |
|||
<ng-template #prefixTemplatePassword> |
|||
<span nz-icon nzType="lock"></span> |
|||
<nz-divider nzType="vertical"></nz-divider> |
|||
</ng-template> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-control> |
|||
<button |
|||
nz-button |
|||
nzType="primary" |
|||
nzBlock |
|||
class="btn" |
|||
nzSize="large" |
|||
(click)="onLogin()" |
|||
[nzLoading]="loading" |
|||
> |
|||
登录 |
|||
</button> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<ng-template #formErrorTipsTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
@ -1,20 +0,0 @@ |
|||
.login-page { |
|||
|
|||
|
|||
.bg { |
|||
background-image: url(/assets/images/login-bg.jpg); |
|||
background-repeat: no-repeat; |
|||
background-size: cover; |
|||
filter: blur(1px); |
|||
} |
|||
|
|||
|
|||
|
|||
.login-form { |
|||
|
|||
background-color: #fff; |
|||
background-color: rgba(255, 255, 255, .7); |
|||
-webkit-backdrop-filter: blur(10px); |
|||
backdrop-filter: blur(10px); |
|||
} |
|||
} |
@ -1,54 +0,0 @@ |
|||
import { Component } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { SharedModule } from '../../shared/shared.module' |
|||
import { FormValidators } from 'app/utils' |
|||
import { ApiService, LocalHttpInterceptorService } from 'app/services' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { Router } from '@angular/router' |
|||
import { finalize } from 'rxjs' |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
selector: 'app-login', |
|||
templateUrl: './login.component.html', |
|||
styleUrls: ['./login.component.less'], |
|||
}) |
|||
export class LoginComponent { |
|||
constructor( |
|||
private api: ApiService, |
|||
private msg: NzMessageService, |
|||
private local: LocalHttpInterceptorService, |
|||
private router: Router, |
|||
) {} |
|||
|
|||
loading = false |
|||
|
|||
loginForm = new FormGroup({ |
|||
username: new FormControl('', [FormValidators.required('请输入用户名')]), |
|||
password: new FormControl('', [FormValidators.required('请输入密码')]), |
|||
}) |
|||
|
|||
onLogin() { |
|||
if (FormValidators.validateFormGroup(this.loginForm)) { |
|||
this.loading = true |
|||
this.router.navigate(['/']) |
|||
return |
|||
this.api |
|||
.login(this.loginForm.value) |
|||
.pipe( |
|||
finalize(() => { |
|||
this.loading = false |
|||
}), |
|||
) |
|||
.subscribe((res) => { |
|||
this.msg.success('登录成功') |
|||
this.local.setAccess({ |
|||
access_token: res.data, |
|||
}) |
|||
localStorage.setItem('add', res.data) |
|||
this.router.navigate(['/']) |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -1,5 +0,0 @@ |
|||
<nz-card [nzBordered]="false" class="h-screen"> |
|||
<div class="flex items-center justify-center"> |
|||
<nz-result nzStatus="404" nzTitle="此页面未找到。"></nz-result> |
|||
</div> |
|||
</nz-card> |
@ -1,11 +0,0 @@ |
|||
import { Component } from '@angular/core' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
|
|||
@Component({ |
|||
selector: 'app-notfound', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './notfound.component.html', |
|||
styleUrl: './notfound.component.less', |
|||
}) |
|||
export class NotfoundComponent {} |
@ -1,43 +0,0 @@ |
|||
<div> |
|||
<nz-card [nzBordered]="false" nzTitle="产品详情" [nzExtra]="nzExtraTpl"> |
|||
<ng-template #nzExtraTpl> |
|||
<nz-space> |
|||
<button *nzSpaceItem nz-button [routerLink]="['/', 'product']">返回</button> |
|||
</nz-space> |
|||
</ng-template> |
|||
|
|||
@if (detail(); as info) { |
|||
<nz-descriptions [nzColumn]="2" class="ml-16"> |
|||
<nz-descriptions-item nzTitle="产品ID"> |
|||
{{ info.productId }} |
|||
</nz-descriptions-item> |
|||
<nz-descriptions-item nzTitle="产品名称"> |
|||
{{ info.name }} |
|||
</nz-descriptions-item> |
|||
|
|||
<nz-descriptions-item nzTitle="说明">{{ info.remark || '-' }}</nz-descriptions-item> |
|||
</nz-descriptions> |
|||
} |
|||
</nz-card> |
|||
</div> |
|||
<!-- <div class="mt-4"> |
|||
<nz-card [nzBordered]="false" nzTitle="版本管理" [nzExtra]="versionExtraTpl"> |
|||
<ng-template #versionExtraTpl> |
|||
<nz-space> |
|||
<button *nzSpaceItem nz-button nzType="primary" (click)="createVersion()">添加</button> |
|||
</nz-space> |
|||
</ng-template> |
|||
<app-server-paginated-table [options]="tableOption"></app-server-paginated-table> |
|||
</nz-card> |
|||
</div> --> |
|||
|
|||
<ng-template #versionFormTpl> |
|||
<form nz-form [formGroup]="formGroup"> |
|||
<nz-form-item> |
|||
<nz-form-label nzRequired>版本号</nz-form-label> |
|||
<nz-form-control> |
|||
<input nz-input formControlName="name" placeholder="请输入版本号" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</ng-template> |
@ -1,84 +0,0 @@ |
|||
import { TemplateRef } from '@angular/core' |
|||
import { ViewChild } from '@angular/core' |
|||
import { Component, OnInit, signal, computed, effect } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { ActivatedRoute, Router } from '@angular/router' |
|||
import { TableOption } from 'app/components/server-paginated-table' |
|||
import { ApiService } from 'app/services' |
|||
import { VersionDTO } from 'app/services/api.dto' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { FormValidators } from 'app/utils' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { lastValueFrom } from 'rxjs' |
|||
|
|||
@Component({ |
|||
selector: 'app-product-detail', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './product-detail.component.html', |
|||
styleUrl: './product-detail.component.less', |
|||
}) |
|||
export class ProductDetailComponent implements OnInit { |
|||
constructor( |
|||
private api: ApiService, |
|||
private router: Router, |
|||
private route: ActivatedRoute, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
@ViewChild('versionFormTpl') versionFormTpl!: TemplateRef<{}> |
|||
|
|||
tableOption = new TableOption(this.fetchData.bind(this)) |
|||
|
|||
formGroup = new FormGroup({ |
|||
name: new FormControl('', [FormValidators.required('请输入产品版本号')]), |
|||
}) |
|||
|
|||
detail = signal({ |
|||
productId: '', |
|||
name: '', |
|||
remark: '', |
|||
}) |
|||
|
|||
id!: string |
|||
|
|||
ngOnInit(): void { |
|||
this.id = this.route.snapshot.paramMap.get('id')! |
|||
this.api.getProductDetail(this.id).subscribe((res) => { |
|||
this.detail.set(res.data) |
|||
}) |
|||
} |
|||
|
|||
fetchData(p: {}, q: {}) { |
|||
return this.api.getProductVersionPage(p, { ...q, productId: this.id }) |
|||
} |
|||
|
|||
createVersion(version?: VersionDTO) { |
|||
this.modal.create({ |
|||
nzTitle: '添加版本', |
|||
nzContent: this.versionFormTpl, |
|||
nzOnOk: async () => { |
|||
if (FormValidators.validateFormGroup(this.formGroup)) { |
|||
await lastValueFrom(this.api.saveVersion({ ...(version ?? {}), ...this.formGroup.value })) |
|||
this.msg.success('保存成功') |
|||
this.tableOption.ref?.reload() |
|||
} |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
deleteItem(v: VersionDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要删除该版本?', |
|||
nzOkDanger: true, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.deleteVersion(v.id, this.id)) |
|||
this.msg.success('删除成功') |
|||
this.tableOption.ref?.reload() |
|||
}, |
|||
}) |
|||
} |
|||
} |
@ -1,80 +0,0 @@ |
|||
<nz-card [nzBordered]="false"> |
|||
<app-server-paginated-table |
|||
#tableTpl |
|||
[renderColumn]="renderColumnsTpl" |
|||
[formGroup]="queryForm" |
|||
[simpleSearch]="true" |
|||
[options]="table" |
|||
> |
|||
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row"> |
|||
@switch (key) { |
|||
@case ('name') { |
|||
<a [routerLink]="['/', 'product', row.id, 'detail']"> |
|||
{{ data }} |
|||
</a> |
|||
} |
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
|
|||
<div *appTableForm nz-row [nzGutter]="[24, 24]"> |
|||
<div nz-col nzSpan="8"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px">产品名称</nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<input nz-input placeholder="请输入产品名称" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
<div nz-col nzSpan="12"> |
|||
<nz-form-item> |
|||
<nz-form-label nzFlex="80px">创建时间</nz-form-label> |
|||
<nz-form-control nzSpan="18"> |
|||
<!-- <nz-range-picker nzShowTime formControlName="createTime"></nz-range-picker> --> |
|||
<app-range-picker [showTime]="true" formControlName="createTime"></app-range-picker> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</div> |
|||
</div> |
|||
<div *appTableAction class="flex"> |
|||
<div> |
|||
<nz-space> |
|||
<button *nzSpaceItem nzType="primary" nz-button (click)="create()">添加产品</button> |
|||
</nz-space> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- <div action>Custom Modal action</div> --> |
|||
</app-server-paginated-table> |
|||
</nz-card> |
|||
|
|||
<ng-template #productFormTpl> |
|||
<form [formGroup]="createForm" nz-form [nzLayout]="'vertical'"> |
|||
<nz-form-item> |
|||
<nz-form-label nzRequired> 产品名称 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入产品名称" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
|
|||
<nz-form-item> |
|||
<nz-form-label nzRequired> 产品ID </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入产品ID" formControlName="productId" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
|
|||
<nz-form-item> |
|||
<nz-form-label> 产品说明 </nz-form-label> |
|||
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
|||
<textarea nz-input placeholder="请输入产品说明" formControlName="remark"></textarea> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #formErrorTipsTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
@ -1,104 +0,0 @@ |
|||
import { Component, ElementRef, OnInit, TemplateRef, ViewChild } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { ApiService } from 'app/services' |
|||
import { AnyObject, ServerPaginatedTableComponent, TableOption } from 'app/components/server-paginated-table' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
import { FormValidators } from 'app/utils' |
|||
import { lastValueFrom } from 'rxjs' |
|||
import { ProductDTO } from 'app/services/api.dto' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { format } from 'date-fns' |
|||
|
|||
@Component({ |
|||
selector: 'app-product-list', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './product-list.component.html', |
|||
styleUrl: './product-list.component.less', |
|||
}) |
|||
export class ProductListComponent { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
@ViewChild('productFormTpl') productFormTpl!: TemplateRef<{}> |
|||
|
|||
table = new TableOption( |
|||
this.fetchData.bind(this), |
|||
[ |
|||
{ key: 'name', title: '产品名称' }, |
|||
{ key: 'productId', title: '产品ID' }, |
|||
{ key: 'remark', title: '产品说明', width: '500px' }, |
|||
{ key: 'createTime', title: '创建时间' }, |
|||
], |
|||
[], |
|||
) |
|||
|
|||
queryForm = new FormGroup({ |
|||
name: new FormControl(''), |
|||
createTime: new FormControl(), |
|||
}) |
|||
|
|||
createForm = new FormGroup({ |
|||
name: new FormControl('', [FormValidators.required('请输入产品名称'), FormValidators.maxLength(30)]), |
|||
productId: new FormControl('', [FormValidators.required('请输入产品ID'), FormValidators.maxLength(30)]), |
|||
remark: new FormControl('', [FormValidators.maxLength(200)]), |
|||
}) |
|||
|
|||
ngOnInit(): void { |
|||
this.table.setRowOperate([ |
|||
{ title: '编辑', onClick: this.create.bind(this) }, |
|||
{ title: '删除', onClick: this.deleteItem.bind(this) }, |
|||
]) |
|||
} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
if (Array.isArray(q['createTime'])) { |
|||
const createTimeStart = q['createTime']?.[0] |
|||
const createTimeEnd = q['createTime']?.[1] |
|||
|
|||
q['createTimeStart'] = createTimeStart ? format(new Date(createTimeStart), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
q['createTimeEnd'] = createTimeEnd ? format(new Date(createTimeEnd), 'yyyy-MM-dd HH:mm:ss') : '' |
|||
} |
|||
return this.api.getProductPage(p, q) |
|||
} |
|||
|
|||
onSearch() {} |
|||
|
|||
create(product?: ProductDTO) { |
|||
if (product) { |
|||
this.createForm.patchValue(product) |
|||
} |
|||
this.modal.create({ |
|||
nzTitle: product ? '编辑产品' : '添加产品', |
|||
nzContent: this.productFormTpl, |
|||
nzOnOk: async () => { |
|||
if (FormValidators.validateFormGroup(this.createForm)) { |
|||
await lastValueFrom(this.api.saveProduct({ ...(product ?? {}), ...this.createForm.value })) |
|||
this.msg.success('保存成功') |
|||
this.table.ref?.reload() |
|||
this.createForm.reset() |
|||
} |
|||
}, |
|||
nzOnCancel: () => { |
|||
this.createForm.reset() |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
deleteItem(product: ProductDTO) { |
|||
this.modal.confirm({ |
|||
nzTitle: '警告', |
|||
nzContent: '是否要删除该产品?', |
|||
nzOkDanger: true, |
|||
nzOnOk: async () => { |
|||
await lastValueFrom(this.api.deleteProduct(product.id)) |
|||
this.msg.success('删除成功') |
|||
this.table.ref?.reload() |
|||
}, |
|||
}) |
|||
} |
|||
} |
@ -1,28 +0,0 @@ |
|||
<div class="w-[600px] pt-6"> |
|||
<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit()"> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4" nzRequired> 用户名 </nz-form-label> |
|||
<nz-form-control nzSpan="16"> |
|||
<input nz-input placeholder="请输入用户名" formControlName="username" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4" nzRequired> 新密码 </nz-form-label> |
|||
<nz-form-control nzSpan="16"> |
|||
<input nz-input type="password" placeholder="请输入新密码" formControlName="password" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4" nzRequired> 确认密码 </nz-form-label> |
|||
<nz-form-control nzSpan="16"> |
|||
<input nz-input type="password" placeholder="请再次输入密码" formControlName="confirmPassword" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
|
|||
<nz-form-item> |
|||
<nz-form-control nzOffset="4"> |
|||
<button nz-button nzType="primary">保存</button> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</div> |
@ -1,46 +0,0 @@ |
|||
import { Component } from '@angular/core' |
|||
import { SharedModule } from '../../shared/shared.module' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
import { FormValidators } from 'app/utils' |
|||
import { ApiService, LocalHttpInterceptorService } from 'app/services' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
selector: 'app-profile-account', |
|||
templateUrl: './profile-account.component.html', |
|||
styleUrls: ['./profile-account.component.less'], |
|||
}) |
|||
export class ProfileAccountComponent { |
|||
constructor( |
|||
private local: LocalHttpInterceptorService, |
|||
private api: ApiService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
formGroup = new FormGroup({ |
|||
id: new FormControl(this.api.authInfo.id), |
|||
username: new FormControl({ value: this.api.authInfo.username, disabled: true }, [ |
|||
FormValidators.required('请输入用户名'), |
|||
]), |
|||
password: new FormControl('', [FormValidators.required('请输入密码')]), |
|||
confirmPassword: new FormControl('', [FormValidators.required('请再次输入密码')]), |
|||
}) |
|||
|
|||
onSubmit() { |
|||
if (FormValidators.validateFormGroup(this.formGroup)) { |
|||
if (this.formGroup.value.confirmPassword !== this.formGroup.value.password) { |
|||
this.msg.error('两次输入密码不一致') |
|||
return |
|||
} |
|||
const v = this.formGroup.getRawValue() |
|||
this.api.changePassword(v).subscribe(() => { |
|||
this.msg.success('修改成功,请重新登录').onClose.subscribe(() => { |
|||
this.local.removeAccess() |
|||
window.location.href = '/login' |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -1,54 +0,0 @@ |
|||
<div class="w-[600px] pt-6"> |
|||
<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit()"> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4" nzRequired>姓名</nz-form-label> |
|||
<nz-form-control nzSpan="16" [nzErrorTip]="formErrorTipsTpl"> |
|||
<input nz-input placeholder="请输入姓名" formControlName="name" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
|
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4">备注</nz-form-label> |
|||
<nz-form-control nzSpan="16"> |
|||
<textarea nz-input placeholder="请输入备注" formControlName="remark"></textarea> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<!-- <nz-form-item> |
|||
<nz-form-label nzSpan="4">登录限制</nz-form-label> |
|||
<nz-form-control nzSpan="16"> |
|||
<nz-switch></nz-switch> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
<nz-form-item> |
|||
<nz-form-label nzSpan="4">限制规则</nz-form-label> |
|||
<nz-form-control nzSpan="16"> |
|||
<div> |
|||
<nz-input-group nzAddOnBefore="登录失败达到" nzAddOnAfter="次"> |
|||
<input type="number" nz-input /> |
|||
</nz-input-group> |
|||
</div> |
|||
<div class="mt-2"> |
|||
<ng-template #nzAddOnAfterTpl> |
|||
<nz-select class="!w-20"> |
|||
<nz-option nzValue="m" nzLabel="分钟"></nz-option> |
|||
<nz-option nzValue="h" nzLabel="小时"></nz-option> |
|||
<nz-option nzValue="d" nzLabel="天"></nz-option> |
|||
</nz-select> |
|||
</ng-template> |
|||
<nz-input-group nzAddOnBefore="锁定账号" [nzAddOnAfter]="nzAddOnAfterTpl"> |
|||
<input type="number" nz-input /> |
|||
</nz-input-group> |
|||
</div> |
|||
</nz-form-control> |
|||
</nz-form-item> --> |
|||
<nz-form-item> |
|||
<nz-form-control nzOffset="4"> |
|||
<button nz-button nzType="primary">保存</button> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
|
|||
<ng-template #formErrorTipsTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
|||
</div> |
@ -1,52 +0,0 @@ |
|||
import { Component, OnDestroy, OnInit } from '@angular/core' |
|||
import { SharedModule } from '../../shared/shared.module' |
|||
import { ApiService } from 'app/services' |
|||
import { UserFormComponent } from 'app/components/user-form/user-form.component' |
|||
import { FormBuilder, FormControl, FormGroup } from '@angular/forms' |
|||
import { FormValidators } from 'app/utils' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { Subscription } from 'rxjs' |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule, UserFormComponent], |
|||
selector: 'app-profile-basic', |
|||
templateUrl: './profile-basic.component.html', |
|||
styleUrls: ['./profile-basic.component.less'], |
|||
}) |
|||
export class ProfileBasicComponent implements OnInit, OnDestroy { |
|||
constructor( |
|||
public api: ApiService, |
|||
private fb: FormBuilder, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
formGroup!: FormGroup |
|||
|
|||
ngOnInit(): void { |
|||
this.formGroup = this.fb.group({ |
|||
name: new FormControl(this.api.authInfo.name, [FormValidators.required('请输入姓名')]), |
|||
remark: new FormControl(this.api.authInfo.remark), |
|||
}) |
|||
} |
|||
|
|||
ngOnDestroy(): void {} |
|||
|
|||
public getValues() { |
|||
let values = null |
|||
if (FormValidators.validateFormGroup(this.formGroup)) { |
|||
values = this.formGroup.value |
|||
} |
|||
return values |
|||
} |
|||
|
|||
onSubmit() { |
|||
const vals = this.getValues() |
|||
if (vals) { |
|||
this.api.saveUser({ ...this.api.authInfo, ...vals }).subscribe(() => { |
|||
this.msg.success('保存成功') |
|||
this.api.getAuthInfo(true).subscribe(() => {}) |
|||
}) |
|||
} |
|||
} |
|||
} |
@ -1,36 +0,0 @@ |
|||
<div> |
|||
<nz-card [nzBordered]="false"> |
|||
<nz-descriptions [nzColumn]="2" class="ml-16"> |
|||
<nz-descriptions-item nzTitle="用户名"> |
|||
{{ api.authInfo.username }} |
|||
</nz-descriptions-item> |
|||
<nz-descriptions-item nzTitle="姓名"> |
|||
{{ api.authInfo.name }} |
|||
</nz-descriptions-item> |
|||
<nz-descriptions-item nzTitle="角色"> |
|||
{{ api.authInfo.roleName }} |
|||
</nz-descriptions-item> |
|||
<nz-descriptions-item nzTitle="状态"> |
|||
@if (api.authInfo.enable) { |
|||
<nz-badge nzStatus="success" nzText="启用"></nz-badge> |
|||
} @else { |
|||
<nz-badge nzStatus="errot" nzText="禁用"></nz-badge> |
|||
} |
|||
</nz-descriptions-item> |
|||
<nz-descriptions-item nzTitle="备注">{{ api.authInfo.remark || '-' }}</nz-descriptions-item> |
|||
</nz-descriptions> |
|||
</nz-card> |
|||
</div> |
|||
<div class="mt-4"> |
|||
<nz-card [nzBordered]="false"> |
|||
<div class="nav-bar"> |
|||
<ul> |
|||
<li class="cursor-pointer" [routerLink]="['/profile/basic']" routerLinkActive="active">基础信息</li> |
|||
<li class="cursor-pointer" [routerLink]="['/profile/account']" routerLinkActive="active">账号密码</li> |
|||
</ul> |
|||
</div> |
|||
<div class="py-4"> |
|||
<router-outlet></router-outlet> |
|||
</div> |
|||
</nz-card> |
|||
</div> |
@ -1,18 +0,0 @@ |
|||
.nav-bar { |
|||
ul { |
|||
display: flex; |
|||
|
|||
li { |
|||
padding: 6px 24px; |
|||
margin-right: 12px; |
|||
font-size: 14px; |
|||
border-radius: 20px; |
|||
font-weight: bold; |
|||
|
|||
&.active { |
|||
background-color: #f2f3f5; |
|||
color: var(--primary); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,22 +0,0 @@ |
|||
import { Component, OnDestroy, OnInit } from '@angular/core' |
|||
import { SharedModule } from '../../shared/shared.module' |
|||
import { ApiService } from 'app/services' |
|||
import { UserDTO } from 'app/services/api.dto' |
|||
import { Subscription } from 'rxjs' |
|||
|
|||
@Component({ |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
selector: 'app-profile', |
|||
templateUrl: './profile.component.html', |
|||
styleUrls: ['./profile.component.less'], |
|||
}) |
|||
export class ProfileComponent implements OnInit, OnDestroy { |
|||
constructor(public api: ApiService) {} |
|||
|
|||
ngOnInit(): void { |
|||
this.api.getUserInfo(this.api.authInfo.id).subscribe((res) => {}) |
|||
} |
|||
|
|||
ngOnDestroy(): void {} |
|||
} |
@ -0,0 +1,10 @@ |
|||
.icon { |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
background-image: linear-gradient(135deg, #77abf4, #2f7deb); |
|||
font-size: 32px; |
|||
color: #fff; |
|||
|
|||
} |
@ -1 +1,31 @@ |
|||
<p>flow-my-apply works!</p> |
|||
<app-page> |
|||
<div class="flex-1 overflow-hidden"> |
|||
<app-server-paginated-table [options]="table" [renderColumn]="renderColumnTpl"> |
|||
<ng-template #renderColumnTpl let-data let-key="key" let-row="row"> |
|||
@switch (key) { |
|||
@case ('_assignee') { |
|||
<nz-tag> {{ data.userName }} </nz-tag> |
|||
} |
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
</app-server-paginated-table> |
|||
</div> |
|||
</app-page> |
|||
|
|||
<ng-template #createFormTpl> |
|||
<form nz-form [formGroup]="createForm"> |
|||
<nz-form-item> |
|||
<nz-form-label [nzSpan]="6" [nzRequired]="true">审批人</nz-form-label> |
|||
<nz-form-control [nzSpan]="12" [nzErrorTip]="errorTpl"> |
|||
<app-select-user-by-org formControlName="userId" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #errorTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
|||
|
@ -1,12 +1,91 @@ |
|||
import { Component } from '@angular/core'; |
|||
import { Component, TemplateRef, ViewChild } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
|
|||
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table' |
|||
import { ApiService } from 'app/services' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
|
|||
import { lastValueFrom, map, of } from 'rxjs' |
|||
import { NzSafeAny } from 'ng-zorro-antd/core/types' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { FormValidators } from 'app/utils' |
|||
|
|||
@Component({ |
|||
selector: 'app-flow-my-apply', |
|||
standalone: true, |
|||
imports: [], |
|||
templateUrl: './flow-my-apply.component.html', |
|||
styleUrl: './flow-my-apply.component.less' |
|||
selector: 'app-flow-my-apply', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './flow-my-apply.component.html', |
|||
styleUrl: './flow-my-apply.component.less', |
|||
}) |
|||
export class FlowMyApplyComponent { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
@ViewChild('createFormTpl') createFormTpl!: TemplateRef<{}> |
|||
|
|||
createForm = new FormGroup({ |
|||
formId: new FormControl(''), |
|||
userId: new FormControl<NzSafeAny[]>([], [FormValidators.required('请选择')]), |
|||
}) |
|||
|
|||
table = new TableOption(this.fetchData.bind(this)) |
|||
|
|||
ngOnInit(): void { |
|||
this.table |
|||
// .setConfig({
|
|||
// selectable: true,
|
|||
// rowKey: 'id',
|
|||
// })
|
|||
.setColumn([ |
|||
{ key: 'taskName', title: '标识', visible: true }, |
|||
{ key: 'name', title: '名称', visible: true }, |
|||
{ key: 'status', title: '审批状态', visible: true }, |
|||
{ key: 'category', title: '流程类型', visible: true }, |
|||
{ key: 'assigneeName', title: '审批人', visible: true }, |
|||
{ key: 'createTime', title: '提交时间', visible: true }, |
|||
// { key: 'createTime', title: '作废时间', visible: true },
|
|||
// { key: 'createTime', title: '完成时间', visible: true },
|
|||
]) |
|||
.setRowOperate([{ title: '详情' }, { title: '作废' }]) |
|||
} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
return this.api.getMyApplyAssetFlow({ ...p, ...q }) |
|||
} |
|||
|
|||
onSetApprover(data?: NzSafeAny) { |
|||
if (data) { |
|||
console.log('data._assignee.userId', data._assignee.userId) |
|||
this.createForm.patchValue({ |
|||
userId: data._assignee.userId ? [data._assignee.userId] : [], |
|||
}) |
|||
} |
|||
this.modal.create({ |
|||
nzTitle: '设置审批人', |
|||
nzContent: this.createFormTpl, |
|||
nzOnOk: async () => { |
|||
if (FormValidators.validateFormGroup(this.createForm)) { |
|||
const vals = this.createForm.value |
|||
const res = await lastValueFrom( |
|||
this.api.setFlowFormsAssignee({ |
|||
...vals, |
|||
userId: vals.userId?.[0], |
|||
}), |
|||
) |
|||
this.msg.success(res.desc) |
|||
this.table.ref.reload() |
|||
this.createForm.reset() |
|||
return true |
|||
} |
|||
return false |
|||
}, |
|||
nzOnCancel: () => { |
|||
this.createForm.reset() |
|||
}, |
|||
}) |
|||
} |
|||
} |
|||
|
@ -0,0 +1,31 @@ |
|||
<app-page> |
|||
<div class="flex-1 overflow-hidden"> |
|||
<app-server-paginated-table [options]="table" [renderColumn]="renderColumnTpl"> |
|||
<ng-template #renderColumnTpl let-data let-key="key" let-row="row"> |
|||
@switch (key) { |
|||
@case ('_assignee') { |
|||
<nz-tag> {{ data.userName }} </nz-tag> |
|||
} |
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
</app-server-paginated-table> |
|||
</div> |
|||
</app-page> |
|||
|
|||
<ng-template #createFormTpl> |
|||
<form nz-form [formGroup]="createForm"> |
|||
<nz-form-item> |
|||
<nz-form-label [nzSpan]="6" [nzRequired]="true">审批人</nz-form-label> |
|||
<nz-form-control [nzSpan]="12" [nzErrorTip]="errorTpl"> |
|||
<app-select-user-by-org formControlName="userId" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #errorTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
@ -0,0 +1,91 @@ |
|||
import { Component, TemplateRef, ViewChild } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
|
|||
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table' |
|||
import { ApiService } from 'app/services' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
|
|||
import { lastValueFrom, map, of } from 'rxjs' |
|||
import { NzSafeAny } from 'ng-zorro-antd/core/types' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { FormValidators } from 'app/utils' |
|||
|
|||
@Component({ |
|||
selector: 'app-flow-my-finished', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './flow-my-finished.component.html', |
|||
styleUrl: './flow-my-finished.component.less', |
|||
}) |
|||
export class FlowMyFinishedComponent { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
@ViewChild('createFormTpl') createFormTpl!: TemplateRef<{}> |
|||
|
|||
createForm = new FormGroup({ |
|||
formId: new FormControl(''), |
|||
userId: new FormControl<NzSafeAny[]>([], [FormValidators.required('请选择')]), |
|||
}) |
|||
|
|||
table = new TableOption(this.fetchData.bind(this)) |
|||
|
|||
ngOnInit(): void { |
|||
this.table |
|||
// .setConfig({
|
|||
// selectable: true,
|
|||
// rowKey: 'id',
|
|||
// })
|
|||
.setColumn([ |
|||
{ key: 'taskName', title: '标识', visible: true }, |
|||
{ key: 'name', title: '名称', visible: true }, |
|||
{ key: 'status', title: '审批状态', visible: true }, |
|||
{ key: 'category', title: '流程类型', visible: true }, |
|||
{ key: 'assigneeName', title: '审批人', visible: true }, |
|||
{ key: 'createTime', title: '提交时间', visible: true }, |
|||
// { key: 'createTime', title: '作废时间', visible: true },
|
|||
// { key: 'createTime', title: '完成时间', visible: true },
|
|||
]) |
|||
.setRowOperate([{ title: '详情' }, { title: '作废' }]) |
|||
} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
return this.api.getMyFinishedAssetFlow({ ...p, ...q }) |
|||
} |
|||
|
|||
onSetApprover(data?: NzSafeAny) { |
|||
if (data) { |
|||
console.log('data._assignee.userId', data._assignee.userId) |
|||
this.createForm.patchValue({ |
|||
userId: data._assignee.userId ? [data._assignee.userId] : [], |
|||
}) |
|||
} |
|||
this.modal.create({ |
|||
nzTitle: '设置审批人', |
|||
nzContent: this.createFormTpl, |
|||
nzOnOk: async () => { |
|||
if (FormValidators.validateFormGroup(this.createForm)) { |
|||
const vals = this.createForm.value |
|||
const res = await lastValueFrom( |
|||
this.api.setFlowFormsAssignee({ |
|||
...vals, |
|||
userId: vals.userId?.[0], |
|||
}), |
|||
) |
|||
this.msg.success(res.desc) |
|||
this.table.ref.reload() |
|||
this.createForm.reset() |
|||
return true |
|||
} |
|||
return false |
|||
}, |
|||
nzOnCancel: () => { |
|||
this.createForm.reset() |
|||
}, |
|||
}) |
|||
} |
|||
} |
@ -1 +1,31 @@ |
|||
<p>flow-my-todo works!</p> |
|||
<app-page> |
|||
<div class="flex-1 overflow-hidden"> |
|||
<app-server-paginated-table [options]="table" [renderColumn]="renderColumnTpl"> |
|||
<ng-template #renderColumnTpl let-data let-key="key" let-row="row"> |
|||
@switch (key) { |
|||
@case ('_assignee') { |
|||
<nz-tag> {{ data.userName }} </nz-tag> |
|||
} |
|||
@default { |
|||
{{ data }} |
|||
} |
|||
} |
|||
</ng-template> |
|||
</app-server-paginated-table> |
|||
</div> |
|||
</app-page> |
|||
|
|||
<ng-template #createFormTpl> |
|||
<form nz-form [formGroup]="createForm"> |
|||
<nz-form-item> |
|||
<nz-form-label [nzSpan]="6" [nzRequired]="true">审批人</nz-form-label> |
|||
<nz-form-control [nzSpan]="12" [nzErrorTip]="errorTpl"> |
|||
<app-select-user-by-org formControlName="userId" /> |
|||
</nz-form-control> |
|||
</nz-form-item> |
|||
</form> |
|||
</ng-template> |
|||
|
|||
<ng-template #errorTpl let-control> |
|||
<form-error-tips [control]="control"></form-error-tips> |
|||
</ng-template> |
|||
|
@ -1,12 +1,91 @@ |
|||
import { Component } from '@angular/core'; |
|||
import { Component, TemplateRef, ViewChild } from '@angular/core' |
|||
import { FormControl, FormGroup } from '@angular/forms' |
|||
|
|||
import { AnyObject, TableOption } from 'app/shared/components/server-paginated-table' |
|||
import { ApiService } from 'app/services' |
|||
import { SharedModule } from 'app/shared/shared.module' |
|||
|
|||
import { lastValueFrom, map, of } from 'rxjs' |
|||
import { NzSafeAny } from 'ng-zorro-antd/core/types' |
|||
import { NzModalService } from 'ng-zorro-antd/modal' |
|||
import { NzMessageService } from 'ng-zorro-antd/message' |
|||
import { FormValidators } from 'app/utils' |
|||
|
|||
@Component({ |
|||
selector: 'app-flow-my-todo', |
|||
standalone: true, |
|||
imports: [], |
|||
templateUrl: './flow-my-todo.component.html', |
|||
styleUrl: './flow-my-todo.component.less' |
|||
selector: 'app-flow-my-todo', |
|||
standalone: true, |
|||
imports: [SharedModule], |
|||
templateUrl: './flow-my-todo.component.html', |
|||
styleUrl: './flow-my-todo.component.less', |
|||
}) |
|||
export class FlowMyTodoComponent { |
|||
constructor( |
|||
private api: ApiService, |
|||
private modal: NzModalService, |
|||
private msg: NzMessageService, |
|||
) {} |
|||
|
|||
@ViewChild('createFormTpl') createFormTpl!: TemplateRef<{}> |
|||
|
|||
createForm = new FormGroup({ |
|||
formId: new FormControl(''), |
|||
userId: new FormControl<NzSafeAny[]>([], [FormValidators.required('请选择')]), |
|||
}) |
|||
|
|||
table = new TableOption(this.fetchData.bind(this)) |
|||
|
|||
ngOnInit(): void { |
|||
this.table |
|||
// .setConfig({
|
|||
// selectable: true,
|
|||
// rowKey: 'id',
|
|||
// })
|
|||
.setColumn([ |
|||
{ key: 'taskName', title: '标识', visible: true }, |
|||
{ key: 'name', title: '名称', visible: true }, |
|||
{ key: 'status', title: '审批状态', visible: true }, |
|||
{ key: 'category', title: '流程类型', visible: true }, |
|||
{ key: 'assigneeName', title: '审批人', visible: true }, |
|||
{ key: 'createTime', title: '提交时间', visible: true }, |
|||
// { key: 'createTime', title: '作废时间', visible: true },
|
|||
// { key: 'createTime', title: '完成时间', visible: true },
|
|||
]) |
|||
.setRowOperate([{ title: '详情' }, { title: '作废' }]) |
|||
} |
|||
|
|||
fetchData(p: {}, q: AnyObject) { |
|||
return this.api.getMyTodoAssetFlow({ ...p, ...q }) |
|||
} |
|||
|
|||
onSetApprover(data?: NzSafeAny) { |
|||
if (data) { |
|||
console.log('data._assignee.userId', data._assignee.userId) |
|||
this.createForm.patchValue({ |
|||
userId: data._assignee.userId ? [data._assignee.userId] : [], |
|||
}) |
|||
} |
|||
this.modal.create({ |
|||
nzTitle: '设置审批人', |
|||
nzContent: this.createFormTpl, |
|||
nzOnOk: async () => { |
|||
if (FormValidators.validateFormGroup(this.createForm)) { |
|||
const vals = this.createForm.value |
|||
const res = await lastValueFrom( |
|||
this.api.setFlowFormsAssignee({ |
|||
...vals, |
|||
userId: vals.userId?.[0], |
|||
}), |
|||
) |
|||
this.msg.success(res.desc) |
|||
this.table.ref.reload() |
|||
this.createForm.reset() |
|||
return true |
|||
} |
|||
return false |
|||
}, |
|||
nzOnCancel: () => { |
|||
this.createForm.reset() |
|||
}, |
|||
}) |
|||
} |
|||
} |
|||
|
Loading…
Reference in new issue