Browse Source

食谱菜品支持修改食材

main
kkerwin 2 years ago
parent
commit
6087548d00
  1. 209
      projects/admin/src/app/pages/food/food.component.html
  2. 182
      projects/admin/src/app/pages/food/food.component.ts
  3. 149
      projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts
  4. 137
      projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.html
  5. 98
      projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.ts
  6. 51
      projects/cdk/src/ingredient/ingredient-analysis/ingredient-analysis.component.ts
  7. 51
      projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html
  8. 40
      projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.ts
  9. 4
      projects/cdk/src/ingredient/ingredient-preview/ingredient-preview.component.less
  10. 23
      projects/cdk/src/ingredient/ingredient.module.ts
  11. 33
      projects/cdk/src/ingredient/select-food/select-food.component.html
  12. 0
      projects/cdk/src/ingredient/select-food/select-food.component.less
  13. 66
      projects/cdk/src/ingredient/select-food/select-food.component.ts
  14. 410
      projects/cdk/src/table-list/table-list/table-list.component.html
  15. 285
      projects/cdk/src/table-list/table-list/table-list.component.ts

209
projects/admin/src/app/pages/food/food.component.html

@ -1,114 +1,111 @@
<app-page [scroll]="false">
<ng-template #pageExtraTpl>
<nz-space>
<button *nzSpaceItem nz-button [disabled]="!selectedIds.length" (click)="deleteFood()">批量删除</button>
<button *nzSpaceItem nz-button (click)="showImportForm(importFormTpl)">导入食材清单</button>
<button *nzSpaceItem nz-button nzType="primary" (click)="showFoodForm()">
<i nz-icon nzType="plus"></i>
新增食材
</button>
</nz-space>
</ng-template>
<div nz-row class="h-full overflow-hidden bg-white rounded-lg">
<div nz-col nzFlex="220px" class="food-type h-full">
<nz-card class="h-full" [nzBordered]="false" nzTitle="食材类型"
[nzBodyStyle]="{padding:'1px 0 0 0', height:'100%',overflow:'auto'}">
<ul nz-menu nzMode="inline">
<li nz-menu-item (click)="onTypeChange('')" [nzSelected]="!queryForm.get('type')?.value">
<a>
全部
</a>
</li>
<li nz-menu-item [nzSelected]="cate.key === queryForm.get('type')?.value"
*ngFor="let cate of globalEnum.category" (click)="onTypeChange(cate.key)">
<a>
{{cate.key}}
</a>
</li>
</ul>
</nz-card>
</div>
<div nz-col nzFlex="1" class="flex-1 overflow-hidden bg-white h-full">
<ng-template #pageExtraTpl>
<nz-space>
<button *nzSpaceItem nz-button [disabled]="!selectedIds.length" (click)="deleteFood()">批量删除</button>
<button *nzSpaceItem nz-button (click)="showImportForm(importFormTpl)">导入食材清单</button>
<button *nzSpaceItem nz-button nzType="primary" (click)="showFoodForm()">
<i nz-icon nzType="plus"></i>
新增食材
</button>
</nz-space>
</ng-template>
<div nz-row class="h-full overflow-hidden bg-white rounded-lg">
<div nz-col nzFlex="220px" class="food-type h-full">
<nz-card
class="h-full"
[nzBordered]="false"
nzTitle="食材类型"
[nzBodyStyle]="{ padding: '1px 0 0 0', height: '100%', overflow: 'auto' }"
>
<ul nz-menu nzMode="inline">
<li nz-menu-item (click)="onTypeChange('')" [nzSelected]="!queryForm.get('type')?.value">
<a> 全部 </a>
</li>
<li
nz-menu-item
[nzSelected]="cate.key === queryForm.get('type')?.value"
*ngFor="let cate of globalEnum.category"
(click)="onTypeChange(cate.key)"
>
<a>
{{ 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">
<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>
<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>
</div>
</nz-card>
</div>
</div>
<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>
</div>
</nz-card>
</div>
</div>
</app-page>
<ng-template #importFormTpl>
<p class=" text-slate-400">
提示:<a (click)="downloadTemplate()">下载示例模版</a>,进行编辑,导入Excel文件,批量导入食材
</p>
<div>
<nz-spin [nzSpinning]="uploadLoading">
<div class="upload-area flex-col"
(drop)="handleDrop($event)"
(dragenter)="suppress($event)"
(dragover)="suppress($event)">
<input type="file" id="file" (change)="onFileChange($event)" accept=".xlsx,.xls" />
<div class="text-center">
<p class="text-4xl mb-1">
<a nz-icon nzType="upload" nzTheme="outline"></a>
</p>
<p class="mb-1">
点击或将文件拖拽到这里上传
</p>
<p class="text-slate-400">
支持扩展名:.xls .xlsx
</p>
</div>
</div>
</nz-spin>
</div>
<p class="text-slate-400">
提示:<a (click)="downloadTemplate()">下载示例模版</a>,进行编辑,导入Excel文件,批量导入食材
</p>
<div>
<nz-spin [nzSpinning]="uploadLoading">
<div
class="upload-area flex-col"
(drop)="handleDrop($event)"
(dragenter)="suppress($event)"
(dragover)="suppress($event)"
>
<input type="file" id="file" (change)="onFileChange($event)" accept=".xlsx,.xls" />
<div class="text-center">
<p class="text-4xl mb-1">
<a nz-icon nzType="upload" nzTheme="outline"></a>
</p>
<p class="mb-1">点击或将文件拖拽到这里上传</p>
<p class="text-slate-400">支持扩展名:.xls .xlsx</p>
</div>
</div>
</nz-spin>
</div>
</ng-template>
<ng-template #foodFormFooterTpl>
<nz-space>
<button *nzSpaceItem nz-button (click)="cancelFoodForm()" type="button">
取消
</button>
<button *nzSpaceItem nz-button nzType="primary" [nzLoading]="submitLoading" (click)="onFoodSubmit()">
保存
</button>
</nz-space>
</ng-template>
<nz-space>
<button *nzSpaceItem nz-button (click)="cancelFoodForm()" type="button">取消</button>
<button *nzSpaceItem nz-button nzType="primary" [nzLoading]="submitLoading" (click)="onFoodSubmit()">
保存
</button>
</nz-space>
</ng-template>

182
projects/admin/src/app/pages/food/food.component.ts

@ -1,210 +1,210 @@
import { FoodFormComponent } from "@admin/app/components";
import { ApiService } from "@cdk/services";
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { AnyObject, TableListOption } from "@cdk/public-api";
import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer";
import { NzModalRef, NzModalService } from "ng-zorro-antd/modal";
import { Subject, finalize, lastValueFrom, map, takeUntil } from "rxjs";
import { NzMessageService } from "ng-zorro-antd/message";
import { FoodFormComponent } from '@admin/app/components'
import { ApiService } from '@cdk/services'
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { AnyObject, TableListOption } from '@cdk/public-api'
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer'
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal'
import { Subject, finalize, lastValueFrom, map, takeUntil } from 'rxjs'
import { NzMessageService } from 'ng-zorro-antd/message'
@Component({
selector: "app-food",
templateUrl: "./food.component.html",
styleUrls: ["./food.component.less"],
selector: 'app-food',
templateUrl: './food.component.html',
styleUrls: ['./food.component.less'],
})
export class FoodComponent implements OnInit, OnDestroy {
constructor(
private drawer: NzDrawerService,
private api: ApiService,
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), {
selectable: true,
frontPagination: false,
rowKey: "key",
});
rowKey: 'key',
})
public globalEnum = this.api.globalEnum;
public globalEnum = this.api.globalEnum
public queryForm = new FormGroup({
keyword: new FormControl(""),
type: new FormControl(""),
});
keyword: 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 {
this.initTableList();
this.initTableList()
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 {
this.destroy$.next();
this.destroy$.complete();
this.destroy$.next()
this.destroy$.complete()
}
initTableList() {
this.tableList.scroll = { x: null };
this.tableList.scroll = { x: null }
this.tableList = this.tableList.setColumns([
{ key: "key", title: "食材编号" },
{ key: "name", title: "食材名称" },
{ key: "type", title: "食材类型" },
{ key: "nutrientArr", title: "营养素(每100g可食部)", width: "40%" },
{ key: "modify", title: "更新日期" },
]);
{ key: 'key', title: '食材编号' },
{ key: 'name', title: '食材名称' },
{ key: 'type', title: '食材类型' },
{ key: 'nutrientArr', title: '营养素(每100g可食部)', width: '40%' },
{ key: 'modify', title: '更新日期' },
])
this.tableList = this.tableList.setOptions([
{
title: "编辑",
title: '编辑',
premissions: [],
onClick: this.showFoodForm.bind(this),
},
{
title: "删除",
title: '删除',
premissions: [],
onClick: this.deleteFood.bind(this),
},
]);
])
}
fetchData(query: AnyObject, pager: AnyObject) {
return this.api.getFoodPage(pager, query).pipe();
return this.api.getFoodPage(pager, query).pipe()
}
onTypeChange(type: string) {
this.queryForm.patchValue({ type });
this.tableList.reset();
this.queryForm.patchValue({ type })
this.tableList.reset()
}
showFoodForm(food?: any) {
this.editItem = food;
this.editItem = food
this.drawerRef = this.drawer.create({
nzTitle: food ? "编辑食材" : "新增食材",
nzTitle: food ? '编辑食材' : '新增食材',
nzWidth: 520,
nzContentParams: {
food,
},
nzContent: FoodFormComponent,
nzFooter: this.foodFormFooterTpl,
});
})
}
onFoodSubmit() {
if (this.drawerRef) {
const com = this.drawerRef.getContentComponent() as FoodFormComponent;
const val = com.getValues();
const com = this.drawerRef.getContentComponent() as FoodFormComponent
const val = com.getValues()
if (val) {
this.submitLoading = true;
this.submitLoading = true
this.api
.saveFood(val, !!this.editItem)
.pipe(
finalize(() => {
this.submitLoading = false;
})
this.submitLoading = false
}),
)
.subscribe((res) => {
this.msg.success(res.desc);
this.cancelFoodForm();
this.tableList.run();
});
this.msg.success(res.desc)
this.cancelFoodForm()
this.tableList.run()
})
}
}
}
cancelFoodForm() {
this.drawerRef?.close();
this.drawerRef?.close()
}
deleteFood(v?: any) {
const ids = v ? [v.key] : this.selectedIds;
const ids = v ? [v.key] : this.selectedIds
this.modal.confirm({
nzTitle: "警告",
nzTitle: '警告',
nzContent: `是否要删除${ids.length}个食材?`,
nzOkDanger: true,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteFoods(ids));
this.msg.success(res.desc);
this.tableList.run();
const res = await lastValueFrom(this.api.deleteFoods(ids))
this.msg.success(res.desc)
this.tableList.run()
},
});
})
}
downloadTemplate() {
this.api.getFoodExcelTemplate().subscribe((res) => {
console.log("res", res);
});
console.log('res', res)
})
}
showImportForm(nzContent: TemplateRef<{}>) {
this.importModalRef = this.modal.create({
nzTitle: "导入食材清单",
nzTitle: '导入食材清单',
nzWidth: 520,
nzContent,
nzFooter: null,
});
})
}
suppress(e: Event) {
e.stopPropagation();
e.preventDefault();
e.stopPropagation()
e.preventDefault()
}
handleDrop = (e: Event) => {
e.stopPropagation();
e.preventDefault();
const event = e as DragEvent;
const files = event.dataTransfer?.files;
e.stopPropagation()
e.preventDefault()
const event = e as DragEvent
const files = event.dataTransfer?.files
if (files) {
this.onFileChange(files);
this.onFileChange(files)
}
};
}
onFileChange(e: FileList | Event) {
let files: FileList;
let files: FileList
if (e instanceof FileList) {
files = e;
files = e
} else {
const target = e.target as HTMLInputElement;
files = target.files!;
const target = e.target as HTMLInputElement
files = target.files!
}
if (files?.length > 0) {
const formData = new FormData();
formData.append("file", files[0]);
this.uploadLoading = true;
const formData = new FormData()
formData.append('file', files[0])
this.uploadLoading = true
this.api
.importFood(formData)
.pipe(
finalize(() => {
this.uploadLoading = false;
})
this.uploadLoading = false
}),
)
.subscribe(() => {
this.msg.success("导入成功");
this.tableList.run();
this.importModalRef?.close();
});
this.msg.success('导入成功')
this.tableList.run()
this.importModalRef?.close()
})
}
if (e instanceof Event) {
const target = e.target as HTMLInputElement;
target.value = "";
const target = e.target as HTMLInputElement
target.value = ''
}
}
}

149
projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts

@ -1,20 +1,20 @@
import { Component, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { ConfirmIngredientComponent } from "@cdk/ingredient/confirm-ingredient/confirm-ingredient.component";
import { IngredientAnalysisComponent } from "@cdk/ingredient/ingredient-analysis/ingredient-analysis.component";
import { DishInterface, IngredientDishComponent } from "@cdk/ingredient/ingredient-dish/ingredient-dish.component";
import { MealDishInterface } from "@cdk/ingredient/ingredient-meals/ingredient-meals.component";
import { ApiService } from "@cdk/services";
import { OptionItemInterface } from "@cdk/types";
import { NzDrawerService } from "ng-zorro-antd/drawer";
import { NzMessageService } from "ng-zorro-antd/message";
import { NzModalService } from "ng-zorro-antd/modal";
import { forkJoin } from "rxjs";
import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { ConfirmIngredientComponent } from '@cdk/ingredient/confirm-ingredient/confirm-ingredient.component'
import { IngredientAnalysisComponent } from '@cdk/ingredient/ingredient-analysis/ingredient-analysis.component'
import { DishInterface, IngredientDishComponent } from '@cdk/ingredient/ingredient-dish/ingredient-dish.component'
import { MealDishInterface } from '@cdk/ingredient/ingredient-meals/ingredient-meals.component'
import { ApiService } from '@cdk/services'
import { OptionItemInterface } from '@cdk/types'
import { NzDrawerService } from 'ng-zorro-antd/drawer'
import { NzMessageService } from 'ng-zorro-antd/message'
import { NzModalService } from 'ng-zorro-antd/modal'
import { forkJoin } from 'rxjs'
@Component({
selector: "app-ingredient-form",
templateUrl: "./ingredient-form.component.html",
styleUrls: ["./ingredient-form.component.less"],
selector: 'app-ingredient-form',
templateUrl: './ingredient-form.component.html',
styleUrls: ['./ingredient-form.component.less'],
})
export class IngredientFormComponent implements OnInit {
constructor(
@ -23,59 +23,59 @@ export class IngredientFormComponent implements OnInit {
private router: Router,
private route: ActivatedRoute,
private api: ApiService,
private drawer: NzDrawerService
private drawer: NzDrawerService,
) {
this.id = this.route.snapshot.paramMap.get("id");
this.id = this.route.snapshot.paramMap.get('id')
}
@ViewChild("menuDish") menuDish!: IngredientDishComponent;
@ViewChild('menuDish') menuDish!: IngredientDishComponent
step = 0;
step = 0
id: string | null = "";
id: string | null = ''
menuItem: any = null;
menuItem: any = null
menuDishFormServer: any = null;
menuDishFormServer: any = null
ngOnInit(): void {
this.step = this.id && this.id !== "create" ? 1 : 0;
this.getDetail();
this.step = this.id && this.id !== 'create' ? 1 : 0
this.getDetail()
}
getDetail() {
if (this.id && this.id !== "create") {
const id = this.id.split(",")[0];
if (this.id && this.id !== 'create') {
const id = this.id.split(',')[0]
this.api.getMenuItem(id).subscribe((res) => {
if (res.body) {
this.menuItem = res.body;
this.menuItem = res.body
}
});
})
this.api.getMenuDist(id).subscribe((res) => {
if (Array.isArray(res.body)) {
res.body.forEach((d) => {
d.ingredient.forEach((f: any) => {
f["groupValues"] = Object.entries(f.value).map(([peopleName, value]) => {
f['groupValues'] = Object.entries(f.value).map(([peopleName, value]) => {
return {
peopleName,
value,
};
});
});
});
this.initMenuDish(res.body);
}
})
})
})
this.initMenuDish(res.body)
}
});
})
}
}
initMenuDish(menuDishFormServer: any[]) {
const foodIds = new Set<number>();
const foodIds = new Set<number>()
menuDishFormServer.forEach((i: any) => {
i.ingredient.map((food: any) => {
foodIds.add(food.key);
});
});
foodIds.add(food.key)
})
})
forkJoin([this.api.getFoodList({ keys: Array.from(foodIds) })]).subscribe(([res]) => {
this.menuDishFormServer = menuDishFormServer.map((i: any) => {
return {
@ -83,35 +83,35 @@ export class IngredientFormComponent implements OnInit {
dishName: i.name,
mealIndex: this.menuItem.meals.findIndex((m: string) => m === i.meal),
items: i.ingredient.map((food: any) => {
const fd = res.body.find((f) => f.key === food.key);
food.foodName = fd.name;
return food;
const fd = res.body.find((f) => f.key === food.key)
food.foodName = fd.name
return food
}),
};
});
});
}
})
})
}
onStepChange(idStr: string) {
this.step = 1;
this.id = idStr;
this.getDetail();
this.step = 1
this.id = String(idStr)
this.getDetail()
}
createNewMenu() {
this.modal.confirm({
nzTitle: "警告",
nzContent: "新建食谱将清空本次所有的配餐数据,确认要清空吗?",
nzTitle: '警告',
nzContent: '新建食谱将清空本次所有的配餐数据,确认要清空吗?',
nzOnOk: () => {
this.menuDish.mealDishList = [];
this.menuDish.mealDishList = []
},
});
})
}
analysis() {
this.drawer.create({
nzWidth: 720,
nzWrapClassName: "analysis-drawer",
nzWrapClassName: 'analysis-drawer',
nzContent: IngredientAnalysisComponent,
nzContentParams: {
menu: {
@ -120,59 +120,60 @@ export class IngredientFormComponent implements OnInit {
},
current: {},
},
});
})
}
previewMenu() {
const { mealDishList } = this.menuDish;
const snapshot = Date.now().toString();
const { mealDishList } = this.menuDish
const snapshot = Date.now().toString()
sessionStorage.setItem(
snapshot,
JSON.stringify({
basic: this.menuItem,
dishs: this.formatData(mealDishList),
})
);
window.open(`/ingredient/preview?snapshot=${snapshot}`);
}),
)
window.open(`/ingredient/preview?snapshot=${snapshot}`)
}
confirmSave() {
this.modal.create({
nzTitle: "确认食谱信息",
nzTitle: '确认食谱信息',
nzContent: ConfirmIngredientComponent,
nzData: this.menuItem,
nzWidth: 650,
nzOnOk: () => {
const { mealDishList } = this.menuDish;
const { mealDishList } = this.menuDish
this.api
.saveMenuDist({
menuIds: this.id?.split(","),
menuIds: String(this.id)?.split(','),
dishes: this.formatData(mealDishList),
})
.subscribe((res) => {
this.msg.success(res.desc);
this.router.navigate(["/ingredient/item/list"]);
});
this.msg.success(res.desc)
this.router.navigate(['/ingredient/item/list'])
})
},
});
})
}
formatData(d: DishInterface[]) {
const data: DishInterface[] = JSON.parse(JSON.stringify(d));
const data: DishInterface[] = JSON.parse(JSON.stringify(d))
data.forEach((dish) => {
dish["dishId"] = dish.dish;
dish['dishId'] = dish.dish
dish.items = dish.items.map((i) => {
return {
...i,
value: (i["groupValues"] as any[]).reduce((a, c) => {
value: (i['groupValues'] as any[]).reduce((a, c) => {
return {
...a,
[c.peopleName]: c.value,
};
}
}, {} as Record<string, number>),
};
});
});
return data;
}
})
})
return data
}
}

137
projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.html

@ -1,28 +1,28 @@
<div nz-form>
<div nz-row [nzGutter]="12">
<div nz-col nzSpan="14">
<nz-form-item>
<nz-form-label nzRequired="">菜品名称</nz-form-label>
<nz-form-control>
<!-- 请输入菜品名称搜索 -->
<app-dish-select [(ngModel)]="dish" (ngModelChange)="onDishChange($event)"></app-dish-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="10">
<nz-form-item>
<nz-form-label nzRequired="">菜品标签</nz-form-label>
<nz-form-control>
<nz-select nzPlaceHolder="请选择菜品标签" [(ngModel)]="mark">
<nz-option *ngFor="let item of globalEnum.mark" [nzValue]="item.value"
[nzLabel]="item.key"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
</div>
<div nz-row [nzGutter]="12">
<div nz-col nzSpan="14">
<nz-form-item>
<nz-form-label nzRequired="">菜品名称</nz-form-label>
<nz-form-control>
<!-- 请输入菜品名称搜索 -->
<app-dish-select [(ngModel)]="dish" (ngModelChange)="onDishChange($event)"></app-dish-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="10">
<nz-form-item>
<nz-form-label nzRequired="">菜品标签</nz-form-label>
<nz-form-control>
<nz-select nzPlaceHolder="请选择菜品标签" [(ngModel)]="mark">
<nz-option *ngFor="let item of globalEnum.mark" [nzValue]="item.value" [nzLabel]="item.key">
</nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
</div>
<!-- <nz-form-item>
<!-- <nz-form-item>
<nz-form-label nzRequired="">食材搜索方式</nz-form-label>
<nz-form-control>
<nz-radio-group nzButtonStyle="solid">
@ -32,44 +32,47 @@
</nz-form-control>
</nz-form-item> -->
<div>
<nz-table nzTemplateMode [nzBordered]="true" nzSize="small" [nzScroll]="{ x: '1000px' }">
<thead>
<tr>
<!-- <th nzWidth="80px" nzLeft>删除</th> -->
<th nzWidth="200px" nzLeft>食材</th>
<th nzWidth="80px" nzLeft>是否主料</th>
<th *ngFor="let p of peopleGroups" nzWidth="120px">
{{ p }}
</th>
<div>
<nz-table nzTemplateMode [nzBordered]="true" nzSize="small" [nzScroll]="{ x: '1000px' }">
<thead>
<tr>
<th nzWidth="200px">
食材
</th>
<th nzWidth="80px">
是否主料
</th>
<th *ngFor="let p of peopleGroups" nzWidth="120px">
{{p}}
</th>
<!-- <th nzRight nzWidth="150px">
<!-- <th nzRight nzWidth="150px">
操作
</th> -->
</tr>
</thead>
<tbody>
<tr *ngFor="let item of foods">
<td>
{{item.foodName}}
</td>
<td>
<nz-switch
[(ngModel)]="item.isMain"
[nzDisabled]="true"
nzCheckedChildren="是"
nzUnCheckedChildren="否">
</nz-switch>
</td>
<td *ngFor="let p of item.groupValues">
<nz-input-group nzAddOnAfter="g">
<input nz-input type="number" min="0" placeholder="重量" [(ngModel)]="p.value" />
</nz-input-group>
</td>
<!-- <td nzRight>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of foods">
<!-- <td nzLeft>
<button nz-button nzType="link" (click)="deleteFood(item)">
<i nz-icon nzType="delete"></i>
</button>
</td> -->
<td nzLeft>
{{ item.foodName }}
</td>
<td nzLeft>
<nz-switch
[(ngModel)]="item.isMain"
[nzDisabled]="true"
nzCheckedChildren="是"
nzUnCheckedChildren="否"
>
</nz-switch>
</td>
<td *ngFor="let p of item.groupValues">
<nz-input-group nzAddOnAfter="g" class="w-28">
<input nz-input type="number" min="0" placeholder="重量" [(ngModel)]="p.value" />
</nz-input-group>
</td>
<!-- <td nzRight>
<nz-space nzSize="small">
<button *nzSpaceItem nz-button nzType="link">
修改
@ -79,10 +82,14 @@
</button>
</nz-space>
</td> -->
</tr>
</tbody>
</nz-table>
<nz-empty class="mt-4" *ngIf="foods.length === 0"></nz-empty>
</div>
</div>
</tr>
<!-- <tr *ngIf="dish">
<td [attr.colspan]="peopleGroups.length + 3">
<button nz-button [nzBlock]="true" (click)="addNewFood()">新增食材</button>
</td>
</tr> -->
</tbody>
</nz-table>
<nz-empty class="mt-4" *ngIf="foods.length === 0"></nz-empty>
</div>
</div>

98
projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.ts

@ -1,34 +1,36 @@
import { Component, Input, OnInit } from "@angular/core";
import { ApiService } from "@cdk/services";
import { Component, Input, OnInit } from '@angular/core'
import { ApiService } from '@cdk/services'
import { NzModalService } from 'ng-zorro-antd/modal'
import { SelectFoodComponent } from '../select-food/select-food.component'
export interface FoodInDishInterface {
foodName: string;
key: string;
isMain: boolean;
foodName: string
key: string
isMain: boolean
groupValues: Array<{
peopleName: string;
value: number;
}>;
value: Record<string, number>;
peopleName: string
value: number
}>
value: Record<string, number>
}
@Component({
selector: "app-add-dish-to-ingredient",
templateUrl: "./add-dish-to-ingredient.component.html",
styleUrls: ["./add-dish-to-ingredient.component.less"],
selector: 'app-add-dish-to-ingredient',
templateUrl: './add-dish-to-ingredient.component.html',
styleUrls: ['./add-dish-to-ingredient.component.less'],
})
export class AddDishToIngredientComponent implements OnInit {
constructor(private api: ApiService) {}
constructor(private api: ApiService, private modal: NzModalService) {}
@Input() peopleGroups: string[] = [];
@Input() peopleGroups: string[] = []
globalEnum = this.api.globalEnum;
globalEnum = this.api.globalEnum
dish: any = null;
dish: any = null
mark: string = "";
mark: string = ''
foods: FoodInDishInterface[] = [];
foods: FoodInDishInterface[] = []
ngOnInit(): void {
// console.log("this.peopleGroups", this.peopleGroups);
@ -36,30 +38,50 @@ export class AddDishToIngredientComponent implements OnInit {
onDishChange(dish: any) {
if (dish) {
this.dish = dish;
this.mark = dish.marks;
this.getFoodNameByKeys(dish.ingredient);
this.dish = dish
this.mark = dish.marks
this.getFoodNameByKeys(dish.ingredient)
}
}
getFoodNameByKeys(foods: any[]) {
const keys = foods.map((i) => i.key);
const keys = foods.map((i) => i.key)
this.api.getFoodList({ keys }).subscribe((res) => {
this.foods = res.body.map((i) => {
const value = this.dish?.ingredient?.find((f: any) => f["key"] === i.key)?.value ?? 0;
return {
foodName: i.name,
key: i.key,
isMain: foods.find((f) => f.key === i.key)?.isMain ?? false,
groupValues: this.peopleGroups.map((p) => {
return {
peopleName: p,
value,
};
}),
value: {},
};
});
});
this.foods = this.addPeopleToFood(res.body, foods)
})
}
addPeopleToFood(pureFoods: any[], foods: any[] = []): FoodInDishInterface[] {
return pureFoods.map((i) => {
const value = this.dish?.ingredient?.find((f: any) => f['key'] === i.key)?.value ?? 0
return {
foodName: i.name,
key: i.key,
isMain: foods.find((f) => f.key === i.key)?.isMain ?? false,
groupValues: this.peopleGroups.map((p) => {
return {
peopleName: p,
value,
}
}),
value: {},
}
})
}
deleteFood(food: FoodInDishInterface) {
this.foods = this.foods.filter((f) => f.key !== food.key)
}
addNewFood() {
this.modal.create({
nzTitle: '添加食材',
nzContent: SelectFoodComponent,
nzWidth: 800,
nzOnOk: (e) => {
const newSelectedFoods = e.getSelectedFoods()
this.foods = this.foods.concat(this.addPeopleToFood(newSelectedFoods, []))
},
})
}
}

51
projects/cdk/src/ingredient/ingredient-analysis/ingredient-analysis.component.ts

@ -113,32 +113,29 @@ export class IngredientAnalysisComponent implements OnInit {
}
nzSelectedIndexChange(d: any) {
if (d === 2) {
const xAxis: string[] = Object.keys(this.suger['oil']).map((i: any) => weekdayMap[i])
const series: any[] = []
Object.entries(this.suger).forEach(([k, v]) => {
if (k !== 'crow') {
series.push({
type: 'line',
name: sugerMap.get(k),
data: Object.values(v as any),
})
}
})
const option = {
legend: {},
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: xAxis },
yAxis: {},
series,
}
if (!this.sugerRef) {
this.sugerRef = init(this.sugerEl.nativeElement)
}
this.sugerRef.setOption(option)
}
// if (d === 2) {
// const xAxis: string[] = Object.keys(this.suger['oil']).map((i: any) => weekdayMap[i])
// const series: any[] = []
// Object.entries(this.suger).forEach(([k, v]) => {
// if (k !== 'crow') {
// series.push({
// type: 'line',
// name: sugerMap.get(k),
// data: Object.values(v as any),
// })
// }
// })
// const option = {
// legend: {},
// tooltip: { trigger: 'axis' },
// xAxis: { type: 'category', data: xAxis },
// yAxis: {},
// series,
// }
// if (!this.sugerRef) {
// this.sugerRef = init(this.sugerEl.nativeElement)
// }
// this.sugerRef.setOption(option)
// }
}
}

51
projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html

@ -17,7 +17,7 @@
</tr> -->
<tr>
<th nzWidth="200px" nzLeft class="placeholder-th">&nbsp;</th>
<th nzWidth="300px" nzLeft class="placeholder-th">&nbsp;</th>
<th nzWidth="200px" nzLeft>
<span class="absolute top-2 left-[500px] z-10 w-[150px] h-[40px]">重量/克</span>
</th>
@ -49,16 +49,18 @@
</nz-tag>
</div>
</div>
<button nz-button nzType="text" (click)="onRemoveDish(dish, dishIndex)">
<i nz-icon nzType="delete"></i>
<button nz-button nzType="text" nz-dropdown [nzDropdownMenu]="dishOptions">
<i nz-icon nzType="more"></i>
</button>
<!-- nz-dropdown [nzDropdownMenu]="dishOptions" -->
<!-- <nz-dropdown-menu #dishOptions="nzDropdownMenu">
<ul nz-menu nzSelectable class=" w-20">
<li nz-menu-item>编辑</li>
<li nz-menu-item nzDanger>删除</li>
</ul>
</nz-dropdown-menu> -->
<nz-dropdown-menu #dishOptions="nzDropdownMenu">
<ul nz-menu nzSelectable class="w-20">
<li nz-menu-item (click)="addNewFood(dish)">新增食材</li>
<li nz-menu-item nzDanger (click)="onRemoveDish(dish, dishIndex)">
删除菜品
</li>
</ul>
</nz-dropdown-menu>
</div>
</td>
<td nzLeft>
@ -66,19 +68,28 @@
<span>
{{ food['foodName'] }}
</span>
<!-- <button nz-button nzType="text" nz-dropdown [nzDropdownMenu]="foodOptions">
<i nz-icon nzType="more"></i>
</button>
<nz-dropdown-menu #foodOptions="nzDropdownMenu">
<ul nz-menu nzSelectable class="w-100">
<li nz-menu-item>设置价格</li>
<li nz-menu-item nzDanger>删除</li>
</ul>
</nz-dropdown-menu> -->
<button nz-button nzType="text" nz-dropdown [nzDropdownMenu]="foodOptions">
<i nz-icon nzType="more"></i>
</button>
<nz-dropdown-menu #foodOptions="nzDropdownMenu">
<ul nz-menu nzSelectable class="w-100">
<!-- <li nz-menu-item>设置价格</li> -->
<li nz-menu-item nzDanger (click)="removeFood(dish, food['key'])">
删除食材
</li>
</ul>
</nz-dropdown-menu>
</div>
</td>
<td *ngFor="let g of food['groupValues']">
<input nz-input type="number" [(ngModel)]="g.value" (ngModelChange)="onValueChange()" />
<nz-input-group nzAddOnAfter="g" class="w-28">
<input
nz-input
type="number"
[(ngModel)]="g.value"
(ngModelChange)="onValueChange()"
/>
</nz-input-group>
</td>
</tr>
</ng-container>

40
projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.ts

@ -18,6 +18,7 @@ import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer'
import { NzMessageService } from 'ng-zorro-antd/message'
import { Augmented } from '@cdk/types'
import { DishInterface } from '../ingredient-dish/ingredient-dish.component'
import { SelectFoodComponent } from '../select-food/select-food.component'
export type MealDishInterface = Augmented<{
dishId: number
@ -101,6 +102,45 @@ export class IngredientMealsComponent implements OnChanges, OnInit {
})
}
addNewFood(d: DishInterface) {
this.modal.create({
nzTitle: '添加食材',
nzContent: SelectFoodComponent,
nzWidth: 800,
nzOnOk: (e) => {
const newSelectedFoods = e.getSelectedFoods()
d.items = d.items.concat(this.addPeopleToFood(newSelectedFoods))
this.calcTotal()
},
})
}
addPeopleToFood(pureFoods: any[]): FoodInDishInterface[] {
return pureFoods.map((i) => {
return {
foodName: i.name,
key: i.key,
isMain: false,
groupValues: this.peopleGroups.map((p) => {
return {
peopleName: p,
value: 0,
}
}),
value: {},
}
})
}
removeFood(d: DishInterface, foodKey: string) {
d.items = d.items.filter((f) => f.key !== foodKey)
if (d.items.length === 0) {
this.mealDishs = this.mealDishs.filter((d) => d.dish !== d.dish)
}
this.calcTotal()
}
clearThisMeal() {
this.modal.confirm({
nzTitle: '警告',

4
projects/cdk/src/ingredient/ingredient-preview/ingredient-preview.component.less

@ -17,6 +17,10 @@
min-height: 200px;
padding-bottom: 42px;
>div:not(:last-child) {
border-bottom: 1px solid #e8e8e8;
}
.total {
position: absolute;
bottom: 0;

23
projects/cdk/src/ingredient/ingredient.module.ts

@ -1,13 +1,14 @@
import { NgModule } from "@angular/core";
import { SharedModule } from "@cdk/shared/shared.module";
import { AddDishToIngredientComponent } from "./add-dish-to-ingredient/add-dish-to-ingredient.component";
import { IngredientMealsComponent } from "./ingredient-meals/ingredient-meals.component";
import { ConfirmIngredientComponent } from "./confirm-ingredient/confirm-ingredient.component";
import { IngredientDishComponent } from "./ingredient-dish/ingredient-dish.component";
import { IngredientFormBasicComponent } from "./ingredient-form-basic/ingredient-form-basic.component";
import { IngredientPreviewComponent } from "./ingredient-preview/ingredient-preview.component";
import { IngredientAnalysisComponent } from "./ingredient-analysis/ingredient-analysis.component";
import { NutritionTableComponent } from "./nutrition-table/nutrition-table.component";
import { NgModule } from '@angular/core'
import { SharedModule } from '@cdk/shared/shared.module'
import { AddDishToIngredientComponent } from './add-dish-to-ingredient/add-dish-to-ingredient.component'
import { IngredientMealsComponent } from './ingredient-meals/ingredient-meals.component'
import { ConfirmIngredientComponent } from './confirm-ingredient/confirm-ingredient.component'
import { IngredientDishComponent } from './ingredient-dish/ingredient-dish.component'
import { IngredientFormBasicComponent } from './ingredient-form-basic/ingredient-form-basic.component'
import { IngredientPreviewComponent } from './ingredient-preview/ingredient-preview.component'
import { IngredientAnalysisComponent } from './ingredient-analysis/ingredient-analysis.component'
import { NutritionTableComponent } from './nutrition-table/nutrition-table.component'
import { SelectFoodComponent } from './select-food/select-food.component'
@NgModule({
declarations: [
@ -19,6 +20,7 @@ import { NutritionTableComponent } from "./nutrition-table/nutrition-table.compo
IngredientPreviewComponent,
IngredientAnalysisComponent,
NutritionTableComponent,
SelectFoodComponent,
],
imports: [SharedModule],
exports: [
@ -30,6 +32,7 @@ import { NutritionTableComponent } from "./nutrition-table/nutrition-table.compo
IngredientPreviewComponent,
IngredientAnalysisComponent,
NutritionTableComponent,
SelectFoodComponent,
],
})
export class IngredientModule {}

33
projects/cdk/src/ingredient/select-food/select-food.component.html

@ -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
projects/cdk/src/ingredient/select-food/select-food.component.less

66
projects/cdk/src/ingredient/select-food/select-food.component.ts

@ -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: '食材类型' },
])
}
}

410
projects/cdk/src/table-list/table-list/table-list.component.html

@ -1,225 +1,221 @@
<form nz-form class="query-form mb-2" [formGroup]="formGroup" [nzLayout]="searchLayout">
<div>
<div nz-row>
<div nz-col nzFlex="auto" nz-row [nzGutter]="[12,12]" class="search-row">
<ng-container>
<ng-container [ngTemplateOutlet]="search!"></ng-container>
<div nz-col nzFlex="120px">
<nz-form-item>
<nz-form-label nzNoColon></nz-form-label>
<nz-form-control>
<nz-space>
<button nz-button nzGhost nzType="primary" *nzSpaceItem (click)="doQuery()">
查询
</button>
<button nz-button *nzSpaceItem (click)="reset()">
重置
</button>
</nz-space>
</nz-form-control>
</nz-form-item>
</div>
</ng-container>
</div>
<div nz-col class="flex items-center justify-end">
<ng-container *ngIf="action">
<ng-container [ngTemplateOutlet]="action"></ng-container>
</ng-container>
</div>
</div>
</div>
<div>
<div nz-row>
<div nz-col nzFlex="auto" nz-row [nzGutter]="[12, 12]" class="search-row">
<ng-container>
<ng-container [ngTemplateOutlet]="search!"></ng-container>
<div nz-col nzFlex="120px">
<nz-form-item>
<nz-form-label nzNoColon></nz-form-label>
<nz-form-control>
<nz-space>
<button nz-button nzGhost nzType="primary" *nzSpaceItem (click)="doQuery()">
查询
</button>
<button nz-button *nzSpaceItem (click)="reset()">重置</button>
</nz-space>
</nz-form-control>
</nz-form-item>
</div>
</ng-container>
</div>
<div nz-col class="flex items-center justify-end">
<ng-container *ngIf="action">
<ng-container [ngTemplateOutlet]="action"></ng-container>
</ng-container>
</div>
</div>
</div>
</form>
<ng-template #renderTableTpl>
<div class="table-card table-list shadow-sm ">
<div #tableEl class="overflow-auto">
<nz-table
#basicTable
[nzData]="dataSource"
[nzPageSizeOptions]="[5,10,20,]"
[nzLoading]="props.pager.loading"
[(nzPageSize)]="props.pager.size"
[(nzPageIndex)]="props.pager.page"
[nzTotal]="props.pager.total"
[nzShowTotal]="totalTpl"
[nzFrontPagination]="props.frontPagination"
[nzShowPagination]="true"
[nzShowSizeChanger]="true"
[nzShowQuickJumper]="true"
(nzPageIndexChange)="onPageChange()"
(nzPageSizeChange)="onPageChange()"
[nzTableLayout]="props.scroll.x ? 'fixed' : 'auto' "
[nzScroll]="props.scroll">
<thead>
<tr>
<th
*ngIf="props.selectable"
[nzChecked]="dataSource && selection.selected.length === dataSource.length && dataSource.length !== 0"
(nzCheckedChange)="onChecked($event)"
nzWidth="40px">
</th>
<ng-container *ngFor="let col of columns">
<th *ngIf="col.visible"
[nzWidth]="col.width || null "
[nzShowSort]="col.sort"
[nzSortDirections]="['ascend', 'descend']"
[nzSortOrder]="props.pager.sort[col.key] || null"
(nzSortOrderChange)="onSort($event,col.key)">
{{col.title}}
</th>
</ng-container>
<th *ngIf="operation.length" [nzWidth]="optionWidth!" [nzRight]="!!props.scroll.x">
操作
</th>
<th nzRight nzWidth="40px" *ngIf="props.theadSettable">
<span (click)="toggleColumnVisible(columnVisibleSettingTpl)"
class="cursor-pointer"
nz-icon
nzType="setting"
nzTheme="outline">
</span>
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let dataItem of basicTable.data" (click)="onTrClick(dataItem)"
[ngClass]="rowClass">
<td *ngIf="props.selectable" [nzChecked]="selection.isSelected(dataItem[props.rowKey])"
(nzCheckedChange)="onChecked($event,dataItem[props.rowKey])">
</td>
<ng-container *ngFor="let col of columns">
<td *ngIf="col.visible" nzEllipsis>
<ng-container [ngSwitch]="col.key">
<ng-container *ngSwitchCase="'createTime'">
<ng-container
[ngTemplateOutlet]="dateTimeTpl"
[ngTemplateOutletContext]="{$implicit:dataItem[col.key]}">
</ng-container>
</ng-container>
<ng-container *ngSwitchCase="'updateTime'">
<ng-container
[ngTemplateOutlet]="dateTimeTpl"
[ngTemplateOutletContext]="{$implicit:dataItem[col.key]}">
</ng-container>
</ng-container>
<ng-container *ngSwitchDefault>
<ng-container *ngIf="renderColumns else defaultTdTpl"
[ngTemplateOutlet]="renderColumns"
[ngTemplateOutletContext]="{
$implicit:dataItem[col.key],
key:col.key,
row:dataItem,
column:col
}">
</ng-container>
<ng-template #defaultTdTpl>
{{dataItem[col.key]}}
</ng-template>
</ng-container>
</ng-container>
</td>
</ng-container>
<td *ngIf="operation.length" [nzRight]="!!props.scroll.x" class="operation">
<dec-table-operation [rowData]="dataItem" [options]="operation">
</dec-table-operation>
</td>
<td nzRight *ngIf="props.theadSettable"></td>
</tr>
</tbody>
</nz-table>
</div>
</div>
<div class="table-card table-list shadow-sm">
<div #tableEl class="overflow-auto">
<nz-table
#basicTable
[nzData]="dataSource"
[nzPageSizeOptions]="[5, 10, 20]"
[nzLoading]="props.pager.loading"
[(nzPageSize)]="props.pager.size"
[(nzPageIndex)]="props.pager.page"
[nzTotal]="props.pager.total"
[nzShowTotal]="totalTpl"
[nzFrontPagination]="props.frontPagination"
[nzShowPagination]="true"
[nzShowSizeChanger]="true"
[nzShowQuickJumper]="true"
(nzPageIndexChange)="onPageChange()"
(nzPageSizeChange)="onPageChange()"
[nzTableLayout]="props.scroll.x ? 'fixed' : 'auto'"
[nzScroll]="props.scroll"
>
<thead>
<tr>
<!-- [nzChecked]="dataSource && selection.selected.length === dataSource.length && dataSource.length !== 0" -->
<th
*ngIf="props.selectable"
[nzChecked]="checkedAll(dataSource)"
(nzCheckedChange)="onChecked($event)"
nzWidth="40px"
></th>
<ng-container *ngFor="let col of columns">
<th
*ngIf="col.visible"
[nzWidth]="col.width || null"
[nzShowSort]="col.sort"
[nzSortDirections]="['ascend', 'descend']"
[nzSortOrder]="props.pager.sort[col.key] || null"
(nzSortOrderChange)="onSort($event, col.key)"
>
{{ col.title }}
</th>
</ng-container>
<th *ngIf="operation.length" [nzWidth]="optionWidth!" [nzRight]="!!props.scroll.x">操作</th>
<th nzRight nzWidth="40px" *ngIf="props.theadSettable">
<span
(click)="toggleColumnVisible(columnVisibleSettingTpl)"
class="cursor-pointer"
nz-icon
nzType="setting"
nzTheme="outline"
>
</span>
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let dataItem of basicTable.data" (click)="onTrClick(dataItem)" [ngClass]="rowClass">
<td
*ngIf="props.selectable"
[nzChecked]="selection.isSelected(dataItem[props.rowKey])"
(nzCheckedChange)="onChecked($event, dataItem[props.rowKey])"
></td>
<ng-container *ngFor="let col of columns">
<td *ngIf="col.visible" nzEllipsis>
<ng-container [ngSwitch]="col.key">
<ng-container *ngSwitchCase="'createTime'">
<ng-container
[ngTemplateOutlet]="dateTimeTpl"
[ngTemplateOutletContext]="{ $implicit: dataItem[col.key] }"
>
</ng-container>
</ng-container>
<ng-container *ngSwitchCase="'updateTime'">
<ng-container
[ngTemplateOutlet]="dateTimeTpl"
[ngTemplateOutletContext]="{ $implicit: dataItem[col.key] }"
>
</ng-container>
</ng-container>
<ng-container *ngSwitchDefault>
<ng-container
*ngIf="renderColumns; else defaultTdTpl"
[ngTemplateOutlet]="renderColumns"
[ngTemplateOutletContext]="{
$implicit: dataItem[col.key],
key: col.key,
row: dataItem,
column: col
}"
>
</ng-container>
<ng-template #defaultTdTpl>
{{ dataItem[col.key] }}
</ng-template>
</ng-container>
</ng-container>
</td>
</ng-container>
<td *ngIf="operation.length" [nzRight]="!!props.scroll.x" class="operation">
<dec-table-operation [rowData]="dataItem" [options]="operation"> </dec-table-operation>
</td>
<td nzRight *ngIf="props.theadSettable"></td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</ng-template>
<ng-container *ngIf="renderItem else renderTableTpl">
<ng-container *ngIf="props.pager.loading">
<nz-card [nzBordered]="false">
<nz-skeleton [nzActive]="true"></nz-skeleton>
</nz-card>
</ng-container>
<div class="custom-render" *ngIf="!props.pager.loading">
<ng-container *ngIf="dataSource.length > 0 else emptyTpl">
<div>
<ng-container
[ngTemplateOutlet]="renderItem"
[ngTemplateOutletContext]="{$implicit:dataSource}">
</ng-container>
</div>
<div class="mt-4 flex justify-end">
<nz-pagination [nzPageSizeOptions]="[10,20,50,100]"
[(nzPageSize)]="props.pager.size"
[(nzPageIndex)]="props.pager.page"
[nzTotal]="props.pager.total"
[nzShowTotal]="totalTpl"
[nzShowSizeChanger]="true"
[nzShowQuickJumper]="true"
(nzPageIndexChange)="onPageChange()"
(nzPageSizeChange)="onPageChange()">
</nz-pagination>
</div>
</ng-container>
<ng-template #emptyTpl>
<nz-card [nzBordered]="false">
<nz-empty></nz-empty>
</nz-card>
</ng-template>
</div>
<ng-container *ngIf="renderItem; else renderTableTpl">
<ng-container *ngIf="props.pager.loading">
<nz-card [nzBordered]="false">
<nz-skeleton [nzActive]="true"></nz-skeleton>
</nz-card>
</ng-container>
<div class="custom-render" *ngIf="!props.pager.loading">
<ng-container *ngIf="dataSource.length > 0; else emptyTpl">
<div>
<ng-container [ngTemplateOutlet]="renderItem" [ngTemplateOutletContext]="{ $implicit: dataSource }">
</ng-container>
</div>
<div class="mt-4 flex justify-end">
<nz-pagination
[nzPageSizeOptions]="[10, 20, 50, 100]"
[(nzPageSize)]="props.pager.size"
[(nzPageIndex)]="props.pager.page"
[nzTotal]="props.pager.total"
[nzShowTotal]="totalTpl"
[nzShowSizeChanger]="true"
[nzShowQuickJumper]="true"
(nzPageIndexChange)="onPageChange()"
(nzPageSizeChange)="onPageChange()"
>
</nz-pagination>
</div>
</ng-container>
<ng-template #emptyTpl>
<nz-card [nzBordered]="false">
<nz-empty></nz-empty>
</nz-card>
</ng-template>
</div>
</ng-container>
<ng-template #columnVisibleSettingTpl>
<nz-checkbox-wrapper class="w-full">
<ul cdkDropList (cdkDropListDropped)="colunmsSort($event)" class="columns-list">
<li *ngFor="let item of columns"
class="table-setting-item cursor-pointer" cdkDrag>
<div class="columns-item-placeholder" *cdkDragPlaceholder></div>
<div class="flex items-center justify-between p-2">
<div class="flex-shrink-0">
<span nz-icon nzType="holder" nzTheme="outline"></span>
</div>
<div class="flex-1 pl-1">
{{item.title}}
</div>
<div class="flex-shrink-0">
<nz-switch
nzSize="small"
[disabled]="!!item.disabled"
[(ngModel)]="item.visible"
(ngModelChange)="onColumnsChange()">
</nz-switch>
</div>
</div>
</li>
</ul>
</nz-checkbox-wrapper>
<nz-checkbox-wrapper class="w-full">
<ul cdkDropList (cdkDropListDropped)="colunmsSort($event)" class="columns-list">
<li *ngFor="let item of columns" class="table-setting-item cursor-pointer" cdkDrag>
<div class="columns-item-placeholder" *cdkDragPlaceholder></div>
<div class="flex items-center justify-between p-2">
<div class="flex-shrink-0">
<span nz-icon nzType="holder" nzTheme="outline"></span>
</div>
<div class="flex-1 pl-1">
{{ item.title }}
</div>
<div class="flex-shrink-0">
<nz-switch
nzSize="small"
[disabled]="!!item.disabled"
[(ngModel)]="item.visible"
(ngModelChange)="onColumnsChange()"
>
</nz-switch>
</div>
</div>
</li>
</ul>
</nz-checkbox-wrapper>
</ng-template>
<ng-template #totalTpl let-total>
<ng-container *ngIf="showTotal">
<ng-template [ngTemplateOutlet]="showTotal" [ngTemplateOutletContext]="{$implicit:props.pager}"></ng-template>
</ng-container>
<ng-container *ngIf="!showTotal">
共{{total}}条
</ng-container>
<ng-container *ngIf="showTotal">
<ng-template
[ngTemplateOutlet]="showTotal"
[ngTemplateOutletContext]="{ $implicit: props.pager }"
></ng-template>
</ng-container>
<ng-container *ngIf="!showTotal"> 共{{ total }}条 </ng-container>
</ng-template>
<ng-template #dateTimeTpl let-date>
{{date| date:'yyyy-MM-dd HH:mm:ss'}}
{{ date | date : 'yyyy-MM-dd HH:mm:ss' }}
</ng-template>
<!-- 为了计算操作栏的宽度 ---- start -->
<dec-table-operation #operationEl [rowData]="{}" [options]="operation" class="hidden-option">
</dec-table-operation>
<!-- 为了计算操作栏的宽度 ---- end -->
<dec-table-operation #operationEl [rowData]="{}" [options]="operation" class="hidden-option"> </dec-table-operation>
<!-- 为了计算操作栏的宽度 ---- end -->

285
projects/cdk/src/table-list/table-list/table-list.component.ts

@ -17,36 +17,36 @@ import {
Renderer2,
ChangeDetectorRef,
OnDestroy,
} from "@angular/core";
import { CommonModule } from "@angular/common";
import { SelectionModel } from "@angular/cdk/collections";
import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop";
} from '@angular/core'
import { CommonModule } from '@angular/common'
import { SelectionModel } from '@angular/cdk/collections'
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'
import { Router } from "@angular/router";
import { debounceTime, finalize } from "rxjs/operators";
import { FormsModule, FormControl, FormGroup, AbstractControl } from "@angular/forms";
import { NzDrawerModule, NzDrawerService } from "ng-zorro-antd/drawer";
import { Router } from '@angular/router'
import { debounceTime, finalize } from 'rxjs/operators'
import { FormsModule, FormControl, FormGroup, AbstractControl } from '@angular/forms'
import { NzDrawerModule, NzDrawerService } from 'ng-zorro-antd/drawer'
import { DecSafeAny, PageResult, ResponseType, TableListColumns, TableOperation } from "../../types";
import { TableListOption } from "../table-list-options";
import { CacheItem, CacheService, StorageService } from "../../storage";
import { TableOperationComponent } from "../table-operation/table-operation.component";
import { DecSafeAny, PageResult, ResponseType, TableListColumns, TableOperation } from '../../types'
import { TableListOption } from '../table-list-options'
import { CacheItem, CacheService, StorageService } from '../../storage'
import { TableOperationComponent } from '../table-operation/table-operation.component'
@Pipe({
name: "operationFilter",
name: 'operationFilter',
})
export class OperationPipe implements PipeTransform {
transform(operations: TableOperation[], rowItem: any): TableOperation[] {
return operations?.filter((f) => (f.visible ? f.visible(rowItem) : true)) ?? [];
return operations?.filter((f) => (f.visible ? f.visible(rowItem) : true)) ?? []
}
}
const DATE_RANGE_FIELDS = ["createTime", "updateTime"];
const DATE_RANGE_FIELDS = ['createTime', 'updateTime']
@Component({
selector: "table-list",
templateUrl: "./table-list.component.html",
styleUrls: ["./table-list.component.less"],
selector: 'table-list',
templateUrl: './table-list.component.html',
styleUrls: ['./table-list.component.less'],
})
export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
constructor(
@ -56,13 +56,13 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD
private router: Router,
private drawerService: NzDrawerService,
private storage: StorageService,
private cacheService: CacheService
private cacheService: CacheService,
) {}
@Input() props!: TableListOption;
@Input() props!: TableListOption
// https://github.com/angular/angular/issues/13761
@Input() formGroup = new FormGroup<any>({});
@Input() formGroup = new FormGroup<any>({})
/**
*
@ -71,211 +71,218 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD
* row:dataItem `当前行数据`
* column:col `当前列`
*/
@Input() renderColumns?: TemplateRef<{}>;
@Input() renderColumns?: TemplateRef<{}>
/**
* 使
*/
@Input() renderItem?: TemplateRef<{}>;
@Input() renderItem?: TemplateRef<{}>
@Input() action?: TemplateRef<{}>;
@Input() action?: TemplateRef<{}>
@Input() search?: TemplateRef<{}>;
@Input() search?: TemplateRef<{}>
@Input() searchLayout: "horizontal" | "vertical" = "horizontal";
@Input() searchLayout: 'horizontal' | 'vertical' = 'horizontal'
/**
* @deprecated
*/
@Input() advanceSearch?: TemplateRef<{}>;
@Input() advanceSearch?: TemplateRef<{}>
@Input() showTotal?: TemplateRef<{}>;
@Input() showTotal?: TemplateRef<{}>
@Input() beforeReset?: Function;
@Input() beforeReset?: Function
@Input() rowClass?: string;
@Input() rowClass?: string
@Input() public optionWidth?: string;
@Input() public optionWidth?: string
// @Input() resizeable?: boolean;
@Output() onRowClick = new EventEmitter();
@Output() onRowClick = new EventEmitter()
dataSource: DecSafeAny[] = [];
dataSource: DecSafeAny[] = []
totalPages = 0;
totalPages = 0
public selection = new SelectionModel<number>(true);
public selection = new SelectionModel<number>(true)
public advanceSearchVisible: boolean = false;
public advanceSearchVisible: boolean = false
private cache?: CacheItem;
private cache?: CacheItem
get columns(): TableListColumns[] {
return this.props.columns ?? [];
return this.props.columns ?? []
}
get operation(): TableOperation[] {
return this.props.operations ?? [];
return this.props.operations ?? []
}
get createTime() {
return this.formGroup.get("createTime");
return this.formGroup.get('createTime')
}
ngOnInit(): void {
this.props.trigger$.pipe(debounceTime(100)).subscribe((e?: any) => {
if (this.props.fetchData) {
this.props.pager.loading = true;
this.selection.clear();
this.emitState();
const query = this.formGroup.getRawValue();
this.props.pager.loading = true
// this.selection.clear();
this.emitState()
const query = this.formGroup.getRawValue()
// console.log("query", query);
// this.saveQueryDataToCache(query);
const pager = this.parsePager();
const pager = this.parsePager()
this.props
.fetchData(pager, this.parseQueryValue(), e)
.pipe(
finalize(() => {
this.props.pager.loading = false;
})
this.props.pager.loading = false
}),
)
.subscribe((f: ResponseType<PageResult>) => {
// alert(f.body.totalElements);
this.dataSource = f.body.content;
this.props.pager.total = f.body.totalElements;
this.totalPages = Math.ceil(this.props.pager.total / this.props.pager.size);
console.log("this.props.pager.total", this.props.pager.total);
this.checkPage();
});
this.dataSource = f.body.content
this.props.pager.total = f.body.totalElements
this.totalPages = Math.ceil(this.props.pager.total / this.props.pager.size)
console.log('this.props.pager.total', this.props.pager.total)
this.checkPage()
})
}
});
})
setTimeout(() => {
this.emitState();
}, 10);
this.emitState()
}, 10)
// 初始化的时候?
if (!this.props.manual) {
this.props.run();
this.props.run()
}
this.getCacheData();
this.getCacheData()
}
ngOnDestroy(): void {
// console.log("ngOnDestroy");
}
checkedAll(d: any[]) {
if (!d || !Array.isArray(d) || d?.length === 0) {
return false
}
return d.every((d) => this.selection.isSelected(d[this.props.rowKey]))
}
ngAfterViewInit(): void {
const opEl: HTMLDivElement = this.el.nativeElement.querySelector(".hidden-option");
const opEl: HTMLDivElement = this.el.nativeElement.querySelector('.hidden-option')
if (opEl) {
setTimeout(() => {
const paddingX = 2 * 24;
const paddingX = 2 * 24
if (!this.optionWidth) {
this.optionWidth = Math.ceil(opEl.offsetWidth + paddingX) + "px";
this.optionWidth = Math.ceil(opEl.offsetWidth + paddingX) + 'px'
}
this.cdr.detectChanges();
});
this.cdr.detectChanges()
})
}
}
ngOnChanges(changes: SimpleChanges): void {
const props = changes["props"];
const currentProps = props?.currentValue;
const previousProps = props?.previousValue;
const props = changes['props']
const currentProps = props?.currentValue
const previousProps = props?.previousValue
if (currentProps) {
if (previousProps?.["cacheKey"] !== currentProps?.["cacheKey"]) {
this.removeOldCache();
this.getCacheData();
if (previousProps?.['cacheKey'] !== currentProps?.['cacheKey']) {
this.removeOldCache()
this.getCacheData()
}
this.parseColumus(currentProps?.["columns"]);
this.parseFormControls(currentProps?.["queryForm"]);
this.parseColumus(currentProps?.['columns'])
this.parseFormControls(currentProps?.['queryForm'])
}
}
private saveQueryDataToCache(query: {}) {
if (this.cache) {
const { page, size, sort, total } = this.props.pager;
this.cache.setItem({ page, size, sort, total, ...query });
const { page, size, sort, total } = this.props.pager
this.cache.setItem({ page, size, sort, total, ...query })
}
}
private removeOldCache() {
this.cache?.remove();
this.cache?.remove()
}
private getCacheData() {
let { cacheKey, cacheTo = [] } = this.props;
let { cacheKey, cacheTo = [] } = this.props
this.formGroup.reset();
this.formGroup.reset()
if (!cacheKey) {
cacheKey = `DATA_CACHE_${this.formatePathname()}`;
cacheKey = `DATA_CACHE_${this.formatePathname()}`
}
if (!this.cache) {
this.cache = this.cacheService.initCache(cacheKey, [this.router.url, ...cacheTo]);
this.cache = this.cacheService.initCache(cacheKey, [this.router.url, ...cacheTo])
}
const cacheData = this.cache?.getItem();
const cacheData = this.cache?.getItem()
if (cacheData) {
const { page, size, sort, total, ...query } = cacheData;
const { page, size, sort, total, ...query } = cacheData
this.props.pager = {
...this.props.pager,
total,
page,
size,
sort,
};
}
this.formGroup.patchValue(query);
this.formGroup.patchValue(query)
}
}
private parsePager() {
let { page, size } = this.props.pager;
let { page, size } = this.props.pager
if (this.props.pageFromZero) {
page = page - 1;
page = page - 1
}
const pager = { pageNo: page, pageSize: size, sort: this.formatSort() };
return pager;
const pager = { pageNo: page, pageSize: size, sort: this.formatSort() }
return pager
}
private parseQueryValue(): {} {
const o = Object.create(null);
const o = Object.create(null)
Object.entries(this.formGroup.getRawValue()).forEach(([k, v]) => {
if (DATE_RANGE_FIELDS.includes(k) && Array.isArray(v)) {
const from = v?.[0] instanceof Date ? v?.[0]?.toISOString() : v[0];
const to = v?.[1] instanceof Date ? v?.[1]?.toISOString() : v[1];
o[k] = { from, to };
const from = v?.[0] instanceof Date ? v?.[0]?.toISOString() : v[0]
const to = v?.[1] instanceof Date ? v?.[1]?.toISOString() : v[1]
o[k] = { from, to }
} else {
o[k] = v;
o[k] = v
}
});
return o;
})
return o
}
private checkPage() {
const maxPages = this.totalPages === 0 ? 1 : this.totalPages;
const maxPages = this.totalPages === 0 ? 1 : this.totalPages
if (maxPages < this.props.pager.page) {
this.props.pager.page = maxPages;
this.reload();
this.props.pager.page = maxPages
this.reload()
}
}
private emitState() {
this.props.getState$.emit({ selectedKeys: this.selection.selected });
this.props.getState$.emit({ selectedKeys: this.selection.selected })
}
private parseColumus(currentCols: TableListColumns[]) {
if (this.props.columns.some((s) => s.coverStorage)) {
this.onColumnsChange();
this.onColumnsChange()
}
const colsFormStorage: TableListColumns[] = this.storage.get(this.formatePathname()) ?? [];
const colsFormStorage: TableListColumns[] = this.storage.get(this.formatePathname()) ?? []
this.props.columns = currentCols
.map((i: TableListColumns) => {
const storageCol = colsFormStorage.find((f) => f.key === i.key);
let visible = i.visible !== void 0 ? i.visible : true;
let width = i.width;
const storageCol = colsFormStorage.find((f) => f.key === i.key)
let visible = i.visible !== void 0 ? i.visible : true
let width = i.width
// if (["createTime", "updateTime"].includes(i.key)) {
// width = "180px";
// }
@ -284,9 +291,9 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD
visible,
width,
...(storageCol ?? {}),
};
}
})
.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
.sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
}
private parseFormControls(formGroup?: FormGroup) {
@ -297,95 +304,95 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD
}
formatSort() {
const { sort } = this.props.pager;
const { sort } = this.props.pager
if (!sort) {
return null;
return null
}
const sortArr = [...Object.entries(sort)]?.[0];
const sortArr = [...Object.entries(sort)]?.[0]
if (!sortArr) {
return null;
return null
}
return `${sortArr[0]},${sortArr[1] === "ascend" ? "asc" : "desc"}`;
return `${sortArr[0]},${sortArr[1] === 'ascend' ? 'asc' : 'desc'}`
}
colunmsSort(event: unknown) {
const e = event as CdkDragDrop<TableListColumns[]>;
moveItemInArray(this.props.columns, e.previousIndex, e.currentIndex);
this.onColumnsChange();
const e = event as CdkDragDrop<TableListColumns[]>
moveItemInArray(this.props.columns, e.previousIndex, e.currentIndex)
this.onColumnsChange()
}
reload() {
this.props.run();
this.props.run()
}
onPageChange() {
if (!this.props.frontPagination) {
this.props.run();
this.props.run()
}
}
doQuery() {
this.props.pager.page = 1;
this.reload();
this.props.pager.page = 1
this.reload()
}
reset() {
this.beforeReset?.();
this.formGroup.reset();
this.doQuery();
this.beforeReset?.()
this.formGroup.reset()
this.doQuery()
}
onSort(v: string | null, fieldName: string) {
this.props.pager.sort = { [fieldName]: v as "ascend" | "descend" };
this.reload();
this.props.pager.sort = { [fieldName]: v as 'ascend' | 'descend' }
this.reload()
}
toggleAdvanceSearch(show?: boolean) {
if (typeof show === "boolean") {
this.advanceSearchVisible = show;
if (typeof show === 'boolean') {
this.advanceSearchVisible = show
} else {
this.advanceSearchVisible = !this.advanceSearchVisible;
this.advanceSearchVisible = !this.advanceSearchVisible
}
}
filteroperation(dataItem: any): TableOperation[] {
return this.operation?.filter((f) => (f.visible ? f.visible(dataItem) : true)) ?? [];
return this.operation?.filter((f) => (f.visible ? f.visible(dataItem) : true)) ?? []
}
toggleColumnVisible(nzContent: TemplateRef<DecSafeAny>) {
this.drawerService.create({
nzTitle: "设置展示项",
nzTitle: '设置展示项',
nzWidth: 280,
nzContent,
nzWrapClassName: "table-settings",
});
nzWrapClassName: 'table-settings',
})
}
private formatePathname() {
return this.props.columnKey ?? this.router.url.replace(/\//g, "_");
return this.props.columnKey ?? this.router.url.replace(/\//g, '_')
}
onColumnsChange() {
const columnStorageKey = `COLUMN_${this.formatePathname()}`;
const columnStorageKey = `COLUMN_${this.formatePathname()}`
this.storage.set(
columnStorageKey,
this.columns.map((i, idx) => {
const { key, width, visible } = i;
return { key, width, visible, order: idx };
})
);
const { key, width, visible } = i
return { key, width, visible, order: idx }
}),
)
}
onChecked(checked: boolean, rowKey?: DecSafeAny) {
const fn = checked ? "select" : "deselect";
const rowKeys = rowKey ? [rowKey] : this.dataSource.map((i) => i[this.props.rowKey]);
this.selection[fn](...rowKeys);
this.emitState();
const fn = checked ? 'select' : 'deselect'
const rowKeys = rowKey ? [rowKey] : this.dataSource.map((i) => i[this.props.rowKey])
this.selection[fn](...rowKeys)
this.emitState()
}
onTrClick(dataItem: DecSafeAny) {
if (this.onRowClick) {
this.onRowClick.emit(dataItem);
this.onRowClick.emit(dataItem)
}
}
}

Loading…
Cancel
Save