777 lines
19 KiB
Vue
777 lines
19 KiB
Vue
<template>
|
||
<view class="content-class">
|
||
<template v-if="isLoggedIn">
|
||
<!-- 顶部渐变背景层 -->
|
||
<view class="bg-gradient"></view>
|
||
|
||
<!-- 页面内容区 -->
|
||
<view class="page-content">
|
||
<view class="sticky-header">
|
||
<!-- 状态栏占位 -->
|
||
<view class="status_bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||
<!-- 导航栏 -->
|
||
<view class="nav-bar">
|
||
<text class="nav-title">首页</text>
|
||
</view>
|
||
<!-- 小区选择 -->
|
||
<view class="header-container" @click="navigateToPage">
|
||
<view class="location-area">
|
||
<view class="location-icon">
|
||
<image
|
||
src="https://wuyeadmin.bugtc.com/images/imgs/adress.png"
|
||
style="height: 100%; width: 100%"
|
||
></image>
|
||
</view>
|
||
<view class="community-selector">
|
||
<text class="community-name">{{ currentCommunity }}</text>
|
||
<view class="community-icon">
|
||
<image
|
||
src="https://wuyeadmin.bugtc.com/images/imgs/三角形.png"
|
||
style="height: 100%; width: 100%"
|
||
></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 可滚动内容区 -->
|
||
<view class="scroll-content">
|
||
<!-- banner -->
|
||
<view class="bannarClass" v-if="bannerList && bannerList.length > 0">
|
||
<up-swiper
|
||
:list="bannerList"
|
||
indicator
|
||
indicatorMode="dot"
|
||
radius="15"
|
||
height="180"
|
||
keyName="url"
|
||
circular
|
||
>
|
||
<template #default="{ item, index }">
|
||
<image :src="item.url || item" mode="aspectFill" class="banner-img"></image>
|
||
</template>
|
||
</up-swiper>
|
||
</view>
|
||
|
||
<!-- 巡检 -->
|
||
<view class="inspectionClass">
|
||
<!-- 消息通知栏 -->
|
||
<view class="noticeClass">
|
||
<view class="notice-left">
|
||
<image
|
||
src="https://wuyeadmin.bugtc.com/images/imgs/notice.png"
|
||
class="notice-icon"
|
||
></image>
|
||
<view class="notice-line"></view>
|
||
</view>
|
||
<view class="notice-right" @click="getNoticeMore">
|
||
<uni-notice-bar
|
||
:text="noticeText"
|
||
type="line"
|
||
:showIcon="false"
|
||
show-get-more
|
||
scrollable
|
||
color="#fff"
|
||
background-color="transparent"
|
||
moreColor="#fff"
|
||
no-border
|
||
>
|
||
</uni-notice-bar>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 巡检数据统计区 -->
|
||
<view class="statistics-wrap">
|
||
<view class="statistics-item" @click="goToInspectionRecord">
|
||
<text class="num">{{ allCount }}</text>
|
||
<text class="label">全部巡检</text>
|
||
</view>
|
||
<view class="statistics-item" @click="goToDaysInspection">
|
||
<text class="num">{{ pendingCount }}</text>
|
||
<text class="label">待巡检</text>
|
||
</view>
|
||
<view class="statistics-item">
|
||
<text class="num">{{ InspectedCount }}</text>
|
||
<text class="label">已巡检</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 网格布局功能 -->
|
||
<view class="function-container">
|
||
<template v-for="item in functionList" :key="item.action">
|
||
<view
|
||
class="function-item"
|
||
@click="handleFunctionClick(item)"
|
||
v-if="permStore.hasPermi(item.permKey)"
|
||
>
|
||
<image class="item-icon" :src="item.icon" mode="aspectFit"></image>
|
||
<text class="item-text">{{ item.text }}</text>
|
||
<view
|
||
v-if="item.permKey === 'butler:workOrder:mine' && MyOrderNum > 0"
|
||
class="todoNum"
|
||
>{{ MyOrderNum > 99 ? '99' : MyOrderNum }}</view
|
||
>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
<view v-else class="launch-placeholder"></view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { onLoad, onUnload, onShow, onReady, onPullDownRefresh } from '@dcloudio/uni-app'
|
||
import {
|
||
getCurrentVillage,
|
||
getTodayInspection,
|
||
getNewNoticeData,
|
||
getBannarList,
|
||
myOrderCount
|
||
} from '../../api/api.js'
|
||
|
||
import { usePermStore } from '@/stores/usePermStore'
|
||
|
||
const permStore = usePermStore()
|
||
|
||
// 登录状态:未登录时启动跳引导页
|
||
const isLoggedIn = ref(!!uni.getStorageSync('token'))
|
||
|
||
// 首次加载标记
|
||
const hasInit = ref(false)
|
||
|
||
// banner 缓存 key 和缓存时长(30分钟)
|
||
const BANNER_CACHE_KEY = 'home_banner_cache'
|
||
const BANNER_CACHE_TIME = 30 * 60 * 1000
|
||
|
||
// 列表数据状态
|
||
const currentCommunity = ref('请先绑定房屋')
|
||
const bannerList = ref([])
|
||
const noticeText = ref('暂无公告')
|
||
const allCount = ref(0) // 全部巡检
|
||
const pendingCount = ref(0) //待巡检
|
||
const InspectedCount = ref(0) //已巡检
|
||
const statusBarHeight = ref(uni.getSystemInfoSync().statusBarHeight || 0)
|
||
// =======方法=======
|
||
// 跳转小区
|
||
const navigateToPage = () => {
|
||
const curVillageId = uni.getStorageSync('currentVillage')
|
||
let villageId = ''
|
||
if (curVillageId) {
|
||
try {
|
||
villageId = JSON.parse(curVillageId).villageId || JSON.parse(curVillageId).id || ''
|
||
} catch (e) {}
|
||
}
|
||
uni.navigateTo({
|
||
url: `/pageSubPack/notice-list/select-community?villageId=${villageId}`
|
||
})
|
||
}
|
||
// 跳转公告
|
||
const getNoticeMore = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/notice-list/notice-list'
|
||
})
|
||
}
|
||
// 跳转一键开门
|
||
const goToOneOpenDoor = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/oneClickOpen/oneClickOpen'
|
||
})
|
||
}
|
||
// 工单大厅
|
||
const goToTicketHall = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/ticket/hall'
|
||
})
|
||
}
|
||
// 我的工单
|
||
const goToMyTicket = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/ticket/myticket?MyOrderNum=' + MyOrderNum.value
|
||
})
|
||
}
|
||
// 跳转到 今日巡检
|
||
const goToDaysInspection = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/inspection/toDays_inscpection?type=0'
|
||
})
|
||
}
|
||
// 跳转到 巡检记录
|
||
const goToInspectionRecord = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/inspection/inspection_record'
|
||
})
|
||
}
|
||
// 跳转到 投诉处理
|
||
const goToComplaint = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/complaint/Details'
|
||
})
|
||
}
|
||
// 故障上报
|
||
const goToReport = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/fault-reporting/fault-reporting'
|
||
})
|
||
}
|
||
// 跳转到仪表换新
|
||
const goToReplacement_record = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/instrument/replacement_record'
|
||
})
|
||
}
|
||
// 跳转到实收统计
|
||
const goToRevenueStatistics = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/instrument/revenue_statistics'
|
||
})
|
||
}
|
||
// 跳转到收费总览
|
||
const goToFeeOverview = () => {
|
||
uni.navigateTo({
|
||
url: '/pageSubPack/statistics/statistics'
|
||
})
|
||
}
|
||
|
||
// 功能列表数据
|
||
const functionList = [
|
||
{
|
||
permKey: 'butler:fault:report',
|
||
icon: 'https://wuyeadmin.bugtc.com/images/imgs/fault-report.png',
|
||
text: '故障上报',
|
||
action: 'goToReport'
|
||
},
|
||
{
|
||
permKey: 'butler:door:open',
|
||
icon: 'https://wuyeadmin.bugtc.com/images/imgs/open.png',
|
||
text: '一键开门',
|
||
action: 'goToOneOpenDoor'
|
||
},
|
||
{
|
||
permKey: 'butler:workOrder:hall',
|
||
icon: 'https://wuyeadmin.bugtc.com/images/imgs/work-order.png',
|
||
text: '工单大厅',
|
||
action: 'goToTicketHall'
|
||
},
|
||
{
|
||
permKey: 'butler:workOrder:mine',
|
||
icon: 'https://wuyeadmin.bugtc.com/images/imgs/my-work.png',
|
||
text: '我的工单',
|
||
action: 'goToMyTicket'
|
||
},
|
||
{
|
||
permKey: 'butler:complaint:handle',
|
||
icon: 'https://wuyeadmin.bugtc.com/images/imgs/complaint.png',
|
||
text: '投诉处理',
|
||
action: 'goToComplaint'
|
||
},
|
||
{
|
||
permKey: 'butler:meter:replace',
|
||
icon: 'https://wuye.ckdzkj.com/images/home/updateDevice.png',
|
||
text: '仪表换新',
|
||
action: 'goToReplacement_record'
|
||
},
|
||
{
|
||
permKey: 'butler:actualReceipt:stats',
|
||
icon: 'https://wuye.ckdzkj.com/images/imgs/revenue-statistics.png',
|
||
text: '实收统计',
|
||
action: 'goToRevenueStatistics'
|
||
},
|
||
{
|
||
permKey: 'butler:feeOverview:view',
|
||
icon: 'https://wuye.ckdzkj.com/images/imgs/fee-overview.png',
|
||
text: '收费总览',
|
||
action: 'goToFeeOverview'
|
||
}
|
||
]
|
||
|
||
// 统一点击处理
|
||
const actionMap = {
|
||
goToReport,
|
||
goToOneOpenDoor,
|
||
goToTicketHall,
|
||
goToMyTicket,
|
||
goToComplaint,
|
||
goToReplacement_record,
|
||
goToRevenueStatistics,
|
||
goToFeeOverview
|
||
}
|
||
|
||
const handleFunctionClick = item => {
|
||
const handler = actionMap[item.action]
|
||
if (handler) handler()
|
||
}
|
||
// 获取当前小区
|
||
const currentVillageData = () => {
|
||
currentCommunity.value = '请先绑定房屋'
|
||
return getCurrentVillage()
|
||
.then(res => {
|
||
const data = res.data
|
||
if (data) {
|
||
currentCommunity.value = data.villageName
|
||
uni.setStorageSync('currentVillage', JSON.stringify(data))
|
||
getNoticeData()
|
||
}
|
||
})
|
||
.catch(() => {
|
||
currentCommunity.value = '请先绑定房屋'
|
||
})
|
||
}
|
||
// 获取今日巡检数据
|
||
const getInspectionData = () => {
|
||
return getTodayInspection()
|
||
.then(res => {
|
||
if (res.code === 200) {
|
||
if (res.data) {
|
||
allCount.value = res.data.totalTasks
|
||
pendingCount.value = res.data.unfinishedTasks
|
||
InspectedCount.value = res.data.completedTasks
|
||
} else {
|
||
allCount.value = 0
|
||
pendingCount.value = 0
|
||
InspectedCount.value = 0
|
||
}
|
||
} else {
|
||
uni.showToast({ title: res.msg || '获取失败', icon: 'none' })
|
||
}
|
||
})
|
||
.catch(err => {
|
||
uni.showToast({ title: err.msg || '获取失败', icon: 'none' })
|
||
})
|
||
}
|
||
// 获取消息通知
|
||
const getNoticeData = () => {
|
||
getNewNoticeData().then(res => {
|
||
const notice = res.code === 200 && res.data ? (res.data.problem || res.data.notice) : '暂无公告'
|
||
// 仅在内容真正变化时才更新
|
||
if (noticeText.value !== notice) {
|
||
noticeText.value = notice
|
||
}
|
||
})
|
||
.catch(() => {})
|
||
}
|
||
// 获取bannar图
|
||
function getbannarData(forceRefresh = false) {
|
||
// 非强制刷新时,优先读缓存
|
||
if (!forceRefresh) {
|
||
try {
|
||
const cached = uni.getStorageSync(BANNER_CACHE_KEY)
|
||
if (cached) {
|
||
const { data, time } = JSON.parse(cached)
|
||
if (data && data.length > 0 && Date.now() - time < BANNER_CACHE_TIME) {
|
||
bannerList.value = data
|
||
return // 缓存有效,不发起请求
|
||
}
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
return getBannarList()
|
||
.then(res => {
|
||
if (res.code === 200 && res.data) {
|
||
const newData = res.data
|
||
const oldData = bannerList.value
|
||
if (JSON.stringify(newData) !== JSON.stringify(oldData)) {
|
||
bannerList.value = newData
|
||
}
|
||
// 写入缓存
|
||
uni.setStorageSync(
|
||
BANNER_CACHE_KEY,
|
||
JSON.stringify({
|
||
data: newData,
|
||
time: Date.now()
|
||
})
|
||
)
|
||
} else {
|
||
bannerList.value = []
|
||
}
|
||
})
|
||
.catch(() => {
|
||
bannerList.value = []
|
||
})
|
||
}
|
||
|
||
const MyOrderNum = ref(0)
|
||
// 查询我的工单-待办数量
|
||
function getMyOrderNum() {
|
||
return myOrderCount()
|
||
.then(res => {
|
||
if (res.code === 200 && res.data) {
|
||
MyOrderNum.value = res.data
|
||
} else {
|
||
MyOrderNum.value = 0
|
||
}
|
||
})
|
||
.catch(() => {
|
||
MyOrderNum.value = 0
|
||
})
|
||
}
|
||
|
||
// 接收选择小区返回的参数
|
||
const slelctHomeData = data => {
|
||
currentCommunity.value = data.villageName
|
||
uni.setStorageSync('currentVillage', JSON.stringify(data))
|
||
getNoticeData()
|
||
getInspectionData()
|
||
}
|
||
|
||
onShow(() => {
|
||
if (!isLoggedIn.value) return
|
||
if (!hasInit.value) {
|
||
// 首次加载:onLoad 已触发过核心数据请求,这里只补 onLoad 没调的和需要每次都刷新的
|
||
hasInit.value = true
|
||
getbannarData() // onLoad 没调 banner
|
||
getMyOrderNum() // onLoad 没调工单数
|
||
permStore.initPerm() // 刷新权限缓存
|
||
// currentVillageData 和 getInspectionData 已在 onLoad 中调用,不再重复
|
||
return
|
||
}
|
||
// 从其他页面返回 / 从后台恢复:只刷新可能变化的数据
|
||
getbannarData()
|
||
getMyOrderNum()
|
||
getNoticeData()
|
||
// 换账号登录后 currentVillage 缓存已被清除,需要重新获取小区
|
||
if (!uni.getStorageSync('currentVillage')) {
|
||
currentVillageData()
|
||
getInspectionData()
|
||
}
|
||
})
|
||
|
||
onLoad(() => {
|
||
// 未登录:登录过→登录页;首次下载→引导页
|
||
if (!isLoggedIn.value) {
|
||
const hasShowGuide = uni.getStorageSync('hasShowGuide')
|
||
uni.hideTabBar({ animation: false })
|
||
uni.reLaunch({
|
||
url: hasShowGuide ? '/pageSubPack/loginSub/pwd-login' : '/pages/guide/guide',
|
||
animationType: 'none',
|
||
animationDuration: 0
|
||
})
|
||
return
|
||
}
|
||
// 已登录:确保 tabBar 显示(未登录启动时曾被 hideTabBar 隐藏,switchTab 不会自动恢复)
|
||
uni.showTabBar({ animation: false })
|
||
uni.$on('confirm', slelctHomeData)
|
||
currentVillageData()
|
||
getInspectionData()
|
||
})
|
||
|
||
onReady(() => {
|
||
// 已登录:首页即最终页,渲染完成后关闭启动屏(未登录由引导页 onReady 关闭)
|
||
if (isLoggedIn.value) {
|
||
// #ifdef APP-PLUS
|
||
plus.navigator.closeSplashscreen()
|
||
// #endif
|
||
}
|
||
})
|
||
|
||
onUnload(() => {
|
||
uni.$off('confirm', slelctHomeData)
|
||
})
|
||
|
||
// 下拉刷新
|
||
onPullDownRefresh(async () => {
|
||
if (!isLoggedIn.value) {
|
||
uni.stopPullDownRefresh()
|
||
return
|
||
}
|
||
try {
|
||
await Promise.allSettled([
|
||
currentVillageData(),
|
||
getInspectionData(),
|
||
getbannarData(true),
|
||
getMyOrderNum()
|
||
])
|
||
} finally {
|
||
uni.stopPullDownRefresh()
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.todoNum {
|
||
position: absolute;
|
||
top: 0rpx;
|
||
right: 17%;
|
||
min-width: 30rpx;
|
||
height: 30rpx;
|
||
background: #f53f3f;
|
||
color: #fff;
|
||
text-align: center;
|
||
font-size: 20rpx;
|
||
line-height: 30rpx;
|
||
border-radius: 50%;
|
||
padding: 3rpx;
|
||
}
|
||
.content-class {
|
||
background-color: #f9f9f9;
|
||
min-height: 100vh;
|
||
position: relative;
|
||
}
|
||
|
||
/* 未登录启动占位:背景与引导页一致,过渡不闪烁 */
|
||
.launch-placeholder {
|
||
min-height: 100vh;
|
||
background: linear-gradient(to bottom, #e2f0ff, #f6faff);
|
||
}
|
||
|
||
/* 顶部渐变背景 - 增加高度确保覆盖粘性头部区域 */
|
||
.bg-gradient {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 600rpx;
|
||
background: repeating-linear-gradient(to right, #edf4fa, #c0e4fb);
|
||
z-index: 0;
|
||
}
|
||
|
||
/* 页面内容容器 */
|
||
.page-content {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 0 40rpx 40rpx;
|
||
}
|
||
|
||
/* 粘性头部区域 - 滚动时固定在顶部 */
|
||
.sticky-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
/* 与顶部渐变背景一致,保证滚动时视觉效果连贯 */
|
||
background: repeating-linear-gradient(to right, #edf4fa, #c0e4fb);
|
||
margin: 0 -40rpx; /* 抵消父容器内边距,使背景完全延伸 */
|
||
padding: 0 40rpx;
|
||
/* 可选:添加轻微阴影增强层次感 */
|
||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.02);
|
||
}
|
||
|
||
.status_bar {
|
||
width: 100%;
|
||
}
|
||
|
||
/* 导航栏 */
|
||
.nav-bar {
|
||
height: 88rpx;
|
||
line-height: 88rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.nav-title {
|
||
font-size: 32rpx;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.header-container {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 4rpx 0;
|
||
}
|
||
|
||
/* 左侧区域 */
|
||
.location-area {
|
||
display: flex;
|
||
align-items: center;
|
||
position: relative;
|
||
flex: 1;
|
||
min-width: 0;
|
||
|
||
.location-icon {
|
||
width: 45rpx;
|
||
height: 45rpx;
|
||
margin-right: 12rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.community-selector {
|
||
display: flex;
|
||
align-items: center;
|
||
max-width: 300rpx;
|
||
cursor: pointer;
|
||
|
||
.community-name {
|
||
font-size: 26rpx;
|
||
font-weight: 500;
|
||
color: #000;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 200rpx;
|
||
}
|
||
|
||
.community-icon {
|
||
width: 20rpx;
|
||
height: 20rpx;
|
||
margin-left: 20rpx;
|
||
margin-top: -22rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 可滚动内容区域 */
|
||
.scroll-content {
|
||
/* 确保内部元素正常布局 */
|
||
width: 100%;
|
||
}
|
||
|
||
.bannarClass {
|
||
padding: 20rpx 0;
|
||
}
|
||
|
||
.banner-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 15rpx;
|
||
}
|
||
|
||
.inspectionClass {
|
||
background: linear-gradient(to right, #7b87fa, #4d5dfa);
|
||
border-radius: 16rpx;
|
||
box-sizing: border-box;
|
||
padding: 30rpx;
|
||
}
|
||
|
||
/* 消息通知栏 */
|
||
.noticeClass {
|
||
display: flex;
|
||
align-items: center;
|
||
height: 80rpx;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
border-radius: 16rpx;
|
||
padding: 6rpx 20rpx;
|
||
margin-bottom: 30rpx;
|
||
border: 1rpx solid rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
/* 左侧"消息通知"文字 */
|
||
.notice-left {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-right: 16rpx;
|
||
|
||
.notice-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-right: 15rpx;
|
||
}
|
||
|
||
.notice-line {
|
||
width: 1rpx;
|
||
height: 40rpx;
|
||
background-color: rgba(255, 255, 255, 0.4);
|
||
}
|
||
}
|
||
|
||
/* 右侧公告滚动区 */
|
||
.notice-right {
|
||
flex: 1;
|
||
}
|
||
|
||
/* 深度修改uni-notice-bar样式 */
|
||
:deep(.uni-noticebar) {
|
||
background-color: transparent !important;
|
||
height: 100% !important;
|
||
line-height: 80rpx !important;
|
||
padding: 0 !important;
|
||
margin: 0 !important;
|
||
}
|
||
|
||
/* 公告文字样式 */
|
||
:deep(.uni-noticebar__content) {
|
||
font-size: 26rpx !important;
|
||
color: #fff !important;
|
||
padding: 0 !important;
|
||
}
|
||
|
||
/* 右侧箭头按钮 */
|
||
:deep(.uni-noticebar__more) {
|
||
color: #fff !important;
|
||
font-size: 24rpx !important;
|
||
padding: 0 0 0 10rpx !important;
|
||
}
|
||
|
||
/* 隐藏默认滚动动画的多余样式 */
|
||
:deep(.uni-noticebar__content-wrapper--scrollable) {
|
||
left: 0 !important;
|
||
width: calc(100% - 30rpx) !important;
|
||
}
|
||
|
||
/* 统计区布局 */
|
||
.statistics-wrap {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 20rpx;
|
||
}
|
||
|
||
/* 统计项样式 */
|
||
.statistics-item {
|
||
text-align: center;
|
||
}
|
||
|
||
.statistics-item .num {
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
color: #fff;
|
||
display: block;
|
||
line-height: 1;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.statistics-item .label {
|
||
font-size: 24rpx;
|
||
color: #fff;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.function-container {
|
||
background-color: #ffffff;
|
||
border-radius: 16rpx;
|
||
padding: 30rpx 0;
|
||
box-sizing: border-box;
|
||
margin-top: 20rpx;
|
||
display: grid;
|
||
|
||
grid-template-columns: repeat(4, 1fr);
|
||
}
|
||
|
||
/* 功能行布局 */
|
||
.function-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
|
||
.function-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 10rpx 0;
|
||
position: relative;
|
||
}
|
||
|
||
/* 功能图标样式 */
|
||
.item-icon {
|
||
width: 88rpx;
|
||
height: 88rpx;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
/* 功能文字样式 */
|
||
.item-text {
|
||
font-size: 24rpx;
|
||
color: #333333;
|
||
font-weight: 400;
|
||
text-align: center;
|
||
}
|
||
</style>
|