1048 lines
24 KiB
Vue
1048 lines
24 KiB
Vue
<template>
|
||
<view class="workbench">
|
||
<!-- 移动设备顶部状态栏 -->
|
||
<view class="top_bar flex w-full" v-if="isMobile">
|
||
<view class="chat-header">
|
||
<view class="header-left">
|
||
<i class="fas fa-bell header-icon" @click="handleNotification"></i>
|
||
</view>
|
||
<view class="header-title">工作台</view>
|
||
<view class="header-right">
|
||
<i class="fas fa-search header-icon" @click="handleSearch"></i>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 浏览器环境顶部导航栏 -->
|
||
<view class="unified-header" v-else>
|
||
<view class="header-content">
|
||
<view class="header-left">
|
||
<i class="fas fa-bell header-icon" @click="handleNotification"></i>
|
||
</view>
|
||
<view class="header-title">工作台</view>
|
||
<view class="header-right">
|
||
<i class="fas fa-search header-icon" @click="handleSearch"></i>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 页面内容 -->
|
||
<scroll-view scroll-y class="unified-content">
|
||
<!-- 欢迎和天气模块 -->
|
||
<view class="welcome-section">
|
||
<view class="welcome-header">
|
||
<view class="welcome-info">
|
||
<text class="welcome-text"
|
||
>{{ getGreeting() }},{{ userName }}</text
|
||
>
|
||
<text class="welcome-date">{{ currentDate }}</text>
|
||
</view>
|
||
<view class="weather-card">
|
||
<view class="weather-icon">
|
||
<i class="fas fa-sun weather-icon-fa"></i>
|
||
</view>
|
||
<view class="weather-info">
|
||
<text class="weather-temp">{{ weather.temperature }}°</text>
|
||
<text class="weather-desc">{{ weather.description }}</text>
|
||
<text class="weather-location">{{ weather.location }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 工作状态卡片 -->
|
||
<view class="status-card">
|
||
<view class="status-header">
|
||
<text class="status-title">今日工作状态</text>
|
||
<view class="status-indicator" :class="workStatus">
|
||
<text class="status-text">{{ workStatusText }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="status-content">
|
||
<view class="status-item">
|
||
<text class="status-label">上班时间</text>
|
||
<text class="status-value">{{ workTime }}</text>
|
||
</view>
|
||
<view class="status-item">
|
||
<text class="status-label">工作时长</text>
|
||
<text class="status-value">{{ workDuration }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 数据统计 -->
|
||
<view class="stats-section">
|
||
<view class="stats-grid">
|
||
<view class="stat-card pending" @click="goToApproval">
|
||
<view class="stat-icon">
|
||
<i class="fas fa-clipboard-list stat-icon-fa"></i>
|
||
</view>
|
||
<view class="stat-content">
|
||
<text class="stat-number">{{ pendingApproval }}</text>
|
||
<text class="stat-label">待审批</text>
|
||
</view>
|
||
</view>
|
||
<view class="stat-card tasks" @click="goToTasks">
|
||
<view class="stat-icon">
|
||
<i class="fas fa-check-circle stat-icon-fa"></i>
|
||
</view>
|
||
<view class="stat-content">
|
||
<text class="stat-number">{{ completedTasks }}</text>
|
||
<text class="stat-label">已完成</text>
|
||
</view>
|
||
</view>
|
||
<view class="stat-card money" @click="goToReimbursement">
|
||
<view class="stat-icon">
|
||
<i class="fas fa-money-bill-wave stat-icon-fa"></i>
|
||
</view>
|
||
<view class="stat-content">
|
||
<text class="stat-number">¥{{ reimbursementAmount }}</text>
|
||
<text class="stat-label">本月报销</text>
|
||
</view>
|
||
</view>
|
||
<view class="stat-card attendance" @click="goToAttendance">
|
||
<view class="stat-icon">
|
||
<i class="fas fa-clock stat-icon-fa"></i>
|
||
</view>
|
||
<view class="stat-content">
|
||
<text class="stat-number">{{ attendanceRate }}%</text>
|
||
<text class="stat-label">出勤率</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 快捷功能 -->
|
||
<view class="functions-section">
|
||
<view class="section-header">
|
||
<text class="section-title">快捷功能</text>
|
||
<text class="more-btn" @click="showAllFunctions">查看全部</text>
|
||
</view>
|
||
<view class="functions-grid">
|
||
<view
|
||
class="function-card"
|
||
v-for="(action, index) in quickActions"
|
||
:key="index"
|
||
@click="handleQuickAction(action)"
|
||
>
|
||
<view
|
||
class="function-icon"
|
||
:style="{ background: action.gradient }"
|
||
>
|
||
<i :class="action.iconClass" class="function-icon-fa"></i>
|
||
</view>
|
||
<text class="function-name">{{ action.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 最近动态 -->
|
||
<view class="recent-section">
|
||
<view class="section-header">
|
||
<text class="section-title">最近动态</text>
|
||
</view>
|
||
<view class="recent-list">
|
||
<view
|
||
class="recent-item"
|
||
v-for="(item, index) in recentActivities"
|
||
:key="index"
|
||
@click="handleRecentItem(item)"
|
||
>
|
||
<view
|
||
class="recent-icon"
|
||
:style="{ background: item.color + '20' }"
|
||
>
|
||
<i :class="item.iconClass" class="recent-icon-fa"></i>
|
||
</view>
|
||
<view class="recent-content">
|
||
<text class="recent-title">{{ item.title }}</text>
|
||
<text class="recent-desc">{{ item.description }}</text>
|
||
<text class="recent-time">{{ item.time }}</text>
|
||
</view>
|
||
<view class="recent-arrow">
|
||
<i class="fas fa-chevron-right arrow-icon"></i>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { ref, reactive, computed } from "vue";
|
||
import { useAuthStore } from "../../src/store/authStore.js";
|
||
|
||
export default {
|
||
setup() {
|
||
const authStore = useAuthStore();
|
||
|
||
// 用户信息 - 从 Pinia store 获取
|
||
const userInfo = computed(() => {
|
||
return (
|
||
authStore.userInfo || {
|
||
nickname: "未登录",
|
||
name: "未登录",
|
||
department: "未知部门",
|
||
dept: { name: "未知部门" },
|
||
employeeId: "N/A",
|
||
avatar: "static\\imgs\\default_avatar.png",
|
||
attendanceRate: 0,
|
||
completedTasks: 0,
|
||
pendingAmount: "0",
|
||
}
|
||
);
|
||
});
|
||
|
||
// 登录状态
|
||
const isLogin = computed(() => {
|
||
return authStore.isAuthenticated;
|
||
});
|
||
|
||
// 设备检测
|
||
const isMobile = computed(() => {
|
||
return getApp().globalData.isMobile;
|
||
});
|
||
|
||
// 用户信息
|
||
const userName = authStore.userInfo?.nickname || '未登录';
|
||
|
||
// 获取当前日期,格式:2024年10月15日 星期二
|
||
function getFormattedDate() {
|
||
const now = new Date();
|
||
const year = now.getFullYear();
|
||
const month = now.getMonth() + 1;
|
||
const day = now.getDate();
|
||
const weekDays = [
|
||
"星期日",
|
||
"星期一",
|
||
"星期二",
|
||
"星期三",
|
||
"星期四",
|
||
"星期五",
|
||
"星期六",
|
||
];
|
||
const weekDay = weekDays[now.getDay()];
|
||
return `${year}年${month}月${day}日 ${weekDay}`;
|
||
}
|
||
const currentDate = ref(getFormattedDate());
|
||
|
||
// 工作状态
|
||
const workStatus = ref("working");
|
||
const workStatusText = ref("工作中");
|
||
const workTime = ref("09:00");
|
||
const workDuration = ref("6小时30分");
|
||
|
||
// 统计数据
|
||
const unreadCount = ref(3);
|
||
const pendingApproval = ref(3);
|
||
const completedTasks = ref(12);
|
||
const reimbursementAmount = ref("2,580");
|
||
const attendanceRate = ref(98);
|
||
|
||
// 天气信息
|
||
const weather = reactive({
|
||
temperature: 22,
|
||
description: "晴朗",
|
||
location: "北京市",
|
||
icon: "fas fa-sun",
|
||
});
|
||
|
||
// 快捷功能数据
|
||
const quickActions = reactive([
|
||
{
|
||
iconClass: "fas fa-tasks",
|
||
label: "任务管理",
|
||
action: "tasks",
|
||
gradient: "linear-gradient(135deg, #3498db, #5dade2)",
|
||
},
|
||
{
|
||
iconClass: "fas fa-calendar-alt",
|
||
label: "请假申请",
|
||
action: "leave",
|
||
gradient: "linear-gradient(135deg, #ef4444, #f87171)",
|
||
},
|
||
{
|
||
iconClass: "fas fa-receipt",
|
||
label: "报销提交",
|
||
action: "reimbursement",
|
||
gradient: "linear-gradient(135deg, #10b981, #34d399)",
|
||
},
|
||
{
|
||
iconClass: "fas fa-clock",
|
||
label: "考勤打卡",
|
||
action: "checkin",
|
||
gradient: "linear-gradient(135deg, #3b82f6, #60a5fa)",
|
||
},
|
||
{
|
||
iconClass: "fas fa-building",
|
||
label: "会议预订",
|
||
action: "meeting",
|
||
gradient: "linear-gradient(135deg, #8b5cf6, #a78bfa)",
|
||
},
|
||
{
|
||
iconClass: "fas fa-users",
|
||
label: "客户管理",
|
||
action: "customer",
|
||
gradient: "linear-gradient(135deg, #f59e0b, #fbbf24)",
|
||
},
|
||
{
|
||
iconClass: "fas fa-chart-bar",
|
||
label: "工作报告",
|
||
action: "report",
|
||
gradient: "linear-gradient(135deg, #06b6d4, #22d3ee)",
|
||
},
|
||
]);
|
||
|
||
// 最近动态数据
|
||
const recentActivities = reactive([
|
||
{
|
||
iconClass: "fas fa-check-circle",
|
||
title: "请假申请已通过",
|
||
description: "您的年假申请已获得部门经理批准",
|
||
time: "2小时前",
|
||
color: "#10b981",
|
||
},
|
||
{
|
||
iconClass: "fas fa-money-bill-wave",
|
||
title: "报销到账通知",
|
||
description: "差旅费报销 ¥1,200 已到账",
|
||
time: "昨天",
|
||
color: "#3b82f6",
|
||
},
|
||
{
|
||
iconClass: "fas fa-calendar-check",
|
||
title: "会议提醒",
|
||
description: "项目评审会议将在30分钟后开始",
|
||
time: "3小时前",
|
||
color: "#f59e0b",
|
||
},
|
||
{
|
||
iconClass: "fas fa-exclamation-triangle",
|
||
title: "考勤异常",
|
||
description: "今日下班打卡时间异常,请确认",
|
||
time: "昨天",
|
||
color: "#ef4444",
|
||
},
|
||
]);
|
||
|
||
// 方法
|
||
const handleSearch = () => {
|
||
uni.showToast({
|
||
title: "搜索功能",
|
||
icon: "none",
|
||
});
|
||
};
|
||
|
||
const handleNotification = () => {
|
||
uni.switchTab({
|
||
url: "/pages/message/message",
|
||
});
|
||
};
|
||
|
||
const goToApproval = () => {
|
||
uni.showToast({
|
||
title: "跳转审批列表",
|
||
icon: "none",
|
||
});
|
||
};
|
||
|
||
const goToTasks = () => {
|
||
uni.showToast({
|
||
title: "跳转任务列表",
|
||
icon: "none",
|
||
});
|
||
};
|
||
|
||
const goToAttendance = () => {
|
||
uni.showToast({
|
||
title: "跳转考勤详情",
|
||
icon: "none",
|
||
});
|
||
};
|
||
|
||
const goToReimbursement = () => {
|
||
uni.showToast({
|
||
title: "跳转报销进度",
|
||
icon: "none",
|
||
});
|
||
};
|
||
|
||
const showAllFunctions = () => {
|
||
uni.switchTab({
|
||
url: "/pages/function/function",
|
||
});
|
||
};
|
||
|
||
const handleQuickAction = (action) => {
|
||
switch (action.action) {
|
||
case "tasks":
|
||
uni.navigateTo({
|
||
url: "/pages/tasks/index",
|
||
});
|
||
break;
|
||
case "leave":
|
||
uni.showToast({
|
||
title: "请假申请功能开发中",
|
||
icon: "none",
|
||
});
|
||
break;
|
||
case "reimbursement":
|
||
uni.showToast({
|
||
title: "报销提交功能开发中",
|
||
icon: "none",
|
||
});
|
||
break;
|
||
case "checkin":
|
||
uni.showToast({
|
||
title: "考勤打卡功能开发中",
|
||
icon: "none",
|
||
});
|
||
break;
|
||
case "meeting":
|
||
uni.showToast({
|
||
title: "会议预订功能开发中",
|
||
icon: "none",
|
||
});
|
||
break;
|
||
case "customer":
|
||
uni.showToast({
|
||
title: "客户管理功能开发中",
|
||
icon: "none",
|
||
});
|
||
break;
|
||
case "report":
|
||
uni.showToast({
|
||
title: "工作报告功能开发中",
|
||
icon: "none",
|
||
});
|
||
break;
|
||
default:
|
||
uni.showToast({
|
||
title: `打开${action.label}`,
|
||
icon: "none",
|
||
});
|
||
}
|
||
};
|
||
|
||
const handleRecentItem = (item) => {
|
||
uni.showToast({
|
||
title: `查看${item.title}`,
|
||
icon: "none",
|
||
});
|
||
};
|
||
|
||
// 获取天气信息
|
||
const getWeatherInfo = () => {
|
||
// 这里可以调用天气API获取实时天气
|
||
// 目前使用模拟数据
|
||
const weatherData = {
|
||
temperature: Math.floor(Math.random() * 15) + 15, // 15-30度随机温度
|
||
description: ["晴朗", "多云", "小雨", "阴天"][
|
||
Math.floor(Math.random() * 4)
|
||
],
|
||
location: "北京市",
|
||
icon: "fas fa-sun",
|
||
};
|
||
|
||
weather.temperature = weatherData.temperature;
|
||
weather.description = weatherData.description;
|
||
weather.location = weatherData.location;
|
||
weather.icon = weatherData.icon;
|
||
};
|
||
|
||
// 获取问候语
|
||
const getGreeting = () => {
|
||
const hour = new Date().getHours();
|
||
if (hour < 6) return "夜深了";
|
||
if (hour < 9) return "早上好";
|
||
if (hour < 12) return "上午好";
|
||
if (hour < 14) return "中午好";
|
||
if (hour < 18) return "下午好";
|
||
if (hour < 22) return "晚上好";
|
||
return "夜深了";
|
||
};
|
||
|
||
return {
|
||
userName,
|
||
currentDate,
|
||
workStatus,
|
||
workStatusText,
|
||
workTime,
|
||
workDuration,
|
||
unreadCount,
|
||
pendingApproval,
|
||
completedTasks,
|
||
reimbursementAmount,
|
||
attendanceRate,
|
||
weather,
|
||
quickActions,
|
||
recentActivities,
|
||
handleSearch,
|
||
handleNotification,
|
||
goToApproval,
|
||
goToTasks,
|
||
goToAttendance,
|
||
goToReimbursement,
|
||
showAllFunctions,
|
||
handleQuickAction,
|
||
handleRecentItem,
|
||
getWeatherInfo,
|
||
getGreeting,
|
||
isMobile,
|
||
};
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.workbench {
|
||
min-height: 100vh;
|
||
background: var(--gradient-surface);
|
||
position: relative;
|
||
width: 100vw;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* 浏览器环境下的顶部间距 */
|
||
.unified-header + .unified-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx);
|
||
padding-top: 30rpx;
|
||
}
|
||
|
||
/* 支持安全区域的设备 - 移动设备不需要额外的 padding-top,因为使用了 top_bar */
|
||
|
||
/* 移动设备顶部状态栏 */
|
||
.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 + .unified-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx + env(safe-area-inset-top));
|
||
padding-top: 30rpx;
|
||
}
|
||
}
|
||
|
||
/* 移动设备下的导航栏样式 */
|
||
.top_bar .chat-header {
|
||
background: transparent;
|
||
border-bottom: none;
|
||
box-shadow: none;
|
||
width: 100%;
|
||
height: 88rpx;
|
||
padding: 0 20rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.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;
|
||
}
|
||
|
||
/* 移动设备下为内容添加顶部间距 */
|
||
.top_bar + .unified-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx);
|
||
padding-top: 30rpx;
|
||
}
|
||
|
||
/* 浏览器环境顶部导航栏 */
|
||
.unified-header {
|
||
background: var(--gradient-primary);
|
||
box-shadow: var(--shadow-lg);
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 9999;
|
||
height: calc(var(--status-bar-height) + 88rpx);
|
||
}
|
||
|
||
.unified-header .header-content {
|
||
padding: 20rpx 30rpx;
|
||
padding-top: calc(var(--status-bar-height) + 20rpx);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.unified-header .header-title {
|
||
flex: 1;
|
||
text-align: center;
|
||
color: var(--white);
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
margin: 0 20rpx;
|
||
}
|
||
|
||
.unified-header .header-left,
|
||
.unified-header .header-right {
|
||
display: flex;
|
||
align-items: center;
|
||
min-width: 80rpx;
|
||
}
|
||
|
||
.unified-header .header-right {
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.unified-header .header-icon {
|
||
color: var(--white);
|
||
font-size: 36rpx;
|
||
padding: 10rpx;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.unified-header .header-icon:active {
|
||
background: rgba(255, 255, 255, 0.2);
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
/* 支持安全区域的设备 */
|
||
@supports (padding: max(0px)) {
|
||
.unified-header {
|
||
height: calc(var(--status-bar-height) + 88rpx + env(safe-area-inset-top));
|
||
}
|
||
|
||
.unified-header .header-content {
|
||
padding-top: calc(var(--status-bar-height) + 20rpx + env(safe-area-inset-top));
|
||
}
|
||
|
||
.unified-header + .unified-content {
|
||
margin-top: calc(var(--status-bar-height) + 88rpx + env(safe-area-inset-top));
|
||
}
|
||
}
|
||
|
||
|
||
/* 欢迎和天气模块 */
|
||
.welcome-section {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.welcome-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
background: var(--gradient-primary);
|
||
border-radius: 20rpx;
|
||
padding: 40rpx 32rpx;
|
||
color: var(--white);
|
||
box-shadow: var(--shadow-lg);
|
||
}
|
||
|
||
.welcome-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.welcome-text {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
margin-bottom: 12rpx;
|
||
display: block;
|
||
}
|
||
|
||
.welcome-date {
|
||
font-size: 26rpx;
|
||
opacity: 0.9;
|
||
display: block;
|
||
}
|
||
|
||
.weather-card {
|
||
display: flex;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
border-radius: 16rpx;
|
||
padding: 20rpx 24rpx;
|
||
backdrop-filter: blur(10rpx);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.weather-icon {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
border-radius: 12rpx;
|
||
background: rgba(255, 255, 255, 0.2);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.weather-icon-fa {
|
||
font-size: 28rpx;
|
||
color: var(--white);
|
||
}
|
||
|
||
.weather-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.weather-temp {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
margin-bottom: 4rpx;
|
||
display: block;
|
||
}
|
||
|
||
.weather-desc {
|
||
font-size: 22rpx;
|
||
opacity: 0.9;
|
||
margin-bottom: 4rpx;
|
||
display: block;
|
||
}
|
||
|
||
.weather-location {
|
||
font-size: 20rpx;
|
||
opacity: 0.8;
|
||
display: block;
|
||
}
|
||
|
||
/* 工作状态卡片 */
|
||
.status-card {
|
||
background: var(--white);
|
||
border-radius: 16rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: var(--shadow);
|
||
border: 1rpx solid var(--border-light);
|
||
}
|
||
|
||
.status-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.status-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.status-indicator {
|
||
padding: 12rpx 24rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.status-indicator.working {
|
||
background: var(--gradient-success);
|
||
color: var(--white);
|
||
}
|
||
|
||
.status-text {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.status-content {
|
||
display: flex;
|
||
gap: 60rpx;
|
||
}
|
||
|
||
.status-item {
|
||
flex: 1;
|
||
}
|
||
|
||
.status-label {
|
||
font-size: 24rpx;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
}
|
||
|
||
.status-value {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
/* 数据统计 */
|
||
.stats-section {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.stats-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 20rpx;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.stat-card {
|
||
background: var(--white);
|
||
border-radius: 12rpx;
|
||
padding: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
box-shadow: var(--shadow);
|
||
border: 1rpx solid var(--border-light);
|
||
transition: all 0.3s ease;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.stat-card:active {
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
.stat-icon {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.stat-card.pending .stat-icon {
|
||
background: var(--gradient-error);
|
||
}
|
||
|
||
.stat-card.tasks .stat-icon {
|
||
background: var(--gradient-success);
|
||
}
|
||
|
||
.stat-card.money .stat-icon {
|
||
background: var(--gradient-primary);
|
||
}
|
||
|
||
.stat-card.attendance .stat-icon {
|
||
background: var(--gradient-warning);
|
||
}
|
||
|
||
.stat-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.stat-number {
|
||
font-size: 36rpx;
|
||
font-weight: 700;
|
||
color: var(--text-color);
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 24rpx;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
/* 快捷功能 */
|
||
.functions-section {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
.more-btn {
|
||
font-size: 26rpx;
|
||
color: var(--primary-color);
|
||
}
|
||
|
||
.functions-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20rpx;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.function-card {
|
||
background: var(--white);
|
||
border-radius: 12rpx;
|
||
padding: 24rpx 16rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
box-shadow: var(--shadow);
|
||
border: 1rpx solid var(--border-light);
|
||
transition: all 0.3s ease;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.function-card:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.function-icon {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.function-name {
|
||
font-size: 24rpx;
|
||
color: var(--text-color);
|
||
text-align: center;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 最近动态 */
|
||
.recent-section {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.recent-list {
|
||
background: var(--white);
|
||
border-radius: 12rpx;
|
||
overflow: hidden;
|
||
box-shadow: var(--shadow);
|
||
border: 1rpx solid var(--border-light);
|
||
}
|
||
|
||
.recent-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.05);
|
||
transition: background-color 0.3s ease;
|
||
}
|
||
|
||
.recent-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.recent-item:active {
|
||
background-color: rgba(0, 0, 0, 0.02);
|
||
}
|
||
|
||
.recent-icon {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
border-radius: 12rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.recent-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.recent-title {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: var(--text-color);
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
}
|
||
|
||
.recent-desc {
|
||
font-size: 24rpx;
|
||
color: var(--text-secondary);
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
}
|
||
|
||
.recent-time {
|
||
font-size: 22rpx;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.recent-arrow {
|
||
margin-left: 20rpx;
|
||
}
|
||
|
||
/* 底部安全区域适配 */
|
||
.safe-area-bottom {
|
||
padding-bottom: constant(safe-area-inset-bottom);
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media screen and (max-width: 750rpx) {
|
||
.page-content {
|
||
padding: 20rpx;
|
||
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
|
||
min-height: calc(100vh - 120rpx);
|
||
}
|
||
|
||
.welcome-header {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.weather-card {
|
||
align-self: flex-end;
|
||
}
|
||
|
||
.stats-grid {
|
||
gap: 15rpx;
|
||
}
|
||
|
||
.functions-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 15rpx;
|
||
}
|
||
}
|
||
</style>
|