更新
This commit is contained in:
@@ -105,7 +105,7 @@
|
||||
<text class="error-text">{{ error }}</text>
|
||||
<view class="retry-btn" @click="loadDetail">重试</view>
|
||||
</view>
|
||||
|
||||
<view v-if="doctor">
|
||||
<!-- 底部操作栏 -->
|
||||
<view v-if="doctor.enable_image_consult || doctor.enable_video_consult" class="bottom-bar">
|
||||
<view class="btn-chat" @click="goChat" v-if="doctor.enable_image_consult">
|
||||
@@ -117,6 +117,7 @@
|
||||
<text class="btn-text">视频问诊</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 顶部标题 -->
|
||||
<view class="page-header">
|
||||
<text class="page-title">名医推荐</text>
|
||||
</view>
|
||||
|
||||
<!-- 医生列表 -->
|
||||
<view class="doctors-list">
|
||||
<view
|
||||
v-for="doctor in doctors"
|
||||
:key="doctor.id"
|
||||
class="doctor-card"
|
||||
@click="selectDoctor(doctor)"
|
||||
>
|
||||
<image :src="doctor.avatar || defaultAvatar" class="doctor-photo" mode="aspectFill"></image>
|
||||
<view class="doctor-info">
|
||||
<view class="doctor-top">
|
||||
<text class="doctor-name">{{ doctor.name }}</text>
|
||||
<text class="doctor-rating">★ {{ doctor.rating || '4.9' }}</text>
|
||||
</view>
|
||||
<text class="doctor-specialty">{{ doctor.specialty || doctor.title || '中医' }}</text>
|
||||
<view class="doctor-price-row">
|
||||
<text class="doctor-price">{{ doctor.price || '' }}</text>
|
||||
<text class="doctor-unit" v-if="doctor.title">{{doctor.title}}</text>
|
||||
</view>
|
||||
<view class="doctor-actions">
|
||||
<view class="appointment-btn" @click.stop="selectDoctor(doctor)">预约</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view class="load-more" v-if="hasMore" @click="loadMore">
|
||||
<text class="load-more-text">{{ loading ? '加载中...' : '加载更多' }}</text>
|
||||
</view>
|
||||
<view class="no-more" v-else-if="doctors.length > 0">
|
||||
<text class="no-more-text">没有更多了</text>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty" v-if="!loading && doctors.length === 0">
|
||||
<text class="empty-text">暂无医生信息</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, getCurrentInstance } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const doctors = ref([])
|
||||
const loading = ref(false)
|
||||
const pageNo = ref(1)
|
||||
const pageSize = 10
|
||||
const hasMore = ref(true)
|
||||
const defaultAvatar = '/static/user/user.png'
|
||||
|
||||
const selectDoctor = (doctor) => {
|
||||
uni.navigateTo({
|
||||
url: `/doctor/pages/doctor/doctor?id=${doctor.id}`
|
||||
})
|
||||
}
|
||||
|
||||
const fetchDoctors = async (reset = false) => {
|
||||
if (loading.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
const response = await proxy.apiUrl({
|
||||
url: '/api/doctor/lists',
|
||||
method: 'GET',
|
||||
data: {
|
||||
page_no: pageNo.value,
|
||||
page_size: pageSize
|
||||
}
|
||||
})
|
||||
|
||||
if (response && response.code === 1) {
|
||||
const list = response.data?.lists || []
|
||||
if (reset) {
|
||||
doctors.value = list
|
||||
} else {
|
||||
doctors.value.push(...list)
|
||||
}
|
||||
hasMore.value = list.length === pageSize
|
||||
} else {
|
||||
console.warn('获取医生列表失败:', response?.msg)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('请求异常:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadMore = () => {
|
||||
if (!hasMore.value || loading.value) return
|
||||
pageNo.value++
|
||||
fetchDoctors()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchDoctors(true)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$background: #faf9f5;
|
||||
$primary: #204e2b;
|
||||
$on-primary: #ffffff;
|
||||
$on-primary-container: #afe2b3;
|
||||
$surface-container-lowest: #ffffff;
|
||||
$surface-container-high: #e9e8e4;
|
||||
$surface-container-highest: #e3e2df;
|
||||
$on-surface: #1b1c1a;
|
||||
$on-surface-variant: #414941;
|
||||
$outline: #727970;
|
||||
|
||||
.container {
|
||||
background: $background;
|
||||
min-height: 100vh;
|
||||
padding: 24rpx 32rpx 120rpx;
|
||||
font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: $on-surface;
|
||||
font-family: 'Noto Serif', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', serif;
|
||||
}
|
||||
|
||||
.doctors-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.doctor-card {
|
||||
background: $surface-container-lowest;
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.doctor-photo {
|
||||
width: 160rpx;
|
||||
height: 230rpx;
|
||||
border-radius: 16rpx;
|
||||
flex-shrink: 0;
|
||||
background: $surface-container-highest;
|
||||
}
|
||||
|
||||
.doctor-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: 192rpx;
|
||||
}
|
||||
|
||||
.doctor-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.doctor-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: $on-surface;
|
||||
font-family: 'Noto Serif', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', serif;
|
||||
}
|
||||
|
||||
.doctor-rating {
|
||||
font-size: 24rpx;
|
||||
color: #805533;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.doctor-specialty {
|
||||
font-size: 28rpx;
|
||||
color: $on-surface-variant;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.doctor-price-row {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.doctor-price {
|
||||
font-size: 28rpx;
|
||||
color: $primary;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.doctor-unit {
|
||||
font-size: 24rpx;
|
||||
font-weight: normal;
|
||||
color: $on-surface-variant;
|
||||
}
|
||||
|
||||
.doctor-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.appointment-btn {
|
||||
background: $primary;
|
||||
color: $on-primary;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 9999rpx;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0 20rpx;
|
||||
}
|
||||
|
||||
.load-more-text {
|
||||
font-size: 28rpx;
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 40rpx 0 20rpx;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 26rpx;
|
||||
color: $outline;
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
padding: 120rpx 0;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 30rpx;
|
||||
color: $outline;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user