diff --git a/angular.json b/angular.json index deb0b41..76ab956 100644 --- a/angular.json +++ b/angular.json @@ -72,7 +72,8 @@ "browserTarget": "admin:build:production" }, "development": { - "browserTarget": "admin:build:development" + "browserTarget": "admin:build:development", + "port": 4200 } }, "defaultConfiguration": "development" @@ -125,6 +126,97 @@ } } } + }, + "client": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "less" + } + }, + "root": "projects/client", + "sourceRoot": "projects/client/src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/client", + "index": "projects/client/src/index.html", + "main": "projects/client/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "projects/client/tsconfig.app.json", + "inlineStyleLanguage": "less", + "assets": [ + "projects/client/src/favicon.ico", + "projects/client/src/assets", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + } + ], + "styles": ["projects/client/src/styles.less"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "client:build:production" + }, + "development": { + "browserTarget": "client:build:development", + "port": 4201 + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "client:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": ["zone.js", "zone.js/testing"], + "tsConfig": "projects/client/tsconfig.spec.json", + "inlineStyleLanguage": "less", + "assets": ["projects/client/src/favicon.ico", "projects/client/src/assets"], + "styles": ["projects/client/src/styles.less"], + "scripts": [] + } + } + } } } } diff --git a/doc/basic.md b/doc/basic.md new file mode 100644 index 0000000..db4dec9 --- /dev/null +++ b/doc/basic.md @@ -0,0 +1,182 @@ +# 基础部分 + +# 1. 登录 + +> GET /user/login?uid=xxx&pwd=BE56E057F20F883E +> MD5加密后大写取后16位,示例原密码为123456 + +### 输出: +``` +{ + "body": { + "roleName": "超级管理员", + "uid": "xxx", + "admin": false, // 是否管理端,true-是管理端, false-业务端 + "name": "业务端测试账号", + "phone": "13919103409", + "roleId": 2, + "roleItems": [ + { + "category": "基础权限", + "id": 18, + "itemName": "使用流程", + "itemType": "业务端" + } + ], + "vender": { + "account": "13919103408", + "address": "百仁路", + "contacts": "曹先生", + "expire": 1693651185000, + "icon": "data:image/jpeg;base64,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", + "id": 1, // 单位编号,后续操作都需要这个单位编号 + "name": "成都实验小学", + "phone": "13919103408", + "status": true + } + }, + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 2. 登出 + +> GET /user/logout + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 3. 修改自己的账号 + +> POST /api/basic/user + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +name=曹 // 修改姓名 +password=BE56E057F20F883E // 修改密码 +``` + +### 输出: +``` +{ +"code": 200, +"desc": "成功", +"success": true +} +``` + +# 4. 获取所有枚举信息 + +> GET /api/basic/enum + +### 输出: +``` +{ + "body": { + "nutrient": [ + { + "key": "vitamin-a", + "measurement": "μgRAE", + "nrv": 1.10, + "value": "维生素A" + }, + { + "key": "calcium", + "measurement": "mg", + "nrv": 2.20, + "value": "钙" + }, + { + "key": "protein", + "measurement": "g", + "nrv": 3.30, + "value": "蛋白质" + }, + { + "key": "energy", + "measurement": "kcal", + "nrv": 5.00, + "value": "能量" + }, + { + "key": "fat", + "measurement": "g", + "nrv": 8.80, + "value": "脂肪" + } + ], + "category": [ + { + "key": "谷薯类", + "value": "谷薯类" + }, + { + "key": "大豆类及其制品", + "value": "大豆类及其制品" + }, + { + "key": "蔬菜类", + "value": "蔬菜类" + }, + { + "key": "水果类", + "value": "水果类" + }, + { + "key": "坚果", + "value": "坚果" + }, + { + "key": "畜禽肉类", + "value": "畜禽肉类" + }, + { + "key": "奶及奶制品", + "value": "奶及奶制品" + }, + { + "key": "蛋类", + "value": "蛋类" + }, + { + "key": "鱼虾类", + "value": "鱼虾类" + }, + { + "key": "婴幼儿食品", + "value": "婴幼儿食品" + } + ], + "mark": [ + { + "key": "汤类", + "value": "汤类" + }, + { + "key": "主食", + "value": "主食" + }, + { + "key": "主荤", + "value": "主荤" + }, + { + "key": "次荤", + "value": "次荤" + } + ] + }, + "code": 200, + "desc": "成功", + "success": true +} +``` \ No newline at end of file diff --git a/doc/change.md b/doc/change.md new file mode 100644 index 0000000..0756f7d --- /dev/null +++ b/doc/change.md @@ -0,0 +1,15 @@ +# 修改记录 + +> 9.10 +``` +基础协议 +用户协议 +角色协议 +单位协议 +``` + +> 9.11 +``` +食材 +菜品 +食谱 diff --git a/doc/index.md b/doc/index.md new file mode 100644 index 0000000..9c04ae5 --- /dev/null +++ b/doc/index.md @@ -0,0 +1,42 @@ +# 协议约定 +>协议格式: restfull + json + utf-8 + +>协议格式中,凡是用 * 标识字段均为必须字段,否则为可选字段。 + +>密码:协议中涉及password字段全部使用16位的MD5加密传输(MD5加密后取后16位,大写) + +### 协议列表 +``` +* [协议约定](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, "操作失败!"); + +``` diff --git a/projects/admin/src/app/shared/components/index.ts b/doc/readme.md similarity index 100% rename from projects/admin/src/app/shared/components/index.ts rename to doc/readme.md diff --git a/doc/user.md b/doc/user.md new file mode 100644 index 0000000..4eb2bc8 --- /dev/null +++ b/doc/user.md @@ -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 +} +``` \ No newline at end of file diff --git a/doc/vender.md b/doc/vender.md new file mode 100644 index 0000000..db68537 --- /dev/null +++ b/doc/vender.md @@ -0,0 +1,180 @@ +# 单位部分 + +# 1. 检验账号重复性 + +> GET /api/vender/check/account?account=xxx + +### 输出: +``` +{ + "body": false, // true未被占用,可用 + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 2. 检查单位名称重复性 + +> GET /api/vender/check/name?name=xxx + +### 输出: +``` +{ + "body": false, // true未被占用,可用 + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 3. 查询单位配置 + +> GET /api/vender/config + +### 输出: +``` +{ + "body": { + "breakfast": 10.00, + "dinner": 10.00, + "lunch": 10.00 + }, + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 4. 修改单位配置 + +> POST /api/vender/config + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +vender=1 // 必填 +breakfast=10.00 // 必填 +dinner=10 // 必填 +lunch=10 // 必填 +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 5. 添加企业 + +> PUT /api/vender +> +> 管理端接口 +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +account=ccc // 必填, 初始管理员账号, 不能重复 +password=BE56E057F20F883E // 必填, MD5加密后大写取后16位,示例原密码为123456 +name=曹 // 必填, 单位名称 +expire=2019-10-10 // 必填, 过期时间 +icon=23423 //单位logo, 前端可用的base64字符串 +address= +contacts= +phone= +email= +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 6. 删除企业 + +> DELETE /api/vender +> +> 管理端接口 +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +vender=1 // 必填 +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 7. 修改企业 + +> POST /api/vender +> +> 续费和开关仅管理端,其他管理端或者业务端主账号操作 + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +expire=2019-10-10 // 仅管理端可以改过期时间 +status=false // 仅管理端可以改状态, false-关闭,true-打开 + +account=ccc // 改绑定的主账户, 将自动为改账户赋管理员权限, 不能重复 +name=曹 // 改单位名称 +icon=23423 //单位logo, 前端可用的base64字符串, 最大好像就几十KB吧,不能太大 +address= +contacts= +phone= +email= +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + + +# 8. 获取企业列表 + +> GET /api/vender +> +> 管理端接口 + +### 输出: +``` +{ + "body": [ + { + "account": "xxx", + "address": "百仁路", + "area": "青羊区", + "category": "小学", + "city": "成都市", + "contacts": "曹先生", + "expire": 1695033585000, + "icon": "data:image/jpeg;base64,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", + "id": 1, + "name": "成都实验小学", + "phone": "13919103408", + "province": "四川省", + "status": true + } + ], + "code": 200, + "desc": "成功", + "success": true +} +``` \ No newline at end of file diff --git a/package.json b/package.json index 60f30f0..a2d9663 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,10 @@ "version": "0.0.0", "scripts": { "ng": "ng", - "start": "ng serve", - "build": "ng build", + "start:admin": "ng serve admin", + "start:client": "ng serve client", + "build:admin": "ng build admin", + "build:client": "ng build client", "watch": "ng build --watch --configuration development", "test": "ng test" }, diff --git a/projects/admin/src/app/app.module.ts b/projects/admin/src/app/app.module.ts index 750fa44..3be3e7d 100644 --- a/projects/admin/src/app/app.module.ts +++ b/projects/admin/src/app/app.module.ts @@ -10,12 +10,9 @@ 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 { IconsProviderModule } from "./icons-provider.module"; -import { SharedModule } from "./shared/shared.module"; import { AppLayoutComponent, - AppPageComponent, FoodFormComponent, DishFormComponent, IngredientFormBasicComponent, @@ -39,6 +36,9 @@ import { StandardSettingComponent, } from "./pages"; import { HTTPInterceptor } from "./services/http.interceptor"; +import { IconsProviderModule } from "@cdk/public-api"; +import { SharedModule } from "@cdk/shared/shared.module"; +import { IngredientModule } from "@cdk/ingredient/ingredient.module"; registerLocaleData(zh); @@ -46,7 +46,6 @@ registerLocaleData(zh); declarations: [ AppComponent, AppLayoutComponent, - AppPageComponent, FoodFormComponent, DishFormComponent, IngredientFormBasicComponent, @@ -80,6 +79,7 @@ registerLocaleData(zh); BrowserAnimationsModule, IconsProviderModule, SharedModule, + IngredientModule, ], providers: [ { provide: NZ_I18N, useValue: zh_CN }, diff --git a/projects/admin/src/app/components/app-layout/app-layout.component.html b/projects/admin/src/app/components/app-layout/app-layout.component.html index f00263a..bcc85ba 100644 --- a/projects/admin/src/app/components/app-layout/app-layout.component.html +++ b/projects/admin/src/app/components/app-layout/app-layout.component.html @@ -1,18 +1,34 @@
- - -
    + + +
    • 食材管理 diff --git a/projects/admin/src/app/components/app-layout/app-layout.component.less b/projects/admin/src/app/components/app-layout/app-layout.component.less index 5aa4d22..75334d1 100644 --- a/projects/admin/src/app/components/app-layout/app-layout.component.less +++ b/projects/admin/src/app/components/app-layout/app-layout.component.less @@ -11,17 +11,19 @@ flex-direction: column; flex: 1; height: 100%; + } .app-header { position: fixed; top: 0; - left: 0; + left: 220px; right: 0; z-index: 100; height: @header-height; line-height: @header-height; padding: 0 24px; + background-color: #fff; } @@ -29,13 +31,19 @@ ::ng-deep { .anticon { font-size: 16px; + color: #fff; + + svg, + path { + fill: currentColor !important; + } } } } .sider-menu { position: fixed; - top: @header-height; + top: 0; left: 0; bottom: 0; z-index: 100; @@ -47,7 +55,7 @@ .inner-layout { padding-top: @header-height; - padding-left: 200px; + padding-left: 220px; ::ng-deep { router-outlet+* { diff --git a/projects/admin/src/app/components/app-layout/app-layout.component.ts b/projects/admin/src/app/components/app-layout/app-layout.component.ts index bb63ced..4c4de7b 100644 --- a/projects/admin/src/app/components/app-layout/app-layout.component.ts +++ b/projects/admin/src/app/components/app-layout/app-layout.component.ts @@ -1,5 +1,7 @@ import { Component } from "@angular/core"; -import { NavigationEnd, Router } from "@angular/router"; +import { NavigationEnd, Router, RouterModule } from "@angular/router"; + +import { NzModalService } from "ng-zorro-antd/modal"; import { Subject, filter, takeUntil } from "rxjs"; @Component({ @@ -8,7 +10,7 @@ import { Subject, filter, takeUntil } from "rxjs"; styleUrls: ["./app-layout.component.less"], }) export class AppLayoutComponent { - constructor(private router: Router) { + constructor(private router: Router, private modal: NzModalService) { this.router.events .pipe( takeUntil(this.unSubscribe$), @@ -22,4 +24,12 @@ export class AppLayoutComponent { unSubscribe$ = new Subject(); currentUrl: string = ""; + + logout() { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要退出登录?", + nzOnOk: () => {}, + }); + } } diff --git a/projects/admin/src/app/components/index.ts b/projects/admin/src/app/components/index.ts index 7396790..89e2ca5 100644 --- a/projects/admin/src/app/components/index.ts +++ b/projects/admin/src/app/components/index.ts @@ -1,5 +1,4 @@ export * from "./app-layout/app-layout.component"; -export * from "./app-page/app-page.component"; export * from "./food-form/food-form.component"; export * from "./dish-form/dish-form.component"; diff --git a/projects/admin/src/app/pages/dish/dish.component.html b/projects/admin/src/app/pages/dish/dish.component.html index 054278c..9d78596 100644 --- a/projects/admin/src/app/pages/dish/dish.component.html +++ b/projects/admin/src/app/pages/dish/dish.component.html @@ -2,7 +2,7 @@ - + - + + - @@ -53,6 +54,30 @@ + + + + + + 共10中营养素 + + +
      + + 能量{{item}}:10kcal + +
      +
      +
      + + + {{data}} + + +
      +
@@ -61,6 +86,31 @@ + +

+ 提示:下载示例模版,进行编辑,导入Excel文件,批量导入食材 +

+
+
+ +
+

+ +

+

+ 点击或将文件拖拽到这里上传 +

+

+ 支持扩展名:.xls .xlsx +

+
+
+
+
+ diff --git a/projects/admin/src/app/pages/food/food.component.ts b/projects/admin/src/app/pages/food/food.component.ts index 0a82242..03bd907 100644 --- a/projects/admin/src/app/pages/food/food.component.ts +++ b/projects/admin/src/app/pages/food/food.component.ts @@ -1,30 +1,48 @@ import { FoodFormComponent } from "@admin/app/components"; import { ApiService } from "@admin/app/services"; -import { Component, OnInit, TemplateRef, ViewChild } from "@angular/core"; +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"; @Component({ selector: "app-food", templateUrl: "./food.component.html", styleUrls: ["./food.component.less"], }) -export class FoodComponent implements OnInit { - constructor(private drawer: NzDrawerService, private api: ApiService) {} +export class FoodComponent implements OnInit, OnDestroy { + constructor(private drawer: NzDrawerService, private api: ApiService, private modal: NzModalService) {} @ViewChild("foofFormFooterTpl") foofFormFooterTpl!: TemplateRef<{}>; private drawerRef?: NzDrawerRef; - public tableList = new TableListOption(this.fetchData.bind(this)); + public tableList = new TableListOption(this.fetchData.bind(this), { + selectable: true, + }); public queryForm = new FormGroup({ name: new FormControl(""), }); + private destroy$ = new Subject(); + + 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; + }); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); } initTableList() { @@ -33,7 +51,7 @@ export class FoodComponent implements OnInit { { key: "name", title: "食材编号" }, { key: "name", title: "食材名称" }, { key: "name", title: "食材类型" }, - { key: "name", title: "营养素(每100g可食部)", width: "50%" }, + { key: "name1", title: "营养素(每100g可食部)" }, { key: "name", title: "更新日期" }, ]); @@ -46,7 +64,7 @@ export class FoodComponent implements OnInit { { title: "删除", premissions: [], - onClick: this.deleteItem.bind(this), + onClick: this.deleteFood.bind(this), }, ]); } @@ -68,5 +86,38 @@ export class FoodComponent implements OnInit { this.drawerRef?.close(); } - deleteItem() {} + deleteFood(v?: any) { + const ids = v ? [v.id] : this.selectedIds; + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该食材?", + nzOkDanger: true, + nzOnOk: () => {}, + }); + } + + showImportForm(nzContent: TemplateRef<{}>) { + this.modal.create({ + nzTitle: "导入食材清单", + nzWidth: 520, + nzContent, + }); + } + + suppress(e: Event) { + e.stopPropagation(); + e.preventDefault(); + } + + handleDrop = (e: Event) => { + e.stopPropagation(); + e.preventDefault(); + const event = e as DragEvent; + const files = event.dataTransfer?.files; + if (files) { + this.onFileChange(files); + } + }; + + onFileChange(e: Event | FileList | null) {} } diff --git a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html index 6282642..50bce09 100644 --- a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html +++ b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.html @@ -28,7 +28,7 @@ - + + 第{{i}}天 + + + + + + + + + @@ -47,233 +72,11 @@ -
- - - - - 菜品 - - - 食材 - - - 轻体力(体重过低) - - - 轻体力(正常体重) - - - 休息(超重/肥胖) - - - 轻体力(体重过低) - - - 轻体力(正常体重) - - - - - - -
- - 番茄煎蛋面 - - -
- - - -
- - 番茄 - - -
- - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - - -
- - 面条 - - -
- - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - -
- - 鸡蛋青菜面 - - -
- - -
- - 食用油 - - -
- - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - -
- - 小白菜[青菜] - - -
- - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - -
- - 鸡蛋(均值) - - -
- - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - - - -
- - 面条(均值) - - -
- - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - -
+
+
- - - - - - +
\ No newline at end of file diff --git a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.less b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.less index e69de29..7d41880 100644 --- a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.less +++ b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.less @@ -0,0 +1,7 @@ +.day-item { + ::ng-deep { + .ant-card-head-title { + overflow: visible; + } + } +} \ No newline at end of file diff --git a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts index 4d3e276..06cdaf2 100644 --- a/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts +++ b/projects/admin/src/app/pages/ingredients/ingredient-form/ingredient-form.component.ts @@ -1,5 +1,6 @@ import { IngredientFormBasicComponent } from "@admin/app/components"; import { Component, OnInit } from "@angular/core"; +import { ConfirmIngredientComponent } from "@cdk/ingredient/confirm-ingredient/confirm-ingredient.component"; import { NzModalService } from "ng-zorro-antd/modal"; @Component({ @@ -12,6 +13,10 @@ export class IngredientFormComponent implements OnInit { step = 1; + expanded = new Set(); + + ingredients = Array.from({ length: 7 }, (_, i) => 1 + i); + ngOnInit(): void {} onStepChange() { @@ -19,7 +24,23 @@ export class IngredientFormComponent implements OnInit { console.log(456); } - showForm(food?: any) {} + shopDishForm() {} cancelForm() {} + + expandChange(i: number) { + if (this.expanded.has(i)) { + this.expanded.delete(i); + } else { + this.expanded.add(i); + } + } + + confirmSave() { + this.modal.create({ + nzTitle: "确认食谱信息", + nzContent: ConfirmIngredientComponent, + nzWidth: 650, + }); + } } diff --git a/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.html b/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.html index fa0bf8b..b40215a 100644 --- a/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.html +++ b/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.html @@ -1,15 +1,21 @@ - - - - - -
- - + + + + + + + + +
+ + + + + @@ -17,25 +23,23 @@ - + - + - - + - + + - + + + {{data}} @@ -44,18 +48,7 @@ - -
- - +
+ - - - - - - \ No newline at end of file +
\ No newline at end of file diff --git a/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.ts b/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.ts index 177cc13..2e8c3ea 100644 --- a/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.ts +++ b/projects/admin/src/app/pages/ingredients/ingredient-review/ingredient-review.component.ts @@ -4,6 +4,7 @@ import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; import { AnyObject, TableListOption } from "@cdk/public-api"; import { DishFormComponent } from "@admin/app/components"; import { ApiService } from "@admin/app/services"; +import { ActivatedRoute, Router } from "@angular/router"; @Component({ selector: "app-ingredient-review", @@ -11,12 +12,19 @@ import { ApiService } from "@admin/app/services"; styleUrls: ["./ingredient-review.component.less"], }) export class IngredientReviewComponent { - constructor(private drawer: NzDrawerService, private api: ApiService) {} + constructor( + private drawer: NzDrawerService, + private router: Router, + private route: ActivatedRoute, + private api: ApiService + ) {} @ViewChild("foofFormFooterTpl") foofFormFooterTpl!: TemplateRef<{}>; private drawerRef?: NzDrawerRef; + status = 0; + tempImg = "https://cdn.pixabay.com/photo/2023/08/08/18/01/butterfly-8177925_1280.jpg"; public tableList = new TableListOption(this.fetchData.bind(this), { @@ -28,6 +36,7 @@ export class IngredientReviewComponent { }); ngOnInit(): void { + this.status = Number(this.route.snapshot.queryParamMap.get("status")) || 0; this.initTableList(); } @@ -78,4 +87,14 @@ export class IngredientReviewComponent { } deleteItem() {} + + onStatusChange(index: number) { + this.status = index; + this.router.navigate(["/ingredient/review"], { + queryParams: { + status: index, + }, + queryParamsHandling: "merge", + }); + } } diff --git a/projects/admin/src/styles.less b/projects/admin/src/styles.less index a18a81e..81f114b 100644 --- a/projects/admin/src/styles.less +++ b/projects/admin/src/styles.less @@ -38,6 +38,42 @@ li { } } +.dropUpload { + position: relative; + padding: 36px 0; + text-align: center; + font-size: 24px; + color: rgba(0, 0, 0, 0.35); + border: 1px dashed #e8e8e8; + border-radius: 4px; + background-color: #fafafa; + cursor: pointer; +} + + +.upload-area { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 160px; + border: 1px dashed #e8e8e8; + border-radius: 10px; + + input { + width: 100%; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0; + z-index: 2; + cursor: pointer; + } +} + .fixed-footter { box-shadow: 0 0 10px -2px rgba(0, 0, 0, .25) } diff --git a/projects/admin/src/app/components/app-page/app-page.component.html b/projects/cdk/src/app-page/app-page.component.html similarity index 100% rename from projects/admin/src/app/components/app-page/app-page.component.html rename to projects/cdk/src/app-page/app-page.component.html diff --git a/projects/admin/src/app/components/app-page/app-page.component.less b/projects/cdk/src/app-page/app-page.component.less similarity index 100% rename from projects/admin/src/app/components/app-page/app-page.component.less rename to projects/cdk/src/app-page/app-page.component.less diff --git a/projects/admin/src/app/components/app-page/app-page.component.ts b/projects/cdk/src/app-page/app-page.component.ts similarity index 89% rename from projects/admin/src/app/components/app-page/app-page.component.ts rename to projects/cdk/src/app-page/app-page.component.ts index 56dc17e..2a21573 100644 --- a/projects/admin/src/app/components/app-page/app-page.component.ts +++ b/projects/cdk/src/app-page/app-page.component.ts @@ -1,6 +1,8 @@ +import { CommonModule } from "@angular/common"; import { Component, Input, OnDestroy, TemplateRef } from "@angular/core"; import { ActivatedRoute, NavigationEnd, Router, Scroll } from "@angular/router"; import { Subject, filter, startWith, take, takeUntil } from "rxjs"; +import { NzOutletModule } from "ng-zorro-antd/core/outlet"; interface BreadcrumbInterface { label: string; @@ -8,9 +10,11 @@ interface BreadcrumbInterface { } @Component({ + standalone: true, selector: "app-page", templateUrl: "./app-page.component.html", styleUrls: ["./app-page.component.less"], + imports: [CommonModule, NzOutletModule], }) export class AppPageComponent implements OnDestroy { constructor(private route: ActivatedRoute, private router: Router) { diff --git a/projects/admin/src/app/icons-provider.module.ts b/projects/cdk/src/icons/icons-provider.module.ts similarity index 100% rename from projects/admin/src/app/icons-provider.module.ts rename to projects/cdk/src/icons/icons-provider.module.ts diff --git a/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.html b/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.html new file mode 100644 index 0000000..6a7bf0f --- /dev/null +++ b/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.html @@ -0,0 +1,127 @@ +
+
+
+ + 菜品名称 + + + + +
+
+ + 菜品标签 + + + + +
+
+ + + 食材搜索方式 + + + + + + + +
+ + + + + 食材 + + + 是否主料 + + + 轻体力1 + + + 轻体力2 + + + 操作 + + + + + + + 味精 + + + + + + + + + + + + + + + + + + + + 味精 + + + + + + + + + + + + + + + + + + + + 味精 + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.less b/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.ts b/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.ts new file mode 100644 index 0000000..bac1a93 --- /dev/null +++ b/projects/cdk/src/ingredient/add-dish-to-ingredient/add-dish-to-ingredient.component.ts @@ -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 {} diff --git a/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.html b/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.html new file mode 100644 index 0000000..93ff90d --- /dev/null +++ b/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.html @@ -0,0 +1,53 @@ +
+ + + 天数 + + + 7天 + + + + + 餐次 + + + + 早餐 + 午餐 + 晚餐 + + + + + + 食谱名称 + + + + + + + + 适用月份 + + +
+ +
+ + + +
+
+
\ No newline at end of file diff --git a/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.less b/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.less new file mode 100644 index 0000000..ef91c37 --- /dev/null +++ b/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.less @@ -0,0 +1,8 @@ +.month-wrap { + ::ng-deep { + .ant-checkbox-wrapper { + margin: 6px 0; + flex-basis: calc(100% / 4); + } + } +} \ No newline at end of file diff --git a/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.ts b/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.ts new file mode 100644 index 0000000..caafbd3 --- /dev/null +++ b/projects/cdk/src/ingredient/confirm-ingredient/confirm-ingredient.component.ts @@ -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; + } + } +} diff --git a/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html b/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html new file mode 100644 index 0000000..11eb0eb --- /dev/null +++ b/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.html @@ -0,0 +1,252 @@ +
+
+ + + + +
+ + + + + + + 重量/克 + + + + + + + 菜品 + + + 食材 + + + 轻体力(体重过低) + + + 轻体力(正常体重) + + + 休息(超重/肥胖) + + + 轻体力(体重过低) + + + 轻体力(正常体重) + + + + + + + +
+ + 番茄煎蛋面 + + + +
    +
  • 编辑
  • +
  • 删除
  • +
+
+
+ + + +
+ + 番茄 + + + +
    +
  • 设置价格
  • +
  • 删除
  • +
+
+
+ + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + +
+ + 面条 + + +
+ + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + +
+ + 鸡蛋青菜面 + + +
+ + +
+ + 食用油 + + +
+ + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + +
+ + 小白菜[青菜] + + +
+ + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + +
+ + 鸡蛋(均值) + + +
+ + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + +
+ + 面条(均值) + + +
+ + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + +
+
\ No newline at end of file diff --git a/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.less b/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.ts b/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.ts new file mode 100644 index 0000000..d862389 --- /dev/null +++ b/projects/cdk/src/ingredient/ingredient-meals/ingredient-meals.component.ts @@ -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, + }); + } +} diff --git a/projects/cdk/src/ingredient/ingredient.module.ts b/projects/cdk/src/ingredient/ingredient.module.ts new file mode 100644 index 0000000..8b79912 --- /dev/null +++ b/projects/cdk/src/ingredient/ingredient.module.ts @@ -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 {} diff --git a/projects/cdk/src/public-api.ts b/projects/cdk/src/public-api.ts index dd37eba..7c81b53 100644 --- a/projects/cdk/src/public-api.ts +++ b/projects/cdk/src/public-api.ts @@ -12,3 +12,5 @@ export * from "./input-space-error/input-space-error.directive"; // export * from "./quick-date-range/quick-date-range.component"; export * from "./table-list"; export * from "./storage"; + +export * from "./icons/icons-provider.module"; diff --git a/projects/cdk/src/shared/components/index.ts b/projects/cdk/src/shared/components/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/projects/admin/src/app/shared/ng-zorro.ts b/projects/cdk/src/shared/ng-zorro.ts similarity index 100% rename from projects/admin/src/app/shared/ng-zorro.ts rename to projects/cdk/src/shared/ng-zorro.ts diff --git a/projects/admin/src/app/shared/shared.module.ts b/projects/cdk/src/shared/shared.module.ts similarity index 87% rename from projects/admin/src/app/shared/shared.module.ts rename to projects/cdk/src/shared/shared.module.ts index 206a9a7..9523e08 100644 --- a/projects/admin/src/app/shared/shared.module.ts +++ b/projects/cdk/src/shared/shared.module.ts @@ -19,6 +19,7 @@ import { } from "@cdk/public-api"; // import { environment } from "@manage/environments/environment"; import { NgxPermissionsModule } from "ngx-permissions"; +import { AppPageComponent } from "@cdk/app-page/app-page.component"; const ngModules = [CommonModule, HttpClientModule, FormsModule, RouterModule, ReactiveFormsModule]; const components: any = []; @@ -35,7 +36,7 @@ const cdks = [ @NgModule({ declarations: [...components, ...directives], - imports: [...ngZorroModules, ...ngModules, ...cdks], - exports: [...ngZorroModules, ...ngModules, ...components, ...directives, ...cdks], + imports: [...ngZorroModules, ...ngModules, ...cdks, AppPageComponent], + exports: [...ngZorroModules, ...ngModules, ...components, ...directives, ...cdks, AppPageComponent], }) export class SharedModule {} diff --git a/projects/cdk/src/table-list/table-list-options.ts b/projects/cdk/src/table-list/table-list-options.ts index 491cd60..8314333 100644 --- a/projects/cdk/src/table-list/table-list-options.ts +++ b/projects/cdk/src/table-list/table-list-options.ts @@ -19,7 +19,7 @@ type ITableListConfig = { }; type TableListState = { - selectedKeys: number[]; + selectedKeys: (number | string)[]; }; type TableListPager = { diff --git a/projects/cdk/src/table-list/table-list/table-list.component.html b/projects/cdk/src/table-list/table-list/table-list.component.html index be6f515..aadc4d5 100644 --- a/projects/cdk/src/table-list/table-list/table-list.component.html +++ b/projects/cdk/src/table-list/table-list/table-list.component.html @@ -1,15 +1,15 @@
-
+
- - + + +
- + diff --git a/projects/cdk/src/table-list/table-list/table-list.component.ts b/projects/cdk/src/table-list/table-list/table-list.component.ts index b11014c..7b5f2b8 100644 --- a/projects/cdk/src/table-list/table-list/table-list.component.ts +++ b/projects/cdk/src/table-list/table-list/table-list.component.ts @@ -124,12 +124,14 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD } ngOnInit(): void { + console.log("this.formGroup", this.formGroup); this.props.trigger$.pipe(debounceTime(100)).subscribe((e?: any) => { if (this.props.fetchData) { this.props.pager.loading = true; this.selection.clear(); this.emitState(); const query = this.formGroup.getRawValue(); + console.log("query", query); // this.saveQueryDataToCache(query); const pager = this.parsePager(); this.props @@ -212,6 +214,7 @@ export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnD this.cache = this.cacheService.initCache(cacheKey, [this.router.url, ...cacheTo]); } const cacheData = this.cache?.getItem(); + if (cacheData) { const { page, size, sort, total, ...query } = cacheData; this.props.pager = { diff --git a/projects/client/src/app/app-routing.module.ts b/projects/client/src/app/app-routing.module.ts new file mode 100644 index 0000000..dbb4cf5 --- /dev/null +++ b/projects/client/src/app/app-routing.module.ts @@ -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 {} diff --git a/projects/client/src/app/app.component.html b/projects/client/src/app/app.component.html new file mode 100644 index 0000000..90c6b64 --- /dev/null +++ b/projects/client/src/app/app.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/client/src/app/app.component.less b/projects/client/src/app/app.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/app.component.spec.ts b/projects/client/src/app/app.component.spec.ts new file mode 100644 index 0000000..b69da71 --- /dev/null +++ b/projects/client/src/app/app.component.spec.ts @@ -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!'); + }); +}); diff --git a/projects/client/src/app/app.component.ts b/projects/client/src/app/app.component.ts new file mode 100644 index 0000000..c2c895d --- /dev/null +++ b/projects/client/src/app/app.component.ts @@ -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'; +} diff --git a/projects/client/src/app/app.module.ts b/projects/client/src/app/app.module.ts new file mode 100644 index 0000000..c63954f --- /dev/null +++ b/projects/client/src/app/app.module.ts @@ -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 {} diff --git a/projects/client/src/app/components/app-layout/app-layout.component.html b/projects/client/src/app/components/app-layout/app-layout.component.html new file mode 100644 index 0000000..24e3030 --- /dev/null +++ b/projects/client/src/app/components/app-layout/app-layout.component.html @@ -0,0 +1,73 @@ + + +
+ +
+ + +
    +
  • + 退出登录 +
  • +
+
+
+
+
+ + + +
    +
  • + + 使用流程 +
  • +
  • + + 大屏显示 +
  • +
  • + + 配餐设置 +
  • +
  • + + 食材管理 +
  • +
  • + + 菜品管理 +
  • + + +
  • +
      +
    • 食谱库
    • +
    • 食谱发布计划
    • +
    +
  • + +
  • +
      +
    • 用户管理
    • +
    +
  • +
+
+ + + +
+
\ No newline at end of file diff --git a/projects/client/src/app/components/app-layout/app-layout.component.less b/projects/client/src/app/components/app-layout/app-layout.component.less new file mode 100644 index 0000000..b3a0778 --- /dev/null +++ b/projects/client/src/app/components/app-layout/app-layout.component.less @@ -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%; + } + } +} \ No newline at end of file diff --git a/projects/client/src/app/components/app-layout/app-layout.component.ts b/projects/client/src/app/components/app-layout/app-layout.component.ts new file mode 100644 index 0000000..4c4de7b --- /dev/null +++ b/projects/client/src/app/components/app-layout/app-layout.component.ts @@ -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(); + + currentUrl: string = ""; + + logout() { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要退出登录?", + nzOnOk: () => {}, + }); + } +} diff --git a/projects/client/src/app/components/index.ts b/projects/client/src/app/components/index.ts new file mode 100644 index 0000000..2e8054e --- /dev/null +++ b/projects/client/src/app/components/index.ts @@ -0,0 +1 @@ +export * from "./app-layout/app-layout.component"; diff --git a/projects/client/src/app/pages/dashboard/dashboard.component.html b/projects/client/src/app/pages/dashboard/dashboard.component.html new file mode 100644 index 0000000..fca0c10 --- /dev/null +++ b/projects/client/src/app/pages/dashboard/dashboard.component.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/projects/client/src/app/pages/dashboard/dashboard.component.less b/projects/client/src/app/pages/dashboard/dashboard.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/pages/dashboard/dashboard.component.ts b/projects/client/src/app/pages/dashboard/dashboard.component.ts new file mode 100644 index 0000000..6dc2d56 --- /dev/null +++ b/projects/client/src/app/pages/dashboard/dashboard.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.less'] +}) +export class DashboardComponent { + +} diff --git a/projects/client/src/app/pages/data-vis/data-vis.component.html b/projects/client/src/app/pages/data-vis/data-vis.component.html new file mode 100644 index 0000000..edf50d8 --- /dev/null +++ b/projects/client/src/app/pages/data-vis/data-vis.component.html @@ -0,0 +1 @@ +

data-vis works!

diff --git a/projects/client/src/app/pages/data-vis/data-vis.component.less b/projects/client/src/app/pages/data-vis/data-vis.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/pages/data-vis/data-vis.component.ts b/projects/client/src/app/pages/data-vis/data-vis.component.ts new file mode 100644 index 0000000..8fc3e64 --- /dev/null +++ b/projects/client/src/app/pages/data-vis/data-vis.component.ts @@ -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 { + +} diff --git a/projects/client/src/app/pages/dish/dish.component.html b/projects/client/src/app/pages/dish/dish.component.html new file mode 100644 index 0000000..e498386 --- /dev/null +++ b/projects/client/src/app/pages/dish/dish.component.html @@ -0,0 +1,74 @@ + + +
+
+ + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + {{data}} + + +
+
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/projects/client/src/app/pages/dish/dish.component.less b/projects/client/src/app/pages/dish/dish.component.less new file mode 100644 index 0000000..0a79c6b --- /dev/null +++ b/projects/client/src/app/pages/dish/dish.component.less @@ -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; +} \ No newline at end of file diff --git a/projects/client/src/app/pages/dish/dish.component.ts b/projects/client/src/app/pages/dish/dish.component.ts new file mode 100644 index 0000000..f60c702 --- /dev/null +++ b/projects/client/src/app/pages/dish/dish.component.ts @@ -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(); + + 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; + }); + } + + 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, + // }); + } +} diff --git a/projects/client/src/app/pages/food/food.component.html b/projects/client/src/app/pages/food/food.component.html new file mode 100644 index 0000000..b4003a8 --- /dev/null +++ b/projects/client/src/app/pages/food/food.component.html @@ -0,0 +1,87 @@ + + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + 共10中营养素 + + +
+ + 能量{{item}}:10kcal + +
+
+
+ + + {{data}} + + +
+
+
+
+
+ +
+
+
\ No newline at end of file diff --git a/projects/client/src/app/pages/food/food.component.less b/projects/client/src/app/pages/food/food.component.less new file mode 100644 index 0000000..e4c7ef0 --- /dev/null +++ b/projects/client/src/app/pages/food/food.component.less @@ -0,0 +1,9 @@ +.food-type { + border-right: 1px solid #e8e8e8; + + ::ng-deep { + .ant-menu-inline { + border-right: none; + } + } +} \ No newline at end of file diff --git a/projects/client/src/app/pages/food/food.component.ts b/projects/client/src/app/pages/food/food.component.ts new file mode 100644 index 0000000..0436fae --- /dev/null +++ b/projects/client/src/app/pages/food/food.component.ts @@ -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(); + + 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; + }); + } + + 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: () => {}, + }); + } +} diff --git a/projects/client/src/app/pages/index.ts b/projects/client/src/app/pages/index.ts new file mode 100644 index 0000000..b3c36fd --- /dev/null +++ b/projects/client/src/app/pages/index.ts @@ -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"; diff --git a/projects/client/src/app/pages/login/login.component.html b/projects/client/src/app/pages/login/login.component.html new file mode 100644 index 0000000..aa204d7 --- /dev/null +++ b/projects/client/src/app/pages/login/login.component.html @@ -0,0 +1,65 @@ +
+ +
+ + +
+ +
+
\ No newline at end of file diff --git a/projects/client/src/app/pages/login/login.component.less b/projects/client/src/app/pages/login/login.component.less new file mode 100644 index 0000000..4aee99a --- /dev/null +++ b/projects/client/src/app/pages/login/login.component.less @@ -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; + } +} \ No newline at end of file diff --git a/projects/client/src/app/pages/login/login.component.ts b/projects/client/src/app/pages/login/login.component.ts new file mode 100644 index 0000000..f29b4fc --- /dev/null +++ b/projects/client/src/app/pages/login/login.component.ts @@ -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(["/"]); + } + } +} diff --git a/projects/client/src/app/pages/meal-setting/meal-setting.component.html b/projects/client/src/app/pages/meal-setting/meal-setting.component.html new file mode 100644 index 0000000..2f2c1a5 --- /dev/null +++ b/projects/client/src/app/pages/meal-setting/meal-setting.component.html @@ -0,0 +1,48 @@ + + +
+ + + 早餐能量、营养摄入比例 + + + + + + + + + + 午餐能量、营养摄入比例 + + + + + + + + + + 晚餐能量、营养摄入比例 + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/projects/client/src/app/pages/meal-setting/meal-setting.component.less b/projects/client/src/app/pages/meal-setting/meal-setting.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/pages/meal-setting/meal-setting.component.ts b/projects/client/src/app/pages/meal-setting/meal-setting.component.ts new file mode 100644 index 0000000..f0a16e8 --- /dev/null +++ b/projects/client/src/app/pages/meal-setting/meal-setting.component.ts @@ -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 { + +} diff --git a/projects/client/src/app/services/client-api.service.ts b/projects/client/src/app/services/client-api.service.ts new file mode 100644 index 0000000..c7516eb --- /dev/null +++ b/projects/client/src/app/services/client-api.service.ts @@ -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("/", v); + } + + page(v: {}, q: {}) { + return this.http.get("https://jsonplaceholder.typicode.com/users", v).pipe( + map((r) => { + return { + total: 10, + content: r, + }; + }) + ); + } +} diff --git a/projects/client/src/app/services/http.interceptor.ts b/projects/client/src/app/services/http.interceptor.ts new file mode 100644 index 0000000..82d9b50 --- /dev/null +++ b/projects/client/src/app/services/http.interceptor.ts @@ -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, next: HttpHandler): Observable> { + 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): Observable> { + 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; + }) + ); + } +} diff --git a/projects/client/src/app/services/index.ts b/projects/client/src/app/services/index.ts new file mode 100644 index 0000000..c393398 --- /dev/null +++ b/projects/client/src/app/services/index.ts @@ -0,0 +1 @@ +export * from "./client-api.service"; diff --git a/projects/client/src/assets/.gitkeep b/projects/client/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/assets/images/jl-logo.png b/projects/client/src/assets/images/jl-logo.png new file mode 100644 index 0000000..eb2c5d3 Binary files /dev/null and b/projects/client/src/assets/images/jl-logo.png differ diff --git a/projects/client/src/assets/images/login-bg.svg b/projects/client/src/assets/images/login-bg.svg new file mode 100644 index 0000000..977af7b --- /dev/null +++ b/projects/client/src/assets/images/login-bg.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/projects/client/src/assets/images/login.png b/projects/client/src/assets/images/login.png new file mode 100644 index 0000000..b2cb327 Binary files /dev/null and b/projects/client/src/assets/images/login.png differ diff --git a/projects/client/src/assets/k-icon/carrot.svg b/projects/client/src/assets/k-icon/carrot.svg new file mode 100644 index 0000000..e8e4a77 --- /dev/null +++ b/projects/client/src/assets/k-icon/carrot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/client/src/assets/k-icon/food.svg b/projects/client/src/assets/k-icon/food.svg new file mode 100644 index 0000000..9573982 --- /dev/null +++ b/projects/client/src/assets/k-icon/food.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/client/src/favicon.ico b/projects/client/src/favicon.ico new file mode 100644 index 0000000..997406a Binary files /dev/null and b/projects/client/src/favicon.ico differ diff --git a/projects/client/src/index.html b/projects/client/src/index.html new file mode 100644 index 0000000..4e14dac --- /dev/null +++ b/projects/client/src/index.html @@ -0,0 +1,16 @@ + + + + + + 智慧配餐系统 + + + + + + + + + + \ No newline at end of file diff --git a/projects/client/src/main.ts b/projects/client/src/main.ts new file mode 100644 index 0000000..c58dc05 --- /dev/null +++ b/projects/client/src/main.ts @@ -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)); diff --git a/projects/client/src/styles.less b/projects/client/src/styles.less new file mode 100644 index 0000000..a18a81e --- /dev/null +++ b/projects/client/src/styles.less @@ -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; + } + +} \ No newline at end of file diff --git a/projects/client/tsconfig.app.json b/projects/client/tsconfig.app.json new file mode 100644 index 0000000..e4e0762 --- /dev/null +++ b/projects/client/tsconfig.app.json @@ -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" + ] +} diff --git a/projects/client/tsconfig.spec.json b/projects/client/tsconfig.spec.json new file mode 100644 index 0000000..a9c0752 --- /dev/null +++ b/projects/client/tsconfig.spec.json @@ -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" + ] +}