994 lines
26 KiB
Vue
994 lines
26 KiB
Vue
<template>
|
||
<view class="statistics-container">
|
||
<!-- 移动设备顶部状态栏 -->
|
||
<view class="top_bar flex w-full" v-if="isMobile">
|
||
<view class="chat-header">
|
||
<view class="header-left" @click="goBack">
|
||
<i class="fas fa-arrow-left"></i>
|
||
</view>
|
||
<view class="header-title">考勤统计</view>
|
||
<view class="header-right" @click="showMoreOptions">
|
||
<i class="fas fa-ellipsis-v"></i>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 浏览器环境下的导航栏 -->
|
||
<view class="chat-header" v-else>
|
||
<view class="header-left" @click="goBack">
|
||
<i class="fas fa-arrow-left"></i>
|
||
</view>
|
||
<view class="header-title">考勤统计</view>
|
||
<view class="header-right" @click="showMoreOptions">
|
||
<i class="fas fa-ellipsis-v"></i>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 页面内容 -->
|
||
<scroll-view scroll-y class="statistics-content">
|
||
|
||
<!-- 导出报表 -->
|
||
<view class="export-card card">
|
||
<view class="export-title">导出报表</view>
|
||
<view class="exports">
|
||
<view class="btn-export" @click="exportReport"> 导出 </view>
|
||
<i class="fas fa-angle-right" style="font-size: 20rpx; color: var(--tab-inactive);position: relative;top: 4rpx;"></i>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 统计数据 -->
|
||
<view class="stats-card card">
|
||
<!-- Tabbar -->
|
||
<view class="stat-tabs">
|
||
<view
|
||
v-for="t in tabs"
|
||
:key="t.value"
|
||
class="stat-tab"
|
||
:class="{ active: statTab === t.value }"
|
||
@click="statTab = t.value"
|
||
>{{ t.label }}</view
|
||
>
|
||
</view>
|
||
|
||
<!-- 日统计(显示日历) -->
|
||
<view v-if="statTab === 'day'" class="tab-content">
|
||
<view class="calendar">
|
||
<view class="cal-title">
|
||
{{ today.getFullYear() }}年{{ today.getMonth() + 1 }}月
|
||
</view>
|
||
<view class="cal-week-head">
|
||
<text
|
||
v-for="w in ['日', '一', '二', '三', '四', '五', '六']"
|
||
:key="w"
|
||
>{{ w }}</text
|
||
>
|
||
</view>
|
||
<view class="cal-body">
|
||
<view
|
||
v-for="(week, weekIndex) in calendarWeeks"
|
||
:key="weekIndex"
|
||
class="cal-row"
|
||
>
|
||
<view
|
||
v-for="day in week"
|
||
:key="day.key"
|
||
class="cal-cell"
|
||
:class="{
|
||
empty: day.empty,
|
||
selected:
|
||
!day.empty && calendarSelected.includes(day.fullDate),
|
||
}"
|
||
@click="
|
||
!day.empty &&
|
||
selectDay({
|
||
fullDate: day.fullDate,
|
||
day: day.day,
|
||
month: day.month,
|
||
year: day.year,
|
||
})
|
||
"
|
||
>{{ day.empty ? "" : day.day }}</view
|
||
>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 选中日期的数据显示卡片 -->
|
||
<view v-if="selectedDayInfo" class="day-data-card">
|
||
<view class="day-data-header">
|
||
<view class="day-data-title">
|
||
<i class="fas fa-calendar-day"></i>
|
||
<text>{{ selectedDayInfo.year }}年{{ selectedDayInfo.month }}月{{ selectedDayInfo.day }}日</text>
|
||
</view>
|
||
<view class="day-data-subtitle">考勤详情</view>
|
||
</view>
|
||
|
||
<view class="day-data-content">
|
||
<view
|
||
class="day-data-item"
|
||
v-for="(item, index) in dailyStats"
|
||
:key="index"
|
||
>
|
||
<view class="day-data-icon" :class="item.status || 'default'">
|
||
<i :class="item.icon"></i>
|
||
</view>
|
||
<view class="day-data-info">
|
||
<view class="day-data-label">{{ item.title }}</view>
|
||
<view class="day-data-value" :class="item.status || 'default'">
|
||
{{ item.value }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 周统计 -->
|
||
<view v-if="statTab === 'week'" class="tab-content">
|
||
<view class="bar-tabs">
|
||
<view
|
||
class="bar-tab"
|
||
v-for="(item, index) in weekTabs"
|
||
:key="item.value"
|
||
:class="{ active: weekTab === item.value }"
|
||
@click="weekTab = item.value"
|
||
>{{ item.label }}</view
|
||
>
|
||
</view>
|
||
<view class="count-list">
|
||
<view
|
||
class="count-item"
|
||
v-for="(item, idx) in (weekStats[weekTab] || [])"
|
||
:key="idx"
|
||
>
|
||
<view class="c-value">{{ item.value }}</view>
|
||
<view class="c-title">{{ item.title }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 月统计 -->
|
||
<view v-if="statTab === 'month'" class="tab-content">
|
||
<view class="month-grid">
|
||
<view
|
||
class="month-item"
|
||
v-for="(item, index) in monthTabs"
|
||
:key="item.value"
|
||
:class="{ active: monthTab === item.value }"
|
||
@click="monthTab = item.value"
|
||
>
|
||
<view class="month-label">{{ item.label }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="count-list">
|
||
<view
|
||
class="count-item"
|
||
v-for="(item, idx) in (monthStats[monthTab] || [])"
|
||
:key="idx"
|
||
>
|
||
<view class="c-value">{{ item.value }}</view>
|
||
<view class="c-title">{{ item.title }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
const today = new Date();
|
||
return {
|
||
today: today,
|
||
tabs: [
|
||
{ label: "日统计", value: "day" },
|
||
{ label: "周统计", value: "week" },
|
||
{ label: "月统计", value: "month" },
|
||
],
|
||
statTab: "day",
|
||
calendarSelected: [
|
||
`${today.getFullYear()}-${String(today.getMonth() + 1).padStart(
|
||
2,
|
||
"0"
|
||
)}-${String(today.getDate()).padStart(2, "0")}`,
|
||
],
|
||
weekTabs: [
|
||
{ label: "第1周", value: "1" },
|
||
{ label: "第2周", value: "2" },
|
||
{ label: "第3周", value: "3" },
|
||
{ label: "第4周", value: "4" },
|
||
],
|
||
weekTab: "1",
|
||
monthTabs: Array.from({ length: 12 }, (_, i) => ({
|
||
label: `${i + 1}月`,
|
||
value: String(i + 1),
|
||
})),
|
||
monthTab: String(today.getMonth() + 1),
|
||
baseStat: [
|
||
{ title: "平均工时", value: "7.8h" },
|
||
{ title: "迟到次数", value: "1" },
|
||
{ title: "早退次数", value: "0" },
|
||
{ title: "缺卡次数", value: "0" },
|
||
{ title: "旷工次数", value: "0" },
|
||
{ title: "外勤次数", value: "2" },
|
||
{ title: "加班时长", value: "4h" },
|
||
{ title: "调休时长", value: "2h" },
|
||
],
|
||
selectedDayData: null, // 选中日期的数据
|
||
selectedDayInfo: null, // 选中日期的基本信息
|
||
};
|
||
},
|
||
computed: {
|
||
weekStats() {
|
||
try {
|
||
return {
|
||
"1": this.baseStat || [],
|
||
"2": (this.baseStat || []).map((item, i) =>
|
||
i === 1 ? { ...item, value: "0" } : item
|
||
),
|
||
"3": (this.baseStat || []).map((item, i) =>
|
||
i === 3 ? { ...item, value: "1" } : item
|
||
),
|
||
"4": (this.baseStat || []).map((item, i) =>
|
||
i === 5 ? { ...item, value: "3" } : item
|
||
),
|
||
};
|
||
} catch (error) {
|
||
console.error('周统计数据生成错误:', error);
|
||
return {};
|
||
}
|
||
},
|
||
monthStats() {
|
||
try {
|
||
const stats = {};
|
||
(this.monthTabs || []).forEach((_, i) => {
|
||
stats[String(i + 1)] = (this.baseStat || []).map((item) => ({
|
||
...item,
|
||
value: String(
|
||
Math.floor(Math.random() * 3) +
|
||
(item.value.includes("h") ? "h" : "")
|
||
),
|
||
}));
|
||
});
|
||
return stats;
|
||
} catch (error) {
|
||
console.error('月统计数据生成错误:', error);
|
||
return {};
|
||
}
|
||
},
|
||
// 日历相关计算属性
|
||
days() {
|
||
const d = new Date(
|
||
this.today.getFullYear(),
|
||
this.today.getMonth() + 1,
|
||
0
|
||
).getDate();
|
||
return Array.from({ length: d }, (_, i) => i + 1);
|
||
},
|
||
firstDay() {
|
||
return new Date(
|
||
this.today.getFullYear(),
|
||
this.today.getMonth(),
|
||
1
|
||
).getDay();
|
||
},
|
||
calendarWeeks() {
|
||
try {
|
||
const year = this.today.getFullYear();
|
||
const month = this.today.getMonth();
|
||
const firstDay = new Date(year, month, 1).getDay();
|
||
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
||
|
||
const weeks = [];
|
||
let currentWeek = [];
|
||
|
||
// 添加空白日期(上个月的末尾几天)
|
||
for (let i = 0; i < firstDay; i++) {
|
||
currentWeek.push({
|
||
key: `empty-${i}`,
|
||
empty: true,
|
||
day: "",
|
||
fullDate: "",
|
||
month: month,
|
||
year: year,
|
||
});
|
||
}
|
||
|
||
// 添加当前月的日期
|
||
for (let day = 1; day <= daysInMonth; day++) {
|
||
const fullDate = `${year}-${String(month + 1).padStart(
|
||
2,
|
||
"0"
|
||
)}-${String(day).padStart(2, "0")}`;
|
||
currentWeek.push({
|
||
key: `day-${day}`,
|
||
empty: false,
|
||
day: day,
|
||
fullDate: fullDate,
|
||
month: month + 1,
|
||
year: year,
|
||
});
|
||
|
||
// 如果一周满了(7天),开始新的一周
|
||
if (currentWeek.length === 7) {
|
||
weeks.push([...currentWeek]);
|
||
currentWeek = [];
|
||
}
|
||
}
|
||
|
||
// 如果最后一周不满7天,用空白日期填充
|
||
while (currentWeek.length > 0 && currentWeek.length < 7) {
|
||
currentWeek.push({
|
||
key: `empty-end-${currentWeek.length}`,
|
||
empty: true,
|
||
day: "",
|
||
fullDate: "",
|
||
month: month,
|
||
year: year,
|
||
});
|
||
}
|
||
|
||
// 如果还有未完成的周,添加到结果中
|
||
if (currentWeek.length > 0) {
|
||
weeks.push(currentWeek);
|
||
}
|
||
|
||
return weeks;
|
||
} catch (error) {
|
||
console.error('日历生成错误:', error);
|
||
return [];
|
||
}
|
||
},
|
||
isMobile() {
|
||
return getApp().globalData.isMobile;
|
||
},
|
||
// 生成每日数据
|
||
dailyStats() {
|
||
if (!this.selectedDayInfo) return [];
|
||
|
||
const { year, month, day } = this.selectedDayInfo;
|
||
const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||
|
||
// 模拟不同日期的不同数据
|
||
const randomSeed = year * 10000 + month * 100 + day;
|
||
const random = (seed) => {
|
||
const x = Math.sin(seed) * 10000;
|
||
return x - Math.floor(x);
|
||
};
|
||
|
||
return [
|
||
{
|
||
title: "上班时间",
|
||
value: `${String(Math.floor(random(randomSeed) * 2) + 8).padStart(2, '0')}:${String(Math.floor(random(randomSeed + 1) * 60)).padStart(2, '0')}`,
|
||
icon: "fas fa-clock"
|
||
},
|
||
{
|
||
title: "下班时间",
|
||
value: `${String(Math.floor(random(randomSeed + 2) * 2) + 17).padStart(2, '0')}:${String(Math.floor(random(randomSeed + 3) * 60)).padStart(2, '0')}`,
|
||
icon: "fas fa-clock"
|
||
},
|
||
{
|
||
title: "迟到状态",
|
||
value: random(randomSeed + 5) > 0.8 ? "迟到" : "正常",
|
||
icon: random(randomSeed + 5) > 0.8 ? "fas fa-exclamation-triangle" : "fas fa-check-circle",
|
||
status: random(randomSeed + 5) > 0.8 ? "warning" : "success"
|
||
},
|
||
{
|
||
title: "早退状态",
|
||
value: random(randomSeed + 6) > 0.9 ? "早退" : "正常",
|
||
icon: random(randomSeed + 6) > 0.9 ? "fas fa-exclamation-triangle" : "fas fa-check-circle",
|
||
status: random(randomSeed + 6) > 0.9 ? "warning" : "success"
|
||
},
|
||
{
|
||
title: "工作时长",
|
||
value: `${(random(randomSeed + 4) * 4 + 6).toFixed(1)}h`,
|
||
icon: "fas fa-hourglass-half"
|
||
},
|
||
{
|
||
title: "外勤次数",
|
||
value: Math.floor(random(randomSeed + 7) * 3).toString(),
|
||
icon: "fas fa-map-marker-alt"
|
||
},
|
||
{
|
||
title: "加班时长",
|
||
value: random(randomSeed + 8) > 0.6 ? `${(random(randomSeed + 8) * 3).toFixed(1)}h` : "0h",
|
||
icon: "fas fa-moon"
|
||
},
|
||
{
|
||
title: "调休时长",
|
||
value: random(randomSeed + 9) > 0.7 ? `${(random(randomSeed + 9) * 2).toFixed(1)}h` : "0h",
|
||
icon: "fas fa-calendar-alt"
|
||
},
|
||
];
|
||
},
|
||
},
|
||
mounted() {
|
||
console.log('统计页面初始化');
|
||
console.log('当前月份:', this.today.getMonth() + 1);
|
||
console.log('基础数据:', this.baseStat);
|
||
console.log('周标签:', this.weekTabs);
|
||
console.log('月标签:', this.monthTabs);
|
||
console.log('当前周标签值:', this.weekTab, typeof this.weekTab);
|
||
console.log('当前月标签值:', this.monthTab, typeof this.monthTab);
|
||
console.log('周统计数据:', this.weekStats);
|
||
console.log('月统计数据:', this.monthStats);
|
||
console.log('周统计键:', Object.keys(this.weekStats));
|
||
console.log('月统计键:', Object.keys(this.monthStats));
|
||
console.log('周统计访问测试:', this.weekStats[this.weekTab]);
|
||
console.log('月统计访问测试:', this.monthStats[this.monthTab]);
|
||
|
||
// 初始化默认选中今天
|
||
this.selectedDayInfo = {
|
||
year: this.today.getFullYear(),
|
||
month: this.today.getMonth() + 1,
|
||
day: this.today.getDate(),
|
||
fullDate: `${this.today.getFullYear()}-${String(this.today.getMonth() + 1).padStart(2, '0')}-${String(this.today.getDate()).padStart(2, '0')}`
|
||
};
|
||
console.log('默认选中今天:', this.selectedDayInfo);
|
||
},
|
||
methods: {
|
||
selectDay(day) {
|
||
this.calendarSelected = [day.fullDate];
|
||
this.selectedDayInfo = {
|
||
year: day.year,
|
||
month: day.month,
|
||
day: day.day,
|
||
fullDate: day.fullDate
|
||
};
|
||
console.log('选择日期:', day);
|
||
console.log('选中日期信息:', this.selectedDayInfo);
|
||
},
|
||
exportReport() {
|
||
uni.showToast({ title: "导出功能暂未开放" });
|
||
},
|
||
goBack() {
|
||
uni.navigateBack();
|
||
},
|
||
showMoreOptions() {
|
||
uni.showActionSheet({
|
||
itemList: ['刷新数据', '导出报表', '设置'],
|
||
success: (res) => {
|
||
if (res.tapIndex === 0) {
|
||
uni.showToast({ title: '刷新成功' });
|
||
} else if (res.tapIndex === 1) {
|
||
this.exportReport();
|
||
} else if (res.tapIndex === 2) {
|
||
uni.showToast({ title: '设置功能暂未开放' });
|
||
}
|
||
}
|
||
});
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
/* 移动设备顶部状态栏 */
|
||
.top_bar {
|
||
background: var(--gradient-primary);
|
||
box-shadow: var(--shadow-lg);
|
||
z-index: 9999;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: calc(var(--status-bar-height) + 88rpx);
|
||
display: flex;
|
||
align-items: flex-end;
|
||
padding-top: var(--status-bar-height);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 支持安全区域的设备 */
|
||
@supports (padding: max(0px)) {
|
||
.top_bar {
|
||
height: calc(var(--status-bar-height) + 88rpx + env(safe-area-inset-top));
|
||
padding-top: calc(var(--status-bar-height) + env(safe-area-inset-top));
|
||
}
|
||
|
||
.top_bar + .statistics-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx + env(safe-area-inset-top));
|
||
}
|
||
}
|
||
|
||
/* 顶部导航栏 */
|
||
.chat-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
height: 88rpx;
|
||
background-color: var(--surface);
|
||
border-bottom: 1rpx solid var(--border);
|
||
padding: 0 20rpx;
|
||
box-sizing: border-box;
|
||
box-shadow: var(--shadow);
|
||
}
|
||
|
||
/* 移动设备下的导航栏样式 */
|
||
.top_bar .chat-header {
|
||
background: transparent;
|
||
border-bottom: none;
|
||
box-shadow: none;
|
||
width: 100%;
|
||
height: 88rpx;
|
||
padding: 0 20rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.top_bar .header-title {
|
||
color: var(--white);
|
||
font-weight: 600;
|
||
font-size: 36rpx;
|
||
}
|
||
|
||
.top_bar .header-left i,
|
||
.top_bar .header-right i {
|
||
color: var(--white);
|
||
font-size: 40rpx;
|
||
}
|
||
|
||
.header-left,
|
||
.header-right {
|
||
width: 80rpx;
|
||
height: 88rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background-color 0.2s ease;
|
||
}
|
||
|
||
/* 移动设备下的按钮悬停效果 */
|
||
.top_bar .header-left:active,
|
||
.top_bar .header-right:active {
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.header-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: var(--title-color);
|
||
}
|
||
|
||
.header-icon {
|
||
font-size: 36rpx;
|
||
color: var(--text-color);
|
||
padding: 10rpx;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.header-icon:active {
|
||
background: var(--hover-bg);
|
||
transform: scale(0.95);
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
/* 移动设备下为内容添加顶部间距 */
|
||
.top_bar + .statistics-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx);
|
||
}
|
||
|
||
/* 浏览器环境下为内容添加顶部间距 */
|
||
.chat-header + .statistics-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx);
|
||
}
|
||
|
||
.statistics-container {
|
||
background: #f7f8fa;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.statistics-content {
|
||
padding: 32rpx 0;
|
||
min-height: calc(100vh - 88rpx);
|
||
}
|
||
|
||
.card {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 16rpx 0 rgba(0, 0, 0, 0.04);
|
||
margin: 0 32rpx 32rpx;
|
||
padding: 32rpx;
|
||
}
|
||
.export-card {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
.export-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
}
|
||
.btn-export {
|
||
// background: #3c9cff;
|
||
color: var(--tab-inactive);
|
||
font-size: 28rpx;
|
||
border: none;
|
||
// padding: 4rpx 40rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.exports {
|
||
display: flex;
|
||
align-items: center;
|
||
.btn-export {
|
||
margin-right: 16rpx;
|
||
}
|
||
}
|
||
}
|
||
.stats-card {
|
||
.stat-tabs {
|
||
display: flex;
|
||
margin-bottom: 32rpx;
|
||
.stat-tab {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
color: var(--text-muted);
|
||
padding-bottom: 16rpx;
|
||
border-bottom: 4rpx solid transparent;
|
||
transition: all 0.2s;
|
||
&.active {
|
||
color: var(--primary-color);
|
||
font-weight: 600;
|
||
border-color: var(--primary-color);
|
||
}
|
||
}
|
||
}
|
||
.tab-content {
|
||
margin-top: 16rpx;
|
||
}
|
||
// 月统计网格布局
|
||
.month-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 12rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
.month-item {
|
||
background: var(--gray-lighter);
|
||
border-radius: 12rpx;
|
||
padding: 20rpx 12rpx;
|
||
text-align: center;
|
||
border: 1rpx solid var(--border-light);
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
|
||
.month-label {
|
||
font-size: 26rpx;
|
||
color: var(--text-secondary);
|
||
font-weight: 500;
|
||
}
|
||
|
||
&.active {
|
||
background: var(--primary-color);
|
||
border-color: var(--primary-color);
|
||
box-shadow: var(--shadow-md);
|
||
transform: translateY(-2rpx);
|
||
|
||
.month-label {
|
||
color: var(--white);
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
&:not(.active):active {
|
||
background: var(--primary-light);
|
||
transform: scale(0.98);
|
||
|
||
.month-label {
|
||
color: var(--white);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.bar-tabs {
|
||
display: flex;
|
||
background: var(--gray-lighter);
|
||
border-radius: 12rpx;
|
||
padding: 6rpx;
|
||
margin-bottom: 24rpx;
|
||
position: relative;
|
||
|
||
.bar-tab {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
color: var(--text-secondary);
|
||
padding: 16rpx 12rpx;
|
||
border-radius: 8rpx;
|
||
margin: 0 2rpx;
|
||
background: transparent;
|
||
transition: all 0.3s ease;
|
||
position: relative;
|
||
font-weight: 500;
|
||
|
||
&.active {
|
||
color: var(--primary-color);
|
||
background: var(--surface);
|
||
font-weight: 600;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
transform: translateY(-1rpx);
|
||
}
|
||
|
||
&:not(.active):active {
|
||
background: rgba(60, 156, 255, 0.1);
|
||
}
|
||
}
|
||
}
|
||
|
||
.bar-tabs-scroll {
|
||
background: #f8f9fa;
|
||
border-radius: 12rpx;
|
||
padding: 6rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
.bar-scroll {
|
||
white-space: nowrap;
|
||
|
||
.bar-tab {
|
||
display: inline-block;
|
||
min-width: 120rpx;
|
||
margin: 0 4rpx;
|
||
padding: 16rpx 20rpx;
|
||
text-align: center;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
border-radius: 8rpx;
|
||
background: transparent;
|
||
transition: all 0.3s ease;
|
||
font-weight: 500;
|
||
|
||
&.active {
|
||
color: #3c9cff;
|
||
background: #fff;
|
||
font-weight: 600;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
transform: translateY(-1rpx);
|
||
}
|
||
|
||
&:not(.active):active {
|
||
background: rgba(60, 156, 255, 0.1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 日统计数据显示卡片
|
||
.day-data-card {
|
||
margin-top: 24rpx;
|
||
background: var(--surface);
|
||
border-radius: 16rpx;
|
||
box-shadow: var(--shadow-md);
|
||
overflow: hidden;
|
||
border: 1rpx solid var(--border);
|
||
|
||
.day-data-header {
|
||
background: var(--gradient-primary);
|
||
padding: 32rpx 24rpx;
|
||
color: var(--white);
|
||
|
||
.day-data-title {
|
||
display: flex;
|
||
align-items: center;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
margin-bottom: 8rpx;
|
||
color: var(--white);
|
||
|
||
i {
|
||
margin-right: 12rpx;
|
||
font-size: 28rpx;
|
||
color: var(--white);
|
||
}
|
||
}
|
||
|
||
.day-data-subtitle {
|
||
font-size: 24rpx;
|
||
opacity: 0.9;
|
||
color: var(--white);
|
||
}
|
||
}
|
||
|
||
.day-data-content {
|
||
padding: 24rpx;
|
||
background: var(--surface);
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: space-between;
|
||
|
||
.day-data-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx 16rpx;
|
||
width: 48%;
|
||
margin-bottom: 16rpx;
|
||
background: var(--gray-lighter);
|
||
border-radius: 12rpx;
|
||
border: 1rpx solid var(--border-light);
|
||
box-sizing: border-box;
|
||
|
||
&:nth-child(odd) {
|
||
margin-right: 2%;
|
||
}
|
||
|
||
&:nth-child(even) {
|
||
margin-left: 2%;
|
||
}
|
||
|
||
.day-data-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 12rpx;
|
||
flex-shrink: 0;
|
||
|
||
i {
|
||
font-size: 20rpx;
|
||
}
|
||
|
||
&.default {
|
||
background: var(--gray-light);
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
&.success {
|
||
background: var(--success-light);
|
||
color: var(--success);
|
||
}
|
||
|
||
&.warning {
|
||
background: var(--warning-light);
|
||
color: var(--warning);
|
||
}
|
||
}
|
||
|
||
.day-data-info {
|
||
flex: 1;
|
||
min-width: 0;
|
||
|
||
.day-data-label {
|
||
font-size: 22rpx;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 6rpx;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.day-data-value {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
|
||
&.default {
|
||
color: var(--text-color);
|
||
}
|
||
|
||
&.success {
|
||
color: var(--success);
|
||
}
|
||
|
||
&.warning {
|
||
color: var(--warning);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.count-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
margin-top: 16rpx;
|
||
justify-content: space-between;
|
||
.count-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
width: 48%;
|
||
margin-bottom: 16rpx;
|
||
padding: 24rpx;
|
||
background: var(--gray-lighter);
|
||
border-radius: 12rpx;
|
||
box-sizing: border-box;
|
||
border: 1rpx solid var(--border-light);
|
||
.c-title {
|
||
color: var(--text-secondary);
|
||
margin-bottom: 8rpx;
|
||
font-size: 20rpx;
|
||
}
|
||
.c-value {
|
||
color: var(--text-color);
|
||
font-size: 40rpx;
|
||
font-weight: 500;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 日历样式 */
|
||
.calendar {
|
||
background: var(--surface);
|
||
border-radius: 12rpx;
|
||
padding: 24rpx;
|
||
margin-top: 16rpx;
|
||
border: 1rpx solid var(--border);
|
||
box-shadow: var(--shadow);
|
||
|
||
.cal-title {
|
||
text-align: center;
|
||
font-weight: 600;
|
||
font-size: 32rpx;
|
||
color: var(--title-color);
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.cal-week-head {
|
||
display: flex;
|
||
margin-bottom: 16rpx;
|
||
|
||
text {
|
||
flex: 1;
|
||
text-align: center;
|
||
font-size: 26rpx;
|
||
color: var(--text-muted);
|
||
font-weight: 500;
|
||
padding: 12rpx 0;
|
||
}
|
||
}
|
||
|
||
.cal-body {
|
||
.cal-row {
|
||
display: flex;
|
||
margin-bottom: 8rpx;
|
||
|
||
.cal-cell {
|
||
flex: 1;
|
||
height: 64rpx;
|
||
line-height: 64rpx;
|
||
text-align: center;
|
||
border-radius: 8rpx;
|
||
margin: 0 4rpx;
|
||
background: var(--gray-lighter);
|
||
font-size: 28rpx;
|
||
color: var(--text-color);
|
||
transition: all 0.2s ease;
|
||
position: relative;
|
||
|
||
&:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
&.selected {
|
||
background: var(--primary-color);
|
||
color: var(--white);
|
||
font-weight: 600;
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
&.empty {
|
||
background: transparent;
|
||
pointer-events: none;
|
||
}
|
||
|
||
&:not(.empty):not(.selected):hover {
|
||
background: var(--primary-light);
|
||
color: var(--white);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
:deep() {
|
||
.uni-scroll-view {
|
||
overflow: hidden !important;
|
||
}
|
||
}
|
||
</style>
|