Browse Source

权限

main
kkerwin 2 years ago
parent
commit
ee282e115e
  1. 2
      package.json
  2. 8
      pnpm-lock.yaml
  3. 94
      projects/admin/src/app/app-routing.module.ts
  4. 2
      projects/admin/src/app/app.module.ts
  5. 12
      projects/admin/src/app/pages/dish/dish.component.ts
  6. 2
      projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html
  7. 20
      projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts
  8. 23
      projects/admin/src/app/pages/ingredients/ingredient-preview-page/ingredient-preview-page.component.ts
  9. 10
      projects/admin/src/app/pages/system/user-manage/user-manage.component.html
  10. 36
      projects/admin/src/app/services/permisson.guard.ts
  11. BIN
      projects/admin/src/favicon.ico
  12. 4
      projects/admin/src/index.html
  13. 14
      projects/admin/src/styles.less
  14. 154
      projects/cdk/src/ingredient/ingredient-analysis/ingredient-analysis.component.html
  15. 21
      projects/cdk/src/ingredient/ingredient-analysis/ingredient-analysis.component.ts
  16. 10
      projects/cdk/src/ingredient/ingredient-dish/ingredient-dish.component.html
  17. 16
      projects/cdk/src/ingredient/ingredient-dish/ingredient-dish.component.less
  18. 3
      projects/cdk/src/ingredient/ingredient-dish/ingredient-dish.component.ts
  19. 4
      projects/cdk/src/ingredient/ingredient-form-basic/ingredient-form-basic.component.html
  20. 2
      projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html
  21. 4
      projects/cdk/src/ingredient/ingredient-preview/ingredient-preview.component.html
  22. 22
      projects/cdk/src/ingredient/ingredient-preview/ingredient-preview.component.ts
  23. 36
      projects/cdk/src/ingredient/nutrition-table/nutrition-table.component.html
  24. 25
      projects/cdk/src/ingredient/nutrition-table/nutrition-table.component.less
  25. 9
      projects/cdk/src/services/api.service.ts
  26. 4
      projects/cdk/src/shared/components/forbidden/forbidden.component.html
  27. 0
      projects/cdk/src/shared/components/forbidden/forbidden.component.less
  28. 14
      projects/cdk/src/shared/components/forbidden/forbidden.component.ts
  29. 2
      projects/cdk/src/shared/components/index.ts
  30. 6
      projects/cdk/src/shared/components/notfound/notfound.component.html
  31. 0
      projects/cdk/src/shared/components/notfound/notfound.component.less
  32. 10
      projects/cdk/src/shared/components/notfound/notfound.component.ts
  33. 7
      projects/cdk/src/shared/shared.module.ts
  34. 15
      projects/cdk/src/types/index.ts
  35. 2
      projects/cdk/src/utils/index.ts
  36. 89
      projects/client/src/app/app-routing.module.ts
  37. 3
      projects/client/src/app/app.module.ts
  38. 33
      projects/client/src/app/components/app-layout/app-layout.component.html
  39. 29
      projects/client/src/app/pages/data-vis/data-vis.component.html
  40. 12
      projects/client/src/app/pages/data-vis/data-vis.component.less
  41. 19
      projects/client/src/app/pages/data-vis/data-vis.component.ts
  42. 4
      projects/client/src/app/pages/dish/dish.component.html
  43. 11
      projects/client/src/app/pages/dish/dish.component.ts
  44. 4
      projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html
  45. 109
      projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts
  46. 9
      projects/client/src/app/pages/system/user-manage/user-manage.component.html
  47. 2
      projects/client/src/app/pages/system/user-manage/user-manage.component.ts
  48. 36
      projects/client/src/app/services/permisson.guard.ts
  49. BIN
      projects/client/src/favicon.ico
  50. 2
      projects/client/src/index.html
  51. 14
      projects/client/src/styles.less

2
package.json

@ -26,7 +26,7 @@
"date-fns": "^2.30.0",
"immer": "^10.0.2",
"ng-zorro-antd": "16.1.0",
"ngx-permissions": "^15.0.1",
"ngx-permissions": "^16.0.1",
"query-string": "^8.1.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",

8
pnpm-lock.yaml

@ -48,8 +48,8 @@ dependencies:
specifier: 16.1.0
version: 16.1.0(@angular/animations@16.1.0)(@angular/common@16.1.0)(@angular/core@16.1.0)(@angular/forms@16.1.0)(@angular/platform-browser@16.1.0)(@angular/router@16.1.0)(rxjs@7.8.0)
ngx-permissions:
specifier: ^15.0.1
version: 15.0.1(@angular/core@16.1.0)(@angular/router@16.1.0)(rxjs@7.8.0)
specifier: ^16.0.1
version: 16.0.1(@angular/core@16.1.0)(@angular/router@16.1.0)(rxjs@7.8.0)
query-string:
specifier: ^8.1.0
version: 8.1.0
@ -5345,8 +5345,8 @@ packages:
- rxjs
dev: false
/ngx-permissions@15.0.1(@angular/core@16.1.0)(@angular/router@16.1.0)(rxjs@7.8.0):
resolution: {integrity: sha512-GjPF54B0DYtzqVb95YUh1XZivU4ilpCnx04gtADnIz4grihb/AtVwGwjgeeC1N/zrwUaZWLxTkIm5emN11JlDw==}
/ngx-permissions@16.0.1(@angular/core@16.1.0)(@angular/router@16.1.0)(rxjs@7.8.0):
resolution: {integrity: sha512-4nGBuZCMgVySgUbwLpTNRFAS73bTt8uFCwBC5XQW/RxvkIH7UmtdtBD9VKBa7fgG8nEW5GPOCXy7L7ixP1gTvg==}
peerDependencies:
'@angular/core': '>=13 || >18'
'@angular/router': '>=13 || >18'

94
projects/admin/src/app/app-routing.module.ts

@ -19,20 +19,55 @@ import {
} from "./pages";
import { AppLayoutComponent } from "./components";
import { authGuard } from "./services/auth.guard";
// import { PermissionLoadGuard } from "@client/app/services/permisson.guard";
import { ngxPermissionsGuard } from "ngx-permissions";
import { ForbiddenComponent, NotfoundComponent } from "@cdk/shared/components";
import { PermissionLoadGuard } from "./services/permisson.guard";
const routes: Routes = [
{ path: "login", component: LoginComponent },
{ path: "forbidden", component: ForbiddenComponent },
{
path: "",
component: AppLayoutComponent,
canActivate: [authGuard],
canActivate: [authGuard, PermissionLoadGuard],
children: [
{ path: "", pathMatch: "full", redirectTo: "food" },
{ path: "home", component: HomeComponent },
{ path: "food", component: FoodComponent, title: "食材管理" },
{ path: "dish", component: DishComponent, title: "菜品管理" },
{
path: "food",
component: FoodComponent,
title: "食材管理",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["1", "2"],
redirectTo: "/forbidden",
},
},
},
{
path: "dish",
component: DishComponent,
title: "菜品管理",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["3", "4"],
redirectTo: "/forbidden",
},
},
},
{
path: "standard",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["11", "12"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "",
@ -56,6 +91,13 @@ const routes: Routes = [
{
path: "ingredient",
title: "食谱管理",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["5", "6", "7", "8", "9", "10"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "",
@ -65,6 +107,13 @@ const routes: Routes = [
{
path: "item",
title: "食谱库",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["5", "6"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "",
@ -86,22 +135,50 @@ const routes: Routes = [
path: "review",
title: "食谱审核",
component: IngredientReviewComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["7", "8"],
redirectTo: "/forbidden",
},
},
},
{
path: "preview",
title: "食谱预览",
component: IngredientPreviewPageComponent,
// canActivate: [ngxPermissionsGuard],
// data: {
// permissions: {
// only: ["23", "24"],
// redirectTo: "/forbidden",
// },
// },
},
{
path: "release",
title: "食谱发布计划",
component: IngredientReleaseComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["9", "10"],
redirectTo: "/forbidden",
},
},
},
],
},
{
path: "organization",
title: "单位管理",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["13", "14"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "",
@ -121,6 +198,13 @@ const routes: Routes = [
{
path: "system",
title: "系统设置",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["15", "16", "17"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "user",
@ -131,6 +215,10 @@ const routes: Routes = [
},
],
},
{
path: "**",
component: NotfoundComponent,
},
];
@NgModule({

2
projects/admin/src/app/app.module.ts

@ -40,6 +40,7 @@ import { HTTPInterceptor } from "./services/http.interceptor";
import { IconsProviderModule, PROJECT_NAME } from "@cdk/public-api";
import { SharedModule } from "@cdk/shared/shared.module";
import { IngredientModule } from "@cdk/ingredient/ingredient.module";
import { NgxPermissionsModule } from "ngx-permissions";
registerLocaleData(zh);
@ -81,6 +82,7 @@ registerLocaleData(zh);
IconsProviderModule,
SharedModule,
IngredientModule,
NgxPermissionsModule.forRoot(),
],
providers: [
{ provide: NZ_I18N, useValue: zh_CN },

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

@ -138,10 +138,18 @@ export class DishComponent {
this.msg.loading("数据请求中,请不要刷新页面", {
nzDuration: 0,
});
this.api.getDishLabel(v.id).subscribe((res) => {
this.api
.getDishLabel(v.id)
.pipe(
finalize(() => {
setTimeout(() => {
this.msg.remove();
}, 1000);
})
)
.subscribe((res) => {
this.printData = res.body[0];
this.printRef.print();
this.msg.remove();
});
}

2
projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html

@ -17,7 +17,7 @@
</div>
<nz-space>
<button *nzSpaceItem nz-button>
<button *nzSpaceItem nz-button (click)="analysis()">
食谱营养分析
</button>
<button *nzSpaceItem nz-button (click)="createNewMenu()">

20
projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts

@ -1,10 +1,12 @@
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 { MealDishInterface } from "@cdk/ingredient/ingredient-meals/ingredient-meals.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";
@ -20,7 +22,8 @@ export class IngredientFormComponent implements OnInit {
private msg: NzMessageService,
private router: Router,
private route: ActivatedRoute,
private api: ApiService
private api: ApiService,
private drawer: NzDrawerService
) {
this.id = this.route.snapshot.paramMap.get("id");
}
@ -114,6 +117,21 @@ export class IngredientFormComponent implements OnInit {
});
}
analysis() {
this.drawer.create({
nzWidth: 620,
nzWrapClassName: "analysis-drawer",
nzContent: IngredientAnalysisComponent,
nzContentParams: {
menu: {
...this.menuItem,
days: [],
},
current: {},
},
});
}
previewMenu() {
const { mealDishList } = this.menuDish;
const snapshot = Date.now().toString();

23
projects/admin/src/app/pages/ingredients/ingredient-preview-page/ingredient-preview-page.component.ts

@ -10,18 +10,15 @@ export class IngredientPreviewPageComponent implements OnInit {
constructor(private route: ActivatedRoute, private router: Router) {}
ngOnInit(): void {
const id = this.route.snapshot.queryParamMap.get("id");
const storage = sessionStorage.getItem("current_menu");
if (id) {
console.log(id);
return;
}
if (storage) {
return;
}
this.router.navigate(["/ingredient/item/list"]);
// const id = this.route.snapshot.queryParamMap.get("id");
// const storage = sessionStorage.getItem("current_menu");
// if (id) {
// console.log(id);
// return;
// }
// if (storage) {
// return;
// }
// this.router.navigate(["/ingredient/item/list"]);
}
}

10
projects/admin/src/app/pages/system/user-manage/user-manage.component.html

@ -1,13 +1,13 @@
<app-page [scroll]="false">
<div nz-row class="h-full overflow-hidden bg-white rounded-lg">
<div nz-col nzFlex="220px" class="user-type">
<div nz-col nzFlex="220px" class="user-type h-full">
<nz-card
class="h-full "
class="h-full flex flex-col"
[nzBordered]="false"
nzTitle="用户角色"
[nzBodyStyle]="{padding:'1px 0 0 0'}">
[nzBodyStyle]="{padding:'1px 0 0 0',flex:'1', 'overflow':'hidden'}">
<div class="h-full overflow-y-auto overflow-x-hidden">
<ul nz-menu nzMode="inline">
<li
*ngFor="let item of roleList"
@ -38,6 +38,8 @@
</span>
</button>
</div>
</div>
</nz-card>
</div>
<div nz-col nzFlex="1" class="flex-1 h-full overflow-hidden bg-white ">

36
projects/admin/src/app/services/permisson.guard.ts

@ -0,0 +1,36 @@
import { inject } from "@angular/core";
import {
ActivatedRoute,
ActivatedRouteSnapshot,
CanActivateChildFn,
CanActivateFn,
Route,
Router,
RouterStateSnapshot,
} from "@angular/router";
import { ClientAccountDTO } from "@cdk/dtos";
import { ApiService } from "@cdk/services";
import { NgxPermissionsService } from "ngx-permissions";
export const PermissionLoadGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const permissionsService = inject(NgxPermissionsService);
const api = inject(ApiService);
const auth = localStorage.getItem(api.accountKey);
if (auth) {
try {
const authData = JSON.parse(auth) as ClientAccountDTO;
if (Array.isArray(authData.roleItems)) {
const permissionList = authData.roleItems;
const permissions = permissionList.reduce((a, c) => {
if (c.itemType === "管理端") {
return a.concat(String(c.id));
}
return a;
}, [] as string[]);
permissionsService.loadPermissions(permissions);
}
} catch (error) {}
}
return true;
};

BIN
projects/admin/src/favicon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 66 KiB

4
projects/admin/src/index.html

File diff suppressed because one or more lines are too long

14
projects/admin/src/styles.less

@ -151,3 +151,17 @@ li {
font-weight: normal;
}
}
.analysis-drawer {
.ant-drawer-header-title {
position: absolute;
right: 0;
top: 24px;
}
.ant-drawer-body {
padding-top: 0;
}
}

154
projects/cdk/src/ingredient/ingredient-analysis/ingredient-analysis.component.html

@ -1,9 +1,9 @@
<nz-tabset>
<nz-tab nzTitle="营养分析">
<div nz-row [nzGutter]="12">
<div nz-col nzSpan="8">
<div nz-col nzSpan="8" *ngIf="menu.days.length">
<nz-select class="w-full" [(ngModel)]="currentDay" (ngModelChange)="getAnalysis()">
<nz-option *ngFor="let item of menu.days" [nzLabel]="'' + (item + 1) + ''" [nzValue]="item+1">
<nz-option *ngFor="let item of menu.days" [nzLabel]="'' + (item) + ''" [nzValue]="item">
</nz-option>
</nz-select>
@ -26,10 +26,158 @@
</div>
<nz-divider nzDashed></nz-divider>
<div>
<nz-tabset>
<nz-tab nzTitle="营养素分析">
<nz-spin [nzSpinning]="analysisLoading">
<lib-nutrition-table *ngIf="analysis" [nutritions]="analysis.ingredient"></lib-nutrition-table>
</nz-spin>
</nz-tab>
<nz-tab nzTitle="能量来源分分布">
<nz-table nzTemplateMode nzSize="small" nzBordered *ngIf="energy?.energy">
<thead>
<tr>
<th>
能量占比
</th>
<th>
要求(%)
</th>
<th>
实际摄入(%)
</th>
<th>
评价
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let e of energy.energy">
<td>
{{e.name}}
</td>
<td>
{{e.standard}}
</td>
<td>
{{e.value}}
</td>
<td>
<ng-container [ngSwitch]="e.conclusion">
<ng-container *ngSwitchCase="'合适'">
<div class=" text-green-500">
<span nz-icon nzType="smile" nzTheme="outline"></span>
{{e.conclusion}}
</div>
</ng-container>
<ng-container *ngSwitchCase="'略低'">
<div class=" text-gray-500">
<span nz-icon nzType="frown" nzTheme="outline"></span>
{{e.conclusion}}
</div>
</ng-container>
<ng-container *ngSwitchCase="'略高'">
<div class=" text-red-500">
<span nz-icon nzType="frown" nzTheme="outline"></span>
{{e.conclusion}}
</div>
</ng-container>
<ng-container *ngSwitchDefault>{{e.conclusion}}</ng-container>
</ng-container>
</td>
</tr>
</tbody>
</nz-table>
</nz-tab>
</nz-tabset>
</div>
</nz-tab>
<nz-tab nzTitle="食材种类">
<ng-container *ngIf="rules">
<h4 class="my-4">
周规则
</h4>
<div>
<nz-table nzTemplateMode nzSize="small" nzBordered>
<thead>
<tr>
<th>
种类名称
</th>
<th>
至少需要
</th>
<th>
当前含有
</th>
<th>
还需
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let w of rules.weekRule">
<td>
{{w.name}}
</td>
<td>
{{w.standard}}
</td>
<td>
{{w.supplied}}
</td>
<td>
{{w.lack}}
</td>
</tr>
</tbody>
</nz-table>
</div>
<h4 class="my-4">
日规则
</h4>
<div>
<div *ngFor="let day of rules.dayRule" class="mb-3">
<nz-table nzTemplateMode nzSize="small" nzBordered>
<thead>
<tr>
<th [attr.colspan]="2">
种类名称
</th>
<th>
至少需要
</th>
<th>
当前含有
</th>
<th>
还需
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let d of day;let first = first">
<td *ngIf="first" [attr.rowspan]="day.length">
第{{d.day}}天
</td>
<td>
{{d.name}}
</td>
<td>
{{d.standard}}
</td>
<td>
{{d.supplied}}
</td>
<td>
{{d.lack}}
</td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</ng-container>
</nz-tab>
<!-- <nz-tab nzTitle="食材种类">Content of Tab Pane 2</nz-tab> -->
</nz-tabset>

21
projects/cdk/src/ingredient/ingredient-analysis/ingredient-analysis.component.ts

@ -23,16 +23,20 @@ export class IngredientAnalysisComponent implements OnInit {
analysis: any;
rules: any;
energy: any;
analysisLoading = false;
ngOnInit(): void {
this.currentDay = this.current.day;
this.currentPeople = this.menu.crows[0];
this.getAnalysis();
this.getRule();
}
getAnalysis() {
if (this.currentDay && this.currentPeople) {
this.analysisLoading = true;
this.api
.getAnalysis(this.menu.id, this.currentDay, this.currentPeople)
@ -44,8 +48,19 @@ export class IngredientAnalysisComponent implements OnInit {
.subscribe((res) => {
this.analysis = res.body;
});
} else {
console.error(this.currentDay, this.currentPeople, "this.currentDay && this.currentPeople 不存在");
this.getEnergy();
}
getEnergy() {
this.api.getAnalysisEnergy(this.menu.id, this.currentDay, this.currentPeople).subscribe((res) => {
this.energy = res.body;
});
}
getRule() {
this.api.getAnalysisRule(this.menu.id, this.currentDay, this.currentPeople).subscribe((res) => {
this.rules = res.body;
});
}
}

10
projects/cdk/src/ingredient/ingredient-dish/ingredient-dish.component.html

@ -15,16 +15,16 @@
<span class="expanded-icon" nz-icon nzType="caret-right" nzTheme="outline"></span>
</button>
<span>
第 {{day + 1}} 天
第 {{day}} 天
</span>
</div>
</ng-template>
<ng-template #dayExtraTpl>
<nz-space>
<button *nzSpaceItem nz-button nzType="link" (click)="reuse(day + 1, selectDayTpl)">
<button *nzSpaceItem nz-button nzType="link" (click)="reuse(day, selectDayTpl)">
本天菜品应用到其他天
</button>
<button *nzSpaceItem nz-button nzType="link" (click)="analysis(day + 1)">
<button *nzSpaceItem nz-button nzType="link" (click)="analysis(day )">
本日营养分析
</button>
</nz-space>
@ -39,12 +39,12 @@
<div class="p-4">
<ng-container *ngFor="let meal of menuBaisc.meals; let mealIndex = index ">
<app-ingredient-meals *ngIf="mealCurrentIndex[day] === mealIndex"
[day]="day + 1"
[day]="day "
[mealIndex]="mealIndex"
[meals]="menuBaisc.meals"
[peopleGroups]="menuBaisc.crows"
[mealDishs]="mealDishList"
(onSaveDish)="onSaveDish($event,day+1,mealIndex)">
(onSaveDish)="onSaveDish($event,day,mealIndex)">
<!-- (onSaveDish)="onSaveDish($event,day+1,mealIndex)" -->
</app-ingredient-meals>
</ng-container>

16
projects/cdk/src/ingredient/ingredient-dish/ingredient-dish.component.less

@ -23,19 +23,3 @@
}
}
}
::ng-deep {
.analysis-drawer {
.ant-drawer-header-title {
position: absolute;
right: 0;
top: 24px;
}
.ant-drawer-body {
padding-top: 0;
}
}
}

3
projects/cdk/src/ingredient/ingredient-dish/ingredient-dish.component.ts

@ -118,7 +118,7 @@ export class IngredientDishComponent implements OnChanges {
// [idx]: [],
// };
// }, {} as Record<number, MealDishInterface[]>);
return i;
return i + 1;
});
}
}
@ -158,6 +158,7 @@ export class IngredientDishComponent implements OnChanges {
}
analysis(day: number) {
console.log("this.days", this.days);
this.drawer.create({
nzWidth: 620,
nzWrapClassName: "analysis-drawer",

4
projects/cdk/src/ingredient/ingredient-form-basic/ingredient-form-basic.component.html

@ -90,14 +90,14 @@
<nz-divider></nz-divider>
<nz-form-item>
<!-- <nz-form-item>
<nz-form-label nzRequired nzSpan="6">
批量修改重量
</nz-form-label>
<nz-form-control [nzErrorTip]="formControlErrorTpl" nzSpan="12">
<nz-switch></nz-switch>
</nz-form-control>
</nz-form-item>
</nz-form-item> -->
<nz-form-item>
<nz-form-control>

2
projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html

@ -103,7 +103,7 @@
本餐生重总量
</td>
<td *ngFor="let p of peopleGroups">
{{totalObj[p]?.toFixed(2)}}
{{$any(totalObj[p])?.toFixed(2)}}
</td>
</tr>

4
projects/cdk/src/ingredient/ingredient-preview/ingredient-preview.component.html

@ -1,5 +1,6 @@
<nz-spin [nzSpinning]="!basic">
<div *ngIf="!basic" class="h-60"></div>
<ng-container *ngIf="basic">
<header class="header text-center text-base relative">
<button nz-button routerLink="/ingredient/item/list" class=" absolute left-4 top-[6px]">
@ -38,6 +39,9 @@
{{c}}
</nz-tag>
</nz-descriptions-item>
<nz-descriptions-item nzTitle="营养分析">
<a (click)="analysis(1)">点击查看</a>
</nz-descriptions-item>
</nz-descriptions>
</div>
</ng-container>

22
projects/cdk/src/ingredient/ingredient-preview/ingredient-preview.component.ts

@ -4,6 +4,8 @@ import { ApiService } from "@cdk/services";
import { NzMessageService } from "ng-zorro-antd/message";
import { DishInterface } from "../ingredient-dish/ingredient-dish.component";
import { forkJoin, map } from "rxjs";
import { IngredientAnalysisComponent } from "../ingredient-analysis/ingredient-analysis.component";
import { NzDrawerService } from "ng-zorro-antd/drawer";
@Component({
selector: "app-ingredient-preview",
@ -15,7 +17,8 @@ export class IngredientPreviewComponent {
private route: ActivatedRoute,
private router: Router,
private api: ApiService,
private msg: NzMessageService
private msg: NzMessageService,
private drawer: NzDrawerService
) {}
basic: any | null;
@ -128,4 +131,21 @@ export class IngredientPreviewComponent {
});
return total.toFixed(2);
}
analysis(day: number) {
this.drawer.create({
nzWidth: 620,
nzWrapClassName: "analysis-drawer",
nzContent: IngredientAnalysisComponent,
nzContentParams: {
menu: {
...this.basic,
days: this.days,
},
current: {
day,
},
},
});
}
}

36
projects/cdk/src/ingredient/nutrition-table/nutrition-table.component.html

@ -53,3 +53,39 @@
</tr>
</tbody>
</table>
<div class="flex justify-center text-center mt-4">
<nz-space>
<div *nzSpaceItem>
<div class="tag less">
</div>
<p>
不足
</p>
</div>
<div *nzSpaceItem>
<div class="tag success">
</div>
<p>
适量
</p>
</div>
<div *nzSpaceItem>
<div class="tag warning">
</div>
<p>
过量
</p>
</div>
<div *nzSpaceItem>
<div class="tag danger">
</div>
<p>
严重超标
</p>
</div>
</nz-space>
</div>

25
projects/cdk/src/ingredient/nutrition-table/nutrition-table.component.less

@ -24,21 +24,32 @@
}
.row {
&.less .inner {
}
.tag {
display: inline-block;
width: 48px;
height: 20px;
border-radius: 4px;
}
.less {
background-color: #a7a7a7;
color: #fff;
}
&.success .inner {
.success {
background-color: #1bbc9b;
color: #fff;
}
&.warning .inner {
.warning {
background-color: #f3c200;
color: #fff;
}
&.danger .inner {
.danger {
background-color: #f5222d;
}
}
color: #fff;
}

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

@ -458,6 +458,15 @@ export class ApiService {
return this.http.get<ResponseType>(`/api/menu/dish/analysis?${params}`);
}
getAnalysisEnergy(id: number, day?: number, crow?: string) {
const params = Utils.objectStringify({ id, day, crow });
return this.http.get<ResponseType>(`/api/menu/dish/analysis/energy?${params}`);
}
getAnalysisRule(id: number, day?: number, crow?: string) {
const params = Utils.objectStringify({ id, day, crow });
return this.http.get<ResponseType>(`/api/menu/dish/analysis/types?${params}`);
}
getMenuDataVis() {
return this.http.get<ResponseType>(`/api/menu/dish`);
}

4
projects/cdk/src/shared/components/forbidden/forbidden.component.html

@ -0,0 +1,4 @@
<div class="pt-20">
<nz-result nzStatus="403"></nz-result>
<h2 class=" text-center">你没有此页面的访问权限。</h2>
</div>

0
projects/cdk/src/shared/components/forbidden/forbidden.component.less

14
projects/cdk/src/shared/components/forbidden/forbidden.component.ts

@ -0,0 +1,14 @@
import { ActivatedRoute, Router } from "@angular/router";
import { Component, OnInit } from "@angular/core";
import { NgxPermissionsService } from "ngx-permissions";
@Component({
selector: "app-forbidden",
templateUrl: "./forbidden.component.html",
styleUrls: ["./forbidden.component.less"],
})
export class ForbiddenComponent implements OnInit {
constructor(private perm: NgxPermissionsService, private router: Router, private route: ActivatedRoute) {}
async ngOnInit() {}
}

2
projects/cdk/src/shared/components/index.ts

@ -3,3 +3,5 @@ export * from "./month-select/month-select.component";
export * from "./org-select/org-select.component";
export * from "./dish-select/dish-select.component";
export * from "./print/print.component";
export * from "./forbidden/forbidden.component";
export * from "./notfound/notfound.component";

6
projects/cdk/src/shared/components/notfound/notfound.component.html

@ -0,0 +1,6 @@
<div class="mt-20">
<nz-result nzStatus="404"></nz-result>
<h2 class="text-center">
此页面未找到。
</h2>
</div>

0
projects/cdk/src/shared/components/notfound/notfound.component.less

10
projects/cdk/src/shared/components/notfound/notfound.component.ts

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-notfound',
templateUrl: './notfound.component.html',
styleUrls: ['./notfound.component.less']
})
export class NotfoundComponent {
}

7
projects/cdk/src/shared/shared.module.ts

@ -26,6 +26,8 @@ import {
OrgSelectComponent,
DishSelectComponent,
PrintComponent,
ForbiddenComponent,
NotfoundComponent,
} from "./components";
const ngModules = [CommonModule, HttpClientModule, FormsModule, RouterModule, ReactiveFormsModule];
@ -39,6 +41,7 @@ const cdks = [
TableListModule,
StorageModule,
// QuickDateRangeComponent,
NgxPermissionsModule,
] as any;
@NgModule({
@ -50,6 +53,8 @@ const cdks = [
DishSelectComponent,
OrgSelectComponent,
PrintComponent,
ForbiddenComponent,
NotfoundComponent,
],
imports: [...ngZorroModules, ...ngModules, ...cdks, AppPageComponent],
exports: [
@ -64,6 +69,8 @@ const cdks = [
OrgSelectComponent,
DishSelectComponent,
PrintComponent,
ForbiddenComponent,
NotfoundComponent,
],
})
export class SharedModule {}

15
projects/cdk/src/types/index.ts

@ -48,18 +48,3 @@ export interface PageResult<T = DecSafeAny> {
totalElements: number;
totalPages: number;
}
export interface AuthInterface {
role: string;
userId: string;
userName: string;
permissionList: AuthPermissionInterface[];
}
export interface AuthPermissionInterface {
name: string;
roleId: string;
scope: 1 | 0;
type: number;
value: "true" | "false";
}

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

@ -68,7 +68,7 @@ export class Utils {
if (obj.hasOwnProperty(key)) {
let value = obj[key];
if (![void 0, null, ""].includes(value)) {
if (typeof value === "object") {
if (typeof value === "object" && !Array.isArray(value)) {
params.append(key, JSON.stringify(value));
} else {
params.append(key, value);

89
projects/client/src/app/app-routing.module.ts

@ -16,13 +16,18 @@ import {
} from "./pages";
import { AppLayoutComponent } from "./components";
import { authGuard } from "./services/auth.guard";
import { PermissionLoadGuard } from "./services/permisson.guard";
import { ForbiddenComponent, NotfoundComponent } from "@cdk/shared/components";
import { ngxPermissionsGuard } from "ngx-permissions";
const routes: Routes = [
{ path: "login", component: LoginComponent },
{ path: "forbidden", component: ForbiddenComponent },
{
path: "",
component: AppLayoutComponent,
canActivate: [authGuard],
canActivate: [authGuard, PermissionLoadGuard],
children: [
{
path: "",
@ -32,26 +37,68 @@ const routes: Routes = [
{
path: "dashboard",
component: DashboardComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["18"],
redirectTo: "/forbidden",
},
},
},
{
path: "meal-setting",
component: MealSettingComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["21", "22"],
redirectTo: "/forbidden",
},
},
},
{
path: "data-vis",
component: DataVisComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["19", "20"],
redirectTo: "/forbidden",
},
},
},
{
path: "food",
component: FoodComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["23", "24"],
redirectTo: "/forbidden",
},
},
},
{
path: "dish",
component: DishComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["25", "26"],
redirectTo: "/forbidden",
},
},
},
{
path: "ingredient",
title: "食谱管理",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["27", "28", "29", "30", "31"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "",
@ -61,6 +108,13 @@ const routes: Routes = [
{
path: "item",
title: "食谱库",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["27", "28"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "",
@ -86,25 +140,58 @@ const routes: Routes = [
{
path: "release",
title: "食谱发布计划",
canActivate: [ngxPermissionsGuard],
component: IngredientReleaseComponent,
data: {
permissions: {
only: ["30", "31"],
redirectTo: "/forbidden",
},
},
},
],
},
{
path: "system",
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["33", "34", "35", "36", "37"],
redirectTo: "/forbidden",
},
},
children: [
{
path: "org",
component: OrgInfoComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["33", "34"],
redirectTo: "/forbidden",
},
},
},
{
path: "user",
component: ClientUserManageComponent,
canActivate: [ngxPermissionsGuard],
data: {
permissions: {
only: ["35", "36", "37"],
redirectTo: "/forbidden",
},
},
},
],
},
],
},
{
path: "**",
component: NotfoundComponent,
},
];
@NgModule({

3
projects/client/src/app/app.module.ts

@ -36,6 +36,7 @@ import {
} from "./pages";
import { HTTPInterceptor } from "./services/http.interceptor";
import { IngredientModule } from "@cdk/ingredient/ingredient.module";
import { NgxPermissionsModule } from "ngx-permissions";
registerLocaleData(zh);
@ -71,6 +72,8 @@ registerLocaleData(zh);
SharedModule,
IngredientModule,
TableListModule,
NgxPermissionsModule.forRoot(),
],
providers: [
{ provide: PROJECT_NAME, useValue: "client" },

33
projects/client/src/app/components/app-layout/app-layout.component.html

@ -35,41 +35,52 @@
<nz-sider nzWidth="200px" class="sider-menu" nzTheme="light">
<ul nz-menu nzMode="inline">
<li nz-menu-item class="k-icon" [routerLink]="['/','dashboard']" nzMatchRouter>
<li nz-menu-item class="k-icon" [routerLink]="['/','dashboard']" nzMatchRouter
*ngxPermissionsOnly="['18']">
<span nz-icon nzType="question-circle" nzTheme="outline"></span>
<span>使用流程</span>
</li>
<li nz-menu-item class="k-icon" (click)="openDataVis()" nzMatchRouter>
<li nz-menu-item class="k-icon" (click)="openDataVis()" nzMatchRouter
*ngxPermissionsOnly="['19','20']">
<span nz-icon nzType="fund" nzTheme="outline"></span>
<span>大屏显示</span>
</li>
<li nz-menu-item [routerLink]="['/','meal-setting']" nzMatchRouter>
<li nz-menu-item [routerLink]="['/','meal-setting']" nzMatchRouter
*ngxPermissionsOnly="['21','22']">
<span nz-icon nzType="setting" nzTheme="outline"></span>
<span>配餐设置</span>
</li>
<li nz-menu-item class="k-icon" [routerLink]="['/','food']" nzMatchRouter>
<li nz-menu-item class="k-icon" [routerLink]="['/','food']" nzMatchRouter
*ngxPermissionsOnly="['23','24']">
<span nz-icon nzType="k-icon:carrot" nzTheme="outline"></span>
<span>食材管理</span>
</li>
<li nz-menu-item class="k-icon" [routerLink]="['/','dish']" nzMatchRouter>
<li nz-menu-item class="k-icon" [routerLink]="['/','dish']" nzMatchRouter
*ngxPermissionsOnly="['25','26']">
<span nz-icon nzType="k-icon:food" nzTheme="outline"></span>
<span>菜品管理</span>
</li>
<li nz-submenu nzTitle="食谱管理" nzIcon="book" [nzOpen]="currentUrl.includes('/ingredient/')">
<li nz-submenu nzTitle="食谱管理" nzIcon="book" [nzOpen]="currentUrl.includes('/ingredient/')"
*ngxPermissionsOnly="['27','28','29','30','31']">
<ul>
<li nz-menu-item nzMatchRouter [routerLink]="['/','ingredient','item']">食谱库</li>
<li nz-menu-item nzMatchRouter [routerLink]="['/','ingredient','release']">食谱发布计划</li>
<li nz-menu-item nzMatchRouter *ngxPermissionsOnly="['27','28','29']"
[routerLink]="['/','ingredient','item']">食谱库</li>
<li nz-menu-item nzMatchRouter *ngxPermissionsOnly="['30','31']"
[routerLink]="['/','ingredient','release']">食谱发布计划</li>
</ul>
</li>
<li nz-submenu nzTitle="基础信息设置" nzIcon="user" [nzOpen]="currentUrl.includes('/system/')">
<li nz-submenu nzTitle="基础信息设置" nzIcon="user" [nzOpen]="currentUrl.includes('/system/')"
*ngxPermissionsOnly="['33','34','35','36','37']">
<ul>
<li nz-menu-item nzMatchRouter [routerLink]="['/','system','org']">单位信息设置</li>
<li nz-menu-item nzMatchRouter [routerLink]="['/','system','org']"
*ngxPermissionsOnly="['33','34',]">单位信息设置</li>
</ul>
<ul>
<li nz-menu-item nzMatchRouter [routerLink]="['/','system','user']">用户管理</li>
<li nz-menu-item nzMatchRouter [routerLink]="['/','system','user']"
*ngxPermissionsOnly="['35','36','37']">用户管理</li>
</ul>
</li>
</ul>

29
projects/client/src/app/pages/data-vis/data-vis.component.html

@ -12,8 +12,8 @@
</div> -->
<div class="flex-1 flex flex-col">
<div class="flex-1 overflow-hidden">
<div class="box mb-2 ">
<div class="flex-1 overflow-hidden pb-2">
<div class="box">
<div class="tit">今日带量食谱</div>
<div class="boxnav overflow-hidden" #tableEl>
<table class="w-full">
@ -59,18 +59,35 @@
</div>
</div>
</div>
<div class="flex-1 overflow-hidden">
<div class="box mt-2">
<div class="flex-1 overflow-hidden pt-2">
<div class="box">
<div class="tit">今日食材种类</div>
<div class="boxnav">
<div class="p-4">
<div nz-row [nzGutter]="[12,12]">
<div nz-col nzSpan="6" *ngFor="let type of analysis.types | keyvalue">
{{type.key}} : <b>{{type.value}}</b>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="w-1/3 pl-4">
<div class="box">
<div class="tit">今日营养分析</div>
<div class="tit flex justify-between items-center">
<span>
今日营养分析
</span>
<span>
<select [(ngModel)]="people" class="select" (ngModelChange)="getAnalysis()">
<option *ngFor="let p of peoples" [value]="p">
{{p}}
</option>
</select>
</span>
</div>
<div class="boxnav overflow-hidden" #nutritionEl>
<div class="p-4">
<nz-spin [nzSpinning]="analysisLoading">

12
projects/client/src/app/pages/data-vis/data-vis.component.less

@ -226,6 +226,18 @@ i {
top: -1px;
}
.select {
background-color: transparent;
color: #fff;
border: none;
outline: none;
option {
background-color: #fff;
color: #012059;
}
}
.boxnav {
flex: 1;

19
projects/client/src/app/pages/data-vis/data-vis.component.ts

@ -35,6 +35,10 @@ export class DataVisComponent implements AfterViewInit {
scroll: Record<string, number> = {};
people = "";
menuId!: number;
ngOnInit(): void {
this.orgName = this.api.account?.vender?.name ?? "";
interval(1000)
@ -47,12 +51,13 @@ 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];
if (!this.peoples) {
console.error("dishs?.[0]?.ingredient?.[0]?.value 数据错误:", dishs);
return;
}
this.getAnalysis(dishs?.[0]?.menu);
this.menuId = dishs?.[0]?.menu;
this.getAnalysis();
dishs.forEach((i: any) => {
// 把每个食材按照不同的人群将重量加起来
@ -109,9 +114,9 @@ export class DataVisComponent implements AfterViewInit {
});
}
getAnalysis(menu: number) {
getAnalysis() {
this.api
.getAnalysis(menu)
.getAnalysis(this.menuId, void 0, this.people)
.pipe(
finalize(() => {
this.analysisLoading = false;
@ -119,9 +124,9 @@ export class DataVisComponent implements AfterViewInit {
)
.subscribe((res) => {
this.analysis = res.body;
setTimeout(() => {
this.autoScroll(this.nutritionEl.nativeElement, "2");
}, 1000);
// setTimeout(() => {
// this.autoScroll(this.nutritionEl.nativeElement, "2");
// }, 1000);
});
}
}

4
projects/client/src/app/pages/dish/dish.component.html

@ -1,7 +1,7 @@
<app-page [scroll]="false">
<div nz-row class="h-full overflow-hidden bg-white rounded-lg">
<div nz-col nzFlex="220px" class="food-type">
<!-- <div nz-col nzFlex="220px" class="food-type">
<nz-card class="h-full" [nzBordered]="false" nzTitle="菜品分类" [nzBodyStyle]="{padding:'1px 0 0 0'}">
<ul nz-menu nzMode="inline">
<li nz-menu-item>
@ -17,7 +17,7 @@
</ul>
</nz-card>
</div>
</div> -->
<div nz-col nzFlex="1" class="flex-1 overflow-hidden bg-white h-full">
<nz-card [nzBordered]="false" nzTitle="菜品列表" class="scroll-card-body">

11
projects/client/src/app/pages/dish/dish.component.ts

@ -151,7 +151,16 @@ export class DishComponent {
this.msg.loading("数据请求中,请不要刷新页面", {
nzDuration: 0,
});
this.api.getDishLabel(v.id).subscribe((res) => {
this.api
.getDishLabel(v.id)
.pipe(
finalize(() => {
setTimeout(() => {
this.msg.remove();
}, 1000);
})
)
.subscribe((res) => {
this.printData = res.body[0];
this.printRef.print();
this.msg.remove();

4
projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html

@ -19,7 +19,7 @@
</div>
<nz-space>
<button *nzSpaceItem nz-button>
<button *nzSpaceItem nz-button (click)="analysis()">
食谱营养分析
</button>
<button *nzSpaceItem nz-button (click)="createNewMenu()">
@ -28,7 +28,7 @@
<button *nzSpaceItem nz-button>
导入食谱
</button>
<button *nzSpaceItem nz-button>
<button *nzSpaceItem nz-button (click)="previewMenu()">
食谱预览
</button>
<button *nzSpaceItem nz-button nzType="primary" (click)="confirmSave()">

109
projects/client/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts

@ -1,12 +1,14 @@
import { Component, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { ConfirmIngredientComponent } from "@cdk/ingredient/confirm-ingredient/confirm-ingredient.component";
import { IngredientDishComponent } from "@cdk/ingredient/ingredient-dish/ingredient-dish.component";
import { MealDishInterface } from "@cdk/ingredient/ingredient-meals/ingredient-meals.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";
@Component({
selector: "app-ingredient-form",
@ -19,7 +21,8 @@ export class IngredientFormComponent implements OnInit {
private msg: NzMessageService,
private router: Router,
private route: ActivatedRoute,
private api: ApiService
private api: ApiService,
private drawer: NzDrawerService
) {
this.id = this.route.snapshot.paramMap.get("id");
}
@ -58,12 +61,35 @@ export class IngredientFormComponent implements OnInit {
});
});
});
this.menuDishFormServer = res.body;
this.initMenuDish(res.body);
}
});
}
}
initMenuDish(menuDishFormServer: any[]) {
const foodIds = new Set<number>();
menuDishFormServer.forEach((i: any) => {
i.ingredient.map((food: any) => {
foodIds.add(food.key);
});
});
forkJoin([this.api.getFoodList({ keys: Array.from(foodIds) })]).subscribe(([res]) => {
this.menuDishFormServer = menuDishFormServer.map((i: any) => {
return {
...i,
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;
}),
};
});
});
}
onStepChange(basicInfo: any) {
this.step = 1;
this.menuItem = {
@ -90,6 +116,34 @@ export class IngredientFormComponent implements OnInit {
});
}
analysis() {
this.drawer.create({
nzWidth: 620,
nzWrapClassName: "analysis-drawer",
nzContent: IngredientAnalysisComponent,
nzContentParams: {
menu: {
...this.menuItem,
days: [],
},
current: {},
},
});
}
previewMenu() {
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}`);
}
confirmSave() {
this.modal.create({
nzTitle: "确认食谱信息",
@ -99,25 +153,10 @@ export class IngredientFormComponent implements OnInit {
nzOnOk: () => {
const { mealDishList } = this.menuDish;
mealDishList.forEach((dish) => {
dish["dishId"] = dish.dish;
dish.items = dish.items.map((i) => {
return {
...i,
value: (i["groupValues"] as any[]).reduce((a, c) => {
return {
...a,
[c.peopleName]: c.value,
};
}, {} as Record<string, number>),
};
});
});
console.log("mealDishList", mealDishList);
this.api
.saveMenuDist({
menuIds: this.menuItem.menuIds ?? [this.menuItem.id],
dishes: mealDishList,
dishes: this.formatData(mealDishList),
})
.subscribe((res) => {
this.msg.success(res.desc);
@ -127,36 +166,22 @@ export class IngredientFormComponent implements OnInit {
});
}
formatData(menuObject: any) {
let dishes: any[] = [];
Object.entries(menuObject).forEach(([day, v]) => {
Object.entries(v as Record<string, MealDishInterface[]>).forEach(([mealIndex, dishList]) => {
dishList.forEach((dish) => {
dishes.push({
...dish,
day: Number(day),
meal: this.menuItem.meals[mealIndex],
items: dish.foods.map((food) => {
formatData(d: DishInterface[]) {
const data: DishInterface[] = JSON.parse(JSON.stringify(d));
data.forEach((dish) => {
dish["dishId"] = dish.dish;
dish.items = dish.items.map((i) => {
return {
...food,
value: food.groupValues.reduce((a, c) => {
...i,
value: (i["groupValues"] as any[]).reduce((a, c) => {
return {
...a,
[c.peopleName]: c.value,
};
}, {} as Record<string, number>),
};
}),
});
});
});
});
const toServer = {
menuIds: this.menuItem.menuIds ?? [this.menuItem.id],
dishes,
};
return toServer;
return data;
}
}

9
projects/client/src/app/pages/system/user-manage/user-manage.component.html

@ -1,13 +1,13 @@
<app-page [scroll]="false">
<div nz-row class="h-full overflow-hidden bg-white rounded-lg">
<div nz-col nzFlex="220px" class="user-type">
<div nz-col nzFlex="220px" class="user-type h-full">
<nz-card
class="h-full "
class="h-full flex"
[nzBordered]="false"
nzTitle="用户角色"
[nzBodyStyle]="{padding:'1px 0 0 0'}">
[nzBodyStyle]="{padding:'1px 0 0 0',flex:'1', 'overflow':'hidden'}">
<div class="h-full overflow-y-auto overflow-x-hidden">
<ul nz-menu nzMode="inline">
<li
*ngFor="let item of roleList"
@ -38,6 +38,7 @@
</span>
</button>
</div>
</div>
</nz-card>
</div>
<div nz-col nzFlex="1" class="flex-1 h-full overflow-hidden bg-white ">

2
projects/client/src/app/pages/system/user-manage/user-manage.component.ts

@ -30,7 +30,7 @@ export class ClientUserManageComponent {
public roleForm = new FormGroup({
roleId: new FormControl(""),
roleName: new FormControl("", [FormValidators.required("请输入角色名称")]),
items: new FormControl([]),
items: new FormControl(),
});
public allPerms: PermItemDTO[] = [];

36
projects/client/src/app/services/permisson.guard.ts

@ -0,0 +1,36 @@
import { inject } from "@angular/core";
import {
ActivatedRoute,
ActivatedRouteSnapshot,
CanActivateChildFn,
CanActivateFn,
Route,
Router,
RouterStateSnapshot,
} from "@angular/router";
import { ClientAccountDTO } from "@cdk/dtos";
import { ApiService } from "@cdk/services";
import { NgxPermissionsService } from "ngx-permissions";
export const PermissionLoadGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const permissionsService = inject(NgxPermissionsService);
const api = inject(ApiService);
const auth = localStorage.getItem(api.accountKey);
if (auth) {
try {
const authData = JSON.parse(auth) as ClientAccountDTO;
if (Array.isArray(authData.roleItems)) {
const permissionList = authData.roleItems;
const permissions = permissionList.reduce((a, c) => {
if (c.itemType === "业务端") {
return a.concat(String(c.id));
}
return a;
}, [] as string[]);
permissionsService.loadPermissions(permissions);
}
} catch (error) {}
}
return true;
};

BIN
projects/client/src/favicon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 66 KiB

2
projects/client/src/index.html

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html>
<head>
<meta charset="utf-8">

14
projects/client/src/styles.less

@ -114,3 +114,17 @@ li {
font-weight: normal;
}
}
.analysis-drawer {
.ant-drawer-header-title {
position: absolute;
right: 0;
top: 24px;
}
.ant-drawer-body {
padding-top: 0;
}
}
Loading…
Cancel
Save