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>
 |