| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 | 
							- import { Injectable, inject } from '@angular/core';
 
- import { HttpClient } from '@angular/common/http';
 
- import { Observable, of, BehaviorSubject } from 'rxjs';
 
- import { delay, map, catchError } from 'rxjs/operators';
 
- // 通知类型枚举
 
- export enum NotificationType {
 
-   PAYMENT_COMPLETED = 'payment_completed',
 
-   IMAGE_UNLOCKED = 'image_unlocked',
 
-   SETTLEMENT_CONFIRMED = 'settlement_confirmed',
 
-   REMINDER = 'reminder',
 
-   SYSTEM = 'system'
 
- }
 
- // 通知渠道枚举
 
- export enum NotificationChannel {
 
-   SMS = 'sms',
 
-   EMAIL = 'email',
 
-   WECHAT = 'wechat',
 
-   PUSH = 'push',
 
-   IN_APP = 'in_app'
 
- }
 
- // 通知接口
 
- export interface Notification {
 
-   id: string;
 
-   type: NotificationType;
 
-   title: string;
 
-   content: string;
 
-   recipient: string;
 
-   channels: NotificationChannel[];
 
-   templateData?: any;
 
-   scheduledAt?: Date;
 
-   sentAt?: Date;
 
-   status: 'pending' | 'sent' | 'failed' | 'cancelled';
 
-   retryCount?: number;
 
-   metadata?: any;
 
- }
 
- // 通知模板接口
 
- export interface NotificationTemplate {
 
-   id: string;
 
-   type: NotificationType;
 
-   name: string;
 
-   title: string;
 
-   content: string;
 
-   channels: NotificationChannel[];
 
-   variables: string[];
 
- }
 
- // 通知发送结果接口
 
- export interface NotificationResult {
 
-   success: boolean;
 
-   notificationId: string;
 
-   sentChannels: NotificationChannel[];
 
-   failedChannels: NotificationChannel[];
 
-   error?: string;
 
- }
 
- @Injectable({
 
-   providedIn: 'root'
 
- })
 
- export class NotificationService {
 
-   private http = inject(HttpClient);
 
-   private notifications$ = new BehaviorSubject<Notification[]>([]);
 
-   
 
-   // 预定义通知模板
 
-   private templates: NotificationTemplate[] = [
 
-     {
 
-       id: 'payment_completed',
 
-       type: NotificationType.PAYMENT_COMPLETED,
 
-       name: '支付完成通知',
 
-       title: '🎉 尾款已到账,大图已解锁!',
 
-       content: `
 
-         亲爱的客户,您好!
 
-         
 
-         您的尾款支付已确认到账:
 
-         • 支付方式:{{paymentMethod}}
 
-         • 支付金额:¥{{amount}}
 
-         • 处理时间:{{processedAt}}
 
-         
 
-         🎨 高清渲染图已为您解锁,您现在可以:
 
-         • 下载所有高清渲染图
 
-         • 查看全景漫游链接
 
-         • 获取设计方案文件
 
-         
 
-         感谢您选择银三色摄影工作室!
 
-         如有任何问题,请随时联系我们。
 
-       `,
 
-       channels: [NotificationChannel.SMS, NotificationChannel.WECHAT, NotificationChannel.IN_APP],
 
-       variables: ['paymentMethod', 'amount', 'processedAt', 'customerName', 'projectName']
 
-     },
 
-     {
 
-       id: 'image_unlocked',
 
-       type: NotificationType.IMAGE_UNLOCKED,
 
-       name: '大图解锁通知',
 
-       title: '📸 您的高清渲染图已解锁',
 
-       content: `
 
-         {{customerName}},您好!
 
-         
 
-         项目"{{projectName}}"的高清渲染图已为您解锁:
 
-         • 解锁图片数量:{{imageCount}}张
 
-         • 图片分辨率:{{resolution}}
 
-         • 下载有效期:{{validUntil}}
 
-         
 
-         立即下载:{{downloadLink}}
 
-         
 
-         银三色摄影工作室
 
-       `,
 
-       channels: [NotificationChannel.SMS, NotificationChannel.EMAIL, NotificationChannel.IN_APP],
 
-       variables: ['customerName', 'projectName', 'imageCount', 'resolution', 'validUntil', 'downloadLink']
 
-     },
 
-     {
 
-       id: 'settlement_reminder',
 
-       type: NotificationType.REMINDER,
 
-       name: '结算提醒',
 
-       title: '💰 尾款结算提醒',
 
-       content: `
 
-         {{customerName}},您好!
 
-         
 
-         您的项目"{{projectName}}"已完成,请及时结算尾款:
 
-         • 应付金额:¥{{amount}}
 
-         • 截止日期:{{dueDate}}
 
-         
 
-         支付完成后,我们将立即为您解锁高清渲染图。
 
-         
 
-         银三色摄影工作室
 
-       `,
 
-       channels: [NotificationChannel.SMS, NotificationChannel.WECHAT],
 
-       variables: ['customerName', 'projectName', 'amount', 'dueDate']
 
-     }
 
-   ];
 
-   /**
 
-    * 发送支付完成通知
 
-    */
 
-   sendPaymentCompletedNotification(data: {
 
-     recipient: string;
 
-     paymentMethod: string;
 
-     amount: number;
 
-     customerName: string;
 
-     projectName: string;
 
-     channels?: NotificationChannel[];
 
-   }): Observable<NotificationResult> {
 
-     console.log('发送支付完成通知:', data);
 
-     const template = this.getTemplate(NotificationType.PAYMENT_COMPLETED);
 
-     if (!template) {
 
-       return of({
 
-         success: false,
 
-         notificationId: '',
 
-         sentChannels: [],
 
-         failedChannels: [],
 
-         error: '未找到通知模板'
 
-       });
 
-     }
 
-     const notification: Notification = {
 
-       id: `notification_${Date.now()}`,
 
-       type: NotificationType.PAYMENT_COMPLETED,
 
-       title: template.title,
 
-       content: this.renderTemplate(template.content, {
 
-         paymentMethod: data.paymentMethod,
 
-         amount: data.amount.toString(),
 
-         processedAt: new Date().toLocaleString(),
 
-         customerName: data.customerName,
 
-         projectName: data.projectName
 
-       }),
 
-       recipient: data.recipient,
 
-       channels: data.channels || template.channels,
 
-       templateData: data,
 
-       status: 'pending'
 
-     };
 
-     return this.sendNotification(notification);
 
-   }
 
-   /**
 
-    * 发送大图解锁通知
 
-    */
 
-   sendImageUnlockedNotification(data: {
 
-     recipient: string;
 
-     customerName: string;
 
-     projectName: string;
 
-     imageCount: number;
 
-     resolution: string;
 
-     validUntil: string;
 
-     downloadLink: string;
 
-     channels?: NotificationChannel[];
 
-   }): Observable<NotificationResult> {
 
-     console.log('发送大图解锁通知:', data);
 
-     const template = this.getTemplate(NotificationType.IMAGE_UNLOCKED);
 
-     if (!template) {
 
-       return of({
 
-         success: false,
 
-         notificationId: '',
 
-         sentChannels: [],
 
-         failedChannels: [],
 
-         error: '未找到通知模板'
 
-       });
 
-     }
 
-     const notification: Notification = {
 
-       id: `notification_${Date.now()}`,
 
-       type: NotificationType.IMAGE_UNLOCKED,
 
-       title: template.title,
 
-       content: this.renderTemplate(template.content, data),
 
-       recipient: data.recipient,
 
-       channels: data.channels || template.channels,
 
-       templateData: data,
 
-       status: 'pending'
 
-     };
 
-     return this.sendNotification(notification);
 
-   }
 
-   /**
 
-    * 发送结算提醒通知
 
-    */
 
-   sendSettlementReminderNotification(data: {
 
-     recipient: string;
 
-     customerName: string;
 
-     projectName: string;
 
-     amount: number;
 
-     dueDate: string;
 
-     channels?: NotificationChannel[];
 
-   }): Observable<NotificationResult> {
 
-     console.log('发送结算提醒通知:', data);
 
-     const template = this.getTemplate(NotificationType.REMINDER);
 
-     if (!template) {
 
-       return of({
 
-         success: false,
 
-         notificationId: '',
 
-         sentChannels: [],
 
-         failedChannels: [],
 
-         error: '未找到通知模板'
 
-       });
 
-     }
 
-     const notification: Notification = {
 
-       id: `notification_${Date.now()}`,
 
-       type: NotificationType.REMINDER,
 
-       title: template.title,
 
-       content: this.renderTemplate(template.content, {
 
-         customerName: data.customerName,
 
-         projectName: data.projectName,
 
-         amount: data.amount.toString(),
 
-         dueDate: data.dueDate
 
-       }),
 
-       recipient: data.recipient,
 
-       channels: data.channels || template.channels,
 
-       templateData: data,
 
-       status: 'pending'
 
-     };
 
-     return this.sendNotification(notification);
 
-   }
 
-   /**
 
-    * 发送通知
 
-    */
 
-   private sendNotification(notification: Notification): Observable<NotificationResult> {
 
-     console.log('发送通知:', notification);
 
-     // 模拟发送过程
 
-     return of(null).pipe(
 
-       delay(1500), // 模拟网络延迟
 
-       map(() => {
 
-         // 模拟发送结果
 
-         const successRate = 0.95; // 95%成功率
 
-         const success = Math.random() < successRate;
 
-         if (success) {
 
-           notification.status = 'sent';
 
-           notification.sentAt = new Date();
 
-           // 添加到通知历史
 
-           this.addToNotificationHistory(notification);
 
-           return {
 
-             success: true,
 
-             notificationId: notification.id,
 
-             sentChannels: notification.channels,
 
-             failedChannels: [],
 
-           };
 
-         } else {
 
-           notification.status = 'failed';
 
-           notification.retryCount = (notification.retryCount || 0) + 1;
 
-           return {
 
-             success: false,
 
-             notificationId: notification.id,
 
-             sentChannels: [],
 
-             failedChannels: notification.channels,
 
-             error: '网络错误或服务暂时不可用'
 
-           };
 
-         }
 
-       }),
 
-       catchError(error => {
 
-         console.error('通知发送失败:', error);
 
-         notification.status = 'failed';
 
-         
 
-         return of({
 
-           success: false,
 
-           notificationId: notification.id,
 
-           sentChannels: [],
 
-           failedChannels: notification.channels,
 
-           error: error.message || '发送失败'
 
-         });
 
-       })
 
-     );
 
-   }
 
-   /**
 
-    * 获取通知模板
 
-    */
 
-   private getTemplate(type: NotificationType): NotificationTemplate | undefined {
 
-     return this.templates.find(t => t.type === type);
 
-   }
 
-   /**
 
-    * 渲染模板内容
 
-    */
 
-   private renderTemplate(template: string, data: any): string {
 
-     let rendered = template;
 
-     
 
-     Object.keys(data).forEach(key => {
 
-       const placeholder = `{{${key}}}`;
 
-       rendered = rendered.replace(new RegExp(placeholder, 'g'), data[key]);
 
-     });
 
-     return rendered;
 
-   }
 
-   /**
 
-    * 添加到通知历史
 
-    */
 
-   private addToNotificationHistory(notification: Notification): void {
 
-     const current = this.notifications$.value;
 
-     this.notifications$.next([notification, ...current]);
 
-   }
 
-   /**
 
-    * 获取通知历史
 
-    */
 
-   getNotificationHistory(): Observable<Notification[]> {
 
-     return this.notifications$.asObservable();
 
-   }
 
-   /**
 
-    * 获取通知统计
 
-    */
 
-   getNotificationStatistics(): Observable<{
 
-     total: number;
 
-     sent: number;
 
-     failed: number;
 
-     pending: number;
 
-     byType: { [key: string]: number };
 
-     byChannel: { [key: string]: number };
 
-   }> {
 
-     return this.notifications$.pipe(
 
-       map(notifications => {
 
-         const total = notifications.length;
 
-         const sent = notifications.filter(n => n.status === 'sent').length;
 
-         const failed = notifications.filter(n => n.status === 'failed').length;
 
-         const pending = notifications.filter(n => n.status === 'pending').length;
 
-         const byType: { [key: string]: number } = {};
 
-         const byChannel: { [key: string]: number } = {};
 
-         notifications.forEach(n => {
 
-           byType[n.type] = (byType[n.type] || 0) + 1;
 
-           n.channels.forEach(channel => {
 
-             byChannel[channel] = (byChannel[channel] || 0) + 1;
 
-           });
 
-         });
 
-         return {
 
-           total,
 
-           sent,
 
-           failed,
 
-           pending,
 
-           byType,
 
-           byChannel
 
-         };
 
-       })
 
-     );
 
-   }
 
-   /**
 
-    * 重试失败的通知
 
-    */
 
-   retryFailedNotification(notificationId: string): Observable<NotificationResult> {
 
-     const notifications = this.notifications$.value;
 
-     const notification = notifications.find(n => n.id === notificationId);
 
-     if (!notification || notification.status !== 'failed') {
 
-       return of({
 
-         success: false,
 
-         notificationId,
 
-         sentChannels: [],
 
-         failedChannels: [],
 
-         error: '通知不存在或状态不正确'
 
-       });
 
-     }
 
-     notification.status = 'pending';
 
-     return this.sendNotification(notification);
 
-   }
 
-   /**
 
-    * 获取支持的通知渠道
 
-    */
 
-   getSupportedChannels(): NotificationChannel[] {
 
-     return Object.values(NotificationChannel);
 
-   }
 
-   /**
 
-    * 获取通知模板列表
 
-    */
 
-   getTemplates(): NotificationTemplate[] {
 
-     return [...this.templates];
 
-   }
 
- }
 
 
  |