88 changed files with 2912 additions and 309 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,15 @@ |
|||||
|
# 修改记录 |
||||
|
|
||||
|
> 9.10 |
||||
|
``` |
||||
|
基础协议 |
||||
|
用户协议 |
||||
|
角色协议 |
||||
|
单位协议 |
||||
|
``` |
||||
|
|
||||
|
> 9.11 |
||||
|
``` |
||||
|
食材 |
||||
|
菜品 |
||||
|
食谱 |
||||
@ -0,0 +1,42 @@ |
|||||
|
# 协议约定 |
||||
|
>协议格式: restfull + json + utf-8 |
||||
|
|
||||
|
>协议格式中,凡是用 * 标识字段均为必须字段,否则为可选字段。 |
||||
|
|
||||
|
>密码:<font color=red>协议中涉及password字段全部使用16位的MD5加密传输(MD5加密后取后16位,大写)</font> |
||||
|
|
||||
|
### 协议列表 |
||||
|
``` |
||||
|
* [协议约定](protocol.md) |
||||
|
* [修改记录](change.md) |
||||
|
* [基础协议](basic.md) |
||||
|
* [用户权限](user.md) |
||||
|
* [单位协议](vender.md) |
||||
|
``` |
||||
|
|
||||
|
### 响应示例 |
||||
|
``` |
||||
|
{ |
||||
|
"body": {......}, //返回的业务数据 |
||||
|
"code":*1, //结果码 |
||||
|
"desc":*"成功", //结果描述 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 返回码表 |
||||
|
``` |
||||
|
基础返回码: |
||||
|
success (200, "成功"), |
||||
|
|
||||
|
invalid_user_password (300, "用户名或者密码错误!"), |
||||
|
|
||||
|
expired_vender (301, "账户过期,请联系管理员续费!"), |
||||
|
|
||||
|
illegal_argument (400, "参数错误!"), |
||||
|
need_login (401, "未登录!"), |
||||
|
not_support_operate (404, "不支持的请求!"), |
||||
|
not_privileged (405, "无权限执行该操作!"), |
||||
|
system_error (500, "系统异常!"), |
||||
|
operate_failure (503, "操作失败!"); |
||||
|
|
||||
|
``` |
||||
@ -0,0 +1,303 @@ |
|||||
|
# 用户部分 |
||||
|
|
||||
|
# 1. 检查UID的是否重复 |
||||
|
|
||||
|
> GET /api/user/check?uid=zzz |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"body": false, // true标识uid未被占用 |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
# 2. 添加用户 |
||||
|
|
||||
|
> PUT /api/user |
||||
|
|
||||
|
### 输入: |
||||
|
``` |
||||
|
Content-Type:application/x-www-form-urlencoded |
||||
|
uid=ccc // 必填, 用户ID, 不能重复 |
||||
|
name=曹 // 必填, 用户姓名 |
||||
|
password=BE56E057F20F883E // 必填, MD5加密后大写取后16位,示例原密码为123456 |
||||
|
roleId=2 //角色编号,只能是自己单位的角色,必填,从角色列表选择一个 |
||||
|
``` |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
# 3. 删除用户 |
||||
|
|
||||
|
> DELETE /api/user |
||||
|
|
||||
|
### 输入: |
||||
|
``` |
||||
|
Content-Type:application/x-www-form-urlencoded |
||||
|
uid=ccc // 必填, |
||||
|
``` |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
# 4. 修改用户 |
||||
|
|
||||
|
> POST /api/user |
||||
|
|
||||
|
### 输入: |
||||
|
``` |
||||
|
Content-Type:application/x-www-form-urlencoded |
||||
|
uid=ccc // 用户ID, 必填 |
||||
|
name=曹 // 修改姓名 |
||||
|
password=BE56E057F20F883E // 修改密码 |
||||
|
roleId=2 //修改角色, 0-标识回收角色,其他-标识分配角色 |
||||
|
``` |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
# 5. 获取用户列表 |
||||
|
|
||||
|
> GET /api/user |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"body": [ |
||||
|
{ |
||||
|
"name": "业务端测试账号", |
||||
|
"phone": "13919103409", |
||||
|
"roleId": 2, |
||||
|
"roleName": "超级管理员", |
||||
|
"uid": "xxx" |
||||
|
} |
||||
|
], |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
# 6. 获取当前用户所在端的权限项列表 |
||||
|
|
||||
|
> GET /api/role/item |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"body": [ |
||||
|
{ |
||||
|
"category": "基础权限", |
||||
|
"id": 18, |
||||
|
"itemName": "使用流程", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "基础权限", |
||||
|
"id": 19, |
||||
|
"itemName": "数据大屏-大屏显示", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "基础权限", |
||||
|
"id": 20, |
||||
|
"itemName": "数据大屏-大屏显示(LED)", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "配餐设置", |
||||
|
"id": 21, |
||||
|
"itemName": "配餐设置-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "配餐设置", |
||||
|
"id": 22, |
||||
|
"itemName": "配餐设置-编辑", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "食材管理", |
||||
|
"id": 23, |
||||
|
"itemName": "食材列表-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "食材管理", |
||||
|
"id": 24, |
||||
|
"itemName": "食材-常用/忌用", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "菜品管理", |
||||
|
"id": 25, |
||||
|
"itemName": "菜品列表-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "菜品管理", |
||||
|
"id": 26, |
||||
|
"itemName": "菜品-新增/编辑/删除", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "食谱管理", |
||||
|
"id": 27, |
||||
|
"itemName": "食谱列表-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "食谱管理", |
||||
|
"id": 28, |
||||
|
"itemName": "食谱-新增/编辑/删除", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "食谱管理", |
||||
|
"id": 29, |
||||
|
"itemName": "食谱审核记录-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "基础信息管理", |
||||
|
"id": 30, |
||||
|
"itemName": "单位基础信息-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "基础信息管理", |
||||
|
"id": 31, |
||||
|
"itemName": "单位基础信息-修改", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "系统设置", |
||||
|
"id": 32, |
||||
|
"itemName": "用户列表-查看", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "系统设置", |
||||
|
"id": 33, |
||||
|
"itemName": "用户-新增/编辑/删除", |
||||
|
"itemType": "业务端" |
||||
|
}, |
||||
|
{ |
||||
|
"category": "系统设置", |
||||
|
"id": 34, |
||||
|
"itemName": "角色权限-查看/新增/编辑/删除", |
||||
|
"itemType": "业务端" |
||||
|
} |
||||
|
], |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
# 7. 添加角色 |
||||
|
|
||||
|
> PUT /api/role |
||||
|
|
||||
|
### 输入: |
||||
|
``` |
||||
|
Content-Type:application/x-www-form-urlencoded |
||||
|
roleName=ccc // 必填, 角色名称 |
||||
|
items=1,2,3 // 必填, 赋予的权限项 |
||||
|
``` |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
# 8. 删除角色 |
||||
|
|
||||
|
> DELETE /api/role |
||||
|
|
||||
|
### 输入: |
||||
|
``` |
||||
|
Content-Type:application/x-www-form-urlencoded |
||||
|
roleId=1 // 必填 |
||||
|
``` |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
# 9. 修改角色 |
||||
|
|
||||
|
> POST /api/role |
||||
|
|
||||
|
### 输入: |
||||
|
``` |
||||
|
Content-Type:application/x-www-form-urlencoded |
||||
|
roleId=1 // 必填 |
||||
|
roleName=ccc // 角色名称 |
||||
|
items=1,2,3 // 赋予的权限项 |
||||
|
``` |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
# 10. 获取角色列表 |
||||
|
|
||||
|
> GET /api/role |
||||
|
|
||||
|
### 输出: |
||||
|
``` |
||||
|
{ |
||||
|
"body": [ |
||||
|
{ |
||||
|
"id": 2, |
||||
|
"roleItems": "[18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]", |
||||
|
"roleName": "超级管理员", |
||||
|
"roleType": "系统", |
||||
|
"vender": 1 |
||||
|
} |
||||
|
], |
||||
|
"code": 200, |
||||
|
"desc": "成功", |
||||
|
"success": true |
||||
|
} |
||||
|
``` |
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,7 @@ |
|||||
|
.day-item { |
||||
|
::ng-deep { |
||||
|
.ant-card-head-title { |
||||
|
overflow: visible; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,127 @@ |
|||||
|
<form nz-form> |
||||
|
<div nz-row [nzGutter]="12"> |
||||
|
<div nz-col nzSpan="12"> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzRequired="">菜品名称</nz-form-label> |
||||
|
<nz-form-control> |
||||
|
<nz-select nzShowSearch nzPlaceHolder="请输入菜品名称搜索"></nz-select> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</div> |
||||
|
<div nz-col nzSpan="12"> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzRequired="">菜品标签</nz-form-label> |
||||
|
<nz-form-control> |
||||
|
<nz-select nzPlaceHolder="请选择菜品标签"></nz-select> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzRequired="">食材搜索方式</nz-form-label> |
||||
|
<nz-form-control> |
||||
|
<nz-radio-group nzButtonStyle="solid"> |
||||
|
<label nz-radio nzValue="1" nz-radio-button>食材种类</label> |
||||
|
<label nz-radio nzValue="2" nz-radio-button>营养素</label> |
||||
|
</nz-radio-group> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<div> |
||||
|
<nz-table nzTemplateMode [nzBordered]="true" nzSize="small"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th> |
||||
|
食材 |
||||
|
</th> |
||||
|
<th> |
||||
|
是否主料 |
||||
|
</th> |
||||
|
<th> |
||||
|
轻体力1 |
||||
|
</th> |
||||
|
<th> |
||||
|
轻体力2 |
||||
|
</th> |
||||
|
<th> |
||||
|
操作 |
||||
|
</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td> |
||||
|
味精 |
||||
|
</td> |
||||
|
<td> |
||||
|
<nz-switch nzCheckedChildren="是" nzUnCheckedChildren="否"></nz-switch> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input nz-input placeholder="重量" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input nz-input placeholder="重量" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="link"> |
||||
|
修改 |
||||
|
</button> |
||||
|
<button *nzSpaceItem nz-button nzType="link" nzDanger> |
||||
|
删除 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td> |
||||
|
味精 |
||||
|
</td> |
||||
|
<td> |
||||
|
<nz-switch nzCheckedChildren="是" nzUnCheckedChildren="否"></nz-switch> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input nz-input placeholder="重量" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input nz-input placeholder="重量" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="link"> |
||||
|
修改 |
||||
|
</button> |
||||
|
<button *nzSpaceItem nz-button nzType="link" nzDanger> |
||||
|
删除 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td> |
||||
|
味精 |
||||
|
</td> |
||||
|
<td> |
||||
|
<nz-switch nzCheckedChildren="是" nzUnCheckedChildren="否"></nz-switch> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input nz-input placeholder="重量" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input nz-input placeholder="重量" /> |
||||
|
</td> |
||||
|
<td> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="link"> |
||||
|
修改 |
||||
|
</button> |
||||
|
<button *nzSpaceItem nz-button nzType="link" nzDanger> |
||||
|
删除 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</nz-table> |
||||
|
</div> |
||||
|
</form> |
||||
@ -0,0 +1,8 @@ |
|||||
|
import { Component } from "@angular/core"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "lib-add-dish-to-ingredient", |
||||
|
templateUrl: "./add-dish-to-ingredient.component.html", |
||||
|
styleUrls: ["./add-dish-to-ingredient.component.less"], |
||||
|
}) |
||||
|
export class AddDishToIngredientComponent {} |
||||
@ -0,0 +1,53 @@ |
|||||
|
<form nz-form [formGroup]="formGroup"> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="4"> |
||||
|
天数 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="12"> |
||||
|
<nz-tag nzColor="cyan">7天</nz-tag> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="4"> |
||||
|
餐次 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="12"> |
||||
|
<nz-space> |
||||
|
<nz-tag *nzSpaceItem nzColor="blue">早餐</nz-tag> |
||||
|
<nz-tag *nzSpaceItem nzColor="blue">午餐</nz-tag> |
||||
|
<nz-tag *nzSpaceItem nzColor="blue">晚餐</nz-tag> |
||||
|
</nz-space> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="4" nzRequired> |
||||
|
食谱名称 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="16"> |
||||
|
<input nz-input placeholder="请输入食谱名称" /> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzSpan="4" nzRequired> |
||||
|
适用月份 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="16"> |
||||
|
<div> |
||||
|
<label |
||||
|
nz-checkbox |
||||
|
[(ngModel)]="allMonthChecked" |
||||
|
[ngModelOptions]="{standalone: true}" |
||||
|
(ngModelChange)="updateAllMonthChecked()" |
||||
|
[nzIndeterminate]="indeterminate"> |
||||
|
全年 |
||||
|
</label> |
||||
|
</div> |
||||
|
<nz-divider nzDashed class="my-2"></nz-divider> |
||||
|
<nz-checkbox-group [ngModel]="allMonth" |
||||
|
class="flex flex-wrap month-wrap" |
||||
|
formControlName="month" |
||||
|
(ngModelChange)="monthChecked()"> |
||||
|
</nz-checkbox-group> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</form> |
||||
@ -0,0 +1,8 @@ |
|||||
|
.month-wrap { |
||||
|
::ng-deep { |
||||
|
.ant-checkbox-wrapper { |
||||
|
margin: 6px 0; |
||||
|
flex-basis: calc(100% / 4); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
import { Component } from "@angular/core"; |
||||
|
import { FormBuilder, FormGroup } from "@angular/forms"; |
||||
|
import { FormValidators } from "@cdk/public-api"; |
||||
|
import { NzMessageService } from "ng-zorro-antd/message"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "lib-confirm-ingredient", |
||||
|
templateUrl: "./confirm-ingredient.component.html", |
||||
|
styleUrls: ["./confirm-ingredient.component.less"], |
||||
|
}) |
||||
|
export class ConfirmIngredientComponent { |
||||
|
constructor(private fb: FormBuilder, private msg: NzMessageService) {} |
||||
|
|
||||
|
formGroup!: FormGroup; |
||||
|
|
||||
|
allMonth = [ |
||||
|
{ value: "1", label: "一月", checked: false }, |
||||
|
{ value: "2", label: "二月", checked: false }, |
||||
|
{ value: "3", label: "三月", checked: false }, |
||||
|
{ value: "4", label: "四月", checked: false }, |
||||
|
{ value: "5", label: "五月", checked: false }, |
||||
|
{ value: "6", label: "六月", checked: false }, |
||||
|
{ value: "7", label: "七月", checked: false }, |
||||
|
{ value: "8", label: "八月", checked: false }, |
||||
|
{ value: "9", label: "九月", checked: false }, |
||||
|
{ value: "10", label: "十月", checked: false }, |
||||
|
{ value: "11", label: "十一月", checked: false }, |
||||
|
{ value: "12", label: "十二月", checked: false }, |
||||
|
]; |
||||
|
|
||||
|
allMonthChecked = false; |
||||
|
|
||||
|
indeterminate = false; |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.formGroup = this.fb.group({ |
||||
|
id: this.fb.control("", [FormValidators.required()]), |
||||
|
|
||||
|
name: this.fb.control("", [FormValidators.required()]), |
||||
|
|
||||
|
month: this.fb.control([], [FormValidators.required()]), |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
updateAllMonthChecked() { |
||||
|
this.indeterminate = false; |
||||
|
if (this.allMonthChecked) { |
||||
|
this.allMonth = this.allMonth.map((item) => ({ |
||||
|
...item, |
||||
|
checked: true, |
||||
|
})); |
||||
|
} else { |
||||
|
this.allMonth = this.allMonth.map((item) => ({ |
||||
|
...item, |
||||
|
checked: false, |
||||
|
})); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
monthChecked() { |
||||
|
if (this.allMonth.every((item) => !item.checked)) { |
||||
|
this.allMonthChecked = false; |
||||
|
this.indeterminate = false; |
||||
|
} else if (this.allMonth.every((item) => item.checked)) { |
||||
|
this.allMonthChecked = true; |
||||
|
this.indeterminate = false; |
||||
|
} else { |
||||
|
this.indeterminate = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,252 @@ |
|||||
|
<div> |
||||
|
<div class="mb-3"> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="primary" (click)="shopDishForm()"> |
||||
|
添加菜品 |
||||
|
</button> |
||||
|
<button *nzSpaceItem nz-button> |
||||
|
清空本餐 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</div> |
||||
|
<nz-table nzTemplateMode [nzBordered]="true" nzSize="small"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th colSpan="2"></th> |
||||
|
|
||||
|
<th [colSpan]="5"> |
||||
|
重量/克 |
||||
|
</th> |
||||
|
|
||||
|
</tr> |
||||
|
<tr> |
||||
|
|
||||
|
<th [rowSpan]="2"> |
||||
|
菜品 |
||||
|
</th> |
||||
|
<th [rowSpan]="2"> |
||||
|
食材 |
||||
|
</th> |
||||
|
<th> |
||||
|
轻体力(体重过低) |
||||
|
</th> |
||||
|
<th> |
||||
|
轻体力(正常体重) |
||||
|
</th> |
||||
|
<th> |
||||
|
休息(超重/肥胖) |
||||
|
</th> |
||||
|
<th> |
||||
|
轻体力(体重过低) |
||||
|
</th> |
||||
|
<th> |
||||
|
轻体力(正常体重) |
||||
|
</th> |
||||
|
</tr> |
||||
|
|
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td [rowSpan]="2"> |
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
番茄煎蛋面 |
||||
|
</span> |
||||
|
<button nz-button nzType="text" nz-dropdown [nzDropdownMenu]="dishOptions"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
<nz-dropdown-menu #dishOptions="nzDropdownMenu"> |
||||
|
<ul nz-menu nzSelectable class=" w-20"> |
||||
|
<li nz-menu-item>编辑</li> |
||||
|
<li nz-menu-item nzDanger>删除</li> |
||||
|
</ul> |
||||
|
</nz-dropdown-menu> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
|
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
番茄 |
||||
|
</span> |
||||
|
<button nz-button nzType="text" nz-dropdown [nzDropdownMenu]="foodOptions"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
<nz-dropdown-menu #foodOptions="nzDropdownMenu"> |
||||
|
<ul nz-menu nzSelectable class="w-100"> |
||||
|
<li nz-menu-item>设置价格</li> |
||||
|
<li nz-menu-item nzDanger>删除</li> |
||||
|
</ul> |
||||
|
</nz-dropdown-menu> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
|
||||
|
<td> |
||||
|
|
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
面条 |
||||
|
</span> |
||||
|
<button nz-button nzType="text"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td [rowSpan]="4"> |
||||
|
|
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
鸡蛋青菜面 |
||||
|
</span> |
||||
|
<button nz-button nzType="text"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
食用油 |
||||
|
</span> |
||||
|
<button nz-button nzType="text"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td> |
||||
|
|
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
小白菜[青菜] |
||||
|
</span> |
||||
|
<button nz-button nzType="text"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td> |
||||
|
|
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
鸡蛋(均值) |
||||
|
</span> |
||||
|
<button nz-button nzType="text"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td> |
||||
|
|
||||
|
<div class="flex justify-between"> |
||||
|
<span> |
||||
|
面条(均值) |
||||
|
</span> |
||||
|
<button nz-button nzType="text"> |
||||
|
<i nz-icon nzType="more"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
<td> |
||||
|
1 |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</nz-table> |
||||
|
</div> |
||||
@ -0,0 +1,21 @@ |
|||||
|
import { Component } from "@angular/core"; |
||||
|
import { NzModalService } from "ng-zorro-antd/modal"; |
||||
|
import { AddDishToIngredientComponent } from "../add-dish-to-ingredient/add-dish-to-ingredient.component"; |
||||
|
import { NzDrawerService } from "ng-zorro-antd/drawer"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "lib-ingredient-meals", |
||||
|
templateUrl: "./ingredient-meals.component.html", |
||||
|
styleUrls: ["./ingredient-meals.component.less"], |
||||
|
}) |
||||
|
export class IngredientMealsComponent { |
||||
|
constructor(private modal: NzModalService, private drawer: NzDrawerService) {} |
||||
|
|
||||
|
shopDishForm() { |
||||
|
this.drawer.create({ |
||||
|
nzTitle: "添加菜品", |
||||
|
nzWidth: 1000, |
||||
|
nzContent: AddDishToIngredientComponent, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
import { NgModule } from "@angular/core"; |
||||
|
import { SharedModule } from "@cdk/shared/shared.module"; |
||||
|
import { AddDishToIngredientComponent } from "./add-dish-to-ingredient/add-dish-to-ingredient.component"; |
||||
|
import { IngredientMealsComponent } from "./ingredient-meals/ingredient-meals.component"; |
||||
|
import { ConfirmIngredientComponent } from "./confirm-ingredient/confirm-ingredient.component"; |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [AddDishToIngredientComponent, IngredientMealsComponent, ConfirmIngredientComponent], |
||||
|
imports: [SharedModule], |
||||
|
exports: [AddDishToIngredientComponent, IngredientMealsComponent, ConfirmIngredientComponent], |
||||
|
}) |
||||
|
export class IngredientModule {} |
||||
@ -0,0 +1,52 @@ |
|||||
|
import { NgModule } from "@angular/core"; |
||||
|
import { RouterModule, Routes } from "@angular/router"; |
||||
|
import { |
||||
|
DashboardComponent, |
||||
|
DataVisComponent, |
||||
|
DishComponent, |
||||
|
FoodComponent, |
||||
|
LoginComponent, |
||||
|
MealSettingComponent, |
||||
|
} from "./pages"; |
||||
|
import { AppLayoutComponent } from "./components"; |
||||
|
|
||||
|
const routes: Routes = [ |
||||
|
{ path: "login", component: LoginComponent }, |
||||
|
{ |
||||
|
path: "", |
||||
|
component: AppLayoutComponent, |
||||
|
children: [ |
||||
|
{ |
||||
|
path: "", |
||||
|
pathMatch: "full", |
||||
|
redirectTo: "dashboard", |
||||
|
}, |
||||
|
{ |
||||
|
path: "dashboard", |
||||
|
component: DashboardComponent, |
||||
|
}, |
||||
|
{ |
||||
|
path: "meal-setting", |
||||
|
component: MealSettingComponent, |
||||
|
}, |
||||
|
{ |
||||
|
path: "data-vis", |
||||
|
component: DataVisComponent, |
||||
|
}, |
||||
|
{ |
||||
|
path: "food", |
||||
|
component: FoodComponent, |
||||
|
}, |
||||
|
{ |
||||
|
path: "dish", |
||||
|
component: DishComponent, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
@NgModule({ |
||||
|
imports: [RouterModule.forRoot(routes)], |
||||
|
exports: [RouterModule], |
||||
|
}) |
||||
|
export class AppRoutingModule {} |
||||
@ -0,0 +1 @@ |
|||||
|
<router-outlet></router-outlet> |
||||
@ -0,0 +1,29 @@ |
|||||
|
import { TestBed } from '@angular/core/testing'; |
||||
|
import { RouterTestingModule } from '@angular/router/testing'; |
||||
|
import { AppComponent } from './app.component'; |
||||
|
|
||||
|
describe('AppComponent', () => { |
||||
|
beforeEach(() => TestBed.configureTestingModule({ |
||||
|
imports: [RouterTestingModule], |
||||
|
declarations: [AppComponent] |
||||
|
})); |
||||
|
|
||||
|
it('should create the app', () => { |
||||
|
const fixture = TestBed.createComponent(AppComponent); |
||||
|
const app = fixture.componentInstance; |
||||
|
expect(app).toBeTruthy(); |
||||
|
}); |
||||
|
|
||||
|
it(`should have as title 'client'`, () => { |
||||
|
const fixture = TestBed.createComponent(AppComponent); |
||||
|
const app = fixture.componentInstance; |
||||
|
expect(app.title).toEqual('client'); |
||||
|
}); |
||||
|
|
||||
|
it('should render title', () => { |
||||
|
const fixture = TestBed.createComponent(AppComponent); |
||||
|
fixture.detectChanges(); |
||||
|
const compiled = fixture.nativeElement as HTMLElement; |
||||
|
expect(compiled.querySelector('.content span')?.textContent).toContain('client app is running!'); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,10 @@ |
|||||
|
import { Component } from '@angular/core'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'app-root', |
||||
|
templateUrl: './app.component.html', |
||||
|
styleUrls: ['./app.component.less'] |
||||
|
}) |
||||
|
export class AppComponent { |
||||
|
title = 'client'; |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
import { NgModule } from "@angular/core"; |
||||
|
import { BrowserModule } from "@angular/platform-browser"; |
||||
|
|
||||
|
import { NZ_I18N } from "ng-zorro-antd/i18n"; |
||||
|
import { zh_CN } from "ng-zorro-antd/i18n"; |
||||
|
import { registerLocaleData } from "@angular/common"; |
||||
|
import zh from "@angular/common/locales/zh"; |
||||
|
import { FormsModule } from "@angular/forms"; |
||||
|
import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http"; |
||||
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; |
||||
|
|
||||
|
import { AppRoutingModule } from "./app-routing.module"; |
||||
|
import { AppComponent } from "./app.component"; |
||||
|
import { AppLayoutComponent } from "./components"; |
||||
|
import { IconsProviderModule, TableListModule } from "@cdk/public-api"; |
||||
|
import { SharedModule } from "@cdk/shared/shared.module"; |
||||
|
import { |
||||
|
DashboardComponent, |
||||
|
LoginComponent, |
||||
|
MealSettingComponent, |
||||
|
DataVisComponent, |
||||
|
FoodComponent, |
||||
|
DishComponent, |
||||
|
} from "./pages"; |
||||
|
|
||||
|
registerLocaleData(zh); |
||||
|
|
||||
|
@NgModule({ |
||||
|
declarations: [ |
||||
|
AppComponent, |
||||
|
AppLayoutComponent, |
||||
|
DashboardComponent, |
||||
|
LoginComponent, |
||||
|
MealSettingComponent, |
||||
|
DataVisComponent, |
||||
|
FoodComponent, |
||||
|
DishComponent, |
||||
|
], |
||||
|
imports: [ |
||||
|
BrowserModule, |
||||
|
AppRoutingModule, |
||||
|
FormsModule, |
||||
|
HttpClientModule, |
||||
|
BrowserAnimationsModule, |
||||
|
IconsProviderModule, |
||||
|
SharedModule, |
||||
|
TableListModule, |
||||
|
], |
||||
|
providers: [{ provide: NZ_I18N, useValue: zh_CN }], |
||||
|
bootstrap: [AppComponent], |
||||
|
}) |
||||
|
export class AppModule {} |
||||
@ -0,0 +1,73 @@ |
|||||
|
<nz-layout class="app-layout"> |
||||
|
<nz-header class="app-header"> |
||||
|
<div class="flex items-center justify-between h-full"> |
||||
|
<div class="logo flex items-center h-full"> |
||||
|
<img class="block h-[40px] mr-2" src="../assets/images/jl-logo.png" /> |
||||
|
<span class="text-lg text-white font-bold"> |
||||
|
智慧配餐系统 |
||||
|
</span> |
||||
|
</div> |
||||
|
<div class="profile"> |
||||
|
<button |
||||
|
nz-button |
||||
|
nzType="text" |
||||
|
nz-dropdown |
||||
|
[nzDropdownMenu]="menu" |
||||
|
class="text-white hover:text-white focus:text-white"> |
||||
|
admin |
||||
|
</button> |
||||
|
<nz-dropdown-menu #menu="nzDropdownMenu"> |
||||
|
<ul nz-menu nzSelectable> |
||||
|
<li nz-menu-item (click)="logout()"> |
||||
|
退出登录 |
||||
|
</li> |
||||
|
</ul> |
||||
|
</nz-dropdown-menu> |
||||
|
</div> |
||||
|
</div> |
||||
|
</nz-header> |
||||
|
<nz-layout class="app-layout-main"> |
||||
|
<nz-sider nzWidth="200px" class="sider-menu" nzTheme="light"> |
||||
|
|
||||
|
<ul nz-menu nzMode="inline"> |
||||
|
<li nz-menu-item class="k-icon" [routerLink]="['/','dashboard']" nzMatchRouter> |
||||
|
<span nz-icon nzType="question-circle" nzTheme="outline"></span> |
||||
|
<span>使用流程</span> |
||||
|
</li> |
||||
|
<li nz-menu-item class="k-icon" [routerLink]="['/','data-vis']" nzMatchRouter> |
||||
|
<span nz-icon nzType="fund" nzTheme="outline"></span> |
||||
|
<span>大屏显示</span> |
||||
|
</li> |
||||
|
<li nz-menu-item class="k-icon" [routerLink]="['/','meal-setting']" nzMatchRouter> |
||||
|
<span nz-icon nzType="k-icon:food" nzTheme="outline"></span> |
||||
|
<span>配餐设置</span> |
||||
|
</li> |
||||
|
<li nz-menu-item class="k-icon" [routerLink]="['/','food']" nzMatchRouter> |
||||
|
<span nz-icon nzType="k-icon:food" nzTheme="outline"></span> |
||||
|
<span>食材管理</span> |
||||
|
</li> |
||||
|
<li nz-menu-item class="k-icon" [routerLink]="['/','dish']" nzMatchRouter> |
||||
|
<span nz-icon nzType="k-icon:food" nzTheme="outline"></span> |
||||
|
<span>菜品管理</span> |
||||
|
</li> |
||||
|
|
||||
|
|
||||
|
<li nz-submenu nzTitle="食谱管理" nzIcon="book" [nzOpen]="currentUrl.includes('/ingredient/')"> |
||||
|
<ul> |
||||
|
<li nz-menu-item nzMatchRouter [routerLink]="['/','ingredient','item']">食谱库</li> |
||||
|
<li nz-menu-item nzMatchRouter [routerLink]="['/','ingredient','release']">食谱发布计划</li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
|
||||
|
<li nz-submenu nzTitle="系统设置" nzIcon="setting" [nzOpen]="currentUrl.includes('/system/')"> |
||||
|
<ul> |
||||
|
<li nz-menu-item nzMatchRouter [routerLink]="['/','system','user']">用户管理</li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</nz-sider> |
||||
|
<nz-layout class="inner-layout overflow-hidden"> |
||||
|
<router-outlet></router-outlet> |
||||
|
</nz-layout> |
||||
|
</nz-layout> |
||||
|
</nz-layout> |
||||
@ -0,0 +1,64 @@ |
|||||
|
:host { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
@header-height: 48px; |
||||
|
|
||||
|
.app-layout { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
flex: 1; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.app-header { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 100; |
||||
|
height: @header-height; |
||||
|
line-height: @header-height; |
||||
|
padding: 0 24px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.k-icon { |
||||
|
::ng-deep { |
||||
|
.anticon { |
||||
|
font-size: 16px; |
||||
|
|
||||
|
svg, |
||||
|
path { |
||||
|
fill: currentColor !important; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.sider-menu { |
||||
|
position: fixed; |
||||
|
top: @header-height; |
||||
|
left: 0; |
||||
|
bottom: 0; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
|
.app-layout-main { |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.inner-layout { |
||||
|
padding-top: @header-height; |
||||
|
padding-left: 200px; |
||||
|
|
||||
|
::ng-deep { |
||||
|
router-outlet+* { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
import { Component } from "@angular/core"; |
||||
|
import { NavigationEnd, Router, RouterModule } from "@angular/router"; |
||||
|
|
||||
|
import { NzModalService } from "ng-zorro-antd/modal"; |
||||
|
import { Subject, filter, takeUntil } from "rxjs"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-layout", |
||||
|
templateUrl: "./app-layout.component.html", |
||||
|
styleUrls: ["./app-layout.component.less"], |
||||
|
}) |
||||
|
export class AppLayoutComponent { |
||||
|
constructor(private router: Router, private modal: NzModalService) { |
||||
|
this.router.events |
||||
|
.pipe( |
||||
|
takeUntil(this.unSubscribe$), |
||||
|
filter((e): e is NavigationEnd => e instanceof NavigationEnd) |
||||
|
) |
||||
|
.subscribe((e) => { |
||||
|
this.currentUrl = e.url; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
unSubscribe$ = new Subject<void>(); |
||||
|
|
||||
|
currentUrl: string = ""; |
||||
|
|
||||
|
logout() { |
||||
|
this.modal.confirm({ |
||||
|
nzTitle: "警告", |
||||
|
nzContent: "是否要退出登录?", |
||||
|
nzOnOk: () => {}, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
export * from "./app-layout/app-layout.component"; |
||||
@ -0,0 +1,5 @@ |
|||||
|
<app-page [pageTitle]="'使用流程'"> |
||||
|
<nz-card> |
||||
|
|
||||
|
</nz-card> |
||||
|
</app-page> |
||||
@ -0,0 +1,10 @@ |
|||||
|
import { Component } from '@angular/core'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'app-dashboard', |
||||
|
templateUrl: './dashboard.component.html', |
||||
|
styleUrls: ['./dashboard.component.less'] |
||||
|
}) |
||||
|
export class DashboardComponent { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
<p>data-vis works!</p> |
||||
@ -0,0 +1,10 @@ |
|||||
|
import { Component } from '@angular/core'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'app-data-vis', |
||||
|
templateUrl: './data-vis.component.html', |
||||
|
styleUrls: ['./data-vis.component.less'] |
||||
|
}) |
||||
|
export class DataVisComponent { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,74 @@ |
|||||
|
<app-page [scroll]="false"> |
||||
|
|
||||
|
<div nz-row class="h-full overflow-hidden bg-white rounded-lg"> |
||||
|
<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> |
||||
|
<a> |
||||
|
全部 |
||||
|
</a> |
||||
|
</li> |
||||
|
<li nz-menu-item> |
||||
|
<a> |
||||
|
时令菜品 |
||||
|
</a> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
</nz-card> |
||||
|
</div> |
||||
|
<div nz-col nzFlex="1" class="flex-1 overflow-hidden bg-white h-full"> |
||||
|
|
||||
|
<nz-card [nzBordered]="false" nzTitle="菜品列表" class="scroll-card-body"> |
||||
|
<div class="m-4"> |
||||
|
<ng-template #pageExtraTpl> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button>批量删除</button> |
||||
|
<button *nzSpaceItem nz-button>批量打印营养标签</button> |
||||
|
<button *nzSpaceItem nz-button nzType="primary" (click)="showFoodForm()"> |
||||
|
<i nz-icon nzType="plus"></i> |
||||
|
新增菜品 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</ng-template> |
||||
|
<table-list [props]="tableList" [search]="searchTpl" [action]="pageExtraTpl" [formGroup]="queryForm" |
||||
|
[renderColumns]="renderColumnsTpl"> |
||||
|
|
||||
|
<ng-template #actionTpl> |
||||
|
<button nz-button>批量删除</button> |
||||
|
</ng-template> |
||||
|
<ng-template #searchTpl> |
||||
|
|
||||
|
<nz-form-item class="w-50"> |
||||
|
<nz-form-control> |
||||
|
<nz-select nzPlaceHolder="菜品标签" [nzOptions]="[]"></nz-select> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<input nz-input placeholder="请输入菜品名称" formControlName="name" /> |
||||
|
</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'"> |
||||
|
<div class="dish-img overflow-auto" |
||||
|
[ngStyle]="{'background-image':'url(' + tempImg + ')'}"> |
||||
|
</div> |
||||
|
</ng-container> |
||||
|
<ng-container *ngSwitchDefault> |
||||
|
|
||||
|
{{data}} |
||||
|
|
||||
|
</ng-container> |
||||
|
</ng-container> |
||||
|
</ng-template> |
||||
|
</table-list> |
||||
|
</div> |
||||
|
</nz-card> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</app-page> |
||||
@ -0,0 +1,18 @@ |
|||||
|
.food-type { |
||||
|
border-right: 1px solid #e8e8e8; |
||||
|
|
||||
|
::ng-deep { |
||||
|
.ant-menu-inline { |
||||
|
border-right: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.dish-img { |
||||
|
width: 64px; |
||||
|
height: 64px; |
||||
|
border-radius: 10px; |
||||
|
background-size: cover; |
||||
|
background-position: center; |
||||
|
background-repeat: no-repeat; |
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from "@angular/core"; |
||||
|
import { FormControl, FormGroup } from "@angular/forms"; |
||||
|
import { AnyObject, TableListOption } from "@cdk/public-api"; |
||||
|
import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; |
||||
|
import { NzModalService } from "ng-zorro-antd/modal"; |
||||
|
import { Subject, takeUntil } from "rxjs"; |
||||
|
import { ClientApiService } from "../../services"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-dish", |
||||
|
templateUrl: "./dish.component.html", |
||||
|
styleUrls: ["./dish.component.less"], |
||||
|
}) |
||||
|
export class DishComponent implements OnInit, OnDestroy { |
||||
|
constructor(private drawer: NzDrawerService, private api: ClientApiService, private modal: NzModalService) {} |
||||
|
|
||||
|
@ViewChild("foofFormFooterTpl") foofFormFooterTpl!: TemplateRef<{}>; |
||||
|
|
||||
|
tempImg = "https://cdn.pixabay.com/photo/2023/08/08/18/01/butterfly-8177925_1280.jpg"; |
||||
|
|
||||
|
public tableList = new TableListOption(this.fetchData.bind(this), { |
||||
|
selectable: true, |
||||
|
}); |
||||
|
|
||||
|
public queryForm = new FormGroup({ |
||||
|
type: new FormControl({ value: "A", disabled: false }), |
||||
|
name: new FormControl("addd"), |
||||
|
}); |
||||
|
|
||||
|
private destroy$ = new Subject<void>(); |
||||
|
|
||||
|
public selectedIds: string[] = []; |
||||
|
|
||||
|
temp = Array.from({ length: 50 }, (_, i) => i); |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.initTableList(); |
||||
|
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => { |
||||
|
this.selectedIds = res.selectedKeys as Array<string>; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy(): void { |
||||
|
this.destroy$.next(); |
||||
|
this.destroy$.complete(); |
||||
|
} |
||||
|
|
||||
|
initTableList() { |
||||
|
this.tableList.scroll = { x: null }; |
||||
|
this.tableList = this.tableList.setColumns([ |
||||
|
{ key: "img", title: "菜品图片", width: "66px" }, |
||||
|
{ key: "name", title: "菜品名称" }, |
||||
|
{ key: "name", title: "菜品标签" }, |
||||
|
{ key: "name", title: "食材及含量", width: "30%" }, |
||||
|
{ key: "name", title: "单位" }, |
||||
|
]); |
||||
|
|
||||
|
this.tableList = this.tableList.setOptions([ |
||||
|
{ |
||||
|
title: "打印营养标签", |
||||
|
premissions: [], |
||||
|
onClick: this.showFoodForm.bind(this), |
||||
|
}, |
||||
|
{ |
||||
|
title: "编辑", |
||||
|
premissions: [], |
||||
|
onClick: this.showFoodForm.bind(this), |
||||
|
}, |
||||
|
{ |
||||
|
title: "删除", |
||||
|
premissions: [], |
||||
|
onClick: this.deleteItem.bind(this), |
||||
|
}, |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
fetchData(pager: AnyObject, query: AnyObject) { |
||||
|
return this.api.page(pager, query); |
||||
|
} |
||||
|
|
||||
|
deleteItem(v?: any) { |
||||
|
const ids = v ? [v.id] : this.selectedIds; |
||||
|
this.modal.confirm({ |
||||
|
nzTitle: "警告", |
||||
|
nzContent: "是否要删除该食材?", |
||||
|
nzOkDanger: true, |
||||
|
nzOnOk: () => {}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
showFoodForm(food?: any) { |
||||
|
// this.drawerRef = this.drawer.create({
|
||||
|
// nzTitle: food ? "编辑菜品" : "新增菜品",
|
||||
|
// nzWidth: 700,
|
||||
|
// nzContent: DishFormComponent,
|
||||
|
// nzFooter: this.formFooterTpl,
|
||||
|
// });
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,87 @@ |
|||||
|
<app-page [scroll]="false"> |
||||
|
|
||||
|
<div nz-row class="h-full overflow-hidden bg-white rounded-lg"> |
||||
|
<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> |
||||
|
<a> |
||||
|
全部 |
||||
|
</a> |
||||
|
</li> |
||||
|
<li nz-menu-item> |
||||
|
<a> |
||||
|
谷薯类 |
||||
|
</a> |
||||
|
</li> |
||||
|
<li nz-menu-item> |
||||
|
<a> |
||||
|
大豆类及其制品 |
||||
|
</a> |
||||
|
</li> |
||||
|
<li nz-menu-item> |
||||
|
<a> |
||||
|
蔬菜类 |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</nz-card> |
||||
|
</div> |
||||
|
<div nz-col nzFlex="1" class="flex-1 overflow-hidden bg-white h-full"> |
||||
|
|
||||
|
<nz-card [nzBordered]="false" nzTitle="食材管理" class="scroll-card-body"> |
||||
|
<div class="m-4"> |
||||
|
<table-list |
||||
|
[props]="tableList" |
||||
|
[formGroup]="queryForm" |
||||
|
[search]="searchTpl" |
||||
|
[renderColumns]="renderColumnsTpl"> |
||||
|
|
||||
|
<ng-template #searchTpl> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<nz-radio-group nzButtonStyle="solid" formControlName="type"> |
||||
|
<label nz-radio-button nzValue="A">全部</label> |
||||
|
<label nz-radio-button nzValue="B">常用</label> |
||||
|
<label nz-radio-button nzValue="c">忌用</label> |
||||
|
<label nz-radio-button nzValue="d">其他</label> |
||||
|
</nz-radio-group> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<input nz-input placeholder="请输入食材名称/编号" formControlName="name" /> |
||||
|
</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="'name1'"> |
||||
|
<a nz-popover |
||||
|
[nzPopoverContent]="popoverTpl" |
||||
|
nzPopoverTitle="营养素"> |
||||
|
共<b>10</b>中营养素 |
||||
|
</a> |
||||
|
<ng-template #popoverTpl> |
||||
|
<div class=" max-w-sm max-h-60 overflow-auto"> |
||||
|
<nz-tag *ngFor="let item of temp" class="m-1"> |
||||
|
能量{{item}}:10kcal |
||||
|
</nz-tag> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
</ng-container> |
||||
|
<ng-container *ngSwitchDefault> |
||||
|
|
||||
|
{{data}} |
||||
|
|
||||
|
</ng-container> |
||||
|
</ng-container> |
||||
|
</ng-template> |
||||
|
</table-list> |
||||
|
</div> |
||||
|
</nz-card> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</app-page> |
||||
@ -0,0 +1,9 @@ |
|||||
|
.food-type { |
||||
|
border-right: 1px solid #e8e8e8; |
||||
|
|
||||
|
::ng-deep { |
||||
|
.ant-menu-inline { |
||||
|
border-right: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from "@angular/core"; |
||||
|
import { FormControl, FormGroup } from "@angular/forms"; |
||||
|
import { AnyObject, TableListOption } from "@cdk/public-api"; |
||||
|
import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; |
||||
|
import { NzModalService } from "ng-zorro-antd/modal"; |
||||
|
import { Subject, takeUntil } from "rxjs"; |
||||
|
import { ClientApiService } from "../../services"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-food", |
||||
|
templateUrl: "./food.component.html", |
||||
|
styleUrls: ["./food.component.less"], |
||||
|
}) |
||||
|
export class FoodComponent implements OnInit, OnDestroy { |
||||
|
constructor(private drawer: NzDrawerService, private api: ClientApiService, private modal: NzModalService) {} |
||||
|
|
||||
|
@ViewChild("foofFormFooterTpl") foofFormFooterTpl!: TemplateRef<{}>; |
||||
|
|
||||
|
public tableList = new TableListOption(this.fetchData.bind(this), { |
||||
|
selectable: true, |
||||
|
}); |
||||
|
|
||||
|
public queryForm = new FormGroup({ |
||||
|
type: new FormControl({ value: "A", disabled: false }), |
||||
|
name: new FormControl("addd"), |
||||
|
}); |
||||
|
|
||||
|
private destroy$ = new Subject<void>(); |
||||
|
|
||||
|
public selectedIds: string[] = []; |
||||
|
|
||||
|
temp = Array.from({ length: 50 }, (_, i) => i); |
||||
|
|
||||
|
ngOnInit(): void { |
||||
|
this.initTableList(); |
||||
|
this.tableList.getState$.pipe(takeUntil(this.destroy$)).subscribe((res) => { |
||||
|
this.selectedIds = res.selectedKeys as Array<string>; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy(): void { |
||||
|
this.destroy$.next(); |
||||
|
this.destroy$.complete(); |
||||
|
} |
||||
|
|
||||
|
initTableList() { |
||||
|
this.tableList.scroll = { x: null }; |
||||
|
this.tableList = this.tableList.setColumns([ |
||||
|
{ key: "name", title: "食材编号" }, |
||||
|
{ key: "name", title: "食材名称" }, |
||||
|
{ key: "name", title: "食材类型" }, |
||||
|
{ key: "name1", title: "营养素(每100g可食部)" }, |
||||
|
{ key: "name", title: "更新日期" }, |
||||
|
]); |
||||
|
|
||||
|
this.tableList = this.tableList.setOptions([ |
||||
|
{ |
||||
|
title: "常用", |
||||
|
premissions: [], |
||||
|
onClick: this.deleteFood.bind(this), |
||||
|
}, |
||||
|
{ |
||||
|
title: "忌用", |
||||
|
premissions: [], |
||||
|
onClick: this.deleteFood.bind(this), |
||||
|
}, |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
fetchData(pager: AnyObject, query: AnyObject) { |
||||
|
return this.api.page(pager, query); |
||||
|
} |
||||
|
|
||||
|
deleteFood(v?: any) { |
||||
|
const ids = v ? [v.id] : this.selectedIds; |
||||
|
this.modal.confirm({ |
||||
|
nzTitle: "警告", |
||||
|
nzContent: "是否要删除该食材?", |
||||
|
nzOkDanger: true, |
||||
|
nzOnOk: () => {}, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
export * from "./dashboard/dashboard.component"; |
||||
|
export * from "./login/login.component"; |
||||
|
export * from "./meal-setting/meal-setting.component"; |
||||
|
export * from "./data-vis/data-vis.component"; |
||||
|
export * from "./food/food.component"; |
||||
|
export * from "./dish/dish.component"; |
||||
@ -0,0 +1,65 @@ |
|||||
|
<section class="h-full "> |
||||
|
<div class="login"> |
||||
|
<!-- <div> |
||||
|
<h1 class="text-center my-[25px]"> |
||||
|
<img class="logo" [src]="'/assets/images/jl-logo.png'" /> |
||||
|
|
||||
|
</h1> |
||||
|
</div> --> |
||||
|
<div class="card "> |
||||
|
<div class="img flex items-center justify-center"> |
||||
|
<img src="assets/images/login.png" /> |
||||
|
</div> |
||||
|
<div class="form py-5 px-10 flex-1"> |
||||
|
<div class="form-inner"> |
||||
|
<h2 class="mt-4 text-3xl font-bold">智慧配餐管理</h2> |
||||
|
<h3 class="mt-10 text-xl">登录</h3> |
||||
|
|
||||
|
<form nz-form [formGroup]="loginForm" class="mt-10"> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
||||
|
<nz-input-group [nzPrefix]="prefixTemplateUser" nzSize="large"> |
||||
|
<input nz-input nzSize="large" placeholder="账户" formControlName="uid" /> |
||||
|
</nz-input-group> |
||||
|
<ng-template #prefixTemplateUser> |
||||
|
<span nz-icon nzType="user"></span> |
||||
|
<nz-divider nzType="vertical"></nz-divider> |
||||
|
</ng-template> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control [nzErrorTip]="formErrorTipsTpl"> |
||||
|
<nz-input-group [nzPrefix]="prefixTemplatePassword" nzSize="large"> |
||||
|
<input nz-input type="password" placeholder="密码" formControlName="password" /> |
||||
|
</nz-input-group> |
||||
|
<ng-template #prefixTemplatePassword> |
||||
|
<span nz-icon nzType="lock"></span> |
||||
|
<nz-divider nzType="vertical"></nz-divider> |
||||
|
</ng-template> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<button nz-button |
||||
|
nzType="primary" |
||||
|
nzBlock |
||||
|
class="btn" |
||||
|
nzSize="large" |
||||
|
(click)="onLogin()" |
||||
|
[nzLoading]="loading"> |
||||
|
登录 |
||||
|
</button> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<ng-template #formErrorTipsTpl let-control> |
||||
|
<div class="text-left"> |
||||
|
<form-error-tips [control]="control"></form-error-tips> |
||||
|
</div> |
||||
|
</ng-template> |
||||
@ -0,0 +1,81 @@ |
|||||
|
// |
||||
|
|
||||
|
:host { |
||||
|
display: block; |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
position: relative; |
||||
|
background-color: #edf0f5; |
||||
|
background-repeat: no-repeat; |
||||
|
background-size: cover; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.login { |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
position: relative; |
||||
|
z-index: 1; |
||||
|
background-color: #fff; |
||||
|
|
||||
|
h1 { |
||||
|
margin-bottom: 24px; |
||||
|
font-size: 24px; |
||||
|
font-weight: 400; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.logo { |
||||
|
display: inline-block; |
||||
|
height: 36px; |
||||
|
} |
||||
|
|
||||
|
.card { |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
background-color: #fff; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
|
||||
|
.img { |
||||
|
flex: 1; |
||||
|
height: 100%; |
||||
|
background-repeat: no-repeat; |
||||
|
background-position: center right; |
||||
|
background-size: auto 100%; |
||||
|
background-image: url('/assets/images/login-bg.svg'); |
||||
|
|
||||
|
img { |
||||
|
width: 40vw; |
||||
|
margin-left: -6vw; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.form { |
||||
|
|
||||
|
margin: 0 auto; |
||||
|
background-color: #fff; |
||||
|
border-radius: 6px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
|
||||
|
.form-inner { |
||||
|
width: 400px; |
||||
|
margin-left: 5vw; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
p { |
||||
|
font-size: 16px; |
||||
|
line-height: 24px; |
||||
|
letter-spacing: 0.23em; |
||||
|
text-shadow: 0px 8px 20px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.btn { |
||||
|
margin-top: 16px; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
import { Component } from "@angular/core"; |
||||
|
import { FormControl, FormGroup } from "@angular/forms"; |
||||
|
import { Router } from "@angular/router"; |
||||
|
import { NzMessageService } from "ng-zorro-antd/message"; |
||||
|
import { FormValidators } from "projects/cdk/src/public-api"; |
||||
|
import { Utils } from "projects/cdk/src/utils"; |
||||
|
import { finalize, lastValueFrom } from "rxjs"; |
||||
|
import { ClientApiService } from "../../services"; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: "app-login", |
||||
|
templateUrl: "./login.component.html", |
||||
|
styleUrls: ["./login.component.less"], |
||||
|
}) |
||||
|
export class LoginComponent { |
||||
|
constructor(private msg: NzMessageService, private api: ClientApiService, private router: Router) {} |
||||
|
|
||||
|
public loginForm = new FormGroup({ |
||||
|
uid: new FormControl("", [FormValidators.required("请输入账户")]), |
||||
|
password: new FormControl("", [FormValidators.required("请输入密码")]), |
||||
|
}); |
||||
|
|
||||
|
public loading: boolean = false; |
||||
|
|
||||
|
ngOnInit(): void {} |
||||
|
|
||||
|
async onLogin() { |
||||
|
if (Utils.validateFormGroup(this.loginForm)) { |
||||
|
const { value } = this.loginForm; |
||||
|
this.loading = true; |
||||
|
const res = await lastValueFrom( |
||||
|
this.api.login(value).pipe( |
||||
|
finalize(() => { |
||||
|
this.loading = false; |
||||
|
}) |
||||
|
) |
||||
|
); |
||||
|
this.msg.success(res.desc); |
||||
|
this.router.navigate(["/"]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
<app-page> |
||||
|
<nz-card nzTitle="餐次、能量摄入比例配置"> |
||||
|
<form nz-form nzLayout="vertical"> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzRequired> |
||||
|
早餐能量、营养摄入比例 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="10"> |
||||
|
<nz-input-group nzAddOnAfter="%"> |
||||
|
<input nz-input type="number" placeholder="请输入" /> |
||||
|
</nz-input-group> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzRequired> |
||||
|
午餐能量、营养摄入比例 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="10"> |
||||
|
<nz-input-group nzAddOnAfter="%"> |
||||
|
<input nz-input type="number" placeholder="请输入" /> |
||||
|
</nz-input-group> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-label nzRequired> |
||||
|
晚餐能量、营养摄入比例 |
||||
|
</nz-form-label> |
||||
|
<nz-form-control nzSpan="10"> |
||||
|
<nz-input-group nzAddOnAfter="%"> |
||||
|
<input nz-input type="number" placeholder="请输入" /> |
||||
|
</nz-input-group> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
<nz-form-item> |
||||
|
<nz-form-control> |
||||
|
<nz-space> |
||||
|
<button *nzSpaceItem nz-button nzType="primary"> |
||||
|
保存 |
||||
|
</button> |
||||
|
<button *nzSpaceItem nz-button> |
||||
|
取消 |
||||
|
</button> |
||||
|
</nz-space> |
||||
|
</nz-form-control> |
||||
|
</nz-form-item> |
||||
|
</form> |
||||
|
</nz-card> |
||||
|
</app-page> |
||||
@ -0,0 +1,10 @@ |
|||||
|
import { Component } from '@angular/core'; |
||||
|
|
||||
|
@Component({ |
||||
|
selector: 'app-meal-setting', |
||||
|
templateUrl: './meal-setting.component.html', |
||||
|
styleUrls: ['./meal-setting.component.less'] |
||||
|
}) |
||||
|
export class MealSettingComponent { |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
import { HttpClient } from "@angular/common/http"; |
||||
|
import { Injectable } from "@angular/core"; |
||||
|
import { map } from "rxjs"; |
||||
|
|
||||
|
@Injectable({ |
||||
|
providedIn: "root", |
||||
|
}) |
||||
|
export class ClientApiService { |
||||
|
constructor(private http: HttpClient) {} |
||||
|
|
||||
|
login(v: {}) { |
||||
|
return this.http.post<any>("/", v); |
||||
|
} |
||||
|
|
||||
|
page(v: {}, q: {}) { |
||||
|
return this.http.get<any>("https://jsonplaceholder.typicode.com/users", v).pipe( |
||||
|
map((r) => { |
||||
|
return { |
||||
|
total: 10, |
||||
|
content: r, |
||||
|
}; |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,84 @@ |
|||||
|
import { Inject, Injectable } from "@angular/core"; |
||||
|
import { |
||||
|
HttpRequest, |
||||
|
HttpHandler, |
||||
|
HttpEvent, |
||||
|
HttpInterceptor, |
||||
|
HttpErrorResponse, |
||||
|
HttpResponse, |
||||
|
} from "@angular/common/http"; |
||||
|
import { catchError, Observable, switchMap, tap, throwError, timer } from "rxjs"; |
||||
|
import { Router } from "@angular/router"; |
||||
|
import { NzMessageService } from "ng-zorro-antd/message"; |
||||
|
import { ResponseType } from "@cdk/types"; |
||||
|
|
||||
|
@Injectable({ providedIn: "root" }) |
||||
|
export class HTTPInterceptor implements HttpInterceptor { |
||||
|
constructor(private router: Router, private msg: NzMessageService) {} |
||||
|
|
||||
|
private msgFlag = false; |
||||
|
|
||||
|
private localStroageKey = "catering"; |
||||
|
|
||||
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { |
||||
|
const token = localStorage.getItem(this.localStroageKey); |
||||
|
|
||||
|
if (token) { |
||||
|
req = req.clone({ |
||||
|
// headers: req.headers.set('Authorization', `Bearer ${token}`),
|
||||
|
headers: req.headers.set("Authorization", token), |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return this.handleResult(next, req); |
||||
|
} |
||||
|
|
||||
|
private handleResult(next: HttpHandler, authReq: HttpRequest<any>): Observable<HttpEvent<any>> { |
||||
|
return next.handle(authReq).pipe( |
||||
|
tap((res) => { |
||||
|
if (res instanceof HttpResponse) { |
||||
|
const Authorization = res.headers.get("Authorization"); |
||||
|
if (Authorization) { |
||||
|
localStorage.setItem(this.localStroageKey, Authorization); |
||||
|
} |
||||
|
|
||||
|
// if (this.decConfig.triggerError) {
|
||||
|
// this.decConfig.triggerError(res);
|
||||
|
// }
|
||||
|
|
||||
|
if (res.body?.success === false && res.body.desc) { |
||||
|
throw new HttpErrorResponse({ error: res.body }); |
||||
|
} |
||||
|
} |
||||
|
}), |
||||
|
|
||||
|
catchError((err: HttpErrorResponse) => { |
||||
|
const throwErr = throwError(() => err); |
||||
|
if (this.msgFlag) { |
||||
|
return throwErr; |
||||
|
} |
||||
|
|
||||
|
setTimeout(() => { |
||||
|
this.msgFlag = false; |
||||
|
}, 1500); |
||||
|
const error: ResponseType = err.error; |
||||
|
this.msgFlag = true; |
||||
|
|
||||
|
if (error.success === false) { |
||||
|
this.msg.error(error.desc); |
||||
|
switch (error.code) { |
||||
|
case 401: |
||||
|
this.router.navigate(["/", "login"]); |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} else { |
||||
|
this.msg.error("服务器出错了!"); |
||||
|
} |
||||
|
|
||||
|
return throwErr; |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
export * from "./client-api.service"; |
||||
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 948 B |
@ -0,0 +1,16 @@ |
|||||
|
<!doctype html> |
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<title>智慧配餐系统</title> |
||||
|
<base href="/"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<app-root></app-root> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
||||
@ -0,0 +1,7 @@ |
|||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; |
||||
|
|
||||
|
import { AppModule } from './app/app.module'; |
||||
|
|
||||
|
|
||||
|
platformBrowserDynamic().bootstrapModule(AppModule) |
||||
|
.catch(err => console.error(err)); |
||||
@ -0,0 +1,59 @@ |
|||||
|
// Custom Theming for NG-ZORRO |
||||
|
// For more information: https://ng.ant.design/docs/customize-theme/en |
||||
|
@import "../../../node_modules/ng-zorro-antd/ng-zorro-antd.less"; |
||||
|
|
||||
|
// Override less variables to here |
||||
|
// View all variables: https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/components/style/themes/default.less |
||||
|
|
||||
|
// @primary-color: #1890ff; |
||||
|
/* You can add global styles to this file, and also import other style files */ |
||||
|
|
||||
|
@tailwind utilities; |
||||
|
|
||||
|
html, |
||||
|
|
||||
|
body { |
||||
|
height: 100vh; |
||||
|
} |
||||
|
|
||||
|
ul, |
||||
|
li { |
||||
|
list-style: none; |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
.upload-btn { |
||||
|
position: relative; |
||||
|
|
||||
|
input { |
||||
|
display: block; |
||||
|
height: 100%; |
||||
|
background-color: red; |
||||
|
position: absolute; |
||||
|
inset: 0; |
||||
|
opacity: 0; |
||||
|
font-size: 0; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.fixed-footter { |
||||
|
box-shadow: 0 0 10px -2px rgba(0, 0, 0, .25) |
||||
|
} |
||||
|
|
||||
|
.scroll-card-body { |
||||
|
height: 100%; |
||||
|
|
||||
|
&>.ant-card-body { |
||||
|
overflow: auto; |
||||
|
height: calc(100% - 60px); |
||||
|
padding: 0 |
||||
|
} |
||||
|
|
||||
|
&>.ant-card-head { |
||||
|
position: relative; |
||||
|
z-index: 10; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */ |
||||
|
{ |
||||
|
"extends": "../../tsconfig.json", |
||||
|
"compilerOptions": { |
||||
|
"outDir": "../../out-tsc/app", |
||||
|
"types": [] |
||||
|
}, |
||||
|
"files": [ |
||||
|
"src/main.ts" |
||||
|
], |
||||
|
"include": [ |
||||
|
"src/**/*.d.ts" |
||||
|
] |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */ |
||||
|
{ |
||||
|
"extends": "../../tsconfig.json", |
||||
|
"compilerOptions": { |
||||
|
"outDir": "../../out-tsc/spec", |
||||
|
"types": [ |
||||
|
"jasmine" |
||||
|
] |
||||
|
}, |
||||
|
"include": [ |
||||
|
"src/**/*.spec.ts", |
||||
|
"src/**/*.d.ts" |
||||
|
] |
||||
|
} |
||||
Loading…
Reference in new issue