From 7827a1fdc45c54e125f8263d5b2b17f0be2301f4 Mon Sep 17 00:00:00 2001
From: zrlibs <jesting_rr@163.com>
Date: 星期五, 07 三月 2025 10:54:53 +0800
Subject: [PATCH] commit

---
 src/views/account/logout.vue               |   19 
 vite.config.js                             |   18 
 src/views/test-view-1-1/index.vue          |   24 
 src/components/TheWelcome.vue              |   94 +
 src/libs/util.js                           |   72 
 src/components/icons/IconEcosystem.vue     |    7 
 public/skin/green.css                      |   38 
 src/components/icons/IconTooling.vue       |   19 
 package.json                               |   24 
 src/layout/menu.json                       |   87 +
 public/web.config.js                       |    2 
 src/index.less                             |   38 
 package-lock.json                          | 2970 ++++++++++++++++++++++++++++++++++
 README.md                                  |    8 
 src/views/test-view-3-3/index.vue          |   17 
 public/skin/light.css                      |   38 
 src/components/icons/IconDocumentation.vue |    7 
 src/api/test.js                            |   14 
 .gitignore                                 |  206 --
 public/favicon.ico                         |    0 
 src/locale/lang/en-US.js                   |    5 
 src/router/routes.js                       |   83 
 src/views/test-view-3-1/index.vue          |   17 
 index.html                                 |   14 
 src/libs/http.js                           |   90 +
 src/views/test-view-4/index.vue            |   17 
 src/main.js                                |   21 
 public/skin/dark.css                       |   38 
 src/views/test-view-2-1/index.vue          |   17 
 src/views/account/login.vue                |  107 +
 src/components/HelloWorld.vue              |   47 
 documents/使用说明.md                          |   88 +
 src/views/test-view-1-2/index.vue          |   17 
 src/layout/index.vue                       |  221 ++
 src/components/icons/IconCommunity.vue     |    7 
 src/views/test-view-2-2/index.vue          |   17 
 public/skin/red.css                        |   38 
 src/layout/locale.vue                      |   79 
 src/router/index.js                        |   30 
 public/skin/purple.css                     |   38 
 documents/项目结构说明.md                        |   25 
 src/views/test-view-1-3/index.vue          |   17 
 src/layout/skin.vue                        |  169 +
 src/views/test-view-3-2/index.vue          |   17 
 src/components/icons/IconSupport.vue       |    7 
 src/App.vue                                |    6 
 src/locale/lang/zh-CN.js                   |    5 
 src/components/WelcomeItem.vue             |   87 +
 src/views/test-view-2-3/index.vue          |   17 
 .vscode/extensions.json                    |    3 
 jsconfig.json                              |    8 
 public/skin/blue.css                       |   38 
 src/locale/index.js                        |   25 
 53 files changed, 4,934 insertions(+), 183 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1c38a68..8ee54e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,186 +1,30 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.sln.docstates
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-build/
-bld/
-[Bb]in/
-[Oo]bj/
-
-# Roslyn cache directories
-*.ide/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-#NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
+# Logs
+logs
 *.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
 
-# Chutzpah Test files
-_Chutzpah*
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
 
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-*.cachefile
+/cypress/videos/
+/cypress/screenshots/
 
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
 
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding addin-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-## TODO: Comment the next line if you want to checkin your
-## web deploy settings but do note that will include unencrypted
-## passwords
-*.pubxml
-
-# NuGet Packages
-packages/*
-*.nupkg
-## TODO: If the tool you use requires repositories.config
-## uncomment the next line
-#!packages/repositories.config
-
-# Enable "build/" folder in the NuGet Packages folder since
-# NuGet packages use it for MSBuild targets.
-# This line needs to be after the ignore of the build folder
-# (and the packages folder if the line above has been uncommented)
-!packages/build/
-
-# Windows Azure Build Output
-csx/
-*.build.csdef
-
-# Windows Store app package directory
-AppPackages/
-
-# Others
-sql/
-*.Cache
-ClientBin/
-[Ss]tyle[Cc]op.*
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-node_modules/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
+*.tsbuildinfo
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..a7cea0b
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+  "recommendations": ["Vue.volar"]
+}
diff --git a/README.md b/README.md
index e9114dd..07233cf 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
-## VUE_Template
+# 瀹夎渚濊禆鍖�+npm install
 
+# 璋冭瘯杩愯
+npm run dev
 
-
+# 缂栬瘧
+npm run build
\ No newline at end of file
diff --git "a/documents/\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/documents/\344\275\277\347\224\250\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..5695d3b
--- /dev/null
+++ "b/documents/\344\275\277\347\224\250\350\257\264\346\230\216.md"
@@ -0,0 +1,88 @@
+### 閰嶇疆鑿滃崟
+- 閰嶇疆鏂规硶锛氭墦寮�rc/layout/menu.json鏂囦欢锛屾寜椤圭洰闇�眰閰嶇疆鑿滃崟椤�+- 閰嶇疆璇存槑锛�+``` json
+[
+    {
+        // 浜岀骇鑿滃崟鐨勯厤缃悓涓�骇鑿滃崟
+        "id": "鍞竴鏍囪瘑",
+        "name": "缁戝畾璺敱鍚嶇О",
+        "title": "鏄剧ず鍦ㄨ彍鍗曢」涓殑鏍囬",
+        "isFolder": false,
+        "icon": "鍥炬爣"
+    },
+    {
+        "id": "鍞竴鏍囪瘑",
+        "title": "鏄剧ず鍦ㄨ彍鍗曢」涓殑鏍囬",
+        "isFolder": true, 鏄惁鏄枃浠跺す
+        "icon": "鍥炬爣",
+        "children": [
+            {
+                // 浜岀骇鑿滃崟鐨勯厤缃悓涓�骇鑿滃崟
+                "id": "鍞竴鏍囪瘑",
+                "name": "缁戝畾璺敱鍚嶇О",
+                "title": "鏄剧ず鍦ㄨ彍鍗曢」涓殑鏍囬",
+                "icon": "鍥炬爣"
+            }...
+        ]
+    },
+    ... 
+]
+
+### 閰嶇疆璺敱
+- 閰嶇疆鏂规硶锛氭墦寮�rc/router/routes.js鏂囦欢锛屾寜椤圭洰闇�眰閰嶇疆璺敱
+- 閰嶇疆璇存槑锛�+``` json
+[
+    {
+        path: '/login',         // url鍖归厤/login
+        name: 'login',          // 璺敱鍚嶇О锛屽嵆璺敱鏍囪瘑
+        meta: { title: '鐧诲綍椤甸潰' },    // 闄勫姞鍏冩暟鎹紝闈炲繀濉�+        component: () => import('@/views/account/login.vue') // 缁戝畾鍔ㄦ�缁勪欢锛屼竴鑸槸缁戝畾@/views涓殑瑙嗗浘椤甸潰
+    },
+    {
+        path: '/',              // 璺敱鎸夎嚜涓婂埌涓嬬殑椤哄簭鐩磋嚦鍖归厤鍒皃ath涓鸿嚦锛屾澶勮矾鐢卞畾涔夊湪/login涔嬩笅锛屽洜姝ゅ尮閰嶇殑鏄櫎/login澶栦互/寮�ご鐨勫叾瀹僽rl
+        component: () => import('@/layout/index.vue'),
+        meta: { authorize: false, title: 'vue-project' }, // 闄勫姞鍏冩暟鎹產uthorize琛ㄧず姝よ矾鐢辨槸鍚﹂渶瑕佽繘琛岀櫥褰曢獙璇�+        children: [     // 浜岀骇瀛愯矾鐢�+            {
+                path: 'test-view-1-1',
+                name: 'test-view-1-1',
+                component: () => import('@/views/test-view-1-1/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰1-1' }
+            },
+            ...
+        ]
+    }
+]
+- path鏀寔鍔ㄦ�鍖归厤銆佹鍒欏尮閰嶇瓑锛屽 /location/:id銆�location/:id(\\d+)锛岃缁嗗唴瀹瑰弬鑰僾ue-router瀹樻柟鏂囨。
+- 鐧诲綍楠岃瘉鐨勫疄鐜版柟娉曞湪src/libs/util.js涓殑checkLogin()锛宻rc/router/index.js涓殑authorize
+
+
+### 鏂板鍔熻兘鐐�+- 閰嶇疆鏂规硶锛氭柊澧炲姛鑳界偣瑕侀厤缃笁閮ㄥ垎鍐呭
+1. src/views/涓嬫柊寤洪〉闈㈠锛歱age1.vue鎴杙age1/index.vue
+2. 閰嶇疆璺敱锛屽皢璺敱鍔ㄦ�缁戝畾姝ら〉闈細濡倇path:'/page1',name:'page1',component: () => import('@/views/page1/index.vue')}
+3. 閰嶇疆鑿滃崟锛屽皢鑿滃崟閫氳繃璺敱鏍囪瘑缁戝畾璺敱锛屽锛�name": "page1",
+- 娉ㄦ剰浜嬮」锛氫互涓婁笁鑰呯殑缁戝畾鍏崇郴鏄矾鐢辩粦瀹氶〉闈�閫氳繃component灞炴�)锛岃彍鍗曠粦瀹氳矾鐢�閫氳繃name灞炴�)
+
+
+### 浠g爜瑙勮寖
+- 鍛藉悕瑙勮寖锛屾病鏈夊己鍒剁殑鍛藉悕瑙勮寖锛屽師鍒欎笂鍦ㄥ崟鏂囦欢鍐呬腑锛屽睘鎬с�鏂规硶銆乤pi绛変娇鐢ㄥ皬椹煎嘲鍛藉悕锛岀被銆佺粍浠朵娇鐢ㄥぇ椹煎嘲銆丳ascal鍛藉悕锛屽叏灞�父閲忎娇鐢ㄥ叏澶у啓鍔犱笅鍒掔嚎鍛藉悕锛宎pi浣跨敤RESTful瑙勮寖
+- 浠g爜鏂囦欢瀛樻斁鏂瑰紡锛宻rc/views涓彧瀛樻斁椤甸潰鎴栦笌椤甸潰鎵�粦瀹氱殑缁勪欢锛宻rc/components瀛樻斁鑷畾涔夊叕鍏辩粍浠躲�浜屾灏佽缁勪欢锛屽湪瀹為檯寮�彂涓紝閫氬父寤鸿鎶婁竴涓〉闈㈠垎闅旀垚鑻ュ共涓姛鑳界嫭绔嬨�閫昏緫鍏宠仈鐨勫皬缁勪欢锛岀劧鍚庤繘琛屾嫾瑁咃紝鏂逛究鍚庢湡缁存姢銆佸鐢ㄥ拰杩佺Щ銆�+
+
+### http璇锋眰
+- fetch锛屾绀轰緥椤圭洰涓娇鐢╢etch杩涜api璇锋眰锛宖etch鏄痚s6鐗规�涓殑涓�锛岄�甯稿彲婊¤冻澶ч儴鍒嗕娇鐢ㄥ満鏅�+- 鎺ュ彛杩斿洖鍊硷紝src/libs/http鏄痟ttp璇锋眰宸ュ叿绫伙紝缁熶竴澶勭悊鎺ュ彛杩斿洖鐨勯敊璇爜锛岀ず渚嬮」鐩腑浠ユ帴鍙h繑鍥瀧err_code:0, err_msg:'',result:{}}涓轰緥锛屽疄闄呴」鐩腑锛岃渚濇嵁鏈嶅姟绔殑瑙勮寖杩涜璋冩暣
+
+
+### 鎹㈣偆
+- 瀹炵幇鏂规硶锛屽姩鎬佸垱寤�link />鏍囩鍐欏叆鍒�head />涓紝姝ょず渚嬮」鐩腑宸插疄鐜�+- 鑷畾涔夌毊鑲わ紝瀛樻斁鍦╬ublic/skin涓紝姣忎釜鐨偆鍗曠嫭涓�釜鏂囦欢
+- 閮ㄧ讲娉ㄦ剰浜嬮」锛寃eb.config.js涓殑skinRoot瀹氫箟浜嗛儴缃叉椂鐨勭毊鑲ゆ枃浠惰矾寰�+
+### 澶氳瑷�+- 瀹炵幇鏂规硶锛寁ue-i18n搴擄紝姝ょず渚嬮」鐩腑宸查泦鎴�+- 鑷畾涔夋枃鏈紝鍦╯rc/locale/lang/涓厤缃�+- 浣跨敤鏂规硶锛岀粍浠跺凡鍏ㄥ眬娉ㄥ唽锛屽湪绋嬪簭涓娇鐢�t('鏍囪瘑')鍗冲彲缁戝畾vue-i18n锛屽叿浣撳弬鑰僺rc/views/test-view-1-1/index.vue
\ No newline at end of file
diff --git "a/documents/\351\241\271\347\233\256\347\273\223\346\236\204\350\257\264\346\230\216.md" "b/documents/\351\241\271\347\233\256\347\273\223\346\236\204\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..cd573b2
--- /dev/null
+++ "b/documents/\351\241\271\347\233\256\347\273\223\346\236\204\350\257\264\346\230\216.md"
@@ -0,0 +1,25 @@
+|- .vscode              -- 缂栬緫鍣ㄧ敓鎴愮殑鏂囦欢澶�+|- documents            -- 浣跨敤鏂囨。
+|- node_modules         -- 椤圭洰鐢ㄥ埌鐨勬墍鏈塶pm鍖咃紝鐢眓pm宸ュ叿绠$悊锛宯pm install鏃惰嚜鍔ㄧ敓鎴�+|- public               -- 姝ゆ枃浠跺す涓殑鍐呭涓嶄細琚紪璇戯紝鍥犳鍙互鐢ㄦ潵瀛樻斁闈欐�鏂囦欢
+    |- skin             -- 鐨偆鏂囦欢
+    |- favicon.ico      -- 娴忚鍣ㄦ爣绛鹃〉涓婃樉绀虹殑缃戠珯logo
+    |- web.config.js    -- 缃戠珯閰嶇疆鏂囦欢
+|- src                  -- 婧愪唬鐮�+    |- api              -- api鎺ュ彛灏佽锛屽彲鎸夐渶姹傚垎閰嶄笉鍚岀殑鏂囦欢澶瑰0鏄庯紝鍏蜂綋鐪嬮」鐩渶姹�+    |- assets           -- 缃戠珯璧勬簮鏂囦欢锛屽鍥剧墖銆佸浘鏍囥�瀛椾綋绛�+    |- components       -- 瀛樻斁鑷畾涔夌粍浠躲�鍏叡缁勪欢
+    |- layout           -- 缃戠珯甯冨眬妯℃澘
+        |- menu.json    -- 閰嶇疆鑿滃崟椤�+    |- libs             -- 宸ュ叿鍑芥暟銆侀�鐢ㄧ被
+    |- locale           -- 澶氳瑷�厤缃�+    |- router           -- 璺敱閰嶇疆
+    |- views            -- 鎵�湁璺敱椤甸潰
+    |- App.vue          -- 鍞竴涓婚〉闈�+    |- index.less       -- 涓绘牱寮忚〃
+    |- main.js          -- 涓诲嚱鏁�+|- .gitignore           -- 閰嶇疆git蹇界暐鍒楄〃
+|- index.html           -- 鍞竴鍏ュ彛椤甸潰
+|- package.json         -- npm鍖呯殑閰嶇疆鏂囦欢锛屽寘鍚玭pm鍖呮弿杩般�npm鑴氭湰銆乬it淇℃伅銆佷緷璧栧垪琛ㄧ瓑
+|- README.md            -- 椤圭洰鑷堪鏂囦欢
+|- vite.config.js       -- vite閰嶇疆
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f5b2834
--- /dev/null
+++ b/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="UTF-8">
+    <link rel="icon" href="/favicon.ico">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Vite App</title>
+    <script src="/web.config.js"></script>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..5a1f2d2
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,8 @@
+{
+  "compilerOptions": {
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  },
+  "exclude": ["node_modules", "dist"]
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..3f4ddbd
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2970 @@
+{
+  "name": "vue-project",
+  "version": "0.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "vue-project",
+      "version": "0.0.0",
+      "dependencies": {
+        "js-base64": "^3.7.7",
+        "view-ui-plus": "^1.3.19",
+        "vue": "^3.5.13",
+        "vue-i18n": "^11.1.1",
+        "vue-router": "^4.5.0"
+      },
+      "devDependencies": {
+        "@vitejs/plugin-vue": "^5.2.1",
+        "less": "^4.2.2",
+        "vite": "^6.1.0",
+        "vite-plugin-vue-devtools": "^7.7.2"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz",
+      "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@antfu/utils": {
+      "version": "0.7.10",
+      "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
+      "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.26.2",
+      "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.26.2.tgz",
+      "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.25.9",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.26.8",
+      "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.26.8.tgz",
+      "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.26.9.tgz",
+      "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==",
+      "dev": true,
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.26.2",
+        "@babel/generator": "^7.26.9",
+        "@babel/helper-compilation-targets": "^7.26.5",
+        "@babel/helper-module-transforms": "^7.26.0",
+        "@babel/helpers": "^7.26.9",
+        "@babel/parser": "^7.26.9",
+        "@babel/template": "^7.26.9",
+        "@babel/traverse": "^7.26.9",
+        "@babel/types": "^7.26.9",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.26.9.tgz",
+      "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.26.9",
+        "@babel/types": "^7.26.9",
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jsesc": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-annotate-as-pure": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+      "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.26.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz",
+      "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/compat-data": "^7.26.5",
+        "@babel/helper-validator-option": "^7.25.9",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-create-class-features-plugin": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz",
+      "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.25.9",
+        "@babel/helper-member-expression-to-functions": "^7.25.9",
+        "@babel/helper-optimise-call-expression": "^7.25.9",
+        "@babel/helper-replace-supers": "^7.26.5",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+        "@babel/traverse": "^7.26.9",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-member-expression-to-functions": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
+      "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/traverse": "^7.25.9",
+        "@babel/types": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+      "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/traverse": "^7.25.9",
+        "@babel/types": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.26.0",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+      "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.25.9",
+        "@babel/helper-validator-identifier": "^7.25.9",
+        "@babel/traverse": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-optimise-call-expression": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
+      "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.26.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
+      "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-replace-supers": {
+      "version": "7.26.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz",
+      "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-member-expression-to-functions": "^7.25.9",
+        "@babel/helper-optimise-call-expression": "^7.25.9",
+        "@babel/traverse": "^7.26.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
+      "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/traverse": "^7.25.9",
+        "@babel/types": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+      "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+      "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+      "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.26.9.tgz",
+      "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.26.9",
+        "@babel/types": "^7.26.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.26.9.tgz",
+      "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==",
+      "dependencies": {
+        "@babel/types": "^7.26.9"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-decorators": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz",
+      "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-create-class-features-plugin": "^7.25.9",
+        "@babel/helper-plugin-utils": "^7.25.9",
+        "@babel/plugin-syntax-decorators": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-decorators": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz",
+      "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-attributes": {
+      "version": "7.26.0",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz",
+      "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-meta": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-jsx": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+      "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-typescript": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+      "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-typescript": {
+      "version": "7.26.8",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz",
+      "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.25.9",
+        "@babel/helper-create-class-features-plugin": "^7.25.9",
+        "@babel/helper-plugin-utils": "^7.26.5",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+        "@babel/plugin-syntax-typescript": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.26.9.tgz",
+      "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.26.2",
+        "@babel/parser": "^7.26.9",
+        "@babel/types": "^7.26.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.26.9.tgz",
+      "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.26.2",
+        "@babel/generator": "^7.26.9",
+        "@babel/parser": "^7.26.9",
+        "@babel/template": "^7.26.9",
+        "@babel/types": "^7.26.9",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.26.9",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.26.9.tgz",
+      "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.25.9",
+        "@babel/helper-validator-identifier": "^7.25.9"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
+      "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz",
+      "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz",
+      "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz",
+      "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
+      "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz",
+      "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz",
+      "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz",
+      "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz",
+      "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz",
+      "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz",
+      "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz",
+      "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz",
+      "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz",
+      "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz",
+      "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz",
+      "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz",
+      "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz",
+      "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz",
+      "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz",
+      "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz",
+      "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz",
+      "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz",
+      "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz",
+      "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz",
+      "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@intlify/core-base": {
+      "version": "11.1.1",
+      "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.1.1.tgz",
+      "integrity": "sha512-bb8gZvoeKExCI2r/NVCK9E4YyOkvYGaSCPxVZe8T0jz8aX+dHEOZWxK06Z/Y9mWRkJfBiCH4aOhDF1yr1t5J8Q==",
+      "dependencies": {
+        "@intlify/message-compiler": "11.1.1",
+        "@intlify/shared": "11.1.1"
+      },
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      }
+    },
+    "node_modules/@intlify/message-compiler": {
+      "version": "11.1.1",
+      "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.1.1.tgz",
+      "integrity": "sha512-4iEsUZ3aF7jXY19CJFN5VP+pPyLITD9FVsjB13z9TU1UxaZLlFsmNhvRxlPDSOfHAP5RpNF2QKKdZ3DHVf4Yzw==",
+      "dependencies": {
+        "@intlify/shared": "11.1.1",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      }
+    },
+    "node_modules/@intlify/shared": {
+      "version": "11.1.1",
+      "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.1.1.tgz",
+      "integrity": "sha512-2kGiWoXaeV8HZlhU/Nml12oTbhv7j2ufsJ5vQaa0VTjzUmZVdd/nmKFRAOJ/FtjO90Qba5AnZDwsrY7ZND5udA==",
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.8",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+      "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@polka/url": {
+      "version": "1.0.0-next.28",
+      "resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.28.tgz",
+      "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
+      "dev": true
+    },
+    "node_modules/@rollup/pluginutils": {
+      "version": "5.1.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
+      "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "^1.0.0",
+        "estree-walker": "^2.0.2",
+        "picomatch": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+      },
+      "peerDependenciesMeta": {
+        "rollup": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
+      "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz",
+      "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz",
+      "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz",
+      "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz",
+      "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz",
+      "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz",
+      "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz",
+      "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz",
+      "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz",
+      "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz",
+      "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz",
+      "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz",
+      "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz",
+      "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz",
+      "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz",
+      "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz",
+      "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz",
+      "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz",
+      "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@sec-ant/readable-stream": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
+      "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
+      "dev": true
+    },
+    "node_modules/@sindresorhus/merge-streams": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
+      "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz",
+      "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+      "dev": true
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz",
+      "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==",
+      "dev": true,
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^5.0.0 || ^6.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@vue/babel-helper-vue-transform-on": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.2.5.tgz",
+      "integrity": "sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==",
+      "dev": true
+    },
+    "node_modules/@vue/babel-plugin-jsx": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.2.5.tgz",
+      "integrity": "sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.24.7",
+        "@babel/helper-plugin-utils": "^7.24.8",
+        "@babel/plugin-syntax-jsx": "^7.24.7",
+        "@babel/template": "^7.25.0",
+        "@babel/traverse": "^7.25.6",
+        "@babel/types": "^7.25.6",
+        "@vue/babel-helper-vue-transform-on": "1.2.5",
+        "@vue/babel-plugin-resolve-type": "1.2.5",
+        "html-tags": "^3.3.1",
+        "svg-tags": "^1.0.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      },
+      "peerDependenciesMeta": {
+        "@babel/core": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/babel-plugin-resolve-type": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.2.5.tgz",
+      "integrity": "sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.24.7",
+        "@babel/helper-module-imports": "^7.24.7",
+        "@babel/helper-plugin-utils": "^7.24.8",
+        "@babel/parser": "^7.25.6",
+        "@vue/compiler-sfc": "^3.5.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
+      "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
+      "dependencies": {
+        "@babel/parser": "^7.25.3",
+        "@vue/shared": "3.5.13",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
+      "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.13",
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
+      "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
+      "dependencies": {
+        "@babel/parser": "^7.25.3",
+        "@vue/compiler-core": "3.5.13",
+        "@vue/compiler-dom": "3.5.13",
+        "@vue/compiler-ssr": "3.5.13",
+        "@vue/shared": "3.5.13",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.11",
+        "postcss": "^8.4.48",
+        "source-map-js": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
+      "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.13",
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.4",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
+    },
+    "node_modules/@vue/devtools-core": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-core/-/devtools-core-7.7.2.tgz",
+      "integrity": "sha512-lexREWj1lKi91Tblr38ntSsy6CvI8ba7u+jmwh2yruib/ltLUcsIzEjCnrkh1yYGGIKXbAuYV2tOG10fGDB9OQ==",
+      "dev": true,
+      "dependencies": {
+        "@vue/devtools-kit": "^7.7.2",
+        "@vue/devtools-shared": "^7.7.2",
+        "mitt": "^3.0.1",
+        "nanoid": "^5.0.9",
+        "pathe": "^2.0.2",
+        "vite-hot-client": "^0.2.4"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/@vue/devtools-core/node_modules/nanoid": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.2.tgz",
+      "integrity": "sha512-b+CiXQCNMUGe0Ri64S9SXFcP9hogjAJ2Rd6GdVxhPLRm7mhGaM7VgOvCAJ1ZshfHbqVDI3uqTI5C8/GaKuLI7g==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.js"
+      },
+      "engines": {
+        "node": "^18 || >=20"
+      }
+    },
+    "node_modules/@vue/devtools-kit": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
+      "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
+      "dev": true,
+      "dependencies": {
+        "@vue/devtools-shared": "^7.7.2",
+        "birpc": "^0.2.19",
+        "hookable": "^5.5.3",
+        "mitt": "^3.0.1",
+        "perfect-debounce": "^1.0.0",
+        "speakingurl": "^14.0.1",
+        "superjson": "^2.2.1"
+      }
+    },
+    "node_modules/@vue/devtools-shared": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
+      "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
+      "dev": true,
+      "dependencies": {
+        "rfdc": "^1.4.1"
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
+      "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
+      "dependencies": {
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
+      "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
+      "dependencies": {
+        "@vue/reactivity": "3.5.13",
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
+      "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
+      "dependencies": {
+        "@vue/reactivity": "3.5.13",
+        "@vue/runtime-core": "3.5.13",
+        "@vue/shared": "3.5.13",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
+      "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.13",
+        "@vue/shared": "3.5.13"
+      },
+      "peerDependencies": {
+        "vue": "3.5.13"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz",
+      "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="
+    },
+    "node_modules/async-validator": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-3.5.2.tgz",
+      "integrity": "sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ=="
+    },
+    "node_modules/batch-processor": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/batch-processor/-/batch-processor-1.0.0.tgz",
+      "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA=="
+    },
+    "node_modules/birpc": {
+      "version": "0.2.19",
+      "resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz",
+      "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.24.4",
+      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.24.4.tgz",
+      "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
+      "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"
+        }
+      ],
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001688",
+        "electron-to-chromium": "^1.5.73",
+        "node-releases": "^2.0.19",
+        "update-browserslist-db": "^1.1.1"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/bundle-name": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz",
+      "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
+      "dev": true,
+      "dependencies": {
+        "run-applescript": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001701",
+      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001701.tgz",
+      "integrity": "sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw==",
+      "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"
+        }
+      ]
+    },
+    "node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "dev": true
+    },
+    "node_modules/copy-anything": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
+      "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+      "dev": true,
+      "dependencies": {
+        "is-what": "^4.1.8"
+      },
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/countup.js": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmmirror.com/countup.js/-/countup.js-1.9.3.tgz",
+      "integrity": "sha512-UHf2P/mFKaESqdPq+UdBJm/1y8lYdlcDd0nTZHNC8cxWoJwZr1Eldm1PpWui446vDl5Pd8PtRYkr3q6K4+Qa5A=="
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+    },
+    "node_modules/debug": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.0.tgz",
+      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deepmerge": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-2.2.1.tgz",
+      "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/default-browser": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.2.1.tgz",
+      "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
+      "dev": true,
+      "dependencies": {
+        "bundle-name": "^4.1.0",
+        "default-browser-id": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/default-browser-id": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-5.0.0.tgz",
+      "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/define-lazy-prop": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+      "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.109",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.109.tgz",
+      "integrity": "sha512-AidaH9JETVRr9DIPGfp1kAarm/W6hRJTPuCnkF+2MqhF4KaAgRIcBc8nvjk+YMXZhwfISof/7WG29eS4iGxQLQ==",
+      "dev": true
+    },
+    "node_modules/element-resize-detector": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmmirror.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz",
+      "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==",
+      "dependencies": {
+        "batch-processor": "1.0.0"
+      }
+    },
+    "node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/errno": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz",
+      "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "prr": "~1.0.1"
+      },
+      "bin": {
+        "errno": "cli.js"
+      }
+    },
+    "node_modules/error-stack-parser-es": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmmirror.com/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz",
+      "integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.25.0",
+      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.0.tgz",
+      "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.25.0",
+        "@esbuild/android-arm": "0.25.0",
+        "@esbuild/android-arm64": "0.25.0",
+        "@esbuild/android-x64": "0.25.0",
+        "@esbuild/darwin-arm64": "0.25.0",
+        "@esbuild/darwin-x64": "0.25.0",
+        "@esbuild/freebsd-arm64": "0.25.0",
+        "@esbuild/freebsd-x64": "0.25.0",
+        "@esbuild/linux-arm": "0.25.0",
+        "@esbuild/linux-arm64": "0.25.0",
+        "@esbuild/linux-ia32": "0.25.0",
+        "@esbuild/linux-loong64": "0.25.0",
+        "@esbuild/linux-mips64el": "0.25.0",
+        "@esbuild/linux-ppc64": "0.25.0",
+        "@esbuild/linux-riscv64": "0.25.0",
+        "@esbuild/linux-s390x": "0.25.0",
+        "@esbuild/linux-x64": "0.25.0",
+        "@esbuild/netbsd-arm64": "0.25.0",
+        "@esbuild/netbsd-x64": "0.25.0",
+        "@esbuild/openbsd-arm64": "0.25.0",
+        "@esbuild/openbsd-x64": "0.25.0",
+        "@esbuild/sunos-x64": "0.25.0",
+        "@esbuild/win32-arm64": "0.25.0",
+        "@esbuild/win32-ia32": "0.25.0",
+        "@esbuild/win32-x64": "0.25.0"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "node_modules/execa": {
+      "version": "9.5.2",
+      "resolved": "https://registry.npmmirror.com/execa/-/execa-9.5.2.tgz",
+      "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==",
+      "dev": true,
+      "dependencies": {
+        "@sindresorhus/merge-streams": "^4.0.0",
+        "cross-spawn": "^7.0.3",
+        "figures": "^6.1.0",
+        "get-stream": "^9.0.0",
+        "human-signals": "^8.0.0",
+        "is-plain-obj": "^4.1.0",
+        "is-stream": "^4.0.1",
+        "npm-run-path": "^6.0.0",
+        "pretty-ms": "^9.0.0",
+        "signal-exit": "^4.1.0",
+        "strip-final-newline": "^4.0.0",
+        "yoctocolors": "^2.0.0"
+      },
+      "engines": {
+        "node": "^18.19.0 || >=20.5.0"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
+    "node_modules/figures": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/figures/-/figures-6.1.0.tgz",
+      "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
+      "dev": true,
+      "dependencies": {
+        "is-unicode-supported": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/fs-extra": {
+      "version": "11.3.0",
+      "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.0.tgz",
+      "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=14.14"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-stream": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-9.0.1.tgz",
+      "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
+      "dev": true,
+      "dependencies": {
+        "@sec-ant/readable-stream": "^0.4.1",
+        "is-stream": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "dev": true
+    },
+    "node_modules/hookable": {
+      "version": "5.5.3",
+      "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
+      "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+      "dev": true
+    },
+    "node_modules/html-tags": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/html-tags/-/html-tags-3.3.1.tgz",
+      "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/human-signals": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-8.0.0.tgz",
+      "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==",
+      "dev": true,
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
+      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/image-size": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz",
+      "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
+      "dev": true,
+      "optional": true,
+      "bin": {
+        "image-size": "bin/image-size.js"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-docker": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz",
+      "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+      "dev": true,
+      "bin": {
+        "is-docker": "cli.js"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-inside-container": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz",
+      "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+      "dev": true,
+      "dependencies": {
+        "is-docker": "^3.0.0"
+      },
+      "bin": {
+        "is-inside-container": "cli.js"
+      },
+      "engines": {
+        "node": ">=14.16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-plain-obj": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+      "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-stream": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-4.0.1.tgz",
+      "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-unicode-supported": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
+      "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-what": {
+      "version": "4.1.16",
+      "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
+      "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/is-wsl": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.0.tgz",
+      "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
+      "dev": true,
+      "dependencies": {
+        "is-inside-container": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
+    "node_modules/js-base64": {
+      "version": "3.7.7",
+      "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.7.tgz",
+      "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw=="
+    },
+    "node_modules/js-calendar": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmmirror.com/js-calendar/-/js-calendar-1.2.3.tgz",
+      "integrity": "sha512-dAA1/Zbp4+c5E+ARCVTIuKepXsNLzSYfzvOimiYD4S5eeP9QuplSHLcdhfqFSwyM1o1u6ku6RRRCyaZ0YAjiBw=="
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "node_modules/jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "dev": true,
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true,
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonfile": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "dev": true,
+      "dependencies": {
+        "universalify": "^2.0.0"
+      },
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/kolorist": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz",
+      "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
+      "dev": true
+    },
+    "node_modules/less": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmmirror.com/less/-/less-4.2.2.tgz",
+      "integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==",
+      "dev": true,
+      "dependencies": {
+        "copy-anything": "^2.0.1",
+        "parse-node-version": "^1.0.1",
+        "tslib": "^2.3.0"
+      },
+      "bin": {
+        "lessc": "bin/lessc"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "optionalDependencies": {
+        "errno": "^0.1.1",
+        "graceful-fs": "^4.1.2",
+        "image-size": "~0.5.0",
+        "make-dir": "^2.1.0",
+        "mime": "^1.4.1",
+        "needle": "^3.1.0",
+        "source-map": "~0.6.0"
+      }
+    },
+    "node_modules/less/node_modules/copy-anything": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz",
+      "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
+      "dev": true,
+      "dependencies": {
+        "is-what": "^3.14.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/less/node_modules/is-what": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz",
+      "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
+      "dev": true
+    },
+    "node_modules/lodash.chunk": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
+      "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
+    },
+    "node_modules/lodash.throttle": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+      "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.17",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
+      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/make-dir/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "optional": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "optional": true,
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mitt": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
+      "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+      "dev": true
+    },
+    "node_modules/mrmime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.1.tgz",
+      "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.8",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.8.tgz",
+      "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/needle": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/needle/-/needle-3.3.1.tgz",
+      "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "iconv-lite": "^0.6.3",
+        "sax": "^1.2.4"
+      },
+      "bin": {
+        "needle": "bin/needle"
+      },
+      "engines": {
+        "node": ">= 4.4.x"
+      }
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.19",
+      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.19.tgz",
+      "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+      "dev": true
+    },
+    "node_modules/npm-run-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-6.0.0.tgz",
+      "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^4.0.0",
+        "unicorn-magic": "^0.3.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/npm-run-path/node_modules/path-key": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz",
+      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/numeral": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/numeral/-/numeral-2.0.6.tgz",
+      "integrity": "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA==",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/open": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmmirror.com/open/-/open-10.1.0.tgz",
+      "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
+      "dev": true,
+      "dependencies": {
+        "default-browser": "^5.2.1",
+        "define-lazy-prop": "^3.0.0",
+        "is-inside-container": "^1.0.0",
+        "is-wsl": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parse-ms": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz",
+      "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parse-node-version": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
+      "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pathe": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz",
+      "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+      "dev": true
+    },
+    "node_modules/perfect-debounce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+      "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+      "dev": true
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+    },
+    "node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/popper.js": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmmirror.com/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
+      "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/popperjs"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.3",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.3.tgz",
+      "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+      "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"
+        }
+      ],
+      "dependencies": {
+        "nanoid": "^3.3.8",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/pretty-ms": {
+      "version": "9.2.0",
+      "resolved": "https://registry.npmmirror.com/pretty-ms/-/pretty-ms-9.2.0.tgz",
+      "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==",
+      "dev": true,
+      "dependencies": {
+        "parse-ms": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
+      "dev": true,
+      "optional": true
+    },
+    "node_modules/rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+      "dev": true
+    },
+    "node_modules/rollup": {
+      "version": "4.34.8",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.34.8.tgz",
+      "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "1.0.6"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.34.8",
+        "@rollup/rollup-android-arm64": "4.34.8",
+        "@rollup/rollup-darwin-arm64": "4.34.8",
+        "@rollup/rollup-darwin-x64": "4.34.8",
+        "@rollup/rollup-freebsd-arm64": "4.34.8",
+        "@rollup/rollup-freebsd-x64": "4.34.8",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.34.8",
+        "@rollup/rollup-linux-arm-musleabihf": "4.34.8",
+        "@rollup/rollup-linux-arm64-gnu": "4.34.8",
+        "@rollup/rollup-linux-arm64-musl": "4.34.8",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.34.8",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8",
+        "@rollup/rollup-linux-riscv64-gnu": "4.34.8",
+        "@rollup/rollup-linux-s390x-gnu": "4.34.8",
+        "@rollup/rollup-linux-x64-gnu": "4.34.8",
+        "@rollup/rollup-linux-x64-musl": "4.34.8",
+        "@rollup/rollup-win32-arm64-msvc": "4.34.8",
+        "@rollup/rollup-win32-ia32-msvc": "4.34.8",
+        "@rollup/rollup-win32-x64-msvc": "4.34.8",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/run-applescript": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/run-applescript/-/run-applescript-7.0.0.tgz",
+      "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true,
+      "optional": true
+    },
+    "node_modules/sax": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.1.tgz",
+      "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+      "dev": true,
+      "optional": true
+    },
+    "node_modules/select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
+    "node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/sirv": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/sirv/-/sirv-3.0.1.tgz",
+      "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==",
+      "dev": true,
+      "dependencies": {
+        "@polka/url": "^1.0.0-next.24",
+        "mrmime": "^2.0.0",
+        "totalist": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/speakingurl": {
+      "version": "14.0.1",
+      "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
+      "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/strip-final-newline": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
+      "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/superjson": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
+      "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+      "dev": true,
+      "dependencies": {
+        "copy-anything": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/svg-tags": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz",
+      "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
+      "dev": true
+    },
+    "node_modules/tinycolor2": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz",
+      "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
+    },
+    "node_modules/totalist": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/totalist/-/totalist-3.0.1.tgz",
+      "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+      "dev": true
+    },
+    "node_modules/unicorn-magic": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
+      "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
+      "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/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"
+        }
+      ],
+      "dependencies": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/v-click-outside-x": {
+      "version": "3.7.1",
+      "resolved": "https://registry.npmmirror.com/v-click-outside-x/-/v-click-outside-x-3.7.1.tgz",
+      "integrity": "sha512-WmUgmcIXr9clVpm1AYS/FgHtcDicfnfoxgQCNg4O6vfk9GVnxA0vSqO321ogUo0b7czYTidj7fQENvWFMWOkUg==",
+      "engines": {
+        "node": ">=8.11.4",
+        "npm": "6.4.1"
+      }
+    },
+    "node_modules/view-ui-plus": {
+      "version": "1.3.19",
+      "resolved": "https://registry.npmmirror.com/view-ui-plus/-/view-ui-plus-1.3.19.tgz",
+      "integrity": "sha512-CBIuO/9+mbTTQnCWs2GOY+jyQiJLlc5EdxdvuyEGIiKV0YxQW/rLXUQabmm1w9n0iNTXV6adtqXYo2xzdr1NIA==",
+      "dependencies": {
+        "async-validator": "^3.3.0",
+        "countup.js": "^1.9.3",
+        "dayjs": "^1.11.0",
+        "deepmerge": "^2.2.1",
+        "element-resize-detector": "^1.2.0",
+        "js-calendar": "^1.2.3",
+        "lodash.chunk": "^4.2.0",
+        "lodash.throttle": "^4.1.1",
+        "numeral": "^2.0.6",
+        "popper.js": "^1.14.6",
+        "select": "^1.1.2",
+        "tinycolor2": "^1.4.1",
+        "v-click-outside-x": "^3.7.1"
+      }
+    },
+    "node_modules/vite": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmmirror.com/vite/-/vite-6.2.0.tgz",
+      "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "^0.25.0",
+        "postcss": "^8.5.3",
+        "rollup": "^4.30.1"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || ^20.0.0 || >=22.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 || >=22.0.0",
+        "jiti": ">=1.21.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "sass-embedded": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.16.0",
+        "tsx": "^4.8.1",
+        "yaml": "^2.4.2"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "jiti": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        },
+        "tsx": {
+          "optional": true
+        },
+        "yaml": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vite-hot-client": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmmirror.com/vite-hot-client/-/vite-hot-client-0.2.4.tgz",
+      "integrity": "sha512-a1nzURqO7DDmnXqabFOliz908FRmIppkBKsJthS8rbe8hBEXwEwe4C3Pp33Z1JoFCYfVL4kTOMLKk0ZZxREIeA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0"
+      }
+    },
+    "node_modules/vite-plugin-inspect": {
+      "version": "0.8.9",
+      "resolved": "https://registry.npmmirror.com/vite-plugin-inspect/-/vite-plugin-inspect-0.8.9.tgz",
+      "integrity": "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A==",
+      "dev": true,
+      "dependencies": {
+        "@antfu/utils": "^0.7.10",
+        "@rollup/pluginutils": "^5.1.3",
+        "debug": "^4.3.7",
+        "error-stack-parser-es": "^0.1.5",
+        "fs-extra": "^11.2.0",
+        "open": "^10.1.0",
+        "perfect-debounce": "^1.0.0",
+        "picocolors": "^1.1.1",
+        "sirv": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1"
+      },
+      "peerDependenciesMeta": {
+        "@nuxt/kit": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vite-plugin-vue-devtools": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.7.2.tgz",
+      "integrity": "sha512-5V0UijQWiSBj32blkyPEqIbzc6HO9c1bwnBhx+ay2dzU0FakH+qMdNUT8nF9BvDE+i6I1U8CqCuJiO20vKEdQw==",
+      "dev": true,
+      "dependencies": {
+        "@vue/devtools-core": "^7.7.2",
+        "@vue/devtools-kit": "^7.7.2",
+        "@vue/devtools-shared": "^7.7.2",
+        "execa": "^9.5.1",
+        "sirv": "^3.0.0",
+        "vite-plugin-inspect": "0.8.9",
+        "vite-plugin-vue-inspector": "^5.3.1"
+      },
+      "engines": {
+        "node": ">=v14.21.3"
+      },
+      "peerDependencies": {
+        "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0"
+      }
+    },
+    "node_modules/vite-plugin-vue-inspector": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmmirror.com/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.1.tgz",
+      "integrity": "sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.23.0",
+        "@babel/plugin-proposal-decorators": "^7.23.0",
+        "@babel/plugin-syntax-import-attributes": "^7.22.5",
+        "@babel/plugin-syntax-import-meta": "^7.10.4",
+        "@babel/plugin-transform-typescript": "^7.22.15",
+        "@vue/babel-plugin-jsx": "^1.1.5",
+        "@vue/compiler-dom": "^3.3.4",
+        "kolorist": "^1.8.0",
+        "magic-string": "^0.30.4"
+      },
+      "peerDependencies": {
+        "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0"
+      }
+    },
+    "node_modules/vue": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz",
+      "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.13",
+        "@vue/compiler-sfc": "3.5.13",
+        "@vue/runtime-dom": "3.5.13",
+        "@vue/server-renderer": "3.5.13",
+        "@vue/shared": "3.5.13"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-i18n": {
+      "version": "11.1.1",
+      "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.1.1.tgz",
+      "integrity": "sha512-0P6DkKy96R4Wh2sIZJEHw8ivnlD1pnB6Ib/eldoF1SUpQutfKZv6aMqZwICS1gW0rwq24ZSXw7y3jW+PRVYqWA==",
+      "dependencies": {
+        "@intlify/core-base": "11.1.1",
+        "@intlify/shared": "11.1.1",
+        "@vue/devtools-api": "^6.5.0"
+      },
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.0.tgz",
+      "integrity": "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
+    "node_modules/yoctocolors": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/yoctocolors/-/yoctocolors-2.1.1.tgz",
+      "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..55ff826
--- /dev/null
+++ b/package.json
@@ -0,0 +1,24 @@
+{
+  "name": "vue-project",
+  "version": "0.0.0",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "js-base64": "^3.7.7",
+    "view-ui-plus": "^1.3.19",
+    "vue": "^3.5.13",
+    "vue-i18n": "^11.1.1",
+    "vue-router": "^4.5.0"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^5.2.1",
+    "less": "^4.2.2",
+    "vite": "^6.1.0",
+    "vite-plugin-vue-devtools": "^7.7.2"
+  }
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..df36fcf
--- /dev/null
+++ b/public/favicon.ico
Binary files differ
diff --git a/public/skin/blue.css b/public/skin/blue.css
new file mode 100644
index 0000000..a552ccd
--- /dev/null
+++ b/public/skin/blue.css
@@ -0,0 +1,38 @@
+:root {
+    --first-background-color: #138ec7;
+    --second-background-color: #189edd;
+    --third-background-color: #dff3f9;
+}
+
+.layout-header,
+.ivu-layout-header {
+    background-color: var(--first-background-color) !important;
+}
+
+.side-area {
+    background-color: var(--second-background-color) !important;
+}
+
+.ivu-menu-light {
+    background-color: var(--third-background-color) !important;
+}
+
+.ivu-btn-primary {
+    background-color: var(--first-background-color);
+    border-color: var(--second-background-color);
+}
+
+.ivu-btn-primary:hover {
+    background-color: var(--second-background-color);
+    border-color: var(--third-background-color);
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu) {
+    color: var(--first-background-color);
+    background: #fff;
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    width: 5px;
+    background-color: var(--first-background-color)
+}
\ No newline at end of file
diff --git a/public/skin/dark.css b/public/skin/dark.css
new file mode 100644
index 0000000..b2b6569
--- /dev/null
+++ b/public/skin/dark.css
@@ -0,0 +1,38 @@
+:root {
+    --first-background-color: #404040;
+    --second-background-color: #7f7f7f;
+    --third-background-color: #e3e3e3;
+}
+
+.layout-header,
+.ivu-layout-header {
+    background-color: var(--first-background-color) !important;
+}
+
+.side-area {
+    background-color: var(--second-background-color) !important;
+}
+
+.ivu-menu-light {
+    background-color: var(--third-background-color) !important;
+}
+
+.ivu-btn-primary {
+    background-color: var(--first-background-color);
+    border-color: var(--second-background-color);
+}
+
+.ivu-btn-primary:hover {
+    background-color: var(--second-background-color);
+    border-color: var(--third-background-color);
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu) {
+    color: var(--first-background-color);
+    background: #fff;
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    width: 5px;
+    background-color: var(--first-background-color)
+}
\ No newline at end of file
diff --git a/public/skin/green.css b/public/skin/green.css
new file mode 100644
index 0000000..7eedefd
--- /dev/null
+++ b/public/skin/green.css
@@ -0,0 +1,38 @@
+:root {
+    --first-background-color: #3fa329;
+    --second-background-color: #61d149;
+    --third-background-color: #d5fce1;
+}
+
+.layout-header,
+.ivu-layout-header {
+    background-color: var(--first-background-color) !important;
+}
+
+.side-area {
+    background-color: var(--second-background-color) !important;
+}
+
+.ivu-menu-light {
+    background-color: var(--third-background-color) !important;
+}
+
+.ivu-btn-primary {
+    background-color: var(--first-background-color);
+    border-color: var(--second-background-color);
+}
+
+.ivu-btn-primary:hover {
+    background-color: var(--second-background-color);
+    border-color: var(--third-background-color);
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu) {
+    color: var(--first-background-color);
+    background: #fff;
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    width: 5px;
+    background-color: var(--first-background-color)
+}
\ No newline at end of file
diff --git a/public/skin/light.css b/public/skin/light.css
new file mode 100644
index 0000000..8a609a0
--- /dev/null
+++ b/public/skin/light.css
@@ -0,0 +1,38 @@
+:root {
+    --first-background-color: #2db7f5;
+    --second-background-color: #40c3ff;
+    --third-background-color: #cceeff;
+}
+
+.layout-header,
+.ivu-layout-header {
+    background-color: var(--first-background-color) !important;
+}
+
+.side-area {
+    background-color: var(--second-background-color) !important;
+}
+
+.ivu-menu-light {
+    background-color: var(--third-background-color) !important;
+}
+
+.ivu-btn-primary {
+    background-color: var(--first-background-color);
+    border-color: var(--second-background-color);
+}
+
+.ivu-btn-primary:hover {
+    background-color: var(--second-background-color);
+    border-color: var(--third-background-color);
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu) {
+    color: var(--first-background-color);
+    background: #fff;
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    width: 5px;
+    background-color: var(--first-background-color)
+}
\ No newline at end of file
diff --git a/public/skin/purple.css b/public/skin/purple.css
new file mode 100644
index 0000000..1d862d3
--- /dev/null
+++ b/public/skin/purple.css
@@ -0,0 +1,38 @@
+:root {
+    --first-background-color: #415aca;
+    --second-background-color: #7a85f8;
+    --third-background-color: #b8c0fd;
+}
+
+.layout-header,
+.ivu-layout-header {
+    background-color: var(--first-background-color) !important;
+}
+
+.side-area {
+    background-color: var(--second-background-color) !important;
+}
+
+.ivu-menu-light {
+    background-color: var(--third-background-color) !important;
+}
+
+.ivu-btn-primary {
+    background-color: var(--first-background-color);
+    border-color: var(--second-background-color);
+}
+
+.ivu-btn-primary:hover {
+    background-color: var(--second-background-color);
+    border-color: var(--third-background-color);
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu) {
+    color: var(--first-background-color);
+    background: #fff;
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    width: 5px;
+    background-color: var(--first-background-color)
+}
\ No newline at end of file
diff --git a/public/skin/red.css b/public/skin/red.css
new file mode 100644
index 0000000..eea57c0
--- /dev/null
+++ b/public/skin/red.css
@@ -0,0 +1,38 @@
+:root {
+    --first-background-color: #cb1b59;
+    --second-background-color: #ec719c;
+    --third-background-color: #ffe6ee;
+}
+
+.layout-header,
+.ivu-layout-header {
+    background-color: var(--first-background-color) !important;
+}
+
+.side-area {
+    background-color: var(--second-background-color) !important;
+}
+
+.ivu-menu-light {
+    background-color: var(--third-background-color) !important;
+}
+
+.ivu-btn-primary {
+    background-color: var(--first-background-color);
+    border-color: var(--second-background-color);
+}
+
+.ivu-btn-primary:hover {
+    background-color: var(--second-background-color);
+    border-color: var(--third-background-color);
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu) {
+    color: var(--first-background-color);
+    background: #fff;
+}
+
+.ivu-menu-light.ivu-menu-vertical .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    width: 5px;
+    background-color: var(--first-background-color);
+}
\ No newline at end of file
diff --git a/public/web.config.js b/public/web.config.js
new file mode 100644
index 0000000..28664ca
--- /dev/null
+++ b/public/web.config.js
@@ -0,0 +1,2 @@
+window.apiRoot = 'http://115.29.185.26:5101'
+window.skinRoot = '/skin'
\ No newline at end of file
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..ec8e742
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,6 @@
+<template>
+  <router-view />
+</template>
+
+<style lang="less">
+</style>
\ No newline at end of file
diff --git a/src/api/test.js b/src/api/test.js
new file mode 100644
index 0000000..b1f3e20
--- /dev/null
+++ b/src/api/test.js
@@ -0,0 +1,14 @@
+import HttpRequest from '@/libs/http'
+const httpRequest = new HttpRequest(window.apiRoot)
+
+/**
+ * 鐧诲綍
+ * @param {*} param0 
+ * @returns 
+ */
+export const login = ({ user_login,user_psw }) => {
+    return httpRequest.post('api/user/ace/verifypassword', {
+        user_login,
+        user_psw
+    })
+}
\ No newline at end of file
diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue
new file mode 100644
index 0000000..b4c796b
--- /dev/null
+++ b/src/components/HelloWorld.vue
@@ -0,0 +1,47 @@
+<script setup>
+defineProps({
+  msg: {
+    type: String,
+    required: true,
+  },
+});
+</script>
+
+<template>
+  <div class="greetings">
+    <h1 class="green">{{ msg }}</h1>
+    <h3>
+      You鈥檝e successfully created a project with
+      <a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
+      <a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
+    </h3>
+  </div>
+</template>
+
+<style scoped>
+.greetings {
+  margin-bottom: 11px;
+}
+h1 {
+  font-weight: 500;
+  font-size: 2.6rem;
+  position: relative;
+  top: -10px;
+}
+
+h3 {
+  font-size: 1.2rem;
+}
+
+.greetings h1,
+.greetings h3 {
+  text-align: center;
+}
+
+@media (min-width: 1024px) {
+  .greetings h1,
+  .greetings h3 {
+    text-align: left;
+  }
+}
+</style>
diff --git a/src/components/TheWelcome.vue b/src/components/TheWelcome.vue
new file mode 100644
index 0000000..f3ad467
--- /dev/null
+++ b/src/components/TheWelcome.vue
@@ -0,0 +1,94 @@
+<script setup>
+import WelcomeItem from './WelcomeItem.vue'
+import DocumentationIcon from './icons/IconDocumentation.vue'
+import ToolingIcon from './icons/IconTooling.vue'
+import EcosystemIcon from './icons/IconEcosystem.vue'
+import CommunityIcon from './icons/IconCommunity.vue'
+import SupportIcon from './icons/IconSupport.vue'
+
+const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
+</script>
+
+<template>
+  <WelcomeItem>
+    <template #icon>
+      <DocumentationIcon />
+    </template>
+    <template #heading>Documentation</template>
+
+    Vue鈥檚
+    <a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
+    provides you with all information you need to get started.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <ToolingIcon />
+    </template>
+    <template #heading>Tooling</template>
+
+    This project is served and bundled with
+    <a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
+    recommended IDE setup is
+    <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
+    +
+    <a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
+    you need to test your components and web pages, check out
+    <a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
+    and
+    <a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
+    /
+    <a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
+
+    <br />
+
+    More instructions are available in
+    <a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
+    >.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <EcosystemIcon />
+    </template>
+    <template #heading>Ecosystem</template>
+
+    Get official tools and libraries for your project:
+    <a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
+    <a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
+    <a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
+    <a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
+    you need more resources, we suggest paying
+    <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
+    a visit.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <CommunityIcon />
+    </template>
+    <template #heading>Community</template>
+
+    Got stuck? Ask your question on
+    <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
+    (our official Discord server), or
+    <a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
+      >StackOverflow</a
+    >. You should also follow the official
+    <a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
+    Bluesky account or the
+    <a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
+    X account for latest news in the Vue world.
+  </WelcomeItem>
+
+  <WelcomeItem>
+    <template #icon>
+      <SupportIcon />
+    </template>
+    <template #heading>Support Vue</template>
+
+    As an independent project, Vue relies on community backing for its sustainability. You can help
+    us by
+    <a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
+  </WelcomeItem>
+</template>
diff --git a/src/components/WelcomeItem.vue b/src/components/WelcomeItem.vue
new file mode 100644
index 0000000..adf229f
--- /dev/null
+++ b/src/components/WelcomeItem.vue
@@ -0,0 +1,87 @@
+<template>
+  <div class="item">
+    <i>
+      <slot name="icon"></slot>
+    </i>
+    <div class="details">
+      <h3>
+        <slot name="heading"></slot>
+      </h3>
+      <slot></slot>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.item {
+  margin-top: 2rem;
+  display: flex;
+  position: relative;
+}
+
+.details {
+  flex: 1;
+  margin-left: 1rem;
+  padding-left: 30px;
+}
+
+i {
+  display: flex;
+  place-items: center;
+  place-content: center;
+  width: 32px;
+  height: 32px;
+  color: var(--color-text);
+}
+
+h3 {
+  font-size: 1.2rem;
+  font-weight: 500;
+  margin-bottom: 0.4rem;
+  margin-left: 26px;
+  color: var(--color-heading);
+}
+
+@media (min-width: 1024px) {
+  .item {
+    margin-top: 0;
+    padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
+  }
+
+  i {
+    top: calc(50% - 25px);
+    position: absolute;
+    border: 1px solid var(--color-border);
+    background: var(--color-background);
+    border-radius: 8px;
+    width: 50px;
+    height: 50px;
+  }
+
+  .item:before {
+    content: " ";
+    border-left: 1px solid var(--color-border);
+    position: absolute;
+    left: 0;
+    bottom: calc(50% + 25px);
+    height: calc(50% - 25px);
+  }
+
+  .item:after {
+    content: " ";
+    border-left: 1px solid var(--color-border);
+    position: absolute;
+    left: 0;
+    top: calc(50% + 25px);
+    height: calc(50% - 25px);
+  }
+
+  .item:first-of-type:before {
+    display: none;
+  }
+
+  .item:last-of-type:after {
+    display: none;
+  }
+}
+</style>
diff --git a/src/components/icons/IconCommunity.vue b/src/components/icons/IconCommunity.vue
new file mode 100644
index 0000000..2dc8b05
--- /dev/null
+++ b/src/components/icons/IconCommunity.vue
@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
+    <path
+      d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
+    />
+  </svg>
+</template>
diff --git a/src/components/icons/IconDocumentation.vue b/src/components/icons/IconDocumentation.vue
new file mode 100644
index 0000000..6d4791c
--- /dev/null
+++ b/src/components/icons/IconDocumentation.vue
@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
+    <path
+      d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
+    />
+  </svg>
+</template>
diff --git a/src/components/icons/IconEcosystem.vue b/src/components/icons/IconEcosystem.vue
new file mode 100644
index 0000000..c3a4f07
--- /dev/null
+++ b/src/components/icons/IconEcosystem.vue
@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
+    <path
+      d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
+    />
+  </svg>
+</template>
diff --git a/src/components/icons/IconSupport.vue b/src/components/icons/IconSupport.vue
new file mode 100644
index 0000000..7452834
--- /dev/null
+++ b/src/components/icons/IconSupport.vue
@@ -0,0 +1,7 @@
+<template>
+  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
+    <path
+      d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
+    />
+  </svg>
+</template>
diff --git a/src/components/icons/IconTooling.vue b/src/components/icons/IconTooling.vue
new file mode 100644
index 0000000..660598d
--- /dev/null
+++ b/src/components/icons/IconTooling.vue
@@ -0,0 +1,19 @@
+<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
+<template>
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    aria-hidden="true"
+    role="img"
+    class="iconify iconify--mdi"
+    width="24"
+    height="24"
+    preserveAspectRatio="xMidYMid meet"
+    viewBox="0 0 24 24"
+  >
+    <path
+      d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
+      fill="currentColor"
+    ></path>
+  </svg>
+</template>
diff --git a/src/index.less b/src/index.less
new file mode 100644
index 0000000..88864ea
--- /dev/null
+++ b/src/index.less
@@ -0,0 +1,38 @@
+html,
+body,
+#app {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+}
+
+/* 婊氬姩鏉�*/
+*::-webkit-scrollbar {
+    width: 8px;
+    height: 8px;
+}
+
+*::-webkit-scrollbar-thumb {
+    height: 8px;
+    background-color: rgba(0, 0, 0, 0.30);
+}
+
+*::-webkit-scrollbar-thumb:hover {
+    background-color: rgba(0, 0, 0, 0.6);
+}
+
+* {
+    scrollbar-width: thin;
+    -moz-scrollbar-width: thin;
+}
+
+.view {
+    width: 100%;
+    height: 100%;
+    padding: 9px;
+
+    &>div {
+        background-color: #fff;
+        padding: 11px;
+    }
+}
\ No newline at end of file
diff --git a/src/layout/index.vue b/src/layout/index.vue
new file mode 100644
index 0000000..3079db6
--- /dev/null
+++ b/src/layout/index.vue
@@ -0,0 +1,221 @@
+<template>
+  <div class="vue-project-layout">
+    <div class="layout">
+      <div class="layout-header">
+        <div class="logo">
+          <img :src="logo" />
+        </div>
+        <div class="user-dropdown">
+          <Dropdown trigger="click" @on-click="onClick">
+            <a href="javascript:void(0)">
+              <Avatar icon="ios-person" :src="avatar" size="large" />
+              <span class="username">{{ userName }}</span>
+              <Icon type="md-arrow-dropdown" size="18"></Icon>
+            </a>
+            <template #list>
+              <DropdownMenu>
+                <DropdownItem name="profile">涓汉涓績</DropdownItem>
+                <DropdownItem name="logout">閫�嚭鐧诲綍</DropdownItem>
+              </DropdownMenu>
+            </template>
+          </Dropdown>
+        </div>
+        <Skin></Skin>
+        <Locale></Locale>
+      </div>
+      <div class="layout-body">
+        <div class="menu-list">
+          <Menu
+            :active-name="activeName"
+            :open-names="openNames"
+            accordion
+            @on-select="onMenuClick"
+            ref="refMenu"
+          >
+            <template v-for="list in menuList" :key="list.id">
+              <Submenu v-if="list.isFolder" :name="list.id">
+                <template #title>
+                  <Icon :custom="list.icon" />
+                  {{ list.title }}
+                </template>
+                <MenuItem
+                  v-for="app in list.children"
+                  :key="app.id"
+                  :name="app.id"
+                >
+                  <Icon :custom="app.icon" />
+                  {{ app.title }}</MenuItem
+                >
+              </Submenu>
+              <MenuItem v-else :name="list.id">
+                <Icon :custom="list.icon" />
+                {{ list.title }}
+              </MenuItem>
+            </template>
+          </Menu>
+        </div>
+        <div class="view">
+          <RouterView v-slot="{ Component }">
+            <template v-if="Component">
+              <KeepAlive>
+                <component :is="Component" :key="$route.fullPath" />
+              </KeepAlive>
+            </template>
+          </RouterView>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { ref } from "vue";
+import Skin from "./skin.vue";
+import Locale from "./locale.vue";
+import menuList from "./menu.json";
+import { showError } from "@/libs/util";
+export default {
+  name: "Layout",
+  components: {
+    Skin,
+    Locale,
+  },
+  data() {
+    return {
+      menuList,
+      activeName: "",
+      openNames: [],
+      logo: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI4AAAAcCAYAAAC3U4dAAAAAAXNSR0IArs4c6QAACSpJREFUaEPtmwesZVUVhr+FvfeusccSS+wVsStRrCD2blARKwI2REWxgQUL2Im9YCG2OIJiCPaWKFEpIorKKCAWFMss8032nuw5c8495829c53gXcnLZO7b+5y91/r3v/619n3BnJaZJwPXm/GYo4GHR8Q5Q2Myc3/gucDlBsasB14eEYfNudzV9AV5IOZ9zgTg/AzYB/h8RGT3fZl5aeCTwL2AC6yAM29EljN/GcD5l6AB9gVOjQj/T2b67ksBewDPB646Y8srxlkOHia/ZRnAcTF/B74KvBM4EdgAXBZ4KPAU4GojK14BZ3JIlzNwWcCpu/kL8CvgXODawJWAHSZsdRJwMvP6wFU6Ke+kiPjdDH118bKWKzZjfg2cXtmxJ72aUm9Y1l9/7eE4LSLWZ+ZFgesC9Zn/BE4CzupL1z3Pv0SZXzWfLH1yRPyhbx+Zec3C3u0eHOq8s4G/AX+NiD9N8PWkIcsGzqRF9QyaCpwXAnsDV26ecXBE+NkWlpmC9k7Aq4GdmgHvAV4VEacNzBOcH2/mqN2+D7w4ItZlpsXC64Bdy3yD90bgfcAZs8CTmQL5fsBLgNuU+WcCe0aE79xkmXl14GbAI4AbA3fprPfPZV2nAr8AjvLfiPj31gaizju/Aec6wLuBuwMXLJsUdDtFhCJ9M8vMywPPBl4EXLjDOILtqIj4RydYgm134CPN5wLDNPzKiDivBzgOdczBgKBcP1AoCBqLBPVgC4ItgJOZMtozgWcBMtwUe0upTgcr3CkPccz5CjhuKDP31DmdNPJB4KkRYcrYaIVtDI5McPseh30BeE5E2G5oT7lgU+zLVJp67TvAXhHxvfLsLuPU+YLnTcBh3bSTmRcD7t0DGuf2AeegAppL1i0BPwG+1SzXw2DRYcpTFnymgHsFnG7AM/NawBHAjg3rSNk7R8TxDXBMN88rPy3b1CHqsWcAR7ask5mPBQRiCwb7SwdUYA4wTh2vzngzcGhEnFWAdhHgvoX5KiDbrW0GnMwULF8rqawefvXMrhFhOqqHo2otiw/98kfg6C6L9hya0Y+2NeMoGH8DKE4VdgZQYewp1VmW41cop0KBZ6XVJ5YnaZzGYU8HXtM0FH3fx4Anl1RiGjMlmF6k/CEzOD7rRFNLZnpyrQ5v3bDNDwub/ah5/xDjtOB5G3AIIEDvIRMAdxxYSBc4+uwbwE2b8eqWxwHHKNBHIz/ngG0BHIN0CvDjIszUFm7EzeskwaSY9JRbPRgMxaxCTzF4W+Dmnby9VuB4wj4A3LNhHYG7W0Qcm5nS936mosZ/vyw6xMrsMuVzU5sd7SMi4tzMfFIRuHWalP/2wjYb+1OFQcaA4zDnCtzjylruOiOWXeDouyOLiL5QfW3xu4DS96ZPAS/LLNwWDRyV+1eALwMGwoafDDPJMvMagIETPA8oAlFmWhNwSvAeWASsrKYZWJ1t+pFt1BrSd/2dQNPpis07NAtWtzyxrEG2uUUTKDXFoyPCfzfZQKqyDXF6YasqZgWPh+xWzXTH+JmptlqfxtmtiG2Zuo2jB9fxP9f/wA+Add01TgrIjEGLAo79gy8B7yrlnumpdaSnQlHpOE9LvXoQVPZL7DO042Uiy8udS9AM/pruqkpZ+yHgwU36c10vBXbx/qx55U+LoBYYAmev0g+qoHqtPRjgDQ2DyZ5vLWyzWXk7ABwBaDoynTwEqEzRbv33gJWPrKwOmgUcr2rcm2v1oPXF8j9FIri/TwOfWlQaWwRwjgE+B3wxIuwKW7HYIPMkeHJNO7KI6cPKwd9V4OhwA+JpNKVJscfXPkMpl2/nqQa+udZLzsy0N7OuCZKs47usMGo6ErwC3lL67My8CfCOUtLXwP0WMAj1dLt+97pLRMiym9kM4FjGq6/UX3bNWz1nShGY7y+M+NFZwCl+1p/qHAW1fnr8AEnIQurMQ4HDF9EIXARw1CV2Z88p9093LifKUlewGCAZpK9ycZ9uyhPmCbbiUGR+vZyOMzNTR5tSNkSEQZ9smWmas9/ysBmTFLc27kyvgl4msD/ixay6q8/s7djgs0kooCYDJyJOKcASJHVdFg2mTist9/xIYBQ49aWlylIr3qAASAYylXXNtLWfTcrJThwYuAjg7BARGzLzRkVs3r9USpaMU64Tuks7rwjHE4APK3JlIPsuvmetG85MezTfHphnwCylX9FqscwU8HZ57zNwY29H+W5DQJ7FOAKnAFQ9p0D3ru71pr2mPF8TcBoA1YtjfX/L0mpwD9UU+3tHhMwzl80NnOIET6iNNzu3dj8XYaYxG2Y22w7ZWnFXGEsA2pbvmn0dm3wbG3edADyhaJIqoOuvZZgDTDdDQJ4CnOI32w/+eIcliDfaFMbJTLWYKfO9fX2ZzJTlrQK7IBE4drDnsrmBk5mKOXOrKWnu5/XsxrRg+jKd2FdZs2WmVYs03ZraSqcOpZua5qzO2jSrttkxIs4YWshU4MyYP8o4makOq4fBuzZLbw9Z1ZgyjunUbnQ1U/0+EfGJNTuxM2HuQGemjjS3bktTOB4UETbM1mxFtyg6H9NMPhZ41MjNudWPjTrTSrU9IkIxPWhLAs7hpUJTIMvOsk+byo2t+rCVC96T7T9rz1OduwjgjH11dOpaZo2zLyFwtopii2iXdb5bHGmFcWBEeGpnWjnZ9nEMkEWAX6cYm9PXADQd7l41zgjwpjCOVZmMafPUOAqQrqYUTKZW06Bi228K2F+b2/4vgKOXSs63cnmQpb3fPJzS08hMq0bvvrzb2jciFM1jwPG7Rl602i+qZrp9WkTYlBubLyhaVlPrmWI+252YmRYjgtlri7Zp6FDf5VWLLQ73vDBbJnBEvmV3e1elgLP8HVvHXIyzMG+tHrTJA2MBG3XVhC+r+wzLQBtlflXBuxmp086wp9/mlT2IWWtZAWc0EssdsAzgKNysaA4s3eVNDbPMtHx/QRGtQ38ao0dWwFkuLkbftgzgKES967Er2vfnMTYOrRDsNNdv7XUXvgLOaCiXO2ARwPF6oC1Xuzvw5vhlsxp4mWkH1UpCzdNnXkV4x2I5ubLtwAOLAI73LXaLt2CTsj+/EnFcRCiMe61cV3gZatOtz9RIJ0SEt7wr2w48MDdwtoM9rJbwP/DAfwEGg7pKrm8BNAAAAABJRU5ErkJggg==",
+      avatar: "http://115.29.185.26:5101/userphoto?login=sa",
+      userName: "鐢ㄦ埛鍚�,
+    };
+  },
+  computed: {
+    viewList() {
+      let routes = [];
+      this.menuList.forEach((menu) => {
+        if (menu.isFolder) routes.push(...menu.children);
+        else routes.push(menu);
+      });
+      return routes;
+    },
+  },
+  methods: {
+    onClick(name) {
+      if (name == "logout") {
+        this.$router.push({ name: "logout" });
+      }
+    },
+    onMenuClick(id) {
+      let route = this.viewList.find((r) => r.id == id);
+      if (!route)
+        this.showError(
+          `鏈壘鍒癷d=${id}鎵�搴旂殑璺敱锛岃妫�煡鑿滃崟銆佽矾鐢辩殑閰嶇疆鏄惁姝g‘`
+        );
+
+      this.activeName = route.id;
+      this.menuList.forEach((list) => {
+        if (list.isFolder && list.children.find((l) => l.id == route.id))
+          this.openNames = [list.id];
+        else if (list.id == route.id) this.openNames = [];
+      });
+      this.$nextTick(() => {
+        this.refMenu.updateOpened();
+      });
+
+      this.$router.push({
+        name: route.name,
+        query: {
+          menuId: id,
+        },
+      });
+    },
+    showError(ex) {
+      showError(this, ex);
+    },
+  },
+  mounted() {
+    let firstRoute = this.viewList[0];
+    this.onMenuClick(firstRoute.id);
+  },
+  setup() {
+    let refMenu = ref(null);
+    return { refMenu };
+  },
+};
+</script>
+
+<style lang="less">
+.vue-project-layout {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  .layout {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    overflow: hidden;
+    -webkit-box-orient: vertical;
+    -webkit-box-direction: normal;
+    flex-direction: column;
+    -webkit-box-flex: 1;
+    background: #f5f7f9;
+    .layout-header {
+      width: 100%;
+      padding: 0;
+      height: 64px;
+      line-height: 64px;
+      flex: 0 0 auto;
+      .logo {
+        height: 64px;
+        display: inline-block;
+        width: 240px;
+        padding: 5px 20px;
+        text-align: center;
+        transition: width 0.2sease-out;
+        img {
+          max-width: 200px;
+          max-height: 54px;
+          vertical-align: sub;
+        }
+      }
+      .user-dropdown {
+        float: right;
+        height: 64px;
+        padding-right: 40px;
+        line-height: 64px;
+        .username {
+          display: inline-block;
+          margin-left: 5px;
+          color: #fff;
+        }
+        .ivu-icon {
+          color: #fff;
+        }
+      }
+    }
+    .layout-body {
+      width: 100%;
+      height: calc(100% - 64px);
+      display: flex;
+      flex: auto;
+      .menu-list {
+        flex-shrink: 0;
+        flex-grow: 0;
+        flex-basis: 240px;
+        height: 100%;
+        border-right: 1px solid #dcdee2;
+        overflow-x: hidden;
+        overflow-y: auto;
+        .ivu-menu {
+          height: 100%;
+        }
+
+        .ivu-menu-vertical.ivu-menu-light:after {
+          display: none;
+        }
+      }
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/layout/locale.vue b/src/layout/locale.vue
new file mode 100644
index 0000000..c08d62e
--- /dev/null
+++ b/src/layout/locale.vue
@@ -0,0 +1,79 @@
+<template>
+  <div class="locale-dropdown">
+    <Dropdown trigger="click" @on-click="selectLang">
+      <a href="javascript:;">
+        {{ title }}
+        <Icon :size="18" color="#fff" type="md-arrow-dropdown"></Icon>
+      </a>
+      <template #list>
+        <DropdownMenu>
+          <DropdownItem
+            v-for="(value, key) in localeList"
+            :selected="key == locale"
+            :name="key"
+            :key="key"
+            >{{ value }}</DropdownItem
+          >
+        </DropdownMenu>
+      </template>
+    </Dropdown>
+  </div>
+</template>
+
+<script>
+import { useI18n } from "vue-i18n";
+import { localSave, localRead } from "@/libs/util";
+const localeKey = "locale";
+export default {
+  name: "LayoutLocale",
+  data() {
+    return {
+      lang: "",
+      langList: {
+        "zh-CN": "璇█",
+        "en-US": "Lang",
+      },
+      localeList: {
+        "zh-CN": "涓枃绠�綋",
+        "en-US": "English",
+      },
+    };
+  },
+  computed: {
+    title() {
+      return this.langList[this.lang];
+    },
+  },
+  methods: {
+    selectLang(name) {
+      this.setLocal(name);
+      this.changeLang(name);
+    },
+    setLocal(name) {
+      this.lang = name;
+      localSave(localeKey, name);
+    },
+  },
+  mounted() {
+    this.lang = localRead(localeKey) || "zh-CN";
+    this.selectLang(this.lang);
+  },
+  setup() {
+    const { locale } = useI18n();
+    const changeLang = (name) => {
+      locale.value = name;
+    };
+    return { locale, changeLang };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.locale-dropdown {
+  margin-right: 10px;
+  float: right;
+  a {
+    color: #fff;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/layout/menu.json b/src/layout/menu.json
new file mode 100644
index 0000000..c1baede
--- /dev/null
+++ b/src/layout/menu.json
@@ -0,0 +1,87 @@
+[
+    {
+        "id": "fake-id-1",
+        "title": "娴嬭瘯鏂囦欢澶�",
+        "isFolder": true,
+        "icon": "",
+        "children": [
+            {
+                "id": "fake-id-1-1",
+                "name": "test-view-1-1",
+                "title": "娴嬭瘯椤甸潰1-1",
+                "icon": ""
+            },
+            {
+                "id": "fake-id-1-2",
+                "name": "test-view-1-2",
+                "title": "娴嬭瘯椤甸潰1-2",
+                "icon": ""
+            },
+            {
+                "id": "fake-id-1-3",
+                "name": "test-view-1-3",
+                "title": "娴嬭瘯椤甸潰1-3",
+                "icon": ""
+            }
+        ]
+    },
+    {
+        "id": "fake-id-2",
+        "title": "娴嬭瘯鏂囦欢澶�",
+        "isFolder": true,
+        "icon": "",
+        "children": [
+            {
+                "id": "fake-id-2-1",
+                "name": "test-view-2-1",
+                "title": "娴嬭瘯椤甸潰2-1",
+                "icon": ""
+            },
+            {
+                "id": "fake-id-2-2",
+                "name": "test-view-2-2",
+                "title": "娴嬭瘯椤甸潰2-2",
+                "icon": ""
+            },
+            {
+                "id": "fake-id-2-3",
+                "name": "test-view-2-3",
+                "title": "娴嬭瘯椤甸潰2-3",
+                "icon": ""
+            }
+        ]
+    },
+    {
+        "id": "fake-id-3",
+        "title": "娴嬭瘯鏂囦欢澶�",
+        "isFolder": true,
+        "icon": "",
+        "children": [
+            {
+                "id": "fake-id-3-1",
+                "name": "test-view-3-1",
+                "title": "娴嬭瘯椤甸潰3-1",
+                "icon": ""
+            },
+            {
+                "id": "fake-id-3-2",
+                "name": "test-view-3-2",
+                "title": "娴嬭瘯椤甸潰3-2",
+                "icon": ""
+            },
+            {
+                "id": "fake-id-3-3",
+                "name": "test-view-3-3",
+                "title": "娴嬭瘯椤甸潰3-3",
+                "icon": ""
+            }
+        ]
+    },
+    {
+        "id": "fake-id-4",
+        "name": "test-view-4",
+        "title": "娴嬭瘯椤甸潰4",
+        "isFolder": false,
+        "icon": ""
+    }
+]
\ No newline at end of file
diff --git a/src/layout/skin.vue b/src/layout/skin.vue
new file mode 100644
index 0000000..8aa8776
--- /dev/null
+++ b/src/layout/skin.vue
@@ -0,0 +1,169 @@
+<template>
+  <div class="skin-dropdown">
+    <Poptip v-model="visible" transfer popper-class="skin">
+      <a>
+        <slot>
+          <span class="icon-text">鎹㈣偆</span>
+        </slot>
+        <Icon :size="18" color="#fff" type="md-arrow-dropdown"></Icon>
+      </a>
+      <template #content>
+        <ul class="skin-list">
+          <li v-for="skin in skinList" :key="skin.label">
+            <Tooltip :content="skin.title">
+              <a
+                href="javascript:;"
+                :style="{ 'background-color': skin.color }"
+                :class="{ active: curSkin == skin.label }"
+                @click="onClick(skin)"
+              ></a>
+            </Tooltip>
+          </li>
+        </ul>
+      </template>
+    </Poptip>
+  </div>
+</template>
+
+<script>
+import { localSave, localRead } from "@/libs/util";
+import { showError } from "@/libs/util";
+const skinKey = "skin";
+export default {
+  name: "LayoutSkin",
+  data() {
+    return {
+      visible: false,
+      linkId: "skin",
+      curSkin: "",
+      skinList: [
+        {
+          title: "娴呰壊",
+          label: "light",
+          color: "#2db7f5",
+        },
+        {
+          title: "娣辫壊",
+          label: "dark",
+          color: "#404040",
+        },
+        {
+          title: "绾㈣壊",
+          label: "red",
+          color: "#cb1b59",
+        },
+        {
+          title: "缁胯壊",
+          label: "green",
+          color: "#3fa329",
+        },
+        {
+          title: "绱壊",
+          label: "purple",
+          color: "#415aca",
+        },
+        {
+          title: "钃濊壊",
+          label: "blue",
+          color: "#138ec7",
+        },
+      ],
+    };
+  },
+  methods: {
+    close() {
+      this.visible = false;
+    },
+    async onClick(skin) {
+      if (this.curSkin == skin.label) return this.close();
+
+      this.curSkin = skin.label;
+      localSave(skinKey, skin.label);
+      
+      await this.changeSkin(skin);
+      this.close();
+    },
+    async changeSkin(skin) {
+      var skinLink = this.getSkinLink();
+      var linkUrl = this.getLinkUrl(skin);
+
+      if (!skin.label) {
+        document.head.removeChild(skinLink);
+      }
+
+      try {
+        let res = await (await fetch(linkUrl)).text();
+        skinLink.innerHTML = res || "";
+      } catch (ex) {
+        this.showError(`鍔犺浇鐨偆鏂囦欢${linkUrl}澶辫触`);
+      }
+    },
+    getSkinLink() {
+      let link = document.querySelector("#" + this.linkId);
+      if (!link) {
+        link = document.createElement("style");
+        link.type = "text/css";
+        link.id = this.linkId;
+        document.head.appendChild(link);
+      }
+      return link;
+    },
+    getLinkUrl(skin) {
+      return `${window.skinRoot}/${skin.label}.css`;
+    },
+    loadSkin(skin) {
+      this.curSkin = skin.label;
+      this.changeSkin(skin);
+    },
+    showError(ex) {
+      showError(this, ex);
+    },
+  },
+  mounted() {
+    let skin;
+    const curSkin = localRead(skinKey) || "light";
+    if (curSkin) skin = this.skinList.find((l) => l.label == curSkin);
+    this.loadSkin(skin);
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.skin-dropdown {
+  margin-right: 10px;
+  float: right;
+  a {
+    color: #fff;
+  }
+}
+</style>
+<style lang="less">
+.skin {
+  .ivu-poptip-body-content {
+    overflow: hidden;
+  }
+  .skin-list {
+    list-style: none;
+    width: 144px;
+    &:after {
+      content: "";
+      display: table;
+      clear: both;
+    }
+    li {
+      margin: 2px;
+      width: 20px;
+      height: 20px;
+      float: left;
+      a {
+        width: 20px;
+        height: 20px;
+        display: inline-block;
+        &.active {
+          box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.2);
+        }
+      }
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/libs/http.js b/src/libs/http.js
new file mode 100644
index 0000000..af911e1
--- /dev/null
+++ b/src/libs/http.js
@@ -0,0 +1,90 @@
+/**
+ * 浣跨敤es6-fetch鍙戦�http璇锋眰,涓嶅吋瀹规棫鐗堟祻瑙堝櫒
+ * 鏇挎崲鏂规鍙�axios涔嬬被鐨勫簱
+ */
+
+import { Message } from 'view-ui-plus'
+
+class HttpRequest {
+    constructor(apiRoot){
+        this.apiRoot = apiRoot
+    }
+    get(url) {
+        return new Promise((resolve, reject) => {
+            try {
+                const apiUrl = this.getUrl(url)
+                fetch(apiUrl).then(res => {
+                    if (res.ok)
+                        return res.json()
+                    else {
+                        let err = JSON.stringify({
+                            type: res.type,
+                            status: res.status,
+                            statusText: res.statusText
+                        })
+                        Message.error({
+                            content: `璋冪敤${url}鎺ュ彛澶辫触锛宍 + err,
+                            duration: 10
+                        });
+                        reject(err);
+                    }
+                }).then(res => {
+                    if (res.err_code === 0)
+                        resolve(res.result);
+                    else
+                        reject(`code=${res.err_code},` + res.err_msg);
+                }).catch(err => {
+                    reject(`璋冪敤${url}鎺ュ彛澶辫触锛宍 + err);
+                });
+            }
+            catch (err) {
+                reject(err);
+            }
+        });
+    }
+    post(url, data) {
+        return new Promise((resolve, reject) => {
+            try {
+                const apiUrl = this.getUrl(url)
+                fetch(apiUrl, {
+                    method: 'POST',
+                    body: JSON.stringify(data),
+                    headers: {
+                        'Content-Type': 'application/json',
+                    },
+                }).then(res => {
+                    if (res.ok)
+                        return res.json()
+                    else {
+                        let err = JSON.stringify({
+                            type: res.type,
+                            status: res.status,
+                            statusText: res.statusText
+                        })
+                        Message.error({
+                            content: `璋冪敤${url}鎺ュ彛澶辫触锛宍 + err,
+                            duration: 10
+                        });
+                        reject(err);
+                    }
+                }).then(res => {
+                    if (res.err_code === 0)
+                        resolve(res.result);
+                    else
+                        reject(`code=${res.err_code},` + res.err_msg);
+                    // resolve(res);
+                }).catch(err => {
+                    reject(`璋冪敤${url}鎺ュ彛澶辫触锛宍 + err)
+                })
+            }
+            catch (err) {
+                reject(err);
+            }
+        })
+    }
+    getUrl(url) {
+        return `${this.apiRoot}/${url}`;
+    }
+}
+
+export default HttpRequest;
\ No newline at end of file
diff --git a/src/libs/util.js b/src/libs/util.js
new file mode 100644
index 0000000..6425a7a
--- /dev/null
+++ b/src/libs/util.js
@@ -0,0 +1,72 @@
+const APP_CODE = 'vue-project'
+const TOKEN_KEY = 'token'
+
+/**
+ * localStorage璇诲彇
+ * @param {*} key 
+ * @returns 
+ */
+export const localRead = (key) => {
+    return localStorage.getItem(`${APP_CODE}.${key}`) || ''
+}
+
+/**
+ * localStorage鏈湴瀛樺偍
+ * @param {*} key 
+ * @param {*} value 
+ */
+export const localSave = (key, value) => {
+    localStorage.setItem(`${APP_CODE}.${key}`, value)
+}
+
+/**
+ * 鑾峰彇token
+ * @returns token
+ */
+export const getToken = () => {
+    return localRead(TOKEN_KEY) || '';
+}
+
+/**
+ * 璁剧疆token
+ * @returns token
+ */
+export const setToken = (token) => {
+    return localSave(TOKEN_KEY, token);
+}
+
+/**
+ * 鐧诲綍妫�祴
+ * @returns 
+ */
+export const checkLogin = () => {
+    return !!getToken()
+}
+
+/**
+ * 閿欒鎻愮ず
+ * @param {*} vm 
+ * @param {*} ex 
+ */
+export const showError = (vm, ex) => {
+    let tip = typeof ex == 'string' ? ex : ex.message || ex.err_info
+    vm.$Message.error({
+        content: tip,
+        duration: 0,
+        closable: true
+    })
+    console.log(ex)
+}
+
+/**
+ * 鎴愬姛鎻愰啋
+ * @param {*} vm 
+ * @param {*} ex 
+ */
+export const showSuccess = (vm, tip) => {
+    vm.$Message.success({
+        content: tip,
+        duration: 3,
+        closable: false
+    })
+}
\ No newline at end of file
diff --git a/src/locale/index.js b/src/locale/index.js
new file mode 100644
index 0000000..100e186
--- /dev/null
+++ b/src/locale/index.js
@@ -0,0 +1,25 @@
+import { createI18n } from 'vue-i18n'
+import { localRead } from '@/libs/util'
+
+// view-ui-plus
+import LocalZhCn from 'view-ui-plus/src/locale/lang/zh-CN.js'
+import LocalEnUs from 'view-ui-plus/src/locale/lang/en-US.js'
+// custom
+import customZhCn from './lang/zh-CN'
+import customEnUs from './lang/en-US'
+
+const messages = {
+    'zh-CN': Object.assign(LocalZhCn, customZhCn),
+    'en-US': Object.assign(LocalEnUs, customEnUs),
+}
+
+const LOCAL_KEY = 'local'
+let lang = localRead(LOCAL_KEY) || 'zh-CN'
+
+const i18n = createI18n({
+    legacy: false,
+    locale: lang,
+    messages: messages
+})
+
+export default i18n
\ No newline at end of file
diff --git a/src/locale/lang/en-US.js b/src/locale/lang/en-US.js
new file mode 100644
index 0000000..d41bfa1
--- /dev/null
+++ b/src/locale/lang/en-US.js
@@ -0,0 +1,5 @@
+const lang = {
+    "view.test.1-1": "test-view-1-1"
+}
+
+export default lang
\ No newline at end of file
diff --git a/src/locale/lang/zh-CN.js b/src/locale/lang/zh-CN.js
new file mode 100644
index 0000000..b7f1865
--- /dev/null
+++ b/src/locale/lang/zh-CN.js
@@ -0,0 +1,5 @@
+const lang = {
+    "view.test.1-1": "娴嬭瘯椤甸潰1-1"
+}
+
+export default lang
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..a117347
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,21 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+
+const app = createApp(App)
+
+// view-ui-plus
+import ViewUIPlus from 'view-ui-plus'
+import 'view-ui-plus/dist/styles/viewuiplus.css'
+app.use(ViewUIPlus)
+
+// i18n
+import i18n from './locale'
+app.use(i18n)
+
+// vue-router
+import VueRouter from './router'
+app.use(VueRouter)
+
+// 鍏ㄥ眬less鏍峰紡
+import './index.less'
+app.mount('#app')
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..2f3a779
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,30 @@
+import routes from './routes'
+import { createRouter, createWebHashHistory } from 'vue-router'
+import ViewUIPlus from 'view-ui-plus'
+import { checkLogin } from '@/libs/util'
+var router = createRouter({
+  routes: routes,
+  history: createWebHashHistory(),
+})
+router.beforeEach((to, from, next) => {
+  ViewUIPlus.LoadingBar.start();
+  // 鎸夐」鐩疄闄呴渶姹備慨鏀规爣棰�+  document.title = to.meta.title
+  if (to.matched.some(t => t.meta.authorize) && !checkLogin()) {
+    next({ name: 'login' })
+  }
+  else {
+    next()
+  }
+})
+router.afterEach(() => {
+  ViewUIPlus.LoadingBar.finish()
+})
+// 璺敱鍔犺浇鍑洪敊
+router.onError((err) => {
+  ViewUIPlus.LoadingBar.error()
+  // 鎸夐」鐩疄闄呴渶姹傚鐞嗛敊璇紓甯�+  throw new Error(err)
+})
+
+export default router
\ No newline at end of file
diff --git a/src/router/routes.js b/src/router/routes.js
new file mode 100644
index 0000000..762612f
--- /dev/null
+++ b/src/router/routes.js
@@ -0,0 +1,83 @@
+const routes = [
+    {
+        path: '/login',
+        name: 'login',
+        meta: { title: '鐧诲綍椤甸潰' },
+        component: () => import('@/views/account/login.vue')
+    },
+    {
+        path: '/logout',
+        name: 'logout',
+        meta: { title: '閫�嚭鐧诲綍' },
+        component: () => import('@/views/account/logout.vue')
+    },
+    {
+        path: '/',
+        component: () => import('@/layout/index.vue'),
+        meta: { authorize: true, title: 'vue-project' },
+        children: [
+            {
+                path: 'test-view-1-1',
+                name: 'test-view-1-1',
+                component: () => import('@/views/test-view-1-1/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰1-1' }
+            },
+            {
+                path: 'test-view-1-2',
+                name: 'test-view-1-2',
+                component: () => import('@/views/test-view-1-2/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰1-2' }
+            },
+            {
+                path: 'test-view-1-3',
+                name: 'test-view-1-3',
+                component: () => import('@/views/test-view-1-3/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰1-3' }
+            },
+            {
+                path: 'test-view-2-1',
+                name: 'test-view-2-1',
+                component: () => import('@/views/test-view-2-1/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰2-1' }
+            },
+            {
+                path: 'test-view-2-2',
+                name: 'test-view-2-2',
+                component: () => import('@/views/test-view-2-2/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰2-2' }
+            },
+            {
+                path: 'test-view-2-3',
+                name: 'test-view-2-3',
+                component: () => import('@/views/test-view-2-3/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰2-3' }
+            },
+            {
+                path: 'test-view-3-1',
+                name: 'test-view-3-1',
+                component: () => import('@/views/test-view-3-1/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰3-1' }
+            },
+            {
+                path: 'test-view-3-2',
+                name: 'test-view-3-2',
+                component: () => import('@/views/test-view-3-2/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰3-2' }
+            },
+            {
+                path: 'test-view-3-3',
+                name: 'test-view-3-3',
+                component: () => import('@/views/test-view-3-3/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰3-3' }
+            },
+            {
+                path: 'test-view-4',
+                name: 'test-view-4',
+                component: () => import('@/views/test-view-4/index.vue'),
+                meta: { title: '娴嬭瘯椤甸潰4' }
+            }
+        ]
+    }
+]
+
+export default routes
\ No newline at end of file
diff --git a/src/views/account/login.vue b/src/views/account/login.vue
new file mode 100644
index 0000000..533b648
--- /dev/null
+++ b/src/views/account/login.vue
@@ -0,0 +1,107 @@
+<template>
+  <div class="login-view">
+    <Form :model="formInline" :rules="ruleInline" inline ref="refFormInline">
+      <FormItem prop="user">
+        <Input type="text" v-model="formInline.user" placeholder="Username">
+          <template #prepend>
+            <Icon type="ios-person-outline"></Icon>
+          </template>
+        </Input>
+      </FormItem>
+      <FormItem prop="password">
+        <Input
+          type="password"
+          v-model="formInline.password"
+          placeholder="Password"
+        >
+          <template #prepend>
+            <Icon type="ios-lock-outline"></Icon>
+          </template>
+        </Input>
+      </FormItem>
+      <FormItem>
+        <Button type="primary" @click="onSignIn">Signin</Button>
+      </FormItem>
+    </Form>
+  </div>
+</template>
+
+<script>
+import { ref } from "vue";
+import { login } from "@/api/test";
+import { Base64 } from "js-base64";
+import { showError, showSuccess, setToken } from "@/libs/util";
+export default {
+  name: "LoginView",
+  data() {
+    return {
+      formInline: {
+        user: "",
+        password: "",
+      },
+      ruleInline: {
+        user: [
+          {
+            required: true,
+            message: "Please fill in the user name",
+            trigger: "blur",
+          },
+        ],
+        password: [
+          {
+            required: true,
+            message: "Please fill in the password.",
+            trigger: "blur",
+          },
+          {
+            type: "string",
+            min: 6,
+            message: "The password length cannot be less than 6 bits",
+            trigger: "blur",
+          },
+        ],
+      },
+    };
+  },
+  methods: {
+    onSignIn() {
+      this.refFormInline.validate(async (valid) => {
+        try {
+          if (valid) {
+            let res = await login({
+              user_login: Base64.encode(this.formInline.user),
+              user_psw: Base64.encode(this.formInline.password),
+            });
+            setToken(res.session_id);
+            this.showSuccess("鐧诲綍鎴愬姛");
+            this.$router.push("/");
+          } else {
+            this.showError("琛ㄥ崟楠岃瘉澶辫触!");
+          }
+        } catch (ex) {
+          this.showError(ex);
+        }
+      });
+    },
+    showError(ex) {
+      showError(this, ex);
+    },
+    showSuccess(tip) {
+      showSuccess(this, tip);
+    },
+  },
+  setup() {
+    const refFormInline = ref(null);
+    return { refFormInline };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.login-view {
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/account/logout.vue b/src/views/account/logout.vue
new file mode 100644
index 0000000..74f19b6
--- /dev/null
+++ b/src/views/account/logout.vue
@@ -0,0 +1,19 @@
+<template>
+  <div class="login-view">娓呯┖鐧诲綍淇℃伅</div>
+</template>
+
+<script>
+export default {
+  name: "LoginView",
+  mounted() {
+    setTimeout(() => {
+      this.$router.replace("/login");
+    }, 3 * 1000);
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.login-view {
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-1-1/index.vue b/src/views/test-view-1-1/index.vue
new file mode 100644
index 0000000..5f5cfc4
--- /dev/null
+++ b/src/views/test-view-1-1/index.vue
@@ -0,0 +1,24 @@
+<template>
+  <div class="test-view-1-1">
+    <HelloWorld :msg="$t('view.test.1-1')" />
+    <TheWelcome />
+  </div>
+</template>
+
+<script>
+import HelloWorld from "@/components/HelloWorld.vue";
+import TheWelcome from "@/components/TheWelcome.vue";
+export default {
+  name: "TestView11",
+  components: {
+    HelloWorld,
+    TheWelcome,
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.test-view-1-1 {
+  height: 100%;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-1-2/index.vue b/src/views/test-view-1-2/index.vue
new file mode 100644
index 0000000..07e0ee3
--- /dev/null
+++ b/src/views/test-view-1-2/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-1-2">
+        娴嬭瘯椤甸潰1-2
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView12'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-1-2{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-1-3/index.vue b/src/views/test-view-1-3/index.vue
new file mode 100644
index 0000000..8aa49e4
--- /dev/null
+++ b/src/views/test-view-1-3/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-1-3">
+        娴嬭瘯椤甸潰1-3
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView13'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-1-3{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-2-1/index.vue b/src/views/test-view-2-1/index.vue
new file mode 100644
index 0000000..81f9b7d
--- /dev/null
+++ b/src/views/test-view-2-1/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-2-1">
+        娴嬭瘯椤甸潰2-1
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView21'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-2-1{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-2-2/index.vue b/src/views/test-view-2-2/index.vue
new file mode 100644
index 0000000..cc5e0b3
--- /dev/null
+++ b/src/views/test-view-2-2/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-2-2">
+        娴嬭瘯椤甸潰2-2
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView22'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-2-2{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-2-3/index.vue b/src/views/test-view-2-3/index.vue
new file mode 100644
index 0000000..a3ac6e7
--- /dev/null
+++ b/src/views/test-view-2-3/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-2-3">
+        娴嬭瘯椤甸潰2-3
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView23'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-2-3{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-3-1/index.vue b/src/views/test-view-3-1/index.vue
new file mode 100644
index 0000000..82ba382
--- /dev/null
+++ b/src/views/test-view-3-1/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-3-1">
+        娴嬭瘯椤甸潰3-1
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView31'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-3-1{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-3-2/index.vue b/src/views/test-view-3-2/index.vue
new file mode 100644
index 0000000..dc06e44
--- /dev/null
+++ b/src/views/test-view-3-2/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-3-2">
+        娴嬭瘯椤甸潰3-2
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView32'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-3-2{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-3-3/index.vue b/src/views/test-view-3-3/index.vue
new file mode 100644
index 0000000..7987a24
--- /dev/null
+++ b/src/views/test-view-3-3/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-3-3">
+        娴嬭瘯椤甸潰3-3
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView33'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-3-3{
+    
+}
+</style>
\ No newline at end of file
diff --git a/src/views/test-view-4/index.vue b/src/views/test-view-4/index.vue
new file mode 100644
index 0000000..c7af9ac
--- /dev/null
+++ b/src/views/test-view-4/index.vue
@@ -0,0 +1,17 @@
+<template>
+    <div class="test-view-4">
+        娴嬭瘯椤甸潰4
+    </div>
+</template>
+
+<script>
+export default {
+    name:'TestView4'
+}
+</script>
+
+<style lang="less" scoped>
+.test-view-4{
+    
+}
+</style>
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..4217010
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,18 @@
+import { fileURLToPath, URL } from 'node:url'
+
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import vueDevTools from 'vite-plugin-vue-devtools'
+
+// https://vite.dev/config/
+export default defineConfig({
+  plugins: [
+    vue(),
+    vueDevTools(),
+  ],
+  resolve: {
+    alias: {
+      '@': fileURLToPath(new URL('./src', import.meta.url))
+    },
+  },
+})

--
Gitblit v1.9.1