소스 검색

feat:ai-interview

0235477 3 일 전
부모
커밋
7c4dfd9dde

+ 0 - 24
.gitignore

@@ -1,24 +0,0 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?

+ 0 - 3
.vscode/extensions.json

@@ -1,3 +0,0 @@
-{
-  "recommendations": ["Vue.volar"]
-}

+ 0 - 163
README.md

@@ -1,163 +0,0 @@
-# 🚀 招聘简历筛选系统项目
-
-## 🌟 项目介绍
-
-### 项目名称和简介
-
-本项目是一个功能强大的招聘管理系统,旨在帮助企业高效地进行岗位管理、简历筛选、候选人管理以及数据分析,简化招聘流程,提高招聘效率。
-
-### 核心功能特性
-
-* **智能岗位管理**:轻松创建、编辑、暂停、恢复和删除招聘岗位,实时跟踪岗位状态和简历处理进度。
-* **AI 简历筛选**:利用 AI 技术对简历进行智能筛选,根据预设的评分标准快速筛选出符合要求的候选人。
-* **候选人管理**:全面管理候选人信息,查看候选人简历、AI 分析报告,对候选人进行标记和面试邀请。
-* **数据分析面板**:提供直观的招聘数据统计和分析,包括总岗位数、总候选人数、已面试人数、岗位招聘表现等,帮助企业了解招聘效果。
-
-### 技术亮点
-
-* **现代化 UI 设计**:采用 Tailwind CSS 和 Lucide Vue Next 图标库,打造简洁美观、响应式的用户界面。
-* **高性能动画**:使用 @vueuse/motion 库实现流畅的动画效果,提升用户体验。
-* **移动端优化**:确保在移动端设备上也能提供良好的使用体验。
-* **TypeScript 支持**:使用 TypeScript 进行开发,提高代码的可维护性和可靠性。
-
-## 🛠️ 技术栈详情
-
-### 前端框架
-
-* **Vue 3**:渐进式 JavaScript 框架,用于构建用户界面。
-* **TypeScript**:JavaScript 的超集,提供静态类型检查,增强代码的可维护性。
-* **Vite**:快速的构建工具,提供高效的开发体验。
-
-### UI 样式
-
-* **Tailwind CSS**:实用类优先的 CSS 框架,可快速构建自定义的用户界面。
-* **Lucide Vue Next**:基于 Vue 3 的图标库,提供丰富的图标资源。
-*  **@vueuse/motion**:用于实现高性能动画效果的 Vue 组合式函数库。
-
-### 状态管理
-
-* **Pinia**:Vue.js 的轻量级状态管理库,提供简单、可扩展的状态管理解决方案。
-
-### 开发工具
-
-* **Vue TSC**:Vue 3 的 TypeScript 编译器,用于类型检查和代码生成。
-* **PostCSS**:用 JavaScript 编写的工具,用于将 CSS 转换为另一种 CSS。
-* **Autoprefixer**:PostCSS 的插件,用于自动添加浏览器前缀。
-
-## 📖 完整的使用指南
-
-### 环境要求和安装步骤
-
-**环境要求**:确保已经安装了 Node.js(版本 >= 14)和 npm(版本 >= 6)。
-
-**安装步骤**:
-
-1. 克隆项目仓库:
-
-```bash
-git clone <项目仓库地址>
-```
-
-2. 进入项目目录:
-
-```bash
-cd <项目目录名>
-```
-
-3. 安装依赖:
-
-```bash
-npm install
-```
-
-### 开发、构建、预览命令
-
-* **开发模式**:启动开发服务器,监听文件变化并实时更新:
-
-```bash
-npm run dev
-```
-
-* **构建项目**:生成生产环境的静态文件:
-
-```bash
-npm run build
-```
-
-* **预览构建结果**:在本地预览生产环境的构建结果:
-
-```bash
-npm run preview
-```
-
-### 详细的项目结构说明
-
-```plaintext
-src/
-├── components/       # 组件目录
-│   ├── CandidateDetailModal.vue  # 候选人详情模态框组件
-│   ├── JobCard.vue               # 岗位卡片组件
-│   ├── JobCreatorModal.vue       # 岗位创建模态框组件
-│   ├── JobDetailModal.vue        # 岗位详情模态框组件
-│   ├── JobEditModal.vue          # 岗位编辑模态框组件
-│   └── BottomNavigation.vue      # 底部导航栏组件
-├── views/          # 视图目录
-│   ├── JobManagementView.vue     # 岗位管理视图
-│   ├── CandidateView.vue         # 候选人管理视图
-│   └── DashboardView.vue         # 数据面板视图
-├── stores/         # 状态管理目录
-│   └── jobStore.ts               # 岗位状态管理文件
-├── App.vue         # 根组件
-├── style.css       # 全局样式文件
-└── vite-env.d.ts   # Vite环境类型声明文件
-```
-
-### 核心功能使用说明
-
-#### 岗位管理
-
-* 创建岗位:在岗位管理页面,点击 “创建新岗位” 按钮,填写岗位信息,包括岗位名称、部门、工作地点、岗位描述和 AI 筛选评分标准,点击 “保存” 即可创建新岗位。
-* 查看岗位详情:在岗位卡片上点击 “查看详情” 按钮,弹出岗位详情模态框,可查看岗位的基础信息、岗位描述、招聘统计和 AI 筛选评分标准。
-* 编辑岗位:在岗位卡片上点击 “编辑岗位” 按钮,弹出岗位编辑模态框,可修改岗位信息,修改完成后点击 “保存” 即可更新岗位信息。
-* 暂停 / 恢复招聘:在岗位卡片上点击 “暂停招聘” 或 “恢复招聘” 按钮,可暂停或恢复该岗位的招聘。
-* 删除岗位:在岗位卡片的下拉菜单中点击 “删除岗位” 按钮,确认删除后即可删除该岗位。
-
-#### 候选人管理
-
-* 筛选候选人:在候选人管理页面,使用筛选器筛选候选人,可根据状态和岗位进行筛选。
-* 查看候选人详情:点击候选人卡片,弹出候选人详情模态框,可查看候选人的基本信息、简历原文、AI 分析报告和待考察点。
-* 标记候选人状态:在候选人详情模态框中,点击 “通过”、“拒绝” 或 “发送面试邀请” 按钮,可标记候选人的状态。
-
-#### 数据面板
-
-在数据面板页面,可查看招聘数据统计和分析,包括总岗位数、总候选人数、已面试人数、岗位招聘表现等。
-
-## 💎 设计特色
-
-### 响应式设计理念
-
-本项目采用响应式设计理念,确保在不同设备上都能提供良好的用户体验。使用 Tailwind CSS 的响应式类,根据设备屏幕宽度自动调整布局和样式。
-
-### 动画效果实现
-
-使用 @vueuse/motion 库实现高性能动画效果,如页面切换动画、卡片出现动画和数字滚动动画等,提升用户体验。
-
-### 现代化 UI 特点
-
-* **简洁美观**:采用简洁的设计风格,去除多余的元素,使界面更加清晰易读。
-* **色彩搭配**:使用明亮、柔和的色彩搭配,营造舒适的视觉效果。
-* **图标使用**:使用 Lucide Vue Next 图标库,提供丰富的图标资源,增强界面的可读性和交互性。
-
-## ⚙️ 配置和部署
-
-### 各种配置文件说明
-
-* **vite.config.ts**:Vite 的配置文件,用于配置项目的构建和开发选项。
-* **tsconfig.json**:TypeScript 的配置文件,用于配置 TypeScript 编译器的选项。
-* **postcss.config.js**:PostCSS 的配置文件,用于配置 PostCSS 插件。
-* **tailwind.config.js**:Tailwind CSS 的配置文件,用于配置 Tailwind CSS 的选项。
-
-### 静态部署和服务器部署选项
-
-* **静态部署**:将dist目录下的静态文件部署到静态文件服务器,如 GitHub Pages、Netlify 等。
-* **服务器部署**:将项目部署到服务器上,如 Node.js 服务器、Nginx 服务器等。

+ 0 - 47
index.html

@@ -1,47 +0,0 @@
-<!doctype html>
-<html lang="zh">
-  <head>
-    <meta charset="UTF-8" />
-    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
-    <title>智能招聘助手</title>
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
-    <style>
-      /* 全局样式重置和优化 */
-      * {
-        -webkit-tap-highlight-color: transparent;
-        -webkit-touch-callout: none;
-        -webkit-user-select: none;
-        -moz-user-select: none;
-        -ms-user-select: none;
-        user-select: none;
-      }
-      
-      body {
-        overscroll-behavior: none;
-        -webkit-overflow-scrolling: touch;
-      }
-      
-      /* 玻璃拟态效果基础样式 */
-      .glass-morphism {
-        background: rgba(255, 255, 255, 0.25);
-        backdrop-filter: blur(20px);
-        -webkit-backdrop-filter: blur(20px);
-        border: 1px solid rgba(255, 255, 255, 0.18);
-      }
-      
-      .glass-dark {
-        background: rgba(0, 0, 0, 0.25);
-        backdrop-filter: blur(20px);
-        -webkit-backdrop-filter: blur(20px);
-        border: 1px solid rgba(255, 255, 255, 0.1);
-      }
-    </style>
-  </head>
-  <body class="font-sans antialiased">
-    <div id="app"></div>
-    <script type="module" src="/src/main.ts"></script>
-  </body>
-</html>

+ 0 - 4094
package-lock.json

@@ -1,4094 +0,0 @@
-{
-  "name": "hr-recruitment-app",
-  "version": "0.0.0",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "hr-recruitment-app",
-      "version": "0.0.0",
-      "dependencies": {
-        "@vueuse/motion": "^2.0.0",
-        "events": "^3.3.0",
-        "lucide-vue-next": "^0.290.0",
-        "pinia": "^2.1.7",
-        "stream-browserify": "^3.0.0",
-        "util": "^0.12.5",
-        "vue": "^3.4.38"
-      },
-      "devDependencies": {
-        "@vitejs/plugin-vue": "^5.2.4",
-        "autoprefixer": "^10.4.16",
-        "postcss": "^8.4.32",
-        "tailwindcss": "^3.4.0",
-        "typescript": "^5.5.3",
-        "vite": "^5.4.2",
-        "vue-tsc": "^2.1.4"
-      }
-    },
-    "node_modules/@alloc/quick-lru": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
-      "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@babel/helper-string-parser": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
-      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
-      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/parser": {
-      "version": "7.27.7",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz",
-      "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.27.7"
-      },
-      "bin": {
-        "parser": "bin/babel-parser.js"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@babel/types": {
-      "version": "7.27.7",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz",
-      "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-string-parser": "^7.27.1",
-        "@babel/helper-validator-identifier": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@esbuild/aix-ppc64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
-      "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "aix"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/android-arm": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
-      "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/android-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
-      "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/android-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
-      "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/darwin-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
-      "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/darwin-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
-      "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/freebsd-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
-      "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/freebsd-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
-      "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-arm": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
-      "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
-      "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-ia32": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
-      "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-loong64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
-      "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
-      "cpu": [
-        "loong64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-mips64el": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
-      "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
-      "cpu": [
-        "mips64el"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-ppc64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
-      "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-riscv64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
-      "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
-      "cpu": [
-        "riscv64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-s390x": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
-      "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
-      "cpu": [
-        "s390x"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/linux-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
-      "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/netbsd-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
-      "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "netbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/openbsd-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
-      "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "openbsd"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/sunos-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
-      "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "sunos"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/win32-arm64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
-      "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/win32-ia32": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
-      "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@esbuild/win32-x64": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
-      "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@isaacs/cliui": {
-      "version": "8.0.2",
-      "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
-      "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "string-width": "^5.1.2",
-        "string-width-cjs": "npm:string-width@^4.2.0",
-        "strip-ansi": "^7.0.1",
-        "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
-        "wrap-ansi": "^8.1.0",
-        "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@jridgewell/gen-mapping": {
-      "version": "0.3.11",
-      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.11.tgz",
-      "integrity": "sha512-C512c1ytBTio4MrpWKlJpyFHT6+qfFL8SZ58zBzJ1OOzUEjHeF1BtjY2fH7n4x/g2OV/KiiMLAivOp1DXmiMMw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.5.0",
-        "@jridgewell/trace-mapping": "^0.3.24"
-      }
-    },
-    "node_modules/@jridgewell/resolve-uri": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
-      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.5.3",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.3.tgz",
-      "integrity": "sha512-AiR5uKpFxP3PjO4R19kQGIMwxyRyPuXmKEEy301V1C0+1rVjS94EZQXf1QKZYN8Q0YM+estSPhmx5JwNftv6nw==",
-      "license": "MIT"
-    },
-    "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.28",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.28.tgz",
-      "integrity": "sha512-KNNHHwW3EIp4EDYOvYFGyIFfx36R2dNJYH4knnZlF8T5jdbD5Wx8xmSaQ2gP9URkJ04LGEtlcCtwArKcmFcwKw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/resolve-uri": "^3.1.0",
-        "@jridgewell/sourcemap-codec": "^1.4.14"
-      }
-    },
-    "node_modules/@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nuxt/kit": {
-      "version": "3.17.5",
-      "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.17.5.tgz",
-      "integrity": "sha512-NdCepmA+S/SzgcaL3oYUeSlXGYO6BXGr9K/m1D0t0O9rApF8CSq/QQ+ja5KYaYMO1kZAEWH4s2XVcE3uPrrAVg==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "c12": "^3.0.4",
-        "consola": "^3.4.2",
-        "defu": "^6.1.4",
-        "destr": "^2.0.5",
-        "errx": "^0.1.0",
-        "exsolve": "^1.0.5",
-        "ignore": "^7.0.5",
-        "jiti": "^2.4.2",
-        "klona": "^2.0.6",
-        "knitwork": "^1.2.0",
-        "mlly": "^1.7.4",
-        "ohash": "^2.0.11",
-        "pathe": "^2.0.3",
-        "pkg-types": "^2.1.0",
-        "scule": "^1.3.0",
-        "semver": "^7.7.2",
-        "std-env": "^3.9.0",
-        "tinyglobby": "^0.2.14",
-        "ufo": "^1.6.1",
-        "unctx": "^2.4.1",
-        "unimport": "^5.0.1",
-        "untyped": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=18.12.0"
-      }
-    },
-    "node_modules/@pkgjs/parseargs": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
-      "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/@rollup/rollup-android-arm-eabi": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz",
-      "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ]
-    },
-    "node_modules/@rollup/rollup-android-arm64": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz",
-      "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "android"
-      ]
-    },
-    "node_modules/@rollup/rollup-darwin-arm64": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz",
-      "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ]
-    },
-    "node_modules/@rollup/rollup-darwin-x64": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz",
-      "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ]
-    },
-    "node_modules/@rollup/rollup-freebsd-arm64": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz",
-      "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ]
-    },
-    "node_modules/@rollup/rollup-freebsd-x64": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz",
-      "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz",
-      "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz",
-      "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==",
-      "cpu": [
-        "arm"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-arm64-gnu": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz",
-      "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-arm64-musl": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz",
-      "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz",
-      "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==",
-      "cpu": [
-        "loong64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz",
-      "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==",
-      "cpu": [
-        "ppc64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz",
-      "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==",
-      "cpu": [
-        "riscv64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-riscv64-musl": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz",
-      "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==",
-      "cpu": [
-        "riscv64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-s390x-gnu": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz",
-      "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==",
-      "cpu": [
-        "s390x"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-x64-gnu": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz",
-      "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-linux-x64-musl": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz",
-      "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "linux"
-      ]
-    },
-    "node_modules/@rollup/rollup-win32-arm64-msvc": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz",
-      "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==",
-      "cpu": [
-        "arm64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ]
-    },
-    "node_modules/@rollup/rollup-win32-ia32-msvc": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz",
-      "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==",
-      "cpu": [
-        "ia32"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ]
-    },
-    "node_modules/@rollup/rollup-win32-x64-msvc": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz",
-      "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==",
-      "cpu": [
-        "x64"
-      ],
-      "dev": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "win32"
-      ]
-    },
-    "node_modules/@types/estree": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
-      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
-      "devOptional": true,
-      "license": "MIT"
-    },
-    "node_modules/@types/web-bluetooth": {
-      "version": "0.0.20",
-      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
-      "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
-      "license": "MIT"
-    },
-    "node_modules/@vitejs/plugin-vue": {
-      "version": "5.2.4",
-      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
-      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "peerDependencies": {
-        "vite": "^5.0.0 || ^6.0.0",
-        "vue": "^3.2.25"
-      }
-    },
-    "node_modules/@volar/language-core": {
-      "version": "2.4.15",
-      "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.15.tgz",
-      "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@volar/source-map": "2.4.15"
-      }
-    },
-    "node_modules/@volar/source-map": {
-      "version": "2.4.15",
-      "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.15.tgz",
-      "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/@volar/typescript": {
-      "version": "2.4.15",
-      "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.15.tgz",
-      "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@volar/language-core": "2.4.15",
-        "path-browserify": "^1.0.1",
-        "vscode-uri": "^3.0.8"
-      }
-    },
-    "node_modules/@vue/compiler-core": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz",
-      "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/parser": "^7.27.5",
-        "@vue/shared": "3.5.17",
-        "entities": "^4.5.0",
-        "estree-walker": "^2.0.2",
-        "source-map-js": "^1.2.1"
-      }
-    },
-    "node_modules/@vue/compiler-core/node_modules/estree-walker": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
-      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
-      "license": "MIT"
-    },
-    "node_modules/@vue/compiler-dom": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz",
-      "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/compiler-core": "3.5.17",
-        "@vue/shared": "3.5.17"
-      }
-    },
-    "node_modules/@vue/compiler-sfc": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz",
-      "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/parser": "^7.27.5",
-        "@vue/compiler-core": "3.5.17",
-        "@vue/compiler-dom": "3.5.17",
-        "@vue/compiler-ssr": "3.5.17",
-        "@vue/shared": "3.5.17",
-        "estree-walker": "^2.0.2",
-        "magic-string": "^0.30.17",
-        "postcss": "^8.5.6",
-        "source-map-js": "^1.2.1"
-      }
-    },
-    "node_modules/@vue/compiler-sfc/node_modules/estree-walker": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
-      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
-      "license": "MIT"
-    },
-    "node_modules/@vue/compiler-ssr": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz",
-      "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/compiler-dom": "3.5.17",
-        "@vue/shared": "3.5.17"
-      }
-    },
-    "node_modules/@vue/compiler-vue2": {
-      "version": "2.7.16",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
-      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "de-indent": "^1.0.2",
-        "he": "^1.2.0"
-      }
-    },
-    "node_modules/@vue/devtools-api": {
-      "version": "6.6.4",
-      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
-      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
-      "license": "MIT"
-    },
-    "node_modules/@vue/language-core": {
-      "version": "2.2.10",
-      "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.10.tgz",
-      "integrity": "sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@volar/language-core": "~2.4.11",
-        "@vue/compiler-dom": "^3.5.0",
-        "@vue/compiler-vue2": "^2.7.16",
-        "@vue/shared": "^3.5.0",
-        "alien-signals": "^1.0.3",
-        "minimatch": "^9.0.3",
-        "muggle-string": "^0.4.1",
-        "path-browserify": "^1.0.1"
-      },
-      "peerDependencies": {
-        "typescript": "*"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@vue/reactivity": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.17.tgz",
-      "integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/shared": "3.5.17"
-      }
-    },
-    "node_modules/@vue/runtime-core": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.17.tgz",
-      "integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/reactivity": "3.5.17",
-        "@vue/shared": "3.5.17"
-      }
-    },
-    "node_modules/@vue/runtime-dom": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz",
-      "integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/reactivity": "3.5.17",
-        "@vue/runtime-core": "3.5.17",
-        "@vue/shared": "3.5.17",
-        "csstype": "^3.1.3"
-      }
-    },
-    "node_modules/@vue/server-renderer": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.17.tgz",
-      "integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/compiler-ssr": "3.5.17",
-        "@vue/shared": "3.5.17"
-      },
-      "peerDependencies": {
-        "vue": "3.5.17"
-      }
-    },
-    "node_modules/@vue/shared": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz",
-      "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==",
-      "license": "MIT"
-    },
-    "node_modules/@vueuse/core": {
-      "version": "10.11.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz",
-      "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/web-bluetooth": "^0.0.20",
-        "@vueuse/metadata": "10.11.1",
-        "@vueuse/shared": "10.11.1",
-        "vue-demi": ">=0.14.8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
-    "node_modules/@vueuse/metadata": {
-      "version": "10.11.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz",
-      "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
-    "node_modules/@vueuse/motion": {
-      "version": "2.2.6",
-      "resolved": "https://registry.npmjs.org/@vueuse/motion/-/motion-2.2.6.tgz",
-      "integrity": "sha512-gKFktPtrdypSv44SaW1oBJKLBiP6kE5NcoQ6RsAU3InemESdiAutgQncfPe/rhLSLCtL4jTAhMmFfxoR6gm5LQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@vueuse/core": "^10.10.0",
-        "@vueuse/shared": "^10.10.0",
-        "csstype": "^3.1.3",
-        "framesync": "^6.1.2",
-        "popmotion": "^11.0.5",
-        "style-value-types": "^5.1.2"
-      },
-      "optionalDependencies": {
-        "@nuxt/kit": "^3.13.0"
-      },
-      "peerDependencies": {
-        "vue": ">=3.0.0"
-      }
-    },
-    "node_modules/@vueuse/shared": {
-      "version": "10.11.1",
-      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz",
-      "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==",
-      "license": "MIT",
-      "dependencies": {
-        "vue-demi": ">=0.14.8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
-    "node_modules/acorn": {
-      "version": "8.15.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-      "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
-      "license": "MIT",
-      "optional": true,
-      "bin": {
-        "acorn": "bin/acorn"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/alien-signals": {
-      "version": "1.0.13",
-      "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-1.0.13.tgz",
-      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/ansi-regex": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
-      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
-      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/any-promise": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/anymatch": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/arg": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
-      "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/autoprefixer": {
-      "version": "10.4.21",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
-      "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/autoprefixer"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "browserslist": "^4.24.4",
-        "caniuse-lite": "^1.0.30001702",
-        "fraction.js": "^4.3.7",
-        "normalize-range": "^0.1.2",
-        "picocolors": "^1.1.1",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "bin": {
-        "autoprefixer": "bin/autoprefixer"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/available-typed-arrays": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
-      "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
-      "license": "MIT",
-      "dependencies": {
-        "possible-typed-array-names": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/binary-extensions": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
-      "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/brace-expansion": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
-      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0"
-      }
-    },
-    "node_modules/braces": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
-      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "fill-range": "^7.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/browserslist": {
-      "version": "4.25.1",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
-      "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/browserslist"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "caniuse-lite": "^1.0.30001726",
-        "electron-to-chromium": "^1.5.173",
-        "node-releases": "^2.0.19",
-        "update-browserslist-db": "^1.1.3"
-      },
-      "bin": {
-        "browserslist": "cli.js"
-      },
-      "engines": {
-        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-      }
-    },
-    "node_modules/c12": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/c12/-/c12-3.0.4.tgz",
-      "integrity": "sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "chokidar": "^4.0.3",
-        "confbox": "^0.2.2",
-        "defu": "^6.1.4",
-        "dotenv": "^16.5.0",
-        "exsolve": "^1.0.5",
-        "giget": "^2.0.0",
-        "jiti": "^2.4.2",
-        "ohash": "^2.0.11",
-        "pathe": "^2.0.3",
-        "perfect-debounce": "^1.0.0",
-        "pkg-types": "^2.1.0",
-        "rc9": "^2.1.2"
-      },
-      "peerDependencies": {
-        "magicast": "^0.3.5"
-      },
-      "peerDependenciesMeta": {
-        "magicast": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/call-bind": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.8.tgz",
-      "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.0",
-        "es-define-property": "^1.0.0",
-        "get-intrinsic": "^1.2.4",
-        "set-function-length": "^1.2.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/call-bind-apply-helpers": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
-      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
-      "license": "MIT",
-      "dependencies": {
-        "es-errors": "^1.3.0",
-        "function-bind": "^1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/call-bound": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz",
-      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.2",
-        "get-intrinsic": "^1.3.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/camelcase-css": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
-      "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/caniuse-lite": {
-      "version": "1.0.30001726",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz",
-      "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "CC-BY-4.0"
-    },
-    "node_modules/chokidar": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
-      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "readdirp": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 14.16.0"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
-    "node_modules/citty": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
-      "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "consola": "^3.2.3"
-      }
-    },
-    "node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/commander": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
-      "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/confbox": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
-      "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/consola": {
-      "version": "3.4.2",
-      "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
-      "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": "^14.18.0 || >=16.10.0"
-      }
-    },
-    "node_modules/cross-spawn": {
-      "version": "7.0.6",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
-      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/cssesc": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
-      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
-      "dev": true,
-      "license": "MIT",
-      "bin": {
-        "cssesc": "bin/cssesc"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/csstype": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
-      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
-      "license": "MIT"
-    },
-    "node_modules/de-indent": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
-      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/define-data-property": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
-      "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
-      "license": "MIT",
-      "dependencies": {
-        "es-define-property": "^1.0.0",
-        "es-errors": "^1.3.0",
-        "gopd": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/defu": {
-      "version": "6.1.4",
-      "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
-      "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/destr": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
-      "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/didyoumean": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
-      "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
-      "dev": true,
-      "license": "Apache-2.0"
-    },
-    "node_modules/dlv": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
-      "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/dotenv": {
-      "version": "16.6.1",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
-      "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
-      "license": "BSD-2-Clause",
-      "optional": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://dotenvx.com"
-      }
-    },
-    "node_modules/dunder-proto": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
-      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.1",
-        "es-errors": "^1.3.0",
-        "gopd": "^1.2.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/eastasianwidth": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
-      "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/electron-to-chromium": {
-      "version": "1.5.178",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.178.tgz",
-      "integrity": "sha512-wObbz/ar3Bc6e4X5vf0iO8xTN8YAjN/tgiAOJLr7yjYFtP9wAjq8Mb5h0yn6kResir+VYx2DXBj9NNobs0ETSA==",
-      "dev": true,
-      "license": "ISC"
-    },
-    "node_modules/emoji-regex": {
-      "version": "9.2.2",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
-      "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/entities": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
-      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=0.12"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/entities?sponsor=1"
-      }
-    },
-    "node_modules/errx": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/errx/-/errx-0.1.0.tgz",
-      "integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/es-define-property": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
-      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/es-errors": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
-      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/es-object-atoms": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
-      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
-      "license": "MIT",
-      "dependencies": {
-        "es-errors": "^1.3.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/esbuild": {
-      "version": "0.21.5",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
-      "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
-      "dev": true,
-      "hasInstallScript": true,
-      "bin": {
-        "esbuild": "bin/esbuild"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "optionalDependencies": {
-        "@esbuild/aix-ppc64": "0.21.5",
-        "@esbuild/android-arm": "0.21.5",
-        "@esbuild/android-arm64": "0.21.5",
-        "@esbuild/android-x64": "0.21.5",
-        "@esbuild/darwin-arm64": "0.21.5",
-        "@esbuild/darwin-x64": "0.21.5",
-        "@esbuild/freebsd-arm64": "0.21.5",
-        "@esbuild/freebsd-x64": "0.21.5",
-        "@esbuild/linux-arm": "0.21.5",
-        "@esbuild/linux-arm64": "0.21.5",
-        "@esbuild/linux-ia32": "0.21.5",
-        "@esbuild/linux-loong64": "0.21.5",
-        "@esbuild/linux-mips64el": "0.21.5",
-        "@esbuild/linux-ppc64": "0.21.5",
-        "@esbuild/linux-riscv64": "0.21.5",
-        "@esbuild/linux-s390x": "0.21.5",
-        "@esbuild/linux-x64": "0.21.5",
-        "@esbuild/netbsd-x64": "0.21.5",
-        "@esbuild/openbsd-x64": "0.21.5",
-        "@esbuild/sunos-x64": "0.21.5",
-        "@esbuild/win32-arm64": "0.21.5",
-        "@esbuild/win32-ia32": "0.21.5",
-        "@esbuild/win32-x64": "0.21.5"
-      }
-    },
-    "node_modules/escalade": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
-      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
-      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/estree-walker": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
-      "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "@types/estree": "^1.0.0"
-      }
-    },
-    "node_modules/events": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
-      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8.x"
-      }
-    },
-    "node_modules/exsolve": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
-      "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/fast-glob": {
-      "version": "3.3.3",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
-      "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.8"
-      },
-      "engines": {
-        "node": ">=8.6.0"
-      }
-    },
-    "node_modules/fast-glob/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/fastq": {
-      "version": "1.19.1",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
-      "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "node_modules/fill-range": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
-      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/for-each": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.5.tgz",
-      "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
-      "license": "MIT",
-      "dependencies": {
-        "is-callable": "^1.2.7"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/foreground-child": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
-      "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "cross-spawn": "^7.0.6",
-        "signal-exit": "^4.0.1"
-      },
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/fraction.js": {
-      "version": "4.3.7",
-      "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
-      "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "type": "patreon",
-        "url": "https://github.com/sponsors/rawify"
-      }
-    },
-    "node_modules/framesync": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz",
-      "integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==",
-      "license": "MIT",
-      "dependencies": {
-        "tslib": "2.4.0"
-      }
-    },
-    "node_modules/fsevents": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-      "dev": true,
-      "hasInstallScript": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-      }
-    },
-    "node_modules/function-bind": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/get-intrinsic": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
-      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bind-apply-helpers": "^1.0.2",
-        "es-define-property": "^1.0.1",
-        "es-errors": "^1.3.0",
-        "es-object-atoms": "^1.1.1",
-        "function-bind": "^1.1.2",
-        "get-proto": "^1.0.1",
-        "gopd": "^1.2.0",
-        "has-symbols": "^1.1.0",
-        "hasown": "^2.0.2",
-        "math-intrinsics": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/get-proto": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
-      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
-      "license": "MIT",
-      "dependencies": {
-        "dunder-proto": "^1.0.1",
-        "es-object-atoms": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/giget": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
-      "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "citty": "^0.1.6",
-        "consola": "^3.4.0",
-        "defu": "^6.1.4",
-        "node-fetch-native": "^1.6.6",
-        "nypm": "^0.6.0",
-        "pathe": "^2.0.3"
-      },
-      "bin": {
-        "giget": "dist/cli.mjs"
-      }
-    },
-    "node_modules/glob": {
-      "version": "10.4.5",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
-      "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "foreground-child": "^3.1.0",
-        "jackspeak": "^3.1.2",
-        "minimatch": "^9.0.4",
-        "minipass": "^7.1.2",
-        "package-json-from-dist": "^1.0.0",
-        "path-scurry": "^1.11.1"
-      },
-      "bin": {
-        "glob": "dist/esm/bin.mjs"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/glob-parent": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "is-glob": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/gopd": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
-      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-property-descriptors": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
-      "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
-      "license": "MIT",
-      "dependencies": {
-        "es-define-property": "^1.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-symbols": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
-      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-tostringtag": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
-      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-symbols": "^1.0.3"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/hasown": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
-      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-      "license": "MIT",
-      "dependencies": {
-        "function-bind": "^1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/he": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
-      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
-      "dev": true,
-      "license": "MIT",
-      "bin": {
-        "he": "bin/he"
-      }
-    },
-    "node_modules/hey-listen": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz",
-      "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
-      "license": "MIT"
-    },
-    "node_modules/ignore": {
-      "version": "7.0.5",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
-      "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "license": "ISC"
-    },
-    "node_modules/is-arguments": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.2.0.tgz",
-      "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-binary-path": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "binary-extensions": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-callable": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz",
-      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-core-module": {
-      "version": "2.16.1",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
-      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "hasown": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-generator-function": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/is-generator-function/-/is-generator-function-1.1.0.tgz",
-      "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bound": "^1.0.3",
-        "get-proto": "^1.0.0",
-        "has-tostringtag": "^1.0.2",
-        "safe-regex-test": "^1.1.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
-    "node_modules/is-regex": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.2.1.tgz",
-      "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "gopd": "^1.2.0",
-        "has-tostringtag": "^1.0.2",
-        "hasown": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-typed-array": {
-      "version": "1.1.15",
-      "resolved": "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.15.tgz",
-      "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
-      "license": "MIT",
-      "dependencies": {
-        "which-typed-array": "^1.1.16"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-      "dev": true,
-      "license": "ISC"
-    },
-    "node_modules/jackspeak": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
-      "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
-      "dev": true,
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "@isaacs/cliui": "^8.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      },
-      "optionalDependencies": {
-        "@pkgjs/parseargs": "^0.11.0"
-      }
-    },
-    "node_modules/jiti": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
-      "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
-      "license": "MIT",
-      "optional": true,
-      "bin": {
-        "jiti": "lib/jiti-cli.mjs"
-      }
-    },
-    "node_modules/js-tokens": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
-      "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/klona": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
-      "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/knitwork": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/knitwork/-/knitwork-1.2.0.tgz",
-      "integrity": "sha512-xYSH7AvuQ6nXkq42x0v5S8/Iry+cfulBz/DJQzhIyESdLD7425jXsPy4vn5cCXU+HhRN2kVw51Vd1K6/By4BQg==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/lilconfig": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
-      "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antonk52"
-      }
-    },
-    "node_modules/lines-and-columns": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/local-pkg": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz",
-      "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "mlly": "^1.7.4",
-        "pkg-types": "^2.0.1",
-        "quansync": "^0.2.8"
-      },
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
-    "node_modules/lru-cache": {
-      "version": "10.4.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
-      "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
-      "dev": true,
-      "license": "ISC"
-    },
-    "node_modules/lucide-vue-next": {
-      "version": "0.290.0",
-      "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.290.0.tgz",
-      "integrity": "sha512-M3EAXDq7Gy7W3OvK+98P9QA+zX2T7EGrXUCAeEa0/CuRjNXZRRFcZEe9j/+O6CpMtlmWceh2K3qpQXNdQ/pmsw==",
-      "license": "ISC",
-      "peerDependencies": {
-        "vue": ">=3.0.1"
-      }
-    },
-    "node_modules/magic-string": {
-      "version": "0.30.17",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
-      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.5.0"
-      }
-    },
-    "node_modules/math-intrinsics": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
-      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/micromatch": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
-      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "braces": "^3.0.3",
-        "picomatch": "^2.3.1"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "9.0.5",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
-      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/minipass": {
-      "version": "7.1.2",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
-      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
-      "dev": true,
-      "license": "ISC",
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      }
-    },
-    "node_modules/mlly": {
-      "version": "1.7.4",
-      "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
-      "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "acorn": "^8.14.0",
-        "pathe": "^2.0.1",
-        "pkg-types": "^1.3.0",
-        "ufo": "^1.5.4"
-      }
-    },
-    "node_modules/mlly/node_modules/confbox": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
-      "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/mlly/node_modules/pkg-types": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
-      "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "confbox": "^0.1.8",
-        "mlly": "^1.7.4",
-        "pathe": "^2.0.1"
-      }
-    },
-    "node_modules/muggle-string": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
-      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/mz": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
-      "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "any-promise": "^1.0.0",
-        "object-assign": "^4.0.1",
-        "thenify-all": "^1.0.0"
-      }
-    },
-    "node_modules/nanoid": {
-      "version": "3.3.11",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
-      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "bin": {
-        "nanoid": "bin/nanoid.cjs"
-      },
-      "engines": {
-        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-      }
-    },
-    "node_modules/node-fetch-native": {
-      "version": "1.6.6",
-      "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
-      "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/node-releases": {
-      "version": "2.0.19",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
-      "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/normalize-range": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
-      "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/nypm": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.0.tgz",
-      "integrity": "sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "citty": "^0.1.6",
-        "consola": "^3.4.0",
-        "pathe": "^2.0.3",
-        "pkg-types": "^2.0.0",
-        "tinyexec": "^0.3.2"
-      },
-      "bin": {
-        "nypm": "dist/cli.mjs"
-      },
-      "engines": {
-        "node": "^14.16.0 || >=16.10.0"
-      }
-    },
-    "node_modules/object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/object-hash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
-      "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/ohash": {
-      "version": "2.0.11",
-      "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
-      "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/package-json-from-dist": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
-      "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
-      "dev": true,
-      "license": "BlueOak-1.0.0"
-    },
-    "node_modules/path-browserify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
-      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-parse": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/path-scurry": {
-      "version": "1.11.1",
-      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
-      "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
-      "dev": true,
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "lru-cache": "^10.2.0",
-        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
-      },
-      "engines": {
-        "node": ">=16 || 14 >=14.18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/pathe": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
-      "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/perfect-debounce": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
-      "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/picocolors": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
-      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
-      "license": "ISC"
-    },
-    "node_modules/picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/pify": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
-      "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/pinia": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz",
-      "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/devtools-api": "^6.6.3",
-        "vue-demi": "^0.14.10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/posva"
-      },
-      "peerDependencies": {
-        "typescript": ">=4.4.4",
-        "vue": "^2.7.0 || ^3.5.11"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/pirates": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
-      "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/pkg-types": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.2.0.tgz",
-      "integrity": "sha512-2SM/GZGAEkPp3KWORxQZns4M+WSeXbC2HEvmOIJe3Cmiv6ieAJvdVhDldtHqM5J1Y7MrR1XhkBT/rMlhh9FdqQ==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "confbox": "^0.2.2",
-        "exsolve": "^1.0.7",
-        "pathe": "^2.0.3"
-      }
-    },
-    "node_modules/popmotion": {
-      "version": "11.0.5",
-      "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.5.tgz",
-      "integrity": "sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==",
-      "license": "MIT",
-      "dependencies": {
-        "framesync": "6.1.2",
-        "hey-listen": "^1.0.8",
-        "style-value-types": "5.1.2",
-        "tslib": "2.4.0"
-      }
-    },
-    "node_modules/possible-typed-array-names": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
-      "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/postcss": {
-      "version": "8.5.6",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
-      "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/postcss"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "nanoid": "^3.3.11",
-        "picocolors": "^1.1.1",
-        "source-map-js": "^1.2.1"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      }
-    },
-    "node_modules/postcss-import": {
-      "version": "15.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
-      "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "postcss-value-parser": "^4.0.0",
-        "read-cache": "^1.0.0",
-        "resolve": "^1.1.7"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.0.0"
-      }
-    },
-    "node_modules/postcss-js": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
-      "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "camelcase-css": "^2.0.1"
-      },
-      "engines": {
-        "node": "^12 || ^14 || >= 16"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/postcss/"
-      },
-      "peerDependencies": {
-        "postcss": "^8.4.21"
-      }
-    },
-    "node_modules/postcss-load-config": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
-      "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "lilconfig": "^3.0.0",
-        "yaml": "^2.3.4"
-      },
-      "engines": {
-        "node": ">= 14"
-      },
-      "peerDependencies": {
-        "postcss": ">=8.0.9",
-        "ts-node": ">=9.0.0"
-      },
-      "peerDependenciesMeta": {
-        "postcss": {
-          "optional": true
-        },
-        "ts-node": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/postcss-nested": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
-      "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "postcss-selector-parser": "^6.1.1"
-      },
-      "engines": {
-        "node": ">=12.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.14"
-      }
-    },
-    "node_modules/postcss-selector-parser": {
-      "version": "6.1.2",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
-      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "cssesc": "^3.0.0",
-        "util-deprecate": "^1.0.2"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/postcss-value-parser": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
-      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/quansync": {
-      "version": "0.2.10",
-      "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
-      "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://github.com/sponsors/antfu"
-        },
-        {
-          "type": "individual",
-          "url": "https://github.com/sponsors/sxzz"
-        }
-      ],
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/rc9": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
-      "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "defu": "^6.1.4",
-        "destr": "^2.0.3"
-      }
-    },
-    "node_modules/read-cache": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
-      "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "pify": "^2.3.0"
-      }
-    },
-    "node_modules/readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-      "license": "MIT",
-      "dependencies": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/readdirp": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
-      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">= 14.18.0"
-      },
-      "funding": {
-        "type": "individual",
-        "url": "https://paulmillr.com/funding/"
-      }
-    },
-    "node_modules/resolve": {
-      "version": "1.22.10",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
-      "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "is-core-module": "^2.16.0",
-        "path-parse": "^1.0.7",
-        "supports-preserve-symlinks-flag": "^1.0.0"
-      },
-      "bin": {
-        "resolve": "bin/resolve"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/reusify": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
-      "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "iojs": ">=1.0.0",
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/rollup": {
-      "version": "4.44.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz",
-      "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@types/estree": "1.0.8"
-      },
-      "bin": {
-        "rollup": "dist/bin/rollup"
-      },
-      "engines": {
-        "node": ">=18.0.0",
-        "npm": ">=8.0.0"
-      },
-      "optionalDependencies": {
-        "@rollup/rollup-android-arm-eabi": "4.44.1",
-        "@rollup/rollup-android-arm64": "4.44.1",
-        "@rollup/rollup-darwin-arm64": "4.44.1",
-        "@rollup/rollup-darwin-x64": "4.44.1",
-        "@rollup/rollup-freebsd-arm64": "4.44.1",
-        "@rollup/rollup-freebsd-x64": "4.44.1",
-        "@rollup/rollup-linux-arm-gnueabihf": "4.44.1",
-        "@rollup/rollup-linux-arm-musleabihf": "4.44.1",
-        "@rollup/rollup-linux-arm64-gnu": "4.44.1",
-        "@rollup/rollup-linux-arm64-musl": "4.44.1",
-        "@rollup/rollup-linux-loongarch64-gnu": "4.44.1",
-        "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1",
-        "@rollup/rollup-linux-riscv64-gnu": "4.44.1",
-        "@rollup/rollup-linux-riscv64-musl": "4.44.1",
-        "@rollup/rollup-linux-s390x-gnu": "4.44.1",
-        "@rollup/rollup-linux-x64-gnu": "4.44.1",
-        "@rollup/rollup-linux-x64-musl": "4.44.1",
-        "@rollup/rollup-win32-arm64-msvc": "4.44.1",
-        "@rollup/rollup-win32-ia32-msvc": "4.44.1",
-        "@rollup/rollup-win32-x64-msvc": "4.44.1",
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "queue-microtask": "^1.2.2"
-      }
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/safe-regex-test": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
-      "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bound": "^1.0.2",
-        "es-errors": "^1.3.0",
-        "is-regex": "^1.2.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/scule": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz",
-      "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/semver": {
-      "version": "7.7.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
-      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
-      "license": "ISC",
-      "optional": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/set-function-length": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
-      "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
-      "license": "MIT",
-      "dependencies": {
-        "define-data-property": "^1.1.4",
-        "es-errors": "^1.3.0",
-        "function-bind": "^1.1.2",
-        "get-intrinsic": "^1.2.4",
-        "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "shebang-regex": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/signal-exit": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-      "dev": true,
-      "license": "ISC",
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/source-map-js": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
-      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/std-env": {
-      "version": "3.9.0",
-      "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz",
-      "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/stream-browserify": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/stream-browserify/-/stream-browserify-3.0.0.tgz",
-      "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
-      "license": "MIT",
-      "dependencies": {
-        "inherits": "~2.0.4",
-        "readable-stream": "^3.5.0"
-      }
-    },
-    "node_modules/string_decoder": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz",
-      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
-      "license": "MIT",
-      "dependencies": {
-        "safe-buffer": "~5.2.0"
-      }
-    },
-    "node_modules/string-width": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
-      "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "eastasianwidth": "^0.2.0",
-        "emoji-regex": "^9.2.2",
-        "strip-ansi": "^7.0.1"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/string-width-cjs": {
-      "name": "string-width",
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/string-width-cjs/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/string-width-cjs/node_modules/emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/string-width-cjs/node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-ansi": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
-      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/strip-ansi?sponsor=1"
-      }
-    },
-    "node_modules/strip-ansi-cjs": {
-      "name": "strip-ansi",
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-literal": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz",
-      "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "js-tokens": "^9.0.1"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      }
-    },
-    "node_modules/style-value-types": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.1.2.tgz",
-      "integrity": "sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==",
-      "license": "MIT",
-      "dependencies": {
-        "hey-listen": "^1.0.8",
-        "tslib": "2.4.0"
-      }
-    },
-    "node_modules/sucrase": {
-      "version": "3.35.0",
-      "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
-      "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.2",
-        "commander": "^4.0.0",
-        "glob": "^10.3.10",
-        "lines-and-columns": "^1.1.6",
-        "mz": "^2.7.0",
-        "pirates": "^4.0.1",
-        "ts-interface-checker": "^0.1.9"
-      },
-      "bin": {
-        "sucrase": "bin/sucrase",
-        "sucrase-node": "bin/sucrase-node"
-      },
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      }
-    },
-    "node_modules/supports-preserve-symlinks-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/tailwindcss": {
-      "version": "3.4.17",
-      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
-      "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@alloc/quick-lru": "^5.2.0",
-        "arg": "^5.0.2",
-        "chokidar": "^3.6.0",
-        "didyoumean": "^1.2.2",
-        "dlv": "^1.1.3",
-        "fast-glob": "^3.3.2",
-        "glob-parent": "^6.0.2",
-        "is-glob": "^4.0.3",
-        "jiti": "^1.21.6",
-        "lilconfig": "^3.1.3",
-        "micromatch": "^4.0.8",
-        "normalize-path": "^3.0.0",
-        "object-hash": "^3.0.0",
-        "picocolors": "^1.1.1",
-        "postcss": "^8.4.47",
-        "postcss-import": "^15.1.0",
-        "postcss-js": "^4.0.1",
-        "postcss-load-config": "^4.0.2",
-        "postcss-nested": "^6.2.0",
-        "postcss-selector-parser": "^6.1.2",
-        "resolve": "^1.22.8",
-        "sucrase": "^3.35.0"
-      },
-      "bin": {
-        "tailwind": "lib/cli.js",
-        "tailwindcss": "lib/cli.js"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/tailwindcss/node_modules/chokidar": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
-      "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
-      },
-      "engines": {
-        "node": ">= 8.10.0"
-      },
-      "funding": {
-        "url": "https://paulmillr.com/funding/"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/tailwindcss/node_modules/chokidar/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/tailwindcss/node_modules/jiti": {
-      "version": "1.21.7",
-      "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
-      "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
-      "dev": true,
-      "license": "MIT",
-      "bin": {
-        "jiti": "bin/jiti.js"
-      }
-    },
-    "node_modules/tailwindcss/node_modules/readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "picomatch": "^2.2.1"
-      },
-      "engines": {
-        "node": ">=8.10.0"
-      }
-    },
-    "node_modules/thenify": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
-      "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "any-promise": "^1.0.0"
-      }
-    },
-    "node_modules/thenify-all": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
-      "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "thenify": ">= 3.1.0 < 4"
-      },
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/tinyexec": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
-      "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/tinyglobby": {
-      "version": "0.2.14",
-      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
-      "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "fdir": "^6.4.4",
-        "picomatch": "^4.0.2"
-      },
-      "engines": {
-        "node": ">=12.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/SuperchupuDev"
-      }
-    },
-    "node_modules/tinyglobby/node_modules/fdir": {
-      "version": "6.4.6",
-      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
-      "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
-      "license": "MIT",
-      "optional": true,
-      "peerDependencies": {
-        "picomatch": "^3 || ^4"
-      },
-      "peerDependenciesMeta": {
-        "picomatch": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/tinyglobby/node_modules/picomatch": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
-      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "is-number": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
-    "node_modules/ts-interface-checker": {
-      "version": "0.1.13",
-      "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
-      "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
-      "dev": true,
-      "license": "Apache-2.0"
-    },
-    "node_modules/tslib": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
-      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
-      "license": "0BSD"
-    },
-    "node_modules/typescript": {
-      "version": "5.8.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
-      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
-      "devOptional": true,
-      "license": "Apache-2.0",
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=14.17"
-      }
-    },
-    "node_modules/ufo": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
-      "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/unctx": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/unctx/-/unctx-2.4.1.tgz",
-      "integrity": "sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "acorn": "^8.14.0",
-        "estree-walker": "^3.0.3",
-        "magic-string": "^0.30.17",
-        "unplugin": "^2.1.0"
-      }
-    },
-    "node_modules/unimport": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/unimport/-/unimport-5.1.0.tgz",
-      "integrity": "sha512-wMmuG+wkzeHh2KCE6yiDlHmKelN8iE/maxkUYMbmrS6iV8+n6eP1TH3yKKlepuF4hrkepinEGmBXdfo9XZUvAw==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "acorn": "^8.15.0",
-        "escape-string-regexp": "^5.0.0",
-        "estree-walker": "^3.0.3",
-        "local-pkg": "^1.1.1",
-        "magic-string": "^0.30.17",
-        "mlly": "^1.7.4",
-        "pathe": "^2.0.3",
-        "picomatch": "^4.0.2",
-        "pkg-types": "^2.1.1",
-        "scule": "^1.3.0",
-        "strip-literal": "^3.0.0",
-        "tinyglobby": "^0.2.14",
-        "unplugin": "^2.3.5",
-        "unplugin-utils": "^0.2.4"
-      },
-      "engines": {
-        "node": ">=18.12.0"
-      }
-    },
-    "node_modules/unimport/node_modules/picomatch": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
-      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/unplugin": {
-      "version": "2.3.5",
-      "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.5.tgz",
-      "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "acorn": "^8.14.1",
-        "picomatch": "^4.0.2",
-        "webpack-virtual-modules": "^0.6.2"
-      },
-      "engines": {
-        "node": ">=18.12.0"
-      }
-    },
-    "node_modules/unplugin-utils": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
-      "integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "pathe": "^2.0.2",
-        "picomatch": "^4.0.2"
-      },
-      "engines": {
-        "node": ">=18.12.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sxzz"
-      }
-    },
-    "node_modules/unplugin-utils/node_modules/picomatch": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
-      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/unplugin/node_modules/picomatch": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
-      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
-      "license": "MIT",
-      "optional": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/untyped": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/untyped/-/untyped-2.0.0.tgz",
-      "integrity": "sha512-nwNCjxJTjNuLCgFr42fEak5OcLuB3ecca+9ksPFNvtfYSLpjf+iJqSIaSnIile6ZPbKYxI5k2AfXqeopGudK/g==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "citty": "^0.1.6",
-        "defu": "^6.1.4",
-        "jiti": "^2.4.2",
-        "knitwork": "^1.2.0",
-        "scule": "^1.3.0"
-      },
-      "bin": {
-        "untyped": "dist/cli.mjs"
-      }
-    },
-    "node_modules/update-browserslist-db": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
-      "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/browserslist"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "escalade": "^3.2.0",
-        "picocolors": "^1.1.1"
-      },
-      "bin": {
-        "update-browserslist-db": "cli.js"
-      },
-      "peerDependencies": {
-        "browserslist": ">= 4.21.0"
-      }
-    },
-    "node_modules/util": {
-      "version": "0.12.5",
-      "resolved": "https://registry.npmmirror.com/util/-/util-0.12.5.tgz",
-      "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
-      "license": "MIT",
-      "dependencies": {
-        "inherits": "^2.0.3",
-        "is-arguments": "^1.0.4",
-        "is-generator-function": "^1.0.7",
-        "is-typed-array": "^1.1.3",
-        "which-typed-array": "^1.1.2"
-      }
-    },
-    "node_modules/util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "license": "MIT"
-    },
-    "node_modules/vite": {
-      "version": "5.4.19",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
-      "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "esbuild": "^0.21.3",
-        "postcss": "^8.4.43",
-        "rollup": "^4.20.0"
-      },
-      "bin": {
-        "vite": "bin/vite.js"
-      },
-      "engines": {
-        "node": "^18.0.0 || >=20.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/vitejs/vite?sponsor=1"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.3"
-      },
-      "peerDependencies": {
-        "@types/node": "^18.0.0 || >=20.0.0",
-        "less": "*",
-        "lightningcss": "^1.21.0",
-        "sass": "*",
-        "sass-embedded": "*",
-        "stylus": "*",
-        "sugarss": "*",
-        "terser": "^5.4.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/node": {
-          "optional": true
-        },
-        "less": {
-          "optional": true
-        },
-        "lightningcss": {
-          "optional": true
-        },
-        "sass": {
-          "optional": true
-        },
-        "sass-embedded": {
-          "optional": true
-        },
-        "stylus": {
-          "optional": true
-        },
-        "sugarss": {
-          "optional": true
-        },
-        "terser": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/vscode-uri": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
-      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/vue": {
-      "version": "3.5.17",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.17.tgz",
-      "integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==",
-      "license": "MIT",
-      "dependencies": {
-        "@vue/compiler-dom": "3.5.17",
-        "@vue/compiler-sfc": "3.5.17",
-        "@vue/runtime-dom": "3.5.17",
-        "@vue/server-renderer": "3.5.17",
-        "@vue/shared": "3.5.17"
-      },
-      "peerDependencies": {
-        "typescript": "*"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/vue-demi": {
-      "version": "0.14.10",
-      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
-      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
-      "hasInstallScript": true,
-      "license": "MIT",
-      "bin": {
-        "vue-demi-fix": "bin/vue-demi-fix.js",
-        "vue-demi-switch": "bin/vue-demi-switch.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/antfu"
-      },
-      "peerDependencies": {
-        "@vue/composition-api": "^1.0.0-rc.1",
-        "vue": "^3.0.0-0 || ^2.6.0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/composition-api": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/vue-tsc": {
-      "version": "2.2.10",
-      "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.10.tgz",
-      "integrity": "sha512-jWZ1xSaNbabEV3whpIDMbjVSVawjAyW+x1n3JeGQo7S0uv2n9F/JMgWW90tGWNFRKya4YwKMZgCtr0vRAM7DeQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@volar/typescript": "~2.4.11",
-        "@vue/language-core": "2.2.10"
-      },
-      "bin": {
-        "vue-tsc": "bin/vue-tsc.js"
-      },
-      "peerDependencies": {
-        "typescript": ">=5.0.0"
-      }
-    },
-    "node_modules/webpack-virtual-modules": {
-      "version": "0.6.2",
-      "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
-      "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dev": true,
-      "license": "ISC",
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "node-which": "bin/node-which"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/which-typed-array": {
-      "version": "1.1.19",
-      "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.19.tgz",
-      "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
-      "license": "MIT",
-      "dependencies": {
-        "available-typed-arrays": "^1.0.7",
-        "call-bind": "^1.0.8",
-        "call-bound": "^1.0.4",
-        "for-each": "^0.3.5",
-        "get-proto": "^1.0.1",
-        "gopd": "^1.2.0",
-        "has-tostringtag": "^1.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/wrap-ansi": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
-      "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^6.1.0",
-        "string-width": "^5.0.1",
-        "strip-ansi": "^7.0.1"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi-cjs": {
-      "name": "wrap-ansi",
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/wrap-ansi-cjs/node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/yaml": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
-      "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
-      "dev": true,
-      "license": "ISC",
-      "bin": {
-        "yaml": "bin.mjs"
-      },
-      "engines": {
-        "node": ">= 14.6"
-      }
-    }
-  }
-}

+ 0 - 29
package.json

@@ -1,29 +0,0 @@
-{
-  "name": "hr-recruitment-app",
-  "private": true,
-  "version": "0.0.0",
-  "type": "module",
-  "scripts": {
-    "dev": "vite",
-    "build": "vue-tsc && vite build",
-    "preview": "vite preview"
-  },
-  "dependencies": {
-    "@vueuse/motion": "^2.0.0",
-    "events": "^3.3.0",
-    "lucide-vue-next": "^0.290.0",
-    "pinia": "^2.1.7",
-    "stream-browserify": "^3.0.0",
-    "util": "^0.12.5",
-    "vue": "^3.4.38"
-  },
-  "devDependencies": {
-    "@vitejs/plugin-vue": "^5.2.4",
-    "autoprefixer": "^10.4.16",
-    "postcss": "^8.4.32",
-    "tailwindcss": "^3.4.0",
-    "typescript": "^5.5.3",
-    "vite": "^5.4.2",
-    "vue-tsc": "^2.1.4"
-  }
-}

+ 0 - 6
postcss.config.js

@@ -1,6 +0,0 @@
-export default {
-  plugins: {
-    tailwindcss: {},
-    autoprefixer: {},
-  },
-}

+ 0 - 1
public/vite.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

+ 0 - 70
src/App.vue

@@ -1,70 +0,0 @@
-<script setup lang="ts">
-import { ref, onMounted } from 'vue'
-import { useJobStore } from './stores/jobStore'
-import JobManagementView from './views/JobManagementView.vue'
-import CandidateView from './views/CandidateView.vue'
-import DashboardView from './views/DashboardView.vue'
-import BottomNavigation from './components/BottomNavigation.vue'
-
-const jobStore = useJobStore()
-const currentView = ref('jobs')
-
-const views = {
-  jobs: JobManagementView,
-  candidates: CandidateView,
-  dashboard: DashboardView
-}
-
-const handleNavChange = (view: string) => {
-  currentView.value = view
-}
-
-onMounted(() => {
-  // 初始化应用数据
-  jobStore.initializeData()
-})
-</script>
-
-<template>
-  <div class="min-h-screen bg-gradient-to-br from-gray-50 via-blue-50/30 to-purple-50/30 flex flex-col">
-    <!-- 主内容区域 -->
-    <main class="flex-1 pb-20 safe-area-top">
-      <Transition
-        name="page"
-        mode="out-in"
-        appear
-      >
-        <component 
-          :is="views[currentView as keyof typeof views]"
-          :key="currentView"
-          class="min-h-full"
-        />
-      </Transition>
-    </main>
-    
-    <!-- 底部导航栏 -->
-    <BottomNavigation 
-      :current-view="currentView"
-      @change="handleNavChange"
-      class="safe-area-bottom"
-    />
-  </div>
-</template>
-
-<style scoped>
-/* 页面切换动画 */
-.page-enter-active,
-.page-leave-active {
-  transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
-}
-
-.page-enter-from {
-  opacity: 0;
-  transform: translateX(20px);
-}
-
-.page-leave-to {
-  opacity: 0;
-  transform: translateX(-20px);
-}
-</style>

+ 0 - 1
src/assets/vue.svg

@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

+ 0 - 79
src/components/BottomNavigation.vue

@@ -1,79 +0,0 @@
-<script setup lang="ts">
-import { Briefcase, Users, BarChart3 } from 'lucide-vue-next'
-
-interface Props {
-  currentView: string
-}
-
-interface Emits {
-  (e: 'change', view: string): void
-}
-
-defineProps<Props>()
-const emit = defineEmits<Emits>()
-
-const navItems = [
-  {
-    id: 'jobs',
-    label: '岗位管理',
-    icon: Briefcase
-  },
-  {
-    id: 'candidates',
-    label: '候选人',
-    icon: Users
-  },
-  {
-    id: 'dashboard',
-    label: '数据面板',
-    icon: BarChart3
-  }
-]
-
-const handleNavClick = (viewId: string) => {
-  emit('change', viewId)
-}
-</script>
-
-<template>
-  <nav class="fixed bottom-0 left-0 right-0 bg-white/90 backdrop-blur-lg border-t border-gray-200 safe-area-bottom">
-    <div class="flex items-center justify-around px-4 py-2">
-      <button
-        v-for="item in navItems"
-        :key="item.id"
-        @click="handleNavClick(item.id)"
-        :class="[
-          'flex flex-col items-center justify-center px-4 py-3 rounded-xl transition-all duration-300 min-w-0 flex-1',
-          currentView === item.id 
-            ? 'text-primary-600 bg-primary-50' 
-            : 'text-gray-500 hover:text-gray-700 active:scale-95'
-        ]"
-      >
-        <component 
-          :is="item.icon" 
-          :size="20" 
-          :class="[
-            'mb-1 transition-all duration-300',
-            currentView === item.id ? 'scale-110' : ''
-          ]"
-        />
-        <span 
-          :class="[
-            'text-xs font-medium transition-all duration-300',
-            currentView === item.id ? 'font-semibold' : ''
-          ]"
-        >
-          {{ item.label }}
-        </span>
-        
-        <!-- 活跃指示器 -->
-        <div 
-          :class="[
-            'w-1 h-1 bg-primary-600 rounded-full mt-1 transition-all duration-300',
-            currentView === item.id ? 'opacity-100 scale-100' : 'opacity-0 scale-50'
-          ]"
-        ></div>
-      </button>
-    </div>
-  </nav>
-</template>

+ 0 - 241
src/components/CandidateCard.vue

@@ -1,241 +0,0 @@
-<script setup lang="ts">
-import { computed } from 'vue'
-import { type Candidate } from '../stores/jobStore'
-import { Clock, CheckCircle, XCircle, UserCheck, Star, MapPin, Calendar } from 'lucide-vue-next'
-
-interface Props {
-  candidate: Candidate
-  isSelected?: boolean
-}
-
-interface Emits {
-  (e: 'click'): void
-  (e: 'toggle-selection'): void
-}
-
-const props = defineProps<Props>()
-const emit = defineEmits<Emits>()
-
-const getStatusConfig = (status: Candidate['status']) => {
-  switch (status) {
-    case 'pending':
-      return { 
-        label: '待处理', 
-        class: 'bg-warning-100 text-warning-700 border-warning-200',
-        icon: Clock,
-        dotClass: 'bg-warning-500'
-      }
-    case 'passed':
-      return { 
-        label: '已通过', 
-        class: 'bg-success-100 text-success-700 border-success-200',
-        icon: CheckCircle,
-        dotClass: 'bg-success-500'
-      }
-    case 'rejected':
-      return { 
-        label: '已拒绝', 
-        class: 'bg-error-100 text-error-700 border-error-200',
-        icon: XCircle,
-        dotClass: 'bg-error-500'
-      }
-    case 'interviewed':
-      return { 
-        label: '已面试', 
-        class: 'bg-primary-100 text-primary-700 border-primary-200',
-        icon: UserCheck,
-        dotClass: 'bg-primary-500'
-      }
-    default:
-      return { 
-        label: '未知', 
-        class: 'bg-gray-100 text-gray-700 border-gray-200',
-        icon: Clock,
-        dotClass: 'bg-gray-500'
-      }
-  }
-}
-
-const getScoreColor = (score: number) => {
-  if (score >= 85) return 'text-success-600'
-  if (score >= 70) return 'text-primary-600'
-  return 'text-warning-600'
-}
-
-const getScoreBackground = (score: number) => {
-  if (score >= 85) return 'from-success-500 to-success-600'
-  if (score >= 70) return 'from-primary-500 to-primary-600'
-  return 'from-warning-500 to-warning-600'
-}
-
-const statusConfig = computed(() => getStatusConfig(props.candidate.status))
-
-const handleCardClick = (event: Event) => {
-  // 如果点击的是选择框,不触发卡片点击
-  if ((event.target as HTMLElement).closest('.selection-checkbox')) {
-    return
-  }
-  emit('click')
-}
-
-const handleSelectionToggle = (event: Event) => {
-  event.stopPropagation()
-  emit('toggle-selection')
-}
-
-const formatDate = (date: Date) => {
-  return new Intl.DateTimeFormat('zh-CN', {
-    month: 'short',
-    day: 'numeric',
-    hour: '2-digit',
-    minute: '2-digit'
-  }).format(date)
-}
-</script>
-
-<template>
-  <div 
-    @click="handleCardClick"
-    :class="[
-      'glass-card p-6 cursor-pointer transition-all duration-300 group relative',
-      'hover:shadow-xl hover:-translate-y-1',
-      isSelected && 'ring-2 ring-primary-500 bg-primary-50/50'
-    ]"
-    v-motion-fade-visible-once
-  >
-    <!-- 选择框 (仅待处理状态显示) -->
-    <div 
-      v-if="candidate.status === 'pending'"
-      class="selection-checkbox absolute top-4 right-4"
-    >
-      <input
-        type="checkbox"
-        :checked="isSelected"
-        @change="handleSelectionToggle"
-        class="w-5 h-5 text-primary-600 bg-white border-2 border-gray-300 rounded focus:ring-primary-500 focus:ring-2"
-      >
-    </div>
-
-    <!-- 卡片头部 -->
-    <div class="flex items-start justify-between mb-4">
-      <div class="flex-1 min-w-0 pr-8">
-        <div class="flex items-center gap-2 mb-2">
-          <h3 class="text-lg font-semibold text-gray-900 group-hover:text-primary-600 transition-colors">
-            {{ candidate.name }}
-          </h3>
-          <div :class="['w-2 h-2 rounded-full', statusConfig.dotClass]"></div>
-        </div>
-        
-        <p class="text-sm text-gray-600 mb-1">{{ candidate.jobTitle }}</p>
-        
-        <div class="flex items-center gap-4 text-xs text-gray-500">
-          <div class="flex items-center gap-1">
-            <Calendar :size="12" />
-            {{ formatDate(candidate.submittedAt) }}
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <!-- 匹配度分数 -->
-    <div class="flex items-center justify-between mb-4">
-      <div class="flex items-center gap-2">
-        <Star :size="16" class="text-yellow-500" />
-        <span class="text-sm font-medium text-gray-700">AI匹配度</span>
-      </div>
-      
-      <div class="relative">
-        <div 
-          :class="[
-            'text-2xl font-bold px-3 py-1 rounded-lg',
-            getScoreColor(candidate.matchScore)
-          ]"
-          :style="{
-            background: `linear-gradient(135deg, var(--tw-gradient-stops))`,
-            '--tw-gradient-from': candidate.matchScore >= 85 ? '#10b981' : candidate.matchScore >= 70 ? '#3b82f6' : '#f59e0b',
-            '--tw-gradient-to': candidate.matchScore >= 85 ? '#059669' : candidate.matchScore >= 70 ? '#2563eb' : '#d97706',
-            color: 'white'
-          }"
-        >
-          {{ candidate.matchScore }}
-        </div>
-      </div>
-    </div>
-
-    <!-- 候选人信息 -->
-    <div class="grid grid-cols-2 gap-4 mb-4 text-sm">
-      <div>
-        <span class="text-gray-500">学历:</span>
-        <span class="ml-1 font-medium text-gray-900">{{ candidate.education }}</span>
-      </div>
-      <div>
-        <span class="text-gray-500">经验:</span>
-        <span class="ml-1 font-medium text-gray-900">{{ candidate.experience }}</span>
-      </div>
-    </div>
-
-    <!-- 技能标签 -->
-    <div class="mb-4">
-      <div class="flex flex-wrap gap-2">
-        <span 
-          v-for="skill in candidate.skills.slice(0, 3)"
-          :key="skill"
-          class="px-2 py-1 bg-primary-100 text-primary-700 text-xs rounded-md font-medium"
-        >
-          {{ skill }}
-        </span>
-        <span 
-          v-if="candidate.skills.length > 3"
-          class="px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded-md"
-        >
-          +{{ candidate.skills.length - 3 }}
-        </span>
-      </div>
-    </div>
-
-    <!-- 亮点预览 -->
-    <div class="mb-4">
-      <h4 class="text-sm font-medium text-gray-900 mb-2">主要亮点</h4>
-      <ul class="space-y-1">
-        <li 
-          v-for="highlight in candidate.highlights.slice(0, 2)"
-          :key="highlight"
-          class="flex items-start gap-2 text-sm text-gray-700"
-        >
-          <CheckCircle :size="14" class="text-success-600 mt-0.5 flex-shrink-0" />
-          <span class="line-clamp-1">{{ highlight }}</span>
-        </li>
-      </ul>
-      <p 
-        v-if="candidate.highlights.length > 2"
-        class="text-xs text-gray-500 mt-1"
-      >
-        还有 {{ candidate.highlights.length - 2 }} 个亮点...
-      </p>
-    </div>
-
-    <!-- 状态标签 -->
-    <div class="flex items-center justify-between pt-4 border-t border-gray-100">
-      <span :class="['px-3 py-1 rounded-full text-xs font-medium border', statusConfig.class]">
-        <component :is="statusConfig.icon" :size="12" class="inline mr-1" />
-        {{ statusConfig.label }}
-      </span>
-      
-      <div v-if="candidate.reviewedAt" class="text-xs text-gray-500">
-        {{ formatDate(candidate.reviewedAt) }} 处理
-      </div>
-    </div>
-
-    <!-- 悬浮效果指示器 -->
-    <div class="absolute inset-0 rounded-2xl bg-gradient-to-r from-primary-500/0 to-secondary-500/0 group-hover:from-primary-500/5 group-hover:to-secondary-500/5 transition-all duration-300 pointer-events-none"></div>
-  </div>
-</template>
-
-<style scoped>
-.line-clamp-1 {
-  display: -webkit-box;
-  -webkit-line-clamp: 1;
-  -webkit-box-orient: vertical;
-  overflow: hidden;
-}
-</style>

+ 0 - 373
src/components/CandidateDetailModal.vue

@@ -1,373 +0,0 @@
-<script setup lang="ts">
-import { computed, ref } from 'vue'
-import { useJobStore } from '../stores/jobStore'
-import { X, Star, CheckCircle, XCircle, AlertTriangle, User, FileText, MessageSquare, ArrowRight } from 'lucide-vue-next'
-
-interface Props {
-  isOpen: boolean
-}
-
-interface Emits {
-  (e: 'close'): void
-}
-
-const props = defineProps<Props>()
-const emit = defineEmits<Emits>()
-
-const jobStore = useJobStore()
-
-const candidate = computed(() => jobStore.currentCandidate)
-
-const activeTab = ref('analysis')
-
-const getScoreColor = (score: number) => {
-  if (score >= 85) return 'text-success-600'
-  if (score >= 70) return 'text-primary-600'
-  return 'text-warning-600'
-}
-
-const getScoreBackground = (score: number) => {
-  if (score >= 85) return 'from-success-500 to-success-600'
-  if (score >= 70) return 'from-primary-500 to-primary-600'
-  return 'from-warning-500 to-warning-600'
-}
-
-const handleClose = () => {
-  emit('close')
-}
-
-const handleStatusUpdate = (status: 'passed' | 'rejected') => {
-  if (!candidate.value) return
-  
-  jobStore.updateCandidateStatus(candidate.value.id, status)
-  
-  const statusText = status === 'passed' ? '通过' : '拒绝'
-  alert(`已将 ${candidate.value.name} 标记为${statusText}`)
-  
-  handleClose()
-}
-
-const handleInviteInterview = () => {
-  if (!candidate.value) return
-  
-  jobStore.updateCandidateStatus(candidate.value.id, 'interviewed')
-  alert(`已为 ${candidate.value.name} 发送面试邀请`)
-  
-  handleClose()
-}
-</script>
-
-<template>
-  <Teleport to="body">
-    <Transition name="modal" appear>
-      <div 
-        v-if="isOpen && candidate"
-        class="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4"
-        @click.self="handleClose"
-      >
-        <!-- 背景遮罩 -->
-        <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
-        
-        <!-- 模态框内容 -->
-        <div 
-          class="relative w-full max-w-4xl max-h-[90vh] bg-white rounded-t-3xl sm:rounded-3xl shadow-2xl overflow-hidden flex flex-col"
-          v-motion-slide-bottom
-        >
-          <!-- 模态框头部 -->
-          <div class="flex items-center justify-between p-6 border-b border-gray-100 flex-shrink-0">
-            <div class="flex items-center gap-4">
-              <div class="w-12 h-12 rounded-full bg-gradient-to-br from-primary-500 to-secondary-500 flex items-center justify-center text-white font-bold text-lg">
-                {{ candidate.name.charAt(0) }}
-              </div>
-              <div>
-                <h2 class="text-xl font-bold text-gray-900">{{ candidate.name }}</h2>
-                <p class="text-gray-600">{{ candidate.jobTitle }}</p>
-              </div>
-            </div>
-            
-            <button
-              @click="handleClose"
-              class="p-2 rounded-full hover:bg-gray-100 transition-colors"
-            >
-              <X :size="20" class="text-gray-500" />
-            </button>
-          </div>
-
-          <!-- Tab导航 -->
-          <div class="flex border-b border-gray-100 flex-shrink-0">
-            <button
-              @click="activeTab = 'analysis'"
-              :class="[
-                'flex-1 px-6 py-4 text-sm font-medium transition-colors',
-                activeTab === 'analysis' 
-                  ? 'text-primary-600 border-b-2 border-primary-600 bg-primary-50' 
-                  : 'text-gray-500 hover:text-gray-700'
-              ]"
-            >
-              <Star :size="16" class="inline mr-2" />
-              AI分析报告
-            </button>
-            <button
-              @click="activeTab = 'resume'"
-              :class="[
-                'flex-1 px-6 py-4 text-sm font-medium transition-colors',
-                activeTab === 'resume' 
-                  ? 'text-primary-600 border-b-2 border-primary-600 bg-primary-50' 
-                  : 'text-gray-500 hover:text-gray-700'
-              ]"
-            >
-              <FileText :size="16" class="inline mr-2" />
-              简历原文
-            </button>
-          </div>
-
-          <!-- Tab内容 - 可滚动区域 -->
-          <div class="flex-1 overflow-y-auto">
-            <div class="p-6">
-              <!-- AI分析报告 -->
-              <div v-if="activeTab === 'analysis'" class="space-y-6">
-                <!-- 匹配度仪表盘 -->
-                <div class="text-center">
-                  <div class="relative w-32 h-32 mx-auto mb-4">
-                    <svg class="w-32 h-32 transform -rotate-90" viewBox="0 0 36 36">
-                      <path
-                        class="text-gray-200"
-                        stroke="currentColor"
-                        stroke-width="3"
-                        fill="none"
-                        d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
-                      />
-                      <path
-                        :class="getScoreColor(candidate.matchScore)"
-                        stroke="currentColor"
-                        stroke-width="3"
-                        stroke-linecap="round"
-                        fill="none"
-                        :stroke-dasharray="`${candidate.matchScore}, 100`"
-                        d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
-                      />
-                    </svg>
-                    <div class="absolute inset-0 flex items-center justify-center">
-                      <div class="text-center">
-                        <div :class="['text-3xl font-bold', getScoreColor(candidate.matchScore)]">
-                          {{ candidate.matchScore }}
-                        </div>
-                        <div class="text-sm text-gray-500">匹配度</div>
-                      </div>
-                    </div>
-                  </div>
-                </div>
-
-                <!-- AI综合评语 -->
-                <div class="bg-gray-50 rounded-xl p-6">
-                  <h3 class="text-lg font-semibold text-gray-900 mb-3 flex items-center gap-2">
-                    <MessageSquare :size="20" class="text-primary-600" />
-                    AI综合评语
-                  </h3>
-                  <p class="text-gray-700 leading-relaxed">{{ candidate.summary }}</p>
-                </div>
-
-                <!-- 候选人基本信息 -->
-                <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
-                  <div class="bg-gray-50 rounded-xl p-6">
-                    <h3 class="text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
-                      <User :size="20" class="text-primary-600" />
-                      基本信息
-                    </h3>
-                    <div class="space-y-3">
-                      <div>
-                        <span class="text-sm text-gray-500">学历背景:</span>
-                        <p class="font-medium text-gray-900">{{ candidate.education }}</p>
-                      </div>
-                      <div>
-                        <span class="text-sm text-gray-500">工作经验:</span>
-                        <p class="font-medium text-gray-900">{{ candidate.experience }}</p>
-                      </div>
-                      <div>
-                        <span class="text-sm text-gray-500">核心技能:</span>
-                        <div class="flex flex-wrap gap-2 mt-2">
-                          <span 
-                            v-for="skill in candidate.skills"
-                            :key="skill"
-                            class="px-2 py-1 bg-primary-100 text-primary-700 text-xs rounded-md font-medium"
-                          >
-                            {{ skill }}
-                          </span>
-                        </div>
-                      </div>
-                    </div>
-                  </div>
-
-                  <!-- 亮点与关注点 -->
-                  <div class="space-y-4">
-                    <!-- 亮点 -->
-                    <div class="bg-success-50 rounded-xl p-6 border border-success-100">
-                      <h4 class="font-semibold text-success-900 mb-3 flex items-center gap-2">
-                        <CheckCircle :size="18" class="text-success-600" />
-                        候选人亮点
-                      </h4>
-                      <ul class="space-y-2">
-                        <li 
-                          v-for="highlight in candidate.highlights"
-                          :key="highlight"
-                          class="flex items-start gap-2 text-sm text-success-800"
-                        >
-                          <CheckCircle :size="14" class="text-success-600 mt-0.5 flex-shrink-0" />
-                          {{ highlight }}
-                        </li>
-                      </ul>
-                    </div>
-
-                    <!-- 待考察点 -->
-                    <div class="bg-warning-50 rounded-xl p-6 border border-warning-100">
-                      <h4 class="font-semibold text-warning-900 mb-3 flex items-center gap-2">
-                        <AlertTriangle :size="18" class="text-warning-600" />
-                        待考察点
-                      </h4>
-                      <ul class="space-y-2">
-                        <li 
-                          v-for="concern in candidate.concerns"
-                          :key="concern"
-                          class="flex items-start gap-2 text-sm text-warning-800"
-                        >
-                          <AlertTriangle :size="14" class="text-warning-600 mt-0.5 flex-shrink-0" />
-                          {{ concern }}
-                        </li>
-                      </ul>
-                    </div>
-                  </div>
-                </div>
-              </div>
-
-              <!-- 简历原文 -->
-              <div v-if="activeTab === 'resume'" class="space-y-4">
-                <div class="bg-gray-50 rounded-xl p-6">
-                  <h3 class="text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
-                    <FileText :size="20" class="text-primary-600" />
-                    简历原文
-                  </h3>
-                  <div class="prose prose-sm max-w-none">
-                    <pre class="whitespace-pre-wrap text-gray-700 leading-relaxed">{{ candidate.resumeText }}</pre>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-
-          <!-- 模态框底部操作 - 固定在底部 -->
-          <div v-if="candidate.status === 'pending'" class="border-t border-gray-100 bg-gray-50 flex-shrink-0">
-            <!-- 移动端布局 -->
-            <div class="block sm:hidden p-4 space-y-3">
-              <button
-                @click="handleStatusUpdate('rejected')"
-                class="w-full py-4 px-4 bg-error-500 text-white font-medium rounded-xl hover:bg-error-600 transition-colors flex items-center justify-center gap-2 text-base"
-              >
-                <XCircle :size="18" />
-                不合适
-              </button>
-              
-              <button
-                @click="handleStatusUpdate('passed')"
-                class="w-full py-4 px-4 bg-success-500 text-white font-medium rounded-xl hover:bg-success-600 transition-colors flex items-center justify-center gap-2 text-base"
-              >
-                <CheckCircle :size="18" />
-                通过初筛
-              </button>
-              
-              <button
-                v-if="candidate.matchScore >= 75"
-                @click="handleInviteInterview"
-                class="w-full py-4 px-4 bg-primary-500 text-white font-medium rounded-xl hover:bg-primary-600 transition-colors flex items-center justify-center gap-2 text-base"
-              >
-                邀请面试
-                <ArrowRight :size="18" />
-              </button>
-            </div>
-
-            <!-- 桌面端布局 -->
-            <div class="hidden sm:flex gap-3 p-6">
-              <button
-                @click="handleStatusUpdate('rejected')"
-                class="flex-1 py-3 px-4 bg-error-500 text-white font-medium rounded-xl hover:bg-error-600 transition-colors flex items-center justify-center gap-2 min-h-[48px]"
-              >
-                <XCircle :size="16" />
-                不合适
-              </button>
-              
-              <button
-                @click="handleStatusUpdate('passed')"
-                class="flex-1 py-3 px-4 bg-success-500 text-white font-medium rounded-xl hover:bg-success-600 transition-colors flex items-center justify-center gap-2 min-h-[48px]"
-              >
-                <CheckCircle :size="16" />
-                通过初筛
-              </button>
-              
-              <button
-                v-if="candidate.matchScore >= 75"
-                @click="handleInviteInterview"
-                class="flex-1 py-3 px-4 bg-primary-500 text-white font-medium rounded-xl hover:bg-primary-600 transition-colors flex items-center justify-center gap-2 min-h-[48px]"
-              >
-                邀请面试
-                <ArrowRight :size="16" />
-              </button>
-            </div>
-          </div>
-        </div>
-      </div>
-    </Transition>
-  </Teleport>
-</template>
-
-<style scoped>
-/* 模态框动画 */
-.modal-enter-active,
-.modal-leave-active {
-  transition: all 0.3s ease-out;
-}
-
-.modal-enter-from,
-.modal-leave-to {
-  opacity: 0;
-}
-
-.modal-enter-from .relative,
-.modal-leave-to .relative {
-  transform: translateY(100px) scale(0.95);
-}
-
-.prose pre {
-  background: transparent;
-  padding: 0;
-  margin: 0;
-  border: none;
-  font-family: inherit;
-}
-
-/* 确保模态框内容区域正确滚动 */
-.modal-content {
-  display: flex;
-  flex-direction: column;
-  max-height: 90vh;
-}
-
-/* 移动端优化 */
-@media (max-width: 640px) {
-  /* 确保移动端按钮有足够的触摸区域 */
-  .mobile-button {
-    min-height: 48px;
-    padding: 12px 16px;
-  }
-  
-  /* 移动端模态框高度优化 */
-  .relative {
-    max-height: 95vh;
-  }
-}
-
-/* 桌面端按钮最小高度 */
-@media (min-width: 640px) {
-  .desktop-button {
-    min-height: 48px;
-  }
-}
-</style>

+ 0 - 41
src/components/HelloWorld.vue

@@ -1,41 +0,0 @@
-<script setup lang="ts">
-import { ref } from 'vue'
-
-defineProps<{ msg: string }>()
-
-const count = ref(0)
-</script>
-
-<template>
-  <h1>{{ msg }}</h1>
-
-  <div class="card">
-    <button type="button" @click="count++">count is {{ count }}</button>
-    <p>
-      Edit
-      <code>components/HelloWorld.vue</code> to test HMR
-    </p>
-  </div>
-
-  <p>
-    Check out
-    <a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
-      >create-vue</a
-    >, the official Vue + Vite starter
-  </p>
-  <p>
-    Learn more about IDE Support for Vue in the
-    <a
-      href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
-      target="_blank"
-      >Vue Docs Scaling up Guide</a
-    >.
-  </p>
-  <p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
-</template>
-
-<style scoped>
-.read-the-docs {
-  color: #888;
-}
-</style>

+ 0 - 284
src/components/JobCard.vue

@@ -1,284 +0,0 @@
-<script setup lang="ts">
-import { computed, ref, onMounted, onUnmounted } from 'vue'
-import { useJobStore, type Job } from '../stores/jobStore'
-import { Briefcase, MapPin, Clock, Users, Zap, MoreHorizontal, Eye, Edit, Pause, Play, Trash2 } from 'lucide-vue-next'
-import JobDetailModal from './JobDetailModal.vue'
-import JobEditModal from './JobEditModal.vue'
-
-interface Props {
-  job: Job
-}
-
-const props = defineProps<Props>()
-const jobStore = useJobStore()
-
-const isScreening = ref(false)
-const showDetailModal = ref(false)
-const showEditModal = ref(false)
-const showDropdown = ref(false)
-
-const statusConfig = computed(() => {
-  switch (props.job.status) {
-    case 'active':
-      return { label: '招聘中', class: 'bg-success-100 text-success-700' }
-    case 'paused':
-      return { label: '已暂停', class: 'bg-warning-100 text-warning-700' }
-    case 'draft':
-      return { label: '草稿', class: 'bg-warning-100 text-warning-700' }
-    default:
-      return { label: '未知', class: 'bg-gray-100 text-gray-500' }
-  }
-})
-
-const handleScreening = async () => {
-  if (props.job.pendingResumes === 0) return
-  
-  isScreening.value = true
-  
-  try {
-    await jobStore.triggerScreening(props.job.id)
-    
-    // 成功提示
-    setTimeout(() => {
-      alert(`${props.job.title} 的AI智能筛选已完成!`)
-    }, 100)
-  } catch (error) {
-    alert('筛选过程中出现错误,请稍后重试')
-  } finally {
-    isScreening.value = false
-  }
-}
-
-const handleViewDetails = () => {
-  showDetailModal.value = true
-}
-
-const handleEditJob = () => {
-  showEditModal.value = true
-}
-
-const handlePauseJob = () => {
-  if (props.job.status === 'active') {
-    jobStore.pauseJob(props.job.id)
-  } else if (props.job.status === 'paused') {
-    jobStore.resumeJob(props.job.id)
-  }
-}
-
-const handleEditSave = (updatedJob: Job) => {
-  showEditModal.value = false
-}
-
-const toggleDropdown = () => {
-  showDropdown.value = !showDropdown.value
-}
-
-const handleDelete = () => {
-  if (confirm('确定要删除这个岗位吗?此操作不可撤销。')) {
-    jobStore.deleteJob(props.job.id)
-  }
-  showDropdown.value = false
-}
-
-// 点击外部关闭下拉菜单
-const handleClickOutside = (event: MouseEvent) => {
-  const target = event.target as HTMLElement
-  if (!target.closest('.relative')) {
-    showDropdown.value = false
-  }
-}
-
-onMounted(() => {
-  document.addEventListener('click', handleClickOutside)
-})
-
-onUnmounted(() => {
-  document.removeEventListener('click', handleClickOutside)
-})
-</script>
-
-<template>
-  <div 
-    class="glass-card p-6 hover:shadow-xl transition-all duration-300 group"
-    v-motion-fade-visible-once
-  >
-    <!-- 卡片头部 -->
-    <div class="flex items-start justify-between mb-4">
-      <div class="flex-1 min-w-0">
-        <h3 class="text-lg font-semibold text-gray-900 mb-1 group-hover:text-primary-600 transition-colors">
-          {{ job.title }}
-        </h3>
-        <div class="flex items-center gap-4 text-sm text-gray-500">
-          <div class="flex items-center gap-1">
-            <Briefcase :size="14" />
-            {{ job.department }}
-          </div>
-          <div class="flex items-center gap-1">
-            <MapPin :size="14" />
-            {{ job.location }}
-          </div>
-        </div>
-      </div>
-      
-      <div class="flex items-center gap-2">
-        <span :class="['px-3 py-1 rounded-full text-xs font-medium', statusConfig.class]">
-          {{ statusConfig.label }}
-        </span>
-        <div class="relative">
-          <button 
-            @click="toggleDropdown"
-            class="p-2 rounded-lg hover:bg-gray-100 transition-colors"
-          >
-            <MoreHorizontal :size="16" class="text-gray-400" />
-          </button>
-          
-          <!-- 下拉菜单 -->
-          <div 
-            v-if="showDropdown"
-            class="absolute right-0 top-full mt-1 w-32 bg-white rounded-lg shadow-lg border border-gray-200 z-50"
-          >
-            <button 
-              @click="handleDelete"
-              class="w-full px-3 py-2 text-left text-sm text-red-600 hover:bg-red-50 rounded-lg flex items-center gap-2 transition-colors"
-            >
-              <Trash2 :size="14" />
-              删除岗位
-            </button>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <!-- 统计数据 -->
-    <div class="grid grid-cols-2 gap-4 mb-6">
-      <div class="text-center p-4 bg-gradient-to-br from-warning-50 to-orange-50 rounded-xl border border-warning-100">
-        <div class="text-2xl font-bold text-warning-600 mb-1 animate-number-roll">
-          {{ job.pendingResumes }}
-        </div>
-        <div class="text-xs text-warning-700 font-medium">待处理简历</div>
-      </div>
-      
-      <div class="text-center p-4 bg-gradient-to-br from-success-50 to-green-50 rounded-xl border border-success-100">
-        <div class="text-2xl font-bold text-success-600 mb-1">
-          {{ job.passedResumes }}
-        </div>
-        <div class="text-xs text-success-700 font-medium">已通过初筛</div>
-      </div>
-    </div>
-
-    <!-- 操作按钮区域 -->
-    <div class="space-y-3">
-      <!-- 一键筛选按钮 -->
-      <button
-        @click="handleScreening"
-        :disabled="job.pendingResumes === 0 || isScreening"
-        :class="[
-          'w-full py-3 px-4 rounded-xl font-medium text-white transition-all duration-300 flex items-center justify-center gap-2',
-          job.pendingResumes > 0 && !isScreening
-            ? 'bg-gradient-to-r from-primary-500 to-secondary-500 hover:shadow-lg active:scale-95 shimmer'
-            : 'bg-gray-300 cursor-not-allowed'
-        ]"
-      >
-        <div v-if="isScreening" class="flex items-center gap-2">
-          <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
-          <span>AI正在筛选中...</span>
-        </div>
-        <div v-else class="flex items-center gap-2">
-          <Zap :size="16" />
-          <span>一键智能筛选</span>
-        </div>
-      </button>
-
-      <!-- 次要操作按钮 -->
-      <div class="flex gap-2">
-        <button 
-          @click="handleViewDetails"
-          class="flex-1 py-2.5 px-4 text-sm font-medium text-gray-600 hover:text-gray-800 transition-colors flex items-center justify-center gap-1"
-        >
-          <Eye :size="14" />
-          查看详情
-        </button>
-        <button 
-          @click="handleEditJob"
-          class="flex-1 py-2.5 px-4 text-sm font-medium text-gray-600 hover:text-gray-800 transition-colors flex items-center justify-center gap-1"
-        >
-          <Edit :size="14" />
-          编辑岗位
-        </button>
-        <button 
-          v-if="job.status === 'active' || job.status === 'paused'"
-          @click="handlePauseJob"
-          class="flex-1 py-2.5 px-4 text-sm font-medium text-gray-600 hover:text-gray-800 transition-colors flex items-center justify-center gap-1"
-        >
-          <Pause v-if="job.status === 'active'" :size="14" />
-          <Play v-else :size="14" />
-          {{ job.status === 'active' ? '暂停招聘' : '恢复招聘' }}
-        </button>
-      </div>
-    </div>
-
-    <!-- 更新时间 -->
-    <div class="flex items-center gap-1 text-xs text-gray-400 mt-4 pt-4 border-t border-gray-100">
-      <Clock :size="12" />
-      最后更新: {{ new Date(job.updatedAt).toLocaleDateString() }}
-    </div>
-  </div>
-
-  <!-- 模态框 -->
-  <JobDetailModal 
-    :is-open="showDetailModal"
-    :job="job"
-    @close="showDetailModal = false"
-  />
-  
-  <JobEditModal 
-    :is-open="showEditModal"
-    :job="job"
-    @close="showEditModal = false"
-    @save="handleEditSave"
-  />
-</template>
-
-<style scoped>
-/* 数字滚动动画 */
-@keyframes number-roll {
-  0% {
-    transform: translateY(-10px);
-    opacity: 0;
-  }
-  100% {
-    transform: translateY(0);
-    opacity: 1;
-  }
-}
-
-.animate-number-roll {
-  animation: number-roll 0.6s ease-out;
-}
-
-/* 按钮闪光效果 */
-.shimmer {
-  position: relative;
-  overflow: hidden;
-}
-
-.shimmer::before {
-  content: '';
-  position: absolute;
-  top: 0;
-  left: -100%;
-  width: 100%;
-  height: 100%;
-  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
-  animation: shimmer 3s infinite;
-}
-
-@keyframes shimmer {
-  0% {
-    left: -100%;
-  }
-  100% {
-    left: 100%;
-  }
-}
-</style>

+ 0 - 425
src/components/JobCreatorModal.vue

@@ -1,425 +0,0 @@
-<script setup lang="ts">
-import { ref, computed } from 'vue'
-import { useJobStore } from '../stores/jobStore'
-import { X, Plus, Trash2, Save } from 'lucide-vue-next'
-
-const jobStore = useJobStore()
-
-const formData = ref({
-  title: '',
-  department: '',
-  location: '',
-  description: '',
-  aiCriteria: {
-    education: { condition: '>=', value: '本科', weight: 20 },
-    experience: { condition: '>=', value: '3年', weight: 30 },
-    skills: { condition: 'includes', value: '', weight: 35 },
-    language: { condition: '>=', value: '英语四级', weight: 15 }
-  }
-})
-
-const isSubmitting = ref(false)
-
-const departments = [
-  '技术部', '产品部', '设计部', '市场部', '运营部', '销售部', '人事部', '财务部'
-]
-
-const locations = [
-  '北京', '上海', '广州', '深圳', '杭州', '成都', '武汉', '西安', '南京', '苏州'
-]
-
-const educationOptions = [
-  '不限', '高中', '专科', '本科', '硕士', '博士'
-]
-
-const experienceOptions = [
-  '不限', '1年', '2年', '3年', '5年', '8年', '10年以上'
-]
-
-const languageOptions = [
-  '无要求', '英语四级', '英语六级', '英语专业八级', '托福', '雅思'
-]
-
-const conditionOptions = [
-  { value: '>=', label: '大于等于' },
-  { value: '=', label: '等于' },
-  { value: 'includes', label: '包含' }
-]
-
-const isFormValid = computed(() => {
-  return formData.value.title.trim() && 
-         formData.value.department && 
-         formData.value.location && 
-         formData.value.description.trim()
-})
-
-const totalWeight = computed(() => {
-  return Object.values(formData.value.aiCriteria).reduce((sum, criteria) => sum + criteria.weight, 0)
-})
-
-const handleClose = () => {
-  if (!isSubmitting.value) {
-    resetForm()
-    jobStore.closeModal()
-  }
-}
-
-const resetForm = () => {
-  formData.value = {
-    title: '',
-    department: '',
-    location: '',
-    description: '',
-    aiCriteria: {
-      education: { condition: '>=', value: '本科', weight: 20 },
-      experience: { condition: '>=', value: '3年', weight: 30 },
-      skills: { condition: 'includes', value: '', weight: 35 },
-      language: { condition: '>=', value: '英语四级', weight: 15 }
-    }
-  }
-}
-
-const handleSubmit = async () => {
-  if (!isFormValid.value || totalWeight.value !== 100) return
-  
-  isSubmitting.value = true
-  
-  try {
-    // 模拟API调用
-    await new Promise(resolve => setTimeout(resolve, 1500))
-    
-    jobStore.addJob({
-      ...formData.value,
-      status: 'active',
-      pendingResumes: 0,
-      passedResumes: 0
-    })
-    
-    alert('岗位创建成功!')
-    handleClose()
-  } catch (error) {
-    alert('创建失败,请稍后重试')
-  } finally {
-    isSubmitting.value = false
-  }
-}
-
-const adjustWeight = (key: keyof typeof formData.value.aiCriteria, delta: number) => {
-  const currentWeight = formData.value.aiCriteria[key].weight
-  const newWeight = Math.max(0, Math.min(100, currentWeight + delta))
-  formData.value.aiCriteria[key].weight = newWeight
-}
-</script>
-
-<template>
-  <Teleport to="body">
-    <Transition name="modal" appear>
-      <div 
-        v-if="jobStore.isModalOpen"
-        class="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4"
-        @click.self="handleClose"
-      >
-        <!-- 背景遮罩 -->
-        <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
-        
-        <!-- 模态框内容 -->
-        <div 
-          class="relative w-full max-w-2xl max-h-[90vh] bg-white rounded-t-3xl sm:rounded-3xl shadow-2xl overflow-hidden flex flex-col"
-          v-motion-slide-bottom
-        >
-          <!-- 模态框头部 -->
-          <div class="flex items-center justify-between p-6 border-b border-gray-100">
-            <h2 class="text-2xl font-bold text-gray-900">创建新的招聘岗位</h2>
-            <button
-              @click="handleClose"
-              class="p-2 rounded-full hover:bg-gray-100 transition-colors"
-              :disabled="isSubmitting"
-            >
-              <X :size="20" class="text-gray-500" />
-            </button>
-          </div>
-
-          <!-- 模态框内容 -->
-          <div class="flex-1 p-6 overflow-y-auto" style="max-height: calc(90vh - 200px);">
-            <form @submit.prevent="handleSubmit" class="space-y-8">
-              <!-- 基础信息 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">基础信息</h3>
-                <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
-                  <div>
-                    <label class="block text-sm font-medium text-gray-700 mb-2">
-                      岗位名称 *
-                    </label>
-                    <input
-                      v-model="formData.title"
-                      type="text"
-                      placeholder="请输入岗位名称"
-                      class="input-field"
-                      required
-                    >
-                  </div>
-                  
-                  <div>
-                    <label class="block text-sm font-medium text-gray-700 mb-2">
-                      所属部门 *
-                    </label>
-                    <select v-model="formData.department" class="input-field" required>
-                      <option value="">请选择部门</option>
-                      <option v-for="dept in departments" :key="dept" :value="dept">
-                        {{ dept }}
-                      </option>
-                    </select>
-                  </div>
-                  
-                  <div class="sm:col-span-2">
-                    <label class="block text-sm font-medium text-gray-700 mb-2">
-                      工作地点 *
-                    </label>
-                    <select v-model="formData.location" class="input-field" required>
-                      <option value="">请选择城市</option>
-                      <option v-for="city in locations" :key="city" :value="city">
-                        {{ city }}
-                      </option>
-                    </select>
-                  </div>
-                </div>
-              </section>
-
-              <!-- 岗位描述 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">岗位描述 (JD)</h3>
-                <textarea
-                  v-model="formData.description"
-                  placeholder="请详细描述岗位职责、任职要求等信息..."
-                  class="input-field min-h-[120px] resize-none"
-                  required
-                ></textarea>
-              </section>
-
-              <!-- AI筛选硬性指标 -->
-              <section>
-                <div class="flex items-center justify-between mb-4">
-                  <h3 class="text-lg font-semibold text-gray-900">AI筛选评分标准</h3>
-                  <div class="text-sm text-gray-500">
-                    权重总计: 
-                    <span :class="totalWeight === 100 ? 'text-success-600' : 'text-error-600'">
-                      {{ totalWeight }}%
-                    </span>
-                  </div>
-                </div>
-                
-                <div class="space-y-6">
-                  <!-- 学历要求 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">学历要求</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('education', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.education.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('education', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.education.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <select v-model="formData.aiCriteria.education.value" class="input-field">
-                        <option v-for="edu in educationOptions" :key="edu" :value="edu">
-                          {{ edu }}
-                        </option>
-                      </select>
-                    </div>
-                  </div>
-
-                  <!-- 工作经验 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">工作经验</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('experience', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.experience.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('experience', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.experience.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <select v-model="formData.aiCriteria.experience.value" class="input-field">
-                        <option v-for="exp in experienceOptions" :key="exp" :value="exp">
-                          {{ exp }}
-                        </option>
-                      </select>
-                    </div>
-                  </div>
-
-                  <!-- 技术能力 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">技术能力</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('skills', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.skills.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('skills', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.skills.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <input
-                        v-model="formData.aiCriteria.skills.value"
-                        type="text"
-                        placeholder="例:Vue.js,TypeScript,Node.js"
-                        class="input-field"
-                      >
-                    </div>
-                  </div>
-
-                  <!-- 语言要求 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">语言要求</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('language', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.language.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('language', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.language.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <select v-model="formData.aiCriteria.language.value" class="input-field">
-                        <option v-for="lang in languageOptions" :key="lang" :value="lang">
-                          {{ lang }}
-                        </option>
-                      </select>
-                    </div>
-                  </div>
-                </div>
-
-                <div v-if="totalWeight !== 100" class="mt-4 p-3 bg-warning-50 border border-warning-200 rounded-lg">
-                  <p class="text-sm text-warning-700">
-                    权重总计必须为100%,当前为{{ totalWeight }}%
-                  </p>
-                </div>
-              </section>
-            </form>
-          </div>
-
-          <!-- 模态框底部 -->
-          <div class="flex justify-center gap-4 p-6 border-t border-gray-100 bg-gray-50">
-            <button
-              @click="handleClose"
-              class="btn-secondary px-8"
-              :disabled="isSubmitting"
-            >
-              取消
-            </button>
-            
-            <button
-              @click="handleSubmit"
-              :disabled="!isFormValid || totalWeight !== 100 || isSubmitting"
-              :class="[
-                'btn-primary flex items-center justify-center gap-2 px-8',
-                (!isFormValid || totalWeight !== 100 || isSubmitting) && 'opacity-50 cursor-not-allowed'
-              ]"
-            >
-              <div v-if="isSubmitting" class="flex items-center gap-2">
-                <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
-                创建中...
-              </div>
-              <div v-else class="flex items-center gap-2">
-                <Save :size="16" />
-                创建并发布
-              </div>
-            </button>
-          </div>
-        </div>
-      </div>
-    </Transition>
-  </Teleport>
-</template>
-
-<style scoped>
-/* 模态框动画 */
-.modal-enter-active,
-.modal-leave-active {
-  transition: all 0.3s ease-out;
-}
-
-.modal-enter-from,
-.modal-leave-to {
-  opacity: 0;
-}
-
-.modal-enter-from .relative,
-.modal-leave-to .relative {
-  transform: translateY(100px) scale(0.95);
-}
-</style>

+ 0 - 236
src/components/JobDetailModal.vue

@@ -1,236 +0,0 @@
-<script setup lang="ts">
-import { computed } from 'vue'
-import { useJobStore, type Job } from '../stores/jobStore'
-import { X, Briefcase, MapPin, Users, Calendar, Star } from 'lucide-vue-next'
-
-interface Props {
-  isOpen: boolean
-  job: Job | null
-}
-
-interface Emits {
-  (e: 'close'): void
-}
-
-const props = defineProps<Props>()
-const emit = defineEmits<Emits>()
-
-const jobStore = useJobStore()
-
-const handleClose = () => {
-  emit('close')
-}
-
-const getStatusConfig = (status: Job['status']) => {
-  switch (status) {
-    case 'active':
-      return { label: '招聘中', class: 'bg-success-100 text-success-700' }
-    case 'paused':
-      return { label: '已暂停', class: 'bg-gray-100 text-gray-700' }
-    case 'draft':
-      return { label: '草稿', class: 'bg-warning-100 text-warning-700' }
-    default:
-      return { label: '未知', class: 'bg-gray-100 text-gray-500' }
-  }
-}
-
-const statusConfig = computed(() => 
-  props.job ? getStatusConfig(props.job.status) : { label: '', class: '' }
-)
-</script>
-
-<template>
-  <Teleport to="body">
-    <Transition name="modal" appear>
-      <div 
-        v-if="isOpen && job"
-        class="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4"
-        @click.self="handleClose"
-      >
-        <!-- 背景遮罩 -->
-        <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
-        
-        <!-- 模态框内容 -->
-        <div 
-          class="relative w-full max-w-2xl max-h-[90vh] bg-white rounded-t-3xl sm:rounded-3xl shadow-2xl overflow-hidden"
-          v-motion-slide-bottom
-        >
-          <!-- 模态框头部 -->
-          <div class="flex items-center justify-between p-6 border-b border-gray-100">
-            <div class="flex items-center gap-3">
-              <h2 class="text-2xl font-bold text-gray-900">岗位详情</h2>
-              <span :class="['px-3 py-1 rounded-full text-xs font-medium', statusConfig.class]">
-                {{ statusConfig.label }}
-              </span>
-            </div>
-            <button
-              @click="handleClose"
-              class="p-2 rounded-full hover:bg-gray-100 transition-colors"
-            >
-              <X :size="20" class="text-gray-500" />
-            </button>
-          </div>
-
-          <!-- 模态框内容 -->
-          <div class="p-6 overflow-y-auto max-h-[calc(90vh-140px)]">
-            <div class="space-y-8">
-              <!-- 基础信息 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">基础信息</h3>
-                <div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
-                  <div class="bg-gray-50 rounded-xl p-4">
-                    <div class="flex items-center gap-2 mb-2">
-                      <Briefcase :size="16" class="text-primary-600" />
-                      <span class="text-sm font-medium text-gray-700">岗位名称</span>
-                    </div>
-                    <p class="text-gray-900 font-semibold">{{ job.title }}</p>
-                  </div>
-                  
-                  <div class="bg-gray-50 rounded-xl p-4">
-                    <div class="flex items-center gap-2 mb-2">
-                      <Users :size="16" class="text-primary-600" />
-                      <span class="text-sm font-medium text-gray-700">所属部门</span>
-                    </div>
-                    <p class="text-gray-900 font-semibold">{{ job.department }}</p>
-                  </div>
-                  
-                  <div class="bg-gray-50 rounded-xl p-4">
-                    <div class="flex items-center gap-2 mb-2">
-                      <MapPin :size="16" class="text-primary-600" />
-                      <span class="text-sm font-medium text-gray-700">工作地点</span>
-                    </div>
-                    <p class="text-gray-900 font-semibold">{{ job.location }}</p>
-                  </div>
-                  
-                  <div class="bg-gray-50 rounded-xl p-4">
-                    <div class="flex items-center gap-2 mb-2">
-                      <Calendar :size="16" class="text-primary-600" />
-                      <span class="text-sm font-medium text-gray-700">创建时间</span>
-                    </div>
-                    <p class="text-gray-900 font-semibold">{{ new Date(job.createdAt).toLocaleDateString() }}</p>
-                  </div>
-                </div>
-              </section>
-
-              <!-- 岗位描述 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">岗位描述 (JD)</h3>
-                <div class="bg-gray-50 rounded-xl p-6">
-                  <pre class="whitespace-pre-wrap text-gray-700 leading-relaxed font-sans">{{ job.description }}</pre>
-                </div>
-              </section>
-
-              <!-- 招聘统计 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">招聘统计</h3>
-                <div class="grid grid-cols-2 gap-4">
-                  <div class="text-center p-4 bg-gradient-to-br from-warning-50 to-orange-50 rounded-xl border border-warning-100">
-                    <div class="text-2xl font-bold text-warning-600 mb-1">
-                      {{ job.pendingResumes }}
-                    </div>
-                    <div class="text-xs text-warning-700 font-medium">待处理简历</div>
-                  </div>
-                  
-                  <div class="text-center p-4 bg-gradient-to-br from-success-50 to-green-50 rounded-xl border border-success-100">
-                    <div class="text-2xl font-bold text-success-600 mb-1">
-                      {{ job.passedResumes }}
-                    </div>
-                    <div class="text-xs text-success-700 font-medium">已通过初筛</div>
-                  </div>
-                </div>
-              </section>
-
-              <!-- AI筛选评分标准 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4 flex items-center gap-2">
-                  <Star :size="20" class="text-primary-600" />
-                  AI筛选评分标准
-                </h3>
-                
-                <div class="space-y-4">
-                  <!-- 学历要求 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-2">
-                      <h4 class="font-medium text-gray-900">学历要求</h4>
-                      <span class="text-sm font-medium text-primary-600">
-                        {{ job.aiCriteria.education.weight }}%
-                      </span>
-                    </div>
-                    <p class="text-gray-700">
-                      {{ job.aiCriteria.education.condition === '>=' ? '大于等于' : 
-                         job.aiCriteria.education.condition === '=' ? '等于' : '包含' }} 
-                      {{ job.aiCriteria.education.value }}
-                    </p>
-                  </div>
-
-                  <!-- 工作经验 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-2">
-                      <h4 class="font-medium text-gray-900">工作经验</h4>
-                      <span class="text-sm font-medium text-primary-600">
-                        {{ job.aiCriteria.experience.weight }}%
-                      </span>
-                    </div>
-                    <p class="text-gray-700">
-                      {{ job.aiCriteria.experience.condition === '>=' ? '大于等于' : 
-                         job.aiCriteria.experience.condition === '=' ? '等于' : '包含' }} 
-                      {{ job.aiCriteria.experience.value }}
-                    </p>
-                  </div>
-
-                  <!-- 技术能力 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-2">
-                      <h4 class="font-medium text-gray-900">技术能力</h4>
-                      <span class="text-sm font-medium text-primary-600">
-                        {{ job.aiCriteria.skills.weight }}%
-                      </span>
-                    </div>
-                    <p class="text-gray-700">
-                      {{ job.aiCriteria.skills.condition === '>=' ? '大于等于' : 
-                         job.aiCriteria.skills.condition === '=' ? '等于' : '包含' }} 
-                      {{ job.aiCriteria.skills.value || '无特殊要求' }}
-                    </p>
-                  </div>
-
-                  <!-- 语言要求 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-2">
-                      <h4 class="font-medium text-gray-900">语言要求</h4>
-                      <span class="text-sm font-medium text-primary-600">
-                        {{ job.aiCriteria.language.weight }}%
-                      </span>
-                    </div>
-                    <p class="text-gray-700">
-                      {{ job.aiCriteria.language.condition === '>=' ? '大于等于' : 
-                         job.aiCriteria.language.condition === '=' ? '等于' : '包含' }} 
-                      {{ job.aiCriteria.language.value }}
-                    </p>
-                  </div>
-                </div>
-              </section>
-            </div>
-          </div>
-        </div>
-      </div>
-    </Transition>
-  </Teleport>
-</template>
-
-<style scoped>
-/* 模态框动画 */
-.modal-enter-active,
-.modal-leave-active {
-  transition: all 0.3s ease-out;
-}
-
-.modal-enter-from,
-.modal-leave-to {
-  opacity: 0;
-}
-
-.modal-enter-from .relative,
-.modal-leave-to .relative {
-  transform: translateY(100px) scale(0.95);
-}
-</style>

+ 0 - 431
src/components/JobEditModal.vue

@@ -1,431 +0,0 @@
-<script setup lang="ts">
-import { ref, computed, watch } from 'vue'
-import { useJobStore, type Job } from '../stores/jobStore'
-import { X, Save } from 'lucide-vue-next'
-
-interface Props {
-  isOpen: boolean
-  job: Job | null
-}
-
-interface Emits {
-  (e: 'close'): void
-  (e: 'save', job: Job): void
-}
-
-const props = defineProps<Props>()
-const emit = defineEmits<Emits>()
-
-const jobStore = useJobStore()
-
-const formData = ref({
-  title: '',
-  department: '',
-  location: '',
-  description: '',
-  aiCriteria: {
-    education: { condition: '>=', value: '本科', weight: 20 },
-    experience: { condition: '>=', value: '3年', weight: 30 },
-    skills: { condition: 'includes', value: '', weight: 35 },
-    language: { condition: '>=', value: '英语四级', weight: 15 }
-  }
-})
-
-const isSubmitting = ref(false)
-
-const departments = [
-  '技术部', '产品部', '设计部', '市场部', '运营部', '销售部', '人事部', '财务部'
-]
-
-const locations = [
-  '北京', '上海', '广州', '深圳', '杭州', '成都', '武汉', '西安', '南京', '苏州'
-]
-
-const educationOptions = [
-  '不限', '高中', '专科', '本科', '硕士', '博士'
-]
-
-const experienceOptions = [
-  '不限', '1年', '2年', '3年', '5年', '8年', '10年以上'
-]
-
-const languageOptions = [
-  '无要求', '英语四级', '英语六级', '英语专业八级', '托福', '雅思'
-]
-
-const conditionOptions = [
-  { value: '>=', label: '大于等于' },
-  { value: '=', label: '等于' },
-  { value: 'includes', label: '包含' }
-]
-
-const isFormValid = computed(() => {
-  return formData.value.title.trim() && 
-         formData.value.department && 
-         formData.value.location && 
-         formData.value.description.trim()
-})
-
-const totalWeight = computed(() => {
-  return Object.values(formData.value.aiCriteria).reduce((sum, criteria) => sum + criteria.weight, 0)
-})
-
-// 监听job变化,初始化表单数据
-watch(() => props.job, (newJob) => {
-  if (newJob) {
-    formData.value = {
-      title: newJob.title,
-      department: newJob.department,
-      location: newJob.location,
-      description: newJob.description,
-      aiCriteria: {
-        education: { ...newJob.aiCriteria.education },
-        experience: { ...newJob.aiCriteria.experience },
-        skills: { ...newJob.aiCriteria.skills },
-        language: { ...newJob.aiCriteria.language }
-      }
-    }
-  }
-}, { immediate: true })
-
-const handleClose = () => {
-  if (!isSubmitting.value) {
-    emit('close')
-  }
-}
-
-const handleSubmit = async () => {
-  if (!isFormValid.value || totalWeight.value !== 100 || !props.job) return
-  
-  isSubmitting.value = true
-  
-  try {
-    // 模拟API调用
-    await new Promise(resolve => setTimeout(resolve, 1000))
-    
-    // 更新岗位信息
-    jobStore.updateJob(props.job.id, {
-      ...formData.value
-    })
-    
-    emit('save', { ...props.job, ...formData.value })
-    alert('岗位信息更新成功!')
-    handleClose()
-  } catch (error) {
-    alert('更新失败,请稍后重试')
-  } finally {
-    isSubmitting.value = false
-  }
-}
-
-const adjustWeight = (key: keyof typeof formData.value.aiCriteria, delta: number) => {
-  const currentWeight = formData.value.aiCriteria[key].weight
-  const newWeight = Math.max(0, Math.min(100, currentWeight + delta))
-  formData.value.aiCriteria[key].weight = newWeight
-}
-</script>
-
-<template>
-  <Teleport to="body">
-    <Transition name="modal" appear>
-      <div 
-        v-if="isOpen && job"
-        class="fixed inset-0 z-50 flex items-end sm:items-center justify-center p-4"
-        @click.self="handleClose"
-      >
-        <!-- 背景遮罩 -->
-        <div class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
-        
-        <!-- 模态框内容 -->
-        <div 
-          class="relative w-full max-w-2xl max-h-[90vh] bg-white rounded-t-3xl sm:rounded-3xl shadow-2xl overflow-hidden flex flex-col"
-          v-motion-slide-bottom
-        >
-          <!-- 模态框头部 -->
-          <div class="flex items-center justify-between p-6 border-b border-gray-100">
-            <h2 class="text-2xl font-bold text-gray-900">编辑岗位信息</h2>
-            <button
-              @click="handleClose"
-              class="p-2 rounded-full hover:bg-gray-100 transition-colors"
-              :disabled="isSubmitting"
-            >
-              <X :size="20" class="text-gray-500" />
-            </button>
-          </div>
-
-          <!-- 模态框内容 -->
-          <div class="flex-1 p-6 overflow-y-auto" style="max-height: calc(90vh - 200px);">
-            <form @submit.prevent="handleSubmit" class="space-y-8">
-              <!-- 基础信息 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">基础信息</h3>
-                <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
-                  <div>
-                    <label class="block text-sm font-medium text-gray-700 mb-2">
-                      岗位名称 *
-                    </label>
-                    <input
-                      v-model="formData.title"
-                      type="text"
-                      placeholder="请输入岗位名称"
-                      class="input-field"
-                      required
-                    >
-                  </div>
-                  
-                  <div>
-                    <label class="block text-sm font-medium text-gray-700 mb-2">
-                      所属部门 *
-                    </label>
-                    <select v-model="formData.department" class="input-field" required>
-                      <option value="">请选择部门</option>
-                      <option v-for="dept in departments" :key="dept" :value="dept">
-                        {{ dept }}
-                      </option>
-                    </select>
-                  </div>
-                  
-                  <div class="sm:col-span-2">
-                    <label class="block text-sm font-medium text-gray-700 mb-2">
-                      工作地点 *
-                    </label>
-                    <select v-model="formData.location" class="input-field" required>
-                      <option value="">请选择城市</option>
-                      <option v-for="city in locations" :key="city" :value="city">
-                        {{ city }}
-                      </option>
-                    </select>
-                  </div>
-                </div>
-              </section>
-
-              <!-- 岗位描述 -->
-              <section>
-                <h3 class="text-lg font-semibold text-gray-900 mb-4">岗位描述 (JD)</h3>
-                <textarea
-                  v-model="formData.description"
-                  placeholder="请详细描述岗位职责、任职要求等信息..."
-                  class="input-field min-h-[120px] resize-none"
-                  required
-                ></textarea>
-              </section>
-
-              <!-- AI筛选硬性指标 -->
-              <section>
-                <div class="flex items-center justify-between mb-4">
-                  <h3 class="text-lg font-semibold text-gray-900">AI筛选评分标准</h3>
-                  <div class="text-sm text-gray-500">
-                    权重总计: 
-                    <span :class="totalWeight === 100 ? 'text-success-600' : 'text-error-600'">
-                      {{ totalWeight }}%
-                    </span>
-                  </div>
-                </div>
-                
-                <div class="space-y-6">
-                  <!-- 学历要求 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">学历要求</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('education', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.education.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('education', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.education.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <select v-model="formData.aiCriteria.education.value" class="input-field">
-                        <option v-for="edu in educationOptions" :key="edu" :value="edu">
-                          {{ edu }}
-                        </option>
-                      </select>
-                    </div>
-                  </div>
-
-                  <!-- 工作经验 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">工作经验</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('experience', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.experience.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('experience', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.experience.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <select v-model="formData.aiCriteria.experience.value" class="input-field">
-                        <option v-for="exp in experienceOptions" :key="exp" :value="exp">
-                          {{ exp }}
-                        </option>
-                      </select>
-                    </div>
-                  </div>
-
-                  <!-- 技术能力 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">技术能力</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('skills', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.skills.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('skills', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.skills.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <input
-                        v-model="formData.aiCriteria.skills.value"
-                        type="text"
-                        placeholder="例:Vue.js,TypeScript,Node.js"
-                        class="input-field"
-                      >
-                    </div>
-                  </div>
-
-                  <!-- 语言要求 -->
-                  <div class="p-4 border border-gray-200 rounded-xl">
-                    <div class="flex items-center justify-between mb-3">
-                      <h4 class="font-medium text-gray-900">语言要求</h4>
-                      <div class="flex items-center gap-2">
-                        <button
-                          type="button"
-                          @click="adjustWeight('language', -5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          -
-                        </button>
-                        <span class="text-sm font-medium w-8 text-center">
-                          {{ formData.aiCriteria.language.weight }}%
-                        </span>
-                        <button
-                          type="button"
-                          @click="adjustWeight('language', 5)"
-                          class="w-6 h-6 rounded-full bg-gray-100 hover:bg-gray-200 flex items-center justify-center text-xs"
-                        >
-                          +
-                        </button>
-                      </div>
-                    </div>
-                    <div class="grid grid-cols-2 gap-3">
-                      <select v-model="formData.aiCriteria.language.condition" class="input-field">
-                        <option v-for="opt in conditionOptions" :key="opt.value" :value="opt.value">
-                          {{ opt.label }}
-                        </option>
-                      </select>
-                      <select v-model="formData.aiCriteria.language.value" class="input-field">
-                        <option v-for="lang in languageOptions" :key="lang" :value="lang">
-                          {{ lang }}
-                        </option>
-                      </select>
-                    </div>
-                  </div>
-                </div>
-
-                <div v-if="totalWeight !== 100" class="mt-4 p-3 bg-warning-50 border border-warning-200 rounded-lg">
-                  <p class="text-sm text-warning-700">
-                    权重总计必须为100%,当前为{{ totalWeight }}%
-                  </p>
-                </div>
-              </section>
-            </form>
-          </div>
-
-          <!-- 模态框底部 -->
-          <div class="flex justify-end gap-3 p-6 border-t border-gray-100 bg-gray-50">
-            <button
-              @click="handleSubmit"
-              :disabled="!isFormValid || totalWeight !== 100 || isSubmitting"
-              :class="[
-                'btn-primary flex items-center justify-center gap-2 px-8',
-                (!isFormValid || totalWeight !== 100 || isSubmitting) && 'opacity-50 cursor-not-allowed'
-              ]"
-            >
-              <div v-if="isSubmitting" class="flex items-center gap-2">
-                <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
-                保存中...
-              </div>
-              <div v-else class="flex items-center gap-2">
-                <Save :size="16" />
-                保存
-              </div>
-            </button>
-          </div>
-        </div>
-      </div>
-    </Transition>
-  </Teleport>
-</template>
-
-<style scoped>
-/* 模态框动画 */
-.modal-enter-active,
-.modal-leave-active {
-  transition: all 0.3s ease-out;
-}
-
-.modal-enter-from,
-.modal-leave-to {
-  opacity: 0;
-}
-
-.modal-enter-from .relative,
-.modal-leave-to .relative {
-  transform: translateY(100px) scale(0.95);
-}
-</style>

+ 0 - 39
src/main.ts

@@ -1,39 +0,0 @@
-import { createApp } from 'vue'
-import { createPinia } from 'pinia'
-import { MotionPlugin } from '@vueuse/motion'
-import App from './App.vue'
-import './style.css'
-
-// --- Parse 初始化配置 ---
-// 动态导入Parse以避免LiveQuery初始化问题
-let Parse: any;
-
-async function initializeParse() {
-  try {
-    // 设置环境变量禁用LiveQuery
-    (window as any).process = { env: { PARSE_DISABLE_LIVEQUERY: 'true' } };
-    
-    // 动态导入Parse
-    const ParseModule = await import('parse');
-    Parse = ParseModule.default;
-    
-    // 初始化Parse
-    Parse.initialize("myAppId", "myJavascriptKey");
-    Parse.serverURL = "http://localhost:1337/parse";
-    
-    console.log("Parse SDK 成功初始化!");
-  } catch (error) {
-    console.error("Parse SDK 初始化失败:", error);
-  }
-}
-
-// 异步初始化Parse
-initializeParse();
-
-const app = createApp(App)
-const pinia = createPinia()
-
-app.use(pinia)
-app.use(MotionPlugin)
-
-app.mount('#app')

+ 0 - 443
src/stores/jobStore.ts

@@ -1,443 +0,0 @@
-import { defineStore } from 'pinia'
-import { ref, computed } from 'vue'
-
-export interface Job {
-  id: string
-  title: string
-  department: string
-  location: string
-  description: string
-  status: 'active' | 'paused' | 'draft'
-  pendingResumes: number
-  passedResumes: number
-  aiCriteria: {
-    education: { condition: string; value: string; weight: number }
-    experience: { condition: string; value: string; weight: number }
-    skills: { condition: string; value: string; weight: number }
-    language: { condition: string; value: string; weight: number }
-  }
-  createdAt: Date
-  updatedAt: Date
-}
-
-export interface Candidate {
-  id: string
-  name: string
-  jobId: string
-  jobTitle: string
-  matchScore: number
-  status: 'pending' | 'passed' | 'rejected' | 'interviewed'
-  highlights: string[]
-  concerns: string[]
-  summary: string
-  resumeText: string
-  education: string
-  experience: string
-  skills: string[]
-  submittedAt: Date
-  reviewedAt?: Date
-}
-
-export interface Interview {
-  id: string
-  title: string
-  description: string
-  questions: string[]
-  duration: number
-  createdAt: Date
-}
-
-export const useJobStore = defineStore('job', () => {
-  // 状态
-  const jobs = ref<Job[]>([])
-  const candidates = ref<Candidate[]>([])
-  const interviews = ref<Interview[]>([])
-  const isModalOpen = ref(false)
-  const isLoading = ref(false)
-  const currentJob = ref<Job | null>(null)
-  const currentCandidate = ref<Candidate | null>(null)
-
-  // 计算属性
-  const activeJobs = computed(() => 
-    jobs.value.filter(job => job.status === 'active')
-  )
-
-  const totalPendingResumes = computed(() =>
-    jobs.value.reduce((sum, job) => sum + job.pendingResumes, 0)
-  )
-
-  const totalCandidates = computed(() => candidates.value.length)
-
-  const pendingCandidates = computed(() =>
-    candidates.value.filter(candidate => candidate.status === 'pending')
-  )
-
-  const passedCandidates = computed(() =>
-    candidates.value.filter(candidate => candidate.status === 'passed')
-  )
-
-  const rejectedCandidates = computed(() =>
-    candidates.value.filter(candidate => candidate.status === 'rejected')
-  )
-
-  const interviewedCandidates = computed(() =>
-    candidates.value.filter(candidate => candidate.status === 'interviewed')
-  )
-
-  const getCandidatesByJob = computed(() => (jobId: string) =>
-    candidates.value.filter(candidate => candidate.jobId === jobId)
-  )
-
-  const getJobById = computed(() => (jobId: string) =>
-    jobs.value.find(job => job.id === jobId)
-  )
-
-  // 统计数据
-  const dashboardStats = computed(() => ({
-    totalJobs: jobs.value.length,
-    activeJobs: activeJobs.value.length,
-    totalCandidates: totalCandidates.value,
-    pendingCandidates: pendingCandidates.value.length,
-    passedCandidates: passedCandidates.value.length,
-    rejectedCandidates: rejectedCandidates.value.length,
-    interviewedCandidates: interviewedCandidates.value.length,
-    averageMatchScore: candidates.value.length > 0 
-      ? Math.round(candidates.value.reduce((sum, c) => sum + c.matchScore, 0) / candidates.value.length)
-      : 0,
-    passRate: candidates.value.length > 0 
-      ? Math.round((passedCandidates.value.length / candidates.value.length) * 100)
-      : 0
-  }))
-
-  // 动作
-  const initializeData = () => {
-    // 模拟初始数据
-    jobs.value = [
-      {
-        id: '1',
-        title: 'Vue.js前端工程师',
-        department: '技术部',
-        location: '上海',
-        description: '负责前端产品开发,具备Vue.js、TypeScript等技术栈经验',
-        status: 'active',
-        pendingResumes: 12,
-        passedResumes: 3,
-        aiCriteria: {
-          education: { condition: '>=', value: '本科', weight: 20 },
-          experience: { condition: '>=', value: '3年', weight: 30 },
-          skills: { condition: 'includes', value: 'Vue.js,TypeScript', weight: 35 },
-          language: { condition: '>=', value: '英语四级', weight: 15 }
-        },
-        createdAt: new Date('2024-01-15'),
-        updatedAt: new Date('2024-01-20')
-      },
-      {
-        id: '2',
-        title: 'Java后端工程师',
-        department: '技术部',
-        location: '北京',
-        description: '负责后端服务开发,熟悉Spring Boot、微服务架构',
-        status: 'active',
-        pendingResumes: 8,
-        passedResumes: 5,
-        aiCriteria: {
-          education: { condition: '>=', value: '本科', weight: 25 },
-          experience: { condition: '>=', value: '5年', weight: 35 },
-          skills: { condition: 'includes', value: 'Java,Spring Boot,MySQL', weight: 30 },
-          language: { condition: '>=', value: '英语四级', weight: 10 }
-        },
-        createdAt: new Date('2024-01-10'),
-        updatedAt: new Date('2024-01-18')
-      },
-      {
-        id: '3',
-        title: 'UI/UX设计师',
-        department: '设计部',
-        location: '深圳',
-        description: '负责产品界面和用户体验设计',
-        status: 'active',
-        pendingResumes: 15,
-        passedResumes: 2,
-        aiCriteria: {
-          education: { condition: '>=', value: '专科', weight: 15 },
-          experience: { condition: '>=', value: '2年', weight: 25 },
-          skills: { condition: 'includes', value: 'Figma,Sketch,Adobe', weight: 45 },
-          language: { condition: '>=', value: '无要求', weight: 15 }
-        },
-        createdAt: new Date('2024-01-12'),
-        updatedAt: new Date('2024-01-19')
-      }
-    ]
-
-    candidates.value = [
-      {
-        id: '1',
-        name: '张小明',
-        jobId: '1',
-        jobTitle: 'Vue.js前端工程师',
-        matchScore: 88,
-        status: 'pending',
-        highlights: ['5年Vue.js开发经验', '熟悉TypeScript', '有大型项目经验', '具备团队协作能力'],
-        concerns: ['缺少移动端开发经验', '团队管理经验不足'],
-        summary: '具备扎实的前端技术基础,Vue.js经验丰富,适合高级前端开发岗位。在技术深度和项目经验方面表现出色,但在移动端开发和团队管理方面还有提升空间。',
-        education: '本科 - 计算机科学与技术',
-        experience: '5年前端开发经验',
-        skills: ['Vue.js', 'TypeScript', 'JavaScript', 'CSS3', 'Webpack'],
-        resumeText: '张小明,本科学历,计算机科学专业毕业。拥有5年前端开发经验,精通Vue.js、TypeScript等现代前端技术栈。曾在多家互联网公司担任前端工程师,参与过多个大型项目的开发...',
-        submittedAt: new Date('2024-01-20')
-      },
-      {
-        id: '2',
-        name: '李小红',
-        jobId: '1',
-        jobTitle: 'Vue.js前端工程师',
-        matchScore: 75,
-        status: 'pending',
-        highlights: ['3年前端开发经验', '熟悉React和Vue.js', '有组件库开发经验'],
-        concerns: ['TypeScript经验较少', '项目规模偏小', '缺少性能优化经验'],
-        summary: '前端基础良好,技术栈匹配度较高,有一定成长潜力。在组件化开发方面有实践经验,但在TypeScript和大型项目经验方面需要进一步提升。',
-        education: '本科 - 软件工程',
-        experience: '3年前端开发经验',
-        skills: ['Vue.js', 'React', 'JavaScript', 'HTML5', 'CSS3'],
-        resumeText: '李小红,本科学历,软件工程专业。3年前端开发经验,熟悉Vue.js和React框架,有组件库开发经验...',
-        submittedAt: new Date('2024-01-19')
-      },
-      {
-        id: '3',
-        name: '王大强',
-        jobId: '2',
-        jobTitle: 'Java后端工程师',
-        matchScore: 92,
-        status: 'passed',
-        highlights: ['8年Java开发经验', '精通Spring Boot', '有微服务架构经验', '熟悉分布式系统'],
-        concerns: ['缺少云原生经验', '团队规模相对较小'],
-        summary: '资深Java后端工程师,技术功底扎实,项目经验丰富。在微服务架构和分布式系统方面有深入理解,是团队的技术骨干候选人。',
-        education: '硕士 - 计算机科学',
-        experience: '8年Java后端开发经验',
-        skills: ['Java', 'Spring Boot', 'MySQL', 'Redis', 'Kafka'],
-        resumeText: '王大强,硕士学历,8年Java后端开发经验。精通Spring Boot框架,有丰富的微服务架构设计和实施经验...',
-        submittedAt: new Date('2024-01-18'),
-        reviewedAt: new Date('2024-01-19')
-      },
-      {
-        id: '4',
-        name: '陈小美',
-        jobId: '3',
-        jobTitle: 'UI/UX设计师',
-        matchScore: 85,
-        status: 'interviewed',
-        highlights: ['4年UI/UX设计经验', '精通Figma和Sketch', '有B端产品设计经验', '用户体验思维强'],
-        concerns: ['缺少移动端设计经验', '技术理解需要加强'],
-        summary: '优秀的UI/UX设计师,设计功底扎实,用户体验意识强。在B端产品设计方面有丰富经验,但在移动端设计和技术理解方面还有提升空间。',
-        education: '本科 - 视觉传达设计',
-        experience: '4年UI/UX设计经验',
-        skills: ['Figma', 'Sketch', 'Adobe Creative Suite', 'Principle', 'Axure'],
-        resumeText: '陈小美,本科学历,视觉传达设计专业。4年UI/UX设计经验,精通各类设计工具,有丰富的B端产品设计经验...',
-        submittedAt: new Date('2024-01-17'),
-        reviewedAt: new Date('2024-01-18')
-      },
-      {
-        id: '5',
-        name: '刘小刚',
-        jobId: '2',
-        jobTitle: 'Java后端工程师',
-        matchScore: 65,
-        status: 'rejected',
-        highlights: ['2年Java开发经验', '熟悉Spring框架'],
-        concerns: ['经验不足', '缺少大型项目经验', '技术深度有限', '沟通能力待提升'],
-        summary: '初级Java开发工程师,基础技能掌握良好,但经验和技术深度不足以满足当前岗位要求。建议继续积累项目经验后再申请。',
-        education: '专科 - 计算机应用技术',
-        experience: '2年Java开发经验',
-        skills: ['Java', 'Spring', 'MySQL', 'HTML', 'CSS'],
-        resumeText: '刘小刚,专科学历,2年Java开发经验。熟悉Spring框架,参与过小型项目开发...',
-        submittedAt: new Date('2024-01-16'),
-        reviewedAt: new Date('2024-01-17')
-      }
-    ]
-
-    interviews.value = [
-      {
-        id: '1',
-        title: 'Vue.js前端工程师初面',
-        description: '主要考察前端基础知识和Vue.js技术栈',
-        questions: [
-          'Vue 3的Composition API相比Options API有什么优势?',
-          '请解释Vue的响应式原理',
-          '如何优化Vue应用的性能?',
-          '描述一个你负责的复杂前端项目'
-        ],
-        duration: 60,
-        createdAt: new Date('2024-01-15')
-      },
-      {
-        id: '2',
-        title: 'Java后端工程师技术面试',
-        description: '重点考察Java技术栈和系统设计能力',
-        questions: [
-          'Spring Boot的自动配置原理是什么?',
-          '如何设计一个高并发的秒杀系统?',
-          'MySQL的索引优化策略有哪些?',
-          '微服务架构的优缺点是什么?'
-        ],
-        duration: 90,
-        createdAt: new Date('2024-01-12')
-      }
-    ]
-  }
-
-  const addJob = (jobData: Omit<Job, 'id' | 'createdAt' | 'updatedAt'>) => {
-    const newJob: Job = {
-      ...jobData,
-      id: Date.now().toString(),
-      createdAt: new Date(),
-      updatedAt: new Date()
-    }
-    jobs.value.push(newJob)
-  }
-
-  const updateJob = (jobId: string, updates: Partial<Job>) => {
-    const index = jobs.value.findIndex(job => job.id === jobId)
-    if (index !== -1) {
-      jobs.value[index] = {
-        ...jobs.value[index],
-        ...updates,
-        updatedAt: new Date()
-      }
-    }
-  }
-
-  const triggerScreening = async (jobId: string) => {
-    const job = jobs.value.find(j => j.id === jobId)
-    if (!job) return
-
-    isLoading.value = true
-    
-    // 模拟AI筛选过程
-    await new Promise(resolve => setTimeout(resolve, 2000))
-    
-    // 更新简历数量
-    job.pendingResumes = 0
-    job.passedResumes += Math.floor(Math.random() * 3) + 1
-    job.updatedAt = new Date()
-    
-    isLoading.value = false
-  }
-
-  const updateCandidateStatus = (candidateId: string, status: Candidate['status']) => {
-    const candidate = candidates.value.find(c => c.id === candidateId)
-    if (candidate) {
-      candidate.status = status
-      candidate.reviewedAt = new Date()
-    }
-  }
-
-  const batchScreenCandidates = async (candidateIds: string[]) => {
-    isLoading.value = true
-    
-    // 模拟批量筛选
-    await new Promise(resolve => setTimeout(resolve, 1500))
-    
-    candidateIds.forEach(id => {
-      const candidate = candidates.value.find(c => c.id === id)
-      if (candidate && candidate.status === 'pending') {
-        // 根据匹配度自动判断
-        candidate.status = candidate.matchScore >= 75 ? 'passed' : 'rejected'
-        candidate.reviewedAt = new Date()
-      }
-    })
-    
-    isLoading.value = false
-  }
-
-  const openModal = () => {
-    isModalOpen.value = true
-  }
-
-  const closeModal = () => {
-    isModalOpen.value = false
-    currentJob.value = null
-  }
-
-  const setCurrentJob = (job: Job | null) => {
-    currentJob.value = job
-  }
-
-  const setCurrentCandidate = (candidate: Candidate | null) => {
-    currentCandidate.value = candidate
-  }
-
-  const addInterview = (interviewData: Omit<Interview, 'id' | 'createdAt'>) => {
-    const newInterview: Interview = {
-      ...interviewData,
-      id: Date.now().toString(),
-      createdAt: new Date()
-    }
-    interviews.value.push(newInterview)
-  }
-
-  const pauseJob = (jobId: string) => {
-    const job = jobs.value.find(j => j.id === jobId)
-    if (job) {
-      job.status = 'paused'
-      job.updatedAt = new Date()
-    }
-  }
-
-  const resumeJob = (jobId: string) => {
-    const job = jobs.value.find(j => j.id === jobId)
-    if (job) {
-      job.status = 'active'
-      job.updatedAt = new Date()
-    }
-  }
-
-  const deleteJob = (jobId: string) => {
-    const index = jobs.value.findIndex(j => j.id === jobId)
-    if (index !== -1) {
-      jobs.value.splice(index, 1)
-      // 同时删除相关的候选人数据
-      candidates.value = candidates.value.filter(c => c.jobId !== jobId)
-      // 删除相关的面试数据
-      //interviews.value = interviews.value.filter(i => i.jobId !== jobId)
-    }
-  }
-
-  return {
-    // 状态
-    jobs,
-    candidates,
-    interviews,
-    isModalOpen,
-    isLoading,
-    currentJob,
-    currentCandidate,
-    
-    // 计算属性
-    activeJobs,
-    totalPendingResumes,
-    totalCandidates,
-    pendingCandidates,
-    passedCandidates,
-    rejectedCandidates,
-    interviewedCandidates,
-    getCandidatesByJob,
-    getJobById,
-    dashboardStats,
-    
-    // 动作
-    initializeData,
-    addJob,
-    updateJob,
-    triggerScreening,
-    updateCandidateStatus,
-    batchScreenCandidates,
-    openModal,
-    closeModal,
-    setCurrentJob,
-    setCurrentCandidate,
-    addInterview,
-    pauseJob,
-    resumeJob,
-    deleteJob
-  }
-})

+ 0 - 112
src/style.css

@@ -1,112 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/* 全局样式优化 */
-@layer base {
-  html {
-    font-family: 'Inter', system-ui, sans-serif;
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
-  }
-  
-  body {
-    @apply bg-gray-50 text-gray-900 overflow-x-hidden;
-    min-height: 100vh;
-    min-height: -webkit-fill-available;
-  }
-  
-  /* 移动端适配 */
-  @media screen and (max-width: 768px) {
-    body {
-      min-height: 100vh;
-      min-height: -webkit-fill-available;
-    }
-  }
-}
-
-/* 组件样式 */
-@layer components {
-  .btn-primary {
-    @apply bg-gradient-to-r from-primary-500 to-secondary-500 text-white font-medium py-3 px-6 rounded-xl shadow-lg hover:shadow-xl transition-all duration-300 active:scale-95;
-  }
-  
-  .btn-secondary {
-    @apply bg-white text-gray-700 font-medium py-3 px-6 rounded-xl border border-gray-200 shadow-sm hover:shadow-md transition-all duration-300 active:scale-95;
-  }
-  
-  .card {
-    @apply bg-white rounded-2xl shadow-sm hover:shadow-lg transition-all duration-300 border border-gray-100;
-  }
-  
-  .glass-card {
-    @apply rounded-2xl shadow-xl transition-all duration-300;
-    background: rgba(255, 255, 255, 0.85);
-    backdrop-filter: blur(20px);
-    -webkit-backdrop-filter: blur(20px);
-    border: 1px solid rgba(255, 255, 255, 0.2);
-  }
-  
-  .input-field {
-    @apply w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-primary-500 focus:ring-2 focus:ring-primary-500/20 transition-colors duration-200 outline-none;
-  }
-  
-  .animate-stagger {
-    animation: fade-in-up 0.6s ease-out both;
-  }
-  
-  .animate-stagger:nth-child(1) { animation-delay: 0.1s; }
-  .animate-stagger:nth-child(2) { animation-delay: 0.2s; }
-  .animate-stagger:nth-child(3) { animation-delay: 0.3s; }
-  .animate-stagger:nth-child(4) { animation-delay: 0.4s; }
-  .animate-stagger:nth-child(5) { animation-delay: 0.5s; }
-}
-
-/* 工具样式 */
-@layer utilities {
-  .text-gradient {
-    @apply bg-gradient-to-r from-primary-600 to-secondary-600 bg-clip-text text-transparent;
-  }
-  
-  .shimmer {
-    position: relative;
-    overflow: hidden;
-  }
-  
-  .shimmer::before {
-    content: '';
-    position: absolute;
-    top: 0;
-    left: -100%;
-    width: 100%;
-    height: 100%;
-    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
-    animation: shimmer 2s infinite;
-  }
-  
-  .safe-area-bottom {
-    padding-bottom: env(safe-area-inset-bottom);
-  }
-  
-  .safe-area-top {
-    padding-top: env(safe-area-inset-top);
-  }
-}
-
-/* 滚动条优化 */
-::-webkit-scrollbar {
-  width: 4px;
-}
-
-::-webkit-scrollbar-track {
-  background: transparent;
-}
-
-::-webkit-scrollbar-thumb {
-  background: rgba(156, 163, 175, 0.5);
-  border-radius: 2px;
-}
-
-::-webkit-scrollbar-thumb:hover {
-  background: rgba(156, 163, 175, 0.8);
-}

+ 0 - 518
src/views/CandidateView.vue

@@ -1,518 +0,0 @@
-<script setup lang="ts">
-import { ref, computed } from 'vue'
-import { useJobStore } from '../stores/jobStore'
-import CandidateCard from '../components/CandidateCard.vue'
-import CandidateDetailModal from '../components/CandidateDetailModal.vue'
-import { Users, Filter, CheckCircle, XCircle, Clock, UserCheck, ChevronDown, Briefcase } from 'lucide-vue-next'
-
-const jobStore = useJobStore()
-
-const selectedStatus = ref<string>('all')
-const selectedJob = ref<string>('all')
-const isDetailModalOpen = ref(false)
-const selectedCandidateIds = ref<string[]>([])
-const isJobDropdownOpen = ref(false)
-
-const statusOptions = [
-  { value: 'all', label: '全部状态', icon: Users },
-  { value: 'pending', label: '待处理', icon: Clock },
-  { value: 'passed', label: '已通过', icon: CheckCircle },
-  { value: 'rejected', label: '已拒绝', icon: XCircle },
-  { value: 'interviewed', label: '已面试', icon: UserCheck }
-]
-
-const jobOptions = computed(() => [
-  { value: 'all', label: '全部岗位', department: '' },
-  ...jobStore.jobs.map(job => ({
-    value: job.id,
-    label: job.title,
-    department: job.department
-  }))
-])
-
-const selectedJobLabel = computed(() => {
-  const job = jobOptions.value.find(option => option.value === selectedJob.value)
-  return job ? job.label : '全部岗位'
-})
-
-const filteredCandidates = computed(() => {
-  let filtered = jobStore.candidates
-
-  if (selectedStatus.value !== 'all') {
-    filtered = filtered.filter(candidate => candidate.status === selectedStatus.value)
-  }
-
-  if (selectedJob.value !== 'all') {
-    filtered = filtered.filter(candidate => candidate.jobId === selectedJob.value)
-  }
-
-  return filtered.sort((a, b) => new Date(b.submittedAt).getTime() - new Date(a.submittedAt).getTime())
-})
-
-const pendingCandidates = computed(() => 
-  filteredCandidates.value.filter(c => c.status === 'pending')
-)
-
-const canBatchScreen = computed(() => 
-  selectedCandidateIds.value.length > 0 && 
-  selectedCandidateIds.value.every(id => 
-    jobStore.candidates.find(c => c.id === id)?.status === 'pending'
-  )
-)
-
-const handleCandidateClick = (candidate: any) => {
-  jobStore.setCurrentCandidate(candidate)
-  isDetailModalOpen.value = true
-}
-
-const handleCloseDetailModal = () => {
-  isDetailModalOpen.value = false
-  jobStore.setCurrentCandidate(null)
-}
-
-const handleBatchScreen = async () => {
-  if (!canBatchScreen.value) return
-  
-  await jobStore.batchScreenCandidates(selectedCandidateIds.value)
-  selectedCandidateIds.value = []
-  
-  // 显示成功提示
-  setTimeout(() => {
-    alert(`已完成 ${selectedCandidateIds.value.length} 位候选人的批量筛选!`)
-  }, 100)
-}
-
-const toggleCandidateSelection = (candidateId: string) => {
-  const index = selectedCandidateIds.value.indexOf(candidateId)
-  if (index > -1) {
-    selectedCandidateIds.value.splice(index, 1)
-  } else {
-    selectedCandidateIds.value.push(candidateId)
-  }
-}
-
-const selectAllPending = () => {
-  const pendingIds = pendingCandidates.value.map(c => c.id)
-  selectedCandidateIds.value = [...pendingIds]
-}
-
-const clearSelection = () => {
-  selectedCandidateIds.value = []
-}
-
-const selectJob = (jobValue: string) => {
-  selectedJob.value = jobValue
-  isJobDropdownOpen.value = false
-}
-
-const toggleJobDropdown = () => {
-  isJobDropdownOpen.value = !isJobDropdownOpen.value
-}
-
-// 点击外部关闭下拉框
-const handleClickOutside = (event: Event) => {
-  const dropdown = document.querySelector('.job-dropdown')
-  if (dropdown && !dropdown.contains(event.target as Node)) {
-    isJobDropdownOpen.value = false
-  }
-}
-
-// 监听点击外部事件
-document.addEventListener('click', handleClickOutside)
-
-const getStatusConfig = (status: string) => {
-  switch (status) {
-    case 'pending':
-      return { label: '待处理', class: 'bg-warning-100 text-warning-700', icon: Clock }
-    case 'passed':
-      return { label: '已通过', class: 'bg-success-100 text-success-700', icon: CheckCircle }
-    case 'rejected':
-      return { label: '已拒绝', class: 'bg-error-100 text-error-700', icon: XCircle }
-    case 'interviewed':
-      return { label: '已面试', class: 'bg-primary-100 text-primary-700', icon: UserCheck }
-    default:
-      return { label: '未知', class: 'bg-gray-100 text-gray-700', icon: Users }
-  }
-}
-</script>
-
-<template>
-  <div class="px-4 py-6">
-    <!-- 头部标题区域 -->
-    <div 
-      class="mb-6"
-      v-motion-fade-visible-once
-      :delay="100"
-    >
-      <h1 class="text-3xl font-bold text-gradient mb-2">候选人管理</h1>
-      <p class="text-gray-600">查看和管理所有候选人,进行智能筛选</p>
-    </div>
-
-    <!-- 筛选器 -->
-    <div 
-      class="glass-card p-4 mb-6 space-y-4 relative z-10"
-      v-motion-slide-visible-once
-      :delay="200"
-    >
-      <!-- 状态筛选 -->
-      <div>
-        <label class="block text-sm font-medium text-gray-700 mb-2">
-          <Filter :size="16" class="inline mr-1" />
-          筛选状态
-        </label>
-        <div class="flex flex-wrap gap-2">
-          <button
-            v-for="option in statusOptions"
-            :key="option.value"
-            @click="selectedStatus = option.value"
-            :class="[
-              'flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium transition-all duration-200',
-              selectedStatus === option.value
-                ? 'bg-primary-500 text-white shadow-md'
-                : 'bg-gray-100 text-gray-600 hover:bg-gray-200'
-            ]"
-          >
-            <component :is="option.icon" :size="14" />
-            {{ option.label }}
-          </button>
-        </div>
-      </div>
-
-      <!-- 岗位筛选 - 自定义下拉框 -->
-      <div>
-        <label class="block text-sm font-medium text-gray-700 mb-2">筛选岗位</label>
-        <div class="relative job-dropdown">
-          <!-- 下拉框触发器 -->
-          <button
-            @click="toggleJobDropdown"
-            :class="[
-              'w-full flex items-center justify-between px-4 py-3 bg-white border border-gray-200 rounded-xl text-left transition-all duration-200',
-              'hover:border-primary-300 focus:border-primary-500 focus:ring-2 focus:ring-primary-500/20',
-              isJobDropdownOpen && 'border-primary-500 ring-2 ring-primary-500/20'
-            ]"
-          >
-            <div class="flex items-center gap-3 flex-1 min-w-0">
-              <div class="w-8 h-8 rounded-lg bg-primary-100 flex items-center justify-center flex-shrink-0">
-                <Briefcase :size="16" class="text-primary-600" />
-              </div>
-              <div class="min-w-0 flex-1">
-                <div class="font-medium text-gray-900 truncate">{{ selectedJobLabel }}</div>
-                <div v-if="selectedJob !== 'all'" class="text-sm text-gray-500 truncate">
-                  {{ jobOptions.find(j => j.value === selectedJob)?.department }}
-                </div>
-              </div>
-            </div>
-            <ChevronDown 
-              :size="20" 
-              :class="[
-                'text-gray-400 transition-transform duration-200 flex-shrink-0',
-                isJobDropdownOpen && 'rotate-180'
-              ]" 
-            />
-          </button>
-
-          <!-- 下拉选项 -->
-          <Transition name="dropdown">
-            <div 
-              v-if="isJobDropdownOpen"
-              class="dropdown-menu absolute top-full left-0 right-0 mt-2 bg-white border border-gray-200 rounded-xl shadow-2xl max-h-64 overflow-y-auto"
-            >
-              <div class="py-2">
-                <button
-                  v-for="option in jobOptions"
-                  :key="option.value"
-                  @click="selectJob(option.value)"
-                  :class="[
-                    'w-full flex items-center gap-3 px-4 py-3 text-left transition-colors duration-150',
-                    'hover:bg-gray-50 active:bg-gray-100',
-                    selectedJob === option.value && 'bg-primary-50 text-primary-700'
-                  ]"
-                >
-                  <div 
-                    :class="[
-                      'w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0',
-                      selectedJob === option.value ? 'bg-primary-200' : 'bg-gray-100'
-                    ]"
-                  >
-                    <Briefcase 
-                      :size="16" 
-                      :class="selectedJob === option.value ? 'text-primary-700' : 'text-gray-500'" 
-                    />
-                  </div>
-                  <div class="min-w-0 flex-1">
-                    <div 
-                      :class="[
-                        'font-medium truncate',
-                        selectedJob === option.value ? 'text-primary-900' : 'text-gray-900'
-                      ]"
-                    >
-                      {{ option.label }}
-                    </div>
-                    <div 
-                      v-if="option.department" 
-                      :class="[
-                        'text-sm truncate',
-                        selectedJob === option.value ? 'text-primary-600' : 'text-gray-500'
-                      ]"
-                    >
-                      {{ option.department }}
-                    </div>
-                  </div>
-                  <!-- 选中指示器 -->
-                  <div 
-                    v-if="selectedJob === option.value"
-                    class="w-2 h-2 bg-primary-500 rounded-full flex-shrink-0"
-                  ></div>
-                </button>
-              </div>
-            </div>
-          </Transition>
-        </div>
-      </div>
-    </div>
-
-    <!-- 批量操作栏 -->
-    <div 
-      v-if="pendingCandidates.length > 0"
-      class="glass-card p-4 mb-6 relative z-0"
-      v-motion-slide-visible-once
-      :delay="300"
-    >
-      <div class="flex items-center justify-between mb-3">
-        <h3 class="font-semibold text-gray-900">批量操作</h3>
-        <div class="text-sm text-gray-500">
-          已选择 {{ selectedCandidateIds.length }} / {{ pendingCandidates.length }} 位候选人
-        </div>
-      </div>
-      
-      <div class="flex flex-wrap gap-3">
-        <button
-          @click="selectAllPending"
-          class="btn-secondary text-sm flex-shrink-0"
-        >
-          全选待处理
-        </button>
-        
-        <button
-          @click="clearSelection"
-          class="btn-secondary text-sm flex-shrink-0"
-          :disabled="selectedCandidateIds.length === 0"
-        >
-          清空选择
-        </button>
-        
-        <button
-          @click="handleBatchScreen"
-          :disabled="!canBatchScreen || jobStore.isLoading"
-          :class="[
-            'btn-primary text-sm flex items-center gap-2 flex-shrink-0',
-            (!canBatchScreen || jobStore.isLoading) && 'opacity-50 cursor-not-allowed'
-          ]"
-        >
-          <div v-if="jobStore.isLoading" class="flex items-center gap-2">
-            <div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
-            批量筛选中...
-          </div>
-          <div v-else>
-            一键批量筛选
-          </div>
-        </button>
-      </div>
-    </div>
-
-    <!-- 统计卡片 -->
-    <div 
-      class="grid grid-cols-2 sm:grid-cols-4 gap-4 mb-6"
-      v-motion-fade-visible-once
-      :delay="400"
-    >
-      <div class="glass-card p-4 text-center">
-        <div class="text-2xl font-bold text-gray-900 mb-1">
-          {{ filteredCandidates.length }}
-        </div>
-        <div class="text-sm text-gray-600">候选人总数</div>
-      </div>
-      
-      <div class="glass-card p-4 text-center">
-        <div class="text-2xl font-bold text-warning-600 mb-1">
-          {{ jobStore.pendingCandidates.length }}
-        </div>
-        <div class="text-sm text-gray-600">待处理</div>
-      </div>
-      
-      <div class="glass-card p-4 text-center">
-        <div class="text-2xl font-bold text-success-600 mb-1">
-          {{ jobStore.passedCandidates.length }}
-        </div>
-        <div class="text-sm text-gray-600">已通过</div>
-      </div>
-      
-      <div class="glass-card p-4 text-center">
-        <div class="text-2xl font-bold text-primary-600 mb-1">
-          {{ jobStore.interviewedCandidates.length }}
-        </div>
-        <div class="text-sm text-gray-600">已面试</div>
-      </div>
-    </div>
-
-    <!-- 候选人列表 -->
-    <div class="space-y-4">
-      <TransitionGroup
-        name="stagger"
-        tag="div"
-        class="space-y-4"
-      >
-        <CandidateCard
-          v-for="(candidate, index) in filteredCandidates"
-          :key="candidate.id"
-          :candidate="candidate"
-          :is-selected="selectedCandidateIds.includes(candidate.id)"
-          :class="`animate-stagger`"
-          :style="{ 'animation-delay': `${index * 0.1}s` }"
-          @click="handleCandidateClick(candidate)"
-          @toggle-selection="toggleCandidateSelection(candidate.id)"
-        />
-      </TransitionGroup>
-      
-      <!-- 空状态 -->
-      <div 
-        v-if="filteredCandidates.length === 0"
-        class="text-center py-16"
-        v-motion-fade-visible-once
-        :delay="500"
-      >
-        <div class="w-24 h-24 mx-auto mb-4 rounded-full bg-gray-100 flex items-center justify-center">
-          <Users :size="32" class="text-gray-400" />
-        </div>
-        <h3 class="text-lg font-medium text-gray-900 mb-2">暂无候选人</h3>
-        <p class="text-gray-500 mb-6">当前筛选条件下没有找到候选人</p>
-      </div>
-    </div>
-
-    <!-- 候选人详情模态框 -->
-    <CandidateDetailModal 
-      :is-open="isDetailModalOpen"
-      @close="handleCloseDetailModal"
-    />
-  </div>
-</template>
-
-<style scoped>
-/* 交错动画 */
-.stagger-enter-active {
-  transition: all 0.6s ease-out;
-}
-
-.stagger-enter-from {
-  opacity: 0;
-  transform: translateY(20px);
-}
-
-.stagger-move {
-  transition: transform 0.4s ease;
-}
-
-/* 下拉框动画 */
-.dropdown-enter-active,
-.dropdown-leave-active {
-  transition: all 0.2s ease-out;
-}
-
-.dropdown-enter-from,
-.dropdown-leave-to {
-  opacity: 0;
-  transform: translateY(-10px) scale(0.95);
-}
-
-/* 下拉框样式优化 - 超高层级 */
-.dropdown-menu {
-  /* 设置超高z-index确保在所有元素之上 */
-  z-index: 99999 !important;
-  /* 增强阴影效果 */
-  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(0, 0, 0, 0.1) !important;
-  /* 确保背景完全不透明 */
-  background-color: white !important;
-  /* 移除背景模糊效果,避免透明度问题 */
-  backdrop-filter: none !important;
-  -webkit-backdrop-filter: none !important;
-  /* 确保边框清晰 */
-  border: 1px solid rgba(0, 0, 0, 0.1) !important;
-}
-
-/* 移动端优化 */
-@media (max-width: 640px) {
-  .job-dropdown .dropdown-menu {
-    left: -1rem;
-    right: -1rem;
-    width: calc(100vw - 2rem);
-    /* 移动端也保持最高层级 */
-    z-index: 99999 !important;
-  }
-}
-
-/* 滚动条样式 */
-.dropdown-menu::-webkit-scrollbar {
-  width: 4px;
-}
-
-.dropdown-menu::-webkit-scrollbar-track {
-  background: transparent;
-}
-
-.dropdown-menu::-webkit-scrollbar-thumb {
-  background: rgba(156, 163, 175, 0.5);
-  border-radius: 2px;
-}
-
-.dropdown-menu::-webkit-scrollbar-thumb:hover {
-  background: rgba(156, 163, 175, 0.8);
-}
-
-/* 确保下拉框容器有正确的层叠上下文 */
-.job-dropdown {
-  position: relative;
-  z-index: 50;
-}
-
-/* 当下拉框打开时,提升整个容器的层级到最高 */
-.job-dropdown:has(.dropdown-menu) {
-  z-index: 99999 !important;
-}
-
-/* 筛选器容器层级 */
-.glass-card.z-10 {
-  z-index: 10;
-}
-
-/* 批量操作栏层级 */
-.glass-card.z-0 {
-  z-index: 0;
-}
-
-/* 确保批量操作按钮正确换行和显示 */
-.btn-secondary,
-.btn-primary {
-  white-space: nowrap;
-  min-height: 40px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-/* 移动端按钮优化 */
-@media (max-width: 640px) {
-  .btn-secondary,
-  .btn-primary {
-    min-width: auto;
-    flex: 1;
-    min-height: 44px; /* 增加移动端触摸区域 */
-  }
-  
-  /* 确保按钮文字完全显示 */
-  .btn-primary,
-  .btn-secondary {
-    padding: 12px 16px;
-    font-size: 14px;
-  }
-}
-</style>

+ 0 - 264
src/views/DashboardView.vue

@@ -1,264 +0,0 @@
-<script setup lang="ts">
-import { computed } from 'vue'
-import { useJobStore } from '../stores/jobStore'
-import { BarChart3, TrendingUp, Users, Briefcase, Clock, CheckCircle, XCircle, UserCheck } from 'lucide-vue-next'
-
-const jobStore = useJobStore()
-
-const stats = computed(() => jobStore.dashboardStats)
-
-const recentCandidates = computed(() => 
-  jobStore.candidates
-    .sort((a, b) => new Date(b.submittedAt).getTime() - new Date(a.submittedAt).getTime())
-    .slice(0, 5)
-)
-
-const jobPerformance = computed(() => 
-  jobStore.jobs.map(job => {
-    const candidates = jobStore.getCandidatesByJob(job.id)
-    const passedCount = candidates.filter(c => c.status === 'passed').length
-    const totalCount = candidates.length
-    const passRate = totalCount > 0 ? Math.round((passedCount / totalCount) * 100) : 0
-    
-    return {
-      ...job,
-      candidateCount: totalCount,
-      passedCount,
-      passRate
-    }
-  }).sort((a, b) => b.candidateCount - a.candidateCount)
-)
-
-const getStatusIcon = (status: string) => {
-  switch (status) {
-    case 'pending': return Clock
-    case 'passed': return CheckCircle
-    case 'rejected': return XCircle
-    case 'interviewed': return UserCheck
-    default: return Users
-  }
-}
-
-const getStatusColor = (status: string) => {
-  switch (status) {
-    case 'pending': return 'text-warning-600'
-    case 'passed': return 'text-success-600'
-    case 'rejected': return 'text-error-600'
-    case 'interviewed': return 'text-primary-600'
-    default: return 'text-gray-600'
-  }
-}
-
-const formatDate = (date: Date) => {
-  return new Intl.DateTimeFormat('zh-CN', {
-    month: 'short',
-    day: 'numeric',
-    hour: '2-digit',
-    minute: '2-digit'
-  }).format(date)
-}
-</script>
-
-<template>
-  <div class="px-4 py-6">
-    <!-- 头部标题区域 -->
-    <div 
-      class="mb-8"
-      v-motion-fade-visible-once
-      :delay="100"
-    >
-      <h1 class="text-3xl font-bold text-gradient mb-2">数据面板</h1>
-      <p class="text-gray-600">全面了解招聘数据和筛选效果</p>
-    </div>
-
-    <!-- 核心指标卡片 -->
-    <div 
-      class="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8"
-      v-motion-fade-visible-once
-      :delay="200"
-    >
-      <!-- 总岗位数 -->
-      <div class="glass-card p-6 text-center">
-        <div class="w-12 h-12 mx-auto mb-3 rounded-full bg-primary-100 flex items-center justify-center">
-          <Briefcase :size="24" class="text-primary-600" />
-        </div>
-        <div class="text-2xl font-bold text-gray-900 mb-1">
-          {{ stats.totalJobs }}
-        </div>
-        <div class="text-sm text-gray-600">总岗位数</div>
-        <div class="text-xs text-primary-600 mt-1">
-          {{ stats.activeJobs }} 个活跃
-        </div>
-      </div>
-
-      <!-- 总候选人数 -->
-      <div class="glass-card p-6 text-center">
-        <div class="w-12 h-12 mx-auto mb-3 rounded-full bg-secondary-100 flex items-center justify-center">
-          <Users :size="24" class="text-secondary-600" />
-        </div>
-        <div class="text-2xl font-bold text-gray-900 mb-1">
-          {{ stats.totalCandidates }}
-        </div>
-        <div class="text-sm text-gray-600">总候选人</div>
-        <div class="text-xs text-secondary-600 mt-1">
-          {{ stats.pendingCandidates }} 待处理
-        </div>
-      </div>
-
-      <!-- 平均匹配度 -->
-      <div class="glass-card p-6 text-center">
-        <div class="w-12 h-12 mx-auto mb-3 rounded-full bg-success-100 flex items-center justify-center">
-          <TrendingUp :size="24" class="text-success-600" />
-        </div>
-        <div class="text-2xl font-bold text-gray-900 mb-1">
-          {{ stats.averageMatchScore }}
-        </div>
-        <div class="text-sm text-gray-600">平均匹配度</div>
-        <div class="text-xs text-success-600 mt-1">
-          AI评分
-        </div>
-      </div>
-
-      <!-- 通过率 -->
-      <div class="glass-card p-6 text-center">
-        <div class="w-12 h-12 mx-auto mb-3 rounded-full bg-warning-100 flex items-center justify-center">
-          <BarChart3 :size="24" class="text-warning-600" />
-        </div>
-        <div class="text-2xl font-bold text-gray-900 mb-1">
-          {{ stats.passRate }}%
-        </div>
-        <div class="text-sm text-gray-600">初筛通过率</div>
-        <div class="text-xs text-warning-600 mt-1">
-          {{ stats.passedCandidates }}/{{ stats.totalCandidates }}
-        </div>
-      </div>
-    </div>
-
-    <!-- 状态分布 -->
-    <div 
-      class="glass-card p-6 mb-8"
-      v-motion-slide-visible-once
-      :delay="300"
-    >
-      <h3 class="text-lg font-semibold text-gray-900 mb-4">候选人状态分布</h3>
-      
-      <div class="grid grid-cols-2 sm:grid-cols-4 gap-4">
-        <div class="text-center p-4 bg-warning-50 rounded-xl border border-warning-100">
-          <Clock :size="24" class="mx-auto mb-2 text-warning-600" />
-          <div class="text-xl font-bold text-warning-700">{{ stats.pendingCandidates }}</div>
-          <div class="text-sm text-warning-600">待处理</div>
-        </div>
-        
-        <div class="text-center p-4 bg-success-50 rounded-xl border border-success-100">
-          <CheckCircle :size="24" class="mx-auto mb-2 text-success-600" />
-          <div class="text-xl font-bold text-success-700">{{ stats.passedCandidates }}</div>
-          <div class="text-sm text-success-600">已通过</div>
-        </div>
-        
-        <div class="text-center p-4 bg-error-50 rounded-xl border border-error-100">
-          <XCircle :size="24" class="mx-auto mb-2 text-error-600" />
-          <div class="text-xl font-bold text-error-700">{{ stats.rejectedCandidates }}</div>
-          <div class="text-sm text-error-600">已拒绝</div>
-        </div>
-        
-        <div class="text-center p-4 bg-primary-50 rounded-xl border border-primary-100">
-          <UserCheck :size="24" class="mx-auto mb-2 text-primary-600" />
-          <div class="text-xl font-bold text-primary-700">{{ stats.interviewedCandidates }}</div>
-          <div class="text-sm text-primary-600">已面试</div>
-        </div>
-      </div>
-    </div>
-
-    <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
-      <!-- 岗位表现 -->
-      <div 
-        class="glass-card p-6"
-        v-motion-slide-visible-once="{ initial: { x: -50, opacity: 0 } }"
-        :delay="400"
-      >
-        <h3 class="text-lg font-semibold text-gray-900 mb-4">岗位招聘表现</h3>
-        
-        <div class="space-y-4">
-          <div 
-            v-for="job in jobPerformance"
-            :key="job.id"
-            class="p-4 bg-gray-50 rounded-xl"
-          >
-            <div class="flex items-center justify-between mb-2">
-              <h4 class="font-medium text-gray-900">{{ job.title }}</h4>
-              <span class="text-sm text-gray-500">{{ job.department }}</span>
-            </div>
-            
-            <div class="grid grid-cols-3 gap-4 text-center">
-              <div>
-                <div class="text-lg font-bold text-gray-900">{{ job.candidateCount }}</div>
-                <div class="text-xs text-gray-600">总候选人</div>
-              </div>
-              <div>
-                <div class="text-lg font-bold text-success-600">{{ job.passedCount }}</div>
-                <div class="text-xs text-gray-600">已通过</div>
-              </div>
-              <div>
-                <div class="text-lg font-bold text-primary-600">{{ job.passRate }}%</div>
-                <div class="text-xs text-gray-600">通过率</div>
-              </div>
-            </div>
-            
-            <!-- 进度条 -->
-            <div class="mt-3">
-              <div class="w-full bg-gray-200 rounded-full h-2">
-                <div 
-                  class="bg-gradient-to-r from-success-500 to-primary-500 h-2 rounded-full transition-all duration-500"
-                  :style="{ width: `${job.passRate}%` }"
-                ></div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- 最近候选人 -->
-      <div 
-        class="glass-card p-6"
-        v-motion-slide-visible-once="{ initial: { x: 50, opacity: 0 } }"
-        :delay="500"
-      >
-        <h3 class="text-lg font-semibold text-gray-900 mb-4">最近候选人</h3>
-        
-        <div class="space-y-3">
-          <div 
-            v-for="candidate in recentCandidates"
-            :key="candidate.id"
-            class="flex items-center justify-between p-3 bg-gray-50 rounded-xl"
-          >
-            <div class="flex-1 min-w-0">
-              <div class="flex items-center gap-2 mb-1">
-                <h4 class="font-medium text-gray-900 truncate">{{ candidate.name }}</h4>
-                <component 
-                  :is="getStatusIcon(candidate.status)" 
-                  :size="14" 
-                  :class="getStatusColor(candidate.status)"
-                />
-              </div>
-              <p class="text-sm text-gray-600 truncate">{{ candidate.jobTitle }}</p>
-              <p class="text-xs text-gray-500">{{ formatDate(candidate.submittedAt) }}</p>
-            </div>
-            
-            <div class="text-right ml-3">
-              <div 
-                :class="[
-                  'text-lg font-bold',
-                  candidate.matchScore >= 85 ? 'text-success-600' :
-                  candidate.matchScore >= 70 ? 'text-primary-600' : 'text-warning-600'
-                ]"
-              >
-                {{ candidate.matchScore }}
-              </div>
-              <div class="text-xs text-gray-500">匹配度</div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>

+ 0 - 117
src/views/JobManagementView.vue

@@ -1,117 +0,0 @@
-<script setup lang="ts">
-import { ref } from 'vue'
-import { useJobStore } from '../stores/jobStore'
-import JobCard from '../components/JobCard.vue'
-import JobCreatorModal from '../components/JobCreatorModal.vue'
-import { Plus } from 'lucide-vue-next'
-
-const jobStore = useJobStore()
-
-const handleCreateJob = () => {
-  jobStore.openModal()
-}
-</script>
-
-<template>
-  <div class="px-4 py-6">
-    <!-- 头部标题区域 -->
-    <div 
-      class="flex items-center justify-between mb-8"
-      v-motion-fade-visible-once
-      :delay="100"
-    >
-      <div>
-        <h1 class="text-3xl font-bold text-gradient mb-2">岗位管理</h1>
-        <p class="text-gray-600">管理招聘岗位,追踪简历处理进度</p>
-      </div>
-      
-      <!-- 创建岗位按钮 -->
-      <button
-        @click="handleCreateJob"
-        class="btn-primary flex items-center gap-2 text-sm shadow-lg hover:shadow-xl transform hover:scale-105"
-        v-motion-slide-visible-once
-        :delay="200"
-      >
-        <Plus :size="16" />
-        <span class="hidden sm:inline">创建新岗位</span>
-      </button>
-    </div>
-
-    <!-- 统计卡片 -->
-    <div 
-      class="grid grid-cols-2 gap-4 mb-8"
-      v-motion-fade-visible-once
-      :delay="300"
-    >
-      <div class="glass-card p-4 text-center">
-        <div class="text-2xl font-bold text-primary-600 mb-1">
-          {{ jobStore.activeJobs.length }}
-        </div>
-        <div class="text-sm text-gray-600">活跃岗位</div>
-      </div>
-      
-      <div class="glass-card p-4 text-center">
-        <div class="text-2xl font-bold text-warning-600 mb-1">
-          {{ jobStore.totalPendingResumes }}
-        </div>
-        <div class="text-sm text-gray-600">待处理简历</div>
-      </div>
-    </div>
-
-    <!-- 岗位列表 -->
-    <div class="space-y-4">
-      <TransitionGroup
-        name="stagger"
-        tag="div"
-        class="space-y-4"
-      >
-        <JobCard
-          v-for="(job, index) in jobStore.jobs"
-          :key="job.id"
-          :job="job"
-          :class="`animate-stagger`"
-          :style="{ 'animation-delay': `${index * 0.1}s` }"
-        />
-      </TransitionGroup>
-      
-      <!-- 空状态 -->
-      <div 
-        v-if="jobStore.jobs.length === 0"
-        class="text-center py-16"
-        v-motion-fade-visible-once
-        :delay="400"
-      >
-        <div class="w-24 h-24 mx-auto mb-4 rounded-full bg-gray-100 flex items-center justify-center">
-          <Plus :size="32" class="text-gray-400" />
-        </div>
-        <h3 class="text-lg font-medium text-gray-900 mb-2">暂无岗位</h3>
-        <p class="text-gray-500 mb-6">点击右上角按钮创建您的第一个岗位</p>
-        <button 
-          @click="handleCreateJob"
-          class="btn-primary"
-        >
-          创建新岗位
-        </button>
-      </div>
-    </div>
-
-    <!-- 创建岗位模态框 -->
-    <JobCreatorModal />
-  </div>
-</template>
-
-<style scoped>
-/* 交错动画 */
-.stagger-enter-active {
-  transition: all 0.6s ease-out;
-}
-
-.stagger-enter-from {
-  opacity: 0;
-  transform: translateY(20px);
-}
-
-.stagger-move {
-  transition: transform 0.4s ease;
-}
-</style>

+ 0 - 1
src/vite-env.d.ts

@@ -1 +0,0 @@
-/// <reference types="vite/client" />

+ 0 - 109
tailwind.config.js

@@ -1,109 +0,0 @@
-/** @type {import('tailwindcss').Config} */
-export default {
-  content: [
-    "./index.html",
-    "./src/**/*.{vue,js,ts,jsx,tsx}",
-  ],
-  theme: {
-    extend: {
-      fontFamily: {
-        sans: ['Inter', 'system-ui', 'sans-serif'],
-      },
-      colors: {
-        primary: {
-          50: '#eff6ff',
-          100: '#dbeafe',
-          500: '#3b82f6',
-          600: '#2563eb',
-          700: '#1d4ed8',
-        },
-        secondary: {
-          50: '#f5f3ff',
-          100: '#ede9fe',
-          500: '#8b5cf6',
-          600: '#7c3aed',
-          700: '#6d28d9',
-        },
-        success: {
-          50: '#ecfdf5',
-          100: '#d1fae5',
-          500: '#10b981',
-          600: '#059669',
-          700: '#047857',
-        },
-        warning: {
-          50: '#fffbeb',
-          100: '#fef3c7',
-          500: '#f59e0b',
-          600: '#d97706',
-          700: '#b45309',
-        },
-        error: {
-          50: '#fef2f2',
-          100: '#fee2e2',
-          500: '#ef4444',
-          600: '#dc2626',
-          700: '#b91c1c',
-        }
-      },
-      spacing: {
-        '18': '4.5rem',
-        '88': '22rem',
-      },
-      backdropBlur: {
-        xs: '2px',
-      },
-      animation: {
-        'fade-in-up': 'fade-in-up 0.6s ease-out',
-        'scale-in': 'scale-in 0.3s ease-out',
-        'number-roll': 'number-roll 0.8s ease-out',
-        'shimmer': 'shimmer 2s infinite linear',
-      },
-      keyframes: {
-        'fade-in-up': {
-          '0%': {
-            opacity: '0',
-            transform: 'translateY(20px)',
-          },
-          '100%': {
-            opacity: '1',
-            transform: 'translateY(0)',
-          },
-        },
-        'scale-in': {
-          '0%': {
-            opacity: '0',
-            transform: 'scale(0.9)',
-          },
-          '100%': {
-            opacity: '1',
-            transform: 'scale(1)',
-          },
-        },
-        'number-roll': {
-          '0%': {
-            transform: 'translateY(-100%)',
-            opacity: '0',
-          },
-          '50%': {
-            transform: 'translateY(-50%)',
-            opacity: '0.5',
-          },
-          '100%': {
-            transform: 'translateY(0)',
-            opacity: '1',
-          },
-        },
-        'shimmer': {
-          '0%': {
-            transform: 'translateX(-100%)',
-          },
-          '100%': {
-            transform: 'translateX(100%)',
-          },
-        },
-      },
-    },
-  },
-  plugins: [],
-}

+ 0 - 24
tsconfig.app.json

@@ -1,24 +0,0 @@
-{
-  "compilerOptions": {
-    "target": "ES2020",
-    "useDefineForClassFields": true,
-    "module": "ESNext",
-    "lib": ["ES2020", "DOM", "DOM.Iterable"],
-    "skipLibCheck": true,
-
-    /* Bundler mode */
-    "moduleResolution": "bundler",
-    "allowImportingTsExtensions": true,
-    "isolatedModules": true,
-    "moduleDetection": "force",
-    "noEmit": true,
-    "jsx": "preserve",
-
-    /* Linting */
-    "strict": true,
-    "noUnusedLocals": true,
-    "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true
-  },
-  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
-}

+ 0 - 7
tsconfig.json

@@ -1,7 +0,0 @@
-{
-  "files": [],
-  "references": [
-    { "path": "./tsconfig.app.json" },
-    { "path": "./tsconfig.node.json" }
-  ]
-}

+ 0 - 22
tsconfig.node.json

@@ -1,22 +0,0 @@
-{
-  "compilerOptions": {
-    "target": "ES2022",
-    "lib": ["ES2023"],
-    "module": "ESNext",
-    "skipLibCheck": true,
-
-    /* Bundler mode */
-    "moduleResolution": "bundler",
-    "allowImportingTsExtensions": true,
-    "isolatedModules": true,
-    "moduleDetection": "force",
-    "noEmit": true,
-
-    /* Linting */
-    "strict": true,
-    "noUnusedLocals": true,
-    "noUnusedParameters": true,
-    "noFallthroughCasesInSwitch": true
-  },
-  "include": ["vite.config.ts"]
-}

+ 0 - 29
vite.config.ts

@@ -1,29 +0,0 @@
-import { defineConfig } from 'vite'
-import vue from '@vitejs/plugin-vue'
-
-// https://vitejs.dev/config/
-export default defineConfig({
-  plugins: [vue()],
-  define: {
-    global: 'globalThis',
-    'process.env': '{}',
-    'process.env.NODE_ENV': '"development"',
-    'process.env.PARSE_DISABLE_LIVEQUERY': '"true"',
-  },
-  optimizeDeps: {
-    include: ['parse', 'events'],
-    exclude: ['parse/lib/browser/ParseLiveQuery'],
-  },
-  resolve: {
-    alias: {
-      events: 'events',
-      util: 'util',
-      stream: 'stream-browserify',
-    },
-  },
-  build: {
-    rollupOptions: {
-      external: [],
-    },
-  },
-})