From 24fb762a2e186f6b1016dfdbef227a35cd20aef9 Mon Sep 17 00:00:00 2001 From: kkerwin Date: Thu, 14 Dec 2023 23:06:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E5=B1=8F=E8=BD=AE=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../food-form/food-form.component.ts | 92 +++++------ .../ingredient-form.component.ts | 18 +- .../pages/data-vis/data-vis.component.html | 2 +- .../app/pages/data-vis/data-vis.component.ts | 126 +++++++++----- .../ingredient-form.component.ts | 155 +++++++++--------- 5 files changed, 220 insertions(+), 173 deletions(-) diff --git a/projects/admin/src/app/components/food-form/food-form.component.ts b/projects/admin/src/app/components/food-form/food-form.component.ts index 3073103..40b0eb8 100644 --- a/projects/admin/src/app/components/food-form/food-form.component.ts +++ b/projects/admin/src/app/components/food-form/food-form.component.ts @@ -1,95 +1,95 @@ -import { ApiService } from "@cdk/services"; -import { Component, Input, OnInit } from "@angular/core"; -import { FormArray, FormBuilder, FormGroup } from "@angular/forms"; -import { Utils } from "@cdk/utils"; -import { FormValidators } from "@cdk/validators"; -import { NzMessageService } from "ng-zorro-antd/message"; +import { ApiService } from '@cdk/services' +import { Component, Input, OnInit } from '@angular/core' +import { FormArray, FormBuilder, FormGroup } from '@angular/forms' +import { Utils } from '@cdk/utils' +import { FormValidators } from '@cdk/validators' +import { NzMessageService } from 'ng-zorro-antd/message' @Component({ - selector: "app-food-form", - templateUrl: "./food-form.component.html", - styleUrls: ["./food-form.component.less"], + selector: 'app-food-form', + templateUrl: './food-form.component.html', + styleUrls: ['./food-form.component.less'], }) export class FoodFormComponent implements OnInit { constructor(private fb: FormBuilder, private api: ApiService, private msg: NzMessageService) {} - formGroup!: FormGroup; + formGroup!: FormGroup - @Input() food: any; + @Input() food: any - public globalEnum = this.api.globalEnum; + public globalEnum = this.api.globalEnum get nutrition(): FormArray { - return this.formGroup.get("_nutrition") as FormArray; + return this.formGroup.get('_nutrition') as FormArray } ngOnInit(): void { this.formGroup = this.fb.group({ - key: this.fb.control("", [FormValidators.required("请输入食材编号")]), - name: this.fb.control("", [FormValidators.required("请输入食材名称")]), - type: this.fb.control("", [FormValidators.required("请选择食材类型")]), - nutrient: this.fb.control(null, [FormValidators.required("请输入营养素")]), + key: this.fb.control('', [FormValidators.required('请输入食材编号')]), + name: this.fb.control('', [FormValidators.required('请输入食材名称')]), + type: this.fb.control('', [FormValidators.required('请选择食材类型')]), + nutrient: this.fb.control(null, [FormValidators.required('请输入营养素')]), _nutrition: this.fb.array([], []), - }); + }) if (this.food) { - this.formGroup.patchValue(this.food); - this.formGroup.get("key")?.disable(); + this.formGroup.patchValue(this.food) + this.formGroup.get('key')?.disable() this.food.nutrientArr?.forEach((n: any) => { - this.createNutrition(n); - }); + this.createNutrition(n) + }) } } nutritionChange(v: string, idx: number) { - const nutrient = this.globalEnum.nutrient.find((f) => f.key === v); + const nutrient = this.globalEnum.nutrient.find((f) => f.key === v) if (this.nutrition.value?.filter((s: any) => s.nutritionName === nutrient?.key).length < 2) { this.nutrition.at(idx).patchValue({ measurement: nutrient?.measurement, - }); + }) } else { - this.msg.error("重复的营养素"); + this.msg.error('重复的营养素') this.nutrition.at(idx).patchValue( { - nutritionName: "", - measurement: "", + nutritionName: '', + measurement: '', }, - { emitEvent: false } - ); + { emitEvent: false }, + ) } } createNutrition(v?: any) { this.nutrition.push( this.fb.group({ - nutritionName: this.fb.control(v?.key ?? ""), + nutritionName: this.fb.control(v?.key ?? ''), nutritionNum: this.fb.control(v?.value ?? 0), - measurement: this.fb.control(v?.measurement ?? ""), - }) - ); - const nutrient = this.formGroup.get("nutrient"); + measurement: this.fb.control(v?.measurement ?? ''), + }), + ) + const nutrient = this.formGroup.get('nutrient') if (!nutrient?.value) { - nutrient?.patchValue({}); + nutrient?.patchValue({}) } } removeNutrition(idx: number) { - this.nutrition.removeAt(idx); + this.nutrition.removeAt(idx) } public getValues() { - let values = null; + let values = null if (Utils.validateFormGroup(this.formGroup)) { - const { _nutrition, key, name, type } = this.formGroup.getRawValue(); - let nutrient = Object.create(null); + const { _nutrition, key, name, type } = this.formGroup.getRawValue() + let nutrient = Object.create(null) if (Array.isArray(_nutrition)) { for (const n of _nutrition) { - let num = Number(n.nutritionNum); - if (!n.nutritionName || !num) { - this.msg.error("请输入正确的营养素"); - return; + let num = Number(n.nutritionNum) + if (!n.nutritionName) { + this.msg.error('请选择正确的营养素') + return } - nutrient[n.nutritionName] = num; + nutrient[n.nutritionName] = num } } values = { @@ -97,8 +97,8 @@ export class FoodFormComponent implements OnInit { name, type, nutrient, - }; + } } - return values; + return values } } diff --git a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts index 3ca26c5..0620814 100644 --- a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts +++ b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts @@ -9,7 +9,7 @@ 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 { forkJoin, lastValueFrom } from 'rxjs' @Component({ selector: 'app-ingredient-form', @@ -142,17 +142,17 @@ export class IngredientFormComponent implements OnInit { nzContent: ConfirmIngredientComponent, nzData: this.menuItem, nzWidth: 650, - nzOnOk: () => { + nzOnOk: async () => { const { mealDishList } = this.menuDish - this.api - .saveMenuDist({ + const res = await lastValueFrom( + this.api.saveMenuDist({ 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']) }, }) } diff --git a/projects/client/src/app/pages/data-vis/data-vis.component.html b/projects/client/src/app/pages/data-vis/data-vis.component.html index a06a322..8a84f80 100644 --- a/projects/client/src/app/pages/data-vis/data-vis.component.html +++ b/projects/client/src/app/pages/data-vis/data-vis.component.html @@ -90,7 +90,7 @@
今日营养分析 - diff --git a/projects/client/src/app/pages/data-vis/data-vis.component.ts b/projects/client/src/app/pages/data-vis/data-vis.component.ts index 639643d..0c8268d 100644 --- a/projects/client/src/app/pages/data-vis/data-vis.component.ts +++ b/projects/client/src/app/pages/data-vis/data-vis.component.ts @@ -10,7 +10,8 @@ interface MenuDisplayItem { id: number } -const changeTime = 1000 * 60 * 3 +const menuChangeTime = 1000 * 60 * 3 +const peopleChangeTime = 1000 * 10 @Component({ selector: 'app-data-vis', @@ -58,12 +59,18 @@ export class DataVisComponent implements AfterViewInit { currentMenu: MenuDisplayItem | null = null - lastTime: number = 0 + menuChangeLastTime: number = 0 + + peopleChangeLastTime: number = 0 weekdayMap = weekdayMap scrollFlag = true + dishCache = new Map() + + analysisCache = new Map() + ngOnInit(): void { this.api.getOrgInfo().subscribe((res) => { const account = this.api.account @@ -76,7 +83,8 @@ export class DataVisComponent implements AfterViewInit { .subscribe(() => { const now = new Date() this.showTime = format(new Date(), 'yyyy-MM-dd HH:mm:ss') - if (now.getTime() - this.lastTime > changeTime) { + + if (now.getTime() - this.menuChangeLastTime > menuChangeTime) { const currentIndex = this.menus.findIndex((f) => f.id === this.currentMenu?.id) let idx = currentIndex + 1 if (idx > this.menus.length - 1) { @@ -84,8 +92,25 @@ export class DataVisComponent implements AfterViewInit { } this.currentMenu = this.menus[idx] if (this.currentMenu) { - this.lastTime = now.getTime() - this.getDataVisData(this.currentMenu.id) + this.menuChangeLastTime = now.getTime() + this.getDishData(this.currentMenu.id) + } + } + + if (now.getTime() - this.peopleChangeLastTime > peopleChangeTime) { + const currentPeopleIndex = this.peoples.findIndex((f) => f === this.people) + if (this.peoples.length > 1) { + let idx = currentPeopleIndex + 1 + if (idx > this.peoples.length - 1) { + idx = 0 + } + this.people = this.peoples[idx] + } else if (this.peoples.length === 1) { + this.people = this.peoples[0] + } + if (this.people) { + this.peopleChangeLastTime = now.getTime() + this.getAnalysis() } } }) @@ -107,13 +132,6 @@ export class DataVisComponent implements AfterViewInit { }) } - ngAfterViewInit(): void {} - - ngOnDestroy(): void { - this.destroy$.next(null) - this.destroy$.complete() - } - getMenuListByDay() { if (!this.day) { this.msg.error('请选择星期') @@ -122,15 +140,11 @@ export class DataVisComponent implements AfterViewInit { this.api.getMenusByDay(this.day).subscribe((res) => { this.menus = res.body //重置轮播时间 - this.lastTime = new Date('2023-01-01').getTime() + this.resetAutoPlay() }) } - dayChange() { - this.getMenuListByDay() - } - - getDataVisData(id: number) { + getDishData(id: number) { this.analysis = null this.peoples = [] this.people = '' @@ -145,13 +159,15 @@ export class DataVisComponent implements AfterViewInit { const dishs = res.body if (Array.isArray(dishs)) { this.peoples = Object.keys(dishs?.[0]?.ingredient?.[0]?.value) - this.people = this.peoples[0] + // this.people = this.peoples[0] if (!this.peoples) { + this.msg.error('没有找到当前食谱适用的人群') console.error('dishs?.[0]?.ingredient?.[0]?.value 数据错误:', dishs) return } + this.peopleChangeLastTime = 0 this.menuId = dishs?.[0]?.menu - this.getAnalysis() + // this.getAnalysis() dishs.forEach((i: any) => { // 把每个食材按照不同的人群将重量加起来 @@ -180,6 +196,57 @@ export class DataVisComponent implements AfterViewInit { }) } + ngAfterViewInit(): void {} + + ngOnDestroy(): void { + this.destroy$.next(null) + this.destroy$.complete() + } + + resetAutoPlay() { + this.menuChangeLastTime = 0 + this.peopleChangeLastTime = 0 + } + + resetData() { + this.analysis = null + this.menus = [] + this.people = '' + this.peoples = [] + this.dishs = {} + } + + dayChange() { + this.resetData() + this.getMenuListByDay() + } + + peopleChange() { + this.peopleChangeLastTime = this.peopleChangeLastTime + peopleChangeTime + this.analysis = null + this.getAnalysis() + } + + getAnalysis() { + if (!this.menuId) { + return + } + + this.api + .getAnalysis(this.menuId, this.day, this.people) + .pipe( + finalize(() => { + this.analysisLoading = false + }), + ) + .subscribe((res) => { + this.analysis = res.body + // setTimeout(() => { + // this.autoScroll(this.nutritionEl.nativeElement, "2"); + // }, 1000); + }) + } + scrollSubs$?: Subscription @HostListener('window:resize') @@ -220,23 +287,4 @@ export class DataVisComponent implements AfterViewInit { }, }) } - - getAnalysis() { - if (!this.menuId) { - return - } - this.api - .getAnalysis(this.menuId, this.day, this.people) - .pipe( - finalize(() => { - this.analysisLoading = false - }), - ) - .subscribe((res) => { - this.analysis = res.body - // setTimeout(() => { - // this.autoScroll(this.nutritionEl.nativeElement, "2"); - // }, 1000); - }) - } } diff --git a/projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts b/projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts index 65a19d1..b19b4fb 100644 --- a/projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts +++ b/projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts @@ -1,19 +1,19 @@ -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 { 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 { 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, lastValueFrom } 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( @@ -22,58 +22,58 @@ 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") { + if (this.id && this.id !== 'create') { this.api.getMenuItem(this.id).subscribe((res) => { if (res.body) { - this.menuItem = res.body; + this.menuItem = res.body } - }); + }) this.api.getMenuDist(this.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(); + const foodIds = new Set() 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 { @@ -81,35 +81,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 = 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: { @@ -118,60 +118,59 @@ 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; - - this.api - .saveMenuDist({ - menuIds: this.id?.split(","), + nzOnOk: async () => { + const { mealDishList } = this.menuDish + const res = await lastValueFrom( + this.api.saveMenuDist({ + menuIds: 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), - }; - }); - }); - return data; + } + }) + }) + return data } }