372 lines
8.2 KiB
Vue
372 lines
8.2 KiB
Vue
<template>
|
|
<view class="planner-list-page">
|
|
<!-- 自定义导航栏 -->
|
|
<Navbar title="学业规划" :showBack="true" />
|
|
|
|
<!-- 页面内容 -->
|
|
<view class="page-content">
|
|
<!-- 提示文字 -->
|
|
<view class="page-tip">点击选择您喜欢的规划师</view>
|
|
|
|
<!-- 加载状态 -->
|
|
<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="card-top">
|
|
<!-- 头像 -->
|
|
<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-row">
|
|
<text class="planner-name">{{ item.name || '规划师' }}</text>
|
|
<text v-if="item.title" class="planner-title">|{{ item.title }}</text>
|
|
</view>
|
|
|
|
<!-- 标签列表 -->
|
|
<view class="planner-tags" v-if="parseTags(item.tags).length > 0">
|
|
<view
|
|
class="tag-item"
|
|
v-for="(tag, tagIndex) in parseTags(item.tags)"
|
|
:key="tagIndex"
|
|
>
|
|
{{ tag }}
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 无标签时显示简介 -->
|
|
<view class="planner-intro" v-else-if="item.introduction">
|
|
{{ item.introduction }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 下半部分:价格 + 按钮 -->
|
|
<view class="card-bottom">
|
|
<view class="planner-price">
|
|
<text class="price-symbol">¥</text>
|
|
<text class="price-value">{{ formatPrice(item.price) }}</text>
|
|
</view>
|
|
<view class="select-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 {string} tags - 逗号分隔的标签字符串
|
|
* @returns {string[]}
|
|
*/
|
|
function parseTags(tags) {
|
|
if (!tags) return []
|
|
return tags.split(',').map(t => t.trim()).filter(Boolean)
|
|
}
|
|
|
|
/**
|
|
* 格式化价格
|
|
* @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';
|
|
|
|
// 橙色主题色
|
|
$orange-color: #E8740E;
|
|
$orange-light: #FFF8F0;
|
|
$orange-gradient-start: #FFF5EB;
|
|
$orange-gradient-end: #FFFFFF;
|
|
|
|
.planner-list-page {
|
|
min-height: 100vh;
|
|
background-color: $bg-color;
|
|
}
|
|
|
|
.page-content {
|
|
padding: 24rpx 28rpx;
|
|
padding-bottom: env(safe-area-inset-bottom);
|
|
}
|
|
|
|
// 顶部提示文字
|
|
.page-tip {
|
|
text-align: center;
|
|
font-size: $font-size-md;
|
|
color: $text-secondary;
|
|
margin-bottom: 28rpx;
|
|
}
|
|
|
|
// 规划师列表
|
|
.planner-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24rpx;
|
|
}
|
|
|
|
// 规划师卡片 - 顶部橙色渐变,无左侧边框
|
|
.planner-card {
|
|
background: linear-gradient(180deg, $orange-gradient-start 0%, $orange-gradient-end 40%);
|
|
border-radius: 24rpx;
|
|
padding: 28rpx;
|
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
|
|
|
|
&:active {
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
|
|
// 上半部分:头像 + 信息
|
|
.card-top {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
// 头像
|
|
.planner-avatar {
|
|
flex-shrink: 0;
|
|
width: 160rpx;
|
|
height: 180rpx;
|
|
border-radius: 16rpx;
|
|
overflow: hidden;
|
|
margin-right: 24rpx;
|
|
|
|
.avatar-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
// 右侧信息区
|
|
.planner-info {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
// 姓名 + 职称行
|
|
.planner-name-row {
|
|
display: flex;
|
|
align-items: baseline;
|
|
flex-wrap: wrap;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
|
|
.planner-name {
|
|
font-size: 34rpx;
|
|
font-weight: $font-weight-bold;
|
|
color: $text-color;
|
|
}
|
|
|
|
.planner-title {
|
|
font-size: $font-size-sm;
|
|
color: $text-secondary;
|
|
margin-left: 4rpx;
|
|
}
|
|
|
|
// 标签列表
|
|
.planner-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.tag-item {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 8rpx 18rpx;
|
|
font-size: 22rpx;
|
|
color: $orange-color;
|
|
background-color: rgba(232, 116, 14, 0.08);
|
|
border: 1rpx solid rgba(232, 116, 14, 0.2);
|
|
border-radius: 8rpx;
|
|
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;
|
|
}
|
|
|
|
// 下半部分:价格 + 按钮
|
|
.card-bottom {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
// 价格
|
|
.planner-price {
|
|
display: flex;
|
|
align-items: baseline;
|
|
|
|
.price-symbol {
|
|
font-size: 28rpx;
|
|
color: $orange-color;
|
|
font-weight: $font-weight-bold;
|
|
}
|
|
|
|
.price-value {
|
|
font-size: 48rpx;
|
|
color: $orange-color;
|
|
font-weight: $font-weight-bold;
|
|
margin-left: 2rpx;
|
|
}
|
|
}
|
|
|
|
// 点击选择按钮
|
|
.select-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 18rpx 56rpx;
|
|
background-color: $orange-color;
|
|
color: $text-white;
|
|
font-size: $font-size-md;
|
|
font-weight: $font-weight-medium;
|
|
border-radius: $border-radius-round;
|
|
|
|
&:active {
|
|
opacity: 0.85;
|
|
}
|
|
}
|
|
|
|
// 空状态
|
|
.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>
|