1225 lines
29 KiB
Vue
1225 lines
29 KiB
Vue
<!-- 使用 type="home" 属性设置首页,其他页面不需要设置,默认为page -->
|
||
<route lang="jsonc" type="home">
|
||
{
|
||
"layout": "tabbar",
|
||
"needLogin": false,
|
||
"style": {
|
||
// 'custom' 表示开启自定义导航栏,默认 'default'
|
||
"navigationStyle": "custom",
|
||
"navigationBarTitleText": "首页"
|
||
}
|
||
}
|
||
</route>
|
||
|
||
<script lang="ts" setup>
|
||
import { inject, onMounted, ref } from 'vue'
|
||
import { router } from '@/utils/tools'
|
||
|
||
const OSS = inject('OSS')
|
||
const navbarHeight = inject('navbarHeight')
|
||
|
||
// 获取状态栏高度(用于自定义导航栏的安全区域适配)
|
||
const statusBarHeight = ref(0)
|
||
onMounted(() => {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
statusBarHeight.value = systemInfo.statusBarHeight || 0
|
||
})
|
||
|
||
// 本地图片资源
|
||
const bgImage = './image/背景@2x.png'
|
||
const decorationImage = './image/组 116127@2x.png'
|
||
const menuIcon = './image/蒙版组 14407@2x.png'
|
||
const clockIcon = './image/clock@2x.png'
|
||
const positionIcon = './image/position-pin@2x.png'
|
||
const navigateIcon = './image/小箭头 copy@2x.png'
|
||
const speakerIcon = './image/蒙版组 14651@2x.png'
|
||
const arrowIcon = './image/小箭头 copy@2x.png'
|
||
const playIcon = './image/播放 (5)@2x.png'
|
||
|
||
const bg = `${OSS}images/chayishi/bg.png`
|
||
|
||
// 用户信息(模拟数据)
|
||
const userInfo = ref({
|
||
nickname: '茶艺师昵称',
|
||
avatar: '',
|
||
})
|
||
|
||
// 等级信息(模拟数据 - 5个等级)
|
||
const levelList = ref([
|
||
{
|
||
level: 1,
|
||
performanceCommission: 50,
|
||
overtimeCommission: 55,
|
||
currentPerformance: 150,
|
||
targetPerformance: 1000,
|
||
remainingPerformance: 850,
|
||
progressPercent: 0,
|
||
},
|
||
{
|
||
level: 2,
|
||
performanceCommission: 60,
|
||
overtimeCommission: 65,
|
||
currentPerformance: 300,
|
||
targetPerformance: 2000,
|
||
remainingPerformance: 1700,
|
||
progressPercent: 0,
|
||
},
|
||
{
|
||
level: 3,
|
||
performanceCommission: 70,
|
||
overtimeCommission: 75,
|
||
currentPerformance: 1500,
|
||
targetPerformance: 5000,
|
||
remainingPerformance: 3500,
|
||
progressPercent: 0,
|
||
},
|
||
{
|
||
level: 4,
|
||
performanceCommission: 80,
|
||
overtimeCommission: 85,
|
||
currentPerformance: 3000,
|
||
targetPerformance: 10000,
|
||
remainingPerformance: 7000,
|
||
progressPercent: 0,
|
||
},
|
||
{
|
||
level: 5,
|
||
performanceCommission: 90,
|
||
overtimeCommission: 95,
|
||
currentPerformance: 8000,
|
||
targetPerformance: 20000,
|
||
remainingPerformance: 12000,
|
||
progressPercent: 0,
|
||
},
|
||
])
|
||
|
||
// 当前等级索引
|
||
const currentLevelIndex = ref(1) // 默认显示第2个等级(索引1)
|
||
|
||
// 当前显示的等级信息(用于兼容旧代码)
|
||
const levelInfo = computed(() => levelList.value[currentLevelIndex.value])
|
||
|
||
// 今日订单列表(模拟数据)
|
||
const todayOrders = ref<Array<any>>([
|
||
{
|
||
id: 1,
|
||
date: '2025-09-21',
|
||
start_time: '15:00',
|
||
end_time: '18:00',
|
||
location: '苓苑共享茶室空间',
|
||
address: '上海浦东新区新金桥路58号新银东大厦15楼F室',
|
||
service_type: '到店服务',
|
||
status: '待服务',
|
||
latitude: 31.2304,
|
||
longitude: 121.4737,
|
||
},
|
||
{
|
||
id: 2,
|
||
date: '2025-09-22',
|
||
start_time: '15:00',
|
||
end_time: '18:00',
|
||
location: '苓苑共享茶室空间',
|
||
address: '上海浦东新区新金桥路58号新银东大厦15楼F室',
|
||
service_type: '到店服务',
|
||
status: '待服务',
|
||
latitude: 31.2304,
|
||
longitude: 121.4737,
|
||
},
|
||
])
|
||
|
||
// 公告列表(模拟数据)
|
||
const announcements = ref<Array<any>>([
|
||
{
|
||
id: 1,
|
||
title: '必备课,茶文化基础与通识,了解茶的起源?',
|
||
time: '2025-08-09 17:21',
|
||
image: './image/Rectangle 327@2x.png',
|
||
type: 'image',
|
||
},
|
||
{
|
||
id: 2,
|
||
title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?',
|
||
time: '2025-08-09 17:21',
|
||
image: './image/Rectangle 327@2x.png',
|
||
type: 'video',
|
||
},
|
||
{
|
||
id: 3,
|
||
title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?',
|
||
time: '2025-08-09 17:21',
|
||
image: './image/Rectangle 327@2x.png',
|
||
type: 'image',
|
||
},
|
||
{
|
||
id: 4,
|
||
title: '行为举止要领,茶艺师职业礼仪与行茶举止规范?',
|
||
time: '2025-08-09 17:21',
|
||
image: './image/Rectangle 327@2x.png',
|
||
type: 'image',
|
||
},
|
||
])
|
||
|
||
// 计算进度百分比
|
||
function calculateProgress() {
|
||
levelList.value.forEach((level) => {
|
||
const { currentPerformance, targetPerformance } = level
|
||
level.progressPercent = Math.min((currentPerformance / targetPerformance) * 100, 100)
|
||
})
|
||
}
|
||
|
||
// 页面加载时计算进度
|
||
onMounted(() => {
|
||
calculateProgress()
|
||
})
|
||
|
||
// 处理等级卡片滑动
|
||
function handleLevelScroll(e: any) {
|
||
const scrollLeft = e.detail.scrollLeft
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
// 每个卡片项的宽度:100vw - 120rpx,加上左右margin各30rpx
|
||
// 1rpx = windowWidth / 750
|
||
const rpxToPx = systemInfo.windowWidth / 750
|
||
// 卡片宽度 + 左右margin = (100vw - 120rpx) + 60rpx = 100vw - 60rpx
|
||
const itemWidthPx = systemInfo.windowWidth - (60 * rpxToPx)
|
||
const index = Math.round(scrollLeft / itemWidthPx)
|
||
if (index >= 0 && index < levelList.value.length) {
|
||
currentLevelIndex.value = index
|
||
}
|
||
}
|
||
|
||
// 格式化日期
|
||
function formatDate(dateStr: string, type: 'day' | 'month') {
|
||
if (!dateStr)
|
||
return ''
|
||
// 处理格式如 "2025-09-21" 的日期字符串
|
||
const parts = dateStr.split('-')
|
||
if (parts.length >= 3) {
|
||
if (type === 'day') {
|
||
return Number.parseInt(parts[2]).toString()
|
||
}
|
||
else {
|
||
return Number.parseInt(parts[1]).toString()
|
||
}
|
||
}
|
||
// 如果不是标准格式,尝试使用Date对象解析
|
||
const date = new Date(dateStr)
|
||
if (!Number.isNaN(date.getTime())) {
|
||
if (type === 'day') {
|
||
return date.getDate().toString()
|
||
}
|
||
else {
|
||
return (date.getMonth() + 1).toString()
|
||
}
|
||
}
|
||
return ''
|
||
}
|
||
|
||
// 菜单点击
|
||
function handleMenuClick() {
|
||
console.log('菜单点击')
|
||
}
|
||
|
||
// 当前订单索引(用于指示点)
|
||
const currentOrderIndex = ref(0)
|
||
|
||
// 滚动事件处理
|
||
function handleScroll(e: any) {
|
||
const scrollLeft = e.detail.scrollLeft
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
// 每个订单项的宽度:100vw - 120rpx,转换为 px
|
||
// 1rpx = windowWidth / 750
|
||
const rpxToPx = systemInfo.windowWidth / 750
|
||
const itemWidthPx = systemInfo.windowWidth - (120 * rpxToPx) + (20 * rpxToPx) // 加上间距
|
||
const index = Math.round(scrollLeft / itemWidthPx)
|
||
if (index >= 0 && index < todayOrders.value.length) {
|
||
currentOrderIndex.value = index
|
||
}
|
||
}
|
||
|
||
// 导航点击
|
||
function handleNavigate(order: any) {
|
||
if (order.latitude && order.longitude) {
|
||
uni.openLocation({
|
||
latitude: order.latitude,
|
||
longitude: order.longitude,
|
||
name: order.location,
|
||
address: order.address,
|
||
})
|
||
}
|
||
}
|
||
|
||
// 更多公告
|
||
function handleMoreAnnouncement() {
|
||
console.log('更多公告')
|
||
}
|
||
|
||
// 公告点击
|
||
function handleAnnouncementClick(item: any) {
|
||
console.log('公告点击', item)
|
||
}
|
||
|
||
onLoad(() => {
|
||
calculateProgress()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<view
|
||
class="home-container"
|
||
:style="{ backgroundImage: `url(${bg})`, backgroundPosition: 'top center', backgroundSize: '100% 400rpx', backgroundRepeat: 'no-repeat' }"
|
||
>
|
||
<!-- 顶部导航栏 -->
|
||
<view class="navbar-wrapper" :style="{ paddingTop: `${statusBarHeight}px` }">
|
||
<view class="navbar-content">
|
||
<view class="greeting-text">
|
||
你好, {{ userInfo.nickname || '茶艺师' }}
|
||
</view>
|
||
<view class="navbar-icons">
|
||
<view class="icon-btn" @click="handleMenuClick">
|
||
<image class="menu-icon" :src="menuIcon" mode="aspectFit" />
|
||
</view>
|
||
<view class="icon-btn" @click="router.navigateTo('/pages/my/my')">
|
||
<wd-img
|
||
width="48rpx" height="48rpx"
|
||
:src="userInfo.avatar || `${OSS}images/store/my/image1.png`" mode="aspectFill" round
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="content-wrapper">
|
||
<!-- 背景图片 -->
|
||
<image class="home-bg-image" :src="bgImage" mode="aspectFill" />
|
||
|
||
<!-- 等级业绩卡片 -->
|
||
<view class="level-card-wrapper mt-30rpx">
|
||
<scroll-view
|
||
class="level-scroll" :scroll-x="true" :show-scrollbar="false" :enable-flex="true"
|
||
@scroll="handleLevelScroll"
|
||
>
|
||
<view class="level-scroll-content">
|
||
<view v-for="(level, index) in levelList" :key="index" class="level-card-item">
|
||
<view
|
||
:style="{ height: '350rpx', backgroundImage: `url(${`${OSS}images/chayishi/vip${level.level}.png`})` }"
|
||
class="level-card-bg"
|
||
>
|
||
<view class="level-header">
|
||
<view class="level-info">
|
||
<wd-img
|
||
width="48rpx" height="48rpx"
|
||
:src="`${OSS}images/chayishi/vip${level.level}_icon.png`"
|
||
mode="aspectFill"
|
||
/>
|
||
<text class="level-text">LV{{ level.level }}</text>
|
||
<view class="level-label-wrapper">
|
||
<text class="level-label">当前等级</text>
|
||
</view>
|
||
</view>
|
||
<image class="level-decoration" :src="decorationImage" mode="aspectFit" />
|
||
</view>
|
||
<view class="commission-info">
|
||
新功能即将推出
|
||
<!-- <view class="commission-item">
|
||
<text class="commission-label">业绩分成</text>
|
||
<text class="commission-value">{{ level.performanceCommission }}%</text>
|
||
</view>
|
||
<view class="commission-item">
|
||
<text class="commission-label">加钟分成</text>
|
||
<text class="commission-value">{{ level.overtimeCommission }}%</text>
|
||
</view> -->
|
||
</view>
|
||
<!-- <view class="progress-section">
|
||
<view class="progress-text">
|
||
<text class="progress-current">{{ level.currentPerformance }}</text>
|
||
<text class="progress-separator">/</text>
|
||
<text class="progress-target">{{ level.targetPerformance }}</text>
|
||
<text class="progress-label">业绩</text>
|
||
<text class="progress-tip">还差{{ level.remainingPerformance }}可升级</text>
|
||
</view>
|
||
<view class="progress-bar-wrapper">
|
||
<view class="progress-bar-bg">
|
||
<view class="progress-bar-fill" :style="{ width: `${level.progressPercent}%` }" />
|
||
</view>
|
||
</view>
|
||
</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<!-- 分页指示点 -->
|
||
<!-- <view class="level-indicators">
|
||
<view
|
||
v-for="(level, index) in levelList"
|
||
:key="`level-indicator-${index}`"
|
||
class="level-indicator"
|
||
:class="{ 'level-indicator-active': index === currentLevelIndex }"
|
||
/>
|
||
</view> -->
|
||
</view>
|
||
|
||
<!-- 今日行程 -->
|
||
<view class="schedule-section mx-30rpx mt-30rpx">
|
||
<view class="section-header" style="justify-content: flex-start;border-radius: 16rpx;">
|
||
<text class="section-title">今日行程</text>
|
||
<text class="section-tip">其他日期行程可至行程记录查看</text>
|
||
</view>
|
||
<view class="schedule-list">
|
||
<view v-if="todayOrders.length === 0" class="empty-schedule">
|
||
<text class="empty-text">今日暂无行程</text>
|
||
</view>
|
||
<!-- 当订单数量大于1时,使用scroll-view实现横向滑动 -->
|
||
<view v-else-if="todayOrders.length > 1" class="schedule-scroll-wrapper">
|
||
<scroll-view
|
||
class="schedule-scroll" :scroll-x="true" :show-scrollbar="false"
|
||
:enable-flex="true" @scroll="handleScroll"
|
||
>
|
||
<view class="schedule-scroll-content">
|
||
<view
|
||
v-for="(order, index) in todayOrders" :key="order.id || index"
|
||
class="schedule-item-wrapper"
|
||
>
|
||
<view class="schedule-header-row">
|
||
<text class="schedule-type">预约单</text>
|
||
<text class="schedule-status">{{ order.status || '待服务' }}</text>
|
||
</view>
|
||
<view class="schedule-item">
|
||
<view class="schedule-date">
|
||
<text class="date-day">{{ formatDate(order.date, 'day') }}</text>
|
||
<text class="date-month">{{ formatDate(order.date, 'month') }}月</text>
|
||
</view>
|
||
<view class="schedule-content">
|
||
<view class="schedule-location-row">
|
||
<text class="schedule-location">
|
||
{{ order.location || order.store_name
|
||
}}
|
||
</text>
|
||
<text class="schedule-service-type">
|
||
{{ order.service_type || '到店服务'
|
||
}}
|
||
</text>
|
||
</view>
|
||
<view class="schedule-time-row">
|
||
<wd-icon color="#8A94A3" name="time" size="22px" />
|
||
<text class="schedule-time">
|
||
{{ order.start_time }}-{{ order.end_time
|
||
}}
|
||
</text>
|
||
</view>
|
||
<view class="schedule-address-row">
|
||
<wd-icon color="#8A94A3" name="location" size="22px" />
|
||
<view class="schedule-address">
|
||
{{ order.address || order.store_address
|
||
}}
|
||
</view>
|
||
<view class="schedule-navigate" @click="handleNavigate(order)">
|
||
<image class="navigate-icon" :src="`${OSS}images/chayishi/send2.png`" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- <view class="schedule-navigate" @click="handleNavigate(order)">
|
||
<image class="navigate-icon" :src="navigateIcon" mode="aspectFit" />
|
||
</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<!-- 分页指示点 -->
|
||
<view class="schedule-indicators">
|
||
<view
|
||
v-for="(order, index) in todayOrders" :key="`indicator-${order.id || index}`"
|
||
class="schedule-indicator"
|
||
:class="{ 'schedule-indicator-active': index === currentOrderIndex }"
|
||
/>
|
||
</view>
|
||
</view>
|
||
<!-- 当订单数量等于1时,直接显示 -->
|
||
<template v-else>
|
||
<view v-for="(order, index) in todayOrders" :key="order.id || index" class="schedule-item">
|
||
<view class="schedule-date">
|
||
<text class="date-day">{{ formatDate(order.date, 'day') }}</text>
|
||
<text class="date-month">{{ formatDate(order.date, 'month') }}月</text>
|
||
</view>
|
||
<view class="schedule-content">
|
||
<view class="schedule-header-row">
|
||
<text class="schedule-type">预约单</text>
|
||
<text class="schedule-status">{{ order.status || '待服务' }}</text>
|
||
</view>
|
||
<view class="schedule-location-row">
|
||
<text class="schedule-location">{{ order.location || order.store_name }}</text>
|
||
<text class="schedule-service-type">{{ order.service_type || '到店服务' }}</text>
|
||
</view>
|
||
<view class="schedule-time-row">
|
||
<image class="time-icon" :src="clockIcon" mode="aspectFit" />
|
||
<text class="schedule-time">{{ order.start_time }}-{{ order.end_time }}</text>
|
||
</view>
|
||
<view class="schedule-address-row">
|
||
<image class="position-icon" :src="positionIcon" mode="aspectFit" />
|
||
<view class="schedule-address">
|
||
{{ order.address || order.store_address }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- <view class="schedule-navigate" @click="handleNavigate(order)">
|
||
<image class="navigate-icon" :src="navigateIcon" mode="aspectFit" />
|
||
</view> -->
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 平台公告 -->
|
||
<view class="announcement-section mx-30rpx mt-30rpx">
|
||
<view class="section-header">
|
||
<view class="announcement-header-left">
|
||
<image class="speaker-icon" :src="`${OSS}images/chayishi/laba.png`" mode="aspectFit" />
|
||
<text class="section-title">平台公告</text>
|
||
<text class="section-divider">|</text>
|
||
<text class="section-subtitle">消息早知道</text>
|
||
</view>
|
||
<view class="more-btn" @click="handleMoreAnnouncement">
|
||
<text class="more-text">更多</text>
|
||
<wd-icon name="arrow-right" size="20rpx" color="#909399" />
|
||
</view>
|
||
</view>
|
||
<view class="announcement-list">
|
||
<view
|
||
v-for="(item, index) in announcements" :key="item.id || index" class="announcement-item"
|
||
@click="handleAnnouncementClick(item)"
|
||
>
|
||
<view class="announcement-content">
|
||
<text class="announcement-title">{{ item.title }}</text>
|
||
<text class="announcement-time">{{ item.time }}</text>
|
||
</view>
|
||
<view class="announcement-image-wrapper">
|
||
<image v-if="item.image" class="announcement-image" :src="item.image" mode="aspectFill" />
|
||
<image v-if="item.type === 'video'" class="play-icon" :src="playIcon" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<style lang="scss">
|
||
page {
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.home-container {
|
||
background-color: #f5f5f5;
|
||
position: relative;
|
||
/* 为原生tabbar留出空间 */
|
||
padding-bottom: constant(safe-area-inset-bottom);
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
padding-bottom: 100rpx;
|
||
/* 原生tabbar高度约100rpx */
|
||
}
|
||
|
||
// 导航栏
|
||
.navbar-wrapper {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
background-color: transparent;
|
||
}
|
||
|
||
.navbar-content {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 20rpx 30rpx;
|
||
}
|
||
|
||
.greeting-text {
|
||
font-size: 32rpx;
|
||
font-weight: 400;
|
||
color: #303133;
|
||
line-height: 44rpx;
|
||
}
|
||
|
||
.navbar-icons {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.icon-btn {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.menu-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
|
||
// 内容区域
|
||
.content-wrapper {
|
||
padding-top: 100rpx;
|
||
position: relative;
|
||
}
|
||
|
||
.home-bg-image {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: -1;
|
||
object-fit: cover;
|
||
}
|
||
|
||
// 等级卡片背景
|
||
// 等级卡片滑动容器
|
||
.level-card-wrapper {
|
||
width: 100%;
|
||
position: relative;
|
||
}
|
||
|
||
.level-scroll {
|
||
width: 100%;
|
||
margin-bottom: 20rpx;
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
-webkit-overflow-scrolling: touch;
|
||
/* #endif */
|
||
/* 微信小程序平台兼容 */
|
||
/* #ifdef MP-WEIXIN */
|
||
white-space: nowrap;
|
||
/* #endif */
|
||
}
|
||
|
||
.level-scroll-content {
|
||
display: flex;
|
||
flex-direction: row;
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
flex-wrap: nowrap;
|
||
gap: 20rpx;
|
||
/* #endif */
|
||
/* 微信小程序平台兼容 */
|
||
/* #ifdef MP-WEIXIN */
|
||
display: inline-flex;
|
||
/* #endif */
|
||
}
|
||
|
||
.level-card-item {
|
||
flex-shrink: 0;
|
||
/* 微信小程序需要明确宽度 */
|
||
/* #ifdef MP-WEIXIN */
|
||
width: calc(100vw - 120rpx);
|
||
display: inline-block;
|
||
vertical-align: top;
|
||
margin-right: 20rpx;
|
||
/* #endif */
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
width: calc(100vw - 120rpx);
|
||
min-width: calc(100vw - 120rpx);
|
||
/* #endif */
|
||
}
|
||
|
||
.level-card-item:first-child {
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
margin-left: 30rpx;
|
||
/* #endif */
|
||
/* 微信小程序平台兼容 */
|
||
/* #ifdef MP-WEIXIN */
|
||
margin-left: 30rpx;
|
||
/* #endif */
|
||
}
|
||
|
||
.level-card-item:last-child {
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
margin-right: 30rpx;
|
||
/* #endif */
|
||
/* 微信小程序平台兼容 */
|
||
/* #ifdef MP-WEIXIN */
|
||
margin-right: 30rpx;
|
||
/* #endif */
|
||
}
|
||
|
||
.level-card-bg {
|
||
background-size: 100% 100%;
|
||
background-repeat: no-repeat;
|
||
background-position: center center;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
}
|
||
|
||
// 等级卡片
|
||
.level-card {
|
||
background: linear-gradient(135deg, #ffe5c4 0%, #fff5e8 100%);
|
||
border-radius: 24rpx;
|
||
padding: 40rpx 30rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.level-header {
|
||
display: flex;
|
||
align-items: center;
|
||
height: 60rpx;
|
||
justify-content: space-between;
|
||
margin-bottom: 10rpx;
|
||
box-sizing: border-box;
|
||
margin: 48rpx 24rpx;
|
||
}
|
||
|
||
.level-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.level-text {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #825f37;
|
||
line-height: 66rpx;
|
||
}
|
||
|
||
.level-label-wrapper {
|
||
background-color: #5a5d74;
|
||
border-radius: 16rpx;
|
||
padding: 10rpx;
|
||
display: inline-block;
|
||
color: #fff;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.level-label {
|
||
font-size: 24rpx;
|
||
color: #ffffff;
|
||
line-height: 34rpx;
|
||
}
|
||
|
||
.level-decoration {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
}
|
||
|
||
.commission-info {
|
||
display: flex;
|
||
gap: 60rpx;
|
||
margin-left: 24rpx;
|
||
}
|
||
|
||
.commission-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.commission-label {
|
||
font-size: 24rpx;
|
||
color: #825f37;
|
||
line-height: 34rpx;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.commission-value {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #825f37;
|
||
line-height: 50rpx;
|
||
}
|
||
|
||
.progress-section {
|
||
margin-top: 30rpx;
|
||
}
|
||
|
||
.progress-text {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 8rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.progress-current {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #825f37;
|
||
}
|
||
|
||
.progress-separator {
|
||
font-size: 28rpx;
|
||
color: #825f37;
|
||
}
|
||
|
||
.progress-target {
|
||
font-size: 28rpx;
|
||
color: #825f37;
|
||
}
|
||
|
||
.progress-label {
|
||
font-size: 24rpx;
|
||
color: #825f37;
|
||
margin-left: 10rpx;
|
||
}
|
||
|
||
.progress-tip {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.progress-bar-wrapper {
|
||
width: 100%;
|
||
}
|
||
|
||
.progress-bar-bg {
|
||
width: 100%;
|
||
height: 12rpx;
|
||
background-color: rgba(255, 255, 255, 0.5);
|
||
border-radius: 6rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.progress-bar-fill {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, #ffd700 0%, #ffa500 100%);
|
||
border-radius: 6rpx;
|
||
transition: width 0.3s;
|
||
}
|
||
|
||
// 今日行程
|
||
.schedule-section {
|
||
border-radius: 24rpx;
|
||
// padding: 30rpx;
|
||
margin-top: 30rpx;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 8rpx;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
color: #303133;
|
||
line-height: 44rpx;
|
||
}
|
||
|
||
.section-tip {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
line-height: 34rpx;
|
||
margin-left: 20rpx;
|
||
}
|
||
|
||
.schedule-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 20rpx;
|
||
width: 100%;
|
||
position: relative;
|
||
}
|
||
|
||
.schedule-scroll-wrapper {
|
||
width: 100%;
|
||
position: relative;
|
||
}
|
||
|
||
.schedule-scroll {
|
||
width: 100%;
|
||
margin-bottom: 20rpx;
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
-webkit-overflow-scrolling: touch;
|
||
/* #endif */
|
||
/* 微信小程序平台兼容 */
|
||
/* #ifdef MP-WEIXIN */
|
||
box-sizing: border-box;
|
||
white-space: nowrap;
|
||
/* #endif */
|
||
}
|
||
|
||
.schedule-scroll-content {
|
||
display: flex;
|
||
white-space: nowrap;
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
flex-wrap: nowrap;
|
||
gap: 20rpx;
|
||
/* #endif */
|
||
/* 微信小程序平台兼容 */
|
||
/* #ifdef MP-WEIXIN */
|
||
display: inline-flex;
|
||
/* #endif */
|
||
}
|
||
|
||
.schedule-item-wrapper {
|
||
flex-shrink: 0;
|
||
border: 4rpx solid #4a90e2;
|
||
border-radius: 16rpx;
|
||
/* 微信小程序需要明确宽度 */
|
||
/* #ifdef MP-WEIXIN */
|
||
width: calc(100vw - 60rpx);
|
||
display: inline-block;
|
||
vertical-align: top;
|
||
margin-right: 20rpx;
|
||
/* #endif */
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
width: calc(100vw - 60rpx);
|
||
min-width: calc(100vw - 60rpx);
|
||
margin-right: 20rpx;
|
||
background-color: #fff;
|
||
box-sizing: border-box;
|
||
padding: 8rpx;
|
||
/* #endif */
|
||
}
|
||
|
||
.schedule-item-wrapper:last-child {
|
||
/* H5 平台兼容 */
|
||
/* #ifdef H5 */
|
||
margin-right: 0;
|
||
/* #endif */
|
||
}
|
||
|
||
.schedule-item-wrapper .schedule-item {
|
||
width: 100%;
|
||
display: flex;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 分页指示点 */
|
||
.schedule-indicators {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-top: 20rpx;
|
||
padding-bottom: 10rpx;
|
||
}
|
||
|
||
// 等级指示点
|
||
.level-indicators {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-top: 20rpx;
|
||
padding-bottom: 10rpx;
|
||
}
|
||
|
||
.level-indicator {
|
||
width: 12rpx;
|
||
height: 12rpx;
|
||
border-radius: 50%;
|
||
background-color: #e4e7ed;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
.level-indicator-active {
|
||
background-color: #4c9f44;
|
||
width: 24rpx;
|
||
border-radius: 6rpx;
|
||
}
|
||
|
||
.schedule-indicator {
|
||
width: 12rpx;
|
||
height: 12rpx;
|
||
border-radius: 50%;
|
||
background-color: #e4e7ed;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
.schedule-indicator-active {
|
||
background-color: #4c9f44;
|
||
width: 24rpx;
|
||
border-radius: 6rpx;
|
||
}
|
||
|
||
.empty-schedule {
|
||
text-align: center;
|
||
padding: 60rpx 0;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 28rpx;
|
||
color: #909399;
|
||
}
|
||
|
||
.schedule-item {
|
||
display: flex;
|
||
background-color: #ffffff;
|
||
border-radius: 16rpx;
|
||
padding: 0rpx 30rpx 30rpx 30rpx;
|
||
position: relative;
|
||
align-items: center;
|
||
}
|
||
|
||
.schedule-date {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 100rpx;
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
background-color: #000000;
|
||
border-radius: 12rpx;
|
||
margin-right: 30rpx;
|
||
padding: 10rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.date-day {
|
||
font-size: 48rpx;
|
||
font-weight: bold;
|
||
color: #ffffff;
|
||
line-height: 48rpx;
|
||
}
|
||
|
||
.date-month {
|
||
font-size: 24rpx;
|
||
color: #ffffff;
|
||
line-height: 34rpx;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.schedule-content {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.schedule-header-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
padding-left: 16rpx;
|
||
padding-right: 16rpx;
|
||
box-sizing: border-box;
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
// margin-bottom: 16rpx;
|
||
}
|
||
|
||
.schedule-type {
|
||
font-size: 28rpx;
|
||
color: #303133;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.schedule-status {
|
||
font-size: 24rpx;
|
||
color: #4c9f44;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.schedule-location-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-top: 16rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.schedule-location {
|
||
font-size: 30rpx;
|
||
color: #303133;
|
||
font-weight: 500;
|
||
line-height: 42rpx;
|
||
}
|
||
|
||
.schedule-service-type {
|
||
font-size: 22rpx;
|
||
color: #ffffff;
|
||
background-color: #d4a574;
|
||
padding: 4rpx 12rpx;
|
||
border-radius: 4rpx;
|
||
line-height: 30rpx;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.schedule-time-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.schedule-address-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.time-icon,
|
||
.position-icon {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
}
|
||
|
||
.schedule-time,
|
||
.schedule-address {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
line-height: 34rpx;
|
||
}
|
||
|
||
.schedule-address {
|
||
flex: 1;
|
||
min-width: 0;
|
||
word-wrap: break-word;
|
||
word-break: break-all;
|
||
overflow-wrap: break-word;
|
||
white-space: normal;
|
||
display: block;
|
||
}
|
||
|
||
.schedule-navigate {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: flex-end;
|
||
margin-left: 20rpx;
|
||
padding: 10rpx;
|
||
align-self: flex-end;
|
||
background-color: #f6f7f9;
|
||
border-radius: 24rpx;
|
||
}
|
||
|
||
.navigate-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
opacity: 0.6;
|
||
filter: grayscale(100%);
|
||
}
|
||
|
||
// 平台公告
|
||
.announcement-section {
|
||
background-color: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 30rpx;
|
||
margin-top: 30rpx;
|
||
}
|
||
|
||
.announcement-header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.speaker-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
|
||
.section-divider {
|
||
font-size: 28rpx;
|
||
color: #d9d9d9;
|
||
margin: 0 12rpx;
|
||
}
|
||
|
||
.section-subtitle {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
line-height: 34rpx;
|
||
}
|
||
|
||
.more-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.more-text {
|
||
font-size: 24rpx;
|
||
color: #909399;
|
||
line-height: 34rpx;
|
||
}
|
||
|
||
.arrow-icon {
|
||
width: 20rpx;
|
||
height: 20rpx;
|
||
}
|
||
|
||
.announcement-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 30rpx;
|
||
margin-top: 30rpx;
|
||
}
|
||
|
||
.announcement-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding-bottom: 30rpx;
|
||
border-bottom: 2rpx solid #f6f7f9;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
padding-bottom: 0;
|
||
}
|
||
}
|
||
|
||
.announcement-content {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
margin-right: 26rpx;
|
||
}
|
||
|
||
.announcement-title {
|
||
font-size: 26rpx;
|
||
color: #303133;
|
||
line-height: 40rpx;
|
||
display: -webkit-box;
|
||
-webkit-box-orient: vertical;
|
||
-webkit-line-clamp: 2;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.announcement-time {
|
||
font-size: 22rpx;
|
||
color: #909399;
|
||
line-height: 32rpx;
|
||
}
|
||
|
||
.announcement-image-wrapper {
|
||
position: relative;
|
||
width: 164rpx;
|
||
height: 108rpx;
|
||
border-radius: 8rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.announcement-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.play-icon {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
}
|
||
</style>
|