与牧同行-小程序用户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

896 lines
14 KiB

  1. /* 页面整体样式 */
  2. .consult-page {
  3. width: 100vw;
  4. height: 100vh;
  5. background: #f5f5f5;
  6. display: flex;
  7. flex-direction: column;
  8. }
  9. /* 头部样式 */
  10. .consult-header {
  11. background: #ffffff;
  12. border-bottom: 1rpx solid #e5e5e5;
  13. position: relative;
  14. z-index: 1000;
  15. box-shadow: 0 1rpx 6rpx rgba(0, 0, 0, 0.05);
  16. }
  17. .header-content {
  18. display: flex;
  19. align-items: center;
  20. padding: 12rpx 24rpx;
  21. height: 96rpx;
  22. }
  23. .header-center {
  24. flex: 1;
  25. display: flex;
  26. justify-content: center;
  27. }
  28. .expert-info {
  29. display: flex;
  30. flex-direction: column;
  31. align-items: center;
  32. justify-content: center;
  33. }
  34. .expert-name {
  35. font-size: 32rpx;
  36. font-weight: 600;
  37. color: #000000;
  38. line-height: 44rpx;
  39. margin-bottom: 4rpx;
  40. }
  41. .expert-status {
  42. display: flex;
  43. align-items: center;
  44. justify-content: center;
  45. }
  46. .status-dot {
  47. width: 16rpx;
  48. height: 16rpx;
  49. border-radius: 50%;
  50. margin-right: 8rpx;
  51. }
  52. .status-dot.online {
  53. background: #07c160;
  54. animation: pulse 2s infinite;
  55. }
  56. .status-dot.offline {
  57. background: #cccccc;
  58. }
  59. @keyframes pulse {
  60. 0% {
  61. box-shadow: 0 0 0 0 rgba(7, 193, 96, 0.4);
  62. }
  63. 70% {
  64. box-shadow: 0 0 0 8rpx rgba(7, 193, 96, 0);
  65. }
  66. 100% {
  67. box-shadow: 0 0 0 0 rgba(7, 193, 96, 0);
  68. }
  69. }
  70. .status-text {
  71. font-size: 24rpx;
  72. color: #666666;
  73. }
  74. /* 聊天容器 */
  75. .chat-container {
  76. flex: 1;
  77. padding: 20rpx 0;
  78. background: #f5f5f5;
  79. overflow-y: auto;
  80. position: relative;
  81. }
  82. /* 日期分隔线 */
  83. .date-divider {
  84. display: flex;
  85. justify-content: center;
  86. margin: 40rpx 0 30rpx;
  87. }
  88. .date-text {
  89. background: rgba(0, 0, 0, 0.1);
  90. padding: 8rpx 32rpx;
  91. border-radius: 100rpx;
  92. font-size: 24rpx;
  93. color: #ffffff;
  94. font-weight: 400;
  95. background-color: #d8d8d8;
  96. }
  97. /* 消息项 */
  98. .message-item {
  99. display: flex;
  100. margin-bottom: 24rpx;
  101. padding: 0 30rpx;
  102. opacity: 0;
  103. animation: fadeIn 0.3s ease forwards;
  104. align-items: flex-start;
  105. position: relative;
  106. }
  107. @keyframes fadeIn {
  108. from {
  109. opacity: 0;
  110. transform: translateY(10rpx);
  111. }
  112. to {
  113. opacity: 1;
  114. transform: translateY(0);
  115. }
  116. }
  117. .message-left {
  118. justify-content: flex-start;
  119. }
  120. .message-right {
  121. justify-content: flex-end;
  122. }
  123. /* 头像 */
  124. .message-avatar {
  125. width: 80rpx;
  126. height: 80rpx;
  127. border-radius: 8rpx;
  128. overflow: hidden;
  129. flex-shrink: 0;
  130. background: #ffffff;
  131. border: 1rpx solid #f0f0f0;
  132. position: relative;
  133. z-index: 1;
  134. }
  135. .message-left .message-avatar {
  136. margin-right: 16rpx;
  137. }
  138. .message-right .message-avatar {
  139. margin-left: 16rpx;
  140. }
  141. .avatar-img {
  142. width: 100%;
  143. height: 100%;
  144. object-fit: cover;
  145. }
  146. /* 消息内容包装器 */
  147. .message-content-wrapper {
  148. max-width: 480rpx;
  149. position: relative;
  150. display: flex;
  151. flex-direction: column;
  152. z-index: 2;
  153. }
  154. .message-left .message-content-wrapper {
  155. align-items: flex-start;
  156. }
  157. .message-right .message-content-wrapper {
  158. align-items: flex-end;
  159. }
  160. /* 气泡箭头*/
  161. .message-arrow {
  162. position: absolute;
  163. width: 0;
  164. height: 0;
  165. border-style: solid;
  166. border-width: 12rpx;
  167. top: 30rpx; /* 固定在头像中间位置 (80rpx/2 = 40rpx) */
  168. z-index: 1;
  169. }
  170. /* 左侧箭头(专家) */
  171. .arrow-left {
  172. left: -24rpx;
  173. border-color: transparent #ffffff transparent transparent;
  174. }
  175. /* 右侧箭头(用户) */
  176. .arrow-right {
  177. right: -24rpx;
  178. border-color: transparent transparent transparent #95ec69;
  179. }
  180. /* 消息气泡通用样式 */
  181. .message-bubble {
  182. position: relative;
  183. padding: 16rpx 20rpx;
  184. word-break: break-word;
  185. box-sizing: border-box;
  186. min-height: 60rpx;
  187. display: flex;
  188. align-items: center;
  189. }
  190. /* 左侧气泡(专家) */
  191. .bubble-left {
  192. background: #ffffff;
  193. border-radius: 10rpx;
  194. border-top-left-radius: 4rpx;
  195. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  196. }
  197. /* 右侧气泡(用户) */
  198. .bubble-right {
  199. background: #95ec69;
  200. border-radius: 10rpx;
  201. border-top-right-radius: 4rpx;
  202. box-shadow: 0 2rpx 8rpx rgba(149, 236, 105, 0.2);
  203. }
  204. /* 文本消息 */
  205. .message-text {
  206. font-size: 32rpx;
  207. color: #000000;
  208. line-height: 1.4;
  209. }
  210. .bubble-right .message-text {
  211. color: #000000;
  212. }
  213. /* 媒体消息通用样式 */
  214. .media-bubble {
  215. position: relative;
  216. border-radius: 10rpx;
  217. overflow: hidden;
  218. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
  219. background: #ffffff;
  220. min-height: 60rpx;
  221. display: flex;
  222. align-items: center;
  223. justify-content: center;
  224. }
  225. .message-left .media-bubble {
  226. border-top-left-radius: 4rpx;
  227. }
  228. .message-right .media-bubble {
  229. border-top-right-radius: 4rpx;
  230. }
  231. /* 图片消息 */
  232. .message-image {
  233. width: 280rpx;
  234. height: 280rpx;
  235. display: block;
  236. }
  237. /* 视频消息 */
  238. .message-video {
  239. width: 280rpx;
  240. height: 280rpx;
  241. background: #000000;
  242. }
  243. .video-play-overlay {
  244. position: absolute;
  245. top: 50%;
  246. left: 50%;
  247. transform: translate(-50%, -50%);
  248. width: 80rpx;
  249. height: 80rpx;
  250. border-radius: 50%;
  251. background: rgba(0, 0, 0, 0.6);
  252. display: flex;
  253. align-items: center;
  254. justify-content: center;
  255. }
  256. .play-icon {
  257. width: 40rpx;
  258. height: 40rpx;
  259. margin-left: 4rpx;
  260. }
  261. /* 语音消息 */
  262. .message-audio {
  263. min-width: 240rpx;
  264. padding: 20rpx;
  265. display: flex;
  266. align-items: center;
  267. min-height: 60rpx;
  268. }
  269. .audio-icon-left,
  270. .audio-icon-right {
  271. width: 32rpx;
  272. height: 32rpx;
  273. flex-shrink: 0;
  274. }
  275. .audio-icon-left {
  276. margin-right: 16rpx;
  277. }
  278. .audio-icon-right {
  279. margin-left: 16rpx;
  280. }
  281. .audio-content {
  282. flex: 1;
  283. display: flex;
  284. align-items: center;
  285. justify-content: space-between;
  286. }
  287. .audio-wave {
  288. display: flex;
  289. align-items: flex-end;
  290. height: 28rpx;
  291. margin-right: 16rpx;
  292. }
  293. .wave-bar {
  294. width: 4rpx;
  295. margin: 0 2rpx;
  296. background: currentColor;
  297. border-radius: 2rpx;
  298. animation: wave 1s ease-in-out infinite;
  299. }
  300. @keyframes wave {
  301. 0%, 100% {
  302. height: 12rpx;
  303. }
  304. 50% {
  305. height: 28rpx;
  306. }
  307. }
  308. .audio-duration {
  309. font-size: 26rpx;
  310. font-weight: 500;
  311. color: #000000;
  312. }
  313. /* 文件消息 */
  314. .message-file {
  315. min-width: 280rpx;
  316. padding: 20rpx;
  317. display: flex;
  318. align-items: center;
  319. min-height: 60rpx;
  320. }
  321. .file-icon-box {
  322. width: 56rpx;
  323. height: 72rpx;
  324. margin-right: 16rpx;
  325. position: relative;
  326. flex-shrink: 0;
  327. }
  328. .file-icon {
  329. width: 100%;
  330. height: 100%;
  331. }
  332. .file-info {
  333. flex: 1;
  334. display: flex;
  335. flex-direction: column;
  336. justify-content: center;
  337. overflow: hidden;
  338. }
  339. .file-name {
  340. font-size: 28rpx;
  341. font-weight: 500;
  342. color: #000000;
  343. margin-bottom: 6rpx;
  344. overflow: hidden;
  345. text-overflow: ellipsis;
  346. white-space: nowrap;
  347. }
  348. .file-size {
  349. font-size: 24rpx;
  350. color: #666666;
  351. }
  352. /* 上传进度 */
  353. .upload-progress {
  354. position: absolute;
  355. top: 0;
  356. left: 0;
  357. right: 0;
  358. bottom: 0;
  359. background: rgba(0, 0, 0, 0.5);
  360. display: flex;
  361. align-items: center;
  362. justify-content: center;
  363. border-radius: inherit;
  364. }
  365. .progress-circle {
  366. width: 80rpx;
  367. height: 80rpx;
  368. border-radius: 50%;
  369. border: 6rpx solid rgba(255, 255, 255, 0.3);
  370. border-top-color: #ffffff;
  371. animation: spin 1s linear infinite;
  372. display: flex;
  373. align-items: center;
  374. justify-content: center;
  375. }
  376. @keyframes spin {
  377. 0% {
  378. transform: rotate(0deg);
  379. }
  380. 100% {
  381. transform: rotate(360deg);
  382. }
  383. }
  384. .progress-text {
  385. font-size: 20rpx;
  386. color: #ffffff;
  387. font-weight: 600;
  388. }
  389. /* 底部留白区域 */
  390. .chat-bottom-space {
  391. height: 40rpx;
  392. }
  393. /* 加载更多提示 */
  394. .load-more-tip {
  395. display: flex;
  396. justify-content: center;
  397. align-items: center;
  398. padding: 30rpx 0;
  399. color: #999999;
  400. font-size: 24rpx;
  401. }
  402. /* 空状态提示 */
  403. .empty-tip {
  404. display: flex;
  405. flex-direction: column;
  406. align-items: center;
  407. justify-content: center;
  408. padding: 100rpx 0;
  409. color: #999999;
  410. }
  411. .empty-icon {
  412. width: 200rpx;
  413. height: 200rpx;
  414. margin-bottom: 30rpx;
  415. opacity: 0.6;
  416. }
  417. .empty-text {
  418. font-size: 28rpx;
  419. color: #999999;
  420. }
  421. /* 输入区域 */
  422. .input-section {
  423. background: #ffffff;
  424. border-top: 1rpx solid #e5e5e5;
  425. padding: 20rpx 30rpx;
  426. position: relative;
  427. z-index: 100;
  428. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  429. }
  430. /* 语音输入面板 */
  431. .voice-input-panel {
  432. display: flex;
  433. align-items: center;
  434. gap: 20rpx;
  435. height: 80rpx;
  436. }
  437. /* 文字输入面板 */
  438. .text-input-panel {
  439. display: flex;
  440. align-items: center;
  441. gap: 20rpx;
  442. height: 80rpx;
  443. }
  444. /* 语音输入按钮(切换按钮) */
  445. .voice-input-btn {
  446. width: 80rpx;
  447. height: 80rpx;
  448. display: flex;
  449. align-items: center;
  450. justify-content: center;
  451. transition: all 0.2s;
  452. }
  453. .voice-btn-icon {
  454. width: 70rpx;
  455. height: 70rpx;
  456. }
  457. /* 输入框包装器 */
  458. .input-wrapper {
  459. flex: 1;
  460. position: relative;
  461. background: #f5f5f5;
  462. border-radius: 40rpx;
  463. height: 80rpx;
  464. display: flex;
  465. align-items: center;
  466. transition: all 0.2s;
  467. overflow: hidden;
  468. min-width: 0;
  469. }
  470. /* 语音输入模式下的输入框 */
  471. .voice-input-panel .input-wrapper {
  472. padding: 0;
  473. background: #f5f5f5;
  474. }
  475. /* 文字输入模式下的输入框 */
  476. .text-input-panel .input-wrapper {
  477. padding: 0 30rpx;
  478. }
  479. .input-wrapper:active {
  480. background: #e8e8e8;
  481. }
  482. /* 语音输入按钮 */
  483. .voice-record-btn {
  484. width: 100%;
  485. height: 100%;
  486. border-radius: 40rpx;
  487. display: flex;
  488. flex-direction: column;
  489. align-items: center;
  490. justify-content: center;
  491. transition: all 0.2s;
  492. }
  493. .voice-record-btn:active {
  494. background: #e0e0e0;
  495. }
  496. .voice-tip {
  497. font-size: 24rpx;
  498. color: #666666;
  499. }
  500. /* 文字输入框 */
  501. .chat-input {
  502. flex: 1;
  503. height: 100%;
  504. font-size: 32rpx;
  505. color: #000000;
  506. line-height: 80rpx;
  507. min-width: 0;
  508. }
  509. .input-placeholder {
  510. color: #999999;
  511. font-size: 24rpx;
  512. }
  513. .input-actions {
  514. position: absolute;
  515. right: 20rpx;
  516. top: 50%;
  517. transform: translateY(-50%);
  518. }
  519. .clear-btn {
  520. width: 40rpx;
  521. height: 40rpx;
  522. border: none;
  523. background: transparent;
  524. padding: 0;
  525. margin: 0;
  526. line-height: 1;
  527. border-radius: 50%;
  528. display: flex;
  529. align-items: center;
  530. justify-content: center;
  531. }
  532. .clear-btn:active {
  533. background: rgba(0, 0, 0, 0.05);
  534. }
  535. .clear-icon {
  536. width: 32rpx;
  537. height: 32rpx;
  538. }
  539. /* 更多按钮 */
  540. .more-btn {
  541. width: 80rpx;
  542. height: 80rpx;
  543. border-radius: 50%;
  544. border: none;
  545. background: transparent;
  546. display: flex;
  547. align-items: center;
  548. justify-content: center;
  549. transition: all 0.2s;
  550. padding: 0;
  551. margin: 0;
  552. line-height: 1;
  553. flex-shrink: 0;
  554. }
  555. .more-btn:active {
  556. background: rgba(0, 0, 0, 0.05);
  557. }
  558. .more-icon {
  559. width: 70rpx;
  560. height: 70rpx;
  561. }
  562. /* 发送按钮 */
  563. .send-btn {
  564. background: #07c160;
  565. width: 120rpx;
  566. border-radius: 40rpx;
  567. height: 80rpx;
  568. border: none;
  569. display: flex;
  570. align-items: center;
  571. justify-content: center;
  572. transition: all 0.2s;
  573. padding: 0;
  574. margin: 0;
  575. line-height: 1;
  576. flex-shrink: 0;
  577. }
  578. .send-btn:active {
  579. background: #06ad56;
  580. transform: scale(0.98);
  581. }
  582. .send-text {
  583. font-size: 28rpx;
  584. color: #ffffff;
  585. font-weight: 500;
  586. }
  587. /* 多媒体选择面板 */
  588. .media-action-sheet {
  589. position: fixed;
  590. top: 0;
  591. left: 0;
  592. right: 0;
  593. bottom: 0;
  594. background: rgba(0, 0, 0, 0.5);
  595. display: flex;
  596. align-items: flex-end;
  597. justify-content: center;
  598. z-index: 2000;
  599. animation: fadeIn 0.3s ease;
  600. }
  601. .media-sheet-content {
  602. width: 100%;
  603. background: #F7F7F7;
  604. border-radius: 40rpx 40rpx 0 0;
  605. padding: 40rpx 30rpx calc(10rpx + env(safe-area-inset-bottom));
  606. animation: slideUp 0.3s ease;
  607. box-sizing: border-box;
  608. }
  609. @keyframes slideUp {
  610. from {
  611. transform: translateY(100%);
  612. }
  613. to {
  614. transform: translateY(0);
  615. }
  616. }
  617. .media-sheet-header {
  618. display: flex;
  619. align-items: center;
  620. justify-content: space-between;
  621. margin-bottom: 40rpx;
  622. padding: 0 10rpx 20rpx;
  623. border-bottom: 1px solid #E4E4E4;
  624. }
  625. .sheet-title {
  626. font-size: 32rpx;
  627. font-weight: 600;
  628. color: #000000;
  629. }
  630. .close-sheet-btn {
  631. display: flex;
  632. align-items: center;
  633. justify-content: center;
  634. }
  635. .close-sheet-btn image {
  636. width: 60rpx;
  637. height: 60rpx;
  638. }
  639. .media-options-grid {
  640. display: grid;
  641. grid-template-columns: repeat(4, 1fr);
  642. gap: 40rpx 30rpx;
  643. margin-bottom: 40rpx;
  644. }
  645. .media-option {
  646. display: flex;
  647. flex-direction: column;
  648. align-items: center;
  649. border: none;
  650. background: transparent;
  651. padding: 0;
  652. margin: 0;
  653. line-height: 1;
  654. }
  655. .option-icon-box {
  656. width: 120rpx;
  657. height: 120rpx;
  658. border-radius: 30rpx;
  659. display: flex;
  660. align-items: center;
  661. justify-content: center;
  662. margin-bottom: 16rpx;
  663. transition: transform 0.2s;
  664. background-color: #fff;
  665. }
  666. .media-option:active .option-icon-box {
  667. transform: scale(0.95);
  668. }
  669. .option-icon-box image {
  670. width: 60rpx;
  671. height: 60rpx;
  672. }
  673. .option-text {
  674. font-size: 26rpx;
  675. color: #666666;
  676. }
  677. .sheet-bottom {
  678. text-align: center;
  679. }
  680. .bottom-tip {
  681. font-size: 24rpx;
  682. color: #999999;
  683. }
  684. /* 录音模态框 */
  685. .recording-modal {
  686. position: fixed;
  687. top: 0;
  688. left: 0;
  689. right: 0;
  690. bottom: 0;
  691. background: rgba(0, 0, 0, 0.7);
  692. display: flex;
  693. align-items: center;
  694. justify-content: center;
  695. z-index: 3000;
  696. animation: fadeIn 0.2s ease;
  697. }
  698. .recording-box {
  699. background: rgba(0, 0, 0, 0.8);
  700. border-radius: 40rpx;
  701. padding: 60rpx 80rpx;
  702. display: flex;
  703. flex-direction: column;
  704. align-items: center;
  705. min-width: 400rpx;
  706. }
  707. .recording-box.is-canceling {
  708. background: rgba(0, 0, 0, 0.9);
  709. }
  710. .recording-icon {
  711. width: 160rpx;
  712. height: 160rpx;
  713. margin-bottom: 40rpx;
  714. display: flex;
  715. align-items: center;
  716. justify-content: center;
  717. }
  718. .recording-mic-icon {
  719. width: 120rpx;
  720. height: 120rpx;
  721. }
  722. .recording-tip {
  723. font-size: 32rpx;
  724. color: #ffffff;
  725. font-weight: 500;
  726. margin-bottom: 30rpx;
  727. text-align: center;
  728. }
  729. .recording-box.is-canceling .recording-tip {
  730. color: #ff4444;
  731. }
  732. .recording-meter {
  733. display: flex;
  734. flex-direction: column;
  735. align-items: center;
  736. }
  737. .recording-waves {
  738. display: flex;
  739. align-items: flex-end;
  740. height: 60rpx;
  741. margin-bottom: 20rpx;
  742. }
  743. .recording-wave {
  744. width: 8rpx;
  745. margin: 0 4rpx;
  746. background: #07c160;
  747. border-radius: 4rpx;
  748. animation: recordingWave 1.2s ease-in-out infinite;
  749. }
  750. .recording-box.is-canceling .recording-wave {
  751. background: #ff4444;
  752. }
  753. @keyframes recordingWave {
  754. 0%, 100% {
  755. height: 20rpx;
  756. }
  757. 50% {
  758. height: 60rpx;
  759. }
  760. }
  761. .recording-time {
  762. font-size: 36rpx;
  763. color: #ffffff;
  764. font-weight: bold;
  765. }
  766. /* 适配全面屏 */
  767. .safe-area-bottom {
  768. padding-bottom: env(safe-area-inset-bottom);
  769. }