317 lines
6.9 KiB
Vue
317 lines
6.9 KiB
Vue
<template>
|
|
<view class="planner-list-page">
|
|
<!-- 自定义导航栏 -->
|
|
<Navbar title="学业规划" :showBack="true" />
|
|
|
|
<!-- 页面内容 -->
|
|
<view class="page-content">
|
|
<!-- 加载状态 -->
|
|
<Loading v-if="pageLoading" type="page" :loading="true" />
|
|
|
|
<!-- 规划师列表 -->
|
|
<view v-else class="planner-list">
|
|
<!-- 有数据时显示列表 -->
|
|
<template v-if="plannerList.length > 0">
|
|
<view
|
|
class="planner-card"
|
|
v-for="(item, index) in plannerList"
|
|
:key="item.id || index"
|
|
@click="handlePlannerClick(item)"
|
|
>
|
|
<!-- 规划师头像 -->
|
|
<view class="planner-avatar">
|
|
<image
|
|
:src="item.avatar || item.photo || '/static/ic_empty.png'"
|
|
mode="aspectFill"
|
|
class="avatar-image"
|
|
@error="handleAvatarError(index)"
|
|
/>
|
|
</view>
|
|
|
|
<!-- 规划师信息 -->
|
|
<view class="planner-info">
|
|
<!-- 姓名 -->
|
|
<view class="planner-name">{{ item.name || '规划师' }}</view>
|
|
|
|
<!-- 介绍 -->
|
|
<view class="planner-intro">{{ item.intro || item.introduction || '暂无介绍' }}</view>
|
|
|
|
<!-- 价格 -->
|
|
<view class="planner-price">
|
|
<text class="price-symbol">¥</text>
|
|
<text class="price-value">{{ formatPrice(item.price) }}</text>
|
|
<text class="price-unit">/次</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 预约按钮 -->
|
|
<view class="planner-action">
|
|
<view class="book-btn">预约</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<!-- 无数据时显示空状态 -->
|
|
<view v-else class="empty-state">
|
|
<image
|
|
src="/static/ic_empty.png"
|
|
mode="aspectFit"
|
|
class="empty-icon"
|
|
/>
|
|
<text class="empty-text">暂无规划师</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 底部安全区域 -->
|
|
<view class="safe-bottom"></view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
/**
|
|
* 规划师列表页面
|
|
* 展示规划师卡片:照片、姓名、介绍、价格
|
|
*/
|
|
import { ref, onMounted } from 'vue'
|
|
import { onPullDownRefresh } from '@dcloudio/uni-app'
|
|
import { getPlannerList } from '@/api/planner.js'
|
|
import Navbar from '@/components/Navbar/index.vue'
|
|
import Loading from '@/components/Loading/index.vue'
|
|
|
|
// 页面状态
|
|
const pageLoading = ref(true)
|
|
const plannerList = ref([])
|
|
|
|
/**
|
|
* 加载规划师列表
|
|
*/
|
|
async function loadPlannerList() {
|
|
pageLoading.value = true
|
|
try {
|
|
const res = await getPlannerList()
|
|
if (res && res.code === 0 && res.data) {
|
|
// 支持多种数据格式
|
|
if (Array.isArray(res.data)) {
|
|
plannerList.value = res.data
|
|
} else if (res.data.list && Array.isArray(res.data.list)) {
|
|
plannerList.value = res.data.list
|
|
} else {
|
|
plannerList.value = []
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('加载规划师列表失败:', error)
|
|
uni.showToast({
|
|
title: '加载失败,请稍后重试',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
pageLoading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 格式化价格
|
|
* @param {number|string} price - 价格
|
|
* @returns {string} 格式化后的价格
|
|
*/
|
|
function formatPrice(price) {
|
|
if (price === undefined || price === null) return '0'
|
|
const num = Number(price)
|
|
if (isNaN(num)) return '0'
|
|
// 如果是整数,不显示小数点
|
|
if (Number.isInteger(num)) return num.toString()
|
|
// 否则保留两位小数
|
|
return num.toFixed(2)
|
|
}
|
|
|
|
/**
|
|
* 处理头像加载失败
|
|
*/
|
|
function handleAvatarError(index) {
|
|
console.error(`规划师头像 ${index + 1} 加载失败`)
|
|
}
|
|
|
|
/**
|
|
* 处理规划师点击
|
|
*/
|
|
function handlePlannerClick(item) {
|
|
// 跳转到预约页面
|
|
uni.navigateTo({
|
|
url: `/pages/planner/book/index?plannerId=${item.id}&plannerName=${encodeURIComponent(item.name || '')}`
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 下拉刷新
|
|
*/
|
|
onPullDownRefresh(async () => {
|
|
await loadPlannerList()
|
|
uni.stopPullDownRefresh()
|
|
})
|
|
|
|
/**
|
|
* 页面加载
|
|
*/
|
|
onMounted(() => {
|
|
loadPlannerList()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import '@/styles/variables.scss';
|
|
|
|
.planner-list-page {
|
|
min-height: 100vh;
|
|
background-color: $bg-color;
|
|
}
|
|
|
|
// 页面内容
|
|
.page-content {
|
|
padding: $spacing-lg;
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
|
|
// 规划师列表
|
|
.planner-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $spacing-md;
|
|
}
|
|
|
|
// 规划师卡片
|
|
.planner-card {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: $bg-white;
|
|
border-radius: $border-radius-lg;
|
|
padding: $spacing-lg;
|
|
box-shadow: $shadow-sm;
|
|
|
|
&:active {
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
|
|
// 规划师头像
|
|
.planner-avatar {
|
|
flex-shrink: 0;
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
border-radius: $border-radius-md;
|
|
overflow: hidden;
|
|
margin-right: $spacing-md;
|
|
|
|
.avatar-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
// 规划师信息
|
|
.planner-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: $spacing-xs;
|
|
}
|
|
|
|
// 规划师姓名
|
|
.planner-name {
|
|
font-size: $font-size-lg;
|
|
font-weight: $font-weight-medium;
|
|
color: $text-color;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
// 规划师介绍
|
|
.planner-intro {
|
|
font-size: $font-size-sm;
|
|
color: $text-secondary;
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 2;
|
|
overflow: hidden;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
// 规划师价格
|
|
.planner-price {
|
|
display: flex;
|
|
align-items: baseline;
|
|
margin-top: $spacing-xs;
|
|
|
|
.price-symbol {
|
|
font-size: $font-size-sm;
|
|
color: $error-color;
|
|
font-weight: $font-weight-medium;
|
|
}
|
|
|
|
.price-value {
|
|
font-size: $font-size-xl;
|
|
color: $error-color;
|
|
font-weight: $font-weight-bold;
|
|
margin-left: 2rpx;
|
|
}
|
|
|
|
.price-unit {
|
|
font-size: $font-size-xs;
|
|
color: $text-placeholder;
|
|
margin-left: 4rpx;
|
|
}
|
|
}
|
|
|
|
// 预约按钮区域
|
|
.planner-action {
|
|
flex-shrink: 0;
|
|
margin-left: $spacing-md;
|
|
|
|
.book-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 120rpx;
|
|
height: 64rpx;
|
|
background-color: $primary-color;
|
|
color: $text-white;
|
|
font-size: $font-size-md;
|
|
font-weight: $font-weight-medium;
|
|
border-radius: $border-radius-round;
|
|
|
|
&:active {
|
|
background-color: $primary-dark;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 空状态
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 200rpx 0;
|
|
|
|
.empty-icon {
|
|
width: 200rpx;
|
|
height: 200rpx;
|
|
margin-bottom: $spacing-lg;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: $font-size-md;
|
|
color: $text-placeholder;
|
|
}
|
|
}
|
|
|
|
// 底部安全区域
|
|
.safe-bottom {
|
|
height: 40rpx;
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
</style>
|