员工管理

This commit is contained in:
Taric Xin
2021-11-30 11:11:02 +08:00
parent 08d5b09401
commit 83208b4934
22 changed files with 650 additions and 53 deletions

View File

@ -41,7 +41,7 @@ function getRule(params: any): any {
if (params.no) {
ret = ret.filter(data => data.no.indexOf(params.no) > -1);
}
return { data: ret, success: true };
return { data: { records: ret, total: ret.length }, success: true };
}
function removeRule(nos: string): any {
@ -51,7 +51,7 @@ function removeRule(nos: string): any {
list.splice(idx, 1);
}
});
return { data: true, success: true };
}
@ -78,6 +78,6 @@ function saveRule(description: string): void {
export const RULES = {
'POST /rule': (req: MockRequest) => getRule(req.queryString),
'POST /delete/rule': (req: MockRequest) => removeRule(req.body.nos),
'POST /delete/rule': (req: MockRequest) => removeRule(req.body.nos)
// 'POST /rule': (req: MockRequest) => saveRule(req.body.description)
};

View File

@ -58,8 +58,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
"maximumWarning": "4mb",
"maximumError": "10mb"
}
]
},

View File

@ -39,6 +39,6 @@
</nz-alert>
</div>
<st #st [data]="url" [columns]="columns" [req]="{method:'POST'}" [res]="{reName:{list:'data'}}"
<st #st [data]="url" [columns]="columns" [req]="{method:'POST'}" [res]="{reName:{ list: 'data.records', total: 'data.total' }}"
(change)="stChange($event)"></st>
</nz-card>

View File

@ -69,8 +69,8 @@ export class ZorroDemoComponent implements OnInit {
this.service
.request('/rule?_allow_anonymous=true', this.q)
.pipe(
map((list: Array<{ status: number; statusText: string; statusType: string }>) =>
list.map(i => {
map((list: { records: Array<{ status: number; statusText: string; statusType: string }> }) =>
list.records.map(i => {
const statusItem = this.status[i.status];
i.statusText = statusItem.text;
i.statusType = statusItem.type;

View File

@ -25,12 +25,13 @@ const routes: Routes = [
{ path: 'demo', loadChildren: () => import('./demo/demo.module').then(m => m.DemoModule) },
{
path: 'account',
loadChildren: () => import('./account/account.module').then((m) => m.AccountModule),
loadChildren: () => import('./account/account.module').then(m => m.AccountModule)
},
{
path: 'usercenter',
loadChildren: () => import('./usercenter/usercenter.module').then((m) => m.UsercenterModule),
loadChildren: () => import('./usercenter/usercenter.module').then(m => m.UsercenterModule)
},
{ path: 'system', loadChildren: () => import('./sys-setting/sys-setting.module').then(m => m.SysSettingModule) }
]
},
// passport

View File

@ -0,0 +1,40 @@
<page-header-wrapper title="员工管理">
</page-header-wrapper>
<nz-card class="search-box">
<div nz-row nzGutter="8">
<div nz-col [nzSpan]="6">
<sf #sf [schema]="searchSchema" [ui]="{ '*': { spanLabelFixed: 90,grid: { span: 24 } }}" [compact]="true"
[button]="'none'"></sf>
</div>
<div nz-col [nzSpan]="8" nzOffset="1">
<button nz-button nzType="primary" [nzLoading]="service.http.loading" (click)="st?.load(1)">查询</button>
<button nz-button (click)="resetSF()">重置</button>
</div>
</div>
</nz-card>
<nz-card class="content-box">
<div class="d-flex justify-content-between mb-sm">
<label style="font-size: 18px;">员工列表</label>
<div>
<button nz-button nzType="primary" (click)="staffAction()">添加员工</button>
<button nz-button>导出</button>
</div>
</div>
<div class="mb-md">
<nz-alert [nzType]="'info'" [nzShowIcon]="true" [nzMessage]="message">
<ng-template #message>
已选择
<strong class="text-primary">{{ selectedRows.length }}</strong>
</ng-template>
</nz-alert>
</div>
<st #st [data]="url" [columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="service.http.loading" [scroll]="{ y: '370px' }" (change)="stChange($event)"></st>
</nz-card>

View File

@ -0,0 +1,13 @@
:host::ng-deep{
.search-box{
.ant-card-body{
padding-bottom: 18px;
}
}
.content-box{
.ant-card-body{
padding-top: 14px;
}
}
}

View File

@ -0,0 +1,155 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { STComponent, STColumn, STChange } from '@delon/abc/st';
import { SFComponent, SFSchema } from '@delon/form';
import { NzModalService } from 'ng-zorro-antd/modal';
import { SystemService } from '../../services/system.service';
import { SystemStaffStaffModalComponent } from './staff-modal/staff-modal.component';
import { BuyerTranspowerComponent } from './transpower/transpower.component';
@Component({
selector: 'app-staff-management',
templateUrl: './staff-management.component.html',
styleUrls: ['./staff-management.component.less']
})
export class StaffManagementComponent implements OnInit {
@ViewChild('st', { static: true })
st!: STComponent;
@ViewChild('sf', { static: false })
sf!: SFComponent;
url = `/rule?_allow_anonymous=true`;
searchSchema: SFSchema = {
properties: {
receiveName: {
type: 'string',
title: '输入搜索',
ui: { placeholder: '手机号码 / 成员姓名' }
}
}
};
columns: STColumn[] = [
{ title: '', index: 'key', type: 'checkbox' },
{ title: '员工姓名', index: 'no' },
{ title: '手机号码', index: 'description' },
{ title: '角色', index: 'description' },
{
title: '最后登录时间',
index: 'updatedAt',
type: 'date'
},
{
title: '成员状态',
className: 'text-center',
index: 'status',
type: 'badge',
badge: {
0: { text: '正常', color: 'success' },
2: { text: '废弃', color: 'warning' },
3: { text: '废弃', color: 'warning' },
1: { text: '冻结', color: 'error' }
}
},
{
title: '操作',
buttons: [
{
text: '编辑',
click: item => this.staffAction(item)
},
{
text: '恢复',
iif: item => item.status === 1,
click: item => this.action(2)
},
{
text: '冻结',
iif: item => item.status === 0,
click: item => this.action(1)
},
{
text: '超管转授',
iif: item => item.status === 0,
click: item => this.transpowerAction(item)
},
{
text: '删除',
iif: item => item.status === 1,
click: item => this.action(3)
}
]
}
];
selectedRows: any[] = [];
reqParams = { pageIndex: 1, pageSize: 10 };
actionLabel = {
1: { title: '确认冻结?', text: '冻结后用户在本系统将无法登录使用,请谨慎操作!' },
2: { title: '确认恢复?', text: '恢复后用户在本系统的权限将一并重新开启。' },
3: { title: '确认删除?', text: '删除后该用户ID将在本系统中将无法登录使用并删除请谨慎操作' }
};
constructor(public service: SystemService, private nzModalService: NzModalService) {}
ngOnInit(): void {}
stChange(e: STChange): void {
switch (e.type) {
case 'checkbox':
this.selectedRows = e.checkbox!;
break;
case 'filter':
this.st.load();
break;
}
}
action(type: 1 | 2 | 3) {
this.nzModalService.error({
nzTitle: this.actionLabel[type].title,
nzContent: `<label class="error-color">${this.actionLabel[type].text}</label>`,
nzClosable: false,
nzCancelText: '取消',
nzOnOk: () => {
switch (type) {
case 1:
break;
default:
break;
}
}
});
}
transpowerAction(item: any) {
const modal = this.nzModalService.create({
nzContent: BuyerTranspowerComponent,
nzComponentParams: { i: { ...item } },
nzFooter: null
});
modal.afterClose.subscribe(res => {
this.st.load();
});
}
staffAction(item?: any) {
const modal = this.nzModalService.create({
nzContent: SystemStaffStaffModalComponent,
nzComponentParams: item ? { i: { ...item, roleId: '1,2,3', name: '用户名', phone: 18555555555 } } : { i: { id: 0 } },
nzFooter: null
});
modal.afterClose.subscribe(res => {
this.st.load();
});
}
/**
* 重置表单
*/
resetSF() {
this.sf.reset();
}
}

View File

@ -0,0 +1,24 @@
<div class="modal-header">
<div class="modal-title">{{ i.id === 0 ? '添加员工' : '编辑员工' }}</div>
</div>
<div>
<sf #sf [compact]="true" [ui]="ui" [schema]="schema" [button]="'none'">
<ng-template sf-template="account" let-me let-ui="ui" let-schema="schema">
<sv-container labelWidth="1">
<sv label="">
<div class="staffBox">
<!-- <img [src]="i.avatar" alt="" /> -->
<dl>
<!-- <dt>{{ i.name }}</dt> -->
<dd>{{ i.phone }}</dd>
</dl>
</div>
</sv>
</sv-container>
</ng-template>
</sf>
</div>
<div class="modal-footer">
<button nz-button type="button" (click)="close()">取消</button>
<button nz-button type="button" nzType="primary" (click)="sure()" [disabled]="!sf.valid">保存</button>
</div>

View File

@ -0,0 +1,146 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { SFComponent, SFSchema, SFUISchema } from '@delon/form';
import { _HttpClient } from '@delon/theme';
import { copy } from '@delon/util';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { map } from 'rxjs/operators';
import { EAEnterpriseService } from 'src/app/shared/services/business/enterprise.service';
import { SystemService } from '../../../services/system.service';
@Component({
selector: 'app-system-add',
templateUrl: './staff-modal.component.html',
styleUrls: ['./staff-modal.less']
})
export class SystemStaffStaffModalComponent implements OnInit {
@ViewChild('sf', { static: false })
sf!: SFComponent;
i: any;
schema!: SFSchema;
ui!: SFUISchema;
roleList = [];
roleNames: any = [];
constructor(
private modal: NzModalRef,
public msgSrv: NzMessageService,
public service: SystemService,
private enterpriseSrv: EAEnterpriseService
) {}
ngOnInit(): void {
if (this.i?.id !== 0) {
this.i.roleIds = this.i.roleId !== '' ? this.i.roleId.split(',') : [];
}
this.initSF(this.i);
}
initSF(staff: any) {
console.log(staff);
this.schema = {
properties: {
name: {
title: '员工姓名',
type: 'string',
maxLength: 32,
ui: { widget: staff?.name ? 'text' : 'string', placeholder: '请输入员工姓名' },
default: staff.name
},
phone: {
title: '手机号码',
type: 'string',
format: 'mobile',
maxLength: 11,
ui: { widget: staff?.phone ? 'text' : 'string', placeholder: '请输入员工手机号' },
default: staff.phone
},
roleIds: {
title: '角色',
type: 'string',
ui: {
widget: 'select',
placeholder: '请选择员工角色',
mode: 'multiple',
maxMultipleCount: 5,
// asyncData: () => {
// return this.service.request(this.service.$api_getAppRoleList).pipe(
// map((res: any) => {
// this.roleList = res;
// return res.map((item: any) => {
// return { label: item.roleName, value: item.id };
// });
// }),
// );
// },
change: (i: any) => {
this.sf.value.roleIds = i;
this.sf?.setValue('/roleIds', i);
}
},
default: staff?.roleIds
}
},
required: ['name', 'phone', 'roleIds']
};
this.ui = {
'*': {
spanLabelFixed: 120,
grid: { span: 24 }
}
};
}
sure() {
if (!this.sf.value.roleIds || this.sf.value.roleIds.length === 0) {
this.service.msgSrv.error('员工角色不能为空!');
return;
}
this.roleNames = [];
this.roleList.forEach((item: { id: any; roleName: string }) => {
this.sf.value.roleIds.forEach((ele: any) => {
if (ele === item.id) {
this.roleNames.push(item.roleName);
}
});
});
if (this.i.id === 0) {
const params: any = {
...this.sf.value,
roleId: this.sf.value.roleIds,
roleNames: this.roleNames.join(','),
telephone: this.sf.value.phone,
staffName: this.sf.value.name
};
// this.service.request(this.service.$api_addStaff, params).subscribe((res) => {
// console.log(res);
// if (res) {
// this.service.msgSrv.success('保存成功!');
// this.modal.close(true);
// }
// // this.showInviteFlag = true;
// // this.inviteCode = res.inviteCode;
// });
} else {
const params: any = {
appUserId: this.i.appUserId,
staffName: this.sf.value.name,
roleId: this.sf.value.roleIds,
telephone: this.i.telephone
};
// this.service.request(this.service.$api_editorStaff, params).subscribe((res) => {
// this.service.msgSrv.success('编辑成功!');
// // this.loadMyIdentity();
// this.modal.close(true);
// });
}
}
loadMyIdentity() {
this.enterpriseSrv.loadEnterpises().subscribe((data: any[]) => {
this.enterpriseSrv.setCache(data);
});
}
close() {
this.modal.destroy();
}
}

View File

@ -0,0 +1,25 @@
.info {
width: 100%;
margin: 0 auto 10px auto;
color: #333;
text-indent: 24px;
}
.staffBox {
display: flex;
img {
width: 30px;
height: 30px;
overflow: hidden;
border-radius: 50px;
}
dl {
margin: 0 0 0 5px;
dt {
font-size: 14px;
line-height: 28px;
}
dd {
font-size: 12px;
}
}
}

View File

@ -0,0 +1,27 @@
<div class="modal-header">
<div class="modal-title">超级管理员转授</div>
</div>
<form nz-form #f="ngForm" se-container="1">
<se label="转授员工">张三13411223344</se>
<se style="margin:0">
<div class="code">为了账户安全,需超管手机验证({{ superPhone }}</div>
</se>
<se label="验证码">
<div class="inputBox">
<div nz-row [nzGutter]="8">
<div nz-col [nzSpan]="12">
<input nz-input name="smsVerifyCode" [(ngModel)]="smsVerifyCode" maxlength="6" placeholder="请输入短信验证码" />
</div>
<div nz-col [nzSpan]="12">
<button nz-button (click)="sendCode()" [disabled]="count > 0">
{{ count > 0 ? '请等待' + count + 's' : '发送验证码' }}
</button>
</div>
</div>
</div>
</se>
</form>
<div class="modal-footer">
<button nz-button type="button" (click)="close()">取消</button>
<button nz-button type="button" (click)="sure()" [disabled]="f.invalid" nzType="primary">确定</button>
</div>

View File

@ -0,0 +1,83 @@
import { ChangeDetectorRef, Component, OnInit, TemplateRef } from '@angular/core';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';
import { DunHelper } from 'src/app/shared/components/captcha/dun.helper';
import { EACaptchaService } from 'src/app/shared/services/business/captcha.service';
@Component({
selector: 'app-buyer-transpower',
templateUrl: './transpower.component.html',
styleUrls: ['./transpower.less']
})
export class BuyerTranspowerComponent implements OnInit {
record: any = {};
count = 0;
interval$: any;
i: any;
smsVerifyCode = '';
superPhone = '';
staffId = 1;
staffList: any = [];
constructor(
private modal: NzModalRef,
public captchaService: EACaptchaService,
private dunHelper: DunHelper,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void {
this.getPhone();
}
getPhone() {
// this.service.request(this.service.$api_getAppLesseeAdmin).subscribe((res) => {
// console.log(res);
// if (res) {
// this.superPhone = res.telephone;
// }
// });
}
sure() {
const params = {
appUserId: this.i.appUserId,
smsVerifyCode: this.smsVerifyCode
};
// this.service.request(this.service.$api_shiftResellerAdmin, params).subscribe((res) => {
// if (res) {
// this.service.msgSrv.success('操作成功!');
// this.modal.close(true);
// }
// });
}
close() {
this.modal.destroy();
}
/**
* 获取手机验证码
*/
sendCode() {
this.captchaService.getAppLesseeAdminSMVerificationCode().subscribe(res => {
if (res.success && res.data.code === '1') {
this.captchaService.msgSrv.success('发送验证码成功');
this.createInterval();
} else if (res.data.code === '503046') {
this.dunHelper.popUp().subscribe(_ => {
this.createInterval();
this.dunHelper.destory();
});
} else {
this.captchaService.msgSrv.warning(res.msg);
}
});
}
private createInterval() {
this.count = 59;
interval(1000)
.pipe(take(60))
.subscribe(x => {
this.count = 59 - (x + 1);
this.cdr.detectChanges();
});
}
}

View File

@ -0,0 +1,41 @@
.info {
width : 90%;
margin : 0 auto;
color : #333;
text-indent: 24px;
}
.staffBox {
display : flex;
align-items: center;
img {
width : 30px;
height : 30px;
overflow : hidden;
border-radius: 50px;
}
dl {
margin: 0 0 0 5px;
dt {
font-size : 14px;
line-height: 28px;
}
dd {
font-size: 12px;
}
}
}
.inputBox {
position: relative;
a {
position: absolute;
top : 0;
right : 5px;
}
}

View File

@ -0,0 +1,11 @@
import { Injectable, Injector } from '@angular/core';
import { BaseService } from 'src/app/shared/services';
@Injectable({
providedIn: 'root'
})
export class SystemService extends BaseService {
constructor(public injector: Injector) {
super(injector);
}
}

View File

@ -1,7 +1,8 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { StaffManagementComponent } from './components/staff-management/staff-management.component';
const routes: Routes = [];
const routes: Routes = [{ path: 'staff-management', component: StaffManagementComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],

View File

@ -1,9 +1,14 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared';
import { StaffManagementComponent } from './components/staff-management/staff-management.component';
import { SysSettingRoutingModule } from './sys-setting-routing.module';
import { BuyerTranspowerComponent } from './components/staff-management/transpower/transpower.component';
import { SystemStaffStaffModalComponent } from './components/staff-management/staff-modal/staff-modal.component';
const COMPONENTS = [StaffManagementComponent, BuyerTranspowerComponent, SystemStaffStaffModalComponent];
@NgModule({
declarations: [],
imports: [CommonModule, SharedModule]
declarations: COMPONENTS,
imports: [CommonModule, SysSettingRoutingModule, SharedModule]
})
export class SysSettingModule {}

View File

@ -3,20 +3,21 @@
nz-card {
.page-title {
margin-bottom: 39px;
color: #333;
font-weight: 500;
font-size: 20px;
line-height: 28px;
text-align: center;
color : #333;
font-weight : 500;
font-size : 20px;
line-height : 28px;
text-align : center;
}
.step-title {
display: block;
width: 800px !important;
margin: 0 auto;
width : 800px !important;
margin : 0 auto;
}
.myForm {
width: 680px;
width : 680px;
margin: 5rem auto;
}
@ -27,69 +28,82 @@
.btn-submit {
margin-top: 16px;
}
.pr {
position: relative;
}
.pa {
position: absolute;
top: 35px;
left: 150px;
top : 35px;
left : 150px;
}
.tips {
display: flex;
display : flex;
margin-bottom: 0;
color: #333;
color : #333;
dt {
width: 150px;
}
dd {
width: 190px;
width : 190px;
margin-bottom: 0;
text-align: center;
text-align : center;
}
}
.form-title {
margin-bottom: 10px;
padding-left: 8px;
color: #333;
font-weight: 700;
font-size: 18px;
line-height: 20px;
border-left: solid 3px #1890ff;
padding-left : 8px;
color : #333;
font-weight : 700;
font-size : 18px;
line-height : 20px;
border-left : solid 3px #1890ff;
}
.form-content {
padding: 48px 32px;
}
.apply-sv {
margin: 16px 0;
padding: 20px;
background: #f8f8f8;
margin : 16px 0;
padding : 20px;
background : #f8f8f8;
border-radius: 2px;
}
.result-date {
font-size: 12px;
}
.result-tips {
color: #ff4d4f;
color : #ff4d4f;
font-size: 14px;
}
.sv-img {
display: inline-block;
width: 104px;
height: 104px;
margin-right: 20px;
padding: 8px;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.15);
display : inline-block;
width : 104px;
height : 104px;
margin-right : 20px;
padding : 8px;
background : #fff;
border : 1px solid rgba(0, 0, 0, 0.15);
border-radius: 2px;
img {
width: 100%;
width : 100%;
height: 100%;
}
}
}
/deep/ .ant-row {
.ant-row {
margin-left: 100px;
}
}
}
}

View File

@ -69,7 +69,7 @@
"children": [
{
"text": "员工管理",
"link": "/demo/zorro"
"link": "/system/staff-management"
},
{
"text": "角色管理",

View File

@ -104,5 +104,5 @@ export const ICONS_AUTO = [
UsbOutline,
UserOutline,
WeiboCircleOutline,
EyeInvisibleOutline
EyeInvisibleOutline,
];

View File

@ -6,8 +6,15 @@
@import './styles/index';
@import './styles/theme';
@layout-gutter: 8px;
/* 全局滚动条美化 */
*::-webkit-scrollbar {
width : (@layout-gutter);
height: (@layout-gutter);
}
// .page-header {
// margin-left: -24px;
// margin-top : -24px;
// }
*::-webkit-scrollbar-thumb {
background : #d9d9d9;
cursor : pointer;
border-radius: (@layout-gutter) / 2;
}

View File

@ -8,3 +8,7 @@
// ==========Custom brand visual color==========
// ==========Custom brand visual color==========
.error-color {
color: #ff4d4f;
}