Browse Source

更新文档

main
kkerwin 2 years ago
parent
commit
a2939f9ce1
  1. 13
      README.md
  2. 15
      doc/change.md
  3. 184
      doc/dish.md
  4. 1
      doc/index.md
  5. 6
      doc/ingredient.md
  6. 7
      doc/user.md
  7. 39
      doc/vender.md
  8. 5
      projects/admin/src/app/pages/food/food.component.ts
  9. 2
      projects/admin/src/app/pages/login/login.component.less
  10. 16
      projects/admin/src/app/pages/standard/standard-form/standard-form.component.html
  11. 85
      projects/admin/src/app/pages/standard/standard-form/standard-form.component.ts
  12. 24
      projects/admin/src/app/pages/standard/standard-list/standard-list.component.html
  13. 57
      projects/admin/src/app/pages/standard/standard-list/standard-list.component.ts
  14. 11
      projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.html
  15. 62
      projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.ts
  16. 52
      projects/cdk/src/services/api.service.ts
  17. 7
      projects/cdk/src/utils/index.ts
  18. 3
      projects/client/src/app/pages/food/food.component.ts

13
README.md

@ -25,3 +25,16 @@ Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To u
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
------
# 09/16 ~ 09/17
1. 业务端取消常用/忌用 系统异常
2. 修改食材 提示成功 但是数据没有变化。 食材编号 是否允许 修改,若修改 会报错 [参数错误]食材不存在!
3. 业务端 配餐设置 POST /api/vender/config 405 无权限执行该操作!
4. 管理端 用户列表、修改角色名称、删除角色 报错: 系统异常 好像大部分用户管理的接口 都在报错
5. 删除 食材 系统异常
6. 管理端 食材列表 没有返回 更新日期
7. 营养标准列表 列表 没有 更新时间
8. 营养标准添加成功 需要 返回他的 id

15
doc/change.md

@ -10,6 +10,15 @@
> 9.11
```
食材
菜品
食谱
用户列表协议返回字段增加添加时间:time
添加角色协议请求中的权限项列表允许为空
角色列表协议返回的权限项由字符串给位数组
```
```
9.17
食材接口: mark接口的(PUT, DELETE) ingredient(DELETE)参数名字改了下,
单位接口: vender接口的(GET) 增加keyword参数,并改为分页查询;
增加/api/vender/select(GET), 用于管理端其他部分下来狂选择单位

184
doc/dish.md

File diff suppressed because one or more lines are too long

1
doc/index.md

@ -7,7 +7,6 @@
### 协议列表
```
* [协议约定](protocol.md)
* [修改记录](change.md)
* [基础协议](basic.md)
* [用户权限](user.md)

6
doc/ingredient.md

@ -97,7 +97,7 @@ nutrient={"fat": 10, "energy": 10, "calcium": 12, "protein": 15, "vitamin-a": 23
### 输入:
```
Content-Type:application/x-www-form-urlencoded
ingredients=010101,0101012,0101013 // 必填
keys=010101,0101012,0101013 // 必填
```
@ -117,7 +117,7 @@ ingredients=010101,0101012,0101013 // 必填
### 输入:
```
Content-Type:application/x-www-form-urlencoded
ingredient=010101 // 食材编号
key=010101 // 食材编号
mark=常用 // 必填, 取值: 常用/忌用
```
@ -138,7 +138,7 @@ mark=常用 // 必填, 取值: 常用/忌用
### 输入:
```
Content-Type:application/x-www-form-urlencoded
ingredient=010101 // 食材编号
key=010101 // 食材编号
```

7
doc/user.md

@ -92,7 +92,8 @@ roleId=2 //修改角色, 0-标识回收角色,其他-标识分配角色
"phone": "13919103409",
"roleId": 2,
"roleName": "超级管理员",
"uid": "xxx"
"uid": "xxx",
"time" 123412341234
}
],
"code": 200,
@ -227,7 +228,7 @@ roleId=2 //修改角色, 0-标识回收角色,其他-标识分配角色
```
Content-Type:application/x-www-form-urlencoded
roleName=ccc // 必填, 角色名称
items=1,2,3 // 必填, 赋予的权限项
items=1,2,3 // 赋予的权限项
```
### 输出:
@ -290,7 +291,7 @@ items=1,2,3 // 赋予的权限项
"body": [
{
"id": 2,
"roleItems": "[18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]",
"roleItems": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34],
"roleName": "超级管理员",
"roleType": "系统",
"vender": 1

39
doc/vender.md

@ -125,6 +125,7 @@ vender=1 // 必填
### 输入:
```
Content-Type:application/x-www-form-urlencoded
vender=1 // 必填
expire=2019-10-10 // 仅管理端可以改过期时间
status=false // 仅管理端可以改状态, false-关闭,true-打开
@ -152,11 +153,16 @@ email=
> GET /api/vender
>
> 管理端接口
### 输入:
```
keyword=1 // 根据单位名称模糊匹配
```
### 输出:
```
{
"body": [
"body": {
"content": [
{
"account": "xxx",
"address": "百仁路",
@ -173,6 +179,37 @@ email=
"status": true
}
],
"number": 0,
"size": 20,
"totalElements": 1,
"totalPages": 1
},
"code": 200,
"desc": "成功",
"success": true
}
```
# 9. 获取企业列表(管理端其他部分选择企业使用)
> GET /api/vender/select
>
> 管理端接口
### 输入:
```
keyword=1 // 根据单位名称模糊匹配
```
### 输出:
```
{
"body": [
{
"account": "xxx",
"category": "小学",
"id": 1,
"name": "成都实验小学"
}
],
"code": 200,
"desc": "成功",
"success": true

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

@ -46,6 +46,8 @@ export class FoodComponent implements OnInit, OnDestroy {
submitLoading = false;
editItem = null;
ngOnInit(): void {
this.initTableList();
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => {
@ -92,6 +94,7 @@ export class FoodComponent implements OnInit, OnDestroy {
}
showFoodForm(food?: any) {
this.editItem = food;
this.drawerRef = this.drawer.create({
nzTitle: food ? "编辑食材" : "新增食材",
nzWidth: 520,
@ -110,7 +113,7 @@ export class FoodComponent implements OnInit, OnDestroy {
if (val) {
this.submitLoading = true;
this.api
.saveFood(val)
.saveFood(val, !!this.editItem)
.pipe(
finalize(() => {
this.submitLoading = false;

2
projects/admin/src/app/pages/login/login.component.less

@ -29,7 +29,7 @@
.card {
width: 960px;
height: 60vh;
height: 580px;
min-height: 410px;
display: flex;
align-items: center;

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

@ -7,7 +7,7 @@
营养标准名称
</nz-form-label>
<nz-form-control [nzErrorTip]="formControlErrorTpl" nzSpan="12">
<input nz-input placeholder="请输入营养标准名称" />
<input nz-input placeholder="请输入营养标准名称" formControlName="name" />
</nz-form-control>
</nz-form-item>
@ -17,7 +17,7 @@
</nz-form-label>
<nz-form-control [nzErrorTip]="formControlErrorTpl" nzSpan="12">
<nz-input-group nzAddOnBefore="±" nzAddOnAfter="%">
<input nz-input />
<input nz-input formControlName="overflow" />
</nz-input-group>
</nz-form-control>
</nz-form-item>
@ -27,19 +27,23 @@
适用单位
</nz-form-label>
<nz-form-control [nzErrorTip]="formControlErrorTpl" nzSpan="12">
<nz-select [nzOptions]="[]" nzMode="multiple" nzPlaceHolder="请选择适用单位"></nz-select>
<nz-select nzMode="multiple" nzPlaceHolder="请选择适用单位" formControlName="vendors">
<nz-option *ngFor="let org of orgList" [nzValue]="org.id" [nzLabel]="org.name"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzErrorTip]="formControlErrorTpl" nzSpan="12">
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit()">
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit(true)"
[nzLoading]="submitLoading">
保存并设置营养标准
</button>
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit()">
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit()"
[nzLoading]="submitLoading">
确定
</button>
<button *nzSpaceItem nz-button>
<button *nzSpaceItem nz-button type="button" [routerLink]="['/standard/list']">
取消
</button>
</nz-space>

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

@ -1,7 +1,12 @@
import { Component } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { Router } from "@angular/router";
import { ActivatedRoute, Router } from "@angular/router";
import { OrgDTO } from "@cdk/dtos";
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";
@Component({
selector: "app-standard-form",
@ -9,49 +14,59 @@ import { FormValidators } from "@cdk/validators";
styleUrls: ["./standard-form.component.less"],
})
export class StandardFormComponent {
constructor(private fb: FormBuilder, private router: Router) {}
constructor(
private fb: FormBuilder,
private router: Router,
private route: ActivatedRoute,
private api: ApiService,
private msg: NzMessageService
) {
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"]);
}
}
}
formGroup!: FormGroup;
uploadLoading = false;
submitLoading = false;
orgList: OrgDTO[] = [];
state: any;
ngOnInit(): void {
this.api.getOrgList().subscribe((res) => {
this.orgList = res.body;
});
this.formGroup = this.fb.group({
id: this.fb.control("", [FormValidators.required()]),
id: this.fb.control("", []),
name: this.fb.control("", [FormValidators.required()]),
unit: this.fb.control("", [FormValidators.required()]),
day: this.fb.control("1", [FormValidators.required()]),
logo: this.fb.control("", []),
month: this.fb.control([], []),
vendors: this.fb.control([], [FormValidators.required()]),
overflow: this.fb.control("0", [FormValidators.required()]),
});
this.formGroup.patchValue(this.state);
}
onSubmit() {
this.router.navigate(["/", "standard", "setting", "45"]);
onSubmit(gotoSetting?: boolean) {
if (Utils.validateFormGroup(this.formGroup)) {
this.submitLoading = true;
this.api
.saveStandard(this.formGroup.value)
.pipe(
finalize(() => {
this.submitLoading = false;
})
)
.subscribe((res) => {
this.msg.success(res.desc);
const redirectTo = gotoSetting ? ["/", "standard", "setting", res.body] : ["/standard/list"];
this.router.navigate(redirectTo);
});
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement;
const file = target.files![0];
target.value = "";
const formData = new FormData();
const fileReader = new FileReader();
fileReader.onload = () => {
const base64 = fileReader.result as string;
const v = base64.split("base64,")[1];
};
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);
// });
}
}

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

@ -17,15 +17,21 @@
<ng-template #searchTpl>
<nz-form-item class="w-60">
<nz-form-control>
<input nz-input placeholder="请输入营养标准名称" />
<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="'img'">
<ng-container *ngSwitchCase="'time'">
{{ data|date:'yyyy-MM-dd HH:mm:ss'}}
</ng-container>
<ng-container *ngSwitchCase="'vendors'">
{{ data.length }}个单位
</ng-container>
<ng-container *ngSwitchCase="'people'">
{{ data.length }}个人群
</ng-container>
<ng-container *ngSwitchDefault>
@ -38,15 +44,3 @@
</nz-card>
</div>
</app-page>
<ng-template #formFooterTpl>
<nz-space>
<button *nzSpaceItem nz-button (click)="cancelFoodForm()">
取消
</button>
<button *nzSpaceItem nz-button nzType="primary">
保存
</button>
</nz-space>
</ng-template>

57
projects/admin/src/app/pages/standard/standard-list/standard-list.component.ts

@ -4,6 +4,10 @@ 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 { NzModalService } from "ng-zorro-antd/modal";
import { lastValueFrom } from "rxjs";
import { NzMessageService } from "ng-zorro-antd/message";
import { Router } from "@angular/router";
@Component({
selector: "app-standard-list",
@ -11,16 +15,17 @@ import { ApiService } from "@cdk/services";
styleUrls: ["./standard-list.component.less"],
})
export class StandardListComponent {
constructor(private drawer: NzDrawerService, private api: ApiService) {}
@ViewChild("formFooterTpl") formFooterTpl!: TemplateRef<{}>;
private drawerRef?: NzDrawerRef;
constructor(
private api: ApiService,
private modal: NzModalService,
private msg: NzMessageService,
private router: Router
) {}
public tableList = new TableListOption(this.fetchData.bind(this));
public queryForm = new FormGroup({
name: new FormControl(""),
keyword: new FormControl(""),
});
ngOnInit(): void {
@ -31,21 +36,21 @@ export class StandardListComponent {
this.tableList.scroll = { x: null };
this.tableList = this.tableList.setColumns([
{ key: "name", title: "营养标准名称" },
{ key: "name", title: "人群细分" },
{ key: "name", title: "适用单位" },
{ key: "name", title: "更新时间" },
{ key: "people", title: "人群细分" },
{ key: "vendors", title: "适用单位" },
{ key: "time", title: "更新时间" },
]);
this.tableList = this.tableList.setOptions([
{
title: "标准设置",
premissions: [],
onClick: this.showFoodForm.bind(this),
onClick: this.toSetting.bind(this),
},
{
title: "编辑",
premissions: [],
onClick: this.showFoodForm.bind(this),
onClick: this.toEdit.bind(this),
},
{
title: "删除",
@ -56,21 +61,31 @@ export class StandardListComponent {
}
fetchData(query: AnyObject, pager: AnyObject) {
return this.api.page(pager, query);
return this.api.getStandardPage(pager, query);
}
showFoodForm(food?: any) {
this.drawerRef = this.drawer.create({
nzTitle: food ? "编辑菜品" : "新增菜品",
nzWidth: 700,
nzContent: DishFormComponent,
nzFooter: this.formFooterTpl,
toEdit(d: AnyObject) {
this.router.navigate([`/standard/form/${d["id"]}`], {
state: d,
});
}
cancelFoodForm() {
this.drawerRef?.close();
toSetting(d: AnyObject) {
this.router.navigate([`/standard/setting/${d["id"]}`], {
state: d,
});
}
deleteItem() {}
deleteItem(v: any) {
this.modal.confirm({
nzTitle: "警告",
nzContent: `是否要删除该营养标准?`,
nzOkDanger: true,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.deleteStandard(v.id));
this.msg.success(res.desc);
this.tableList.run();
},
});
}
}

11
projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.html

@ -39,4 +39,15 @@
<ng-template #formControlErrorTpl let-control>
<form-error-tips [control]="control"></form-error-tips>
</ng-template>
<div class="fixed-footter left-[218px] fixed bottom-0 right-0 bg-white z-10 pl-8 py-2">
<nz-space>
<button *nzSpaceItem nz-button nzType="primary" (click)="onSubmit()">
确定
</button>
<button *nzSpaceItem nz-button>
取消
</button>
</nz-space>
</div>
</app-page>

62
projects/admin/src/app/pages/standard/standard-setting/standard-setting.component.ts

@ -1,7 +1,9 @@
import { Component } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import { Router } from "@angular/router";
import { ActivatedRoute, Router } from "@angular/router";
import { ApiService } from "@cdk/services";
import { FormValidators } from "@cdk/validators";
import { NzMessageService } from "ng-zorro-antd/message";
@Component({
selector: "app-standard-setting",
@ -9,49 +11,33 @@ import { FormValidators } from "@cdk/validators";
styleUrls: ["./standard-setting.component.less"],
})
export class StandardSettingComponent {
constructor(private fb: FormBuilder, private router: Router) {}
constructor(
private fb: FormBuilder,
private router: Router,
private route: ActivatedRoute,
private api: ApiService,
private msg: NzMessageService
) {
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"]);
}
}
}
state: any;
formGroup!: FormGroup;
uploadLoading = false;
ngOnInit(): void {
this.formGroup = this.fb.group({
id: this.fb.control("", [FormValidators.required()]),
name: this.fb.control("", [FormValidators.required()]),
unit: this.fb.control("", [FormValidators.required()]),
day: this.fb.control("1", [FormValidators.required()]),
logo: this.fb.control("", []),
month: this.fb.control([], []),
});
}
ngOnInit(): void {}
onSubmit() {
this.router.navigate(["/", "standard", "setting", "45"]);
}
onFileChange(e: Event) {
const target = e.target as HTMLInputElement;
const file = target.files![0];
target.value = "";
const formData = new FormData();
const fileReader = new FileReader();
fileReader.onload = () => {
const base64 = fileReader.result as string;
const v = base64.split("base64,")[1];
};
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);
// });
}
}

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

@ -211,24 +211,60 @@ export class ApiService {
);
}
saveFood(food: AnyObject) {
saveFood(food: AnyObject, isEdit?: boolean) {
const body = Utils.objectToFormData(food);
const method = food["id"] ? "post" : "put";
const method = isEdit ? "post" : "put";
return this.http[method]<ResponseType>("/api/ingredient", body);
}
deleteFoods(ids: number[]) {
const params = Utils.objectStringify({ nutrients: ids });
console.log("params", params, { nutrients: ids });
return this.http.delete<ResponseType>(`/api/ingredient?${params}`);
const params = Utils.objectToFormData({ ingredients: ids.join(",") });
return this.http.delete<ResponseType>(`/api/ingredient`, { body: params });
}
importFood(f: FormData) {
return this.http.put<ResponseType>("/api/ingredient/mark", f);
return this.http.put<ResponseType>("/api/ingredient/upload", f);
}
markFood(mark: string, nutrient: string) {
const params = Utils.objectToFormData({ mark, nutrient }, false);
markFood(mark: string, ingredient: string) {
const params = Utils.objectToFormData({ mark, ingredient });
return this.http.put<ResponseType>("/api/ingredient/mark", params);
}
removeFoodMark(ingredient: string) {
const params = Utils.objectToFormData({ ingredient });
return this.http.delete<ResponseType>("/api/ingredient/mark", { body: params });
}
getStandardPage(p: {}, q: {}) {
const params = Utils.objectStringify({ ...p, ...q });
return this.http.get<ResponseType<PageResult>>(`/api/nutrition?${params}`).pipe(
map((r) => {
if (Array.isArray(r.body.content)) {
r.body.content = r.body.content.map((o) => {
return {
...o,
people: Object.entries(o.ingredient ?? {}).map(([k, v]) => {
return {
peopleGroupName: k,
...((v as any) ?? {}),
};
}),
};
});
}
return r;
})
);
}
saveStandard(v: AnyObject, isEdit?: boolean) {
const body = Utils.objectToFormData({ ...v, vendors: v["vendors"].join(",") });
const method = isEdit ? "post" : "put";
return this.http[method]<ResponseType>("/api/nutrition", body);
}
deleteStandard(id: string) {
const params = Utils.objectToFormData({ id });
return this.http.delete<ResponseType>(`/api/nutrition`, { body: params });
}
}

7
projects/cdk/src/utils/index.ts

@ -61,15 +61,13 @@ export class Utils {
return params;
}
static objectToFormData(obj: AnyObject, skipEmpty: boolean = true): FormData {
static objectToFormData(obj: AnyObject): FormData {
let params = new FormData();
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
let value = obj[key];
if (skipEmpty && [void 0, null, ""].includes(value)) {
break;
}
if (![void 0, null, ""].includes(value)) {
if (typeof value === "object") {
params.append(key, JSON.stringify(value));
} else {
@ -77,6 +75,7 @@ export class Utils {
}
}
}
}
return params;
}

3
projects/client/src/app/pages/food/food.component.ts

@ -119,7 +119,8 @@ export class FoodComponent implements OnInit, OnDestroy {
nzContent: `是否要将食材该食材${text}`,
nzOkDanger: true,
nzOnOk: async () => {
const res = await lastValueFrom(this.api.markFood(mark, v.key));
const api = mark ? this.api.markFood(mark, v.key) : this.api.removeFoodMark(v.key);
const res = await lastValueFrom(api);
this.msg.success(res.desc);
this.tableList.run();
},

Loading…
Cancel
Save