Files
taimed/pages/medicalRecords/medicalDetail.vue
liuyuan 456b296477 提交
2025-07-30 09:06:50 +08:00

1949 lines
46 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view style="height: 100%">
<scroll-view
scroll-y
:style="{ height: '100%' }"
:scroll-into-view="scrollIntoView"
scroll-with-animation
>
<view
class="message-container-block"
:class="{
'message-container-detail': type == 'detail',
'content_detail_0': statusId == 0,
'content_detail_1': statusId == 1,
'content_detail_2': statusId == 2,
'content_detail_3': statusId == 3,
'content_detail_3_talents': page == 'talents',
}"
>
<view class="loading-spinner" v-if="loading"></view>
<uni-notice-bar :color="medicalRecords.state==0?'#eb3c41':medicalRecords.state==2?'#e78083':''"
:background-color="medicalRecords.state==3?'#e7808330':medicalRecords.state==2?'#e7808330':''"
:text="`审核备注:${markInfo}`"
v-if="markInfo" style="margin-bottom: 0;"/>
<view style="" class="detail_top" :class="{
'detail_top_0': statusId == 0,
'detail_top_1': statusId == 1,
'detail_top_2': statusId == 2,
'detail_top_3': statusId == 3,
'detail_top_3_talents': page == 'talents',
}" v-if="type == 'detail'">
<view class="detail_top_left" :style="`${page?'width:100%;padding-bottom:0':''}`">
<view class="detail_top_item">
<view class="detail_top_item_name">{{ formData.title }}</view>
<view class="label_title">分类 : {{ formData.labelTitle }}</view>
</view>
</view>
<image
class="image_box"
v-if="statusId == 1&&!page"
src="../../static/icon/shenghezhong.png"
style=""
></image>
<image
class="image_box"
v-if="statusId == 2&&!page"
src="../../static/icon/weitongguo.png"
style=""
></image>
<image
class="image_box"
v-if="statusId == 3&&!page"
src="../../static/icon/yitongguo.png"
style="width: 150rpx;"
></image
></view>
<view class="home_wrap" style="margin: 0" v-if="!loading">
<view
class="home_form"
style="margin-top: 40rpx"
v-if="type != 'detail'"
>
<view class="form_item">
<text>医案标题</text>
<textarea
auto-height
v-model="formData.title"
maxlength="-1"
placeholder="请输入医案标题"
placeholder-class="custom-placeholder"
/>
</view>
<view class="form_item">
<text>医案分类</text>
<view
style=""
@click="showDrawer"
class="form_item_customize"
:style="formData.labelId ? 'color:#000;' : 'color:#888'"
>{{
formData.labelId ? formData.labelTitle : "请选择医案分类"
}}</view
>
</view>
<view
class="form_item"
style="
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 14px;
"
>
<text>医案详情</text>
<view style="width: calc(100% - 200rpx)">
<view
class=""
v-for="(html, key) in record"
:key="key"
style="
padding: 4rpx;
margin-bottom: 20rpx;
box-sizing: border-box;
"
>
<!-- 显示字段标题 -->
<view
class="h1_box"
v-html="`${getTitleHtml(html, key)}`"
style="
margin-top: 0;
margin-bottom: 10px;
font-weight: bold;
display: flex;
align-items: center;
"
></view>
<view class="editor-wrapper">
<editor
placeholder=""
style="color: black"
:value="editableMap[key]"
@input="(e) => editorInput(e, key)"
@ready="onEditorReady(key)"
:id="`editorId${key}`"
></editor>
</view>
<!-- <view
class="detail_info_medical"
v-else
v-html="editableMap[key]"
></view> -->
</view>
</view>
</view>
<view
class="form_item"
style="
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 14px;
"
>
<text>上传图片</text>
<view class="in" style="border: none" @click="checkPermision">
<u-upload
:fileList="fileList1"
@afterRead="addPic"
@delete="deletePic"
multiple
width="55"
height="55"
:previewFullImage="true"
>
</u-upload>
</view>
</view>
</view>
<view
class="home_form"
style="margin-top: 0rpx; padding: 0 40rpx"
v-else
>
<!-- <view class="medical_title">医案详情</view> -->
<view
class="form_item"
style="
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 14px;
"
>
<view style="width: calc(100%)">
<view
class=""
v-for="(html, key) in record"
:key="key"
style="
padding: 4rpx;
margin-bottom: 20rpx;
box-sizing: border-box;
"
>
<!-- 显示字段标题 -->
<view
class="h1_box"
v-html="`${getTitleHtml(html, key)}`"
style="
margin-top: 0;
margin-bottom: 10px;
font-weight: bold;
display: flex;
align-items: center;
"
></view>
<!-- <view class="editor-wrapper"> -->
<rich-text style="color: #474343;"
:nodes="editableMap[key]"
v-if="editableMap[key]"
></rich-text>
<rich-text nodes="<p>无</p>" v-else style="color: #474343;"></rich-text>
<!-- </view> -->
</view>
<view v-if="fileList1.length>0"
class="form_item"
style="
display: block;
margin-bottom: 14px;
"
>
<view
class="h1_box"
v-html="`<h1>图片</h1>`"
style="
margin-top: 0;
margin-bottom: 14px;
font-weight: bold;
display: flex;
align-items: center;
"
></view>
<view
class="in"
style="border: none; width: 100%"
@click="checkPermision"
>
<u-upload
:fileList="fileList1"
@afterRead="addPic"
@delete="deletePic"
multiple
width="55"
height="55"
:previewFullImage="true"
>
</u-upload>
</view>
</view>
</view>
</view>
</view>
<!-- 搜索结果列表 -->
</view>
</view>
<view id="bottom-anchor"></view>
</scroll-view>
<tree-list
ref="treeList"
v-if="treeListVisible"
@clickCourseInfo="clickCourseInfo"
></tree-list>
<!-- <z-navigation></z-navigation> -->
</view>
</template>
<script>
import $http from "@/config/requestConfig.js";
import { mapState, mapMutations } from "vuex";
import treeList from "./tag.vue";
import qs from "qs";
export default {
components: {
treeList,
},
props: ["loading", "form", "medicalRecords", "type", "statusId",'page'],
data() {
return {
markInfo:'',
editorOptions: {
theme: "snow", // Quill 编辑器的主题
modules: {
toolbar: [["bold", "italic"], ["link"]],
},
},
fileList1: [],
treeListVisible: false,
containerHeight: null,
formData: {},
chatId: null, //选择助手的id
chatName: "",
chatAssistants: [],
activeIndex: null,
sessionId: "5fe38e6b-8816-4668-879c-99910b5e431b", //对话id
eventSource: null,
showMessages: false,
question: "", //传递的问题
messages: [],
record: [],
previousAnswer: null, //存储上一条回答内容
question_send: "",
pauseStatus: false, //暂停操作
record_list: [], //对话列表
null_text: "",
activeRecord: null,
tishi: false, //提示语
folderList: [], //病历夹列表
folderName: "", //病历夹名称
chatAssistantName: "",
patientName: "",
pageData: {},
pageType: "", //从患者列表过来的type
isChecked: true,
selectedItems: [], //模糊已选项
selectedId: [],
searchResults: [], //模糊搜索结果
searchResultStatus: false,
vipCount: null,
vipText: "",
vipStatus: null,
freeCount: null,
freeText: "",
freeStatus: null,
flag: null,
scrollIntoView: "",
recordData: {
information: "<h1>一般信息</h1>",
chiefComplaint: "<h1>主诉</h1>",
historyOfPresentIllness: "<h1>现病史</h1>",
pastHistory: "<h1>既往史</h1>",
personalAndFamilyHistory: "<h1>家族史</h1>",
physicaExamination: "<h1>体格检查</h1>",
diagnosis: "<h1>诊断</h1>",
treatmentPlan: "<h1>治疗和后续治疗</h1>",
},
editableMap: {},
};
},
computed: {
...mapState(["userInfo"]),
},
onLoad() {},
watch: {
medicalRecords: {
handler(newVal, oldVal) {
this.initRecordData(this.medicalRecords);
},
deep: true, // 开启深度监听
},
editableMap: {
handler(newVal, oldVal) {
this.$emit("editableMap", this.editableMap);
},
deep: true, // 开启深度监听
},
fileList1: {
handler(newVal, oldVal) {
this.$emit("fileList1", this.fileList1);
},
deep: true, // 开启深度监听
},
formData: {
handler(newVal, oldVal) {
this.$emit("formData", this.formData);
},
deep: true, // 开启深度监听
},
record: {
handler(newVal, oldVal) {
this.$emit("record", this.record);
},
deep: true, // 开启深度监听
},
},
onShow() {},
methods: {
onStatusChange(e) {
this.formats = e.detail;
},
editorInput(e, key) {
console.log("key at line 292:", e, key);
this.editableMap[key] = e.detail.html;
},
onEditorReady(key) {
this.$nextTick(() => {
// 在 DOM 更新后执行 createSelectorQuery
uni
.createSelectorQuery()
.in(this)
.select(`#editorId${key}`)
.context((res) => {
console.log("res at line 303:", res); // 输出调试信息
if (!res || !res.context) return; // 如果没有找到 context直接返回
// 获取编辑器内容,判断是否为空内容或无效内容
let content = this.editableMap[key] || "";
// 判断是否为空或无效内容
if (this.isEmptyContent(content)) {
content = ""; // 如果内容无效,清空编辑器内容
} else {
// 替换所有的 HTML 实体,如 &quot; => "
content = this.replaceHtmlEntities(content);
}
if (content) {
// 如果内容有效,设置编辑器内容
res.context.setContents({
html: content,
});
} else {
// 如果没有有效内容,可以选择清空编辑器
console.log("No valid content to set in the editor.");
}
})
.exec();
});
},
// 判断内容是否为空或无效
isEmptyContent(content) {
// 检查是否为空字符串或仅包含空白字符
return !content.trim() || content === '""';
},
// 替换 HTML 实体字符
replaceHtmlEntities(content) {
// 替换常见的 HTML 实体
return content
.replace(/&quot;/g, '"') // 替换 &quot; 为 "
.replace(/&lt;/g, "<") // 替换 &lt; 为 <
.replace(/&gt;/g, ">") // 替换 &gt; 为 >
.replace(/&amp;/g, "&") // 替换 &amp; 为 &
.replace(/&nbsp;/g, " "); // 替换 &nbsp; 为 空格
},
getInnerHtml(html) {
// Regular expression to capture all HTML tags excluding the first <h1> tag
const h1Match = html.match(/<h1[^>]*>.*?<\/h1>/);
// If an <h1> is found, remove it and process the rest
if (h1Match) {
// Remove the first <h1> and its content, then return the rest of the HTML
html = html.replace(h1Match[0], '');
}
// Return the remaining HTML
return html;
},
getTitleHtml(html, key) {
const str = [
"chiefComplaint",
"historyOfPresentIllness",
"physicaExamination",
"treatmentPlan",
].includes(key)
? `<span style="color:#F56C6C;margin-right:4px">*</span>`
: "";
// Regular expression to capture the first <h1> element in the HTML
const h1Match = html.match(/<h1[^>]*>(.*?)<\/h1>/);
if (h1Match) {
// If an <h1> is found, return it with the prepended star if needed
return `<h1>${str}${h1Match[1]}</h1>`;
} else {
// If no <h1> is found, return an empty <h1>
return "<h1></h1>";
}
},
async checkPermision() {
var result = await permission.premissionCheck("CAMERA_EXTERNAL_STORAGE");
if (result != 1) {
return false;
}
},
async addPic(e) {
let that = this;
for (var i = 0; i < e.file.length; i++) {
uni.uploadFile({
url: this.$baseUrl + "/oss/fileoss",
filePath: e.file[i].url,
name: "file",
formData: {},
success: (res) => {
that.fileList1.push({
url: JSON.parse(res.data).url,
});
},
fail: (error) => {},
});
}
},
deletePic(event) {
this.fileList1.splice(event.index, 1);
},
clickCourseInfo(val) {
console.log(val);
this.formData.labelId = val.id;
this.formData.labelTitle = val.title;
this.$emit("formData", this.formData);
this.$forceUpdate();
},
showDrawer() {
this.treeListVisible = true;
this.$nextTick(() => {
this.$refs["treeList"].getData();
});
},
//设置滚动到最底部
scrollToBottom() {
this.scrollIntoView = "";
setTimeout(() => {
this.scrollIntoView = "bottom-anchor";
}, 50);
},
//基因
handleInput(val) {
let name = val.detail.value;
this.getGenes(name);
},
//模糊搜索选中
selectItem(item) {
if (!this.selectedItems.some((i) => i.id === item.id)) {
this.selectedItems.push(item.name);
this.selectedId.push(item.id);
}
this.formData.genetic = "";
this.searchResultStatus = false;
console.log(this.selectedItems);
console.log(this.selectedId);
},
//删除标签
removeTag(index) {
this.selectedItems.splice(index, 1);
this.selectedId.splice(index, 1);
console.log(this.selectedItems);
console.log(this.selectedId);
},
//基因模糊查询列表
getGenes(name) {
this.$http
.request({
url: "taihumed/precisionMedicine/getPrecisionMedicineGenes",
method: "POST",
data: { name: name },
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
if (res.genes && res.genes.length > 0) {
this.searchResults = res.genes;
this.searchResultStatus = true;
} else {
this.searchResults = "";
this.searchResultStatus = false;
}
}
});
},
//勾选
toggleCheck() {
this.isChecked = !this.isChecked;
},
//获取病症种类数据
//获取对话记录数据
getRecordsData() {
this.record_list = [];
this.$http
.request({
url: "common/ragFlowApi/getChats",
method: "POST",
data: {
chatId: "",
sessionId: "",
page: 1,
pageSize: 300,
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
console.log("请求最新列表");
if (res.list && res.list.length > 0) {
this.record_list = res.list;
//患者列表跳转来的
const index = res.list.findIndex(
(item) =>
item.chatAssistantId === this.pageData.chatAssistantId &&
item.chatId === this.pageData.chatId
);
if (this.pageType && this.pageType == "patient") {
this.clickRecord(this.pageData, index);
}
} else {
this.record_list = [];
this.null_text = "暂无数据";
}
}
})
.catch((e) => {
console.log(e);
});
},
//请求问答剩余次数
getUserAiVipCount() {
this.$http
.request({
url: "taihumed/aiVip/getUserAiVip",
method: "POST",
data: {},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
this.flag = res.flag; //0-免费次数1-可升级
if (res.aiVipLog && res.aiVipLog.surplusCount >= 0) {
this.vipCount = res.aiVipLog.surplusCount;
this.vipText = "问答剩余:";
this.vipStatus = true;
}
if (res.freeCount >= 0) {
this.freeStatus = true;
this.freeCount = res.freeCount;
this.freeText = "赠送[全科医生]免费问答:";
} else {
this.freeStatus = false;
this.freeCount = null;
}
}
})
.catch((e) => {
uni.setStorageSync("guidePages", 2);
});
},
//点击每个记录
clickRecord(item, index) {
//重新定义id
this.chatId = item.chatAssistantId;
this.sessionId = item.chatId;
//助手类型
this.chatName = item.chatAssistantName;
this.patientName = item.patientName;
console.log("我是:" + this.patientName);
uni.setStorageSync("homeParams", { data: item, index: index });
this.activeRecord = index;
this.messages = [];
this.showMessages = true;
//请求病历夹接口
this.getRecordFolderList();
//如果正在回答的时候切换需要中断回答
this.closeWebSocket();
uni.showLoading({
title: "加载中",
});
this.$http
.request({
url: "common/ragFlowApi/getChats",
method: "POST",
data: {
chatId: item.chatAssistantId,
sessionId: item.chatId,
page: 1,
pageSize: 300,
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
uni.hideLoading();
if (res.list && res.list.length > 0) {
this.messages = res.list.map((item) => {
let content = item.content.replace(/##\d+$$/g, "");
content = item.content.replace(/<\/?think>/g, "");
content = content.replace(
/\*\*(.*?)\*\*/g,
'<b class="bold-text">$1</b>'
);
content = content.replace(
/\*(.*?)\*/g,
'<span class="red-text">$1</span>'
);
content = content.replace(/\n\n/g, "\n");
content = content.replace(/\n/g, "<br>");
//content = content.replace(/^#{3,4}.*(\r?\n)?/gm, '');
return {
...item,
type: item.type === 1 ? "answer" : "question",
content: content,
};
});
//滚动到最底部锚点
this.$nextTick(() => {
this.scrollToBottom();
});
}
this.tishi = false; //提示语不用展示
this.$refs.drawer.close();
}
});
},
//选中科目类别
clickAssistants(item, index) {
this.activeIndex = index;
this.chatId = item.id;
this.chatName = item.name;
},
initRecordData(data) {
this.markInfo=''
this.formData.title = data.title ? data.title : "";
this.formData.labelId = data.labelId ? data.labelId : "";
this.formData.labelTitle = data.labelTitle ? data.labelTitle : "";
if(data.mark){
this.markList = JSON.parse(data.mark);
const latest = this.markList.reduce((latest, current) => {
return new Date(current.time) > new Date(latest.time) ? current : latest;
});
if(data.state!=1&&data.state!=3&&latest){
this.markInfo=latest.mark?latest.mark:''
}
// medicalRecords.mark&&medicalRecords.state!=1&&medicalRecords.state!=3
}
this.record = {
information: data.information
? data.information
: recordData.information,
chiefComplaint: data.chiefComplaint
? data.chiefComplaint
: recordData.chiefComplaint,
historyOfPresentIllness: data.historyOfPresentIllness
? data.historyOfPresentIllness
: recordData.historyOfPresentIllness,
pastHistory: data.pastHistory
? data.pastHistory
: recordData.pastHistory,
personalAndFamilyHistory: data.personalAndFamilyHistory
? data.personalAndFamilyHistory
: recordData.personalAndFamilyHistory,
physicaExamination: data.physicaExamination
? data.physicaExamination
: recordData.physicaExamination,
diagnosis: data.diagnosis ? data.diagnosis : recordData.diagnosis,
treatmentPlan: data.treatmentPlan
? data.treatmentPlan
: recordData.treatmentPlan,
};
for (const key in this.record) {
this.$set(this.editableMap, key, this.getInnerHtml(this.record[key]));
}
},
//交谈请求,获取回答
//开始监听 SSE 数据
startSSE(params) {
const queryString = qs.stringify(params);
var data = {};
this.eventSource = uni.connectSocket({
url: this.$baseUrl + `websocket`,
success: () => {
console.log("WebSocket连接中...");
$http
.request({
url: `common/ragFlowApi/chatToAssistantStream?${queryString}`,
method: "GET",
data,
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
console.log("请求成功");
})
.catch((e) => {
console.log("失败");
});
},
fail: (err) => {
console.error("连接失败", err);
uni.showToast({ title: "连接失败", icon: "error" });
},
});
// 监听服务器发送的消息
uni.onSocketMessage((event) => {
try {
const message = JSON.parse(event.data);
if (message.data === true) {
console.log("回答已结束");
this.pauseStatus = false;
this.loading = false;
//获取最近的会话记录数据
this.getRecordsData();
setTimeout(() => {
this.closeWebSocket();
}, 200);
return;
}
const answer = message.data.answer.replace(/##\d+$$/g, "");
console.log(message.data.answer);
let newAnswer = ""; //初始化 newAnswer 变量
if (this.previousAnswer === null) {
console.log("第一次进来");
//如果没有包含上一条的内容,则直接显示当前 answer
newAnswer = answer;
this.messages.push({ content: newAnswer, type: "answer" });
this.previousAnswer = newAnswer;
} else {
//只显示新增的部分
newAnswer = answer.replace(this.previousAnswer, "");
newAnswer = newAnswer.replace(
/\*\*(.*?)\*\*/g,
'<b class="bold-text">$1</b>'
);
newAnswer = newAnswer.replace(
/\*(.*?)\*/g,
'<span class="red-text">$1</span>'
);
newAnswer = newAnswer.replace(/\n\n/g, "\n");
newAnswer = newAnswer.replace(/\n/g, "<br>");
newAnswer = newAnswer
.replace(/####([\s\S]*?)$/gm, "<h4>$1</h4>")
.replace(/###([\s\S]*?)$/gm, "<h3>$1</h3>");
this.messages.push({ content: newAnswer, type: "answer" });
this.previousAnswer = answer;
}
//滚动到最底部锚点
this.$nextTick(() => {
this.scrollToBottom();
});
} catch (error) {
this.loading = false;
this.closeWebSocket();
}
});
//监听WebSocket连接打开
uni.onSocketOpen(() => {
console.log("WebSocket已连接");
});
//监听WebSocket错误
uni.onSocketError((err) => {
console.error("WebSocket连接错误", err);
});
//监听WebSocket关闭
uni.onSocketClose((res) => {
console.log("WebSocket 已关闭", res);
});
},
//回答界面的提交
sendAgain() {
console.log("这是再一次提问");
if (!this.pauseStatus) {
if (!this.question_send) {
this.$commonJS.showToast("请输入发送内容");
return;
}
const params = {
chatId: this.chatId,
chatName: this.chatName,
question: this.question_send,
sessionId: this.sessionId,
sessionName: this.question_send.slice(0, 15),
patientName: this.formData.name,
};
this.messages.push({
content: `${this.question_send}`,
type: "question",
});
//滚动到最底部锚点
this.$nextTick(() => {
this.scrollToBottom();
});
this.loading = true;
this.question_send = "";
this.pauseStatus = true;
this.previousAnswer = null;
//调用后端 SSE 接口,发送问题并接收实时回答
this.startSSE(params);
} else {
console.log("不能点击了");
}
},
//点击左侧弹窗
openDrawer() {
this.$refs.drawer.open();
},
//点击新会话
showMode() {
this.showMessages = false;
this.messages = [];
this.formData = {
diagnosis: "",
illness: "",
symptoms: "",
genetic: "",
name: "",
};
this.chatId = null;
this.activeIndex = null;
this.activeRecord = null;
this.patientName = "";
this.selectedItems = [];
this.searchResultStatus = false;
//中断
this.closeWebSocket();
this.previousAnswer = null;
this.pauseStatus = false;
//把缓存清除
uni.removeStorageSync("homeParams");
//剩余次数
this.getUserAiVipCount();
},
//问答界面点击创建病历夹
clickFolder() {
if (this.pauseStatus) {
this.$commonJS.showToast("正在回答中,请稍候");
return;
}
if (this.folderList.length == 0) {
uni.showModal({
title: "提示",
content: "您还没有病历夹,确定创建新的病历夹吗?",
confirmText: "确定",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
this.$refs.add_folder.open("center");
} else if (res.cancel) {
console.log("取消创建病历夹");
}
},
});
} else {
this.$refs.popup.open("center");
}
},
//获取病历夹列表
getRecordFolderList() {
this.$http
.request({
url: "taihumed/aiRecordFolder/getRecordFolders",
method: "POST",
data: {
assistantId: this.chatId,
chatId: this.sessionId,
folderName: "",
patientName: "",
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
if (res.list && res.list.length > 0) {
this.folderList = res.list;
}
}
})
.catch((e) => {
console.log(e);
});
},
//点击创建病历夹
createFolder() {
this.$refs.popup.close();
this.$refs.add_folder.open();
this.folderName = "";
this.isChecked = true;
},
//创建病历夹
addRecordFolder() {
if (!this.folderName) {
this.$commonJS.showToast("请输入病历夹名称");
return;
}
if (!this.isChecked) {
uni.showLoading({
title: "正在创建中",
});
}
this.$http
.request({
url: "taihumed/aiRecordFolder/addRecordFolder",
method: "POST",
data: {
folderName: this.folderName,
sort: 0,
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
if (res.code == 0) {
uni.hideLoading();
//如果把当前对话放入病历夹
if (this.isChecked) {
let id = res.aiRecordFolder.id;
this.addRecordFolderChat(id);
} else {
uni.showToast({
title: "创建成功",
icon: "success",
});
this.$refs.add_folder.close();
this.getRecordFolderList(); //刷新列表数据
}
}
});
},
//询问是否加入
askJoin(data) {
if (data.here == 1) {
this.$commonJS.showToast("不可重复加入病历夹");
return;
}
this.$refs.popup.close();
uni.showModal({
title: "提示",
content: "确定加入[" + data.folderName + "]病历夹吗?",
confirmText: "确定",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
this.addRecordFolderChat(data.id, "0");
} else if (res.cancel) {
console.log("取消加入病历夹");
}
},
});
},
//对话记录加入病历夹
addRecordFolderChat(id, type) {
let text1 = "";
let text2 = "";
let patientName = "";
if (type == "0") {
text1 = "正在加入该病历夹";
text2 = "加入成功";
} else {
text1 = "正在创建中";
text2 = "创建成功";
}
uni.showLoading({
title: text1,
});
//患者名字
if (this.formData.name) {
patientName = this.formData.name;
} else {
patientName = this.patientName;
}
this.$http
.request({
url: "taihumed/aiRecordFolder/addRecordFolderChat",
method: "POST",
data: {
folderId: id,
patientName: patientName,
chatAssistantId: this.chatId,
chatId: this.sessionId,
},
header: {
"Content-Type": "application/json",
},
})
.then((res) => {
uni.hideLoading();
uni.showToast({
title: text2,
icon: "success",
});
this.$refs.add_folder.close();
this.$refs.popup.close();
this.getRecordFolderList(); //刷新列表数据
});
},
//关闭进程和监听
closeWebSocket() {
if (this.eventSource) {
// 关闭连接并移除监听
this.eventSource.close({
success: () => {
console.log("WebSocket 已关闭-closeWebSocket");
uni.offSocketMessage(); //移除消息监听
},
});
this.eventSource = null;
this.loading = false;
this.pauseStatus = false;
}
},
},
onHide() {
this.closeWebSocket();
},
onUnload() {
this.closeWebSocket();
},
};
</script>
<style lang="scss" scoped>
@import "@/static/mixin.scss";
.content {
background: linear-gradient(to bottom, #d8e6ff 0%, #d8e6ff57 90%, #fff 98%);
}
.home_top {
width: 100%;
background: #fff;
position: fixed;
top: 0;
left: 0;
padding: 90rpx 50rpx 30rpx;
text-align: center;
box-sizing: border-box;
z-index: 999;
.home_top_icon {
position: absolute;
left: 40rpx;
top: 85rpx;
display: flex;
align-items: center;
.home_top_left,
.home_top_right {
width: 60rpx;
height: 60rpx;
padding: 10rpx;
box-sizing: border-box;
}
.home_top_right {
margin-left: 30rpx;
}
}
text {
font-size: 43rpx;
line-height: 44rpx;
font-weight: bold;
color: $themeColor;
}
.home_top_folder {
padding: 12rpx;
position: absolute;
right: 40rpx;
top: 75rpx;
image {
width: 50rpx;
height: 50rpx;
}
}
}
.home_wrap {
margin: 0rpx 30rpx 0;
// padding-bottom: 300rpx;
overflow: hidden;
.home_logo {
padding-top: 40rpx;
image {
display: block;
width: 130rpx;
height: 130rpx;
margin: 0 auto;
}
.logo_main {
text-align: center;
display: block;
padding-top: 30rpx;
font-size: 35rpx;
color: $themeColor;
line-height: 46rpx;
}
.logo_con {
display: block;
width: 510rpx;
margin: 30rpx auto;
font-size: 28rpx;
color: #303030;
line-height: 40rpx;
text-indent: 2em;
}
}
}
.home_form {
margin-top: 60rpx;
padding-bottom: 80rpx;
position: relative;
.form_item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
text {
line-height: 68rpx;
font-size: 30rpx;
color: #fff;
background: $themeBgColor;
text-align: center;
border-radius: 20rpx;
padding: 0 25rpx;
border: 1rpx solid $themeBgColor;
box-sizing: border-box;
}
textarea,
input,
.form_item_customize {
display: inline-block;
width: calc(100% - 200rpx);
height: 70rpx;
line-height: 35rpx;
padding: 17rpx 30rpx;
font-size: 28rpx;
color: #000;
border-radius: 50rpx;
border: 1rpx solid #777778;
box-sizing: border-box;
resize: none;
max-height: 200rpx;
overflow-y: scroll;
}
}
}
.custom-placeholder {
font-size: 28rpx;
color: #8b8c90 !important;
}
.submit_form {
width: 100%;
height: 90px;
background: #fff;
position: fixed;
left: 0;
bottom: 120rpx;
padding: 0 50rpx;
z-index: 999;
}
.submit_form_2 {
height: 135rpx;
padding: 30rpx;
.assistants_list {
textarea,
input {
width: calc(100% - 65px);
font-size: 26rpx;
line-height: 34rpx;
border-radius: 50rpx;
padding: 22rpx 30rpx;
color: #303030;
background: #f3f4f6;
max-height: 72rpx;
overflow: hidden;
}
}
.submit_btn {
top: 42rpx;
}
}
.assistants_list {
display: flex;
align-items: center;
flex-wrap: wrap;
.assistants_item {
display: flex;
align-items: center;
width: 217rpx;
margin-top: 30rpx;
image {
width: 38rpx;
height: 38rpx;
}
text {
padding-left: 10rpx;
display: inline-block;
font-size: 28rpx;
color: #606061;
}
.assistants_img_1 {
display: block;
}
.assistants_img_2 {
display: none;
}
}
}
.submit_btn {
position: absolute;
right: 0rpx;
bottom: 10rpx;
image {
width: 55rpx;
height: 55rpx;
}
}
.active {
text {
color: $themeBgColor;
}
.assistants_img_1 {
display: none !important;
}
.assistants_img_2 {
display: block !important;
}
}
.message_title {
text-align: center;
font-size: 34rpx;
color: #333;
line-height: 50rpx;
display: block;
font-weight: bold;
padding: 10rpx 0;
}
.message-container-block {
padding-top: 20rpx;
padding-bottom: 80px;
font-size: 30rpx;
}
.message-container {
display: inline;
line-height: 48rpx;
}
/* 自定义的loading效果 */
.loading-spinner {
margin-top: 10rpx;
border: 2px solid #f3f3f3;
/* 灰色背景 */
border-top: 2px solid #3498db;
/* 蓝色顶部 */
border-radius: 50%;
width: 16px;
height: 16px;
animation: spin 1s linear infinite;
/* 旋转动画 */
}
/* 旋转动画 */
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.bold-text {
display: block;
font-weight: bold;
font-size: 28rpx;
/* 增大字号 */
}
h3 {
font-size: 36rpx;
font-weight: bold;
}
h3 {
font-size: 32rpx;
}
.red-text {
color: red;
font-size: 28rpx;
/* 增大字号 */
}
.message-right {
display: block;
text-align: right;
margin: 30rpx 0;
text {
display: inline-block;
padding: 20rpx;
line-height: 38rpx;
background-color: rgba(81, 136, 229, 0.2);
border-radius: 15rpx;
color: #333;
font-size: 28rpx;
text-align: left;
}
}
.drawer-content {
height: 100vh;
display: flex;
flex-direction: column;
}
.list_content {
padding: 70rpx 20rpx 30rpx;
overflow-y: auto;
}
.list_item {
padding: 18rpx 10rpx;
}
.text_item {
display: block;
width: 100%;
font-size: 30rpx;
line-height: 40rpx;
padding: 0 10rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.null_text {
display: block;
text-align: center;
font-size: 30rpx;
color: #999;
padding-top: 150rpx;
}
.active_item {
background: #d8e6ff;
border-radius: 15rpx;
text {
color: #5188e5;
}
}
.folder_popup {
z-index: 9999;
.popup-content {
padding: 30rpx;
width: 550rpx;
background: #fff;
border-radius: 10rpx;
.popup-top {
padding: 15rpx;
display: flex;
align-items: center;
background: #5188e5;
border-radius: 10rpx;
color: #fff;
font-size: 28rpx;
line-height: 45rpx;
.uni-icons {
margin-right: 2rpx;
}
}
.popup-list {
.item-list {
padding: 15rpx;
background: #d8e6ff;
border-radius: 10rpx;
font-size: 28rpx;
line-height: 45rpx;
color: #5188e5;
margin-top: 15rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
position: relative;
text {
position: absolute;
right: 20rpx;
top: 12rpx;
font-size: 22rpx;
line-height: 45rpx;
color: #ff7800;
}
}
.popup-scroll {
max-height: 330rpx;
}
}
}
}
.add_folder_name {
font-size: 30rpx;
line-height: 45rpx;
color: #5188e5;
}
.add_folder_input {
margin-top: 20rpx;
input {
height: 70rpx;
line-height: 70rpx;
padding: 0 20rpx;
font-size: 26rpx;
color: #303030;
border-radius: 10rpx;
border: 1rpx solid #ddd;
box-sizing: border-box;
}
.custom-placeholder {
font-size: 26rpx;
}
}
.add_folder_btn {
width: 50%;
margin: 25rpx auto 0;
background: #5188e5;
border-radius: 50rpx;
font-size: 26rpx;
color: #fff;
line-height: 70rpx;
}
.checkbox-item {
display: flex;
align-items: center;
margin-top: 20rpx;
checkbox {
transform: scale(0.55);
/deep/.uni-checkbox-input {
border: 1rpx solid $themeColor;
margin-right: 0;
}
}
text {
color: #666;
font-size: 26rpx;
margin-left: -5rpx;
}
}
//基因模糊
.tags-block {
width: calc(100% - 255rpx);
line-height: 46rpx;
padding: 12rpx 20rpx;
border-radius: 50rpx;
border: 1rpx solid #777778;
box-sizing: border-box;
input {
border: none !important;
padding: 5rpx 10rpx !important;
height: 50rpx !important;
}
}
.tags-container {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.tag {
margin: 5rpx;
display: flex;
align-items: center;
background-color: #d8e6ff;
border-radius: 20rpx;
color: $themeColor;
padding: 0 15rpx;
font-size: 24rpx;
line-height: 38rpx;
}
.tag-close {
font-size: 24rpx;
font-weight: bold;
padding-left: 10rpx;
}
.result-list {
background: #fff;
width: calc(100% - 200rpx);
max-height: 325rpx;
border: 1px solid #eee;
border-radius: 10rpx;
margin-top: -30rpx;
float: right;
}
.result-item {
padding: 18rpx 20rpx;
border-bottom: 1px solid #f5f5f5;
font-size: 26rpx;
line-height: 30rpx;
}
.result-item:last-child {
border-bottom: 0;
}
.vip_count {
font-size: 26rpx;
color: red;
text-indent: 0;
text {
display: block;
}
}
.vip_count_block {
display: inline-block;
text-indent: 0;
padding-top: 10rpx;
}
.aiFlag {
position: absolute;
bottom: 55px;
left: 20px;
width: calc(100% - 40px);
font-size: 11px;
line-height: 16px;
color: #f69e12;
z-index: 999;
background: rgba(254, 243, 225, 0.8);
border: 1px solid #f2d7aa;
padding: 5px;
border-radius: 6px;
}
.in {
border: 1rpx solid #eeeeee;
border-radius: 8rpx;
width: calc(100% - 200rpx);
}
.shangpin_editor {
width: 100%;
}
/deep/.h1_box {
height: 24px;
margin-top: 40rpx;
h1 {
margin: 0 !important;
font-size: 20px;
line-height: 24px;
color: #373535;
}
}
#editor {
height: 300px;
border: 1px solid #ccc;
}
.ql-container {
height: auto;
min-height: auto;
}
.editor-wrapper {
// background-color: #f0f0f080;
padding: 20rpx;
box-sizing: border-box;
border-radius: 20rpx;
border: 0.5px solid #777778;
}
.footer_box {
background: #fff;
padding-top: 10rpx;
height: 100rpx;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
z-index: 502;
box-sizing: content-box;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
box-shadow: 0 1px 15px rgba(0, 0, 0, 0.1);
}
.footer_bg {
background-color: #fff;
box-shadow: 0 0px 10px 1px #0000001a;
}
.footer_item {
position: relative;
flex: 1;
.button {
width: 88%;
background-color: #1985fd;
margin: auto auto;
margin-top: 10rpx;
border-radius: 50px;
line-height: 40px;
height: 40px;
text-align: center;
color: #fff;
font-weight: bold;
}
.savebutton {
background-color: #e4f0ff;
color: #1985fd;
}
}
/deep/.u-upload__button {
background-color: #fff;
.uicon-camera-fill {
color: #5188e5 !important;
}
}
.analysis_box {
padding-bottom: 40px;
width: 100%;
background-color: #fff;
border: 4rpx solid #188bff !important;
border-radius: 20rpx;
height: 88vh;
border-radius: 10px;
box-sizing: border-box !important;
uni-textarea {
border: none !important;
}
.analysis_title {
display: flex;
align-items: center;
padding: 18rpx 32rpx 0 16rpx;
color: #1781ff;
font-size: 18px;
font-weight: 700;
}
}
/deep/.home_wrap_analysis {
height: 92vh;
.home_form {
padding-bottom: 0px;
}
.form_item {
margin-bottom: 0 !important;
textarea {
// padding-top: 20rpx;
// height: 80vh !important;
}
.uni-textarea-wrapper {
// height: 100% !important;
}
}
.submit_btn {
padding: 0 40rpx;
position: absolute;
right: 24rpx;
bottom: 24rpx;
background-color: #1985fd;
margin: auto auto;
margin-top: 10rpx;
border-radius: 20rpx;
line-height: 62rpx;
height: 62rpx;
text-align: center;
color: #fff;
// font-weight: bold;
}
}
.message-container-detail {
padding-top: 0rpx;
/deep/.u-upload__deletable {
display: none !important;
}
/deep/.u-upload__button {
display: none !important;
}
}
.content_detail_1{
background: #fff4e026;
}
.content_detail_3{
background: linear-gradient(to bottom, #f6fcfb 0%, #fff 90%);
}
.content_detail_3_talents{
background: linear-gradient(to bottom, #e9f2fc 0%, #ffffff 90%);
}
// .content_detail_2{
// background: linear-gradient(to bottom, #f2f1f6 0%, #fff 90%);
// }
.content_detail_2{
// background: linear-gradient(to bottom, #e7808330 0%, #fff 90%);
}
.detail_top {
width: 100%;
min-height: 280rpx;
position: relative;
// background: linear-gradient(to bottom, #fff4e0 0%, #fff 90%);
.image_box {
width: 130rpx;
height: 130rpx;
position: absolute;
right: 20rpx;
top: 40rpx;
}
.detail_top_left {
padding: 60rpx 40rpx 40rpx;
width: calc(100% - 170rpx);
}
.detail_top_item_name {
font-weight: bold;
font-size: 46rpx;
line-height: 50rpx;
}
.label_title {
font-size: 28rpx;
// font-weight: bold;
margin-top: 30rpx;
height: 52rpx;
display: inline-block;
line-height: 48rpx;
padding: 0rpx 20rpx;
border-radius: 10rpx;
padding-left: 0;
// background-color: #e4f0ff;
color: #1985fd;
}
}
.medical_title {
color: #294a97;
font-size: 38rpx;
font-weight: bold;
margin-bottom: 40rpx;
}
.detail_top_1{
background: linear-gradient(to bottom, #fff4e0 0%, #fff4e026 90%);
}
.detail_top_2{
background: linear-gradient(to bottom, #f2f1f6 0%, #fff 90%);
}
.detail_top_3{
background: linear-gradient(to bottom, #22be973d 0%, #f6fcfb 90%);
}
.detail_top_3_talents{
background: linear-gradient(to bottom, #d8e6ff 0%, #e9f2fc 90%);
min-height:260rpx;
}
</style>