|
|
|
@ -24,7 +24,8 @@ |
|
|
|
<div style="display: flex;"> |
|
|
|
<el-tabs v-model="activeName" tab-position="bottom" style="width: 200px;"> |
|
|
|
<el-tab-pane label="组合项目" name="asbitem"> |
|
|
|
<RegisterCheckList :refParams="refParamsQuery" @clickAsbBak="clickAsbBak" :patient_register="patient_register"/> |
|
|
|
<RegisterCheckList :refParams="refParamsQuery" @clickAsbBak="clickAsbBak" |
|
|
|
:patient_register="patient_register" /> |
|
|
|
</el-tab-pane> |
|
|
|
<el-tab-pane v-if="LocalConfig.doctorCheck.isQueue == 'Y'" label="叫号" name="call"> |
|
|
|
<QueueCheckList /> |
|
|
|
@ -63,7 +64,7 @@ |
|
|
|
</el-tabs> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<div style="width:110px;"> |
|
|
|
<div style="width:110px;"> |
|
|
|
<div style="margin-left: 5px;z-index: 2001;"> |
|
|
|
<div v-show="checkPagePriv(pagePriv.privs, '人员列表')" class="divBtnClass"> |
|
|
|
<el-button type="primary" class="commonbutton" @click="prList">人员列表</el-button> |
|
|
|
@ -153,7 +154,7 @@ |
|
|
|
<div v-show="dialogWin.doctorPrList" |
|
|
|
:style="`z-index:2;border-radius: 10px;border: 1px solid #ddd;background-color:#FFF; position: absolute;top:50px;right:120px;width:350px;height: ${window.pageHeight - 42 - 10}px;opacity:1;`"> |
|
|
|
|
|
|
|
<PatientRegisterList win="doctorCheck" :winAbsolute="true" @choosedBak="choosedBak"/> |
|
|
|
<PatientRegisterList win="doctorCheck" :winAbsolute="true" @choosedBak="choosedBak" /> |
|
|
|
|
|
|
|
</div> |
|
|
|
</div> |
|
|
|
@ -164,7 +165,7 @@ |
|
|
|
<div> |
|
|
|
<!-- AI诊断--> |
|
|
|
<div v-show="AI.visible" |
|
|
|
:style="`z-index:3;border-radius: 10px;border: 1px solid #ddd;background-color:#FFF; position: absolute;top:50px;right:0px;width:${AI.width}px;height: ${AI.height}px;opacity:1;`"> |
|
|
|
:style="`z-index:3;border-radius: 10px;border: 1px solid #ddd;background-color:#FFF; position: absolute;top:50px;right:120px;width:${AI.width}px;height: ${AI.height}px;opacity:1;`"> |
|
|
|
<div v-show="AI.max" style="display: flex;justify-content: space-between;"> |
|
|
|
<p>AI诊断内容:</p> |
|
|
|
<el-tooltip content="隐藏 AI诊断内容" placement="top"> |
|
|
|
@ -176,16 +177,19 @@ |
|
|
|
<i class="el-icon-plus" @click="btnAImax(AI.max)" style="font-size: 24px;color: red;cursor:pointer;"></i> |
|
|
|
</el-tooltip> |
|
|
|
</div> |
|
|
|
<!-- <el-input v-show="AI.max" type="textarea" v-model="AI.diagnosis" placeholder="AI诊断内容" |
|
|
|
:autosize="{ minRows: AIDH, maxRows: AIDH }" style="text-align: right;"> |
|
|
|
</el-input> --> |
|
|
|
<div ref="aiContent" v-html="AI.html" |
|
|
|
:style="`height:${AI.height - 42 - 48}px;overflow-y: auto;display: blockresize:vertical;padding: 5px 5px 5px 20px;line-height: 1.5;box-sizing: border-box;width: 100%;font-size: inherit;background-color: #fff;background-image: none;border: 1px solid #dcdfe6;border-radius: 4px;transition: border-color .2s cubic-bezier(.645, .045, .355, 1);`"> |
|
|
|
<div v-if="AI.isAssistant" style="margin-bottom: 5px;"> |
|
|
|
<el-input type="textarea" v-model="AI.question" placeholder="向 AI 提出你的问题" |
|
|
|
:autosize="{ minRows: 3, maxRows: 3 }"> |
|
|
|
</el-input> |
|
|
|
</div> |
|
|
|
<div v-show="AI.max" style="text-align: right; margin-top: 10px;"> |
|
|
|
<div v-show="AI.max" style="text-align: right; margin: 5px;"> |
|
|
|
<el-button class="commonbutton" @click="btnAIdiagnosis(true)">AI 提问</el-button> |
|
|
|
<el-button class="commonbutton" @click="AI.visible = false">关闭</el-button> |
|
|
|
<el-button class="commonbutton" @click="btnAIdiagnosis(true)">AI重新诊断</el-button> |
|
|
|
</div> |
|
|
|
<div ref="aiContent" v-html="AI.html" |
|
|
|
:style="`height:${AIcontentH}px;overflow-y: auto;display: blockresize:vertical;padding: 5px 5px 5px 20px;line-height: 1.5;box-sizing: border-box;width: 100%;font-size: inherit;background-color: #fff;background-image: none;border: 1px solid #dcdfe6;border-radius: 4px;transition: border-color .2s cubic-bezier(.645, .045, .355, 1);`"> |
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
<!-- 危急值 --> |
|
|
|
<el-dialog title="危急值" :visible.sync="dialogWin.FollowCriticalCheck" width="800px" :show-close="false" |
|
|
|
@ -243,7 +247,7 @@ |
|
|
|
</template> |
|
|
|
<script> |
|
|
|
import { mapState } from "vuex"; |
|
|
|
import { getapi, postapi, putapi, deletapi } from "@/api/api"; |
|
|
|
import { getapi, postapi, putapi, deletapi, fetchStream } from "@/api/api"; |
|
|
|
import { getPagePriv, checkPagePriv, arrayExistObj, tcdate, deepCopy } from "../../utlis/proFunc"; |
|
|
|
import { photoParse } from "../../utlis/proApi"; |
|
|
|
|
|
|
|
@ -347,7 +351,7 @@ export default { |
|
|
|
}, |
|
|
|
LocalConfigInit: {}, |
|
|
|
doctor_check_check_charge: 'Y', // 默认判断收费 |
|
|
|
medical_report_print_after_summary_check_is_audit:'N', |
|
|
|
medical_report_print_after_summary_check_is_audit: 'N', |
|
|
|
|
|
|
|
medicalStartDate: '', //设置体检日期 |
|
|
|
medicalStartDateTemp: '', //设置体检日期 临时体检日期 |
|
|
|
@ -421,14 +425,17 @@ export default { |
|
|
|
displayPrList: false, //是否显示人员列表 |
|
|
|
dialogVisibleCheckHistory: false, //历次结果 |
|
|
|
tabChoosed: '2', |
|
|
|
|
|
|
|
AI: { |
|
|
|
width: 500, |
|
|
|
height: 24, |
|
|
|
max: true, |
|
|
|
visible: false, |
|
|
|
diagnosis: 'AI诊断信息', |
|
|
|
rawText: "", // 原始 markdown 内容(流式累加) |
|
|
|
html: "", // 渲染后的 HTML(逐字更新) |
|
|
|
isAssistant: true, // 是否AI助手 |
|
|
|
question: "", // 所提问题 |
|
|
|
rawText: '', |
|
|
|
html: "" |
|
|
|
}, |
|
|
|
|
|
|
|
// 历次明细 |
|
|
|
@ -513,7 +520,13 @@ export default { |
|
|
|
// AIdiagnosisHeight |
|
|
|
AIDH() { |
|
|
|
return Math.floor((this.AI.height - 24 - 42 - 4) / 21.5) |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
AIcontentH() { |
|
|
|
let ret = this.AI.height - 65 |
|
|
|
if (this.AI.isAssistant) ret = ret - 80 |
|
|
|
return ret |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
methods: { |
|
|
|
@ -580,15 +593,15 @@ export default { |
|
|
|
postapi('/api/app/SysParmValue/GetSysParmValueBySysParmId', { sysParmId: 'doctor_check_check_charge' }) |
|
|
|
.then(res => { |
|
|
|
if (res.code > -1) { |
|
|
|
this.doctor_check_check_charge = res?.data.toUpperCase()||'Y' |
|
|
|
this.doctor_check_check_charge = res?.data.toUpperCase() || 'Y' |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
// 系统参数--报告是否审核后才可打印 |
|
|
|
postapi('/api/app/SysParmValue/GetSysParmValueBySysParmId', { sysParmId: 'medical_report_print_after_summary_check_is_audit' }) |
|
|
|
.then(res => { |
|
|
|
if (res.code > -1) { |
|
|
|
this.medical_report_print_after_summary_check_is_audit = res?.data.toUpperCase()||'N' |
|
|
|
this.medical_report_print_after_summary_check_is_audit = res?.data.toUpperCase() || 'N' |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
@ -1453,7 +1466,7 @@ export default { |
|
|
|
|
|
|
|
// 总检审核后才能打印 |
|
|
|
if (this.patient_register.completeFlag != '3') toOutShell.preViewCanPrint = 'N' |
|
|
|
if (toOutShell.preViewCanPrint == 'Y' && this.patient_register.isAudit == 'N') { |
|
|
|
if (toOutShell.preViewCanPrint == 'Y' && this.patient_register.isAudit == 'N') { |
|
|
|
if (this.medical_report_print_after_summary_check_is_audit == 'Y') toOutShell.preViewCanPrint = 'N' |
|
|
|
} |
|
|
|
|
|
|
|
@ -1545,37 +1558,36 @@ export default { |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
let message = '' |
|
|
|
if(!this.AI.visible){ |
|
|
|
this.AI.question = '' |
|
|
|
this.AI.visible = true |
|
|
|
} |
|
|
|
let message = this.AI.question |
|
|
|
let linkStr = ';' |
|
|
|
this.doctorCheck.checkItemList.forEach(e => { |
|
|
|
if (e.result) { |
|
|
|
if (message) { |
|
|
|
linkStr = ';' |
|
|
|
} else { |
|
|
|
linkStr = '' |
|
|
|
if (!message) { |
|
|
|
this.doctorCheck.checkItemList.forEach(e => { |
|
|
|
if (e.result) { |
|
|
|
if (message) { |
|
|
|
linkStr = ';' |
|
|
|
} else { |
|
|
|
linkStr = '' |
|
|
|
} |
|
|
|
message += linkStr + e.itemName + ':' + e.result |
|
|
|
if (e.unitName) message += e.unitName |
|
|
|
if (e.referenceRangeValue) message += '(正常范围:' + e.referenceRangeValue + ')' |
|
|
|
} |
|
|
|
message += linkStr + e.itemName + ':' + e.result |
|
|
|
if (e.unitName) message += e.unitName |
|
|
|
if (e.referenceRangeValue) message += '(正常范围:' + e.referenceRangeValue + ')' |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
this.AI.question = message |
|
|
|
} |
|
|
|
if(!message) return |
|
|
|
|
|
|
|
// postapi('/api/app/AIMessage/GetAIMessageResult', { message }) |
|
|
|
// .then(res => { |
|
|
|
// if (res.code > -1) { |
|
|
|
// this.AI.visible = true |
|
|
|
// this.AI.diagnosis = res.data.result |
|
|
|
// this.btnAImax(false) |
|
|
|
// } else { |
|
|
|
// this.$message.error({ showClose: true, message: res.message }) |
|
|
|
// } |
|
|
|
// }) |
|
|
|
|
|
|
|
this.AI.rawText = ''; |
|
|
|
this.AI.html = ''; |
|
|
|
|
|
|
|
try { |
|
|
|
await fetchStream('/api/app/AiMessageWs/GetAIMessageResult', { message }, (chunk) => { |
|
|
|
await fetchStream('/api/app/AiMessageWs/GetAIMessageResult', { message }, (chunk) => { |
|
|
|
|
|
|
|
// 清洗 SSE 风格前缀并移除结束标志 |
|
|
|
let cleaned = String(chunk).replace(/data:\s*\[DONE\]/g, '').replace(/^data:\s*/gm, ''); |
|
|
|
if (!cleaned) return; |
|
|
|
@ -1594,6 +1606,8 @@ export default { |
|
|
|
if (el) el.scrollTop = el.scrollHeight; |
|
|
|
} catch (e) { } |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
}); |
|
|
|
} catch (err) { |
|
|
|
// 回退:非流式请求(axios/postapi) |
|
|
|
@ -1604,7 +1618,7 @@ export default { |
|
|
|
if (cleaned) { |
|
|
|
// 回退响应到达后显示弹窗并展开 |
|
|
|
if (!this.AI.visible) { |
|
|
|
this.AI.visible = true; |
|
|
|
|
|
|
|
this.btnAImax(false); |
|
|
|
} |
|
|
|
this.AI.rawText += cleaned; |
|
|
|
@ -1617,30 +1631,7 @@ export default { |
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
startTyping() { |
|
|
|
if (this.AI.typingTimer) clearInterval(this.AI.typingTimer); |
|
|
|
|
|
|
|
this.AI.typingTimer = setInterval(() => { |
|
|
|
if (this.AI.typingIndex < this.AI.rawText.length) { |
|
|
|
const current = this.AI.rawText.slice(0, this.AI.typingIndex); |
|
|
|
this.AI.html = md.render(current); |
|
|
|
this.AI.typingIndex++; |
|
|
|
// 每次更新后滚动到容器底部,确保最新输出可见 |
|
|
|
this.$nextTick(() => { |
|
|
|
try { |
|
|
|
const el = this.$refs.aiContent; |
|
|
|
if (el) { |
|
|
|
el.scrollTop = el.scrollHeight; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
// ignore |
|
|
|
} |
|
|
|
}); |
|
|
|
} else { |
|
|
|
clearInterval(this.AI.typingTimer); |
|
|
|
} |
|
|
|
}, 30); // 每 30ms 打一个字 |
|
|
|
}, |
|
|
|
|
|
|
|
btnAImax(max) { |
|
|
|
this.AI.max = !max |
|
|
|
if (this.AI.max) { |
|
|
|
@ -1700,7 +1691,8 @@ export default { |
|
|
|
@import '../../assets/css/global_input.css'; |
|
|
|
@import '../../assets/css/global_table.css'; |
|
|
|
@import '../../assets/css/global.css'; |
|
|
|
|
|
|
|
.divBtnClass { |
|
|
|
margin-top: 5px; |
|
|
|
margin-top: 5px; |
|
|
|
} |
|
|
|
</style> |