Files
wangxiaowei 9266b6b80d 更新文件
2025-12-28 14:23:16 +08:00

1225 lines
29 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 使用 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>