2 lines
14 KiB
JavaScript
2 lines
14 KiB
JavaScript
import{d as e,a,r as t,c as s,o as l,b as n,e as o,f as i,w as c,i as u,E as r,j as d,t as m,l as f,m as v,F as p,n as _,k as g,g as h,G as y,y as b,z as k,x as w,S as x,u as C,I as $}from"./index-pnQqyMoS.js";import{_ as E}from"./config-doctor.TgARj_nM.js";import{r as j}from"./cases.4_d-snq4.js";import{F as D,a as A,r as I,b as T,d as O,u as N,s as q,e as P}from"./session.CQodznPl.js";import{c as S,a as F,b as V}from"./navigation.DVfJwOxJ.js";import{_ as G}from"./_plugin-vue_export-helper.BCo6x5W8.js";const K={id:"case-1006004",title:"持续胸痛3小时",patientName:"陈先生",gender:"男",age:60,department:"心血管内科",scene:"住院部",caseNo:"1006004",tone:"orange",mode:"training"};function M(e){if(!Number.isInteger(e)||e<=0)throw new Error("未找到当前会话,请先生成模拟场景")}async function R(e,a){var t;M(e);const s=await fetch(`${D}/sessions/${e}/${a}`,{method:"GET",headers:A()});if(!s.ok)throw new Error(await I(s));const l=await s.json();if("OK"!==l.code||!Array.isArray(null==(t=l.data)?void 0:t.items))throw new Error(l.message||"检查列表加载失败");return l.data.items}async function U(e,a,t){var s;M(e);const l=await fetch(`${D}/sessions/${e}/${a}/${encodeURIComponent(t)}`,{method:"POST",headers:A()});if(!l.ok)throw new Error(await I(l));const n=await l.json();if("OK"!==n.code||!(null==(s=n.data)?void 0:s.item_code))throw new Error(n.message||"检查结果获取失败");return n.data}const z=G(e({__name:"chat",props:{caseItem:{}},emits:["open-settings","open-profile","go-home"],setup(e,{emit:D}){const A=e,I=D,G=S(I),M=F(I),z=V(I),B=a({patient:{name:"陈先生",gender:"男",age:60,department:"心血管内科",chiefComplaint:"持续胸痛3小时"},stages:[{key:"history",label:"病史采集",active:!0},{key:"diagnosis",label:"初步诊断",active:!1},{key:"treatment",label:"治疗方案",active:!1}],messages:[]}),Q=t(""),H=t(!1),J=t(!1),L=t(!1),W=t(0),X=t(""),Y=t(!1),Z=t(!1),ee=t(!1),ae=t(null),te=t(null),se=t([]),le=t([]),ne=t(!1),oe=t(!1),ie=t(!1);let ce=null,ue=null,re=null;const de=s((()=>A.caseItem||te.value)),me=s((()=>B.patient.chiefComplaint.includes("胸痛")?"胸痛":B.patient.chiefComplaint.slice(0,6)));function fe(){(function(e){const a=e||K,t="毕波涛"===a.patientName?"陈先生":a.patientName;return Promise.resolve({patient:{name:t,gender:a.gender,age:a.age,department:a.department,chiefComplaint:a.title},stages:[{key:"history",label:"病史采集",active:!0},{key:"diagnosis",label:"初步诊断",active:!1},{key:"treatment",label:"治疗方案",active:!1}],messages:[{id:"patient-initial",role:"patient",content:"心血管内科"===a.department?"医生,我心口这儿针扎一样疼了两个小时了,现在感觉喘气都费劲。":`医生,我这次主要是${a.title},有点担心。`,label:"患者"},{id:"mentor-initial",role:"mentor",content:"观察患者的面部表情和生命体征。你的第一个问题应该如何询问,以明确疼痛的性质?",label:"王主任"}]})})(de.value).then((e=>{var a;Object.assign(B.patient,e.patient),B.stages=e.stages;const t=T();if(null==(a=null==t?void 0:t.session)?void 0:a.session_id)return ae.value=t.session.session_id,B.messages=t.session.patient_opening?[{id:`patient-opening-${t.session.session_id}`,role:"patient",content:t.session.patient_opening,label:"患者"}]:[],Ce(),void we("开始问诊");B.messages=e.messages,Ce()}))}async function ve(){if(L.value)return;if(H.value||J.value)return void $e("请等待当前回复完成");const e=ae.value;if(e){L.value=!0;try{const a=await O(e);N(a.status),y({url:"/pages/diagnosis/diagnosis"})}catch(a){$e(a instanceof Error?a.message:"完成采集失败")}finally{L.value=!1}}else $e("未找到当前会话,请先生成模拟场景")}async function pe(){const e=ae.value;if(e){if(ee.value=!1,Z.value=!0,!(le.value.length>0||oe.value)){oe.value=!0;try{le.value=await function(e){return R(e,"auxiliary-exams")}(e)}catch(a){$e(a instanceof Error?a.message:"辅助检查列表加载失败")}finally{oe.value=!1}}}else $e("未找到当前会话,请先生成模拟场景")}async function _e(){const e=ae.value;if(e){if(Z.value=!1,ee.value=!0,!(se.value.length>0||ne.value)){ne.value=!0;try{se.value=await function(e){return R(e,"physical-exams")}(e)}catch(a){$e(a instanceof Error?a.message:"体格检查列表加载失败")}finally{ne.value=!1}}}else $e("未找到当前会话,请先生成模拟场景")}async function ge(e){const a=ae.value;if(a&&!ie.value){ie.value=!0;try{const t=await function(e,a){return U(e,"physical-exams",a)}(a,e.item_code);ee.value=!1,ye("体格检查",t)}catch(t){$e(t instanceof Error?t.message:"体格检查结果获取失败")}finally{ie.value=!1}}}async function he(e){const a=ae.value;if(a&&!ie.value){ie.value=!0;try{const t=await function(e,a){return U(e,"auxiliary-exams",a)}(a,e.item_code);Z.value=!1,ye("辅助检查",t)}catch(t){$e(t instanceof Error?t.message:"辅助检查结果获取失败")}finally{ie.value=!1}}}function ye(e,a){const t=Date.now(),s=[{id:`doctor-exam-${t}`,role:"doctor",content:`选择${e}:${a.item_name}`,label:"我"},{id:`mentor-exam-${t+1}`,role:"mentor",content:be(a),label:"AI助手"}];B.messages.push(...s),Ce()}function be(e){const a=[e.is_abnormal?"异常":"",e.is_key?"关键检查":"",e.already_ordered?"已检查过":""].filter(Boolean),t=a.length?`(${a.join(",")})`:"";return`${e.item_name}${t}:${e.result_text||"暂无结果。"}`}function ke(){const e=Q.value.trim();if(e&&!H.value){if(Q.value="",ae.value)return B.messages.push({id:`doctor-${Date.now()}`,role:"doctor",content:e,label:"我"}),Ce(),void we(e);H.value=!0,function(e){const a=e.trim(),t=a.includes("出冷汗")||a.includes("恶心")?"有,刚才疼得厉害的时候出了一身冷汗,还有点恶心,但没有吐。":a.includes("体格检查")?"患者面色苍白,额部出汗,心率偏快,血压较入院时略低。":a.includes("辅助检查")?"心电图提示下壁导联 ST 段抬高,肌钙蛋白待回报。":"疼痛主要在胸骨后,像压榨一样,休息后也没有明显缓解。";return Promise.resolve([{id:`doctor-${Date.now()}`,role:"doctor",content:a,label:"我"},{id:`patient-${Date.now()+1}`,role:"patient",content:t,label:"患者"},{id:`mentor-${Date.now()+2}`,role:"mentor",content:"很好,继续围绕 OPQRST 思路追问疼痛诱因、部位、性质、放射、持续时间和缓解因素,同时关注危险信号。",label:"王主任"}])}(e).then((e=>{B.messages.push(...e),Ce()})).finally((()=>{H.value=!1}))}}async function we(e){const a=ae.value;if(!a)return;H.value=!0,null==ue||ue.abort(),ue=new AbortController;const t=B.messages.length;B.messages.push({id:`patient-stream-${Date.now()}`,role:"patient",content:"",label:"患者"}),Ce();try{await q(a,e,{onDelta(e){B.messages[t].content+=e,Ce()}},ue.signal)}catch(s){if(s instanceof DOMException&&"AbortError"===s.name)return;B.messages[t].content.trim()||(B.messages[t].content="AI 病人回复失败,请重试。"),$e(s instanceof Error?s.message:"AI 流式回复异常")}finally{H.value=!1,ue=null,Ce()}}async function xe(){const e=ae.value;if(!e)return void $e("请先生成模拟场景");if(J.value)return;J.value=!0,null==re||re.abort(),re=new AbortController;const a=B.messages.length;B.messages.push({id:`mentor-hint-${Date.now()}`,role:"mentor",content:"王主任正在生成提示...",label:"王主任"}),Ce();try{let t=!1;await P(e,function(){const e=[...B.messages].reverse().find((e=>"doctor"===e.role));return(null==e?void 0:e.content)||"开始问诊"}(),{onDelta(e){t||(B.messages[a].content="",t=!0),B.messages[a].content+=e,Ce()}},re.signal)}catch(t){if(t instanceof DOMException&&"AbortError"===t.name)return;B.messages[a].content.trim()&&"王主任正在生成提示..."!==B.messages[a].content||(B.messages[a].content="练习提示生成失败,请稍后重试。"),$e(t instanceof Error?t.message:"练习提示生成失败,请稍后重试")}finally{J.value=!1,re=null,Ce()}}function Ce(){setTimeout((()=>{W.value+=1e3}),60)}function $e(e){ce&&clearTimeout(ce),X.value=e,Y.value=!0,ce=setTimeout((()=>{Y.value=!1}),2200)}return l((()=>{te.value=j(),fe()})),n((()=>{null==ue||ue.abort(),null==re||re.abort(),ce&&clearTimeout(ce)})),(e,a)=>{const t=b,s=k,l=w,n=x,y=C,j=$;return o(),i(t,{class:"chat-page"},{default:c((()=>[u(t,{class:"chat-shell"},{default:c((()=>[u(t,{class:"top-nav"},{default:c((()=>[u(s,{class:"icon-button","aria-label":"设置",onClick:r(M)},{default:c((()=>[u(t,{class:"settings-icon"})])),_:1},8,["onClick"]),u(s,{class:"icon-button home-button","aria-label":"首页",onClick:r(z)},{default:c((()=>[u(t,{class:"home-icon"})])),_:1},8,["onClick"]),u(t,{class:"nav-spacer"}),u(s,{class:"icon-button","aria-label":"个人中心",onClick:r(G)},{default:c((()=>[u(t,{class:"account-icon"})])),_:1},8,["onClick"])])),_:1}),u(t,{class:"case-header"},{default:c((()=>[u(t,{class:"case-title-row"},{default:c((()=>[u(l,{class:"case-heading"},{default:c((()=>[d("患者:"+m(B.patient.name)+" ("+m(me.value)+")",1)])),_:1}),u(s,{class:"finish-button",disabled:L.value,onClick:ve},{default:c((()=>[u(t,{class:"check-icon"}),u(l,null,{default:c((()=>[d(m(L.value?"提交中":"完成采集"),1)])),_:1})])),_:1},8,["disabled"])])),_:1}),u(t,{class:"patient-meta"},{default:c((()=>[u(l,null,{default:c((()=>[d("姓名:"+m(B.patient.name),1)])),_:1}),u(l,null,{default:c((()=>[d("性别:"+m(B.patient.gender),1)])),_:1}),u(l,null,{default:c((()=>[d("年龄:"+m(B.patient.age)+"岁",1)])),_:1}),u(l,null,{default:c((()=>[d("科室:"+m(B.patient.department),1)])),_:1})])),_:1})])),_:1}),u(t,{class:"stage-bar"},{default:c((()=>[u(t,{class:"stage-line"}),u(t,{class:"stage-line-active"}),(o(!0),f(p,null,v(B.stages,(e=>(o(),i(t,{key:e.key,class:_(["stage-item",{active:e.active}])},{default:c((()=>[u(t,{class:"stage-dot"},{default:c((()=>[u(t,{class:_(["stage-icon",`stage-icon-${e.key}`])},null,8,["class"])])),_:2},1024),u(l,null,{default:c((()=>[d(m(e.label),1)])),_:2},1024)])),_:2},1032,["class"])))),128))])),_:1}),u(n,{class:"chat-body","scroll-y":"","scroll-top":W.value},{default:c((()=>[u(t,{class:"message-list"},{default:c((()=>[(o(!0),f(p,null,v(B.messages,(e=>(o(),i(t,{key:e.id,class:_(["message-row",[`role-${e.role}`]])},{default:c((()=>["patient"===e.role?(o(),i(t,{key:0,class:"avatar patient-avatar"},{default:c((()=>[u(l,null,{default:c((()=>[d(m(B.patient.name.slice(0,1)),1)])),_:1})])),_:1})):h("",!0),u(t,{class:_(["message-bubble",`${e.role}-bubble`])},{default:c((()=>[u(l,{class:"message-content"},{default:c((()=>[d('"'+m(e.content)+'"',1)])),_:2},1024),u(t,{class:_(["message-label",{mentor:"mentor"===e.role}])},{default:c((()=>["mentor"===e.role?(o(),i(t,{key:0,class:"star-icon"})):h("",!0),u(l,null,{default:c((()=>[d(m(e.label),1)])),_:2},1024)])),_:2},1032,["class"])])),_:2},1032,["class"]),"doctor"===e.role?(o(),i(t,{key:1,class:"avatar doctor-avatar"},{default:c((()=>[u(t,{class:"person-icon"})])),_:1})):h("",!0)])),_:2},1032,["class"])))),128))])),_:1})])),_:1},8,["scroll-top"]),u(t,{class:_(["mentor-float",{loading:J.value}]),onClick:[g(xe,["stop"]),g(xe,["stop"])]},{default:c((()=>[u(l,{class:"mentor-badge"},{default:c((()=>[d("王主任")])),_:1}),u(t,{class:"mentor-avatar",onClick:[g(xe,["stop"]),g(xe,["stop"])]},{default:c((()=>[u(y,{src:E,mode:"aspectFill"})])),_:1})])),_:1},8,["class"]),u(t,{class:"input-panel"},{default:c((()=>[u(n,{class:"quick-actions","scroll-x":""},{default:c((()=>[u(t,{class:"quick-row"},{default:c((()=>[u(s,{class:"quick-chip",onClick:_e},{default:c((()=>[d("体格检查")])),_:1}),u(s,{class:"quick-chip",onClick:pe},{default:c((()=>[d("辅助检查")])),_:1})])),_:1})])),_:1}),u(t,{class:"input-row"},{default:c((()=>[u(j,{class:"chat-input",modelValue:Q.value,"onUpdate:modelValue":a[0]||(a[0]=e=>Q.value=e),type:"text",placeholder:"输入你对患者的提问...","placeholder-class":"input-placeholder",onConfirm:ke},null,8,["modelValue"]),u(s,{class:"send-button",disabled:H.value,onClick:ke},{default:c((()=>[u(t,{class:"send-icon"})])),_:1},8,["disabled"])])),_:1})])),_:1})])),_:1}),ee.value?(o(),i(t,{key:0,class:"exam-mask",onClick:a[3]||(a[3]=e=>ee.value=!1)},{default:c((()=>[u(t,{class:"physical-panel",onClick:a[2]||(a[2]=g((()=>{}),["stop"]))},{default:c((()=>[u(t,{class:"exam-header"},{default:c((()=>[u(l,{class:"exam-title"},{default:c((()=>[d("选择体格检查")])),_:1}),u(s,{class:"exam-close","aria-label":"关闭",onClick:a[1]||(a[1]=e=>ee.value=!1)},{default:c((()=>[u(t,{class:"close-icon"})])),_:1})])),_:1}),u(t,{class:"exam-list"},{default:c((()=>[ne.value?(o(),i(t,{key:0,class:"exam-empty"},{default:c((()=>[u(l,null,{default:c((()=>[d("体格检查加载中...")])),_:1})])),_:1})):0===se.value.length?(o(),i(t,{key:1,class:"exam-empty"},{default:c((()=>[u(l,null,{default:c((()=>[d("暂无可选体格检查")])),_:1})])),_:1})):(o(!0),f(p,{key:2},v(se.value,(e=>(o(),i(s,{key:e.item_code,class:"exam-item",disabled:ie.value,onClick:a=>ge(e)},{default:c((()=>[u(l,{class:"exam-name"},{default:c((()=>[d(m(e.item_name),1)])),_:2},1024),u(t,{class:"chevron-icon"})])),_:2},1032,["disabled","onClick"])))),128))])),_:1})])),_:1})])),_:1})):h("",!0),Z.value?(o(),i(t,{key:1,class:"exam-mask",onClick:a[6]||(a[6]=e=>Z.value=!1)},{default:c((()=>[u(t,{class:"exam-panel",onClick:a[5]||(a[5]=g((()=>{}),["stop"]))},{default:c((()=>[u(t,{class:"exam-header"},{default:c((()=>[u(l,{class:"exam-title"},{default:c((()=>[d("选择辅助检查")])),_:1}),u(s,{class:"exam-close","aria-label":"关闭",onClick:a[4]||(a[4]=e=>Z.value=!1)},{default:c((()=>[u(t,{class:"close-icon"})])),_:1})])),_:1}),u(t,{class:"exam-list"},{default:c((()=>[oe.value?(o(),i(t,{key:0,class:"exam-empty"},{default:c((()=>[u(l,null,{default:c((()=>[d("辅助检查加载中...")])),_:1})])),_:1})):0===le.value.length?(o(),i(t,{key:1,class:"exam-empty"},{default:c((()=>[u(l,null,{default:c((()=>[d("暂无可选辅助检查")])),_:1})])),_:1})):(o(!0),f(p,{key:2},v(le.value,(e=>(o(),i(s,{key:e.item_code,class:"exam-item",disabled:ie.value,onClick:a=>he(e)},{default:c((()=>[u(l,{class:"exam-name"},{default:c((()=>[d(m(e.item_name),1)])),_:2},1024),u(t,{class:"chevron-icon"})])),_:2},1032,["disabled","onClick"])))),128))])),_:1})])),_:1})])),_:1})):h("",!0),u(t,{class:_(["toast",{visible:Y.value}])},{default:c((()=>[d(m(X.value),1)])),_:1},8,["class"])])),_:1})}}}),[["__scopeId","data-v-c81fb762"]]);export{z as default};
|