2025-09-26 19:06:31 +08:00

489 lines
13 KiB
Vue

<template>
<view class="consult-page">
<!-- 顶部导航与标签 -->
<navBar title="公益咨询" />
<view class="tabs">
<view :class="['tab', activeTab==='new' ? 'active' : '']" @tap="switchTab('new')">新的咨询</view>
<view :class="['tab', activeTab==='mine' ? 'active' : '']" @tap="switchTab('mine')">我已回答</view>
</view>
<view class="tabs-spacer"></view>
<!-- 列表 -->
<scroll-view
scroll-y
class="list-scroll"
refresher-enabled
:refresher-triggered="isRefreshing"
@refresherrefresh="onRefresh"
@scrolltolower="onReachBottom"
lower-threshold="80"
>
<view v-for="(item, idx) in displayList" :key="idx" class="consult-card" @click="goDetail(item.id,item.patientUuid)">
<view class="card-head">
<text class="user-name">{{ item.maskName }}</text>
<text class="date">{{ item.date }}</text>
</view>
<view class="card-body">
<text class="content">{{ item.content }}</text>
</view>
<view class="card-foot" v-if="bottomActive==='multi'">
<text class="reply-count">{{ item.answer_num }}位医生已回答</text>
<view v-if="item.tag" class="tag">{{ item.tag }}</view>
</view>
<view class="card-foot" v-else>
<view class="left">
<view class="detail">问题详情</view>
<view v-if="item.tag" class="tag">{{ item.tag }}</view>
</view>
</view>
</view>
<empty v-if="displayList.length===0" />
<view v-if="isLoading" style="text-align:center;color:#9aa0a6;padding:10px 0;">加载中...</view>
<view v-else-if="!hasMore && displayList.length>0" style="text-align:center;color:#9aa0a6;padding:10px 0;">没有更多了</view>
</scroll-view>
<!-- 底部操作条:双按钮 Tab -->
<view class="bottom-bar" :style="{height: bottomBarHeight+'px'}">
<view :class="['bottom-tab', bottomActive==='quick' ? 'active' : '']" @click="switchBottomTab('quick')">快速问医生</view>
<view :class="['bottom-tab', bottomActive==='multi' ? 'active' : '']" @click="switchBottomTab('multi')">多对一解惑</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import navBar from '@/components/navBar/navBar.vue'
import empty from '@/components/empty/empty.vue'
import api from '@/api/api.js'
import navTo from '@/utils/navTo.js'
const activeTab = ref('new');
const bottomBarHeight = 56
const page=ref(1)
const pageSize=ref(10)
const hasMore = ref(true)
const isLoading = ref(false)
const isRefreshing = ref(false)
const goDetail=async(uuid,patientUuid)=>{
if(bottomActive.value==='quick'){
if(activeTab.value==='new'){
navTo({
url:'/pages_app/freeDetail/freeDetail?uuid='+uuid
})
}else{
let userId=uni.getStorageSync('userInfo').uuid.toLowerCase();
let conversationId=userId+'|1|'+patientUuid.toLowerCase();
await uni.$UIKitStore.uiStore.selectConversation(conversationId)
navTo({
url:'/pages_chat/chat/index?from=consult&&patientUuid='+patientUuid+'&&uuid='+uuid
})
}
}else{
let status=0;
if(activeTab.value==='new'){
status=0;
}else{
status=1;
}
navTo({
url:'/pages_app/consultDetail/consultDetail?uuid='+uuid+'&status='+status
})
}
};
function maskName(name){
if(!name) return '**'
const first = name.slice(0,1)
return `${first}**`
}
const newConsultList=async(isRefresh=false)=>{
if(isLoading.value) return
isLoading.value = true
if(isRefresh){
page.value = 1
hasMore.value = true
listNew.value = []
}
const res=await api.newConsultList({
page:page.value,
pageSize:pageSize.value
})
console.log(res)
if(res && res.code===200 && res.data && res.data.consult_list){
const list = Array.isArray(res.data.consult_list.list) ? res.data.consult_list.list : []
const mapped = list.map(item=>({
maskName: maskName(item.realName || ''),
date: (item.createDate || '').slice(0,10),
content: item.content || '',
replyCount: 0,
tag: item.diseaseName || '',
id:item.uuid || '',
patientUuid:item.patientUuid || ''
}))
if(isRefresh){
listNew.value = mapped
}else{
listNew.value = page.value===1 ? mapped : [...listNew.value, ...mapped]
}
const totalPage = Number(res.data.consult_list.totalPage || 1)
hasMore.value = page.value < totalPage
}
isLoading.value = false
if(isRefresh){
isRefreshing.value = false
}
}
const consultListHis=async(isRefresh=false)=>{
if(isLoading.value) return
isLoading.value = true
if(isRefresh){
page.value = 1
hasMore.value = true
listMine.value = []
}
const res=await api.consultListHis({
page:page.value,
pageSize:pageSize.value
})
console.log(res)
if(res.code==200){
const list = Array.isArray(res.data.list) ? res.data.list : []
const mapped = list.map(item=>({
maskName: maskName(item.realName || ''),
date: (item.createDate || '').slice(0,10),
content: item.content || '',
replyCount: 0,
tag: item.diseaseName || '',
id:item.uuid || '',
patientUuid:item.patientUuid || ''
}))
if(isRefresh){
listMine.value = mapped
}else{
listMine.value = page.value===1 ? mapped : [...listMine.value, ...mapped]
}
const totalPage = Number(res.data.totalPage || 1)
hasMore.value = page.value < totalPage
}
isLoading.value = false
if(isRefresh){
isRefreshing.value = false
}
}
const listNewInterrogation=async(isRefresh=false)=>{
if(isLoading.value) return
isLoading.value = true
if(isRefresh){
page.value = 1
hasMore.value = true
listNew.value = []
}
const res=await api.listNewInterrogation({
page:page.value,
pageSize:pageSize.value
})
if(res.code ==200){
const list =res.data.list;
console.log(1111)
console.log(list)
const mapped = list.map(item=>({
maskName: maskName(item.name || ''),
date: (item.create_date || '').slice(0,10),
content: item.your_question || '',
disease_describe:item.your_question || '',
answer_num: item.answer_num || 0,
tag: item.disease_name || '',
id:item.step1_uuid || ''
}))
if(isRefresh){
listNew.value = mapped
}else{
listNew.value = page.value===1 ? mapped : [...listNew.value, ...mapped]
}
const totalPage = Number(res.data.pages || 1)
hasMore.value = page.value < totalPage
}
isLoading.value = false
if(isRefresh){
isRefreshing.value = false
}
}
const listMyAnsweredInterrogation=async(isRefresh=false)=>{
if(isLoading.value) return
isLoading.value = true
if(isRefresh){
page.value = 1
hasMore.value = true
listMine.value = []
}
const res=await api.listMyAnsweredInterrogation({
page:page.value,
pageSize:pageSize.value
})
console.log(res)
if(res.code==200){
const list = Array.isArray(res.data.list) ? res.data.list : []
const mapped = list.map(item=>({
maskName: maskName(item.name || ''),
date: (item.create_date || '').slice(0,10),
content: item.your_question || '',
disease_describe:item.disease_describe || '',
answer_num: item.answer_num || 0,
tag: item.disease_name || '',
id:item.step1_uuid || ''
}))
if(isRefresh){
listMine.value = mapped
}else{
listMine.value = page.value===1 ? mapped : [...listMine.value, ...mapped]
}
const totalPage = Number(res.data.pages || 1)
hasMore.value = page.value < totalPage
}
isLoading.value = false
if(isRefresh){
isRefreshing.value = false
}
};
onShow(()=>{
page.value = 1
hasMore.value = true;
if(bottomActive.value==='quick'){
if(activeTab.value==='new'){
newConsultList(true)
}else{
consultListHis(true)
}
}else{
if(activeTab.value==='new'){
listNewInterrogation(true)
}else{
listMyAnsweredInterrogation(true)
}
}
})
const listNew = ref([])
const listMine = ref([])
const displayList = computed(() => (activeTab.value === 'new' ? listNew.value : listMine.value))
function switchTab(key) {
activeTab.value = key;
isLoading.value = false;
listNew.value = [];
listMine.value=[];
if(bottomActive.value==='quick'){
if(activeTab.value==='new'){
newConsultList(true)
}else{
consultListHis(true)
}
}else{
if(activeTab.value==='new'){
listNewInterrogation(true)
}else{
listMyAnsweredInterrogation(true)
}
}
}
function goBack() {
// #ifdef H5
history.back()
// #endif
// #ifndef H5
uni.navigateBack({ delta: 1 })
// #endif
}
// 底部tab交互
const bottomActive = ref('quick')
const switchBottomTab=(key)=>{
isLoading.value = false;
bottomActive.value = key;
listNew.value = [];
listMine.value=[];
if(key=='quick'){
if(activeTab.value==='new'){
newConsultList(true)
}else{
consultListHis(true)
}
}else{
if(activeTab.value==='new'){
console.log('listNewInterrogation')
listNewInterrogation(true);
}else{
listMyAnsweredInterrogation(true)
}
}
}
// 下拉刷新
function onRefresh(){
if(isRefreshing.value) return
isRefreshing.value = true
page.value = 1
hasMore.value = true
if(bottomActive.value==='quick'){
if(activeTab.value==='new'){
newConsultList(true)
}else{
consultListHis(true)
}
}else{
if(activeTab.value==='new'){
listNewInterrogation(true)
}else{
listMyAnsweredInterrogation(true)
}
}
}
// 触底加载
function onReachBottom(){
if(!hasMore.value || isLoading.value) return
page.value += 1
if(bottomActive.value==='quick'){
if(activeTab.value==='new'){
newConsultList(false)
}else{
consultListHis(false)
}
}else{
if(activeTab.value==='new'){
listNewInterrogation(false)
}else{
listMyAnsweredInterrogation(false)
}
}
}
</script>
<style lang="scss" scoped>
.consult-page {
background-color: #f7f7f7;
height: 100vh;
display: flex;
flex-direction: column;
}
.tabs {
display: flex;
justify-content: space-around;
align-items: center;
height: 44px;
padding: 0 16px;
position: fixed;
top: 140rpx;
left: 0;
right: 0;
z-index: 10;
background-color: #ffffff;
box-shadow: 0 1px 0 rgba(0,0,0,0.06);
.tab {
flex: 1;
text-align: center;
font-size: 16px;
color: #7a7a7a;
padding: 10px 0;
&.active { color: #8B2316; position: relative; }
&.active::after { content: ''; position: absolute; left: 25%; right: 25%; bottom: 2px; height: 3px; background-color: #8B2316; border-radius: 2px; }
}
}
.tabs-spacer { height: 44px; }
.list-scroll {
flex: 1;
position: fixed;
top: 228rpx;
bottom: 136rpx;
padding: 8px 0px 0 0px;
margin: 20rpx 30rpx 0;
box-sizing: border-box;
width:auto;
}
.consult-card {
background-color: #ffffff;
border-radius: 8px;
padding: 12px;
margin-bottom: 12px;
.card-head {
display: flex;
justify-content: space-between;
align-items: center;
.user-name { font-size: 16px; color: #a31712; }
.date { font-size: 14px; color: #9aa0a6; }
}
.card-body {
background: #efefef;
padding: 20rpx;
margin: 10px 0;
.content {
word-break: break-all;
font-size: 15px; color: #2b2f33; line-height: 1.6;
} }
.card-foot {
.left{
display: flex;
.detail{
font-size: 28rpx;
background: #a31712;
color:#fff;
border-radius: 14rpx;
margin-right: 10rpx;
padding: 8rpx 16rpx;
border-radius: 28rpx;
font-size: 28rpx;
display: flex;
align-items: center;
justify-content: center;
border:2rpx solid #a31712;
}
}
display: flex; align-items: center; justify-content: space-between; margin-top: 8px;
.reply-count { font-size:28rpx; color: #8B2316; }
.tag {
display: flex;
align-items: center;
justify-content: center;
padding: 8rpx 16rpx; background: #fff5f5; color: #a31712; border-radius: 28rpx; font-size: 24rpx; border:2rpx solid #a31712;}
}
}
.bottom-bar {
position: fixed;
left: 0; right: 0; bottom: 0;
background-color: #ffffff;
box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
display: flex; align-items: center; justify-content: center;
padding: 8px 12px;
gap: 12px;
.bottom-tab {
flex: 1;
height: 40px;
line-height: 40px;
text-align: center;
border-radius: 6px;
font-size: 16px;
color: #a31712;
background-color: #fff5f5;
}
.bottom-tab.active {
background-color: #a31712;
color: #ffffff;
}
}
</style>