diff --git a/README.md b/README.md index 5f3d656..dd49a63 100644 --- a/README.md +++ b/README.md @@ -37,4 +37,17 @@ To get more help on the Angular CLI use `ng help` or go check out the [Angular C 5. 删除 食材 系统异常 6. 管理端 食材列表 没有返回 更新日期 7. 营养标准列表 列表 没有 更新时间 -8. 营养标准添加成功 需要 返回他的 id \ No newline at end of file +8. 营养标准添加成功 需要 返回他的 id + +------------------ +# 09/17 下午 + +1. 获取企业列表 原型上 还有个 单位类型 +2. 营养标准 需要 返回 单位名称和id vendors:[{label:"单位名称",id:vendorId}] +3. 根据关键字搜索单位 报错或者 返回空 list + +---------------- + +1. 食材也需要一个 类似 /api/vender/select 的接口 +2. 新增菜品 -> 食材名称 -> 食材标签 的枚举值 有哪些? +3. 单位修改 status 我调用的是编辑接口报错 \ No newline at end of file diff --git a/projects/admin/src/app/components/dish-form/dish-form.component.html b/projects/admin/src/app/components/dish-form/dish-form.component.html index 8c2e47c..d740b5e 100644 --- a/projects/admin/src/app/components/dish-form/dish-form.component.html +++ b/projects/admin/src/app/components/dish-form/dish-form.component.html @@ -4,12 +4,23 @@ 单位 - + --> + + @@ -27,11 +38,10 @@ - + @@ -64,10 +74,14 @@ 菜品图片 + + + + 上传图片 - + diff --git a/projects/admin/src/app/components/dish-form/dish-form.component.ts b/projects/admin/src/app/components/dish-form/dish-form.component.ts index 28d6395..69c6258 100644 --- a/projects/admin/src/app/components/dish-form/dish-form.component.ts +++ b/projects/admin/src/app/components/dish-form/dish-form.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from "@angular/core"; import { FormArray, FormBuilder, FormGroup } from "@angular/forms"; +import { ApiService } from "@cdk/services"; import { FormValidators } from "@cdk/validators"; import { NzMessageService } from "ng-zorro-antd/message"; import { finalize } from "rxjs"; @@ -10,10 +11,18 @@ import { finalize } from "rxjs"; styleUrls: ["./dish-form.component.less"], }) export class DishFormComponent { - constructor(private fb: FormBuilder, private msg: NzMessageService) {} + constructor(private fb: FormBuilder, private msg: NzMessageService, private api: ApiService) {} formGroup!: FormGroup; + selectedValue = null; + + listOfOption: Array<{ value: string; text: string }> = []; + + nzFilterOption = (): boolean => true; + + globalEnum = this.api.globalEnum; + allMonth = [ { value: "1", label: "一月", checked: false }, { value: "2", label: "二月", checked: false }, @@ -41,18 +50,38 @@ export class DishFormComponent { return this.formGroup.get("food") as FormArray; } + get icon() { + return this.formGroup.get("icon")?.value; + } + ngOnInit(): void { this.formGroup = this.fb.group({ id: this.fb.control("", [FormValidators.required()]), - unit: this.fb.control([], [FormValidators.required()]), + vendors: this.fb.control([], [FormValidators.required()]), name: this.fb.control("", [FormValidators.required()]), - img: this.fb.control("", []), - tag: this.fb.control([], []), + icon: this.fb.control("", []), + mark: this.fb.control([], []), food: this.fb.array([], [FormValidators.required()]), month: this.fb.control([], []), }); } + search(value: string): void { + this.api + .getOrgList({ keyword: value }) + + .subscribe((data) => { + const listOfOption: Array<{ value: string; text: string }> = []; + data.body.forEach((item) => { + listOfOption.push({ + value: item.id.toString(), + text: item.account, + }); + }); + this.listOfOption = listOfOption; + }); + } + addFood() { this.food.push( this.fb.group({ @@ -98,25 +127,15 @@ export class DishFormComponent { const target = e.target as HTMLInputElement; const file = target.files![0]; target.value = ""; - const formData = new FormData(); + if (file.size / 1024 / 1024 >= 5) { + this.msg.error("图片大小不能超过5M"); + return; + } const fileReader = new FileReader(); fileReader.onload = () => { const base64 = fileReader.result as string; - - const v = base64.split("base64,")[1]; + this.formGroup.get("icon")?.setValue(base64); }; - formData.append("file", file); - this.uploadLoading = true; - // this.api - // .uploadLogo(formData) - // .pipe( - // finalize(() => { - // this.uploadLoading = false; - // }) - // ) - // .subscribe((r) => { - // this.msg.success(r.desc); - // fileReader.readAsDataURL(file); - // }); + fileReader.readAsDataURL(file); } } 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 dd77723..3073103 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 @@ -33,6 +33,7 @@ export class FoodFormComponent implements OnInit { }); if (this.food) { this.formGroup.patchValue(this.food); + this.formGroup.get("key")?.disable(); this.food.nutrientArr?.forEach((n: any) => { this.createNutrition(n); }); @@ -78,7 +79,7 @@ export class FoodFormComponent implements OnInit { public getValues() { let values = null; if (Utils.validateFormGroup(this.formGroup)) { - const { _nutrition, key, name, type } = this.formGroup.value; + const { _nutrition, key, name, type } = this.formGroup.getRawValue(); let nutrient = Object.create(null); if (Array.isArray(_nutrition)) { for (const n of _nutrition) { diff --git a/projects/admin/src/app/pages/dish/dish.component.html b/projects/admin/src/app/pages/dish/dish.component.html index 9d78596..18b515e 100644 --- a/projects/admin/src/app/pages/dish/dish.component.html +++ b/projects/admin/src/app/pages/dish/dish.component.html @@ -1,7 +1,7 @@ - 批量删除 + 批量删除 批量打印营养标签 @@ -15,9 +15,7 @@ - - 批量删除 - + @@ -26,7 +24,11 @@ - + + + + @@ -37,11 +39,28 @@ - + + [ngStyle]="{'background-image':'url(' + data + ')'}"> + + {{tableOrg[data] || '-'}} + + + + 共{{data.length}}中营养素 + + + + + {{item.label}}:{{item.value}}{{item.measurement}} + + + + {{data}} diff --git a/projects/admin/src/app/pages/dish/dish.component.ts b/projects/admin/src/app/pages/dish/dish.component.ts index 0e3d9bb..02ad4dc 100644 --- a/projects/admin/src/app/pages/dish/dish.component.ts +++ b/projects/admin/src/app/pages/dish/dish.component.ts @@ -4,7 +4,9 @@ import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; import { AnyObject, TableListOption } from "@cdk/public-api"; import { DishFormComponent } from "@admin/app/components"; import { ApiService } from "@cdk/services"; -import { Subject } from "rxjs"; +import { Subject, lastValueFrom, tap } from "rxjs"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { NzMessageService } from "ng-zorro-antd/message"; @Component({ selector: "app-dish", @@ -12,7 +14,12 @@ import { Subject } from "rxjs"; styleUrls: ["./dish.component.less"], }) export class DishComponent { - constructor(private drawer: NzDrawerService, private api: ApiService) {} + constructor( + private drawer: NzDrawerService, + private api: ApiService, + private modal: NzModalService, + private msg: NzMessageService + ) {} @ViewChild("formFooterTpl") formFooterTpl!: TemplateRef<{}>; @@ -20,16 +27,22 @@ export class DishComponent { private destroy$ = new Subject(); - tempImg = "https://cdn.pixabay.com/photo/2023/08/08/18/01/butterfly-8177925_1280.jpg"; + public globalEnum = this.api.globalEnum; public tableList = new TableListOption(this.fetchData.bind(this), { selectable: true, + frontPagination: false, }); public queryForm = new FormGroup({ name: new FormControl(""), + mark: new FormControl(""), }); + public selectedIds: string[] = []; + + tableOrg: { [k: number]: string } = {}; + ngOnInit(): void { this.initTableList(); } @@ -42,11 +55,11 @@ export class DishComponent { initTableList() { this.tableList.scroll = { x: null }; this.tableList = this.tableList.setColumns([ - { key: "img", title: "菜品图片", width: "66px" }, + { key: "icon", title: "菜品图片", width: "66px" }, { key: "name", title: "菜品名称" }, - { key: "name", title: "菜品标签" }, - { key: "name", title: "食材及含量", width: "30%" }, - { key: "name", title: "单位" }, + { key: "marks", title: "菜品标签" }, + { key: "foodArr", title: "食材及含量", width: "30%" }, + { key: "vender", title: "单位" }, ]); this.tableList = this.tableList.setOptions([ @@ -69,7 +82,22 @@ export class DishComponent { } fetchData(query: AnyObject, pager: AnyObject) { - return this.api.page(pager, query); + return this.api.getDishPage(pager, query).pipe( + tap((res) => { + if (Array.isArray(res.body.content)) { + this.api.getOrgList({ vendors: res.body.content.map((i) => i.vender) }).subscribe((org) => { + if (Array.isArray(org.body)) { + this.tableOrg = org.body.reduce((a, c) => { + return { + ...a, + [c.id]: c.account, + }; + }, {} as AnyObject); + } + }); + } + }) + ); } showFoodForm(food?: any) { @@ -85,5 +113,17 @@ export class DishComponent { this.drawerRef?.close(); } - deleteItem() {} + deleteItem(v?: any) { + const ids = v ? [v.key] : this.selectedIds; + this.modal.confirm({ + nzTitle: "警告", + nzContent: `是否要删除${ids.length}个菜品?`, + nzOkDanger: true, + nzOnOk: async () => { + const res = await lastValueFrom(this.api.deleteDish(ids)); + this.msg.success(res.desc); + this.tableList.run(); + }, + }); + } } diff --git a/projects/admin/src/app/pages/organization/organization-form/organization-form.component.html b/projects/admin/src/app/pages/organization/organization-form/organization-form.component.html index 8ce50fe..5a85adc 100644 --- a/projects/admin/src/app/pages/organization/organization-form/organization-form.component.html +++ b/projects/admin/src/app/pages/organization/organization-form/organization-form.component.html @@ -10,6 +10,18 @@ + + + 单位类型 + + + + + + + + 单位Logo @@ -71,7 +83,7 @@ - + 初始密码 @@ -96,7 +108,7 @@ 确定 - + 取消 diff --git a/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts b/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts index ade8e33..3058fca 100644 --- a/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts +++ b/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts @@ -39,6 +39,8 @@ export class OrganizationFormComponent { uploadLoading = false; + globalEnum = this.api.globalEnum; + get icon() { return this.formGroup.get("icon")?.value; } @@ -47,8 +49,9 @@ export class OrganizationFormComponent { this.formGroup = this.fb.group({ id: this.fb.control(""), account: this.fb.control("", [FormValidators.required("账号不能为空")]), - password: this.fb.control("", [FormValidators.required("密码不能为空")]), + password: this.fb.control("", this.state ? [] : [FormValidators.required("密码不能为空")]), name: this.fb.control("", [FormValidators.required("单位名称不能为空")]), + category: this.fb.control("", [FormValidators.required("单位类型不能为空")]), expire: this.fb.control("", [FormValidators.required("账号到期时间不能为空")]), icon: this.fb.control("", []), address: this.fb.control("", []), @@ -62,7 +65,7 @@ export class OrganizationFormComponent { async onSubmit() { if (Utils.validateFormGroup(this.formGroup)) { const org = { ...(this.state ?? {}), ...this.formGroup.value }; - org["password"] = MD5(org.password!).toString().substring(16).toUpperCase(); + org["password"] = org.password ? MD5(org.password!).toString().substring(16).toUpperCase() : void 0; org["expire"] = format(org["expire"], "yyyy-MM-dd"); org["venderId"] = org.id; // const account = await lastValueFrom(this.api.checkOrgAccount(org.account!)); diff --git a/projects/admin/src/app/pages/organization/organization-list/organization-list.component.html b/projects/admin/src/app/pages/organization/organization-list/organization-list.component.html index fb8f095..31218ef 100644 --- a/projects/admin/src/app/pages/organization/organization-list/organization-list.component.html +++ b/projects/admin/src/app/pages/organization/organization-list/organization-list.component.html @@ -5,70 +5,62 @@ + + + + + 新增单位 + + + - - - + + + - + + + + - + - - - - - 新增单位 - - - - - - - - 账号 - 单位名称 - 单位类型 - 地址 - 联系人 - 联系电话 - 账号使用状态 - 账号到期时间 - 操作 - - - - - {{data.account}} - {{data.name}} - {{data.category}} - {{data.province}}{{data.area}}{{data.address}} - {{data.contacts}} - {{data.phone}} - - - - - {{data.expire | date:'yyyy-MM-dd'}} - - 编辑 - - 删除 - - - - - - - - + + + + + {{ data|date:'yyyy-MM-dd HH:mm:ss'}} + + + + + + + + + + + {{row.province}}{{row.area}}{{data}} + + + {{data}} + + + + \ No newline at end of file diff --git a/projects/admin/src/app/pages/organization/organization-list/organization-list.component.ts b/projects/admin/src/app/pages/organization/organization-list/organization-list.component.ts index 3597f95..62b32b3 100644 --- a/projects/admin/src/app/pages/organization/organization-list/organization-list.component.ts +++ b/projects/admin/src/app/pages/organization/organization-list/organization-list.component.ts @@ -23,19 +23,51 @@ export class OrganizationListComponent { private msg: NzMessageService ) {} - originalOrgList: OrgDTO[] = []; + public tableList = new TableListOption(this.fetchData.bind(this), { + frontPagination: false, + }); - orgList: OrgDTO[] = []; + globalEnum = this.api.globalEnum; + + public queryForm = new FormGroup({ + category: new FormControl(""), + keyword: new FormControl(""), + }); ngOnInit(): void { - this.getList(); + this.initTableList(); } - getList() { - this.api.getOrgList().subscribe((res) => { - this.originalOrgList = res.body ?? []; - this.orgList = this.originalOrgList; - }); + initTableList() { + this.tableList.scroll = { x: null }; + + this.tableList = this.tableList.setColumns([ + { key: "account", title: "账号" }, + { key: "name", title: "单位名称" }, + { key: "category", title: "单位类型" }, + { key: "address", title: "地址" }, + { key: "contacts", title: "联系人" }, + { key: "phone", title: "联系电话" }, + { key: "status", title: "账号使用状态" }, + { key: "expire", title: "账号到期时间" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: this.toEdit.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + fetchData(p: {}, q: {}) { + return this.api.getOrgPage(p, q); } toEdit(org: OrgDTO) { @@ -44,17 +76,23 @@ export class OrganizationListComponent { }); } - deleteItem(id: number) { + toggleStatus(v: any) { + this.api.saveOrg({ ...v, venderId: v.id, status: !v.status }).subscribe((res) => { + this.msg.success(res.desc); + this.tableList.run(); + }); + } + + deleteItem(v: any) { this.modal.confirm({ nzTitle: "警告", nzContent: "是否要删除该单位?", nzOkDanger: true, nzOnOk: async () => { - const res = await lastValueFrom(this.api.deleteOrg(id)); + const res = await lastValueFrom(this.api.deleteOrg(v.id)); if (res.success) { this.msg.success(res.desc); - this.originalOrgList = this.originalOrgList.filter((f) => f.id !== id); - this.orgList = this.orgList.filter((f) => f.id !== id); + this.tableList.run(); return true; } return false; diff --git a/projects/admin/src/app/pages/standard/standard-form/standard-form.component.html b/projects/admin/src/app/pages/standard/standard-form/standard-form.component.html index 74c6ecd..cca922c 100644 --- a/projects/admin/src/app/pages/standard/standard-form/standard-form.component.html +++ b/projects/admin/src/app/pages/standard/standard-form/standard-form.component.html @@ -24,12 +24,37 @@ - 适用单位 + + 适用单位 + + + + + + + + + 添加单位 + + - - - + + + {{v.label}} + + + + + + @@ -41,7 +66,7 @@ - 确定 + 保存 取消 diff --git a/projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts b/projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts index fbac2c2..39bc4d8 100644 --- a/projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts +++ b/projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts @@ -3,10 +3,11 @@ import { FormBuilder, FormGroup } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; import { OrgDTO } from "@cdk/dtos"; import { ApiService } from "@cdk/services"; +import { OptionItemInterface } from "@cdk/types"; import { Utils } from "@cdk/utils"; import { FormValidators } from "@cdk/validators"; import { NzMessageService } from "ng-zorro-antd/message"; -import { finalize } from "rxjs"; +import { finalize, map } from "rxjs"; @Component({ selector: "app-standard-form", @@ -40,10 +41,11 @@ export class StandardFormComponent { state: any; + nzPopoverVisible = false; + + vendors: OptionItemInterface[] = []; + ngOnInit(): void { - this.api.getOrgList().subscribe((res) => { - this.orgList = res.body; - }); this.formGroup = this.fb.group({ id: this.fb.control("", []), name: this.fb.control("", [FormValidators.required()]), @@ -52,11 +54,39 @@ export class StandardFormComponent { }); this.formGroup.patchValue(this.state); } + + searchOrg = (k: string) => { + return this.api.getOrgList({ keyword: k }).pipe( + map((res) => { + return res.body.map((i) => ({ + label: i.name, + value: i.id + "", + })); + }) + ); + }; + + 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)); + } + onSubmit(gotoSetting?: boolean) { if (Utils.validateFormGroup(this.formGroup)) { this.submitLoading = true; + const { foodCategoryDay, foodCategoryWeek, ingredient } = this.state; this.api - .saveStandard(this.formGroup.value) + .saveStandard({ foodCategoryDay, foodCategoryWeek, ingredient, ...this.formGroup.value }) .pipe( finalize(() => { this.submitLoading = false; diff --git a/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.html b/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.html index cc42a51..06b66f4 100644 --- a/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.html +++ b/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.html @@ -1,53 +1,198 @@ - + - + - + 添加食物种类 - - add + + 0"> + + + + + + + + + + + + + + + + + + + + + + + + + - + - + 添加食物种类 - + + 0"> + + + + + + + + + + + + + + + + + + + + + + + + - + + + 0"> + + + + + 人群名称: + + + + + + + + + + 添加营养素 + + + 删除人群 + + + + + 0"> + 每人每天能量和营养素供给量标准 + + + + + + + + + + + + + + ~ + + + + + + + + + ul值 + + + + + + + + + + + + + + + + + + + + + + + + 添加人群 + + - + - - - - 确定 - - - 取消 - - + + + + + 确定 + + + 取消 + + + \ No newline at end of file diff --git a/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.ts b/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.ts index fc21c90..b96fdd9 100644 --- a/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.ts +++ b/projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.ts @@ -2,9 +2,23 @@ import { Component } 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"; +export type StandardItemInterface = { + type: string; + value: number; +}; + +export type StandardPeopleInterface = { + ul?: number; + hasUl: boolean; + max: number; + min: number; + nutrition: string; +}; + @Component({ selector: "app-standard-setting", templateUrl: "./standard-setting.component.html", @@ -29,15 +43,155 @@ export class StandardSettingComponent { } } - state: any; + public globalEnum = this.api.globalEnum; - formGroup!: FormGroup; + state: any; uploadLoading = false; - ngOnInit(): void {} + foodCategoryDay: StandardItemInterface[] = []; + + foodCategoryWeek: StandardItemInterface[] = []; + + ingredient: { name: string; nutritions: StandardPeopleInterface[] }[] = []; + + ngOnInit(): void { + this.foodCategoryDay = this.parseFoodCategory(this.state?.foodCategoryDay); + this.foodCategoryWeek = this.parseFoodCategory(this.state?.foodCategoryWeek); + this.ingredient = this.parseIngredient(this.state?.ingredient); + } + + parseIngredient(data: any): { name: string; nutritions: StandardPeopleInterface[] }[] { + if (!data) { + return []; + } + return Object.entries(data).map(([k, v]) => { + return { + name: k, + nutritions: !v + ? [] + : Object.entries(v).map(([kn, vn]) => { + return { + ul: vn?.ul ?? 0, + hasUl: !!vn?.ul, + max: vn?.max ?? 0, + min: vn?.min ?? 0, + nutrition: kn, + }; + }), + }; + }); + } + + parseFoodCategory(data: any): StandardItemInterface[] { + if (!data) { + return []; + } + return Object.entries(data).map(([k, v]) => { + return { + type: k, + value: v as number, + }; + }); + } onSubmit() { - this.router.navigate(["/", "standard", "setting", "45"]); + if (this.foodCategoryDay.some((s) => !s.type || !s.value)) { + this.msg.error("请设置正确的食物种类及数量标准(日)"); + return; + } + if (this.foodCategoryWeek.some((s) => !s.type || !s.value)) { + 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.reduce((a, c) => { + return { + ...a, + [c.type]: c.value, + }; + }, {} as AnyObject); + + const foodCategoryWeek = this.foodCategoryWeek.reduce((a, c) => { + return { + ...a, + [c.type]: c.value, + }; + }, {} as AnyObject); + + const ingredient = this.ingredient.reduce((a, c) => { + return { + ...a, + [c.name]: c.nutritions.reduce((an, cn) => { + const ul = cn.hasUl ? { ul: cn.ul } : {}; + return { + ...an, + [cn.nutrition]: { + min: cn.min, + max: cn.max, + ...ul, + }, + }; + }, {} as AnyObject), + }; + }, {} as AnyObject); + + this.api + .saveStandard({ id: this.state.id, foodCategoryDay, foodCategoryWeek, ingredient }, 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({ type: withoutSelectType?.key ?? "", value: 1 }); + } + + removeFoodType(type: string, foodType: string) { + if (type === "day") { + this.foodCategoryDay = this.foodCategoryDay.filter((f) => f.type !== foodType); + } else { + this.foodCategoryWeek = this.foodCategoryWeek.filter((f) => f.type !== foodType); + } + } + + addPeopleGroup() { + this.ingredient.push({ + name: "", + nutritions: [], + }); + } + + removePeopleGroup(idx: number) { + this.ingredient = this.ingredient.filter((_, i) => i !== idx); + } + + addNutrition(idx: number) { + const current = this.ingredient[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; + }); } } diff --git a/projects/cdk/src/dtos/enum.dto.ts b/projects/cdk/src/dtos/enum.dto.ts index a9a8493..4e26c97 100644 --- a/projects/cdk/src/dtos/enum.dto.ts +++ b/projects/cdk/src/dtos/enum.dto.ts @@ -2,6 +2,7 @@ export type GlobalEnum = { category: CategoryDTO[]; mark: MarkDTO[]; nutrient: NutrientDTO[]; + venderType: CategoryDTO[]; }; export type CategoryDTO = { diff --git a/projects/cdk/src/services/api.service.ts b/projects/cdk/src/services/api.service.ts index 58f32e7..d53653e 100644 --- a/projects/cdk/src/services/api.service.ts +++ b/projects/cdk/src/services/api.service.ts @@ -151,8 +151,15 @@ export class ApiService { }); } - getOrgList() { - return this.http.get>("/api/vender"); + getOrgList(query: {}) { + const q = Utils.objectStringify(query); + return this.http.get>(`/api/vender/select?${q}`); + } + + getOrgPage(p: {}, q: {}) { + let params = Utils.objectStringify({ ...p, ...q }, { skipEmptyString: false, skipNull: false }); + + return this.http.get>>(`/api/vender?${params}`); } checkOrgAccount(account: string) { @@ -170,9 +177,9 @@ export class ApiService { } deleteOrg(id: number) { - const params = new HttpParams().set("vender", id); + const params = Utils.objectToFormData({ venderId: id }); return this.http.delete("/api/vender", { - params, + body: params, }); } @@ -211,6 +218,11 @@ export class ApiService { ); } + getFoodList(query: {}) { + const q = Utils.objectStringify(query); + return this.http.get>(`/api/vender/select?${q}`); + } + saveFood(food: AnyObject, isEdit?: boolean) { const body = Utils.objectToFormData(food); const method = isEdit ? "post" : "put"; @@ -230,6 +242,7 @@ export class ApiService { const params = Utils.objectToFormData({ mark, ingredient }); return this.http.put("/api/ingredient/mark", params); } + removeFoodMark(ingredient: string) { const params = Utils.objectToFormData({ ingredient }); return this.http.delete("/api/ingredient/mark", { body: params }); @@ -258,8 +271,8 @@ export class ApiService { } saveStandard(v: AnyObject, isEdit?: boolean) { - const body = Utils.objectToFormData({ ...v, vendors: v["vendors"].join(",") }); - const method = isEdit ? "post" : "put"; + const body = Utils.objectToFormData({ ...v, vendors: v["vendors"]?.join(",") }); + const method = v["id"] ? "post" : "put"; return this.http[method]("/api/nutrition", body); } @@ -267,4 +280,32 @@ export class ApiService { const params = Utils.objectToFormData({ id }); return this.http.delete(`/api/nutrition`, { body: params }); } + + getDishPage(p: {}, q: {}) { + const params = Utils.objectStringify({ ...p, ...q }); + return this.http.get>(`/api/dish?${params}`).pipe( + map((r) => { + if (Array.isArray(r.body.content)) { + r.body.content = r.body.content.map((o) => { + return { + ...o, + foodArr: Object.entries(o.ingredient).map(([k, v]) => { + return { + key: k, + value: v, + label: k, + }; + }), + }; + }); + } + return r; + }) + ); + } + + deleteDish(ids: string[]) { + const params = Utils.objectToFormData({ id: ids.join(",") }); + return this.http.delete(`/api/dish`, { body: params }); + } } diff --git a/projects/cdk/src/shared/components/index.ts b/projects/cdk/src/shared/components/index.ts index e69de29..31254ed 100644 --- a/projects/cdk/src/shared/components/index.ts +++ b/projects/cdk/src/shared/components/index.ts @@ -0,0 +1 @@ +export * from "./search-and-select/search-and-select.component"; diff --git a/projects/cdk/src/shared/components/search-and-select/search-and-select.component.html b/projects/cdk/src/shared/components/search-and-select/search-and-select.component.html new file mode 100644 index 0000000..741223b --- /dev/null +++ b/projects/cdk/src/shared/components/search-and-select/search-and-select.component.html @@ -0,0 +1,47 @@ + + + + + + + + + + 确定 + + + + + + 0" + class="ant-dropdown-menu ant-dropdown-menu-root ant-dropdown-menu-light ant-dropdown-menu-vertical shadow-none"> + + {{o.label}} + + + + + + + \ No newline at end of file diff --git a/projects/cdk/src/shared/components/search-and-select/search-and-select.component.less b/projects/cdk/src/shared/components/search-and-select/search-and-select.component.less new file mode 100644 index 0000000..0b97de3 --- /dev/null +++ b/projects/cdk/src/shared/components/search-and-select/search-and-select.component.less @@ -0,0 +1,17 @@ +:host { + display: block; + width: 100%; +} + +.search-select { + width: 100%; + + min-height: 200px; + max-height: 400px; + + .select { + + overflow-y: auto; + } + +} \ No newline at end of file diff --git a/projects/cdk/src/shared/components/search-and-select/search-and-select.component.ts b/projects/cdk/src/shared/components/search-and-select/search-and-select.component.ts new file mode 100644 index 0000000..10d60b7 --- /dev/null +++ b/projects/cdk/src/shared/components/search-and-select/search-and-select.component.ts @@ -0,0 +1,58 @@ +import { Component, EventEmitter, Input, Output } from "@angular/core"; +import { OptionItemInterface } from "@cdk/types"; +import { NzSelectModeType } from "ng-zorro-antd/select"; +import { Observable, debounceTime } from "rxjs"; + +@Component({ + selector: "search-and-select", + templateUrl: "./search-and-select.component.html", + styleUrls: ["./search-and-select.component.less"], +}) +export class SearchAndSelectComponent { + constructor() {} + + @Input() handleSearh!: (keyword: string) => Observable; + + @Input() placeHolder: string = "输入关键字搜索然后选择"; + + @Input() mode: NzSelectModeType = "multiple"; + + @Output() onSelect = new EventEmitter>(); + + listOfOption: Array = []; + + searchValue = ""; + + selected = new Set(); + + nzFilterOption = (): boolean => true; + + search(value: string) { + if (!value) { + return; + } + this.handleSearh + .call(this, value) + .pipe(debounceTime(500)) + .subscribe((data) => { + this.listOfOption = data; + // this.listOfOption = Array.from({ length: 2 }, (_, i) => ({ label: "dd" + i, value: i.toString() })); + }); + } + + handleSelect(v: string) { + if (this.selected.has(v)) { + this.selected.delete(v); + } else { + this.selected.add(v); + } + } + + onSubmit() { + const selects: OptionItemInterface[] = []; + this.selected.forEach((i) => { + selects.push(this.listOfOption.find((f) => f.value === i)!); + }); + this.onSelect.emit(selects); + } +} diff --git a/projects/cdk/src/shared/shared.module.ts b/projects/cdk/src/shared/shared.module.ts index 9523e08..666a971 100644 --- a/projects/cdk/src/shared/shared.module.ts +++ b/projects/cdk/src/shared/shared.module.ts @@ -20,6 +20,7 @@ import { // import { environment } from "@manage/environments/environment"; import { NgxPermissionsModule } from "ngx-permissions"; import { AppPageComponent } from "@cdk/app-page/app-page.component"; +import { SearchAndSelectComponent } from "./components"; const ngModules = [CommonModule, HttpClientModule, FormsModule, RouterModule, ReactiveFormsModule]; const components: any = []; @@ -35,8 +36,16 @@ const cdks = [ ] as any; @NgModule({ - declarations: [...components, ...directives], + declarations: [...components, ...directives, SearchAndSelectComponent], imports: [...ngZorroModules, ...ngModules, ...cdks, AppPageComponent], - exports: [...ngZorroModules, ...ngModules, ...components, ...directives, ...cdks, AppPageComponent], + exports: [ + ...ngZorroModules, + ...ngModules, + ...components, + ...directives, + ...cdks, + AppPageComponent, + SearchAndSelectComponent, + ], }) export class SharedModule {} diff --git a/projects/cdk/src/table-list/table-list/table-list.component.ts b/projects/cdk/src/table-list/table-list/table-list.component.ts index 465a6ae..b2c9575 100644 --- a/projects/cdk/src/table-list/table-list/table-list.component.ts +++ b/projects/cdk/src/table-list/table-list/table-list.component.ts @@ -141,6 +141,7 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD }) ) .subscribe((f: ResponseType) => { + // 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); diff --git a/projects/cdk/src/types/index.ts b/projects/cdk/src/types/index.ts index 2494cad..bfd3ed4 100644 --- a/projects/cdk/src/types/index.ts +++ b/projects/cdk/src/types/index.ts @@ -6,6 +6,11 @@ export type DecText = number | string; export type Augmented = O & AnyObject; +export type OptionItemInterface = Augmented<{ + label: string; + value: string; +}>; + export interface ResponseType { body: T; code: number; diff --git a/projects/cdk/src/utils/index.ts b/projects/cdk/src/utils/index.ts index 25a2b16..bfbc3dd 100644 --- a/projects/cdk/src/utils/index.ts +++ b/projects/cdk/src/utils/index.ts @@ -1,7 +1,7 @@ import { HttpParams } from "@angular/common/http"; import { AbstractControl, FormControl, FormGroup } from "@angular/forms"; import { AnyObject } from "@cdk/types"; -import queryString from "query-string"; +import queryString, { StringifyOptions } from "query-string"; export class Utils { static validateFormGroup(formGroup: FormGroup) { @@ -92,11 +92,13 @@ export class Utils { } }; - static objectStringify(o: AnyObject) { - return queryString.stringify(o, { + static objectStringify(o: AnyObject, option?: StringifyOptions) { + const config = { skipEmptyString: true, skipNull: true, - arrayFormat: "comma", - }); + arrayFormat: "comma" as any, + ...option, + }; + return queryString.stringify(o, config); } }