detail.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. <template>
  2. <div class="detail-container">
  3. <!-- 页面头部 -->
  4. <div class="detail-header">
  5. <h2 class="detail-title">处方订单详情</h2>
  6. <el-button
  7. type="primary"
  8. icon="el-icon-arrow-left"
  9. @click="goBack"
  10. class="back-button"
  11. plain
  12. >
  13. 返回列表
  14. </el-button>
  15. </div>
  16. <!-- 选项卡 -->
  17. <el-tabs v-model="activeTab" class="detail-tabs" @tab-click="handleTabClick">
  18. <!-- 详细信息选项卡 -->
  19. <el-tab-pane label="详细信息" name="detail">
  20. <div class="detail-content" v-loading="detailLoading">
  21. <div class="detail-card">
  22. <div class="detail-info">
  23. <div class="info-grid">
  24. <div class="info-item">
  25. <label>用户ID:</label>
  26. <span>{{ prescriptionDetail.userId || '-' }}</span>
  27. </div>
  28. <div class="info-item">
  29. <label>处方ID:</label>
  30. <span>{{ prescriptionDetail.pid || '-' }}</span>
  31. </div>
  32. <div class="info-item">
  33. <label>处方编号:</label>
  34. <span>{{ prescriptionDetail.serialNo || '-' }}</span>
  35. </div>
  36. <div class="info-item">
  37. <label>问诊单ID:</label>
  38. <span>{{ prescriptionDetail.diagnosisId || '-' }}</span>
  39. </div>
  40. <div class="info-item">
  41. <label>商城订单ID:</label>
  42. <span>{{ prescriptionDetail.storeOrderId || '-' }}</span>
  43. </div>
  44. <div class="info-item">
  45. <label>服务类型:</label>
  46. <span>{{ getServiceTypeText(prescriptionDetail.serviceType) }}</span>
  47. </div>
  48. <div class="info-item">
  49. <label>是否需要审方:</label>
  50. <span>{{ getYesNoText(prescriptionDetail.isExamine) }}</span>
  51. </div>
  52. <div class="info-item">
  53. <label>来源:</label>
  54. <span>{{ getSourceText(prescriptionDetail.souceFrom) }}</span>
  55. </div>
  56. <div class="info-item">
  57. <label>是否孕妇:</label>
  58. <span>{{ getYesNoText(prescriptionDetail.isPregnantWoman) }}</span>
  59. </div>
  60. <div class="info-item">
  61. <label>是否哺乳期:</label>
  62. <span>{{ getYesNoText(prescriptionDetail.isLactation) }}</span>
  63. </div>
  64. <div class="info-item">
  65. <label>开方情况:</label>
  66. <span>{{ getPrescriptionStatusText(prescriptionDetail.prescriptionStatus) }}</span>
  67. </div>
  68. <div class="info-item">
  69. <label>就诊人姓名:</label>
  70. <span>{{ prescriptionDetail.userFamilyName || '-' }}</span>
  71. </div>
  72. <div class="info-item">
  73. <label>就诊人身份证:</label>
  74. <span>{{ prescriptionDetail.userFamilyIdCard || '-' }}</span>
  75. </div>
  76. <div class="info-item">
  77. <label>就诊人年龄:</label>
  78. <span>{{ prescriptionDetail.userFamilyAge || '-' }}</span>
  79. </div>
  80. <div class="info-item">
  81. <label>就诊人性别:</label>
  82. <span>{{ getGenderText(prescriptionDetail.userFamilyGender) }}</span>
  83. </div>
  84. <div class="info-item">
  85. <label>就诊人手机号:</label>
  86. <span>{{ prescriptionDetail.userFamilyPhone || '-' }}</span>
  87. </div>
  88. <div class="info-item">
  89. <label>关系:</label>
  90. <span>{{ getRelationshipText(prescriptionDetail.relationship) }}</span>
  91. </div>
  92. <div class="info-item">
  93. <label>就诊人住址:</label>
  94. <span>{{ prescriptionDetail.userFamilyAddr || '-' }}</span>
  95. </div>
  96. <div class="info-item">
  97. <label>医院名称:</label>
  98. <span>{{ prescriptionDetail.hospitalName || '-' }}</span>
  99. </div>
  100. <div class="info-item">
  101. <label>药店ID:</label>
  102. <span>{{ prescriptionDetail.storeId || '-' }}</span>
  103. </div>
  104. <div class="info-item">
  105. <label>药店名称:</label>
  106. <span>{{ prescriptionDetail.storeName || '-' }}</span>
  107. </div>
  108. <div class="info-item">
  109. <label>医生ID:</label>
  110. <span>{{ prescriptionDetail.doctorId || '-' }}</span>
  111. </div>
  112. <div class="info-item">
  113. <label>医生姓名:</label>
  114. <span>{{ prescriptionDetail.doctorName || '-' }}</span>
  115. </div>
  116. <div class="info-item">
  117. <label>医生科室:</label>
  118. <span>{{ prescriptionDetail.doctorOffice || '-' }}</span>
  119. </div>
  120. <div class="info-item">
  121. <label>医生签名时间:</label>
  122. <span>{{ parseTime(prescriptionDetail.doctorSignTime) || '-' }}</span>
  123. </div>
  124. <div class="info-item">
  125. <label>诊断标签:</label>
  126. <span>{{ prescriptionDetail.tags || '-' }}</span>
  127. </div>
  128. <div class="info-item">
  129. <label>处方状态:</label>
  130. <span>{{ getStatusText(prescriptionDetail.status) }}</span>
  131. </div>
  132. <div class="info-item">
  133. <label>审核状态:</label>
  134. <span>{{ getAuditStatusText(prescriptionDetail.auditStatus) }}</span>
  135. </div>
  136. <div class="info-item">
  137. <label>审方药师:</label>
  138. <span>{{ prescriptionDetail.auditApothecaryName || '-' }}</span>
  139. </div>
  140. <div class="info-item">
  141. <label>审方时间:</label>
  142. <span>{{ parseTime(prescriptionDetail.auditTime) || '-' }}</span>
  143. </div>
  144. <div class="info-item">
  145. <label>审核不通过理由:</label>
  146. <span>{{ prescriptionDetail.reason || '-' }}</span>
  147. </div>
  148. <div class="info-item">
  149. <label>图片附件URL:</label>
  150. <span>{{ prescriptionDetail.imgList || '-' }}</span>
  151. </div>
  152. <div class="info-item">
  153. <label>三方跳转地址:</label>
  154. <span>{{ prescriptionDetail.thirdReturnUrl || '-' }}</span>
  155. </div>
  156. <div class="info-item">
  157. <label>问诊知情确认页面URL:</label>
  158. <span>{{ prescriptionDetail.jumpUrl || '-' }}</span>
  159. </div>
  160. <div class="info-item">
  161. <label>处方图片地址:</label>
  162. <span>{{ prescriptionDetail.dstFilePath || '-' }}</span>
  163. </div>
  164. <div class="info-item">
  165. <label>备注:</label>
  166. <span>{{ prescriptionDetail.memo || '-' }}</span>
  167. </div>
  168. <div class="info-item">
  169. <label>说明:</label>
  170. <span>{{ prescriptionDetail.remarks || '-' }}</span>
  171. </div>
  172. <div class="info-item">
  173. <label>问诊时间:</label>
  174. <span>{{ parseTime(prescriptionDetail.createTime) || '-' }}</span>
  175. </div>
  176. <div class="info-item">
  177. <label>开方时间:</label>
  178. <span>{{ parseTime(prescriptionDetail.createdTime) || '-' }}</span>
  179. </div>
  180. <div class="info-item">
  181. <label>更新时间:</label>
  182. <span>{{ parseTime(prescriptionDetail.updateTime) || '-' }}</span>
  183. </div>
  184. </div>
  185. </div>
  186. <!-- 药品列表 -->
  187. <div class="list-title">药品列表</div>
  188. <el-table
  189. :data="prescriptionDetail.drugRspList || []"
  190. border
  191. style="width: 100%; margin-bottom: 20px;"
  192. :empty-text="prescriptionDetail.drugRspList && prescriptionDetail.drugRspList.length === 0 ? '暂无药品信息' : ''"
  193. >
  194. <el-table-column prop="drugCommonName" label="药品通用名" />
  195. <el-table-column prop="drugName" label="药品名称" />
  196. <el-table-column prop="amount" label="药品数量" width="100" />
  197. <el-table-column prop="instructions" label="使用说明" />
  198. <el-table-column prop="spec" label="药品规格" />
  199. <el-table-column prop="commodityCode" label="三方商品编码" width="120" />
  200. <el-table-column prop="medicineId" label="系统药品ID" width="120" />
  201. </el-table>
  202. <!-- 问诊答案列表 -->
  203. <div class="list-title">问诊答案列表</div>
  204. <el-table
  205. :data="prescriptionDetail.beforeAiDataList || []"
  206. border
  207. style="width: 100%; margin-bottom: 20px;"
  208. :empty-text="prescriptionDetail.beforeAiDataList && prescriptionDetail.beforeAiDataList.length === 0 ? '暂无问诊答案信息' : ''"
  209. >
  210. <el-table-column prop="subjectId" label="题目ID" width="80" />
  211. <el-table-column prop="title" label="题目" />
  212. <el-table-column prop="answer" label="答案" />
  213. <el-table-column prop="answerMedicine" label="用药信息" width="150" />
  214. </el-table>
  215. </div>
  216. </div>
  217. </el-tab-pane>
  218. <!-- 聊天内容选项卡 -->
  219. <el-tab-pane label="聊天内容" name="chat">
  220. <div class="chat-content" v-loading="chatLoading">
  221. <el-card class="chat-card">
  222. <div class="chat-container">
  223. <!-- 聊天消息列表 -->
  224. <div
  225. v-for="(message, index) in chatMessages"
  226. :key="index"
  227. class="message-item"
  228. :class="{ 'patient-message': message.target === 1, 'doctor-message': message.target === 2 }"
  229. >
  230. <!-- 医生消息 - 左对齐 -->
  231. <template v-if="message.target === 2">
  232. <div class="message-avatar">
  233. <el-avatar :size="32" :src="doctorAvatar">医</el-avatar>
  234. </div>
  235. <div class="message-bubble doctor-bubble">
  236. <!-- type=1: 纯文本内容 -->
  237. <div class="message-content" v-if="message.type === 1">
  238. <!-- 检查是否为处方信息 -->
  239. <template v-if="isPrescriptionContent(message.content)">
  240. <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
  241. </template>
  242. <template v-else>
  243. {{ message.content }}
  244. </template>
  245. </div>
  246. <!-- type=2: 图片内容 -->
  247. <div class="message-content" v-else-if="message.type === 2">
  248. <el-image
  249. :src="message.content"
  250. fit="cover"
  251. style="width: 200px; height: 150px;"
  252. :preview-src-list="[message.content]"
  253. />
  254. </div>
  255. <!-- type=3: JSON数据渲染 -->
  256. <div class="message-content" v-else-if="message.type === 3">
  257. <template v-if="isPrescriptionContent(message.content)">
  258. <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
  259. </template>
  260. <template v-else>
  261. <pre class="json-content">{{ formatJsonContent(message.content) }}</pre>
  262. </template>
  263. </div>
  264. <!-- type=4: 格式化文本(HTML标签解析) -->
  265. <div class="message-content" v-else-if="message.type === 4">
  266. <div class="formatted-text" v-html="message.content"></div>
  267. </div>
  268. <!-- 其他类型: 默认显示 -->
  269. <div class="message-content" v-else>
  270. {{ message.content }}
  271. </div>
  272. <div class="message-time">
  273. {{ parseTime(message.createdTime) }}
  274. </div>
  275. </div>
  276. </template>
  277. <!-- 患者消息 - 右对齐 -->
  278. <template v-else>
  279. <div class="message-bubble patient-bubble">
  280. <!-- type=1: 纯文本内容 -->
  281. <div class="message-content" v-if="message.type === 1">
  282. <!-- 检查是否为处方信息 -->
  283. <template v-if="isPrescriptionContent(message.content)">
  284. <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
  285. </template>
  286. <template v-else>
  287. {{ message.content }}
  288. </template>
  289. </div>
  290. <!-- type=2: 图片内容 -->
  291. <div class="message-content" v-else-if="message.type === 2">
  292. <el-image
  293. :src="message.content"
  294. fit="cover"
  295. style="width: 200px; height: 150px;"
  296. :preview-src-list="[message.content]"
  297. />
  298. </div>
  299. <!-- type=3: JSON数据渲染 -->
  300. <div class="message-content" v-else-if="message.type === 3">
  301. <template v-if="isPrescriptionContent(message.content)">
  302. <PrescriptionCard :prescriptionData="parsePrescriptionContent(message.content)" />
  303. </template>
  304. <template v-else>
  305. <pre class="json-content">{{ formatJsonContent(message.content) }}</pre>
  306. </template>
  307. </div>
  308. <!-- type=4: 格式化文本(HTML标签解析) -->
  309. <div class="message-content" v-else-if="message.type === 4">
  310. <div class="formatted-text" v-html="message.content"></div>
  311. </div>
  312. <!-- 其他类型: 默认显示 -->
  313. <div class="message-content" v-else>
  314. {{ message.content }}
  315. </div>
  316. <div class="message-time">
  317. {{ parseTime(message.createdTime) }}
  318. </div>
  319. </div>
  320. <div class="message-avatar">
  321. <el-avatar :size="32" :src="userAvatar">患</el-avatar>
  322. </div>
  323. </template>
  324. </div>
  325. <!-- 空状态提示 -->
  326. <div v-if="chatMessages.length === 0 && !chatLoading" class="no-messages">
  327. 暂无聊天记录
  328. </div>
  329. </div>
  330. </el-card>
  331. </div>
  332. </el-tab-pane>
  333. </el-tabs>
  334. </div>
  335. </template>
  336. <script>
  337. import { getPrescription, getChatMessages } from "@/api/hisStore/storePrescription";
  338. import PrescriptionCard from "@/components/PrescriptionCard/index.vue";
  339. export default {
  340. name: "StorePrescriptionDetail",
  341. components: {
  342. PrescriptionCard
  343. },
  344. data() {
  345. return {
  346. // 当前选中的选项卡
  347. activeTab: 'detail',
  348. // 处方ID
  349. preId: null,
  350. // 详细信息加载状态
  351. detailLoading: false,
  352. // 问诊信息加载状态
  353. consultationLoading: false,
  354. // 聊天内容加载状态
  355. chatLoading: false,
  356. // 处方详情数据
  357. prescriptionDetail: {},
  358. // 聊天消息数据
  359. chatMessages: [],
  360. // 头像
  361. doctorAvatar: '',
  362. userAvatar: '',
  363. // 性别选项
  364. genderOptions: [
  365. { dictLabel: "未知", dictValue: "0" },
  366. { dictLabel: "男", dictValue: "1" },
  367. { dictLabel: "女", dictValue: "2" }
  368. ],
  369. // 审核状态选项
  370. auditStatusOptions: [
  371. { dictLabel: "待审核", dictValue: "1" },
  372. { dictLabel: "审核通过", dictValue: "2" },
  373. { dictLabel: "审核不通过", dictValue: "3" }
  374. ]
  375. };
  376. },
  377. created() {
  378. this.preId = this.$route.params.preId;
  379. this.getPrescriptionDetail();
  380. },
  381. methods: {
  382. /** 返回列表 */
  383. goBack() {
  384. this.$router.go(-1);
  385. },
  386. /** 选项卡切换 */
  387. handleTabClick(tab) {
  388. if (tab.name === 'chat' && this.chatMessages.length === 0) {
  389. this.getChatMessages();
  390. }
  391. },
  392. /** 获取处方详情 */
  393. getPrescriptionDetail() {
  394. this.detailLoading = true;
  395. getPrescription(this.preId).then(response => {
  396. this.prescriptionDetail = response.data;
  397. this.detailLoading = false;
  398. }).catch(() => {
  399. this.detailLoading = false;
  400. });
  401. },
  402. /** 获取聊天消息 */
  403. getChatMessages() {
  404. this.chatLoading = true;
  405. getChatMessages(this.preId).then(response => {
  406. this.chatMessages = response.data || [];
  407. this.chatLoading = false;
  408. }).catch(() => {
  409. this.chatLoading = false;
  410. // 不显示模拟数据,保持空数组
  411. this.chatMessages = [];
  412. });
  413. },
  414. /** 获取性别文本 */
  415. getGenderText(value) {
  416. const option = this.genderOptions.find(item => item.dictValue === String(value));
  417. return option ? option.dictLabel : '-';
  418. },
  419. /** 获取审核状态文本 */
  420. getAuditStatusText(value) {
  421. const option = this.auditStatusOptions.find(item => item.dictValue === String(value));
  422. return option ? option.dictLabel : '-';
  423. },
  424. /** 获取服务类型文本 */
  425. getServiceTypeText(value) {
  426. const types = { '0': '图文', '1': '视频' };
  427. return types[String(value)] || '-';
  428. },
  429. /** 获取是否文本 */
  430. getYesNoText(value) {
  431. const types = { '0': '否', '1': '是' };
  432. return types[String(value)] || '-';
  433. },
  434. /** 获取来源文本 */
  435. getSourceText(value) {
  436. const sources = { '0': '微信小程序', '1': 'APP', '2': 'H5', '3': '支付宝小程序' };
  437. return sources[String(value)] || '-';
  438. },
  439. /** 获取关系文本 */
  440. getRelationshipText(value) {
  441. const relationships = { '1': '本人', '2': '父母', '3': '配偶', '4': '子女', '5': '其他' };
  442. return relationships[String(value)] || '-';
  443. },
  444. /** 检查是否为处方信息 */
  445. isPrescriptionContent(content) {
  446. // 检查输入是否为有效字符串
  447. if (!content || typeof content !== 'string') {
  448. return false;
  449. }
  450. try {
  451. const parsed = JSON.parse(content);
  452. // 检查解析结果是否为对象,且包含必要字段
  453. return parsed &&
  454. typeof parsed === 'object' &&
  455. parsed.id &&
  456. parsed.list &&
  457. Array.isArray(parsed.list);
  458. } catch (e) {
  459. return false;
  460. }
  461. },
  462. /** 解析处方信息内容 */
  463. parsePrescriptionContent(content) {
  464. try {
  465. return JSON.parse(content);
  466. } catch (e) {
  467. return null;
  468. }
  469. },
  470. /** 格式化JSON内容显示 */
  471. formatJsonContent(content) {
  472. try {
  473. const parsed = JSON.parse(content);
  474. return JSON.stringify(parsed, null, 2);
  475. } catch (e) {
  476. return content;
  477. }
  478. },
  479. /** 获取开方情况文本 */
  480. getPrescriptionStatusText(value) {
  481. const statuses = { '0': '未开方', '1': '开方', '2': '拒绝' };
  482. return statuses[String(value)] || '-';
  483. },
  484. /** 获取处方状态文本 */
  485. getStatusText(value) {
  486. const statuses = { '1': '正常', '2': '已作废' };
  487. return statuses[String(value)] || '-';
  488. }
  489. }
  490. };
  491. </script>
  492. <style scoped>
  493. .detail-container {
  494. padding: 20px;
  495. background-color: #f8f9fa;
  496. min-height: 100vh;
  497. }
  498. .detail-header {
  499. display: flex;
  500. justify-content: space-between;
  501. align-items: center;
  502. margin-bottom: 20px;
  503. padding: 16px 0;
  504. border-bottom: 1px solid #e9ecef;
  505. }
  506. .detail-title {
  507. font-size: 20px;
  508. font-weight: 600;
  509. color: #212529;
  510. margin: 0;
  511. }
  512. .back-button {
  513. background-color: #6c757d;
  514. border-color: #6c757d;
  515. color: #ffffff;
  516. }
  517. .back-button:hover {
  518. background-color: #5a6268;
  519. border-color: #545b62;
  520. }
  521. .detail-tabs {
  522. background-color: #ffffff;
  523. border-radius: 8px;
  524. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  525. }
  526. .detail-card {
  527. border: none;
  528. box-shadow: none;
  529. background-color: #ffffff;
  530. }
  531. .detail-info {
  532. padding: 24px;
  533. }
  534. /* 信息网格布局 */
  535. .info-grid {
  536. display: grid;
  537. grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  538. gap: 16px 24px;
  539. padding: 0;
  540. }
  541. .info-item {
  542. display: flex;
  543. align-items: flex-start;
  544. padding: 12px 0;
  545. border-bottom: 1px solid #f0f0f0;
  546. min-height: 40px;
  547. }
  548. .info-item:last-child {
  549. border-bottom: none;
  550. }
  551. .info-item label {
  552. font-weight: 500;
  553. color: #333333;
  554. min-width: 120px;
  555. margin-right: 12px;
  556. flex-shrink: 0;
  557. font-size: 14px;
  558. line-height: 1.5;
  559. }
  560. .info-item span {
  561. color: #666666;
  562. flex: 1;
  563. word-break: break-all;
  564. font-size: 14px;
  565. line-height: 1.5;
  566. }
  567. .list-title {
  568. font-size: 16px;
  569. font-weight: 600;
  570. color: #212529;
  571. margin: 32px 0 16px 0;
  572. padding: 12px 0;
  573. border-bottom: 2px solid #dee2e6;
  574. background-color: #f8f9fa;
  575. padding-left: 16px;
  576. border-radius: 4px 4px 0 0;
  577. }
  578. /* 表格样式优化 */
  579. :deep(.el-table) {
  580. border: 1px solid #dee2e6;
  581. border-radius: 6px;
  582. overflow: hidden;
  583. }
  584. :deep(.el-table th) {
  585. background-color: #f8f9fa;
  586. color: #495057;
  587. font-weight: 600;
  588. border-bottom: 1px solid #dee2e6;
  589. }
  590. :deep(.el-table td) {
  591. color: #212529;
  592. border-bottom: 1px solid #f1f3f4;
  593. }
  594. :deep(.el-table tr:hover > td) {
  595. background-color: #f8f9fa;
  596. }
  597. /* 选项卡样式 */
  598. :deep(.el-tabs__header) {
  599. margin: 0;
  600. border-bottom: 1px solid #dee2e6;
  601. background-color: #f8f9fa;
  602. }
  603. :deep(.el-tabs__nav-wrap) {
  604. padding: 0 24px;
  605. }
  606. :deep(.el-tabs__item) {
  607. color: #6c757d;
  608. font-weight: 500;
  609. padding: 0 20px;
  610. height: 48px;
  611. line-height: 48px;
  612. }
  613. :deep(.el-tabs__item.is-active) {
  614. color: #212529;
  615. font-weight: 600;
  616. }
  617. :deep(.el-tabs__active-bar) {
  618. background-color: #495057;
  619. }
  620. /* 聊天内容样式 */
  621. .chat-content {
  622. background-color: #ffffff;
  623. }
  624. .chat-card {
  625. border: none;
  626. box-shadow: none;
  627. background-color: #ffffff;
  628. }
  629. .chat-container {
  630. padding: 24px;
  631. max-height: 600px;
  632. overflow-y: auto;
  633. background-color: #f8f9fa;
  634. border-radius: 8px;
  635. }
  636. .message-item {
  637. display: flex;
  638. margin-bottom: 16px;
  639. align-items: flex-start;
  640. }
  641. .doctor-message {
  642. justify-content: flex-start;
  643. }
  644. .patient-message {
  645. justify-content: flex-end;
  646. }
  647. .message-bubble {
  648. max-width: 60%;
  649. border-radius: 12px;
  650. padding: 12px 16px;
  651. position: relative;
  652. margin: 0 10px;
  653. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  654. }
  655. .doctor-bubble {
  656. background-color: #ffffff;
  657. color: #212529;
  658. border: 1px solid #dee2e6;
  659. }
  660. .patient-bubble {
  661. background-color: #6c757d;
  662. color: #ffffff;
  663. }
  664. .message-content {
  665. word-break: break-word;
  666. line-height: 1.5;
  667. font-size: 14px;
  668. }
  669. /* 格式化文本样式 */
  670. .formatted-text {
  671. line-height: 1.6;
  672. font-size: 14px;
  673. }
  674. .formatted-text br {
  675. line-height: 1.8;
  676. }
  677. /* JSON内容样式 */
  678. .json-content {
  679. background-color: #f8f9fa;
  680. border: 1px solid #e9ecef;
  681. border-radius: 4px;
  682. padding: 12px;
  683. font-family: 'Courier New', monospace;
  684. font-size: 12px;
  685. line-height: 1.4;
  686. color: #495057;
  687. white-space: pre-wrap;
  688. word-break: break-all;
  689. max-width: 100%;
  690. overflow-x: auto;
  691. }
  692. .message-time {
  693. font-size: 12px;
  694. margin-top: 8px;
  695. text-align: right;
  696. opacity: 0.7;
  697. }
  698. .doctor-bubble .message-time {
  699. color: #6c757d;
  700. }
  701. .patient-bubble .message-time {
  702. color: rgba(255, 255, 255, 0.8);
  703. }
  704. .message-avatar {
  705. flex-shrink: 0;
  706. }
  707. .no-messages {
  708. text-align: center;
  709. color: #6c757d;
  710. padding: 60px 0;
  711. font-size: 14px;
  712. background-color: #ffffff;
  713. border-radius: 8px;
  714. border: 1px solid #dee2e6;
  715. }
  716. /* 响应式设计 */
  717. @media (max-width: 768px) {
  718. .detail-container {
  719. padding: 16px;
  720. }
  721. .detail-info {
  722. padding: 16px;
  723. }
  724. .info-item {
  725. flex-direction: column;
  726. align-items: flex-start;
  727. padding: 8px 0;
  728. }
  729. .info-item label {
  730. margin-bottom: 4px;
  731. min-width: auto;
  732. }
  733. .message-bubble {
  734. max-width: 80%;
  735. }
  736. .chat-container {
  737. padding: 16px;
  738. }
  739. .list-title {
  740. margin: 24px 0 12px 0;
  741. padding-left: 12px;
  742. }
  743. }
  744. </style>