import { CommonModule } from '@angular/common'; import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { ModalController, IonHeader, IonTitle, IonContent, IonButton, IonList, IonItem, IonLabel, IonIcon, IonCardContent, IonCardSubtitle, IonCardTitle, IonCardHeader, IonCard, IonRow, IonCol, IonGrid, IonAvatar, IonBadge, IonText, IonListHeader, IonToolbar, IonFooter } from '@ionic/angular/standalone'; import { NavController } from '@ionic/angular/standalone'; import { ChatPanelOptions, FmChatModalInput, FmodeChat, FmodeChatMessage, openChatPanelModal } from 'fmode-ng'; // import { ModalAudioMessageComponent } from 'fmode-ng/lib/aigc/chat/chat-modal-input/modal-audio-message/modal-audio-message.component'; import Parse from "parse"; import { CloudObject, CloudQuery } from 'src/lib/ncloud'; @Component({ selector: 'app-tab2', templateUrl: 'tab2.page.html', styleUrls: ['tab2.page.scss'], standalone: true, imports: [ CommonModule, IonHeader, IonTitle, IonContent, IonButton, IonList, IonItem, IonLabel, IonIcon, IonAvatar, IonCardContent, IonCardSubtitle, IonCardTitle, IonCardHeader, IonCard, IonRow, IonCol, IonGrid, IonAvatar, IonBadge, IonText, IonListHeader, IonToolbar, IonFooter, // ASR语音输入模块 FmChatModalInput, // ModalAudioMessageComponent ] }) export class Tab2Page { constructor( private modalCtrl: ModalController, private router: Router, private navCtrl: NavController, ) { } goTraining() { this.navCtrl.navigateRoot(['tabs', 'demo', 'training']) } title: string = "123" /** 示例:问诊ChatPanel面板 */ openInquiry(chatId?: string) { localStorage.setItem("company", "E4KpGvTEto") let options: ChatPanelOptions = { roleId: "2DXJkRsjXK", // 预设,无需更改 chatId: chatId, // 若存在,则恢复会话。若不存在,则开启新会话 onChatInit: (chat: FmodeChat) => { console.log("onChatInit"); console.log("Chat类", chat); console.log("预设角色", chat.role); // 角色名称 chat.role.set("name", "晓晓"); // 角色称号 chat.role.set("title", "全科医生"); // 角色描述 chat.role.set("desc", "一名亲切和蔼的门诊全科主任医生,晓晓,年龄36岁"); // 角色标签 chat.role.set("tags", ["全科", "门诊"]); // 角色头像 chat.role.set("avatar", "https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/aigc/imagine/Q4Zif7fTbK-0.png") // 角色提示词 chat.role.set("prompt", ` # 角色设定 您是一名亲切和蔼的专业的全科医生,晓晓,年龄36岁,需要完成一次完整的门诊服务。 # 对话环节 请您严格按照以下环节和用户展开对话,并且注意完成每个环节时,一定要携带[xx完成]的标记。 ## 1. 导诊环节 - **开始话语**: - “欢迎来到医院,请问您是第一次来吗?我会帮助您找到合适的科室。” - **进入下个环节条件**: - “已经大致了解您反映的情况,建议您到XX科室。[导诊完成] ## 2. 问诊环节 - **对话内容**: - “请您详细描述一下您的情况,我需要了解您的病史和相关症状。” - “您是否有过敏史或其他健康问题?” - “根据您的情况,我认为我们需要进行一些检查,您觉得可以吗?” - **进入下个环节的条件**: - “谢谢您的配合,我将为您安排相关检查。[问诊完成]” ## 3. 检查环节 - **对话内容**: - “我们已经完成了问诊,现在我会为您安排必要的检查。” - “请您稍等,检查结果会在不久后出来。” - “检查结果已经出来了,请您填写下报告的具体数据,让我来为您分析一下。” - **进入下个环节的条件**: - “检查结果已经初步分析,接下来需要请主任医生开始诊断。[检查完成]” ## 4. 诊断与处方环节 - **对话内容**: - “根据问诊和检查结果,我的诊断是……” - “接下来,我会为您开具相应的处方,请您仔细阅读治疗方案和注意事项。” - “您是否有任何问题或者需要进一步的解释?” - **进入下个环节的条件**: - “感谢您的配合,您的处方已经开好,请您按照建议进行后续的治疗或复诊安排。[处方完成]” # 开始话语 当您准备好了,可以以一个医生的身份,向来访的用户打招呼。`); // 对话灵感分类 let promptCates = [ { "img": "https://file-cloud.fmode.cn/UP2cStyjuk/20231211/r1ltv1023812146.png", "name": "外科" }, { "img": "https://file-cloud.fmode.cn/UP2cStyjuk/20231211/fo81fg034154259.png", "name": "内科" }, { "img": "https://file-cloud.fmode.cn/UP2cStyjuk/20231211/fc1nqi034201098.png", "name": "心理" } ] setTimeout(() => { chat.role.set("promptCates", promptCates) }, 500); // 对话灵感列表 let promptList = [ { cate: "外科123", img: "https://file-cloud.fmode.cn/UP2cStyjuk/20231211/r1ltv1023812146.png", messageList: ["局部疼痛或肿胀", "伤口出血或感染", "关节活动受限", "体表肿块或结节", "外伤后活动障碍", "皮肤溃疡不愈合", "异物刺入或嵌顿", "术后并发症复查", "肢体麻木或无力", "运动损伤疼痛"] }, { cate: "内科", img: "https://file-cloud.fmode.cn/UP2cStyjuk/20231211/fo81fg034154259.png", messageList: ["反复发热或低热", "持续咳嗽咳痰", "胸闷气短心悸", "慢性腹痛腹泻", "头晕头痛乏力", "体重骤增或骤减", "食欲异常或消化不良", "尿频尿急尿痛", "睡眠障碍易醒", "异常出汗或怕冷"] }, { cate: "心理", img: "https://file-cloud.fmode.cn/UP2cStyjuk/20231211/fc1nqi034201098.png", messageList: ["持续情绪低落", "焦虑紧张不安", "失眠或睡眠过多", "注意力难以集中", "社交恐惧回避", "强迫思维或行为", "记忆减退疑虑", "躯体无器质性疼痛", "自杀倾向念头", "现实感丧失体验"] }, ] let ChatPrompt = Parse.Object.extend("ChatPrompt"); setTimeout(() => { chat.promptList = promptList.map(item => { let prompt = new ChatPrompt(); prompt.set(item); prompt.img = item.img; return prompt; }) }, 500); // 功能按钮区域预设 chat.leftButtons = [ { // 提示 当角色配置预设提示词时 显示 title: "话题灵感", // 按钮标题 showTitle: true, // 是否显示标题文字 icon: "color-wand-outline", // 标题icon图标 onClick: () => { // 按钮点击事件 chat.isPromptModalOpen = true }, show: () => { // 按钮显示条件 return chat?.promptList?.length // 存在话题提示词时显示 } }, { // 总结 结束并归档本次对话 title: "门诊归档", showTitle: true, icon: "archive-outline", onClick: () => { // 门诊归档,记录用户门诊咨询,并进行过程评价 console.log(chat?.chatSession) // 本次会话内容数据 }, show: () => { return true // 一直显示 } } ] }, onMessage: (chat: FmodeChat, message: FmodeChatMessage) => { console.log("onMessage", message) let content: any = message?.content if (typeof content == "string") { // 根据阶段标记判断下一步处理过程 if (content.includes('[导诊完成]')) { // 进入问诊环节 console.log('进入问诊环节'); } else if (content.includes('[问诊完成]')) { // 进入检查环节 console.log('进入检查环节'); } else if (content.includes('[检查完成]')) { // 进入诊断与处方环节 console.log('进入诊断与处方环节'); } else if (content.includes('[处方完成]')) { // 结束会话或其他逻辑 console.log('结束会话'); } } }, onChatSaved: (chat: FmodeChat) => { // chat?.chatSession?.id 本次会话的 chatId console.log("onChatSaved", chat, chat?.chatSession, chat?.chatSession?.id) } } openChatPanelModal(this.modalCtrl, options) } openConsult(chatId?: string) { localStorage.setItem("company", "E4KpGvTEto") let options: ChatPanelOptions = { roleId: "2DXJkRsjXK", // 预设,无需更改 chatId: chatId, // 若存在,则恢复会话。若不存在,则开启新会话 onChatInit: (chat: FmodeChat) => { console.log("onChatInit"); console.log("Chat类", chat); console.log("预设角色", chat.role); // 角色名称 chat.role.set("name", "宋珀尔"); // 角色称号 chat.role.set("title", "专业教练"); // 角色描述 chat.role.set("desc", "一名亲切和蔼的健身教练,宋珀尔,年龄26岁"); // 角色标签 chat.role.set("tags", ['跑步', '动感单车']); // 角色头像 chat.role.set("avatar", "/assets/avatars/jiaolian1.jpg") // 角色提示词 chat.role.set("prompt", ` # 角色设定 您是一名亲切和蔼的健身教练,宋珀尔,年龄26岁,需要您解答用户健身方面的专业问题。 请您模仿一个正常教练对话,语言简短不需要长篇大论。 `); // 对话灵感分类 let promptCates = [ { "img": "/assets/icon/yy.jpg", "name": "有氧" }, { "img": "/assets/icon/jz.jpg", "name": "减脂" }, { "img": "/assets/icon/zj.jpg", "name": "增肌" } ] setTimeout(() => { chat.role.set("promptCates", promptCates) }, 500); // 对话灵感列表 let promptList = [ { cate: "有氧", img: "/assets/icon/yy.jpg", messageList: [ "有氧运动多久才能有效减脂?", "跑步和游泳哪个减肥效果更好?", "空腹有氧真的更燃脂吗?", "有氧运动会不会掉肌肉?", "心率控制在多少才能高效燃脂?", "每天做有氧运动会不会过度疲劳?", "有氧运动前要不要吃东西?", "椭圆机和跑步机哪个更适合新手?", "跳绳会不会伤膝盖?", "有氧运动后怎么补充能量?" ] }, { cate: "减脂", img: "/assets/icon/jz.jpg", messageList: [ "减脂一定要做有氧吗?", "为什么体重没变但看起来瘦了?", "局部减脂(如瘦肚子)真的存在吗?", "减脂期每天应该吃多少热量?", "低碳饮食和低脂饮食哪个更适合减脂?", "为什么运动后体重反而增加了?", "减脂期可以吃零食吗?", "平台期怎么突破?", "晚上吃东西会不会更容易长胖?", "减脂期要不要计算蛋白质摄入?" ] }, { cate: "增肌", img: "/assets/icon/zj.jpg", messageList: [ "增肌一定要喝蛋白粉吗?", "为什么练了很久肌肉不长?", "增肌期可以同时减脂吗?", "训练后多久补充蛋白质最有效?", "增肌需要每天练同一个部位吗?", "徒手训练(如俯卧撑)能有效增肌吗?", "增肌期体重不增长是怎么回事?", "肌肉酸痛还能继续练吗?", "增肌训练每组做多少次最合适?", "睡眠对增肌的影响有多大?" ] }, ] let ChatPrompt = Parse.Object.extend("ChatPrompt"); setTimeout(() => { chat.promptList = promptList.map(item => { let prompt = new ChatPrompt(); prompt.set(item); prompt.img = item.img; return prompt; }) }, 500); // 功能按钮区域预设 chat.leftButtons = [ { // 提示 当角色配置预设提示词时 显示 title: "话题灵感", // 按钮标题 showTitle: true, // 是否显示标题文字 icon: "color-wand-outline", // 标题icon图标 onClick: () => { // 按钮点击事件 chat.isPromptModalOpen = true }, show: () => { // 按钮显示条件 return chat?.promptList?.length // 存在话题提示词时显示 } }, ] }, onMessage: (chat: FmodeChat, message: FmodeChatMessage) => { console.log("onMessage", message) let content: any = message?.content if (typeof content == "string") { // 根据阶段标记判断下一步处理过程 if (content.includes('[导诊完成]')) { // 进入问诊环节 console.log('进入问诊环节'); } else if (content.includes('[问诊完成]')) { // 进入检查环节 console.log('进入检查环节'); } else if (content.includes('[检查完成]')) { // 进入诊断与处方环节 console.log('进入诊断与处方环节'); } else if (content.includes('[处方完成]')) { // 结束会话或其他逻辑 console.log('结束会话'); } } }, onChatSaved: async (chat: FmodeChat) => { // chat?.chatSession?.id 本次会话的 chatId console.log("onChatSaved", chat, chat?.chatSession, chat?.chatSession?.id) let chatId = chat?.chatSession?.id; console.log("chatId", chatId) let query = new CloudQuery("TrainingConsult"); let trainingConsult = await query.get(chatId); console.log("trainingConsult", trainingConsult); if (!trainingConsult?.id) { // 若无重复记录,则实例化一个新的咨询记录 trainingConsult = new CloudObject("TrainingConsult") } trainingConsult.set({ "chatId": chatId, "messageList": chat.messageList, "name": chat.role.get("name"), "avatar": chat.role.get("avatar") }) console.log("trainingConsult", trainingConsult) trainingConsult.save(); } } openChatPanelModal(this.modalCtrl, options) } // 加载健康咨询记录 consultList: Array = [] async loadConsult() { let query = new CloudQuery("TrainingConsult"); this.consultList = await query.find() console.log(this.consultList) } /** * 开始聊天 */ openChat() { let options: ChatPanelOptions = { roleId: "2DXJkRsjXK", onChatSaved: (chat: FmodeChat) => { // chat?.chatSession?.id 本次会话的 chatId console.log("onChatSaved", chat, chat?.chatSession, chat?.chatSession?.id) }, } openChatPanelModal(this.modalCtrl, options) } /** * 恢复聊天 * @chatId 从onChatSaved生命周期中,获取chat?.chatSession?.id */ restoreChat(chatId: string) { let options: ChatPanelOptions = { roleId: "2DXJkRsjXK", chatId: chatId } openChatPanelModal(this.modalCtrl, options) } goChat() { this.router.navigateByUrl("/chat/session/role/2DXJkRsjXK") } // audioModalHeightPoint:number = 0.35; // async startTalk(){ // // 根据手机兼容性,适配组件弹出高度 // let height = document.body.clientHeight || 960; // this.audioModalHeightPoint = Number((165/height).toFixed(2)); // // 弹出组件 // let modal:any // let chat:any // modal = await this.modalCtrl.create({ // component:ModalAudioMessageComponent, // componentProps:{ // chat:chat, // modal:modal, // onBreakPointSet:()=>{ // modal?.setCurrentBreakpoint(this.audioModalHeightPoint) // } // } // }) // modal.present(); // } }