Prechádzať zdrojové kódy

feat: #update add prototype templates

wei.k.li 1 týždeň pred
rodič
commit
8eded322d2
54 zmenil súbory, kde vykonal 31048 pridanie a 775 odobranie
  1. 1 1
      README.md
  2. 367 767
      package-lock.json
  3. 1 0
      package.json
  4. 294 0
      src/assets/templates/prototype/common/login.vue
  5. 858 0
      src/assets/templates/prototype/customer/CustomerManagement.vue
  6. 549 0
      src/assets/templates/prototype/customer/CustomerRelationshipManagement.vue
  7. 964 0
      src/assets/templates/prototype/customer/CustomerServiceAnalytics.vue
  8. 357 0
      src/assets/templates/prototype/customer/CustomerServiceManagement.vue
  9. 603 0
      src/assets/templates/prototype/customer/UserBehavior.vue
  10. 694 0
      src/assets/templates/prototype/ecommerce/EcommerceAfterSalesManagement.vue
  11. 733 0
      src/assets/templates/prototype/ecommerce/EcommerceAnalytics.vue
  12. 707 0
      src/assets/templates/prototype/ecommerce/EcommerceLogisticsManagement.vue
  13. 647 0
      src/assets/templates/prototype/ecommerce/EcommerceMarketingManagement.vue
  14. 861 0
      src/assets/templates/prototype/ecommerce/EcommerceOrderManagement.vue
  15. 854 0
      src/assets/templates/prototype/ecommerce/EcommerceProductManagement.vue
  16. 807 0
      src/assets/templates/prototype/ecommerce/EcommerceReviewManagement.vue
  17. 795 0
      src/assets/templates/prototype/ecommerce/EcommerceUserManagement.vue
  18. 2565 0
      src/assets/templates/prototype/ecommerce/EcommerceVendorManagement.vue
  19. 2301 0
      src/assets/templates/prototype/ecommerce/ProductManagement.vue
  20. 809 0
      src/assets/templates/prototype/finance/EnterpriseDashboard.vue
  21. 344 0
      src/assets/templates/prototype/finance/FinancialManagement.vue
  22. 750 0
      src/assets/templates/prototype/finance/MarketingAnalytics.vue
  23. 717 0
      src/assets/templates/prototype/finance/ProductAnalytics.vue
  24. 435 0
      src/assets/templates/prototype/hr/AttendanceManagement.vue
  25. 424 0
      src/assets/templates/prototype/hr/HRManagement.vue
  26. 534 0
      src/assets/templates/prototype/hr/PerformanceManagement.vue
  27. 325 0
      src/assets/templates/prototype/hr/RecruitmentManagement.vue
  28. 453 0
      src/assets/templates/prototype/hr/SalaryManagement.vue
  29. 574 0
      src/assets/templates/prototype/hr/TrainingManagement.vue
  30. 453 0
      src/assets/templates/prototype/knowledge/DocumentManagement.vue
  31. 422 0
      src/assets/templates/prototype/knowledge/KnowledgeBaseManagement.vue
  32. 525 0
      src/assets/templates/prototype/production/AssetManagement.vue
  33. 747 0
      src/assets/templates/prototype/production/EquipmentManagement.vue
  34. 467 0
      src/assets/templates/prototype/production/ProductionManagement.vue
  35. 731 0
      src/assets/templates/prototype/production/QualityManagement.vue
  36. 509 0
      src/assets/templates/prototype/project/MeetingManagement.vue
  37. 362 0
      src/assets/templates/prototype/project/ProjectManagement.vue
  38. 477 0
      src/assets/templates/prototype/project/TaskManagement.vue
  39. 546 0
      src/assets/templates/prototype/sales/ContractManagement.vue
  40. 314 0
      src/assets/templates/prototype/sales/ReportManagement.vue
  41. 398 0
      src/assets/templates/prototype/sales/SalesManagement.vue
  42. 723 0
      src/assets/templates/prototype/supply-chain/InventoryAnalytics.vue
  43. 351 0
      src/assets/templates/prototype/supply-chain/InventoryManagement.vue
  44. 308 0
      src/assets/templates/prototype/supply-chain/LogisticsManagement.vue
  45. 549 0
      src/assets/templates/prototype/supply-chain/PurchaseManagement.vue
  46. 683 0
      src/assets/templates/prototype/supply-chain/SupplierManagement.vue
  47. 310 0
      src/assets/templates/prototype/system/LogManagement.vue
  48. 469 0
      src/assets/templates/prototype/system/NotificationManagement.vue
  49. 416 0
      src/assets/templates/prototype/system/PermissionManagement.vue
  50. 363 0
      src/assets/templates/prototype/system/RoleManagement.vue
  51. 181 0
      src/assets/templates/prototype/system/SystemSettings.vue
  52. 372 0
      src/assets/templates/prototype/system/UserManagement.vue
  53. 0 7
      template_desc.txt
  54. 49 0
      template_desc_prototype.txt

+ 1 - 1
README.md

@@ -62,4 +62,4 @@ tailwind.config tailwind 配置文件
 ```
 1. 请以ES6的方式引入图片
 2. 请检查是否存在图片被元素遮挡或图片的容器尺寸不足
-```
+```

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 367 - 767
package-lock.json


+ 1 - 0
package.json

@@ -9,6 +9,7 @@
     "preview": "vite preview"
   },
   "dependencies": {
+    "echarts": "^5.6.0",
     "lucide-vue-next": "^0.475.0",
     "vue": "^3.5.13",
     "vue-router": "^4.5.0"

+ 294 - 0
src/assets/templates/prototype/common/login.vue

@@ -0,0 +1,294 @@
+<template>
+  <div class="login-container">
+    <!-- Header -->
+    <header class="header">
+      <div class="logo">
+        <h1>XXX</h1>
+        <span>Logo</span>
+      </div>
+      <div class="language-selector">
+        <Globe class="globe-icon" size="16" />
+        <span>中文</span>
+        <ChevronDown class="chevron-icon" size="14" />
+      </div>
+    </header>
+
+    <!-- Main Content -->
+    <main class="main-content">
+      <div class="login-card">
+        <h2 class="greeting">"Hello, 欢迎回来</h2>
+        <p class="subtitle">请登录外包管理系统</p>
+
+        <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>
+
+          <div class="form-group">
+            <label for="password">密码</label>
+            <input 
+              type="password" 
+              id="password" 
+              v-model="password" 
+              placeholder="请输入"
+              class="form-input"
+            />
+          </div>
+
+          <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 type="submit" class="login-button">登录</button>
+        </form>
+
+        <div class="alternative-login">
+          <p>其他登录方式</p>
+          <a href="#" class="sms-login">使用短信验证码登录</a>
+        </div>
+      </div>
+    </main>
+
+    <!-- Footer - hidden on mobile -->
+    <footer class="footer">
+      <p>© 2023 上海外服 All Rights Reserved.</p>
+    </footer>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+import { Globe, ChevronDown } from 'lucide-vue-next';
+
+// Form data
+const username = ref('');
+const password = ref('');
+const rememberMe = ref(false);
+
+// Login handler
+const handleLogin = () => {
+  console.log('Login attempt:', { 
+    username: username.value, 
+    password: password.value,
+    rememberMe: rememberMe.value
+  });
+  // Add actual login logic here
+};
+</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;
+}
+
+.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>

+ 858 - 0
src/assets/templates/prototype/customer/CustomerManagement.vue

@@ -0,0 +1,858 @@
+<template>
+  <div class="p-6">
+    <!-- 头部操作区 -->
+    <div class="bg-white rounded-lg shadow p-6 mb-6">
+      <div class="flex justify-between items-center">
+        <h2 class="text-2xl font-bold text-gray-800">客户管理</h2>
+        <div class="flex space-x-4">
+          <button 
+            @click="showAddDialog = true"
+            class="flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
+          >
+            <PlusIcon class="w-5 h-5 mr-2" />
+            新增客户
+          </button>
+          <button 
+            @click="showAnalysisDialog = true"
+            class="flex items-center px-4 py-2 bg-yellow-500 text-white rounded-lg hover:bg-yellow-600 transition-colors"
+          >
+            <BarChartIcon class="w-5 h-5 mr-2" />
+            客户分析
+          </button>
+          <button 
+            @click="handleExport"
+            class="flex items-center px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors"
+          >
+            <DownloadIcon class="w-5 h-5 mr-2" />
+            导出数据
+          </button>
+          <div class="relative">
+            <input 
+              type="file" 
+              class="hidden" 
+              ref="fileInput"
+              @change="handleFileChange"
+            />
+            <button 
+              @click="$refs.fileInput.click()"
+              class="flex items-center px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
+            >
+              <UploadIcon class="w-5 h-5 mr-2" />
+              导入数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 筛选区 -->
+    <div class="bg-white rounded-lg shadow p-6 mb-6">
+      <div class="flex flex-wrap gap-4">
+        <div class="relative flex-1 min-w-[200px]">
+          <SearchIcon class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
+          <input 
+            v-model="searchQuery"
+            type="text"
+            placeholder="搜索客户名称/联系人/电话"
+            class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
+            @input="handleSearch"
+          />
+        </div>
+        <select 
+          v-model="filterLevel"
+          class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
+          @change="handleSearch"
+        >
+          <option value="">客户等级</option>
+          <option v-for="level in customerLevels" :key="level.value" :value="level.value">
+            {{ level.label }}
+          </option>
+        </select>
+        <select 
+          v-model="filterStatus"
+          class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
+          @change="handleSearch"
+        >
+          <option value="">客户状态</option>
+          <option v-for="status in customerStatuses" :key="status.value" :value="status.value">
+            {{ status.label }}
+          </option>
+        </select>
+        <div class="flex items-center space-x-2">
+          <input 
+            type="date" 
+            v-model="dateRange[0]"
+            class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
+            @change="handleSearch"
+          />
+          <span>至</span>
+          <input 
+            type="date" 
+            v-model="dateRange[1]"
+            class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
+            @change="handleSearch"
+          />
+        </div>
+      </div>
+    </div>
+
+    <!-- 客户列表 -->
+    <div class="bg-white rounded-lg shadow overflow-hidden">
+      <div class="overflow-x-auto">
+        <table class="min-w-full divide-y divide-gray-200">
+          <thead class="bg-gray-50">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
+                <input 
+                  type="checkbox" 
+                  v-model="selectAll"
+                  class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
+                />
+              </th>
+              <th 
+                v-for="column in columns" 
+                :key="column.prop"
+                class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider cursor-pointer"
+                @click="handleSort(column.prop)"
+              >
+                <div class="flex items-center">
+                  {{ column.label }}
+                  <span class="ml-1">
+                    <ChevronUpIcon v-if="sortKey === column.prop && sortOrder === 'asc'" class="h-4 w-4 inline-block" />
+                    <ChevronDownIcon v-else-if="sortKey === column.prop && sortOrder === 'desc'" class="h-4 w-4 inline-block" />
+                  </span>
+                </div>
+              </th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
+                操作
+              </th>
+            </tr>
+          </thead>
+          <tbody class="bg-white divide-y divide-gray-200">
+            <tr v-for="customer in filteredCustomers" :key="customer.id" class="hover:bg-gray-50">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <input 
+                  type="checkbox" 
+                  v-model="selectedItems"
+                  :value="customer.id"
+                  class="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
+                />
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">{{ customer.name }}</td>
+              <td class="px-6 py-4 whitespace-nowrap">{{ customer.contact }}</td>
+              <td class="px-6 py-4 whitespace-nowrap">{{ customer.phone }}</td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span 
+                  :class="[
+                    'px-2 py-1 text-xs font-semibold rounded-full',
+                    getLevelClass(customer.level)
+                  ]"
+                >
+                  {{ getLevelLabel(customer.level) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span 
+                  :class="[
+                    'px-2 py-1 text-xs font-semibold rounded-full',
+                    getStatusClass(customer.status)
+                  ]"
+                >
+                  {{ getStatusLabel(customer.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">{{ formatDateTime(customer.createTime) }}</td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="flex space-x-2">
+                  <button 
+                    @click="showDetail(customer)"
+                    class="px-3 py-1 text-sm text-blue-600 hover:text-blue-800"
+                  >
+                    详情
+                  </button>
+                  <button 
+                    @click="handleEdit(customer)"
+                    class="px-3 py-1 text-sm text-green-600 hover:text-green-800"
+                  >
+                    编辑
+                  </button>
+                  <button 
+                    @click="handleDelete(customer)"
+                    class="px-3 py-1 text-sm text-red-600 hover:text-red-800"
+                  >
+                    删除
+                  </button>
+                </div>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 批量操作 -->
+      <div v-if="selectedItems.length > 0" class="px-6 py-4 bg-gray-50 border-t border-gray-200">
+        <div class="flex items-center justify-between">
+          <span class="text-sm text-gray-600">已选择 {{ selectedItems.length }} 项</span>
+          <div class="flex space-x-4">
+            <button 
+              @click="handleBatchEdit"
+              class="flex items-center px-4 py-2 text-sm text-blue-600 hover:text-blue-800"
+            >
+              <EditIcon class="w-4 h-4 mr-1" />
+              批量编辑
+            </button>
+            <button 
+              @click="handleBatchDelete"
+              class="flex items-center px-4 py-2 text-sm text-red-600 hover:text-red-800"
+            >
+              <TrashIcon class="w-4 h-4 mr-1" />
+              批量删除
+            </button>
+          </div>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="px-6 py-4 bg-gray-50 border-t border-gray-200">
+        <div class="flex items-center justify-between">
+          <div class="flex items-center">
+            <span class="text-sm text-gray-700 mr-4">每页显示</span>
+            <select 
+              v-model="pageSize"
+              class="px-2 py-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+              @change="handleSizeChange"
+            >
+              <option v-for="size in [10, 20, 50, 100]" :key="size" :value="size">
+                {{ size }}
+              </option>
+            </select>
+          </div>
+          <div class="flex items-center space-x-2">
+            <button 
+              @click="currentPage--"
+              :disabled="currentPage === 1"
+              class="px-3 py-1 border border-gray-300 rounded-md disabled:opacity-50"
+            >
+              <ChevronLeftIcon class="w-4 h-4" />
+            </button>
+            <span class="text-sm text-gray-700">
+              第 {{ currentPage }} 页 / 共 {{ totalPages }} 页
+            </span>
+            <button 
+              @click="currentPage++"
+              :disabled="currentPage === totalPages"
+              class="px-3 py-1 border border-gray-300 rounded-md disabled:opacity-50"
+            >
+              <ChevronRightIcon class="w-4 h-4" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 客户统计 -->
+    <div class="grid grid-cols-4 gap-6 mt-6">
+      <div v-for="stat in statistics" :key="stat.title" class="bg-white rounded-lg shadow p-6">
+        <div class="text-gray-500 text-sm">{{ stat.title }}</div>
+        <div class="text-2xl font-bold text-gray-800 mt-2">{{ stat.value }}</div>
+      </div>
+    </div>
+
+    <!-- 客户分析图表 -->
+    <div class="bg-white rounded-lg shadow p-6 mt-6">
+      <div class="flex justify-between items-center mb-6">
+        <h3 class="text-lg font-semibold text-gray-800">客户分析</h3>
+        <div class="flex space-x-2">
+          <button 
+            v-for="type in ['level', 'status', 'growth']"
+            :key="type"
+            @click="analysisType = type"
+            :class="[
+              'px-4 py-2 rounded-lg',
+              analysisType === type 
+                ? 'bg-blue-600 text-white' 
+                : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+            ]"
+          >
+            {{ type === 'level' ? '等级分布' : type === 'status' ? '状态分布' : '增长趋势' }}
+          </button>
+        </div>
+      </div>
+      <div class="h-80" ref="analysisChart"></div>
+    </div>
+
+    <!-- 新增/编辑客户对话框 -->
+    <div v-if="showAddDialog" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
+      <div class="bg-white rounded-lg shadow-xl w-1/2 max-w-2xl">
+        <div class="flex justify-between items-center p-6 border-b">
+          <h3 class="text-lg font-semibold">{{ isEdit ? '编辑客户' : '新增客户' }}</h3>
+          <button @click="showAddDialog = false" class="text-gray-400 hover:text-gray-500">
+            <XIcon class="w-5 h-5" />
+          </button>
+        </div>
+        <form @submit.prevent="handleSubmit" class="p-6">
+          <div class="grid grid-cols-2 gap-6">
+            <div>
+              <label class="block text-sm font-medium text-gray-700 mb-1">客户名称</label>
+              <input 
+                v-model="addForm.name"
+                type="text"
+                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+                required
+              />
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 mb-1">客户等级</label>
+              <select 
+                v-model="addForm.level"
+                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+                required
+              >
+                <option v-for="level in customerLevels" :key="level.value" :value="level.value">
+                  {{ level.label }}
+                </option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 mb-1">联系人</label>
+              <input 
+                v-model="addForm.contact"
+                type="text"
+                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+                required
+              />
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 mb-1">联系电话</label>
+              <input 
+                v-model="addForm.phone"
+                type="tel"
+                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+                required
+              />
+            </div>
+          </div>
+          <div class="mt-6 flex justify-end space-x-4">
+            <button 
+              type="button"
+              @click="showAddDialog = false"
+              class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50"
+            >
+              取消
+            </button>
+            <button 
+              type="submit"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
+            >
+              确定
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 客户分析对话框 -->
+    <div v-if="showAnalysisDialog" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
+      <div class="bg-white rounded-lg shadow-xl w-3/4 max-w-4xl">
+        <div class="flex justify-between items-center p-6 border-b">
+          <h3 class="text-lg font-semibold">客户分析</h3>
+          <button @click="showAnalysisDialog = false" class="text-gray-400 hover:text-gray-500">
+            <XIcon class="w-5 h-5" />
+          </button>
+        </div>
+        <div class="p-6">
+          <div class="flex justify-center space-x-4 mb-6">
+            <button 
+              v-for="type in ['level', 'status', 'growth']"
+              :key="type"
+              @click="analysisType = type"
+              :class="[
+                'px-4 py-2 rounded-lg',
+                analysisType === type 
+                  ? 'bg-blue-600 text-white' 
+                  : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
+              ]"
+            >
+              {{ type === 'level' ? '等级分布' : type === 'status' ? '状态分布' : '增长趋势' }}
+            </button>
+          </div>
+          <div class="h-96" ref="analysisChart"></div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  PlusIcon, 
+  DownloadIcon, 
+  UploadIcon, 
+  SearchIcon, 
+  ChevronUpIcon,
+  ChevronDownIcon,
+  EditIcon,
+  TrashIcon,
+  ChevronLeftIcon,
+  ChevronRightIcon,
+  XIcon,
+  BarChartIcon
+} from 'lucide-vue-next'
+import { useRouter } from 'vue-router'
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+const router = useRouter()
+
+// Mock 数据
+const mockData = {
+  customers: {
+    list: [
+      {
+        id: 1,
+        name: '客户A',
+        contact: '张三',
+        phone: '13800138000',
+        level: 'vip',
+        status: 'active',
+        createTime: '2024-03-20T10:00:00'
+      },
+      {
+        id: 2,
+        name: '客户B',
+        contact: '李四',
+        phone: '13800138001',
+        level: 'normal',
+        status: 'inactive',
+        createTime: '2024-03-19T09:30:00'
+      }
+    ],
+    total: 2
+  },
+  statistics: {
+    totalCustomers: 100,
+    activeCustomers: 80,
+    vipCustomers: 20,
+    newCustomers: 10
+  }
+}
+
+// 状态管理
+const loading = ref(false)
+const searchQuery = ref('')
+const filterLevel = ref('')
+const filterStatus = ref('')
+const dateRange = ref(['', ''])
+const currentPage = ref(1)
+const pageSize = ref(10)
+const total = ref(0)
+const selectedItems = ref([])
+const showAddDialog = ref(false)
+const showAnalysisDialog = ref(false)
+const analysisType = ref('level')
+const isEdit = ref(false)
+const sortKey = ref('')
+const sortOrder = ref('asc')
+const analysisChart = ref(null)
+const statistics = ref([
+  { title: '总客户数', value: mockData.statistics.totalCustomers },
+  { title: '活跃客户', value: mockData.statistics.activeCustomers },
+  { title: 'VIP客户', value: mockData.statistics.vipCustomers },
+  { title: '新增客户', value: mockData.statistics.newCustomers }
+])
+const addForm = ref({
+  name: '',
+  level: '',
+  contact: '',
+  phone: ''
+})
+
+// 常量定义
+const customerLevels = [
+  { value: 'vip', label: 'VIP客户' },
+  { value: 'normal', label: '普通客户' }
+]
+
+const customerStatuses = [
+  { value: 'active', label: '活跃' },
+  { value: 'inactive', label: '非活跃' }
+]
+
+const columns = [
+  { prop: 'name', label: '客户名称' },
+  { prop: 'contact', label: '联系人' },
+  { prop: 'phone', label: '联系电话' },
+  { prop: 'level', label: '客户等级' },
+  { prop: 'status', label: '客户状态' },
+  { prop: 'createTime', label: '创建时间' }
+]
+
+// 计算属性
+const filteredCustomers = computed(() => {
+  return mockData.customers.list
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(total.value / pageSize.value)
+})
+
+const selectAll = computed({
+  get: () => selectedItems.value.length === filteredCustomers.value.length,
+  set: (value) => {
+    selectedItems.value = value ? filteredCustomers.value.map(c => c.id) : []
+  }
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+  fetchCustomers()
+}
+
+const handleSort = (prop) => {
+  if (sortKey.value === prop) {
+    sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
+  } else {
+    sortKey.value = prop
+    sortOrder.value = 'asc'
+  }
+  const sortedCustomers = [...filteredCustomers.value]
+  sortedCustomers.sort((a, b) => {
+    const aValue = a[prop]
+    const bValue = b[prop]
+    if (sortOrder.value === 'asc') {
+      return aValue > bValue ? 1 : -1
+    } else {
+      return aValue < bValue ? 1 : -1
+    }
+  })
+  filteredCustomers.value = sortedCustomers
+}
+
+const handleSizeChange = () => {
+  currentPage.value = 1
+  fetchCustomers()
+}
+
+const handleCurrentChange = (page) => {
+  currentPage.value = page
+  fetchCustomers()
+}
+
+const handleFileChange = (event) => {
+  const file = event.target.files[0]
+  if (file) {
+    // 处理文件上传
+  }
+}
+
+const handleExport = () => {
+  // 实现导出逻辑
+}
+
+const handleBatchEdit = () => {
+  // 实现批量编辑逻辑
+}
+
+const handleBatchDelete = () => {
+  // 实现批量删除逻辑
+}
+
+const showDetail = (customer) => {
+  // 实现查看详情逻辑
+}
+
+const handleEdit = (customer) => {
+  isEdit.value = true
+  addForm.value = { ...customer }
+  showAddDialog.value = true
+}
+
+const handleDelete = (customer) => {
+  // 实现删除逻辑
+}
+
+const handleSubmit = () => {
+  // 实现表单提交逻辑
+}
+
+const getLevelClass = (level) => {
+  return {
+    'bg-purple-100 text-purple-800': level === 'vip',
+    'bg-gray-100 text-gray-800': level === 'normal'
+  }
+}
+
+const getStatusClass = (status) => {
+  return {
+    'bg-green-100 text-green-800': status === 'active',
+    'bg-red-100 text-red-800': status === 'inactive'
+  }
+}
+
+const getLevelLabel = (level) => {
+  return customerLevels.find(l => l.value === level)?.label || level
+}
+
+const getStatusLabel = (status) => {
+  return customerStatuses.find(s => s.value === status)?.label || status
+}
+
+const formatDateTime = (dateString) => {
+  if (!dateString) return ''
+  const date = new Date(dateString)
+  return date.toLocaleString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    hour: '2-digit',
+    minute: '2-digit'
+  })
+}
+
+// 图表相关方法
+const initAnalysisChart = () => {
+  if (!analysisChart.value) return
+  
+  const chart = echarts.init(analysisChart.value)
+  
+  const updateChart = () => {
+    let option = {}
+    
+    switch (analysisType.value) {
+      case 'level':
+        option = {
+          title: {
+            text: '客户等级分布',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'item',
+            formatter: '{a} <br/>{b}: {c} ({d}%)'
+          },
+          legend: {
+            orient: 'vertical',
+            left: 'left',
+            data: ['VIP客户', '普通客户']
+          },
+          series: [
+            {
+              name: '客户等级',
+              type: 'pie',
+              radius: ['50%', '70%'],
+              avoidLabelOverlap: false,
+              itemStyle: {
+                borderRadius: 10,
+                borderColor: '#fff',
+                borderWidth: 2
+              },
+              label: {
+                show: false,
+                position: 'center'
+              },
+              emphasis: {
+                label: {
+                  show: true,
+                  fontSize: '20',
+                  fontWeight: 'bold'
+                }
+              },
+              labelLine: {
+                show: false
+              },
+              data: [
+                { value: mockData.statistics.vipCustomers, name: 'VIP客户' },
+                { value: mockData.statistics.totalCustomers - mockData.statistics.vipCustomers, name: '普通客户' }
+              ]
+            }
+          ]
+        }
+        break
+        
+      case 'status':
+        option = {
+          title: {
+            text: '客户状态分布',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'item',
+            formatter: '{a} <br/>{b}: {c} ({d}%)'
+          },
+          legend: {
+            orient: 'vertical',
+            left: 'left',
+            data: ['活跃客户', '非活跃客户']
+          },
+          series: [
+            {
+              name: '客户状态',
+              type: 'pie',
+              radius: ['50%', '70%'],
+              avoidLabelOverlap: false,
+              itemStyle: {
+                borderRadius: 10,
+                borderColor: '#fff',
+                borderWidth: 2
+              },
+              label: {
+                show: false,
+                position: 'center'
+              },
+              emphasis: {
+                label: {
+                  show: true,
+                  fontSize: '20',
+                  fontWeight: 'bold'
+                }
+              },
+              labelLine: {
+                show: false
+              },
+              data: [
+                { value: mockData.statistics.activeCustomers, name: '活跃客户' },
+                { value: mockData.statistics.totalCustomers - mockData.statistics.activeCustomers, name: '非活跃客户' }
+              ]
+            }
+          ]
+        }
+        break
+        
+      case 'growth':
+        option = {
+          title: {
+            text: '客户增长趋势',
+            left: 'center'
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'shadow'
+            }
+          },
+          legend: {
+            data: ['新增客户']
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
+          },
+          yAxis: {
+            type: 'value'
+          },
+          series: [
+            {
+              name: '新增客户',
+              type: 'line',
+              smooth: true,
+              data: [5, 8, 10, 12, 15, 18, 20, 22, 25, 28, 30, 35],
+              itemStyle: {
+                color: '#409EFF'
+              },
+              areaStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                  {
+                    offset: 0,
+                    color: 'rgba(64,158,255,0.3)'
+                  },
+                  {
+                    offset: 1,
+                    color: 'rgba(64,158,255,0.1)'
+                  }
+                ])
+              }
+            }
+          ]
+        }
+        break
+    }
+    
+    // 在设置新选项之前,先清除之前的图表
+    chart.clear()
+    chart.setOption(option)
+  }
+  
+  // 监听窗口大小变化
+  window.addEventListener('resize', () => {
+    chart.resize()
+  })
+  
+  // 监听分析类型变化
+  watch(analysisType, () => {
+    updateChart()
+  })
+  
+  // 初始化图表
+  updateChart()
+}
+
+// 生命周期钩子
+onMounted(() => {
+  fetchCustomers()
+  initAnalysisChart()
+})
+
+onUnmounted(() => {
+  if (analysisChart.value) {
+    echarts.dispose(analysisChart.value)
+  }
+})
+
+// 数据获取
+const fetchCustomers = async () => {
+  try {
+    loading.value = true
+    // 模拟网络延迟
+    await new Promise(resolve => setTimeout(resolve, 500))
+    total.value = mockData.customers.total
+  } catch (error) {
+    console.error('获取数据失败:', error)
+  } finally {
+    loading.value = false
+  }
+}
+
+// 添加 watch 监听对话框显示状态
+watch(showAnalysisDialog, (newVal) => {
+  if (newVal) {
+    // 对话框显示时初始化图表
+    nextTick(() => {
+      initAnalysisChart()
+    })
+  }
+})
+</script> 

+ 549 - 0
src/assets/templates/prototype/customer/CustomerRelationshipManagement.vue

@@ -0,0 +1,549 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">客户关系管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddCustomerModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              添加客户
+            </button>
+            <button @click="showAddFollowupModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              添加跟进
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 客户统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">总客户数</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalCustomers }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">活跃客户</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ activeCustomers }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">平均满意度</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ averageSatisfaction }}%</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">待跟进</div>
+          <div class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">{{ pendingFollowups }}</div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="客户名称/联系人" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有类型</option>
+              <option v-for="type in customerTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户等级</label>
+            <select v-model="filters.level" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有等级</option>
+              <option v-for="level in customerLevels" :key="level.id" :value="level.id">{{ level.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in statusTypes" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 客户列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">客户列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">客户信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">等级</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="customer in filteredCustomers" :key="customer.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ customer.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ customer.contact }}</div>
+                <div class="text-xs text-gray-500 dark:text-gray-400">{{ customer.phone }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ getCustomerTypeName(customer.type) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getCustomerLevelClass(customer.level)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getCustomerLevelName(customer.level) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getCustomerStatusClass(customer.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getCustomerStatusName(customer.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewCustomer(customer)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editCustomer(customer)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteCustomer(customer)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 跟进记录列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">跟进记录</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">客户</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">跟进方式</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">跟进内容</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">跟进人</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">跟进时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="followup in filteredFollowups" :key="followup.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ followup.customerName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ followup.contact }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ getFollowupTypeName(followup.type) }}
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ followup.content }}</div>
+                <div class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ followup.nextFollowupDate }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ followup.follower }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ formatDate(followup.date) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewFollowup(followup)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editFollowup(followup)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteFollowup(followup)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 添加客户模态框 -->
+    <div v-if="showAddCustomerModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加客户</h2>
+        <form @submit.prevent="addCustomer">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户名称</label>
+            <input type="text" v-model="newCustomer.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">联系人</label>
+            <input type="text" v-model="newCustomer.contact" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">联系电话</label>
+            <input type="tel" v-model="newCustomer.phone" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户类型</label>
+            <select v-model="newCustomer.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in customerTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户等级</label>
+            <select v-model="newCustomer.level" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="level in customerLevels" :key="level.id" :value="level.id">{{ level.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newCustomer.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddCustomerModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 添加跟进记录模态框 -->
+    <div v-if="showAddFollowupModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加跟进记录</h2>
+        <form @submit.prevent="addFollowup">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户</label>
+            <select v-model="newFollowup.customerId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="customer in customers" :key="customer.id" :value="customer.id">{{ customer.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">跟进方式</label>
+            <select v-model="newFollowup.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in followupTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">跟进内容</label>
+            <textarea v-model="newFollowup.content" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">下次跟进时间</label>
+            <input type="date" v-model="newFollowup.nextFollowupDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newFollowup.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddFollowupModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 客户数据
+const customers = ref([
+  {
+    id: 1,
+    name: 'ABC科技有限公司',
+    contact: '张三',
+    phone: '13800138000',
+    type: 1,
+    level: 2,
+    status: 1,
+    remark: '重要客户'
+  },
+  {
+    id: 2,
+    name: 'XYZ贸易有限公司',
+    contact: '李四',
+    phone: '13900139000',
+    type: 2,
+    level: 1,
+    status: 2,
+    remark: '潜在客户'
+  }
+])
+
+// 跟进记录数据
+const followups = ref([
+  {
+    id: 1,
+    customerId: 1,
+    customerName: 'ABC科技有限公司',
+    contact: '张三',
+    type: 1,
+    content: '讨论新项目需求',
+    follower: '王五',
+    date: '2024-03-15',
+    nextFollowupDate: '2024-03-22',
+    remark: '需要准备详细方案'
+  },
+  {
+    id: 2,
+    customerId: 2,
+    customerName: 'XYZ贸易有限公司',
+    contact: '李四',
+    type: 2,
+    content: '产品演示',
+    follower: '赵六',
+    date: '2024-03-16',
+    nextFollowupDate: '2024-03-23',
+    remark: '客户对产品很感兴趣'
+  }
+])
+
+// 客户类型
+const customerTypes = ref([
+  { id: 1, name: '企业客户' },
+  { id: 2, name: '个人客户' },
+  { id: 3, name: '政府机构' },
+  { id: 4, name: '教育机构' }
+])
+
+// 客户等级
+const customerLevels = ref([
+  { id: 1, name: '普通客户' },
+  { id: 2, name: '重要客户' },
+  { id: 3, name: 'VIP客户' }
+])
+
+// 客户状态
+const statusTypes = ref([
+  { id: 1, name: '活跃' },
+  { id: 2, name: '潜在' },
+  { id: 3, name: '流失' }
+])
+
+// 跟进方式
+const followupTypes = ref([
+  { id: 1, name: '电话' },
+  { id: 2, name: '拜访' },
+  { id: 3, name: '邮件' },
+  { id: 4, name: '会议' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  level: '',
+  status: ''
+})
+
+// 模态框状态
+const showAddCustomerModal = ref(false)
+const showAddFollowupModal = ref(false)
+
+// 新客户表单
+const newCustomer = ref({
+  name: '',
+  contact: '',
+  phone: '',
+  type: '',
+  level: '',
+  remark: ''
+})
+
+// 新跟进记录表单
+const newFollowup = ref({
+  customerId: '',
+  type: '',
+  content: '',
+  nextFollowupDate: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredCustomers = computed(() => {
+  return customers.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.name.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.contact.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || item.type === filters.value.type
+    const matchesLevel = !filters.value.level || item.level === filters.value.level
+    const matchesStatus = !filters.value.status || item.status === filters.value.status
+    return matchesSearch && matchesType && matchesLevel && matchesStatus
+  })
+})
+
+const filteredFollowups = computed(() => {
+  return followups.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.customerName.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.contact.toLowerCase().includes(searchText.value.toLowerCase())
+    return matchesSearch
+  })
+})
+
+const totalCustomers = computed(() => customers.value.length)
+
+const activeCustomers = computed(() => {
+  return customers.value.filter(item => item.status === 1).length
+})
+
+const averageSatisfaction = computed(() => {
+  // 这里假设有一个满意度评分系统
+  return 85
+})
+
+const pendingFollowups = computed(() => {
+  const today = new Date().toISOString().split('T')[0]
+  return followups.value.filter(item => item.nextFollowupDate <= today).length
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取客户类型名称
+const getCustomerTypeName = (typeId) => {
+  const type = customerTypes.value.find(t => t.id === typeId)
+  return type ? type.name : '未知类型'
+}
+
+// 获取客户等级名称
+const getCustomerLevelName = (levelId) => {
+  const level = customerLevels.value.find(l => l.id === levelId)
+  return level ? level.name : '未知等级'
+}
+
+// 获取客户状态名称
+const getCustomerStatusName = (statusId) => {
+  const status = statusTypes.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取跟进方式名称
+const getFollowupTypeName = (typeId) => {
+  const type = followupTypes.value.find(t => t.id === typeId)
+  return type ? type.name : '未知方式'
+}
+
+// 获取客户等级样式
+const getCustomerLevelClass = (levelId) => {
+  const classes = {
+    1: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-purple-100 text-purple-800 dark:bg-purple-700 dark:text-purple-300'
+  }
+  return classes[levelId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 获取客户状态样式
+const getCustomerStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加客户
+const addCustomer = () => {
+  const item = {
+    id: customers.value.length + 1,
+    ...newCustomer.value,
+    status: 1 // 默认为活跃状态
+  }
+  customers.value.push(item)
+  showAddCustomerModal.value = false
+  resetNewCustomer()
+}
+
+// 重置新客户表单
+const resetNewCustomer = () => {
+  newCustomer.value = {
+    name: '',
+    contact: '',
+    phone: '',
+    type: '',
+    level: '',
+    remark: ''
+  }
+}
+
+// 添加跟进记录
+const addFollowup = () => {
+  const customer = customers.value.find(c => c.id === newFollowup.value.customerId)
+  const item = {
+    id: followups.value.length + 1,
+    ...newFollowup.value,
+    customerName: customer.name,
+    contact: customer.contact,
+    follower: '当前用户', // 这里应该获取当前登录用户
+    date: new Date().toISOString().split('T')[0]
+  }
+  followups.value.push(item)
+  showAddFollowupModal.value = false
+  resetNewFollowup()
+}
+
+// 重置新跟进记录表单
+const resetNewFollowup = () => {
+  newFollowup.value = {
+    customerId: '',
+    type: '',
+    content: '',
+    nextFollowupDate: '',
+    remark: ''
+  }
+}
+
+// 查看客户
+const viewCustomer = (item) => {
+  // 实现查看客户逻辑
+  console.log('查看客户:', item)
+}
+
+// 编辑客户
+const editCustomer = (item) => {
+  // 实现编辑客户逻辑
+  console.log('编辑客户:', item)
+}
+
+// 删除客户
+const deleteCustomer = (item) => {
+  if (confirm(`确定要删除客户"${item.name}"吗?`)) {
+    const index = customers.value.findIndex(c => c.id === item.id)
+    if (index !== -1) {
+      customers.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看跟进记录
+const viewFollowup = (item) => {
+  // 实现查看跟进记录逻辑
+  console.log('查看跟进记录:', item)
+}
+
+// 编辑跟进记录
+const editFollowup = (item) => {
+  // 实现编辑跟进记录逻辑
+  console.log('编辑跟进记录:', item)
+}
+
+// 删除跟进记录
+const deleteFollowup = (item) => {
+  if (confirm(`确定要删除"${item.customerName}"的跟进记录吗?`)) {
+    const index = followups.value.findIndex(f => f.id === item.id)
+    if (index !== -1) {
+      followups.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 964 - 0
src/assets/templates/prototype/customer/CustomerServiceAnalytics.vue

@@ -0,0 +1,964 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">客服分析</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索客服/工单号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="serviceType"
+            @change="handleServiceTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类型</option>
+            <option value="consult">咨询</option>
+            <option value="complaint">投诉</option>
+            <option value="refund">退款</option>
+            <option value="technical">技术支持</option>
+          </select>
+          <select 
+            v-model="status"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="pending">待处理</option>
+            <option value="processing">处理中</option>
+            <option value="resolved">已解决</option>
+            <option value="closed">已关闭</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 客服统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <HeadphonesIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总工单数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockTickets.length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ClockIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">平均响应时间</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">15分钟</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <AlertTriangleIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">待处理工单</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockTickets.filter(ticket => ticket.status === 'pending').length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <XCircleIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">投诉工单</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockTickets.filter(ticket => ticket.type === 'complaint').length }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 客服分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">工单趋势</h3>
+          <div ref="trendChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">工单类型分布</h3>
+          <div ref="typeChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">用户增长趋势</h3>
+          <div ref="userGrowthChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">用户等级分布</h3>
+          <div ref="userLevelChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 工单列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">工单信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">客服</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">创建时间</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="ticket in paginatedTickets" :key="ticket.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-full object-cover" :src="ticket.customer.avatar" :alt="ticket.customer.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ ticket.title }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ ticket.customer.name }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['type-tag', `type-${ticket.type}`]">
+                    {{ ticket.type === 'consult' ? '咨询' : 
+                       ticket.type === 'complaint' ? '投诉' : 
+                       ticket.type === 'refund' ? '退款' : '技术支持' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-8 w-8">
+                      <img class="h-8 w-8 rounded-full object-cover" :src="ticket.agent.avatar" :alt="ticket.agent.name">
+                    </div>
+                    <div class="ml-3">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ ticket.agent.name }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ ticket.createTime }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${ticket.status}`]">
+                    {{ ticket.status === 'pending' ? '待处理' : 
+                       ticket.status === 'processing' ? '处理中' : 
+                       ticket.status === 'resolved' ? '已解决' : '已关闭' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewTicket(ticket)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleAssignTicket(ticket)"
+                    class="action-button edit-button"
+                  >
+                    <UserPlusIcon class="h-4 w-4 inline-block mr-1" />
+                    分配
+                  </button>
+                  <button 
+                    @click="handleCloseTicket(ticket)"
+                    class="action-button delete-button"
+                  >
+                    <XIcon class="h-4 w-4 inline-block mr-1" />
+                    关闭
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredTickets.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredTickets.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { CanvasRenderer } from 'echarts/renderers'
+import { LineChart, PieChart } from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+} from 'echarts/components'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  UsersIcon,
+  ActivityIcon,
+  TrendingUpIcon,
+  TargetIcon,
+  DownloadIcon,
+  EyeIcon,
+  UserPlusIcon,
+  XIcon,
+  HeadphonesIcon,
+  ClockIcon,
+  AlertTriangleIcon,
+  XCircleIcon
+} from 'lucide-vue-next'
+
+// 注册所有图标组件
+const icons = {
+  SearchIcon,
+  SettingsIcon,
+  ChevronLeftIcon,
+  ChevronRightIcon,
+  UsersIcon,
+  ActivityIcon,
+  TrendingUpIcon,
+  TargetIcon,
+  DownloadIcon,
+  EyeIcon,
+  UserPlusIcon,
+  XIcon,
+  HeadphonesIcon,
+  ClockIcon,
+  AlertTriangleIcon,
+  XCircleIcon
+}
+
+// 注册必要的组件
+echarts.use([
+  CanvasRenderer,
+  LineChart,
+  PieChart,
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const serviceType = ref('')
+const status = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalTickets = ref(100)
+
+// 默认图片
+const defaultImages = {
+  avatar: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop&auto=format'
+}
+
+const mockTickets = ref([
+  {
+    id: 'T1001',
+    customer: {
+      id: 'U1001',
+      name: '张三',
+      level: 'vip',
+      avatar: defaultImages.avatar
+    },
+    type: 'product',
+    title: '商品质量问题',
+    content: '收到的智能手表屏幕有划痕,要求换货',
+    status: 'pending',
+    priority: 'high',
+    agent: {
+      id: 'A1001',
+      name: '客服小王',
+      avatar: defaultImages.avatar
+    },
+    createTime: '2024-03-20 10:30:00',
+    updateTime: '2024-03-20 10:30:00',
+    responseTime: 0,
+    resolutionTime: 0
+  },
+  {
+    id: 'T1002',
+    customer: {
+      id: 'U1002',
+      name: '李四',
+      level: 'normal',
+      avatar: defaultImages.avatar
+    },
+    type: 'delivery',
+    title: '物流问题',
+    content: '订单已发货3天,物流信息未更新',
+    status: 'processing',
+    priority: 'medium',
+    agent: {
+      id: 'A1002',
+      name: '客服小李',
+      avatar: defaultImages.avatar
+    },
+    createTime: '2024-03-19 14:20:00',
+    updateTime: '2024-03-19 15:30:00',
+    responseTime: 70,
+    resolutionTime: 0
+  },
+  {
+    id: 'T1003',
+    customer: {
+      id: 'U1003',
+      name: '王五',
+      level: 'vip',
+      avatar: defaultImages.avatar
+    },
+    type: 'refund',
+    title: '退款申请',
+    content: '商品与描述不符,申请退款',
+    status: 'completed',
+    priority: 'high',
+    agent: {
+      id: 'A1001',
+      name: '客服小王',
+      avatar: defaultImages.avatar
+    },
+    createTime: '2024-03-18 09:15:00',
+    updateTime: '2024-03-18 11:30:00',
+    responseTime: 30,
+    resolutionTime: 135
+  },
+  {
+    id: 'T1004',
+    customer: {
+      id: 'U1004',
+      name: '赵六',
+      level: 'normal',
+      avatar: defaultImages.avatar
+    },
+    type: 'complaint',
+    title: '服务投诉',
+    content: '客服态度不好,要求道歉',
+    status: 'processing',
+    priority: 'high',
+    agent: {
+      id: 'A1003',
+      name: '客服小张',
+      avatar: defaultImages.avatar
+    },
+    createTime: '2024-03-17 16:45:00',
+    updateTime: '2024-03-17 17:00:00',
+    responseTime: 15,
+    resolutionTime: 0
+  },
+  {
+    id: 'T1005',
+    customer: {
+      id: 'U1005',
+      name: '钱七',
+      level: 'vip',
+      avatar: defaultImages.avatar
+    },
+    type: 'product',
+    title: '商品咨询',
+    content: '想了解新品的具体参数',
+    status: 'completed',
+    priority: 'low',
+    agent: {
+      id: 'A1002',
+      name: '客服小李',
+      avatar: defaultImages.avatar
+    },
+    createTime: '2024-03-16 11:25:00',
+    updateTime: '2024-03-16 11:40:00',
+    responseTime: 15,
+    resolutionTime: 15
+  }
+])
+
+// 客服统计数据
+const serviceStats = ref({
+  totalTickets: 1234,
+  avgResponseTime: 25,
+  pendingTickets: 56,
+  complaintTickets: 12
+})
+
+// 工单类型分布
+const ticketTypeDistribution = ref([
+  { type: 'product', value: 450 },
+  { type: 'delivery', value: 300 },
+  { type: 'refund', value: 250 },
+  { type: 'complaint', value: 150 },
+  { type: 'other', value: 84 }
+])
+
+// 客服绩效数据
+const agentPerformance = ref([
+  {
+    id: 'A1001',
+    name: '客服小王',
+    avatar: defaultImages.avatar,
+    totalTickets: 280,
+    avgResponseTime: 20,
+    avgResolutionTime: 45,
+    satisfactionRate: 0.95
+  },
+  {
+    id: 'A1002',
+    name: '客服小李',
+    avatar: defaultImages.avatar,
+    totalTickets: 250,
+    avgResponseTime: 25,
+    avgResolutionTime: 50,
+    satisfactionRate: 0.92
+  },
+  {
+    id: 'A1003',
+    name: '客服小张',
+    avatar: defaultImages.avatar,
+    totalTickets: 200,
+    avgResponseTime: 30,
+    avgResolutionTime: 60,
+    satisfactionRate: 0.88
+  }
+])
+
+// 图表相关
+const trendChartRef = ref(null)
+const typeChartRef = ref(null)
+const userGrowthChartRef = ref(null)
+const userLevelChartRef = ref(null)
+let trendChart = null
+let typeChart = null
+let userGrowthChart = null
+let userLevelChart = null
+
+// 模拟用户增长数据
+const mockUserGrowthData = ref([
+  { date: '2024-01', value: 1000 },
+  { date: '2024-02', value: 1200 },
+  { date: '2024-03', value: 1500 },
+  { date: '2024-04', value: 1800 },
+  { date: '2024-05', value: 2000 },
+  { date: '2024-06', value: 2200 }
+])
+
+// 模拟用户等级分布数据
+const mockUserLevelData = ref([
+  { value: 500, name: '普通用户' },
+  { value: 300, name: 'VIP用户' },
+  { value: 200, name: 'SVIP用户' },
+  { value: 100, name: '钻石用户' }
+])
+
+// 初始化趋势图表
+const initTrendChart = () => {
+  if (!trendChartRef.value) return
+  
+  if (trendChart) {
+    trendChart.dispose()
+  }
+  
+  trendChart = echarts.init(trendChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis'
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
+      boundaryGap: false
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '工单数量',
+        type: 'line',
+        data: [120, 132, 101, 134, 90, 230, 210],
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      }
+    ]
+  }
+  trendChart.setOption(option)
+}
+
+// 初始化类型分布图表
+const initTypeChart = () => {
+  if (!typeChartRef.value) return
+  
+  if (typeChart) {
+    typeChart.dispose()
+  }
+  
+  typeChart = echarts.init(typeChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}: {c} ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left',
+      top: 'middle'
+    },
+    series: [
+      {
+        name: '工单类型',
+        type: 'pie',
+        radius: ['40%', '70%'],
+        center: ['60%', '50%'],
+        data: [
+          { value: 235, name: '咨询' },
+          { value: 274, name: '投诉' },
+          { value: 310, name: '退款' },
+          { value: 335, name: '技术支持' }
+        ],
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 5,
+          borderColor: '#fff',
+          borderWidth: 2
+        }
+      }
+    ]
+  }
+  typeChart.setOption(option)
+}
+
+// 初始化用户增长趋势图表
+const initUserGrowthChart = () => {
+  if (!userGrowthChartRef.value) return
+  
+  if (userGrowthChart) {
+    userGrowthChart.dispose()
+  }
+  
+  userGrowthChart = echarts.init(userGrowthChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      formatter: '{b}<br/>{a}: {c}人'
+    },
+    xAxis: {
+      type: 'category',
+      data: mockUserGrowthData.value.map(item => item.date),
+      axisLabel: {
+        rotate: 45
+      }
+    },
+    yAxis: {
+      type: 'value',
+      name: '用户数量'
+    },
+    series: [
+      {
+        name: '用户数量',
+        type: 'line',
+        data: mockUserGrowthData.value.map(item => item.value),
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      }
+    ]
+  }
+  userGrowthChart.setOption(option)
+}
+
+// 初始化用户等级分布图表
+const initUserLevelChart = () => {
+  if (!userLevelChartRef.value) return
+  
+  if (userLevelChart) {
+    userLevelChart.dispose()
+  }
+  
+  userLevelChart = echarts.init(userLevelChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}: {c}人 ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '用户等级',
+        type: 'pie',
+        radius: '50%',
+        data: mockUserLevelData.value,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 5,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: true,
+          formatter: '{b}: {c}人'
+        }
+      }
+    ]
+  }
+  userLevelChart.setOption(option)
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (trendChart) trendChart.resize()
+  if (typeChart) typeChart.resize()
+  if (userGrowthChart) userGrowthChart.resize()
+  if (userLevelChart) userLevelChart.resize()
+}
+
+// 计算属性
+const filteredTickets = computed(() => {
+  let result = [...mockTickets.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(ticket => 
+      ticket.title.includes(searchText.value) ||
+      ticket.customer.name.includes(searchText.value) ||
+      ticket.agent.name.includes(searchText.value)
+    )
+  }
+  
+  // 类型过滤
+  if (serviceType.value) {
+    result = result.filter(ticket => ticket.type === serviceType.value)
+  }
+  
+  // 状态过滤
+  if (status.value) {
+    result = result.filter(ticket => ticket.status === status.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(ticket => {
+      const createTime = new Date(ticket.createTime)
+      
+      switch (timeRange.value) {
+        case 'today':
+          return createTime.toDateString() === now.toDateString()
+        case 'week':
+          const weekStart = new Date(now.setDate(now.getDate() - now.getDay()))
+          const weekEnd = new Date(weekStart)
+          weekEnd.setDate(weekStart.getDate() + 6)
+          return createTime >= weekStart && createTime <= weekEnd
+        case 'month':
+          const monthStart = new Date(now.getFullYear(), now.getMonth(), 1)
+          const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0)
+          return createTime >= monthStart && createTime <= monthEnd
+        case 'quarter':
+          const quarter = Math.floor(now.getMonth() / 3)
+          const quarterStart = new Date(now.getFullYear(), quarter * 3, 1)
+          const quarterEnd = new Date(now.getFullYear(), quarter * 3 + 3, 0)
+          return createTime >= quarterStart && createTime <= quarterEnd
+        default:
+          return true
+      }
+    })
+  }
+  
+  return result
+})
+
+const paginatedTickets = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredTickets.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredTickets.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleServiceTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewTicket = (ticket) => {
+  console.log('查看工单:', ticket)
+}
+
+const handleAssignTicket = (ticket) => {
+  console.log('分配工单:', ticket)
+}
+
+const handleCloseTicket = (ticket) => {
+  console.log('关闭工单:', ticket)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化图表
+  initTrendChart()
+  initTypeChart()
+  initUserGrowthChart()
+  initUserLevelChart()
+  
+  // 添加窗口大小变化监听
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  // 移除窗口大小变化监听
+  window.removeEventListener('resize', handleResize)
+  
+  // 销毁图表实例
+  if (trendChart) trendChart.dispose()
+  if (typeChart) typeChart.dispose()
+  if (userGrowthChart) userGrowthChart.dispose()
+  if (userLevelChart) userLevelChart.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 工单类型标签样式 */
+.type-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.type-consult {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.type-complaint {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+.type-refund {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.type-technical {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+/* 工单状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-pending {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-processing {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.status-resolved {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-closed {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.delete-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 357 - 0
src/assets/templates/prototype/customer/CustomerServiceManagement.vue

@@ -0,0 +1,357 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">客户服务管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddTicketModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建工单
+            </button>
+            <button @click="exportServiceData" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 服务统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">待处理工单</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ pendingTickets }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">今日处理</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ todayProcessed }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">平均响应时间</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ averageResponseTime }}分钟</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">客户满意度</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ satisfactionRate }}%</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">工单类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="type in ticketTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">工单状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in ticketStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">优先级</label>
+            <select v-model="filters.priority" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="工单号/客户名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 工单列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">工单信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">客户信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">优先级</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="ticket in filteredTickets" :key="ticket.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ ticket.number }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ ticket.type }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(ticket.createdAt) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ ticket.customerName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ ticket.customerContact }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getPriorityClass(ticket.priority)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getPriorityName(ticket.priority) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(ticket.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(ticket.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewTicket(ticket)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="processTicket(ticket)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">处理</button>
+                <button @click="closeTicket(ticket)" class="text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-300">关闭</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建工单模态框 -->
+    <div v-if="showAddTicketModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建工单</h2>
+        <form @submit.prevent="addTicket">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">工单类型</label>
+            <select v-model="newTicket.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in ticketTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户名称</label>
+            <input type="text" v-model="newTicket.customerName" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">联系方式</label>
+            <input type="text" v-model="newTicket.customerContact" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">优先级</label>
+            <select v-model="newTicket.priority" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">问题描述</label>
+            <textarea v-model="newTicket.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddTicketModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 工单数据
+const tickets = ref([
+  {
+    id: 1,
+    number: 'CS20240315001',
+    type: 1,
+    customerName: '张三',
+    customerContact: '13800138000',
+    priority: 2,
+    status: 1,
+    description: '产品使用问题咨询',
+    createdAt: new Date().toISOString()
+  },
+  {
+    id: 2,
+    number: 'CS20240315002',
+    type: 2,
+    customerName: '李四',
+    customerContact: '13900139000',
+    priority: 1,
+    status: 2,
+    description: '售后服务请求',
+    createdAt: new Date(Date.now() - 86400000).toISOString()
+  }
+])
+
+// 工单类型
+const ticketTypes = [
+  { id: 1, name: '咨询' },
+  { id: 2, name: '投诉' },
+  { id: 3, name: '建议' },
+  { id: 4, name: '售后' }
+]
+
+// 工单状态
+const ticketStatuses = [
+  { id: 1, name: '待处理' },
+  { id: 2, name: '处理中' },
+  { id: 3, name: '已完成' },
+  { id: 4, name: '已关闭' }
+]
+
+// 优先级
+const priorities = [
+  { id: 1, name: '低' },
+  { id: 2, name: '中' },
+  { id: 3, name: '高' },
+  { id: 4, name: '紧急' }
+]
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  status: '',
+  priority: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddTicketModal = ref(false)
+
+// 新工单表单
+const newTicket = ref({
+  type: '',
+  customerName: '',
+  customerContact: '',
+  priority: '',
+  description: ''
+})
+
+// 计算属性
+const filteredTickets = computed(() => {
+  return tickets.value.filter(ticket => {
+    const matchesType = !filters.value.type || ticket.type === filters.value.type
+    const matchesStatus = !filters.value.status || ticket.status === filters.value.status
+    const matchesPriority = !filters.value.priority || ticket.priority === filters.value.priority
+    const matchesSearch = !filters.value.search ||
+      ticket.number.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      ticket.customerName.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesStatus && matchesPriority && matchesSearch
+  })
+})
+
+const pendingTickets = computed(() => {
+  return tickets.value.filter(ticket => ticket.status === 1).length
+})
+
+const todayProcessed = computed(() => {
+  const today = new Date().toISOString().split('T')[0]
+  return tickets.value.filter(ticket => 
+    ticket.status === 3 && 
+    new Date(ticket.createdAt).toISOString().split('T')[0] === today
+  ).length
+})
+
+const averageResponseTime = computed(() => {
+  // 这里使用一个简单的计算方式,实际应用中应该根据实际的响应时间计算
+  return 30
+})
+
+const satisfactionRate = computed(() => {
+  // 这里使用一个简单的计算方式,实际应用中应该根据实际的满意度评价计算
+  return 95
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleString('zh-CN')
+}
+
+// 获取优先级名称
+const getPriorityName = (priorityId) => {
+  const priority = priorities.find(p => p.id === priorityId)
+  return priority ? priority.name : '未知'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = ticketStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取优先级样式
+const getPriorityClass = (priorityId) => {
+  const classes = {
+    1: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[priorityId] || classes[1]
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    4: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 添加工单
+const addTicket = () => {
+  const ticket = {
+    id: tickets.value.length + 1,
+    number: `CS${new Date().getTime()}`,
+    ...newTicket.value,
+    status: 1,
+    createdAt: new Date().toISOString()
+  }
+  tickets.value.push(ticket)
+  showAddTicketModal.value = false
+  resetNewTicket()
+}
+
+// 重置新工单表单
+const resetNewTicket = () => {
+  newTicket.value = {
+    type: '',
+    customerName: '',
+    customerContact: '',
+    priority: '',
+    description: ''
+  }
+}
+
+// 查看工单
+const viewTicket = (ticket) => {
+  // 实现查看工单逻辑
+  console.log('查看工单:', ticket)
+}
+
+// 处理工单
+const processTicket = (ticket) => {
+  if (confirm(`确定要处理工单 ${ticket.number} 吗?`)) {
+    ticket.status = 2
+  }
+}
+
+// 关闭工单
+const closeTicket = (ticket) => {
+  if (confirm(`确定要关闭工单 ${ticket.number} 吗?`)) {
+    ticket.status = 4
+  }
+}
+
+// 导出服务数据
+const exportServiceData = () => {
+  // 实现导出服务数据的逻辑
+  console.log('导出服务数据')
+}
+</script> 

+ 603 - 0
src/assets/templates/prototype/customer/UserBehavior.vue

@@ -0,0 +1,603 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">用户行为分析</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索用户ID/名称..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="userType"
+            @change="handleUserTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有用户类型</option>
+            <option value="new">新用户</option>
+            <option value="regular">普通用户</option>
+            <option value="vip">VIP用户</option>
+          </select>
+          <select 
+            v-model="behaviorType"
+            @change="handleBehaviorTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有行为类型</option>
+            <option value="browse">浏览</option>
+            <option value="search">搜索</option>
+            <option value="purchase">购买</option>
+            <option value="comment">评论</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 用户行为统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <UsersIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">活跃用户数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">12,345</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ActivityIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">平均访问时长</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">8.5分钟</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <ShoppingCartIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">转化率</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">3.2%</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <RepeatIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">复购率</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">45.6%</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 用户行为分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">用户行为趋势</h3>
+          <div ref="trendChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">行为类型分布</h3>
+          <div ref="distributionChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 用户行为列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">用户信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">用户类型</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">行为类型</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">行为详情</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">时间</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="behavior in paginatedBehaviors" :key="behavior.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-full object-cover" :src="behavior.user.avatar" :alt="behavior.user.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ behavior.user.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ behavior.user.id }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['user-type-tag', `type-${behavior.user.type}`]">
+                    {{ behavior.user.type === 'new' ? '新用户' : 
+                       behavior.user.type === 'regular' ? '普通用户' : 'VIP用户' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['behavior-type-tag', `type-${behavior.type}`]">
+                    {{ behavior.type === 'browse' ? '浏览' : 
+                       behavior.type === 'search' ? '搜索' : 
+                       behavior.type === 'purchase' ? '购买' : '评论' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ behavior.details }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ behavior.time }}</div>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewBehavior(behavior)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleExportBehavior(behavior)"
+                    class="action-button export-button"
+                  >
+                    <DownloadIcon class="h-4 w-4 inline-block mr-1" />
+                    导出
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredBehaviors.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredBehaviors.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  SearchIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  UsersIcon,
+  ActivityIcon,
+  ShoppingCartIcon,
+  RepeatIcon,
+  DownloadIcon,
+  EyeIcon,
+  ChevronUpIcon,
+  ChevronDownIcon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const userType = ref('')
+const behaviorType = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalBehaviors = ref(100)
+
+// 图表相关
+const trendChartRef = ref(null)
+const distributionChartRef = ref(null)
+let trendChart = null
+let distributionChart = null
+
+// Mock data
+// 模拟数据
+const mockUserBehaviors = ref([
+  {
+    id: 'B1001',
+    userId: 'U1001',
+    userName: '张三',
+    userType: 'vip',
+    userAvatar: 'https://images.unsplash.com/photo-1695048133148-1e0e1b0b0b0b',
+    behaviorType: 'browse',
+    targetId: 'P1001',
+    targetName: '智能手表 Pro',
+    targetType: 'product',
+    duration: 300,
+    timestamp: '2024-03-20 10:30:00',
+    location: '首页',
+    device: 'iPhone 13',
+    ip: '192.168.1.1'
+  },
+  {
+    id: 'B1002',
+    userId: 'U1002',
+    userName: '李四',
+    userType: 'normal',
+    userAvatar: 'https://images.unsplash.com/photo-1695048133148-1e0e1b0b0b0c',
+    behaviorType: 'search',
+    targetId: null,
+    targetName: '无线耳机',
+    targetType: 'keyword',
+    duration: 60,
+    timestamp: '2024-03-20 11:15:00',
+    location: '搜索页',
+    device: 'Huawei P40',
+    ip: '192.168.1.2'
+  },
+  {
+    id: 'B1003',
+    userId: 'U1003',
+    userName: '王五',
+    userType: 'vip',
+    userAvatar: 'https://images.unsplash.com/photo-1695048133148-1e0e1b0b0b0d',
+    behaviorType: 'add_to_cart',
+    targetId: 'P1002',
+    targetName: '无线耳机 Air',
+    targetType: 'product',
+    duration: 120,
+    timestamp: '2024-03-20 14:20:00',
+    location: '商品详情页',
+    device: 'iPad Pro',
+    ip: '192.168.1.3'
+  },
+  {
+    id: 'B1004',
+    userId: 'U1004',
+    userName: '赵六',
+    userType: 'normal',
+    userAvatar: 'https://images.unsplash.com/photo-1695048133148-1e0e1b0b0b0e',
+    behaviorType: 'purchase',
+    targetId: 'P1003',
+    targetName: '智能音箱 Mini',
+    targetType: 'product',
+    duration: 180,
+    timestamp: '2024-03-20 16:45:00',
+    location: '购物车',
+    device: 'Xiaomi 12',
+    ip: '192.168.1.4'
+  },
+  {
+    id: 'B1005',
+    userId: 'U1005',
+    userName: '钱七',
+    userType: 'vip',
+    userAvatar: 'https://images.unsplash.com/photo-1695048133148-1e0e1b0b0b0f',
+    behaviorType: 'review',
+    targetId: 'P1004',
+    targetName: '运动相机 4K',
+    targetType: 'product',
+    duration: 240,
+    timestamp: '2024-03-20 19:30:00',
+    location: '商品评价页',
+    device: 'MacBook Pro',
+    ip: '192.168.1.5'
+  }
+])
+
+// 用户行为统计数据
+const behaviorStats = ref({
+  totalBehaviors: 1234,
+  activeUsers: 1024,
+  avgSessionDuration: 180,
+  conversionRate: 0.15
+})
+
+// 行为类型分布
+const behaviorTypeDistribution = ref([
+  { type: 'browse', value: 450 },
+  { type: 'search', value: 300 },
+  { type: 'add_to_cart', value: 250 },
+  { type: 'purchase', value: 150 },
+  { type: 'review', value: 84 }
+])
+
+// 用户行为趋势
+const behaviorTrends = ref([
+  { date: '2024-03-01', behaviors: 120, users: 100, duration: 150 },
+  { date: '2024-03-02', behaviors: 150, users: 120, duration: 160 },
+  { date: '2024-03-03', behaviors: 180, users: 150, duration: 170 },
+  { date: '2024-03-04', behaviors: 200, users: 180, duration: 180 },
+  { date: '2024-03-05', behaviors: 220, users: 200, duration: 190 },
+  { date: '2024-03-06', behaviors: 250, users: 220, duration: 200 },
+  { date: '2024-03-07', behaviors: 280, users: 250, duration: 210 }
+])
+
+// 用户设备分布
+const deviceDistribution = ref([
+  { device: 'iPhone', value: 450 },
+  { device: 'Android', value: 300 },
+  { device: 'iPad', value: 250 },
+  { device: 'PC', value: 150 },
+  { device: 'Mac', value: 84 }
+])
+
+// 计算属性
+const filteredBehaviors = computed(() => {
+  let result = [...mockUserBehaviors.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(behavior => 
+      behavior.userName.includes(searchText.value) ||
+      behavior.userId.includes(searchText.value)
+    )
+  }
+  
+  // 用户类型过滤
+  if (userType.value) {
+    result = result.filter(behavior => behavior.userType === userType.value)
+  }
+  
+  // 行为类型过滤
+  if (behaviorType.value) {
+    result = result.filter(behavior => behavior.behaviorType === behaviorType.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(behavior => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedBehaviors = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredBehaviors.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredBehaviors.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleUserTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleBehaviorTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewBehavior = (behavior) => {
+  console.log('查看行为:', behavior)
+}
+
+const handleExportBehavior = (behavior) => {
+  console.log('导出行为:', behavior)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化数据
+  console.log('用户行为分析页面已加载')
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 用户类型标签样式 */
+.user-type-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.type-new {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.type-regular {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.type-vip {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+/* 行为类型标签样式 */
+.behavior-type-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.type-browse {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.type-search {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.type-purchase {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.type-comment {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.export-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 694 - 0
src/assets/templates/prototype/ecommerce/EcommerceAfterSalesManagement.vue

@@ -0,0 +1,694 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">售后管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索订单号/售后单号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="afterSalesType"
+            @change="handleTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类型</option>
+            <option value="refund">退款</option>
+            <option value="return">退货</option>
+            <option value="exchange">换货</option>
+            <option value="repair">维修</option>
+          </select>
+          <select 
+            v-model="afterSalesStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="pending">待处理</option>
+            <option value="processing">处理中</option>
+            <option value="completed">已完成</option>
+            <option value="rejected">已拒绝</option>
+            <option value="cancelled">已取消</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 售后统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <ClipboardListIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">待处理</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">23</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <ClockIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">处理中</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">15</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <CheckCircleIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">已完成</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">156</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <XCircleIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">已拒绝</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">8</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 售后分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">售后趋势</h3>
+          <div class="h-64">
+            <!-- 这里可以集成图表库,如 ECharts 或 Chart.js -->
+            <div id="afterSalesTrendChart" class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400"></div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">售后类型分布</h3>
+          <div class="h-64">
+            <!-- 这里可以集成图表库,如 ECharts 或 Chart.js -->
+            <div id="afterSalesDistributionChart" class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400"></div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 售后列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">售后信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">订单信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">申请信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="afterSales in paginatedAfterSales" :key="afterSales.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">售后单号: {{ afterSales.id }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ afterSales.createTime }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">订单号: {{ afterSales.orderId }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ afterSales.productName }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ afterSales.type === 'refund' ? '退款' : 
+                                                                                  afterSales.type === 'return' ? '退货' : 
+                                                                                  afterSales.type === 'exchange' ? '换货' : '维修' }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ afterSales.reason }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${afterSales.status}`]">
+                    {{ afterSales.status === 'pending' ? '待处理' : 
+                       afterSales.status === 'processing' ? '处理中' : 
+                       afterSales.status === 'completed' ? '已完成' : 
+                       afterSales.status === 'rejected' ? '已拒绝' : '已取消' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewAfterSales(afterSales)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleProcessAfterSales(afterSales)"
+                    class="action-button process-button"
+                  >
+                    <CheckIcon class="h-4 w-4 inline-block mr-1" />
+                    处理
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredAfterSales.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredAfterSales.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  ClipboardListIcon,
+  ClockIcon,
+  CheckCircleIcon,
+  XCircleIcon,
+  DownloadIcon,
+  EyeIcon,
+  CheckIcon
+} from 'lucide-vue-next'
+import * as echarts from 'echarts/core'
+import { CanvasRenderer } from 'echarts/renderers'
+import { LineChart, PieChart } from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  VisualMapComponent
+} from 'echarts/components'
+
+// 注册 ECharts 组件
+echarts.use([
+  CanvasRenderer,
+  LineChart,
+  PieChart,
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  VisualMapComponent
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const afterSalesType = ref('')
+const afterSalesStatus = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 模拟数据
+const mockAfterSales = ref([
+  {
+    id: 'AS1001',
+    orderId: 'O1001',
+    productName: 'iPhone 13 Pro',
+    type: 'refund',
+    reason: '商品质量问题',
+    status: 'pending',
+    createTime: '2024-03-20 10:30:00',
+    processTime: '',
+    completeTime: '',
+    amount: 8999,
+    description: '手机屏幕有划痕',
+    images: [],
+    processNotes: ''
+  },
+  {
+    id: 'AS1002',
+    orderId: 'O1002',
+    productName: 'MacBook Pro',
+    type: 'return',
+    reason: '商品与描述不符',
+    status: 'processing',
+    createTime: '2024-03-19 14:20:00',
+    processTime: '2024-03-19 15:30:00',
+    completeTime: '',
+    amount: 12999,
+    description: '配置与页面描述不一致',
+    images: ['image1.jpg', 'image2.jpg'],
+    processNotes: '已联系客户确认退货地址'
+  },
+  {
+    id: 'AS1003',
+    orderId: 'O1003',
+    productName: 'AirPods Pro',
+    type: 'exchange',
+    reason: '商品损坏',
+    status: 'completed',
+    createTime: '2024-03-18 09:15:00',
+    processTime: '2024-03-18 10:30:00',
+    completeTime: '2024-03-19 16:00:00',
+    amount: 1999,
+    description: '耳机右耳无法充电',
+    images: ['image3.jpg'],
+    processNotes: '已换新,客户已确认收货'
+  },
+  {
+    id: 'AS1004',
+    orderId: 'O1004',
+    productName: 'Apple Watch',
+    type: 'repair',
+    reason: '商品故障',
+    status: 'rejected',
+    createTime: '2024-03-17 16:45:00',
+    processTime: '2024-03-17 17:30:00',
+    completeTime: '2024-03-17 18:00:00',
+    amount: 3299,
+    description: '手表无法开机',
+    images: ['image4.jpg'],
+    processNotes: '经检测为人为损坏,不在保修范围内'
+  },
+  {
+    id: 'AS1005',
+    orderId: 'O1005',
+    productName: 'iPad Pro',
+    type: 'refund',
+    reason: '商品未收到',
+    status: 'cancelled',
+    createTime: '2024-03-16 11:25:00',
+    processTime: '',
+    completeTime: '2024-03-16 12:30:00',
+    amount: 6799,
+    description: '物流显示已签收,但未收到商品',
+    images: [],
+    processNotes: '客户取消申请,商品已找到'
+  }
+])
+
+// 售后统计数据
+const afterSalesStats = ref({
+  pending: 23,
+  processing: 15,
+  completed: 156,
+  rejected: 8
+})
+
+// 售后趋势数据
+const afterSalesTrends = ref([
+  { date: '2024-03-01', refunds: 10, returns: 5, exchanges: 3, repairs: 2 },
+  { date: '2024-03-02', refunds: 12, returns: 6, exchanges: 4, repairs: 1 },
+  { date: '2024-03-03', refunds: 15, returns: 7, exchanges: 5, repairs: 3 },
+  { date: '2024-03-04', refunds: 18, returns: 8, exchanges: 6, repairs: 2 },
+  { date: '2024-03-05', refunds: 20, returns: 9, exchanges: 7, repairs: 4 },
+  { date: '2024-03-06', refunds: 22, returns: 10, exchanges: 8, repairs: 3 },
+  { date: '2024-03-07', refunds: 25, returns: 12, exchanges: 9, repairs: 4 }
+])
+
+// 售后类型分布
+const afterSalesDistribution = ref([
+  { type: '退款', value: 120 },
+  { type: '退货', value: 80 },
+  { type: '换货', value: 50 },
+  { type: '维修', value: 30 }
+])
+
+// 计算属性
+const filteredAfterSales = computed(() => {
+  let result = [...mockAfterSales.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(afterSales => 
+      afterSales.id.includes(searchText.value) ||
+      afterSales.orderId.includes(searchText.value)
+    )
+  }
+  
+  // 类型过滤
+  if (afterSalesType.value) {
+    result = result.filter(afterSales => afterSales.type === afterSalesType.value)
+  }
+  
+  // 状态过滤
+  if (afterSalesStatus.value) {
+    result = result.filter(afterSales => afterSales.status === afterSalesStatus.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(afterSales => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedAfterSales = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredAfterSales.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredAfterSales.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewAfterSales = (afterSales) => {
+  console.log('查看售后:', afterSales)
+}
+
+const handleProcessAfterSales = (afterSales) => {
+  console.log('处理售后:', afterSales)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 图表实例
+const trendChart = ref(null)
+const distributionChart = ref(null)
+
+// 初始化趋势图表
+const initTrendChart = () => {
+  const chartDom = document.getElementById('afterSalesTrendChart')
+  if (!chartDom) return
+  
+  trendChart.value = echarts.init(chartDom)
+  const option = {
+    title: {
+      text: '售后趋势分析',
+      left: 'center'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['退款', '退货', '换货', '维修'],
+      bottom: 0
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '15%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: afterSalesTrends.value.map(item => item.date)
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '退款',
+        type: 'line',
+        data: afterSalesTrends.value.map(item => item.refunds)
+      },
+      {
+        name: '退货',
+        type: 'line',
+        data: afterSalesTrends.value.map(item => item.returns)
+      },
+      {
+        name: '换货',
+        type: 'line',
+        data: afterSalesTrends.value.map(item => item.exchanges)
+      },
+      {
+        name: '维修',
+        type: 'line',
+        data: afterSalesTrends.value.map(item => item.repairs)
+      }
+    ]
+  }
+  trendChart.value.setOption(option)
+}
+
+// 初始化分布图表
+const initDistributionChart = () => {
+  const chartDom = document.getElementById('afterSalesDistributionChart')
+  if (!chartDom) return
+  
+  distributionChart.value = echarts.init(chartDom)
+  const option = {
+    title: {
+      text: '售后类型分布',
+      left: 'center'
+    },
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '售后类型',
+        type: 'pie',
+        radius: '50%',
+        data: afterSalesDistribution.value.map(item => ({
+          name: item.type,
+          value: item.value
+        })),
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+  distributionChart.value.setOption(option)
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  trendChart.value?.resize()
+  distributionChart.value?.resize()
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化数据
+  console.log('售后管理页面已加载')
+  
+  // 初始化图表
+  initTrendChart()
+  initDistributionChart()
+  
+  // 添加窗口大小变化监听
+  window.addEventListener('resize', handleResize)
+})
+
+// 组件卸载时清理
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  trendChart.value?.dispose()
+  distributionChart.value?.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-pending {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-processing {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.status-completed {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-rejected {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+.status-cancelled {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.process-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 733 - 0
src/assets/templates/prototype/ecommerce/EcommerceAnalytics.vue

@@ -0,0 +1,733 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">数据分析</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="refreshData"
+              class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
+            >
+              <RefreshCwIcon class="h-6 w-6" />
+            </button>
+            <div class="relative">
+              <button 
+                @click="exportData"
+                class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+              >
+                <DownloadIcon class="h-5 w-5" />
+                <span>导出</span>
+              </button>
+              <select 
+                v-model="exportFormat"
+                class="absolute right-0 mt-1 w-32 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md shadow-lg py-1 px-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
+              >
+                <option value="csv">CSV</option>
+                <option value="excel">Excel</option>
+                <option value="json">JSON</option>
+              </select>
+            </div>
+            <button 
+              @click="shareData"
+              class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
+            >
+              <Share2Icon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 时间范围选择 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="flex flex-wrap gap-4">
+          <div class="flex items-center space-x-2">
+            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">时间范围:</label>
+            <select 
+              v-model="timeRange"
+              class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            >
+              <option value="today">今天</option>
+              <option value="week">本周</option>
+              <option value="month">本月</option>
+              <option value="quarter">本季度</option>
+              <option value="year">本年</option>
+            </select>
+          </div>
+          <div class="flex items-center space-x-2">
+            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">对比:</label>
+            <select 
+              v-model="comparison"
+              class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            >
+              <option value="none">不对比</option>
+              <option value="last_period">上期</option>
+              <option value="last_year">去年同期</option>
+            </select>
+          </div>
+          <div class="flex items-center space-x-2">
+            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">指标:</label>
+            <div class="flex flex-wrap gap-2">
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="selectedMetrics" value="sales" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">销售额</span>
+              </label>
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="selectedMetrics" value="orders" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">订单数</span>
+              </label>
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="selectedMetrics" value="visitors" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">访客数</span>
+              </label>
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="selectedMetrics" value="conversion" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">转化率</span>
+              </label>
+            </div>
+          </div>
+          <div class="flex items-center space-x-2">
+            <label class="text-sm font-medium text-gray-700 dark:text-gray-300">预测:</label>
+            <button 
+              @click="showPrediction = !showPrediction"
+              class="px-4 py-2 rounded-md flex items-center space-x-2"
+              :class="showPrediction ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-700'"
+            >
+              <TrendingUpIcon class="h-5 w-5" />
+              <span>{{ showPrediction ? '隐藏预测' : '显示预测' }}</span>
+            </button>
+          </div>
+        </div>
+      </div>
+
+      <!-- 图表控制栏 -->
+      <div class="mb-6 flex flex-wrap items-center justify-between gap-4">
+        <div class="flex items-center space-x-4">
+          <button 
+            @click="updateChartType('line')"
+            class="p-2 rounded-md"
+            :class="chartType === 'line' ? 'bg-blue-100 dark:bg-blue-900' : 'hover:bg-gray-100 dark:hover:bg-gray-700'"
+          >
+            <LineChartIcon class="h-6 w-6" />
+          </button>
+          <button 
+            @click="updateChartType('bar')"
+            class="p-2 rounded-md"
+            :class="chartType === 'bar' ? 'bg-blue-100 dark:bg-blue-900' : 'hover:bg-gray-100 dark:hover:bg-gray-700'"
+          >
+            <BarChartIcon class="h-6 w-6" />
+          </button>
+          <button 
+            @click="updateChartType('pie')"
+            class="p-2 rounded-md"
+            :class="chartType === 'pie' ? 'bg-blue-100 dark:bg-blue-900' : 'hover:bg-gray-100 dark:hover:bg-gray-700'"
+          >
+            <PieChartIcon class="h-6 w-6" />
+          </button>
+        </div>
+        <div class="flex items-center space-x-4">
+          <button 
+            @click="compareData"
+            class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
+          >
+            数据对比
+          </button>
+        </div>
+      </div>
+
+      <!-- 图表区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div ref="chartRef" class="h-96"></div>
+      </div>
+
+      <!-- 关键指标卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100">
+              <DollarSignIcon class="h-6 w-6 text-blue-600" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600">总销售额</p>
+              <p class="text-2xl font-semibold text-gray-900">¥123,456</p>
+              <p class="text-sm text-green-600">↑ 12.5%</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100">
+              <ShoppingCartIcon class="h-6 w-6 text-green-600" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600">订单数量</p>
+              <p class="text-2xl font-semibold text-gray-900">1,234</p>
+              <p class="text-sm text-green-600">↑ 8.3%</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100">
+              <UsersIcon class="h-6 w-6 text-yellow-600" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600">访客数</p>
+              <p class="text-2xl font-semibold text-gray-900">5,678</p>
+              <p class="text-sm text-green-600">↑ 15.2%</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100">
+              <PercentIcon class="h-6 w-6 text-purple-600" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600">转化率</p>
+              <p class="text-2xl font-semibold text-gray-900">21.7%</p>
+              <p class="text-sm text-green-600">↑ 2.3%</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 数据表格 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">详细数据</h2>
+          <div class="flex items-center space-x-4">
+            <div class="relative">
+              <input
+                v-model="filterText"
+                type="text"
+                placeholder="搜索..."
+                class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+              >
+              <FilterIcon class="absolute right-3 top-2.5 h-5 w-5 text-gray-400" />
+            </div>
+          </div>
+        </div>
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th 
+                  v-for="(header, index) in ['日期', '销售额', '订单数', '访客数', '转化率', '客单价']"
+                  :key="index"
+                  class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-600"
+                  @click="toggleSort(['date', 'sales', 'orders', 'visitors', 'conversion', 'avgPrice'][index])"
+                >
+                  <div class="flex items-center space-x-1">
+                    <span>{{ header }}</span>
+                    <component 
+                      :is="getSortIcon(['date', 'sales', 'orders', 'visitors', 'conversion', 'avgPrice'][index])"
+                      v-if="getSortIcon(['date', 'sales', 'orders', 'visitors', 'conversion', 'avgPrice'][index])"
+                      class="h-4 w-4"
+                    />
+                  </div>
+                </th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr 
+                v-for="item in filteredData" 
+                :key="item.date"
+                class="hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer"
+                :class="{ 'bg-blue-50 dark:bg-blue-900': selectedDate === item.date }"
+                @click="handleDateSelect(item.date)"
+              >
+                <td class="px-6 py-4 text-sm text-gray-900 dark:text-white">{{ item.date }}</td>
+                <td class="px-6 py-4 text-sm text-gray-900 dark:text-white">¥{{ item.sales }}</td>
+                <td class="px-6 py-4 text-sm text-gray-900 dark:text-white">{{ item.orders }}</td>
+                <td class="px-6 py-4 text-sm text-gray-900 dark:text-white">{{ item.visitors }}</td>
+                <td class="px-6 py-4 text-sm text-gray-900 dark:text-white">{{ item.conversion }}%</td>
+                <td class="px-6 py-4 text-sm text-gray-900 dark:text-white">¥{{ item.avgPrice }}</td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  RefreshCwIcon, 
+  DownloadIcon, 
+  Share2Icon,
+  LineChartIcon,
+  BarChartIcon,
+  PieChartIcon,
+  DollarSignIcon,
+  ShoppingCartIcon,
+  UsersIcon,
+  PercentIcon,
+  FilterIcon,
+  ArrowUpIcon,
+  ArrowDownIcon,
+  ChevronUpIcon,
+  ChevronDownIcon,
+  TrendingUpIcon,
+  TrendingDownIcon,
+  AlertCircleIcon,
+  CameraIcon,
+  ClockIcon,
+  XIcon,
+  BrainIcon,
+  LinkIcon,
+  EyeIcon,
+  FileSpreadsheetIcon,
+  LayersIcon,
+  FileTextIcon,
+  LightbulbIcon,
+  BookOpenIcon,
+  SparklesIcon,
+  CompassIcon,
+  ActivityIcon
+} from 'lucide-vue-next'
+
+// 状态管理
+const timeRange = ref('week')
+const comparison = ref('none')
+const selectedMetrics = ref(['sales', 'orders'])
+const showPrediction = ref(false)
+const chartType = ref('line')
+const exportFormat = ref('csv')
+const filterText = ref('')
+const sortField = ref('date')
+const sortOrder = ref('asc')
+const selectedDate = ref(null)
+
+// 图表相关
+const chartRef = ref(null)
+let chartInstance = null
+
+// Mock data
+const mockData = ref([
+  { date: '2024-03-01', sales: 12345, orders: 123, visitors: 567, conversion: 21.7, avgPrice: 100.37 },
+  { date: '2024-03-02', sales: 13456, orders: 134, visitors: 589, conversion: 22.7, avgPrice: 100.42 },
+  { date: '2024-03-03', sales: 14567, orders: 145, visitors: 612, conversion: 23.7, avgPrice: 100.46 },
+  { date: '2024-03-04', sales: 15678, orders: 156, visitors: 634, conversion: 24.6, avgPrice: 100.50 },
+  { date: '2024-03-05', sales: 16789, orders: 167, visitors: 657, conversion: 25.4, avgPrice: 100.53 },
+  { date: '2024-03-06', sales: 17890, orders: 178, visitors: 679, conversion: 26.2, avgPrice: 100.51 },
+  { date: '2024-03-07', sales: 18901, orders: 189, visitors: 702, conversion: 26.9, avgPrice: 100.01 }
+])
+
+// 计算属性
+const filteredData = computed(() => {
+  let result = [...mockData.value]
+  
+  // 过滤
+  if (filterText.value) {
+    result = result.filter(item => 
+      item.date.includes(filterText.value) ||
+      item.sales.toString().includes(filterText.value) ||
+      item.orders.toString().includes(filterText.value) ||
+      item.visitors.toString().includes(filterText.value) ||
+      item.conversion.toString().includes(filterText.value) ||
+      item.avgPrice.toString().includes(filterText.value)
+    )
+  }
+  
+  // 排序
+  if (sortField.value) {
+    result.sort((a, b) => {
+      const aValue = a[sortField.value]
+      const bValue = b[sortField.value]
+      return sortOrder.value === 'asc' ? aValue - bValue : bValue - aValue
+    })
+  }
+  
+  return result
+})
+
+// 方法
+const refreshData = () => {
+  // 模拟刷新数据
+  updateChart()
+}
+
+const exportData = () => {
+  // 模拟导出数据
+  console.log('导出数据:', exportFormat.value)
+}
+
+const shareData = () => {
+  // 模拟分享数据
+  console.log('分享数据')
+}
+
+const compareData = () => {
+  // 模拟数据对比
+  console.log('数据对比')
+}
+
+const toggleSort = (field) => {
+  if (sortField.value === field) {
+    sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
+  } else {
+    sortField.value = field
+    sortOrder.value = 'asc'
+  }
+}
+
+const getSortIcon = (field) => {
+  if (sortField.value !== field) return null
+  return sortOrder.value === 'asc' ? ChevronUpIcon : ChevronDownIcon
+}
+
+const handleDateSelect = (date) => {
+  selectedDate.value = selectedDate.value === date ? null : date
+}
+
+// 初始化图表
+const initChart = () => {
+  if (chartInstance) {
+    chartInstance.dispose()
+  }
+  chartInstance = echarts.init(chartRef.value)
+  updateChart()
+}
+
+// 更新图表
+const updateChart = () => {
+  if (!chartInstance) return
+
+  const options = {
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['销售额', '订单数', '访客数', '转化率']
+    },
+    xAxis: {
+      type: 'category',
+      data: mockData.value.map(item => item.date)
+    },
+    yAxis: [
+      {
+        type: 'value',
+        name: '金额/数量'
+      },
+      {
+        type: 'value',
+        name: '转化率',
+        axisLabel: {
+          formatter: '{value}%'
+        }
+      }
+    ],
+    series: [
+      {
+        name: '销售额',
+        type: chartType.value,
+        data: mockData.value.map(item => item.sales)
+      },
+      {
+        name: '订单数',
+        type: chartType.value,
+        data: mockData.value.map(item => item.orders)
+      },
+      {
+        name: '访客数',
+        type: chartType.value,
+        data: mockData.value.map(item => item.visitors)
+      },
+      {
+        name: '转化率',
+        type: chartType.value,
+        yAxisIndex: 1,
+        data: mockData.value.map(item => item.conversion)
+      }
+    ]
+  }
+
+  if (chartType.value === 'pie') {
+    options.series = [{
+      type: 'pie',
+      radius: '50%',
+      data: [
+        { value: mockData.value[mockData.value.length - 1].sales, name: '销售额' },
+        { value: mockData.value[mockData.value.length - 1].orders, name: '订单数' },
+        { value: mockData.value[mockData.value.length - 1].visitors, name: '访客数' },
+        { value: mockData.value[mockData.value.length - 1].conversion, name: '转化率' }
+      ]
+    }]
+  }
+
+  chartInstance.setOption(options)
+}
+
+// 更新图表类型
+const updateChartType = (type) => {
+  chartType.value = type
+  updateChart()
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (chartInstance) {
+    chartInstance.resize()
+  }
+}
+
+// 生命周期钩子
+onMounted(() => {
+  initChart()
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  if (chartInstance) {
+    chartInstance.dispose()
+  }
+})
+
+// 监听数据变化
+watch([timeRange, comparison, selectedMetrics, showPrediction], () => {
+  updateChart()
+})
+</script>
+
+<style scoped>
+/* 响应式布局 */
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 图表缩放动画 */
+.chart-container {
+  @apply transition-transform duration-300 ease-in-out;
+}
+
+/* 数据钻取动画 */
+.drill-down {
+  @apply animate-[drillDown_0.3s_ease];
+}
+
+@keyframes drillDown {
+  from {
+    @apply scale-95 opacity-0;
+  }
+  to {
+    @apply scale-100 opacity-100;
+  }
+}
+
+/* 预警动画 */
+@keyframes pulse {
+  0% {
+    @apply scale-100;
+  }
+  50% {
+    @apply scale-105;
+  }
+  100% {
+    @apply scale-100;
+  }
+}
+
+.alert-pulse {
+  @apply animate-[pulse_2s_infinite];
+}
+
+/* 注释样式 */
+.comment-bubble {
+  @apply relative bg-gray-100 rounded-lg p-2 mt-2;
+}
+
+.comment-bubble::before {
+  content: '';
+  @apply absolute -top-2 left-4 border-2 border-transparent border-b-gray-100;
+}
+
+/* 趋势分析动画 */
+@keyframes trendUp {
+  from {
+    @apply translate-y-2.5 opacity-0;
+  }
+  to {
+    @apply translate-y-0 opacity-100;
+  }
+}
+
+.trend-up {
+  @apply animate-[trendUp_0.3s_ease-out];
+}
+
+@keyframes trendDown {
+  from {
+    @apply -translate-y-2.5 opacity-0;
+  }
+  to {
+    @apply translate-y-0 opacity-100;
+  }
+}
+
+.trend-down {
+  @apply animate-[trendDown_0.3s_ease-out];
+}
+
+/* 异常检测样式 */
+.anomaly-high {
+  @apply border-l-4 border-red-500;
+}
+
+.anomaly-low {
+  @apply border-l-4 border-yellow-500;
+}
+
+/* 快照样式 */
+.snapshot-card {
+  @apply transition-transform duration-200 ease-in-out;
+}
+
+.snapshot-card:hover {
+  @apply -translate-y-0.5;
+}
+
+/* 预测模型样式 */
+.prediction-error {
+  @apply transition-colors duration-300 ease-in-out;
+}
+
+/* 关联分析样式 */
+.correlation-cell {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.correlation-cell:hover {
+  @apply scale-105;
+}
+
+/* 可视化设置样式 */
+.setting-item {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.setting-item:hover {
+  @apply bg-black/5;
+}
+
+/* 导出模板样式 */
+.template-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.template-card:hover {
+  @apply -translate-y-0.5;
+}
+
+/* 聚类分析样式 */
+.cluster-card {
+  @apply transition-transform duration-200 ease-in-out;
+}
+
+.cluster-card:hover {
+  @apply -translate-y-0.5;
+}
+
+/* 时间序列分析样式 */
+.time-series-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.time-series-card:hover {
+  @apply bg-black/5;
+}
+
+/* 报告生成样式 */
+.report-template {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.report-template:hover {
+  @apply translate-x-1;
+}
+
+/* 数据洞察样式 */
+.insight-card {
+  @apply transition-transform duration-200 ease-in-out;
+}
+
+.insight-card:hover {
+  @apply -translate-y-0.5;
+}
+
+/* 数据故事样式 */
+.story-section {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.story-section:hover {
+  @apply bg-black/5;
+}
+
+/* 协作样式 */
+.collaborator-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.collaborator-card:hover {
+  @apply bg-black/5;
+}
+
+.comment-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.comment-card:hover {
+  @apply translate-x-1;
+}
+
+/* 智能推荐样式 */
+.recommendation-card {
+  @apply transition-transform duration-200 ease-in-out;
+}
+
+.recommendation-card:hover {
+  @apply -translate-y-0.5;
+}
+
+/* 数据探索样式 */
+.exploration-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.exploration-card:hover {
+  @apply bg-black/5;
+}
+
+/* 监控面板样式 */
+.monitoring-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.monitoring-card:hover {
+  @apply scale-105;
+}
+
+.alert-card {
+  @apply transition-all duration-200 ease-in-out;
+}
+
+.alert-card:hover {
+  @apply translate-x-1;
+}
+</style> 

+ 707 - 0
src/assets/templates/prototype/ecommerce/EcommerceLogisticsManagement.vue

@@ -0,0 +1,707 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">物流管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索订单号/物流单号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="logisticsStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="pending">待发货</option>
+            <option value="shipped">已发货</option>
+            <option value="in_transit">运输中</option>
+            <option value="delivered">已送达</option>
+            <option value="returned">已退回</option>
+            <option value="exception">异常</option>
+          </select>
+          <select 
+            v-model="logisticsCompany"
+            @change="handleCompanyChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有物流公司</option>
+            <option value="sf">顺丰速运</option>
+            <option value="sto">申通快递</option>
+            <option value="yto">圆通速递</option>
+            <option value="zto">中通快递</option>
+            <option value="ems">EMS</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 物流统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <PackageIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">待发货</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">56</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <TruckIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">运输中</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">123</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <CheckCircleIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">已送达</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,024</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <AlertTriangleIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">异常订单</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">12</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 物流分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">物流时效分析</h3>
+          <div ref="deliveryTimeChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">物流公司分布</h3>
+          <div ref="companyDistributionChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 物流订单列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">订单信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">物流信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">收货信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="order in paginatedOrders" :key="order.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.orderNo }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.createTime }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.logisticsNo }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.logisticsCompany }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.receiverName }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.receiverPhone }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.receiverAddress }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span 
+                    :class="[
+                      'px-2 inline-flex text-xs leading-5 font-semibold rounded-full',
+                      getStatusClass(order.status)
+                    ]"
+                  >
+                    {{ getStatusText(order.status) }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewOrder(order)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    v-if="order.status === 'pending'"
+                    @click="handleShipOrder(order)"
+                    class="action-button ship-button"
+                  >
+                    <TruckIcon class="h-4 w-4 inline-block mr-1" />
+                    发货
+                  </button>
+                  <button 
+                    v-if="order.status === 'exception'"
+                    @click="handleHandleException(order)"
+                    class="action-button exception-button"
+                  >
+                    <AlertTriangleIcon class="h-4 w-4 inline-block mr-1" />
+                    处理异常
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredOrders.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredOrders.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { CanvasRenderer } from 'echarts/renderers'
+import { LineChart, PieChart } from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+} from 'echarts/components'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  PackageIcon,
+  TruckIcon,
+  CheckCircleIcon,
+  AlertTriangleIcon,
+  DownloadIcon,
+  EyeIcon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  CanvasRenderer,
+  LineChart,
+  PieChart,
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const logisticsStatus = ref('')
+const logisticsCompany = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 模拟数据
+const mockOrders = ref([
+  {
+    id: 'L1001',
+    orderNo: '202403200001',
+    logisticsNo: 'SF1234567890',
+    logisticsCompany: '顺丰速运',
+    receiverName: '张三',
+    receiverPhone: '13800138000',
+    receiverAddress: '广东省深圳市南山区科技园路1号',
+    status: 'pending',
+    createTime: '2024-03-20 10:30:00'
+  },
+  {
+    id: 'L1002',
+    orderNo: '202403200002',
+    logisticsNo: 'STO9876543210',
+    logisticsCompany: '申通快递',
+    receiverName: '李四',
+    receiverPhone: '13900139000',
+    receiverAddress: '北京市朝阳区建国路88号',
+    status: 'shipped',
+    createTime: '2024-03-19 14:20:00'
+  },
+  {
+    id: 'L1003',
+    orderNo: '202403200003',
+    logisticsNo: 'YTO5678901234',
+    logisticsCompany: '圆通速递',
+    receiverName: '王五',
+    receiverPhone: '13700137000',
+    receiverAddress: '上海市浦东新区张江高科技园区',
+    status: 'in_transit',
+    createTime: '2024-03-18 09:15:00'
+  },
+  {
+    id: 'L1004',
+    orderNo: '202403200004',
+    logisticsNo: 'ZTO3456789012',
+    logisticsCompany: '中通快递',
+    receiverName: '赵六',
+    receiverPhone: '13600136000',
+    receiverAddress: '浙江省杭州市西湖区文三路100号',
+    status: 'delivered',
+    createTime: '2024-03-17 16:45:00'
+  },
+  {
+    id: 'L1005',
+    orderNo: '202403200005',
+    logisticsNo: 'EMS9012345678',
+    logisticsCompany: 'EMS',
+    receiverName: '钱七',
+    receiverPhone: '13500135000',
+    receiverAddress: '江苏省南京市鼓楼区中山路200号',
+    status: 'exception',
+    createTime: '2024-03-16 11:25:00'
+  }
+])
+
+// 物流统计数据
+const logisticsStats = ref({
+  pendingShipment: 56,
+  inTransit: 123,
+  delivered: 1024,
+  exception: 12
+})
+
+// 物流时效分析数据
+const deliveryTimeAnalysis = ref([
+  { date: '2024-03-01', avgTime: 2.5, maxTime: 4, minTime: 1 },
+  { date: '2024-03-02', avgTime: 2.3, maxTime: 3.5, minTime: 1.2 },
+  { date: '2024-03-03', avgTime: 2.7, maxTime: 4.2, minTime: 1.5 },
+  { date: '2024-03-04', avgTime: 2.4, maxTime: 3.8, minTime: 1.3 },
+  { date: '2024-03-05', avgTime: 2.6, maxTime: 4.1, minTime: 1.4 },
+  { date: '2024-03-06', avgTime: 2.8, maxTime: 4.5, minTime: 1.6 },
+  { date: '2024-03-07', avgTime: 2.5, maxTime: 4.3, minTime: 1.3 }
+])
+
+// 物流公司分布数据
+const logisticsCompanyDistribution = ref([
+  { company: '顺丰速运', count: 300, amount: 300000 },
+  { company: '申通快递', count: 250, amount: 250000 },
+  { company: '圆通速递', count: 200, amount: 200000 },
+  { company: '中通快递', count: 180, amount: 180000 },
+  { company: 'EMS', count: 70, amount: 70000 }
+])
+
+// 图表相关
+const deliveryTimeChartRef = ref(null)
+const companyDistributionChartRef = ref(null)
+let deliveryTimeChart = null
+let companyDistributionChart = null
+
+// 初始化物流时效分析图表
+const initDeliveryTimeChart = () => {
+  if (!deliveryTimeChartRef.value) return
+  
+  if (deliveryTimeChart) {
+    deliveryTimeChart.dispose()
+  }
+  
+  deliveryTimeChart = echarts.init(deliveryTimeChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'cross'
+      }
+    },
+    legend: {
+      data: ['平均时效', '最长时效', '最短时效']
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: deliveryTimeAnalysis.value.map(item => item.date),
+      boundaryGap: false
+    },
+    yAxis: {
+      type: 'value',
+      name: '天数',
+      min: 0,
+      max: 5
+    },
+    series: [
+      {
+        name: '平均时效',
+        type: 'line',
+        data: deliveryTimeAnalysis.value.map(item => item.avgTime),
+        smooth: true,
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      },
+      {
+        name: '最长时效',
+        type: 'line',
+        data: deliveryTimeAnalysis.value.map(item => item.maxTime),
+        smooth: true,
+        lineStyle: {
+          width: 2,
+          type: 'dashed'
+        },
+        itemStyle: {
+          color: '#EF4444'
+        }
+      },
+      {
+        name: '最短时效',
+        type: 'line',
+        data: deliveryTimeAnalysis.value.map(item => item.minTime),
+        smooth: true,
+        lineStyle: {
+          width: 2,
+          type: 'dashed'
+        },
+        itemStyle: {
+          color: '#10B981'
+        }
+      }
+    ]
+  }
+  deliveryTimeChart.setOption(option)
+}
+
+// 初始化物流公司分布图表
+const initCompanyDistributionChart = () => {
+  if (!companyDistributionChartRef.value) return
+  
+  if (companyDistributionChart) {
+    companyDistributionChart.dispose()
+  }
+  
+  companyDistributionChart = echarts.init(companyDistributionChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}: {c}单 ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '物流公司分布',
+        type: 'pie',
+        radius: '50%',
+        data: logisticsCompanyDistribution.value.map(item => ({
+          value: item.count,
+          name: item.company
+        })),
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 5,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: true,
+          formatter: '{b}: {c}单'
+        }
+      }
+    ]
+  }
+  companyDistributionChart.setOption(option)
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (deliveryTimeChart) deliveryTimeChart.resize()
+  if (companyDistributionChart) companyDistributionChart.resize()
+}
+
+// 计算属性
+const filteredOrders = computed(() => {
+  let result = [...mockOrders.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(order => 
+      order.orderNo.includes(searchText.value) ||
+      order.logisticsNo.includes(searchText.value)
+    )
+  }
+  
+  // 状态过滤
+  if (logisticsStatus.value) {
+    result = result.filter(order => order.status === logisticsStatus.value)
+  }
+  
+  // 物流公司过滤
+  if (logisticsCompany.value) {
+    result = result.filter(order => order.logisticsCompany === logisticsCompany.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(order => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedOrders = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredOrders.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredOrders.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleCompanyChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const getStatusClass = (status) => {
+  const classes = {
+    pending: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
+    shipped: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
+    in_transit: 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300',
+    delivered: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
+    returned: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300',
+    exception: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'
+}
+
+const getStatusText = (status) => {
+  const texts = {
+    pending: '待发货',
+    shipped: '已发货',
+    in_transit: '运输中',
+    delivered: '已送达',
+    returned: '已退回',
+    exception: '异常'
+  }
+  return texts[status] || '未知状态'
+}
+
+const handleViewOrder = (order) => {
+  console.log('查看订单:', order)
+}
+
+const handleShipOrder = (order) => {
+  console.log('发货订单:', order)
+}
+
+const handleHandleException = (order) => {
+  console.log('处理异常订单:', order)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化图表
+  initDeliveryTimeChart()
+  initCompanyDistributionChart()
+  
+  // 添加窗口大小变化监听
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  // 移除窗口大小变化监听
+  window.removeEventListener('resize', handleResize)
+  
+  // 销毁图表实例
+  if (deliveryTimeChart) deliveryTimeChart.dispose()
+  if (companyDistributionChart) companyDistributionChart.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.ship-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.exception-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 647 - 0
src/assets/templates/prototype/ecommerce/EcommerceMarketingManagement.vue

@@ -0,0 +1,647 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">营销管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleAddCampaign"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <PlusIcon class="h-5 w-5" />
+              <span>新增活动</span>
+            </button>
+            <button 
+              @click="handleExportData"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出数据</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索活动名称/编号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="campaignType"
+            @change="handleTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类型</option>
+            <option value="discount">折扣活动</option>
+            <option value="coupon">优惠券</option>
+            <option value="flash">限时抢购</option>
+            <option value="group">拼团活动</option>
+          </select>
+          <select 
+            v-model="campaignStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="draft">草稿</option>
+            <option value="pending">待审核</option>
+            <option value="active">进行中</option>
+            <option value="ended">已结束</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 营销活动统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <MegaphoneIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总活动数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockCampaigns.length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ActivityIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">进行中</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockCampaigns.filter(campaign => campaign.status === 'active').length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <ClockIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">待审核</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockCampaigns.filter(campaign => campaign.status === 'pending').length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <XCircleIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">已结束</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockCampaigns.filter(campaign => campaign.status === 'ended').length }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 营销活动列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">活动信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">时间</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">参与人数</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="campaign in paginatedCampaigns" :key="campaign.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-md object-cover" :src="campaign.image" :alt="campaign.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ campaign.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ campaign.code }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['type-tag', `type-${campaign.type}`]">
+                    {{ campaign.type === 'discount' ? '折扣活动' : 
+                       campaign.type === 'coupon' ? '优惠券' : 
+                       campaign.type === 'flash' ? '限时抢购' : '拼团活动' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ campaign.startTime }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ campaign.endTime }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ campaign.participants }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${campaign.status}`]">
+                    {{ campaign.status === 'draft' ? '草稿' : 
+                       campaign.status === 'pending' ? '待审核' : 
+                       campaign.status === 'active' ? '进行中' : '已结束' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewCampaign(campaign)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditCampaign(campaign)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                  <button 
+                    @click="handleDeleteCampaign(campaign)"
+                    class="action-button delete-button"
+                  >
+                    <TrashIcon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredCampaigns.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredCampaigns.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  MegaphoneIcon,
+  ActivityIcon,
+  ClockIcon,
+  XCircleIcon,
+  DownloadIcon,
+  PlusIcon,
+  EyeIcon,
+  EditIcon,
+  TrashIcon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const campaignType = ref('')
+const campaignStatus = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalCampaigns = ref(100)
+
+// 默认图片配置
+const defaultImages = {
+  avatar: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop&auto=format',
+  product: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=200&h=200&fit=crop&auto=format'
+}
+
+// 模拟数据
+const mockCampaigns = ref([
+  {
+    id: 'C1001',
+    name: '春季新品促销',
+    code: 'SPRING2024',
+    type: 'discount',
+    status: 'active',
+    startTime: '2024-03-01',
+    endTime: '2024-03-31',
+    budget: 50000,
+    spent: 35000,
+    impressions: 120000,
+    clicks: 15000,
+    conversions: 1200,
+    roi: 2.5,
+    image: defaultImages.product,
+    participants: 1200,
+    products: [
+      {
+        id: 'P1001',
+        name: 'iPhone 15 Pro',
+        image: defaultImages.product,
+        price: 8999,
+        discount: 0.9
+      },
+      {
+        id: 'P1002',
+        name: 'MacBook Pro',
+        image: defaultImages.product,
+        price: 12999,
+        discount: 0.95
+      }
+    ],
+    targetAudience: {
+      age: '18-35',
+      gender: 'all',
+      interests: ['科技', '数码']
+    }
+  },
+  {
+    id: 'C1002',
+    name: '会员专享优惠',
+    code: 'VIP2024',
+    type: 'membership',
+    status: 'active',
+    startTime: '2024-03-15',
+    endTime: '2024-04-15',
+    budget: 30000,
+    spent: 12000,
+    impressions: 80000,
+    clicks: 8000,
+    conversions: 600,
+    roi: 1.8,
+    image: defaultImages.product,
+    participants: 800,
+    products: [
+      {
+        id: 'P1003',
+        name: 'AirPods Pro',
+        image: defaultImages.product,
+        price: 1999,
+        discount: 0.85
+      },
+      {
+        id: 'P1004',
+        name: 'iPad Pro',
+        image: defaultImages.product,
+        price: 6999,
+        discount: 0.9
+      }
+    ],
+    targetAudience: {
+      age: '25-45',
+      gender: 'all',
+      interests: ['音乐', '娱乐']
+    }
+  },
+  {
+    id: 'C1003',
+    name: '限时秒杀活动',
+    code: 'FLASH2024',
+    type: 'flash_sale',
+    status: 'completed',
+    startTime: '2024-02-20',
+    endTime: '2024-02-21',
+    budget: 20000,
+    spent: 20000,
+    impressions: 150000,
+    clicks: 20000,
+    conversions: 1800,
+    roi: 3.2,
+    image: defaultImages.product,
+    participants: 1800,
+    products: [
+      {
+        id: 'P1005',
+        name: 'Apple Watch',
+        image: defaultImages.product,
+        price: 2999,
+        discount: 0.7
+      }
+    ],
+    targetAudience: {
+      age: '20-40',
+      gender: 'all',
+      interests: ['健康', '运动']
+    }
+  }
+])
+
+// 营销统计数据
+const marketingStats = ref({
+  totalCampaigns: 1234,
+  activeCampaigns: 56,
+  completedCampaigns: 1024,
+  cancelledCampaigns: 154
+})
+
+// 计算属性
+const filteredCampaigns = computed(() => {
+  let result = [...mockCampaigns.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(campaign => 
+      campaign.name.includes(searchText.value) ||
+      campaign.code.includes(searchText.value)
+    )
+  }
+  
+  // 类型过滤
+  if (campaignType.value) {
+    result = result.filter(campaign => campaign.type === campaignType.value)
+  }
+  
+  // 状态过滤
+  if (campaignStatus.value) {
+    result = result.filter(campaign => campaign.status === campaignStatus.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(campaign => {
+      const startTime = new Date(campaign.startTime)
+      const endTime = new Date(campaign.endTime)
+      
+      switch (timeRange.value) {
+        case 'today':
+          return startTime <= now && endTime >= now
+        case 'week':
+          const weekStart = new Date(now.setDate(now.getDate() - now.getDay()))
+          const weekEnd = new Date(weekStart)
+          weekEnd.setDate(weekStart.getDate() + 6)
+          return startTime <= weekEnd && endTime >= weekStart
+        case 'month':
+          const monthStart = new Date(now.getFullYear(), now.getMonth(), 1)
+          const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0)
+          return startTime <= monthEnd && endTime >= monthStart
+        case 'quarter':
+          const quarter = Math.floor(now.getMonth() / 3)
+          const quarterStart = new Date(now.getFullYear(), quarter * 3, 1)
+          const quarterEnd = new Date(now.getFullYear(), quarter * 3 + 3, 0)
+          return startTime <= quarterEnd && endTime >= quarterStart
+        default:
+          return true
+      }
+    })
+  }
+  
+  return result
+})
+
+const paginatedCampaigns = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredCampaigns.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredCampaigns.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleAddCampaign = () => {
+  console.log('新增活动')
+}
+
+const handleViewCampaign = (campaign) => {
+  console.log('查看活动:', campaign)
+}
+
+const handleEditCampaign = (campaign) => {
+  console.log('编辑活动:', campaign)
+}
+
+const handleDeleteCampaign = (campaign) => {
+  console.log('删除活动:', campaign)
+}
+
+const handleExportData = () => {
+  console.log('导出数据')
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化数据
+  console.log('营销管理页面已加载')
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 活动类型标签样式 */
+.type-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.type-discount {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.type-coupon {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+.type-flash {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.type-group {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+/* 活动状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-draft {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+.status-pending {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-active {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-ended {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.delete-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 861 - 0
src/assets/templates/prototype/ecommerce/EcommerceOrderManagement.vue

@@ -0,0 +1,861 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex">
+            <div class="flex-shrink-0 flex items-center">
+              <h1 class="text-xl font-bold text-gray-900 dark:text-white">订单管理</h1>
+            </div>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExport"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出订单</span>
+            </button>
+            <button 
+              @click="handleImport"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <UploadIcon class="h-5 w-5" />
+              <span>导入订单</span>
+            </button>
+            <button 
+              @click="handleAddOrder"
+              class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 flex items-center space-x-2"
+            >
+              <PlusIcon class="h-5 w-5" />
+              <span>添加订单</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="mb-6 bg-white dark:bg-gray-800 shadow rounded-lg p-4">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              type="text"
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
+              placeholder="搜索订单号/商品名称"
+            />
+            <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+              <SearchIcon class="h-5 w-5 text-gray-400" />
+            </div>
+          </div>
+          <select class="border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
+            <option value="">所有状态</option>
+            <option value="pending">待付款</option>
+            <option value="paid">已付款</option>
+            <option value="shipped">已发货</option>
+            <option value="completed">已完成</option>
+            <option value="cancelled">已取消</option>
+          </select>
+          <select class="border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
+            <option value="">所有支付方式</option>
+            <option value="alipay">支付宝</option>
+            <option value="wechat">微信支付</option>
+            <option value="bank">银行转账</option>
+          </select>
+          <button 
+            @click="showAdvancedFilter = true"
+            class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+          >
+            <FilterIcon class="h-4 w-4 mr-2" />
+            高级筛选
+          </button>
+        </div>
+      </div>
+
+      <!-- 订单列表 -->
+      <div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                订单信息
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                商品信息
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                金额
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                状态
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                操作
+              </th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="order in orders" :key="order.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">
+                  {{ order.id }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ formatDate(order.createdAt) }}
+                </div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">
+                  {{ order.productName }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  数量: {{ order.quantity }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">
+                  ¥{{ order.totalAmount }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ order.paymentMethod }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(order.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusText(order.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button 
+                  @click="handleViewDetails(order)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  详情
+                </button>
+                <button 
+                  @click="handleEditOrder(order)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  编辑
+                </button>
+                <button 
+                  @click="handleDeleteOrder(order)"
+                  class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                >
+                  删除
+                </button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 分页 -->
+      <div class="mt-4 flex justify-between items-center">
+        <div class="text-sm text-gray-700 dark:text-gray-300">
+          显示 1 到 10 条,共 100 条
+        </div>
+        <div class="flex space-x-2">
+          <button class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+            上一页
+          </button>
+          <button class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+            下一页
+          </button>
+        </div>
+      </div>
+    </main>
+
+    <!-- 订单详情弹窗 -->
+    <div v-if="showOrderDetails" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">订单详情</h3>
+            <button 
+              @click="showOrderDetails = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <!-- 基本信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">基本信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">订单编号</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.id }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">创建时间</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedOrder?.createdAt) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">订单状态</p>
+                <span :class="getStatusClass(selectedOrder?.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusText(selectedOrder?.status) }}
+                </span>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">支付方式</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.paymentMethod }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 商品信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">商品信息</h4>
+            <div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
+              <div class="flex items-center">
+                <div class="flex-1">
+                  <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.productName }}</p>
+                  <p class="text-sm text-gray-500 dark:text-gray-400">数量: {{ selectedOrder?.quantity }}</p>
+                </div>
+                <div class="text-right">
+                  <p class="text-sm font-medium text-gray-900 dark:text-white">¥{{ selectedOrder?.totalAmount }}</p>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <!-- 收货信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">收货信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">收货人</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.receiverName }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">联系电话</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.receiverPhone }}</p>
+              </div>
+              <div class="md:col-span-2">
+                <p class="text-sm text-gray-500 dark:text-gray-400">收货地址</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.receiverAddress }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 物流信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">物流信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">物流公司</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.shippingCompany }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">物流单号</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedOrder?.trackingNumber }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">发货时间</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedOrder?.shippingTime) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">预计送达</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedOrder?.estimatedDeliveryTime) }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 备注信息 -->
+          <div>
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">备注信息</h4>
+            <p class="text-sm text-gray-900 dark:text-white">{{ selectedOrder?.remarks || '无' }}</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 编辑订单弹窗 -->
+    <div v-if="showEditOrder" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">编辑订单</h3>
+            <button 
+              @click="showEditOrder = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitEdit" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">订单状态</label>
+                <select 
+                  v-model="editOrder.status"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="pending">待付款</option>
+                  <option value="paid">已付款</option>
+                  <option value="shipped">已发货</option>
+                  <option value="completed">已完成</option>
+                  <option value="cancelled">已取消</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">支付方式</label>
+                <select 
+                  v-model="editOrder.paymentMethod"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="alipay">支付宝</option>
+                  <option value="wechat">微信支付</option>
+                  <option value="bank">银行转账</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品数量</label>
+                <input 
+                  type="number" 
+                  v-model="editOrder.quantity"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">总金额</label>
+                <input 
+                  type="number" 
+                  v-model="editOrder.totalAmount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">备注</label>
+                <textarea 
+                  v-model="editOrder.remarks"
+                  rows="3"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showEditOrder = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                保存
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 添加订单弹窗 -->
+    <div v-if="showAddOrder" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">添加订单</h3>
+            <button 
+              @click="showAddOrder = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitAdd" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                <input 
+                  type="text" 
+                  v-model="newOrder.productName"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品数量</label>
+                <input 
+                  type="number" 
+                  v-model="newOrder.quantity"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">总金额</label>
+                <input 
+                  type="number" 
+                  v-model="newOrder.totalAmount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">支付方式</label>
+                <select 
+                  v-model="newOrder.paymentMethod"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="alipay">支付宝</option>
+                  <option value="wechat">微信支付</option>
+                  <option value="bank">银行转账</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">收货人</label>
+                <input 
+                  type="text" 
+                  v-model="newOrder.receiverName"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">联系电话</label>
+                <input 
+                  type="text" 
+                  v-model="newOrder.receiverPhone"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">收货地址</label>
+                <input 
+                  type="text" 
+                  v-model="newOrder.receiverAddress"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">备注</label>
+                <textarea 
+                  v-model="newOrder.remarks"
+                  rows="3"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showAddOrder = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                添加
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 删除确认弹窗 -->
+    <div v-if="showDeleteConfirm" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">确认删除</h3>
+            <button 
+              @click="showDeleteConfirm = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
+            确定要删除订单 {{ selectedOrder?.id }} 吗?此操作不可撤销。
+          </p>
+
+          <div class="flex justify-end space-x-3">
+            <button 
+              @click="showDeleteConfirm = false"
+              class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              取消
+            </button>
+            <button 
+              @click="confirmDelete"
+              class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
+            >
+              删除
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 高级筛选弹窗 -->
+    <div v-if="showAdvancedFilter" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">高级筛选</h3>
+            <button 
+              @click="showAdvancedFilter = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleFilter" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">订单编号</label>
+                <input 
+                  type="text" 
+                  v-model="filters.id"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入订单编号"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                <input 
+                  type="text" 
+                  v-model="filters.productName"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入商品名称"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">订单状态</label>
+                <select 
+                  v-model="filters.status"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="">所有状态</option>
+                  <option value="pending">待付款</option>
+                  <option value="paid">已付款</option>
+                  <option value="shipped">已发货</option>
+                  <option value="completed">已完成</option>
+                  <option value="cancelled">已取消</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">支付方式</label>
+                <select 
+                  v-model="filters.paymentMethod"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="">所有支付方式</option>
+                  <option value="alipay">支付宝</option>
+                  <option value="wechat">微信支付</option>
+                  <option value="bank">银行转账</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">最小金额</label>
+                <input 
+                  type="number" 
+                  v-model="filters.minAmount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入最小金额"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">最大金额</label>
+                <input 
+                  type="number" 
+                  v-model="filters.maxAmount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入最大金额"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">开始日期</label>
+                <input 
+                  type="date" 
+                  v-model="filters.startDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结束日期</label>
+                <input 
+                  type="date" 
+                  v-model="filters.endDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="resetFilters"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                重置
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                筛选
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { 
+  SearchIcon, 
+  PlusIcon,
+  FilterIcon,
+  DownloadIcon,
+  UploadIcon,
+  XIcon
+} from 'lucide-vue-next'
+
+// 订单数据
+const orders = ref([
+  {
+    id: 'O202401010001',
+    productName: '商品A',
+    quantity: 2,
+    totalAmount: 199.00,
+    paymentMethod: '支付宝',
+    status: 'pending',
+    createdAt: '2024-01-01 10:00:00'
+  },
+  {
+    id: 'O202401010002',
+    productName: '商品B',
+    quantity: 1,
+    totalAmount: 299.00,
+    paymentMethod: '微信支付',
+    status: 'paid',
+    createdAt: '2024-01-01 11:00:00'
+  },
+  {
+    id: 'O202401010003',
+    productName: '商品C',
+    quantity: 3,
+    totalAmount: 399.00,
+    paymentMethod: '银行转账',
+    status: 'shipped',
+    createdAt: '2024-01-01 12:00:00'
+  }
+])
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    pending: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
+    paid: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200',
+    shipped: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    completed: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200',
+    cancelled: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+// 获取状态文本
+const getStatusText = (status) => {
+  const texts = {
+    pending: '待付款',
+    paid: '已付款',
+    shipped: '已发货',
+    completed: '已完成',
+    cancelled: '已取消'
+  }
+  return texts[status] || '未知'
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleString()
+}
+
+// 订单详情相关
+const showOrderDetails = ref(false)
+const selectedOrder = ref(null)
+
+// 编辑订单相关
+const showEditOrder = ref(false)
+const editOrder = ref({
+  id: '',
+  productName: '',
+  quantity: 0,
+  totalAmount: 0,
+  paymentMethod: '',
+  status: '',
+  remarks: ''
+})
+
+// 添加订单相关
+const showAddOrder = ref(false)
+const newOrder = ref({
+  productName: '',
+  quantity: 0,
+  totalAmount: 0,
+  paymentMethod: 'alipay',
+  status: 'pending',
+  receiverName: '',
+  receiverPhone: '',
+  receiverAddress: '',
+  remarks: ''
+})
+
+// 删除确认相关
+const showDeleteConfirm = ref(false)
+
+// 高级筛选相关
+const showAdvancedFilter = ref(false)
+const filters = ref({
+  id: '',
+  productName: '',
+  status: '',
+  paymentMethod: '',
+  minAmount: '',
+  maxAmount: '',
+  startDate: '',
+  endDate: ''
+})
+
+// 处理查看详情
+const handleViewDetails = (order) => {
+  selectedOrder.value = order
+  showOrderDetails.value = true
+}
+
+// 处理编辑订单
+const handleEditOrder = (order) => {
+  editOrder.value = { ...order }
+  showEditOrder.value = true
+}
+
+// 处理提交编辑
+const handleSubmitEdit = () => {
+  const index = orders.value.findIndex(o => o.id === editOrder.value.id)
+  if (index !== -1) {
+    orders.value[index] = { ...editOrder.value }
+  }
+  showEditOrder.value = false
+}
+
+// 处理添加订单
+const handleAddOrder = () => {
+  newOrder.value = {
+    productName: '',
+    quantity: 0,
+    totalAmount: 0,
+    paymentMethod: 'alipay',
+    status: 'pending',
+    receiverName: '',
+    receiverPhone: '',
+    receiverAddress: '',
+    remarks: ''
+  }
+  showAddOrder.value = true
+}
+
+// 处理提交添加
+const handleSubmitAdd = () => {
+  const order = {
+    ...newOrder.value,
+    id: `O${new Date().getTime()}`,
+    createdAt: new Date().toISOString()
+  }
+  orders.value.push(order)
+  showAddOrder.value = false
+}
+
+// 处理删除订单
+const handleDeleteOrder = (order) => {
+  selectedOrder.value = order
+  showDeleteConfirm.value = true
+}
+
+// 确认删除
+const confirmDelete = () => {
+  const index = orders.value.findIndex(o => o.id === selectedOrder.value.id)
+  if (index !== -1) {
+    orders.value.splice(index, 1)
+  }
+  showDeleteConfirm.value = false
+}
+
+// 处理导出
+const handleExport = () => {
+  const data = JSON.stringify(orders.value, null, 2)
+  const blob = new Blob([data], { type: 'application/json' })
+  const url = URL.createObjectURL(blob)
+  const a = document.createElement('a')
+  a.href = url
+  a.download = `orders_${new Date().toISOString().split('T')[0]}.json`
+  document.body.appendChild(a)
+  a.click()
+  document.body.removeChild(a)
+  URL.revokeObjectURL(url)
+}
+
+// 处理导入
+const handleImport = () => {
+  const input = document.createElement('input')
+  input.type = 'file'
+  input.accept = '.json'
+  input.onchange = (e) => {
+    const file = e.target.files[0]
+    if (file) {
+      const reader = new FileReader()
+      reader.onload = (e) => {
+        try {
+          const data = JSON.parse(e.target.result)
+          if (Array.isArray(data)) {
+            orders.value = data
+          }
+        } catch (error) {
+          console.error('导入失败:', error)
+        }
+      }
+      reader.readAsText(file)
+    }
+  }
+  input.click()
+}
+
+// 处理筛选
+const handleFilter = () => {
+  // 实现筛选逻辑
+  showAdvancedFilter.value = false
+}
+
+// 重置筛选条件
+const resetFilters = () => {
+  filters.value = {
+    id: '',
+    productName: '',
+    status: '',
+    paymentMethod: '',
+    minAmount: '',
+    maxAmount: '',
+    startDate: '',
+    endDate: ''
+  }
+}
+</script> 

+ 854 - 0
src/assets/templates/prototype/ecommerce/EcommerceProductManagement.vue

@@ -0,0 +1,854 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">商品管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleAddProduct"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <PlusIcon class="h-5 w-5" />
+              <span>添加商品</span>
+            </button>
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索商品名称/编号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="productCategory"
+            @change="handleCategoryChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有分类</option>
+            <option value="phone">手机</option>
+            <option value="laptop">笔记本</option>
+            <option value="tablet">平板</option>
+            <option value="watch">智能手表</option>
+            <option value="accessories">配件</option>
+          </select>
+          <select 
+            v-model="productStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="active">在售</option>
+            <option value="inactive">下架</option>
+            <option value="outOfStock">缺货</option>
+          </select>
+          <select 
+            v-model="priceRange"
+            @change="handlePriceRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有价格</option>
+            <option value="0-1000">1000元以下</option>
+            <option value="1000-5000">1000-5000元</option>
+            <option value="5000-10000">5000-10000元</option>
+            <option value="10000+">10000元以上</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 商品统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <PackageIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总商品数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,234</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ShoppingBagIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">在售商品</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,024</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <AlertTriangleIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">库存预警</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">56</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <TrendingUpIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">热销商品</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">78</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 商品分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">销量趋势</h3>
+          <div class="h-64">
+            <!-- 这里可以集成图表库,如 ECharts 或 Chart.js -->
+            <div ref="salesChartRef" class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
+              销量趋势图表
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">分类分布</h3>
+          <div class="h-64">
+            <!-- 这里可以集成图表库,如 ECharts 或 Chart.js -->
+            <div ref="categoryChartRef" class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
+              分类分布图表
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 商品列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">商品信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">分类</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">价格</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">库存</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="product in paginatedProducts" :key="product.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <img :src="product.image" :alt="product.name" class="h-16 w-16 rounded object-cover" />
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ product.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ product.description }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">商品编号: {{ product.sku }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ getCategoryText(product.category) }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">¥{{ product.price }}</div>
+                  <div v-if="product.originalPrice" class="text-sm text-gray-500 dark:text-gray-400 line-through">
+                    ¥{{ product.originalPrice }}
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ product.stock }}</div>
+                  <div v-if="product.stock <= product.stockWarning" class="text-sm text-red-600 dark:text-red-400">
+                    库存不足
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span 
+                    :class="[
+                      'px-2 inline-flex text-xs leading-5 font-semibold rounded-full',
+                      getStatusClass(product.status)
+                    ]"
+                  >
+                    {{ getStatusText(product.status) }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewProduct(product)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditProduct(product)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                  <button 
+                    v-if="product.status === 'active'"
+                    @click="handleDeactivateProduct(product)"
+                    class="action-button deactivate-button"
+                  >
+                    <XIcon class="h-4 w-4 inline-block mr-1" />
+                    下架
+                  </button>
+                  <button 
+                    v-if="product.status === 'inactive'"
+                    @click="handleActivateProduct(product)"
+                    class="action-button activate-button"
+                  >
+                    <CheckIcon class="h-4 w-4 inline-block mr-1" />
+                    上架
+                  </button>
+                  <button 
+                    @click="handleDeleteProduct(product)"
+                    class="action-button delete-button"
+                  >
+                    <Trash2Icon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredProducts.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredProducts.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { CanvasRenderer } from 'echarts/renderers'
+import { LineChart, PieChart, BarChart } from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+} from 'echarts/components'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  PackageIcon,
+  ShoppingBagIcon,
+  AlertTriangleIcon,
+  TrendingUpIcon,
+  DollarSignIcon,
+  PlusIcon,
+  DownloadIcon,
+  EyeIcon,
+  EditIcon,
+  XIcon,
+  CheckIcon,
+  Trash2Icon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  CanvasRenderer,
+  LineChart,
+  PieChart,
+  BarChart,
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const productCategory = ref('')
+const productStatus = ref('')
+const priceRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 默认图片
+const defaultImages = {
+  product: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=200&h=200&fit=crop&auto=format'
+}
+
+// 模拟数据
+const mockProducts = ref([
+  {
+    id: 'P1001',
+    name: 'iPhone 15 Pro',
+    category: '手机',
+    price: 8999,
+    stock: 100,
+    sales: 50,
+    status: 'on_sale',
+    image: defaultImages.product,
+    description: '最新款苹果手机,搭载A17芯片',
+    createTime: '2024-03-20 10:30:00',
+    updateTime: '2024-03-20 10:30:00'
+  },
+  {
+    id: 'P1002',
+    name: 'MacBook Pro',
+    category: '电脑',
+    price: 12999,
+    stock: 50,
+    sales: 20,
+    status: 'on_sale',
+    image: defaultImages.product,
+    description: '专业级笔记本电脑,M2芯片',
+    createTime: '2024-03-19 14:20:00',
+    updateTime: '2024-03-19 15:30:00'
+  },
+  {
+    id: 'P1003',
+    name: 'AirPods Pro',
+    category: '耳机',
+    price: 1999,
+    stock: 200,
+    sales: 100,
+    status: 'on_sale',
+    image: defaultImages.product,
+    description: '主动降噪无线耳机',
+    createTime: '2024-03-18 09:15:00',
+    updateTime: '2024-03-18 11:30:00'
+  },
+  {
+    id: 'P1004',
+    name: 'iPad Pro',
+    category: '平板',
+    price: 6999,
+    stock: 80,
+    sales: 30,
+    status: 'on_sale',
+    image: defaultImages.product,
+    description: '专业级平板电脑,M2芯片',
+    createTime: '2024-03-17 16:45:00',
+    updateTime: '2024-03-17 17:00:00'
+  },
+  {
+    id: 'P1005',
+    name: 'Apple Watch',
+    category: '手表',
+    price: 2999,
+    stock: 150,
+    sales: 70,
+    status: 'on_sale',
+    image: defaultImages.product,
+    description: '智能手表,支持健康监测',
+    createTime: '2024-03-16 11:25:00',
+    updateTime: '2024-03-16 11:40:00'
+  }
+])
+
+// 商品统计数据
+const productStats = ref({
+  totalProducts: 1234,
+  activeProducts: 1024,
+  stockWarning: 56,
+  hotProducts: 78
+})
+
+// 销量趋势数据
+const salesTrends = ref([
+  { date: '2024-03-01', count: 120, amount: 120000 },
+  { date: '2024-03-02', count: 150, amount: 150000 },
+  { date: '2024-03-03', count: 180, amount: 180000 },
+  { date: '2024-03-04', count: 200, amount: 200000 },
+  { date: '2024-03-05', count: 220, amount: 220000 },
+  { date: '2024-03-06', count: 250, amount: 250000 },
+  { date: '2024-03-07', count: 280, amount: 280000 }
+])
+
+// 分类分布数据
+const categoryDistribution = ref([
+  { category: 'phone', count: 200, percentage: 16 },
+  { category: 'laptop', count: 150, percentage: 12 },
+  { category: 'tablet', count: 100, percentage: 8 },
+  { category: 'watch', count: 180, percentage: 15 },
+  { category: 'accessories', count: 604, percentage: 49 }
+])
+
+// 计算属性
+const filteredProducts = computed(() => {
+  let result = [...mockProducts.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(product => 
+      product.name.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      product.sku.toLowerCase().includes(searchText.value.toLowerCase())
+    )
+  }
+  
+  // 分类过滤
+  if (productCategory.value) {
+    result = result.filter(product => product.category === productCategory.value)
+  }
+  
+  // 状态过滤
+  if (productStatus.value) {
+    result = result.filter(product => product.status === productStatus.value)
+  }
+  
+  // 价格范围过滤
+  if (priceRange.value) {
+    const [min, max] = priceRange.value.split('-').map(v => v === '+' ? Infinity : Number(v))
+    result = result.filter(product => {
+      const price = product.price
+      return price >= min && (max === Infinity || price <= max)
+    })
+  }
+  
+  return result
+})
+
+const paginatedProducts = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredProducts.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredProducts.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleCategoryChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handlePriceRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const getCategoryText = (category) => {
+  const texts = {
+    phone: '手机',
+    laptop: '笔记本',
+    tablet: '平板',
+    watch: '智能手表',
+    accessories: '配件'
+  }
+  return texts[category] || category
+}
+
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
+    inactive: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300',
+    outOfStock: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'
+}
+
+const getStatusText = (status) => {
+  const texts = {
+    active: '在售',
+    inactive: '下架',
+    outOfStock: '缺货'
+  }
+  return texts[status] || status
+}
+
+const handleAddProduct = () => {
+  console.log('添加商品')
+}
+
+const handleViewProduct = (product) => {
+  console.log('查看商品:', product)
+}
+
+const handleEditProduct = (product) => {
+  console.log('编辑商品:', product)
+}
+
+const handleActivateProduct = (product) => {
+  console.log('上架商品:', product)
+}
+
+const handleDeactivateProduct = (product) => {
+  console.log('下架商品:', product)
+}
+
+const handleDeleteProduct = (product) => {
+  console.log('删除商品:', product)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 图表相关
+const salesChartRef = ref(null)
+const categoryChartRef = ref(null)
+const inventoryChartRef = ref(null)
+let salesChart = null
+let categoryChart = null
+let inventoryChart = null
+
+// 初始化销售趋势图表
+const initSalesChart = () => {
+  if (!salesChartRef.value) return
+  
+  if (salesChart) {
+    salesChart.dispose()
+  }
+  
+  salesChart = echarts.init(salesChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      formatter: '{b}<br/>{a0}: {c0}件<br/>{a1}: ¥{c1}'
+    },
+    legend: {
+      data: ['销量', '销售额']
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: salesTrends.value.map(item => item.date),
+      boundaryGap: false
+    },
+    yAxis: [
+      {
+        type: 'value',
+        name: '销量',
+        position: 'left'
+      },
+      {
+        type: 'value',
+        name: '销售额',
+        position: 'right'
+      }
+    ],
+    series: [
+      {
+        name: '销量',
+        type: 'line',
+        data: salesTrends.value.map(item => item.quantity),
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      },
+      {
+        name: '销售额',
+        type: 'line',
+        yAxisIndex: 1,
+        data: salesTrends.value.map(item => item.amount),
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#10B981'
+        }
+      }
+    ]
+  }
+  salesChart.setOption(option)
+}
+
+// 初始化分类分布图表
+const initCategoryChart = () => {
+  if (!categoryChartRef.value) return
+  
+  if (categoryChart) {
+    categoryChart.dispose()
+  }
+  
+  categoryChart = echarts.init(categoryChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}: {c}件 ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '商品分类',
+        type: 'pie',
+        radius: '50%',
+        data: categoryDistribution.value.map(item => ({
+          value: item.count,
+          name: item.category
+        })),
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 5,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: true,
+          formatter: '{b}: {c}件'
+        }
+      }
+    ]
+  }
+  categoryChart.setOption(option)
+}
+
+// 初始化库存预警图表
+const initInventoryChart = () => {
+  if (!inventoryChartRef.value) return
+  
+  if (inventoryChart) {
+    inventoryChart.dispose()
+  }
+  
+  inventoryChart = echarts.init(inventoryChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: inventoryAlerts.value.map(item => item.name),
+      axisLabel: {
+        interval: 0,
+        rotate: 45
+      }
+    },
+    yAxis: {
+      type: 'value',
+      name: '库存数量'
+    },
+    series: [
+      {
+        name: '库存',
+        type: 'bar',
+        data: inventoryAlerts.value.map(item => item.stock),
+        itemStyle: {
+          color: function(params) {
+            const value = params.value
+            if (value < 10) {
+              return '#EF4444'
+            } else if (value < 50) {
+              return '#F59E0B'
+            } else {
+              return '#10B981'
+            }
+          }
+        }
+      }
+    ]
+  }
+  inventoryChart.setOption(option)
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (salesChart) salesChart.resize()
+  if (categoryChart) categoryChart.resize()
+  if (inventoryChart) inventoryChart.resize()
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化图表
+  initSalesChart()
+  initCategoryChart()
+  initInventoryChart()
+  
+  // 添加窗口大小变化监听
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  // 移除窗口大小变化监听
+  window.removeEventListener('resize', handleResize)
+  
+  // 销毁图表实例
+  if (salesChart) salesChart.dispose()
+  if (categoryChart) categoryChart.dispose()
+  if (inventoryChart) inventoryChart.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-yellow-600 dark:text-yellow-400 hover:text-yellow-900 dark:hover:text-yellow-300;
+}
+
+.activate-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.deactivate-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+.delete-button {
+  @apply text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 807 - 0
src/assets/templates/prototype/ecommerce/EcommerceReviewManagement.vue

@@ -0,0 +1,807 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">评价管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索商品名称/用户名..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="reviewType"
+            @change="handleTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类型</option>
+            <option value="text">文字评价</option>
+            <option value="image">图片评价</option>
+            <option value="video">视频评价</option>
+          </select>
+          <select 
+            v-model="reviewStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="pending">待审核</option>
+            <option value="approved">已通过</option>
+            <option value="rejected">已拒绝</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 评价统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <MessageSquareIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总评价数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,234</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ImageIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">图片评价</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">456</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <VideoIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">视频评价</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">78</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <StarIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">平均评分</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">4.8</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 评价分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">评分分布</h3>
+          <div ref="ratingDistributionChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">评分趋势</h3>
+          <div ref="ratingTrendChartRef" class="h-64"></div>
+        </div>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">关键词分析</h3>
+        <div ref="keywordAnalysisChartRef" class="h-64"></div>
+      </div>
+
+      <!-- 评价列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">商品信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">用户信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">评价内容</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">评分</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="review in paginatedReviews" :key="review.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <img :src="review.productImage" :alt="review.productName" class="h-10 w-10 rounded object-cover" />
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ review.productName }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ review.productSpec }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <img :src="review.userAvatar" :alt="review.userName" class="h-10 w-10 rounded-full object-cover" />
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ review.userName }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ review.userLevel }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ review.content }}</div>
+                  <div v-if="review.images && review.images.length > 0" class="mt-2 flex space-x-2">
+                    <img 
+                      v-for="(image, index) in review.images" 
+                      :key="index"
+                      :src="image"
+                      class="h-16 w-16 rounded object-cover cursor-pointer hover:opacity-75"
+                      @click="handleViewImage(image)"
+                    />
+                  </div>
+                  <div v-if="review.video" class="mt-2">
+                    <video 
+                      :src="review.video"
+                      class="h-16 w-16 rounded object-cover cursor-pointer hover:opacity-75"
+                      @click="handleViewVideo(review.video)"
+                    />
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex">
+                      <StarIcon 
+                        v-for="star in 5" 
+                        :key="star"
+                        class="h-5 w-5"
+                        :class="star <= review.rating ? 'text-yellow-400' : 'text-gray-300 dark:text-gray-600'"
+                      />
+                    </div>
+                    <span class="ml-2 text-sm text-gray-500 dark:text-gray-400">{{ review.rating }}分</span>
+                  </div>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewReview(review)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    v-if="review.status === 'pending'"
+                    @click="handleApproveReview(review)"
+                    class="action-button approve-button"
+                  >
+                    <CheckIcon class="h-4 w-4 inline-block mr-1" />
+                    通过
+                  </button>
+                  <button 
+                    v-if="review.status === 'pending'"
+                    @click="handleRejectReview(review)"
+                    class="action-button reject-button"
+                  >
+                    <XIcon class="h-4 w-4 inline-block mr-1" />
+                    拒绝
+                  </button>
+                  <button 
+                    @click="handleDeleteReview(review)"
+                    class="action-button delete-button"
+                  >
+                    <Trash2Icon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredReviews.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredReviews.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { CanvasRenderer } from 'echarts/renderers'
+import { LineChart, PieChart, BarChart } from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+} from 'echarts/components'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  MessageSquareIcon,
+  ImageIcon,
+  VideoIcon,
+  StarIcon,
+  DownloadIcon,
+  EyeIcon,
+  CheckIcon,
+  XIcon,
+  Trash2Icon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  CanvasRenderer,
+  LineChart,
+  PieChart,
+  BarChart,
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+])
+
+// 默认图片
+const defaultImages = {
+  avatar: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop&auto=format',
+  product: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=200&h=200&fit=crop&auto=format'
+}
+
+// 图表相关
+const ratingTrendChartRef = ref(null)
+const ratingDistributionChartRef = ref(null)
+const keywordAnalysisChartRef = ref(null)
+let ratingTrendChart = null
+let ratingDistributionChart = null
+let keywordAnalysisChart = null
+
+// 初始化评分趋势图表
+const initRatingTrendChart = () => {
+  if (!ratingTrendChartRef.value) return
+  
+  if (ratingTrendChart) {
+    ratingTrendChart.dispose()
+  }
+  
+  ratingTrendChart = echarts.init(ratingTrendChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis'
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
+      boundaryGap: false
+    },
+    yAxis: {
+      type: 'value',
+      min: 0,
+      max: 5
+    },
+    series: [
+      {
+        name: '平均评分',
+        type: 'line',
+        data: [4.2, 4.5, 4.3, 4.6, 4.4, 4.7, 4.5],
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      }
+    ]
+  }
+  ratingTrendChart.setOption(option)
+}
+
+// 初始化评分分布图表
+const initRatingDistributionChart = () => {
+  if (!ratingDistributionChartRef.value) return
+  
+  if (ratingDistributionChart) {
+    ratingDistributionChart.dispose()
+  }
+  
+  ratingDistributionChart = echarts.init(ratingDistributionChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}: {c}条 ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '评分分布',
+        type: 'pie',
+        radius: '50%',
+        data: [
+          { value: 600, name: '5星' },
+          { value: 400, name: '4星' },
+          { value: 150, name: '3星' },
+          { value: 50, name: '2星' },
+          { value: 34, name: '1星' }
+        ],
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 5,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: true,
+          formatter: '{b}: {c}条'
+        }
+      }
+    ]
+  }
+  ratingDistributionChart.setOption(option)
+}
+
+// 初始化关键词分析图表
+const initKeywordAnalysisChart = () => {
+  if (!keywordAnalysisChartRef.value) return
+  
+  if (keywordAnalysisChart) {
+    keywordAnalysisChart.dispose()
+  }
+  
+  keywordAnalysisChart = echarts.init(keywordAnalysisChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'value',
+      name: '出现次数'
+    },
+    yAxis: {
+      type: 'category',
+      data: ['质量好', '性价比高', '物流快', '服务好', '包装精美', '外观漂亮', '使用方便', '功能强大'],
+      axisLabel: {
+        interval: 0
+      }
+    },
+    series: [
+      {
+        name: '关键词',
+        type: 'bar',
+        data: [120, 200, 150, 80, 70, 110, 130, 90],
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      }
+    ]
+  }
+  keywordAnalysisChart.setOption(option)
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (ratingTrendChart) ratingTrendChart.resize()
+  if (ratingDistributionChart) ratingDistributionChart.resize()
+  if (keywordAnalysisChart) keywordAnalysisChart.resize()
+}
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const reviewType = ref('')
+const reviewStatus = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 模拟数据
+const mockReviews = ref([
+  {
+    id: 'R1001',
+    productId: 'P1001',
+    productName: 'iPhone 15 Pro Max',
+    productSpec: '256GB 石墨色',
+    productImage: defaultImages.product,
+    userId: 'U1001',
+    userName: '张三',
+    userLevel: '钻石会员',
+    userAvatar: defaultImages.avatar,
+    content: '手机很好用,拍照效果很棒,运行流畅,电池续航也不错。',
+    rating: 5,
+    images: [
+      defaultImages.product,
+      defaultImages.product
+    ],
+    video: null,
+    type: 'image',
+    status: 'approved',
+    createTime: '2024-03-20 10:30:00'
+  },
+  {
+    id: 'R1002',
+    productId: 'P1002',
+    productName: 'MacBook Pro 14',
+    productSpec: 'M3 Pro 18GB 512GB',
+    productImage: defaultImages.product,
+    userId: 'U1002',
+    userName: '李四',
+    userLevel: '黄金会员',
+    userAvatar: defaultImages.avatar,
+    content: '性能很强,屏幕显示效果很好,键盘手感也不错。',
+    rating: 4,
+    images: [],
+    video: 'https://example.com/reviews/macbook.mp4',
+    type: 'video',
+    status: 'pending',
+    createTime: '2024-03-20 11:15:00'
+  },
+  {
+    id: 'R1003',
+    productId: 'P1003',
+    productName: 'AirPods Pro 2',
+    productSpec: '第二代',
+    productImage: defaultImages.product,
+    userId: 'U1003',
+    userName: '王五',
+    userLevel: '白银会员',
+    userAvatar: defaultImages.avatar,
+    content: '降噪效果很好,音质也不错,佩戴舒适。',
+    rating: 5,
+    images: [],
+    video: null,
+    type: 'text',
+    status: 'approved',
+    createTime: '2024-03-20 14:20:00'
+  },
+  {
+    id: 'R1004',
+    productId: 'P1004',
+    productName: 'Apple Watch Series 9',
+    productSpec: '45mm GPS',
+    productImage: defaultImages.product,
+    userId: 'U1004',
+    userName: '赵六',
+    userLevel: '普通会员',
+    userAvatar: defaultImages.avatar,
+    content: '功能很全,续航也不错,就是价格有点贵。',
+    rating: 3,
+    images: [
+      defaultImages.product
+    ],
+    video: null,
+    type: 'image',
+    status: 'rejected',
+    createTime: '2024-03-20 16:45:00'
+  },
+  {
+    id: 'R1005',
+    productId: 'P1005',
+    productName: 'iPad Pro 12.9',
+    productSpec: 'M2 256GB',
+    productImage: defaultImages.product,
+    userId: 'U1005',
+    userName: '钱七',
+    userLevel: '铂金会员',
+    userAvatar: defaultImages.avatar,
+    content: '屏幕很大,显示效果很好,适合办公和娱乐。',
+    rating: 5,
+    images: [],
+    video: null,
+    type: 'text',
+    status: 'approved',
+    createTime: '2024-03-20 18:30:00'
+  }
+])
+
+// 评价统计数据
+const reviewStats = ref({
+  totalReviews: 1234,
+  imageReviews: 456,
+  videoReviews: 78,
+  averageRating: 4.8
+})
+
+// 评价分布数据
+const reviewDistribution = ref([
+  { rating: 5, count: 600, percentage: 48 },
+  { rating: 4, count: 400, percentage: 32 },
+  { rating: 3, count: 150, percentage: 12 },
+  { rating: 2, count: 50, percentage: 4 },
+  { rating: 1, count: 34, percentage: 3 }
+])
+
+// 评价趋势数据
+const reviewTrends = ref([
+  { date: '2024-03-01', count: 120, rating: 4.7 },
+  { date: '2024-03-02', count: 150, rating: 4.8 },
+  { date: '2024-03-03', count: 180, rating: 4.9 },
+  { date: '2024-03-04', count: 200, rating: 4.8 },
+  { date: '2024-03-05', count: 220, rating: 4.7 },
+  { date: '2024-03-06', count: 250, rating: 4.8 },
+  { date: '2024-03-07', count: 280, rating: 4.9 }
+])
+
+// 计算属性
+const filteredReviews = computed(() => {
+  let result = [...mockReviews.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(review => 
+      review.productName.includes(searchText.value) ||
+      review.userName.includes(searchText.value)
+    )
+  }
+  
+  // 类型过滤
+  if (reviewType.value) {
+    result = result.filter(review => review.type === reviewType.value)
+  }
+  
+  // 状态过滤
+  if (reviewStatus.value) {
+    result = result.filter(review => review.status === reviewStatus.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(review => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedReviews = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredReviews.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredReviews.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewReview = (review) => {
+  console.log('查看评价:', review)
+}
+
+const handleApproveReview = (review) => {
+  console.log('通过评价:', review)
+}
+
+const handleRejectReview = (review) => {
+  console.log('拒绝评价:', review)
+}
+
+const handleDeleteReview = (review) => {
+  console.log('删除评价:', review)
+}
+
+const handleViewImage = (image) => {
+  console.log('查看图片:', image)
+}
+
+const handleViewVideo = (video) => {
+  console.log('查看视频:', video)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化图表
+  initRatingTrendChart()
+  initRatingDistributionChart()
+  initKeywordAnalysisChart()
+  
+  // 添加窗口大小变化监听
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  // 移除窗口大小变化监听
+  window.removeEventListener('resize', handleResize)
+  
+  // 销毁图表实例
+  if (ratingTrendChart) ratingTrendChart.dispose()
+  if (ratingDistributionChart) ratingDistributionChart.dispose()
+  if (keywordAnalysisChart) keywordAnalysisChart.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.approve-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.reject-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+.delete-button {
+  @apply text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 795 - 0
src/assets/templates/prototype/ecommerce/EcommerceUserManagement.vue

@@ -0,0 +1,795 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">用户管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+            <button class="p-2 rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">
+              <SettingsIcon class="h-6 w-6" />
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索用户名/手机号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="userLevel"
+            @change="handleLevelChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有等级</option>
+            <option value="diamond">钻石会员</option>
+            <option value="platinum">铂金会员</option>
+            <option value="gold">黄金会员</option>
+            <option value="silver">白银会员</option>
+            <option value="bronze">青铜会员</option>
+          </select>
+          <select 
+            v-model="userStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="active">正常</option>
+            <option value="inactive">禁用</option>
+            <option value="banned">封禁</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 用户统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <UsersIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总用户数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,234</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <UserPlusIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">活跃用户</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,024</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <UserCheckIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">新增用户</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">56</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <UserXIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">封禁用户</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">12</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 用户分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">用户增长趋势</h3>
+          <div class="h-64">
+            <!-- 这里可以集成图表库,如 ECharts 或 Chart.js -->
+            <div ref="growthChartRef" class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
+              用户增长趋势图表
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">用户等级分布</h3>
+          <div class="h-64">
+            <!-- 这里可以集成图表库,如 ECharts 或 Chart.js -->
+            <div ref="levelChartRef" class="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
+              用户等级分布图表
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 用户列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">用户信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">等级</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">消费</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="user in paginatedUsers" :key="user.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <img :src="user.avatar" :alt="user.name" class="h-10 w-10 rounded-full object-cover" />
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ user.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ user.phone }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ user.email }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span 
+                    :class="[
+                      'px-2 inline-flex text-xs leading-5 font-semibold rounded-full',
+                      getLevelClass(user.level)
+                    ]"
+                  >
+                    {{ getLevelText(user.level) }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">总消费: ¥{{ user.totalSpent }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">订单数: {{ user.totalOrders }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span 
+                    :class="[
+                      'px-2 inline-flex text-xs leading-5 font-semibold rounded-full',
+                      getStatusClass(user.status)
+                    ]"
+                  >
+                    {{ getStatusText(user.status) }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewUser(user)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditUser(user)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                  <button 
+                    v-if="user.status === 'active'"
+                    @click="handleDeactivateUser(user)"
+                    class="action-button deactivate-button"
+                  >
+                    <XIcon class="h-4 w-4 inline-block mr-1" />
+                    禁用
+                  </button>
+                  <button 
+                    v-if="user.status === 'inactive'"
+                    @click="handleActivateUser(user)"
+                    class="action-button activate-button"
+                  >
+                    <CheckIcon class="h-4 w-4 inline-block mr-1" />
+                    启用
+                  </button>
+                  <button 
+                    v-if="user.status !== 'banned'"
+                    @click="handleBanUser(user)"
+                    class="action-button ban-button"
+                  >
+                    <BanIcon class="h-4 w-4 inline-block mr-1" />
+                    封禁
+                  </button>
+                  <button 
+                    v-if="user.status === 'banned'"
+                    @click="handleUnbanUser(user)"
+                    class="action-button unban-button"
+                  >
+                    <CheckIcon class="h-4 w-4 inline-block mr-1" />
+                    解封
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredUsers.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredUsers.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { CanvasRenderer } from 'echarts/renderers'
+import { LineChart, PieChart } from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+} from 'echarts/components'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  UsersIcon,
+  UserPlusIcon,
+  UserCheckIcon,
+  UserXIcon,
+  DownloadIcon,
+  EyeIcon,
+  EditIcon,
+  XIcon,
+  CheckIcon,
+  BanIcon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  CanvasRenderer,
+  LineChart,
+  PieChart,
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const userLevel = ref('')
+const userStatus = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+
+// 默认头像
+const defaultAvatars = {
+  user: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEBUlEQVR4nO2ZW2xUVRSGv332TCEtIKEUaAFpr1MohVIuBQR5ACUhQIIGNAiJGjU+mKgPhsc+mJj4ZnwxPGiMiS+YmPCggdfyBgYwXKo2bQu9wXRKW2hLQzstM3P2MmtnmDpzOXPOzGnGhC+ZzGT2Xmv/e6+91r/2PpBFFllkcV9DZOj5R4EaYDFQCRQDjwA5wDAwCPQCHUArcAXoS3fgc4EVwBrgKaAEcAO3gF7gGtAO/AacBy6lK/A5wBvAJmAp4FDPbwHtwFngKHAU6Eg18BXA28BmoAiIAt3AZeAX4CegCXCppzwDlALPAi8DS4AQcAP4DvgU+DtVwZcBe4E3gTzgH+Bb4ABwGQhPc48LmA+sB94DCoCbwD7gY2AgmcCdwHvAHiAPGAK+BD4HupK0FQKeB3YBK1GJ8RnwITCWqOHpgp8PfA28gkqNg8AO4K9EjE6BPOBd4ANUBF0H3gL+iNdgLPgKoAFYBUSAE8B24Ho8RuNEIfA5sA6VvZuB0/EYmQq+GDgGrARGgQ+AvcBEPM4kCQ+wE9iOyqQNqNSyhakS1wkcRlV4E/A6cCbNgWtYDHyPyqpDwHOoEjwJU0XgEFAH9APrUWlxr1AHnEJl1yFUdk2CUQTygB9QjasHVd/jqtWpQj6wGngcGADOAX8m4lgYeAn4EVUTXgSak3UoTKwDXkWVxH5UF3fTxPUxwQW8BXyPqh1vAr/H61wYeAb4CVWXX0A1qVSiEHgT1bQGUHPHzXgMCQNPAidRPf0lVHNKJfKBN1DzSQj4CrXKiAlhoBo4gxoRNqMWK6lCLrAJtcgJo0aov+MxJAxUAedQe5x3UNuGVMAN7ES1YwF8gtrexIQwUIZqVB5UlE4n61UMeBc1vLpQK9+EtuhC/VMXqnF4UWueZGeCqVAAfIJa0oaAXcDtRA0KA0WoXlwEDKMWLYkOa9PBi1qwlKM6x/vASDKGhIEC4AiwDBhDzaiJjA5TwY1KmzWoPtOI2m0lDWHABzSgFiNjwFbUGjwZuFE7uZdQPf4gqhZpIQwsBH5GbXy7gDXA70k4WITqM2tRmfI1qlZoQxjwoyJQixoZVgHnE3SwCjUvPInqM4dRtSIlEAb8qGVtDaqULQdaYnRqAXAC1UlvAT+gcyE+HYSBYlS0lqP6wkrgYhQHK1ELlGpUvW9EVXVtGXMvIQyUACeAJ1DbjyrgV+AhVKrUo3p8EHX8sB1VKjMGYeARVCotQW0cV6B2aDtQJ3EBVOm8YpfjwsA84EdgHjAJIeAuKlXuOQxGwIVKFTdqOHVkKvAsspgW/wGLGwDVYvNCYQAAAABJRU5ErkJggg=='
+}
+
+// 模拟数据
+const mockUsers = ref([
+  {
+    id: 'U1001',
+    name: '张三',
+    phone: '13800138001',
+    email: 'zhangsan@example.com',
+    avatar: defaultAvatars.user,
+    level: 'diamond',
+    status: 'active',
+    registerTime: '2024-01-15 10:30:00',
+    lastLogin: '2024-03-20 15:45:00',
+    totalOrders: 50,
+    totalSpent: 99999
+  },
+  {
+    id: 'U1002',
+    name: '李四',
+    phone: '13800138002',
+    email: 'lisi@example.com',
+    avatar: defaultAvatars.user,
+    level: 'platinum',
+    status: 'active',
+    registerTime: '2024-02-01 14:20:00',
+    lastLogin: '2024-03-19 09:15:00',
+    totalOrders: 30,
+    totalSpent: 49999
+  },
+  {
+    id: 'U1003',
+    name: '王五',
+    phone: '13800138003',
+    email: 'wangwu@example.com',
+    avatar: defaultAvatars.user,
+    level: 'gold',
+    status: 'inactive',
+    registerTime: '2023-12-10 16:45:00',
+    lastLogin: '2024-03-15 11:30:00',
+    totalOrders: 20,
+    totalSpent: 29999
+  },
+  {
+    id: 'U1004',
+    name: '赵六',
+    phone: '13800138004',
+    email: 'zhaoliu@example.com',
+    avatar: defaultAvatars.user,
+    level: 'silver',
+    status: 'banned',
+    registerTime: '2024-03-01 09:10:00',
+    lastLogin: '2024-03-20 16:20:00',
+    totalOrders: 10,
+    totalSpent: 9999
+  },
+  {
+    id: 'U1005',
+    name: '钱七',
+    phone: '13800138005',
+    email: 'qianqi@example.com',
+    avatar: defaultAvatars.user,
+    level: 'bronze',
+    status: 'active',
+    registerTime: '2023-11-20 11:25:00',
+    lastLogin: '2024-03-20 14:35:00',
+    totalOrders: 5,
+    totalSpent: 4999
+  }
+])
+
+// 用户统计数据
+const userStats = ref({
+  totalUsers: 1234,
+  activeUsers: 1024,
+  newUsers: 56,
+  bannedUsers: 12
+})
+
+// 用户增长趋势数据
+const userGrowthTrends = ref([
+  { date: '2024-03-01', newUsers: 120, activeUsers: 800 },
+  { date: '2024-03-02', newUsers: 150, activeUsers: 850 },
+  { date: '2024-03-03', newUsers: 180, activeUsers: 900 },
+  { date: '2024-03-04', newUsers: 200, activeUsers: 950 },
+  { date: '2024-03-05', newUsers: 220, activeUsers: 1000 },
+  { date: '2024-03-06', newUsers: 250, activeUsers: 1050 },
+  { date: '2024-03-07', newUsers: 280, activeUsers: 1100 }
+])
+
+// 用户等级分布数据
+const userLevelDistribution = ref([
+  { level: 'diamond', count: 100, percentage: 8 },
+  { level: 'platinum', count: 200, percentage: 16 },
+  { level: 'gold', count: 300, percentage: 24 },
+  { level: 'silver', count: 400, percentage: 32 },
+  { level: 'bronze', count: 234, percentage: 19 }
+])
+
+// 计算属性
+const filteredUsers = computed(() => {
+  let result = [...mockUsers.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(user => 
+      user.name.includes(searchText.value) ||
+      user.phone.includes(searchText.value)
+    )
+  }
+  
+  // 等级过滤
+  if (userLevel.value) {
+    result = result.filter(user => user.level === userLevel.value)
+  }
+  
+  // 状态过滤
+  if (userStatus.value) {
+    result = result.filter(user => user.status === userStatus.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(user => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedUsers = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredUsers.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredUsers.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleLevelChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const getLevelClass = (level) => {
+  const classes = {
+    diamond: 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300',
+    platinum: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
+    gold: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
+    silver: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300',
+    bronze: 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300'
+  }
+  return classes[level] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'
+}
+
+const getLevelText = (level) => {
+  const texts = {
+    diamond: '钻石会员',
+    platinum: '铂金会员',
+    gold: '黄金会员',
+    silver: '白银会员',
+    bronze: '青铜会员'
+  }
+  return texts[level] || level
+}
+
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
+    inactive: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300',
+    banned: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'
+}
+
+const getStatusText = (status) => {
+  const texts = {
+    active: '正常',
+    inactive: '禁用',
+    banned: '封禁'
+  }
+  return texts[status] || status
+}
+
+const handleViewUser = (user) => {
+  console.log('查看用户:', user)
+}
+
+const handleEditUser = (user) => {
+  console.log('编辑用户:', user)
+}
+
+const handleActivateUser = (user) => {
+  console.log('启用用户:', user)
+}
+
+const handleDeactivateUser = (user) => {
+  console.log('禁用用户:', user)
+}
+
+const handleBanUser = (user) => {
+  console.log('封禁用户:', user)
+}
+
+const handleUnbanUser = (user) => {
+  console.log('解封用户:', user)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 图表相关
+const growthChartRef = ref(null)
+const levelChartRef = ref(null)
+let growthChart = null
+let levelChart = null
+
+// 初始化用户增长趋势图表
+const initGrowthChart = () => {
+  if (!growthChartRef.value) return
+  
+  if (growthChart) {
+    growthChart.dispose()
+  }
+  
+  growthChart = echarts.init(growthChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      formatter: '{b}<br/>{a0}: {c0}人<br/>{a1}: {c1}人'
+    },
+    legend: {
+      data: ['新增用户', '活跃用户']
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: userGrowthTrends.value.map(item => item.date),
+      boundaryGap: false
+    },
+    yAxis: {
+      type: 'value',
+      name: '用户数量'
+    },
+    series: [
+      {
+        name: '新增用户',
+        type: 'line',
+        data: userGrowthTrends.value.map(item => item.newUsers),
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#4F46E5'
+        }
+      },
+      {
+        name: '活跃用户',
+        type: 'line',
+        data: userGrowthTrends.value.map(item => item.activeUsers),
+        smooth: true,
+        areaStyle: {
+          opacity: 0.3
+        },
+        lineStyle: {
+          width: 3
+        },
+        itemStyle: {
+          color: '#10B981'
+        }
+      }
+    ]
+  }
+  growthChart.setOption(option)
+}
+
+// 初始化用户等级分布图表
+const initLevelChart = () => {
+  if (!levelChartRef.value) return
+  
+  if (levelChart) {
+    levelChart.dispose()
+  }
+  
+  levelChart = echarts.init(levelChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}: {c}人 ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '用户等级',
+        type: 'pie',
+        radius: '50%',
+        data: userLevelDistribution.value.map(item => ({
+          value: item.count,
+          name: getLevelText(item.level)
+        })),
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 5,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: true,
+          formatter: '{b}: {c}人'
+        }
+      }
+    ]
+  }
+  levelChart.setOption(option)
+}
+
+// 监听窗口大小变化
+const handleResize = () => {
+  if (growthChart) growthChart.resize()
+  if (levelChart) levelChart.resize()
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化图表
+  initGrowthChart()
+  initLevelChart()
+  
+  // 添加窗口大小变化监听
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  // 移除窗口大小变化监听
+  window.removeEventListener('resize', handleResize)
+  
+  // 销毁图表实例
+  if (growthChart) growthChart.dispose()
+  if (levelChart) levelChart.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-yellow-600 dark:text-yellow-400 hover:text-yellow-900 dark:hover:text-yellow-300;
+}
+
+.activate-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.deactivate-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+.ban-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+.unban-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 2565 - 0
src/assets/templates/prototype/ecommerce/EcommerceVendorManagement.vue

@@ -0,0 +1,2565 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex">
+            <div class="flex-shrink-0 flex items-center">
+              <h1 class="text-xl font-bold text-gray-900 dark:text-white">供应商管理</h1>
+            </div>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExport"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出供应商</span>
+            </button>
+            <button 
+              @click="handleImport"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <UploadIcon class="h-5 w-5" />
+              <span>导入供应商</span>
+            </button>
+            <button 
+              @click="handleAddVendor"
+              class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 flex items-center space-x-2"
+            >
+              <PlusIcon class="h-5 w-5" />
+              <span>添加供应商</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="mb-6 bg-white dark:bg-gray-800 shadow rounded-lg p-4">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              type="text"
+              v-model="searchQuery"
+              @input="handleSearch"
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
+              placeholder="搜索供应商名称/联系人"
+            />
+            <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+              <SearchIcon class="h-5 w-5 text-gray-400" />
+            </div>
+          </div>
+          <select 
+            v-model="searchStatus"
+            @change="handleSearch"
+            class="border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="active">正常合作</option>
+            <option value="inactive">暂停合作</option>
+            <option value="blacklisted">黑名单</option>
+          </select>
+          <select 
+            v-model="searchLevel"
+            @change="handleSearch"
+            class="border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
+          >
+            <option value="">所有等级</option>
+            <option value="A">A级</option>
+            <option value="B">B级</option>
+            <option value="C">C级</option>
+          </select>
+          <button 
+            @click="showAdvancedFilter = true"
+            class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+          >
+            <FilterIcon class="h-4 w-4 mr-2" />
+            高级筛选
+          </button>
+        </div>
+      </div>
+
+      <!-- 统计面板 -->
+      <div class="mb-6 bg-white dark:bg-gray-800 shadow rounded-lg p-4">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <!-- 供应商总数 -->
+          <div class="bg-blue-50 dark:bg-blue-900 p-4 rounded-lg">
+            <div class="flex items-center">
+              <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-800">
+                <UsersIcon class="h-6 w-6 text-blue-600 dark:text-blue-300" />
+              </div>
+              <div class="ml-4">
+                <p class="text-sm font-medium text-blue-600 dark:text-blue-300">供应商总数</p>
+                <p class="text-2xl font-semibold text-blue-900 dark:text-blue-100">{{ vendors.length }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 活跃供应商 -->
+          <div class="bg-green-50 dark:bg-green-900 p-4 rounded-lg">
+            <div class="flex items-center">
+              <div class="p-3 rounded-full bg-green-100 dark:bg-green-800">
+                <CheckCircleIcon class="h-6 w-6 text-green-600 dark:text-green-300" />
+              </div>
+              <div class="ml-4">
+                <p class="text-sm font-medium text-green-600 dark:text-green-300">活跃供应商</p>
+                <p class="text-2xl font-semibold text-green-900 dark:text-green-100">{{ activeVendorsCount }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 总信用额度 -->
+          <div class="bg-purple-50 dark:bg-purple-900 p-4 rounded-lg">
+            <div class="flex items-center">
+              <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-800">
+                <CreditCardIcon class="h-6 w-6 text-purple-600 dark:text-purple-300" />
+              </div>
+              <div class="ml-4">
+                <p class="text-sm font-medium text-purple-600 dark:text-purple-300">总信用额度</p>
+                <p class="text-2xl font-semibold text-purple-900 dark:text-purple-100">¥{{ totalCreditLimit }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 已用额度 -->
+          <div class="bg-yellow-50 dark:bg-yellow-900 p-4 rounded-lg">
+            <div class="flex items-center">
+              <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-800">
+                <AlertCircleIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-300" />
+              </div>
+              <div class="ml-4">
+                <p class="text-sm font-medium text-yellow-600 dark:text-yellow-300">已用额度</p>
+                <p class="text-2xl font-semibold text-yellow-900 dark:text-yellow-100">¥{{ totalUsedCredit }}</p>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <!-- 等级分布图表 -->
+        <div class="mt-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">供应商等级分布</h3>
+          <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+            <div v-for="(count, level) in levelDistribution" :key="level" class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+              <div class="flex justify-between items-center">
+                <span class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ level }}级供应商</span>
+                <span class="text-lg font-semibold text-gray-900 dark:text-white">{{ count }}</span>
+              </div>
+              <div class="mt-2">
+                <div class="w-full bg-gray-200 dark:bg-gray-600 rounded-full h-2">
+                  <div 
+                    class="h-2 rounded-full"
+                    :class="{
+                      'bg-blue-500': level === 'A',
+                      'bg-green-500': level === 'B',
+                      'bg-yellow-500': level === 'C'
+                    }"
+                    :style="{ width: `${(count / vendors.length) * 100}%` }"
+                  ></div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <!-- 状态分布图表 -->
+        <div class="mt-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">供应商状态分布</h3>
+          <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
+            <div v-for="(count, status) in statusDistribution" :key="status" class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+              <div class="flex justify-between items-center">
+                <span class="text-sm font-medium text-gray-500 dark:text-gray-400">{{ getStatusText(status) }}</span>
+                <span class="text-lg font-semibold text-gray-900 dark:text-white">{{ count }}</span>
+              </div>
+              <div class="mt-2">
+                <div class="w-full bg-gray-200 dark:bg-gray-600 rounded-full h-2">
+                  <div 
+                    class="h-2 rounded-full"
+                    :class="{
+                      'bg-green-500': status === 'active',
+                      'bg-yellow-500': status === 'inactive',
+                      'bg-red-500': status === 'blacklisted'
+                    }"
+                    :style="{ width: `${(count / vendors.length) * 100}%` }"
+                  ></div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 供应商列表 -->
+      <div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                供应商信息
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                联系方式
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                合作信息
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                状态
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                操作
+              </th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="vendor in paginatedVendors" :key="vendor.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">
+                  {{ vendor.name }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  ID: {{ vendor.id }}
+                </div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">
+                  {{ vendor.contactPerson }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ vendor.phone }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ vendor.email }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">
+                  等级: {{ vendor.level }}
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  合作时间: {{ formatDate(vendor.cooperationDate) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(vendor.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusText(vendor.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button 
+                  @click="handleViewDetails(vendor)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  详情
+                </button>
+                <button 
+                  @click="handleEditVendor(vendor)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  编辑
+                </button>
+                <button 
+                  @click="handleDeleteVendor(vendor)"
+                  class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                >
+                  删除
+                </button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 分页 -->
+      <div class="mt-4 flex justify-between items-center">
+        <div class="text-sm text-gray-700 dark:text-gray-300">
+          显示 {{ (pagination.currentPage - 1) * pagination.pageSize + 1 }} 到 {{ Math.min(pagination.currentPage * pagination.pageSize, vendors.length) }} 条,共 {{ vendors.length }} 条
+        </div>
+        <div class="flex space-x-2">
+          <button 
+            @click="handlePrevPage"
+            :disabled="pagination.currentPage === 1"
+            class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handleNextPage"
+            :disabled="pagination.currentPage === totalPages"
+            class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
+          >
+            下一页
+          </button>
+        </div>
+      </div>
+    </main>
+
+    <!-- 供应商详情弹窗 -->
+    <div v-if="showVendorDetails" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">供应商详情</h3>
+            <button 
+              @click="showVendorDetails = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <!-- 基本信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">基本信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">供应商编号</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.id }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">供应商名称</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.name }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">供应商等级</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.level }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合作时间</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedVendor?.cooperationDate) }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 联系信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">联系信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">联系人</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.contactPerson }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">联系电话</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.phone }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">电子邮箱</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.email }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">传真</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.fax }}</p>
+              </div>
+              <div class="md:col-span-2">
+                <p class="text-sm text-gray-500 dark:text-gray-400">地址</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.address }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 合作信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">合作信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">结算方式</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.paymentMethod }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">结算周期</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedVendor?.paymentCycle }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">信用额度</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">¥{{ selectedVendor?.creditLimit }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">已用额度</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">¥{{ selectedVendor?.usedCredit }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 备注信息 -->
+          <div>
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">备注信息</h4>
+            <p class="text-sm text-gray-900 dark:text-white">{{ selectedVendor?.remarks || '无' }}</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 编辑供应商弹窗 -->
+    <div v-if="showEditVendor" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">编辑供应商</h3>
+            <button 
+              @click="showEditVendor = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitEdit" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商名称</label>
+                <input 
+                  type="text" 
+                  v-model="editVendor.name"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商等级</label>
+                <select 
+                  v-model="editVendor.level"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="A">A级</option>
+                  <option value="B">B级</option>
+                  <option value="C">C级</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">联系人</label>
+                <input 
+                  type="text" 
+                  v-model="editVendor.contactPerson"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">联系电话</label>
+                <input 
+                  type="text" 
+                  v-model="editVendor.phone"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">电子邮箱</label>
+                <input 
+                  type="email" 
+                  v-model="editVendor.email"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">传真</label>
+                <input 
+                  type="text" 
+                  v-model="editVendor.fax"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">地址</label>
+                <input 
+                  type="text" 
+                  v-model="editVendor.address"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结算方式</label>
+                <select 
+                  v-model="editVendor.paymentMethod"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="cash">现金</option>
+                  <option value="bank">银行转账</option>
+                  <option value="check">支票</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结算周期</label>
+                <select 
+                  v-model="editVendor.paymentCycle"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="weekly">每周</option>
+                  <option value="monthly">每月</option>
+                  <option value="quarterly">每季度</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">信用额度</label>
+                <input 
+                  type="number" 
+                  v-model="editVendor.creditLimit"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">状态</label>
+                <select 
+                  v-model="editVendor.status"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="active">正常合作</option>
+                  <option value="inactive">暂停合作</option>
+                  <option value="blacklisted">黑名单</option>
+                </select>
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">备注</label>
+                <textarea 
+                  v-model="editVendor.remarks"
+                  rows="3"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showEditVendor = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                保存
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 添加供应商弹窗 -->
+    <div v-if="showAddVendor" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">添加供应商</h3>
+            <button 
+              @click="showAddVendor = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitAdd" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商名称</label>
+                <input 
+                  type="text" 
+                  v-model="newVendor.name"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商等级</label>
+                <select 
+                  v-model="newVendor.level"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="A">A级</option>
+                  <option value="B">B级</option>
+                  <option value="C">C级</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">联系人</label>
+                <input 
+                  type="text" 
+                  v-model="newVendor.contactPerson"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">联系电话</label>
+                <input 
+                  type="text" 
+                  v-model="newVendor.phone"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">电子邮箱</label>
+                <input 
+                  type="email" 
+                  v-model="newVendor.email"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">传真</label>
+                <input 
+                  type="text" 
+                  v-model="newVendor.fax"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">地址</label>
+                <input 
+                  type="text" 
+                  v-model="newVendor.address"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结算方式</label>
+                <select 
+                  v-model="newVendor.paymentMethod"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="cash">现金</option>
+                  <option value="bank">银行转账</option>
+                  <option value="check">支票</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结算周期</label>
+                <select 
+                  v-model="newVendor.paymentCycle"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="weekly">每周</option>
+                  <option value="monthly">每月</option>
+                  <option value="quarterly">每季度</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">信用额度</label>
+                <input 
+                  type="number" 
+                  v-model="newVendor.creditLimit"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">状态</label>
+                <select 
+                  v-model="newVendor.status"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="active">正常合作</option>
+                  <option value="inactive">暂停合作</option>
+                  <option value="blacklisted">黑名单</option>
+                </select>
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">备注</label>
+                <textarea 
+                  v-model="newVendor.remarks"
+                  rows="3"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showAddVendor = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                添加
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 删除确认弹窗 -->
+    <div v-if="showDeleteConfirm" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">确认删除</h3>
+            <button 
+              @click="showDeleteConfirm = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
+            确定要删除供应商 {{ selectedVendor?.name }} 吗?此操作不可撤销。
+          </p>
+
+          <div class="flex justify-end space-x-3">
+            <button 
+              @click="showDeleteConfirm = false"
+              class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              取消
+            </button>
+            <button 
+              @click="confirmDelete"
+              class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
+            >
+              删除
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 高级筛选弹窗 -->
+    <div v-if="showAdvancedFilter" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">高级筛选</h3>
+            <button 
+              @click="showAdvancedFilter = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleFilter" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商编号</label>
+                <input 
+                  type="text" 
+                  v-model="filters.id"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入供应商编号"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商名称</label>
+                <input 
+                  type="text" 
+                  v-model="filters.name"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入供应商名称"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">供应商等级</label>
+                <select 
+                  v-model="filters.level"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="">所有等级</option>
+                  <option value="A">A级</option>
+                  <option value="B">B级</option>
+                  <option value="C">C级</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">状态</label>
+                <select 
+                  v-model="filters.status"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="">所有状态</option>
+                  <option value="active">正常合作</option>
+                  <option value="inactive">暂停合作</option>
+                  <option value="blacklisted">黑名单</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结算方式</label>
+                <select 
+                  v-model="filters.paymentMethod"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="">所有结算方式</option>
+                  <option value="cash">现金</option>
+                  <option value="bank">银行转账</option>
+                  <option value="check">支票</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结算周期</label>
+                <select 
+                  v-model="filters.paymentCycle"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="">所有结算周期</option>
+                  <option value="weekly">每周</option>
+                  <option value="monthly">每月</option>
+                  <option value="quarterly">每季度</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">最小信用额度</label>
+                <input 
+                  type="number" 
+                  v-model="filters.minCreditLimit"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入最小信用额度"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">最大信用额度</label>
+                <input 
+                  type="number" 
+                  v-model="filters.maxCreditLimit"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="输入最大信用额度"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">开始日期</label>
+                <input 
+                  type="date" 
+                  v-model="filters.startDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">结束日期</label>
+                <input 
+                  type="date" 
+                  v-model="filters.endDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="resetFilters"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                重置
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                筛选
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 错误提示组件 -->
+    <div v-if="showError" class="fixed top-4 right-4 z-50">
+      <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
+        <strong class="font-bold">错误!</strong>
+        <span class="block sm:inline">{{ errorMessage }}</span>
+        <span class="absolute top-0 bottom-0 right-0 px-4 py-3" @click="showError = false">
+          <XIcon class="h-5 w-5 text-red-500" />
+        </span>
+      </div>
+    </div>
+
+    <!-- 成功提示组件 -->
+    <div v-if="showSuccess" class="fixed top-4 right-4 z-50">
+      <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative" role="alert">
+        <strong class="font-bold">成功!</strong>
+        <span class="block sm:inline">{{ successMessage }}</span>
+        <span class="absolute top-0 bottom-0 right-0 px-4 py-3" @click="showSuccess = false">
+          <XIcon class="h-5 w-5 text-green-500" />
+        </span>
+      </div>
+    </div>
+
+    <!-- 供应商评价弹窗 -->
+    <div v-if="showVendorRatings" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">供应商评价</h3>
+            <button 
+              @click="showVendorRatings = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <!-- 评价统计 -->
+          <div class="mb-6 bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+            <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">平均评分</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ averageRating }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">评价总数</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ selectedVendor?.ratings?.length || 0 }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">好评率</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ positiveRatingPercentage }}%</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">最近评价</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ formatDate(selectedVendor?.ratings?.[0]?.date) }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 评分分布 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">评分分布</h4>
+            <div class="space-y-2">
+              <div v-for="(count, rating) in ratingDistribution" :key="rating" class="flex items-center">
+                <span class="w-8 text-sm text-gray-500 dark:text-gray-400">{{ rating }}星</span>
+                <div class="flex-1 h-2 bg-gray-200 dark:bg-gray-600 rounded-full mx-2">
+                  <div 
+                    class="h-2 rounded-full bg-yellow-400"
+                    :style="{ width: `${(count / (selectedVendor?.ratings?.length || 1)) * 100}%` }"
+                  ></div>
+                </div>
+                <span class="w-8 text-sm text-gray-500 dark:text-gray-400">{{ count }}</span>
+              </div>
+            </div>
+          </div>
+
+          <!-- 评价列表 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">评价列表</h4>
+            <div class="space-y-4">
+              <div v-for="rating in selectedVendor?.ratings" :key="rating.id" class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+                <div class="flex justify-between items-start mb-2">
+                  <div class="flex items-center">
+                    <div class="flex">
+                      <StarIcon 
+                        v-for="i in 5" 
+                        :key="i"
+                        class="h-5 w-5"
+                        :class="i <= rating.score ? 'text-yellow-400' : 'text-gray-300 dark:text-gray-500'"
+                      />
+                    </div>
+                    <span class="ml-2 text-sm text-gray-500 dark:text-gray-400">{{ formatDate(rating.date) }}</span>
+                  </div>
+                  <button 
+                    v-if="rating.userId === 'current_user'"
+                    @click="handleDeleteRating(rating)"
+                    class="text-red-500 hover:text-red-700 dark:hover:text-red-400"
+                  >
+                    <Trash2Icon class="h-4 w-4" />
+                  </button>
+                </div>
+                <p class="text-sm text-gray-900 dark:text-white">{{ rating.comment }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 添加评价 -->
+          <div>
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">添加评价</h4>
+            <form @submit.prevent="handleSubmitRating" class="space-y-4">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">评分</label>
+                <div class="flex">
+                  <button 
+                    v-for="i in 5" 
+                    :key="i"
+                    type="button"
+                    @click="newRating.score = i"
+                    class="focus:outline-none"
+                  >
+                    <StarIcon 
+                      class="h-8 w-8"
+                      :class="i <= newRating.score ? 'text-yellow-400' : 'text-gray-300 dark:text-gray-500'"
+                    />
+                  </button>
+                </div>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">评价内容</label>
+                <textarea 
+                  v-model="newRating.comment"
+                  rows="3"
+                  class="w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                  placeholder="请输入评价内容"
+                ></textarea>
+              </div>
+              <div class="flex justify-end">
+                <button 
+                  type="submit"
+                  class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                >
+                  提交评价
+                </button>
+              </div>
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 供应商历史记录弹窗 -->
+    <div v-if="showVendorHistory" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">供应商历史记录</h3>
+            <button 
+              @click="showVendorHistory = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <!-- 历史记录统计 -->
+          <div class="mb-6 bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+            <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">总记录数</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ selectedVendor?.history?.length || 0 }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">最近更新</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ formatDate(selectedVendor?.history?.[0]?.date) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">信息变更</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ infoChangesCount }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">状态变更</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ statusChangesCount }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 历史记录列表 -->
+          <div class="space-y-4">
+            <div v-for="record in selectedVendor?.history" :key="record.id" class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+              <div class="flex justify-between items-start mb-2">
+                <div class="flex items-center">
+                  <div class="p-2 rounded-full" :class="getHistoryTypeClass(record.type)">
+                    <component 
+                      :is="getHistoryTypeIcon(record.type)"
+                      class="h-5 w-5"
+                      :class="getHistoryTypeIconClass(record.type)"
+                    />
+                  </div>
+                  <div class="ml-3">
+                    <p class="text-sm font-medium text-gray-900 dark:text-white">{{ getHistoryTypeText(record.type) }}</p>
+                    <p class="text-xs text-gray-500 dark:text-gray-400">{{ formatDate(record.date) }}</p>
+                  </div>
+                </div>
+                <span class="text-xs text-gray-500 dark:text-gray-400">{{ record.user }}</span>
+              </div>
+              <div class="mt-2">
+                <p class="text-sm text-gray-900 dark:text-white">{{ record.description }}</p>
+                <div v-if="record.changes" class="mt-2 space-y-1">
+                  <div v-for="(value, key) in record.changes" :key="key" class="text-xs text-gray-500 dark:text-gray-400">
+                    <span class="font-medium">{{ getFieldName(key) }}:</span>
+                    <span class="ml-1">{{ formatChangeValue(value) }}</span>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 供应商合同弹窗 -->
+    <div v-if="showVendorContracts" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">供应商合同管理</h3>
+            <button 
+              @click="showVendorContracts = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <!-- 合同统计 -->
+          <div class="mb-6 bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+            <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合同总数</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ selectedVendor?.contracts?.length || 0 }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">有效合同</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ validContractsCount }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">即将到期</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ expiringContractsCount }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">已过期</p>
+                <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ expiredContractsCount }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 合同列表 -->
+          <div class="mb-6">
+            <div class="flex justify-between items-center mb-4">
+              <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400">合同列表</h4>
+              <button 
+                @click="handleAddContract"
+                class="px-3 py-1 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 flex items-center space-x-2"
+              >
+                <PlusIcon class="h-4 w-4" />
+                <span>添加合同</span>
+              </button>
+            </div>
+            <div class="space-y-4">
+              <div v-for="contract in selectedVendor?.contracts" :key="contract.id" class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+                <div class="flex justify-between items-start mb-2">
+                  <div>
+                    <p class="text-sm font-medium text-gray-900 dark:text-white">{{ contract.name }}</p>
+                    <p class="text-xs text-gray-500 dark:text-gray-400">合同编号: {{ contract.id }}</p>
+                  </div>
+                  <div class="flex space-x-2">
+                    <button 
+                      @click="handleViewContract(contract)"
+                      class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300"
+                    >
+                      查看
+                    </button>
+                    <button 
+                      @click="handleEditContract(contract)"
+                      class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300"
+                    >
+                      编辑
+                    </button>
+                    <button 
+                      @click="handleDeleteContract(contract)"
+                      class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                    >
+                      删除
+                    </button>
+                  </div>
+                </div>
+                <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mt-2">
+                  <div>
+                    <p class="text-xs text-gray-500 dark:text-gray-400">签订日期</p>
+                    <p class="text-sm text-gray-900 dark:text-white">{{ formatDate(contract.signDate) }}</p>
+                  </div>
+                  <div>
+                    <p class="text-xs text-gray-500 dark:text-gray-400">生效日期</p>
+                    <p class="text-sm text-gray-900 dark:text-white">{{ formatDate(contract.startDate) }}</p>
+                  </div>
+                  <div>
+                    <p class="text-xs text-gray-500 dark:text-gray-400">到期日期</p>
+                    <p class="text-sm text-gray-900 dark:text-white">{{ formatDate(contract.endDate) }}</p>
+                  </div>
+                </div>
+                <div class="mt-2">
+                  <span :class="getContractStatusClass(contract.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                    {{ getContractStatusText(contract.status) }}
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 合同详情弹窗 -->
+    <div v-if="showContractDetails" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">合同详情</h3>
+            <button 
+              @click="showContractDetails = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <!-- 基本信息 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">基本信息</h4>
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合同编号</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedContract?.id }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合同名称</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedContract?.name }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合同类型</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ getContractTypeText(selectedContract?.type) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合同状态</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ getContractStatusText(selectedContract?.status) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">签订日期</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedContract?.signDate) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">生效日期</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedContract?.startDate) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">到期日期</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">{{ formatDate(selectedContract?.endDate) }}</p>
+              </div>
+              <div>
+                <p class="text-sm text-gray-500 dark:text-gray-400">合同金额</p>
+                <p class="text-sm font-medium text-gray-900 dark:text-white">¥{{ selectedContract?.amount }}</p>
+              </div>
+            </div>
+          </div>
+
+          <!-- 合同条款 -->
+          <div class="mb-6">
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">合同条款</h4>
+            <div class="bg-gray-50 dark:bg-gray-700 p-4 rounded-lg">
+              <p class="text-sm text-gray-900 dark:text-white whitespace-pre-line">{{ selectedContract?.terms }}</p>
+            </div>
+          </div>
+
+          <!-- 附件 -->
+          <div>
+            <h4 class="text-sm font-medium text-gray-500 dark:text-gray-400 mb-4">附件</h4>
+            <div class="space-y-2">
+              <div v-for="attachment in selectedContract?.attachments" :key="attachment.id" class="flex items-center justify-between bg-gray-50 dark:bg-gray-700 p-3 rounded-lg">
+                <div class="flex items-center">
+                  <FileIcon class="h-5 w-5 text-gray-400 mr-2" />
+                  <span class="text-sm text-gray-900 dark:text-white">{{ attachment.name }}</span>
+                </div>
+                <button 
+                  @click="handleDownloadAttachment(attachment)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300"
+                >
+                  下载
+                </button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 编辑合同弹窗 -->
+    <div v-if="showEditContract" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">编辑合同</h3>
+            <button 
+              @click="showEditContract = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitEditContract" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同名称</label>
+                <input 
+                  type="text" 
+                  v-model="editContract.name"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同类型</label>
+                <select 
+                  v-model="editContract.type"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="purchase">采购合同</option>
+                  <option value="service">服务合同</option>
+                  <option value="framework">框架协议</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">签订日期</label>
+                <input 
+                  type="date" 
+                  v-model="editContract.signDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">生效日期</label>
+                <input 
+                  type="date" 
+                  v-model="editContract.startDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">到期日期</label>
+                <input 
+                  type="date" 
+                  v-model="editContract.endDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同金额</label>
+                <input 
+                  type="number" 
+                  v-model="editContract.amount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同条款</label>
+                <textarea 
+                  v-model="editContract.terms"
+                  rows="5"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showEditContract = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                保存
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 添加合同弹窗 -->
+    <div v-if="showAddContract" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">添加合同</h3>
+            <button 
+              @click="showAddContract = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitAddContract" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同名称</label>
+                <input 
+                  type="text" 
+                  v-model="newContract.name"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同类型</label>
+                <select 
+                  v-model="newContract.type"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="purchase">采购合同</option>
+                  <option value="service">服务合同</option>
+                  <option value="framework">框架协议</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">签订日期</label>
+                <input 
+                  type="date" 
+                  v-model="newContract.signDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">生效日期</label>
+                <input 
+                  type="date" 
+                  v-model="newContract.startDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">到期日期</label>
+                <input 
+                  type="date" 
+                  v-model="newContract.endDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同金额</label>
+                <input 
+                  type="number" 
+                  v-model="newContract.amount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">合同条款</label>
+                <textarea 
+                  v-model="newContract.terms"
+                  rows="5"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">上传附件</label>
+                <div class="mt-1 flex justify-center px-6 pt-5 pb-6 border-2 border-gray-300 dark:border-gray-600 border-dashed rounded-md">
+                  <div class="space-y-1 text-center">
+                    <UploadIcon class="mx-auto h-12 w-12 text-gray-400" />
+                    <div class="flex text-sm text-gray-600 dark:text-gray-400">
+                      <label class="relative cursor-pointer bg-white dark:bg-gray-800 rounded-md font-medium text-indigo-600 hover:text-indigo-500 focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500">
+                        <span>上传文件</span>
+                        <input 
+                          type="file" 
+                          class="sr-only"
+                          @change="handleFileUpload"
+                          multiple
+                        />
+                      </label>
+                      <p class="pl-1">或拖拽文件到此处</p>
+                    </div>
+                    <p class="text-xs text-gray-500 dark:text-gray-400">
+                      PDF, DOC, DOCX, XLS, XLSX 格式,最大 10MB
+                    </p>
+                  </div>
+                </div>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showAddContract = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                添加
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+
+    <!-- 删除合同确认弹窗 -->
+    <div v-if="showDeleteContractConfirm" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">确认删除</h3>
+            <button 
+              @click="showDeleteContractConfirm = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
+            确定要删除合同 {{ selectedContract?.name }} 吗?此操作不可撤销。
+          </p>
+
+          <div class="flex justify-end space-x-3">
+            <button 
+              @click="showDeleteContractConfirm = false"
+              class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              取消
+            </button>
+            <button 
+              @click="confirmDeleteContract"
+              class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-600 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500"
+            >
+              删除
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, watch } from 'vue'
+import { 
+  SearchIcon, 
+  PlusIcon,
+  FilterIcon,
+  DownloadIcon,
+  UploadIcon,
+  XIcon,
+  UsersIcon,
+  CheckCircleIcon,
+  CreditCardIcon,
+  AlertCircleIcon,
+  StarIcon,
+  Trash2Icon,
+  EditIcon,
+  AlertTriangleIcon,
+  ClockIcon,
+  UserIcon,
+  FileIcon
+} from 'lucide-vue-next'
+
+// 供应商数据
+const vendors = ref([
+  {
+    id: 'V202401010001',
+    name: '供应商A',
+    level: 'A',
+    contactPerson: '张三',
+    phone: '13800138000',
+    email: 'zhangsan@example.com',
+    fax: '010-12345678',
+    address: '北京市朝阳区xxx街道xxx号',
+    paymentMethod: 'bank',
+    paymentCycle: 'monthly',
+    creditLimit: 100000,
+    usedCredit: 50000,
+    status: 'active',
+    cooperationDate: '2024-01-01',
+    remarks: '长期合作供应商'
+  },
+  {
+    id: 'V202401010002',
+    name: '供应商B',
+    level: 'B',
+    contactPerson: '李四',
+    phone: '13900139000',
+    email: 'lisi@example.com',
+    fax: '010-87654321',
+    address: '上海市浦东新区xxx街道xxx号',
+    paymentMethod: 'cash',
+    paymentCycle: 'weekly',
+    creditLimit: 50000,
+    usedCredit: 20000,
+    status: 'active',
+    cooperationDate: '2024-01-02',
+    remarks: '新合作供应商'
+  },
+  {
+    id: 'V202401010003',
+    name: '供应商C',
+    level: 'C',
+    contactPerson: '王五',
+    phone: '13700137000',
+    email: 'wangwu@example.com',
+    fax: '010-98765432',
+    address: '广州市天河区xxx街道xxx号',
+    paymentMethod: 'check',
+    paymentCycle: 'quarterly',
+    creditLimit: 20000,
+    usedCredit: 10000,
+    status: 'inactive',
+    cooperationDate: '2024-01-03',
+    remarks: '暂停合作'
+  }
+])
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    inactive: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
+    blacklisted: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+// 获取状态文本
+const getStatusText = (status) => {
+  const texts = {
+    active: '正常合作',
+    inactive: '暂停合作',
+    blacklisted: '黑名单'
+  }
+  return texts[status] || '未知'
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleString()
+}
+
+// 供应商详情相关
+const showVendorDetails = ref(false)
+const selectedVendor = ref(null)
+
+// 编辑供应商相关
+const showEditVendor = ref(false)
+const editVendor = ref({
+  id: '',
+  name: '',
+  level: '',
+  contactPerson: '',
+  phone: '',
+  email: '',
+  fax: '',
+  address: '',
+  paymentMethod: '',
+  paymentCycle: '',
+  creditLimit: 0,
+  usedCredit: 0,
+  status: '',
+  cooperationDate: '',
+  remarks: ''
+})
+
+// 添加供应商相关
+const showAddVendor = ref(false)
+const newVendor = ref({
+  name: '',
+  level: 'A',
+  contactPerson: '',
+  phone: '',
+  email: '',
+  fax: '',
+  address: '',
+  paymentMethod: 'bank',
+  paymentCycle: 'monthly',
+  creditLimit: 0,
+  usedCredit: 0,
+  status: 'active',
+  cooperationDate: new Date().toISOString().split('T')[0],
+  remarks: ''
+})
+
+// 删除确认相关
+const showDeleteConfirm = ref(false)
+
+// 高级筛选相关
+const showAdvancedFilter = ref(false)
+const filters = ref({
+  id: '',
+  name: '',
+  level: '',
+  status: '',
+  paymentMethod: '',
+  paymentCycle: '',
+  minCreditLimit: '',
+  maxCreditLimit: '',
+  startDate: '',
+  endDate: ''
+})
+
+// 分页相关
+const pagination = ref({
+  currentPage: 1,
+  pageSize: 10,
+  total: 0
+})
+
+// 计算分页数据
+const paginatedVendors = computed(() => {
+  const start = (pagination.value.currentPage - 1) * pagination.value.pageSize
+  const end = start + pagination.value.pageSize
+  return vendors.value.slice(start, end)
+})
+
+// 计算总页数
+const totalPages = computed(() => {
+  return Math.ceil(vendors.value.length / pagination.value.pageSize)
+})
+
+// 处理查看详情
+const handleViewDetails = (vendor) => {
+  selectedVendor.value = vendor
+  showVendorDetails.value = true
+  showVendorRatings.value = true
+  showVendorHistory.value = true
+}
+
+// 处理编辑供应商
+const handleEditVendor = (vendor) => {
+  editVendor.value = { ...vendor }
+  showEditVendor.value = true
+}
+
+// 表单验证相关
+const validateForm = (formData) => {
+  const errors = {}
+
+  // 验证供应商名称
+  if (!formData.name) {
+    errors.name = '供应商名称不能为空'
+  } else if (formData.name.length < 2) {
+    errors.name = '供应商名称至少需要2个字符'
+  }
+
+  // 验证联系人
+  if (!formData.contactPerson) {
+    errors.contactPerson = '联系人不能为空'
+  }
+
+  // 验证联系电话
+  if (!formData.phone) {
+    errors.phone = '联系电话不能为空'
+  } else if (!/^1[3-9]\d{9}$/.test(formData.phone)) {
+    errors.phone = '请输入有效的手机号码'
+  }
+
+  // 验证电子邮箱
+  if (!formData.email) {
+    errors.email = '电子邮箱不能为空'
+  } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
+    errors.email = '请输入有效的电子邮箱'
+  }
+
+  // 验证信用额度
+  if (formData.creditLimit === undefined || formData.creditLimit === '') {
+    errors.creditLimit = '信用额度不能为空'
+  } else if (isNaN(formData.creditLimit) || formData.creditLimit < 0) {
+    errors.creditLimit = '信用额度必须是非负数'
+  }
+
+  // 验证已用额度
+  if (formData.usedCredit === undefined || formData.usedCredit === '') {
+    errors.usedCredit = '已用额度不能为空'
+  } else if (isNaN(formData.usedCredit) || formData.usedCredit < 0) {
+    errors.usedCredit = '已用额度必须是非负数'
+  } else if (formData.usedCredit > formData.creditLimit) {
+    errors.usedCredit = '已用额度不能超过信用额度'
+  }
+
+  return errors
+}
+
+// 错误提示相关
+const showError = ref(false)
+const errorMessage = ref('')
+const showSuccess = ref(false)
+const successMessage = ref('')
+
+// 显示错误提示
+const showErrorMessage = (message) => {
+  errorMessage.value = message
+  showError.value = true
+  setTimeout(() => {
+    showError.value = false
+  }, 5000)
+}
+
+// 显示成功提示
+const showSuccessMessage = (message) => {
+  successMessage.value = message
+  showSuccess.value = true
+  setTimeout(() => {
+    showSuccess.value = false
+  }, 3000)
+}
+
+// 修改处理提交编辑
+const handleSubmitEdit = () => {
+  const errors = validateForm(editVendor.value)
+  if (Object.keys(errors).length > 0) {
+    showErrorMessage(Object.values(errors).join('\n'))
+    return
+  }
+
+  const index = vendors.value.findIndex(v => v.id === editVendor.value.id)
+  if (index !== -1) {
+    const oldVendor = vendors.value[index]
+    const changes = {}
+    
+    // 比较变更
+    Object.keys(editVendor.value).forEach(key => {
+      if (oldVendor[key] !== editVendor.value[key]) {
+        changes[key] = {
+          old: oldVendor[key],
+          new: editVendor.value[key]
+        }
+      }
+    })
+    
+    // 添加历史记录
+    addHistoryRecord(
+      editVendor.value,
+      'info',
+      '更新供应商信息',
+      changes
+    )
+    
+    vendors.value[index] = { ...editVendor.value }
+    saveToLocalStorage()
+    showSuccessMessage('供应商信息更新成功')
+  }
+  showEditVendor.value = false
+}
+
+// 修改处理提交添加
+const handleSubmitAdd = () => {
+  const errors = validateForm(newVendor.value)
+  if (Object.keys(errors).length > 0) {
+    showErrorMessage(Object.values(errors).join('\n'))
+    return
+  }
+
+  const vendor = {
+    ...newVendor.value,
+    id: `V${new Date().getTime()}`
+  }
+  
+  // 添加历史记录
+  addHistoryRecord(
+    vendor,
+    'info',
+    '新增供应商'
+  )
+  
+  vendors.value.push(vendor)
+  saveToLocalStorage()
+  pagination.value.currentPage = 1
+  showAddVendor.value = false
+  showSuccessMessage('供应商添加成功')
+}
+
+// 处理删除供应商
+const handleDeleteVendor = (vendor) => {
+  selectedVendor.value = vendor
+  showDeleteConfirm.value = true
+}
+
+// 确认删除
+const confirmDelete = () => {
+  const index = vendors.value.findIndex(v => v.id === selectedVendor.value.id)
+  if (index !== -1) {
+    // 添加历史记录
+    addHistoryRecord(
+      selectedVendor.value,
+      'status',
+      '删除供应商'
+    )
+    
+    vendors.value.splice(index, 1)
+    saveToLocalStorage()
+    if (paginatedVendors.value.length === 0 && pagination.value.currentPage > 1) {
+      pagination.value.currentPage--
+    }
+    showSuccessMessage('供应商删除成功')
+  }
+  showDeleteConfirm.value = false
+}
+
+// 本地存储相关
+const STORAGE_KEY = 'ecommerce_vendors'
+
+// 保存数据到本地存储
+const saveToLocalStorage = () => {
+  try {
+    localStorage.setItem(STORAGE_KEY, JSON.stringify(vendors.value))
+  } catch (error) {
+    console.error('保存数据失败:', error)
+  }
+}
+
+// 从本地存储加载数据
+const loadFromLocalStorage = () => {
+  try {
+    const data = localStorage.getItem(STORAGE_KEY)
+    if (data) {
+      vendors.value = JSON.parse(data)
+    }
+  } catch (error) {
+    console.error('加载数据失败:', error)
+  }
+}
+
+// 在组件挂载时加载数据
+onMounted(() => {
+  loadFromLocalStorage()
+})
+
+// 在数据变化时保存数据
+watch(vendors, () => {
+  saveToLocalStorage()
+}, { deep: true })
+
+// 处理筛选
+const handleFilter = () => {
+  // 实现筛选逻辑
+  const filteredVendors = vendors.value.filter(vendor => {
+    // 供应商编号筛选
+    if (filters.value.id && !vendor.id.includes(filters.value.id)) {
+      return false
+    }
+    
+    // 供应商名称筛选
+    if (filters.value.name && !vendor.name.includes(filters.value.name)) {
+      return false
+    }
+    
+    // 供应商等级筛选
+    if (filters.value.level && vendor.level !== filters.value.level) {
+      return false
+    }
+    
+    // 状态筛选
+    if (filters.value.status && vendor.status !== filters.value.status) {
+      return false
+    }
+    
+    // 结算方式筛选
+    if (filters.value.paymentMethod && vendor.paymentMethod !== filters.value.paymentMethod) {
+      return false
+    }
+    
+    // 结算周期筛选
+    if (filters.value.paymentCycle && vendor.paymentCycle !== filters.value.paymentCycle) {
+      return false
+    }
+    
+    // 信用额度范围筛选
+    if (filters.value.minCreditLimit && vendor.creditLimit < Number(filters.value.minCreditLimit)) {
+      return false
+    }
+    if (filters.value.maxCreditLimit && vendor.creditLimit > Number(filters.value.maxCreditLimit)) {
+      return false
+    }
+    
+    // 合作时间范围筛选
+    if (filters.value.startDate && new Date(vendor.cooperationDate) < new Date(filters.value.startDate)) {
+      return false
+    }
+    if (filters.value.endDate && new Date(vendor.cooperationDate) > new Date(filters.value.endDate)) {
+      return false
+    }
+    
+    return true
+  })
+  
+  // 更新显示的数据
+  vendors.value = filteredVendors
+  // 重置页码
+  pagination.value.currentPage = 1
+  showAdvancedFilter.value = false
+}
+
+// 重置筛选条件
+const resetFilters = () => {
+  filters.value = {
+    id: '',
+    name: '',
+    level: '',
+    status: '',
+    paymentMethod: '',
+    paymentCycle: '',
+    minCreditLimit: '',
+    maxCreditLimit: '',
+    startDate: '',
+    endDate: ''
+  }
+}
+
+// 处理上一页
+const handlePrevPage = () => {
+  if (pagination.value.currentPage > 1) {
+    pagination.value.currentPage--
+  }
+}
+
+// 处理下一页
+const handleNextPage = () => {
+  if (pagination.value.currentPage < totalPages.value) {
+    pagination.value.currentPage++
+  }
+}
+
+// 搜索相关
+const searchQuery = ref('')
+const searchStatus = ref('')
+const searchLevel = ref('')
+
+// 处理搜索
+const handleSearch = () => {
+  const filteredVendors = vendors.value.filter(vendor => {
+    // 搜索关键词匹配
+    if (searchQuery.value) {
+      const query = searchQuery.value.toLowerCase()
+      const matchName = vendor.name.toLowerCase().includes(query)
+      const matchContact = vendor.contactPerson.toLowerCase().includes(query)
+      const matchPhone = vendor.phone.includes(query)
+      const matchEmail = vendor.email.toLowerCase().includes(query)
+      if (!matchName && !matchContact && !matchPhone && !matchEmail) {
+        return false
+      }
+    }
+    
+    // 状态筛选
+    if (searchStatus.value && vendor.status !== searchStatus.value) {
+      return false
+    }
+    
+    // 等级筛选
+    if (searchLevel.value && vendor.level !== searchLevel.value) {
+      return false
+    }
+    
+    return true
+  })
+  
+  // 更新显示的数据
+  vendors.value = filteredVendors
+  // 重置页码
+  pagination.value.currentPage = 1
+}
+
+// 重置搜索
+const resetSearch = () => {
+  searchQuery.value = ''
+  searchStatus.value = ''
+  searchLevel.value = ''
+  handleSearch()
+}
+
+// 处理导入
+const handleImport = () => {
+  try {
+    const input = document.createElement('input')
+    input.type = 'file'
+    input.accept = '.json'
+    
+    input.onchange = (e) => {
+      const file = e.target.files[0]
+      if (file) {
+        const reader = new FileReader()
+        
+        reader.onload = (e) => {
+          try {
+            const data = JSON.parse(e.target.result)
+            
+            if (Array.isArray(data)) {
+              // 验证每个供应商数据
+              const invalidVendors = data.filter(vendor => {
+                const errors = validateForm(vendor)
+                return Object.keys(errors).length > 0
+              })
+
+              if (invalidVendors.length > 0) {
+                showErrorMessage('导入的数据中包含无效的供应商信息,请检查数据格式')
+                return
+              }
+
+              vendors.value = data
+              saveToLocalStorage()
+              pagination.value.currentPage = 1
+              showSuccessMessage('供应商数据导入成功')
+            } else {
+              throw new Error('导入的数据必须是数组格式')
+            }
+          } catch (error) {
+            console.error('导入失败:', error)
+            showErrorMessage('导入失败:' + error.message)
+          }
+        }
+        
+        reader.onerror = () => {
+          console.error('文件读取失败')
+          showErrorMessage('文件读取失败')
+        }
+        
+        reader.readAsText(file)
+      }
+    }
+    
+    input.click()
+  } catch (error) {
+    console.error('导入失败:', error)
+    showErrorMessage('导入失败:' + error.message)
+  }
+}
+
+// 处理导出
+const handleExport = () => {
+  try {
+    // 准备导出数据
+    const exportData = vendors.value.map(vendor => ({
+      id: vendor.id,
+      name: vendor.name,
+      level: vendor.level,
+      contactPerson: vendor.contactPerson,
+      phone: vendor.phone,
+      email: vendor.email,
+      fax: vendor.fax,
+      address: vendor.address,
+      paymentMethod: vendor.paymentMethod,
+      paymentCycle: vendor.paymentCycle,
+      creditLimit: vendor.creditLimit,
+      usedCredit: vendor.usedCredit,
+      status: vendor.status,
+      cooperationDate: vendor.cooperationDate,
+      remarks: vendor.remarks
+    }))
+
+    // 转换为JSON字符串
+    const data = JSON.stringify(exportData, null, 2)
+    
+    // 创建Blob对象
+    const blob = new Blob([data], { type: 'application/json' })
+    const url = URL.createObjectURL(blob)
+    
+    // 创建下载链接
+    const a = document.createElement('a')
+    a.href = url
+    a.download = `vendors_${new Date().toISOString().split('T')[0]}.json`
+    
+    // 触发下载
+    document.body.appendChild(a)
+    a.click()
+    document.body.removeChild(a)
+    
+    // 释放URL
+    URL.revokeObjectURL(url)
+    showSuccessMessage('供应商数据导出成功')
+  } catch (error) {
+    console.error('导出失败:', error)
+    showErrorMessage('导出失败:' + error.message)
+  }
+}
+
+// 统计相关计算属性
+const activeVendorsCount = computed(() => {
+  return vendors.value.filter(v => v.status === 'active').length
+})
+
+const totalCreditLimit = computed(() => {
+  return vendors.value.reduce((sum, v) => sum + v.creditLimit, 0)
+})
+
+const totalUsedCredit = computed(() => {
+  return vendors.value.reduce((sum, v) => sum + v.usedCredit, 0)
+})
+
+const levelDistribution = computed(() => {
+  const distribution = { A: 0, B: 0, C: 0 }
+  vendors.value.forEach(v => {
+    distribution[v.level]++
+  })
+  return distribution
+})
+
+const statusDistribution = computed(() => {
+  const distribution = { active: 0, inactive: 0, blacklisted: 0 }
+  vendors.value.forEach(v => {
+    distribution[v.status]++
+  })
+  return distribution
+})
+
+// 评价相关
+const showVendorRatings = ref(false)
+const newRating = ref({
+  score: 0,
+  comment: '',
+  date: new Date().toISOString(),
+  userId: 'current_user'
+})
+
+// 计算平均评分
+const averageRating = computed(() => {
+  if (!selectedVendor.value?.ratings?.length) return 0
+  const sum = selectedVendor.value.ratings.reduce((acc, rating) => acc + rating.score, 0)
+  return (sum / selectedVendor.value.ratings.length).toFixed(1)
+})
+
+// 计算好评率
+const positiveRatingPercentage = computed(() => {
+  if (!selectedVendor.value?.ratings?.length) return 0
+  const positiveCount = selectedVendor.value.ratings.filter(rating => rating.score >= 4).length
+  return ((positiveCount / selectedVendor.value.ratings.length) * 100).toFixed(1)
+})
+
+// 计算评分分布
+const ratingDistribution = computed(() => {
+  const distribution = { 5: 0, 4: 0, 3: 0, 2: 0, 1: 0 }
+  selectedVendor.value?.ratings?.forEach(rating => {
+    distribution[rating.score]++
+  })
+  return distribution
+})
+
+// 处理提交评价
+const handleSubmitRating = () => {
+  if (!newRating.value.score) {
+    showErrorMessage('请选择评分')
+    return
+  }
+  if (!newRating.value.comment) {
+    showErrorMessage('请输入评价内容')
+    return
+  }
+
+  const rating = {
+    ...newRating.value,
+    id: `R${new Date().getTime()}`
+  }
+
+  if (!selectedVendor.value.ratings) {
+    selectedVendor.value.ratings = []
+  }
+  selectedVendor.value.ratings.unshift(rating)
+  
+  // 添加历史记录
+  addHistoryRecord(
+    selectedVendor.value,
+    'rating',
+    '添加评价',
+    {
+      score: rating.score,
+      comment: rating.comment
+    }
+  )
+  
+  // 更新供应商数据
+  const index = vendors.value.findIndex(v => v.id === selectedVendor.value.id)
+  if (index !== -1) {
+    vendors.value[index] = { ...selectedVendor.value }
+    saveToLocalStorage()
+    showSuccessMessage('评价提交成功')
+  }
+
+  // 重置表单
+  newRating.value = {
+    score: 0,
+    comment: '',
+    date: new Date().toISOString(),
+    userId: 'current_user'
+  }
+}
+
+// 处理删除评价
+const handleDeleteRating = (rating) => {
+  const index = selectedVendor.value.ratings.findIndex(r => r.id === rating.id)
+  if (index !== -1) {
+    // 添加历史记录
+    addHistoryRecord(
+      selectedVendor.value,
+      'rating',
+      '删除评价',
+      {
+        score: rating.score,
+        comment: rating.comment
+      }
+    )
+    
+    selectedVendor.value.ratings.splice(index, 1)
+    
+    // 更新供应商数据
+    const vendorIndex = vendors.value.findIndex(v => v.id === selectedVendor.value.id)
+    if (vendorIndex !== -1) {
+      vendors.value[vendorIndex] = { ...selectedVendor.value }
+      saveToLocalStorage()
+      showSuccessMessage('评价删除成功')
+    }
+  }
+}
+
+// 历史记录相关
+const showVendorHistory = ref(false)
+
+// 计算信息变更次数
+const infoChangesCount = computed(() => {
+  if (!selectedVendor.value?.history) return 0
+  return selectedVendor.value.history.filter(record => record.type === 'info').length
+})
+
+// 计算状态变更次数
+const statusChangesCount = computed(() => {
+  if (!selectedVendor.value?.history) return 0
+  return selectedVendor.value.history.filter(record => record.type === 'status').length
+})
+
+// 获取历史记录类型样式
+const getHistoryTypeClass = (type) => {
+  const classes = {
+    info: 'bg-blue-100 dark:bg-blue-900',
+    status: 'bg-yellow-100 dark:bg-yellow-900',
+    credit: 'bg-purple-100 dark:bg-purple-900',
+    rating: 'bg-green-100 dark:bg-green-900'
+  }
+  return classes[type] || 'bg-gray-100 dark:bg-gray-900'
+}
+
+// 获取历史记录类型图标
+const getHistoryTypeIcon = (type) => {
+  const icons = {
+    info: EditIcon,
+    status: AlertTriangleIcon,
+    credit: CreditCardIcon,
+    rating: StarIcon
+  }
+  return icons[type] || ClockIcon
+}
+
+// 获取历史记录类型图标样式
+const getHistoryTypeIconClass = (type) => {
+  const classes = {
+    info: 'text-blue-600 dark:text-blue-300',
+    status: 'text-yellow-600 dark:text-yellow-300',
+    credit: 'text-purple-600 dark:text-purple-300',
+    rating: 'text-green-600 dark:text-green-300'
+  }
+  return classes[type] || 'text-gray-600 dark:text-gray-300'
+}
+
+// 获取历史记录类型文本
+const getHistoryTypeText = (type) => {
+  const texts = {
+    info: '信息变更',
+    status: '状态变更',
+    credit: '信用额度变更',
+    rating: '评价变更'
+  }
+  return texts[type] || '其他变更'
+}
+
+// 获取字段名称
+const getFieldName = (key) => {
+  const names = {
+    name: '供应商名称',
+    level: '供应商等级',
+    contactPerson: '联系人',
+    phone: '联系电话',
+    email: '电子邮箱',
+    fax: '传真',
+    address: '地址',
+    paymentMethod: '结算方式',
+    paymentCycle: '结算周期',
+    creditLimit: '信用额度',
+    usedCredit: '已用额度',
+    status: '状态',
+    remarks: '备注'
+  }
+  return names[key] || key
+}
+
+// 格式化变更值
+const formatChangeValue = (value) => {
+  if (typeof value === 'object') {
+    return `${value.old} → ${value.new}`
+  }
+  return value
+}
+
+// 添加历史记录
+const addHistoryRecord = (vendor, type, description, changes = null) => {
+  if (!vendor.history) {
+    vendor.history = []
+  }
+  
+  const record = {
+    id: `H${new Date().getTime()}`,
+    type,
+    date: new Date().toISOString(),
+    user: '当前用户',
+    description,
+    changes
+  }
+  
+  vendor.history.unshift(record)
+}
+
+// 合同相关
+const showVendorContracts = ref(false)
+const showContractDetails = ref(false)
+const showEditContract = ref(false)
+const showAddContract = ref(false)
+const showDeleteContractConfirm = ref(false)
+const selectedContract = ref(null)
+const editContract = ref({
+  id: '',
+  name: '',
+  type: '',
+  signDate: '',
+  startDate: '',
+  endDate: '',
+  amount: 0,
+  terms: '',
+  status: 'active'
+})
+const newContract = ref({
+  name: '',
+  type: 'purchase',
+  signDate: new Date().toISOString().split('T')[0],
+  startDate: new Date().toISOString().split('T')[0],
+  endDate: '',
+  amount: 0,
+  terms: '',
+  status: 'active'
+})
+
+// 获取合同状态样式
+const getContractStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    expired: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
+    expiring: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+// 获取合同状态文本
+const getContractStatusText = (status) => {
+  const texts = {
+    active: '有效',
+    expired: '已过期',
+    expiring: '即将到期'
+  }
+  return texts[status] || '未知'
+}
+
+// 获取合同类型文本
+const getContractTypeText = (type) => {
+  const texts = {
+    purchase: '采购合同',
+    service: '服务合同',
+    framework: '框架协议'
+  }
+  return texts[type] || '未知'
+}
+
+// 计算有效合同数量
+const validContractsCount = computed(() => {
+  if (!selectedVendor.value?.contracts) return 0
+  return selectedVendor.value.contracts.filter(c => c.status === 'active').length
+})
+
+// 计算即将到期合同数量
+const expiringContractsCount = computed(() => {
+  if (!selectedVendor.value?.contracts) return 0
+  const now = new Date()
+  const thirtyDaysLater = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000)
+  return selectedVendor.value.contracts.filter(c => {
+    const endDate = new Date(c.endDate)
+    return endDate > now && endDate <= thirtyDaysLater
+  }).length
+})
+
+// 计算已过期合同数量
+const expiredContractsCount = computed(() => {
+  if (!selectedVendor.value?.contracts) return 0
+  const now = new Date()
+  return selectedVendor.value.contracts.filter(c => new Date(c.endDate) < now).length
+})
+
+// 处理查看合同
+const handleViewContract = (contract) => {
+  selectedContract.value = contract
+  showContractDetails.value = true
+}
+
+// 处理编辑合同
+const handleEditContract = (contract) => {
+  editContract.value = { ...contract }
+  showEditContract.value = true
+}
+
+// 处理添加合同
+const handleAddContract = () => {
+  showAddContract.value = true
+}
+
+// 处理删除合同
+const handleDeleteContract = (contract) => {
+  selectedContract.value = contract
+  showDeleteContractConfirm.value = true
+}
+
+// 处理文件上传
+const handleFileUpload = (event) => {
+  const files = event.target.files
+  if (files.length > 0) {
+    // 处理文件上传逻辑
+    console.log('Files uploaded:', files)
+  }
+}
+
+// 处理下载附件
+const handleDownloadAttachment = (attachment) => {
+  // 实现下载逻辑
+  console.log('Download attachment:', attachment)
+}
+
+// 处理提交编辑合同
+const handleSubmitEditContract = () => {
+  // 实现编辑合同逻辑
+  const index = selectedVendor.value.contracts.findIndex(c => c.id === editContract.value.id)
+  if (index !== -1) {
+    selectedVendor.value.contracts[index] = { ...editContract.value }
+    saveToLocalStorage()
+    showSuccessMessage('合同更新成功')
+  }
+  showEditContract.value = false
+}
+
+// 处理提交添加合同
+const handleSubmitAddContract = () => {
+  // 实现添加合同逻辑
+  const contract = {
+    ...newContract.value,
+    id: `C${new Date().getTime()}`
+  }
+  
+  if (!selectedVendor.value.contracts) {
+    selectedVendor.value.contracts = []
+  }
+  
+  selectedVendor.value.contracts.push(contract)
+  saveToLocalStorage()
+  showSuccessMessage('合同添加成功')
+  showAddContract.value = false
+}
+
+// 确认删除合同
+const confirmDeleteContract = () => {
+  const index = selectedVendor.value.contracts.findIndex(c => c.id === selectedContract.value.id)
+  if (index !== -1) {
+    selectedVendor.value.contracts.splice(index, 1)
+    saveToLocalStorage()
+    showSuccessMessage('合同删除成功')
+  }
+  showDeleteContractConfirm.value = false
+}
+</script>
+
+<style scoped>
+/* 样式内容 */
+</style>

+ 2301 - 0
src/assets/templates/prototype/ecommerce/ProductManagement.vue

@@ -0,0 +1,2301 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex">
+            <div class="flex-shrink-0 flex items-center">
+              <h1 class="text-xl font-bold text-gray-900 dark:text-white">商品管理</h1>
+            </div>
+          </div>
+          <div class="flex items-center">
+            <button 
+              @click="handleExport"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              <DownloadIcon class="h-4 w-4 mr-2" />
+              导出
+            </button>
+            <button 
+              @click="handleImport"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              <UploadIcon class="h-4 w-4 mr-2" />
+              导入
+            </button>
+            <button 
+              @click="handleManageCategories"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              <ListIcon class="h-4 w-4 mr-2" />
+              分类管理
+            </button>
+            <button 
+              @click="handleManageTags"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              <TagIcon class="h-4 w-4 mr-2" />
+              标签管理
+            </button>
+            <button 
+              @click="handleAddProduct"
+              class="ml-4 inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+            >
+              <PlusIcon class="h-4 w-4 mr-2" />
+              添加商品
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="mb-6 bg-white dark:bg-gray-800 shadow rounded-lg p-4">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              type="text"
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"
+              placeholder="搜索商品名称/编号"
+            />
+            <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
+              <SearchIcon class="h-5 w-5 text-gray-400" />
+            </div>
+          </div>
+          <select class="border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
+            <option value="">所有分类</option>
+            <option value="electronics">电子产品</option>
+            <option value="clothing">服装</option>
+            <option value="food">食品</option>
+          </select>
+          <select class="border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
+            <option value="">所有状态</option>
+            <option value="active">在售</option>
+            <option value="inactive">下架</option>
+            <option value="out_of_stock">缺货</option>
+          </select>
+          <button 
+            @click="showAdvancedFilter = true"
+            class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+          >
+            <FilterIcon class="h-4 w-4 mr-2" />
+            高级筛选
+          </button>
+        </div>
+      </div>
+
+      <!-- 商品列表 -->
+      <div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden">
+        <div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
+          <div class="flex items-center justify-between">
+            <div class="flex items-center space-x-2">
+              <input
+                type="checkbox"
+                v-model="selectAll"
+                @change="handleSelectAll"
+                class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 dark:border-gray-600 rounded"
+              />
+              <span class="text-sm text-gray-700 dark:text-gray-300">全选</span>
+            </div>
+            <div class="flex items-center space-x-2">
+              <span class="text-sm text-gray-700 dark:text-gray-300">
+                已选择 {{ selectedProducts.length }} 个商品
+              </span>
+              <button
+                v-if="selectedProducts.length > 0"
+                @click="showBatchOperationDialog = true"
+                class="inline-flex items-center px-3 py-1.5 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                批量操作
+              </button>
+            </div>
+          </div>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                <input
+                  type="checkbox"
+                  v-model="selectAll"
+                  @change="handleSelectAll"
+                  class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 dark:border-gray-600 rounded"
+                />
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                商品信息
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                分类
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                价格
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                库存
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                状态
+              </th>
+              <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                操作
+              </th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="product in filteredProducts" :key="product.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <input
+                  type="checkbox"
+                  v-model="selectedProducts"
+                  :value="product"
+                  class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 dark:border-gray-600 rounded"
+                />
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="flex items-center">
+                  <div class="flex-shrink-0 h-10 w-10">
+                    <img class="h-10 w-10 rounded-full" :src="product.image" :alt="product.name" />
+                  </div>
+                  <div class="ml-4">
+                    <div class="text-sm font-medium text-gray-900 dark:text-white">
+                      {{ product.name }}
+                    </div>
+                    <div class="text-sm text-gray-500 dark:text-gray-400">
+                      {{ product.id }}
+                    </div>
+                    <div class="flex flex-wrap gap-1 mt-1">
+                      <span 
+                        v-for="tag in product.tags" 
+                        :key="tag.id"
+                        :class="getTagClass(tag.type)"
+                        class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium"
+                      >
+                        {{ tag.name }}
+                      </span>
+                    </div>
+                  </div>
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ product.category }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">¥{{ product.price }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ product.stock }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(product.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusText(product.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button 
+                  @click="handleViewDetails(product)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  详情
+                </button>
+                <button 
+                  @click="handleEditProduct(product)"
+                  class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4"
+                >
+                  编辑
+                </button>
+                <button 
+                  @click="handleDeleteProduct(product)"
+                  class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                >
+                  删除
+                </button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 分页 -->
+      <div class="mt-4 flex justify-between items-center">
+        <div class="text-sm text-gray-700 dark:text-gray-300">
+          显示 1 到 10 条,共 100 条
+        </div>
+        <div class="flex space-x-2">
+          <button class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+            上一页
+          </button>
+          <button class="px-3 py-1 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+            下一页
+          </button>
+        </div>
+      </div>
+    </main>
+
+    <!-- 添加/编辑商品弹窗 -->
+    <div v-if="showProductForm" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    {{ isEdit ? '编辑商品' : '添加商品' }}
+                  </h3>
+                  <button @click="showProductForm = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <form @submit.prevent="handleProductSubmit" class="space-y-4">
+                  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                      <input
+                        v-model="productForm.name"
+                        type="text"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品编号</label>
+                      <input
+                        v-model="productForm.id"
+                        type="text"
+                        :disabled="isEdit"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品分类</label>
+                      <select
+                        v-model="productForm.category"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      >
+                        <option value="">请选择分类</option>
+                        <option value="electronics">电子产品</option>
+                        <option value="clothing">服装</option>
+                        <option value="food">食品</option>
+                      </select>
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品价格</label>
+                      <input
+                        v-model.number="productForm.price"
+                        type="number"
+                        min="0"
+                        step="0.01"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品库存</label>
+                      <input
+                        v-model.number="productForm.stock"
+                        type="number"
+                        min="0"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                    <div>
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品状态</label>
+                      <select
+                        v-model="productForm.status"
+                        required
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      >
+                        <option value="active">在售</option>
+                        <option value="inactive">下架</option>
+                        <option value="out_of_stock">缺货</option>
+                      </select>
+                    </div>
+                    <div class="md:col-span-2">
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品图片</label>
+                      <div class="mt-1 flex items-center">
+                        <img
+                          v-if="productForm.image"
+                          :src="productForm.image"
+                          class="h-20 w-20 rounded-md object-cover"
+                        />
+                        <input
+                          type="file"
+                          accept="image/*"
+                          @change="handleImageUpload"
+                          class="ml-4"
+                        />
+                      </div>
+                    </div>
+                    <div class="md:col-span-2">
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品描述</label>
+                      <textarea
+                        v-model="productForm.description"
+                        rows="3"
+                        class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      ></textarea>
+                    </div>
+                    <div class="md:col-span-2">
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品标签</label>
+                      <div class="mt-1">
+                        <div class="flex flex-wrap gap-2 mb-2">
+                          <span 
+                            v-for="tag in productForm.tags" 
+                            :key="tag.id"
+                            :class="getTagClass(tag.type)"
+                            class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium"
+                          >
+                            {{ tag.name }}
+                            <button 
+                              @click="removeTag(tag)"
+                              class="ml-1 text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+                            >
+                              <XIcon class="h-3 w-3" />
+                            </button>
+                          </span>
+                        </div>
+                        <div class="flex items-center space-x-2">
+                          <select
+                            v-model="selectedTag"
+                            class="flex-1 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                          >
+                            <option value="">选择标签</option>
+                            <option v-for="tag in availableTags" :key="tag.id" :value="tag">
+                              {{ tag.name }} ({{ tag.type }})
+                            </option>
+                          </select>
+                          <button
+                            @click="addTag"
+                            class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                          >
+                            添加标签
+                          </button>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                  <div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
+                    <button
+                      type="submit"
+                      class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+                    >
+                      保存
+                    </button>
+                    <button
+                      type="button"
+                      @click="showProductForm = false"
+                      class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+                    >
+                      取消
+                    </button>
+                  </div>
+                </form>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 确认对话框 -->
+    <div v-if="showConfirmDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                  {{ confirmDialog.title }}
+                </h3>
+                <div class="mt-2">
+                  <p class="text-sm text-gray-500 dark:text-gray-400">
+                    {{ confirmDialog.message }}
+                  </p>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
+            <button
+              type="button"
+              @click="handleConfirm"
+              class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
+            >
+              确认
+            </button>
+            <button
+              type="button"
+              @click="showConfirmDialog = false"
+              class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+            >
+              取消
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 高级筛选弹窗 -->
+    <div v-if="showAdvancedFilter" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    高级筛选
+                  </h3>
+                  <button @click="showAdvancedFilter = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">价格范围</label>
+                    <div class="mt-1 flex space-x-2">
+                      <input
+                        v-model.number="filterForm.minPrice"
+                        type="number"
+                        min="0"
+                        step="0.01"
+                        placeholder="最低价"
+                        class="block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                      <input
+                        v-model.number="filterForm.maxPrice"
+                        type="number"
+                        min="0"
+                        step="0.01"
+                        placeholder="最高价"
+                        class="block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                  </div>
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">库存范围</label>
+                    <div class="mt-1 flex space-x-2">
+                      <input
+                        v-model.number="filterForm.minStock"
+                        type="number"
+                        min="0"
+                        placeholder="最小库存"
+                        class="block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                      <input
+                        v-model.number="filterForm.maxStock"
+                        type="number"
+                        min="0"
+                        placeholder="最大库存"
+                        class="block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                  </div>
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">创建时间</label>
+                    <div class="mt-1 flex space-x-2">
+                      <input
+                        v-model="filterForm.startDate"
+                        type="date"
+                        class="block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                      <input
+                        v-model="filterForm.endDate"
+                        type="date"
+                        class="block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      />
+                    </div>
+                  </div>
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">排序方式</label>
+                    <select
+                      v-model="filterForm.sortBy"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    >
+                      <option value="">默认排序</option>
+                      <option value="price_asc">价格从低到高</option>
+                      <option value="price_desc">价格从高到低</option>
+                      <option value="stock_asc">库存从低到高</option>
+                      <option value="stock_desc">库存从高到低</option>
+                      <option value="created_at_desc">最新创建</option>
+                      <option value="created_at_asc">最早创建</option>
+                    </select>
+                  </div>
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">标签筛选</label>
+                    <div class="mt-1 flex flex-wrap gap-2">
+                      <label 
+                        v-for="tag in tags" 
+                        :key="tag.id"
+                        class="inline-flex items-center"
+                      >
+                        <input
+                          type="checkbox"
+                          :value="tag.id"
+                          v-model="filterForm.selectedTags"
+                          class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 dark:border-gray-600 rounded"
+                        />
+                        <span 
+                          :class="getTagClass(tag.type)"
+                          class="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium"
+                        >
+                          {{ tag.name }}
+                        </span>
+                      </label>
+                    </div>
+                  </div>
+                </div>
+                <div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
+                  <button
+                    type="button"
+                    @click="applyFilters"
+                    class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+                  >
+                    应用筛选
+                  </button>
+                  <button
+                    type="button"
+                    @click="resetFilters"
+                    class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+                  >
+                    重置
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 导入弹窗 -->
+    <div v-if="showImportDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    导入商品
+                  </h3>
+                  <button @click="showImportDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <div class="mb-4">
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">选择文件</label>
+                  <input
+                    type="file"
+                    accept=".csv"
+                    @change="handleFileChange"
+                    class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                  />
+                </div>
+                <div v-if="importPreview.length > 0" class="mb-4">
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">导入预览</label>
+                  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+                    <thead class="bg-gray-50 dark:bg-gray-700">
+                      <tr>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          商品编号
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          商品名称
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          分类
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          价格
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          库存
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          状态
+                        </th>
+                      </tr>
+                    </thead>
+                    <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+                      <tr v-for="(row, index) in importPreview" :key="index">
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[0] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[1] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[2] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[3] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[4] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[5] }}
+                        </td>
+                      </tr>
+                    </tbody>
+                  </table>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
+            <button
+              type="button"
+              @click="handleImportSubmit"
+              class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+            >
+              导入
+            </button>
+            <button
+              type="button"
+              @click="showImportDialog = false"
+              class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+            >
+              取消
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 商品详情弹窗 -->
+    <div v-if="showDetailsDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    商品详情
+                  </h3>
+                  <button @click="showDetailsDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+                  <div>
+                    <div class="aspect-w-1 aspect-h-1 w-full overflow-hidden rounded-lg">
+                      <img
+                        :src="selectedProduct?.image"
+                        :alt="selectedProduct?.name"
+                        class="h-full w-full object-cover object-center"
+                      />
+                    </div>
+                  </div>
+                  <div class="space-y-4">
+                    <div>
+                      <h4 class="text-lg font-medium text-gray-900 dark:text-white">{{ selectedProduct?.name }}</h4>
+                      <p class="text-sm text-gray-500 dark:text-gray-400">商品编号:{{ selectedProduct?.id }}</p>
+                    </div>
+                    <div class="grid grid-cols-2 gap-4">
+                      <div>
+                        <p class="text-sm text-gray-500 dark:text-gray-400">分类</p>
+                        <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedProduct?.category }}</p>
+                      </div>
+                      <div>
+                        <p class="text-sm text-gray-500 dark:text-gray-400">价格</p>
+                        <p class="text-sm font-medium text-gray-900 dark:text-white">¥{{ selectedProduct?.price }}</p>
+                      </div>
+                      <div>
+                        <p class="text-sm text-gray-500 dark:text-gray-400">库存</p>
+                        <p class="text-sm font-medium text-gray-900 dark:text-white">{{ selectedProduct?.stock }}</p>
+                      </div>
+                      <div>
+                        <p class="text-sm text-gray-500 dark:text-gray-400">状态</p>
+                        <span :class="getStatusClass(selectedProduct?.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                          {{ getStatusText(selectedProduct?.status) }}
+                        </span>
+                      </div>
+                    </div>
+                    <div>
+                      <p class="text-sm text-gray-500 dark:text-gray-400">商品标签</p>
+                      <div class="mt-1 flex flex-wrap gap-2">
+                        <span 
+                          v-for="tag in selectedProduct?.tags" 
+                          :key="tag.id"
+                          :class="getTagClass(tag.type)"
+                          class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium"
+                        >
+                          {{ tag.name }}
+                        </span>
+                        <span v-if="!selectedProduct?.tags?.length" class="text-sm text-gray-500 dark:text-gray-400">
+                          暂无标签
+                        </span>
+                      </div>
+                    </div>
+                    <div>
+                      <p class="text-sm text-gray-500 dark:text-gray-400">商品描述</p>
+                      <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ selectedProduct?.description || '暂无描述' }}</p>
+                    </div>
+                    <div>
+                      <p class="text-sm text-gray-500 dark:text-gray-400">创建时间</p>
+                      <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ formatDateTime(selectedProduct?.createdAt) }}</p>
+                    </div>
+                    <div>
+                      <p class="text-sm text-gray-500 dark:text-gray-400">更新时间</p>
+                      <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ formatDateTime(selectedProduct?.updatedAt) }}</p>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
+            <button
+              type="button"
+              @click="showDetailsDialog = false"
+              class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+            >
+              关闭
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 分类管理弹窗 -->
+    <div v-if="showCategoryDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    分类管理
+                  </h3>
+                  <div class="flex items-center space-x-2">
+                    <button 
+                      @click="handleExportCategories"
+                      class="inline-flex items-center px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                    >
+                      <DownloadIcon class="h-4 w-4 mr-1" />
+                      导出
+                    </button>
+                    <button 
+                      @click="handleImportCategories"
+                      class="inline-flex items-center px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                    >
+                      <UploadIcon class="h-4 w-4 mr-1" />
+                      导入
+                    </button>
+                    <button @click="showCategoryDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                      <XIcon class="h-6 w-6" />
+                    </button>
+                  </div>
+                </div>
+                <div class="mb-4">
+                  <div class="flex items-center space-x-2">
+                    <input
+                      v-model="newCategoryName"
+                      type="text"
+                      placeholder="输入新分类名称"
+                      class="flex-1 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    />
+                    <button
+                      @click="handleAddCategory"
+                      class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                    >
+                      添加分类
+                    </button>
+                  </div>
+                </div>
+                <div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
+                  <div class="space-y-2">
+                    <div v-for="category in categories" :key="category.id" class="flex items-center justify-between p-2 bg-white dark:bg-gray-800 rounded-md">
+                      <div class="flex items-center space-x-2">
+                        <input
+                          v-model="category.name"
+                          type="text"
+                          class="border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-1 px-2 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                        />
+                        <span class="text-sm text-gray-500 dark:text-gray-400">{{ category.productCount }} 个商品</span>
+                      </div>
+                      <div class="flex items-center space-x-2">
+                        <button
+                          @click="handleUpdateCategory(category)"
+                          class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300"
+                        >
+                          保存
+                        </button>
+                        <button
+                          @click="handleDeleteCategory(category)"
+                          class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                        >
+                          删除
+                        </button>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 标签管理弹窗 -->
+    <div v-if="showTagDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    标签管理
+                  </h3>
+                  <div class="flex items-center space-x-2">
+                    <button 
+                      @click="handleExportTags"
+                      class="inline-flex items-center px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                    >
+                      <DownloadIcon class="h-4 w-4 mr-1" />
+                      导出
+                    </button>
+                    <button 
+                      @click="handleImportTags"
+                      class="inline-flex items-center px-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                    >
+                      <UploadIcon class="h-4 w-4 mr-1" />
+                      导入
+                    </button>
+                    <button @click="showTagDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                      <XIcon class="h-6 w-6" />
+                    </button>
+                  </div>
+                </div>
+                <div class="mb-4">
+                  <div class="flex items-center space-x-2">
+                    <input
+                      v-model="newTagName"
+                      type="text"
+                      placeholder="输入新标签名称"
+                      class="flex-1 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    />
+                    <select
+                      v-model="newTagType"
+                      class="border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    >
+                      <option value="primary">主要</option>
+                      <option value="secondary">次要</option>
+                      <option value="warning">警告</option>
+                      <option value="success">成功</option>
+                      <option value="info">信息</option>
+                    </select>
+                    <button
+                      @click="handleAddTag"
+                      class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+                    >
+                      添加标签
+                    </button>
+                  </div>
+                </div>
+                <div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
+                  <div class="space-y-2">
+                    <div v-for="tag in tags" :key="tag.id" class="flex items-center justify-between p-2 bg-white dark:bg-gray-800 rounded-md">
+                      <div class="flex items-center space-x-2">
+                        <input
+                          v-model="tag.name"
+                          type="text"
+                          class="border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-1 px-2 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                        />
+                        <select
+                          v-model="tag.type"
+                          class="border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-1 px-2 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                        >
+                          <option value="primary">主要</option>
+                          <option value="secondary">次要</option>
+                          <option value="warning">警告</option>
+                          <option value="success">成功</option>
+                          <option value="info">信息</option>
+                        </select>
+                        <span class="text-sm text-gray-500 dark:text-gray-400">{{ tag.productCount }} 个商品</span>
+                      </div>
+                      <div class="flex items-center space-x-2">
+                        <button
+                          @click="handleUpdateTag(tag)"
+                          class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300"
+                        >
+                          保存
+                        </button>
+                        <button
+                          @click="handleDeleteTag(tag)"
+                          class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+                        >
+                          删除
+                        </button>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 批量操作弹窗 -->
+    <div v-if="showBatchOperationDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    批量操作
+                  </h3>
+                  <button @click="showBatchOperationDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <div class="space-y-4">
+                  <div>
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">操作类型</label>
+                    <select
+                      v-model="batchOperation.type"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    >
+                      <option value="status">修改状态</option>
+                      <option value="delete">删除商品</option>
+                      <option value="tags">添加标签</option>
+                      <option value="price">修改价格</option>
+                      <option value="stock">修改库存</option>
+                      <option value="category">修改分类</option>
+                      <option value="description">修改描述</option>
+                      <option value="image">修改图片</option>
+                      <option value="name">修改名称</option>
+                      <option value="id">修改编号</option>
+                      <option value="createdAt">修改创建时间</option>
+                      <option value="updatedAt">修改更新时间</option>
+                      <option value="tags">修改标签</option>
+                    </select>
+                  </div>
+                  <div v-if="batchOperation.type === 'status'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">状态</label>
+                    <select
+                      v-model="batchOperation.status"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    >
+                      <option value="active">在售</option>
+                      <option value="inactive">下架</option>
+                      <option value="out_of_stock">缺货</option>
+                    </select>
+                  </div>
+                  <div v-if="batchOperation.type === 'price'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">价格调整方式</label>
+                    <div class="mt-1">
+                      <select
+                        v-model="batchOperation.priceAdjustType"
+                        class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:border-gray-600 dark:text-gray-300"
+                      >
+                        <option value="fixed">固定值</option>
+                        <option value="percentage">百分比</option>
+                        <option value="increase">增加</option>
+                        <option value="decrease">减少</option>
+                      </select>
+                    </div>
+                    <div class="mt-2">
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">调整值</label>
+                      <input
+                        type="number"
+                        v-model="batchOperation.priceValue"
+                        :placeholder="batchOperation.priceAdjustType === 'percentage' ? '请输入百分比(如:10表示增加10%)' : '请输入调整值'"
+                        class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:border-gray-600 dark:text-gray-300"
+                      >
+                    </div>
+                  </div>
+                  <div v-if="batchOperation.type === 'stock'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">库存调整方式</label>
+                    <div class="mt-1">
+                      <select
+                        v-model="batchOperation.stockAdjustType"
+                        class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:border-gray-600 dark:text-gray-300"
+                      >
+                        <option value="fixed">固定值</option>
+                        <option value="increase">增加</option>
+                        <option value="decrease">减少</option>
+                      </select>
+                    </div>
+                    <div class="mt-2">
+                      <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">调整值</label>
+                      <input
+                        type="number"
+                        v-model="batchOperation.stockValue"
+                        :placeholder="batchOperation.stockAdjustType === 'fixed' ? '请输入新的库存数量' : '请输入调整数量'"
+                        class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:border-gray-600 dark:text-gray-300"
+                      >
+                    </div>
+                  </div>
+                  <div v-if="batchOperation.type === 'tags'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">标签</label>
+                    <div class="mt-1 space-y-2">
+                      <div v-for="tag in tags" :key="tag.id" class="flex items-center">
+                        <input
+                          type="checkbox"
+                          :id="'tag-' + tag.id"
+                          v-model="batchOperation.selectedTags"
+                          :value="tag.id"
+                          class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded dark:border-gray-600 dark:bg-gray-700"
+                        >
+                        <label :for="'tag-' + tag.id" class="ml-2 block text-sm text-gray-900 dark:text-gray-300">
+                          {{ tag.name }}
+                        </label>
+                      </div>
+                    </div>
+                  </div>
+                  <div v-if="batchOperation.type === 'category'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">选择分类</label>
+                    <select
+                      v-model="batchOperation.category"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    >
+                      <option value="">请选择分类</option>
+                      <option v-for="category in categories" :key="category.id" :value="category.name">
+                        {{ category.name }}
+                      </option>
+                    </select>
+                  </div>
+                  <div v-if="batchOperation.type === 'description'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品描述</label>
+                    <textarea
+                      v-model="batchOperation.description"
+                      rows="3"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                      placeholder="请输入商品描述"
+                    ></textarea>
+                  </div>
+                  <div v-if="batchOperation.type === 'image'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品图片</label>
+                    <div class="mt-1 flex items-center">
+                      <img
+                        v-if="batchOperation.image"
+                        :src="batchOperation.image"
+                        class="h-20 w-20 rounded-md object-cover"
+                      />
+                      <input
+                        type="file"
+                        accept="image/*"
+                        @change="handleBatchImageUpload"
+                        class="ml-4"
+                      />
+                    </div>
+                  </div>
+                  <div v-if="batchOperation.type === 'name'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                    <input
+                      v-model="batchOperation.name"
+                      type="text"
+                      placeholder="请输入新的商品名称"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    />
+                  </div>
+                  <div v-if="batchOperation.type === 'id'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品编号</label>
+                    <input
+                      v-model="batchOperation.id"
+                      type="text"
+                      placeholder="请输入新的商品编号"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    />
+                  </div>
+                  <div v-if="batchOperation.type === 'createdAt'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">创建时间</label>
+                    <input
+                      v-model="batchOperation.createdAt"
+                      type="datetime-local"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    />
+                  </div>
+                  <div v-if="batchOperation.type === 'updatedAt'">
+                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">更新时间</label>
+                    <input
+                      v-model="batchOperation.updatedAt"
+                      type="datetime-local"
+                      class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                    />
+                  </div>
+                  <div v-if="batchOperation.type === 'delete'">
+                    <div class="text-sm text-gray-700 dark:text-gray-300">
+                      确定要删除选中的 {{ selectedProducts.length }} 个商品吗?此操作不可恢复。
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
+            <button
+              type="button"
+              @click="handleBatchOperation"
+              class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+            >
+              确认
+            </button>
+            <button
+              type="button"
+              @click="showBatchOperationDialog = false"
+              class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+            >
+              取消
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 分类导入弹窗 -->
+    <div v-if="showCategoryImportDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    导入分类
+                  </h3>
+                  <button @click="showCategoryImportDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <div class="mb-4">
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">选择文件</label>
+                  <input
+                    type="file"
+                    accept=".csv"
+                    @change="handleCategoryFileChange"
+                    class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                  />
+                </div>
+                <div v-if="categoryImportPreview.length > 0" class="mb-4">
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">导入预览</label>
+                  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+                    <thead class="bg-gray-50 dark:bg-gray-700">
+                      <tr>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          分类名称
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          商品数量
+                        </th>
+                      </tr>
+                    </thead>
+                    <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+                      <tr v-for="(row, index) in categoryImportPreview" :key="index">
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[0] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[1] }}
+                        </td>
+                      </tr>
+                    </tbody>
+                  </table>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
+            <button
+              type="button"
+              @click="handleCategoryImportSubmit"
+              class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+            >
+              导入
+            </button>
+            <button
+              type="button"
+              @click="showCategoryImportDialog = false"
+              class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+            >
+              取消
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 标签导入弹窗 -->
+    <div v-if="showTagImportDialog" class="fixed inset-0 z-50 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <div class="sm:flex sm:items-start">
+              <div class="mt-3 text-center sm:mt-0 sm:text-left w-full">
+                <div class="flex justify-between items-center mb-4">
+                  <h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
+                    导入标签
+                  </h3>
+                  <button @click="showTagImportDialog = false" class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300">
+                    <XIcon class="h-6 w-6" />
+                  </button>
+                </div>
+                <div class="mb-4">
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">选择文件</label>
+                  <input
+                    type="file"
+                    accept=".csv"
+                    @change="handleTagFileChange"
+                    class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-700 dark:text-white"
+                  />
+                </div>
+                <div v-if="tagImportPreview.length > 0" class="mb-4">
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">导入预览</label>
+                  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+                    <thead class="bg-gray-50 dark:bg-gray-700">
+                      <tr>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          标签名称
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          标签类型
+                        </th>
+                        <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
+                          商品数量
+                        </th>
+                      </tr>
+                    </thead>
+                    <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+                      <tr v-for="(row, index) in tagImportPreview" :key="index">
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[0] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[1] }}
+                        </td>
+                        <td class="px-6 py-4 whitespace-nowrap">
+                          {{ row[2] }}
+                        </td>
+                      </tr>
+                    </tbody>
+                  </table>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
+            <button
+              type="button"
+              @click="handleTagImportSubmit"
+              class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm"
+            >
+              导入
+            </button>
+            <button
+              type="button"
+              @click="showTagImportDialog = false"
+              class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-600 shadow-sm px-4 py-2 bg-white dark:bg-gray-700 text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm"
+            >
+              取消
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { 
+  SearchIcon, 
+  PlusIcon,
+  FilterIcon,
+  XIcon,
+  ListIcon,
+  TagIcon,
+  DownloadIcon,
+  UploadIcon
+} from 'lucide-vue-next'
+
+// 商品表单相关状态
+const showProductForm = ref(false)
+const isEdit = ref(false)
+const productForm = ref({
+  id: '',
+  name: '',
+  category: '',
+  price: 0,
+  stock: 0,
+  status: 'active',
+  image: '',
+  description: '',
+  tags: []
+})
+
+// 标签选择相关状态
+const selectedTag = ref(null)
+
+// 计算可用的标签列表(排除已选择的标签)
+const availableTags = computed(() => {
+  return tags.value.filter(tag => !productForm.value.tags?.some(t => t.id === tag.id))
+})
+
+// 获取标签样式
+const getTagClass = (type) => {
+  const classes = {
+    primary: 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200',
+    secondary: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200',
+    warning: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
+    success: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    info: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'
+  }
+  return classes[type] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+// 添加标签
+const addTag = () => {
+  if (selectedTag.value && !productForm.value.tags?.some(t => t.id === selectedTag.value.id)) {
+    if (!productForm.value.tags) {
+      productForm.value.tags = []
+    }
+    productForm.value.tags.push({ ...selectedTag.value })
+    selectedTag.value = null
+  }
+}
+
+// 移除标签
+const removeTag = (tag) => {
+  const index = productForm.value.tags.findIndex(t => t.id === tag.id)
+  if (index !== -1) {
+    productForm.value.tags.splice(index, 1)
+  }
+}
+
+// 确认对话框相关状态
+const showConfirmDialog = ref(false)
+const confirmDialog = ref({
+  title: '',
+  message: '',
+  action: ''
+})
+const selectedProduct = ref(null)
+
+// 高级筛选相关状态
+const showAdvancedFilter = ref(false)
+const filterForm = ref({
+  minPrice: null,
+  maxPrice: null,
+  minStock: null,
+  maxStock: null,
+  startDate: '',
+  endDate: '',
+  sortBy: '',
+  selectedTags: []
+})
+
+// 商品详情相关状态
+const showDetailsDialog = ref(false)
+
+// 分类管理相关状态
+const showCategoryDialog = ref(false)
+const newCategoryName = ref('')
+const categories = ref([
+  { id: 1, name: '电子产品', productCount: 3 },
+  { id: 2, name: '服装', productCount: 0 },
+  { id: 3, name: '食品', productCount: 0 }
+])
+
+// 标签管理相关状态
+const showTagDialog = ref(false)
+const newTagName = ref('')
+const newTagType = ref('primary')
+const tags = ref([
+  { id: 1, name: '新品', type: 'primary', productCount: 2 },
+  { id: 2, name: '热销', type: 'warning', productCount: 1 },
+  { id: 3, name: '促销', type: 'success', productCount: 0 }
+])
+
+// 批量操作相关状态
+const selectAll = ref(false)
+const selectedProducts = ref([])
+const showBatchOperationDialog = ref(false)
+const batchOperation = ref({
+  type: 'status',
+  status: 'active',
+  selectedTags: [],
+  priceAdjustType: 'fixed',
+  priceValue: 0,
+  stockAdjustType: 'fixed',
+  stockValue: 0,
+  category: '',
+  description: '',
+  image: '',
+  name: '',
+  id: '',
+  createdAt: '',
+  updatedAt: ''
+})
+
+// 分类导入导出相关状态
+const showCategoryImportDialog = ref(false)
+const categoryImportFile = ref(null)
+const categoryImportPreview = ref([])
+const categoryImportHeaders = ref([])
+
+// 标签导入导出相关状态
+const showTagImportDialog = ref(false)
+const tagImportFile = ref(null)
+const tagImportPreview = ref([])
+const tagImportHeaders = ref([])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const category = ref('')
+const status = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalProducts = ref(100)
+const showImportDialog = ref(false)
+const showExportDialog = ref(false)
+const showDeleteDialog = ref(false)
+
+// 处理添加商品按钮点击
+const handleAddProduct = () => {
+  isEdit.value = false
+  productForm.value = {
+    id: '',
+    name: '',
+    category: '',
+    price: 0,
+    stock: 0,
+    status: 'active',
+    image: '',
+    description: '',
+    tags: []
+  }
+  showProductForm.value = true
+}
+
+// 处理编辑商品按钮点击
+const handleEditProduct = (product) => {
+  isEdit.value = true
+  productForm.value = { ...product }
+  showProductForm.value = true
+}
+
+// 处理图片上传
+const handleImageUpload = (event) => {
+  const file = event.target.files[0]
+  if (file) {
+    const reader = new FileReader()
+    reader.onload = (e) => {
+      productForm.value.image = e.target.result
+    }
+    reader.readAsDataURL(file)
+  }
+}
+
+// 处理表单提交
+const handleProductSubmit = () => {
+  if (isEdit.value) {
+    // 更新商品
+    const index = products.value.findIndex(p => p.id === productForm.value.id)
+    if (index !== -1) {
+      products.value[index] = { ...productForm.value }
+    }
+  } else {
+    // 添加新商品
+    products.value.push({ ...productForm.value })
+  }
+  showProductForm.value = false
+}
+
+// 处理删除商品
+const handleDeleteProduct = (product) => {
+  selectedProduct.value = product
+  confirmDialog.value = {
+    title: '删除商品',
+    message: `确定要删除商品 "${product.name}" 吗?此操作不可恢复。`,
+    action: 'delete'
+  }
+  showConfirmDialog.value = true
+}
+
+// 应用筛选
+const applyFilters = () => {
+  // 这里添加筛选逻辑
+  showAdvancedFilter.value = false
+}
+
+// 重置筛选
+const resetFilters = () => {
+  filterForm.value = {
+    minPrice: null,
+    maxPrice: null,
+    minStock: null,
+    maxStock: null,
+    startDate: '',
+    endDate: '',
+    sortBy: '',
+    selectedTags: []
+  }
+}
+
+// 计算筛选后的商品列表
+const filteredProducts = computed(() => {
+  let result = [...products.value]
+  
+  // 价格范围筛选
+  if (filterForm.value.minPrice !== null) {
+    result = result.filter(p => p.price >= filterForm.value.minPrice)
+  }
+  if (filterForm.value.maxPrice !== null) {
+    result = result.filter(p => p.price <= filterForm.value.maxPrice)
+  }
+  
+  // 库存范围筛选
+  if (filterForm.value.minStock !== null) {
+    result = result.filter(p => p.stock >= filterForm.value.minStock)
+  }
+  if (filterForm.value.maxStock !== null) {
+    result = result.filter(p => p.stock <= filterForm.value.maxStock)
+  }
+  
+  // 标签筛选
+  if (filterForm.value.selectedTags.length > 0) {
+    result = result.filter(p => {
+      if (!p.tags) return false
+      return filterForm.value.selectedTags.some(tagId => 
+        p.tags.some(tag => tag.id === tagId)
+      )
+    })
+  }
+  
+  // 排序
+  if (filterForm.value.sortBy) {
+    const [field, order] = filterForm.value.sortBy.split('_')
+    result.sort((a, b) => {
+      if (order === 'asc') {
+        return a[field] - b[field]
+      } else {
+        return b[field] - a[field]
+      }
+    })
+  }
+  
+  return result
+})
+
+// 模拟商品数据
+const products = ref([
+  {
+    id: 'P1001',
+    name: 'iPhone 13 Pro',
+    category: '电子产品',
+    price: 7999,
+    stock: 100,
+    status: 'active',
+    image: 'https://images.unsplash.com/photo-1634896941598-b6b500a502a7?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80'
+  },
+  {
+    id: 'P1002',
+    name: 'MacBook Pro',
+    category: '电子产品',
+    price: 12999,
+    stock: 50,
+    status: 'active',
+    image: 'https://images.unsplash.com/photo-1517336714731-489689fd1ca8?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80'
+  },
+  {
+    id: 'P1003',
+    name: 'AirPods Pro',
+    category: '电子产品',
+    price: 1999,
+    stock: 0,
+    status: 'out_of_stock',
+    image: 'https://images.unsplash.com/photo-1572569511254-d8f925fe2cbb?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=80'
+  }
+])
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    inactive: 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200',
+    out_of_stock: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+// 获取状态文本
+const getStatusText = (status) => {
+  const texts = {
+    active: '在售',
+    inactive: '下架',
+    out_of_stock: '缺货'
+  }
+  return texts[status] || '未知'
+}
+
+// 处理查看详情
+const handleViewDetails = (product) => {
+  selectedProduct.value = product
+  showDetailsDialog.value = true
+}
+
+// 格式化日期时间
+const formatDateTime = (date) => {
+  if (!date) return '未知'
+  return new Date(date).toLocaleString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    hour: '2-digit',
+    minute: '2-digit'
+  })
+}
+
+// 处理分类管理按钮点击
+const handleManageCategories = () => {
+  showCategoryDialog.value = true
+}
+
+// 处理添加分类
+const handleAddCategory = () => {
+  if (newCategoryName.value.trim()) {
+    categories.value.push({
+      id: Date.now(),
+      name: newCategoryName.value.trim(),
+      productCount: 0
+    })
+    newCategoryName.value = ''
+  }
+}
+
+// 处理更新分类
+const handleUpdateCategory = (category) => {
+  if (category.name.trim()) {
+    // 更新商品中的分类名称
+    products.value.forEach(product => {
+      if (product.category === category.oldName) {
+        product.category = category.name
+      }
+    })
+  }
+}
+
+// 处理删除分类
+const handleDeleteCategory = (category) => {
+  if (category.productCount > 0) {
+    confirmDialog.value = {
+      title: '删除分类',
+      message: `分类 "${category.name}" 下有 ${category.productCount} 个商品,确定要删除吗?`,
+      action: 'deleteCategory',
+      data: category
+    }
+    showConfirmDialog.value = true
+  } else {
+    const index = categories.value.findIndex(c => c.id === category.id)
+    if (index !== -1) {
+      categories.value.splice(index, 1)
+    }
+  }
+}
+
+// 处理标签管理按钮点击
+const handleManageTags = () => {
+  showTagDialog.value = true
+}
+
+// 处理添加标签
+const handleAddTag = () => {
+  if (newTagName.value.trim()) {
+    tags.value.push({
+      id: Date.now(),
+      name: newTagName.value.trim(),
+      type: newTagType.value,
+      productCount: 0
+    })
+    newTagName.value = ''
+    newTagType.value = 'primary'
+  }
+}
+
+// 处理更新标签
+const handleUpdateTag = (tag) => {
+  if (tag.name.trim()) {
+    // 更新商品中的标签
+    products.value.forEach(product => {
+      if (product.tags) {
+        const index = product.tags.findIndex(t => t.id === tag.id)
+        if (index !== -1) {
+          product.tags[index] = { ...tag }
+        }
+      }
+    })
+  }
+}
+
+// 处理删除标签
+const handleDeleteTag = (tag) => {
+  if (tag.productCount > 0) {
+    confirmDialog.value = {
+      title: '删除标签',
+      message: `标签 "${tag.name}" 下有 ${tag.productCount} 个商品,确定要删除吗?`,
+      action: 'deleteTag',
+      data: tag
+    }
+    showConfirmDialog.value = true
+  } else {
+    const index = tags.value.findIndex(t => t.id === tag.id)
+    if (index !== -1) {
+      tags.value.splice(index, 1)
+    }
+  }
+}
+
+// 处理全选
+const handleSelectAll = () => {
+  if (selectAll.value) {
+    selectedProducts.value = [...filteredProducts.value]
+  } else {
+    selectedProducts.value = []
+  }
+}
+
+// 处理批量操作
+const handleBatchOperation = () => {
+  if (batchOperation.value.type === 'status') {
+    // 批量修改状态
+    if (!batchOperation.value.status) {
+      alert('请选择状态')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].status = batchOperation.value.status
+      }
+    })
+  } else if (batchOperation.value.type === 'price') {
+    // 批量修改价格
+    if (batchOperation.value.priceValue === null || batchOperation.value.priceValue === '') {
+      alert('请输入调整值')
+      return
+    }
+    const value = parseFloat(batchOperation.value.priceValue)
+    if (isNaN(value)) {
+      alert('请输入有效的数值')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        let newPrice = products.value[index].price
+        switch (batchOperation.value.priceAdjustType) {
+          case 'fixed':
+            newPrice = value
+            break
+          case 'percentage':
+            newPrice = newPrice * (1 + value / 100)
+            break
+          case 'increase':
+            newPrice = newPrice + value
+            break
+          case 'decrease':
+            newPrice = newPrice - value
+            break
+        }
+        // 确保价格不为负数
+        products.value[index].price = Math.max(0, newPrice)
+      }
+    })
+  } else if (batchOperation.value.type === 'stock') {
+    // 批量修改库存
+    if (batchOperation.value.stockValue === null || batchOperation.value.stockValue === '') {
+      alert('请输入调整值')
+      return
+    }
+    const value = parseInt(batchOperation.value.stockValue)
+    if (isNaN(value)) {
+      alert('请输入有效的数值')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        let newStock = products.value[index].stock
+        switch (batchOperation.value.stockAdjustType) {
+          case 'fixed':
+            newStock = value
+            break
+          case 'increase':
+            newStock = newStock + value
+            break
+          case 'decrease':
+            newStock = newStock - value
+            break
+        }
+        // 确保库存不为负数
+        products.value[index].stock = Math.max(0, newStock)
+      }
+    })
+  } else if (batchOperation.value.type === 'tags') {
+    // 批量修改标签
+    if (batchOperation.value.selectedTags.length === 0) {
+      alert('请选择至少一个标签')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        if (!products.value[index].tags) {
+          products.value[index].tags = []
+        }
+        // 移除未选中的标签
+        products.value[index].tags = products.value[index].tags.filter(tag => 
+          batchOperation.value.selectedTags.includes(tag.id)
+        )
+        // 添加新选中的标签
+        batchOperation.value.selectedTags.forEach(tagId => {
+          const tag = tags.value.find(t => t.id === tagId)
+          if (tag && !products.value[index].tags.some(t => t.id === tag.id)) {
+            products.value[index].tags.push({ ...tag })
+          }
+        })
+      }
+    })
+  } else if (batchOperation.value.type === 'category') {
+    // 批量修改分类
+    if (!batchOperation.value.category) {
+      alert('请选择分类')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].category = batchOperation.value.category
+      }
+    })
+  } else if (batchOperation.value.type === 'description') {
+    // 批量修改描述
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].description = batchOperation.value.description
+      }
+    })
+  } else if (batchOperation.value.type === 'image') {
+    // 批量修改图片
+    if (!batchOperation.value.image) {
+      alert('请上传图片')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].image = batchOperation.value.image
+      }
+    })
+  } else if (batchOperation.value.type === 'name') {
+    // 批量修改名称
+    if (!batchOperation.value.name) {
+      alert('请输入新的商品名称')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].name = batchOperation.value.name
+      }
+    })
+  } else if (batchOperation.value.type === 'id') {
+    // 批量修改编号
+    if (!batchOperation.value.id) {
+      alert('请输入新的商品编号')
+      return
+    }
+    // 检查是否选择了多个商品
+    if (selectedProducts.value.length > 1) {
+      alert('批量修改编号时只能选择一个商品')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].id = batchOperation.value.id
+      }
+    })
+  } else if (batchOperation.value.type === 'createdAt') {
+    // 批量修改创建时间
+    if (!batchOperation.value.createdAt) {
+      alert('请选择创建时间')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].createdAt = batchOperation.value.createdAt
+      }
+    })
+  } else if (batchOperation.value.type === 'updatedAt') {
+    // 批量修改更新时间
+    if (!batchOperation.value.updatedAt) {
+      alert('请选择更新时间')
+      return
+    }
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value[index].updatedAt = batchOperation.value.updatedAt
+      }
+    })
+  } else if (batchOperation.value.type === 'delete') {
+    // 批量删除商品
+    confirmDialog.value = {
+      title: '批量删除商品',
+      message: `确定要删除选中的 ${selectedProducts.value.length} 个商品吗?此操作不可恢复。`,
+      action: 'batchDelete'
+    }
+    showConfirmDialog.value = true
+    return
+  }
+  
+  // 重置选择
+  selectedProducts.value = []
+  selectAll.value = false
+  batchOperation.value = {
+    type: 'status',
+    status: 'active',
+    selectedTags: [],
+    priceAdjustType: 'fixed',
+    priceValue: 0,
+    stockAdjustType: 'fixed',
+    stockValue: 0,
+    category: '',
+    description: '',
+    image: '',
+    name: '',
+    id: '',
+    createdAt: '',
+    updatedAt: ''
+  }
+  showBatchOperationDialog.value = false
+}
+
+// 处理导入提交
+const handleImportSubmit = () => {
+  if (!importFile.value) return
+  
+  const reader = new FileReader()
+  reader.onload = (e) => {
+    const text = e.target.result
+    const rows = text.split('\n').map(row => row.split(','))
+    const headers = rows[0]
+    
+    const newProducts = rows.slice(1).map(row => {
+      const product = {
+        id: row[headers.indexOf('商品编号')],
+        name: row[headers.indexOf('商品名称')],
+        category: row[headers.indexOf('分类')],
+        price: parseFloat(row[headers.indexOf('价格')]),
+        stock: parseInt(row[headers.indexOf('库存')]),
+        status: getStatusValue(row[headers.indexOf('状态')]),
+        description: row[headers.indexOf('描述')] || '',
+        tags: []
+      }
+      
+      // 处理标签
+      const tagsStr = row[headers.indexOf('标签')]
+      if (tagsStr) {
+        product.tags = tagsStr.split(',').map(tagStr => {
+          const [name, type] = tagStr.split('(')
+          return {
+            id: Date.now() + Math.random(),
+            name: name.trim(),
+            type: type.replace(')', '').trim()
+          }
+        })
+      }
+      
+      return product
+    })
+    
+    // 添加新商品
+    products.value.push(...newProducts)
+    showImportDialog.value = false
+  }
+  reader.readAsText(importFile.value)
+}
+
+// 获取状态值
+const getStatusValue = (text) => {
+  const values = {
+    '在售': 'active',
+    '下架': 'inactive',
+    '缺货': 'out_of_stock'
+  }
+  return values[text] || 'active'
+}
+
+// 处理导出分类
+const handleExportCategories = () => {
+  const headers = ['分类名称', '商品数量']
+  
+  const data = categories.value.map(category => [
+    category.name,
+    category.productCount
+  ])
+  
+  const csvContent = [
+    headers.join(','),
+    ...data.map(row => row.join(','))
+  ].join('\n')
+  
+  const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
+  const link = document.createElement('a')
+  link.href = URL.createObjectURL(blob)
+  link.download = `商品分类_${new Date().toLocaleDateString()}.csv`
+  link.click()
+}
+
+// 处理导入分类
+const handleImportCategories = () => {
+  showCategoryImportDialog.value = true
+  categoryImportFile.value = null
+  categoryImportPreview.value = []
+  categoryImportHeaders.value = []
+}
+
+// 处理分类文件选择
+const handleCategoryFileChange = (event) => {
+  const file = event.target.files[0]
+  if (!file) return
+  
+  if (file.size > 10 * 1024 * 1024) {
+    alert('文件大小不能超过10MB')
+    return
+  }
+  
+  if (!file.name.endsWith('.csv')) {
+    alert('请选择CSV文件')
+    return
+  }
+  
+  categoryImportFile.value = file
+  readCategoryCSVFile(file)
+}
+
+// 读取分类CSV文件
+const readCategoryCSVFile = (file) => {
+  const reader = new FileReader()
+  reader.onload = (e) => {
+    const text = e.target.result
+    const rows = text.split('\n').map(row => row.split(','))
+    categoryImportHeaders.value = rows[0]
+    categoryImportPreview.value = rows.slice(1, 6) // 只显示前5行数据
+  }
+  reader.readAsText(file)
+}
+
+// 处理分类导入提交
+const handleCategoryImportSubmit = () => {
+  if (!categoryImportFile.value) return
+  
+  const reader = new FileReader()
+  reader.onload = (e) => {
+    const text = e.target.result
+    const rows = text.split('\n').map(row => row.split(','))
+    const headers = rows[0]
+    
+    const newCategories = rows.slice(1).map(row => ({
+      id: Date.now() + Math.random(),
+      name: row[headers.indexOf('分类名称')],
+      productCount: parseInt(row[headers.indexOf('商品数量')]) || 0
+    }))
+    
+    // 添加新分类
+    categories.value.push(...newCategories)
+    showCategoryImportDialog.value = false
+  }
+  reader.readAsText(categoryImportFile.value)
+}
+
+// 处理导出标签
+const handleExportTags = () => {
+  const headers = ['标签名称', '标签类型', '商品数量']
+  
+  const data = tags.value.map(tag => [
+    tag.name,
+    tag.type,
+    tag.productCount
+  ])
+  
+  const csvContent = [
+    headers.join(','),
+    ...data.map(row => row.join(','))
+  ].join('\n')
+  
+  const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
+  const link = document.createElement('a')
+  link.href = URL.createObjectURL(blob)
+  link.download = `商品标签_${new Date().toLocaleDateString()}.csv`
+  link.click()
+}
+
+// 处理导入标签
+const handleImportTags = () => {
+  showTagImportDialog.value = true
+  tagImportFile.value = null
+  tagImportPreview.value = []
+  tagImportHeaders.value = []
+}
+
+// 处理标签文件选择
+const handleTagFileChange = (event) => {
+  const file = event.target.files[0]
+  if (!file) return
+  
+  if (file.size > 10 * 1024 * 1024) {
+    alert('文件大小不能超过10MB')
+    return
+  }
+  
+  if (!file.name.endsWith('.csv')) {
+    alert('请选择CSV文件')
+    return
+  }
+  
+  tagImportFile.value = file
+  readTagCSVFile(file)
+}
+
+// 读取标签CSV文件
+const readTagCSVFile = (file) => {
+  const reader = new FileReader()
+  reader.onload = (e) => {
+    const text = e.target.result
+    const rows = text.split('\n').map(row => row.split(','))
+    tagImportHeaders.value = rows[0]
+    tagImportPreview.value = rows.slice(1, 6) // 只显示前5行数据
+  }
+  reader.readAsText(file)
+}
+
+// 处理标签导入提交
+const handleTagImportSubmit = () => {
+  if (!tagImportFile.value) return
+  
+  const reader = new FileReader()
+  reader.onload = (e) => {
+    const text = e.target.result
+    const rows = text.split('\n').map(row => row.split(','))
+    const headers = rows[0]
+    
+    const newTags = rows.slice(1).map(row => ({
+      id: Date.now() + Math.random(),
+      name: row[headers.indexOf('标签名称')],
+      type: row[headers.indexOf('标签类型')],
+      productCount: parseInt(row[headers.indexOf('商品数量')]) || 0
+    }))
+    
+    // 添加新标签
+    tags.value.push(...newTags)
+    showTagImportDialog.value = false
+  }
+  reader.readAsText(tagImportFile.value)
+}
+
+// 处理批量图片上传
+const handleBatchImageUpload = (event) => {
+  const file = event.target.files[0]
+  if (file) {
+    const reader = new FileReader()
+    reader.onload = (e) => {
+      batchOperation.value.image = e.target.result
+    }
+    reader.readAsDataURL(file)
+  }
+}
+
+// 处理确认对话框
+const handleConfirm = () => {
+  if (confirmDialog.value.action === 'delete') {
+    const index = products.value.findIndex(p => p.id === selectedProduct.value.id)
+    if (index !== -1) {
+      products.value.splice(index, 1)
+    }
+  } else if (confirmDialog.value.action === 'batchDelete') {
+    selectedProducts.value.forEach(product => {
+      const index = products.value.findIndex(p => p.id === product.id)
+      if (index !== -1) {
+        products.value.splice(index, 1)
+      }
+    })
+    selectedProducts.value = []
+    selectAll.value = false
+  } else if (confirmDialog.value.action === 'deleteCategory') {
+    const category = confirmDialog.value.data
+    const index = categories.value.findIndex(c => c.id === category.id)
+    if (index !== -1) {
+      categories.value.splice(index, 1)
+    }
+  } else if (confirmDialog.value.action === 'deleteTag') {
+    const tag = confirmDialog.value.data
+    const index = tags.value.findIndex(t => t.id === tag.id)
+    if (index !== -1) {
+      tags.value.splice(index, 1)
+    }
+  }
+  showConfirmDialog.value = false
+}
+</script> 

+ 809 - 0
src/assets/templates/prototype/finance/EnterpriseDashboard.vue

@@ -0,0 +1,809 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">企业仪表盘</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索部门/项目..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="department"
+            @change="handleDepartmentChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有部门</option>
+            <option value="sales">销售部</option>
+            <option value="marketing">市场部</option>
+            <option value="development">研发部</option>
+            <option value="finance">财务部</option>
+          </select>
+          <select 
+            v-model="projectStatus"
+            @change="handleProjectStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="planning">规划中</option>
+            <option value="in_progress">进行中</option>
+            <option value="completed">已完成</option>
+            <option value="on_hold">已暂停</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 企业统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <UsersIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">员工总数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,234</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ActivityIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">活跃项目</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">56</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <TrendingUpIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">季度收入</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">¥12.3M</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <TargetIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">目标完成率</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">85.6%</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 企业数据图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">部门绩效趋势</h3>
+          <div ref="performanceChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">项目状态分布</h3>
+          <div ref="projectChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 项目列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">项目信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">部门</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">进度</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">负责人</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="project in paginatedProjects" :key="project.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-full object-cover" :src="project.avatar" :alt="project.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ project.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ project.id }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['department-tag', `dept-${project.department}`]">
+                    {{ project.department === 'sales' ? '销售部' : 
+                       project.department === 'marketing' ? '市场部' : 
+                       project.department === 'development' ? '研发部' : '财务部' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${project.status}`]">
+                    {{ project.status === 'planning' ? '规划中' : 
+                       project.status === 'in_progress' ? '进行中' : 
+                       project.status === 'completed' ? '已完成' : '已暂停' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2.5">
+                    <div 
+                      class="progress-bar h-2.5 rounded-full"
+                      :class="[
+                        project.status === 'completed' ? 'bg-green-600' :
+                        project.status === 'in_progress' ? 'bg-blue-600' :
+                        project.status === 'planning' ? 'bg-yellow-600' : 'bg-gray-600'
+                      ]"
+                      :style="{ width: `${project.progress}%` }"
+                    ></div>
+                  </div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ project.progress }}%</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-8 w-8">
+                      <img class="h-8 w-8 rounded-full object-cover" :src="project.manager.avatar" :alt="project.manager.name">
+                    </div>
+                    <div class="ml-3">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ project.manager.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ project.manager.position }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewProject(project)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditProject(project)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredProjects.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredProjects.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  SearchIcon, 
+  SettingsIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  UsersIcon,
+  ActivityIcon,
+  TrendingUpIcon,
+  TargetIcon,
+  DownloadIcon,
+  EyeIcon,
+  EditIcon,
+  ChevronUpIcon,
+  ChevronDownIcon
+} from 'lucide-vue-next'
+
+// 默认图片配置
+const defaultImages = {
+  project: 'https://ui-avatars.com/api/?name=Project&background=random&color=fff&size=150',
+  manager: 'https://ui-avatars.com/api/?name=Manager&background=random&color=fff&size=150'
+}
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const department = ref('')
+const projectStatus = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalProjects = ref(100)
+
+// 图表相关
+const performanceChartRef = ref(null)
+const projectChartRef = ref(null)
+let performanceChart = null
+let projectChart = null
+
+// Mock data
+const mockProjects = ref([
+  {
+    id: 'PR1001',
+    name: '智能家居系统',
+    type: 'development',
+    status: 'in_progress',
+    progress: 75,
+    startDate: '2024-01-15',
+    endDate: '2024-06-30',
+    budget: 500000,
+    spent: 375000,
+    avatar: defaultImages.project,
+    manager: {
+      id: 'M1001',
+      name: '张经理',
+      avatar: defaultImages.manager
+    },
+    team: [
+      { id: 'E1001', name: '王开发', role: '前端开发' },
+      { id: 'E1002', name: '李开发', role: '后端开发' },
+      { id: 'E1003', name: '赵测试', role: '测试工程师' }
+    ],
+    description: '开发新一代智能家居控制系统,支持多设备联动和远程控制'
+  },
+  {
+    id: 'PR1002',
+    name: '企业ERP系统',
+    type: 'implementation',
+    status: 'completed',
+    progress: 100,
+    startDate: '2023-10-01',
+    endDate: '2024-02-28',
+    budget: 300000,
+    spent: 280000,
+    avatar: defaultImages.project,
+    manager: {
+      id: 'M1002',
+      name: '李经理',
+      avatar: defaultImages.manager
+    },
+    team: [
+      { id: 'E1004', name: '钱顾问', role: '业务顾问' },
+      { id: 'E1005', name: '孙实施', role: '实施工程师' },
+      { id: 'E1006', name: '周培训', role: '培训师' }
+    ],
+    description: '实施企业资源计划系统,优化业务流程和管理效率'
+  },
+  {
+    id: 'PR1003',
+    name: '数据分析平台',
+    type: 'development',
+    status: 'in_progress',
+    progress: 45,
+    startDate: '2024-02-01',
+    endDate: '2024-08-31',
+    budget: 400000,
+    spent: 180000,
+    avatar: defaultImages.project,
+    manager: {
+      id: 'M1003',
+      name: '王经理',
+      avatar: defaultImages.manager
+    },
+    team: [
+      { id: 'E1007', name: '吴数据', role: '数据分析师' },
+      { id: 'E1008', name: '郑开发', role: '全栈开发' },
+      { id: 'E1009', name: '冯设计', role: 'UI设计师' }
+    ],
+    description: '构建企业级数据分析平台,支持数据可视化和决策支持'
+  },
+  {
+    id: 'PR1004',
+    name: '移动办公系统',
+    type: 'maintenance',
+    status: 'in_progress',
+    progress: 30,
+    startDate: '2024-03-01',
+    endDate: '2024-05-31',
+    budget: 200000,
+    spent: 60000,
+    avatar: defaultImages.project,
+    manager: {
+      id: 'M1004',
+      name: '赵经理',
+      avatar: defaultImages.manager
+    },
+    team: [
+      { id: 'E1010', name: '陈运维', role: '运维工程师' },
+      { id: 'E1011', name: '褚开发', role: '移动开发' },
+      { id: 'E1012', name: '卫测试', role: '测试工程师' }
+    ],
+    description: '维护和优化移动办公系统,提升用户体验和系统稳定性'
+  },
+  {
+    id: 'PR1005',
+    name: '客户关系管理',
+    type: 'planning',
+    status: 'not_started',
+    progress: 0,
+    startDate: '2024-04-01',
+    endDate: '2024-09-30',
+    budget: 350000,
+    spent: 0,
+    avatar: defaultImages.project,
+    manager: {
+      id: 'M1005',
+      name: '钱经理',
+      avatar: defaultImages.manager
+    },
+    team: [
+      { id: 'E1013', name: '蒋产品', role: '产品经理' },
+      { id: 'E1014', name: '沈设计', role: '交互设计师' },
+      { id: 'E1015', name: '韩开发', role: '后端开发' }
+    ],
+    description: '规划新一代客户关系管理系统,提升客户服务质量和满意度'
+  }
+])
+
+// 项目统计数据
+const projectStats = ref({
+  totalProjects: 15,
+  activeProjects: 8,
+  completedProjects: 5,
+  delayedProjects: 2
+})
+
+// 项目类型分布
+const projectTypeDistribution = ref([
+  { type: 'development', value: 6 },
+  { type: 'implementation', value: 4 },
+  { type: 'maintenance', value: 3 },
+  { type: 'planning', value: 2 }
+])
+
+// 项目进度趋势
+const projectProgressTrends = ref([
+  { date: '2024-03-01', completed: 2, inProgress: 6, notStarted: 7 },
+  { date: '2024-03-02', completed: 2, inProgress: 7, notStarted: 6 },
+  { date: '2024-03-03', completed: 3, inProgress: 7, notStarted: 5 },
+  { date: '2024-03-04', completed: 3, inProgress: 8, notStarted: 4 },
+  { date: '2024-03-05', completed: 4, inProgress: 8, notStarted: 3 },
+  { date: '2024-03-06', completed: 4, inProgress: 9, notStarted: 2 },
+  { date: '2024-03-07', completed: 5, inProgress: 8, notStarted: 2 }
+])
+
+// 项目预算使用情况
+const budgetUsage = ref([
+  { projectId: 'PR1001', name: '智能家居系统', budget: 500000, spent: 375000, usage: 75 },
+  { projectId: 'PR1002', name: '企业ERP系统', budget: 300000, spent: 280000, usage: 93 },
+  { projectId: 'PR1003', name: '数据分析平台', budget: 400000, spent: 180000, usage: 45 },
+  { projectId: 'PR1004', name: '移动办公系统', budget: 200000, spent: 60000, usage: 30 },
+  { projectId: 'PR1005', name: '客户关系管理', budget: 350000, spent: 0, usage: 0 }
+])
+
+// 性能数据
+const mockPerformanceData = {
+  cpu: {
+    usage: 65,
+    trend: [45, 50, 55, 60, 65, 70, 65],
+    alerts: 2
+  },
+  memory: {
+    usage: 75,
+    trend: [60, 65, 70, 75, 80, 75, 75],
+    alerts: 1
+  },
+  disk: {
+    usage: 50,
+    trend: [40, 45, 50, 55, 50, 45, 50],
+    alerts: 0
+  },
+  network: {
+    usage: 30,
+    trend: [25, 30, 35, 30, 25, 30, 30],
+    alerts: 0
+  }
+}
+
+// 项目状态分布数据
+const mockProjectData = [
+  { value: 5, name: '已完成' },
+  { value: 8, name: '进行中' },
+  { value: 2, name: '已暂停' }
+]
+
+// 计算属性
+const filteredProjects = computed(() => {
+  let result = [...mockProjects.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(project => 
+      project.id.includes(searchText.value) ||
+      project.name.includes(searchText.value)
+    )
+  }
+  
+  // 部门过滤
+  if (department.value) {
+    result = result.filter(project => project.department === department.value)
+  }
+  
+  // 状态过滤
+  if (projectStatus.value) {
+    result = result.filter(project => project.status === projectStatus.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(project => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedProjects = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredProjects.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredProjects.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleDepartmentChange = () => {
+  currentPage.value = 1
+}
+
+const handleProjectStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewProject = (project) => {
+  console.log('查看项目:', project)
+}
+
+const handleEditProject = (project) => {
+  console.log('编辑项目:', project)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 初始化绩效图表
+const initPerformanceChart = () => {
+  if (!performanceChartRef.value) return
+  
+  performanceChart = echarts.init(performanceChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: ['CPU', '内存', '磁盘', '网络']
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+    },
+    yAxis: {
+      type: 'value',
+      max: 100,
+      axisLabel: {
+        formatter: '{value}%'
+      }
+    },
+    series: [
+      {
+        name: 'CPU',
+        type: 'line',
+        data: mockPerformanceData.cpu.trend,
+        smooth: true,
+        itemStyle: {
+          color: '#409EFF'
+        }
+      },
+      {
+        name: '内存',
+        type: 'line',
+        data: mockPerformanceData.memory.trend,
+        smooth: true,
+        itemStyle: {
+          color: '#67C23A'
+        }
+      },
+      {
+        name: '磁盘',
+        type: 'line',
+        data: mockPerformanceData.disk.trend,
+        smooth: true,
+        itemStyle: {
+          color: '#E6A23C'
+        }
+      },
+      {
+        name: '网络',
+        type: 'line',
+        data: mockPerformanceData.network.trend,
+        smooth: true,
+        itemStyle: {
+          color: '#F56C6C'
+        }
+      }
+    ]
+  }
+  
+  performanceChart.setOption(option)
+}
+
+// 初始化项目图表
+const initProjectChart = () => {
+  if (!projectChartRef.value) return
+  
+  projectChart = echarts.init(projectChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{a} <br/>{b}: {c} ({d}%)'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left',
+      textStyle: {
+        color: '#333'
+      }
+    },
+    series: [
+      {
+        name: '项目状态',
+        type: 'pie',
+        radius: '50%',
+        data: mockProjectData,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        },
+        itemStyle: {
+          borderRadius: 10,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: {
+          show: true,
+          formatter: '{b}: {c} ({d}%)'
+        }
+      }
+    ]
+  }
+  projectChart.setOption(option)
+}
+
+// 处理窗口大小变化
+const handleResize = () => {
+  performanceChart?.resize()
+  projectChart?.resize()
+}
+
+onMounted(() => {
+  initPerformanceChart()
+  initProjectChart()
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  performanceChart?.dispose()
+  projectChart?.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 部门标签样式 */
+.department-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.dept-sales {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.dept-marketing {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.dept-development {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.dept-finance {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+/* 状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-planning {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-in_progress {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.status-completed {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-on_hold {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+/* 进度条样式 */
+.progress-bar {
+  @apply transition-all duration-300 ease-in-out;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 344 - 0
src/assets/templates/prototype/finance/FinancialManagement.vue

@@ -0,0 +1,344 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">财务管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddTransactionModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增交易
+            </button>
+            <button @click="exportFinancialData" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出报表
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 财务概览卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总收入</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">¥{{ formatNumber(totalIncome) }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总支出</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">¥{{ formatNumber(totalExpense) }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">净利润</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">¥{{ formatNumber(netProfit) }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">预算使用率</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ budgetUtilization }}%</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">交易类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="type in transactionTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">交易状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in transactionStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日期范围</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="交易编号/描述" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 交易列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">交易信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">金额</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="transaction in filteredTransactions" :key="transaction.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ transaction.number }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ transaction.description }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(transaction.date) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getAmountClass(transaction.type)" class="text-sm font-medium">
+                  {{ transaction.type === 1 ? '+' : '-' }}¥{{ formatNumber(transaction.amount) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getTypeClass(transaction.type)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getTypeName(transaction.type) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(transaction.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(transaction.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewTransaction(transaction)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editTransaction(transaction)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteTransaction(transaction)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增交易模态框 -->
+    <div v-if="showAddTransactionModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增交易</h2>
+        <form @submit.prevent="addTransaction">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">交易类型</label>
+            <select v-model="newTransaction.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in transactionTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">金额</label>
+            <input type="number" v-model="newTransaction.amount" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日期</label>
+            <input type="date" v-model="newTransaction.date" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">描述</label>
+            <textarea v-model="newTransaction.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddTransactionModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 交易数据
+const transactions = ref([
+  {
+    id: 1,
+    number: 'TR20240315001',
+    type: 1,
+    amount: 5000,
+    description: '产品销售',
+    date: new Date().toISOString().split('T')[0],
+    status: 1
+  },
+  {
+    id: 2,
+    number: 'TR20240315002',
+    type: 2,
+    amount: 2000,
+    description: '办公用品采购',
+    date: new Date(Date.now() - 86400000).toISOString().split('T')[0],
+    status: 1
+  }
+])
+
+// 交易类型
+const transactionTypes = [
+  { id: 1, name: '收入' },
+  { id: 2, name: '支出' }
+]
+
+// 交易状态
+const transactionStatuses = [
+  { id: 1, name: '已完成' },
+  { id: 2, name: '待审核' },
+  { id: 3, name: '已取消' }
+]
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  status: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddTransactionModal = ref(false)
+
+// 新交易表单
+const newTransaction = ref({
+  type: '',
+  amount: '',
+  date: '',
+  description: ''
+})
+
+// 计算属性
+const filteredTransactions = computed(() => {
+  return transactions.value.filter(transaction => {
+    const matchesType = !filters.value.type || transaction.type === filters.value.type
+    const matchesStatus = !filters.value.status || transaction.status === filters.value.status
+    const matchesDate = (!filters.value.startDate || transaction.date >= filters.value.startDate) &&
+      (!filters.value.endDate || transaction.date <= filters.value.endDate)
+    const matchesSearch = !filters.value.search ||
+      transaction.number.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      transaction.description.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesStatus && matchesDate && matchesSearch
+  })
+})
+
+const totalIncome = computed(() => {
+  return transactions.value
+    .filter(t => t.type === 1)
+    .reduce((sum, t) => sum + t.amount, 0)
+})
+
+const totalExpense = computed(() => {
+  return transactions.value
+    .filter(t => t.type === 2)
+    .reduce((sum, t) => sum + t.amount, 0)
+})
+
+const netProfit = computed(() => {
+  return totalIncome.value - totalExpense.value
+})
+
+const budgetUtilization = computed(() => {
+  // 这里使用一个简单的计算方式,实际应用中应该根据实际的预算使用情况计算
+  return 75
+})
+
+// 格式化数字
+const formatNumber = (number) => {
+  return number.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取类型名称
+const getTypeName = (typeId) => {
+  const type = transactionTypes.find(t => t.id === typeId)
+  return type ? type.name : '未知'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = transactionStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取金额样式
+const getAmountClass = (type) => {
+  return type === 1 ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'
+}
+
+// 获取类型样式
+const getTypeClass = (typeId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[typeId] || classes[1]
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 添加交易
+const addTransaction = () => {
+  const transaction = {
+    id: transactions.value.length + 1,
+    number: `TR${new Date().getTime()}`,
+    ...newTransaction.value,
+    status: 1
+  }
+  transactions.value.push(transaction)
+  showAddTransactionModal.value = false
+  resetNewTransaction()
+}
+
+// 重置新交易表单
+const resetNewTransaction = () => {
+  newTransaction.value = {
+    type: '',
+    amount: '',
+    date: '',
+    description: ''
+  }
+}
+
+// 查看交易
+const viewTransaction = (transaction) => {
+  // 实现查看交易逻辑
+  console.log('查看交易:', transaction)
+}
+
+// 编辑交易
+const editTransaction = (transaction) => {
+  // 实现编辑交易逻辑
+  console.log('编辑交易:', transaction)
+}
+
+// 删除交易
+const deleteTransaction = (transaction) => {
+  if (confirm(`确定要删除交易 ${transaction.number} 吗?`)) {
+    const index = transactions.value.findIndex(t => t.id === transaction.id)
+    if (index !== -1) {
+      transactions.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出财务数据
+const exportFinancialData = () => {
+  // 实现导出财务数据的逻辑
+  console.log('导出财务数据')
+}
+</script> 

+ 750 - 0
src/assets/templates/prototype/finance/MarketingAnalytics.vue

@@ -0,0 +1,750 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">营销分析</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索活动名称/ID..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="campaignType"
+            @change="handleCampaignTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类型</option>
+            <option value="email">邮件营销</option>
+            <option value="sms">短信营销</option>
+            <option value="social">社交媒体</option>
+            <option value="ads">广告投放</option>
+          </select>
+          <select 
+            v-model="status"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="running">进行中</option>
+            <option value="completed">已完成</option>
+            <option value="scheduled">已计划</option>
+            <option value="cancelled">已取消</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 营销统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <UsersIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总触达人数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">12,345</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <MousePointerClickIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">点击率</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">3.2%</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <ShoppingCartIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">转化率</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1.8%</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <DollarSignIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">ROI</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">2.5</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 营销分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">营销活动趋势</h3>
+          <div ref="trendChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">渠道效果分析</h3>
+          <div ref="channelChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 营销活动列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">活动信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">预算</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">开始时间</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="campaign in paginatedCampaigns" :key="campaign.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-full object-cover" :src="campaign.image" :alt="campaign.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ campaign.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ campaign.description }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['type-tag', `type-${campaign.type}`]">
+                    {{ campaign.type === 'email' ? '邮件营销' : 
+                       campaign.type === 'sms' ? '短信营销' : 
+                       campaign.type === 'social' ? '社交媒体' : '广告投放' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">¥{{ campaign.budget }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ campaign.startTime }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${campaign.status}`]">
+                    {{ campaign.status === 'running' ? '进行中' : 
+                       campaign.status === 'completed' ? '已完成' : 
+                       campaign.status === 'scheduled' ? '已计划' : '已取消' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewCampaign(campaign)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditCampaign(campaign)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                  <button 
+                    @click="handleDeleteCampaign(campaign)"
+                    class="action-button delete-button"
+                  >
+                    <TrashIcon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredCampaigns.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredCampaigns.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  SearchIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  UsersIcon,
+  MousePointerClickIcon,
+  ShoppingCartIcon,
+  DollarSignIcon,
+  DownloadIcon,
+  EyeIcon,
+  EditIcon,
+  TrashIcon
+} from 'lucide-vue-next'
+
+// 默认图片配置
+const defaultImages = {
+  campaign: 'https://ui-avatars.com/api/?name=Campaign&background=random&color=fff&size=150'
+}
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const campaignType = ref('')
+const status = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalCampaigns = ref(100)
+
+// 模拟数据
+const mockCampaigns = ref([
+  {
+    id: 'C1001',
+    name: '春季新品促销',
+    type: 'discount',
+    startTime: '2024-03-01 00:00:00',
+    endTime: '2024-03-31 23:59:59',
+    status: 'completed',
+    budget: 50000,
+    spent: 48000,
+    reach: 120000,
+    clicks: 24000,
+    conversions: 1200,
+    roi: 2.4,
+    target: 'new_users',
+    description: '针对春季新品的限时折扣活动',
+    image: defaultImages.campaign
+  },
+  {
+    id: 'C1002',
+    name: '会员日特惠',
+    type: 'member',
+    startTime: '2024-03-15 00:00:00',
+    endTime: '2024-03-15 23:59:59',
+    status: 'completed',
+    budget: 30000,
+    spent: 28000,
+    reach: 80000,
+    clicks: 16000,
+    conversions: 800,
+    roi: 2.8,
+    target: 'vip_users',
+    description: '会员专属优惠活动',
+    image: defaultImages.campaign
+  },
+  {
+    id: 'C1003',
+    name: '618大促预热',
+    type: 'pre_sale',
+    startTime: '2024-05-01 00:00:00',
+    endTime: '2024-06-18 23:59:59',
+    status: 'active',
+    budget: 100000,
+    spent: 25000,
+    reach: 150000,
+    clicks: 30000,
+    conversions: 1500,
+    roi: 3.0,
+    target: 'all_users',
+    description: '618购物节预热活动',
+    image: defaultImages.campaign
+  },
+  {
+    id: 'C1004',
+    name: '品牌周年庆',
+    type: 'brand',
+    startTime: '2024-04-01 00:00:00',
+    endTime: '2024-04-30 23:59:59',
+    status: 'scheduled',
+    budget: 80000,
+    spent: 0,
+    reach: 0,
+    clicks: 0,
+    conversions: 0,
+    roi: 0,
+    target: 'all_users',
+    description: '品牌成立周年庆典活动',
+    image: defaultImages.campaign
+  },
+  {
+    id: 'C1005',
+    name: '限时秒杀',
+    type: 'flash_sale',
+    startTime: '2024-03-20 20:00:00',
+    endTime: '2024-03-20 22:00:00',
+    status: 'cancelled',
+    budget: 20000,
+    spent: 0,
+    reach: 0,
+    clicks: 0,
+    conversions: 0,
+    roi: 0,
+    target: 'all_users',
+    description: '限时两小时秒杀活动',
+    image: defaultImages.campaign
+  }
+])
+
+// 营销统计数据
+const marketingStats = ref({
+  totalReach: 350000,
+  clickThroughRate: 0.2,
+  conversionRate: 0.05,
+  roi: 2.8
+})
+
+// 营销活动类型分布
+const campaignTypeDistribution = ref([
+  { type: 'discount', value: 450 },
+  { type: 'member', value: 300 },
+  { type: 'pre_sale', value: 250 },
+  { type: 'brand', value: 150 },
+  { type: 'flash_sale', value: 84 }
+])
+
+// 营销效果趋势数据
+const marketingTrends = ref([
+  { date: '2024-03-01', reach: 12000, clicks: 2400, conversions: 120 },
+  { date: '2024-03-02', reach: 15000, clicks: 3000, conversions: 150 },
+  { date: '2024-03-03', reach: 18000, clicks: 3600, conversions: 180 },
+  { date: '2024-03-04', reach: 20000, clicks: 4000, conversions: 200 },
+  { date: '2024-03-05', reach: 22000, clicks: 4400, conversions: 220 },
+  { date: '2024-03-06', reach: 25000, clicks: 5000, conversions: 250 },
+  { date: '2024-03-07', reach: 28000, clicks: 5600, conversions: 280 }
+])
+
+// 计算属性
+const filteredCampaigns = computed(() => {
+  let result = [...mockCampaigns.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(campaign => 
+      campaign.name.includes(searchText.value) ||
+      campaign.description.includes(searchText.value)
+    )
+  }
+  
+  // 类型过滤
+  if (campaignType.value) {
+    result = result.filter(campaign => campaign.type === campaignType.value)
+  }
+  
+  // 状态过滤
+  if (status.value) {
+    result = result.filter(campaign => campaign.status === status.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(campaign => {
+      const startTime = new Date(campaign.startTime)
+      
+      switch (timeRange.value) {
+        case 'today':
+          return startTime.toDateString() === now.toDateString()
+        case 'week':
+          const weekStart = new Date(now.setDate(now.getDate() - now.getDay()))
+          const weekEnd = new Date(weekStart)
+          weekEnd.setDate(weekStart.getDate() + 6)
+          return startTime >= weekStart && startTime <= weekEnd
+        case 'month':
+          const monthStart = new Date(now.getFullYear(), now.getMonth(), 1)
+          const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0)
+          return startTime >= monthStart && startTime <= monthEnd
+        case 'quarter':
+          const quarter = Math.floor(now.getMonth() / 3)
+          const quarterStart = new Date(now.getFullYear(), quarter * 3, 1)
+          const quarterEnd = new Date(now.getFullYear(), quarter * 3 + 3, 0)
+          return startTime >= quarterStart && startTime <= quarterEnd
+        default:
+          return true
+      }
+    })
+  }
+  
+  return result
+})
+
+const paginatedCampaigns = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredCampaigns.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredCampaigns.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleCampaignTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewCampaign = (campaign) => {
+  console.log('查看活动:', campaign)
+}
+
+const handleEditCampaign = (campaign) => {
+  console.log('编辑活动:', campaign)
+}
+
+const handleDeleteCampaign = (campaign) => {
+  console.log('删除活动:', campaign)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 生命周期钩子
+onMounted(() => {
+  // 初始化数据
+  console.log('营销分析页面已加载')
+})
+
+const trendChartRef = ref(null)
+const channelChartRef = ref(null)
+let trendChart = null
+let channelChart = null
+
+// Mock data
+const mockTrendData = {
+  dates: ['1月', '2月', '3月', '4月', '5月', '6月'],
+  values: {
+    reach: [1200, 1400, 1800, 2200, 2600, 3000],
+    clicks: [300, 400, 500, 600, 700, 800],
+    conversions: [50, 70, 90, 120, 150, 180]
+  }
+}
+
+const mockChannelData = [
+  { value: 40, name: '邮件营销' },
+  { value: 25, name: '短信营销' },
+  { value: 20, name: '社交媒体' },
+  { value: 15, name: '广告投放' }
+]
+
+// Initialize trend chart
+const initTrendChart = () => {
+  if (!trendChartRef.value) return
+  
+  trendChart = echarts.init(trendChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['触达人数', '点击数', '转化数']
+    },
+    xAxis: {
+      type: 'category',
+      data: mockTrendData.dates
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '触达人数',
+        type: 'line',
+        data: mockTrendData.values.reach
+      },
+      {
+        name: '点击数',
+        type: 'line',
+        data: mockTrendData.values.clicks
+      },
+      {
+        name: '转化数',
+        type: 'line',
+        data: mockTrendData.values.conversions
+      }
+    ]
+  }
+  trendChart.setOption(option)
+}
+
+// Initialize channel chart
+const initChannelChart = () => {
+  if (!channelChartRef.value) return
+  
+  channelChart = echarts.init(channelChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '渠道效果',
+        type: 'pie',
+        radius: '50%',
+        data: mockChannelData,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+  channelChart.setOption(option)
+}
+
+// Handle window resize
+const handleResize = () => {
+  trendChart?.resize()
+  channelChart?.resize()
+}
+
+onMounted(() => {
+  initTrendChart()
+  initChannelChart()
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  trendChart?.dispose()
+  channelChart?.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 活动类型标签样式 */
+.type-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.type-email {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.type-sms {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.type-social {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.type-ads {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+/* 活动状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-running {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-completed {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.status-scheduled {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-cancelled {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.delete-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 717 - 0
src/assets/templates/prototype/finance/ProductAnalytics.vue

@@ -0,0 +1,717 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">产品分析</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索产品名称/ID..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="category"
+            @change="handleCategoryChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类别</option>
+            <option value="electronics">电子产品</option>
+            <option value="clothing">服装</option>
+            <option value="food">食品</option>
+            <option value="books">图书</option>
+          </select>
+          <select 
+            v-model="status"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="in_stock">在售</option>
+            <option value="out_of_stock">缺货</option>
+            <option value="discontinued">已下架</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 产品统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <PackageIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总产品数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">1,234</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <ShoppingCartIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总销量</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">56,789</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <DollarSignIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总销售额</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">¥1,234,567</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-purple-100 dark:bg-purple-900">
+              <StarIcon class="h-6 w-6 text-purple-600 dark:text-purple-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">平均评分</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">4.8</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 产品分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">产品销量趋势</h3>
+          <div ref="trendChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">产品类别分布</h3>
+          <div ref="categoryChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 产品列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">产品信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类别</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">价格</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">库存</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="product in paginatedProducts" :key="product.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-full object-cover" :src="product.image" :alt="product.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ product.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ product.description }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['category-tag', `category-${product.category}`]">
+                    {{ product.category === 'electronics' ? '电子产品' : 
+                       product.category === 'clothing' ? '服装' : 
+                       product.category === 'food' ? '食品' : '图书' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">¥{{ product.price }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ product.stock }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${product.status}`]">
+                    {{ product.status === 'in_stock' ? '在售' : 
+                       product.status === 'out_of_stock' ? '缺货' : '已下架' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewProduct(product)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditProduct(product)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                  <button 
+                    @click="handleDeleteProduct(product)"
+                    class="action-button delete-button"
+                  >
+                    <TrashIcon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredProducts.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredProducts.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  SearchIcon, 
+  DownloadIcon, 
+  EyeIcon,
+  EditIcon,
+  TrashIcon,
+  ChevronLeftIcon,
+  ChevronRightIcon,
+  PackageIcon,
+  ShoppingCartIcon,
+  DollarSignIcon,
+  StarIcon
+} from 'lucide-vue-next'
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const category = ref('')
+const status = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalProducts = ref(100)
+
+// 图表相关
+const trendChartRef = ref(null)
+const categoryChartRef = ref(null)
+let trendChart = null
+let categoryChart = null
+
+// 默认图片配置
+const defaultImages = {
+  product: 'https://ui-avatars.com/api/?name=Product&background=random&color=fff&size=150'
+}
+
+// Mock data
+const mockProducts = ref([
+  {
+    id: 'P1001',
+    name: '智能手表 Pro',
+    category: '电子产品',
+    price: 1999,
+    stock: 150,
+    sales: 1200,
+    status: 'in_stock',
+    image: defaultImages.product,
+    description: '最新款智能手表,支持心率监测和运动追踪',
+    createdAt: '2024-01-15 10:00:00',
+    updatedAt: '2024-03-20 15:30:00'
+  },
+  {
+    id: 'P1002',
+    name: '无线耳机 Air',
+    category: '电子产品',
+    price: 999,
+    stock: 200,
+    sales: 800,
+    status: 'in_stock',
+    image: defaultImages.product,
+    description: '真无线蓝牙耳机,支持主动降噪',
+    createdAt: '2024-02-01 09:00:00',
+    updatedAt: '2024-03-19 14:20:00'
+  },
+  {
+    id: 'P1003',
+    name: '智能音箱 Mini',
+    category: '电子产品',
+    price: 299,
+    stock: 50,
+    sales: 1500,
+    status: 'low_stock',
+    image: defaultImages.product,
+    description: '便携式智能音箱,支持语音助手',
+    createdAt: '2024-01-20 11:00:00',
+    updatedAt: '2024-03-18 16:45:00'
+  },
+  {
+    id: 'P1004',
+    name: '运动相机 4K',
+    category: '电子产品',
+    price: 2499,
+    stock: 0,
+    sales: 500,
+    status: 'out_of_stock',
+    image: defaultImages.product,
+    description: '4K高清运动相机,防水防抖',
+    createdAt: '2024-02-15 14:00:00',
+    updatedAt: '2024-03-17 10:30:00'
+  },
+  {
+    id: 'P1005',
+    name: '智能门锁 Pro',
+    category: '智能家居',
+    price: 1299,
+    stock: 100,
+    sales: 300,
+    status: 'in_stock',
+    image: defaultImages.product,
+    description: '指纹识别智能门锁,支持远程控制',
+    createdAt: '2024-03-01 09:30:00',
+    updatedAt: '2024-03-16 11:15:00'
+  }
+])
+
+// 产品统计数据
+const productStats = ref({
+  totalProducts: 1234,
+  inStockProducts: 1024,
+  outOfStockProducts: 56,
+  lowStockProducts: 154
+})
+
+// 产品类别分布
+const categoryDistribution = ref([
+  { category: '电子产品', value: 450 },
+  { category: '智能家居', value: 300 },
+  { category: '办公用品', value: 250 },
+  { category: '生活用品', value: 150 },
+  { category: '其他', value: 84 }
+])
+
+// 产品销售趋势
+const salesTrends = ref([
+  { date: '2024-03-01', sales: 120, revenue: 120000 },
+  { date: '2024-03-02', sales: 150, revenue: 150000 },
+  { date: '2024-03-03', sales: 180, revenue: 180000 },
+  { date: '2024-03-04', sales: 200, revenue: 200000 },
+  { date: '2024-03-05', sales: 220, revenue: 220000 },
+  { date: '2024-03-06', sales: 250, revenue: 250000 },
+  { date: '2024-03-07', sales: 280, revenue: 280000 }
+])
+
+// 产品库存预警
+const stockAlerts = ref([
+  {
+    id: 'P1003',
+    name: '智能音箱 Mini',
+    currentStock: 50,
+    minStock: 100,
+    daysToOutOfStock: 5
+  },
+  {
+    id: 'P1006',
+    name: '智能灯泡',
+    currentStock: 30,
+    minStock: 50,
+    daysToOutOfStock: 3
+  },
+  {
+    id: 'P1007',
+    name: '智能插座',
+    currentStock: 20,
+    minStock: 30,
+    daysToOutOfStock: 2
+  }
+])
+
+// 计算属性
+const filteredProducts = computed(() => {
+  let result = [...mockProducts.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(product => 
+      product.name.includes(searchText.value) ||
+      product.description.includes(searchText.value)
+    )
+  }
+  
+  // 类别过滤
+  if (category.value) {
+    result = result.filter(product => product.category === category.value)
+  }
+  
+  // 状态过滤
+  if (status.value) {
+    result = result.filter(product => product.status === status.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(product => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedProducts = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredProducts.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredProducts.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleCategoryChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewProduct = (product) => {
+  console.log('查看产品:', product)
+}
+
+const handleEditProduct = (product) => {
+  console.log('编辑产品:', product)
+}
+
+const handleDeleteProduct = (product) => {
+  console.log('删除产品:', product)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// 初始化趋势图表
+const initTrendChart = () => {
+  if (!trendChartRef.value) return
+  
+  trendChart = echarts.init(trendChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['电子产品', '服装', '食品', '图书']
+    },
+    xAxis: {
+      type: 'category',
+      data: ['1月', '2月', '3月', '4月', '5月', '6月']
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '电子产品',
+        type: 'line',
+        data: [1200, 1400, 1800, 2200, 2600, 3000]
+      },
+      {
+        name: '服装',
+        type: 'line',
+        data: [800, 1000, 1200, 1400, 1600, 1800]
+      },
+      {
+        name: '食品',
+        type: 'line',
+        data: [1500, 1700, 1900, 2100, 2300, 2500]
+      },
+      {
+        name: '图书',
+        type: 'line',
+        data: [600, 700, 800, 900, 1000, 1100]
+      }
+    ]
+  }
+  trendChart.setOption(option)
+}
+
+// 初始化类别图表
+const initCategoryChart = () => {
+  if (!categoryChartRef.value) return
+  
+  categoryChart = echarts.init(categoryChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '产品类别',
+        type: 'pie',
+        radius: '50%',
+        data: [
+          { value: 40, name: '电子产品' },
+          { value: 25, name: '服装' },
+          { value: 20, name: '食品' },
+          { value: 15, name: '图书' }
+        ],
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+  categoryChart.setOption(option)
+}
+
+// 处理窗口大小变化
+const handleResize = () => {
+  trendChart?.resize()
+  categoryChart?.resize()
+}
+
+onMounted(() => {
+  initTrendChart()
+  initCategoryChart()
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  trendChart?.dispose()
+  categoryChart?.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 产品类别标签样式 */
+.category-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.category-electronics {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.category-clothing {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.category-food {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.category-books {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+/* 产品状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-in_stock {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-out_of_stock {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+.status-discontinued {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.delete-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 435 - 0
src/assets/templates/prototype/hr/AttendanceManagement.vue

@@ -0,0 +1,435 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">考勤管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddLeaveModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              请假申请
+            </button>
+            <button @click="showAddOvertimeModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              加班申请
+            </button>
+            <button @click="exportAttendanceData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 考勤统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">出勤率</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ attendanceRate }}%</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">迟到次数</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ lateCount }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">请假天数</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ leaveDays }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">加班时长</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ overtimeHours }}h</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日期范围</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="filters.department" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">考勤状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in attendanceStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="员工姓名" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 考勤列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">员工信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">日期</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">打卡记录</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">备注</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="record in filteredRecords" :key="record.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ record.employeeName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ getDepartmentName(record.departmentId) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ record.position }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ formatDate(record.date) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ record.weekday }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">上班: {{ record.checkIn || '未打卡' }}</div>
+                <div class="text-sm text-gray-900 dark:text-white">下班: {{ record.checkOut || '未打卡' }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(record.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(record.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ record.remark }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewRecord(record)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editRecord(record)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteRecord(record)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 请假申请模态框 -->
+    <div v-if="showAddLeaveModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">请假申请</h2>
+        <form @submit.prevent="addLeave">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">请假类型</label>
+            <select v-model="newLeave.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in leaveTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+            <input type="date" v-model="newLeave.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+            <input type="date" v-model="newLeave.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">请假原因</label>
+            <textarea v-model="newLeave.reason" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddLeaveModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              提交
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 加班申请模态框 -->
+    <div v-if="showAddOvertimeModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">加班申请</h2>
+        <form @submit.prevent="addOvertime">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">加班日期</label>
+            <input type="date" v-model="newOvertime.date" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始时间</label>
+            <input type="time" v-model="newOvertime.startTime" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束时间</label>
+            <input type="time" v-model="newOvertime.endTime" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">加班原因</label>
+            <textarea v-model="newOvertime.reason" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddOvertimeModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              提交
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 考勤记录数据
+const attendanceRecords = ref([
+  {
+    id: 1,
+    employeeId: 1,
+    employeeName: '张三',
+    departmentId: 1,
+    position: '前端开发工程师',
+    date: '2024-03-20',
+    weekday: '星期三',
+    checkIn: '09:00',
+    checkOut: '18:00',
+    status: 1,
+    remark: '正常出勤'
+  },
+  {
+    id: 2,
+    employeeId: 2,
+    employeeName: '李四',
+    departmentId: 2,
+    position: '产品经理',
+    date: '2024-03-20',
+    weekday: '星期三',
+    checkIn: '09:30',
+    checkOut: '18:30',
+    status: 2,
+    remark: '迟到30分钟'
+  }
+])
+
+// 部门
+const departments = [
+  { id: 1, name: '技术部' },
+  { id: 2, name: '产品部' },
+  { id: 3, name: '设计部' },
+  { id: 4, name: '运营部' }
+]
+
+// 考勤状态
+const attendanceStatuses = [
+  { id: 1, name: '正常' },
+  { id: 2, name: '迟到' },
+  { id: 3, name: '早退' },
+  { id: 4, name: '缺勤' },
+  { id: 5, name: '请假' },
+  { id: 6, name: '加班' }
+]
+
+// 请假类型
+const leaveTypes = [
+  { id: 1, name: '年假' },
+  { id: 2, name: '病假' },
+  { id: 3, name: '事假' },
+  { id: 4, name: '婚假' },
+  { id: 5, name: '产假' },
+  { id: 6, name: '丧假' }
+]
+
+// 筛选条件
+const filters = ref({
+  startDate: '',
+  endDate: '',
+  department: '',
+  status: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddLeaveModal = ref(false)
+const showAddOvertimeModal = ref(false)
+
+// 新请假表单
+const newLeave = ref({
+  type: '',
+  startDate: '',
+  endDate: '',
+  reason: ''
+})
+
+// 新加班表单
+const newOvertime = ref({
+  date: '',
+  startTime: '',
+  endTime: '',
+  reason: ''
+})
+
+// 计算属性
+const filteredRecords = computed(() => {
+  return attendanceRecords.value.filter(record => {
+    const matchesDate = (!filters.value.startDate || record.date >= filters.value.startDate) &&
+                       (!filters.value.endDate || record.date <= filters.value.endDate)
+    const matchesDepartment = !filters.value.department || record.departmentId === filters.value.department
+    const matchesStatus = !filters.value.status || record.status === filters.value.status
+    const matchesSearch = !filters.value.search ||
+      record.employeeName.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesDate && matchesDepartment && matchesStatus && matchesSearch
+  })
+})
+
+const attendanceRate = computed(() => {
+  const total = attendanceRecords.value.length
+  const normal = attendanceRecords.value.filter(record => record.status === 1).length
+  return total > 0 ? Math.round((normal / total) * 100) : 0
+})
+
+const lateCount = computed(() => {
+  return attendanceRecords.value.filter(record => record.status === 2).length
+})
+
+const leaveDays = computed(() => {
+  return attendanceRecords.value.filter(record => record.status === 5).length
+})
+
+const overtimeHours = computed(() => {
+  return attendanceRecords.value.filter(record => record.status === 6).length * 2 // 假设每次加班2小时
+})
+
+// 获取部门名称
+const getDepartmentName = (departmentId) => {
+  const department = departments.find(d => d.id === departmentId)
+  return department ? department.name : '未知部门'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = attendanceStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+    5: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    6: 'bg-purple-100 text-purple-800 dark:bg-purple-700 dark:text-purple-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 添加请假记录
+const addLeave = () => {
+  const leaveType = leaveTypes.find(type => type.id === newLeave.value.type)
+  
+  const record = {
+    id: attendanceRecords.value.length + 1,
+    employeeId: 1, // 假设当前用户ID为1
+    employeeName: '张三', // 假设当前用户名为张三
+    departmentId: 1, // 假设当前用户部门ID为1
+    position: '前端开发工程师', // 假设当前用户职位
+    date: newLeave.value.startDate,
+    weekday: new Date(newLeave.value.startDate).toLocaleDateString('zh-CN', { weekday: 'long' }),
+    checkIn: '',
+    checkOut: '',
+    status: 5,
+    remark: `${leaveType.name}:${newLeave.value.reason}`
+  }
+  
+  attendanceRecords.value.push(record)
+  showAddLeaveModal.value = false
+  resetNewLeave()
+}
+
+// 添加加班记录
+const addOvertime = () => {
+  const record = {
+    id: attendanceRecords.value.length + 1,
+    employeeId: 1, // 假设当前用户ID为1
+    employeeName: '张三', // 假设当前用户名为张三
+    departmentId: 1, // 假设当前用户部门ID为1
+    position: '前端开发工程师', // 假设当前用户职位
+    date: newOvertime.value.date,
+    weekday: new Date(newOvertime.value.date).toLocaleDateString('zh-CN', { weekday: 'long' }),
+    checkIn: newOvertime.value.startTime,
+    checkOut: newOvertime.value.endTime,
+    status: 6,
+    remark: `加班:${newOvertime.value.reason}`
+  }
+  
+  attendanceRecords.value.push(record)
+  showAddOvertimeModal.value = false
+  resetNewOvertime()
+}
+
+// 重置新请假表单
+const resetNewLeave = () => {
+  newLeave.value = {
+    type: '',
+    startDate: '',
+    endDate: '',
+    reason: ''
+  }
+}
+
+// 重置新加班表单
+const resetNewOvertime = () => {
+  newOvertime.value = {
+    date: '',
+    startTime: '',
+    endTime: '',
+    reason: ''
+  }
+}
+
+// 查看记录
+const viewRecord = (record) => {
+  // 实现查看记录逻辑
+  console.log('查看记录:', record)
+}
+
+// 编辑记录
+const editRecord = (record) => {
+  // 实现编辑记录逻辑
+  console.log('编辑记录:', record)
+}
+
+// 删除记录
+const deleteRecord = (record) => {
+  if (confirm(`确定要删除${record.employeeName}的考勤记录吗?`)) {
+    const index = attendanceRecords.value.findIndex(r => r.id === record.id)
+    if (index !== -1) {
+      attendanceRecords.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出考勤数据
+const exportAttendanceData = () => {
+  // 实现导出考勤数据的逻辑
+  console.log('导出考勤数据')
+}
+</script> 

+ 424 - 0
src/assets/templates/prototype/hr/HRManagement.vue

@@ -0,0 +1,424 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900 p-6">
+    <!-- 顶部导航栏 -->
+    <div class="flex justify-between items-center mb-6">
+      <h1 class="text-2xl font-bold text-gray-900 dark:text-white">人力资源管理</h1>
+      <div class="flex space-x-4">
+        <button 
+          @click="showAddEmployee = true"
+          class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+        >
+          <PlusIcon class="h-5 w-5 inline-block mr-2" />
+          添加员工
+        </button>
+      </div>
+    </div>
+
+    <!-- 员工统计卡片 -->
+    <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">总员工数</h3>
+        <p class="mt-2 text-3xl font-bold text-indigo-600">{{ employees.length }}</p>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">在职员工</h3>
+        <p class="mt-2 text-3xl font-bold text-green-600">{{ employees.filter(e => e.status === 'active').length }}</p>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">试用期</h3>
+        <p class="mt-2 text-3xl font-bold text-yellow-600">{{ employees.filter(e => e.status === 'probation').length }}</p>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">离职员工</h3>
+        <p class="mt-2 text-3xl font-bold text-red-600">{{ employees.filter(e => e.status === 'inactive').length }}</p>
+      </div>
+    </div>
+
+    <!-- 搜索和筛选 -->
+    <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">部门</label>
+          <select 
+            v-model="filters.department"
+            class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+          >
+            <option value="">所有部门</option>
+            <option v-for="dept in departments" :key="dept.id" :value="dept.id">
+              {{ dept.name }}
+            </option>
+          </select>
+        </div>
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">职位</label>
+          <select 
+            v-model="filters.position"
+            class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+          >
+            <option value="">所有职位</option>
+            <option v-for="pos in positions" :key="pos.id" :value="pos.id">
+              {{ pos.name }}
+            </option>
+          </select>
+        </div>
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">状态</label>
+          <select 
+            v-model="filters.status"
+            class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="active">在职</option>
+            <option value="probation">试用期</option>
+            <option value="inactive">离职</option>
+          </select>
+        </div>
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜索</label>
+          <div class="mt-1 relative rounded-md shadow-sm">
+            <input 
+              type="text" 
+              v-model="searchText"
+              placeholder="搜索员工姓名..."
+              class="block w-full pr-10 border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+            />
+            <div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
+              <SearchIcon class="h-5 w-5 text-gray-400" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 员工列表 -->
+    <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+      <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+        <thead class="bg-gray-50 dark:bg-gray-700">
+          <tr>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">员工信息</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">部门/职位</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">入职日期</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+          </tr>
+        </thead>
+        <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+          <tr v-for="employee in filteredEmployees" :key="employee.id">
+            <td class="px-6 py-4 whitespace-nowrap">
+              <div class="flex items-center">
+                <div class="flex-shrink-0 h-10 w-10">
+                  <img class="h-10 w-10 rounded-full" :src="employee.avatar" :alt="employee.name">
+                </div>
+                <div class="ml-4">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ employee.name }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ employee.employeeId }}</div>
+                </div>
+              </div>
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap">
+              <div class="text-sm text-gray-900 dark:text-white">{{ getDepartmentName(employee.departmentId) }}</div>
+              <div class="text-sm text-gray-500 dark:text-gray-400">{{ getPositionName(employee.positionId) }}</div>
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              {{ formatDate(employee.joinDate) }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap">
+              <span :class="getStatusClass(employee.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                {{ getStatusText(employee.status) }}
+              </span>
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              <button 
+                @click="handleView(employee)"
+                class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-3"
+              >
+                查看
+              </button>
+              <button 
+                @click="handleEdit(employee)"
+                class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-3"
+              >
+                编辑
+              </button>
+              <button 
+                @click="handleDelete(employee)"
+                class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300"
+              >
+                删除
+              </button>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+
+    <!-- 添加/编辑员工弹窗 -->
+    <div v-if="showAddEmployee" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">
+              {{ selectedEmployee ? '编辑员工' : '添加员工' }}
+            </h3>
+            <button 
+              @click="showAddEmployee = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmit" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">姓名</label>
+                <input 
+                  type="text" 
+                  v-model="employeeForm.name"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">工号</label>
+                <input 
+                  type="text" 
+                  v-model="employeeForm.employeeId"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">部门</label>
+                <select 
+                  v-model="employeeForm.departmentId"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option v-for="dept in departments" :key="dept.id" :value="dept.id">
+                    {{ dept.name }}
+                  </option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">职位</label>
+                <select 
+                  v-model="employeeForm.positionId"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option v-for="pos in positions" :key="pos.id" :value="pos.id">
+                    {{ pos.name }}
+                  </option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">入职日期</label>
+                <input 
+                  type="date" 
+                  v-model="employeeForm.joinDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">状态</label>
+                <select 
+                  v-model="employeeForm.status"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="active">在职</option>
+                  <option value="probation">试用期</option>
+                  <option value="inactive">离职</option>
+                </select>
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">备注</label>
+                <textarea 
+                  v-model="employeeForm.remarks"
+                  rows="3"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showAddEmployee = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                {{ selectedEmployee ? '保存' : '添加' }}
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { 
+  SearchIcon, 
+  PlusIcon,
+  XIcon
+} from 'lucide-vue-next'
+
+// 默认头像配置
+const defaultImages = {
+  avatar: 'https://ui-avatars.com/api/?name=User&background=random&color=fff&size=150'
+}
+
+// 员工数据
+const employees = ref([
+  {
+    id: 1,
+    name: '张三',
+    department: '技术部',
+    position: '高级工程师',
+    status: '在职',
+    joinDate: '2023-01-15',
+    avatar: defaultImages.avatar
+  },
+  {
+    id: 2,
+    name: '李四',
+    department: '市场部',
+    position: '市场经理',
+    status: '在职',
+    joinDate: '2023-03-20',
+    avatar: defaultImages.avatar
+  },
+  {
+    id: 3,
+    name: '王五',
+    department: '人事部',
+    position: '人事专员',
+    status: '试用期',
+    joinDate: '2024-01-10',
+    avatar: defaultImages.avatar
+  }
+])
+
+// 部门数据
+const departments = ref([
+  { id: 'D001', name: '技术部' },
+  { id: 'D002', name: '市场部' },
+  { id: 'D003', name: '人事部' },
+  { id: 'D004', name: '财务部' }
+])
+
+// 职位数据
+const positions = ref([
+  { id: 'P001', name: '前端开发' },
+  { id: 'P002', name: '后端开发' },
+  { id: 'P003', name: '产品经理' },
+  { id: 'P004', name: 'UI设计师' }
+])
+
+// 搜索和筛选
+const searchText = ref('')
+const filters = ref({
+  department: '',
+  position: '',
+  status: ''
+})
+
+// 员工表单
+const showAddEmployee = ref(false)
+const selectedEmployee = ref(null)
+const employeeForm = ref({
+  name: '',
+  employeeId: '',
+  departmentId: '',
+  positionId: '',
+  joinDate: '',
+  status: 'active',
+  remarks: ''
+})
+
+// 计算属性
+const filteredEmployees = computed(() => {
+  return employees.value.filter(employee => {
+    const matchesSearch = !searchText.value || 
+      employee.name.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      employee.employeeId.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesDepartment = !filters.value.department || employee.departmentId === filters.value.department
+    const matchesPosition = !filters.value.position || employee.positionId === filters.value.position
+    const matchesStatus = !filters.value.status || employee.status === filters.value.status
+    return matchesSearch && matchesDepartment && matchesPosition && matchesStatus
+  })
+})
+
+// 方法
+const getDepartmentName = (id) => {
+  const dept = departments.value.find(d => d.id === id)
+  return dept ? dept.name : '未知部门'
+}
+
+const getPositionName = (id) => {
+  const pos = positions.value.find(p => p.id === id)
+  return pos ? pos.name : '未知职位'
+}
+
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    probation: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
+    inactive: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+const getStatusText = (status) => {
+  const texts = {
+    active: '在职',
+    probation: '试用期',
+    inactive: '离职'
+  }
+  return texts[status] || '未知'
+}
+
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString()
+}
+
+const handleView = (employee) => {
+  // 实现查看员工详情的逻辑
+  console.log('查看员工:', employee)
+}
+
+const handleEdit = (employee) => {
+  selectedEmployee.value = employee
+  employeeForm.value = { ...employee }
+  showAddEmployee.value = true
+}
+
+const handleDelete = (employee) => {
+  const index = employees.value.findIndex(e => e.id === employee.id)
+  if (index !== -1) {
+    employees.value.splice(index, 1)
+  }
+}
+
+const handleSubmit = () => {
+  if (selectedEmployee.value) {
+    const index = employees.value.findIndex(e => e.id === selectedEmployee.value.id)
+    if (index !== -1) {
+      employees.value[index] = { ...employeeForm.value }
+    }
+  } else {
+    const employee = {
+      ...employeeForm.value,
+      id: `E${new Date().getTime()}`,
+      avatar: defaultImages.avatar
+    }
+    employees.value.push(employee)
+  }
+  showAddEmployee.value = false
+  selectedEmployee.value = null
+}
+</script> 

+ 534 - 0
src/assets/templates/prototype/hr/PerformanceManagement.vue

@@ -0,0 +1,534 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">绩效管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddAssessmentModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建评估
+            </button>
+            <button @click="showAddGoalModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              添加目标
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 绩效统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">待评估</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ pendingAssessments }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">已完成</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ completedAssessments }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">平均得分</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ averageScore }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">目标达成率</div>
+          <div class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">{{ goalCompletionRate }}%</div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="员工姓名/评估周期" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">评估类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有类型</option>
+              <option v-for="type in assessmentTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in statusTypes" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有时间</option>
+              <option value="week">本周</option>
+              <option value="month">本月</option>
+              <option value="quarter">本季度</option>
+              <option value="year">本年</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 绩效评估列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">绩效评估列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">员工</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">评估类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">评估周期</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">得分</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="assessment in filteredAssessments" :key="assessment.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ assessment.employeeName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ assessment.department }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ getAssessmentTypeName(assessment.type) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ assessment.period }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ assessment.score }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getAssessmentStatusClass(assessment.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getAssessmentStatusName(assessment.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewAssessment(assessment)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editAssessment(assessment)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteAssessment(assessment)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 目标列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">目标列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">员工</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">目标名称</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">开始日期</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">结束日期</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">进度</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="goal in filteredGoals" :key="goal.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ goal.employeeName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ goal.department }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ goal.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ goal.description }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ formatDate(goal.startDate) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ formatDate(goal.endDate) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
+                  <div class="bg-blue-600 h-2.5 rounded-full" :style="{ width: goal.progress + '%' }"></div>
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ goal.progress }}%</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewGoal(goal)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editGoal(goal)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteGoal(goal)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建评估模态框 -->
+    <div v-if="showAddAssessmentModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建绩效评估</h2>
+        <form @submit.prevent="addAssessment">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">员工</label>
+            <select v-model="newAssessment.employeeId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="employee in employees" :key="employee.id" :value="employee.id">{{ employee.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">评估类型</label>
+            <select v-model="newAssessment.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in assessmentTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">评估周期</label>
+            <input type="text" v-model="newAssessment.period" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">评估内容</label>
+            <textarea v-model="newAssessment.content" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">评分标准</label>
+            <textarea v-model="newAssessment.criteria" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddAssessmentModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 添加目标模态框 -->
+    <div v-if="showAddGoalModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加目标</h2>
+        <form @submit.prevent="addGoal">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">员工</label>
+            <select v-model="newGoal.employeeId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="employee in employees" :key="employee.id" :value="employee.id">{{ employee.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">目标名称</label>
+            <input type="text" v-model="newGoal.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">目标描述</label>
+            <textarea v-model="newGoal.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+            <input type="date" v-model="newGoal.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+            <input type="date" v-model="newGoal.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">目标权重</label>
+            <input type="number" v-model="newGoal.weight" required min="1" max="100" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddGoalModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 员工数据
+const employees = ref([
+  { id: 1, name: '张三', department: '技术部' },
+  { id: 2, name: '李四', department: '市场部' },
+  { id: 3, name: '王五', department: '销售部' },
+  { id: 4, name: '赵六', department: '人力资源部' }
+])
+
+// 评估数据
+const assessments = ref([
+  {
+    id: 1,
+    employeeId: 1,
+    employeeName: '张三',
+    department: '技术部',
+    type: 1,
+    period: '2024年第一季度',
+    score: 85,
+    content: '工作表现评估',
+    criteria: '技术能力、团队协作、工作态度',
+    status: 1
+  },
+  {
+    id: 2,
+    employeeId: 2,
+    employeeName: '李四',
+    department: '市场部',
+    type: 2,
+    period: '2024年第一季度',
+    score: 92,
+    content: '项目完成情况评估',
+    criteria: '项目质量、进度控制、客户反馈',
+    status: 2
+  }
+])
+
+// 目标数据
+const goals = ref([
+  {
+    id: 1,
+    employeeId: 1,
+    employeeName: '张三',
+    department: '技术部',
+    name: '提升前端开发能力',
+    description: '完成Vue.js高级课程学习并应用到项目中',
+    startDate: '2024-01-01',
+    endDate: '2024-03-31',
+    progress: 75,
+    weight: 30
+  },
+  {
+    id: 2,
+    employeeId: 2,
+    employeeName: '李四',
+    department: '市场部',
+    name: '增加市场份额',
+    description: '通过营销活动提升品牌知名度',
+    startDate: '2024-01-01',
+    endDate: '2024-06-30',
+    progress: 40,
+    weight: 40
+  }
+])
+
+// 评估类型
+const assessmentTypes = ref([
+  { id: 1, name: '季度评估' },
+  { id: 2, name: '项目评估' },
+  { id: 3, name: '年度评估' },
+  { id: 4, name: '晋升评估' }
+])
+
+// 状态类型
+const statusTypes = ref([
+  { id: 1, name: '待评估' },
+  { id: 2, name: '已完成' },
+  { id: 3, name: '已取消' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  status: '',
+  timeRange: ''
+})
+
+// 模态框状态
+const showAddAssessmentModal = ref(false)
+const showAddGoalModal = ref(false)
+
+// 新评估表单
+const newAssessment = ref({
+  employeeId: '',
+  type: '',
+  period: '',
+  content: '',
+  criteria: ''
+})
+
+// 新目标表单
+const newGoal = ref({
+  employeeId: '',
+  name: '',
+  description: '',
+  startDate: '',
+  endDate: '',
+  weight: 50
+})
+
+// 计算属性
+const filteredAssessments = computed(() => {
+  return assessments.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.employeeName.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.period.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || item.type === filters.value.type
+    const matchesStatus = !filters.value.status || item.status === filters.value.status
+    return matchesSearch && matchesType && matchesStatus
+  })
+})
+
+const filteredGoals = computed(() => {
+  return goals.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.employeeName.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.name.toLowerCase().includes(searchText.value.toLowerCase())
+    return matchesSearch
+  })
+})
+
+const pendingAssessments = computed(() => {
+  return assessments.value.filter(item => item.status === 1).length
+})
+
+const completedAssessments = computed(() => {
+  return assessments.value.filter(item => item.status === 2).length
+})
+
+const averageScore = computed(() => {
+  const scores = assessments.value.map(assessment => assessment.score)
+  const sum = scores.reduce((total, score) => total + score, 0)
+  return scores.length > 0 ? (sum / scores.length).toFixed(1) : '0.0'
+})
+
+const goalCompletionRate = computed(() => {
+  const totalProgress = goals.value.reduce((total, goal) => total + goal.progress, 0)
+  return goals.value.length > 0 ? Math.round(totalProgress / goals.value.length) : 0
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取评估类型名称
+const getAssessmentTypeName = (typeId) => {
+  const type = assessmentTypes.value.find(t => t.id === typeId)
+  return type ? type.name : '未知类型'
+}
+
+// 获取评估状态名称
+const getAssessmentStatusName = (statusId) => {
+  const status = statusTypes.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取评估状态样式
+const getAssessmentStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    2: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    3: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加评估
+const addAssessment = () => {
+  const employee = employees.value.find(e => e.id === newAssessment.value.employeeId)
+  const item = {
+    id: assessments.value.length + 1,
+    ...newAssessment.value,
+    employeeName: employee.name,
+    department: employee.department,
+    score: 0,
+    status: 1
+  }
+  assessments.value.push(item)
+  showAddAssessmentModal.value = false
+  resetNewAssessment()
+}
+
+// 重置新评估表单
+const resetNewAssessment = () => {
+  newAssessment.value = {
+    employeeId: '',
+    type: '',
+    period: '',
+    content: '',
+    criteria: ''
+  }
+}
+
+// 添加目标
+const addGoal = () => {
+  const employee = employees.value.find(e => e.id === newGoal.value.employeeId)
+  const item = {
+    id: goals.value.length + 1,
+    ...newGoal.value,
+    employeeName: employee.name,
+    department: employee.department,
+    progress: 0
+  }
+  goals.value.push(item)
+  showAddGoalModal.value = false
+  resetNewGoal()
+}
+
+// 重置新目标表单
+const resetNewGoal = () => {
+  newGoal.value = {
+    employeeId: '',
+    name: '',
+    description: '',
+    startDate: '',
+    endDate: '',
+    weight: 50
+  }
+}
+
+// 查看评估
+const viewAssessment = (item) => {
+  // 实现查看评估逻辑
+  console.log('查看评估:', item)
+}
+
+// 编辑评估
+const editAssessment = (item) => {
+  // 实现编辑评估逻辑
+  console.log('编辑评估:', item)
+}
+
+// 删除评估
+const deleteAssessment = (item) => {
+  if (confirm(`确定要删除"${item.employeeName}"的评估记录吗?`)) {
+    const index = assessments.value.findIndex(a => a.id === item.id)
+    if (index !== -1) {
+      assessments.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看目标
+const viewGoal = (item) => {
+  // 实现查看目标逻辑
+  console.log('查看目标:', item)
+}
+
+// 编辑目标
+const editGoal = (item) => {
+  // 实现编辑目标逻辑
+  console.log('编辑目标:', item)
+}
+
+// 删除目标
+const deleteGoal = (item) => {
+  if (confirm(`确定要删除"${item.employeeName}"的目标"${item.name}"吗?`)) {
+    const index = goals.value.findIndex(g => g.id === item.id)
+    if (index !== -1) {
+      goals.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 325 - 0
src/assets/templates/prototype/hr/RecruitmentManagement.vue

@@ -0,0 +1,325 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">招聘管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddPositionModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              发布职位
+            </button>
+            <button @click="exportRecruitmentData" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 招聘统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">待处理简历</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ pendingResumes }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">面试安排</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ scheduledInterviews }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">已录用</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ hiredCandidates }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">招聘完成率</h3>
+          <p class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">{{ recruitmentCompletionRate }}%</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">职位类型</label>
+            <select v-model="filters.positionType" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="type in positionTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">简历状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in resumeStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日期范围</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="职位名称/候选人姓名" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 职位列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">职位信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">候选人</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="position in filteredPositions" :key="position.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ position.title }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ position.department }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ getPositionTypeName(position.type) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ position.candidateName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ position.candidateEmail }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ position.candidatePhone }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(position.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(position.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewResume(position)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看简历</button>
+                <button @click="scheduleInterview(position)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">安排面试</button>
+                <button @click="updateStatus(position)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300">更新状态</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 发布职位模态框 -->
+    <div v-if="showAddPositionModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">发布职位</h2>
+        <form @submit.prevent="addPosition">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">职位名称</label>
+            <input type="text" v-model="newPosition.title" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <input type="text" v-model="newPosition.department" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">职位类型</label>
+            <select v-model="newPosition.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in positionTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">职位描述</label>
+            <textarea v-model="newPosition.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">任职要求</label>
+            <textarea v-model="newPosition.requirements" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddPositionModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              发布
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 职位数据
+const positions = ref([
+  {
+    id: 1,
+    title: '前端开发工程师',
+    department: '技术部',
+    type: 1,
+    description: '负责公司产品的前端开发工作',
+    requirements: '3年以上前端开发经验,熟悉Vue.js',
+    candidateName: '张三',
+    candidateEmail: 'zhangsan@example.com',
+    candidatePhone: '13800138000',
+    status: 1
+  },
+  {
+    id: 2,
+    title: '产品经理',
+    department: '产品部',
+    type: 2,
+    description: '负责产品规划和设计',
+    requirements: '5年以上产品经验,熟悉敏捷开发',
+    candidateName: '李四',
+    candidateEmail: 'lisi@example.com',
+    candidatePhone: '13900139000',
+    status: 2
+  }
+])
+
+// 职位类型
+const positionTypes = [
+  { id: 1, name: '技术类' },
+  { id: 2, name: '产品类' },
+  { id: 3, name: '设计类' },
+  { id: 4, name: '运营类' }
+]
+
+// 简历状态
+const resumeStatuses = [
+  { id: 1, name: '待处理' },
+  { id: 2, name: '已安排面试' },
+  { id: 3, name: '面试通过' },
+  { id: 4, name: '已录用' },
+  { id: 5, name: '已拒绝' }
+]
+
+// 筛选条件
+const filters = ref({
+  positionType: '',
+  status: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddPositionModal = ref(false)
+
+// 新职位表单
+const newPosition = ref({
+  title: '',
+  department: '',
+  type: '',
+  description: '',
+  requirements: ''
+})
+
+// 计算属性
+const filteredPositions = computed(() => {
+  return positions.value.filter(position => {
+    const matchesType = !filters.value.positionType || position.type === filters.value.positionType
+    const matchesStatus = !filters.value.status || position.status === filters.value.status
+    const matchesDate = (!filters.value.startDate || position.date >= filters.value.startDate) &&
+      (!filters.value.endDate || position.date <= filters.value.endDate)
+    const matchesSearch = !filters.value.search ||
+      position.title.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      position.candidateName.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesStatus && matchesDate && matchesSearch
+  })
+})
+
+const pendingResumes = computed(() => {
+  return positions.value.filter(position => position.status === 1).length
+})
+
+const scheduledInterviews = computed(() => {
+  return positions.value.filter(position => position.status === 2).length
+})
+
+const hiredCandidates = computed(() => {
+  return positions.value.filter(position => position.status === 4).length
+})
+
+const recruitmentCompletionRate = computed(() => {
+  const totalPositions = positions.value.length
+  if (totalPositions === 0) return 0
+  const completedPositions = positions.value.filter(position => position.status === 4).length
+  return Math.round((completedPositions / totalPositions) * 100)
+})
+
+// 获取职位类型名称
+const getPositionTypeName = (typeId) => {
+  const type = positionTypes.find(t => t.id === typeId)
+  return type ? type.name : '未知'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = resumeStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    4: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    5: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 添加职位
+const addPosition = () => {
+  const position = {
+    id: positions.value.length + 1,
+    ...newPosition.value,
+    status: 1
+  }
+  positions.value.push(position)
+  showAddPositionModal.value = false
+  resetNewPosition()
+}
+
+// 重置新职位表单
+const resetNewPosition = () => {
+  newPosition.value = {
+    title: '',
+    department: '',
+    type: '',
+    description: '',
+    requirements: ''
+  }
+}
+
+// 查看简历
+const viewResume = (position) => {
+  // 实现查看简历逻辑
+  console.log('查看简历:', position)
+}
+
+// 安排面试
+const scheduleInterview = (position) => {
+  // 实现安排面试逻辑
+  console.log('安排面试:', position)
+}
+
+// 更新状态
+const updateStatus = (position) => {
+  // 实现更新状态逻辑
+  console.log('更新状态:', position)
+}
+
+// 导出招聘数据
+const exportRecruitmentData = () => {
+  // 实现导出招聘数据的逻辑
+  console.log('导出招聘数据')
+}
+</script> 

+ 453 - 0
src/assets/templates/prototype/hr/SalaryManagement.vue

@@ -0,0 +1,453 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900 p-6">
+    <!-- 顶部导航栏 -->
+    <div class="flex justify-between items-center mb-6">
+      <h1 class="text-2xl font-bold text-gray-900 dark:text-white">薪资管理</h1>
+      <div class="flex space-x-4">
+        <button 
+          @click="showSalaryAdjustment = true"
+          class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+        >
+          <PlusIcon class="h-5 w-5 inline-block mr-2" />
+          薪资调整
+        </button>
+        <button 
+          @click="handleSalaryPayment"
+          class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+        >
+          <DownloadIcon class="h-5 w-5 inline-block mr-2" />
+          发放薪资
+        </button>
+      </div>
+    </div>
+
+    <!-- 薪资统计卡片 -->
+    <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">本月总薪资</h3>
+        <p class="mt-2 text-3xl font-bold text-indigo-600">¥{{ totalSalary }}</p>
+        <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">本月</p>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">平均薪资</h3>
+        <p class="mt-2 text-3xl font-bold text-green-600">¥{{ averageSalary }}</p>
+        <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">本月</p>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">最高薪资</h3>
+        <p class="mt-2 text-3xl font-bold text-yellow-600">¥{{ maxSalary }}</p>
+        <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">本月</p>
+      </div>
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+        <h3 class="text-lg font-medium text-gray-900 dark:text-white">最低薪资</h3>
+        <p class="mt-2 text-3xl font-bold text-red-600">¥{{ minSalary }}</p>
+        <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">本月</p>
+      </div>
+    </div>
+
+    <!-- 搜索和筛选 -->
+    <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">月份</label>
+          <input 
+            type="month" 
+            v-model="filters.month"
+            class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+          />
+        </div>
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">部门</label>
+          <select 
+            v-model="filters.department"
+            class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+          >
+            <option value="">所有部门</option>
+            <option v-for="dept in departments" :key="dept.id" :value="dept.id">
+              {{ dept.name }}
+            </option>
+          </select>
+        </div>
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">薪资范围</label>
+          <div class="flex space-x-2">
+            <input 
+              type="number" 
+              v-model="filters.minSalary"
+              placeholder="最低"
+              class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+            />
+            <input 
+              type="number" 
+              v-model="filters.maxSalary"
+              placeholder="最高"
+              class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+            />
+          </div>
+        </div>
+        <div>
+          <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜索</label>
+          <div class="mt-1 relative rounded-md shadow-sm">
+            <input 
+              type="text" 
+              v-model="searchText"
+              placeholder="搜索员工姓名..."
+              class="block w-full pr-10 border-gray-300 dark:border-gray-600 rounded-md focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+            />
+            <div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
+              <SearchIcon class="h-5 w-5 text-gray-400" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 薪资列表 -->
+    <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+      <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+        <thead class="bg-gray-50 dark:bg-gray-700">
+          <tr>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">员工信息</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">基本工资</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">绩效奖金</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">加班工资</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">补贴</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">扣款</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">实发工资</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+            <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+          </tr>
+        </thead>
+        <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+          <tr v-for="salary in filteredSalaries" :key="salary.id">
+            <td class="px-6 py-4 whitespace-nowrap">
+              <div class="flex items-center">
+                <div class="flex-shrink-0 h-10 w-10">
+                  <img class="h-10 w-10 rounded-full" :src="salary.employee.avatar" :alt="salary.employee.name">
+                </div>
+                <div class="ml-4">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ salary.employee.name }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ getDepartmentName(salary.employee.departmentId) }}</div>
+                </div>
+              </div>
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              ¥{{ salary.baseSalary }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              ¥{{ salary.bonus }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              ¥{{ salary.overtimePay }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              ¥{{ salary.allowance }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              ¥{{ salary.deduction }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-white">
+              ¥{{ salary.netSalary }}
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap">
+              <span :class="getStatusClass(salary.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                {{ getStatusText(salary.status) }}
+              </span>
+            </td>
+            <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+              <button 
+                @click="handleView(salary)"
+                class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-3"
+              >
+                查看
+              </button>
+              <button 
+                @click="handleAdjust(salary)"
+                class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300"
+              >
+                调整
+              </button>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+
+    <!-- 薪资调整弹窗 -->
+    <div v-if="showSalaryAdjustment" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full">
+        <div class="p-6">
+          <div class="flex justify-between items-center mb-6">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white">薪资调整</h3>
+            <button 
+              @click="showSalaryAdjustment = false"
+              class="text-gray-400 hover:text-gray-500 dark:hover:text-gray-300"
+            >
+              <XIcon class="h-6 w-6" />
+            </button>
+          </div>
+
+          <form @submit.prevent="handleSubmitAdjustment" class="space-y-6">
+            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">员工</label>
+                <select 
+                  v-model="adjustmentForm.employeeId"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option v-for="emp in employees" :key="emp.id" :value="emp.id">
+                    {{ emp.name }}
+                  </option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">调整类型</label>
+                <select 
+                  v-model="adjustmentForm.type"
+                  class="mt-1 block w-full pl-3 pr-10 py-2 text-base border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md dark:bg-gray-700 dark:text-white"
+                >
+                  <option value="base">基本工资</option>
+                  <option value="bonus">绩效奖金</option>
+                  <option value="allowance">补贴</option>
+                </select>
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">调整金额</label>
+                <input 
+                  type="number" 
+                  v-model="adjustmentForm.amount"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div>
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">生效日期</label>
+                <input 
+                  type="date" 
+                  v-model="adjustmentForm.effectiveDate"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                />
+              </div>
+              <div class="md:col-span-2">
+                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">调整原因</label>
+                <textarea 
+                  v-model="adjustmentForm.reason"
+                  rows="3"
+                  class="mt-1 block w-full border border-gray-300 dark:border-gray-600 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm dark:bg-gray-700 dark:text-white"
+                ></textarea>
+              </div>
+            </div>
+
+            <div class="flex justify-end space-x-3">
+              <button 
+                type="button"
+                @click="showSalaryAdjustment = false"
+                class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                取消
+              </button>
+              <button 
+                type="submit"
+                class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
+              >
+                提交
+              </button>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { 
+  SearchIcon, 
+  PlusIcon,
+  DownloadIcon,
+  XIcon
+} from 'lucide-vue-next'
+
+// 默认头像配置
+const defaultImages = {
+  avatar: 'https://ui-avatars.com/api/?name=User&background=random&color=fff&size=150'
+}
+
+// 薪资数据
+const salaries = ref([
+  {
+    id: 'S202401010001',
+    employee: {
+      id: 'E001',
+      name: '张三',
+      departmentId: 'D001',
+      avatar: defaultImages.avatar
+    },
+    baseSalary: 10000,
+    bonus: 2000,
+    overtimePay: 1000,
+    allowance: 500,
+    deduction: 300,
+    netSalary: 13200,
+    status: 'paid',
+    month: '2024-01'
+  },
+  {
+    id: 'S202401010002',
+    employee: {
+      id: 'E002',
+      name: '李四',
+      departmentId: 'D002',
+      avatar: defaultImages.avatar
+    },
+    baseSalary: 8000,
+    bonus: 1500,
+    overtimePay: 800,
+    allowance: 400,
+    deduction: 200,
+    netSalary: 10500,
+    status: 'pending',
+    month: '2024-01'
+  },
+  {
+    id: 'S202401010003',
+    employee: {
+      id: 'E003',
+      name: '王五',
+      departmentId: 'D003',
+      avatar: defaultImages.avatar
+    },
+    baseSalary: 12000,
+    bonus: 3000,
+    overtimePay: 1500,
+    allowance: 600,
+    deduction: 400,
+    netSalary: 16700,
+    status: 'paid',
+    month: '2024-01'
+  }
+])
+
+// 员工数据
+const employees = ref([
+  {
+    id: 1,
+    name: '张三',
+    department: '技术部',
+    position: '高级工程师',
+    baseSalary: 15000,
+    bonus: 3000,
+    avatar: defaultImages.avatar
+  },
+  {
+    id: 2,
+    name: '李四',
+    department: '市场部',
+    position: '市场经理',
+    baseSalary: 12000,
+    bonus: 2000,
+    avatar: defaultImages.avatar
+  }
+])
+
+// 部门数据
+const departments = ref([
+  { id: 'D001', name: '技术部' },
+  { id: 'D002', name: '市场部' },
+  { id: 'D003', name: '人事部' },
+  { id: 'D004', name: '财务部' }
+])
+
+// 搜索和筛选
+const searchText = ref('')
+const filters = ref({
+  month: '',
+  department: '',
+  minSalary: '',
+  maxSalary: ''
+})
+
+// 薪资调整表单
+const showSalaryAdjustment = ref(false)
+const adjustmentForm = ref({
+  employeeId: '',
+  type: 'base',
+  amount: 0,
+  effectiveDate: '',
+  reason: ''
+})
+
+// 计算属性
+const filteredSalaries = computed(() => {
+  return salaries.value.filter(salary => {
+    const matchesSearch = !searchText.value || 
+      salary.employee.name.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesMonth = !filters.value.month || salary.month === filters.value.month
+    const matchesDepartment = !filters.value.department || salary.employee.departmentId === filters.value.department
+    const matchesSalary = (!filters.value.minSalary || salary.netSalary >= Number(filters.value.minSalary)) &&
+      (!filters.value.maxSalary || salary.netSalary <= Number(filters.value.maxSalary))
+    return matchesSearch && matchesMonth && matchesDepartment && matchesSalary
+  })
+})
+
+const totalSalary = computed(() => {
+  return salaries.value.reduce((sum, salary) => sum + salary.netSalary, 0)
+})
+
+const averageSalary = computed(() => {
+  return Math.round(totalSalary.value / salaries.value.length)
+})
+
+const maxSalary = computed(() => {
+  return Math.max(...salaries.value.map(salary => salary.netSalary))
+})
+
+const minSalary = computed(() => {
+  return Math.min(...salaries.value.map(salary => salary.netSalary))
+})
+
+// 方法
+const getDepartmentName = (id) => {
+  const dept = departments.value.find(d => d.id === id)
+  return dept ? dept.name : '未知部门'
+}
+
+const getStatusClass = (status) => {
+  const classes = {
+    paid: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200',
+    pending: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200',
+    cancelled: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'
+}
+
+const getStatusText = (status) => {
+  const texts = {
+    paid: '已发放',
+    pending: '待发放',
+    cancelled: '已取消'
+  }
+  return texts[status] || '未知'
+}
+
+const handleView = (salary) => {
+  // 实现查看薪资详情的逻辑
+  console.log('查看薪资:', salary)
+}
+
+const handleAdjust = (salary) => {
+  adjustmentForm.value.employeeId = salary.employee.id
+  showSalaryAdjustment.value = true
+}
+
+const handleSubmitAdjustment = () => {
+  // 实现提交薪资调整的逻辑
+  console.log('提交薪资调整:', adjustmentForm.value)
+  showSalaryAdjustment.value = false
+}
+
+const handleSalaryPayment = () => {
+  // 实现发放薪资的逻辑
+  console.log('发放薪资')
+}
+</script> 

+ 574 - 0
src/assets/templates/prototype/hr/TrainingManagement.vue

@@ -0,0 +1,574 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">培训管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddPlanModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建培训计划
+            </button>
+            <button @click="showAddCourseModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              添加课程
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 培训统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">进行中培训</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ ongoingTrainings }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">已完成培训</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ completedTrainings }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">总参与人数</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ totalParticipants }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">平均评分</div>
+          <div class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">{{ averageRating }}</div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="培训名称/课程名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">培训类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有类型</option>
+              <option v-for="type in trainingTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in statusTypes" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有时间</option>
+              <option value="week">本周</option>
+              <option value="month">本月</option>
+              <option value="quarter">本季度</option>
+              <option value="year">本年</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 培训计划列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">培训计划列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">培训名称</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">开始时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">结束时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">参与人数</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="plan in filteredPlans" :key="plan.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ plan.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ plan.description }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ getTrainingTypeName(plan.type) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ formatDate(plan.startTime) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ formatDate(plan.endTime) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ plan.participants.length }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getPlanStatusClass(plan.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getPlanStatusName(plan.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewPlan(plan)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editPlan(plan)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deletePlan(plan)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 课程列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">课程列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">课程名称</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">难度</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">时长</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">讲师</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="course in filteredCourses" :key="course.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ course.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ course.description }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ getTrainingTypeName(course.type) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ getDifficultyLevelName(course.difficulty) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ course.duration }}小时
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ course.instructor }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewCourse(course)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editCourse(course)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteCourse(course)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建培训计划模态框 -->
+    <div v-if="showAddPlanModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建培训计划</h2>
+        <form @submit.prevent="addPlan">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">培训名称</label>
+            <input type="text" v-model="newPlan.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">培训类型</label>
+            <select v-model="newPlan.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in trainingTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始时间</label>
+            <input type="datetime-local" v-model="newPlan.startTime" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束时间</label>
+            <input type="datetime-local" v-model="newPlan.endTime" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">培训描述</label>
+            <textarea v-model="newPlan.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">选择课程</label>
+            <div class="space-y-2">
+              <div v-for="course in courses" :key="course.id" class="flex items-center">
+                <input type="checkbox" :value="course.id" v-model="newPlan.courses" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <span class="ml-2 text-sm text-gray-900 dark:text-white">{{ course.name }}</span>
+              </div>
+            </div>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddPlanModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 添加课程模态框 -->
+    <div v-if="showAddCourseModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加课程</h2>
+        <form @submit.prevent="addCourse">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">课程名称</label>
+            <input type="text" v-model="newCourse.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">课程类型</label>
+            <select v-model="newCourse.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in trainingTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">难度级别</label>
+            <select v-model="newCourse.difficulty" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="level in difficultyLevels" :key="level.id" :value="level.id">{{ level.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">课程时长(小时)</label>
+            <input type="number" v-model="newCourse.duration" required min="1" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">讲师</label>
+            <input type="text" v-model="newCourse.instructor" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">课程描述</label>
+            <textarea v-model="newCourse.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddCourseModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 培训计划数据
+const plans = ref([
+  {
+    id: 1,
+    name: '新员工入职培训',
+    type: 1,
+    startTime: '2024-03-01T09:00:00',
+    endTime: '2024-03-05T17:00:00',
+    description: '新员工入职培训计划',
+    courses: [1, 2],
+    participants: [1, 2, 3],
+    status: 1
+  },
+  {
+    id: 2,
+    name: '技术提升培训',
+    type: 2,
+    startTime: '2024-03-10T09:00:00',
+    endTime: '2024-03-12T17:00:00',
+    description: '技术提升培训计划',
+    courses: [3, 4],
+    participants: [4, 5, 6],
+    status: 2
+  }
+])
+
+// 课程数据
+const courses = ref([
+  {
+    id: 1,
+    name: '公司文化介绍',
+    type: 1,
+    difficulty: 1,
+    duration: 2,
+    instructor: '张三',
+    description: '介绍公司文化和价值观'
+  },
+  {
+    id: 2,
+    name: '工作流程培训',
+    type: 1,
+    difficulty: 1,
+    duration: 3,
+    instructor: '李四',
+    description: '介绍公司工作流程和规范'
+  },
+  {
+    id: 3,
+    name: '前端开发进阶',
+    type: 2,
+    difficulty: 3,
+    duration: 8,
+    instructor: '王五',
+    description: '前端开发高级技术培训'
+  },
+  {
+    id: 4,
+    name: '后端开发进阶',
+    type: 2,
+    difficulty: 3,
+    duration: 8,
+    instructor: '赵六',
+    description: '后端开发高级技术培训'
+  }
+])
+
+// 培训类型
+const trainingTypes = ref([
+  { id: 1, name: '入职培训' },
+  { id: 2, name: '技术培训' },
+  { id: 3, name: '管理培训' },
+  { id: 4, name: '产品培训' },
+  { id: 5, name: '销售培训' }
+])
+
+// 难度级别
+const difficultyLevels = ref([
+  { id: 1, name: '初级' },
+  { id: 2, name: '中级' },
+  { id: 3, name: '高级' }
+])
+
+// 状态类型
+const statusTypes = ref([
+  { id: 1, name: '进行中' },
+  { id: 2, name: '已完成' },
+  { id: 3, name: '已取消' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  status: '',
+  timeRange: ''
+})
+
+// 模态框状态
+const showAddPlanModal = ref(false)
+const showAddCourseModal = ref(false)
+
+// 新培训计划表单
+const newPlan = ref({
+  name: '',
+  type: '',
+  startTime: '',
+  endTime: '',
+  description: '',
+  courses: []
+})
+
+// 新课程表单
+const newCourse = ref({
+  name: '',
+  type: '',
+  difficulty: '',
+  duration: '',
+  instructor: '',
+  description: ''
+})
+
+// 计算属性
+const filteredPlans = computed(() => {
+  return plans.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.name.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || item.type === filters.value.type
+    const matchesStatus = !filters.value.status || item.status === filters.value.status
+    const matchesTimeRange = !filters.value.timeRange || checkTimeRange(item.startTime, filters.value.timeRange)
+    return matchesSearch && matchesType && matchesStatus && matchesTimeRange
+  })
+})
+
+const filteredCourses = computed(() => {
+  return courses.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.name.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || item.type === filters.value.type
+    return matchesSearch && matchesType
+  })
+})
+
+const ongoingTrainings = computed(() => {
+  return plans.value.filter(item => item.status === 1).length
+})
+
+const completedTrainings = computed(() => {
+  return plans.value.filter(item => item.status === 2).length
+})
+
+const totalParticipants = computed(() => {
+  return plans.value.reduce((total, plan) => total + plan.participants.length, 0)
+})
+
+const averageRating = computed(() => {
+  const ratings = plans.value.map(plan => plan.rating || 0)
+  const sum = ratings.reduce((total, rating) => total + rating, 0)
+  return ratings.length > 0 ? (sum / ratings.length).toFixed(1) : '0.0'
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 检查时间范围
+const checkTimeRange = (date, range) => {
+  const now = new Date()
+  const targetDate = new Date(date)
+  const diff = targetDate - now
+  const days = Math.floor(diff / (1000 * 60 * 60 * 24))
+
+  switch (range) {
+    case 'week':
+      return days >= 0 && days <= 7
+    case 'month':
+      return days >= 0 && days <= 30
+    case 'quarter':
+      return days >= 0 && days <= 90
+    case 'year':
+      return days >= 0 && days <= 365
+    default:
+      return true
+  }
+}
+
+// 获取培训类型名称
+const getTrainingTypeName = (typeId) => {
+  const type = trainingTypes.value.find(t => t.id === typeId)
+  return type ? type.name : '未知类型'
+}
+
+// 获取难度级别名称
+const getDifficultyLevelName = (levelId) => {
+  const level = difficultyLevels.value.find(l => l.id === levelId)
+  return level ? level.name : '未知级别'
+}
+
+// 获取计划状态名称
+const getPlanStatusName = (statusId) => {
+  const status = statusTypes.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取计划状态样式
+const getPlanStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    2: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    3: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加培训计划
+const addPlan = () => {
+  const item = {
+    id: plans.value.length + 1,
+    ...newPlan.value,
+    participants: [],
+    status: 1
+  }
+  plans.value.push(item)
+  showAddPlanModal.value = false
+  resetNewPlan()
+}
+
+// 重置新培训计划表单
+const resetNewPlan = () => {
+  newPlan.value = {
+    name: '',
+    type: '',
+    startTime: '',
+    endTime: '',
+    description: '',
+    courses: []
+  }
+}
+
+// 添加课程
+const addCourse = () => {
+  const item = {
+    id: courses.value.length + 1,
+    ...newCourse.value
+  }
+  courses.value.push(item)
+  showAddCourseModal.value = false
+  resetNewCourse()
+}
+
+// 重置新课程表单
+const resetNewCourse = () => {
+  newCourse.value = {
+    name: '',
+    type: '',
+    difficulty: '',
+    duration: '',
+    instructor: '',
+    description: ''
+  }
+}
+
+// 查看培训计划
+const viewPlan = (item) => {
+  // 实现查看培训计划逻辑
+  console.log('查看培训计划:', item)
+}
+
+// 编辑培训计划
+const editPlan = (item) => {
+  // 实现编辑培训计划逻辑
+  console.log('编辑培训计划:', item)
+}
+
+// 删除培训计划
+const deletePlan = (item) => {
+  if (confirm(`确定要删除培训计划"${item.name}"吗?`)) {
+    const index = plans.value.findIndex(p => p.id === item.id)
+    if (index !== -1) {
+      plans.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看课程
+const viewCourse = (item) => {
+  // 实现查看课程逻辑
+  console.log('查看课程:', item)
+}
+
+// 编辑课程
+const editCourse = (item) => {
+  // 实现编辑课程逻辑
+  console.log('编辑课程:', item)
+}
+
+// 删除课程
+const deleteCourse = (item) => {
+  if (confirm(`确定要删除课程"${item.name}"吗?`)) {
+    const index = courses.value.findIndex(c => c.id === item.id)
+    if (index !== -1) {
+      courses.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 453 - 0
src/assets/templates/prototype/knowledge/DocumentManagement.vue

@@ -0,0 +1,453 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">文档管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showUploadModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              上传文档
+            </button>
+            <button @click="showShareModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              共享文档
+            </button>
+            <button @click="exportDocumentData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 文档统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总文档数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalDocuments }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">共享文档</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ sharedDocuments }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">最近更新</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ recentUpdates }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">存储空间</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ storageUsed }}GB</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">文档类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="type in documentTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">共享状态</label>
+            <select v-model="filters.shareStatus" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in shareStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">创建时间</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="文档名称/描述" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 文档列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">文档信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">版本信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">共享状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="document in filteredDocuments" :key="document.id">
+              <td class="px-6 py-4">
+                <div class="flex items-center">
+                  <div class="flex-shrink-0 h-10 w-10">
+                    <img :src="getFileIcon(document.type)" :alt="document.name" class="h-10 w-10 rounded-full">
+                  </div>
+                  <div class="ml-4">
+                    <div class="text-sm font-medium text-gray-900 dark:text-white">{{ document.name }}</div>
+                    <div class="text-sm text-gray-500 dark:text-gray-400">{{ document.description }}</div>
+                    <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(document.createdAt) }}</div>
+                  </div>
+                </div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">版本: {{ document.version }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">大小: {{ formatFileSize(document.size) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">更新: {{ formatDate(document.updatedAt) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getShareStatusClass(document.shareStatus)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getShareStatusName(document.shareStatus) }}
+                </span>
+                <div v-if="document.sharedWith" class="text-sm text-gray-500 dark:text-gray-400 mt-1">
+                  共享给: {{ document.sharedWith }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="downloadDocument(document)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">下载</button>
+                <button @click="viewDocument(document)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">查看</button>
+                <button @click="editDocument(document)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteDocument(document)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 上传文档模态框 -->
+    <div v-if="showUploadModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">上传文档</h2>
+        <form @submit.prevent="uploadDocument">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">选择文件</label>
+            <input type="file" @change="handleFileChange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">文档名称</label>
+            <input type="text" v-model="newDocument.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">文档类型</label>
+            <select v-model="newDocument.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in documentTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">文档描述</label>
+            <textarea v-model="newDocument.description" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showUploadModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              上传
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 共享文档模态框 -->
+    <div v-if="showShareModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">共享文档</h2>
+        <form @submit.prevent="shareDocument">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">选择文档</label>
+            <select v-model="shareForm.documentId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="doc in myDocuments" :key="doc.id" :value="doc.id">{{ doc.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">共享对象</label>
+            <select v-model="shareForm.sharedWith" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="user in users" :key="user.id" :value="user.id">{{ user.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限设置</label>
+            <select v-model="shareForm.permission" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="permission in permissions" :key="permission.id" :value="permission.id">{{ permission.name }}</option>
+            </select>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showShareModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              共享
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 文档数据
+const documents = ref([
+  {
+    id: 1,
+    name: '项目需求文档',
+    description: '详细描述项目需求和功能规格',
+    type: 1,
+    version: '1.0.0',
+    size: 1024 * 1024 * 2, // 2MB
+    createdAt: '2024-03-01',
+    updatedAt: '2024-03-15',
+    shareStatus: 1,
+    sharedWith: '李四, 王五'
+  },
+  {
+    id: 2,
+    name: '技术方案设计',
+    description: '系统架构和技术选型说明',
+    type: 2,
+    version: '1.1.0',
+    size: 1024 * 1024 * 3, // 3MB
+    createdAt: '2024-03-05',
+    updatedAt: '2024-03-18',
+    shareStatus: 2,
+    sharedWith: '张三, 赵六'
+  }
+])
+
+// 文档类型
+const documentTypes = [
+  { id: 1, name: '需求文档' },
+  { id: 2, name: '设计文档' },
+  { id: 3, name: '测试文档' },
+  { id: 4, name: '用户手册' },
+  { id: 5, name: '其他文档' }
+]
+
+// 共享状态
+const shareStatuses = [
+  { id: 1, name: '已共享' },
+  { id: 2, name: '未共享' }
+]
+
+// 用户列表
+const users = [
+  { id: 1, name: '张三' },
+  { id: 2, name: '李四' },
+  { id: 3, name: '王五' },
+  { id: 4, name: '赵六' }
+]
+
+// 权限设置
+const permissions = [
+  { id: 1, name: '只读' },
+  { id: 2, name: '可编辑' },
+  { id: 3, name: '完全控制' }
+]
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  shareStatus: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showUploadModal = ref(false)
+const showShareModal = ref(false)
+
+// 新文档表单
+const newDocument = ref({
+  name: '',
+  type: '',
+  description: ''
+})
+
+// 共享表单
+const shareForm = ref({
+  documentId: '',
+  sharedWith: '',
+  permission: ''
+})
+
+// 计算属性
+const filteredDocuments = computed(() => {
+  return documents.value.filter(doc => {
+    const matchesType = !filters.value.type || doc.type === filters.value.type
+    const matchesShareStatus = !filters.value.shareStatus || doc.shareStatus === filters.value.shareStatus
+    const matchesDate = (!filters.value.startDate || doc.createdAt >= filters.value.startDate) &&
+                       (!filters.value.endDate || doc.createdAt <= filters.value.endDate)
+    const matchesSearch = !filters.value.search ||
+      doc.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      doc.description.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesShareStatus && matchesDate && matchesSearch
+  })
+})
+
+const totalDocuments = computed(() => {
+  return documents.value.length
+})
+
+const sharedDocuments = computed(() => {
+  return documents.value.filter(doc => doc.shareStatus === 1).length
+})
+
+const recentUpdates = computed(() => {
+  const today = new Date()
+  const sevenDaysAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000)
+  return documents.value.filter(doc => new Date(doc.updatedAt) >= sevenDaysAgo).length
+})
+
+const storageUsed = computed(() => {
+  const totalSize = documents.value.reduce((sum, doc) => sum + doc.size, 0)
+  return (totalSize / (1024 * 1024 * 1024)).toFixed(2) // 转换为GB
+})
+
+const myDocuments = computed(() => {
+  return documents.value.filter(doc => doc.shareStatus === 2)
+})
+
+// 获取文件图标
+const getFileIcon = (typeId) => {
+  const icons = {
+    1: 'https://cdn-icons-png.flaticon.com/512/281/281760.png', // 文档图标
+    2: 'https://cdn-icons-png.flaticon.com/512/2097/2097743.png', // 设计图标
+    3: 'https://cdn-icons-png.flaticon.com/512/2097/2097743.png', // 测试图标
+    4: 'https://cdn-icons-png.flaticon.com/512/2097/2097743.png', // 手册图标
+    5: 'https://cdn-icons-png.flaticon.com/512/2097/2097743.png'  // 其他图标
+  }
+  return icons[typeId] || icons[5]
+}
+
+// 获取共享状态名称
+const getShareStatusName = (statusId) => {
+  const status = shareStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取共享状态样式
+const getShareStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || classes[2]
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 格式化文件大小
+const formatFileSize = (bytes) => {
+  if (bytes === 0) return '0 B'
+  const k = 1024
+  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
+  const i = Math.floor(Math.log(bytes) / Math.log(k))
+  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
+}
+
+// 处理文件选择
+const handleFileChange = (event) => {
+  const file = event.target.files[0]
+  if (file) {
+    newDocument.value.name = file.name
+    newDocument.value.size = file.size
+  }
+}
+
+// 上传文档
+const uploadDocument = () => {
+  const document = {
+    id: documents.value.length + 1,
+    version: '1.0.0',
+    createdAt: new Date().toISOString().split('T')[0],
+    updatedAt: new Date().toISOString().split('T')[0],
+    shareStatus: 2, // 默认未共享
+    sharedWith: '',
+    ...newDocument.value
+  }
+  
+  documents.value.push(document)
+  showUploadModal.value = false
+  resetNewDocument()
+}
+
+// 共享文档
+const shareDocument = () => {
+  const document = documents.value.find(doc => doc.id === shareForm.value.documentId)
+  if (document) {
+    document.shareStatus = 1
+    document.sharedWith = users.find(user => user.id === shareForm.value.sharedWith).name
+  }
+  
+  showShareModal.value = false
+  resetShareForm()
+}
+
+// 重置新文档表单
+const resetNewDocument = () => {
+  newDocument.value = {
+    name: '',
+    type: '',
+    description: ''
+  }
+}
+
+// 重置共享表单
+const resetShareForm = () => {
+  shareForm.value = {
+    documentId: '',
+    sharedWith: '',
+    permission: ''
+  }
+}
+
+// 下载文档
+const downloadDocument = (document) => {
+  // 实现下载文档的逻辑
+  console.log('下载文档:', document)
+}
+
+// 查看文档
+const viewDocument = (document) => {
+  // 实现查看文档的逻辑
+  console.log('查看文档:', document)
+}
+
+// 编辑文档
+const editDocument = (document) => {
+  // 实现编辑文档的逻辑
+  console.log('编辑文档:', document)
+}
+
+// 删除文档
+const deleteDocument = (document) => {
+  if (confirm(`确定要删除文档 ${document.name} 吗?`)) {
+    const index = documents.value.findIndex(doc => doc.id === document.id)
+    if (index !== -1) {
+      documents.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出文档数据
+const exportDocumentData = () => {
+  // 实现导出文档数据的逻辑
+  console.log('导出文档数据')
+}
+</script> 

+ 422 - 0
src/assets/templates/prototype/knowledge/KnowledgeBaseManagement.vue

@@ -0,0 +1,422 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">知识库管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddCategoryModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              添加分类
+            </button>
+            <button @click="showAddDocumentModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              添加文档
+            </button>
+            <button @click="exportKnowledgeData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 知识库统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总文档数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalDocuments }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">分类数</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ totalCategories }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">本周新增</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ weeklyNewDocuments }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">热门文档</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ popularDocuments }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">分类</label>
+            <select v-model="filters.category" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="category in categories" :key="category.id" :value="category.id">{{ category.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">标签</label>
+            <select v-model="filters.tag" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="tag in tags" :key="tag.id" :value="tag.id">{{ tag.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">创建时间</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="文档标题/内容" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 文档列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">文档信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">分类信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">标签</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">统计</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="document in filteredDocuments" :key="document.id">
+              <td class="px-6 py-4">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ document.title }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">作者: {{ document.author }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">创建时间: {{ formatDate(document.createdAt) }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getCategoryName(document.categoryId) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">子分类: {{ document.subCategory }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="flex flex-wrap gap-1">
+                  <span v-for="tagId in document.tags" :key="tagId" class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300">
+                    {{ getTagName(tagId) }}
+                  </span>
+                </div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">浏览次数: {{ document.views }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">收藏次数: {{ document.favorites }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">评论数: {{ document.comments }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewDocument(document)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editDocument(document)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteDocument(document)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 添加分类模态框 -->
+    <div v-if="showAddCategoryModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加分类</h2>
+        <form @submit.prevent="addCategory">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">分类名称</label>
+            <input type="text" v-model="newCategory.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">父分类</label>
+            <select v-model="newCategory.parentId" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">无</option>
+              <option v-for="category in categories" :key="category.id" :value="category.id">{{ category.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">分类描述</label>
+            <textarea v-model="newCategory.description" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddCategoryModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 添加文档模态框 -->
+    <div v-if="showAddDocumentModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加文档</h2>
+        <form @submit.prevent="addDocument">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">文档标题</label>
+            <input type="text" v-model="newDocument.title" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">分类</label>
+            <select v-model="newDocument.categoryId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="category in categories" :key="category.id" :value="category.id">{{ category.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">子分类</label>
+            <input type="text" v-model="newDocument.subCategory" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">标签</label>
+            <select v-model="newDocument.tags" multiple class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="tag in tags" :key="tag.id" :value="tag.id">{{ tag.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">文档内容</label>
+            <textarea v-model="newDocument.content" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="8"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddDocumentModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 文档数据
+const documents = ref([
+  {
+    id: 1,
+    title: 'Vue.js 入门指南',
+    categoryId: 1,
+    subCategory: '前端开发',
+    tags: [1, 2],
+    author: '张三',
+    createdAt: '2024-03-15',
+    views: 120,
+    favorites: 30,
+    comments: 15,
+    content: 'Vue.js 是一个用于构建用户界面的渐进式框架...'
+  },
+  {
+    id: 2,
+    title: 'Spring Boot 最佳实践',
+    categoryId: 2,
+    subCategory: '后端开发',
+    tags: [3, 4],
+    author: '李四',
+    createdAt: '2024-03-18',
+    views: 85,
+    favorites: 25,
+    comments: 10,
+    content: 'Spring Boot 是一个用于简化 Spring 应用开发的框架...'
+  }
+])
+
+// 分类数据
+const categories = ref([
+  {
+    id: 1,
+    name: '前端开发',
+    parentId: null,
+    description: '前端开发相关文档'
+  },
+  {
+    id: 2,
+    name: '后端开发',
+    parentId: null,
+    description: '后端开发相关文档'
+  },
+  {
+    id: 3,
+    name: 'Vue.js',
+    parentId: 1,
+    description: 'Vue.js 相关文档'
+  },
+  {
+    id: 4,
+    name: 'Spring Boot',
+    parentId: 2,
+    description: 'Spring Boot 相关文档'
+  }
+])
+
+// 标签数据
+const tags = [
+  { id: 1, name: 'JavaScript' },
+  { id: 2, name: 'Vue' },
+  { id: 3, name: 'Java' },
+  { id: 4, name: 'Spring' },
+  { id: 5, name: '数据库' },
+  { id: 6, name: '微服务' }
+]
+
+// 筛选条件
+const filters = ref({
+  category: '',
+  tag: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddCategoryModal = ref(false)
+const showAddDocumentModal = ref(false)
+
+// 新分类表单
+const newCategory = ref({
+  name: '',
+  parentId: '',
+  description: ''
+})
+
+// 新文档表单
+const newDocument = ref({
+  title: '',
+  categoryId: '',
+  subCategory: '',
+  tags: [],
+  content: ''
+})
+
+// 计算属性
+const filteredDocuments = computed(() => {
+  return documents.value.filter(document => {
+    const matchesCategory = !filters.value.category || document.categoryId === filters.value.category
+    const matchesTag = !filters.value.tag || document.tags.includes(filters.value.tag)
+    const matchesDate = (!filters.value.startDate || document.createdAt >= filters.value.startDate) &&
+                       (!filters.value.endDate || document.createdAt <= filters.value.endDate)
+    const matchesSearch = !filters.value.search ||
+      document.title.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      document.content.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesCategory && matchesTag && matchesDate && matchesSearch
+  })
+})
+
+const totalDocuments = computed(() => {
+  return documents.value.length
+})
+
+const totalCategories = computed(() => {
+  return categories.value.length
+})
+
+const weeklyNewDocuments = computed(() => {
+  const oneWeekAgo = new Date()
+  oneWeekAgo.setDate(oneWeekAgo.getDate() - 7)
+  return documents.value.filter(doc => new Date(doc.createdAt) >= oneWeekAgo).length
+})
+
+const popularDocuments = computed(() => {
+  return documents.value.filter(doc => doc.views > 100).length
+})
+
+// 获取分类名称
+const getCategoryName = (categoryId) => {
+  const category = categories.value.find(c => c.id === categoryId)
+  return category ? category.name : '未知分类'
+}
+
+// 获取标签名称
+const getTagName = (tagId) => {
+  const tag = tags.find(t => t.id === tagId)
+  return tag ? tag.name : '未知标签'
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 添加分类
+const addCategory = () => {
+  const category = {
+    id: categories.value.length + 1,
+    ...newCategory.value
+  }
+  
+  categories.value.push(category)
+  showAddCategoryModal.value = false
+  resetNewCategory()
+}
+
+// 添加文档
+const addDocument = () => {
+  const document = {
+    id: documents.value.length + 1,
+    author: '当前用户',
+    createdAt: new Date().toISOString().split('T')[0],
+    views: 0,
+    favorites: 0,
+    comments: 0,
+    ...newDocument.value
+  }
+  
+  documents.value.push(document)
+  showAddDocumentModal.value = false
+  resetNewDocument()
+}
+
+// 重置新分类表单
+const resetNewCategory = () => {
+  newCategory.value = {
+    name: '',
+    parentId: '',
+    description: ''
+  }
+}
+
+// 重置新文档表单
+const resetNewDocument = () => {
+  newDocument.value = {
+    title: '',
+    categoryId: '',
+    subCategory: '',
+    tags: [],
+    content: ''
+  }
+}
+
+// 查看文档
+const viewDocument = (document) => {
+  // 实现查看文档的逻辑
+  console.log('查看文档:', document)
+}
+
+// 编辑文档
+const editDocument = (document) => {
+  // 实现编辑文档的逻辑
+  console.log('编辑文档:', document)
+}
+
+// 删除文档
+const deleteDocument = (document) => {
+  if (confirm(`确定要删除文档 ${document.title} 吗?`)) {
+    const index = documents.value.findIndex(d => d.id === document.id)
+    if (index !== -1) {
+      documents.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出知识库数据
+const exportKnowledgeData = () => {
+  // 实现导出知识库数据的逻辑
+  console.log('导出知识库数据')
+}
+</script> 

+ 525 - 0
src/assets/templates/prototype/production/AssetManagement.vue

@@ -0,0 +1,525 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">资产管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddAssetModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              资产登记
+            </button>
+            <button @click="showBorrowModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              资产领用
+            </button>
+            <button @click="showMaintenanceModal = true" class="bg-yellow-600 text-white px-4 py-2 rounded-md hover:bg-yellow-700">
+              维修申请
+            </button>
+            <button @click="exportAssetData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 资产统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总资产数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalAssets }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">在用资产</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ inUseAssets }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">待维修</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ maintenanceAssets }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">已报废</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ scrappedAssets }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">资产类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="type in assetTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">使用状态</label>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in assetStatus" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="filters.department" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有部门</option>
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 资产列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">资产信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">价值</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="asset in filteredAssets" :key="asset.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ asset.assetNumber }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ asset.name }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getAssetTypeName(asset.type) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">¥{{ asset.value }}</div>
+                <div class="text-xs text-gray-500 dark:text-gray-400">已折旧: ¥{{ asset.depreciatedValue }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(asset.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(asset.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewAsset(asset)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editAsset(asset)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteAsset(asset)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 调拨记录列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">调拨信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">资产</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">原部门</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">目标部门</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="transfer in filteredTransfers" :key="transfer.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ transfer.transferNumber }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ formatDate(transfer.date) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getAssetName(transfer.assetId) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getDepartmentName(transfer.fromDepartment) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getDepartmentName(transfer.toDepartment) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewTransfer(transfer)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editTransfer(transfer)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteTransfer(transfer)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增资产模态框 -->
+    <div v-if="showAddAssetModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增资产</h2>
+        <form @submit.prevent="addAsset">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">资产编号</label>
+            <input type="text" v-model="newAsset.assetNumber" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">资产名称</label>
+            <input type="text" v-model="newAsset.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">资产类型</label>
+            <select v-model="newAsset.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in assetTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">价值</label>
+            <input type="number" v-model="newAsset.value" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="newAsset.department" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="newAsset.status" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="status in assetStatus" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newAsset.remarks" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddAssetModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 资产调拨模态框 -->
+    <div v-if="showTransferModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">资产调拨</h2>
+        <form @submit.prevent="addTransfer">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">调拨编号</label>
+            <input type="text" v-model="newTransfer.transferNumber" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">资产</label>
+            <select v-model="newTransfer.assetId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="asset in assetList" :key="asset.id" :value="asset.id">{{ asset.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">原部门</label>
+            <select v-model="newTransfer.fromDepartment" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">目标部门</label>
+            <select v-model="newTransfer.toDepartment" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">调拨原因</label>
+            <textarea v-model="newTransfer.reason" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showTransferModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-yellow-600 text-white rounded-md hover:bg-yellow-700">
+              提交
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 资产数据
+const assetList = ref([
+  {
+    id: 1,
+    assetNumber: 'AS202403150001',
+    name: '办公电脑',
+    type: 1,
+    value: 5000,
+    depreciatedValue: 1000,
+    department: 1,
+    status: 1,
+    remarks: '正常使用中'
+  },
+  {
+    id: 2,
+    assetNumber: 'AS202403150002',
+    name: '打印机',
+    type: 2,
+    value: 3000,
+    depreciatedValue: 600,
+    department: 2,
+    status: 2,
+    remarks: '需要维修'
+  }
+])
+
+// 调拨记录数据
+const transferRecords = ref([
+  {
+    id: 1,
+    transferNumber: 'TR202403150001',
+    assetId: 1,
+    fromDepartment: 1,
+    toDepartment: 2,
+    date: '2024-03-15',
+    reason: '部门调整'
+  },
+  {
+    id: 2,
+    transferNumber: 'TR202403150002',
+    assetId: 2,
+    fromDepartment: 2,
+    toDepartment: 3,
+    date: '2024-03-15',
+    reason: '设备更新'
+  }
+])
+
+// 资产类型
+const assetTypes = ref([
+  { id: 1, name: '办公设备' },
+  { id: 2, name: '生产设备' },
+  { id: 3, name: '运输设备' }
+])
+
+// 资产状态
+const assetStatus = ref([
+  { id: 1, name: '使用中' },
+  { id: 2, name: '维修中' },
+  { id: 3, name: '已报废' }
+])
+
+// 部门
+const departments = ref([
+  { id: 1, name: '行政部' },
+  { id: 2, name: '生产部' },
+  { id: 3, name: '销售部' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  status: '',
+  department: ''
+})
+
+// 模态框状态
+const showAddAssetModal = ref(false)
+const showTransferModal = ref(false)
+
+// 新资产表单
+const newAsset = ref({
+  assetNumber: '',
+  name: '',
+  type: '',
+  value: '',
+  department: '',
+  status: '',
+  remarks: ''
+})
+
+// 新调拨记录表单
+const newTransfer = ref({
+  transferNumber: '',
+  assetId: '',
+  fromDepartment: '',
+  toDepartment: '',
+  reason: ''
+})
+
+// 计算属性
+const filteredAssets = computed(() => {
+  return assetList.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.assetNumber.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.name.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || item.type === filters.value.type
+    const matchesStatus = !filters.value.status || item.status === filters.value.status
+    const matchesDepartment = !filters.value.department || item.department === filters.value.department
+    return matchesSearch && matchesType && matchesStatus && matchesDepartment
+  })
+})
+
+const filteredTransfers = computed(() => {
+  return transferRecords.value.filter(item => {
+    const asset = assetList.value.find(a => a.id === item.assetId)
+    const matchesSearch = !searchText.value || 
+      item.transferNumber.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      (asset && asset.name.toLowerCase().includes(searchText.value.toLowerCase()))
+    return matchesSearch
+  })
+})
+
+const totalAssets = computed(() => assetList.value.length)
+const scrappedAssets = computed(() => assetList.value.filter(item => item.status === 3).length)
+
+const inUseAssets = computed(() => {
+  return assetList.value.filter(asset => asset.status === 1).length
+})
+
+const maintenanceAssets = computed(() => {
+  return assetList.value.filter(asset => asset.status === 2).length
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取资产类型名称
+const getAssetTypeName = (typeId) => {
+  const type = assetTypes.value.find(t => t.id === typeId)
+  return type ? type.name : '未知类型'
+}
+
+// 获取资产状态名称
+const getStatusName = (statusId) => {
+  const status = assetStatus.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取部门名称
+const getDepartmentName = (departmentId) => {
+  const department = departments.value.find(d => d.id === departmentId)
+  return department ? department.name : '未知部门'
+}
+
+// 获取资产名称
+const getAssetName = (assetId) => {
+  const asset = assetList.value.find(a => a.id === assetId)
+  return asset ? asset.name : '未知资产'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 获取头像
+const getAvatar = (id) => {
+  return `https://ui-avatars.com/api/?name=${id}&background=random&color=fff&size=150`
+}
+
+// 添加资产
+const addAsset = () => {
+  const item = {
+    id: assetList.value.length + 1,
+    ...newAsset.value,
+    depreciatedValue: 0
+  }
+  assetList.value.push(item)
+  showAddAssetModal.value = false
+  resetNewAsset()
+}
+
+// 重置新资产表单
+const resetNewAsset = () => {
+  newAsset.value = {
+    assetNumber: '',
+    name: '',
+    type: '',
+    value: '',
+    department: '',
+    status: '',
+    remarks: ''
+  }
+}
+
+// 添加调拨记录
+const addTransfer = () => {
+  const item = {
+    id: transferRecords.value.length + 1,
+    ...newTransfer.value,
+    date: new Date().toISOString().split('T')[0]
+  }
+  transferRecords.value.push(item)
+  showTransferModal.value = false
+  resetNewTransfer()
+}
+
+// 重置新调拨记录表单
+const resetNewTransfer = () => {
+  newTransfer.value = {
+    transferNumber: '',
+    assetId: '',
+    fromDepartment: '',
+    toDepartment: '',
+    reason: ''
+  }
+}
+
+// 查看资产
+const viewAsset = (item) => {
+  // 实现查看资产逻辑
+  console.log('查看资产:', item)
+}
+
+// 编辑资产
+const editAsset = (item) => {
+  // 实现编辑资产逻辑
+  console.log('编辑资产:', item)
+}
+
+// 删除资产
+const deleteAsset = (item) => {
+  if (confirm(`确定要删除资产 ${item.assetNumber} 吗?`)) {
+    const index = assetList.value.findIndex(a => a.id === item.id)
+    if (index !== -1) {
+      assetList.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看调拨记录
+const viewTransfer = (item) => {
+  // 实现查看调拨记录逻辑
+  console.log('查看调拨记录:', item)
+}
+
+// 编辑调拨记录
+const editTransfer = (item) => {
+  // 实现编辑调拨记录逻辑
+  console.log('编辑调拨记录:', item)
+}
+
+// 删除调拨记录
+const deleteTransfer = (item) => {
+  if (confirm(`确定要删除调拨记录 ${item.transferNumber} 吗?`)) {
+    const index = transferRecords.value.findIndex(t => t.id === item.id)
+    if (index !== -1) {
+      transferRecords.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 747 - 0
src/assets/templates/prototype/production/EquipmentManagement.vue

@@ -0,0 +1,747 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">设备管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddEquipmentModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增设备
+            </button>
+            <button @click="showAddMaintenanceModal = true" class="bg-yellow-600 text-white px-4 py-2 rounded-md hover:bg-yellow-700">
+              新增维护
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 设备统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">设备总数</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalEquipment }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            在用设备 <span class="text-green-600">{{ activeEquipment }}</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">待维护设备</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ pendingMaintenance }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            维护完成率 <span class="text-green-600">{{ maintenanceCompletionRate }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">故障设备</div>
+          <div class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ faultyEquipment }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            平均修复时间 <span class="text-blue-600">{{ averageRepairTime }}天</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">设备利用率</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ equipmentUtilization }}%</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            环比变化 <span :class="utilizationChange >= 0 ? 'text-green-600' : 'text-red-600'">{{ utilizationChange }}%</span>
+          </div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="设备编号/名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">设备类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有类型</option>
+              <option v-for="type in equipmentTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in statusTypes" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="filters.department" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有部门</option>
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 设备列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">设备列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">设备信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">基本信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="equipment in filteredEquipment" :key="equipment.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ equipment.equipmentNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ equipment.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ equipment.typeName }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ equipment.model }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">部门: {{ equipment.departmentName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">负责人: {{ equipment.manager }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(equipment.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(equipment.status) }}
+                </span>
+                <div v-if="equipment.lastMaintenance" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
+                  上次维护: {{ formatDate(equipment.lastMaintenance) }}
+                </div>
+                <div v-if="equipment.nextMaintenance" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
+                  下次维护: {{ formatDate(equipment.nextMaintenance) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewEquipment(equipment)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editEquipment(equipment)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteEquipment(equipment)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 维护计划列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">维护计划列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">维护信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">设备信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="maintenance in filteredMaintenance" :key="maintenance.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ maintenance.maintenanceNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ maintenance.typeName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">计划日期: {{ formatDate(maintenance.planDate) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ maintenance.equipmentName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ maintenance.equipmentNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">负责人: {{ maintenance.manager }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(maintenance.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(maintenance.status) }}
+                </span>
+                <div v-if="maintenance.completionDate" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
+                  完成日期: {{ formatDate(maintenance.completionDate) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewMaintenance(maintenance)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editMaintenance(maintenance)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteMaintenance(maintenance)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增设备模态框 -->
+    <div v-if="showAddEquipmentModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增设备</h2>
+        <form @submit.prevent="addEquipment">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">设备类型</label>
+            <select v-model="newEquipment.typeId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in equipmentTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">设备名称</label>
+            <input type="text" v-model="newEquipment.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">型号</label>
+            <input type="text" v-model="newEquipment.model" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="newEquipment.departmentId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">负责人</label>
+            <select v-model="newEquipment.managerId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="manager in managers" :key="manager.id" :value="manager.id">{{ manager.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">购买日期</label>
+            <input type="date" v-model="newEquipment.purchaseDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">维护周期(天)</label>
+            <input type="number" v-model="newEquipment.maintenanceInterval" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newEquipment.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddEquipmentModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 新增维护计划模态框 -->
+    <div v-if="showAddMaintenanceModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增维护计划</h2>
+        <form @submit.prevent="addMaintenance">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">维护类型</label>
+            <select v-model="newMaintenance.typeId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in maintenanceTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">设备</label>
+            <select v-model="newMaintenance.equipmentId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="equipment in equipments" :key="equipment.id" :value="equipment.id">{{ equipment.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">计划日期</label>
+            <input type="date" v-model="newMaintenance.planDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">负责人</label>
+            <select v-model="newMaintenance.managerId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="manager in managers" :key="manager.id" :value="manager.id">{{ manager.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">维护内容</label>
+            <textarea v-model="newMaintenance.content" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newMaintenance.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddMaintenanceModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-yellow-600 text-white rounded-md hover:bg-yellow-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 设备数据
+const equipments = ref([
+  {
+    id: 1,
+    equipmentNo: 'EQ2024001',
+    typeId: 1,
+    typeName: '生产设备',
+    name: '数控机床',
+    model: 'CNC-001',
+    departmentId: 1,
+    departmentName: '生产部',
+    managerId: 1,
+    manager: '张三',
+    purchaseDate: '2024-01-01',
+    maintenanceInterval: 30,
+    status: 1,
+    lastMaintenance: '2024-01-15',
+    nextMaintenance: '2024-02-15',
+    remark: '主要生产设备'
+  },
+  {
+    id: 2,
+    equipmentNo: 'EQ2024002',
+    typeId: 2,
+    typeName: '检测设备',
+    name: '三坐标测量仪',
+    model: 'CMM-001',
+    departmentId: 2,
+    departmentName: '质检部',
+    managerId: 2,
+    manager: '李四',
+    purchaseDate: '2024-01-05',
+    maintenanceInterval: 15,
+    status: 2,
+    lastMaintenance: '2024-01-20',
+    nextMaintenance: '2024-02-05',
+    remark: '精密测量设备'
+  }
+])
+
+// 维护计划数据
+const maintenancePlans = ref([
+  {
+    id: 1,
+    maintenanceNo: 'MP2024001',
+    typeId: 1,
+    typeName: '定期维护',
+    equipmentId: 1,
+    equipmentName: '数控机床',
+    equipmentNo: 'EQ2024001',
+    managerId: 1,
+    manager: '张三',
+    planDate: '2024-02-15',
+    content: '定期保养和检查',
+    status: 1,
+    completionDate: null,
+    remark: '按计划进行'
+  },
+  {
+    id: 2,
+    maintenanceNo: 'MP2024002',
+    typeId: 2,
+    typeName: '故障维修',
+    equipmentId: 2,
+    equipmentName: '三坐标测量仪',
+    equipmentNo: 'EQ2024002',
+    managerId: 2,
+    manager: '李四',
+    planDate: '2024-02-05',
+    content: '更换传感器',
+    status: 2,
+    completionDate: '2024-02-06',
+    remark: '已完成维修'
+  }
+])
+
+// 设备类型
+const equipmentTypes = ref([
+  { id: 1, name: '生产设备' },
+  { id: 2, name: '检测设备' },
+  { id: 3, name: '辅助设备' },
+  { id: 4, name: '其他设备' }
+])
+
+// 维护类型
+const maintenanceTypes = ref([
+  { id: 1, name: '定期维护' },
+  { id: 2, name: '故障维修' },
+  { id: 3, name: '预防性维护' },
+  { id: 4, name: '其他维护' }
+])
+
+// 状态类型
+const statusTypes = ref([
+  { id: 1, name: '正常' },
+  { id: 2, name: '维护中' },
+  { id: 3, name: '故障' },
+  { id: 4, name: '停用' }
+])
+
+// 部门数据
+const departments = ref([
+  { id: 1, name: '生产部' },
+  { id: 2, name: '质检部' },
+  { id: 3, name: '维修部' },
+  { id: 4, name: '其他部门' }
+])
+
+// 负责人数据
+const managers = ref([
+  { id: 1, name: '张三', position: '设备主管' },
+  { id: 2, name: '李四', position: '维修主管' },
+  { id: 3, name: '王五', position: '技术员' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  status: '',
+  department: ''
+})
+
+// 模态框状态
+const showAddEquipmentModal = ref(false)
+const showAddMaintenanceModal = ref(false)
+
+// 新设备表单
+const newEquipment = ref({
+  typeId: '',
+  name: '',
+  model: '',
+  departmentId: '',
+  managerId: '',
+  purchaseDate: '',
+  maintenanceInterval: '',
+  remark: ''
+})
+
+// 新维护计划表单
+const newMaintenance = ref({
+  typeId: '',
+  equipmentId: '',
+  planDate: '',
+  managerId: '',
+  content: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredEquipment = computed(() => {
+  try {
+    return equipments.value.filter(equipment => {
+      if (!equipment) return false
+      
+      const matchesSearch = !searchText.value || 
+        (equipment.equipmentNo && equipment.equipmentNo.toLowerCase().includes(searchText.value.toLowerCase())) ||
+        (equipment.name && equipment.name.toLowerCase().includes(searchText.value.toLowerCase()))
+      const matchesType = !filters.value.type || equipment.typeId === filters.value.type
+      const matchesStatus = !filters.value.status || equipment.status === filters.value.status
+      const matchesDepartment = !filters.value.department || equipment.departmentId === filters.value.department
+      return matchesSearch && matchesType && matchesStatus && matchesDepartment
+    })
+  } catch (error) {
+    console.error('过滤设备时出错:', error)
+    return []
+  }
+})
+
+const filteredMaintenance = computed(() => {
+  try {
+    return maintenancePlans.value.filter(maintenance => {
+      if (!maintenance) return false
+      
+      const matchesSearch = !searchText.value || 
+        (maintenance.maintenanceNo && maintenance.maintenanceNo.toLowerCase().includes(searchText.value.toLowerCase())) ||
+        (maintenance.equipmentName && maintenance.equipmentName.toLowerCase().includes(searchText.value.toLowerCase()))
+      const matchesType = !filters.value.type || maintenance.typeId === filters.value.type
+      const matchesStatus = !filters.value.status || maintenance.status === filters.value.status
+      return matchesSearch && matchesType && matchesStatus
+    })
+  } catch (error) {
+    console.error('过滤维护计划时出错:', error)
+    return []
+  }
+})
+
+const totalEquipment = computed(() => {
+  return equipments.value.length || 0
+})
+
+const activeEquipment = computed(() => {
+  return equipments.value.filter(equipment => equipment && equipment.status === 1).length || 0
+})
+
+const pendingMaintenance = computed(() => {
+  return maintenancePlans.value.filter(maintenance => maintenance && maintenance.status === 1).length || 0
+})
+
+const maintenanceCompletionRate = computed(() => {
+  if (!maintenancePlans.value.length) return 0
+  const completedMaintenance = maintenancePlans.value.filter(maintenance => maintenance && maintenance.status === 2)
+  return Math.round((completedMaintenance.length / maintenancePlans.value.length) * 100)
+})
+
+const faultyEquipment = computed(() => {
+  return equipments.value.filter(equipment => equipment && equipment.status === 3).length || 0
+})
+
+const averageRepairTime = computed(() => {
+  const completedMaintenance = maintenancePlans.value.filter(maintenance => maintenance && maintenance.status === 2)
+  if (!completedMaintenance.length) return 0
+  const totalDays = completedMaintenance.reduce((sum, maintenance) => {
+    try {
+      const planDate = maintenance.planDate ? new Date(maintenance.planDate) : new Date()
+      const completionDate = maintenance.completionDate ? new Date(maintenance.completionDate) : new Date()
+      return sum + Math.ceil((completionDate - planDate) / (1000 * 60 * 60 * 24))
+    } catch (error) {
+      console.error('计算修复时间时出错:', error)
+      return sum
+    }
+  }, 0)
+  return Math.round(totalDays / completedMaintenance.length)
+})
+
+const equipmentUtilization = computed(() => {
+  // 这里假设有一个计算设备利用率的逻辑
+  return 85
+})
+
+const utilizationChange = computed(() => {
+  // 这里假设有一个计算环比变化的逻辑
+  return 2
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  try {
+    if (!date) return '未知日期'
+    const dateObj = new Date(date)
+    if (isNaN(dateObj.getTime())) {
+      return '无效日期'
+    }
+    return dateObj.toLocaleDateString('zh-CN')
+  } catch (error) {
+    console.error('日期格式化错误:', error)
+    return '无效日期'
+  }
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  try {
+    if (!statusId) return '未知状态'
+    const status = statusTypes.value.find(s => s && s.id === statusId)
+    return status ? status.name : '未知状态'
+  } catch (error) {
+    console.error('获取状态名称时出错:', error)
+    return '未知状态'
+  }
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  try {
+    if (!statusId) return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+    const classes = {
+      1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+      2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+      3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+      4: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+    }
+    return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  } catch (error) {
+    console.error('获取状态样式时出错:', error)
+    return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+}
+
+// 添加设备
+const addEquipment = () => {
+  try {
+    if (!newEquipment.value.typeId || !newEquipment.value.name || !newEquipment.value.model || 
+        !newEquipment.value.departmentId || !newEquipment.value.managerId || 
+        !newEquipment.value.purchaseDate || !newEquipment.value.maintenanceInterval) {
+      alert('请填写所有必填字段')
+      return
+    }
+
+    const type = equipmentTypes.value.find(t => t && t.id === newEquipment.value.typeId)
+    const department = departments.value.find(d => d && d.id === newEquipment.value.departmentId)
+    const manager = managers.value.find(m => m && m.id === newEquipment.value.managerId)
+
+    if (!type || !department || !manager) {
+      alert('无效的选择')
+      return
+    }
+
+    const equipment = {
+      id: equipments.value.length + 1,
+      equipmentNo: `EQ${new Date().getFullYear()}${String(equipments.value.length + 1).padStart(3, '0')}`,
+      typeId: newEquipment.value.typeId,
+      typeName: type.name,
+      name: newEquipment.value.name,
+      model: newEquipment.value.model,
+      departmentId: newEquipment.value.departmentId,
+      departmentName: department.name,
+      managerId: newEquipment.value.managerId,
+      manager: manager.name,
+      purchaseDate: newEquipment.value.purchaseDate,
+      maintenanceInterval: newEquipment.value.maintenanceInterval,
+      status: 1,
+      lastMaintenance: null,
+      nextMaintenance: calculateNextMaintenance(newEquipment.value.purchaseDate, newEquipment.value.maintenanceInterval),
+      remark: newEquipment.value.remark || ''
+    }
+    equipments.value.push(equipment)
+    showAddEquipmentModal.value = false
+    resetNewEquipment()
+  } catch (error) {
+    console.error('添加设备时出错:', error)
+    alert('添加设备失败,请重试')
+  }
+}
+
+// 计算下次维护日期
+const calculateNextMaintenance = (purchaseDate, interval) => {
+  try {
+    if (!purchaseDate || !interval) return null
+    const date = new Date(purchaseDate)
+    date.setDate(date.getDate() + parseInt(interval))
+    return date.toISOString().split('T')[0]
+  } catch (error) {
+    console.error('计算下次维护日期时出错:', error)
+    return null
+  }
+}
+
+// 重置新设备表单
+const resetNewEquipment = () => {
+  newEquipment.value = {
+    typeId: '',
+    name: '',
+    model: '',
+    departmentId: '',
+    managerId: '',
+    purchaseDate: '',
+    maintenanceInterval: '',
+    remark: ''
+  }
+}
+
+// 添加维护计划
+const addMaintenance = () => {
+  try {
+    if (!newMaintenance.value.typeId || !newMaintenance.value.equipmentId || 
+        !newMaintenance.value.planDate || !newMaintenance.value.managerId || 
+        !newMaintenance.value.content) {
+      alert('请填写所有必填字段')
+      return
+    }
+
+    const type = maintenanceTypes.value.find(t => t && t.id === newMaintenance.value.typeId)
+    const equipment = equipments.value.find(e => e && e.id === newMaintenance.value.equipmentId)
+    const manager = managers.value.find(m => m && m.id === newMaintenance.value.managerId)
+
+    if (!type || !equipment || !manager) {
+      alert('无效的选择')
+      return
+    }
+
+    const maintenance = {
+      id: maintenancePlans.value.length + 1,
+      maintenanceNo: `MP${new Date().getFullYear()}${String(maintenancePlans.value.length + 1).padStart(3, '0')}`,
+      typeId: newMaintenance.value.typeId,
+      typeName: type.name,
+      equipmentId: newMaintenance.value.equipmentId,
+      equipmentName: equipment.name,
+      equipmentNo: equipment.equipmentNo,
+      managerId: newMaintenance.value.managerId,
+      manager: manager.name,
+      planDate: newMaintenance.value.planDate,
+      content: newMaintenance.value.content,
+      status: 1,
+      completionDate: null,
+      remark: newMaintenance.value.remark || ''
+    }
+    maintenancePlans.value.push(maintenance)
+    showAddMaintenanceModal.value = false
+    resetNewMaintenance()
+  } catch (error) {
+    console.error('添加维护计划时出错:', error)
+    alert('添加维护计划失败,请重试')
+  }
+}
+
+// 重置新维护计划表单
+const resetNewMaintenance = () => {
+  newMaintenance.value = {
+    typeId: '',
+    equipmentId: '',
+    planDate: '',
+    managerId: '',
+    content: '',
+    remark: ''
+  }
+}
+
+// 查看设备
+const viewEquipment = (equipment) => {
+  // 实现查看设备逻辑
+  console.log('查看设备:', equipment)
+}
+
+// 编辑设备
+const editEquipment = (equipment) => {
+  // 实现编辑设备逻辑
+  console.log('编辑设备:', equipment)
+}
+
+// 删除设备
+const deleteEquipment = (equipment) => {
+  try {
+    if (!equipment) return
+    if (confirm(`确定要删除设备"${equipment.name || '未知设备'}"吗?`)) {
+      const index = equipments.value.findIndex(e => e && e.id === equipment.id)
+      if (index !== -1) {
+        equipments.value.splice(index, 1)
+      }
+    }
+  } catch (error) {
+    console.error('删除设备时出错:', error)
+    alert('删除设备失败,请重试')
+  }
+}
+
+// 查看维护计划
+const viewMaintenance = (maintenance) => {
+  // 实现查看维护计划逻辑
+  console.log('查看维护计划:', maintenance)
+}
+
+// 编辑维护计划
+const editMaintenance = (maintenance) => {
+  // 实现编辑维护计划逻辑
+  console.log('编辑维护计划:', maintenance)
+}
+
+// 删除维护计划
+const deleteMaintenance = (maintenance) => {
+  try {
+    if (!maintenance) return
+    if (confirm(`确定要删除维护计划"${maintenance.maintenanceNo || '未知维护计划'}"吗?`)) {
+      const index = maintenancePlans.value.findIndex(m => m && m.id === maintenance.id)
+      if (index !== -1) {
+        maintenancePlans.value.splice(index, 1)
+      }
+    }
+  } catch (error) {
+    console.error('删除维护计划时出错:', error)
+    alert('删除维护计划失败,请重试')
+  }
+}
+</script> 

+ 467 - 0
src/assets/templates/prototype/production/ProductionManagement.vue

@@ -0,0 +1,467 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">生产管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddPlanModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增计划
+            </button>
+            <button @click="exportData" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 生产统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">本月计划</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ monthlyPlans }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            完成率 <span :class="completionRate >= 80 ? 'text-green-600' : 'text-yellow-600'">{{ completionRate }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">进行中</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ inProgress }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            平均进度 <span class="text-blue-600">{{ averageProgress }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">已完成</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ completed }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            按时完成 <span class="text-green-600">{{ onTimeCompleted }}</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">延迟</div>
+          <div class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ delayed }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            平均延迟 <span class="text-red-600">{{ averageDelay }}天</span>
+          </div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="计划名称/产品名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">生产线</label>
+            <select v-model="filters.line" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有生产线</option>
+              <option v-for="line in productionLines" :key="line.id" :value="line.id">{{ line.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in statusTypes" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有时间</option>
+              <option v-for="range in timeRanges" :key="range.id" :value="range.id">{{ range.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 生产计划列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">生产计划列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">计划信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">生产线</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">进度</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="plan in filteredPlans" :key="plan.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ plan.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ plan.productName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ formatDate(plan.startDate) }} - {{ formatDate(plan.endDate) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ plan.lineName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">负责人: {{ plan.manager }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
+                  <div class="bg-blue-600 h-2.5 rounded-full" :style="{ width: plan.progress + '%' }"></div>
+                </div>
+                <div class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ plan.progress }}%</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(plan.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(plan.status) }}
+                </span>
+                <div v-if="plan.delay" class="mt-1 text-sm text-red-600 dark:text-red-400">
+                  延迟: {{ plan.delay }}天
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewPlan(plan)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editPlan(plan)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deletePlan(plan)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增计划模态框 -->
+    <div v-if="showAddPlanModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增生产计划</h2>
+        <form @submit.prevent="addPlan">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">计划名称</label>
+            <input type="text" v-model="newPlan.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">产品</label>
+            <select v-model="newPlan.productId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="product in products" :key="product.id" :value="product.id">{{ product.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">生产线</label>
+            <select v-model="newPlan.lineId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="line in productionLines" :key="line.id" :value="line.id">{{ line.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">计划数量</label>
+            <input type="number" v-model="newPlan.quantity" required min="1" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+            <input type="date" v-model="newPlan.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+            <input type="date" v-model="newPlan.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">负责人</label>
+            <select v-model="newPlan.managerId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="manager in managers" :key="manager.id" :value="manager.id">{{ manager.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newPlan.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddPlanModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 生产计划数据
+const productionPlans = ref([
+  {
+    id: 1,
+    name: '2024年Q1生产计划',
+    productId: 1,
+    productName: '产品A',
+    lineId: 1,
+    lineName: '生产线A',
+    quantity: 1000,
+    startDate: '2024-01-01',
+    endDate: '2024-03-31',
+    managerId: 1,
+    manager: '张三',
+    progress: 80,
+    status: 1,
+    delay: 0,
+    remark: '第一季度生产计划'
+  },
+  {
+    id: 2,
+    name: '2024年Q2生产计划',
+    productId: 2,
+    productName: '产品B',
+    lineId: 2,
+    lineName: '生产线B',
+    quantity: 2000,
+    startDate: '2024-04-01',
+    endDate: '2024-06-30',
+    managerId: 2,
+    manager: '李四',
+    progress: 30,
+    status: 2,
+    delay: 5,
+    remark: '第二季度生产计划'
+  }
+])
+
+// 产品数据
+const products = ref([
+  { id: 1, name: '产品A', code: 'P001' },
+  { id: 2, name: '产品B', code: 'P002' }
+])
+
+// 生产线数据
+const productionLines = ref([
+  { id: 1, name: '生产线A', location: 'A区' },
+  { id: 2, name: '生产线B', location: 'B区' }
+])
+
+// 负责人数据
+const managers = ref([
+  { id: 1, name: '张三', position: '生产主管' },
+  { id: 2, name: '李四', position: '生产经理' }
+])
+
+// 状态类型
+const statusTypes = ref([
+  { id: 1, name: '进行中' },
+  { id: 2, name: '延迟' },
+  { id: 3, name: '已完成' },
+  { id: 4, name: '已取消' }
+])
+
+// 时间范围
+const timeRanges = ref([
+  { id: 1, name: '本周' },
+  { id: 2, name: '本月' },
+  { id: 3, name: '本季度' },
+  { id: 4, name: '本年' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  line: '',
+  status: '',
+  timeRange: ''
+})
+
+// 模态框状态
+const showAddPlanModal = ref(false)
+
+// 新计划表单
+const newPlan = ref({
+  name: '',
+  productId: '',
+  lineId: '',
+  quantity: '',
+  startDate: '',
+  endDate: '',
+  managerId: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredPlans = computed(() => {
+  return productionPlans.value.filter(plan => {
+    const matchesSearch = !searchText.value || 
+      plan.name.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      plan.productName.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesLine = !filters.value.line || plan.lineId === filters.value.line
+    const matchesStatus = !filters.value.status || plan.status === filters.value.status
+    const matchesTimeRange = !filters.value.timeRange || checkTimeRange(plan, filters.value.timeRange)
+    return matchesSearch && matchesLine && matchesStatus && matchesTimeRange
+  })
+})
+
+const monthlyPlans = computed(() => {
+  return productionPlans.value.filter(plan => {
+    const planDate = new Date(plan.startDate)
+    const now = new Date()
+    return planDate.getMonth() === now.getMonth() && planDate.getFullYear() === now.getFullYear()
+  }).length
+})
+
+const completionRate = computed(() => {
+  const monthlyPlans = productionPlans.value.filter(plan => {
+    const planDate = new Date(plan.startDate)
+    const now = new Date()
+    return planDate.getMonth() === now.getMonth() && planDate.getFullYear() === now.getFullYear()
+  })
+  if (monthlyPlans.length === 0) return 0
+  const completedPlans = monthlyPlans.filter(plan => plan.status === 3)
+  return Math.round((completedPlans.length / monthlyPlans.length) * 100)
+})
+
+const inProgress = computed(() => {
+  return productionPlans.value.filter(plan => plan.status === 1).length
+})
+
+const averageProgress = computed(() => {
+  const inProgressPlans = productionPlans.value.filter(plan => plan.status === 1)
+  if (inProgressPlans.length === 0) return 0
+  const totalProgress = inProgressPlans.reduce((sum, plan) => sum + plan.progress, 0)
+  return Math.round(totalProgress / inProgressPlans.length)
+})
+
+const completed = computed(() => {
+  return productionPlans.value.filter(plan => plan.status === 3).length
+})
+
+const onTimeCompleted = computed(() => {
+  return productionPlans.value.filter(plan => plan.status === 3 && plan.delay === 0).length
+})
+
+const delayed = computed(() => {
+  return productionPlans.value.filter(plan => plan.status === 2).length
+})
+
+const averageDelay = computed(() => {
+  const delayedPlans = productionPlans.value.filter(plan => plan.status === 2)
+  if (delayedPlans.length === 0) return 0
+  const totalDelay = delayedPlans.reduce((sum, plan) => sum + plan.delay, 0)
+  return Math.round(totalDelay / delayedPlans.length)
+})
+
+// 检查时间范围
+const checkTimeRange = (plan, rangeId) => {
+  const now = new Date()
+  const planDate = new Date(plan.startDate)
+  switch (rangeId) {
+    case 1: // 本周
+      const weekStart = new Date(now.setDate(now.getDate() - now.getDay()))
+      const weekEnd = new Date(now.setDate(now.getDate() - now.getDay() + 6))
+      return planDate >= weekStart && planDate <= weekEnd
+    case 2: // 本月
+      return planDate.getMonth() === now.getMonth() && planDate.getFullYear() === now.getFullYear()
+    case 3: // 本季度
+      const quarterStart = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3, 1)
+      const quarterEnd = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3 + 3, 0)
+      return planDate >= quarterStart && planDate <= quarterEnd
+    case 4: // 本年
+      return planDate.getFullYear() === now.getFullYear()
+    default:
+      return true
+  }
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = statusTypes.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    4: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 导出数据
+const exportData = () => {
+  // 实现导出数据逻辑
+  console.log('导出数据')
+}
+
+// 添加计划
+const addPlan = () => {
+  const product = products.value.find(p => p.id === newPlan.value.productId)
+  const line = productionLines.value.find(l => l.id === newPlan.value.lineId)
+  const manager = managers.value.find(m => m.id === newPlan.value.managerId)
+  const plan = {
+    id: productionPlans.value.length + 1,
+    name: newPlan.value.name,
+    productId: newPlan.value.productId,
+    productName: product.name,
+    lineId: newPlan.value.lineId,
+    lineName: line.name,
+    quantity: parseInt(newPlan.value.quantity),
+    startDate: newPlan.value.startDate,
+    endDate: newPlan.value.endDate,
+    managerId: newPlan.value.managerId,
+    manager: manager.name,
+    progress: 0,
+    status: 1,
+    delay: 0,
+    remark: newPlan.value.remark
+  }
+  productionPlans.value.push(plan)
+  showAddPlanModal.value = false
+  resetNewPlan()
+}
+
+// 重置新计划表单
+const resetNewPlan = () => {
+  newPlan.value = {
+    name: '',
+    productId: '',
+    lineId: '',
+    quantity: '',
+    startDate: '',
+    endDate: '',
+    managerId: '',
+    remark: ''
+  }
+}
+
+// 查看计划
+const viewPlan = (plan) => {
+  // 实现查看计划逻辑
+  console.log('查看计划:', plan)
+}
+
+// 编辑计划
+const editPlan = (plan) => {
+  // 实现编辑计划逻辑
+  console.log('编辑计划:', plan)
+}
+
+// 删除计划
+const deletePlan = (plan) => {
+  if (confirm(`确定要删除生产计划"${plan.name}"吗?`)) {
+    const index = productionPlans.value.findIndex(p => p.id === plan.id)
+    if (index !== -1) {
+      productionPlans.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 731 - 0
src/assets/templates/prototype/production/QualityManagement.vue

@@ -0,0 +1,731 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">质量管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddInspectionModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增检验
+            </button>
+            <button @click="showAddIssueModal = true" class="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700">
+              报告问题
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 质量统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">本月检验</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ monthlyInspections }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            合格率 <span :class="passRate >= 95 ? 'text-green-600' : 'text-yellow-600'">{{ passRate }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">待处理问题</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ pendingIssues }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            平均处理时间 <span class="text-blue-600">{{ averageResolutionTime }}天</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">已解决问题</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ resolvedIssues }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            解决率 <span class="text-green-600">{{ resolutionRate }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">质量成本</div>
+          <div class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ formatNumber(qualityCost) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            环比变化 <span :class="costChange >= 0 ? 'text-green-600' : 'text-red-600'">{{ costChange }}%</span>
+          </div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="检验编号/问题描述" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有类型</option>
+              <option v-for="type in inspectionTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in statusTypes" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有时间</option>
+              <option v-for="range in timeRanges" :key="range.id" :value="range.id">{{ range.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 质量检验列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">质量检验列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">检验信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">产品信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">检验结果</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="inspection in filteredInspections" :key="inspection.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ inspection.inspectionNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(inspection.date) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ inspection.typeName }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ inspection.productName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ inspection.productCode }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">批次: {{ inspection.batchNo }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getResultClass(inspection.result)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getResultName(inspection.result) }}
+                </span>
+                <div v-if="inspection.defects" class="mt-1 text-sm text-red-600 dark:text-red-400">
+                  缺陷: {{ inspection.defects }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewInspection(inspection)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editInspection(inspection)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteInspection(inspection)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 质量问题列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">质量问题列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">问题信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">产品信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="issue in filteredIssues" :key="issue.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ issue.issueNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(issue.date) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ issue.description }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ issue.productName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ issue.productCode }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">批次: {{ issue.batchNo }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(issue.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(issue.status) }}
+                </span>
+                <div v-if="issue.resolutionDate" class="mt-1 text-sm text-gray-500 dark:text-gray-400">
+                  解决日期: {{ formatDate(issue.resolutionDate) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewIssue(issue)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editIssue(issue)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteIssue(issue)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增检验模态框 -->
+    <div v-if="showAddInspectionModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增质量检验</h2>
+        <form @submit.prevent="addInspection">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">检验类型</label>
+            <select v-model="newInspection.typeId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in inspectionTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">产品</label>
+            <select v-model="newInspection.productId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="product in products" :key="product.id" :value="product.id">{{ product.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">批次号</label>
+            <input type="text" v-model="newInspection.batchNo" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">检验日期</label>
+            <input type="date" v-model="newInspection.date" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">检验结果</label>
+            <select v-model="newInspection.result" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="result in resultTypes" :key="result.id" :value="result.id">{{ result.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">缺陷描述</label>
+            <textarea v-model="newInspection.defects" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">检验员</label>
+            <select v-model="newInspection.inspectorId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="inspector in inspectors" :key="inspector.id" :value="inspector.id">{{ inspector.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newInspection.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddInspectionModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 报告问题模态框 -->
+    <div v-if="showAddIssueModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">报告质量问题</h2>
+        <form @submit.prevent="addIssue">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">问题类型</label>
+            <select v-model="newIssue.typeId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in issueTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">产品</label>
+            <select v-model="newIssue.productId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="product in products" :key="product.id" :value="product.id">{{ product.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">批次号</label>
+            <input type="text" v-model="newIssue.batchNo" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">问题描述</label>
+            <textarea v-model="newIssue.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">严重程度</label>
+            <select v-model="newIssue.severity" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="severity in severityTypes" :key="severity.id" :value="severity.id">{{ severity.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">报告人</label>
+            <select v-model="newIssue.reporterId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="reporter in reporters" :key="reporter.id" :value="reporter.id">{{ reporter.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newIssue.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddIssueModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700">
+              提交
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 质量检验数据
+const inspections = ref([
+  {
+    id: 1,
+    inspectionNo: 'QI2024001',
+    typeId: 1,
+    typeName: '进货检验',
+    productId: 1,
+    productName: '产品A',
+    productCode: 'P001',
+    batchNo: 'B2024001',
+    date: '2024-01-15',
+    result: 1,
+    defects: '',
+    inspectorId: 1,
+    inspector: '张三',
+    remark: '检验合格'
+  },
+  {
+    id: 2,
+    inspectionNo: 'QI2024002',
+    typeId: 2,
+    typeName: '过程检验',
+    productId: 2,
+    productName: '产品B',
+    productCode: 'P002',
+    batchNo: 'B2024002',
+    date: '2024-01-16',
+    result: 2,
+    defects: '外观缺陷',
+    inspectorId: 2,
+    inspector: '李四',
+    remark: '需要返工'
+  }
+])
+
+// 质量问题数据
+const issues = ref([
+  {
+    id: 1,
+    issueNo: 'QN2024001',
+    typeId: 1,
+    typeName: '产品缺陷',
+    productId: 1,
+    productName: '产品A',
+    productCode: 'P001',
+    batchNo: 'B2024001',
+    date: '2024-01-17',
+    description: '产品表面有划痕',
+    severity: 2,
+    status: 1,
+    reporterId: 1,
+    reporter: '王五',
+    resolutionDate: null,
+    remark: '需要进一步调查'
+  },
+  {
+    id: 2,
+    issueNo: 'QN2024002',
+    typeId: 2,
+    typeName: '工艺问题',
+    productId: 2,
+    productName: '产品B',
+    productCode: 'P002',
+    batchNo: 'B2024002',
+    date: '2024-01-18',
+    description: '加工精度不达标',
+    severity: 3,
+    status: 2,
+    reporterId: 2,
+    reporter: '赵六',
+    resolutionDate: '2024-01-20',
+    remark: '已调整工艺参数'
+  }
+])
+
+// 产品数据
+const products = ref([
+  { id: 1, name: '产品A', code: 'P001' },
+  { id: 2, name: '产品B', code: 'P002' }
+])
+
+// 检验类型
+const inspectionTypes = ref([
+  { id: 1, name: '进货检验' },
+  { id: 2, name: '过程检验' },
+  { id: 3, name: '最终检验' }
+])
+
+// 问题类型
+const issueTypes = ref([
+  { id: 1, name: '产品缺陷' },
+  { id: 2, name: '工艺问题' },
+  { id: 3, name: '设备故障' },
+  { id: 4, name: '其他问题' }
+])
+
+// 检验结果类型
+const resultTypes = ref([
+  { id: 1, name: '合格' },
+  { id: 2, name: '不合格' },
+  { id: 3, name: '待处理' }
+])
+
+// 严重程度类型
+const severityTypes = ref([
+  { id: 1, name: '轻微' },
+  { id: 2, name: '一般' },
+  { id: 3, name: '严重' },
+  { id: 4, name: '致命' }
+])
+
+// 状态类型
+const statusTypes = ref([
+  { id: 1, name: '待处理' },
+  { id: 2, name: '处理中' },
+  { id: 3, name: '已解决' },
+  { id: 4, name: '已关闭' }
+])
+
+// 时间范围
+const timeRanges = ref([
+  { id: 1, name: '本周' },
+  { id: 2, name: '本月' },
+  { id: 3, name: '本季度' },
+  { id: 4, name: '本年' }
+])
+
+// 检验员数据
+const inspectors = ref([
+  { id: 1, name: '张三', position: '质量检验员' },
+  { id: 2, name: '李四', position: '质量主管' }
+])
+
+// 报告人数据
+const reporters = ref([
+  { id: 1, name: '王五', position: '生产主管' },
+  { id: 2, name: '赵六', position: '工艺工程师' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  status: '',
+  timeRange: ''
+})
+
+// 模态框状态
+const showAddInspectionModal = ref(false)
+const showAddIssueModal = ref(false)
+
+// 新检验表单
+const newInspection = ref({
+  typeId: '',
+  productId: '',
+  batchNo: '',
+  date: '',
+  result: '',
+  defects: '',
+  inspectorId: '',
+  remark: ''
+})
+
+// 新问题表单
+const newIssue = ref({
+  typeId: '',
+  productId: '',
+  batchNo: '',
+  description: '',
+  severity: '',
+  reporterId: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredInspections = computed(() => {
+  return inspections.value.filter(inspection => {
+    const matchesSearch = !searchText.value || 
+      inspection.inspectionNo.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      inspection.productName.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || inspection.typeId === filters.value.type
+    const matchesTimeRange = !filters.value.timeRange || checkTimeRange(inspection.date, filters.value.timeRange)
+    return matchesSearch && matchesType && matchesTimeRange
+  })
+})
+
+const filteredIssues = computed(() => {
+  return issues.value.filter(issue => {
+    const matchesSearch = !searchText.value || 
+      issue.issueNo.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      issue.description.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || issue.typeId === filters.value.type
+    const matchesStatus = !filters.value.status || issue.status === filters.value.status
+    const matchesTimeRange = !filters.value.timeRange || checkTimeRange(issue.date, filters.value.timeRange)
+    return matchesSearch && matchesType && matchesStatus && matchesTimeRange
+  })
+})
+
+const monthlyInspections = computed(() => {
+  return inspections.value.filter(inspection => {
+    const inspectionDate = new Date(inspection.date)
+    const now = new Date()
+    return inspectionDate.getMonth() === now.getMonth() && inspectionDate.getFullYear() === now.getFullYear()
+  }).length
+})
+
+const passRate = computed(() => {
+  const monthlyInspections = inspections.value.filter(inspection => {
+    const inspectionDate = new Date(inspection.date)
+    const now = new Date()
+    return inspectionDate.getMonth() === now.getMonth() && inspectionDate.getFullYear() === now.getFullYear()
+  })
+  if (monthlyInspections.length === 0) return 0
+  const passedInspections = monthlyInspections.filter(inspection => inspection.result === 1)
+  return Math.round((passedInspections.length / monthlyInspections.length) * 100)
+})
+
+const pendingIssues = computed(() => {
+  return issues.value.filter(issue => issue.status === 1).length
+})
+
+const averageResolutionTime = computed(() => {
+  const resolvedIssues = issues.value.filter(issue => issue.status === 3)
+  if (resolvedIssues.length === 0) return 0
+  const totalDays = resolvedIssues.reduce((sum, issue) => {
+    const reportDate = new Date(issue.date)
+    const resolveDate = new Date(issue.resolutionDate)
+    return sum + Math.ceil((resolveDate - reportDate) / (1000 * 60 * 60 * 24))
+  }, 0)
+  return Math.round(totalDays / resolvedIssues.length)
+})
+
+const resolvedIssues = computed(() => {
+  return issues.value.filter(issue => issue.status === 3).length
+})
+
+const resolutionRate = computed(() => {
+  if (issues.value.length === 0) return 0
+  const resolvedIssues = issues.value.filter(issue => issue.status === 3)
+  return Math.round((resolvedIssues.length / issues.value.length) * 100)
+})
+
+const qualityCost = computed(() => {
+  // 这里假设有一个计算质量成本的逻辑
+  return 50000
+})
+
+const costChange = computed(() => {
+  // 这里假设有一个计算环比变化的逻辑
+  return -5
+})
+
+// 检查时间范围
+const checkTimeRange = (date, rangeId) => {
+  const now = new Date()
+  const targetDate = new Date(date)
+  switch (rangeId) {
+    case 1: // 本周
+      const weekStart = new Date(now.setDate(now.getDate() - now.getDay()))
+      const weekEnd = new Date(now.setDate(now.getDate() - now.getDay() + 6))
+      return targetDate >= weekStart && targetDate <= weekEnd
+    case 2: // 本月
+      return targetDate.getMonth() === now.getMonth() && targetDate.getFullYear() === now.getFullYear()
+    case 3: // 本季度
+      const quarterStart = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3, 1)
+      const quarterEnd = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3 + 3, 0)
+      return targetDate >= quarterStart && targetDate <= quarterEnd
+    case 4: // 本年
+      return targetDate.getFullYear() === now.getFullYear()
+    default:
+      return true
+  }
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 格式化数字
+const formatNumber = (num) => {
+  return num.toLocaleString('zh-CN')
+}
+
+// 获取结果名称
+const getResultName = (resultId) => {
+  const result = resultTypes.value.find(r => r.id === resultId)
+  return result ? result.name : '未知结果'
+}
+
+// 获取结果样式
+const getResultClass = (resultId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+    3: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300'
+  }
+  return classes[resultId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = statusTypes.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    4: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加检验
+const addInspection = () => {
+  const type = inspectionTypes.value.find(t => t.id === newInspection.value.typeId)
+  const product = products.value.find(p => p.id === newInspection.value.productId)
+  const inspector = inspectors.value.find(i => i.id === newInspection.value.inspectorId)
+  const inspection = {
+    id: inspections.value.length + 1,
+    inspectionNo: `QI${new Date().getFullYear()}${String(inspections.value.length + 1).padStart(3, '0')}`,
+    typeId: newInspection.value.typeId,
+    typeName: type.name,
+    productId: newInspection.value.productId,
+    productName: product.name,
+    productCode: product.code,
+    batchNo: newInspection.value.batchNo,
+    date: newInspection.value.date,
+    result: newInspection.value.result,
+    defects: newInspection.value.defects,
+    inspectorId: newInspection.value.inspectorId,
+    inspector: inspector.name,
+    remark: newInspection.value.remark
+  }
+  inspections.value.push(inspection)
+  showAddInspectionModal.value = false
+  resetNewInspection()
+}
+
+// 重置新检验表单
+const resetNewInspection = () => {
+  newInspection.value = {
+    typeId: '',
+    productId: '',
+    batchNo: '',
+    date: '',
+    result: '',
+    defects: '',
+    inspectorId: '',
+    remark: ''
+  }
+}
+
+// 添加问题
+const addIssue = () => {
+  const type = issueTypes.value.find(t => t.id === newIssue.value.typeId)
+  const product = products.value.find(p => p.id === newIssue.value.productId)
+  const reporter = reporters.value.find(r => r.id === newIssue.value.reporterId)
+  const issue = {
+    id: issues.value.length + 1,
+    issueNo: `QN${new Date().getFullYear()}${String(issues.value.length + 1).padStart(3, '0')}`,
+    typeId: newIssue.value.typeId,
+    typeName: type.name,
+    productId: newIssue.value.productId,
+    productName: product.name,
+    productCode: product.code,
+    batchNo: newIssue.value.batchNo,
+    date: new Date().toISOString().split('T')[0],
+    description: newIssue.value.description,
+    severity: newIssue.value.severity,
+    status: 1,
+    reporterId: newIssue.value.reporterId,
+    reporter: reporter.name,
+    resolutionDate: null,
+    remark: newIssue.value.remark
+  }
+  issues.value.push(issue)
+  showAddIssueModal.value = false
+  resetNewIssue()
+}
+
+// 重置新问题表单
+const resetNewIssue = () => {
+  newIssue.value = {
+    typeId: '',
+    productId: '',
+    batchNo: '',
+    description: '',
+    severity: '',
+    reporterId: '',
+    remark: ''
+  }
+}
+
+// 查看检验
+const viewInspection = (inspection) => {
+  // 实现查看检验逻辑
+  console.log('查看检验:', inspection)
+}
+
+// 编辑检验
+const editInspection = (inspection) => {
+  // 实现编辑检验逻辑
+  console.log('编辑检验:', inspection)
+}
+
+// 删除检验
+const deleteInspection = (inspection) => {
+  if (confirm(`确定要删除检验记录"${inspection.inspectionNo}"吗?`)) {
+    const index = inspections.value.findIndex(i => i.id === inspection.id)
+    if (index !== -1) {
+      inspections.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看问题
+const viewIssue = (issue) => {
+  // 实现查看问题逻辑
+  console.log('查看问题:', issue)
+}
+
+// 编辑问题
+const editIssue = (issue) => {
+  // 实现编辑问题逻辑
+  console.log('编辑问题:', issue)
+}
+
+// 删除问题
+const deleteIssue = (issue) => {
+  if (confirm(`确定要删除问题记录"${issue.issueNo}"吗?`)) {
+    const index = issues.value.findIndex(i => i.id === issue.id)
+    if (index !== -1) {
+      issues.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 509 - 0
src/assets/templates/prototype/project/MeetingManagement.vue

@@ -0,0 +1,509 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">会议管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddMeetingModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              预约会议
+            </button>
+            <button @click="showAddRoomModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              添加会议室
+            </button>
+            <button @click="exportMeetingData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 会议统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">今日会议</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ todayMeetings }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">进行中</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ ongoingMeetings }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">待开始</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ upcomingMeetings }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">会议室数</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ totalRooms }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议室</label>
+            <select v-model="filters.room" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="room in meetingRooms" :key="room.id" :value="room.id">{{ room.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in meetingStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日期范围</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="会议主题/主持人" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 会议列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">会议信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">时间地点</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">参会人员</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="meeting in filteredMeetings" :key="meeting.id">
+              <td class="px-6 py-4">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ meeting.title }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">主持人: {{ meeting.host }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">类型: {{ getMeetingTypeName(meeting.type) }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ formatDate(meeting.date) }}</div>
+                <div class="text-sm text-gray-900 dark:text-white">{{ meeting.startTime }} - {{ meeting.endTime }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ getRoomName(meeting.roomId) }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">参会人数: {{ meeting.participants.length }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">已确认: {{ meeting.confirmedParticipants }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">待确认: {{ meeting.pendingParticipants }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(meeting.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(meeting.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewMeeting(meeting)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editMeeting(meeting)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="cancelMeeting(meeting)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">取消</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 预约会议模态框 -->
+    <div v-if="showAddMeetingModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">预约会议</h2>
+        <form @submit.prevent="addMeeting">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议主题</label>
+            <input type="text" v-model="newMeeting.title" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议类型</label>
+            <select v-model="newMeeting.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in meetingTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议室</label>
+            <select v-model="newMeeting.roomId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="room in availableRooms" :key="room.id" :value="room.id">{{ room.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日期</label>
+            <input type="date" v-model="newMeeting.date" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间</label>
+            <div class="flex space-x-2">
+              <input type="time" v-model="newMeeting.startTime" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="time" v-model="newMeeting.endTime" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">参会人员</label>
+            <select v-model="newMeeting.participants" multiple class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="user in users" :key="user.id" :value="user.id">{{ user.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议描述</label>
+            <textarea v-model="newMeeting.description" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddMeetingModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              预约
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 添加会议室模态框 -->
+    <div v-if="showAddRoomModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加会议室</h2>
+        <form @submit.prevent="addRoom">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会议室名称</label>
+            <input type="text" v-model="newRoom.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">位置</label>
+            <input type="text" v-model="newRoom.location" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">容量</label>
+            <input type="number" v-model="newRoom.capacity" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">设备</label>
+            <div class="space-y-2">
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="newRoom.equipment.projector" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">投影仪</span>
+              </label>
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="newRoom.equipment.whiteboard" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">白板</span>
+              </label>
+              <label class="inline-flex items-center">
+                <input type="checkbox" v-model="newRoom.equipment.videoConference" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">视频会议</span>
+              </label>
+            </div>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddRoomModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 会议数据
+const meetings = ref([
+  {
+    id: 1,
+    title: '项目进度汇报',
+    type: 1,
+    roomId: 1,
+    date: '2024-03-20',
+    startTime: '14:00',
+    endTime: '15:30',
+    host: '张三',
+    participants: [1, 2, 3],
+    confirmedParticipants: 2,
+    pendingParticipants: 1,
+    status: 1,
+    description: '汇报项目最新进展和下一步计划'
+  },
+  {
+    id: 2,
+    title: '技术方案讨论',
+    type: 2,
+    roomId: 2,
+    date: '2024-03-21',
+    startTime: '10:00',
+    endTime: '11:30',
+    host: '李四',
+    participants: [2, 3, 4],
+    confirmedParticipants: 1,
+    pendingParticipants: 2,
+    status: 2,
+    description: '讨论系统架构和技术选型'
+  }
+])
+
+// 会议室数据
+const meetingRooms = ref([
+  {
+    id: 1,
+    name: '会议室A',
+    location: '3楼',
+    capacity: 10,
+    equipment: {
+      projector: true,
+      whiteboard: true,
+      videoConference: false
+    }
+  },
+  {
+    id: 2,
+    name: '会议室B',
+    location: '4楼',
+    capacity: 20,
+    equipment: {
+      projector: true,
+      whiteboard: true,
+      videoConference: true
+    }
+  }
+])
+
+// 会议类型
+const meetingTypes = [
+  { id: 1, name: '项目会议' },
+  { id: 2, name: '技术会议' },
+  { id: 3, name: '部门会议' },
+  { id: 4, name: '客户会议' },
+  { id: 5, name: '其他会议' }
+]
+
+// 会议状态
+const meetingStatuses = [
+  { id: 1, name: '待开始' },
+  { id: 2, name: '进行中' },
+  { id: 3, name: '已结束' },
+  { id: 4, name: '已取消' }
+]
+
+// 用户列表
+const users = [
+  { id: 1, name: '张三' },
+  { id: 2, name: '李四' },
+  { id: 3, name: '王五' },
+  { id: 4, name: '赵六' }
+]
+
+// 筛选条件
+const filters = ref({
+  room: '',
+  status: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddMeetingModal = ref(false)
+const showAddRoomModal = ref(false)
+
+// 新会议表单
+const newMeeting = ref({
+  title: '',
+  type: '',
+  roomId: '',
+  date: '',
+  startTime: '',
+  endTime: '',
+  participants: [],
+  description: ''
+})
+
+// 新会议室表单
+const newRoom = ref({
+  name: '',
+  location: '',
+  capacity: '',
+  equipment: {
+    projector: false,
+    whiteboard: false,
+    videoConference: false
+  }
+})
+
+// 计算属性
+const filteredMeetings = computed(() => {
+  return meetings.value.filter(meeting => {
+    const matchesRoom = !filters.value.room || meeting.roomId === filters.value.room
+    const matchesStatus = !filters.value.status || meeting.status === filters.value.status
+    const matchesDate = (!filters.value.startDate || meeting.date >= filters.value.startDate) &&
+                       (!filters.value.endDate || meeting.date <= filters.value.endDate)
+    const matchesSearch = !filters.value.search ||
+      meeting.title.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      meeting.host.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesRoom && matchesStatus && matchesDate && matchesSearch
+  })
+})
+
+const todayMeetings = computed(() => {
+  const today = new Date().toISOString().split('T')[0]
+  return meetings.value.filter(meeting => meeting.date === today).length
+})
+
+const ongoingMeetings = computed(() => {
+  return meetings.value.filter(meeting => meeting.status === 2).length
+})
+
+const upcomingMeetings = computed(() => {
+  return meetings.value.filter(meeting => meeting.status === 1).length
+})
+
+const totalRooms = computed(() => {
+  return meetingRooms.value.length
+})
+
+const availableRooms = computed(() => {
+  return meetingRooms.value.filter(room => {
+    const isAvailable = !meetings.value.some(meeting => 
+      meeting.roomId === room.id && 
+      meeting.date === newMeeting.value.date &&
+      (
+        (newMeeting.value.startTime >= meeting.startTime && newMeeting.value.startTime < meeting.endTime) ||
+        (newMeeting.value.endTime > meeting.startTime && newMeeting.value.endTime <= meeting.endTime)
+      )
+    )
+    return isAvailable
+  })
+})
+
+// 获取会议类型名称
+const getMeetingTypeName = (typeId) => {
+  const type = meetingTypes.find(t => t.id === typeId)
+  return type ? type.name : '未知类型'
+}
+
+// 获取会议室名称
+const getRoomName = (roomId) => {
+  const room = meetingRooms.value.find(r => r.id === roomId)
+  return room ? `${room.name} (${room.location})` : '未知会议室'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = meetingStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    2: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    3: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 添加会议
+const addMeeting = () => {
+  const meeting = {
+    id: meetings.value.length + 1,
+    status: 1, // 默认待开始
+    confirmedParticipants: 0,
+    pendingParticipants: newMeeting.value.participants.length,
+    ...newMeeting.value
+  }
+  
+  meetings.value.push(meeting)
+  showAddMeetingModal.value = false
+  resetNewMeeting()
+}
+
+// 添加会议室
+const addRoom = () => {
+  const room = {
+    id: meetingRooms.value.length + 1,
+    ...newRoom.value
+  }
+  
+  meetingRooms.value.push(room)
+  showAddRoomModal.value = false
+  resetNewRoom()
+}
+
+// 重置新会议表单
+const resetNewMeeting = () => {
+  newMeeting.value = {
+    title: '',
+    type: '',
+    roomId: '',
+    date: '',
+    startTime: '',
+    endTime: '',
+    participants: [],
+    description: ''
+  }
+}
+
+// 重置新会议室表单
+const resetNewRoom = () => {
+  newRoom.value = {
+    name: '',
+    location: '',
+    capacity: '',
+    equipment: {
+      projector: false,
+      whiteboard: false,
+      videoConference: false
+    }
+  }
+}
+
+// 查看会议
+const viewMeeting = (meeting) => {
+  // 实现查看会议的逻辑
+  console.log('查看会议:', meeting)
+}
+
+// 编辑会议
+const editMeeting = (meeting) => {
+  // 实现编辑会议的逻辑
+  console.log('编辑会议:', meeting)
+}
+
+// 取消会议
+const cancelMeeting = (meeting) => {
+  if (confirm(`确定要取消会议 ${meeting.title} 吗?`)) {
+    const index = meetings.value.findIndex(m => m.id === meeting.id)
+    if (index !== -1) {
+      meetings.value[index].status = 4 // 设置为已取消
+    }
+  }
+}
+
+// 导出会议数据
+const exportMeetingData = () => {
+  // 实现导出会议数据的逻辑
+  console.log('导出会议数据')
+}
+</script> 

+ 362 - 0
src/assets/templates/prototype/project/ProjectManagement.vue

@@ -0,0 +1,362 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">项目管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddProjectModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建项目
+            </button>
+            <button @click="exportProjectData" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 项目统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">进行中</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ activeProjects }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">已完成</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ completedProjects }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">延期</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ delayedProjects }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">平均进度</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ averageProgress }}%</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in projectStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">优先级</label>
+            <select v-model="filters.priority" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">负责人</label>
+            <select v-model="filters.owner" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="owner in owners" :key="owner.id" :value="owner.id">{{ owner.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="项目名称/描述" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 项目列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">项目信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">进度</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">优先级</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="project in filteredProjects" :key="project.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ project.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ project.description }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">负责人: {{ getOwnerName(project.ownerId) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
+                  <div class="bg-blue-600 h-2.5 rounded-full" :style="{ width: project.progress + '%' }"></div>
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ project.progress }}%</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getPriorityClass(project.priority)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getPriorityName(project.priority) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(project.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(project.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewProject(project)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editProject(project)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteProject(project)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建项目模态框 -->
+    <div v-if="showAddProjectModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建项目</h2>
+        <form @submit.prevent="addProject">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目名称</label>
+            <input type="text" v-model="newProject.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目描述</label>
+            <textarea v-model="newProject.description" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">负责人</label>
+            <select v-model="newProject.ownerId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="owner in owners" :key="owner.id" :value="owner.id">{{ owner.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">优先级</label>
+            <select v-model="newProject.priority" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+            <input type="date" v-model="newProject.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+            <input type="date" v-model="newProject.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddProjectModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 项目数据
+const projects = ref([
+  {
+    id: 1,
+    name: '电商平台开发',
+    description: '开发新一代电商平台,支持多商家入驻',
+    ownerId: 1,
+    priority: 2,
+    status: 1,
+    progress: 65,
+    startDate: '2024-01-01',
+    endDate: '2024-06-30'
+  },
+  {
+    id: 2,
+    name: '移动应用开发',
+    description: '开发配套移动应用,支持iOS和Android平台',
+    ownerId: 2,
+    priority: 1,
+    status: 2,
+    progress: 30,
+    startDate: '2024-02-01',
+    endDate: '2024-07-31'
+  }
+])
+
+// 项目状态
+const projectStatuses = [
+  { id: 1, name: '进行中' },
+  { id: 2, name: '已完成' },
+  { id: 3, name: '已延期' },
+  { id: 4, name: '已取消' }
+]
+
+// 优先级
+const priorities = [
+  { id: 1, name: '低' },
+  { id: 2, name: '中' },
+  { id: 3, name: '高' },
+  { id: 4, name: '紧急' }
+]
+
+// 负责人
+const owners = [
+  { id: 1, name: '张三' },
+  { id: 2, name: '李四' },
+  { id: 3, name: '王五' }
+]
+
+// 筛选条件
+const filters = ref({
+  status: '',
+  priority: '',
+  owner: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddProjectModal = ref(false)
+
+// 新项目表单
+const newProject = ref({
+  name: '',
+  description: '',
+  ownerId: '',
+  priority: '',
+  startDate: '',
+  endDate: ''
+})
+
+// 计算属性
+const filteredProjects = computed(() => {
+  return projects.value.filter(project => {
+    const matchesStatus = !filters.value.status || project.status === filters.value.status
+    const matchesPriority = !filters.value.priority || project.priority === filters.value.priority
+    const matchesOwner = !filters.value.owner || project.ownerId === filters.value.owner
+    const matchesSearch = !filters.value.search ||
+      project.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      project.description.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesStatus && matchesPriority && matchesOwner && matchesSearch
+  })
+})
+
+const activeProjects = computed(() => {
+  return projects.value.filter(project => project.status === 1).length
+})
+
+const completedProjects = computed(() => {
+  return projects.value.filter(project => project.status === 2).length
+})
+
+const delayedProjects = computed(() => {
+  return projects.value.filter(project => project.status === 3).length
+})
+
+const averageProgress = computed(() => {
+  if (projects.value.length === 0) return 0
+  const total = projects.value.reduce((sum, project) => sum + project.progress, 0)
+  return Math.round(total / projects.value.length)
+})
+
+// 获取负责人名称
+const getOwnerName = (ownerId) => {
+  const owner = owners.find(o => o.id === ownerId)
+  return owner ? owner.name : '未知'
+}
+
+// 获取优先级名称
+const getPriorityName = (priorityId) => {
+  const priority = priorities.find(p => p.id === priorityId)
+  return priority ? priority.name : '未知'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = projectStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取优先级样式
+const getPriorityClass = (priorityId) => {
+  const classes = {
+    1: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[priorityId] || classes[1]
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    2: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+    4: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 添加项目
+const addProject = () => {
+  const project = {
+    id: projects.value.length + 1,
+    ...newProject.value,
+    status: 1,
+    progress: 0
+  }
+  projects.value.push(project)
+  showAddProjectModal.value = false
+  resetNewProject()
+}
+
+// 重置新项目表单
+const resetNewProject = () => {
+  newProject.value = {
+    name: '',
+    description: '',
+    ownerId: '',
+    priority: '',
+    startDate: '',
+    endDate: ''
+  }
+}
+
+// 查看项目
+const viewProject = (project) => {
+  // 实现查看项目逻辑
+  console.log('查看项目:', project)
+}
+
+// 编辑项目
+const editProject = (project) => {
+  // 实现编辑项目逻辑
+  console.log('编辑项目:', project)
+}
+
+// 删除项目
+const deleteProject = (project) => {
+  if (confirm(`确定要删除项目 ${project.name} 吗?`)) {
+    const index = projects.value.findIndex(p => p.id === project.id)
+    if (index !== -1) {
+      projects.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出项目数据
+const exportProjectData = () => {
+  // 实现导出项目数据的逻辑
+  console.log('导出项目数据')
+}
+</script> 

+ 477 - 0
src/assets/templates/prototype/project/TaskManagement.vue

@@ -0,0 +1,477 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">任务管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddTaskModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建任务
+            </button>
+            <button @click="showAddProjectModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              创建项目
+            </button>
+            <button @click="exportTaskData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 任务统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">待处理</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ pendingTasks }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">进行中</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ inProgressTasks }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">已完成</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ completedTasks }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">逾期</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ overdueTasks }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目</label>
+            <select v-model="filters.project" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="project in projects" :key="project.id" :value="project.id">{{ project.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in taskStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">优先级</label>
+            <select v-model="filters.priority" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="任务名称/负责人" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 任务列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">任务信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">项目信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">进度</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="task in filteredTasks" :key="task.id">
+              <td class="px-6 py-4">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ task.title }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">负责人: {{ getAssigneeName(task.assignee) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">截止日期: {{ formatDate(task.dueDate) }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getProjectName(task.projectId) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">里程碑: {{ task.milestone }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
+                  <div class="bg-blue-600 h-2.5 rounded-full" :style="{ width: task.progress + '%' }"></div>
+                </div>
+                <div class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ task.progress }}%</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(task.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(task.status) }}
+                </span>
+                <span :class="getPriorityClass(task.priority)" class="ml-2 px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getPriorityName(task.priority) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewTask(task)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editTask(task)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteTask(task)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建任务模态框 -->
+    <div v-if="showAddTaskModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建任务</h2>
+        <form @submit.prevent="addTask">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">任务名称</label>
+            <input type="text" v-model="newTask.title" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">所属项目</label>
+            <select v-model="newTask.projectId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="project in projects" :key="project.id" :value="project.id">{{ project.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">负责人</label>
+            <select v-model="newTask.assignee" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="user in users" :key="user.id" :value="user.id">{{ user.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">优先级</label>
+            <select v-model="newTask.priority" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">截止日期</label>
+            <input type="date" v-model="newTask.dueDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">任务描述</label>
+            <textarea v-model="newTask.description" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddTaskModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 创建项目模态框 -->
+    <div v-if="showAddProjectModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建项目</h2>
+        <form @submit.prevent="addProject">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目名称</label>
+            <input type="text" v-model="newProject.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目负责人</label>
+            <select v-model="newProject.manager" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="user in users" :key="user.id" :value="user.id">{{ user.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+            <input type="date" v-model="newProject.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+            <input type="date" v-model="newProject.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">项目描述</label>
+            <textarea v-model="newProject.description" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" rows="4"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddProjectModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 任务数据
+const tasks = ref([
+  {
+    id: 1,
+    title: '需求分析文档编写',
+    projectId: 1,
+    assignee: 1,
+    priority: 1,
+    dueDate: '2024-03-25',
+    progress: 60,
+    status: 2,
+    milestone: '需求分析阶段',
+    description: '完成系统需求分析文档的编写和评审'
+  },
+  {
+    id: 2,
+    title: '数据库设计',
+    projectId: 1,
+    assignee: 2,
+    priority: 2,
+    dueDate: '2024-03-28',
+    progress: 30,
+    status: 1,
+    milestone: '设计阶段',
+    description: '完成数据库表结构设计和ER图'
+  }
+])
+
+// 项目数据
+const projects = ref([
+  {
+    id: 1,
+    name: '客户管理系统',
+    manager: 1,
+    startDate: '2024-03-01',
+    endDate: '2024-06-30',
+    description: '开发新一代客户关系管理系统'
+  },
+  {
+    id: 2,
+    name: '数据分析平台',
+    manager: 2,
+    startDate: '2024-04-01',
+    endDate: '2024-08-31',
+    description: '构建企业级数据分析平台'
+  }
+])
+
+// 任务状态
+const taskStatuses = [
+  { id: 1, name: '待处理' },
+  { id: 2, name: '进行中' },
+  { id: 3, name: '已完成' },
+  { id: 4, name: '已取消' }
+]
+
+// 优先级
+const priorities = [
+  { id: 1, name: '高' },
+  { id: 2, name: '中' },
+  { id: 3, name: '低' }
+]
+
+// 用户列表
+const users = [
+  { id: 1, name: '张三' },
+  { id: 2, name: '李四' },
+  { id: 3, name: '王五' },
+  { id: 4, name: '赵六' }
+]
+
+// 筛选条件
+const filters = ref({
+  project: '',
+  status: '',
+  priority: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddTaskModal = ref(false)
+const showAddProjectModal = ref(false)
+
+// 新任务表单
+const newTask = ref({
+  title: '',
+  projectId: '',
+  assignee: '',
+  priority: '',
+  dueDate: '',
+  progress: 0,
+  status: 1,
+  description: ''
+})
+
+// 新项目表单
+const newProject = ref({
+  name: '',
+  manager: '',
+  startDate: '',
+  endDate: '',
+  description: ''
+})
+
+// 计算属性
+const filteredTasks = computed(() => {
+  return tasks.value.filter(task => {
+    const matchesProject = !filters.value.project || task.projectId === filters.value.project
+    const matchesStatus = !filters.value.status || task.status === filters.value.status
+    const matchesPriority = !filters.value.priority || task.priority === filters.value.priority
+    const matchesSearch = !filters.value.search ||
+      task.title.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      getAssigneeName(task.assignee).toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesProject && matchesStatus && matchesPriority && matchesSearch
+  })
+})
+
+const pendingTasks = computed(() => {
+  return tasks.value.filter(task => task.status === 1).length
+})
+
+const inProgressTasks = computed(() => {
+  return tasks.value.filter(task => task.status === 2).length
+})
+
+const completedTasks = computed(() => {
+  return tasks.value.filter(task => task.status === 3).length
+})
+
+const overdueTasks = computed(() => {
+  const today = new Date().toISOString().split('T')[0]
+  return tasks.value.filter(task => task.status !== 3 && task.dueDate < today).length
+})
+
+// 获取项目名称
+const getProjectName = (projectId) => {
+  const project = projects.value.find(p => p.id === projectId)
+  return project ? project.name : '未知项目'
+}
+
+// 获取负责人名称
+const getAssigneeName = (assigneeId) => {
+  const user = users.find(u => u.id === assigneeId)
+  return user ? user.name : '未知'
+}
+
+// 获取状态名称
+const getStatusName = (statusId) => {
+  const status = taskStatuses.find(s => s.id === statusId)
+  return status ? status.name : '未知'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    2: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    3: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || classes[1]
+}
+
+// 获取优先级名称
+const getPriorityName = (priorityId) => {
+  const priority = priorities.find(p => p.id === priorityId)
+  return priority ? priority.name : '未知'
+}
+
+// 获取优先级样式
+const getPriorityClass = (priorityId) => {
+  const classes = {
+    1: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300'
+  }
+  return classes[priorityId] || classes[3]
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 添加任务
+const addTask = () => {
+  const task = {
+    id: tasks.value.length + 1,
+    progress: 0,
+    status: 1,
+    ...newTask.value
+  }
+  
+  tasks.value.push(task)
+  showAddTaskModal.value = false
+  resetNewTask()
+}
+
+// 添加项目
+const addProject = () => {
+  const project = {
+    id: projects.value.length + 1,
+    ...newProject.value
+  }
+  
+  projects.value.push(project)
+  showAddProjectModal.value = false
+  resetNewProject()
+}
+
+// 重置新任务表单
+const resetNewTask = () => {
+  newTask.value = {
+    title: '',
+    projectId: '',
+    assignee: '',
+    priority: '',
+    dueDate: '',
+    progress: 0,
+    status: 1,
+    description: ''
+  }
+}
+
+// 重置新项目表单
+const resetNewProject = () => {
+  newProject.value = {
+    name: '',
+    manager: '',
+    startDate: '',
+    endDate: '',
+    description: ''
+  }
+}
+
+// 查看任务
+const viewTask = (task) => {
+  // 实现查看任务的逻辑
+  console.log('查看任务:', task)
+}
+
+// 编辑任务
+const editTask = (task) => {
+  // 实现编辑任务的逻辑
+  console.log('编辑任务:', task)
+}
+
+// 删除任务
+const deleteTask = (task) => {
+  if (confirm(`确定要删除任务 ${task.title} 吗?`)) {
+    const index = tasks.value.findIndex(t => t.id === task.id)
+    if (index !== -1) {
+      tasks.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出任务数据
+const exportTaskData = () => {
+  // 实现导出任务数据的逻辑
+  console.log('导出任务数据')
+}
+</script> 

+ 546 - 0
src/assets/templates/prototype/sales/ContractManagement.vue

@@ -0,0 +1,546 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">合同管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddContractModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增合同
+            </button>
+            <button @click="showApprovalModal = true" class="bg-yellow-600 text-white px-4 py-2 rounded-md hover:bg-yellow-700">
+              合同审批
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 合同统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">总合同数</div>
+          <div class="mt-2 text-3xl font-bold text-gray-900 dark:text-white">{{ totalContracts }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">待审批</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ pendingApproval }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">即将到期</div>
+          <div class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ expiringSoon }}</div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">已到期</div>
+          <div class="mt-2 text-3xl font-bold text-gray-600 dark:text-gray-400">{{ expired }}</div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="合同编号/名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合同类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有类型</option>
+              <option v-for="type in contractTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in contractStatus" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="filters.department" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有部门</option>
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 合同列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">合同信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">金额</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="contract in filteredContracts" :key="contract.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ contract.contractNumber }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ contract.name }}</div>
+                <div class="text-xs text-gray-500 dark:text-gray-400">
+                  有效期: {{ formatDate(contract.startDate) }} - {{ formatDate(contract.endDate) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getContractTypeName(contract.type) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">¥{{ contract.amount }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(contract.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(contract.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewContract(contract)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editContract(contract)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteContract(contract)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 审批记录列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">审批信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">合同</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">审批人</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="approval in filteredApprovals" :key="approval.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ approval.approvalNumber }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">
+                  {{ formatDate(approval.date) }}
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getContractName(approval.contractId) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ approval.approver }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getApprovalStatusClass(approval.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getApprovalStatusName(approval.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewApproval(approval)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editApproval(approval)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteApproval(approval)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增合同模态框 -->
+    <div v-if="showAddContractModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增合同</h2>
+        <form @submit.prevent="addContract">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合同编号</label>
+            <input type="text" v-model="newContract.contractNumber" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合同名称</label>
+            <input type="text" v-model="newContract.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合同类型</label>
+            <select v-model="newContract.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in contractTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合同金额</label>
+            <input type="number" v-model="newContract.amount" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+            <input type="date" v-model="newContract.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+            <input type="date" v-model="newContract.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="newContract.department" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newContract.remarks" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddContractModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 合同审批模态框 -->
+    <div v-if="showApprovalModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">合同审批</h2>
+        <form @submit.prevent="addApproval">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">审批编号</label>
+            <input type="text" v-model="newApproval.approvalNumber" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合同</label>
+            <select v-model="newApproval.contractId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="contract in contractList" :key="contract.id" :value="contract.id">{{ contract.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">审批人</label>
+            <input type="text" v-model="newApproval.approver" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">审批意见</label>
+            <textarea v-model="newApproval.comments" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showApprovalModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-yellow-600 text-white rounded-md hover:bg-yellow-700">
+              提交
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 合同数据
+const contractList = ref([
+  {
+    id: 1,
+    contractNumber: 'CT202403150001',
+    name: '办公用品采购合同',
+    type: 1,
+    amount: 50000,
+    startDate: '2024-03-15',
+    endDate: '2025-03-14',
+    department: 1,
+    status: 1,
+    remarks: '正常执行中'
+  },
+  {
+    id: 2,
+    contractNumber: 'CT202403150002',
+    name: '设备维护服务合同',
+    type: 2,
+    amount: 30000,
+    startDate: '2024-03-15',
+    endDate: '2024-09-14',
+    department: 2,
+    status: 2,
+    remarks: '待审批'
+  }
+])
+
+// 审批记录数据
+const approvalRecords = ref([
+  {
+    id: 1,
+    approvalNumber: 'AP202403150001',
+    contractId: 1,
+    approver: '张三',
+    date: '2024-03-15',
+    status: 1,
+    comments: '同意'
+  },
+  {
+    id: 2,
+    approvalNumber: 'AP202403150002',
+    contractId: 2,
+    approver: '李四',
+    date: '2024-03-15',
+    status: 2,
+    comments: '待审核'
+  }
+])
+
+// 合同类型
+const contractTypes = ref([
+  { id: 1, name: '采购合同' },
+  { id: 2, name: '服务合同' },
+  { id: 3, name: '租赁合同' }
+])
+
+// 合同状态
+const contractStatus = ref([
+  { id: 1, name: '执行中' },
+  { id: 2, name: '待审批' },
+  { id: 3, name: '已到期' }
+])
+
+// 审批状态
+const approvalStatus = ref([
+  { id: 1, name: '已通过' },
+  { id: 2, name: '待审核' },
+  { id: 3, name: '已拒绝' }
+])
+
+// 部门
+const departments = ref([
+  { id: 1, name: '行政部' },
+  { id: 2, name: '生产部' },
+  { id: 3, name: '销售部' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  type: '',
+  status: '',
+  department: ''
+})
+
+// 模态框状态
+const showAddContractModal = ref(false)
+const showApprovalModal = ref(false)
+
+// 新合同表单
+const newContract = ref({
+  contractNumber: '',
+  name: '',
+  type: '',
+  amount: '',
+  startDate: '',
+  endDate: '',
+  department: '',
+  remarks: ''
+})
+
+// 新审批记录表单
+const newApproval = ref({
+  approvalNumber: '',
+  contractId: '',
+  approver: '',
+  comments: ''
+})
+
+// 计算属性
+const filteredContracts = computed(() => {
+  return contractList.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.contractNumber.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.name.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !filters.value.type || item.type === filters.value.type
+    const matchesStatus = !filters.value.status || item.status === filters.value.status
+    const matchesDepartment = !filters.value.department || item.department === filters.value.department
+    return matchesSearch && matchesType && matchesStatus && matchesDepartment
+  })
+})
+
+const filteredApprovals = computed(() => {
+  return approvalRecords.value.filter(item => {
+    const contract = contractList.value.find(c => c.id === item.contractId)
+    const matchesSearch = !searchText.value || 
+      item.approvalNumber.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      (contract && contract.name.toLowerCase().includes(searchText.value.toLowerCase()))
+    return matchesSearch
+  })
+})
+
+const totalContracts = computed(() => contractList.value.length)
+const pendingApproval = computed(() => contractList.value.filter(item => item.status === 2).length)
+const expiringSoon = computed(() => {
+  const today = new Date()
+  const thirtyDaysLater = new Date(today)
+  thirtyDaysLater.setDate(today.getDate() + 30)
+  return contractList.value.filter(item => {
+    const endDate = new Date(item.endDate)
+    return endDate > today && endDate <= thirtyDaysLater
+  }).length
+})
+const expired = computed(() => {
+  const today = new Date()
+  return contractList.value.filter(item => new Date(item.endDate) < today).length
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取合同类型名称
+const getContractTypeName = (typeId) => {
+  const type = contractTypes.value.find(t => t.id === typeId)
+  return type ? type.name : '未知类型'
+}
+
+// 获取合同状态名称
+const getStatusName = (statusId) => {
+  const status = contractStatus.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取审批状态名称
+const getApprovalStatusName = (statusId) => {
+  const status = approvalStatus.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取部门名称
+const getDepartmentName = (departmentId) => {
+  const department = departments.value.find(d => d.id === departmentId)
+  return department ? department.name : '未知部门'
+}
+
+// 获取合同名称
+const getContractName = (contractId) => {
+  const contract = contractList.value.find(c => c.id === contractId)
+  return contract ? contract.name : '未知合同'
+}
+
+// 获取状态样式
+const getStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 获取审批状态样式
+const getApprovalStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加合同
+const addContract = () => {
+  const item = {
+    id: contractList.value.length + 1,
+    ...newContract.value,
+    status: 2 // 默认为待审批状态
+  }
+  contractList.value.push(item)
+  showAddContractModal.value = false
+  resetNewContract()
+}
+
+// 重置新合同表单
+const resetNewContract = () => {
+  newContract.value = {
+    contractNumber: '',
+    name: '',
+    type: '',
+    amount: '',
+    startDate: '',
+    endDate: '',
+    department: '',
+    remarks: ''
+  }
+}
+
+// 添加审批记录
+const addApproval = () => {
+  const item = {
+    id: approvalRecords.value.length + 1,
+    ...newApproval.value,
+    date: new Date().toISOString().split('T')[0],
+    status: 2 // 默认为待审核状态
+  }
+  approvalRecords.value.push(item)
+  showApprovalModal.value = false
+  resetNewApproval()
+}
+
+// 重置新审批记录表单
+const resetNewApproval = () => {
+  newApproval.value = {
+    approvalNumber: '',
+    contractId: '',
+    approver: '',
+    comments: ''
+  }
+}
+
+// 查看合同
+const viewContract = (item) => {
+  // 实现查看合同逻辑
+  console.log('查看合同:', item)
+}
+
+// 编辑合同
+const editContract = (item) => {
+  // 实现编辑合同逻辑
+  console.log('编辑合同:', item)
+}
+
+// 删除合同
+const deleteContract = (item) => {
+  if (confirm(`确定要删除合同 ${item.contractNumber} 吗?`)) {
+    const index = contractList.value.findIndex(c => c.id === item.id)
+    if (index !== -1) {
+      contractList.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看审批记录
+const viewApproval = (item) => {
+  // 实现查看审批记录逻辑
+  console.log('查看审批记录:', item)
+}
+
+// 编辑审批记录
+const editApproval = (item) => {
+  // 实现编辑审批记录逻辑
+  console.log('编辑审批记录:', item)
+}
+
+// 删除审批记录
+const deleteApproval = (item) => {
+  if (confirm(`确定要删除审批记录 ${item.approvalNumber} 吗?`)) {
+    const index = approvalRecords.value.findIndex(a => a.id === item.id)
+    if (index !== -1) {
+      approvalRecords.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 314 - 0
src/assets/templates/prototype/sales/ReportManagement.vue

@@ -0,0 +1,314 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">报表管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showGenerateReportModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              生成报表
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 报表统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总报表数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalReports }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">今日生成</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ todayReports }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">待审核</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ pendingReports }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">已归档</h3>
+          <p class="mt-2 text-3xl font-bold text-gray-600 dark:text-gray-400">{{ archivedReports }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">报表类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="type in reportTypes" :key="type.value" :value="type.value">{{ type.label }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">报表状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="status in statusTypes" :key="status.value" :value="status.value">{{ status.label }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="range in timeRanges" :key="range.value" :value="range.value">{{ range.label }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="报表名称/编号" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 报表列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">报表编号</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">报表名称</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">报表类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">生成时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="report in filteredReports" :key="report.id">
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{ report.number }}</td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{ report.name }}</td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{ report.type }}</td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">{{ formatDate(report.createdAt) }}</td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(report.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ report.status }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                <button @click="viewReport(report)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="exportReport(report)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">导出</button>
+                <button @click="deleteReport(report)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 生成报表模态框 -->
+    <div v-if="showGenerateReportModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">生成报表</h2>
+        <form @submit.prevent="generateReport">
+          <div class="grid grid-cols-2 gap-4 mb-4">
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">报表类型</label>
+              <select v-model="reportForm.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <option v-for="type in reportTypes" :key="type.value" :value="type.value">{{ type.label }}</option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">报表名称</label>
+              <input type="text" v-model="reportForm.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">开始日期</label>
+              <input type="date" v-model="reportForm.startDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">结束日期</label>
+              <input type="date" v-model="reportForm.endDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">报表说明</label>
+            <textarea v-model="reportForm.description" rows="4" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showGenerateReportModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              生成
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 报表类型和状态选项
+const reportTypes = [
+  { value: 'sales', label: '销售报表' },
+  { value: 'inventory', label: '库存报表' },
+  { value: 'financial', label: '财务报表' },
+  { value: 'hr', label: '人事报表' }
+]
+
+const statusTypes = [
+  { value: 'pending', label: '待审核' },
+  { value: 'approved', label: '已审核' },
+  { value: 'archived', label: '已归档' }
+]
+
+const timeRanges = [
+  { value: 'today', label: '今日' },
+  { value: 'week', label: '本周' },
+  { value: 'month', label: '本月' },
+  { value: 'year', label: '本年' }
+]
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  status: '',
+  timeRange: '',
+  search: ''
+})
+
+// 报表列表数据
+const reports = ref([
+  {
+    id: 1,
+    number: 'RPT-2024-001',
+    name: '2024年第一季度销售报表',
+    type: 'sales',
+    createdAt: '2024-03-31',
+    status: 'approved',
+    description: '第一季度销售数据分析报告'
+  },
+  {
+    id: 2,
+    number: 'RPT-2024-002',
+    name: '2024年3月库存报表',
+    type: 'inventory',
+    createdAt: '2024-03-31',
+    status: 'pending',
+    description: '3月份库存盘点报告'
+  }
+])
+
+// 模态框状态
+const showGenerateReportModal = ref(false)
+
+// 报表表单
+const reportForm = ref({
+  type: '',
+  name: '',
+  startDate: '',
+  endDate: '',
+  description: ''
+})
+
+// 计算属性
+const totalReports = computed(() => reports.value.length)
+const todayReports = computed(() => reports.value.filter(r => r.createdAt === new Date().toISOString().split('T')[0]).length)
+const pendingReports = computed(() => reports.value.filter(r => r.status === 'pending').length)
+const archivedReports = computed(() => reports.value.filter(r => r.status === 'archived').length)
+
+// 过滤后的报表列表
+const filteredReports = computed(() => {
+  return reports.value.filter(report => {
+    const matchesType = !filters.value.type || report.type === filters.value.type
+    const matchesStatus = !filters.value.status || report.status === filters.value.status
+    const matchesTimeRange = !filters.value.timeRange || checkTimeRange(report.createdAt, filters.value.timeRange)
+    const matchesSearch = !filters.value.search ||
+                         report.number.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+                         report.name.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesStatus && matchesTimeRange && matchesSearch
+  })
+})
+
+// 检查时间范围
+const checkTimeRange = (date, range) => {
+  const today = new Date()
+  const reportDate = new Date(date)
+  
+  switch (range) {
+    case 'today':
+      return reportDate.toDateString() === today.toDateString()
+    case 'week':
+      const weekStart = new Date(today.setDate(today.getDate() - today.getDay()))
+      const weekEnd = new Date(today.setDate(today.getDate() - today.getDay() + 6))
+      return reportDate >= weekStart && reportDate <= weekEnd
+    case 'month':
+      return reportDate.getMonth() === today.getMonth() && reportDate.getFullYear() === today.getFullYear()
+    case 'year':
+      return reportDate.getFullYear() === today.getFullYear()
+    default:
+      return true
+  }
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    pending: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    approved: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    archived: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[status] || classes.pending
+}
+
+// 查看报表
+const viewReport = (report) => {
+  // 实现查看报表逻辑
+  console.log('查看报表:', report)
+}
+
+// 导出报表
+const exportReport = (report) => {
+  // 实现导出报表逻辑
+  console.log('导出报表:', report)
+}
+
+// 删除报表
+const deleteReport = (report) => {
+  if (confirm('确定要删除该报表吗?')) {
+    reports.value = reports.value.filter(r => r.id !== report.id)
+  }
+}
+
+// 生成报表
+const generateReport = () => {
+  const newReport = {
+    id: reports.value.length + 1,
+    number: `RPT-${new Date().getFullYear()}-${String(reports.value.length + 1).padStart(3, '0')}`,
+    name: reportForm.value.name,
+    type: reportForm.value.type,
+    createdAt: new Date().toISOString().split('T')[0],
+    status: 'pending',
+    description: reportForm.value.description
+  }
+  reports.value.push(newReport)
+  showGenerateReportModal.value = false
+  resetForm()
+}
+
+// 重置表单
+const resetForm = () => {
+  reportForm.value = {
+    type: '',
+    name: '',
+    startDate: '',
+    endDate: '',
+    description: ''
+  }
+}
+</script> 

+ 398 - 0
src/assets/templates/prototype/sales/SalesManagement.vue

@@ -0,0 +1,398 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">销售管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddOrderModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增订单
+            </button>
+            <button @click="exportSalesData" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 销售统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">本月销售额</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">¥{{ formatNumber(currentMonthSales) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            环比增长 <span :class="salesGrowth >= 0 ? 'text-green-600' : 'text-red-600'">{{ salesGrowth }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">订单数量</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ totalOrders }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            完成率 <span class="text-green-600">{{ completionRate }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">平均客单价</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">¥{{ formatNumber(averageOrderValue) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            同比增长 <span :class="avgOrderValueGrowth >= 0 ? 'text-green-600' : 'text-red-600'">{{ avgOrderValueGrowth }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">销售预测</div>
+          <div class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">¥{{ formatNumber(salesForecast) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            预计完成率 <span class="text-green-600">{{ forecastCompletionRate }}%</span>
+          </div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="订单号/客户名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in orderStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有时间</option>
+              <option v-for="range in timeRanges" :key="range.id" :value="range.id">{{ range.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">销售员</label>
+            <select v-model="filters.salesperson" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有销售员</option>
+              <option v-for="person in salespersons" :key="person.id" :value="person.id">{{ person.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 销售订单列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">销售订单</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">订单信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">客户信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">金额</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">销售员</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="order in filteredOrders" :key="order.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.orderNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(order.date) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.customerName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.customerContact }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                ¥{{ formatNumber(order.amount) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getOrderStatusClass(order.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getOrderStatusName(order.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                {{ order.salesperson }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewOrder(order)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editOrder(order)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteOrder(order)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增订单模态框 -->
+    <div v-if="showAddOrderModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增订单</h2>
+        <form @submit.prevent="addOrder">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">客户名称</label>
+            <select v-model="newOrder.customerId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="customer in customers" :key="customer.id" :value="customer.id">{{ customer.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单金额</label>
+            <input type="number" v-model="newOrder.amount" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单日期</label>
+            <input type="date" v-model="newOrder.date" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单状态</label>
+            <select v-model="newOrder.status" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="status in orderStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newOrder.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddOrderModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 订单数据
+const orders = ref([
+  {
+    id: 1,
+    orderNo: 'SO20240315001',
+    customerId: 1,
+    customerName: 'ABC科技有限公司',
+    customerContact: '张三',
+    amount: 50000,
+    date: '2024-03-15',
+    status: 1,
+    salesperson: '王五',
+    remark: '新客户首单'
+  },
+  {
+    id: 2,
+    orderNo: 'SO20240316001',
+    customerId: 2,
+    customerName: 'XYZ贸易有限公司',
+    customerContact: '李四',
+    amount: 30000,
+    date: '2024-03-16',
+    status: 2,
+    salesperson: '赵六',
+    remark: '老客户续单'
+  }
+])
+
+// 客户数据
+const customers = ref([
+  {
+    id: 1,
+    name: 'ABC科技有限公司',
+    contact: '张三',
+    phone: '13800138000'
+  },
+  {
+    id: 2,
+    name: 'XYZ贸易有限公司',
+    contact: '李四',
+    phone: '13900139000'
+  }
+])
+
+// 订单状态
+const orderStatuses = ref([
+  { id: 1, name: '待处理' },
+  { id: 2, name: '处理中' },
+  { id: 3, name: '已完成' },
+  { id: 4, name: '已取消' }
+])
+
+// 时间范围
+const timeRanges = ref([
+  { id: 1, name: '今天' },
+  { id: 2, name: '本周' },
+  { id: 3, name: '本月' },
+  { id: 4, name: '本季度' },
+  { id: 5, name: '本年' }
+])
+
+// 销售员
+const salespersons = ref([
+  { id: 1, name: '王五' },
+  { id: 2, name: '赵六' },
+  { id: 3, name: '钱七' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  status: '',
+  timeRange: '',
+  salesperson: ''
+})
+
+// 模态框状态
+const showAddOrderModal = ref(false)
+
+// 新订单表单
+const newOrder = ref({
+  customerId: '',
+  amount: '',
+  date: '',
+  status: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredOrders = computed(() => {
+  return orders.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.orderNo.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.customerName.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesStatus = !filters.value.status || item.status === filters.value.status
+    const matchesSalesperson = !filters.value.salesperson || item.salesperson === filters.value.salesperson
+    return matchesSearch && matchesStatus && matchesSalesperson
+  })
+})
+
+const currentMonthSales = computed(() => {
+  const currentMonth = new Date().getMonth() + 1
+  return orders.value
+    .filter(order => new Date(order.date).getMonth() + 1 === currentMonth)
+    .reduce((sum, order) => sum + order.amount, 0)
+})
+
+const salesGrowth = computed(() => {
+  // 这里假设有一个计算环比增长的逻辑
+  return 15
+})
+
+const totalOrders = computed(() => orders.value.length)
+
+const completionRate = computed(() => {
+  const completedOrders = orders.value.filter(order => order.status === 3).length
+  return Math.round((completedOrders / totalOrders.value) * 100)
+})
+
+const averageOrderValue = computed(() => {
+  return orders.value.reduce((sum, order) => sum + order.amount, 0) / totalOrders.value
+})
+
+const avgOrderValueGrowth = computed(() => {
+  // 这里假设有一个计算同比增长的逻辑
+  return 8
+})
+
+const salesForecast = computed(() => {
+  // 这里假设有一个销售预测的逻辑
+  return currentMonthSales.value * 1.2
+})
+
+const forecastCompletionRate = computed(() => {
+  // 这里假设有一个预测完成率的逻辑
+  return 85
+})
+
+// 格式化数字
+const formatNumber = (num) => {
+  return num.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取订单状态名称
+const getOrderStatusName = (statusId) => {
+  const status = orderStatuses.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取订单状态样式
+const getOrderStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加订单
+const addOrder = () => {
+  const customer = customers.value.find(c => c.id === newOrder.value.customerId)
+  const item = {
+    id: orders.value.length + 1,
+    orderNo: `SO${new Date().getTime()}`,
+    ...newOrder.value,
+    customerName: customer.name,
+    customerContact: customer.contact,
+    salesperson: '当前用户' // 这里应该获取当前登录用户
+  }
+  orders.value.push(item)
+  showAddOrderModal.value = false
+  resetNewOrder()
+}
+
+// 重置新订单表单
+const resetNewOrder = () => {
+  newOrder.value = {
+    customerId: '',
+    amount: '',
+    date: '',
+    status: '',
+    remark: ''
+  }
+}
+
+// 导出销售数据
+const exportSalesData = () => {
+  // 实现导出销售数据的逻辑
+  console.log('导出销售数据')
+}
+
+// 查看订单
+const viewOrder = (item) => {
+  // 实现查看订单逻辑
+  console.log('查看订单:', item)
+}
+
+// 编辑订单
+const editOrder = (item) => {
+  // 实现编辑订单逻辑
+  console.log('编辑订单:', item)
+}
+
+// 删除订单
+const deleteOrder = (item) => {
+  if (confirm(`确定要删除订单"${item.orderNo}"吗?`)) {
+    const index = orders.value.findIndex(o => o.id === item.id)
+    if (index !== -1) {
+      orders.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 723 - 0
src/assets/templates/prototype/supply-chain/InventoryAnalytics.vue

@@ -0,0 +1,723 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">库存分析</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleExportReport"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出报表</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索商品名称/编号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="category"
+            @change="handleCategoryChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类别</option>
+            <option value="electronics">电子产品</option>
+            <option value="clothing">服装</option>
+            <option value="food">食品</option>
+            <option value="books">图书</option>
+          </select>
+          <select 
+            v-model="stockStatus"
+            @change="handleStockStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="normal">正常</option>
+            <option value="low">库存不足</option>
+            <option value="overstock">库存过多</option>
+            <option value="out">缺货</option>
+          </select>
+          <select 
+            v-model="timeRange"
+            @change="handleTimeRangeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有时间</option>
+            <option value="today">今天</option>
+            <option value="week">本周</option>
+            <option value="month">本月</option>
+            <option value="quarter">本季度</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 库存统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <PackageIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总库存量</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockInventory.reduce((sum, item) => sum + item.stock, 0) }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <TrendingUpIcon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">库存周转率</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ inventoryStats.turnoverRate.toFixed(2) }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <AlertTriangleIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">库存不足</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ inventoryStats.lowStockItems }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <XCircleIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">缺货商品</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ inventoryStats.outOfStockItems }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 库存分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">库存趋势</h3>
+          <div ref="trendChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">库存状态分布</h3>
+          <div ref="statusChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 库存列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">商品信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类别</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">库存量</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">安全库存</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="item in paginatedInventory" :key="item.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-md object-cover" :src="item.image" :alt="item.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ item.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ item.code }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['category-tag', `category-${item.category}`]">
+                    {{ item.category === 'electronics' ? '电子产品' : 
+                       item.category === 'clothing' ? '服装' : 
+                       item.category === 'food' ? '食品' : '图书' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ item.stock }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ item.minStock }} - {{ item.maxStock }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${item.status}`]">
+                    {{ item.status === 'normal' ? '正常' : 
+                       item.status === 'low' ? '库存不足' : 
+                       item.status === 'overstock' ? '库存过多' : '缺货' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewItem(item)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleAdjustStock(item)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    调整
+                  </button>
+                  <button 
+                    @click="handleDeleteItem(item)"
+                    class="action-button delete-button"
+                  >
+                    <TrashIcon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredInventory.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredInventory.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  SearchIcon, 
+  DownloadIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  PackageIcon,
+  TrendingUpIcon,
+  AlertTriangleIcon,
+  XCircleIcon,
+  EyeIcon,
+  EditIcon,
+  TrashIcon,
+  ChevronUpIcon,
+  ChevronDownIcon
+} from 'lucide-vue-next'
+
+// 默认图片配置
+const defaultImages = {
+  product: 'https://ui-avatars.com/api/?name=Product&background=random&color=fff&size=150'
+}
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const category = ref('')
+const stockStatus = ref('')
+const timeRange = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalInventory = ref(100)
+
+// 图表相关
+const trendChartRef = ref(null)
+const statusChartRef = ref(null)
+let trendChart = null
+let statusChart = null
+
+// 模拟数据
+const mockInventory = ref([
+  {
+    id: 'I1001',
+    productId: 'P1001',
+    name: '智能手表 Pro',
+    category: 'electronics',
+    stock: 150,
+    minStock: 50,
+    maxStock: 300,
+    status: 'in_stock',
+    turnoverRate: 0.85,
+    lastRestock: '2024-03-15',
+    nextRestock: '2024-04-01',
+    value: 194850,
+    image: defaultImages.product
+  },
+  {
+    id: 'I1002',
+    productId: 'P1002',
+    name: '无线蓝牙耳机',
+    category: 'electronics',
+    stock: 0,
+    minStock: 100,
+    maxStock: 500,
+    status: 'out_of_stock',
+    turnoverRate: 1.2,
+    lastRestock: '2024-03-10',
+    nextRestock: '2024-03-25',
+    value: 0,
+    image: defaultImages.product
+  },
+  {
+    id: 'I1003',
+    productId: 'P1003',
+    name: '运动鞋',
+    category: 'sports',
+    stock: 80,
+    minStock: 100,
+    maxStock: 400,
+    status: 'low_stock',
+    turnoverRate: 0.65,
+    lastRestock: '2024-03-01',
+    nextRestock: '2024-03-20',
+    value: 47920,
+    image: defaultImages.product
+  },
+  {
+    id: 'I1004',
+    productId: 'P1004',
+    name: '男士衬衫',
+    category: 'clothing',
+    stock: 200,
+    minStock: 50,
+    maxStock: 300,
+    status: 'in_stock',
+    turnoverRate: 0.45,
+    lastRestock: '2024-02-15',
+    nextRestock: '2024-04-01',
+    value: 39800,
+    image: defaultImages.product
+  },
+  {
+    id: 'I1005',
+    productId: 'P1005',
+    name: '女士手提包',
+    category: 'accessories',
+    stock: 30,
+    minStock: 20,
+    maxStock: 100,
+    status: 'low_stock',
+    turnoverRate: 0.75,
+    lastRestock: '2024-03-05',
+    nextRestock: '2024-03-25',
+    value: 26970,
+    image: defaultImages.product
+  }
+])
+
+// 库存统计数据
+const inventoryStats = ref({
+  totalInventory: 1234,
+  turnoverRate: 0.85,
+  lowStockItems: 56,
+  outOfStockItems: 12
+})
+
+// 库存趋势数据
+const inventoryTrends = ref([
+  { date: '2024-03-01', value: 1200 },
+  { date: '2024-03-02', value: 1250 },
+  { date: '2024-03-03', value: 1300 },
+  { date: '2024-03-04', value: 1280 },
+  { date: '2024-03-05', value: 1350 },
+  { date: '2024-03-06', value: 1400 },
+  { date: '2024-03-07', value: 1380 }
+])
+
+// 库存分布数据
+const inventoryDistribution = ref([
+  { category: 'electronics', value: 450 },
+  { category: 'clothing', value: 300 },
+  { category: 'sports', value: 250 },
+  { category: 'accessories', value: 150 },
+  { category: 'food', value: 84 }
+])
+
+// 计算属性
+const filteredInventory = computed(() => {
+  let result = [...mockInventory.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(item => 
+      item.name.includes(searchText.value) ||
+      item.code.includes(searchText.value)
+    )
+  }
+  
+  // 类别过滤
+  if (category.value) {
+    result = result.filter(item => item.category === category.value)
+  }
+  
+  // 状态过滤
+  if (stockStatus.value) {
+    result = result.filter(item => item.status === stockStatus.value)
+  }
+  
+  // 时间范围过滤
+  if (timeRange.value) {
+    const now = new Date()
+    result = result.filter(item => {
+      // 这里可以根据实际需求添加时间过滤逻辑
+      return true
+    })
+  }
+  
+  return result
+})
+
+const paginatedInventory = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredInventory.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredInventory.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleCategoryChange = () => {
+  currentPage.value = 1
+}
+
+const handleStockStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleTimeRangeChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleViewItem = (item) => {
+  console.log('查看商品:', item)
+}
+
+const handleAdjustStock = (item) => {
+  console.log('调整库存:', item)
+}
+
+const handleDeleteItem = (item) => {
+  console.log('删除商品:', item)
+}
+
+const handleExportReport = () => {
+  console.log('导出报表')
+}
+
+// Mock data
+const mockTrendData = {
+  dates: ['1月', '2月', '3月', '4月', '5月', '6月'],
+  values: {
+    electronics: [1200, 1400, 1800, 2200, 2600, 3000],
+    clothing: [800, 1000, 1200, 1400, 1600, 1800],
+    food: [1500, 1700, 1900, 2100, 2300, 2500],
+    books: [600, 700, 800, 900, 1000, 1100]
+  }
+}
+
+const mockStatusData = [
+  { value: 40, name: '正常' },
+  { value: 25, name: '库存不足' },
+  { value: 20, name: '库存过多' },
+  { value: 15, name: '缺货' }
+]
+
+// 初始化趋势图表
+const initTrendChart = () => {
+  if (!trendChartRef.value) return
+  
+  trendChart = echarts.init(trendChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['电子产品', '服装', '食品', '图书']
+    },
+    xAxis: {
+      type: 'category',
+      data: mockTrendData.dates
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '电子产品',
+        type: 'line',
+        data: mockTrendData.values.electronics
+      },
+      {
+        name: '服装',
+        type: 'line',
+        data: mockTrendData.values.clothing
+      },
+      {
+        name: '食品',
+        type: 'line',
+        data: mockTrendData.values.food
+      },
+      {
+        name: '图书',
+        type: 'line',
+        data: mockTrendData.values.books
+      }
+    ]
+  }
+  trendChart.setOption(option)
+}
+
+// 初始化状态图表
+const initStatusChart = () => {
+  if (!statusChartRef.value) return
+  
+  statusChart = echarts.init(statusChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '库存状态',
+        type: 'pie',
+        radius: '50%',
+        data: mockStatusData,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+  statusChart.setOption(option)
+}
+
+// 处理窗口大小变化
+const handleResize = () => {
+  trendChart?.resize()
+  statusChart?.resize()
+}
+
+onMounted(() => {
+  initTrendChart()
+  initStatusChart()
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  trendChart?.dispose()
+  statusChart?.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 商品类别标签样式 */
+.category-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.category-electronics {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.category-clothing {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+.category-food {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.category-books {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+/* 库存状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-normal {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-low {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-overstock {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+.status-out {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.delete-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 351 - 0
src/assets/templates/prototype/supply-chain/InventoryManagement.vue

@@ -0,0 +1,351 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex">
+            <div class="flex-shrink-0 flex items-center">
+              <h1 class="text-xl font-bold text-gray-900 dark:text-white">库存管理</h1>
+            </div>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button @click="showAddModal = true" class="btn-primary">
+              新增库存
+            </button>
+            <button @click="exportInventory" class="btn-secondary">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 库存统计 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总库存量</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">
+            {{ totalInventory }}
+          </p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">库存价值</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">
+            ¥{{ formatNumber(totalValue) }}
+          </p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">低库存预警</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">
+            {{ lowStockCount }}
+          </p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">库存周转率</h3>
+          <p class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">
+            {{ turnoverRate }}%
+          </p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow mb-8">
+        <div class="p-6">
+          <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品类型</label>
+              <select v-model="selectedType" class="mt-1 form-select">
+                <option value="">全部</option>
+                <option v-for="type in types" :key="type" :value="type">{{ type }}</option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">库存状态</label>
+              <select v-model="selectedStatus" class="mt-1 form-select">
+                <option value="">全部</option>
+                <option v-for="status in statuses" :key="status" :value="status">{{ status }}</option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">仓库</label>
+              <select v-model="selectedWarehouse" class="mt-1 form-select">
+                <option value="">全部</option>
+                <option v-for="warehouse in warehouses" :key="warehouse" :value="warehouse">{{ warehouse }}</option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">搜索</label>
+              <input
+                v-model="searchText"
+                type="text"
+                placeholder="商品名称/编号"
+                class="mt-1 form-input"
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 库存列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">商品信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">库存数量</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">单位</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">仓库</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="item in filteredInventory" :key="item.id">
+                <td class="px-6 py-4 whitespace-nowrap">
+                  <div class="text-sm font-medium text-gray-900 dark:text-white">{{ item.name }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ item.code }}</div>
+                </td>
+                <td class="px-6 py-4 whitespace-nowrap">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ item.quantity }}</div>
+                </td>
+                <td class="px-6 py-4 whitespace-nowrap">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ item.unit }}</div>
+                </td>
+                <td class="px-6 py-4 whitespace-nowrap">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ item.warehouse }}</div>
+                </td>
+                <td class="px-6 py-4 whitespace-nowrap">
+                  <span :class="getStatusClass(item.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                    {{ item.status }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                  <button @click="viewItem(item)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-4">查看</button>
+                  <button @click="editItem(item)" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-4">编辑</button>
+                  <button @click="deleteItem(item)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+
+    <!-- 新增/编辑库存模态框 -->
+    <div v-if="showAddModal" class="fixed inset-0 z-10 overflow-y-auto">
+      <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
+        <div class="fixed inset-0 transition-opacity" aria-hidden="true">
+          <div class="absolute inset-0 bg-gray-500 dark:bg-gray-900 opacity-75"></div>
+        </div>
+        <div class="inline-block align-bottom bg-white dark:bg-gray-800 rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
+          <div class="bg-white dark:bg-gray-800 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
+            <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">
+              {{ editingItem ? '编辑库存' : '新增库存' }}
+            </h3>
+            <form @submit.prevent="submitForm">
+              <div class="grid grid-cols-1 gap-4">
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品名称</label>
+                  <input v-model="form.name" type="text" class="mt-1 form-input" required />
+                </div>
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品编号</label>
+                  <input v-model="form.code" type="text" class="mt-1 form-input" required />
+                </div>
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">商品类型</label>
+                  <select v-model="form.type" class="mt-1 form-select" required>
+                    <option v-for="type in types" :key="type" :value="type">{{ type }}</option>
+                  </select>
+                </div>
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">库存数量</label>
+                  <input v-model="form.quantity" type="number" class="mt-1 form-input" required />
+                </div>
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">单位</label>
+                  <input v-model="form.unit" type="text" class="mt-1 form-input" required />
+                </div>
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">仓库</label>
+                  <select v-model="form.warehouse" class="mt-1 form-select" required>
+                    <option v-for="warehouse in warehouses" :key="warehouse" :value="warehouse">{{ warehouse }}</option>
+                  </select>
+                </div>
+                <div>
+                  <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">备注</label>
+                  <textarea v-model="form.remark" class="mt-1 form-textarea" rows="3"></textarea>
+                </div>
+              </div>
+              <div class="mt-6 flex justify-end space-x-3">
+                <button type="button" @click="showAddModal = false" class="btn-secondary">
+                  取消
+                </button>
+                <button type="submit" class="btn-primary">
+                  保存
+                </button>
+              </div>
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 数据定义
+const types = ['原材料', '半成品', '成品', '配件']
+const statuses = ['正常', '低库存', '缺货']
+const warehouses = ['主仓库', 'A区仓库', 'B区仓库']
+
+const inventory = ref([
+  {
+    id: 1,
+    name: '商品A',
+    code: 'SP001',
+    type: '成品',
+    quantity: 100,
+    unit: '个',
+    warehouse: '主仓库',
+    status: '正常',
+    remark: ''
+  },
+  // 更多示例数据...
+])
+
+const searchText = ref('')
+const selectedType = ref('')
+const selectedStatus = ref('')
+const selectedWarehouse = ref('')
+const showAddModal = ref(false)
+const editingItem = ref(null)
+
+const form = ref({
+  name: '',
+  code: '',
+  type: '',
+  quantity: 0,
+  unit: '',
+  warehouse: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredInventory = computed(() => {
+  return inventory.value.filter(item => {
+    const matchesSearch = !searchText.value || 
+      item.name.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      item.code.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesType = !selectedType.value || item.type === selectedType.value
+    const matchesStatus = !selectedStatus.value || item.status === selectedStatus.value
+    const matchesWarehouse = !selectedWarehouse.value || item.warehouse === selectedWarehouse.value
+    return matchesSearch && matchesType && matchesStatus && matchesWarehouse
+  })
+})
+
+const totalInventory = computed(() => {
+  return inventory.value.reduce((sum, item) => sum + item.quantity, 0)
+})
+
+const totalValue = computed(() => {
+  // 这里假设每个商品的价值是固定的,实际应用中应该从商品信息中获取
+  return inventory.value.reduce((sum, item) => sum + item.quantity * 100, 0)
+})
+
+const lowStockCount = computed(() => {
+  return inventory.value.filter(item => item.status === '低库存').length
+})
+
+const turnoverRate = computed(() => {
+  // 这里使用一个简单的计算方式,实际应用中应该根据实际的出入库记录计算
+  return Math.round((totalInventory.value / 1000) * 100)
+})
+
+// 方法
+const getStatusClass = (status) => {
+  switch (status) {
+    case '正常':
+      return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300'
+    case '低库存':
+      return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300'
+    case '缺货':
+      return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300'
+    default:
+      return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300'
+  }
+}
+
+const formatNumber = (num) => {
+  return num.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
+}
+
+const viewItem = (item) => {
+  // 实现查看详情逻辑
+}
+
+const editItem = (item) => {
+  editingItem.value = item
+  form.value = { ...item }
+  showAddModal.value = true
+}
+
+const deleteItem = (item) => {
+  if (confirm('确定要删除这个库存记录吗?')) {
+    inventory.value = inventory.value.filter(i => i.id !== item.id)
+  }
+}
+
+const submitForm = () => {
+  if (editingItem.value) {
+    // 更新现有记录
+    const index = inventory.value.findIndex(item => item.id === editingItem.value.id)
+    if (index !== -1) {
+      inventory.value[index] = { ...form.value, id: editingItem.value.id }
+    }
+  } else {
+    // 添加新记录
+    const newItem = {
+      ...form.value,
+      id: inventory.value.length + 1,
+      status: form.value.quantity < 10 ? '低库存' : '正常'
+    }
+    inventory.value.push(newItem)
+  }
+  showAddModal.value = false
+  resetForm()
+}
+
+const resetForm = () => {
+  form.value = {
+    name: '',
+    code: '',
+    type: '',
+    quantity: 0,
+    unit: '',
+    warehouse: '',
+    remark: ''
+  }
+  editingItem.value = null
+}
+
+const exportInventory = () => {
+  // 实现导出逻辑
+  const data = JSON.stringify(inventory.value, null, 2)
+  const blob = new Blob([data], { type: 'application/json' })
+  const url = URL.createObjectURL(blob)
+  const a = document.createElement('a')
+  a.href = url
+  a.download = 'inventory.json'
+  document.body.appendChild(a)
+  a.click()
+  document.body.removeChild(a)
+  URL.revokeObjectURL(url)
+}
+</script> 

+ 308 - 0
src/assets/templates/prototype/supply-chain/LogisticsManagement.vue

@@ -0,0 +1,308 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">物流管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddOrderModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建物流订单
+            </button>
+            <button @click="exportOrders" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              导出订单
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="订单号/收货人/联系电话" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">运输方式</label>
+            <select v-model="filters.transportType" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有方式</option>
+              <option v-for="type in transportTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in orderStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">创建时间</label>
+            <select v-model="filters.createTime" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有时间</option>
+              <option value="today">今天</option>
+              <option value="week">本周</option>
+              <option value="month">本月</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 物流订单列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">订单信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">运输方式</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">创建时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="order in filteredOrders" :key="order.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.orderNumber }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.recipient }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.phone }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300">
+                  {{ order.transportType }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(order.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ order.status }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                {{ formatDate(order.createTime) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewOrder(order)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="trackOrder(order)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">跟踪</button>
+                <button @click="updateStatus(order)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">更新状态</button>
+                <button @click="deleteOrder(order)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建物流订单模态框 -->
+    <div v-if="showAddOrderModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建物流订单</h2>
+        <form @submit.prevent="addOrder">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单号</label>
+            <input type="text" v-model="newOrder.orderNumber" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">收货人</label>
+            <input type="text" v-model="newOrder.recipient" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">联系电话</label>
+            <input type="tel" v-model="newOrder.phone" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">运输方式</label>
+            <select v-model="newOrder.transportType" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="type in transportTypes" :key="type.id" :value="type.id">{{ type.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">收货地址</label>
+            <textarea v-model="newOrder.address" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddOrderModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 物流订单数据
+const orders = ref([
+  {
+    id: 1,
+    orderNumber: 'LOG202403150001',
+    recipient: '张三',
+    phone: '13800138000',
+    transportType: '快递',
+    status: '待发货',
+    createTime: new Date().toISOString(),
+    address: '北京市朝阳区xxx街道xxx号'
+  },
+  {
+    id: 2,
+    orderNumber: 'LOG202403150002',
+    recipient: '李四',
+    phone: '13800138001',
+    transportType: '物流',
+    status: '运输中',
+    createTime: new Date(Date.now() - 86400000).toISOString(),
+    address: '上海市浦东新区xxx街道xxx号'
+  }
+])
+
+// 运输方式
+const transportTypes = ref([
+  { id: 1, name: '快递' },
+  { id: 2, name: '物流' },
+  { id: 3, name: '空运' },
+  { id: 4, name: '海运' }
+])
+
+// 订单状态
+const orderStatuses = ref([
+  { id: 1, name: '待发货' },
+  { id: 2, name: '运输中' },
+  { id: 3, name: '已签收' },
+  { id: 4, name: '已取消' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  transportType: '',
+  status: '',
+  createTime: ''
+})
+
+// 模态框状态
+const showAddOrderModal = ref(false)
+
+// 新订单表单
+const newOrder = ref({
+  orderNumber: '',
+  recipient: '',
+  phone: '',
+  transportType: '',
+  address: ''
+})
+
+// 计算属性
+const filteredOrders = computed(() => {
+  return orders.value.filter(order => {
+    const matchesSearch = !searchText.value || 
+      order.orderNumber.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      order.recipient.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      order.phone.includes(searchText.value)
+    const matchesTransportType = !filters.value.transportType || order.transportType === filters.value.transportType
+    const matchesStatus = !filters.value.status || order.status === filters.value.status
+    const matchesTime = !filters.value.createTime || checkCreateTime(order.createTime)
+    return matchesSearch && matchesTransportType && matchesStatus && matchesTime
+  })
+})
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleString('zh-CN')
+}
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    '待发货': 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    '运输中': 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    '已签收': 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    '已取消': 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 检查创建时间
+const checkCreateTime = (date) => {
+  const now = new Date()
+  const createDate = new Date(date)
+  const diff = now - createDate
+
+  switch (filters.value.createTime) {
+    case 'today':
+      return diff < 86400000
+    case 'week':
+      return diff < 604800000
+    case 'month':
+      return diff < 2592000000
+    default:
+      return true
+  }
+}
+
+// 添加订单
+const addOrder = () => {
+  const order = {
+    id: orders.value.length + 1,
+    ...newOrder.value,
+    status: '待发货',
+    createTime: new Date().toISOString()
+  }
+  orders.value.push(order)
+  showAddOrderModal.value = false
+  resetNewOrder()
+}
+
+// 重置新订单表单
+const resetNewOrder = () => {
+  newOrder.value = {
+    orderNumber: '',
+    recipient: '',
+    phone: '',
+    transportType: '',
+    address: ''
+  }
+}
+
+// 查看订单
+const viewOrder = (order) => {
+  // 实现查看订单逻辑
+  console.log('查看订单:', order)
+}
+
+// 跟踪订单
+const trackOrder = (order) => {
+  // 实现订单跟踪逻辑
+  console.log('跟踪订单:', order)
+}
+
+// 更新状态
+const updateStatus = (order) => {
+  // 实现更新状态逻辑
+  console.log('更新状态:', order)
+}
+
+// 删除订单
+const deleteOrder = (order) => {
+  if (confirm(`确定要删除订单 ${order.orderNumber} 吗?`)) {
+    const index = orders.value.findIndex(o => o.id === order.id)
+    if (index !== -1) {
+      orders.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出订单
+const exportOrders = () => {
+  // 实现导出订单逻辑
+  console.log('导出订单')
+}
+</script> 

+ 549 - 0
src/assets/templates/prototype/supply-chain/PurchaseManagement.vue

@@ -0,0 +1,549 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">采购管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddOrderModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              新增订单
+            </button>
+            <button @click="showAddSupplierModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              新增供应商
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 采购统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">本月采购</div>
+          <div class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">¥{{ formatNumber(currentMonthPurchases) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            环比增长 <span :class="purchaseGrowth >= 0 ? 'text-green-600' : 'text-red-600'">{{ purchaseGrowth }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">总订单数</div>
+          <div class="mt-2 text-3xl font-bold text-purple-600 dark:text-purple-400">{{ formatNumber(totalOrders) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            完成率 <span class="text-green-600">{{ completionRate }}%</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">总供应商</div>
+          <div class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ formatNumber(totalSuppliers) }}</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            活跃供应商 <span class="text-blue-600">{{ formatNumber(activeSuppliers) }}</span>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="text-sm font-medium text-gray-500 dark:text-gray-400">平均采购周期</div>
+          <div class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ averageCycle }}天</div>
+          <div class="mt-2 text-sm text-gray-500 dark:text-gray-400">
+            环比变化 <span :class="cycleChange >= 0 ? 'text-green-600' : 'text-red-600'">{{ cycleChange }}%</span>
+          </div>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="searchText" placeholder="订单号/供应商名称" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有状态</option>
+              <option v-for="status in orderStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <select v-model="filters.timeRange" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="range in timeRanges" :key="range.id" :value="range.id">{{ range.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">采购员</label>
+            <select v-model="filters.purchaser" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">所有采购员</option>
+              <option v-for="purchaser in purchasers" :key="purchaser.id" :value="purchaser.id">{{ purchaser.name }}</option>
+            </select>
+          </div>
+        </div>
+      </div>
+
+      <!-- 采购订单列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden mb-6">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">采购订单</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">订单信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">供应商信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">金额</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="order in filteredOrders" :key="order.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ order.orderNo }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ formatDate(order.orderDate) }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ order.supplierName }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ order.supplierContact }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white">
+                ¥{{ formatNumber(order.amount) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getOrderStatusClass(order.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getOrderStatusName(order.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewOrder(order)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editOrder(order)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteOrder(order)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+
+      <!-- 供应商列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white">供应商列表</h2>
+        </div>
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">供应商信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">联系方式</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">合作状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="supplier in suppliers" :key="supplier.id">
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ supplier.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ supplier.code }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <div class="text-sm text-gray-900 dark:text-white">{{ supplier.contact }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ supplier.phone }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getSupplierStatusClass(supplier.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getSupplierStatusName(supplier.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewSupplier(supplier)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editSupplier(supplier)" class="text-yellow-600 hover:text-yellow-900 dark:text-yellow-400 dark:hover:text-yellow-300 mr-3">编辑</button>
+                <button @click="deleteSupplier(supplier)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 新增订单模态框 -->
+    <div v-if="showAddOrderModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增采购订单</h2>
+        <form @submit.prevent="addOrder">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">供应商</label>
+            <select v-model="newOrder.supplierId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="supplier in suppliers" :key="supplier.id" :value="supplier.id">{{ supplier.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单金额</label>
+            <input type="number" v-model="newOrder.amount" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单日期</label>
+            <input type="date" v-model="newOrder.orderDate" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">订单状态</label>
+            <select v-model="newOrder.status" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="status in orderStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newOrder.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddOrderModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 新增供应商模态框 -->
+    <div v-if="showAddSupplierModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">新增供应商</h2>
+        <form @submit.prevent="addSupplier">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">供应商名称</label>
+            <input type="text" v-model="newSupplier.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">供应商编码</label>
+            <input type="text" v-model="newSupplier.code" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">联系人</label>
+            <input type="text" v-model="newSupplier.contact" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">联系电话</label>
+            <input type="tel" v-model="newSupplier.phone" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">合作状态</label>
+            <select v-model="newSupplier.status" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="status in supplierStatuses" :key="status.id" :value="status.id">{{ status.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">备注</label>
+            <textarea v-model="newSupplier.remark" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddSupplierModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              添加
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 采购订单数据
+const orders = ref([
+  {
+    id: 1,
+    orderNo: 'PO2024001',
+    supplierId: 1,
+    supplierName: '供应商A',
+    supplierContact: '张三',
+    amount: 10000,
+    orderDate: '2024-01-15',
+    status: 1
+  },
+  {
+    id: 2,
+    orderNo: 'PO2024002',
+    supplierId: 2,
+    supplierName: '供应商B',
+    supplierContact: '李四',
+    amount: 20000,
+    orderDate: '2024-01-16',
+    status: 2
+  }
+])
+
+// 供应商数据
+const suppliers = ref([
+  {
+    id: 1,
+    name: '供应商A',
+    code: 'SUP001',
+    contact: '张三',
+    phone: '13800138000',
+    status: 1
+  },
+  {
+    id: 2,
+    name: '供应商B',
+    code: 'SUP002',
+    contact: '李四',
+    phone: '13800138001',
+    status: 2
+  }
+])
+
+// 订单状态
+const orderStatuses = ref([
+  { id: 1, name: '待处理' },
+  { id: 2, name: '已确认' },
+  { id: 3, name: '已完成' },
+  { id: 4, name: '已取消' }
+])
+
+// 供应商状态
+const supplierStatuses = ref([
+  { id: 1, name: '合作中' },
+  { id: 2, name: '暂停合作' },
+  { id: 3, name: '终止合作' }
+])
+
+// 时间范围
+const timeRanges = ref([
+  { id: 1, name: '今天' },
+  { id: 2, name: '本周' },
+  { id: 3, name: '本月' },
+  { id: 4, name: '本季度' },
+  { id: 5, name: '本年' }
+])
+
+// 采购员
+const purchasers = ref([
+  { id: 1, name: '王五' },
+  { id: 2, name: '赵六' }
+])
+
+// 筛选条件
+const searchText = ref('')
+const filters = ref({
+  status: '',
+  timeRange: '',
+  purchaser: ''
+})
+
+// 模态框状态
+const showAddOrderModal = ref(false)
+const showAddSupplierModal = ref(false)
+
+// 新订单表单
+const newOrder = ref({
+  supplierId: '',
+  amount: '',
+  orderDate: '',
+  status: '',
+  remark: ''
+})
+
+// 新供应商表单
+const newSupplier = ref({
+  name: '',
+  code: '',
+  contact: '',
+  phone: '',
+  status: '',
+  remark: ''
+})
+
+// 计算属性
+const filteredOrders = computed(() => {
+  return orders.value.filter(order => {
+    const matchesSearch = !searchText.value || 
+      order.orderNo.toLowerCase().includes(searchText.value.toLowerCase()) ||
+      order.supplierName.toLowerCase().includes(searchText.value.toLowerCase())
+    const matchesStatus = !filters.value.status || order.status === filters.value.status
+    const matchesTimeRange = !filters.value.timeRange || true // 这里需要根据实际时间范围进行过滤
+    const matchesPurchaser = !filters.value.purchaser || true // 这里需要根据实际采购员进行过滤
+    return matchesSearch && matchesStatus && matchesTimeRange && matchesPurchaser
+  })
+})
+
+const currentMonthPurchases = computed(() => {
+  // 这里假设有一个计算本月采购金额的逻辑
+  return 300000
+})
+
+const purchaseGrowth = computed(() => {
+  // 这里假设有一个计算环比增长的逻辑
+  return 5
+})
+
+const totalOrders = computed(() => {
+  return orders.value.length
+})
+
+const completionRate = computed(() => {
+  const completedOrders = orders.value.filter(order => order.status === 3).length
+  return Math.round((completedOrders / totalOrders.value) * 100)
+})
+
+const totalSuppliers = computed(() => {
+  return suppliers.value.length
+})
+
+const activeSuppliers = computed(() => {
+  return suppliers.value.filter(supplier => supplier.status === 1).length
+})
+
+const averageCycle = computed(() => {
+  // 这里假设有一个计算平均采购周期的逻辑
+  return 7
+})
+
+const cycleChange = computed(() => {
+  // 这里假设有一个计算环比变化的逻辑
+  return -2
+})
+
+// 格式化数字
+const formatNumber = (num) => {
+  return num.toLocaleString('zh-CN')
+}
+
+// 格式化日期
+const formatDate = (date) => {
+  return new Date(date).toLocaleDateString('zh-CN')
+}
+
+// 获取订单状态名称
+const getOrderStatusName = (statusId) => {
+  const status = orderStatuses.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取订单状态样式
+const getOrderStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    2: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    3: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    4: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 获取供应商状态名称
+const getSupplierStatusName = (statusId) => {
+  const status = supplierStatuses.value.find(s => s.id === statusId)
+  return status ? status.name : '未知状态'
+}
+
+// 获取供应商状态样式
+const getSupplierStatusClass = (statusId) => {
+  const classes = {
+    1: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    2: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    3: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[statusId] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+}
+
+// 添加订单
+const addOrder = () => {
+  const supplier = suppliers.value.find(s => s.id === newOrder.value.supplierId)
+  const order = {
+    id: orders.value.length + 1,
+    orderNo: `PO${new Date().getFullYear()}${String(orders.value.length + 1).padStart(3, '0')}`,
+    supplierId: newOrder.value.supplierId,
+    supplierName: supplier.name,
+    supplierContact: supplier.contact,
+    amount: newOrder.value.amount,
+    orderDate: newOrder.value.orderDate,
+    status: newOrder.value.status
+  }
+  orders.value.push(order)
+  showAddOrderModal.value = false
+  resetNewOrder()
+}
+
+// 重置新订单表单
+const resetNewOrder = () => {
+  newOrder.value = {
+    supplierId: '',
+    amount: '',
+    orderDate: '',
+    status: '',
+    remark: ''
+  }
+}
+
+// 添加供应商
+const addSupplier = () => {
+  const supplier = {
+    id: suppliers.value.length + 1,
+    ...newSupplier.value
+  }
+  suppliers.value.push(supplier)
+  showAddSupplierModal.value = false
+  resetNewSupplier()
+}
+
+// 重置新供应商表单
+const resetNewSupplier = () => {
+  newSupplier.value = {
+    name: '',
+    code: '',
+    contact: '',
+    phone: '',
+    status: '',
+    remark: ''
+  }
+}
+
+// 查看订单
+const viewOrder = (order) => {
+  // 实现查看订单逻辑
+  console.log('查看订单:', order)
+}
+
+// 编辑订单
+const editOrder = (order) => {
+  // 实现编辑订单逻辑
+  console.log('编辑订单:', order)
+}
+
+// 删除订单
+const deleteOrder = (order) => {
+  if (confirm(`确定要删除订单"${order.orderNo}"吗?`)) {
+    const index = orders.value.findIndex(o => o.id === order.id)
+    if (index !== -1) {
+      orders.value.splice(index, 1)
+    }
+  }
+}
+
+// 查看供应商
+const viewSupplier = (supplier) => {
+  // 实现查看供应商逻辑
+  console.log('查看供应商:', supplier)
+}
+
+// 编辑供应商
+const editSupplier = (supplier) => {
+  // 实现编辑供应商逻辑
+  console.log('编辑供应商:', supplier)
+}
+
+// 删除供应商
+const deleteSupplier = (supplier) => {
+  if (confirm(`确定要删除供应商"${supplier.name}"吗?`)) {
+    const index = suppliers.value.findIndex(s => s.id === supplier.id)
+    if (index !== -1) {
+      suppliers.value.splice(index, 1)
+    }
+  }
+}
+</script> 

+ 683 - 0
src/assets/templates/prototype/supply-chain/SupplierManagement.vue

@@ -0,0 +1,683 @@
+<template>
+  <div class="min-h-screen bg-gray-50 dark:bg-gray-900">
+    <!-- 顶部导航栏 -->
+    <nav class="bg-white dark:bg-gray-800 shadow-sm">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+        <div class="flex justify-between h-16">
+          <div class="flex items-center">
+            <h1 class="text-xl font-bold text-gray-800 dark:text-white">供应商管理</h1>
+          </div>
+          <div class="flex items-center space-x-4">
+            <button 
+              @click="handleAddSupplier"
+              class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center space-x-2"
+            >
+              <PlusIcon class="h-5 w-5" />
+              <span>新增供应商</span>
+            </button>
+            <button 
+              @click="handleExportSuppliers"
+              class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 flex items-center space-x-2"
+            >
+              <DownloadIcon class="h-5 w-5" />
+              <span>导出供应商</span>
+            </button>
+          </div>
+        </div>
+      </div>
+    </nav>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 搜索和筛选区域 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-8">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div class="relative">
+            <input
+              v-model="searchText"
+              @input="handleSearch"
+              type="text"
+              placeholder="搜索供应商名称/编号..."
+              class="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+            />
+            <SearchIcon class="absolute left-3 top-2.5 h-5 w-5 text-gray-400 dark:text-gray-500" />
+          </div>
+          <select 
+            v-model="supplierType"
+            @change="handleTypeChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有类型</option>
+            <option value="manufacturer">生产商</option>
+            <option value="distributor">经销商</option>
+            <option value="wholesaler">批发商</option>
+            <option value="retailer">零售商</option>
+          </select>
+          <select 
+            v-model="supplierStatus"
+            @change="handleStatusChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有状态</option>
+            <option value="active">正常合作</option>
+            <option value="inactive">暂停合作</option>
+            <option value="blacklisted">黑名单</option>
+          </select>
+          <select 
+            v-model="supplierLevel"
+            @change="handleLevelChange"
+            class="border border-gray-300 dark:border-gray-600 rounded-md px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
+          >
+            <option value="">所有等级</option>
+            <option value="A">A级</option>
+            <option value="B">B级</option>
+            <option value="C">C级</option>
+          </select>
+        </div>
+      </div>
+
+      <!-- 供应商统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-blue-100 dark:bg-blue-900">
+              <BuildingIcon class="h-6 w-6 text-blue-600 dark:text-blue-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">总供应商数</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockSuppliers.length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-green-100 dark:bg-green-900">
+              <Building2Icon class="h-6 w-6 text-green-600 dark:text-green-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">正常合作</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockSuppliers.filter(supplier => supplier.status === 'active').length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-yellow-100 dark:bg-yellow-900">
+              <BuildingIcon class="h-6 w-6 text-yellow-600 dark:text-yellow-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">暂停合作</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockSuppliers.filter(supplier => supplier.status === 'inactive').length }}</p>
+            </div>
+          </div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <div class="flex items-center">
+            <div class="p-3 rounded-full bg-red-100 dark:bg-red-900">
+              <BuildingIcon class="h-6 w-6 text-red-600 dark:text-red-400" />
+            </div>
+            <div class="ml-4">
+              <p class="text-sm font-medium text-gray-600 dark:text-gray-400">黑名单</p>
+              <p class="text-2xl font-semibold text-gray-900 dark:text-white">{{ mockSuppliers.filter(supplier => supplier.status === 'blacklisted').length }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 供应商分析图表 -->
+      <div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">供应商类型分布</h3>
+          <div ref="typeChartRef" class="h-64"></div>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white mb-4">供应商等级分布</h3>
+          <div ref="levelChartRef" class="h-64"></div>
+        </div>
+      </div>
+
+      <!-- 供应商列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <div class="overflow-x-auto">
+          <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+            <thead class="bg-gray-50 dark:bg-gray-700">
+              <tr>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">供应商信息</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">等级</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">联系人</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+              </tr>
+            </thead>
+            <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+              <tr v-for="supplier in paginatedSuppliers" :key="supplier.id" class="hover:bg-gray-50 dark:hover:bg-gray-700">
+                <td class="px-6 py-4">
+                  <div class="flex items-center">
+                    <div class="flex-shrink-0 h-10 w-10">
+                      <img class="h-10 w-10 rounded-md object-cover" :src="supplier.logo" :alt="supplier.name">
+                    </div>
+                    <div class="ml-4">
+                      <div class="text-sm font-medium text-gray-900 dark:text-white">{{ supplier.name }}</div>
+                      <div class="text-sm text-gray-500 dark:text-gray-400">{{ supplier.code }}</div>
+                    </div>
+                  </div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['type-tag', `type-${supplier.type}`]">
+                    {{ supplier.type === 'manufacturer' ? '生产商' : 
+                       supplier.type === 'distributor' ? '经销商' : 
+                       supplier.type === 'wholesaler' ? '批发商' : '零售商' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['level-tag', `level-${supplier.level}`]">
+                    {{ supplier.level }}级
+                  </span>
+                </td>
+                <td class="px-6 py-4">
+                  <div class="text-sm text-gray-900 dark:text-white">{{ supplier.contact }}</div>
+                  <div class="text-sm text-gray-500 dark:text-gray-400">{{ supplier.phone }}</div>
+                </td>
+                <td class="px-6 py-4">
+                  <span :class="['status-tag', `status-${supplier.status}`]">
+                    {{ supplier.status === 'active' ? '正常合作' : 
+                       supplier.status === 'inactive' ? '暂停合作' : '黑名单' }}
+                  </span>
+                </td>
+                <td class="px-6 py-4 text-sm font-medium">
+                  <button 
+                    @click="handleViewSupplier(supplier)"
+                    class="action-button view-button"
+                  >
+                    <EyeIcon class="h-4 w-4 inline-block mr-1" />
+                    查看
+                  </button>
+                  <button 
+                    @click="handleEditSupplier(supplier)"
+                    class="action-button edit-button"
+                  >
+                    <EditIcon class="h-4 w-4 inline-block mr-1" />
+                    编辑
+                  </button>
+                  <button 
+                    @click="handleDeleteSupplier(supplier)"
+                    class="action-button delete-button"
+                  >
+                    <TrashIcon class="h-4 w-4 inline-block mr-1" />
+                    删除
+                  </button>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+
+      <!-- 分页 -->
+      <div class="bg-white dark:bg-gray-800 px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-700 sm:px-6 mt-4">
+        <div class="flex-1 flex justify-between sm:hidden">
+          <button 
+            @click="handlePageChange(currentPage - 1)"
+            :disabled="currentPage === 1"
+            class="pagination-button"
+          >
+            上一页
+          </button>
+          <button 
+            @click="handlePageChange(currentPage + 1)"
+            :disabled="currentPage === totalPages"
+            class="pagination-button"
+          >
+            下一页
+          </button>
+        </div>
+        <div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
+          <div>
+            <p class="text-sm text-gray-700 dark:text-gray-300">
+              显示 <span class="font-medium">{{ (currentPage - 1) * pageSize + 1 }}</span> 到 
+              <span class="font-medium">{{ Math.min(currentPage * pageSize, filteredSuppliers.length) }}</span> 条,共 
+              <span class="font-medium">{{ filteredSuppliers.length }}</span> 条
+            </p>
+          </div>
+          <div>
+            <nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">
+              <button 
+                @click="handlePageChange(currentPage - 1)"
+                :disabled="currentPage === 1"
+                class="relative inline-flex items-center px-2 py-2 rounded-l-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronLeftIcon class="h-5 w-5" />
+              </button>
+              <button 
+                v-for="page in totalPages"
+                :key="page"
+                @click="handlePageChange(page)"
+                :class="[
+                  'relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium',
+                  currentPage === page ? 'bg-blue-600 text-white border-blue-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
+                ]"
+              >
+                {{ page }}
+              </button>
+              <button 
+                @click="handlePageChange(currentPage + 1)"
+                :disabled="currentPage === totalPages"
+                class="relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-sm font-medium text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-600"
+              >
+                <ChevronRightIcon class="h-5 w-5" />
+              </button>
+            </nav>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue'
+import * as echarts from 'echarts'
+import { 
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart
+} from 'echarts/charts'
+import {
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { CanvasRenderer } from 'echarts/renderers'
+import { 
+  SearchIcon, 
+  ChevronLeftIcon, 
+  ChevronRightIcon,
+  BuildingIcon,
+  Building2Icon,
+  DownloadIcon,
+  PlusIcon,
+  EyeIcon,
+  EditIcon,
+  TrashIcon
+} from 'lucide-vue-next'
+
+// 默认图片配置
+const defaultImages = {
+  supplier: 'https://ui-avatars.com/api/?name=Supplier&background=random&color=fff&size=150'
+}
+
+// 注册必要的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  LegendComponent,
+  GridComponent,
+  DataZoomComponent,
+  LineChart,
+  BarChart,
+  PieChart,
+  ScatterChart,
+  CanvasRenderer
+])
+
+// 状态管理
+const isLoading = ref(false)
+const searchText = ref('')
+const supplierType = ref('')
+const supplierStatus = ref('')
+const supplierLevel = ref('')
+const currentPage = ref(1)
+const pageSize = ref(10)
+const totalSuppliers = ref(100)
+
+// 图表相关
+const typeChartRef = ref(null)
+const levelChartRef = ref(null)
+let typeChart = null
+let levelChart = null
+
+// 模拟数据
+const mockSuppliers = ref([
+  {
+    id: 'S1001',
+    name: '电子科技公司',
+    code: 'S1001',
+    type: 'manufacturer',
+    level: 'A',
+    contact: '张经理',
+    phone: '13800138001',
+    status: 'active',
+    logo: defaultImages.supplier
+  },
+  {
+    id: 'S1002',
+    name: '服装制造厂',
+    code: 'S1002',
+    type: 'manufacturer',
+    level: 'B',
+    contact: '李经理',
+    phone: '13800138002',
+    status: 'active',
+    logo: defaultImages.supplier
+  },
+  {
+    id: 'S1003',
+    name: '箱包供应商',
+    code: 'S1003',
+    type: 'distributor',
+    level: 'A',
+    contact: '王经理',
+    phone: '13800138003',
+    status: 'inactive',
+    logo: defaultImages.supplier
+  },
+  {
+    id: 'S1004',
+    name: '运动用品公司',
+    code: 'S1004',
+    type: 'wholesaler',
+    level: 'C',
+    contact: '赵经理',
+    phone: '13800138004',
+    status: 'blacklisted',
+    logo: defaultImages.supplier
+  },
+  {
+    id: 'S1005',
+    name: '食品供应商',
+    code: 'S1005',
+    type: 'retailer',
+    level: 'B',
+    contact: '钱经理',
+    phone: '13800138005',
+    status: 'active',
+    logo: defaultImages.supplier
+  }
+])
+
+// 供应商统计数据
+const supplierStats = ref({
+  totalSuppliers: 1234,
+  activeSuppliers: 1024,
+  inactiveSuppliers: 56,
+  blacklistedSuppliers: 12
+})
+
+// 计算属性
+const filteredSuppliers = computed(() => {
+  let result = [...mockSuppliers.value]
+  
+  // 搜索过滤
+  if (searchText.value) {
+    result = result.filter(supplier => 
+      supplier.name.includes(searchText.value) ||
+      supplier.code.includes(searchText.value)
+    )
+  }
+  
+  // 类型过滤
+  if (supplierType.value) {
+    result = result.filter(supplier => supplier.type === supplierType.value)
+  }
+  
+  // 状态过滤
+  if (supplierStatus.value) {
+    result = result.filter(supplier => supplier.status === supplierStatus.value)
+  }
+  
+  // 等级过滤
+  if (supplierLevel.value) {
+    result = result.filter(supplier => supplier.level === supplierLevel.value)
+  }
+  
+  return result
+})
+
+const paginatedSuppliers = computed(() => {
+  const start = (currentPage.value - 1) * pageSize.value
+  const end = start + pageSize.value
+  return filteredSuppliers.value.slice(start, end)
+})
+
+const totalPages = computed(() => {
+  return Math.ceil(filteredSuppliers.value.length / pageSize.value)
+})
+
+// 方法
+const handleSearch = () => {
+  currentPage.value = 1
+}
+
+const handleTypeChange = () => {
+  currentPage.value = 1
+}
+
+const handleStatusChange = () => {
+  currentPage.value = 1
+}
+
+const handleLevelChange = () => {
+  currentPage.value = 1
+}
+
+const handlePageChange = (page) => {
+  currentPage.value = page
+}
+
+const handleAddSupplier = () => {
+  console.log('新增供应商')
+}
+
+const handleViewSupplier = (supplier) => {
+  console.log('查看供应商:', supplier)
+}
+
+const handleEditSupplier = (supplier) => {
+  console.log('编辑供应商:', supplier)
+}
+
+const handleDeleteSupplier = (supplier) => {
+  console.log('删除供应商:', supplier)
+}
+
+const handleExportSuppliers = () => {
+  console.log('导出供应商')
+}
+
+// Mock data
+const mockTypeData = [
+  { value: 40, name: '生产商' },
+  { value: 30, name: '经销商' },
+  { value: 20, name: '批发商' },
+  { value: 10, name: '零售商' }
+]
+
+const mockLevelData = [
+  { value: 50, name: 'A级' },
+  { value: 30, name: 'B级' },
+  { value: 20, name: 'C级' }
+]
+
+// 初始化类型图表
+const initTypeChart = () => {
+  if (!typeChartRef.value) return
+  
+  typeChart = echarts.init(typeChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '供应商类型',
+        type: 'pie',
+        radius: '50%',
+        data: mockTypeData,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+  typeChart.setOption(option)
+}
+
+// 初始化等级图表
+const initLevelChart = () => {
+  if (!levelChartRef.value) return
+  
+  levelChart = echarts.init(levelChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'vertical',
+      left: 'left'
+    },
+    series: [
+      {
+        name: '供应商等级',
+        type: 'pie',
+        radius: '50%',
+        data: mockLevelData,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+  levelChart.setOption(option)
+}
+
+// 处理窗口大小变化
+const handleResize = () => {
+  typeChart?.resize()
+  levelChart?.resize()
+}
+
+onMounted(() => {
+  initTypeChart()
+  initLevelChart()
+  window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize)
+  typeChart?.dispose()
+  levelChart?.dispose()
+})
+</script>
+
+<style scoped>
+@media (max-width: 475px) {
+  .grid {
+    @apply grid-cols-1;
+  }
+  table {
+    @apply block overflow-x-auto whitespace-nowrap;
+  }
+}
+
+/* 供应商类型标签样式 */
+.type-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.type-manufacturer {
+  @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-400;
+}
+
+.type-distributor {
+  @apply bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-400;
+}
+
+.type-wholesaler {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.type-retailer {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+/* 供应商等级标签样式 */
+.level-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.level-A {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+.level-B {
+  @apply bg-orange-100 dark:bg-orange-900 text-orange-800 dark:text-orange-400;
+}
+
+.level-C {
+  @apply bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-400;
+}
+
+/* 供应商状态标签样式 */
+.status-tag {
+  @apply px-2 inline-flex text-xs leading-5 font-semibold rounded-full;
+}
+
+.status-active {
+  @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-400;
+}
+
+.status-inactive {
+  @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-400;
+}
+
+.status-blacklisted {
+  @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-400;
+}
+
+/* 操作按钮样式 */
+.action-button {
+  @apply text-sm font-medium mr-3;
+}
+
+.view-button {
+  @apply text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300;
+}
+
+.edit-button {
+  @apply text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300;
+}
+
+.delete-button {
+  @apply text-red-600 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300;
+}
+
+/* 分页样式 */
+.pagination-button {
+  @apply relative inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600;
+}
+
+.pagination-button-active {
+  @apply bg-blue-600 text-white border-blue-600;
+}
+
+/* 加载动画 */
+.loading-spinner {
+  @apply animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600;
+}
+</style> 

+ 310 - 0
src/assets/templates/prototype/system/LogManagement.vue

@@ -0,0 +1,310 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">日志管理</h1>
+          <div class="flex space-x-4">
+            <button @click="clearLogs" class="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700">
+              清空日志
+            </button>
+            <button @click="exportLogs" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出日志
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 日志统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总日志数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalLogs }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">错误日志</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ errorLogs }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">警告日志</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ warningLogs }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">信息日志</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ infoLogs }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">日志类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="error">错误日志</option>
+              <option value="warning">警告日志</option>
+              <option value="info">信息日志</option>
+              <option value="debug">调试日志</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">模块</label>
+            <select v-model="filters.module" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="module in modules" :key="module" :value="module">{{ module }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <div class="flex space-x-2">
+              <input type="datetime-local" v-model="filters.startTime" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="datetime-local" v-model="filters.endTime" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="日志内容/用户" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 日志列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">模块</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">用户</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">内容</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="log in filteredLogs" :key="log.id">
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                {{ formatDateTime(log.timestamp) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getTypeClass(log.type)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getTypeName(log.type) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                {{ log.module }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                {{ log.user }}
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ log.content }}</div>
+                <div v-if="log.details" class="text-xs text-gray-500 dark:text-gray-400 mt-1">{{ log.details }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewLog(log)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300">查看详情</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 日志详情模态框 -->
+    <div v-if="showLogDetailModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">日志详情</h2>
+        <div class="space-y-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">时间</label>
+            <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ formatDateTime(selectedLog.timestamp) }}</p>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">类型</label>
+            <p class="mt-1">
+              <span :class="getTypeClass(selectedLog.type)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                {{ getTypeName(selectedLog.type) }}
+              </span>
+            </p>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">模块</label>
+            <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ selectedLog.module }}</p>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">用户</label>
+            <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ selectedLog.user }}</p>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">内容</label>
+            <p class="mt-1 text-sm text-gray-900 dark:text-white">{{ selectedLog.content }}</p>
+          </div>
+          <div v-if="selectedLog.details">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">详细信息</label>
+            <pre class="mt-1 text-sm text-gray-900 dark:text-white whitespace-pre-wrap">{{ selectedLog.details }}</pre>
+          </div>
+          <div class="flex justify-end">
+            <button @click="showLogDetailModal = false" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              关闭
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 日志数据
+const logs = ref([
+  {
+    id: 1,
+    timestamp: '2024-03-15T10:30:00',
+    type: 'error',
+    module: '用户管理',
+    user: 'admin',
+    content: '用户登录失败',
+    details: 'IP: 192.168.1.1\n原因: 密码错误'
+  },
+  {
+    id: 2,
+    timestamp: '2024-03-15T10:31:00',
+    type: 'warning',
+    module: '系统管理',
+    user: 'system',
+    content: '系统资源使用率过高',
+    details: 'CPU: 85%\n内存: 75%'
+  },
+  {
+    id: 3,
+    timestamp: '2024-03-15T10:32:00',
+    type: 'info',
+    module: '项目管理',
+    user: 'user1',
+    content: '创建新项目',
+    details: '项目名称: 测试项目\n创建人: user1'
+  },
+  {
+    id: 4,
+    timestamp: '2024-03-15T10:33:00',
+    type: 'debug',
+    module: '权限管理',
+    user: 'admin',
+    content: '权限检查',
+    details: '用户: user1\n权限: read'
+  }
+])
+
+// 模块列表
+const modules = ref([
+  '用户管理',
+  '系统管理',
+  '项目管理',
+  '权限管理',
+  '日志管理'
+])
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  module: '',
+  startTime: '',
+  endTime: '',
+  search: ''
+})
+
+// 模态框状态
+const showLogDetailModal = ref(false)
+const selectedLog = ref({})
+
+// 计算属性
+const filteredLogs = computed(() => {
+  return logs.value.filter(log => {
+    const matchesType = !filters.value.type || log.type === filters.value.type
+    const matchesModule = !filters.value.module || log.module === filters.value.module
+    const matchesTime = (!filters.value.startTime || log.timestamp >= filters.value.startTime) &&
+                       (!filters.value.endTime || log.timestamp <= filters.value.endTime)
+    const matchesSearch = !filters.value.search ||
+      log.content.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      log.user.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesModule && matchesTime && matchesSearch
+  })
+})
+
+const totalLogs = computed(() => {
+  return logs.value.length
+})
+
+const errorLogs = computed(() => {
+  return logs.value.filter(log => log.type === 'error').length
+})
+
+const warningLogs = computed(() => {
+  return logs.value.filter(log => log.type === 'warning').length
+})
+
+const infoLogs = computed(() => {
+  return logs.value.filter(log => log.type === 'info').length
+})
+
+// 获取日志类型名称
+const getTypeName = (type) => {
+  const names = {
+    error: '错误',
+    warning: '警告',
+    info: '信息',
+    debug: '调试'
+  }
+  return names[type] || type
+}
+
+// 获取日志类型样式
+const getTypeClass = (type) => {
+  const classes = {
+    error: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+    warning: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    info: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+    debug: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+  return classes[type] || classes.info
+}
+
+// 格式化日期时间
+const formatDateTime = (datetime) => {
+  const date = new Date(datetime)
+  return date.toLocaleString('zh-CN', {
+    year: 'numeric',
+    month: '2-digit',
+    day: '2-digit',
+    hour: '2-digit',
+    minute: '2-digit',
+    second: '2-digit'
+  })
+}
+
+// 查看日志详情
+const viewLog = (log) => {
+  selectedLog.value = log
+  showLogDetailModal.value = true
+}
+
+// 清空日志
+const clearLogs = () => {
+  if (confirm('确定要清空所有日志吗?此操作不可恢复。')) {
+    logs.value = []
+  }
+}
+
+// 导出日志
+const exportLogs = () => {
+  // 实现导出日志的逻辑
+  console.log('导出日志')
+}
+</script> 

+ 469 - 0
src/assets/templates/prototype/system/NotificationManagement.vue

@@ -0,0 +1,469 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">通知管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddNotificationModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              发送通知
+            </button>
+            <button @click="showSettingsModal = true" class="bg-gray-600 text-white px-4 py-2 rounded-md hover:bg-gray-700">
+              通知设置
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 通知统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总通知数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalNotifications }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">未读通知</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ unreadNotifications }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">系统通知</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ systemNotifications }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">用户通知</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ userNotifications }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">通知类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="system">系统通知</option>
+              <option value="user">用户通知</option>
+              <option value="alert">提醒通知</option>
+              <option value="announcement">公告通知</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="unread">未读</option>
+              <option value="read">已读</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时间范围</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="通知标题/内容" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 通知列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">通知信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">接收者</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">时间</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="notification in filteredNotifications" :key="notification.id">
+              <td class="px-6 py-4">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ notification.title }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ notification.content }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getTypeClass(notification.type)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getTypeName(notification.type) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                {{ notification.receiver }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(notification.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(notification.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
+                {{ formatDateTime(notification.createdAt) }}
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewNotification(notification)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="markAsRead(notification)" v-if="notification.status === 'unread'" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">标记已读</button>
+                <button @click="deleteNotification(notification)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 发送通知模态框 -->
+    <div v-if="showAddNotificationModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">发送通知</h2>
+        <form @submit.prevent="addNotification">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">通知类型</label>
+            <select v-model="newNotification.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="system">系统通知</option>
+              <option value="user">用户通知</option>
+              <option value="alert">提醒通知</option>
+              <option value="announcement">公告通知</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">通知标题</label>
+            <input type="text" v-model="newNotification.title" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">通知内容</label>
+            <textarea v-model="newNotification.content" rows="3" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">接收者</label>
+            <select v-model="newNotification.receiver" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="all">所有用户</option>
+              <option value="admin">管理员</option>
+              <option value="user">普通用户</option>
+            </select>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddNotificationModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              发送
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 通知设置模态框 -->
+    <div v-if="showSettingsModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">通知设置</h2>
+        <div class="space-y-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">通知方式</label>
+            <div class="space-y-2">
+              <div class="flex items-center">
+                <input type="checkbox" v-model="settings.email" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">邮件通知</label>
+              </div>
+              <div class="flex items-center">
+                <input type="checkbox" v-model="settings.sms" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">短信通知</label>
+              </div>
+              <div class="flex items-center">
+                <input type="checkbox" v-model="settings.push" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">推送通知</label>
+              </div>
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">通知时间</label>
+            <select v-model="settings.notificationTime" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="immediate">立即通知</option>
+              <option value="daily">每日汇总</option>
+              <option value="weekly">每周汇总</option>
+            </select>
+          </div>
+          <div class="flex justify-end">
+            <button @click="saveSettings" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              保存设置
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 通知数据
+const notifications = ref([
+  {
+    id: 1,
+    type: 'system',
+    title: '系统维护通知',
+    content: '系统将于今晚22:00进行例行维护,预计持续2小时。',
+    receiver: 'all',
+    status: 'unread',
+    createdAt: '2024-03-15T10:00:00'
+  },
+  {
+    id: 2,
+    type: 'user',
+    title: '新消息提醒',
+    content: '您有3条未读消息,请及时查看。',
+    receiver: 'user',
+    status: 'read',
+    createdAt: '2024-03-15T09:30:00'
+  },
+  {
+    id: 3,
+    type: 'alert',
+    title: '任务截止提醒',
+    content: '您的任务"项目报告"将于今天18:00截止。',
+    receiver: 'user',
+    status: 'unread',
+    createdAt: '2024-03-15T09:00:00'
+  },
+  {
+    id: 4,
+    type: 'announcement',
+    title: '公司公告',
+    content: '公司将于下周一举行全体员工大会,请准时参加。',
+    receiver: 'all',
+    status: 'read',
+    createdAt: '2024-03-15T08:00:00'
+  }
+])
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  status: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddNotificationModal = ref(false)
+const showSettingsModal = ref(false)
+
+// 新通知表单
+const newNotification = ref({
+  type: 'system',
+  title: '',
+  content: '',
+  receiver: 'all'
+})
+
+// 通知设置
+const settings = ref({
+  email: true,
+  sms: false,
+  push: true,
+  notificationTime: 'immediate'
+})
+
+// 计算属性
+const filteredNotifications = computed(() => {
+  try {
+    return notifications.value.filter(notification => {
+      if (!notification) return false
+      
+      const matchesType = !filters.value.type || notification.type === filters.value.type
+      const matchesStatus = !filters.value.status || notification.status === filters.value.status
+      
+      // 修复日期比较
+      const notificationDate = notification.createdAt ? new Date(notification.createdAt).toISOString().split('T')[0] : ''
+      const matchesDate = (!filters.value.startDate || notificationDate >= filters.value.startDate) &&
+                         (!filters.value.endDate || notificationDate <= filters.value.endDate)
+      
+      const matchesSearch = !filters.value.search ||
+        (notification.title && notification.title.toLowerCase().includes(filters.value.search.toLowerCase())) ||
+        (notification.content && notification.content.toLowerCase().includes(filters.value.search.toLowerCase()))
+      
+      return matchesType && matchesStatus && matchesDate && matchesSearch
+    })
+  } catch (error) {
+    console.error('过滤通知时出错:', error)
+    return []
+  }
+})
+
+const totalNotifications = computed(() => {
+  return notifications.value.length || 0
+})
+
+const unreadNotifications = computed(() => {
+  return notifications.value.filter(n => n && n.status === 'unread').length || 0
+})
+
+const systemNotifications = computed(() => {
+  return notifications.value.filter(n => n && n.type === 'system').length || 0
+})
+
+const userNotifications = computed(() => {
+  return notifications.value.filter(n => n && n.type === 'user').length || 0
+})
+
+// 方法
+const getTypeClass = (type) => {
+  try {
+    const classes = {
+      system: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+      user: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300',
+      alert: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300',
+      announcement: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300'
+    }
+    return classes[type] || 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  } catch (error) {
+    console.error('获取类型样式时出错:', error)
+    return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+}
+
+const getTypeName = (type) => {
+  try {
+    const names = {
+      system: '系统通知',
+      user: '用户通知',
+      alert: '提醒通知',
+      announcement: '公告通知'
+    }
+    return names[type] || '未知类型'
+  } catch (error) {
+    console.error('获取类型名称时出错:', error)
+    return '未知类型'
+  }
+}
+
+const getStatusClass = (status) => {
+  try {
+    return status === 'unread'
+      ? 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+      : 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300'
+  } catch (error) {
+    console.error('获取状态样式时出错:', error)
+    return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300'
+  }
+}
+
+const getStatusName = (status) => {
+  try {
+    return status === 'unread' ? '未读' : '已读'
+  } catch (error) {
+    console.error('获取状态名称时出错:', error)
+    return '未知状态'
+  }
+}
+
+const formatDateTime = (dateTime) => {
+  try {
+    if (!dateTime) return '未知时间'
+    const date = new Date(dateTime)
+    if (isNaN(date.getTime())) {
+      return '无效日期'
+    }
+    return date.toLocaleString('zh-CN', {
+      year: 'numeric',
+      month: '2-digit',
+      day: '2-digit',
+      hour: '2-digit',
+      minute: '2-digit'
+    })
+  } catch (error) {
+    console.error('日期格式化错误:', error)
+    return '无效日期'
+  }
+}
+
+const addNotification = () => {
+  try {
+    if (!newNotification.value.title || !newNotification.value.content) {
+      alert('请填写通知标题和内容')
+      return
+    }
+    
+    const notification = {
+      id: notifications.value.length + 1,
+      ...newNotification.value,
+      status: 'unread',
+      createdAt: new Date().toISOString()
+    }
+    notifications.value.unshift(notification)
+    showAddNotificationModal.value = false
+    resetNewNotification()
+  } catch (error) {
+    console.error('添加通知错误:', error)
+    alert('添加通知失败,请重试')
+  }
+}
+
+const resetNewNotification = () => {
+  try {
+    newNotification.value = {
+      type: 'system',
+      title: '',
+      content: '',
+      receiver: 'all'
+    }
+  } catch (error) {
+    console.error('重置通知表单错误:', error)
+  }
+}
+
+const viewNotification = (notification) => {
+  try {
+    if (!notification) return
+    // 实现查看通知详情的逻辑
+    console.log('查看通知:', notification)
+  } catch (error) {
+    console.error('查看通知错误:', error)
+  }
+}
+
+const markAsRead = (notification) => {
+  try {
+    if (!notification) return
+    notification.status = 'read'
+  } catch (error) {
+    console.error('标记已读错误:', error)
+  }
+}
+
+const deleteNotification = (notification) => {
+  try {
+    if (!notification) return
+    if (confirm('确定要删除这条通知吗?')) {
+      const index = notifications.value.findIndex(n => n && n.id === notification.id)
+      if (index !== -1) {
+        notifications.value.splice(index, 1)
+      }
+    }
+  } catch (error) {
+    console.error('删除通知错误:', error)
+  }
+}
+
+const saveSettings = () => {
+  try {
+    // 实现保存设置的逻辑
+    console.log('保存设置:', settings.value)
+    showSettingsModal.value = false
+  } catch (error) {
+    console.error('保存设置错误:', error)
+    alert('保存设置失败,请重试')
+  }
+}
+</script> 

+ 416 - 0
src/assets/templates/prototype/system/PermissionManagement.vue

@@ -0,0 +1,416 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">权限管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddPermissionModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              添加权限
+            </button>
+            <button @click="showAddGroupModal = true" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700">
+              创建权限组
+            </button>
+            <button @click="exportPermissionData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 权限统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总权限数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalPermissions }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">权限组数</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ totalGroups }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">系统权限</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ systemPermissions }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">自定义权限</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ customPermissions }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="system">系统权限</option>
+              <option value="custom">自定义权限</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限组</label>
+            <select v-model="filters.group" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="group in permissionGroups" :key="group.id" :value="group.id">{{ group.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="active">启用</option>
+              <option value="inactive">禁用</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="权限名称/描述" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 权限列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">权限信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">权限组</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="permission in filteredPermissions" :key="permission.id">
+              <td class="px-6 py-4">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ permission.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ permission.description }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getTypeClass(permission.type)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getTypeName(permission.type) }}
+                </span>
+              </td>
+              <td class="px-6 py-4">
+                <span class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300">
+                  {{ getGroupName(permission.groupId) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(permission.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(permission.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewPermission(permission)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editPermission(permission)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deletePermission(permission)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 添加权限模态框 -->
+    <div v-if="showAddPermissionModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加权限</h2>
+        <form @submit.prevent="addPermission">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限名称</label>
+            <input type="text" v-model="newPermission.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限描述</label>
+            <textarea v-model="newPermission.description" rows="3" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限类型</label>
+            <select v-model="newPermission.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="system">系统权限</option>
+              <option value="custom">自定义权限</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限组</label>
+            <select v-model="newPermission.groupId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="group in permissionGroups" :key="group.id" :value="group.id">{{ group.name }}</option>
+            </select>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddPermissionModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+
+    <!-- 创建权限组模态框 -->
+    <div v-if="showAddGroupModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建权限组</h2>
+        <form @submit.prevent="addGroup">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限组名称</label>
+            <input type="text" v-model="newGroup.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限组描述</label>
+            <textarea v-model="newGroup.description" rows="3" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddGroupModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 权限数据
+const permissions = ref([
+  {
+    id: 1,
+    name: '系统管理',
+    description: '系统基础管理权限',
+    type: 'system',
+    groupId: 1,
+    status: 'active',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 2,
+    name: '用户管理',
+    description: '用户信息管理权限',
+    type: 'system',
+    groupId: 1,
+    status: 'active',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 3,
+    name: '角色管理',
+    description: '角色配置管理权限',
+    type: 'system',
+    groupId: 1,
+    status: 'active',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 4,
+    name: '项目管理',
+    description: '项目相关操作权限',
+    type: 'custom',
+    groupId: 2,
+    status: 'active',
+    createdAt: '2024-03-01T00:00:00'
+  }
+])
+
+// 权限组数据
+const permissionGroups = ref([
+  {
+    id: 1,
+    name: '系统权限组',
+    description: '系统基础功能权限组',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 2,
+    name: '业务权限组',
+    description: '业务功能相关权限组',
+    createdAt: '2024-01-01T00:00:00'
+  }
+])
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  group: '',
+  status: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddPermissionModal = ref(false)
+const showAddGroupModal = ref(false)
+
+// 新权限表单
+const newPermission = ref({
+  name: '',
+  description: '',
+  type: 'custom',
+  groupId: '',
+  status: 'active'
+})
+
+// 新权限组表单
+const newGroup = ref({
+  name: '',
+  description: ''
+})
+
+// 计算属性
+const filteredPermissions = computed(() => {
+  return permissions.value.filter(permission => {
+    const matchesType = !filters.value.type || permission.type === filters.value.type
+    const matchesGroup = !filters.value.group || permission.groupId === filters.value.group
+    const matchesStatus = !filters.value.status || permission.status === filters.value.status
+    const matchesSearch = !filters.value.search ||
+      permission.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      permission.description.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesGroup && matchesStatus && matchesSearch
+  })
+})
+
+const totalPermissions = computed(() => {
+  return permissions.value.length
+})
+
+const totalGroups = computed(() => {
+  return permissionGroups.value.length
+})
+
+const systemPermissions = computed(() => {
+  return permissions.value.filter(p => p.type === 'system').length
+})
+
+const customPermissions = computed(() => {
+  return permissions.value.filter(p => p.type === 'custom').length
+})
+
+// 获取权限类型名称
+const getTypeName = (type) => {
+  const names = {
+    system: '系统权限',
+    custom: '自定义权限'
+  }
+  return names[type] || type
+}
+
+// 获取权限类型样式
+const getTypeClass = (type) => {
+  const classes = {
+    system: 'bg-purple-100 text-purple-800 dark:bg-purple-700 dark:text-purple-300',
+    custom: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300'
+  }
+  return classes[type] || classes.custom
+}
+
+// 获取权限组名称
+const getGroupName = (groupId) => {
+  const group = permissionGroups.value.find(g => g.id === groupId)
+  return group ? group.name : '未知权限组'
+}
+
+// 获取状态名称
+const getStatusName = (status) => {
+  const names = {
+    active: '启用',
+    inactive: '禁用'
+  }
+  return names[status] || status
+}
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    inactive: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[status] || classes.active
+}
+
+// 添加权限
+const addPermission = () => {
+  const permission = {
+    id: permissions.value.length + 1,
+    createdAt: new Date().toISOString(),
+    ...newPermission.value
+  }
+  
+  permissions.value.push(permission)
+  showAddPermissionModal.value = false
+  resetNewPermission()
+}
+
+// 重置新权限表单
+const resetNewPermission = () => {
+  newPermission.value = {
+    name: '',
+    description: '',
+    type: 'custom',
+    groupId: '',
+    status: 'active'
+  }
+}
+
+// 添加权限组
+const addGroup = () => {
+  const group = {
+    id: permissionGroups.value.length + 1,
+    createdAt: new Date().toISOString(),
+    ...newGroup.value
+  }
+  
+  permissionGroups.value.push(group)
+  showAddGroupModal.value = false
+  resetNewGroup()
+}
+
+// 重置新权限组表单
+const resetNewGroup = () => {
+  newGroup.value = {
+    name: '',
+    description: ''
+  }
+}
+
+// 查看权限
+const viewPermission = (permission) => {
+  // 实现查看权限的逻辑
+  console.log('查看权限:', permission)
+}
+
+// 编辑权限
+const editPermission = (permission) => {
+  // 实现编辑权限的逻辑
+  console.log('编辑权限:', permission)
+}
+
+// 删除权限
+const deletePermission = (permission) => {
+  if (confirm(`确定要删除权限 ${permission.name} 吗?`)) {
+    const index = permissions.value.findIndex(p => p.id === permission.id)
+    if (index !== -1) {
+      permissions.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出权限数据
+const exportPermissionData = () => {
+  // 实现导出权限数据的逻辑
+  console.log('导出权限数据')
+}
+</script> 

+ 363 - 0
src/assets/templates/prototype/system/RoleManagement.vue

@@ -0,0 +1,363 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">角色管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddRoleModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              创建角色
+            </button>
+            <button @click="exportRoleData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 角色统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总角色数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalRoles }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">系统角色</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ systemRoles }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">自定义角色</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ customRoles }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">使用中角色</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ activeRoles }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">角色类型</label>
+            <select v-model="filters.type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="system">系统角色</option>
+              <option value="custom">自定义角色</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="active">启用</option>
+              <option value="inactive">禁用</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">创建时间</label>
+            <div class="flex space-x-2">
+              <input type="date" v-model="filters.startDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <input type="date" v-model="filters.endDate" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="角色名称/描述" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 角色列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">角色信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">类型</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">权限</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="role in filteredRoles" :key="role.id">
+              <td class="px-6 py-4">
+                <div class="text-sm font-medium text-gray-900 dark:text-white">{{ role.name }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ role.description }}</div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getTypeClass(role.type)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getTypeName(role.type) }}
+                </span>
+              </td>
+              <td class="px-6 py-4">
+                <div class="flex flex-wrap gap-1">
+                  <span v-for="permission in role.permissions" :key="permission" class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300">
+                    {{ getPermissionName(permission) }}
+                  </span>
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(role.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(role.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewRole(role)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editRole(role)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteRole(role)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 创建角色模态框 -->
+    <div v-if="showAddRoleModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">创建角色</h2>
+        <form @submit.prevent="addRole">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">角色名称</label>
+            <input type="text" v-model="newRole.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">角色描述</label>
+            <textarea v-model="newRole.description" rows="3" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">角色类型</label>
+            <select v-model="newRole.type" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="system">系统角色</option>
+              <option value="custom">自定义角色</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">权限设置</label>
+            <div class="space-y-2">
+              <div v-for="permission in permissions" :key="permission.id" class="flex items-center">
+                <input type="checkbox" :id="'permission-' + permission.id" v-model="newRole.permissions" :value="permission.id" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                <label :for="'permission-' + permission.id" class="ml-2 text-sm text-gray-700 dark:text-gray-300">{{ permission.name }}</label>
+              </div>
+            </div>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddRoleModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 角色数据
+const roles = ref([
+  {
+    id: 1,
+    name: '超级管理员',
+    description: '系统最高权限角色',
+    type: 'system',
+    permissions: [1, 2, 3, 4, 5, 6, 7, 8],
+    status: 'active',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 2,
+    name: '部门管理员',
+    description: '部门管理权限',
+    type: 'system',
+    permissions: [2, 3, 4, 5],
+    status: 'active',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 3,
+    name: '普通用户',
+    description: '基础操作权限',
+    type: 'system',
+    permissions: [3, 4],
+    status: 'active',
+    createdAt: '2024-01-01T00:00:00'
+  },
+  {
+    id: 4,
+    name: '项目管理员',
+    description: '项目管理权限',
+    type: 'custom',
+    permissions: [3, 4, 5, 6],
+    status: 'active',
+    createdAt: '2024-03-01T00:00:00'
+  }
+])
+
+// 权限数据
+const permissions = ref([
+  { id: 1, name: '系统管理' },
+  { id: 2, name: '用户管理' },
+  { id: 3, name: '角色管理' },
+  { id: 4, name: '权限管理' },
+  { id: 5, name: '数据管理' },
+  { id: 6, name: '日志管理' },
+  { id: 7, name: '系统设置' },
+  { id: 8, name: '高级功能' }
+])
+
+// 筛选条件
+const filters = ref({
+  type: '',
+  status: '',
+  startDate: '',
+  endDate: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddRoleModal = ref(false)
+
+// 新角色表单
+const newRole = ref({
+  name: '',
+  description: '',
+  type: 'custom',
+  permissions: [],
+  status: 'active'
+})
+
+// 计算属性
+const filteredRoles = computed(() => {
+  return roles.value.filter(role => {
+    const matchesType = !filters.value.type || role.type === filters.value.type
+    const matchesStatus = !filters.value.status || role.status === filters.value.status
+    const matchesDate = (!filters.value.startDate || role.createdAt >= filters.value.startDate) &&
+                       (!filters.value.endDate || role.createdAt <= filters.value.endDate)
+    const matchesSearch = !filters.value.search ||
+      role.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      role.description.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesType && matchesStatus && matchesDate && matchesSearch
+  })
+})
+
+const totalRoles = computed(() => {
+  return roles.value.length
+})
+
+const systemRoles = computed(() => {
+  return roles.value.filter(role => role.type === 'system').length
+})
+
+const customRoles = computed(() => {
+  return roles.value.filter(role => role.type === 'custom').length
+})
+
+const activeRoles = computed(() => {
+  return roles.value.filter(role => role.status === 'active').length
+})
+
+// 获取角色类型名称
+const getTypeName = (type) => {
+  const names = {
+    system: '系统角色',
+    custom: '自定义角色'
+  }
+  return names[type] || type
+}
+
+// 获取角色类型样式
+const getTypeClass = (type) => {
+  const classes = {
+    system: 'bg-purple-100 text-purple-800 dark:bg-purple-700 dark:text-purple-300',
+    custom: 'bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300'
+  }
+  return classes[type] || classes.custom
+}
+
+// 获取权限名称
+const getPermissionName = (permissionId) => {
+  const permission = permissions.value.find(p => p.id === permissionId)
+  return permission ? permission.name : '未知权限'
+}
+
+// 获取状态名称
+const getStatusName = (status) => {
+  const names = {
+    active: '启用',
+    inactive: '禁用'
+  }
+  return names[status] || status
+}
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    inactive: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[status] || classes.active
+}
+
+// 添加角色
+const addRole = () => {
+  const role = {
+    id: roles.value.length + 1,
+    createdAt: new Date().toISOString(),
+    ...newRole.value
+  }
+  
+  roles.value.push(role)
+  showAddRoleModal.value = false
+  resetNewRole()
+}
+
+// 重置新角色表单
+const resetNewRole = () => {
+  newRole.value = {
+    name: '',
+    description: '',
+    type: 'custom',
+    permissions: [],
+    status: 'active'
+  }
+}
+
+// 查看角色
+const viewRole = (role) => {
+  // 实现查看角色的逻辑
+  console.log('查看角色:', role)
+}
+
+// 编辑角色
+const editRole = (role) => {
+  // 实现编辑角色的逻辑
+  console.log('编辑角色:', role)
+}
+
+// 删除角色
+const deleteRole = (role) => {
+  if (confirm(`确定要删除角色 ${role.name} 吗?`)) {
+    const index = roles.value.findIndex(r => r.id === role.id)
+    if (index !== -1) {
+      roles.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出角色数据
+const exportRoleData = () => {
+  // 实现导出角色数据的逻辑
+  console.log('导出角色数据')
+}
+</script> 

+ 181 - 0
src/assets/templates/prototype/system/SystemSettings.vue

@@ -0,0 +1,181 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">系统设置</h1>
+          <div class="flex space-x-4">
+            <button @click="saveSettings" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              保存设置
+            </button>
+            <button @click="resetSettings" class="bg-gray-600 text-white px-4 py-2 rounded-md hover:bg-gray-700">
+              重置设置
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 设置卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
+        <!-- 基本设置 -->
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4">基本设置</h2>
+          <div class="space-y-4">
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">系统名称</label>
+              <input type="text" v-model="settings.systemName" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">系统版本</label>
+              <input type="text" v-model="settings.systemVersion" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">系统语言</label>
+              <select v-model="settings.language" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <option value="zh-CN">简体中文</option>
+                <option value="en-US">English</option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">时区</label>
+              <select v-model="settings.timezone" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <option value="Asia/Shanghai">Asia/Shanghai (GMT+8)</option>
+                <option value="America/New_York">America/New_York (GMT-5)</option>
+                <option value="Europe/London">Europe/London (GMT+0)</option>
+              </select>
+            </div>
+          </div>
+        </div>
+
+        <!-- 主题设置 -->
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4">主题设置</h2>
+          <div class="space-y-4">
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">主题模式</label>
+              <select v-model="settings.theme" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <option value="light">浅色主题</option>
+                <option value="dark">深色主题</option>
+                <option value="system">跟随系统</option>
+              </select>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">主色调</label>
+              <div class="flex space-x-2">
+                <button v-for="color in colors" :key="color.value"
+                  @click="settings.primaryColor = color.value"
+                  :class="[
+                    'w-8 h-8 rounded-full',
+                    color.class,
+                    settings.primaryColor === color.value ? 'ring-2 ring-offset-2 ring-blue-500' : ''
+                  ]"
+                  :title="color.name"
+                ></button>
+              </div>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">字体大小</label>
+              <select v-model="settings.fontSize" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <option value="small">小</option>
+                <option value="medium">中</option>
+                <option value="large">大</option>
+              </select>
+            </div>
+          </div>
+        </div>
+
+        <!-- 安全设置 -->
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h2 class="text-lg font-medium text-gray-900 dark:text-white mb-4">安全设置</h2>
+          <div class="space-y-4">
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">密码策略</label>
+              <div class="space-y-2">
+                <div class="flex items-center">
+                  <input type="checkbox" v-model="settings.passwordPolicy.minLength" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                  <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">最小长度: 8位</label>
+                </div>
+                <div class="flex items-center">
+                  <input type="checkbox" v-model="settings.passwordPolicy.requireNumber" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                  <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">必须包含数字</label>
+                </div>
+                <div class="flex items-center">
+                  <input type="checkbox" v-model="settings.passwordPolicy.requireSpecial" class="rounded border-gray-300 text-blue-600 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600">
+                  <label class="ml-2 text-sm text-gray-700 dark:text-gray-300">必须包含特殊字符</label>
+                </div>
+              </div>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">登录失败锁定</label>
+              <div class="flex items-center">
+                <input type="number" v-model="settings.loginLock.attempts" min="1" class="w-20 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">次失败后锁定</span>
+                <input type="number" v-model="settings.loginLock.duration" min="1" class="w-20 ml-2 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">分钟</span>
+              </div>
+            </div>
+            <div>
+              <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">会话超时</label>
+              <div class="flex items-center">
+                <input type="number" v-model="settings.sessionTimeout" min="1" class="w-20 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+                <span class="ml-2 text-sm text-gray-700 dark:text-gray-300">分钟</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+// 系统设置
+const settings = ref({
+  systemName: '管理系统',
+  systemVersion: '1.0.0',
+  language: 'zh-CN',
+  timezone: 'Asia/Shanghai',
+  theme: 'light',
+  primaryColor: 'blue',
+  fontSize: 'medium',
+  passwordPolicy: {
+    minLength: true,
+    requireNumber: true,
+    requireSpecial: true
+  },
+  loginLock: {
+    attempts: 5,
+    duration: 30
+  },
+  sessionTimeout: 30
+})
+
+// 颜色选项
+const colors = [
+  { name: '蓝色', value: 'blue', class: 'bg-blue-500' },
+  { name: '绿色', value: 'green', class: 'bg-green-500' },
+  { name: '红色', value: 'red', class: 'bg-red-500' },
+  { name: '紫色', value: 'purple', class: 'bg-purple-500' },
+  { name: '黄色', value: 'yellow', class: 'bg-yellow-500' }
+]
+
+// 保存设置
+const saveSettings = () => {
+  // 实现保存设置的逻辑
+  console.log('保存设置:', settings.value)
+}
+
+// 重置设置
+const resetSettings = () => {
+  if (confirm('确定要重置所有设置吗?')) {
+    // 实现重置设置的逻辑
+    console.log('重置设置')
+  }
+}
+</script> 

+ 372 - 0
src/assets/templates/prototype/system/UserManagement.vue

@@ -0,0 +1,372 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-gray-900">
+    <!-- 顶部导航 -->
+    <div class="bg-white dark:bg-gray-800 shadow">
+      <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
+        <div class="flex justify-between items-center">
+          <h1 class="text-2xl font-bold text-gray-900 dark:text-white">用户管理</h1>
+          <div class="flex space-x-4">
+            <button @click="showAddUserModal = true" class="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700">
+              添加用户
+            </button>
+            <button @click="exportUserData" class="bg-purple-600 text-white px-4 py-2 rounded-md hover:bg-purple-700">
+              导出数据
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 主要内容区域 -->
+    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
+      <!-- 用户统计卡片 -->
+      <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6">
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">总用户数</h3>
+          <p class="mt-2 text-3xl font-bold text-blue-600 dark:text-blue-400">{{ totalUsers }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">活跃用户</h3>
+          <p class="mt-2 text-3xl font-bold text-green-600 dark:text-green-400">{{ activeUsers }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">管理员</h3>
+          <p class="mt-2 text-3xl font-bold text-yellow-600 dark:text-yellow-400">{{ adminUsers }}</p>
+        </div>
+        <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
+          <h3 class="text-lg font-medium text-gray-900 dark:text-white">本周新增</h3>
+          <p class="mt-2 text-3xl font-bold text-red-600 dark:text-red-400">{{ weeklyNewUsers }}</p>
+        </div>
+      </div>
+
+      <!-- 搜索和筛选 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="filters.department" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">角色</label>
+            <select v-model="filters.role" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option v-for="role in roles" :key="role.id" :value="role.id">{{ role.name }}</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">状态</label>
+            <select v-model="filters.status" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option value="">全部</option>
+              <option value="active">活跃</option>
+              <option value="inactive">未激活</option>
+              <option value="locked">已锁定</option>
+            </select>
+          </div>
+          <div>
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">搜索</label>
+            <input type="text" v-model="filters.search" placeholder="用户名/姓名/邮箱" class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+        </div>
+      </div>
+
+      <!-- 用户列表 -->
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden">
+        <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
+          <thead class="bg-gray-50 dark:bg-gray-700">
+            <tr>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">用户信息</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">部门/职位</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">角色</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">状态</th>
+              <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">操作</th>
+            </tr>
+          </thead>
+          <tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
+            <tr v-for="user in filteredUsers" :key="user.id">
+              <td class="px-6 py-4">
+                <div class="flex items-center">
+                  <div class="flex-shrink-0 h-10 w-10">
+                    <img class="h-10 w-10 rounded-full" :src="user.avatar" :alt="user.name">
+                  </div>
+                  <div class="ml-4">
+                    <div class="text-sm font-medium text-gray-900 dark:text-white">{{ user.name }}</div>
+                    <div class="text-sm text-gray-500 dark:text-gray-400">{{ user.email }}</div>
+                  </div>
+                </div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="text-sm text-gray-900 dark:text-white">{{ getDepartmentName(user.departmentId) }}</div>
+                <div class="text-sm text-gray-500 dark:text-gray-400">{{ user.position }}</div>
+              </td>
+              <td class="px-6 py-4">
+                <div class="flex flex-wrap gap-1">
+                  <span v-for="roleId in user.roles" :key="roleId" class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800 dark:bg-blue-700 dark:text-blue-300">
+                    {{ getRoleName(roleId) }}
+                  </span>
+                </div>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap">
+                <span :class="getStatusClass(user.status)" class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full">
+                  {{ getStatusName(user.status) }}
+                </span>
+              </td>
+              <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
+                <button @click="viewUser(user)" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300 mr-3">查看</button>
+                <button @click="editUser(user)" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300 mr-3">编辑</button>
+                <button @click="deleteUser(user)" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">删除</button>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <!-- 添加用户模态框 -->
+    <div v-if="showAddUserModal" class="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
+      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6">
+        <h2 class="text-xl font-bold mb-4 text-gray-900 dark:text-white">添加用户</h2>
+        <form @submit.prevent="addUser">
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">用户名</label>
+            <input type="text" v-model="newUser.username" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">姓名</label>
+            <input type="text" v-model="newUser.name" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">邮箱</label>
+            <input type="email" v-model="newUser.email" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">部门</label>
+            <select v-model="newUser.departmentId" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="dept in departments" :key="dept.id" :value="dept.id">{{ dept.name }}</option>
+            </select>
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">职位</label>
+            <input type="text" v-model="newUser.position" required class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+          </div>
+          <div class="mb-4">
+            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">角色</label>
+            <select v-model="newUser.roles" multiple class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
+              <option v-for="role in roles" :key="role.id" :value="role.id">{{ role.name }}</option>
+            </select>
+          </div>
+          <div class="flex justify-end space-x-3">
+            <button type="button" @click="showAddUserModal = false" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700">
+              取消
+            </button>
+            <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
+              创建
+            </button>
+          </div>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+
+// 用户数据
+const users = ref([
+  {
+    id: 1,
+    username: 'admin',
+    name: '管理员',
+    email: 'admin@example.com',
+    avatar: 'https://ui-avatars.com/api/?name=管理员&background=0D8ABC&color=fff',
+    departmentId: 1,
+    position: '系统管理员',
+    roles: [1],
+    status: 'active',
+    lastLogin: '2024-03-20T10:30:00'
+  },
+  {
+    id: 2,
+    username: 'user1',
+    name: '张三',
+    email: 'user1@example.com',
+    avatar: 'https://ui-avatars.com/api/?name=张三&background=0D8ABC&color=fff',
+    departmentId: 2,
+    position: '开发工程师',
+    roles: [2],
+    status: 'active',
+    lastLogin: '2024-03-20T09:15:00'
+  },
+  {
+    id: 3,
+    username: 'user2',
+    name: '李四',
+    email: 'user2@example.com',
+    avatar: 'https://ui-avatars.com/api/?name=李四&background=0D8ABC&color=fff',
+    departmentId: 3,
+    position: '产品经理',
+    roles: [2],
+    status: 'inactive',
+    lastLogin: '2024-03-19T16:45:00'
+  }
+])
+
+// 部门数据
+const departments = ref([
+  { id: 1, name: '管理部' },
+  { id: 2, name: '技术部' },
+  { id: 3, name: '产品部' },
+  { id: 4, name: '市场部' }
+])
+
+// 角色数据
+const roles = ref([
+  { id: 1, name: '管理员' },
+  { id: 2, name: '普通用户' },
+  { id: 3, name: '访客' }
+])
+
+// 筛选条件
+const filters = ref({
+  department: '',
+  role: '',
+  status: '',
+  search: ''
+})
+
+// 模态框状态
+const showAddUserModal = ref(false)
+
+// 新用户表单
+const newUser = ref({
+  username: '',
+  name: '',
+  email: '',
+  departmentId: '',
+  position: '',
+  roles: [],
+  status: 'active'
+})
+
+// 计算属性
+const filteredUsers = computed(() => {
+  return users.value.filter(user => {
+    const matchesDepartment = !filters.value.department || user.departmentId === filters.value.department
+    const matchesRole = !filters.value.role || user.roles.includes(filters.value.role)
+    const matchesStatus = !filters.value.status || user.status === filters.value.status
+    const matchesSearch = !filters.value.search ||
+      user.username.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      user.name.toLowerCase().includes(filters.value.search.toLowerCase()) ||
+      user.email.toLowerCase().includes(filters.value.search.toLowerCase())
+    return matchesDepartment && matchesRole && matchesStatus && matchesSearch
+  })
+})
+
+const totalUsers = computed(() => {
+  return users.value.length
+})
+
+const activeUsers = computed(() => {
+  return users.value.filter(user => user.status === 'active').length
+})
+
+const adminUsers = computed(() => {
+  return users.value.filter(user => user.roles.includes(1)).length
+})
+
+const weeklyNewUsers = computed(() => {
+  const oneWeekAgo = new Date()
+  oneWeekAgo.setDate(oneWeekAgo.getDate() - 7)
+  return users.value.filter(user => new Date(user.lastLogin) >= oneWeekAgo).length
+})
+
+// 获取部门名称
+const getDepartmentName = (departmentId) => {
+  const department = departments.value.find(d => d.id === departmentId)
+  return department ? department.name : '未知部门'
+}
+
+// 获取角色名称
+const getRoleName = (roleId) => {
+  const role = roles.value.find(r => r.id === roleId)
+  return role ? role.name : '未知角色'
+}
+
+// 获取状态名称
+const getStatusName = (status) => {
+  const names = {
+    active: '活跃',
+    inactive: '未激活',
+    locked: '已锁定'
+  }
+  return names[status] || status
+}
+
+// 获取状态样式
+const getStatusClass = (status) => {
+  const classes = {
+    active: 'bg-green-100 text-green-800 dark:bg-green-700 dark:text-green-300',
+    inactive: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-300',
+    locked: 'bg-red-100 text-red-800 dark:bg-red-700 dark:text-red-300'
+  }
+  return classes[status] || classes.active
+}
+
+// 添加用户
+const addUser = () => {
+  const user = {
+    id: users.value.length + 1,
+    avatar: `https://ui-avatars.com/api/?name=${newUser.value.name}&background=0D8ABC&color=fff`,
+    lastLogin: new Date().toISOString(),
+    ...newUser.value
+  }
+  
+  users.value.push(user)
+  showAddUserModal.value = false
+  resetNewUser()
+}
+
+// 重置新用户表单
+const resetNewUser = () => {
+  newUser.value = {
+    username: '',
+    name: '',
+    email: '',
+    departmentId: '',
+    position: '',
+    roles: [],
+    status: 'active'
+  }
+}
+
+// 查看用户
+const viewUser = (user) => {
+  // 实现查看用户的逻辑
+  console.log('查看用户:', user)
+}
+
+// 编辑用户
+const editUser = (user) => {
+  // 实现编辑用户的逻辑
+  console.log('编辑用户:', user)
+}
+
+// 删除用户
+const deleteUser = (user) => {
+  if (confirm(`确定要删除用户 ${user.name} 吗?`)) {
+    const index = users.value.findIndex(u => u.id === user.id)
+    if (index !== -1) {
+      users.value.splice(index, 1)
+    }
+  }
+}
+
+// 导出用户数据
+const exportUserData = () => {
+  // 实现导出用户数据的逻辑
+  console.log('导出用户数据')
+}
+</script> 

+ 0 - 7
template_desc.txt

@@ -1,7 +0,0 @@
-src/assets/templates/FSG/login.vue 登录界面的模板
-src/assets/templates/FSG/organization.vue 组织架构界面的模板
-src/assets/templates/FSG/userList.vue 展示用户列表信息界面的模板
-src/assets/templates/FSG/userProfile.vue 用户详细信息
-src/assets/templates/FSG/PersonalSettingsDialog.vue 用户的个人设置弹框界面的模板
-src/assets/templates/FSG/UnsavedChangesDialog.vue 修改未保存弹框界面的模板
-src/assets/templates/FSG/dashboard.vue 首页(门户网站)页面的模板

+ 49 - 0
template_desc_prototype.txt

@@ -0,0 +1,49 @@
+src/assets/templates/prototype/system/SystemSettings.vue 系统设置模版
+src/assets/templates/prototype/system/LogManagement.vue 日志管理模版
+src/assets/templates/prototype/system/PermissionManagement.vue 权限管理模版
+src/assets/templates/prototype/system/RoleManagement.vue 角色管理模版
+src/assets/templates/prototype/system/UserManagement.vue 用户管理模版
+src/assets/templates/prototype/system/NotificationManagement.vue 通知管理模版
+src/assets/templates/prototype/hr/HRManagement.vue 人力资源管理模版
+src/assets/templates/prototype/hr/SalaryManagement.vue 薪资管理模版
+src/assets/templates/prototype/hr/AttendanceManagement.vue 考勤管理模版
+src/assets/templates/prototype/hr/PerformanceManagement.vue 绩效管理模版
+src/assets/templates/prototype/hr/TrainingManagement.vue 培训管理模版
+src/assets/templates/prototype/hr/RecruitmentManagement.vue 招聘管理模版
+src/assets/templates/prototype/customer/CustomerManagement.vue 客户管理模版
+src/assets/templates/prototype/customer/CustomerServiceAnalytics.vue 客服分析模版
+src/assets/templates/prototype/customer/UserBehavior.vue 用户行为分析模版
+src/assets/templates/prototype/customer/CustomerRelationshipManagement.vue 客户关系管理模版
+src/assets/templates/prototype/customer/CustomerServiceManagement.vue 客服管理模版
+src/assets/templates/prototype/ecommerce/EcommerceMarketingManagement.vue 电商营销管理模版
+src/assets/templates/prototype/ecommerce/EcommerceAfterSalesManagement.vue 电商售后管理模版
+src/assets/templates/prototype/ecommerce/EcommerceLogisticsManagement.vue 电商物流管理模版
+src/assets/templates/prototype/ecommerce/EcommerceReviewManagement.vue 电商评价管理模版
+src/assets/templates/prototype/ecommerce/EcommerceProductManagement.vue 电商商品管理模版
+src/assets/templates/prototype/ecommerce/EcommerceUserManagement.vue 电商用户管理模版
+src/assets/templates/prototype/ecommerce/ProductManagement.vue 商品管理模版
+src/assets/templates/prototype/ecommerce/EcommerceAnalytics.vue 电商分析模版
+src/assets/templates/prototype/ecommerce/EcommerceVendorManagement.vue 电商供应商管理模版
+src/assets/templates/prototype/ecommerce/EcommerceOrderManagement.vue 电商订单管理模版
+src/assets/templates/prototype/production/AssetManagement.vue 资产管理模版
+src/assets/templates/prototype/production/EquipmentManagement.vue 设备管理模版
+src/assets/templates/prototype/production/QualityManagement.vue 质量管理模版
+src/assets/templates/prototype/production/ProductionManagement.vue 生产管理模版
+src/assets/templates/prototype/supply-chain/SupplierManagement.vue 供应商管理模版
+src/assets/templates/prototype/supply-chain/InventoryAnalytics.vue 库存分析模版
+src/assets/templates/prototype/supply-chain/InventoryManagement.vue 库存管理模版
+src/assets/templates/prototype/supply-chain/PurchaseManagement.vue 采购管理模版
+src/assets/templates/prototype/supply-chain/LogisticsManagement.vue 物流管理模版
+src/assets/templates/prototype/sales/SalesManagement.vue 销售管理模版
+src/assets/templates/prototype/sales/ContractManagement.vue 合同管理模版
+src/assets/templates/prototype/sales/ReportManagement.vue 报表管理模版
+src/assets/templates/prototype/project/TaskManagement.vue 任务管理模版
+src/assets/templates/prototype/project/MeetingManagement.vue 会议管理模版
+src/assets/templates/prototype/project/ProjectManagement.vue 项目管理模版
+src/assets/templates/prototype/knowledge/DocumentManagement.vue 文档管理模版
+src/assets/templates/prototype/knowledge/KnowledgeBaseManagement.vue 知识库管理模版
+src/assets/templates/prototype/finance/MarketingAnalytics.vue 营销分析模版
+src/assets/templates/prototype/finance/EnterpriseDashboard.vue 企业仪表盘模版
+src/assets/templates/prototype/finance/ProductAnalytics.vue 产品分析模版
+src/assets/templates/prototype/finance/FinancialManagement.vue 财务管理模版
+src/assets/templates/prototype/common/login.vue 登录页面模版

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov