完善录音时长功能
This commit is contained in:
@@ -1,274 +0,0 @@
|
||||
<template>
|
||||
<uni-popup ref="popup" type="top" :mask-click="true" @change="onPopupChange">
|
||||
<view class="recording-duration-popup">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">录音时长统计</text>
|
||||
<view class="popup-close" @click="close">
|
||||
<text class="close-icon">×</text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="popup-content" scroll-y="true">
|
||||
<!-- 统计卡片 -->
|
||||
<view class="popup-stats-card">
|
||||
<view class="popup-stat-item">
|
||||
<text class="popup-stat-value">{{ totalDuration }}</text>
|
||||
<text class="popup-stat-label">总录音时长</text>
|
||||
</view>
|
||||
<view class="popup-stat-item">
|
||||
<text class="popup-stat-value">{{ todayDuration }}</text>
|
||||
<text class="popup-stat-label">今日录音时长</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 图表区域 -->
|
||||
<view class="popup-chart-section">
|
||||
<text class="popup-section-title">时长趋势图</text>
|
||||
<view class="popup-chart-placeholder">
|
||||
<text class="popup-placeholder-text">📊 图表区域</text>
|
||||
<text class="popup-placeholder-desc">此处将显示录音时长趋势图表</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据列表 -->
|
||||
<view class="popup-data-list">
|
||||
<text class="popup-section-title">详细数据</text>
|
||||
<view class="popup-list-item" v-for="(item, index) in dataList" :key="index">
|
||||
<view class="popup-item-left">
|
||||
<text class="popup-item-date">{{ item.date }}</text>
|
||||
<text class="popup-item-desc">{{ item.description }}</text>
|
||||
</view>
|
||||
<view class="popup-item-right">
|
||||
<text class="popup-item-duration">{{ item.duration }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'RecordingDurationPopup',
|
||||
data() {
|
||||
return {
|
||||
totalDuration: '125.5 小时',
|
||||
todayDuration: '8.2 小时',
|
||||
dataList: [
|
||||
{ date: '2024-02-07', description: '客户咨询录音', duration: '2.5 小时' },
|
||||
{ date: '2024-02-06', description: '销售洽谈录音', duration: '3.2 小时' },
|
||||
{ date: '2024-02-05', description: '培训录音', duration: '1.8 小时' },
|
||||
{ date: '2024-02-04', description: '会议录音', duration: '4.1 小时' },
|
||||
{ date: '2024-02-03', description: '客户反馈录音', duration: '2.9 小时' }
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.popup.open()
|
||||
},
|
||||
close() {
|
||||
this.$refs.popup.close()
|
||||
},
|
||||
onPopupChange(e) {
|
||||
if (!e.show) {
|
||||
this.$emit('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 确保弹出框在导航栏之上 */
|
||||
::v-deep .uni-popup.top {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
|
||||
/* 确保弹出框 wrapper 正确显示 */
|
||||
::v-deep .uni-popup.top .uni-popup__wrapper {
|
||||
overflow: visible !important;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.recording-duration-popup {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx;
|
||||
border-bottom: 1rpx solid #E0E0E0;
|
||||
flex-shrink: 0;
|
||||
background-color: #FFFFFF;
|
||||
box-sizing: border-box;
|
||||
min-height: 112rpx;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
overflow: visible;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
min-width: 64rpx;
|
||||
min-height: 64rpx;
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.2s;
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
overflow: visible;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.popup-close:active {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
font-size: 48rpx;
|
||||
color: #333;
|
||||
line-height: 1;
|
||||
display: block !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.popup-stats-card {
|
||||
display: flex;
|
||||
margin: 20rpx 30rpx;
|
||||
background: #f8f9fa;
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx 30rpx;
|
||||
}
|
||||
|
||||
.popup-stat-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.popup-stat-item:not(:last-child) {
|
||||
border-right: 1rpx solid #e9ecef;
|
||||
}
|
||||
|
||||
.popup-stat-value {
|
||||
display: block;
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #007aff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.popup-stat-label {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.popup-chart-section,
|
||||
.popup-data-list {
|
||||
margin: 20rpx 30rpx;
|
||||
background: #f8f9fa;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.popup-section-title {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #e9ecef;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.popup-chart-placeholder {
|
||||
padding: 80rpx 30rpx;
|
||||
text-align: center;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.popup-placeholder-text {
|
||||
display: block;
|
||||
font-size: 48rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.popup-placeholder-desc {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.popup-list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.popup-list-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.popup-item-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.popup-item-date {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.popup-item-desc {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.popup-item-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.popup-item-duration {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #007aff;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,539 @@
|
||||
<template>
|
||||
<view class="feature-page">
|
||||
<view class="page-header" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="nav-bar">
|
||||
<view class="nav-left" @click="goBack">
|
||||
<text class="back-icon">←</text>
|
||||
</view>
|
||||
<text class="nav-title">录音时长统计</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="content-scroll" scroll-y="true" :style="{ top: contentTop, bottom: contentBottom }">
|
||||
<!-- 搜索区域 -->
|
||||
<view class="search-toolbar">
|
||||
<view class="toolbar-picker-wrapper" @click="toggleTimeRangeDropdown">
|
||||
<view class="toolbar-picker-view">
|
||||
<text class="toolbar-picker-text">{{ timeRangeOptions[timeRangeIndex] }}</text>
|
||||
<uni-icons :type="showTimeRangeDropdown ? 'top' : 'bottom'" size="14" color="#999"></uni-icons>
|
||||
</view>
|
||||
<!-- 自定义下拉菜单 -->
|
||||
<view class="time-range-dropdown" v-if="showTimeRangeDropdown">
|
||||
<view
|
||||
class="dropdown-item"
|
||||
v-for="(option, index) in timeRangeOptions"
|
||||
:key="index"
|
||||
:class="{ 'dropdown-item-active': timeRangeIndex === index }"
|
||||
@click.stop="selectTimeRange(index)">
|
||||
<text>{{ option }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="toolbar-actions">
|
||||
<view class="toolbar-btn toolbar-btn--refresh" @click="onRefresh">
|
||||
<uni-icons type="refresh" size="18" color="#2A68FF"></uni-icons>
|
||||
<text>刷新</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 遮罩层,点击关闭下拉菜单 -->
|
||||
<view class="dropdown-mask" v-if="showTimeRangeDropdown" @click="closeTimeRangeDropdown"></view>
|
||||
|
||||
<!-- 统计卡片 -->
|
||||
<view class="stats-card">
|
||||
<view class="stat-item">
|
||||
<text class="stat-value">{{ totalDuration }}</text>
|
||||
<text class="stat-label">总录音时长</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="stat-value">{{ todayDuration }}</text>
|
||||
<text class="stat-label">今日录音时长</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 图表区域 -->
|
||||
<view class="chart-section">
|
||||
<text class="section-title">时长趋势图</text>
|
||||
<view class="chart-placeholder">
|
||||
<text class="placeholder-text">📊 图表区域</text>
|
||||
<text class="placeholder-desc">此处将显示录音时长趋势图表</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据列表 -->
|
||||
<view class="data-list">
|
||||
<text class="section-title">详细数据</text>
|
||||
<view class="list-item" v-for="(item, index) in dataList" :key="index">
|
||||
<view class="item-left">
|
||||
<text class="item-date">{{ item.date }}</text>
|
||||
<text class="item-desc">{{ item.description }}</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<text class="item-duration">{{ item.duration }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取系统信息的辅助函数
|
||||
function getSystemInfo() {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 微信小程序:优先使用新的 API
|
||||
if (typeof wx !== 'undefined' && wx.getWindowInfo) {
|
||||
try {
|
||||
const windowInfo = wx.getWindowInfo();
|
||||
return {
|
||||
statusBarHeight: windowInfo.statusBarHeight || 20,
|
||||
windowWidth: windowInfo.windowWidth,
|
||||
windowHeight: windowInfo.windowHeight
|
||||
};
|
||||
} catch (e) {
|
||||
console.warn('[RecordingDuration] Failed to use wx.getWindowInfo, fallback to getSystemInfoSync:', e);
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
// 回退到旧的 API 或使用 uni-app 的 API
|
||||
try {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
return {
|
||||
statusBarHeight: systemInfo.statusBarHeight || 20,
|
||||
windowWidth: systemInfo.windowWidth,
|
||||
windowHeight: systemInfo.windowHeight
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('[RecordingDuration] Failed to get system info:', e);
|
||||
return {
|
||||
statusBarHeight: 20,
|
||||
windowWidth: 375,
|
||||
windowHeight: 667
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
data() {
|
||||
// 动态计算导航栏高度
|
||||
const systemInfo = getSystemInfo();
|
||||
const statusBarHeight = systemInfo.statusBarHeight;
|
||||
const navbarHeight = 44; // navbar高度44px
|
||||
// 转换为rpx:1px = 2rpx(在375px设计稿下)
|
||||
const statusBarHeightRpx = statusBarHeight * 2;
|
||||
const navbarHeightRpx = navbarHeight * 2;
|
||||
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
|
||||
|
||||
return {
|
||||
statusBarHeight: statusBarHeight, // 状态栏高度(px)
|
||||
contentTop: totalNavbarHeight + 'rpx', // 内容区域距离顶部的距离
|
||||
contentBottom: '0rpx', // 内容区域距离底部的距离(默认值,会在 onReady 中更新)
|
||||
timeRangeOptions: ['1个月', '3个月', '6个月'],
|
||||
timeRangeIndex: 0, // 默认选择1个月
|
||||
showTimeRangeDropdown: false, // 控制下拉菜单显示
|
||||
totalDuration: '125.5 小时',
|
||||
todayDuration: '8.2 小时',
|
||||
dataList: [
|
||||
{ date: '2024-02-07', description: '客户咨询录音', duration: '2.5 小时' },
|
||||
{ date: '2024-02-06', description: '销售洽谈录音', duration: '3.2 小时' },
|
||||
{ date: '2024-02-05', description: '培训录音', duration: '1.8 小时' },
|
||||
{ date: '2024-02-04', description: '会议录音', duration: '4.1 小时' },
|
||||
{ date: '2024-02-03', description: '客户反馈录音', duration: '2.9 小时' }
|
||||
]
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
// 页面渲染完成后,查询实际导航栏高度并更新位置
|
||||
this.$nextTick(() => {
|
||||
// 查询导航栏实际高度
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('.nav-bar').boundingClientRect((data) => {
|
||||
if (data && data.height) {
|
||||
// 使用实际高度
|
||||
const actualHeight = data.height; // 实际导航栏高度(px)
|
||||
// 转换为rpx:1px = 2rpx(在375px设计稿下)
|
||||
const actualHeightRpx = actualHeight * 2;
|
||||
const statusBarHeightRpx = this.statusBarHeight * 2;
|
||||
const totalHeight = statusBarHeightRpx + actualHeightRpx;
|
||||
// 稍微减小一点,确保紧贴
|
||||
const adjustedHeight = Math.max(totalHeight - 4, 0);
|
||||
this.$set(this, 'contentTop', adjustedHeight + 'rpx');
|
||||
console.log('[RecordingDuration] 使用实际导航栏高度:', actualHeight, 'px =', actualHeightRpx, 'rpx, 总高度:', totalHeight, 'rpx, 调整后:', adjustedHeight, 'rpx');
|
||||
} else {
|
||||
// 如果查询失败,使用默认计算
|
||||
const systemInfo = getSystemInfo();
|
||||
const statusBarHeight = systemInfo.statusBarHeight;
|
||||
const navbarHeight = 44;
|
||||
const statusBarHeightRpx = statusBarHeight * 2;
|
||||
const navbarHeightRpx = navbarHeight * 2;
|
||||
const totalNavbarHeight = statusBarHeightRpx + navbarHeightRpx;
|
||||
const adjustedHeight = Math.max(totalNavbarHeight - 4, 0);
|
||||
this.$set(this, 'contentTop', adjustedHeight + 'rpx');
|
||||
}
|
||||
}).exec();
|
||||
|
||||
// 查询底部 tabbar 实际高度(如果有)
|
||||
const queryTabbar = uni.createSelectorQuery().in(this);
|
||||
queryTabbar.select('.tabbar').boundingClientRect((tabbarData) => {
|
||||
if (tabbarData && tabbarData.height) {
|
||||
// 使用实际高度
|
||||
const tabbarHeight = tabbarData.height; // tabbar 实际高度(px)
|
||||
const tabbarHeightRpx = tabbarHeight * 2;
|
||||
// 稍微减小一点,确保紧贴
|
||||
const adjustedBottom = Math.max(tabbarHeightRpx - 4, 0);
|
||||
this.$set(this, 'contentBottom', adjustedBottom + 'rpx');
|
||||
console.log('[RecordingDuration] 使用实际tabbar高度:', tabbarHeight, 'px =', tabbarHeightRpx, 'rpx, 调整后:', adjustedBottom, 'rpx');
|
||||
} else {
|
||||
// 如果查询失败,使用默认值(无tabbar)
|
||||
this.$set(this, 'contentBottom', '0rpx');
|
||||
}
|
||||
}).exec();
|
||||
|
||||
// 延迟再次更新,确保DOM已渲染
|
||||
setTimeout(() => {
|
||||
// 再次查询并更新导航栏
|
||||
const query2 = uni.createSelectorQuery().in(this);
|
||||
query2.select('.nav-bar').boundingClientRect((data) => {
|
||||
if (data && data.height) {
|
||||
const actualHeight = data.height;
|
||||
const actualHeightRpx = actualHeight * 2;
|
||||
const statusBarHeightRpx = this.statusBarHeight * 2;
|
||||
const totalHeight = statusBarHeightRpx + actualHeightRpx;
|
||||
const adjustedHeight = Math.max(totalHeight - 4, 0);
|
||||
this.$set(this, 'contentTop', adjustedHeight + 'rpx');
|
||||
console.log('[RecordingDuration] 延迟更新导航栏高度:', actualHeight, 'px =', actualHeightRpx, 'rpx, 总高度:', totalHeight, 'rpx, 调整后:', adjustedHeight, 'rpx');
|
||||
}
|
||||
}).exec();
|
||||
|
||||
// 再次查询 tabbar 高度
|
||||
const queryTabbar2 = uni.createSelectorQuery().in(this);
|
||||
queryTabbar2.select('.tabbar').boundingClientRect((tabbarData) => {
|
||||
if (tabbarData && tabbarData.height) {
|
||||
const tabbarHeight = tabbarData.height;
|
||||
const tabbarHeightRpx = tabbarHeight * 2;
|
||||
const adjustedBottom = Math.max(tabbarHeightRpx - 4, 0);
|
||||
this.$set(this, 'contentBottom', adjustedBottom + 'rpx');
|
||||
console.log('[RecordingDuration] 延迟更新tabbar高度:', tabbarHeight, 'px =', tabbarHeightRpx, 'rpx, 调整后:', adjustedBottom, 'rpx');
|
||||
}
|
||||
}).exec();
|
||||
}, 200);
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
toggleTimeRangeDropdown() {
|
||||
this.showTimeRangeDropdown = !this.showTimeRangeDropdown;
|
||||
},
|
||||
closeTimeRangeDropdown() {
|
||||
this.showTimeRangeDropdown = false;
|
||||
},
|
||||
selectTimeRange(index) {
|
||||
this.timeRangeIndex = index;
|
||||
this.showTimeRangeDropdown = false;
|
||||
// 根据选择的时间范围重新加载数据
|
||||
this.loadData();
|
||||
},
|
||||
onRefresh() {
|
||||
// 刷新数据
|
||||
this.loadData();
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
},
|
||||
loadData() {
|
||||
// 根据 timeRangeIndex 加载对应时间范围的数据
|
||||
// 0 -> 1个月, 1 -> 3个月, 2 -> 6个月
|
||||
const months = this.timeRangeIndex === 0 ? 1 : (this.timeRangeIndex === 1 ? 3 : 6);
|
||||
console.log(`加载最近${months}个月的数据`);
|
||||
// TODO: 这里可以调用API加载数据
|
||||
// 示例:调用接口获取数据
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.feature-page {
|
||||
min-height: 100vh;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
background: #ffffff;
|
||||
border-bottom: 1rpx solid #e9ecef;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 88rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 36rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.content-scroll {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0; /* 先从顶部开始,通过内联样式动态设置 */
|
||||
bottom: 0; /* 先从底部开始,通过内联样式动态设置 */
|
||||
/* top和bottom值通过内联样式动态设置,覆盖上面的默认值 */
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.search-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 12rpx 30rpx;
|
||||
margin: 20rpx 30rpx;
|
||||
background-color: #F8F8FA;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #EFEFF2;
|
||||
}
|
||||
|
||||
.toolbar-picker-wrapper {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-width: 120rpx;
|
||||
max-width: 200rpx;
|
||||
flex-shrink: 1;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.toolbar-picker-view {
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
background-color: #F5F6FA;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.toolbar-picker-text {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.time-range-dropdown {
|
||||
position: absolute;
|
||||
top: calc(100% + 8rpx);
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.12);
|
||||
z-index: 101;
|
||||
overflow: hidden;
|
||||
border: 1rpx solid #EFEFF2;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
padding: 20rpx 24rpx;
|
||||
border-bottom: 1rpx solid #F3F4F6;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.dropdown-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.dropdown-item:active {
|
||||
background-color: #F9FAFB;
|
||||
}
|
||||
|
||||
.dropdown-item text {
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.dropdown-item-active {
|
||||
background-color: #F0F7FF;
|
||||
}
|
||||
|
||||
.dropdown-item-active text {
|
||||
color: #2A68FF;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.dropdown-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: transparent;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.toolbar-btn {
|
||||
padding: 0 12rpx;
|
||||
height: 56rpx;
|
||||
min-width: 56rpx;
|
||||
color: #2A68FF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.toolbar-btn text {
|
||||
color: #2A68FF;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
display: flex;
|
||||
margin: 20rpx 30rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-item:not(:last-child) {
|
||||
border-right: 1rpx solid #e9ecef;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
display: block;
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #007aff;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.chart-section, .data-list {
|
||||
margin: 20rpx 30rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #e9ecef;
|
||||
}
|
||||
|
||||
.chart-placeholder {
|
||||
padding: 80rpx 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
display: block;
|
||||
font-size: 48rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.placeholder-desc {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.list-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item-left {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-date {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.item-desc {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.item-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.item-duration {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #007aff;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user