| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- <template>
- <div class="detail-container">
- <!-- 页面头部 -->
- <div class="detail-header">
- <h2 class="detail-title">处方订单详情</h2>
- <el-button
- type="primary"
- icon="el-icon-arrow-left"
- @click="goBack"
- class="back-button"
- plain
- >
- 返回列表
- </el-button>
- </div>
- <!-- 选项卡 -->
- <el-tabs v-model="activeTab" class="detail-tabs" @tab-click="handleTabClick">
- <!-- 详细信息选项卡 -->
- <el-tab-pane label="详细信息" name="detail">
- <div class="detail-content" v-loading="detailLoading">
- <div class="detail-card">
- <div class="detail-info">
- <div class="info-grid">
- <div class="info-item">
- <label>用户ID:</label>
- <span>{{ prescriptionDetail.userId || '-' }}</span>
- </div>
- <div class="info-item">
- <label>处方ID:</label>
- <span>{{ prescriptionDetail.pid || '-' }}</span>
- </div>
- <div class="info-item">
- <label>处方编号:</label>
- <span>{{ prescriptionDetail.serialNo || '-' }}</span>
- </div>
- <div class="info-item">
- <label>问诊单ID:</label>
- <span>{{ prescriptionDetail.diagnosisId || '-' }}</span>
- </div>
- <div class="info-item">
- <label>商城订单ID:</label>
- <span>{{ prescriptionDetail.storeOrderId || '-' }}</span>
- </div>
- <div class="info-item">
- <label>服务类型:</label>
- <span>{{ getServiceTypeText(prescriptionDetail.serviceType) }}</span>
- </div>
- <div class="info-item">
- <label>是否需要审方:</label>
- <span>{{ getYesNoText(prescriptionDetail.isExamine) }}</span>
- </div>
- <div class="info-item">
- <label>来源:</label>
- <span>{{ getSourceText(prescriptionDetail.souceFrom) }}</span>
- </div>
- <div class="info-item">
- <label>是否孕妇:</label>
- <span>{{ getYesNoText(prescriptionDetail.isPregnantWoman) }}</span>
- </div>
- <div class="info-item">
- <label>是否哺乳期:</label>
- <span>{{ getYesNoText(prescriptionDetail.isLactation) }}</span>
- </div>
- <div class="info-item">
- <label>开方情况:</label>
- <span>{{ getPrescriptionStatusText(prescriptionDetail.prescriptionStatus) }}</span>
- </div>
- <div class="info-item">
- <label>就诊人姓名:</label>
- <span>{{ prescriptionDetail.userFamilyName || '-' }}</span>
- </div>
- <div class="info-item">
- <label>就诊人身份证:</label>
- <span>{{ prescriptionDetail.userFamilyIdCard || '-' }}</span>
- </div>
- <div class="info-item">
- <label>就诊人年龄:</label>
- <span>{{ prescriptionDetail.userFamilyAge || '-' }}</span>
- </div>
- <div class="info-item">
- <label>就诊人性别:</label>
- <span>{{ getGenderText(prescriptionDetail.userFamilyGender) }}</span>
- </div>
- <div class="info-item">
- <label>就诊人手机号:</label>
- <span>{{ prescriptionDetail.userFamilyPhone || '-' }}</span>
- </div>
- <div class="info-item">
- <label>关系:</label>
- <span>{{ getRelationshipText(prescriptionDetail.relationship) }}</span>
- </div>
- <div class="info-item">
- <label>就诊人住址:</label>
- <span>{{ prescriptionDetail.userFamilyAddr || '-' }}</span>
- </div>
- <div class="info-item">
- <label>医院名称:</label>
- <span>{{ prescriptionDetail.hospitalName || '-' }}</span>
- </div>
- <div class="info-item">
- <label>药店ID:</label>
- <span>{{ prescriptionDetail.storeId || '-' }}</span>
- </div>
- <div class="info-item">
- <label>药店名称:</label>
- <span>{{ prescriptionDetail.storeName || '-' }}</span>
- </div>
- <div class="info-item">
- <label>医生ID:</label>
- <span>{{ prescriptionDetail.doctorId || '-' }}</span>
- </div>
- <div class="info-item">
- <label>医生姓名:</label>
- <span>{{ prescriptionDetail.doctorName || '-' }}</span>
- </div>
- <div class="info-item">
- <label>医生科室:</label>
- <span>{{ prescriptionDetail.doctorOffice || '-' }}</span>
- </div>
- <div class="info-item">
- <label>医生签名时间:</label>
- <span>{{ parseTime(prescriptionDetail.doctorSignTime) || '-' }}</span>
- </div>
- <div class="info-item">
- <label>诊断标签:</label>
- <span>{{ prescriptionDetail.tags || '-' }}</span>
- </div>
- <div class="info-item">
- <label>处方状态:</label>
- <span>{{ getStatusText(prescriptionDetail.status) }}</span>
- </div>
- <div class="info-item">
- <label>审核状态:</label>
- <span>{{ getAuditStatusText(prescriptionDetail.auditStatus) }}</span>
- </div>
- <div class="info-item">
- <label>审方药师:</label>
- <span>{{ prescriptionDetail.auditApothecaryName || '-' }}</span>
- </div>
- <div class="info-item">
- <label>审方时间:</label>
- <span>{{ parseTime(prescriptionDetail.auditTime) || '-' }}</span>
- </div>
- <div class="info-item">
- <label>审核不通过理由:</label>
- <span>{{ prescriptionDetail.reason || '-' }}</span>
- </div>
- <div class="info-item">
- <label>图片附件URL:</label>
- <span>{{ prescriptionDetail.imgList || '-' }}</span>
- </div>
- <div class="info-item">
- <label>三方跳转地址:</label>
- <span>{{ prescriptionDetail.thirdReturnUrl || '-' }}</span>
- </div>
- <div class="info-item">
- <label>问诊知情确认页面URL:</label>
- <span>{{ prescriptionDetail.jumpUrl || '-' }}</span>
- </div>
- <div class="info-item">
- <label>处方图片地址:</label>
- <span>{{ prescriptionDetail.dstFilePath || '-' }}</span>
- </div>
- <div class="info-item">
- <label>备注:</label>
- <span>{{ prescriptionDetail.memo || '-' }}</span>
- </div>
- <div class="info-item">
- <label>说明:</label>
- <span>{{ prescriptionDetail.remarks || '-' }}</span>
- </div>
- <div class="info-item">
- <label>问诊时间:</label>
- <span>{{ parseTime(prescriptionDetail.createTime) || '-' }}</span>
- </div>
- <div class="info-item">
- <label>开方时间:</label>
- <span>{{ parseTime(prescriptionDetail.createdTime) || '-' }}</span>
- </div>
- <div class="info-item">
- <label>更新时间:</label>
- <span>{{ parseTime(prescriptionDetail.updateTime) || '-' }}</span>
- </div>
- </div>
- </div>
-
- <!-- 药品列表 -->
- <div class="list-title">药品列表</div>
- <el-table
- :data="prescriptionDetail.drugRspList || []"
- border
- style="width: 100%; margin-bottom: 20px;"
- :empty-text="prescriptionDetail.drugRspList && prescriptionDetail.drugRspList.length === 0 ? '暂无药品信息' : ''"
- >
- <el-table-column prop="drugCommonName" label="药品通用名" />
- <el-table-column prop="drugName" label="药品名称" />
- <el-table-column prop="amount" label="药品数量" width="100" />
- <el-table-column prop="instructions" label="使用说明" />
- <el-table-column prop="spec" label="药品规格" />
- <el-table-column prop="commodityCode" label="三方商品编码" width="120" />
- <el-table-column prop="medicineId" label="系统药品ID" width="120" />
- </el-table>
-
- <!-- 问诊答案列表 -->
- <div class="list-title">问诊答案列表</div>
- <el-table
- :data="prescriptionDetail.beforeAiDataList || []"
- border
- style="width: 100%; margin-bottom: 20px;"
- :empty-text="prescriptionDetail.beforeAiDataList && prescriptionDetail.beforeAiDataList.length === 0 ? '暂无问诊答案信息' : ''"
- >
- <el-table-column prop="subjectId" label="题目ID" width="80" />
- <el-table-column prop="title" label="题目" />
- <el-table-column prop="answer" label="答案" />
- <el-table-column prop="answerMedicine" label="用药信息" width="150" />
- </el-table>
- </div>
-
- </div>
- </el-tab-pane>
- <!-- 聊天内容选项卡 -->
- <el-tab-pane label="聊天内容" name="chat">
- <div class="chat-content" v-loading="chatLoading">
- <el-card class="chat-card">
- <div class="chat-container">
- <!-- 聊天消息列表 -->
- <div
- v-for="(message, index) in chatMessages"
- :key="index"
- class="message-item"
- :class="{ 'patient-message': message.target === 1, 'doctor-message': message.target === 2 }"
- >
- <!-- 医生消息 - 左对齐 -->
- <template v-if="message.target === 2">
- <div class="message-avatar">
- <el-avatar :size="32" :src="doctorAvatar">医</el-avatar>
- </div>
- <div class="message-bubble doctor-bubble">
- <!-- type=1: 纯文本内容 -->
- <div class="message-content" v-if="message.type === 1">
- <!-- 检查是否为处方信息 -->
- <template v-if="isPrescriptionContent(message.content)">
- <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
- </template>
- <template v-else>
- {{ message.content }}
- </template>
- </div>
- <!-- type=2: 图片内容 -->
- <div class="message-content" v-else-if="message.type === 2">
- <el-image
- :src="message.content"
- fit="cover"
- style="width: 200px; height: 150px;"
- :preview-src-list="[message.content]"
- />
- </div>
- <!-- type=3: JSON数据渲染 -->
- <div class="message-content" v-else-if="message.type === 3">
- <template v-if="isPrescriptionContent(message.content)">
- <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
- </template>
- <template v-else>
- <pre class="json-content">{{ formatJsonContent(message.content) }}</pre>
- </template>
- </div>
- <!-- type=4: 格式化文本(HTML标签解析) -->
- <div class="message-content" v-else-if="message.type === 4">
- <div class="formatted-text" v-html="message.content"></div>
- </div>
- <!-- 其他类型: 默认显示 -->
- <div class="message-content" v-else>
- {{ message.content }}
- </div>
- <div class="message-time">
- {{ parseTime(message.createdTime) }}
- </div>
- </div>
- </template>
-
- <!-- 患者消息 - 右对齐 -->
- <template v-else>
- <div class="message-bubble patient-bubble">
- <!-- type=1: 纯文本内容 -->
- <div class="message-content" v-if="message.type === 1">
- <!-- 检查是否为处方信息 -->
- <template v-if="isPrescriptionContent(message.content)">
- <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
- </template>
- <template v-else>
- {{ message.content }}
- </template>
- </div>
- <!-- type=2: 图片内容 -->
- <div class="message-content" v-else-if="message.type === 2">
- <el-image
- :src="message.content"
- fit="cover"
- style="width: 200px; height: 150px;"
- :preview-src-list="[message.content]"
- />
- </div>
- <!-- type=3: JSON数据渲染 -->
- <div class="message-content" v-else-if="message.type === 3">
- <template v-if="isPrescriptionContent(message.content)">
- <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
- </template>
- <template v-else>
- <pre class="json-content">{{ formatJsonContent(message.content) }}</pre>
- </template>
- </div>
- <!-- type=4: 格式化文本(HTML标签解析) -->
- <div class="message-content" v-else-if="message.type === 4">
- <div class="formatted-text" v-html="message.content"></div>
- </div>
- <!-- 其他类型: 默认显示 -->
- <div class="message-content" v-else>
- {{ message.content }}
- </div>
- <div class="message-time">
- {{ parseTime(message.createdTime) }}
- </div>
- </div>
- <div class="message-avatar">
- <el-avatar :size="32" :src="userAvatar">患</el-avatar>
- </div>
- </template>
- </div>
-
- <!-- 空状态提示 -->
- <div v-if="chatMessages.length === 0 && !chatLoading" class="no-messages">
- 暂无聊天记录
- </div>
- </div>
- </el-card>
- </div>
- </el-tab-pane>
- </el-tabs>
- </div>
- </template>
- <script>
- import { getPrescription, getChatMessages } from "@/api/hisStore/storePrescription";
- import PrescriptionCard from "@/components/PrescriptionCard/index.vue";
- export default {
- name: "StorePrescriptionDetail",
- components: {
- PrescriptionCard
- },
- data() {
- return {
- // 当前选中的选项卡
- activeTab: 'detail',
- // 处方ID
- preId: null,
- // 详细信息加载状态
- detailLoading: false,
- // 问诊信息加载状态
- consultationLoading: false,
- // 聊天内容加载状态
- chatLoading: false,
- // 处方详情数据
- prescriptionDetail: {},
- // 聊天消息数据
- chatMessages: [],
- // 头像
- doctorAvatar: '',
- userAvatar: '',
- // 性别选项
- genderOptions: [
- { dictLabel: "未知", dictValue: "0" },
- { dictLabel: "男", dictValue: "1" },
- { dictLabel: "女", dictValue: "2" }
- ],
- // 审核状态选项
- auditStatusOptions: [
- { dictLabel: "待审核", dictValue: "1" },
- { dictLabel: "审核通过", dictValue: "2" },
- { dictLabel: "审核不通过", dictValue: "3" }
- ]
- };
- },
- created() {
- this.preId = this.$route.params.preId;
- this.getPrescriptionDetail();
- },
- methods: {
- /** 返回列表 */
- goBack() {
- this.$router.go(-1);
- },
- /** 选项卡切换 */
- handleTabClick(tab) {
- if (tab.name === 'chat' && this.chatMessages.length === 0) {
- this.getChatMessages();
- }
- },
- /** 获取处方详情 */
- getPrescriptionDetail() {
- this.detailLoading = true;
- getPrescription(this.preId).then(response => {
- this.prescriptionDetail = response.data;
- this.detailLoading = false;
- }).catch(() => {
- this.detailLoading = false;
- });
- },
- /** 获取聊天消息 */
- getChatMessages() {
- this.chatLoading = true;
- getChatMessages(this.preId).then(response => {
- this.chatMessages = response.data || [];
- this.chatLoading = false;
- }).catch(() => {
- this.chatLoading = false;
- // 不显示模拟数据,保持空数组
- this.chatMessages = [];
- });
- },
- /** 获取性别文本 */
- getGenderText(value) {
- const option = this.genderOptions.find(item => item.dictValue === String(value));
- return option ? option.dictLabel : '-';
- },
- /** 获取审核状态文本 */
- getAuditStatusText(value) {
- const option = this.auditStatusOptions.find(item => item.dictValue === String(value));
- return option ? option.dictLabel : '-';
- },
- /** 获取服务类型文本 */
- getServiceTypeText(value) {
- const types = { '0': '图文', '1': '视频' };
- return types[String(value)] || '-';
- },
- /** 获取是否文本 */
- getYesNoText(value) {
- const types = { '0': '否', '1': '是' };
- return types[String(value)] || '-';
- },
- /** 获取来源文本 */
- getSourceText(value) {
- const sources = { '0': '微信小程序', '1': 'APP', '2': 'H5', '3': '支付宝小程序' };
- return sources[String(value)] || '-';
- },
- /** 获取关系文本 */
- getRelationshipText(value) {
- const relationships = { '1': '本人', '2': '父母', '3': '配偶', '4': '子女', '5': '其他' };
- return relationships[String(value)] || '-';
- },
- /** 检查是否为处方信息 */
- isPrescriptionContent(content) {
- // 检查输入是否为有效字符串
- if (!content || typeof content !== 'string') {
- return false;
- }
-
- try {
- const parsed = JSON.parse(content);
- // 检查解析结果是否为对象,且包含必要字段
- return parsed &&
- typeof parsed === 'object' &&
- parsed.id &&
- parsed.list &&
- Array.isArray(parsed.list);
- } catch (e) {
- return false;
- }
- },
- /** 解析处方信息内容 */
- parsePrescriptionContent(content) {
- try {
- return JSON.parse(content);
- } catch (e) {
- return null;
- }
- },
- /** 格式化JSON内容显示 */
- formatJsonContent(content) {
- try {
- const parsed = JSON.parse(content);
- return JSON.stringify(parsed, null, 2);
- } catch (e) {
- return content;
- }
- },
- /** 获取开方情况文本 */
- getPrescriptionStatusText(value) {
- const statuses = { '0': '未开方', '1': '开方', '2': '拒绝' };
- return statuses[String(value)] || '-';
- },
- /** 获取处方状态文本 */
- getStatusText(value) {
- const statuses = { '1': '正常', '2': '已作废' };
- return statuses[String(value)] || '-';
- }
- }
- };
- </script>
- <style scoped>
- .detail-container {
- padding: 20px;
- background-color: #f8f9fa;
- min-height: 100vh;
- }
- .detail-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- padding: 16px 0;
- border-bottom: 1px solid #e9ecef;
- }
- .detail-title {
- font-size: 20px;
- font-weight: 600;
- color: #212529;
- margin: 0;
- }
- .back-button {
- background-color: #6c757d;
- border-color: #6c757d;
- color: #ffffff;
- }
- .back-button:hover {
- background-color: #5a6268;
- border-color: #545b62;
- }
- .detail-tabs {
- background-color: #ffffff;
- border-radius: 8px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
- }
- .detail-card {
- border: none;
- box-shadow: none;
- background-color: #ffffff;
- }
- .detail-info {
- padding: 24px;
- }
- /* 信息网格布局 */
- .info-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
- gap: 16px 24px;
- padding: 0;
- }
- .info-item {
- display: flex;
- align-items: flex-start;
- padding: 12px 0;
- border-bottom: 1px solid #f0f0f0;
- min-height: 40px;
- }
- .info-item:last-child {
- border-bottom: none;
- }
- .info-item label {
- font-weight: 500;
- color: #333333;
- min-width: 120px;
- margin-right: 12px;
- flex-shrink: 0;
- font-size: 14px;
- line-height: 1.5;
- }
- .info-item span {
- color: #666666;
- flex: 1;
- word-break: break-all;
- font-size: 14px;
- line-height: 1.5;
- }
- .list-title {
- font-size: 16px;
- font-weight: 600;
- color: #212529;
- margin: 32px 0 16px 0;
- padding: 12px 0;
- border-bottom: 2px solid #dee2e6;
- background-color: #f8f9fa;
- padding-left: 16px;
- border-radius: 4px 4px 0 0;
- }
- /* 表格样式优化 */
- :deep(.el-table) {
- border: 1px solid #dee2e6;
- border-radius: 6px;
- overflow: hidden;
- }
- :deep(.el-table th) {
- background-color: #f8f9fa;
- color: #495057;
- font-weight: 600;
- border-bottom: 1px solid #dee2e6;
- }
- :deep(.el-table td) {
- color: #212529;
- border-bottom: 1px solid #f1f3f4;
- }
- :deep(.el-table tr:hover > td) {
- background-color: #f8f9fa;
- }
- /* 选项卡样式 */
- :deep(.el-tabs__header) {
- margin: 0;
- border-bottom: 1px solid #dee2e6;
- background-color: #f8f9fa;
- }
- :deep(.el-tabs__nav-wrap) {
- padding: 0 24px;
- }
- :deep(.el-tabs__item) {
- color: #6c757d;
- font-weight: 500;
- padding: 0 20px;
- height: 48px;
- line-height: 48px;
- }
- :deep(.el-tabs__item.is-active) {
- color: #212529;
- font-weight: 600;
- }
- :deep(.el-tabs__active-bar) {
- background-color: #495057;
- }
- /* 聊天内容样式 */
- .chat-content {
- background-color: #ffffff;
- }
- .chat-card {
- border: none;
- box-shadow: none;
- background-color: #ffffff;
- }
- .chat-container {
- padding: 24px;
- max-height: 600px;
- overflow-y: auto;
- background-color: #f8f9fa;
- border-radius: 8px;
- }
- .message-item {
- display: flex;
- margin-bottom: 16px;
- align-items: flex-start;
- }
- .doctor-message {
- justify-content: flex-start;
- }
- .patient-message {
- justify-content: flex-end;
- }
- .message-bubble {
- max-width: 60%;
- border-radius: 12px;
- padding: 12px 16px;
- position: relative;
- margin: 0 10px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- }
- .doctor-bubble {
- background-color: #ffffff;
- color: #212529;
- border: 1px solid #dee2e6;
- }
- .patient-bubble {
- background-color: #6c757d;
- color: #ffffff;
- }
- .message-content {
- word-break: break-word;
- line-height: 1.5;
- font-size: 14px;
- }
- /* 格式化文本样式 */
- .formatted-text {
- line-height: 1.6;
- font-size: 14px;
- }
- .formatted-text br {
- line-height: 1.8;
- }
- /* JSON内容样式 */
- .json-content {
- background-color: #f8f9fa;
- border: 1px solid #e9ecef;
- border-radius: 4px;
- padding: 12px;
- font-family: 'Courier New', monospace;
- font-size: 12px;
- line-height: 1.4;
- color: #495057;
- white-space: pre-wrap;
- word-break: break-all;
- max-width: 100%;
- overflow-x: auto;
- }
- .message-time {
- font-size: 12px;
- margin-top: 8px;
- text-align: right;
- opacity: 0.7;
- }
- .doctor-bubble .message-time {
- color: #6c757d;
- }
- .patient-bubble .message-time {
- color: rgba(255, 255, 255, 0.8);
- }
- .message-avatar {
- flex-shrink: 0;
- }
- .no-messages {
- text-align: center;
- color: #6c757d;
- padding: 60px 0;
- font-size: 14px;
- background-color: #ffffff;
- border-radius: 8px;
- border: 1px solid #dee2e6;
- }
- /* 响应式设计 */
- @media (max-width: 768px) {
- .detail-container {
- padding: 16px;
- }
-
- .detail-info {
- padding: 16px;
- }
-
- .info-item {
- flex-direction: column;
- align-items: flex-start;
- padding: 8px 0;
- }
-
- .info-item label {
- margin-bottom: 4px;
- min-width: auto;
- }
-
- .message-bubble {
- max-width: 80%;
- }
-
- .chat-container {
- padding: 16px;
- }
-
- .list-title {
- margin: 24px 0 12px 0;
- padding-left: 12px;
- }
- }
- </style>
|