소스 검색

feat: #update

wei.k.li 1 개월 전
부모
커밋
799f12d0b0
2개의 변경된 파일1139개의 추가작업 그리고 271개의 파일을 삭제
  1. 866 171
      src/assets/templates/FSG/dashboard.vue
  2. 273 100
      src/assets/templates/FSG/login.vue

+ 866 - 171
src/assets/templates/FSG/dashboard.vue

@@ -1,178 +1,309 @@
 <template>
-  <div class="min-h-screen bg-gray-50">
-    <!-- Top Navigation -->
-    <header class="bg-white border-b">
-      <div class="flex items-center justify-between px-4 py-2">
-        <div class="flex items-center space-x-2">
-          <div class="text-blue-600">
-            <div class="w-8 h-8">
-              <div class="w-full h-full" />
-            </div>
-          </div>
-          <span class="text-xl font-medium">ProductName</span>
-        </div>
-
-        <div class="flex-1 max-w-xl mx-4">
-          <div class="relative">
-            <Search class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" size={20} />
-            <input
-                type="text"
-                placeholder="输入内容查询"
-                class="w-full pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
-            />
-          </div>
+  <div class="dashboard-container">
+    <!-- Header -->
+    <header class="header">
+      <div class="header-left">
+        <button class="menu-toggle" @click="toggleSidebar" v-if="isMobile">
+          <Menu size="20" />
+        </button>
+        <div class="logo">
+          <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xMiAyTDIgN0wyIDEzTDEyIDE4TDIyIDEzTDIyIDdMMTIgMloiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFlODhlNSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KICAgIDxwYXRoIGQ9Ik0yIDEzTDEyIDhMMjIgMTMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzFlODhlNSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KICAgIDxwYXRoIGQ9Ik0xMiA4TDEyIDE4IiBmaWxsPSJub25lIiBzdHJva2U9IiMxZTg4ZTUiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPg==" alt="Logo" width="24" height="24" />
+          <span class="product-name">ProductName</span>
         </div>
-
-        <div class="flex items-center space-x-4">
-          <MessageCircle class="w-6 h-6 text-blue-500" />
-          <Bell class="w-6 h-6 text-blue-500" />
-          <Settings class="w-6 h-6 text-gray-400" />
-          <div class="w-8 h-8 rounded-full bg-gray-200"></div>
+      </div>
+      <div class="search-container">
+        <Search size="16" color="#999" />
+        <input type="text" placeholder="输入内容查询" class="search-input" />
+      </div>
+      <div class="header-right">
+        <button class="icon-button">
+          <MessageCircle size="20" />
+        </button>
+        <button class="icon-button notification">
+          <Bell size="20" />
+          <span class="notification-badge"></span>
+        </button>
+        <button class="icon-button">
+          <Settings size="20" />
+        </button>
+        <div class="avatar">
+          <img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzYiIGhlaWdodD0iMzYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3Qgd2lkdGg9IjM2IiBoZWlnaHQ9IjM2IiBmaWxsPSIjZTJlOGYwIiAvPgogIDxjaXJjbGUgY3g9IjE4IiBjeT0iMTQiIHI9IjYiIGZpbGw9IiM5NGEzYjgiIC8+CiAgPHBhdGggZD0iTTMwLDM2IEwzMCwzMCBDMzAsMjQuNDc3MTUyNSAyNS41MjI4NDc1LDIwIDIwLDIwIEwxNiwyMCBDMTAuNDc3MTUyNSwyMCA2LDI0LjQ3NzE1MjUgNiwzMCBMNiwzNiBaIiBmaWxsPSIjOTRhM2I4IiAvPgo8L3N2Zz4=?height=36&width=36" alt="User avatar" />
         </div>
       </div>
     </header>
 
-    <div class="flex">
+    <div class="main-container">
       <!-- Sidebar -->
-      <aside class="w-64 min-h-screen bg-white border-r">
-        <nav class="p-4">
-          <div class="mb-4 text-gray-500">菜单类别标题</div>
-          <ul class="space-y-2">
-            <li>
-              <a href="#" class="flex items-center px-4 py-2 text-blue-600 bg-blue-50 rounded-lg">
-                <LayoutGrid class="w-5 h-5 mr-3" />
-                首页
-              </a>
-            </li>
-            <li v-for="i in 8" :key="i">
-              <a href="#" class="flex items-center px-4 py-2 text-gray-600 hover:bg-gray-50 rounded-lg">
-                <Box class="w-5 h-5 mr-3" />
-                系统模块{{ i }}
-              </a>
-            </li>
-          </ul>
-        </nav>
+      <aside class="sidebar" :class="{ 'sidebar-open': sidebarOpen }">
+        <div class="sidebar-content">
+          <div class="sidebar-section">
+            <div class="sidebar-title">菜单类别标题</div>
+            <ul class="sidebar-menu">
+              <li class="sidebar-menu-item active">
+                <LayoutGrid size="18" />
+                <span>首页</span>
+                <ChevronDown size="16" class="expand-icon" />
+              </li>
+              <li class="sidebar-menu-item">
+                <CircleDot size="18" />
+                <span>系统模块1</span>
+                <ChevronDown size="16" class="expand-icon" />
+              </li>
+              <li class="sidebar-menu-item">
+                <CircleDot size="18" />
+                <span>系统模块1</span>
+                <ChevronDown size="16" class="expand-icon" />
+              </li>
+              <li class="sidebar-menu-item">
+                <Mail size="18" />
+                <span>系统模块1</span>
+                <ChevronDown size="16" class="expand-icon" />
+              </li>
+              <li class="sidebar-menu-item">
+                <BarChart2 size="18" />
+                <span>系统模块1</span>
+                <ChevronUp size="16" class="expand-icon" />
+              </li>
+              <li class="sidebar-menu-subitem">系统模块1</li>
+              <li class="sidebar-menu-subitem">系统模块1</li>
+              <li class="sidebar-menu-subitem">系统模块1</li>
+              <li class="sidebar-menu-item">
+                <FileText size="18" />
+                <span>系统模块1</span>
+                <ChevronDown size="16" class="expand-icon" />
+              </li>
+            </ul>
+          </div>
+          <div class="sidebar-section">
+            <div class="sidebar-title">菜单类别标题</div>
+            <ul class="sidebar-menu">
+              <li class="sidebar-menu-item">
+                <Home size="18" />
+                <span>系统模块1</span>
+                <ChevronDown size="16" class="expand-icon" />
+              </li>
+            </ul>
+          </div>
+        </div>
       </aside>
 
       <!-- Main Content -->
-      <main class="flex-1 p-6">
+      <main class="main-content">
         <!-- Breadcrumb -->
-        <div class="flex items-center text-gray-500 mb-6">
-          <span>首页</span>>
+        <div class="breadcrumb">
+          <FileText size="16" />
+          <span>首页</span>
+          <span>/</span>
           <span>xxx工作台</span>
         </div>
 
-        <!-- Metric Cards -->
-        <div class="grid grid-cols-4 gap-6 mb-6">
-          <div v-for="(metric, index) in metrics" :key="index"
-               class="bg-white rounded-lg p-6 flex items-center space-x-4 shadow-sm">
-            <div :class="[
-              'w-12 h-12 rounded-lg flex items-center justify-center',
-              metric.bgColor
-            ]">
-              <FileText :class="metric.iconColor" size={24} />
-            </div>
-            <div>
-              <div class="text-3xl font-semibold">
-                {{ metric.value }}<span class="text-gray-400 text-lg">/{{ metric.total }}</span>
+        <!-- Contract Stats Cards -->
+        <div class="stats-cards">
+          <div class="stat-card">
+            <div class="stat-card-header">
+              <div class="stat-icon blue">
+                <ClipboardList size="24" color="#1e88e5" />
               </div>
-              <div class="text-gray-500">{{ metric.label }}</div>
+              <div class="stat-title">合同审核</div>
+              <MoreHorizontal size="20" class="more-icon" />
+            </div>
+            <div class="stat-numbers">
+              <span class="stat-main">21</span>
+              <span class="stat-total">/35</span>
             </div>
           </div>
-        </div>
 
-        <!-- Tasks and Projects -->
-        <div class="grid grid-cols-2 gap-6 mb-6">
-          <!-- Special Tasks -->
-          <div class="bg-white rounded-lg p-6 shadow-sm">
-            <div class="flex items-center justify-between mb-4">
-              <h2 class="text-lg font-medium">特办事项</h2>
-              <div class="flex space-x-4">
-                <button class="px-3 py-1 text-blue-600 bg-blue-50 rounded-md">全部</button>
-                <button class="px-3 py-1 text-blue-600">今天</button>
-                <button class="px-3 py-1 text-gray-500">本周</button>
-                <button class="px-3 py-1 text-gray-500">本月</button>
+          <div class="stat-card">
+            <div class="stat-card-header">
+              <div class="stat-icon orange">
+                <ClipboardCheck size="24" color="#ff9800" />
               </div>
+              <div class="stat-title">合同签署</div>
+              <MoreHorizontal size="20" class="more-icon" />
             </div>
-            <div class="space-y-4">
-              <div v-for="(task, index) in tasks" :key="index" class="flex items-start">
-                <input type="checkbox" :checked="task.completed" class="mt-1 mr-3" />
-                <div>
-                  <div class="text-gray-900">{{ task.title }}</div>
-                  <div class="text-gray-500 text-sm">{{ task.project }}</div>
-                </div>
+            <div class="stat-numbers">
+              <span class="stat-main">28</span>
+              <span class="stat-total">/40</span>
+            </div>
+          </div>
+
+          <div class="stat-card">
+            <div class="stat-card-header">
+              <div class="stat-icon green">
+                <ClipboardEdit size="24" color="#4caf50" />
               </div>
+              <div class="stat-title">合同登记</div>
+              <MoreHorizontal size="20" class="more-icon" />
+            </div>
+            <div class="stat-numbers">
+              <span class="stat-main">40</span>
+              <span class="stat-total">/65</span>
+            </div>
+          </div>
+
+          <div class="stat-card">
+            <div class="stat-card-header">
+              <div class="stat-icon red">
+                <Clipboard size="24" color="#f44336" />
+              </div>
+              <div class="stat-title">合同履约</div>
+              <MoreHorizontal size="20" class="more-icon" />
+            </div>
+            <div class="stat-numbers">
+              <span class="stat-main">12</span>
+              <span class="stat-total">/15</span>
             </div>
           </div>
+        </div>
 
-          <!-- Project Progress -->
-          <div class="bg-white rounded-lg p-6 shadow-sm">
-            <div class="flex items-center justify-between mb-4">
-              <h2 class="text-lg font-medium">项目进程</h2>
+        <!-- Two Column Layout -->
+        <div class="two-column-layout">
+          <!-- Special Items Section -->
+          <div class="content-card">
+            <div class="card-header">
+              <h3>特办事项</h3>
+            </div>
+            <div class="tabs">
+              <button class="tab-button active">全部</button>
+              <button class="tab-button">今天</button>
+              <button class="tab-button">本周</button>
+              <button class="tab-button">本月</button>
             </div>
-            <table class="w-full">
+            <div class="task-list">
+              <div class="task-item">
+                <input type="checkbox" checked />
+                <span class="task-text">联系xxx客户,确认具体合同事宜</span>
+              </div>
+              <div class="task-item">
+                <input type="checkbox" checked />
+                <span class="task-text">完成合同模板创建并上传系统</span>
+              </div>
+              <div class="task-item">
+                <input type="checkbox" />
+                <span class="task-text">审核xxxxxxx合同</span>
+              </div>
+              <div class="task-item">
+                <input type="checkbox" checked />
+                <span class="task-text">完善xxxx合同,邮件发送xxxxx客户</span>
+              </div>
+              <div class="task-item">
+                <input type="checkbox" />
+                <span class="task-text">完成xxx银行账户注册,上传账户信息</span>
+              </div>
+              <div class="task-item">
+                <input type="checkbox" />
+                <span class="task-text">完成xxx银行账户注册,上传账户信息</span>
+              </div>
+            </div>
+          </div>
+
+          <!-- Project Progress Section -->
+          <div class="content-card">
+            <div class="card-header">
+              <h3>项目进程</h3>
+            </div>
+            <table class="project-table">
               <thead>
-              <tr class="text-gray-500">
-                <th class="pb-4 text-left font-normal">项目名称</th>
-                <th class="pb-4 text-left font-normal">负责人</th>
-                <th class="pb-4 text-left font-normal">截止日期</th>
-                <th class="pb-4 text-left font-normal">当前状态</th>
-              </tr>
+                <tr>
+                  <th>项目名称</th>
+                  <th>负责人</th>
+                  <th>截止日期</th>
+                  <th>当前状态</th>
+                </tr>
               </thead>
-              <tbody class="text-sm">
-              <tr v-for="(project, index) in projects" :key="index" class="border-t">
-                <td class="py-4">{{ project.name }}</td>
-                <td class="py-4">{{ project.owner }}</td>
-                <td class="py-4">{{ project.deadline }}</td>
-                <td class="py-4">
-                    <span :class="[
-                      'px-2 py-1 rounded text-sm',
-                      project.statusColor
-                    ]">
-                      {{ project.status }}
-                    </span>
-                </td>
-              </tr>
+              <tbody>
+                <tr>
+                  <td>xxxxx公司税金管理</td>
+                  <td>任小东</td>
+                  <td>2023/07/25</td>
+                  <td><span class="status overdue">已延期</span></td>
+                </tr>
+                <tr>
+                  <td>xxxxxxxxxxxxxxxxxxxxxxx公司人事xxxx合同管理</td>
+                  <td>胡晓东</td>
+                  <td>2024/01/09</td>
+                  <td><span class="status in-progress">进行中</span></td>
+                </tr>
+                <tr>
+                  <td>xxxxx公司人员xxxx合同签订</td>
+                  <td>李兵</td>
+                  <td>2025/01/08</td>
+                  <td><span class="status in-progress">进行中</span></td>
+                </tr>
+                <tr>
+                  <td>xxxxxxxxxxxx公司人员资源管理</td>
+                  <td>王天一</td>
+                  <td>2023/09/03</td>
+                  <td><span class="status completed">已完成</span></td>
+                </tr>
+                <tr>
+                  <td>xxxxxxxxxxxx公司人员资源管理</td>
+                  <td>李琳琳</td>
+                  <td>2023/10/23</td>
+                  <td><span class="status pending">审核中</span></td>
+                </tr>
+                <tr>
+                  <td>xxxxx公司人员资源管理</td>
+                  <td>刘琳琳</td>
+                  <td>2023/12/07</td>
+                  <td><span class="status in-progress">进行中</span></td>
+                </tr>
               </tbody>
             </table>
           </div>
         </div>
 
         <!-- Bottom Section -->
-        <div class="grid grid-cols-2 gap-6">
+        <div class="two-column-layout">
           <!-- Quick Functions -->
-          <div class="bg-white rounded-lg p-6 shadow-sm">
-            <div class="flex items-center justify-between mb-4">
-              <h2 class="text-lg font-medium">快捷功能</h2>
-              <MoreHorizontal class="text-gray-400" />
-            </div>
-            <div class="space-y-3">
-              <div v-for="(func, index) in quickFunctions" :key="index"
-                   class="text-gray-700 hover:text-blue-600 cursor-pointer">
-                {{ func }}
-              </div>
+          <div class="content-card">
+            <div class="card-header">
+              <h3>快捷功能</h3>
+              <MoreHorizontal size="20" class="more-icon" />
+            </div>
+            <div class="quick-functions">
+              <div class="function-item">人力资源主合同 (标准版)</div>
+              <div class="function-item">人事代理服务协议 (标准版)</div>
+              <div class="function-item">人事代理服务协议</div>
+              <div class="function-item">人事代理服务协议</div>
+              <div class="function-item">人事代理服务协议 (企业版)</div>
+              <div class="function-item">人事代理服务协议 (定制版)</div>
             </div>
           </div>
 
           <!-- Contract Statistics -->
-          <div class="bg-white rounded-lg p-6 shadow-sm">
-            <div class="flex items-center justify-between mb-4">
-              <h2 class="text-lg font-medium">合同类型统计</h2>
-              <div class="flex items-center space-x-4">
-                <div class="flex items-center">
-                  <div class="w-3 h-3 bg-blue-500 rounded-sm mr-2"></div>
-                  <span class="text-sm text-gray-500">A合同</span>
-                </div>
-                <div class="flex items-center">
-                  <div class="w-3 h-3 bg-green-500 rounded-sm mr-2"></div>
-                  <span class="text-sm text-gray-500">B合同</span>
-                </div>
+          <div class="content-card">
+            <div class="card-header">
+              <h3>合同类型统计</h3>
+            </div>
+            <div class="chart-legend">
+              <div class="legend-item">
+                <span class="legend-color blue"></span>
+                <span>A合同</span>
+              </div>
+              <div class="legend-item">
+                <span class="legend-color green"></span>
+                <span>B合同</span>
               </div>
             </div>
-            <div class="h-64">
-              <!-- Chart would go here - using a placeholder -->
-              <div class="w-full h-full bg-gray-50 rounded flex items-center justify-center">
-                Bar Chart Placeholder
+            <div class="chart-container">
+              <div class="chart">
+                <!-- Simplified chart representation -->
+                <div class="chart-bars">
+                  <div v-for="month in 12" :key="month" class="chart-month">
+                    <div class="chart-bar blue" :style="{ height: getRandomHeight() + 'px' }"></div>
+                    <div class="chart-bar green" :style="{ height: getRandomHeight() + 'px' }"></div>
+                    <div class="month-label">{{ month }}月</div>
+                  </div>
+                </div>
+                <div class="chart-y-axis">
+                  <div>100</div>
+                  <div>80</div>
+                  <div>60</div>
+                  <div>40</div>
+                  <div>20</div>
+                  <div>0</div>
+                </div>
               </div>
             </div>
           </div>
@@ -183,39 +314,603 @@
 </template>
 
 <script setup>
-import {
-  Search, MessageCircle, Bell, Settings,
-  Home, ChevronRight, FileText, Box,
-  LayoutGrid, MoreHorizontal
-} from 'lucide-vue-next'
-
-const metrics = [
-  { label: '合同审核', value: 21, total: 35, bgColor: 'bg-blue-50', iconColor: 'text-blue-500' },
-  { label: '合同签署', value: 28, total: 40, bgColor: 'bg-yellow-50', iconColor: 'text-yellow-500' },
-  { label: '合同登记', value: 40, total: 65, bgColor: 'bg-green-50', iconColor: 'text-green-500' },
-  { label: '合同履约', value: 12, total: 15, bgColor: 'bg-red-50', iconColor: 'text-red-500' }
-]
-
-const tasks = [
-  { title: '联系xxxx客户,商讨具体合同事宜', project: 'xxxx公司公积金管理', completed: true },
-  { title: '完成合同模版创建并上传系统', project: 'xxxxx公司人员xxxx合同管理', completed: true },
-  { title: '审核xxxxxxx合同', project: 'xxxx公司人员xxx合同签订', completed: false },
-  { title: '签署xxxx合同,邮件发送xxxxx客户', project: 'xxxxxxxxx公司人员资源管理', completed: true }
-]
-
-const projects = [
-  { name: 'xxxx公司公积金管理', owner: '任小东', deadline: '2023/07/25', status: '已延期', statusColor: 'bg-red-50 text-red-600' },
-  { name: 'xxxxx公司人员xxxx合同管理', owner: '胡晓东', deadline: '2024/01/09', status: '进行中', statusColor: 'bg-blue-50 text-blue-600' },
-  { name: 'xxxx公司人员xxx合同签订', owner: '李兵', deadline: '2025/01/08', status: '进行中', statusColor: 'bg-blue-50 text-blue-600' },
-  { name: 'xxxxxxxxx公司人员资源管理', owner: '王天一', deadline: '2023/09/03', status: '已完成', statusColor: 'bg-green-50 text-green-600' }
-]
-
-const quickFunctions = [
-  '人力资源主合同(标准版)',
-  '人事代理服务协议(标准版)',
-  '人事代理服务协议',
-  '人事代理服务协议',
-  '人事代理服务协议(企业版)',
-  '人事代理服务协议(定制版)'
-]
-</script>
+import { ref, onMounted, onUnmounted } from 'vue';
+import { 
+  Menu, Search, MessageCircle, Bell, Settings, 
+  FileText, LayoutGrid, CircleDot, Mail, BarChart2, Home,
+  ClipboardList, ClipboardCheck, ClipboardEdit, Clipboard,
+  MoreHorizontal, ChevronDown, ChevronUp
+} from 'lucide-vue-next';
+
+// Responsive sidebar state
+const sidebarOpen = ref(false);
+const isMobile = ref(false);
+
+// Toggle sidebar
+const toggleSidebar = () => {
+  sidebarOpen.value = !sidebarOpen.value;
+};
+
+// Check if mobile on resize
+const checkIfMobile = () => {
+  isMobile.value = window.innerWidth < 475;
+  if (!isMobile.value) {
+    sidebarOpen.value = true;
+  } else {
+    sidebarOpen.value = false;
+  }
+};
+
+// Generate random chart heights
+const getRandomHeight = () => {
+  return Math.floor(Math.random() * 60) + 10;
+};
+
+// Lifecycle hooks
+onMounted(() => {
+  checkIfMobile();
+  window.addEventListener('resize', checkIfMobile);
+});
+
+onUnmounted(() => {
+  window.removeEventListener('resize', checkIfMobile);
+});
+</script>
+
+<style scoped>
+/* Base styles */
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+}
+
+.dashboard-container {
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+  background-color: #f5f7fa;
+}
+
+/* Header styles */
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 20px;
+  height: 60px;
+  background-color: #fff;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
+  position: sticky;
+  top: 0;
+  z-index: 100;
+}
+
+.header-left {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.menu-toggle {
+  background: none;
+  border: none;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 5px;
+}
+
+.logo {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.product-name {
+  font-weight: 600;
+  font-size: 16px;
+}
+
+.search-container {
+  display: flex;
+  align-items: center;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  padding: 0 10px;
+  flex: 1;
+  max-width: 400px;
+  margin: 0 20px;
+}
+
+.search-input {
+  border: none;
+  background: transparent;
+  padding: 8px;
+  width: 100%;
+  font-size: 14px;
+  outline: none;
+}
+
+.header-right {
+  display: flex;
+  align-items: center;
+  gap: 15px;
+}
+
+.icon-button {
+  background: none;
+  border: none;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+  color: #666;
+}
+
+.notification {
+  position: relative;
+}
+
+.notification-badge {
+  position: absolute;
+  top: -2px;
+  right: -2px;
+  width: 8px;
+  height: 8px;
+  background-color: #f44336;
+  border-radius: 50%;
+}
+
+.avatar {
+  width: 36px;
+  height: 36px;
+  border-radius: 50%;
+  overflow: hidden;
+}
+
+.avatar img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+/* Main container */
+.main-container {
+  display: flex;
+  flex: 1;
+}
+
+/* Sidebar styles */
+.sidebar {
+  width: 220px;
+  background-color: #fff;
+  border-right: 1px solid #e0e0e0;
+  transition: transform 0.3s ease;
+  z-index: 90;
+}
+
+.sidebar-content {
+  height: calc(100vh - 60px);
+  overflow-y: auto;
+  position: sticky;
+  top: 60px;
+}
+
+.sidebar-section {
+  padding: 15px 0;
+}
+
+.sidebar-title {
+  padding: 0 15px 10px;
+  color: #999;
+  font-size: 12px;
+}
+
+.sidebar-menu {
+  list-style: none;
+}
+
+.sidebar-menu-item {
+  display: flex;
+  align-items: center;
+  padding: 10px 15px;
+  color: #333;
+  cursor: pointer;
+  position: relative;
+}
+
+.sidebar-menu-item span {
+  margin-left: 10px;
+  flex: 1;
+}
+
+.sidebar-menu-item.active {
+  background-color: #e6f0ff;
+  color: #1976d2;
+}
+
+.expand-icon {
+  color: #999;
+}
+
+.sidebar-menu-subitem {
+  padding: 8px 15px 8px 42px;
+  color: #666;
+  font-size: 14px;
+  cursor: pointer;
+}
+
+/* Sidebar overlay for mobile */
+/* .sidebar-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.5);
+  z-index: 80;
+} */
+
+/* Main content styles */
+.main-content {
+  flex: 1;
+  padding: 20px;
+  overflow-x: hidden;
+}
+
+.breadcrumb {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 20px;
+  color: #666;
+  font-size: 14px;
+}
+
+/* Stats cards */
+.stats-cards {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.stat-card {
+  background-color: #fff;
+  border-radius: 8px;
+  padding: 20px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.stat-card-header {
+  display: flex;
+  align-items: center;
+  margin-bottom: 15px;
+}
+
+.stat-icon {
+  width: 40px;
+  height: 40px;
+  border-radius: 8px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 10px;
+}
+
+.stat-icon.blue {
+  background-color: rgba(30, 136, 229, 0.1);
+}
+
+.stat-icon.orange {
+  background-color: rgba(255, 152, 0, 0.1);
+}
+
+.stat-icon.green {
+  background-color: rgba(76, 175, 80, 0.1);
+}
+
+.stat-icon.red {
+  background-color: rgba(244, 67, 54, 0.1);
+}
+
+.stat-title {
+  flex: 1;
+  font-size: 16px;
+  color: #333;
+}
+
+.more-icon {
+  color: #999;
+  cursor: pointer;
+}
+
+.stat-numbers {
+  font-size: 24px;
+  font-weight: 600;
+}
+
+.stat-main {
+  color: #333;
+}
+
+.stat-total {
+  color: #999;
+  font-size: 18px;
+}
+
+/* Two column layout */
+.two-column-layout {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.content-card {
+  background-color: #fff;
+  border-radius: 8px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+  overflow: hidden;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 15px 20px;
+  border-bottom: 1px solid #eee;
+}
+
+.card-header h3 {
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+/* Tabs */
+.tabs {
+  display: flex;
+  border-bottom: 1px solid #eee;
+}
+
+.tab-button {
+  padding: 10px 20px;
+  background: none;
+  border: none;
+  cursor: pointer;
+  font-size: 14px;
+  color: #666;
+}
+
+.tab-button.active {
+  color: #1976d2;
+  border-bottom: 2px solid #1976d2;
+}
+
+/* Task list */
+.task-list {
+  padding: 10px 20px;
+}
+
+.task-item {
+  display: flex;
+  align-items: center;
+  padding: 10px 0;
+  border-bottom: 1px solid #f5f5f5;
+}
+
+.task-item input[type="checkbox"] {
+  margin-right: 10px;
+}
+
+.task-text {
+  font-size: 14px;
+  color: #333;
+}
+
+/* Project table */
+.project-table {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+.project-table th {
+  text-align: left;
+  padding: 12px 20px;
+  font-size: 14px;
+  font-weight: 500;
+  color: #666;
+  border-bottom: 1px solid #eee;
+}
+
+.project-table td {
+  padding: 12px 20px;
+  font-size: 14px;
+  color: #333;
+  border-bottom: 1px solid #f5f5f5;
+}
+
+.status {
+  display: inline-block;
+  padding: 4px 8px;
+  border-radius: 4px;
+  font-size: 12px;
+}
+
+.status.overdue {
+  background-color: #ffebee;
+  color: #f44336;
+}
+
+.status.in-progress {
+  background-color: #e3f2fd;
+  color: #1976d2;
+}
+
+.status.completed {
+  background-color: #e8f5e9;
+  color: #4caf50;
+}
+
+.status.pending {
+  background-color: #fff8e1;
+  color: #ff9800;
+}
+
+/* Quick functions */
+.quick-functions {
+  padding: 10px 20px;
+}
+
+.function-item {
+  padding: 10px 0;
+  font-size: 14px;
+  color: #333;
+  border-bottom: 1px solid #f5f5f5;
+}
+
+/* Chart */
+.chart-legend {
+  display: flex;
+  padding: 10px 20px;
+  gap: 20px;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+  font-size: 14px;
+}
+
+.legend-color {
+  width: 12px;
+  height: 12px;
+  border-radius: 2px;
+}
+
+.legend-color.blue {
+  background-color: #1976d2;
+}
+
+.legend-color.green {
+  background-color: #4caf50;
+}
+
+.chart-container {
+  padding: 0 20px 20px;
+  height: 250px;
+  position: relative;
+}
+
+.chart {
+  height: 100%;
+  display: flex;
+}
+
+.chart-y-axis {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  padding-right: 10px;
+  color: #999;
+  font-size: 12px;
+}
+
+.chart-bars {
+  display: flex;
+  align-items: flex-end;
+  flex: 1;
+  height: 200px;
+  gap: 15px;
+}
+
+.chart-month {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  flex: 1;
+}
+
+.chart-bar {
+  width: 10px;
+  margin: 0 2px;
+  border-radius: 2px 2px 0 0;
+}
+
+.chart-bar.blue {
+  background-color: #1976d2;
+}
+
+.chart-bar.green {
+  background-color: #4caf50;
+}
+
+.month-label {
+  margin-top: 5px;
+  font-size: 12px;
+  color: #999;
+}
+
+/* Responsive styles */
+@media (max-width: 1024px) {
+  .stats-cards {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  
+  .two-column-layout {
+    grid-template-columns: 1fr;
+  }
+}
+
+@media (max-width: 768px) {
+  .search-container {
+    max-width: 200px;
+  }
+}
+
+@media (max-width: 475px) {
+  /* Mobile styles */
+  .sidebar {
+    position: fixed;
+    top: 60px;
+    bottom: 0;
+    left: 0;
+    transform: translateX(-100%);
+  }
+  
+  .sidebar-open {
+    transform: translateX(0);
+  }
+  
+  .search-container {
+    max-width: 150px;
+    margin: 0 10px;
+  }
+  
+  .header {
+    padding: 0 10px;
+  }
+  
+  .stats-cards {
+    grid-template-columns: 1fr;
+  }
+  
+  .main-content {
+    padding: 15px;
+  }
+  
+  .product-name {
+    font-size: 14px;
+  }
+  
+  .icon-button:not(:last-child) {
+    display: none;
+  }
+}
+</style>

+ 273 - 100
src/assets/templates/FSG/login.vue

@@ -1,121 +1,294 @@
 <template>
-  <div class="min-h-screen bg-gradient-to-br from-blue-50 to-blue-100/50">
-    <div class="container mx-auto px-4">
-      <!-- Header -->
-      <header class="flex justify-between items-center py-6">
-        <div class="text-2xl font-bold text-white">
-          <h1>FSG</h1>
-          <div class="text-sm">上海外服</div>
-        </div>
-        <button class="flex items-center text-blue-600 hover:text-blue-700">
-          <Globe class="w-4 h-4 mr-1" />
-          中文
-        </button>
-      </header>
-
-      <!-- Login Form -->
-      <div class="max-w-md mx-auto mt-12 bg-white rounded-lg shadow-lg p-8">
-        <h2 class="text-3xl font-bold text-center mb-2 text-blue-600">
-          "Hello,欢迎回来"
-        </h2>
-        <p class="text-center text-gray-600 mb-8">请登录外包管理系统</p>
-
-        <form @submit.prevent="handleSubmit">
-          <div class="space-y-6">
-            <div>
-              <label class="block text-sm font-medium text-gray-700 mb-1">租户名称</label>
-              <input
-                  v-model="form.tenant"
-                  type="text"
-                  placeholder="请输入"
-                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
-              />
-            </div>
-
-            <div>
-              <label class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
-              <input
-                  v-model="form.username"
-                  type="text"
-                  placeholder="输入文字中"
-                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
-              />
-            </div>
+  <div class="login-container">
+    <!-- Header -->
+    <header class="header">
+      <div class="logo">
+        <h1>FSG</h1>
+        <span>上海外服</span>
+      </div>
+      <div class="language-selector">
+        <Globe class="globe-icon" size="16" />
+        <span>中文</span>
+        <ChevronDown class="chevron-icon" size="14" />
+      </div>
+    </header>
 
-            <div>
-              <label class="block text-sm font-medium text-gray-700 mb-1">密码</label>
-              <input
-                  v-model="form.password"
-                  type="password"
-                  placeholder="请输入"
-                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
-              />
-            </div>
+    <!-- Main Content -->
+    <main class="main-content">
+      <div class="login-card">
+        <h2 class="greeting">"Hello, 欢迎回来</h2>
+        <p class="subtitle">请登录外包管理系统</p>
 
-            <div class="flex items-center justify-between">
-              <label class="flex items-center">
-                <input
-                    v-model="form.remember"
-                    type="checkbox"
-                    class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
-                />
-                <span class="ml-2 text-sm text-gray-600">记住我</span>
-              </label>
-              <a href="#" class="text-sm text-blue-600 hover:text-blue-700">忘记密码?</a>
-            </div>
+        <form @submit.prevent="handleLogin">
+          <div class="form-group">
+            <label for="username">用户名称</label>
+            <input 
+              type="text" 
+              id="username" 
+              v-model="username" 
+              placeholder="请输入"
+              class="form-input"
+            />
+          </div>
 
-            <button
-                type="submit"
-                class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
-            >
-              登录
-            </button>
+          <div class="form-group">
+            <label for="password">密码</label>
+            <input 
+              type="password" 
+              id="password" 
+              v-model="password" 
+              placeholder="请输入"
+              class="form-input"
+            />
           </div>
-        </form>
 
-        <div class="mt-6">
-          <div class="relative">
-            <div class="absolute inset-0 flex items-center">
-              <div class="w-full border-t border-gray-300"></div>
-            </div>
-            <div class="relative flex justify-center text-sm">
-              <span class="px-2 bg-white text-gray-500">其他登录方式</span>
+          <div class="form-options">
+            <div class="remember-me">
+              <input type="checkbox" id="remember" v-model="rememberMe" />
+              <label for="remember">记住我</label>
             </div>
+            <a href="#" class="forgot-password">忘记密码?</a>
           </div>
 
-          <button
-              class="mt-4 w-full border border-blue-600 text-blue-600 py-2 px-4 rounded-md hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
-          >
-            使用AD域免密自动登录
-          </button>
+          <button type="submit" class="login-button">登录</button>
+        </form>
+
+        <div class="alternative-login">
+          <p>其他登录方式</p>
+          <a href="#" class="sms-login">使用短信验证码登录</a>
         </div>
       </div>
+    </main>
 
-      <!-- Footer -->
-      <footer class="text-center mt-8 pb-6 text-gray-600 text-sm">
-        © 2023 上海外服. All Rights Reserved.
-      </footer>
-    </div>
+    <!-- Footer - hidden on mobile -->
+    <footer class="footer">
+      <p>© 2023 上海外服 All Rights Reserved.</p>
+    </footer>
   </div>
 </template>
 
 <script setup>
-import { ref } from 'vue'
-import { Globe } from 'lucide-vue-next'
+import { ref } from 'vue';
+import { Globe, ChevronDown } from 'lucide-vue-next';
 
-const form = ref({
-  tenant: '',
-  username: '',
-  password: '',
-  remember: false
-})
+// Form data
+const username = ref('');
+const password = ref('');
+const rememberMe = ref(false);
 
-const handleSubmit = () => {
-  // Handle login logic here
-  console.log('Form submitted:', form.value)
-}
+// Login handler
+const handleLogin = () => {
+  console.log('Login attempt:', { 
+    username: username.value, 
+    password: password.value,
+    rememberMe: rememberMe.value
+  });
+  // Add actual login logic here
+};
 </script>
 
-<style>
-/* Add any additional custom styles here if needed */
+<style scoped>
+/* Base styles */
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+}
+
+.login-container {
+  min-height: 100vh;
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  background: linear-gradient(135deg, #e6f0ff 0%, #f0f8ff 100%);
+  position: relative;
+  overflow: hidden;
+}
+
+/* Header styles */
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20px 40px;
+  width: 100%;
+}
+
+.logo {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+  color: #4a90e2;
+}
+
+.logo h1 {
+  font-size: 24px;
+  font-weight: bold;
+  letter-spacing: 1px;
+}
+
+.logo span {
+  font-size: 14px;
+  margin-left: 5px;
+}
+
+.language-selector {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+  cursor: pointer;
+  color: #4a90e2;
+  font-size: 14px;
+}
+
+.globe-icon, .chevron-icon {
+  color: #4a90e2;
+}
+
+/* Main content styles */
+.main-content {
+  flex: 1;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
+}
+
+.login-card {
+  background-color: white;
+  border-radius: 8px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+  padding: 40px;
+  width: 100%;
+  max-width: 420px;
+  text-align: left;
+}
+
+.greeting {
+  color: #2c3e50;
+  font-size: 24px;
+  margin-bottom: 10px;
+  font-weight: 600;
+}
+
+.subtitle {
+  color: #7f8c8d;
+  font-size: 16px;
+  margin-bottom: 30px;
+}
+
+.form-group {
+  margin-bottom: 20px;
+}
+
+.form-group label {
+  display: block;
+  margin-bottom: 8px;
+  font-size: 14px;
+  color: #2c3e50;
+}
+
+.form-input {
+  width: 100%;
+  padding: 12px;
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  font-size: 14px;
+  transition: border-color 0.2s;
+}
+
+.form-input:focus {
+  outline: none;
+  border-color: #4a90e2;
+}
+
+.form-options {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.remember-me {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  font-size: 14px;
+  color: #606266;
+}
+
+.forgot-password {
+  font-size: 14px;
+  color: #4a90e2;
+  text-decoration: none;
+}
+
+.login-button {
+  width: 100%;
+  padding: 12px;
+  background-color: #1976d2;
+  color: white;
+  border: none;
+  border-radius: 4px;
+  font-size: 16px;
+  cursor: pointer;
+  transition: background-color 0.2s;
+}
+
+.login-button:hover {
+  background-color: #1565c0;
+}
+
+.alternative-login {
+  margin-top: 30px;
+  text-align: center;
+}
+
+.alternative-login p {
+  font-size: 14px;
+  color: #909399;
+  margin-bottom: 10px;
+}
+
+.sms-login {
+  color: #4a90e2;
+  text-decoration: none;
+  font-size: 14px;
+}
+
+/* Footer styles */
+.footer {
+  padding: 15px;
+  text-align: center;
+  color: #909399;
+  font-size: 12px;
+}
+
+/* Responsive styles */
+@media (max-width: 475px) {
+  .header {
+    padding: 15px 20px;
+  }
+  
+  .login-card {
+    padding: 25px;
+    box-shadow: none;
+    max-width: 100%;
+  }
+  
+  .greeting {
+    font-size: 20px;
+  }
+  
+  .subtitle {
+    font-size: 14px;
+    margin-bottom: 20px;
+  }
+  
+  /* Hide footer on mobile as requested */
+  .footer {
+    display: none;
+  }
+}
 </style>