cloud-functions.service.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { HttpClient, HttpErrorResponse } from '@angular/common/http';
  2. import { inject, Injectable } from '@angular/core';
  3. import { firstValueFrom } from 'rxjs';
  4. import { CLOUD_FUNCTION_BASE_URL } from './admin.constants';
  5. import { AdminSessionService } from './admin-session.service';
  6. import { CloudEnvelope, LegacyCloudEnvelope } from './admin.models';
  7. export class CloudFunctionError extends Error {
  8. constructor(message: string, readonly status = 0, readonly payload?: unknown) {
  9. super(message);
  10. }
  11. }
  12. @Injectable({ providedIn: 'root' })
  13. export class CloudFunctionsService {
  14. private readonly http = inject(HttpClient);
  15. private readonly sessions = inject(AdminSessionService);
  16. async admin<T>(operation: string, params: Record<string, unknown> = {}): Promise<T> {
  17. const token = this.sessions.session()?.sessionToken;
  18. if (!token) throw new CloudFunctionError('管理员会话已失效', 401);
  19. try {
  20. const envelope = await firstValueFrom(this.http.post<CloudEnvelope<T>>(
  21. `${CLOUD_FUNCTION_BASE_URL}/xiaoshu/admin/gateway`,
  22. { token, params: { operation, ...params } },
  23. ));
  24. if (!envelope.success) throw new CloudFunctionError(envelope.message || envelope.error || '云函数执行失败');
  25. return envelope.data;
  26. } catch (error) {
  27. if (error instanceof CloudFunctionError) throw error;
  28. if (error instanceof HttpErrorResponse) {
  29. const payload = error.error as { error?: string; message?: string } | null;
  30. if (error.status === 401 || error.status === 403) this.sessions.logout();
  31. throw new CloudFunctionError(payload?.message || payload?.error || error.message, error.status, payload);
  32. }
  33. throw new CloudFunctionError(error instanceof Error ? error.message : '未知云函数错误');
  34. }
  35. }
  36. async app<T>(action: string, params: Record<string, unknown> = {}): Promise<T> {
  37. const token = this.sessions.session()?.sessionToken;
  38. if (!token) throw new CloudFunctionError('管理员会话已失效', 401);
  39. try {
  40. const envelope = await firstValueFrom(this.http.post<LegacyCloudEnvelope<T>>(
  41. `${CLOUD_FUNCTION_BASE_URL}/xiaoshu/app/gateway`,
  42. { token, params: { action, ...params } },
  43. ));
  44. if (envelope.retcode === -1) throw new CloudFunctionError(envelope.retmsg || '云函数执行失败');
  45. return envelope.result;
  46. } catch (error) {
  47. if (error instanceof CloudFunctionError) throw error;
  48. if (error instanceof HttpErrorResponse) {
  49. const payload = error.error as { error?: string; message?: string; retmsg?: string } | null;
  50. if (error.status === 401 || error.status === 403) this.sessions.logout();
  51. throw new CloudFunctionError(payload?.retmsg || payload?.message || payload?.error || error.message, error.status, payload);
  52. }
  53. throw new CloudFunctionError(error instanceof Error ? error.message : '未知云函数错误');
  54. }
  55. }
  56. }