Browse Source

添加菜品

main
kkerwin 2 years ago
parent
commit
7349084228
  1. 8
      README.md
  2. 60
      projects/admin/src/app/components/dish-form/dish-form.component.html
  3. 164
      projects/admin/src/app/components/dish-form/dish-form.component.ts
  4. 40
      projects/admin/src/app/pages/dish/dish.component.html
  5. 72
      projects/admin/src/app/pages/dish/dish.component.ts
  6. 55
      projects/admin/src/app/pages/food/food.component.html
  7. 47
      projects/admin/src/app/pages/food/food.component.ts
  8. 24
      projects/admin/src/app/pages/standard/standard-form/standard-form.component.html
  9. 81
      projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts
  10. 46
      projects/cdk/src/services/api.service.ts

8
README.md

@ -50,4 +50,10 @@ To get more help on the Angular CLI use `ng help` or go check out the [Angular C
1. 食材也需要一个 类似 /api/vender/select 的接口
2. 新增菜品 -> 食材名称 -> 食材标签 的枚举值 有哪些?
3. 单位修改 status 我调用的是编辑接口报错
3. 单位修改 status 我调用的是编辑接口报错
# 09/18
1. /api/basic/enum 中 markType 和 venderType 重复
2. /api/ingredient/select 需要 支持关键字

60
projects/admin/src/app/components/dish-form/dish-form.component.html

@ -16,11 +16,11 @@
nzShowSearch
nzServerSearch
nzPlaceHolder="请选择单位,多选时在多个单位均添加此菜品"
[nzShowArrow]="false"
[nzFilterOption]="nzFilterOption"
(nzOnSearch)="search($event)">
<nz-option *ngFor="let o of listOfOption" [nzLabel]="o.text" [nzValue]="o.value"></nz-option>
formControlName="vendors"
(nzOnSearch)="searchOrg($event)">
<nz-option *ngFor="let o of orgListOfOption" [nzLabel]="o.text" [nzValue]="o.value"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
@ -39,7 +39,6 @@
<nz-form-control [nzErrorTip]="formControlErrorTpl">
<nz-select
formControlName="mark"
nzPlaceHolder="请选择菜品标签">
<nz-option *ngFor="let item of globalEnum.mark" [nzValue]="item.value" [nzLabel]="item.key"></nz-option>
</nz-select>
@ -61,11 +60,15 @@
</label>
</div>
<nz-divider nzDashed class="my-1"></nz-divider>
<nz-checkbox-group [ngModel]="allMonth"
<div class="flex flex-wrap month-wrap">
<label *ngFor="let m of allMonth" nz-checkbox [(nzChecked)]="m.checked"
(nzCheckedChange)="monthChecked($event,m.value)">{{m.label}}</label>
</div>
<!-- <nz-checkbox-group [(ngModel)]="allMonth"
class="flex flex-wrap month-wrap"
formControlName="month"
[ngModelOptions]="{standalone: true}"
(ngModelChange)="monthChecked()">
</nz-checkbox-group>
</nz-checkbox-group> -->
</nz-form-control>
</nz-form-item>
@ -101,16 +104,30 @@
<span class="flex-1">
食材名称
</span>
<a nz-button nzType="link" (click)="addFoodVisible = true">
<!-- <a nz-button nzType="link" (click)="addFoodVisible = true">
<span nz-icon nzType="plus"></span>
<span>
添加食材
</span>
</a>
</a> -->
</div>
</nz-form-label>
<nz-form-control [nzErrorTip]="formControlErrorTpl">
<div *ngIf="addFoodVisible">
<nz-select
[nzMode]="'multiple'"
nzShowSearch
nzServerSearch
nzPlaceHolder="请输入食材名称检索"
[nzShowArrow]="false"
[nzFilterOption]="nzFilterOption"
[(ngModel)]="foodSelected"
(ngModelChange)="onFoodSelected($event)"
(nzOnSearch)="searchFood($event)"
[ngModelOptions]="{standalone: true}">
<nz-option *ngFor="let o of foodListOfOption" [nzLabel]="o.text" [nzValue]="o.value"></nz-option>
</nz-select>
<!-- <div *ngIf="addFoodVisible">
<nz-select nzSize="large" nzShowSearch nzPlaceHolder="请输入食材名称/编号检索">
</nz-select>
@ -120,21 +137,28 @@
<button *nzSpaceItem nz-button nzType="primary" (click)="addFood()">确定</button>
</nz-space>
</div>
</div>
<ul formArrayName="food">
<li class="mb-2" *ngFor="let n of food.controls;let i = index" [formGroupName]="i">
</div> -->
<ul class="mt-4">
<li class="mb-2" *ngFor="let f of foodItemSelected;let i = index">
<div class="flex items-center">
<div class="pr-2">
食材名称:
<div class="w-40 pr-2">
<button nz-button nzBlock>
{{f.value}}-{{f.text}}:
</button>
</div>
<div class="pr-2">
<!-- <div class="pr-2">
<nz-select class="!w-[200px]" nzPlaceHolder="食材标签"
formControlName="tag">
</nz-select>
</div>
</div> -->
<div class="flex-1 pr-2">
<nz-input-group [nzAddOnAfter]="'g'" class="w-full">
<input nz-input formControlName="weight" [placeholder]="'请输入xxx重量'" />
<input
nz-input
type="number"
[(ngModel)]="f.num"
[ngModelOptions]="{standalone: true}"
placeholder="请输入{{f.value}}-{{f.text}}重量" />
</nz-input-group>
</div>
<div>

164
projects/admin/src/app/components/dish-form/dish-form.component.ts

@ -1,9 +1,10 @@
import { Component, OnInit } from "@angular/core";
import { Component, Input, OnInit } from "@angular/core";
import { FormArray, FormBuilder, FormGroup } from "@angular/forms";
import { ApiService } from "@cdk/services";
import { Utils } from "@cdk/utils";
import { FormValidators } from "@cdk/validators";
import { NzMessageService } from "ng-zorro-antd/message";
import { finalize } from "rxjs";
import { Subject, debounceTime, distinctUntilChanged, filter, finalize, switchMap, throttleTime } from "rxjs";
@Component({
selector: "app-dish-form",
@ -13,29 +14,47 @@ import { finalize } from "rxjs";
export class DishFormComponent {
constructor(private fb: FormBuilder, private msg: NzMessageService, private api: ApiService) {}
@Input() data: any;
@Input() orgs: any[] = [];
@Input() foods: any[] = [];
private orgSearch$ = new Subject<Record<string, string>>();
private foodSearch$ = new Subject<Record<string, string>>();
formGroup!: FormGroup;
selectedValue = null;
listOfOption: Array<{ value: string; text: string }> = [];
orgListOfOption: Array<{ value: string; text: string }> = [];
foodListOfOption: Array<{ value: string; text: string }> = [];
searchedFood: Array<{ value: string; text: string }> = [];
foodSelected: string[] = [];
foodItemSelected: any[] = [];
nzFilterOption = (): boolean => true;
globalEnum = this.api.globalEnum;
allMonth = [
{ value: "1", label: "一月", checked: false },
{ value: "2", label: "二月", checked: false },
{ value: "3", label: "三月", checked: false },
{ value: "4", label: "四月", checked: false },
{ value: "5", label: "五月", checked: false },
{ value: "6", label: "六月", checked: false },
{ value: "7", label: "七月", checked: false },
{ value: "8", label: "八月", checked: false },
{ value: "9", label: "九月", checked: false },
{ value: "10", label: "十月", checked: false },
{ value: "11", label: "十一月", checked: false },
{ value: "12", label: "十二月", checked: false },
{ value: 1, label: "一月", checked: false },
{ value: 2, label: "二月", checked: false },
{ value: 3, label: "三月", checked: false },
{ value: 4, label: "四月", checked: false },
{ value: 5, label: "五月", checked: false },
{ value: 6, label: "六月", checked: false },
{ value: 7, label: "七月", checked: false },
{ value: 8, label: "八月", checked: false },
{ value: 9, label: "九月", checked: false },
{ value: 10, label: "十月", checked: false },
{ value: 11, label: "十一月", checked: false },
{ value: 12, label: "十二月", checked: false },
];
allMonthChecked = false;
@ -47,7 +66,7 @@ export class DishFormComponent {
addFoodVisible = false;
get food(): FormArray {
return this.formGroup.get("food") as FormArray;
return this.formGroup.get("ingredient") as FormArray;
}
get icon() {
@ -56,30 +75,116 @@ export class DishFormComponent {
ngOnInit(): void {
this.formGroup = this.fb.group({
id: this.fb.control("", [FormValidators.required()]),
id: this.fb.control("", []),
vendors: this.fb.control([], [FormValidators.required()]),
name: this.fb.control("", [FormValidators.required()]),
icon: this.fb.control("", []),
mark: this.fb.control([], []),
food: this.fb.array([], [FormValidators.required()]),
mark: this.fb.control("", [FormValidators.required()]),
month: this.fb.control([], []),
});
}
search(value: string): void {
this.api
.getOrgList({ keyword: value })
this.orgSearch$
.pipe(
debounceTime(500),
distinctUntilChanged(),
switchMap((q) => this.api.getOrgList(q))
)
.subscribe((data) => {
const listOfOption: Array<{ value: string; text: string }> = [];
data.body.forEach((item) => {
listOfOption.push({
value: item.id.toString(),
text: item.account,
text: item.name,
});
});
this.orgListOfOption = listOfOption;
});
this.foodSearch$
.pipe(
filter((f) => !!f),
debounceTime(500),
distinctUntilChanged(),
switchMap((q) => this.api.getFoodList(q))
)
.subscribe((data) => {
const listOfOption: Array<{ value: string; text: string }> = [];
data.body.forEach((item) => {
listOfOption.push({
value: item.key,
text: item.name,
});
});
this.listOfOption = listOfOption;
this.searchedFood = this.searchedFood.concat(listOfOption);
this.foodListOfOption = listOfOption;
});
this.setValues();
}
setValues() {
console.log("this.orgs", this.orgs, this.data);
this.orgListOfOption = this.orgs.map((i) => ({ text: i.name, value: i.id }));
if (this.data) {
this.allMonth = this.allMonth.map((i) =>
(this.data.month ?? []).includes(i.value) ? { ...i, checked: true } : i
);
this.monthCheckEffect();
// console.log("allMonth", allMonth);
this.formGroup.patchValue({
...this.data,
vendors: [this.data.vender],
mark: this.data.marks,
});
}
}
public getValues() {
let values = null;
console.log("this.formGroup.getRawValue()", this.formGroup.getRawValue());
if (Utils.validateFormGroup(this.formGroup)) {
const value = this.formGroup.getRawValue();
// const { _nutrition, key, name, type } = this.formGroup.getRawValue();
let ingredient = Object.create(null);
for (const f of this.foodItemSelected) {
let num = Number(f.num);
if (!num) {
this.msg.error(`请输入${f.value}-${f.text}的重量`);
return;
}
ingredient[f.value] = num;
}
const month = this.allMonth
.reduce((a: any, c: any) => {
if (c.checked) {
return a.concat(Number(c.value));
}
return a;
}, [] as number[])
.join(",");
const vendors = value.vendors?.join(",") ?? "";
values = {
...value,
vendors,
month,
ingredient,
};
}
return values;
}
searchOrg(value: string): void {
if (value) {
this.orgSearch$.next({ keyword: value });
}
}
searchFood(value: string): void {
if (value) {
this.foodSearch$.next({ keyword: value });
}
}
onFoodSelected(v: string[]) {
this.foodItemSelected = this.searchedFood.filter((f) => v.includes(f.value));
}
addFood() {
@ -111,7 +216,12 @@ export class DishFormComponent {
}
}
monthChecked() {
monthChecked(checked: boolean, value: number) {
this.allMonth = this.allMonth.map((i) => (i.value === value ? { ...i, checked } : i));
this.monthCheckEffect();
}
monthCheckEffect() {
if (this.allMonth.every((item) => !item.checked)) {
this.allMonthChecked = false;
this.indeterminate = false;

40
projects/admin/src/app/pages/dish/dish.component.html

@ -17,9 +17,19 @@
<ng-template #searchTpl>
<nz-form-item class="w-40">
<nz-form-item class="w-60">
<nz-form-control>
<nz-select nzPlaceHolder="单位" [nzOptions]="[]"></nz-select>
<nz-select
nzShowSearch
nzServerSearch
nzPlaceHolder="请选择单位"
[nzShowArrow]="false"
formControlName="vendors"
[nzFilterOption]="nzFilterOption"
(nzOnSearch)="searchOrg($event)">
<nz-option *ngFor="let o of listOfOption" [nzLabel]="o.text"
[nzValue]="o.value"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item class="w-40">
@ -33,7 +43,7 @@
</nz-form-item>
<nz-form-item>
<nz-form-control>
<input nz-input placeholder="请输入菜品名称" formControlName="name" />
<input nz-input placeholder="请输入菜品名称" formControlName="keyword" />
</nz-form-control>
</nz-form-item>
</ng-template>
@ -41,25 +51,19 @@
<ng-container [ngSwitch]="key">
<ng-container *ngSwitchCase="'icon'">
<div class="dish-img overflow-auto"
*ngIf="data"
[ngStyle]="{'background-image':'url(' + data + ')'}">
</div>
</ng-container>
<ng-container *ngSwitchCase="'vender'">
{{tableOrg[data] || '-'}}
{{tableOrg[data]?.name || '-'}}
</ng-container>
<ng-container *ngSwitchCase="'foodArr'">
<a nz-popover
[nzPopoverContent]="popoverTpl"
nzPopoverTitle="食材及含量">
<b>{{data.length}}</b>中营养素
</a>
<ng-template #popoverTpl>
<div class=" max-w-sm max-h-60 overflow-auto">
<nz-tag *ngFor="let item of data" class="m-1">
{{item.label}}:{{item.value}}{{item.measurement}}
</nz-tag>
</div>
</ng-template>
<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 *ngSwitchDefault>
@ -76,10 +80,10 @@
<ng-template #formFooterTpl>
<nz-space>
<button *nzSpaceItem nz-button (click)="cancelFoodForm()">
<button *nzSpaceItem nz-button (click)="cancelForm()" type="button">
取消
</button>
<button *nzSpaceItem nz-button nzType="primary">
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit()">
保存
</button>
</nz-space>

72
projects/admin/src/app/pages/dish/dish.component.ts

@ -1,10 +1,10 @@
import { Component, OnInit, TemplateRef, ViewChild } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer";
import { AnyObject, TableListOption } from "@cdk/public-api";
import { AnyObject, OrgDTO, TableListOption } from "@cdk/public-api";
import { DishFormComponent } from "@admin/app/components";
import { ApiService } from "@cdk/services";
import { Subject, lastValueFrom, tap } from "rxjs";
import { Subject, debounceTime, distinctUntilChanged, filter, lastValueFrom, switchMap, takeUntil, tap } from "rxjs";
import { NzModalService } from "ng-zorro-antd/modal";
import { NzMessageService } from "ng-zorro-antd/message";
@ -35,18 +35,53 @@ export class DishComponent {
});
public queryForm = new FormGroup({
name: new FormControl(""),
keyword: new FormControl(""),
mark: new FormControl(""),
vendors: new FormControl(""),
});
private orgSearch$ = new Subject<string>();
public selectedIds: string[] = [];
tableOrg: { [k: number]: string } = {};
tableOrg: { [k: number]: OrgDTO } = {};
listOfOption: Array<{ value: number; text: string }> = [];
nzFilterOption = (): boolean => true;
submitLoading = false;
ngOnInit(): void {
this.initTableList();
this.orgSearch$
.pipe(
filter((f) => !!f),
debounceTime(500),
distinctUntilChanged(),
takeUntil(this.destroy$),
switchMap((term: string) => this.api.getOrgList({ keyword: term }))
)
.subscribe((data) => {
const listOfOption: Array<{ value: number; text: string }> = [];
data.body.forEach((item) => {
listOfOption.push({
value: item.id,
text: item.name,
});
});
this.listOfOption = listOfOption;
});
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => {
this.selectedIds = res.selectedKeys as Array<string>;
});
}
searchOrg = (k: string) => {
this.orgSearch$.next(k);
};
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
@ -90,7 +125,7 @@ export class DishComponent {
this.tableOrg = org.body.reduce((a, c) => {
return {
...a,
[c.id]: c.account,
[c.id]: c,
};
}, {} as AnyObject);
}
@ -100,21 +135,40 @@ export class DishComponent {
);
}
showFoodForm(food?: any) {
showFoodForm(data?: any) {
this.drawerRef = this.drawer.create({
nzTitle: food ? "编辑菜品" : "新增菜品",
nzTitle: data ? "编辑菜品" : "新增菜品",
nzWidth: 700,
nzContent: DishFormComponent,
nzContentParams: {
data,
orgs: Object.values(this.tableOrg),
},
nzFooter: this.formFooterTpl,
});
}
cancelFoodForm() {
cancelForm() {
this.drawerRef?.close();
}
onSubmit() {
if (this.drawerRef) {
const com = this.drawerRef.getContentComponent() as DishFormComponent;
const val = com.getValues();
if (val) {
this.submitLoading = true;
this.api.saveDish(val).subscribe((res) => {
this.msg.success(res.desc);
this.tableList.run();
this.cancelForm();
});
}
}
}
deleteItem(v?: any) {
const ids = v ? [v.key] : this.selectedIds;
const ids = v ? [v.id] : this.selectedIds;
this.modal.confirm({
nzTitle: "警告",
nzContent: `是否要删除${ids.length}个菜品?`,

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

@ -50,20 +50,13 @@
<ng-template #renderColumnsTpl let-data let-key="key" let-row="row">
<ng-container [ngSwitch]="key">
<ng-container *ngSwitchCase="'nutrientArr'">
<a nz-popover
[nzPopoverContent]="popoverTpl"
nzPopoverTitle="营养素">
<b>{{data.length}}</b>中营养素
</a>
<ng-template #popoverTpl>
<div class=" max-w-sm max-h-60 overflow-auto">
<nz-tag *ngFor="let item of data" class="m-1">
{{item.label}}:{{item.value}}{{item.measurement}}
</nz-tag>
</div>
</ng-template>
<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="'time'">
<ng-container *ngSwitchCase="'modify'">
{{data | date:'yyyy-MM-dd HH:mm:ss'}}
</ng-container>
<ng-container *ngSwitchDefault>
@ -83,26 +76,28 @@
<ng-template #importFormTpl>
<p class=" text-slate-400">
提示:<a>下载示例模版</a>,进行编辑,导入Excel文件,批量导入食材
提示:<a (click)="downloadTemplate()">下载示例模版</a>,进行编辑,导入Excel文件,批量导入食材
</p>
<div>
<div class="upload-area flex-col"
(drop)="handleDrop($event)"
(dragenter)="suppress($event)"
(dragover)="suppress($event)">
<input type="file" id="file" (change)="onFileChange($any($event.target).files)" 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>
<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>
</div>
</nz-spin>
</div>
</ng-template>

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

@ -46,6 +46,8 @@ export class FoodComponent implements OnInit, OnDestroy {
submitLoading = false;
uploadLoading = false;
editItem = null;
ngOnInit(): void {
@ -66,8 +68,8 @@ export class FoodComponent implements OnInit, OnDestroy {
{ key: "key", title: "食材编号" },
{ key: "name", title: "食材名称" },
{ key: "type", title: "食材类型" },
{ key: "nutrientArr", title: "营养素(每100g可食部)" },
{ key: "time", title: "更新日期" },
{ key: "nutrientArr", title: "营养素(每100g可食部)", width: "40%" },
{ key: "modify", title: "更新日期" },
]);
this.tableList = this.tableList.setOptions([
@ -145,6 +147,12 @@ export class FoodComponent implements OnInit, OnDestroy {
});
}
downloadTemplate() {
this.api.getFoodExcelTemplate().subscribe((res) => {
console.log("res", res);
});
}
showImportForm(nzContent: TemplateRef<{}>) {
this.importModalRef = this.modal.create({
nzTitle: "导入食材清单",
@ -169,15 +177,36 @@ export class FoodComponent implements OnInit, OnDestroy {
}
};
onFileChange(files: FileList) {
onFileChange(e: FileList | Event) {
let files: FileList;
console.log(e instanceof FileList, e);
if (e instanceof FileList) {
files = e;
} else {
const target = e.target as HTMLInputElement;
console.log(e instanceof FileList, target.files);
files = target.files!;
}
if (files?.length > 0) {
const formData = new FormData();
formData.append("files", files[0]);
this.api.importFood(formData).subscribe((res) => {
this.msg.success(res.desc);
this.tableList.run();
this.importModalRef?.close();
});
formData.append("file", files[0]);
this.uploadLoading = true;
this.api
.importFood(formData)
.pipe(
finalize(() => {
this.uploadLoading = false;
})
)
.subscribe(() => {
this.msg.success("导入成功");
this.tableList.run();
this.importModalRef?.close();
});
}
if (e instanceof Event) {
const target = e.target as HTMLInputElement;
target.value = "";
}
}
}

24
projects/admin/src/app/pages/standard/standard-form/standard-form.component.html

@ -26,14 +26,14 @@
<nz-form-label nzRequired>
<div class="flex justify-between items-center w-full">
<span class="flex-1">适用单位</span>
<ng-template #searchAndSelectTpl>
<!-- <ng-template #searchAndSelectTpl>
<div class=" w-96">
<search-and-select [handleSearh]="searchOrg"
(onSelect)="onSelectOrg($event)">
</search-and-select>
</div>
</ng-template>
<button type="button" nz-button nzType="link"
</ng-template> -->
<!-- <button type="button" nz-button nzType="link"
nz-popover
[nzPopoverVisible]="nzPopoverVisible"
(click)="nzPopoverVisible = !nzPopoverVisible"
@ -42,11 +42,23 @@
[nzPopoverContent]="searchAndSelectTpl">
<i nz-icon nzType="plus"></i>
添加单位
</button>
</button> -->
</div>
</nz-form-label>
<nz-form-control [nzErrorTip]="formControlErrorTpl" nzSpan="12">
<div>
<nz-select
[nzMode]="'multiple'"
nzShowSearch
nzServerSearch
nzPlaceHolder="请选择单位"
[nzShowArrow]="false"
formControlName="vendors"
[nzFilterOption]="nzFilterOption"
(nzOnSearch)="searchOrg($event)">
<nz-option *ngFor="let o of listOfOption" [nzLabel]="o.text"
[nzValue]="o.value"></nz-option>
</nz-select>
<!-- <div>
<nz-tag class="px-3 py-1" *ngFor="let v of vendors">
<span>{{v.label}}</span>
<a (click)="removeOrg(v.value)">
@ -54,7 +66,7 @@
</a>
</nz-tag>
</div>
<input type="hidden" formControlName="vendors" />
<input type="hidden" formControlName="vendors" /> -->
</nz-form-control>
</nz-form-item>
<nz-form-item>

81
projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts

@ -7,7 +7,7 @@ import { OptionItemInterface } from "@cdk/types";
import { Utils } from "@cdk/utils";
import { FormValidators } from "@cdk/validators";
import { NzMessageService } from "ng-zorro-antd/message";
import { finalize, map } from "rxjs";
import { Subject, debounceTime, distinctUntilChanged, filter, finalize, map, switchMap } from "rxjs";
@Component({
selector: "app-standard-form",
@ -33,6 +33,8 @@ export class StandardFormComponent {
}
}
private orgSearch$ = new Subject<string>();
formGroup!: FormGroup;
submitLoading = false;
@ -41,9 +43,13 @@ export class StandardFormComponent {
state: any;
nzPopoverVisible = false;
// nzPopoverVisible = false;
// vendors: OptionItemInterface[] = [];
listOfOption: Array<{ value: number; text: string }> = [];
vendors: OptionItemInterface[] = [];
nzFilterOption = (): boolean => true;
ngOnInit(): void {
this.formGroup = this.fb.group({
@ -52,34 +58,59 @@ export class StandardFormComponent {
vendors: this.fb.control([], [FormValidators.required()]),
overflow: this.fb.control("0", [FormValidators.required()]),
});
this.formGroup.patchValue(this.state);
if (this.state) {
this.formGroup.patchValue(this.state);
if (Array.isArray(this.state.vendors)) {
this.api.getOrgList({ vendors: this.state.vendors }).subscribe((data) => {
const listOfOption: Array<{ value: number; text: string }> = [];
data.body.forEach((item) => {
listOfOption.push({
value: item.id,
text: item.name,
});
});
this.listOfOption = listOfOption;
this.formGroup.patchValue(this.state);
});
}
}
this.orgSearch$
.pipe(
filter((f) => !!f),
debounceTime(500),
distinctUntilChanged(),
switchMap((term: string) => this.api.getOrgList({ keyword: term }))
)
.subscribe((data) => {
const listOfOption: Array<{ value: number; text: string }> = [];
data.body.forEach((item) => {
listOfOption.push({
value: item.id,
text: item.name,
});
});
this.listOfOption = listOfOption;
});
}
searchOrg = (k: string) => {
return this.api.getOrgList({ keyword: k }).pipe(
map((res) => {
return res.body.map((i) => ({
label: i.name,
value: i.id + "",
}));
})
);
this.orgSearch$.next(k);
};
onSelectOrg(v: OptionItemInterface[]) {
v.forEach((i) => {
if (!this.vendors.some((s) => s.value === i.value)) {
this.vendors.push(i);
}
});
this.formGroup.get("vendors")?.setValue(this.vendors.map((i) => i.value));
this.nzPopoverVisible = false;
}
// onSelectOrg(v: OptionItemInterface[]) {
// v.forEach((i) => {
// if (!this.vendors.some((s) => s.value === i.value)) {
// this.vendors.push(i);
// }
// });
// this.formGroup.get("vendors")?.setValue(this.vendors.map((i) => i.value));
// this.nzPopoverVisible = false;
// }
removeOrg(v: string) {
this.vendors = this.vendors.filter((f) => f.value !== v);
this.formGroup.get("vendors")?.setValue(this.vendors.map((i) => i.value));
}
// removeOrg(v: string) {
// this.vendors = this.vendors.filter((f) => f.value !== v);
// this.formGroup.get("vendors")?.setValue(this.vendors.map((i) => i.value));
// }
onSubmit(gotoSetting?: boolean) {
if (Utils.validateFormGroup(this.formGroup)) {

46
projects/cdk/src/services/api.service.ts

@ -1,4 +1,4 @@
import { HttpClient, HttpParams } from "@angular/common/http";
import { HttpClient, HttpParams, HttpResponse } from "@angular/common/http";
import { Inject, Injectable, InjectionToken } from "@angular/core";
import { AnyObject, PageResult, ResponseType } from "@cdk/types";
import { Utils } from "@cdk/utils";
@ -220,7 +220,29 @@ export class ApiService {
getFoodList(query: {}) {
const q = Utils.objectStringify(query);
return this.http.get<ResponseType<OrgDTO[]>>(`/api/vender/select?${q}`);
return this.http.get<ResponseType<any[]>>(`/api/ingredient/select?${q}`);
}
getFoodExcelTemplate() {
return this.http.get("/api/ingredient/excel", { observe: "response", responseType: "blob" as "json" }).pipe(
tap((res) => {
this.downLoadFile(res);
})
);
}
downLoadFile(response: HttpResponse<Object>) {
const fileNameFromHeader = response.headers.get("Content-Disposition");
if (fileNameFromHeader) {
const fileName = fileNameFromHeader.trim()?.split("''")?.[1]?.replace(/"/g, "") ?? `模板_${Date.now()}.xlsx`;
const blob = new Blob([response.body as any]);
const downloadLink = document.createElement("a");
downloadLink.href = URL.createObjectURL(blob);
downloadLink.download = decodeURIComponent(fileName);
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
}
saveFood(food: AnyObject, isEdit?: boolean) {
@ -235,7 +257,17 @@ export class ApiService {
}
importFood(f: FormData) {
return this.http.put<ResponseType>("/api/ingredient/upload", f);
// return this.http.put<ResponseType>("/api/ingredient/upload", f);
return this.http
.put<ResponseType>("/api/ingredient/excel", f, {
observe: "response",
responseType: "blob" as "json",
})
.pipe(
tap((res) => {
this.downLoadFile(res);
})
);
}
markFood(mark: string, ingredient: string) {
@ -304,8 +336,14 @@ export class ApiService {
);
}
saveDish(v: AnyObject) {
const body = Utils.objectToFormData(v);
const method = v["id"] ? "post" : "put";
return this.http[method]<ResponseType>("/api/dish", body);
}
deleteDish(ids: string[]) {
const params = Utils.objectToFormData({ id: ids.join(",") });
const params = Utils.objectToFormData({ ids: ids.join(",") });
return this.http.delete<ResponseType>(`/api/dish`, { body: params });
}
}

Loading…
Cancel
Save