15 changed files with 961 additions and 777 deletions
@ -1,114 +1,111 @@ |
|||||
<app-page [scroll]="false"> |
<app-page [scroll]="false"> |
||||
<ng-template #pageExtraTpl> |
<ng-template #pageExtraTpl> |
||||
<nz-space> |
<nz-space> |
||||
<button *nzSpaceItem nz-button [disabled]="!selectedIds.length" (click)="deleteFood()">批量删除</button> |
<button *nzSpaceItem nz-button [disabled]="!selectedIds.length" (click)="deleteFood()">批量删除</button> |
||||
<button *nzSpaceItem nz-button (click)="showImportForm(importFormTpl)">导入食材清单</button> |
<button *nzSpaceItem nz-button (click)="showImportForm(importFormTpl)">导入食材清单</button> |
||||
<button *nzSpaceItem nz-button nzType="primary" (click)="showFoodForm()"> |
<button *nzSpaceItem nz-button nzType="primary" (click)="showFoodForm()"> |
||||
<i nz-icon nzType="plus"></i> |
<i nz-icon nzType="plus"></i> |
||||
新增食材 |
新增食材 |
||||
</button> |
</button> |
||||
</nz-space> |
</nz-space> |
||||
</ng-template> |
</ng-template> |
||||
<div nz-row class="h-full overflow-hidden bg-white rounded-lg"> |
<div nz-row class="h-full overflow-hidden bg-white rounded-lg"> |
||||
<div nz-col nzFlex="220px" class="food-type h-full"> |
<div nz-col nzFlex="220px" class="food-type h-full"> |
||||
<nz-card class="h-full" [nzBordered]="false" nzTitle="食材类型" |
<nz-card |
||||
[nzBodyStyle]="{padding:'1px 0 0 0', height:'100%',overflow:'auto'}"> |
class="h-full" |
||||
<ul nz-menu nzMode="inline"> |
[nzBordered]="false" |
||||
<li nz-menu-item (click)="onTypeChange('')" [nzSelected]="!queryForm.get('type')?.value"> |
nzTitle="食材类型" |
||||
<a> |
[nzBodyStyle]="{ padding: '1px 0 0 0', height: '100%', overflow: 'auto' }" |
||||
全部 |
> |
||||
</a> |
<ul nz-menu nzMode="inline"> |
||||
</li> |
<li nz-menu-item (click)="onTypeChange('')" [nzSelected]="!queryForm.get('type')?.value"> |
||||
<li nz-menu-item [nzSelected]="cate.key === queryForm.get('type')?.value" |
<a> 全部 </a> |
||||
*ngFor="let cate of globalEnum.category" (click)="onTypeChange(cate.key)"> |
</li> |
||||
<a> |
<li |
||||
{{cate.key}} |
nz-menu-item |
||||
</a> |
[nzSelected]="cate.key === queryForm.get('type')?.value" |
||||
</li> |
*ngFor="let cate of globalEnum.category" |
||||
</ul> |
(click)="onTypeChange(cate.key)" |
||||
</nz-card> |
> |
||||
</div> |
<a> |
||||
<div nz-col nzFlex="1" class="flex-1 overflow-hidden bg-white h-full"> |
{{ cate.key }} |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</nz-card> |
||||
|
</div> |
||||
|
<div nz-col nzFlex="1" class="flex-1 overflow-hidden bg-white h-full"> |
||||
|
<nz-card [nzBordered]="false" nzTitle="食材管理" class="scroll-card-body"> |
||||
|
<div class="m-4"> |
||||
|
<table-list |
||||
|
[props]="tableList" |
||||
|
[search]="searchTpl" |
||||
|
[action]="pageExtraTpl" |
||||
|
[formGroup]="queryForm" |
||||
|
[renderColumns]="renderColumnsTpl" |
||||
|
> |
||||
|
<ng-template #searchTpl> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<input nz-input placeholder="请输入食材名称/编号" formControlName="keyword" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</ng-template> |
||||
|
|
||||
<nz-card [nzBordered]="false" nzTitle="食材管理" class="scroll-card-body"> |
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row"> |
||||
<div class="m-4"> |
<ng-container [ngSwitch]="key"> |
||||
<table-list |
<ng-container *ngSwitchCase="'nutrientArr'"> |
||||
[props]="tableList" |
<div class="flex flex-wrap"> |
||||
[search]="searchTpl" |
<nz-tag *ngFor="let item of data" class="m-1"> |
||||
[action]="pageExtraTpl" |
{{ item.label }}:{{ item.value }}{{ item.measurement }} |
||||
[formGroup]="queryForm" |
</nz-tag> |
||||
[renderColumns]="renderColumnsTpl"> |
</div> |
||||
|
</ng-container> |
||||
<ng-template #searchTpl> |
<ng-container *ngSwitchCase="'modify'"> |
||||
<nz-form-item> |
{{ data | date : 'yyyy-MM-dd HH:mm:ss' }} |
||||
<nz-form-control> |
</ng-container> |
||||
<input nz-input placeholder="请输入食材名称/编号" formControlName="keyword" /> |
<ng-container *ngSwitchDefault> |
||||
</nz-form-control> |
{{ data }} |
||||
</nz-form-item> |
</ng-container> |
||||
</ng-template> |
</ng-container> |
||||
|
</ng-template> |
||||
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row"> |
</table-list> |
||||
<ng-container [ngSwitch]="key"> |
</div> |
||||
<ng-container *ngSwitchCase="'nutrientArr'"> |
</nz-card> |
||||
<div class=" flex flex-wrap"> |
</div> |
||||
<nz-tag *ngFor="let item of data" class="m-1"> |
</div> |
||||
{{item.label}}:{{item.value}}{{item.measurement}} |
|
||||
</nz-tag> |
|
||||
</div> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'modify'"> |
|
||||
{{data | date:'yyyy-MM-dd HH:mm:ss'}} |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchDefault> |
|
||||
|
|
||||
{{data}} |
|
||||
|
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-template> |
|
||||
</table-list> |
|
||||
</div> |
|
||||
</nz-card> |
|
||||
|
|
||||
</div> |
|
||||
</div> |
|
||||
</app-page> |
</app-page> |
||||
|
|
||||
<ng-template #importFormTpl> |
<ng-template #importFormTpl> |
||||
<p class=" text-slate-400"> |
<p class="text-slate-400"> |
||||
提示:<a (click)="downloadTemplate()">下载示例模版</a>,进行编辑,导入Excel文件,批量导入食材 |
提示:<a (click)="downloadTemplate()">下载示例模版</a>,进行编辑,导入Excel文件,批量导入食材 |
||||
</p> |
</p> |
||||
<div> |
<div> |
||||
<nz-spin [nzSpinning]="uploadLoading"> |
<nz-spin [nzSpinning]="uploadLoading"> |
||||
<div class="upload-area flex-col" |
<div |
||||
(drop)="handleDrop($event)" |
class="upload-area flex-col" |
||||
(dragenter)="suppress($event)" |
(drop)="handleDrop($event)" |
||||
(dragover)="suppress($event)"> |
(dragenter)="suppress($event)" |
||||
<input type="file" id="file" (change)="onFileChange($event)" accept=".xlsx,.xls" /> |
(dragover)="suppress($event)" |
||||
<div class="text-center"> |
> |
||||
<p class="text-4xl mb-1"> |
<input type="file" id="file" (change)="onFileChange($event)" accept=".xlsx,.xls" /> |
||||
<a nz-icon nzType="upload" nzTheme="outline"></a> |
<div class="text-center"> |
||||
</p> |
<p class="text-4xl mb-1"> |
||||
<p class="mb-1"> |
<a nz-icon nzType="upload" nzTheme="outline"></a> |
||||
点击或将文件拖拽到这里上传 |
</p> |
||||
</p> |
<p class="mb-1">点击或将文件拖拽到这里上传</p> |
||||
<p class="text-slate-400"> |
<p class="text-slate-400">支持扩展名:.xls .xlsx</p> |
||||
支持扩展名:.xls .xlsx |
</div> |
||||
</p> |
</div> |
||||
</div> |
</nz-spin> |
||||
</div> |
</div> |
||||
</nz-spin> |
|
||||
</div> |
|
||||
</ng-template> |
</ng-template> |
||||
|
|
||||
|
|
||||
<ng-template #foodFormFooterTpl> |
<ng-template #foodFormFooterTpl> |
||||
<nz-space> |
<nz-space> |
||||
<button *nzSpaceItem nz-button (click)="cancelFoodForm()" type="button"> |
<button *nzSpaceItem nz-button (click)="cancelFoodForm()" type="button">取消</button> |
||||
取消 |
<button *nzSpaceItem nz-button nzType="primary" [nzLoading]="submitLoading" (click)="onFoodSubmit()"> |
||||
</button> |
保存 |
||||
<button *nzSpaceItem nz-button nzType="primary" [nzLoading]="submitLoading" (click)="onFoodSubmit()"> |
</button> |
||||
保存 |
</nz-space> |
||||
</button> |
|
||||
</nz-space> |
|
||||
</ng-template> |
</ng-template> |
@ -1,210 +1,210 @@ |
|||||
import { FoodFormComponent } from "@admin/app/components"; |
import { FoodFormComponent } from '@admin/app/components' |
||||
import { ApiService } from "@cdk/services"; |
import { ApiService } from '@cdk/services' |
||||
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from "@angular/core"; |
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core' |
||||
import { FormControl, FormGroup } from "@angular/forms"; |
import { FormControl, FormGroup } from '@angular/forms' |
||||
import { AnyObject, TableListOption } from "@cdk/public-api"; |
import { AnyObject, TableListOption } from '@cdk/public-api' |
||||
import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; |
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer' |
||||
import { NzModalRef, NzModalService } from "ng-zorro-antd/modal"; |
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal' |
||||
import { Subject, finalize, lastValueFrom, map, takeUntil } from "rxjs"; |
import { Subject, finalize, lastValueFrom, map, takeUntil } from 'rxjs' |
||||
import { NzMessageService } from "ng-zorro-antd/message"; |
import { NzMessageService } from 'ng-zorro-antd/message' |
||||
|
|
||||
@Component({ |
@Component({ |
||||
selector: "app-food", |
selector: 'app-food', |
||||
templateUrl: "./food.component.html", |
templateUrl: './food.component.html', |
||||
styleUrls: ["./food.component.less"], |
styleUrls: ['./food.component.less'], |
||||
}) |
}) |
||||
export class FoodComponent implements OnInit, OnDestroy { |
export class FoodComponent implements OnInit, OnDestroy { |
||||
constructor( |
constructor( |
||||
private drawer: NzDrawerService, |
private drawer: NzDrawerService, |
||||
private api: ApiService, |
private api: ApiService, |
||||
private modal: NzModalService, |
private modal: NzModalService, |
||||
private msg: NzMessageService |
private msg: NzMessageService, |
||||
) {} |
) {} |
||||
|
|
||||
@ViewChild("foodFormFooterTpl") foodFormFooterTpl!: TemplateRef<{}>; |
@ViewChild('foodFormFooterTpl') foodFormFooterTpl!: TemplateRef<{}> |
||||
|
|
||||
private drawerRef?: NzDrawerRef; |
private drawerRef?: NzDrawerRef |
||||
|
|
||||
private importModalRef?: NzModalRef; |
private importModalRef?: NzModalRef |
||||
|
|
||||
public tableList = new TableListOption(this.fetchData.bind(this), { |
public tableList = new TableListOption(this.fetchData.bind(this), { |
||||
selectable: true, |
selectable: true, |
||||
frontPagination: false, |
frontPagination: false, |
||||
rowKey: "key", |
rowKey: 'key', |
||||
}); |
}) |
||||
|
|
||||
public globalEnum = this.api.globalEnum; |
public globalEnum = this.api.globalEnum |
||||
|
|
||||
public queryForm = new FormGroup({ |
public queryForm = new FormGroup({ |
||||
keyword: new FormControl(""), |
keyword: new FormControl(''), |
||||
type: new FormControl(""), |
type: new FormControl(''), |
||||
}); |
}) |
||||
|
|
||||
private destroy$ = new Subject<void>(); |
private destroy$ = new Subject<void>() |
||||
|
|
||||
public selectedIds: string[] = []; |
public selectedIds: string[] = [] |
||||
|
|
||||
submitLoading = false; |
submitLoading = false |
||||
|
|
||||
uploadLoading = false; |
uploadLoading = false |
||||
|
|
||||
editItem = null; |
editItem = null |
||||
|
|
||||
ngOnInit(): void { |
ngOnInit(): void { |
||||
this.initTableList(); |
this.initTableList() |
||||
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => { |
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => { |
||||
this.selectedIds = res.selectedKeys as Array<string>; |
this.selectedIds = res.selectedKeys as Array<string> |
||||
}); |
}) |
||||
} |
} |
||||
|
|
||||
ngOnDestroy(): void { |
ngOnDestroy(): void { |
||||
this.destroy$.next(); |
this.destroy$.next() |
||||
this.destroy$.complete(); |
this.destroy$.complete() |
||||
} |
} |
||||
|
|
||||
initTableList() { |
initTableList() { |
||||
this.tableList.scroll = { x: null }; |
this.tableList.scroll = { x: null } |
||||
this.tableList = this.tableList.setColumns([ |
this.tableList = this.tableList.setColumns([ |
||||
{ key: "key", title: "食材编号" }, |
{ key: 'key', title: '食材编号' }, |
||||
{ key: "name", title: "食材名称" }, |
{ key: 'name', title: '食材名称' }, |
||||
{ key: "type", title: "食材类型" }, |
{ key: 'type', title: '食材类型' }, |
||||
{ key: "nutrientArr", title: "营养素(每100g可食部)", width: "40%" }, |
{ key: 'nutrientArr', title: '营养素(每100g可食部)', width: '40%' }, |
||||
{ key: "modify", title: "更新日期" }, |
{ key: 'modify', title: '更新日期' }, |
||||
]); |
]) |
||||
|
|
||||
this.tableList = this.tableList.setOptions([ |
this.tableList = this.tableList.setOptions([ |
||||
{ |
{ |
||||
title: "编辑", |
title: '编辑', |
||||
premissions: [], |
premissions: [], |
||||
onClick: this.showFoodForm.bind(this), |
onClick: this.showFoodForm.bind(this), |
||||
}, |
}, |
||||
{ |
{ |
||||
title: "删除", |
title: '删除', |
||||
premissions: [], |
premissions: [], |
||||
onClick: this.deleteFood.bind(this), |
onClick: this.deleteFood.bind(this), |
||||
}, |
}, |
||||
]); |
]) |
||||
} |
} |
||||
|
|
||||
fetchData(query: AnyObject, pager: AnyObject) { |
fetchData(query: AnyObject, pager: AnyObject) { |
||||
return this.api.getFoodPage(pager, query).pipe(); |
return this.api.getFoodPage(pager, query).pipe() |
||||
} |
} |
||||
|
|
||||
onTypeChange(type: string) { |
onTypeChange(type: string) { |
||||
this.queryForm.patchValue({ type }); |
this.queryForm.patchValue({ type }) |
||||
this.tableList.reset(); |
this.tableList.reset() |
||||
} |
} |
||||
|
|
||||
showFoodForm(food?: any) { |
showFoodForm(food?: any) { |
||||
this.editItem = food; |
this.editItem = food |
||||
this.drawerRef = this.drawer.create({ |
this.drawerRef = this.drawer.create({ |
||||
nzTitle: food ? "编辑食材" : "新增食材", |
nzTitle: food ? '编辑食材' : '新增食材', |
||||
nzWidth: 520, |
nzWidth: 520, |
||||
nzContentParams: { |
nzContentParams: { |
||||
food, |
food, |
||||
}, |
}, |
||||
nzContent: FoodFormComponent, |
nzContent: FoodFormComponent, |
||||
nzFooter: this.foodFormFooterTpl, |
nzFooter: this.foodFormFooterTpl, |
||||
}); |
}) |
||||
} |
} |
||||
|
|
||||
onFoodSubmit() { |
onFoodSubmit() { |
||||
if (this.drawerRef) { |
if (this.drawerRef) { |
||||
const com = this.drawerRef.getContentComponent() as FoodFormComponent; |
const com = this.drawerRef.getContentComponent() as FoodFormComponent |
||||
const val = com.getValues(); |
const val = com.getValues() |
||||
if (val) { |
if (val) { |
||||
this.submitLoading = true; |
this.submitLoading = true |
||||
this.api |
this.api |
||||
.saveFood(val, !!this.editItem) |
.saveFood(val, !!this.editItem) |
||||
.pipe( |
.pipe( |
||||
finalize(() => { |
finalize(() => { |
||||
this.submitLoading = false; |
this.submitLoading = false |
||||
}) |
}), |
||||
) |
) |
||||
.subscribe((res) => { |
.subscribe((res) => { |
||||
this.msg.success(res.desc); |
this.msg.success(res.desc) |
||||
this.cancelFoodForm(); |
this.cancelFoodForm() |
||||
this.tableList.run(); |
this.tableList.run() |
||||
}); |
}) |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
cancelFoodForm() { |
cancelFoodForm() { |
||||
this.drawerRef?.close(); |
this.drawerRef?.close() |
||||
} |
} |
||||
|
|
||||
deleteFood(v?: any) { |
deleteFood(v?: any) { |
||||
const ids = v ? [v.key] : this.selectedIds; |
const ids = v ? [v.key] : this.selectedIds |
||||
this.modal.confirm({ |
this.modal.confirm({ |
||||
nzTitle: "警告", |
nzTitle: '警告', |
||||
nzContent: `是否要删除${ids.length}个食材?`, |
nzContent: `是否要删除${ids.length}个食材?`, |
||||
nzOkDanger: true, |
nzOkDanger: true, |
||||
nzOnOk: async () => { |
nzOnOk: async () => { |
||||
const res = await lastValueFrom(this.api.deleteFoods(ids)); |
const res = await lastValueFrom(this.api.deleteFoods(ids)) |
||||
this.msg.success(res.desc); |
this.msg.success(res.desc) |
||||
this.tableList.run(); |
this.tableList.run() |
||||
}, |
}, |
||||
}); |
}) |
||||
} |
} |
||||
|
|
||||
downloadTemplate() { |
downloadTemplate() { |
||||
this.api.getFoodExcelTemplate().subscribe((res) => { |
this.api.getFoodExcelTemplate().subscribe((res) => { |
||||
console.log("res", res); |
console.log('res', res) |
||||
}); |
}) |
||||
} |
} |
||||
|
|
||||
showImportForm(nzContent: TemplateRef<{}>) { |
showImportForm(nzContent: TemplateRef<{}>) { |
||||
this.importModalRef = this.modal.create({ |
this.importModalRef = this.modal.create({ |
||||
nzTitle: "导入食材清单", |
nzTitle: '导入食材清单', |
||||
nzWidth: 520, |
nzWidth: 520, |
||||
nzContent, |
nzContent, |
||||
nzFooter: null, |
nzFooter: null, |
||||
}); |
}) |
||||
} |
} |
||||
|
|
||||
suppress(e: Event) { |
suppress(e: Event) { |
||||
e.stopPropagation(); |
e.stopPropagation() |
||||
e.preventDefault(); |
e.preventDefault() |
||||
} |
} |
||||
|
|
||||
handleDrop = (e: Event) => { |
handleDrop = (e: Event) => { |
||||
e.stopPropagation(); |
e.stopPropagation() |
||||
e.preventDefault(); |
e.preventDefault() |
||||
const event = e as DragEvent; |
const event = e as DragEvent |
||||
const files = event.dataTransfer?.files; |
const files = event.dataTransfer?.files |
||||
if (files) { |
if (files) { |
||||
this.onFileChange(files); |
this.onFileChange(files) |
||||
} |
} |
||||
}; |
} |
||||
|
|
||||
onFileChange(e: FileList | Event) { |
onFileChange(e: FileList | Event) { |
||||
let files: FileList; |
let files: FileList |
||||
if (e instanceof FileList) { |
if (e instanceof FileList) { |
||||
files = e; |
files = e |
||||
} else { |
} else { |
||||
const target = e.target as HTMLInputElement; |
const target = e.target as HTMLInputElement |
||||
files = target.files!; |
files = target.files! |
||||
} |
} |
||||
if (files?.length > 0) { |
if (files?.length > 0) { |
||||
const formData = new FormData(); |
const formData = new FormData() |
||||
formData.append("file", files[0]); |
formData.append('file', files[0]) |
||||
this.uploadLoading = true; |
this.uploadLoading = true |
||||
this.api |
this.api |
||||
.importFood(formData) |
.importFood(formData) |
||||
.pipe( |
.pipe( |
||||
finalize(() => { |
finalize(() => { |
||||
this.uploadLoading = false; |
this.uploadLoading = false |
||||
}) |
}), |
||||
) |
) |
||||
.subscribe(() => { |
.subscribe(() => { |
||||
this.msg.success("导入成功"); |
this.msg.success('导入成功') |
||||
this.tableList.run(); |
this.tableList.run() |
||||
this.importModalRef?.close(); |
this.importModalRef?.close() |
||||
}); |
}) |
||||
} |
} |
||||
if (e instanceof Event) { |
if (e instanceof Event) { |
||||
const target = e.target as HTMLInputElement; |
const target = e.target as HTMLInputElement |
||||
target.value = ""; |
target.value = '' |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
@ -0,0 +1,33 @@ |
|||||
|
<table-list |
||||
|
#tableRef |
||||
|
[props]="tableList" |
||||
|
[search]="searchTpl" |
||||
|
[formGroup]="queryForm" |
||||
|
[renderColumns]="renderColumnsTpl" |
||||
|
> |
||||
|
<ng-template #searchTpl> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<input nz-input placeholder="请输入食材名称/编号" formControlName="keyword" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row"> |
||||
|
<ng-container [ngSwitch]="key"> |
||||
|
<ng-container *ngSwitchCase="'nutrientArr'"> |
||||
|
<div class="flex flex-wrap"> |
||||
|
<nz-tag *ngFor="let item of data" class="m-1"> |
||||
|
{{ item.label }}:{{ item.value }}{{ item.measurement }} |
||||
|
</nz-tag> |
||||
|
</div> |
||||
|
</ng-container> |
||||
|
<ng-container *ngSwitchCase="'modify'"> |
||||
|
{{ data | date : 'yyyy-MM-dd HH:mm:ss' }} |
||||
|
</ng-container> |
||||
|
<ng-container *ngSwitchDefault> |
||||
|
{{ data }} |
||||
|
</ng-container> |
||||
|
</ng-container> |
||||
|
</ng-template> |
||||
|
</table-list> |
@ -0,0 +1,66 @@ |
|||||
|
import { Component, OnInit, ViewChild } from '@angular/core' |
||||
|
import { FormControl, FormGroup } from '@angular/forms' |
||||
|
import { AnyObject, TableListComponent, TableListOption } from '@cdk/public-api' |
||||
|
import { ApiService } from '@cdk/services' |
||||
|
import { Subject, takeUntil, tap } from 'rxjs' |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'lib-select-food', |
||||
|
templateUrl: './select-food.component.html', |
||||
|
styleUrls: ['./select-food.component.less'], |
||||
|
}) |
||||
|
export class SelectFoodComponent implements OnInit { |
||||
|
constructor(private api: ApiService) {} |
||||
|
|
||||
|
@ViewChild('tableRef') tableRef!: TableListComponent |
||||
|
|
||||
|
selectedIds: string[] = [] |
||||
|
|
||||
|
allFood: any[] = [] |
||||
|
|
||||
|
private destroy$ = new Subject<void>() |
||||
|
|
||||
|
public tableList = new TableListOption(this.fetchData.bind(this), { |
||||
|
selectable: true, |
||||
|
frontPagination: false, |
||||
|
rowKey: 'key', |
||||
|
}) |
||||
|
|
||||
|
public queryForm = new FormGroup({ |
||||
|
keyword: new FormControl(''), |
||||
|
type: new FormControl(''), |
||||
|
}) |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => { |
||||
|
this.selectedIds = res.selectedKeys as Array<string> |
||||
|
}) |
||||
|
this.initTableList() |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy(): void { |
||||
|
this.destroy$.next() |
||||
|
this.destroy$.complete() |
||||
|
} |
||||
|
|
||||
|
fetchData(query: AnyObject, pager: AnyObject) { |
||||
|
return this.api.getFoodPage(pager, query).pipe( |
||||
|
tap((res) => { |
||||
|
this.allFood = this.allFood.concat(res.body.content) |
||||
|
}), |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
getSelectedFoods() { |
||||
|
return this.allFood.filter((f) => this.selectedIds.includes(f['key'])) |
||||
|
} |
||||
|
|
||||
|
initTableList() { |
||||
|
this.tableList.scroll = { x: null } |
||||
|
this.tableList = this.tableList.setColumns([ |
||||
|
{ key: 'key', title: '食材编号' }, |
||||
|
{ key: 'name', title: '食材名称' }, |
||||
|
{ key: 'type', title: '食材类型' }, |
||||
|
]) |
||||
|
} |
||||
|
} |
@ -1,225 +1,221 @@ |
|||||
<form nz-form class="query-form mb-2" [formGroup]="formGroup" [nzLayout]="searchLayout"> |
<form nz-form class="query-form mb-2" [formGroup]="formGroup" [nzLayout]="searchLayout"> |
||||
<div> |
<div> |
||||
<div nz-row> |
<div nz-row> |
||||
<div nz-col nzFlex="auto" nz-row [nzGutter]="[12,12]" class="search-row"> |
<div nz-col nzFlex="auto" nz-row [nzGutter]="[12, 12]" class="search-row"> |
||||
<ng-container> |
<ng-container> |
||||
<ng-container [ngTemplateOutlet]="search!"></ng-container> |
<ng-container [ngTemplateOutlet]="search!"></ng-container> |
||||
|
|
||||
<div nz-col nzFlex="120px"> |
<div nz-col nzFlex="120px"> |
||||
<nz-form-item> |
<nz-form-item> |
||||
<nz-form-label nzNoColon></nz-form-label> |
<nz-form-label nzNoColon></nz-form-label> |
||||
<nz-form-control> |
<nz-form-control> |
||||
<nz-space> |
<nz-space> |
||||
<button nz-button nzGhost nzType="primary" *nzSpaceItem (click)="doQuery()"> |
<button nz-button nzGhost nzType="primary" *nzSpaceItem (click)="doQuery()"> |
||||
查询 |
查询 |
||||
</button> |
</button> |
||||
<button nz-button *nzSpaceItem (click)="reset()"> |
<button nz-button *nzSpaceItem (click)="reset()">重置</button> |
||||
重置 |
</nz-space> |
||||
</button> |
</nz-form-control> |
||||
</nz-space> |
</nz-form-item> |
||||
</nz-form-control> |
</div> |
||||
</nz-form-item> |
</ng-container> |
||||
</div> |
</div> |
||||
</ng-container> |
<div nz-col class="flex items-center justify-end"> |
||||
</div> |
<ng-container *ngIf="action"> |
||||
<div nz-col class="flex items-center justify-end"> |
<ng-container [ngTemplateOutlet]="action"></ng-container> |
||||
<ng-container *ngIf="action"> |
</ng-container> |
||||
<ng-container [ngTemplateOutlet]="action"></ng-container> |
</div> |
||||
</ng-container> |
</div> |
||||
</div> |
</div> |
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
</form> |
</form> |
||||
|
|
||||
|
|
||||
<ng-template #renderTableTpl> |
<ng-template #renderTableTpl> |
||||
<div class="table-card table-list shadow-sm "> |
<div class="table-card table-list shadow-sm"> |
||||
<div #tableEl class="overflow-auto"> |
<div #tableEl class="overflow-auto"> |
||||
<nz-table |
<nz-table |
||||
#basicTable |
#basicTable |
||||
|
[nzData]="dataSource" |
||||
[nzData]="dataSource" |
[nzPageSizeOptions]="[5, 10, 20]" |
||||
[nzPageSizeOptions]="[5,10,20,]" |
[nzLoading]="props.pager.loading" |
||||
[nzLoading]="props.pager.loading" |
[(nzPageSize)]="props.pager.size" |
||||
[(nzPageSize)]="props.pager.size" |
[(nzPageIndex)]="props.pager.page" |
||||
[(nzPageIndex)]="props.pager.page" |
[nzTotal]="props.pager.total" |
||||
[nzTotal]="props.pager.total" |
[nzShowTotal]="totalTpl" |
||||
[nzShowTotal]="totalTpl" |
[nzFrontPagination]="props.frontPagination" |
||||
[nzFrontPagination]="props.frontPagination" |
[nzShowPagination]="true" |
||||
[nzShowPagination]="true" |
[nzShowSizeChanger]="true" |
||||
[nzShowSizeChanger]="true" |
[nzShowQuickJumper]="true" |
||||
[nzShowQuickJumper]="true" |
(nzPageIndexChange)="onPageChange()" |
||||
(nzPageIndexChange)="onPageChange()" |
(nzPageSizeChange)="onPageChange()" |
||||
(nzPageSizeChange)="onPageChange()" |
[nzTableLayout]="props.scroll.x ? 'fixed' : 'auto'" |
||||
[nzTableLayout]="props.scroll.x ? 'fixed' : 'auto' " |
[nzScroll]="props.scroll" |
||||
[nzScroll]="props.scroll"> |
> |
||||
<thead> |
<thead> |
||||
<tr> |
<tr> |
||||
<th |
<!-- [nzChecked]="dataSource && selection.selected.length === dataSource.length && dataSource.length !== 0" --> |
||||
*ngIf="props.selectable" |
<th |
||||
[nzChecked]="dataSource && selection.selected.length === dataSource.length && dataSource.length !== 0" |
*ngIf="props.selectable" |
||||
(nzCheckedChange)="onChecked($event)" |
[nzChecked]="checkedAll(dataSource)" |
||||
nzWidth="40px"> |
(nzCheckedChange)="onChecked($event)" |
||||
</th> |
nzWidth="40px" |
||||
<ng-container *ngFor="let col of columns"> |
></th> |
||||
<th *ngIf="col.visible" |
<ng-container *ngFor="let col of columns"> |
||||
[nzWidth]="col.width || null " |
<th |
||||
[nzShowSort]="col.sort" |
*ngIf="col.visible" |
||||
[nzSortDirections]="['ascend', 'descend']" |
[nzWidth]="col.width || null" |
||||
[nzSortOrder]="props.pager.sort[col.key] || null" |
[nzShowSort]="col.sort" |
||||
(nzSortOrderChange)="onSort($event,col.key)"> |
[nzSortDirections]="['ascend', 'descend']" |
||||
{{col.title}} |
[nzSortOrder]="props.pager.sort[col.key] || null" |
||||
</th> |
(nzSortOrderChange)="onSort($event, col.key)" |
||||
</ng-container> |
> |
||||
<th *ngIf="operation.length" [nzWidth]="optionWidth!" [nzRight]="!!props.scroll.x"> |
{{ col.title }} |
||||
操作 |
</th> |
||||
</th> |
</ng-container> |
||||
<th nzRight nzWidth="40px" *ngIf="props.theadSettable"> |
<th *ngIf="operation.length" [nzWidth]="optionWidth!" [nzRight]="!!props.scroll.x">操作</th> |
||||
<span (click)="toggleColumnVisible(columnVisibleSettingTpl)" |
<th nzRight nzWidth="40px" *ngIf="props.theadSettable"> |
||||
class="cursor-pointer" |
<span |
||||
nz-icon |
(click)="toggleColumnVisible(columnVisibleSettingTpl)" |
||||
nzType="setting" |
class="cursor-pointer" |
||||
nzTheme="outline"> |
nz-icon |
||||
</span> |
nzType="setting" |
||||
</th> |
nzTheme="outline" |
||||
</tr> |
> |
||||
</thead> |
</span> |
||||
<tbody> |
</th> |
||||
<tr *ngFor="let dataItem of basicTable.data" (click)="onTrClick(dataItem)" |
</tr> |
||||
[ngClass]="rowClass"> |
</thead> |
||||
<td *ngIf="props.selectable" [nzChecked]="selection.isSelected(dataItem[props.rowKey])" |
<tbody> |
||||
(nzCheckedChange)="onChecked($event,dataItem[props.rowKey])"> |
<tr *ngFor="let dataItem of basicTable.data" (click)="onTrClick(dataItem)" [ngClass]="rowClass"> |
||||
</td> |
<td |
||||
<ng-container *ngFor="let col of columns"> |
*ngIf="props.selectable" |
||||
<td *ngIf="col.visible" nzEllipsis> |
[nzChecked]="selection.isSelected(dataItem[props.rowKey])" |
||||
|
(nzCheckedChange)="onChecked($event, dataItem[props.rowKey])" |
||||
<ng-container [ngSwitch]="col.key"> |
></td> |
||||
<ng-container *ngSwitchCase="'createTime'"> |
<ng-container *ngFor="let col of columns"> |
||||
<ng-container |
<td *ngIf="col.visible" nzEllipsis> |
||||
[ngTemplateOutlet]="dateTimeTpl" |
<ng-container [ngSwitch]="col.key"> |
||||
[ngTemplateOutletContext]="{$implicit:dataItem[col.key]}"> |
<ng-container *ngSwitchCase="'createTime'"> |
||||
</ng-container> |
<ng-container |
||||
</ng-container> |
[ngTemplateOutlet]="dateTimeTpl" |
||||
<ng-container *ngSwitchCase="'updateTime'"> |
[ngTemplateOutletContext]="{ $implicit: dataItem[col.key] }" |
||||
<ng-container |
> |
||||
[ngTemplateOutlet]="dateTimeTpl" |
</ng-container> |
||||
[ngTemplateOutletContext]="{$implicit:dataItem[col.key]}"> |
</ng-container> |
||||
</ng-container> |
<ng-container *ngSwitchCase="'updateTime'"> |
||||
</ng-container> |
<ng-container |
||||
|
[ngTemplateOutlet]="dateTimeTpl" |
||||
<ng-container *ngSwitchDefault> |
[ngTemplateOutletContext]="{ $implicit: dataItem[col.key] }" |
||||
<ng-container *ngIf="renderColumns else defaultTdTpl" |
> |
||||
[ngTemplateOutlet]="renderColumns" |
</ng-container> |
||||
[ngTemplateOutletContext]="{ |
</ng-container> |
||||
$implicit:dataItem[col.key], |
|
||||
key:col.key, |
<ng-container *ngSwitchDefault> |
||||
row:dataItem, |
<ng-container |
||||
column:col |
*ngIf="renderColumns; else defaultTdTpl" |
||||
}"> |
[ngTemplateOutlet]="renderColumns" |
||||
</ng-container> |
[ngTemplateOutletContext]="{ |
||||
<ng-template #defaultTdTpl> |
$implicit: dataItem[col.key], |
||||
{{dataItem[col.key]}} |
key: col.key, |
||||
</ng-template> |
row: dataItem, |
||||
</ng-container> |
column: col |
||||
</ng-container> |
}" |
||||
</td> |
> |
||||
</ng-container> |
</ng-container> |
||||
|
<ng-template #defaultTdTpl> |
||||
<td *ngIf="operation.length" [nzRight]="!!props.scroll.x" class="operation"> |
{{ dataItem[col.key] }} |
||||
<dec-table-operation [rowData]="dataItem" [options]="operation"> |
</ng-template> |
||||
</dec-table-operation> |
</ng-container> |
||||
</td> |
</ng-container> |
||||
<td nzRight *ngIf="props.theadSettable"></td> |
</td> |
||||
</tr> |
</ng-container> |
||||
</tbody> |
|
||||
</nz-table> |
<td *ngIf="operation.length" [nzRight]="!!props.scroll.x" class="operation"> |
||||
</div> |
<dec-table-operation [rowData]="dataItem" [options]="operation"> </dec-table-operation> |
||||
|
</td> |
||||
</div> |
<td nzRight *ngIf="props.theadSettable"></td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</nz-table> |
||||
|
</div> |
||||
|
</div> |
||||
</ng-template> |
</ng-template> |
||||
|
|
||||
|
<ng-container *ngIf="renderItem; else renderTableTpl"> |
||||
|
<ng-container *ngIf="props.pager.loading"> |
||||
<ng-container *ngIf="renderItem else renderTableTpl"> |
<nz-card [nzBordered]="false"> |
||||
<ng-container *ngIf="props.pager.loading"> |
<nz-skeleton [nzActive]="true"></nz-skeleton> |
||||
<nz-card [nzBordered]="false"> |
</nz-card> |
||||
<nz-skeleton [nzActive]="true"></nz-skeleton> |
</ng-container> |
||||
</nz-card> |
<div class="custom-render" *ngIf="!props.pager.loading"> |
||||
</ng-container> |
<ng-container *ngIf="dataSource.length > 0; else emptyTpl"> |
||||
<div class="custom-render" *ngIf="!props.pager.loading"> |
<div> |
||||
<ng-container *ngIf="dataSource.length > 0 else emptyTpl"> |
<ng-container [ngTemplateOutlet]="renderItem" [ngTemplateOutletContext]="{ $implicit: dataSource }"> |
||||
<div> |
</ng-container> |
||||
<ng-container |
</div> |
||||
[ngTemplateOutlet]="renderItem" |
<div class="mt-4 flex justify-end"> |
||||
[ngTemplateOutletContext]="{$implicit:dataSource}"> |
<nz-pagination |
||||
</ng-container> |
[nzPageSizeOptions]="[10, 20, 50, 100]" |
||||
</div> |
[(nzPageSize)]="props.pager.size" |
||||
<div class="mt-4 flex justify-end"> |
[(nzPageIndex)]="props.pager.page" |
||||
<nz-pagination [nzPageSizeOptions]="[10,20,50,100]" |
[nzTotal]="props.pager.total" |
||||
[(nzPageSize)]="props.pager.size" |
[nzShowTotal]="totalTpl" |
||||
[(nzPageIndex)]="props.pager.page" |
[nzShowSizeChanger]="true" |
||||
[nzTotal]="props.pager.total" |
[nzShowQuickJumper]="true" |
||||
[nzShowTotal]="totalTpl" |
(nzPageIndexChange)="onPageChange()" |
||||
[nzShowSizeChanger]="true" |
(nzPageSizeChange)="onPageChange()" |
||||
[nzShowQuickJumper]="true" |
> |
||||
(nzPageIndexChange)="onPageChange()" |
</nz-pagination> |
||||
(nzPageSizeChange)="onPageChange()"> |
</div> |
||||
</nz-pagination> |
</ng-container> |
||||
</div> |
<ng-template #emptyTpl> |
||||
</ng-container> |
<nz-card [nzBordered]="false"> |
||||
<ng-template #emptyTpl> |
<nz-empty></nz-empty> |
||||
<nz-card [nzBordered]="false"> |
</nz-card> |
||||
<nz-empty></nz-empty> |
</ng-template> |
||||
</nz-card> |
</div> |
||||
</ng-template> |
|
||||
</div> |
|
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
|
|
||||
|
|
||||
<ng-template #columnVisibleSettingTpl> |
<ng-template #columnVisibleSettingTpl> |
||||
<nz-checkbox-wrapper class="w-full"> |
<nz-checkbox-wrapper class="w-full"> |
||||
<ul cdkDropList (cdkDropListDropped)="colunmsSort($event)" class="columns-list"> |
<ul cdkDropList (cdkDropListDropped)="colunmsSort($event)" class="columns-list"> |
||||
<li *ngFor="let item of columns" |
<li *ngFor="let item of columns" class="table-setting-item cursor-pointer" cdkDrag> |
||||
class="table-setting-item cursor-pointer" cdkDrag> |
<div class="columns-item-placeholder" *cdkDragPlaceholder></div> |
||||
<div class="columns-item-placeholder" *cdkDragPlaceholder></div> |
<div class="flex items-center justify-between p-2"> |
||||
<div class="flex items-center justify-between p-2"> |
<div class="flex-shrink-0"> |
||||
<div class="flex-shrink-0"> |
<span nz-icon nzType="holder" nzTheme="outline"></span> |
||||
<span nz-icon nzType="holder" nzTheme="outline"></span> |
</div> |
||||
</div> |
<div class="flex-1 pl-1"> |
||||
<div class="flex-1 pl-1"> |
{{ item.title }} |
||||
{{item.title}} |
</div> |
||||
</div> |
<div class="flex-shrink-0"> |
||||
<div class="flex-shrink-0"> |
<nz-switch |
||||
<nz-switch |
nzSize="small" |
||||
nzSize="small" |
[disabled]="!!item.disabled" |
||||
[disabled]="!!item.disabled" |
[(ngModel)]="item.visible" |
||||
[(ngModel)]="item.visible" |
(ngModelChange)="onColumnsChange()" |
||||
(ngModelChange)="onColumnsChange()"> |
> |
||||
</nz-switch> |
</nz-switch> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</li> |
</li> |
||||
</ul> |
</ul> |
||||
</nz-checkbox-wrapper> |
</nz-checkbox-wrapper> |
||||
</ng-template> |
</ng-template> |
||||
|
|
||||
<ng-template #totalTpl let-total> |
<ng-template #totalTpl let-total> |
||||
<ng-container *ngIf="showTotal"> |
<ng-container *ngIf="showTotal"> |
||||
<ng-template [ngTemplateOutlet]="showTotal" [ngTemplateOutletContext]="{$implicit:props.pager}"></ng-template> |
<ng-template |
||||
</ng-container> |
[ngTemplateOutlet]="showTotal" |
||||
<ng-container *ngIf="!showTotal"> |
[ngTemplateOutletContext]="{ $implicit: props.pager }" |
||||
共{{total}}条 |
></ng-template> |
||||
</ng-container> |
</ng-container> |
||||
|
<ng-container *ngIf="!showTotal"> 共{{ total }}条 </ng-container> |
||||
</ng-template> |
</ng-template> |
||||
|
|
||||
<ng-template #dateTimeTpl let-date> |
<ng-template #dateTimeTpl let-date> |
||||
{{date| date:'yyyy-MM-dd HH:mm:ss'}} |
{{ date | date : 'yyyy-MM-dd HH:mm:ss' }} |
||||
</ng-template> |
</ng-template> |
||||
|
|
||||
|
|
||||
<!-- 为了计算操作栏的宽度 ---- start --> |
<!-- 为了计算操作栏的宽度 ---- start --> |
||||
<dec-table-operation #operationEl [rowData]="{}" [options]="operation" class="hidden-option"> |
<dec-table-operation #operationEl [rowData]="{}" [options]="operation" class="hidden-option"> </dec-table-operation> |
||||
</dec-table-operation> |
|
||||
<!-- 为了计算操作栏的宽度 ---- end --> |
<!-- 为了计算操作栏的宽度 ---- end --> |
Loading…
Reference in new issue