|  | @@ -0,0 +1,269 @@
 | 
	
		
			
				|  |  | +import { CommonModule } from '@angular/common';
 | 
	
		
			
				|  |  | +import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
 | 
	
		
			
				|  |  | +import { ActivatedRoute } from '@angular/router';
 | 
	
		
			
				|  |  | +import { ModalController } from '@ionic/angular/standalone';
 | 
	
		
			
				|  |  | +import { ChatPanelComponent } from 'fmode-ng';
 | 
	
		
			
				|  |  | +import Parse from 'parse';
 | 
	
		
			
				|  |  | +import { combineLatest } from 'rxjs';
 | 
	
		
			
				|  |  | +import {
 | 
	
		
			
				|  |  | +  IonCard,
 | 
	
		
			
				|  |  | +  IonCardContent,
 | 
	
		
			
				|  |  | +  IonCardHeader,
 | 
	
		
			
				|  |  | +  IonCardSubtitle,
 | 
	
		
			
				|  |  | +  IonCardTitle,
 | 
	
		
			
				|  |  | +  IonContent,
 | 
	
		
			
				|  |  | +  IonHeader,
 | 
	
		
			
				|  |  | +  IonTitle,
 | 
	
		
			
				|  |  | +  IonToolbar,
 | 
	
		
			
				|  |  | +} from '@ionic/angular/standalone';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 添加Icons
 | 
	
		
			
				|  |  | +import { addIcons } from 'ionicons';
 | 
	
		
			
				|  |  | +import * as icons from 'ionicons/icons';
 | 
	
		
			
				|  |  | +addIcons(icons);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@Component({
 | 
	
		
			
				|  |  | +  selector: 'app-aichat-page',
 | 
	
		
			
				|  |  | +  templateUrl: './aichat-page.component.html',
 | 
	
		
			
				|  |  | +  styleUrls: ['./aichat-page.component.scss'],
 | 
	
		
			
				|  |  | +  standalone: true,
 | 
	
		
			
				|  |  | +  imports: [
 | 
	
		
			
				|  |  | +    IonHeader,
 | 
	
		
			
				|  |  | +    IonToolbar,
 | 
	
		
			
				|  |  | +    IonTitle,
 | 
	
		
			
				|  |  | +    IonContent,
 | 
	
		
			
				|  |  | +    IonCard,
 | 
	
		
			
				|  |  | +    IonCardContent,
 | 
	
		
			
				|  |  | +    IonCardTitle,
 | 
	
		
			
				|  |  | +    IonCardHeader,
 | 
	
		
			
				|  |  | +    IonCardSubtitle,
 | 
	
		
			
				|  |  | +    CommonModule,
 | 
	
		
			
				|  |  | +    ChatPanelComponent,
 | 
	
		
			
				|  |  | +  ],
 | 
	
		
			
				|  |  | +})
 | 
	
		
			
				|  |  | +export class AichatPageComponent implements OnInit {
 | 
	
		
			
				|  |  | +  @ViewChild(ChatPanelComponent) chatComp: ChatPanelComponent | undefined;
 | 
	
		
			
				|  |  | +  leftButtons: any[] = [];
 | 
	
		
			
				|  |  | +  modelList: any[] = [];
 | 
	
		
			
				|  |  | +  isDirect: boolean = true;
 | 
	
		
			
				|  |  | +  hideShare: boolean = true;
 | 
	
		
			
				|  |  | +  hideModalSelect: boolean = true;
 | 
	
		
			
				|  |  | +  hideInputPreview: boolean = true;
 | 
	
		
			
				|  |  | +  chatId: string = '';
 | 
	
		
			
				|  |  | +  roleId: string = '';
 | 
	
		
			
				|  |  | +  pid: string = '';
 | 
	
		
			
				|  |  | +  constructor(
 | 
	
		
			
				|  |  | +    private route: ActivatedRoute,
 | 
	
		
			
				|  |  | +    private cdRef: ChangeDetectorRef,
 | 
	
		
			
				|  |  | +    private modalCtrl: ModalController
 | 
	
		
			
				|  |  | +  ) {
 | 
	
		
			
				|  |  | +    combineLatest([this.route.params, this.route.queryParams]).subscribe(
 | 
	
		
			
				|  |  | +      async (data: any) => {
 | 
	
		
			
				|  |  | +        let params = data[0] || {};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        this.chatId = params['chatId'] || this.chatId || null;
 | 
	
		
			
				|  |  | +        this.roleId = params['roleId'] || this.roleId || null;
 | 
	
		
			
				|  |  | +        this.pid = params['pid'] || this.pid || null;
 | 
	
		
			
				|  |  | +        console.log('this.pid', this.pid);
 | 
	
		
			
				|  |  | +        // 异步加载的后续数据 操作按钮
 | 
	
		
			
				|  |  | +        let bint = setInterval(() => {
 | 
	
		
			
				|  |  | +          if (this.roleId) {
 | 
	
		
			
				|  |  | +            clearInterval(bint);
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          this.initPanelConfig();
 | 
	
		
			
				|  |  | +        }, 2000);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  ngOnInit() {
 | 
	
		
			
				|  |  | +    this.initPanelConfig();
 | 
	
		
			
				|  |  | +    // 异步加载的后续数据 提示词
 | 
	
		
			
				|  |  | +    let pint = setInterval(() => {
 | 
	
		
			
				|  |  | +      if (this.chatComp?.fmodeChat?.promptList?.length) {
 | 
	
		
			
				|  |  | +        clearInterval(pint);
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      this.getChatPrompt();
 | 
	
		
			
				|  |  | +    }, 2000);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 异步加载的后续数据 采访人物 ChatSession.person
 | 
	
		
			
				|  |  | +    let personInt = setInterval(() => {
 | 
	
		
			
				|  |  | +      if (this.chatComp?.fmodeChat?.chatSession?.get('person')) {
 | 
	
		
			
				|  |  | +        clearInterval(personInt);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (!this.chatComp?.fmodeChat?.chatSession?.get('person')) {
 | 
	
		
			
				|  |  | +        if (this.pid) {
 | 
	
		
			
				|  |  | +          this.chatComp?.fmodeChat?.chatSession?.set('person', {
 | 
	
		
			
				|  |  | +            type: 'Pointer',
 | 
	
		
			
				|  |  | +            className: 'Person',
 | 
	
		
			
				|  |  | +            objectId: this.pid,
 | 
	
		
			
				|  |  | +          });
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }, 2000);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // 初始化聊天面板的设置
 | 
	
		
			
				|  |  | +  initPanelConfig() {
 | 
	
		
			
				|  |  | +    this.roleId =
 | 
	
		
			
				|  |  | +      this.chatComp?.fmodeChat?.chatSession?.get('role')?.id || this.roleId;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 按钮自定义
 | 
	
		
			
				|  |  | +    this.leftButtons = [
 | 
	
		
			
				|  |  | +      // 提示 当角色配置预设提示词时 显示
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        title: '话题灵感',
 | 
	
		
			
				|  |  | +        showTitle: true,
 | 
	
		
			
				|  |  | +        icon: 'color-wand-outline',
 | 
	
		
			
				|  |  | +        onClick: () => {
 | 
	
		
			
				|  |  | +          if (this.chatComp) {
 | 
	
		
			
				|  |  | +            this.chatComp.fmodeChat.isPromptModalOpen = true;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        show: () => {
 | 
	
		
			
				|  |  | +          return this.chatComp?.fmodeChat?.promptList?.length;
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    ];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this.leftButtons.push({
 | 
	
		
			
				|  |  | +      // 总结 结束并归档本次对话
 | 
	
		
			
				|  |  | +      title: 'AI总结对话',
 | 
	
		
			
				|  |  | +      showTitle: true,
 | 
	
		
			
				|  |  | +      icon: 'archive-outline',
 | 
	
		
			
				|  |  | +      onClick: () => {
 | 
	
		
			
				|  |  | +        if (this.chatComp) {
 | 
	
		
			
				|  |  | +          // this.chatComp.fmodeChat.isPromptModalOpen = true
 | 
	
		
			
				|  |  | +          if (this.chatComp.fmodeChat) {
 | 
	
		
			
				|  |  | +            console.log(JSON.stringify(this.chatComp.fmodeChat.messageList));
 | 
	
		
			
				|  |  | +            // alert("处理对话记录")
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      show: () => {
 | 
	
		
			
				|  |  | +        return !this.chatComp?.fmodeChat?.chatSession?.get('story')?.id;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    this.leftButtons.push({
 | 
	
		
			
				|  |  | +      // 总结 结束并归档本次对话
 | 
	
		
			
				|  |  | +      title: '聊天分析',
 | 
	
		
			
				|  |  | +      showTitle: true,
 | 
	
		
			
				|  |  | +      icon: 'archive-outline',
 | 
	
		
			
				|  |  | +      onClick: () => {
 | 
	
		
			
				|  |  | +        if (this.chatComp) {
 | 
	
		
			
				|  |  | +          // this.chatComp.fmodeChat.isPromptModalOpen = true
 | 
	
		
			
				|  |  | +          if (this.chatComp.fmodeChat) {
 | 
	
		
			
				|  |  | +            let messageList = JSON.parse(
 | 
	
		
			
				|  |  | +              JSON.stringify(this.chatComp.fmodeChat.messageList)
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +            messageList = messageList.filter(
 | 
	
		
			
				|  |  | +              (item: any) => item.role != 'system' && item?.hidden != true
 | 
	
		
			
				|  |  | +            );
 | 
	
		
			
				|  |  | +            let qaContent = messageList
 | 
	
		
			
				|  |  | +              .map((item: any) => {
 | 
	
		
			
				|  |  | +                let roleName = '当前用户';
 | 
	
		
			
				|  |  | +                if (item.role != 'user') {
 | 
	
		
			
				|  |  | +                  if (this.chatComp && this.chatComp.fmodeChat.role) {
 | 
	
		
			
				|  |  | +                    roleName = this.chatComp.fmodeChat.role.get('name');
 | 
	
		
			
				|  |  | +                  } else {
 | 
	
		
			
				|  |  | +                    roleName = 'AI助理';
 | 
	
		
			
				|  |  | +                  }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                return `${roleName}:${item.content}`;
 | 
	
		
			
				|  |  | +              })
 | 
	
		
			
				|  |  | +              .join('\n');
 | 
	
		
			
				|  |  | +            // console.log(qaContent);
 | 
	
		
			
				|  |  | +            // alert("处理对话记录")
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      show: () => {
 | 
	
		
			
				|  |  | +        return !this.chatComp?.fmodeChat?.chatSession?.get('story')?.id;
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    setTimeout(() => {
 | 
	
		
			
				|  |  | +      if (this.chatComp && this.chatComp.fmodeChat) {
 | 
	
		
			
				|  |  | +        // 自定义左下角操作按钮
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.leftButtons = this.leftButtons;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 自定义角色名称
 | 
	
		
			
				|  |  | +        //tags
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set('tags', [
 | 
	
		
			
				|  |  | +          '健身',
 | 
	
		
			
				|  |  | +          '营养',
 | 
	
		
			
				|  |  | +          '医疗',
 | 
	
		
			
				|  |  | +          '养生',
 | 
	
		
			
				|  |  | +        ]);
 | 
	
		
			
				|  |  | +        //name
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set('name', '大壮');
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set(
 | 
	
		
			
				|  |  | +          'desc',
 | 
	
		
			
				|  |  | +          '一名亲切和蔼的健身咨询师,大壮,年龄28岁'
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set('title', '高级健身专家');
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set('age', '28');
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set('gender', '男');
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set(
 | 
	
		
			
				|  |  | +          'avatar',
 | 
	
		
			
				|  |  | +          'https://s1.imagehub.cc/images/2024/12/15/925aa3073b1cd2a7dfbc40985ad0fe8f.png'
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        this.chatComp.fmodeChat.role.set(
 | 
	
		
			
				|  |  | +          'prompt',
 | 
	
		
			
				|  |  | +          `
 | 
	
		
			
				|  |  | +          # 角色设定
 | 
	
		
			
				|  |  | +          一名亲切和蔼的健身咨询师,大壮,年龄28岁,随意轻松一些。
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          # 对话环节
 | 
	
		
			
				|  |  | +          0.破冰,互相了解,引导用户介绍自己
 | 
	
		
			
				|  |  | +          1.拓展话题,根据用户的介绍,拓展一些和健身运动相关的话题
 | 
	
		
			
				|  |  | +          - 引导,可深入的点,以用户自述为主
 | 
	
		
			
				|  |  | +          - 当信息充足时候,确认用户需求,并进入下一个环节,给出用户想要的训练计划
 | 
	
		
			
				|  |  | +          2.引导收尾,委婉引导用户结束本次对话
 | 
	
		
			
				|  |  | +          - 用户同意结束后,结束本次对话,如果依依不舍,可以再陪聊一会儿
 | 
	
		
			
				|  |  | +          `
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        this.cdRef.detectChanges();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }, 1000);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 模型自定义
 | 
	
		
			
				|  |  | +    let ChatModel = Parse.Object.extend('ChatModel');
 | 
	
		
			
				|  |  | +    let model1 = new ChatModel();
 | 
	
		
			
				|  |  | +    model1.set({
 | 
	
		
			
				|  |  | +      name: '语伴4.5-128k',
 | 
	
		
			
				|  |  | +      code: 'fmode-4.5-128k',
 | 
	
		
			
				|  |  | +      model: 'gpt-4o-mini',
 | 
	
		
			
				|  |  | +      credit: 0.096,
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    this.modelList = [model1];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 获取对话记录
 | 
	
		
			
				|  |  | +    // console.log('initPanelConfig', this.leftButtons, this.modelList);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  async getChatPrompt() {
 | 
	
		
			
				|  |  | +    let query = new Parse.Query('ChatPrompt');
 | 
	
		
			
				|  |  | +    query.notEqualTo('isDeleted', true);
 | 
	
		
			
				|  |  | +    //  query.equalTo('company', localStorage.getItem("company"))
 | 
	
		
			
				|  |  | +    query.equalTo('role', this.chatComp?.fmodeChat?.role);
 | 
	
		
			
				|  |  | +    query.include('role');
 | 
	
		
			
				|  |  | +    let promptData = await query.find();
 | 
	
		
			
				|  |  | +    if (this.chatComp && this.chatComp.fmodeChat) {
 | 
	
		
			
				|  |  | +      this.chatComp.fmodeChat.promptList = promptData;
 | 
	
		
			
				|  |  | +      this.chatComp.fmodeChat.promptList.forEach((item: any) => {
 | 
	
		
			
				|  |  | +        let cate = item
 | 
	
		
			
				|  |  | +          .get('role')
 | 
	
		
			
				|  |  | +          .get('promptCates')
 | 
	
		
			
				|  |  | +          .filter((cate: any) => cate.name == item.get('cate'));
 | 
	
		
			
				|  |  | +        item.img = cate[0].img;
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 |