|
|
|
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core'
|
|
|
|
import { FormBuilder, FormGroup } from '@angular/forms'
|
|
|
|
import { ActivatedRoute, Router } from '@angular/router'
|
|
|
|
import { ApiService } from '@cdk/services'
|
|
|
|
import { AnyObject } from '@cdk/types'
|
|
|
|
import { FormValidators } from '@cdk/validators'
|
|
|
|
import { NzMessageService } from 'ng-zorro-antd/message'
|
|
|
|
import { StandardService } from '../standard.service'
|
|
|
|
import { Observable, Subscription } from 'rxjs'
|
|
|
|
|
|
|
|
// infer
|
|
|
|
|
|
|
|
export type StandardItemInterface = {
|
|
|
|
min: number
|
|
|
|
max: number | null
|
|
|
|
name: string
|
|
|
|
type: string
|
|
|
|
category: string[]
|
|
|
|
}
|
|
|
|
|
|
|
|
export type StandardPeopleInterface = {
|
|
|
|
ul?: number
|
|
|
|
hasUl: boolean
|
|
|
|
max: number
|
|
|
|
min: number
|
|
|
|
nutrition: string
|
|
|
|
}
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'app-standard-setting',
|
|
|
|
templateUrl: './standard-setting.component.html',
|
|
|
|
styleUrls: ['./standard-setting.component.less'],
|
|
|
|
})
|
|
|
|
export class StandardSettingComponent implements AfterViewInit, OnDestroy {
|
|
|
|
constructor(
|
|
|
|
private fb: FormBuilder,
|
|
|
|
private router: Router,
|
|
|
|
private route: ActivatedRoute,
|
|
|
|
private api: ApiService,
|
|
|
|
private msg: NzMessageService,
|
|
|
|
private standard: StandardService,
|
|
|
|
) {
|
|
|
|
const id = this.route.snapshot.paramMap.get('id')
|
|
|
|
if (id !== 'create') {
|
|
|
|
const data = this.router.getCurrentNavigation()?.extras
|
|
|
|
if (data) {
|
|
|
|
this.state = data.state
|
|
|
|
} else {
|
|
|
|
this.router.navigate(['/standard/list'])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public globalEnum = this.api.globalEnum
|
|
|
|
|
|
|
|
state: any
|
|
|
|
|
|
|
|
calcType = this.globalEnum.measurementType?.[0]?.key
|
|
|
|
|
|
|
|
get calcTypeText() {
|
|
|
|
return this.globalEnum.measurementType.find((f) => f.key === this.calcType)?.value
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadLoading = false
|
|
|
|
|
|
|
|
foodCategoryDay: StandardItemInterface[] = []
|
|
|
|
|
|
|
|
foodCategoryWeek: StandardItemInterface[] = []
|
|
|
|
|
|
|
|
ingredient: { name: string; nutritions: StandardPeopleInterface[] }[] = []
|
|
|
|
|
|
|
|
intersection$ = new Subscription()
|
|
|
|
|
|
|
|
renderIngredient = false
|
|
|
|
|
|
|
|
expanded = new Set<number>()
|
|
|
|
|
|
|
|
@ViewChild('intersectionTpl') intersectionTpl!: ElementRef<HTMLDivElement>
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
|
|
this.foodCategoryDay = this.parseFoodCategory(this.state?.foodCategoryDay)
|
|
|
|
this.foodCategoryWeek = this.parseFoodCategory(this.state?.foodCategoryWeek)
|
|
|
|
|
|
|
|
this.ingredient = this.parseIngredient(this.state)
|
|
|
|
}
|
|
|
|
|
|
|
|
ngOnDestroy(): void {
|
|
|
|
// this.intersection$.unsubscribe()
|
|
|
|
}
|
|
|
|
|
|
|
|
ngAfterViewInit(): void {
|
|
|
|
// const el = this.intersectionTpl.nativeElement
|
|
|
|
// if (el) {
|
|
|
|
// this.intersection$.add(
|
|
|
|
// this.observeElement(el).subscribe((isIn) => {
|
|
|
|
// if (isIn) {
|
|
|
|
// this.renderIngredient = true
|
|
|
|
// this.intersection$.unsubscribe()
|
|
|
|
// }
|
|
|
|
// }),
|
|
|
|
// )
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
observeElement = (element: HTMLElement) => {
|
|
|
|
return new Observable((observer) => {
|
|
|
|
const intersectionObserver = new IntersectionObserver((entries) => {
|
|
|
|
entries.forEach((entry) => {
|
|
|
|
observer.next(entry.isIntersecting)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
intersectionObserver.observe(element)
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
intersectionObserver.disconnect()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
parseIngredient(data: any): { name: string; nutritions: StandardPeopleInterface[] }[] {
|
|
|
|
if (!data?.ingredient) {
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
this.expand(0)
|
|
|
|
const sorts = data.crows ?? Object.keys(data.ingredient)
|
|
|
|
return sorts.map((peopleName: string) => {
|
|
|
|
const v: any = data.ingredient[peopleName]
|
|
|
|
return {
|
|
|
|
name: peopleName,
|
|
|
|
nutritions: !v
|
|
|
|
? []
|
|
|
|
: Object.entries(v).map(([kn, vn]: [string, any]) => {
|
|
|
|
return {
|
|
|
|
ul: vn?.ul ?? void 0,
|
|
|
|
hasUl: !!vn?.ul,
|
|
|
|
max: vn?.max ?? 0,
|
|
|
|
min: vn?.min ?? 0,
|
|
|
|
nutrition: kn,
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
parseFoodCategory(data: any): StandardItemInterface[] {
|
|
|
|
if (!data) {
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
|
|
this.calcType = data[0]?.type
|
|
|
|
}
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
onSubmit() {
|
|
|
|
if (this.foodCategoryDay.some((s) => !s.name || typeof s.min !== 'number' || s.category.length === 0)) {
|
|
|
|
this.msg.error('请设置正确的食物种类及数量标准(日)')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (this.foodCategoryWeek.some((s) => !s.name || typeof s.min !== 'number' || s.category.length === 0)) {
|
|
|
|
this.msg.error('请设置正确的食物种类及数量标准(周)')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (this.ingredient.some((s) => !s.name || !s.nutritions.some((sn) => sn.nutrition))) {
|
|
|
|
this.msg.error('请设置正确的营养标准人群')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const foodCategoryDay = this.foodCategoryDay
|
|
|
|
|
|
|
|
const foodCategoryWeek = this.foodCategoryWeek
|
|
|
|
let crows: string = ''
|
|
|
|
const ingredient = this.ingredient.reduce((a, c, idx) => {
|
|
|
|
const crowsName = (idx === 0 ? '' : ',') + c.name
|
|
|
|
crows += crowsName
|
|
|
|
return {
|
|
|
|
...a,
|
|
|
|
[c.name]: c.nutritions.reduce((an, cn) => {
|
|
|
|
const ul = { ul: cn.hasUl ? cn.ul : void 0 }
|
|
|
|
return {
|
|
|
|
...an,
|
|
|
|
// idx,
|
|
|
|
[cn.nutrition]: {
|
|
|
|
min: cn.min,
|
|
|
|
max: cn.max,
|
|
|
|
...ul,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}, {} as AnyObject),
|
|
|
|
}
|
|
|
|
}, {} as AnyObject)
|
|
|
|
|
|
|
|
this.api
|
|
|
|
.saveStandard({ ...this.state, foodCategoryDay, foodCategoryWeek, ingredient, crows }, true)
|
|
|
|
.subscribe((res) => {
|
|
|
|
this.msg.success(res.desc)
|
|
|
|
this.router.navigate(['/standard/list'])
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
addFoodType(type: string) {
|
|
|
|
const item = type === 'day' ? this.foodCategoryDay : this.foodCategoryWeek
|
|
|
|
// const withoutSelectType = this.globalEnum.category.find((f) => !item.some((s) => s.type === f.key));
|
|
|
|
item.push({
|
|
|
|
category: [],
|
|
|
|
min: 0,
|
|
|
|
max: null,
|
|
|
|
name: '',
|
|
|
|
type: this.calcType,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
removeFoodType(type: string, idx: number) {
|
|
|
|
if (type === 'day') {
|
|
|
|
this.foodCategoryDay = this.foodCategoryDay.filter((f, i) => idx !== i)
|
|
|
|
} else {
|
|
|
|
this.foodCategoryWeek = this.foodCategoryWeek.filter((f, i) => idx !== i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addPeopleGroup() {
|
|
|
|
this.ingredient.push({
|
|
|
|
name: '',
|
|
|
|
nutritions: [],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
removePeopleGroup(idx: number) {
|
|
|
|
this.ingredient = this.ingredient.filter((_, i) => i !== idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
calcTypeChange() {
|
|
|
|
console.log('this.calcType', this.calcType)
|
|
|
|
this.foodCategoryDay = this.foodCategoryDay.map((i) => ({ ...i, type: this.calcType }))
|
|
|
|
this.foodCategoryWeek = this.foodCategoryWeek.map((i) => ({ ...i, type: this.calcType }))
|
|
|
|
}
|
|
|
|
|
|
|
|
moveUp(idx: number) {
|
|
|
|
const arr = this.ingredient
|
|
|
|
if (idx > 0 && idx < arr.length) {
|
|
|
|
;[arr[idx], arr[idx - 1]] = [arr[idx - 1], arr[idx]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
moveDown(idx: number) {
|
|
|
|
const arr = this.ingredient
|
|
|
|
if (idx >= 0 && idx < arr.length - 1) {
|
|
|
|
;[arr[idx], arr[idx + 1]] = [arr[idx + 1], arr[idx]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
expand(idx: number) {
|
|
|
|
if (this.expanded.has(idx)) {
|
|
|
|
this.expanded.delete(idx)
|
|
|
|
} else {
|
|
|
|
this.expanded.add(idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addNutrition(idx: number) {
|
|
|
|
const current = this.ingredient[idx]
|
|
|
|
this.expanded.add(idx)
|
|
|
|
const withoutSelectNutritions = this.globalEnum.nutrient.find(
|
|
|
|
(f) => !current.nutritions.some((s) => s.nutrition === f.key),
|
|
|
|
)
|
|
|
|
current.nutritions.push({
|
|
|
|
nutrition: withoutSelectNutritions?.key ?? '',
|
|
|
|
min: 0,
|
|
|
|
max: 0,
|
|
|
|
hasUl: false,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
removeNutrition(idx: number, nutrition: string) {
|
|
|
|
this.ingredient[idx].nutritions = this.ingredient[idx].nutritions.filter((f) => f.nutrition !== nutrition)
|
|
|
|
}
|
|
|
|
|
|
|
|
ulChange(idx: number, nutrition: string, checked: boolean) {
|
|
|
|
this.ingredient[idx].nutritions = this.ingredient[idx].nutritions.map((i) => {
|
|
|
|
return i.nutrition === nutrition ? { ...i, ul: checked ? 1 : void 0 } : i
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|