572 lines
14 KiB
Vue
572 lines
14 KiB
Vue
<template>
|
||
<view class="consult-page">
|
||
<!-- 顶部导航与标签 -->
|
||
<navBar title="公益咨询" />
|
||
<view class="tabs">
|
||
<view :class="['tab', activeTab==='new' ? 'active' : '']" @tap="switchTab('new')">新的咨询</view>
|
||
<view class="bar"></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">
|
||
<view class="namebox">
|
||
<text class="user-name">{{ item.maskName }}</text>
|
||
<text class="user-avatar" v-if="bottomActive!=='quick'">({{item.sex==1?'女':'男' }}<text decode> </text>{{ calcAge(item.birthDate) }}岁)</text>
|
||
</view>
|
||
<text class="date">{{ item.date }}</text>
|
||
</view>
|
||
<view class="card-body">
|
||
<text class="content twoline">{{ item.disease_describe }}</text>
|
||
</view>
|
||
<view class="card-foot" v-if="bottomActive==='multi'">
|
||
<text class="reply-count" v-if="item.answer_num>0">{{ item.answer_num }}位医生已回答</text>
|
||
<text class="reply-count-none" v-else>暂未有医生回答</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,onBackPress,onLoad } 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)
|
||
onBackPress(()=>{
|
||
plus.runtime.quit();
|
||
return true;
|
||
})
|
||
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();
|
||
uni.sendNativeEvent('goConsultPage', {
|
||
msg: 'chat'
|
||
},ret => {
|
||
console.log(ret);
|
||
})
|
||
//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}**`
|
||
}
|
||
// 根据出生日期计算年龄(birth 可以是 'YYYY-MM-DD' 或可被 Date 解析的字符串 / 时间戳)
|
||
function calcAge(birth) {
|
||
if (!birth) return ''
|
||
const birthDate = new Date(birth)
|
||
if (isNaN(birthDate.getTime())) {
|
||
return ''
|
||
}
|
||
const today = new Date()
|
||
let age = today.getFullYear() - birthDate.getFullYear()
|
||
const m = today.getMonth() - birthDate.getMonth()
|
||
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
|
||
age--
|
||
}
|
||
// 年龄小于 0 视为无效
|
||
return age >= 0 ? age : ''
|
||
}
|
||
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: item.realName,
|
||
date: (item.createDate || '').slice(0,16),
|
||
content: item.content || '',
|
||
replyCount: 0,
|
||
sex: item.sex || 0,
|
||
birthDate: item.birthDate || item.birthday,
|
||
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: item.realName,
|
||
date: (item.createDate || '').slice(0,16),
|
||
content: item.content || '',
|
||
replyCount: 0,
|
||
sex: item.sex || 0,
|
||
birthDate: item.birthDate || item.birthday,
|
||
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.disease_describe || '',
|
||
sex: item.sex || 0,
|
||
birthDate: item.birthday || '',
|
||
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 || '',
|
||
sex: item.sex || 0,
|
||
birthDate: item.birthday || '',
|
||
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
|
||
}
|
||
};
|
||
onLoad(()=>{
|
||
page.value = 1
|
||
hasMore.value = true;
|
||
listNew.value = [];
|
||
listMine.value=[];
|
||
if(bottomActive.value==='quick'){
|
||
if(activeTab.value==='new'){
|
||
newConsultList(false)
|
||
}else{
|
||
consultListHis(false)
|
||
}
|
||
}else{
|
||
if(activeTab.value==='new'){
|
||
listNewInterrogation(false)
|
||
}else{
|
||
listMyAnsweredInterrogation(false)
|
||
}
|
||
|
||
}
|
||
})
|
||
|
||
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=[];
|
||
page.value = 1
|
||
hasMore.value = true;
|
||
if(bottomActive.value==='quick'){
|
||
if(activeTab.value==='new'){
|
||
newConsultList(false)
|
||
}else{
|
||
consultListHis(false)
|
||
}
|
||
|
||
}else{
|
||
if(activeTab.value==='new'){
|
||
listNewInterrogation(false)
|
||
}else{
|
||
listMyAnsweredInterrogation(false)
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
function goBack() {
|
||
// #ifdef H5
|
||
history.back()
|
||
// #endif
|
||
// #ifndef H5
|
||
uni.navigateBack({ delta: 1 })
|
||
// #endif
|
||
}
|
||
|
||
// 底部tab交互
|
||
const bottomActive = ref('multi')
|
||
const switchBottomTab=(key)=>{
|
||
isLoading.value = false;
|
||
bottomActive.value = key;
|
||
page.value = 1
|
||
hasMore.value = true;
|
||
listNew.value = [];
|
||
listMine.value=[];
|
||
if(key=='quick'){
|
||
try {
|
||
plus.runtime.quit();
|
||
} catch (error) {
|
||
|
||
}
|
||
if(activeTab.value==='new'){
|
||
newConsultList(false)
|
||
}else{
|
||
consultListHis(false)
|
||
}
|
||
|
||
}else{
|
||
if(activeTab.value==='new'){
|
||
console.log('listNewInterrogation')
|
||
listNewInterrogation(false);
|
||
}else{
|
||
listMyAnsweredInterrogation(false)
|
||
}
|
||
}
|
||
}
|
||
// 下拉刷新
|
||
function onRefresh(){
|
||
if(isRefreshing.value) return
|
||
isRefreshing.value = true
|
||
page.value = 1
|
||
hasMore.value = true
|
||
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 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: 48px;
|
||
padding: 0 16px;
|
||
position: fixed;
|
||
top: calc(var(--status-bar-height) + 44px);
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 10;
|
||
background-color: #ffffff;
|
||
border-bottom: 1px solid #e5e5e5;
|
||
.bar{
|
||
width:1px;
|
||
height: 100%;
|
||
background-color: #e5e5e5;
|
||
}
|
||
.tab {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 36rpx;
|
||
color: #7a7a7a;
|
||
padding: 10px 0;
|
||
&.active { color: #8B2316; position: relative; }
|
||
|
||
}
|
||
}
|
||
.tabs-spacer { height: 44px; }
|
||
.namebox{
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
.user-avatar{
|
||
margin-left: 10rpx;
|
||
font-size:32rpx;
|
||
color: #666;
|
||
}
|
||
}
|
||
.list-scroll {
|
||
flex: 1;
|
||
position: fixed;
|
||
top: calc(var(--status-bar-height) + 44px + 48px);
|
||
bottom:56px;
|
||
margin: 20rpx rpx 0;
|
||
box-sizing: border-box;
|
||
width:100%;
|
||
}
|
||
|
||
.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: 36rpx; color: #a31712; }
|
||
.date { font-size: 36rpx; 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; }
|
||
.reply-count-none{
|
||
font-size:28rpx;
|
||
color: #999;
|
||
position: relative;
|
||
padding-left: 25rpx;
|
||
}
|
||
.reply-count-none::after{
|
||
content: '';
|
||
position: absolute;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
left: 0;
|
||
width: 20rpx;
|
||
height: 20rpx;
|
||
background: red;
|
||
border-radius: 50%;
|
||
}
|
||
.tag {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0rpx 16rpx; background: #fff; color: #a31712; border-radius: 28rpx; font-size: 24rpx; border:2rpx solid #a31712;}
|
||
}
|
||
}
|
||
|
||
.bottom-bar {
|
||
border-top: 1px solid #e5e5e5;
|
||
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;
|
||
.bottom-tab {
|
||
flex: 1;
|
||
height: 56px;
|
||
line-height: 56px;
|
||
text-align: center;
|
||
|
||
font-size: 36rpx;
|
||
color: #999;
|
||
background-color: #fff;
|
||
}
|
||
.bottom-tab.active {
|
||
background-color: #a31712;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
|