From 4eee651d36cac1cf9ebb6c8a356c1e3ada0a7edf Mon Sep 17 00:00:00 2001 From: kkerwin Date: Sat, 16 Sep 2023 12:45:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E7=AB=AF=20=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/ingredient.md | 172 ++++++++++++++++++ .../organization-form.component.ts | 2 +- projects/cdk/src/dtos/user.dto.ts | 31 ++++ projects/client/src/app/app-routing.module.ts | 2 + projects/client/src/app/app.module.ts | 4 +- projects/client/src/app/components/index.ts | 1 + .../org-form/org-form.component.html | 69 +++++++ .../org-form/org-form.component.less | 0 .../components/org-form/org-form.component.ts | 88 +++++++++ .../meal-setting/meal-setting.component.html | 14 +- .../meal-setting/meal-setting.component.ts | 35 +++- .../system/org-info/org-info.component.html | 2 +- .../system/org-info/org-info.component.ts | 38 +++- .../client/src/app/services/auth.guard.ts | 17 ++ .../src/app/services/client-api.service.ts | 62 ++++++- 15 files changed, 509 insertions(+), 28 deletions(-) create mode 100644 doc/ingredient.md create mode 100644 projects/client/src/app/components/org-form/org-form.component.html create mode 100644 projects/client/src/app/components/org-form/org-form.component.less create mode 100644 projects/client/src/app/components/org-form/org-form.component.ts create mode 100644 projects/client/src/app/services/auth.guard.ts diff --git a/doc/ingredient.md b/doc/ingredient.md new file mode 100644 index 0000000..65250fc --- /dev/null +++ b/doc/ingredient.md @@ -0,0 +1,172 @@ + +# 食材部分 + +# 1. 查询食材 + +> GET /api/ingredient + +### 输入: +``` +pageSize=20 // 默认20, 全部非必填 +pageNo=0 // 默认0, 从0开始 +type=谷薯类 // 食材类型 +mark=常用 // 食材标记. 业务端用标记,管理端没用 +keyword=01 // 查询关键字 +``` + +### 输出: +``` +{ + "body": { + "content": [ + { + "key": "011101", + "mark": "常用", + "name": "小麦", + "nutrient": { + "fat": 10, + "energy": 10, + "calcium": 12, + "protein": 15, + "vitamin-a": 23 + }, + "time": 1693759354000, + "type": "谷薯类" + } + ], + "number": 0, + "size": 20, + "totalElements": 1, + "totalPages": 1 + }, + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 2. 添加食材(管理端接口) + +> PUT /api/ingredient + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +key=010101 // 必填 +name=测试食材 // 必填 +type=粗粮 // 必填 全部必填 取值范围见(/api/basic/enum) category +nutrient={"fat": 10, "energy": 10, "calcium": 12, "protein": 15, "vitamin-a": 23} +// 必填 取值范围见(/api/basic/enum) nutrient +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 3. 修改食材(管理端接口) + +> POST /api/ingredient + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +key=010101 // 必填 +name=测试食材 +type=粗粮 +nutrient={"fat": 10, "energy": 10, "calcium": 12, "protein": 15, "vitamin-a": 23} + +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` +# 4. 删除食材(管理端接口) + +> DELETE /api/ingredient + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +nutrients=010101,020202,030303 // 必填 + +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 5. 食材打标(业务端接口) + +> PUT /api/ingredient/mark + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +nutrient=010101 +mark=常用 // 必填, 取值: 常用/忌用 + +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 6. 取消打标(业务端接口) + +> DELETE /api/ingredient/mark + +### 输入: +``` +Content-Type:application/x-www-form-urlencoded +nutrient=010101 + +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` + +# 7. 批量导入(管理端接口) + +> PUT /api/ingredient/mark + +### 输入: +``` +Content-Type: multipart/form-data +files // 必传 + +``` + +### 输出: +``` +{ + "code": 200, + "desc": "成功", + "success": true +} +``` \ No newline at end of file diff --git a/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts b/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts index e20c2a9..512a6ed 100644 --- a/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts +++ b/projects/admin/src/app/pages/organization/organization-form/organization-form.component.ts @@ -49,7 +49,7 @@ export class OrganizationFormComponent { account: this.fb.control("", [FormValidators.required("账号不能为空")]), password: this.fb.control("", [FormValidators.required("密码不能为空")]), name: this.fb.control("", [FormValidators.required("单位名称不能为空")]), - expire: this.fb.control("", [FormValidators.required("账号到期事件不能为空")]), + expire: this.fb.control("", [FormValidators.required("账号到期时间不能为空")]), icon: this.fb.control("", []), address: this.fb.control("", []), contacts: this.fb.control("", []), diff --git a/projects/cdk/src/dtos/user.dto.ts b/projects/cdk/src/dtos/user.dto.ts index ad2b699..8c87369 100644 --- a/projects/cdk/src/dtos/user.dto.ts +++ b/projects/cdk/src/dtos/user.dto.ts @@ -21,3 +21,34 @@ export type UserDTO = { uid: string; time: string; }; + +export type OrgConfigDTO = { + breakfast: number; + dinner: number; + lunch: number; +}; + +export type ClientAccountDTO = { + name: string; + roleId: number; + roleItems: PermItemDTO[]; + roleName: string; + roleType: string; + time: number; + uid: string; + vender: AccountVenderDTO; +}; + +export type AccountVenderDTO = { + id: number; + name: string; + account: string; + status: true; + + address?: string; + contacts?: string; + email?: string; + expire?: number; + icon?: string; + phone?: string; +}; diff --git a/projects/client/src/app/app-routing.module.ts b/projects/client/src/app/app-routing.module.ts index 54a9177..75b11be 100644 --- a/projects/client/src/app/app-routing.module.ts +++ b/projects/client/src/app/app-routing.module.ts @@ -10,12 +10,14 @@ import { OrgInfoComponent, } from "./pages"; import { AppLayoutComponent } from "./components"; +import { authGuard } from "./services/auth.guard"; const routes: Routes = [ { path: "login", component: LoginComponent }, { path: "", component: AppLayoutComponent, + canActivate: [authGuard], children: [ { path: "", diff --git a/projects/client/src/app/app.module.ts b/projects/client/src/app/app.module.ts index 4d1de7f..b621148 100644 --- a/projects/client/src/app/app.module.ts +++ b/projects/client/src/app/app.module.ts @@ -11,9 +11,9 @@ 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 { AppLayoutComponent, OrgFormComponent } from "./components"; import { DashboardComponent, LoginComponent, @@ -31,6 +31,8 @@ registerLocaleData(zh); declarations: [ AppComponent, AppLayoutComponent, + OrgFormComponent, + DashboardComponent, LoginComponent, MealSettingComponent, diff --git a/projects/client/src/app/components/index.ts b/projects/client/src/app/components/index.ts index 2e8054e..c9116bf 100644 --- a/projects/client/src/app/components/index.ts +++ b/projects/client/src/app/components/index.ts @@ -1 +1,2 @@ export * from "./app-layout/app-layout.component"; +export * from "./org-form/org-form.component"; diff --git a/projects/client/src/app/components/org-form/org-form.component.html b/projects/client/src/app/components/org-form/org-form.component.html new file mode 100644 index 0000000..7dda7fb --- /dev/null +++ b/projects/client/src/app/components/org-form/org-form.component.html @@ -0,0 +1,69 @@ +
+ +
+ + + 单位名称 + + + + + + + + 单位Logo + + +
+ +
+ +
+
+ + + 地址 + + + + + + + + 联系人 + + + + + + + + 联系电话 + + + + + + + + 邮箱 + + + + + + +
+ + +
+ + + + + \ No newline at end of file diff --git a/projects/client/src/app/components/org-form/org-form.component.less b/projects/client/src/app/components/org-form/org-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/components/org-form/org-form.component.ts b/projects/client/src/app/components/org-form/org-form.component.ts new file mode 100644 index 0000000..3d4638d --- /dev/null +++ b/projects/client/src/app/components/org-form/org-form.component.ts @@ -0,0 +1,88 @@ +import { ApiService } from "@admin/app/services"; +import { Component, inject } from "@angular/core"; +import { FormBuilder, FormGroup } from "@angular/forms"; +import { Utils } from "@cdk/utils"; +import { FormValidators } from "@cdk/validators"; +import { MD5 } from "crypto-js"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { lastValueFrom } from "rxjs"; +import { format } from "date-fns"; +import { ActivatedRoute, Router } from "@angular/router"; +import { AnyObject } from "@cdk/types"; +import { NZ_MODAL_DATA } from "ng-zorro-antd/modal"; + +@Component({ + selector: "app-org-form", + templateUrl: "./org-form.component.html", + styleUrls: ["./org-form.component.less"], +}) +export class OrgFormComponent { + constructor( + private fb: FormBuilder, + private api: ApiService, + private msg: NzMessageService, + private router: Router + ) {} + + state = inject(NZ_MODAL_DATA); + + formGroup!: FormGroup; + + uploadLoading = false; + + get icon() { + return this.formGroup.get("icon")?.value; + } + + ngOnInit(): void { + console.log("this.state", this.state); + this.formGroup = this.fb.group({ + id: this.fb.control(""), + name: this.fb.control("", [FormValidators.required("单位名称不能为空")]), + icon: this.fb.control("", []), + address: this.fb.control("", []), + contacts: this.fb.control("", []), + phone: this.fb.control("", []), + email: this.fb.control("", []), + }); + this.formGroup.patchValue(this.state); + } + + async onSubmit() { + if (Utils.validateFormGroup(this.formGroup)) { + const org = { ...(this.state ?? {}), ...this.formGroup.value }; + org["password"] = MD5(org.password!).toString().substring(16).toUpperCase(); + org["expire"] = format(org["expire"], "yyyy-MM-dd"); + org["venderId"] = org.id; + // const account = await lastValueFrom(this.api.checkOrgAccount(org.account!)); + // const name = await lastValueFrom(this.api.checkOrgName(org.name!)); + + // if (!account.body) { + // this.msg.error("账号重复"); + // return; + // } + // if (!name.body) { + // this.msg.error("单位名称重复"); + // return; + // } + + const res = await lastValueFrom(this.api.saveOrg(org)); + this.msg.success(res.desc); + this.router.navigate(["/organization/list"]); + } + } + + onFileChange(e: Event) { + const target = e.target as HTMLInputElement; + const file = target.files![0]; + target.value = ""; + const fileReader = new FileReader(); + fileReader.onload = () => { + const base64 = fileReader.result as string; + this.formGroup.patchValue({ + icon: base64, + }); + }; + fileReader.readAsDataURL(file); + } +} 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 index 2f2c1a5..a93d99d 100644 --- a/projects/client/src/app/pages/meal-setting/meal-setting.component.html +++ b/projects/client/src/app/pages/meal-setting/meal-setting.component.html @@ -1,13 +1,13 @@ -
+ 早餐能量、营养摄入比例 - + @@ -17,7 +17,7 @@ - + @@ -27,19 +27,17 @@ - + - - + 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 index f0a16e8..63a2cfb 100644 --- a/projects/client/src/app/pages/meal-setting/meal-setting.component.ts +++ b/projects/client/src/app/pages/meal-setting/meal-setting.component.ts @@ -1,10 +1,35 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from "@angular/core"; +import { ClientApiService } from "../../services"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Utils } from "@cdk/utils"; @Component({ - selector: 'app-meal-setting', - templateUrl: './meal-setting.component.html', - styleUrls: ['./meal-setting.component.less'] + selector: "app-meal-setting", + templateUrl: "./meal-setting.component.html", + styleUrls: ["./meal-setting.component.less"], }) -export class MealSettingComponent { +export class MealSettingComponent implements OnInit { + constructor(private api: ClientApiService) {} + account = this.api.account; + + formGroup = new FormGroup({ + breakfast: new FormControl(0, []), + dinner: new FormControl(0, []), + lunch: new FormControl(0, []), + }); + + ngOnInit(): void { + this.api.getOrgConfig().subscribe((res) => { + this.formGroup.patchValue(res.body); + }); + } + + onSubmit() { + if (Utils.validateFormGroup(this.formGroup)) { + this.api.saveOrgConfig({ ...this.formGroup.value, vender: this.account.vender.id }).subscribe((res) => { + // this.formGroup. + }); + } + } } diff --git a/projects/client/src/app/pages/system/org-info/org-info.component.html b/projects/client/src/app/pages/system/org-info/org-info.component.html index f633fba..f24fa53 100644 --- a/projects/client/src/app/pages/system/org-info/org-info.component.html +++ b/projects/client/src/app/pages/system/org-info/org-info.component.html @@ -5,7 +5,7 @@ 单位基础信息 - + 编辑 diff --git a/projects/client/src/app/pages/system/org-info/org-info.component.ts b/projects/client/src/app/pages/system/org-info/org-info.component.ts index e63b45d..0a4aaa3 100644 --- a/projects/client/src/app/pages/system/org-info/org-info.component.ts +++ b/projects/client/src/app/pages/system/org-info/org-info.component.ts @@ -6,6 +6,9 @@ import { FormControl, FormGroup } from "@angular/forms"; import { FormValidators } from "@cdk/validators"; import { Utils } from "@cdk/utils"; import { NzMessageService } from "ng-zorro-antd/message"; +import { OrgFormComponent } from "../../../components"; +import { lastValueFrom } from "rxjs"; +import { MD5 } from "crypto-js"; @Component({ selector: "app-org-info", @@ -15,7 +18,7 @@ import { NzMessageService } from "ng-zorro-antd/message"; export class OrgInfoComponent implements OnInit { constructor(private api: ClientApiService, private modal: NzModalService, private msg: NzMessageService) {} - account: any = null; + account: any = this.api.account; pwdForm = new FormGroup({ oldPwd: new FormControl("", [FormValidators.required("请输入原密码")]), @@ -23,14 +26,7 @@ export class OrgInfoComponent implements OnInit { rePwd: new FormControl("", [FormValidators.required("请再次输入新密码")]), }); - ngOnInit(): void { - try { - const strageAccount = localStorage.getItem(this.api.accountKey); - if (strageAccount) { - this.account = JSON.parse(strageAccount); - } - } catch (error) {} - } + ngOnInit(): void {} updateAccount(type: string | number, nzContent: TemplateRef<{}>) { const nzTitle = @@ -44,6 +40,22 @@ export class OrgInfoComponent implements OnInit { }); } + updateOrg() { + this.modal.create({ + nzTitle: "修改单位基础信息", + nzContent: OrgFormComponent, + nzData: this.account.vender, + nzOnOk: async (e) => { + if (Utils.validateFormGroup(e.formGroup)) { + const res = await lastValueFrom(this.api.saveOrg({ ...e.formGroup.value, venderId: this.account.vender.id })); + this.msg.success(res.desc); + return true; + } + return false; + }, + }); + } + cancelPwdForm() { this.pwdForm.reset(); } @@ -59,6 +71,14 @@ export class OrgInfoComponent implements OnInit { this.msg.error("两次密码输入不一致"); return false; } + const res = await lastValueFrom( + this.api.updatePassword({ + password: MD5(value.newPwd!).toString().slice(-16), + // name: + }) + ); + this.msg.success(res.desc); + return true; } return false; }, diff --git a/projects/client/src/app/services/auth.guard.ts b/projects/client/src/app/services/auth.guard.ts new file mode 100644 index 0000000..c1c9c38 --- /dev/null +++ b/projects/client/src/app/services/auth.guard.ts @@ -0,0 +1,17 @@ +import { inject } from "@angular/core"; +import { Router } from "@angular/router"; +import { map } from "rxjs"; +import { ClientApiService } from "./client-api.service"; + +export const authGuard = () => { + const router = inject(Router); + const api = inject(ClientApiService); + const stragedAccount = localStorage.getItem(api.accountKey); + + if (!stragedAccount) { + router.navigate(["/login"]); + return false; + } + + return api.getAllEnum(); +}; diff --git a/projects/client/src/app/services/client-api.service.ts b/projects/client/src/app/services/client-api.service.ts index 6dbf04f..83c3c79 100644 --- a/projects/client/src/app/services/client-api.service.ts +++ b/projects/client/src/app/services/client-api.service.ts @@ -1,16 +1,39 @@ import { HttpClient, HttpParams } from "@angular/common/http"; import { Injectable } from "@angular/core"; -import { Utils, AnyObject, ResponseType, UserRoleDTO, PermItemDTO, UserDTO } from "@cdk/public-api"; -import { map } from "rxjs"; +import { + Utils, + AnyObject, + ResponseType, + UserRoleDTO, + PermItemDTO, + UserDTO, + GlobalEnum, + OrgConfigDTO, + ClientAccountDTO, +} from "@cdk/public-api"; +import { Observable, map, of, tap } from "rxjs"; @Injectable({ providedIn: "root", }) export class ClientApiService { - constructor(private http: HttpClient) {} + constructor(private http: HttpClient) { + try { + const strageAccount = localStorage.getItem(this.accountKey); + if (strageAccount) { + this.account = JSON.parse(strageAccount); + } + } catch (error) { + console.error("获取用户信息失败", error); + } + } + + public account!: ClientAccountDTO; public accountKey = "CATERING_CLIENT_ACCOUNT"; + globalEnum!: GlobalEnum; + page(v: {}, q: {}) { return this.http.get("https://jsonplaceholder.typicode.com/users", v).pipe( map((r) => { @@ -22,6 +45,20 @@ export class ClientApiService { ); } + getAllEnum(force?: boolean): Observable { + if (this.globalEnum && !force) { + return of(this.globalEnum); + } + return this.http.get>("/api/basic/enum").pipe( + map((res) => { + return res.body; + }), + tap((r) => { + this.globalEnum = r; + }) + ); + } + login(v: {}) { const params = Utils.objectToHttpParams(v); return this.http.get("/api/login", { params }); @@ -31,6 +68,11 @@ export class ClientApiService { return this.http.get("/api/logout"); } + updatePassword(v: {}) { + const body = Utils.objectToFormData(v); + return this.http.post("/api/basic/user", body); + } + getRoleList() { return this.http.get>("/api/role"); } @@ -75,4 +117,18 @@ export class ClientApiService { params, }); } + + saveOrg(org: AnyObject) { + const body = Utils.objectToFormData(org); + return this.http.post(" /api/vender", body); + } + + getOrgConfig() { + return this.http.get>("/api/vender/config"); + } + + saveOrgConfig(config: AnyObject) { + const body = Utils.objectToFormData(config); + return this.http.post("/api/vender/config", body); + } }