Browse Source

把ai问诊的按钮实现,把医生的大致ui界面实现

yuebuzu-creater 5 months ago
parent
commit
125c447c10
32 changed files with 1139 additions and 102 deletions
  1. 6 0
      wisdom-app/src/agent/README.md
  2. 18 0
      wisdom-app/src/agent/agent-user-input/agent-user-input.component.html
  3. 0 0
      wisdom-app/src/agent/agent-user-input/agent-user-input.component.scss
  4. 22 0
      wisdom-app/src/agent/agent-user-input/agent-user-input.component.spec.ts
  5. 38 0
      wisdom-app/src/agent/agent-user-input/agent-user-input.component.ts
  6. 23 0
      wisdom-app/src/agent/agent.input.ts
  7. 44 0
      wisdom-app/src/agent/agent.json.ts
  8. 21 0
      wisdom-app/src/agent/agent.start.ts
  9. 94 0
      wisdom-app/src/agent/agent.task.ts
  10. 64 0
      wisdom-app/src/agent/tasks/inquiry/1.inquiry-user-story.ts
  11. 79 0
      wisdom-app/src/agent/tasks/inquiry/2.inquiry-doctor-question.ts
  12. 141 0
      wisdom-app/src/agent/tasks/inquiry/3.inquiry-user-answer.ts
  13. 55 0
      wisdom-app/src/agent/tasks/poem/poem-desc.ts
  14. 43 0
      wisdom-app/src/agent/tasks/poem/poem-picture.ts
  15. 26 0
      wisdom-app/src/app/inquiry-human/inquiry-human.component.html
  16. 0 0
      wisdom-app/src/app/inquiry-human/inquiry-human.component.scss
  17. 22 0
      wisdom-app/src/app/inquiry-human/inquiry-human.component.spec.ts
  18. 23 0
      wisdom-app/src/app/inquiry-human/inquiry-human.component.ts
  19. 18 9
      wisdom-app/src/app/page-inquiry/page-inquiry.component.html
  20. 86 42
      wisdom-app/src/app/page-inquiry/page-inquiry.component.ts
  21. 4 1
      wisdom-app/src/app/poem-picture/poem-picture.component.html
  22. 24 9
      wisdom-app/src/app/poem-picture/poem-picture.component.ts
  23. 0 1
      wisdom-app/src/app/tab1/tab1.page.html
  24. 2 2
      wisdom-app/src/app/tab1/tab1.page.ts
  25. 0 31
      wisdom-app/src/app/tab2/tab2.page.html
  26. 1 6
      wisdom-app/src/app/tab3/tab3.page.html
  27. 2 0
      wisdom-app/src/app/tab3/tab3.page.ts
  28. 6 1
      wisdom-app/src/app/tabs/tabs.routes.ts
  29. 9 0
      wisdom-app/src/app/test-chat-panel/test-chat-panel.component.html
  30. 3 0
      wisdom-app/src/app/test-chat-panel/test-chat-panel.component.scss
  31. 22 0
      wisdom-app/src/app/test-chat-panel/test-chat-panel.component.spec.ts
  32. 243 0
      wisdom-app/src/app/test-chat-panel/test-chat-panel.component.ts

+ 6 - 0
wisdom-app/src/agent/README.md

@@ -0,0 +1,6 @@
+
+
+# 技术设计
+- AgentTaskStep类 智能体任务的某一个步骤(简单任务)
+- TaskExecutor类 任务执行器
+- AgentTaskComponent类 展示任务进行进度的面板

+ 18 - 0
wisdom-app/src/agent/agent-user-input/agent-user-input.component.html

@@ -0,0 +1,18 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button color="medium" (click)="cancel()">取消</ion-button>
+    </ion-buttons>
+    <ion-title>用户输入</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="confirm()" [strong]="true">确认</ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content class="ion-padding">
+  @for(field of fieldsArray;track field.name){
+    <ion-item>
+      <ion-input labelPlacement="stacked" label="请输入 {{field.name}}" [(ngModel)]="inputData[field.name]" placeholder="{{field.desc}}"></ion-input>
+    </ion-item>
+  }
+</ion-content>

+ 0 - 0
wisdom-app/src/agent/agent-user-input/agent-user-input.component.scss


+ 22 - 0
wisdom-app/src/agent/agent-user-input/agent-user-input.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { AgentUserInputComponent } from './agent-user-input.component';
+
+describe('AgentUserInputComponent', () => {
+  let component: AgentUserInputComponent;
+  let fixture: ComponentFixture<AgentUserInputComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [AgentUserInputComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AgentUserInputComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 38 - 0
wisdom-app/src/agent/agent-user-input/agent-user-input.component.ts

@@ -0,0 +1,38 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { ModalController, IonHeader, IonContent, IonInput, IonToolbar, IonItem, IonButtons, IonButton, IonTitle } from '@ionic/angular/standalone';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+export interface AgentUserInputField{
+  name:string, // 字段名称
+  type:string, // 输入类型
+  desc:string, // 字段说明
+}
+@Component({
+  selector: 'agent-user-input',
+  templateUrl: './agent-user-input.component.html',
+  styleUrls: ['./agent-user-input.component.scss'],
+  standalone: true,
+  imports:[
+    IonHeader,IonContent,IonInput,IonToolbar,IonItem,IonButtons,IonButton,
+    IonTitle,
+    FormsModule,ReactiveFormsModule,
+  ]
+})
+export class AgentUserInputComponent  implements OnInit {
+
+  @Input()
+  fieldsArray:AgentUserInputField[]=[]
+
+  @Input()
+  inputData:any = {}
+
+  constructor(private modalCtrl: ModalController) {}
+  ngOnInit(){
+  }
+  cancel() {
+    return this.modalCtrl.dismiss(null, 'cancel');
+  }
+
+  confirm() {
+    return this.modalCtrl.dismiss(this.inputData, 'confirm');
+  }
+}

+ 23 - 0
wisdom-app/src/agent/agent.input.ts

@@ -0,0 +1,23 @@
+import { ModalController } from '@ionic/angular/standalone';
+import { AgentUserInputComponent } from './agent-user-input/agent-user-input.component';
+
+/**
+ * 数据搜集Modal
+ * @description
+ * https://ionicframework.com/docs/api/modal#controller-modals
+ */
+export async function getUserInput(modalCtrl:ModalController,options:{fieldsArray:any}){
+  const modal = await modalCtrl.create({
+    component: AgentUserInputComponent,
+    componentProps:{
+      fieldsArray:options.fieldsArray
+    }
+  });
+  modal.present();
+
+  const { data, role } = await modal.onWillDismiss();
+
+  if (role === 'confirm') {
+    return data;
+  }
+}

+ 44 - 0
wisdom-app/src/agent/agent.json.ts

@@ -0,0 +1,44 @@
+/**
+ * 
+ 结果是:
+ {
+     "keshi":"呼吸科",
+     "user":{
+         "name":""
+     }
+ }
+ */
+export function extactAndParseJsonFromString(inputString:string){
+    let startIndex = inputString.indexOf("{")
+    if(startIndex==-1) return {}
+
+    let count = 0;
+    let endIndex = startIndex;
+
+    // 遍历字符串,计算花括号实现数量平衡
+    for (let i = startIndex; i < inputString.length; i++) {
+        // console.log(i,inputString[i])
+        if(inputString[i]==="{"){
+            count++;
+        }else if(inputString[i]==="}"){
+            count--;
+        }
+        // 当花括号平衡,我们找到了完整的JSON
+        if(count === 0){
+            endIndex = i;
+            break;
+        }
+    }
+    // 若不平衡
+    if(count!=0) return {};
+
+    // 提取JSON字符串,并解析
+    const jsonString = inputString.slice(startIndex,endIndex+1);
+    console.log("jsonString",jsonString)
+    try{
+        return JSON.parse(jsonString);
+    }catch(error){
+        console.error("Failed to parse JSON",error);
+        return {}
+    }
+ }

+ 21 - 0
wisdom-app/src/agent/agent.start.ts

@@ -0,0 +1,21 @@
+import { AgentTaskStep } from "./agent.task";
+
+/**
+ * 任务执行函数
+ */
+export async function TaskExecutor(taskStepList:AgentTaskStep[]){
+
+for (let index = 0; index < taskStepList.length; index++) {
+    let step = taskStepList[index];
+    let result = await step.handle()
+    if(result == false) {break;} 
+
+    if(step.error){
+        break;
+    }
+    if(!step.error){ // 任务执行正常,无Error
+
+    }
+}
+
+}

+ 94 - 0
wisdom-app/src/agent/agent.task.ts

@@ -0,0 +1,94 @@
+
+// 任务步骤初始化参数
+interface AgentTaskStepOptions{
+    title:string
+    shareData?:any
+    handle?():{():Promise<any>}
+}
+
+export class AgentTaskStep{
+    // 任务名称
+    title:string = ""
+
+    // 任务数据 共享数据(整个任务集共享传递的数据)
+    shareData:any = {}
+    // 任务数据 私有数据(当前任务私有的处理数据)
+    data:any = {}
+
+    // 父级组件:任务集组件
+    // @example 当前子任务未完成,且当前任务是必须时,需要在当前任务中,终止整个程序
+    parentComp:any|undefined
+    // 当前任务在任务集数组中的项目
+    parentIndex:number|undefined
+
+    /**
+     * 任务生命周期
+     * @constructor // 构造时执行一次
+     * @onInit // 初始化后执行一次
+     * @onProgress // 进度变化时执行一次
+     * @onComplete // 完成前执行一次
+     */
+    constructor(metaData:AgentTaskStepOptions){
+        this.title = metaData.title
+        this.shareData = metaData.shareData
+        if(metaData.handle){
+            this.handle = metaData.handle
+        }
+        this.init(metaData)
+    }
+    onInit(step:AgentTaskStep){
+        this.isInit = true;
+    }
+    beforeHandle(step:AgentTaskStep){
+
+    }
+    afterHandle(step:AgentTaskStep){
+
+    }
+    onProgress(step:AgentTaskStep,progress:number){
+
+    }
+    onComplete(step:AgentTaskStep){
+
+    }
+    onError(step:AgentTaskStep){
+
+    }
+
+    /**
+     * 任务初始化函数
+     */
+    async init(metaData:AgentTaskStepOptions){
+    }
+    isInit:boolean = false; // 是否初始化
+
+    /** 
+     * 任务执行函数
+     * @desc 函数内必须有明确的完成、结束情形,函数内必须有进度的变化指示 progress从0.00 - 1.00
+     */
+    progress:number = 0;
+    // get progress(){
+    //     return this._progress
+    // }
+    // set progress(v:number){
+    //     this._progress = v
+    //     this.onProgress(this,this.progress)
+    // }
+
+    handle():Promise<any>|any{
+        this.beforeHandle(this)
+
+
+
+
+
+        this.onComplete(this)
+        this.onError(this)
+        return true
+    }
+
+    /**
+     * 任务错误提示
+     */
+    error:string = "" // 错误原因
+}

+ 64 - 0
wisdom-app/src/agent/tasks/inquiry/1.inquiry-user-story.ts

@@ -0,0 +1,64 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+
+export function TaskInqueryUserStory(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        let task1 = new AgentTaskStep({title:"导诊:根据患者描述导诊对应科室",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入的诗词
+                let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+                    {name:"症状口述",type:"text",desc:"描述下感觉到的症状或不适。"}
+                ]});
+
+                if(!userInput?.['症状口述']){
+                    task1.error = "无症状口述,无法判断科室"
+                    resolve(false);
+                }
+
+                // 文本生成
+                let PromptTemplate = `您是一名专业的医护人员,在门诊大厅负责导诊服务,请您根据患者的症状口述,为其选择合适的科室进行挂号。
+                患者症状口述:${userInput['症状口述']}
+                结果以JSON格式表示:
+                症状名称为具体的症状,症状描述为用户的感受,持续时间若没有直接说,可以写近期即可。
+                {
+                    "keshi":"科室名称",
+                    "sympList":[
+                        {"title":"症状名称","desc":"症状描述","duration":"持续时间"}
+                    ]
+                }
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5 && task1.progress <= 0.9){
+                            task1.progress += 0.01
+                        }
+                        if(task1.progress >= 0.9){
+                            task1.progress += 0.001
+                        }
+                        // 打印消息体
+                        console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            options.shareData.userStory = extactAndParseJsonFromString(message.content)
+                            options.shareData.userStory['症状口述'] = userInput['症状口述']
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}

+ 79 - 0
wisdom-app/src/agent/tasks/inquiry/2.inquiry-doctor-question.ts

@@ -0,0 +1,79 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+
+export function TaskInqueryDoctorQuestion(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        /**
+         shareData.userStory // 已经拥有的用户描述数据
+         {
+                  "keshi": "神经内科",
+                  "sympList": [
+                      {
+                          "title": "偏头痛",
+                          "desc": "持续了2天的偏头疼",
+                          "duration": "2天"
+                      },
+                      {
+                          "title": "发冷",
+                          "desc": "感觉发冷,已经有一天",
+                          "duration": "1天"
+                      }
+                  ]
+              }
+         */
+        let task1 = new AgentTaskStep({title:"问诊:医生根据患者情况,主动询问",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入
+                // let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+                //     {name:"症状口述",type:"text",desc:"描述下感觉到的症状或不适。"}
+                // ]});
+
+                // if(!userInput?.['症状口述']){
+                //     task1.error = "无症状口述,无法判断科室"
+                //     resolve(false);
+                // }
+
+                // 文本生成
+                let PromptTemplate = `您是一名专业的${options.shareData.userStory.keshi}主任医生,患者简单描述了一下他的情况,请您思考下还有哪些需要询问。
+                症状口述:${options.shareData.userStory['症状口述']}
+                结果以JSON格式表示:
+                {
+                    "questionList":[
+                        {"title":"问题标题","desc":"问题描述"}
+                    ]
+                }
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5 && task1.progress <= 0.9){
+                            task1.progress += 0.01
+                        }
+                        if(task1.progress >= 0.7){
+                            task1.progress += 0.001
+                        }
+                        // 打印消息体
+                        console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            options.shareData.userStory.questionList = extactAndParseJsonFromString(message.content).questionList || []
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}

+ 141 - 0
wisdom-app/src/agent/tasks/inquiry/3.inquiry-user-answer.ts

@@ -0,0 +1,141 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+
+export function TaskInqueryUserAnswer(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        /**
+         shareData.userStory // 已经拥有的医生主动询问
+         {
+            "questionList": [
+                {
+                    "title": "头痛的性质",
+                    "desc": "请问您的偏头痛是怎样的感觉?是刺痛、跳动还是压迫感?"
+                },
+            ]
+        }
+         */
+        let task1 = new AgentTaskStep({title:"诊断:患者回答具体内容后,医生给出诊断结果",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入的问题清单
+                let questionList = options.shareData.userStory.questionList.map((item:any)=>{return {name:item.title,desc:item.desc,type:"text"}})
+                
+                let userInputResult = await getUserInput(options.modalCtrl,{fieldsArray:questionList});
+                console.log(userInputResult)
+                questionList.forEach((question:any)=>{
+                    question.answer = userInputResult[question.name]
+                })
+            
+                // 文本生成
+                let qaContent = options.shareData.userStory.questionList.map((item:any)=>`医生问:${item.title},${item.desc}\n患者答:${item.answer||"没回答"}`).join("\n")
+                let PromptTemplate = `您是一名专业的${options.shareData.userStory.keshi}主任医生,根据具体的询问,给出初步诊断。
+                症状口述:${options.shareData.userStory['症状口述']}
+                具体询问:${qaContent}
+                结果以JSON格式表示:
+                症状名称为具体的症状,症状描述为用户的感受,持续时间若没有直接说,可以写近期即可。
+                {
+                    "title":"病例标题",
+                    "desc":"病情概括",
+                    "content":"给出完整的治疗方案和建议"
+                }
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5 && task1.progress <= 0.9){
+                            task1.progress += 0.01
+                        }
+                        if(task1.progress >= 0.9){
+                            task1.progress += 0.001
+                        }
+                        // 打印消息体
+                        console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            options.shareData.diagResult = extactAndParseJsonFromString(message.content)
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}
+
+
+const TestShareData = {
+userStory : {
+  "keshi": "神经内科",
+  "sympList": [
+      {
+          "title": "偏头疼",
+          "desc": "已经持续了2天了",
+          "duration": "2天"
+      },
+      {
+          "title": "发冷",
+          "desc": "感觉已经有一天",
+          "duration": "1天"
+      }
+  ],
+  "症状口述": "偏头疼已经持续了2天了,发冷感觉已经有一天。",
+  "questionList": [
+      {
+          "title": "头痛的性质",
+          "desc": "请描述您的头痛是搏动性、压迫性还是其他类型?",
+          "answer":"压迫性头疼"
+      },
+      {
+          "title": "头痛的部位",
+          "desc": "您的头痛主要集中在头部的哪个区域?",
+          "answer":"左侧头疼"
+      },
+      {
+          "title": "伴随症状",
+          "desc": "除了头痛和发冷,您还有其他的症状吗?例如恶心、呕吐、视力模糊或对光敏感等?",
+          "answer":"有点恶心但是没有呕吐"
+      },
+      {
+          "title": "发冷的性质",
+          "desc": "您感到发冷时是否伴随有发热、出汗或其他症状?",
+          "answer":"没有"
+      },
+      {
+          "title": "既往病史",
+          "desc": "您是否有偏头痛或其他头痛的病史?",
+          "answer":"没有"
+      },
+      {
+          "title": "生活习惯",
+          "desc": "您最近的生活习惯是否有变化?例如睡眠不足、压力增大或饮食不规律?",
+          "answer":"经常熬夜,学习压力大"
+      },
+      {
+          "title": "药物使用",
+          "desc": "您是否有服用任何药物来缓解头痛或其他症状?",
+          "answer":"没有"
+      },
+      {
+          "title": "家族病史",
+          "desc": "您的家族中是否有人有类似的头痛或神经系统疾病史?",
+          "answer":"没有"
+      },
+      {
+          "title": "过敏史",
+          "desc": "您是否有药物或其他物质的过敏史?",
+          "answer":"没有"
+      }
+  ]
+}
+}

+ 55 - 0
wisdom-app/src/agent/tasks/poem/poem-desc.ts

@@ -0,0 +1,55 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+
+export function TaskPoemPictureDesc(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        let task1 = new AgentTaskStep({title:"意境分析",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入的诗词
+                let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+                    {name:"诗文内容",type:"text",desc:"诗文句子或段落"}
+                ]});
+                console.log("已获取用户输入:",userInput)
+                if(userInput){
+                    console.log("已获取诗文内容:",userInput['诗文内容'])
+                }
+                if(!userInput?.['诗文内容']){
+                    task1.error = "缺少诗文内容,请重新开始"
+                    resolve(false);
+                }
+
+                    // 文本生成
+                let PromptTemplate = `您是一名专业的美术画家,请您根据古诗文的内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,并且以中国的古风意境为主
+                诗文如下:
+                ${userInput['诗文内容']}
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5){
+                            task1.progress += 0.01
+                        }
+                        // 打印消息体
+                        // console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        options.shareData.PictureDescResult = message.content
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}

+ 43 - 0
wisdom-app/src/agent/tasks/poem/poem-picture.ts

@@ -0,0 +1,43 @@
+import { ModalController } from '@ionic/angular/standalone';
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { ImagineWork, DalleOptions } from 'fmode-ng';
+
+
+export function TaskPoemPictureCreate(options:{
+    modalCtrl:ModalController
+    shareData:any}):AgentTaskStep{
+    let task2 = new AgentTaskStep({title:"意境绘制",shareData:options.shareData})
+    task2.handle = ()=>{
+      return new Promise(resolve=>{
+        // let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+        //   {name:"绘图要求",type:"text",desc:"画风、构图等等"}
+        // ]});
+        // console.log(userInput)
+        console.log("意境绘制:执行过程")
+
+        if(!options.shareData.PictureDescResult){
+          task2.error = "缺少古风描述结果,请重新执行。"
+          resolve(false)
+        }
+        let imagineWork = new ImagineWork();
+        // 图片生成
+        let PicturePrompt = `${options.shareData.PictureDescResult}\n风格:中国古风。画面不带任何文字。`
+        let imgOptions:DalleOptions = {prompt:PicturePrompt}
+        let countDownInt = setInterval(()=>{
+          task2.progress += 0.01
+        },1000)
+        imagineWork?.draw(imgOptions).subscribe((work:any)=>{
+            console.log("imagineWork",work?.toJSON())
+            console.log("images",work?.get("images"))
+            if(work?.get("images")?.length){
+              options.shareData.images = work?.get("images");
+              clearInterval(countDownInt);
+              task2.progress = 1
+              resolve(true)
+            }
+        })
+      })
+
+    }
+    return task2
+}

+ 26 - 0
wisdom-app/src/app/inquiry-human/inquiry-human.component.html

@@ -0,0 +1,26 @@
+<ion-list>
+  <ion-item>
+    <ion-avatar aria-hidden="true" slot="start">
+      <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+    </ion-avatar>
+    <ion-label>Huey</ion-label>
+  </ion-item>
+  <ion-item>
+    <ion-avatar aria-hidden="true" slot="start">
+      <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+    </ion-avatar>
+    <ion-label>Dewey</ion-label>
+  </ion-item>
+  <ion-item>
+    <ion-avatar aria-hidden="true" slot="start">
+      <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+    </ion-avatar>
+    <ion-label>Louie</ion-label>
+  </ion-item>
+  <ion-item>
+    <ion-avatar aria-hidden="true" slot="start">
+      <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
+    </ion-avatar>
+    <ion-label>Fooie</ion-label>
+  </ion-item>
+</ion-list>

+ 0 - 0
wisdom-app/src/app/inquiry-human/inquiry-human.component.scss


+ 22 - 0
wisdom-app/src/app/inquiry-human/inquiry-human.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { InquiryHumanComponent } from './inquiry-human.component';
+
+describe('InquiryHumanComponent', () => {
+  let component: InquiryHumanComponent;
+  let fixture: ComponentFixture<InquiryHumanComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [InquiryHumanComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(InquiryHumanComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 23 - 0
wisdom-app/src/app/inquiry-human/inquiry-human.component.ts

@@ -0,0 +1,23 @@
+import { Component, OnInit } from '@angular/core';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel, IonAvatar } from '@ionic/angular/standalone';
+import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { addIcons } from 'ionicons';
+import { airplane, bluetooth, call, wifi } from 'ionicons/icons';
+addIcons({ airplane, bluetooth, call, wifi });
+
+@Component({
+  selector: 'inquiry-human',
+  templateUrl: './inquiry-human.component.html',
+  styleUrls: ['./inquiry-human.component.scss'],
+  standalone: true,
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent,
+    IonLabel,IonItem,IonList,IonAvatar,IonLabel
+  ]
+})
+export class InquiryHumanComponent  implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {}
+
+}

+ 18 - 9
wisdom-app/src/app/page-inquiry/page-inquiry.component.html

@@ -1,24 +1,33 @@
 
 <ion-content>
 
-  <h1>科室</h1>
-  <ion-input  [value]="keshi" (ionInput)="keshiInput($event)"></ion-input>
+  <!-- <h1>科室</h1>
+  <ion-input  [value]="keshi" placeholder="请输入科室" (ionInput)="keshiInput($event)"></ion-input> -->
 
   <!-- 文本域:生成提示词 -->
-  <h1>症状的描述</h1>
-  <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="文本提示词" autoGrow="true"></ion-textarea>
+  <!-- <h1>症状的描述</h1>
+  <ion-textarea [value]="userPrompt" placeholder="请描述您的症状" (ionInput)="promptInput($event)" autoGrow="true"></ion-textarea> -->
   
   <!-- 按钮:执行消息生成函数 -->
-  <ion-button (click)="sendMessage()" expand="block">初步诊断</ion-button>
+  <!-- <ion-button (click)="sendMessage()" expand="block">初步诊断</ion-button> -->
   
   <!-- 展示:返回消息内容 -->
   <!-- 消息传输过程中,实时预览 -->
-  @if(!isComplete){
+  <!-- @if(!isComplete){
     <div>{{responseMsg}}</div>
-  }
+  } -->
+  
   <!-- 消息传输完成后,实时预览Markdown格式 -->
-  @if(isComplete){
+  <!-- @if(isComplete){
     <fm-markdown-preview class="content-style" [content]="responseMsg"></fm-markdown-preview>
-  }
+  } -->
+  <ion-button (click)="doInqueryTask()">执行问诊任务集</ion-button>
+
+    <!-- 问诊报告生成结果 -->
+    @if(shareData.diagResult){
+      <h1>{{shareData.diagResult.title}}</h1>
+      <h2>{{shareData.diagResult.desc}}</h2>
+      <p>{{shareData.diagResult.content}}</p>
+    }
   
 </ion-content>

+ 86 - 42
wisdom-app/src/app/page-inquiry/page-inquiry.component.ts

@@ -1,7 +1,19 @@
-import { Component, OnInit } from '@angular/core';
-import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton, IonTextarea, IonInput } from '@ionic/angular/standalone';
-/** 引用:从fmode-ng库引用FmodeChatCompletion类 */
-import { FmodeChatCompletion,MarkdownPreviewModule } from 'fmode-ng';
+import { Component,OnInit } from '@angular/core';
+import { IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonIcon, ModalController, IonTextarea, IonInput } from '@ionic/angular/standalone';
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { addIcons } from 'ionicons';
+import { radioButtonOffOutline, reloadOutline, checkmarkCircleOutline, closeCircleOutline } from 'ionicons/icons';
+import { TaskExecutor } from 'src/agent/agent.start';
+import { AgentUserInputComponent } from 'src/agent/agent-user-input/agent-user-input.component';
+import { FmodeChatCompletion, ImagineWork, DalleOptions } from "fmode-ng";
+import { TaskPoemPictureDesc } from 'src/agent/tasks/poem/poem-desc';
+import { TaskPoemPictureCreate } from 'src/agent/tasks/poem/poem-picture';
+import { DecimalPipe } from '@angular/common';
+import { TaskInqueryUserStory } from 'src/agent/tasks/inquiry/1.inquiry-user-story';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+import { TaskInqueryDoctorQuestion } from 'src/agent/tasks/inquiry/2.inquiry-doctor-question';
+import { TaskInqueryUserAnswer } from 'src/agent/tasks/inquiry/3.inquiry-user-answer';
+addIcons({radioButtonOffOutline,reloadOutline,checkmarkCircleOutline,closeCircleOutline})
 
 @Component({
   selector: 'app-page-inquiry',
@@ -9,48 +21,80 @@ import { FmodeChatCompletion,MarkdownPreviewModule } from 'fmode-ng';
   styleUrls: ['./page-inquiry.component.scss'],
   standalone: true,
   imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonButton,IonTextarea,IonInput,
-    // 引入fm-markdown-preview组件模块
-    MarkdownPreviewModule
   ],
 })
 export class PageInquiryComponent  implements OnInit {
-  constructor() {}
-  ngOnInit(){}
-  
-  // 用户输入提示词
-  keshi:string = "门诊"
-  keshiInput(ev:any){
-    this.keshi = ev.detail.value;
-  }
-  // 用户输入提示词
-  userPrompt:string = "请描述您的症状"
-  promptInput(ev:any){
-    this.userPrompt = ev.detail.value;
+  constructor(private modalCtrl:ModalController) {
+
+
   }
-  // 属性:组件内用于展示消息内容的变量
-  responseMsg:any = ""
-  // 方法:实例化completion对象,传入消息数组,并订阅生成的可观察对象。
-  isComplete:boolean = false; // 定义完成状态属性,用来标记是否补全完成
-  sendMessage(){
-    console.log("create")
-
-    let PromptTemplate = `
-    您作为一名专业的${this.keshi}医生,请您根据用户描述的症状,给出初步的诊断,并给出一些建议。
-    以下是用户的口述:${this.userPrompt}
-    `
-
-    let completion = new FmodeChatCompletion([
-      {role:"system",content:""},
-      {role:"user",content:PromptTemplate}
-    ])
-    completion.sendCompletion().subscribe((message:any)=>{
-      // 打印消息体
-      console.log(message.content)
-      // 赋值消息内容给组件内属性
-      this.responseMsg = message.content
-      if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
-        this.isComplete = true
-      }
+
+  taskList:AgentTaskStep[] = []
+
+  wait(duration:number=1000){
+    return new Promise(resolve=>{
+      setTimeout(() => {
+          resolve(true)
+      }, duration);
     })
   }
+
+  shareData:any = {}
+
+  ngOnInit(){}
+  doInqueryTask(){
+    let task1 = TaskInqueryUserStory({shareData:this.shareData,modalCtrl:this.modalCtrl});
+    let task2 = TaskInqueryDoctorQuestion({shareData:this.shareData,modalCtrl:this.modalCtrl});
+    let task3 = TaskInqueryUserAnswer({shareData:this.shareData,modalCtrl:this.modalCtrl});
+
+    // 定义任务集
+    let InquireServiceTaskList = [
+      task1,task2,task3
+    ]
+    // 传递给显示组件
+    this.taskList = InquireServiceTaskList
+    // 开始执行任务
+    TaskExecutor(InquireServiceTaskList)
+  }
+
+  //  http://localhost:4200/
+  // 用户输入提示词
+  // keshi:string = ""
+  // keshiInput(ev:any){
+  //   this.keshi = ev.detail.value;
+  // }
+  // // 用户输入提示词
+  // userPrompt:string = ""
+  // promptInput(ev:any){
+  //   this.userPrompt = ev.detail.value;
+  // }
+
+  // // 属性:组件内用于展示消息内容的变量
+  // responseMsg:any = ""
+  // // 方法:实例化completion对象,传入消息数组,并订阅生成的可观察对象。
+  // isComplete:boolean = false; // 定义完成状态属性,用来标记是否补全完成
+  // sendMessage(){
+  //   console.log("create")
+
+  //   let PromptTemplate = `
+  //   您作为一名专业的${this.keshi}医生,请您根据用户描述的症状,给出初步的诊断,并给出一些建议。
+  //   以下是用户的口述:${this.userPrompt}
+  //   `
+
+  //   let completion = new FmodeChatCompletion([
+  //     {role:"system",content:""},
+  //     {role:"user",content:PromptTemplate}
+  //   ])
+
+  //   completion.sendCompletion().subscribe((message:any)=>{
+  //     // 打印消息体
+  //     console.log(message.content)
+      
+  //     // 赋值消息内容给组件内属性
+  //     this.responseMsg = message.content
+  //     if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+  //       this.isComplete = true
+  //     }
+  //   })
+  // }
 }

+ 4 - 1
wisdom-app/src/app/poem-picture/poem-picture.component.html

@@ -8,9 +8,12 @@
 
 <ion-content [fullscreen]="true">
   <!-- 生成提示词 -->
-  <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="古诗文填写" autoGrow="true"></ion-textarea>
+  <ion-textarea [value]="userPrompt" (ionInput)="promptInput($event)" placeholder="请输入古诗" autoGrow="true"></ion-textarea>
   <ion-button (click)="createImage()" expand="block">生成意境</ion-button>
   <!-- 意境画面提示词 -->
+   <div>
+    明月几时有,把酒问青天。不知天上宫阙,今夕是何年?
+   </div>
   <div>
     {{PictureDescResult}}
   </div>

+ 24 - 9
wisdom-app/src/app/poem-picture/poem-picture.component.ts

@@ -15,18 +15,29 @@ import { DalleOptions, ImagineWork, FmodeChatCompletion } from 'fmode-ng';
     IonTextarea
   ],
 })
+
 export class PoemPictureComponent  implements OnInit {
-  userPrompt:string = "犬吠水声中,桃花带露浓。\n树深时见鹿,溪午不闻钟。"
+  /**
+   * 用户输入的文本
+   */
+  userPrompt:string = ""
   promptInput(ev:any){
-    this.userPrompt = ev.detail.value;
+    console.log(ev.detail.value)
+    if (ev.detail.value.length > 0){
+      this.userPrompt = ev.detail.value;
+    }
   }
-  imagineWork:ImagineWork|undefined
+
+  imagineWork:ImagineWork
   images:Array<string> = []
   constructor(
   ){
     // 示例任务,自己生成图片后请存储新的ID
     this.imagineWork = new ImagineWork("4mPR0IW1i5");
     this.imagineWork.fetchTask().then(work=>{
+      if(work){
+        this.imagineWork.id = work.id
+      }
       this.images = this.imagineWork?.images || [];
     })
   }
@@ -34,6 +45,7 @@ export class PoemPictureComponent  implements OnInit {
   PictureDescResult:string = `` // 画面描述结果
   async createImage(){
     this.imagineWork = new ImagineWork();
+    if (this.userPrompt.length > 0){
     // 文本生成
     let PromptTemplate = `您是一名专业的美术画家,请您根据下面提供的的内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,并且以中国的古风意境为主
     诗文如下:
@@ -48,20 +60,23 @@ export class PoemPictureComponent  implements OnInit {
       console.log(message.content)
       // 赋值消息内容给组件内属性
       this.PictureDescResult = message.content
-      if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+      if(message?.complete){ // 判断message为完成状态,则设置isComplete为完成
         // 图片生成
         let PicturePrompt = `${this.PictureDescResult}\n风格:中国古风。画面不带任何文字。突出色彩。`
       let options:DalleOptions = {prompt:PicturePrompt}
       this.imagineWork?.draw(options).subscribe(work=>{
-          console.log("imagineWork",work.toJSON())
-          console.log("images",work.get("images"))
-          if(work.get("images").length){
-            this.images = work.get("images");
+          console.log("imagineWork",work?.toJSON())
+          console.log("images",work?.get("images"))
+          if(work?.get("images")?.length){
+            this.images = work?.get("images");
           }
       })
       }
     })
-
+  }
+  else{
+    this.userPrompt = "请提供您想要描述的诗文内容,我将根据其意境为您创作一幅古风画面的简短描述。"
+  }
     
   }
   ngOnInit() {}

+ 0 - 1
wisdom-app/src/app/tab1/tab1.page.html

@@ -26,5 +26,4 @@
   <ion-button expand="block" color="primary" size="large" (click)="goToPicture()">
     生成图片
   </ion-button>
-  <app-explore-container name="智养"></app-explore-container>
 </ion-content>

+ 2 - 2
wisdom-app/src/app/tab1/tab1.page.ts

@@ -27,14 +27,14 @@ export class Tab1Page {
    * Go to the ai page
    */
   goToPage1(){
-    this.router.navigate(['/tabs/inquiry'])
+    this.router.navigate(['/tabs/inquiry/ai'])
   }
 
   /**
    * Go to the human page
    */
   goToPage2(){
-    this.router.navigate(['/tabs/page-test'])
+    this.router.navigate(['/tabs/inquiry/human'])
   }
 
   goToPicture(){

+ 0 - 31
wisdom-app/src/app/tab2/tab2.page.html

@@ -7,36 +7,5 @@
 </ion-header>
 
 <ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">Tab 2</ion-title>
-    </ion-toolbar>
-  </ion-header>
 
-  <ion-list>
-    <ion-item>
-      <ion-avatar aria-hidden="true" slot="start">
-        <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-      </ion-avatar>
-      <ion-label>Huey</ion-label>
-    </ion-item>
-    <ion-item>
-      <ion-avatar aria-hidden="true" slot="start">
-        <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-      </ion-avatar>
-      <ion-label>Dewey</ion-label>
-    </ion-item>
-    <ion-item>
-      <ion-avatar aria-hidden="true" slot="start">
-        <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-      </ion-avatar>
-      <ion-label>Louie</ion-label>
-    </ion-item>
-    <ion-item>
-      <ion-avatar aria-hidden="true" slot="start">
-        <img alt="" src="https://ionicframework.com/docs/img/demos/avatar.svg" />
-      </ion-avatar>
-      <ion-label>Fooie</ion-label>
-    </ion-item>
-  </ion-list>
 </ion-content>

+ 1 - 6
wisdom-app/src/app/tab3/tab3.page.html

@@ -7,11 +7,6 @@
 </ion-header>
 
 <ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">Tab 3</ion-title>
-    </ion-toolbar>
-  </ion-header>
 
-  <app-explore-container name="Tab 3 page"></app-explore-container>
+  
 </ion-content>

+ 2 - 0
wisdom-app/src/app/tab3/tab3.page.ts

@@ -1,6 +1,7 @@
 import { Component } from '@angular/core';
 import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { AgentTaskStep } from 'src/agent/agent.task';
 
 @Component({
   selector: 'app-tab3',
@@ -11,4 +12,5 @@ import { ExploreContainerComponent } from '../explore-container/explore-containe
 })
 export class Tab3Page {
   constructor() {}
+
 }

+ 6 - 1
wisdom-app/src/app/tabs/tabs.routes.ts

@@ -32,10 +32,15 @@ export const routes: Routes = [
           import('../poem-picture/poem-picture.component').then((m) => m.PoemPictureComponent),
       },
       {
-        path: 'inquiry',
+        path: 'inquiry/ai',
         loadComponent: () =>
           import('../page-inquiry/page-inquiry.component').then((m) => m.PageInquiryComponent),
       },
+      {
+        path: 'inquiry/human',
+        loadComponent: () =>
+          import('../inquiry-human/inquiry-human.component').then((m) => m.InquiryHumanComponent),
+      },
       {
         path: 'page-test',
         loadComponent: () =>

+ 9 - 0
wisdom-app/src/app/test-chat-panel/test-chat-panel.component.html

@@ -0,0 +1,9 @@
+<app-chat-panel *ngIf="leftButtons?.length&&modelList?.length" #chatComp 
+[roleId]="roleId" 
+[chatId]="chatId" 
+[leftButtons]="leftButtons" 
+[modelList]="modelList" 
+[isDirect]="isDirect"
+[hideModalSelect]="hideModalSelect"
+[hideInputPreview]="hideInputPreview"
+></app-chat-panel>

+ 3 - 0
wisdom-app/src/app/test-chat-panel/test-chat-panel.component.scss

@@ -0,0 +1,3 @@
+app-chat-panel {
+    height: 100vh;
+}

+ 22 - 0
wisdom-app/src/app/test-chat-panel/test-chat-panel.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { TestChatPanelComponent } from './test-chat-panel.component';
+
+describe('TestChatPanelComponent', () => {
+  let component: TestChatPanelComponent;
+  let fixture: ComponentFixture<TestChatPanelComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [TestChatPanelComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(TestChatPanelComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 243 - 0
wisdom-app/src/app/test-chat-panel/test-chat-panel.component.ts

@@ -0,0 +1,243 @@
+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';
+
+// 添加Icons
+import { addIcons } from 'ionicons';
+import * as icons from 'ionicons/icons';
+addIcons(icons);
+
+@Component({
+  selector: 'app-test-chat-panel',
+  templateUrl: './test-chat-panel.component.html',
+  styleUrls: ['./test-chat-panel.component.scss'],
+  standalone: true,
+  imports:[
+    CommonModule,
+    ChatPanelComponent,
+  ]
+})
+export class TestChatPanelComponent  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){
+            // 自定义左下角操作按钮
+            console.log("左下角操作按钮",this.chatComp.fmodeChat.leftButtons);
+            this.chatComp.fmodeChat.leftButtons = this.leftButtons;
+            
+            // 自定义角色名称
+            console.log("自定义角色",this.chatComp.fmodeChat.role);
+                        this.chatComp.fmodeChat.role.set("name","晓晓");
+            this.chatComp.fmodeChat.role.set("title","心理咨询师");
+            this.chatComp.fmodeChat.role.set("desc","一名亲切和蔼的心理咨询师,晓晓,年龄36岁");
+            this.chatComp.fmodeChat.role.set("tags",["焦虑","抑郁"]);
+            this.chatComp.fmodeChat.role.set("avatar","https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/aigc/imagine/Q4Zif7fTbK-0.png")
+            this.chatComp.fmodeChat.role.set("prompt",`
+# 角色设定
+您是一名亲切和蔼的心理咨询师,晓晓,年龄36岁,需要完成陪来访者聊聊天,随意轻松一些。
+
+# 对话环节
+0.破冰,互相了解,引导用户介绍自己
+1.拓展话题,根据用户的介绍,拓展一些和其心理状态相关的话题
+- 引导,可深入的点,以用户自述为主
+- 当信息充足时候,确认用户心理状态,并进入下一个环节
+2.引导收尾,委婉引导用户结束本次对话
+- 用户同意结束后,结束本次对话,如果依依不舍,可以再陪聊一会儿`);
+//             this.chatComp.fmodeChat.role.set("name","晓晓");
+//             this.chatComp.fmodeChat.role.set("title","主任医师");
+//             this.chatComp.fmodeChat.role.set("desc","一名专业的全科医生,晓晓,年龄36岁");
+//             this.chatComp.fmodeChat.role.set("tags",["呼吸道","感染科"]);
+//             this.chatComp.fmodeChat.role.set("avatar","https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/aigc/imagine/Q4Zif7fTbK-0.png")
+//             this.chatComp.fmodeChat.role.set("prompt",`
+// # 角色设定
+// 您是一名专业的全科医生,晓晓,年龄36岁,需要完成一次完整的门诊服务。
+
+// # 对话环节
+// 0.导诊(根据用户基本情况,引导挂号合适的科室)
+// 1.预设的问询方式(感冒问呼吸、肚子疼叩诊)
+// - 打招呼,以用户自述为主
+// - 当信息充足时候,确认用户症状对应的科室,并进入下一个环节
+// 2.拓展的问询细节
+// 例如:用户反映呼吸不畅,拓展出:是否咳嗽;是否感觉痛或者痒等其他需要的问题。
+// - 当问询细节补充完成后进入下一个环节
+// 3.初步的诊断结果,并且同时列出检查检验项目
+// 初步诊断:确定需要有哪些进一步检查
+// 检查检验:获取医学客观数据
+// - 等待用户提交客观数据,进入下一阶段
+// 4.给出诊断方案并给出处方
+
+// # 开始话语
+// 当您准备好了,可以以一个医生的身份,向来访的用户打招呼。
+//             `);
+
+            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
+        })
+      }
+   }
+}