You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
531 lines
14 KiB
531 lines
14 KiB
import { HttpClient, HttpParams, HttpResponse } from "@angular/common/http";
|
|
import { Inject, Injectable, InjectionToken } from "@angular/core";
|
|
import { AnyObject, OptionItemInterface, PageResult, ResponseType } from "@cdk/types";
|
|
import { format, addDays } from "date-fns";
|
|
import { Utils } from "@cdk/utils";
|
|
import { Observable, map, of, tap } from "rxjs";
|
|
import {
|
|
PermItemDTO,
|
|
UserDTO,
|
|
UserRoleDTO,
|
|
GlobalEnum,
|
|
OrgDTO,
|
|
ClientAccountDTO,
|
|
AdminAccountDTO,
|
|
OrgConfigDTO,
|
|
CategoryDTO,
|
|
NutrientDTO,
|
|
} from "@cdk/public-api";
|
|
|
|
export const PROJECT_NAME = new InjectionToken<string>("projectName");
|
|
|
|
@Injectable({
|
|
providedIn: "root",
|
|
})
|
|
export class ApiService {
|
|
constructor(private http: HttpClient, @Inject(PROJECT_NAME) public project: string) {
|
|
this.initAccount();
|
|
}
|
|
|
|
public account!: ClientAccountDTO;
|
|
|
|
public adminAccount!: AdminAccountDTO;
|
|
|
|
public accountKey = this.project === "admin" ? "CATERING_ADMIN_ACCOUNT" : "CATERING_CLIENT_ACCOUNT";
|
|
|
|
globalEnum!: GlobalEnum;
|
|
|
|
// 能量、蛋白质、脂肪、碳水化合物、糖、钠/食盐、钙、铁、锌、维生素A、维生素B1、维生素B2、维生素C、膳食纤维
|
|
nutrientSort = new Map([
|
|
["energy", { sort: 0 }],
|
|
["protein", { sort: 1 }],
|
|
["fat", { sort: 2 }],
|
|
["carbs", { sort: 3 }],
|
|
["sugar", { sort: 4 }],
|
|
["sodium", { sort: 5 }],
|
|
["calcium", { sort: 6 }],
|
|
["iron", { sort: 7 }],
|
|
["zinc", { sort: 8 }],
|
|
["va", { sort: 9 }],
|
|
["vb1", { sort: 10 }],
|
|
["vb2", { sort: 11 }],
|
|
["vc", { sort: 12 }],
|
|
["fiber", { sort: 13 }],
|
|
]);
|
|
|
|
initAccount() {
|
|
try {
|
|
const stragedAccount = localStorage.getItem(this.accountKey);
|
|
if (stragedAccount) {
|
|
if (this.project === "admin") {
|
|
this.adminAccount = JSON.parse(stragedAccount);
|
|
} else {
|
|
this.account = JSON.parse(stragedAccount);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error("获取用户信息失败", error);
|
|
}
|
|
}
|
|
|
|
upload(data: FormData) {
|
|
return this.http.put<ResponseType>("/api/icon", data);
|
|
}
|
|
|
|
private _formatEnum(v: CategoryDTO[]): OptionItemInterface[] {
|
|
return v.map((i) => ({ label: i.key, value: i.value }));
|
|
}
|
|
|
|
private _sortNutrient(n: NutrientDTO[]) {
|
|
return n.map((i) => {
|
|
return { ...i, ...this.nutrientSort.get(i.key) };
|
|
});
|
|
}
|
|
|
|
getAllEnum(force?: boolean): Observable<GlobalEnum> {
|
|
if (this.globalEnum && !force) {
|
|
return of(this.globalEnum);
|
|
}
|
|
return this.http.get<ResponseType<any>>("/api/enum").pipe(
|
|
map((res) => {
|
|
return {
|
|
...res.body,
|
|
mealType: this._formatEnum(res.body.mealType),
|
|
menuStatus: this._formatEnum(res.body.menuStatus),
|
|
nutrient: this._sortNutrient(res.body.nutrient),
|
|
};
|
|
}),
|
|
tap((r) => {
|
|
this.globalEnum = r;
|
|
})
|
|
);
|
|
}
|
|
|
|
login(v: AnyObject) {
|
|
v["admin"] = this.project === "admin";
|
|
const params = Utils.objectToHttpParams(v);
|
|
return this.http.get<ResponseType>("/api/login", { params }).pipe(
|
|
tap((res) => {
|
|
localStorage.setItem(this.accountKey, JSON.stringify(res.body));
|
|
this.initAccount();
|
|
})
|
|
);
|
|
}
|
|
|
|
logout() {
|
|
return this.http.get<ResponseType>("/api/logout").pipe(
|
|
tap((res) => {
|
|
if (res.success) {
|
|
localStorage.removeItem(this.accountKey);
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
getOrgInfo() {
|
|
return this.http.get<ResponseType>("/api/vender/info").pipe(
|
|
tap((res) => {
|
|
this.account["vender"] = res.body;
|
|
})
|
|
);
|
|
}
|
|
|
|
getOrgConfig() {
|
|
return this.http.get<ResponseType<OrgConfigDTO>>("/api/vender/config");
|
|
}
|
|
|
|
saveOrgConfig(config: AnyObject) {
|
|
const body = Utils.objectToFormData(config);
|
|
return this.http.post<ResponseType>("/api/vender/config", body);
|
|
}
|
|
|
|
updatePassword(v: {}) {
|
|
const body = Utils.objectToFormData(v);
|
|
return this.http.post<ResponseType>("/api/password", body);
|
|
}
|
|
|
|
getRoleList() {
|
|
return this.http.get<ResponseType<UserRoleDTO[]>>("/api/role");
|
|
}
|
|
|
|
deleteRole(roleId: string) {
|
|
const params = new HttpParams().set("roleId", roleId);
|
|
return this.http.delete<ResponseType>("/api/role", {
|
|
params,
|
|
});
|
|
}
|
|
|
|
updateRole(rule: AnyObject) {
|
|
const body = Utils.objectToFormData(rule, true);
|
|
const method = rule["roleId"] ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/role", body);
|
|
}
|
|
|
|
getRolePerms() {
|
|
return this.http.get<ResponseType<PermItemDTO[]>>("/api/role/item");
|
|
}
|
|
|
|
getUserList() {
|
|
return this.http.get<ResponseType<UserDTO[]>>("/api/user");
|
|
}
|
|
|
|
checkUid(uid: string) {
|
|
const params = new HttpParams().set("uid", uid);
|
|
return this.http.delete<ResponseType>("/api/user/check", {
|
|
params,
|
|
});
|
|
}
|
|
|
|
saveUser(user: AnyObject, edit: boolean) {
|
|
const body = Utils.objectToFormData(user);
|
|
const method = edit ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/user", body);
|
|
}
|
|
|
|
deleteUser(uid: string) {
|
|
const params = new HttpParams().set("uid", uid);
|
|
return this.http.delete<ResponseType>("/api/user", {
|
|
params,
|
|
});
|
|
}
|
|
|
|
getOrgList(query: { vendors?: number[]; keyword?: string }) {
|
|
const q = Utils.objectStringify(query);
|
|
return this.http.get<ResponseType<OrgDTO[]>>(`/api/vender/select?${q}`);
|
|
}
|
|
|
|
getOrgPage(p: {}, q: {}) {
|
|
let params = Utils.objectStringify({ ...p, ...q }, { skipEmptyString: false, skipNull: false });
|
|
|
|
return this.http.get<ResponseType<PageResult<OrgDTO>>>(`/api/vender?${params}`);
|
|
}
|
|
|
|
checkOrgAccount(account: string) {
|
|
const params = new HttpParams().set("account", account);
|
|
return this.http.get<ResponseType<boolean>>("/api/vender/check/account", {
|
|
params,
|
|
});
|
|
}
|
|
|
|
checkOrgName(name: string) {
|
|
const params = new HttpParams().set("name", name);
|
|
return this.http.get<ResponseType<boolean>>("/api/vender/check/name", {
|
|
params,
|
|
});
|
|
}
|
|
|
|
deleteOrg(id: number) {
|
|
const params = Utils.objectToFormData({ venderId: id });
|
|
return this.http.delete<ResponseType>("/api/vender", {
|
|
body: params,
|
|
});
|
|
}
|
|
|
|
saveOrg(org: AnyObject) {
|
|
const body = Utils.objectToFormData(org);
|
|
const method = org["id"] ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/vender", body);
|
|
}
|
|
|
|
// getOrgConfig() {
|
|
// return this.http.get<ResponseType>("/api/vender/config");
|
|
// }
|
|
|
|
getFoodPage(p: {}, q: {}) {
|
|
const params = Utils.objectStringify({ ...p, ...q });
|
|
return this.http.get<ResponseType<PageResult>>(`/api/ingredient?${params}`).pipe(
|
|
map((r) => {
|
|
if (Array.isArray(r.body.content)) {
|
|
r.body.content = r.body.content.map((o) => {
|
|
return {
|
|
...o,
|
|
nutrientArr: Object.entries(o.nutrient).map(([k, v]) => {
|
|
const nutrient = this.globalEnum.nutrient.find((f) => f.key === k);
|
|
return {
|
|
key: k,
|
|
value: v,
|
|
label: nutrient?.value,
|
|
measurement: nutrient?.measurement,
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
}
|
|
return r;
|
|
})
|
|
);
|
|
}
|
|
|
|
getFoodList(query: {}) {
|
|
const q = Utils.objectStringify(query);
|
|
return this.http.get<ResponseType<any[]>>(`/api/ingredient/select?${q}`);
|
|
}
|
|
|
|
getFoodExcelTemplate() {
|
|
return this.http.get("/api/ingredient/excel", { observe: "response", responseType: "blob" as "json" }).pipe(
|
|
tap((res) => {
|
|
this.downLoadFile(res);
|
|
})
|
|
);
|
|
}
|
|
|
|
downLoadFile(response: HttpResponse<Object>, defaultName = `${Date.now()}.xlsx`) {
|
|
const fileNameFromHeader = response.headers.get("Content-Disposition");
|
|
if (fileNameFromHeader) {
|
|
const fileName = fileNameFromHeader.trim()?.split("''")?.[1]?.replace(/"/g, "") ?? defaultName;
|
|
const blob = new Blob([response.body as any]);
|
|
const downloadLink = document.createElement("a");
|
|
downloadLink.href = URL.createObjectURL(blob);
|
|
downloadLink.download = decodeURIComponent(fileName);
|
|
document.body.appendChild(downloadLink);
|
|
downloadLink.click();
|
|
document.body.removeChild(downloadLink);
|
|
}
|
|
}
|
|
|
|
saveFood(food: AnyObject, isEdit?: boolean) {
|
|
const body = Utils.objectToFormData(food);
|
|
const method = isEdit ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/ingredient", body);
|
|
}
|
|
|
|
deleteFoods(ids: number[]) {
|
|
const params = Utils.objectToFormData({ ingredients: ids.join(",") });
|
|
return this.http.delete<ResponseType>(`/api/ingredient`, { body: params });
|
|
}
|
|
|
|
importFood(f: FormData) {
|
|
// return this.http.put<ResponseType>("/api/ingredient/upload", f);
|
|
return this.http
|
|
.put<ResponseType>("/api/ingredient/excel", f, {
|
|
observe: "response",
|
|
responseType: "blob" as "json",
|
|
})
|
|
.pipe(
|
|
tap((res) => {
|
|
this.downLoadFile(res);
|
|
})
|
|
);
|
|
}
|
|
|
|
markFood(mark: string, key: string) {
|
|
const params = Utils.objectToFormData({ mark, key });
|
|
return this.http.put<ResponseType>("/api/ingredient/mark", params);
|
|
}
|
|
|
|
removeFoodMark(key: string) {
|
|
const params = Utils.objectToFormData({ key });
|
|
return this.http.delete<ResponseType>("/api/ingredient/mark", { body: params });
|
|
}
|
|
|
|
getStandardPage(p: {}, q: {}) {
|
|
const params = Utils.objectStringify({ ...p, ...q });
|
|
return this.http.get<ResponseType<PageResult>>(`/api/nutrition?${params}`).pipe(
|
|
map((r) => {
|
|
if (Array.isArray(r.body.content)) {
|
|
r.body.content = r.body.content.map((o) => {
|
|
return {
|
|
...o,
|
|
people: Object.entries(o.ingredient ?? {}).map(([k, v]) => {
|
|
return {
|
|
peopleGroupName: k,
|
|
...((v as any) ?? {}),
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
}
|
|
return r;
|
|
})
|
|
);
|
|
}
|
|
|
|
getStandard(q: { id?: string; name?: string }) {
|
|
const query = Utils.objectStringify(q);
|
|
return this.http.get<ResponseType<any>>(`/api/nutrition/select?${query}`);
|
|
}
|
|
|
|
saveStandard(v: AnyObject, isEdit?: boolean) {
|
|
const body = Utils.objectToFormData({ ...v, vendors: v["vendors"]?.join(",") });
|
|
const method = v["id"] ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/nutrition", body);
|
|
}
|
|
|
|
deleteStandard(id: string) {
|
|
const params = Utils.objectToFormData({ id });
|
|
return this.http.delete<ResponseType>(`/api/nutrition`, { body: params });
|
|
}
|
|
|
|
getDishPage(p: {}, q: {}) {
|
|
const params = Utils.objectStringify({ ...p, ...q });
|
|
return this.http.get<ResponseType<PageResult>>(`/api/dish?${params}`).pipe(
|
|
map((r) => {
|
|
if (Array.isArray(r.body.content)) {
|
|
// r.body.content = r.body.content.map((o) => {
|
|
// return {
|
|
// ...o,
|
|
// foodArr: Object.entries(o.ingredient).map(([k, v]) => {
|
|
// return {
|
|
// key: k,
|
|
// value: v,
|
|
// label: k,
|
|
// };
|
|
// }),
|
|
// };
|
|
// });
|
|
}
|
|
return r;
|
|
})
|
|
);
|
|
}
|
|
|
|
getDishLabel(ids: (string | number)[]) {
|
|
const query = Utils.objectStringify({ ids });
|
|
return this.http.get<ResponseType<any[]>>(`/api/dish/label?${query}`).pipe(
|
|
map((res) => {
|
|
return {
|
|
...res,
|
|
body: res.body.map((i) => {
|
|
return {
|
|
...i,
|
|
component: (i.component as AnyObject[])
|
|
.map((c) => {
|
|
return {
|
|
...c,
|
|
...this.nutrientSort.get(c["key"]),
|
|
};
|
|
})
|
|
.sort((a, b) => a["sort"]! - b["sort"]!),
|
|
};
|
|
}),
|
|
};
|
|
})
|
|
);
|
|
}
|
|
|
|
saveDish(v: AnyObject) {
|
|
const body = Utils.objectToFormData(v);
|
|
const method = v["id"] ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/dish", body);
|
|
}
|
|
|
|
deleteDish(ids: string[]) {
|
|
const params = Utils.objectToFormData({ ids: ids.join(",") });
|
|
return this.http.delete<ResponseType>(`/api/dish`, { body: params });
|
|
}
|
|
|
|
getMenuStatusPage(p: {}, q: {}) {
|
|
const params = Utils.objectStringify({ ...p, ...q });
|
|
return this.http.get<ResponseType<PageResult>>(`/api/menu/review?${params}`);
|
|
}
|
|
|
|
getMenuPage(p: {}, q: {}) {
|
|
const params = Utils.objectStringify({ ...p, ...q });
|
|
return this.http.get<ResponseType<PageResult>>(`/api/menu?${params}`);
|
|
}
|
|
|
|
getMenuItem(id: string | number) {
|
|
const params = Utils.objectStringify({ id });
|
|
return this.http.get<ResponseType>(`/api/menu?${params}`);
|
|
}
|
|
|
|
getCountByStatus() {
|
|
return this.http.get<ResponseType>(`/api/menu/review/count`);
|
|
}
|
|
|
|
saveMenu(v: AnyObject) {
|
|
const body = Utils.objectToFormData(v);
|
|
const method = v["id"] ? "post" : "put";
|
|
return this.http[method]<ResponseType>("/api/menu", body);
|
|
}
|
|
|
|
// 提交审核
|
|
submitMenuForReview(id: string | number) {
|
|
const params = Utils.objectToFormData({ id });
|
|
return this.http.put<ResponseType>(`/api/menu/review`, params);
|
|
}
|
|
|
|
disableMenu(id: string | number) {
|
|
const params = Utils.objectToFormData({ id });
|
|
return this.http.delete<ResponseType>(`/api/menu/review`, { body: params });
|
|
}
|
|
|
|
reviewMenu(id: number, pass: boolean, reason?: string) {
|
|
const params = Utils.objectToFormData({ id, pass, reason });
|
|
return this.http.post<ResponseType>(`/api/menu/review`, params);
|
|
}
|
|
|
|
release(id: string | number, startTime: Date, amount: number) {
|
|
const endTime = addDays(startTime, amount);
|
|
const params = Utils.objectToFormData({
|
|
id,
|
|
startTime: format(startTime, "yyyy-MM-dd"),
|
|
endTime: format(endTime, "yyyy-MM-dd"),
|
|
});
|
|
return this.http.put<ResponseType>(`/api/menu/release`, params);
|
|
}
|
|
|
|
cancelRelease(id: string | number) {
|
|
const params = Utils.objectToFormData({ id });
|
|
return this.http.delete<ResponseType>(`/api/menu/release`, { body: params });
|
|
}
|
|
|
|
deleteMenu(id: string | number) {
|
|
const params = Utils.objectToFormData({ id });
|
|
return this.http.delete<ResponseType>(`/api/menu`, { body: params });
|
|
}
|
|
|
|
getMenuDist(menuId: number | string) {
|
|
return this.http.get<ResponseType>(`/api/menu/dish?menuId=${menuId}`);
|
|
}
|
|
|
|
saveMenuDist(d: {}) {
|
|
return this.http.put<ResponseType>(`/api/menu/dish/batch`, d);
|
|
}
|
|
|
|
getMenuReleasePage(p: {}, q: {}) {
|
|
const params = Utils.objectStringify({ ...p, ...q });
|
|
return this.http.get<ResponseType<PageResult>>(`/api/menu/release?${params}`).pipe(
|
|
map((res) => {
|
|
if (Array.isArray(res.body.content)) {
|
|
res.body.content = res.body.content.map((i) => ({
|
|
...i,
|
|
dateRange: `${format(new Date(i.startTime), "yyyy-MM-dd")}至${format(new Date(i.endTime), "yyyy-MM-dd")}`,
|
|
}));
|
|
}
|
|
return res;
|
|
})
|
|
);
|
|
}
|
|
|
|
exportMenu(id: number | string) {
|
|
return this.http
|
|
.get<ResponseType>(`/api/menu/dish/export?id=${id}`, {
|
|
observe: "response",
|
|
responseType: "blob" as "json",
|
|
})
|
|
.pipe(
|
|
tap((res) => {
|
|
this.downLoadFile(res);
|
|
})
|
|
);
|
|
}
|
|
|
|
getAnalysis(id: number, day?: number, crow?: string) {
|
|
const params = Utils.objectStringify({ id, day, crow });
|
|
return this.http.get<ResponseType>(`/api/menu/analysis?${params}`);
|
|
}
|
|
|
|
getAnalysisEnergy(id: number, day?: number, crow?: string) {
|
|
const params = Utils.objectStringify({ id, day, crow });
|
|
return this.http.get<ResponseType>(`/api/menu/analysis/energy?${params}`);
|
|
}
|
|
getAnalysisRule(id: number, day?: number, crow?: string) {
|
|
const params = Utils.objectStringify({ id, day, crow });
|
|
return this.http.get<ResponseType>(`/api/menu/analysis/types?${params}`);
|
|
}
|
|
|
|
getMenuDataVis() {
|
|
return this.http.get<ResponseType>(`/api/menu/dish`);
|
|
}
|
|
}
|
|
|