diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 00000000..64778a1e
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
diff --git a/.husky/pre-push b/.husky/pre-push
new file mode 100755
index 00000000..f15e97a1
--- /dev/null
+++ b/.husky/pre-push
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npm run fmt
diff --git a/.vscode/swanlab.code-snippets b/.vscode/swanlab.code-snippets
index 25d525d8..ea21acc3 100644
--- a/.vscode/swanlab.code-snippets
+++ b/.vscode/swanlab.code-snippets
@@ -19,10 +19,7 @@
     "prefix": "comm",
     "scope": "python",
     "description": "python文件块注释",
-    "body": [
-      "# ---------------------------------- $1 ----------------------------------",
-      "$2"
-    ]
+    "body": ["# ---------------------------------- $1 ----------------------------------", "$2"]
   },
   "frontend-comment": {
     "prefix": ["comment", "comm"],
@@ -35,105 +32,105 @@
     "prefix": "vue",
     "description": "vue文件模板",
     "body": [
-        "<template> </template>",
-        "",
-        "<script setup>"
-        "/**",
-        " * @description: $1",
-        " * @file: ${TM_FILENAME} ",
-        " * @since: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND} ",
-        "**/"
-        "$2"
-        "</script>",
-        "",
-        "<style lang=\"scss\" scoped></style>",
-        ""
-      ],
-},
-"vue-chart": {
-	"prefix": "vue-chart",
-	"body": [
-		"<template>",
-		"  <!-- 图表标题 -->",
-		"  <p class=\"text-center font-semibold\">{{ title }}</p>",
-		"  <!-- 如果图表数据错误 -->",
-		"  <div class=\"flex flex-col justify-center grow text-dimmer gap-2\" v-if=\"error\">",
-		"    <SLIcon class=\"mx-auto h-5 w-5\" icon=\"error\" />",
-		"    <p class=\"text-center text-xs\">",
-		"      <!-- 在此处显示错误信息 -->",
-		"    </p>",
-		"  </div>",
-		"  <!-- 如果图表数据正确 -->",
-		"  <template v-else>",
-		"    <!-- 在此处完成图表主体定义 -->",
-		"    <!-- 放大效果弹窗 -->",
-		"    <SLModal class=\"p-10 pt-0 overflow-hidden\" max-w=\"-1\" v-model=\"isZoom\"> </SLModal>",
-		"  </template>",
-		"</template>",
-		"",
-		"<script setup>",
-        "/**",
-        " * @description: $1",
-        " * @file: ${TM_FILENAME} ",
-        " * @since: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND} ",
-        "**/",
-		"import SLModal from '@swanlab-vue/components/SLModal.vue'",
-		"import SLIcon from '@swanlab-vue/components/SLIcon.vue'",
-		"import { ref } from 'vue'",
-		"import { useExperimentStroe } from '@swanlab-vue/store'",
-		"import { addTaskToBrowserMainThread } from '@swanlab-vue/utils/browser'",
-		"import * as UTILS from './utils'",
-		"",
-		"// ---------------------------------- 配置 ----------------------------------",
-		"const experimentStore = useExperimentStroe()",
-		"const props = defineProps({",
-		"  title: {",
-		"    type: String,",
-		"    required: true",
-		"  },",
-		"  chart: {",
-		"    type: Object,",
-		"    required: true",
-		"  }",
-		"})",
-		"",
-		"// ---------------------------------- 错误处理,如果chart.error存在,则下面的api都将不应该被执行 ----------------------------------",
-		"",
-		"const error = ref(props.chart.error)",
-		"",
-		"// ---------------------------------- 组件渲染逻辑 ----------------------------------",
-		"",
-		"// ---------------------------------- 数据格式化 ----------------------------------",
-		"",
-		"// ---------------------------------- 渲染、重渲染功能 ----------------------------------",
-		"",
-		"// 渲染",
-		"const render = (data) => {}",
-		"// 重渲染",
-		"const change = (data) => {}",
-		"",
-		"// ---------------------------------- 放大功能 ----------------------------------",
-		"// 是否放大",
-		"const isZoom = ref(false)",
-		"// 放大数据",
-		"const zoom = (data) => {",
-		"  isZoom.value = true",
-		"  // 放大后图表的高度",
-		"  const height = window.innerHeight * 0.6",
-		"  addTaskToBrowserMainThread(() => {})",
-		"}",
-		"",
-		"// ---------------------------------- 暴露api ----------------------------------",
-		"defineExpose({",
-		"  render,",
-		"  change,",
-		"  zoom",
-		"})",
-		"</script>",
-		"",
-		"<style lang=\"scss\" scoped></style>",
-		""
-	],
-	"description": "vue-chart"
-}
+      "<template> </template>",
+      "",
+      "<script setup>",
+      "/**",
+      " * @description: $1",
+      " * @file: ${TM_FILENAME} ",
+      " * @since: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND} ",
+      "**/",
+      "$2",
+      "</script>",
+      "",
+      "<style lang=\"scss\" scoped></style>",
+      ""
+    ]
+  },
+  "vue-chart": {
+    "prefix": "vue-chart",
+    "body": [
+      "<template>",
+      "  <!-- 图表标题 -->",
+      "  <p class=\"text-center font-semibold\">{{ title }}</p>",
+      "  <!-- 如果图表数据错误 -->",
+      "  <div class=\"flex flex-col justify-center grow text-dimmer gap-2\" v-if=\"error\">",
+      "    <SLIcon class=\"mx-auto h-5 w-5\" icon=\"error\" />",
+      "    <p class=\"text-center text-xs\">",
+      "      <!-- 在此处显示错误信息 -->",
+      "    </p>",
+      "  </div>",
+      "  <!-- 如果图表数据正确 -->",
+      "  <template v-else>",
+      "    <!-- 在此处完成图表主体定义 -->",
+      "    <!-- 放大效果弹窗 -->",
+      "    <SLModal class=\"p-10 pt-0 overflow-hidden\" max-w=\"-1\" v-model=\"isZoom\"> </SLModal>",
+      "  </template>",
+      "</template>",
+      "",
+      "<script setup>",
+      "/**",
+      " * @description: $1",
+      " * @file: ${TM_FILENAME} ",
+      " * @since: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND} ",
+      "**/",
+      "import SLModal from '@swanlab-vue/components/SLModal.vue'",
+      "import SLIcon from '@swanlab-vue/components/SLIcon.vue'",
+      "import { ref } from 'vue'",
+      "import { useExperimentStroe } from '@swanlab-vue/store'",
+      "import { addTaskToBrowserMainThread } from '@swanlab-vue/utils/browser'",
+      "import * as UTILS from './utils'",
+      "",
+      "// ---------------------------------- 配置 ----------------------------------",
+      "const experimentStore = useExperimentStroe()",
+      "const props = defineProps({",
+      "  title: {",
+      "    type: String,",
+      "    required: true",
+      "  },",
+      "  chart: {",
+      "    type: Object,",
+      "    required: true",
+      "  }",
+      "})",
+      "",
+      "// ---------------------------------- 错误处理,如果chart.error存在,则下面的api都将不应该被执行 ----------------------------------",
+      "",
+      "const error = ref(props.chart.error)",
+      "",
+      "// ---------------------------------- 组件渲染逻辑 ----------------------------------",
+      "",
+      "// ---------------------------------- 数据格式化 ----------------------------------",
+      "",
+      "// ---------------------------------- 渲染、重渲染功能 ----------------------------------",
+      "",
+      "// 渲染",
+      "const render = (data) => {}",
+      "// 重渲染",
+      "const change = (data) => {}",
+      "",
+      "// ---------------------------------- 放大功能 ----------------------------------",
+      "// 是否放大",
+      "const isZoom = ref(false)",
+      "// 放大数据",
+      "const zoom = (data) => {",
+      "  isZoom.value = true",
+      "  // 放大后图表的高度",
+      "  const height = window.innerHeight * 0.6",
+      "  addTaskToBrowserMainThread(() => {})",
+      "}",
+      "",
+      "// ---------------------------------- 暴露api ----------------------------------",
+      "defineExpose({",
+      "  render,",
+      "  change,",
+      "  zoom",
+      "})",
+      "</script>",
+      "",
+      "<style lang=\"scss\" scoped></style>",
+      ""
+    ],
+    "description": "vue-chart"
+  }
 }
diff --git a/.vscode/tailwind.json b/.vscode/tailwind.json
index 83e95430..96a1f579 100644
--- a/.vscode/tailwind.json
+++ b/.vscode/tailwind.json
@@ -1,55 +1,55 @@
 {
-    "version": 1.1,
-    "atDirectives": [
-      {
-        "name": "@tailwind",
-        "description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
-        "references": [
-          {
-            "name": "Tailwind Documentation",
-            "url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
-          }
-        ]
-      },
-      {
-        "name": "@apply",
-        "description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that you’d like to extract to a new component.",
-        "references": [
-          {
-            "name": "Tailwind Documentation",
-            "url": "https://tailwindcss.com/docs/functions-and-directives#apply"
-          }
-        ]
-      },
-      {
-        "name": "@responsive",
-        "description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n  .alert {\n    background-color: #E53E3E;\n  }\n}\n```\n",
-        "references": [
-          {
-            "name": "Tailwind Documentation",
-            "url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
-          }
-        ]
-      },
-      {
-        "name": "@screen",
-        "description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n  /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n  /* ... */\n}\n```\n",
-        "references": [
-          {
-            "name": "Tailwind Documentation",
-            "url": "https://tailwindcss.com/docs/functions-and-directives#screen"
-          }
-        ]
-      },
-      {
-        "name": "@variants",
-        "description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n   .btn-brand {\n    background-color: #3182CE;\n  }\n}\n```\n",
-        "references": [
-          {
-            "name": "Tailwind Documentation",
-            "url": "https://tailwindcss.com/docs/functions-and-directives#variants"
-          }
-        ]
-      }
-    ]
-  }
+  "version": 1.1,
+  "atDirectives": [
+    {
+      "name": "@tailwind",
+      "description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.",
+      "references": [
+        {
+          "name": "Tailwind Documentation",
+          "url": "https://tailwindcss.com/docs/functions-and-directives#tailwind"
+        }
+      ]
+    },
+    {
+      "name": "@apply",
+      "description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that you’d like to extract to a new component.",
+      "references": [
+        {
+          "name": "Tailwind Documentation",
+          "url": "https://tailwindcss.com/docs/functions-and-directives#apply"
+        }
+      ]
+    },
+    {
+      "name": "@responsive",
+      "description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n  .alert {\n    background-color: #E53E3E;\n  }\n}\n```\n",
+      "references": [
+        {
+          "name": "Tailwind Documentation",
+          "url": "https://tailwindcss.com/docs/functions-and-directives#responsive"
+        }
+      ]
+    },
+    {
+      "name": "@screen",
+      "description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n  /* ... */\n}\n```\n…gets transformed into this:\n```css\n@media (min-width: 640px) {\n  /* ... */\n}\n```\n",
+      "references": [
+        {
+          "name": "Tailwind Documentation",
+          "url": "https://tailwindcss.com/docs/functions-and-directives#screen"
+        }
+      ]
+    },
+    {
+      "name": "@variants",
+      "description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n   .btn-brand {\n    background-color: #3182CE;\n  }\n}\n```\n",
+      "references": [
+        {
+          "name": "Tailwind Documentation",
+          "url": "https://tailwindcss.com/docs/functions-and-directives#variants"
+        }
+      ]
+    }
+  ]
+}
diff --git a/package.json b/package.json
index 2a007cc6..e9636dbb 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,9 @@
     "dev:mock": "vite --mode mock",
     "build": "vite build",
     "build.release": "vite build --mode release",
-    "preview": "vite preview"
+    "preview": "vite preview",
+    "fmt": "npx prettier --write .",
+    "prepare": "husky install"
   },
   "dependencies": {
     "@antv/g2plot": "^2.4.31",
@@ -36,6 +38,7 @@
     "tailwindcss": "^3.3.5",
     "unplugin-auto-import": "^0.15.2",
     "unplugin-vue-components": "^0.24.1",
-    "vite": "^5.0.0"
+    "vite": "^5.0.0",
+    "husky": "^8.0.0"
   }
 }
diff --git a/vue/src/i18n/en-US/sider.json b/vue/src/i18n/en-US/sider.json
index 4e8a7d0b..3e60305d 100644
--- a/vue/src/i18n/en-US/sider.json
+++ b/vue/src/i18n/en-US/sider.json
@@ -1,12 +1,12 @@
 {
-    "version": {
+  "version": {
     "version": "Current Version: v{version}, View",
     "updates": "Release Notes"
-    },
-    "nav": {
+  },
+  "nav": {
     "home": "Overview",
     "search": "Search Experiments...",
     "experiment": "Experiment",
     "help": "Help"
-    }
+  }
 }
diff --git a/vue/src/theme/color.min.css b/vue/src/theme/color.min.css
index 063d2dcf..2909b5dc 100644
--- a/vue/src/theme/color.min.css
+++ b/vue/src/theme/color.min.css
@@ -1 +1,17 @@
-:root{--background-overlay:rgba(15,21,36,0.8);--background-default:#ffffff;--background-dimmer:#f6f8fa;--outline-default:#d1d7dd;--foreground-default:#000000;--foreground-dimmer:#555555;--foreground-dimmest:#858585;--positive-highest:#d5e4d9;--positive-higher:#cff1d8;--positive-default:#4e9553;--positive-dimmer:#37733c;--primary-default:#1c74dd;--primary-dimmest:#d6e8ff;--negative-default:#bb4c51;--nagative-dimmest:#eddcdc}
+:root {
+  --background-overlay: rgba(15, 21, 36, 0.8);
+  --background-default: #ffffff;
+  --background-dimmer: #f6f8fa;
+  --outline-default: #d1d7dd;
+  --foreground-default: #000000;
+  --foreground-dimmer: #555555;
+  --foreground-dimmest: #858585;
+  --positive-highest: #d5e4d9;
+  --positive-higher: #cff1d8;
+  --positive-default: #4e9553;
+  --positive-dimmer: #37733c;
+  --primary-default: #1c74dd;
+  --primary-dimmest: #d6e8ff;
+  --negative-default: #bb4c51;
+  --nagative-dimmest: #eddcdc;
+}