完成Work组件的界面和一些小修改
> 1. 修改优化路由守卫
> 2. 去除拦截器中的调试信息
> 3. 修改头部导航条下拉菜单的样式增加图标。
> 4. work组件现在使用mock数据

Change-Id: Ic602a35bb02e645a0d5253c5cbd12a68d70bfb33
diff --git a/package.json b/package.json
index 8c00989..ec69ade 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
     "less": "^4.3.0",
     "react": "^19.1.0",
     "react-dom": "^19.1.0",
+    "react-markdown": "^10.1.0",
     "react-redux": "^9.2.0",
     "react-router": "^7.6.0"
   },
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 56f73c4..810efc5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -35,6 +35,9 @@
       react-dom:
         specifier: ^19.1.0
         version: 19.1.0(react@19.1.0)
+      react-markdown:
+        specifier: ^10.1.0
+        version: 10.1.0(@types/react@19.1.4)(react@19.1.0)
       react-redux:
         specifier: ^9.2.0
         version: 9.2.0(@types/react@19.1.4)(react@19.1.0)(redux@5.0.1)
@@ -86,7 +89,7 @@
         version: 6.3.5(@types/node@22.15.30)(less@4.3.0)
       vitest:
         specifier: ^3.1.4
-        version: 3.1.4(@types/node@22.15.30)(jsdom@26.1.0)(less@4.3.0)
+        version: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.30)(jsdom@26.1.0)(less@4.3.0)
 
 packages:
 
@@ -742,9 +745,18 @@
   '@types/babel__traverse@7.20.7':
     resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
 
+  '@types/debug@4.1.12':
+    resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+
+  '@types/estree-jsx@1.0.5':
+    resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
   '@types/estree@1.0.7':
     resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
 
+  '@types/hast@3.0.4':
+    resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
   '@types/istanbul-lib-coverage@2.0.6':
     resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
 
@@ -760,6 +772,12 @@
   '@types/json-schema@7.0.15':
     resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
 
+  '@types/mdast@4.0.4':
+    resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
+  '@types/ms@2.1.0':
+    resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
   '@types/node@22.15.30':
     resolution: {integrity: sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==}
 
@@ -774,6 +792,12 @@
   '@types/stack-utils@2.0.3':
     resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
 
+  '@types/unist@2.0.11':
+    resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
+
+  '@types/unist@3.0.3':
+    resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
   '@types/use-sync-external-store@0.0.6':
     resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
 
@@ -830,6 +854,9 @@
     resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
+  '@ungap/structured-clone@1.3.0':
+    resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+
   '@vitejs/plugin-react@4.4.1':
     resolution: {integrity: sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==}
     engines: {node: ^14.18.0 || >=16.0.0}
@@ -920,6 +947,9 @@
   axios@1.9.0:
     resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==}
 
+  bail@2.0.2:
+    resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
   balanced-match@1.0.2:
     resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
 
@@ -953,6 +983,9 @@
   caniuse-lite@1.0.30001718:
     resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==}
 
+  ccount@2.0.1:
+    resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
   chai@5.2.0:
     resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==}
     engines: {node: '>=12'}
@@ -965,6 +998,18 @@
     resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
     engines: {node: '>=10'}
 
+  character-entities-html4@2.1.0:
+    resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+  character-entities-legacy@3.0.0:
+    resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+  character-entities@2.0.2:
+    resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+
+  character-reference-invalid@2.0.1:
+    resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
   check-error@2.1.1:
     resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
     engines: {node: '>= 16'}
@@ -987,6 +1032,9 @@
     resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
     engines: {node: '>= 0.8'}
 
+  comma-separated-tokens@2.0.3:
+    resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
   compute-scroll-into-view@3.1.1:
     resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==}
 
@@ -1039,6 +1087,9 @@
   decimal.js@10.5.0:
     resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==}
 
+  decode-named-character-reference@1.1.0:
+    resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==}
+
   deep-eql@5.0.2:
     resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
     engines: {node: '>=6'}
@@ -1054,6 +1105,9 @@
     resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
     engines: {node: '>=6'}
 
+  devlop@1.1.0:
+    resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
   diff-sequences@29.6.3:
     resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1164,6 +1218,9 @@
     resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
     engines: {node: '>=4.0'}
 
+  estree-util-is-identifier-name@3.0.0:
+    resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
   estree-walker@3.0.3:
     resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
 
@@ -1179,6 +1236,9 @@
     resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
 
+  extend@3.0.2:
+    resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
   fast-deep-equal@3.1.3:
     resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
 
@@ -1301,10 +1361,19 @@
     resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
     engines: {node: '>= 0.4'}
 
+  hast-util-to-jsx-runtime@2.3.6:
+    resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+  hast-util-whitespace@3.0.0:
+    resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
   html-encoding-sniffer@4.0.0:
     resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
     engines: {node: '>=18'}
 
+  html-url-attributes@3.0.1:
+    resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+
   http-proxy-agent@7.0.2:
     resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
     engines: {node: '>= 14'}
@@ -1345,6 +1414,18 @@
     resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
     engines: {node: '>=8'}
 
+  inline-style-parser@0.2.4:
+    resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
+
+  is-alphabetical@2.0.1:
+    resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+  is-alphanumerical@2.0.1:
+    resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
+  is-decimal@2.0.1:
+    resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
   is-extglob@2.1.1:
     resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
     engines: {node: '>=0.10.0'}
@@ -1353,10 +1434,17 @@
     resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
     engines: {node: '>=0.10.0'}
 
+  is-hexadecimal@2.0.1:
+    resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
   is-number@7.0.0:
     resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
     engines: {node: '>=0.12.0'}
 
+  is-plain-obj@4.1.0:
+    resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+    engines: {node: '>=12'}
+
   is-potential-custom-element-name@1.0.1:
     resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
 
@@ -1446,6 +1534,9 @@
   lodash@4.17.21:
     resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
 
+  longest-streak@3.1.0:
+    resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
   loupe@3.1.3:
     resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==}
 
@@ -1470,10 +1561,97 @@
     resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
     engines: {node: '>= 0.4'}
 
+  mdast-util-from-markdown@2.0.2:
+    resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
+
+  mdast-util-mdx-expression@2.0.1:
+    resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+  mdast-util-mdx-jsx@3.2.0:
+    resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+  mdast-util-mdxjs-esm@2.0.1:
+    resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+  mdast-util-phrasing@4.1.0:
+    resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+  mdast-util-to-hast@13.2.0:
+    resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
+
+  mdast-util-to-markdown@2.1.2:
+    resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+  mdast-util-to-string@4.0.0:
+    resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
   merge2@1.4.1:
     resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
     engines: {node: '>= 8'}
 
+  micromark-core-commonmark@2.0.3:
+    resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
+
+  micromark-factory-destination@2.0.1:
+    resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
+
+  micromark-factory-label@2.0.1:
+    resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+
+  micromark-factory-space@2.0.1:
+    resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
+
+  micromark-factory-title@2.0.1:
+    resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
+
+  micromark-factory-whitespace@2.0.1:
+    resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
+
+  micromark-util-character@2.1.1:
+    resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+  micromark-util-chunked@2.0.1:
+    resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
+
+  micromark-util-classify-character@2.0.1:
+    resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
+
+  micromark-util-combine-extensions@2.0.1:
+    resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
+
+  micromark-util-decode-numeric-character-reference@2.0.2:
+    resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+
+  micromark-util-decode-string@2.0.1:
+    resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
+  micromark-util-encode@2.0.1:
+    resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+  micromark-util-html-tag-name@2.0.1:
+    resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
+
+  micromark-util-normalize-identifier@2.0.1:
+    resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
+
+  micromark-util-resolve-all@2.0.1:
+    resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
+
+  micromark-util-sanitize-uri@2.0.1:
+    resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+  micromark-util-subtokenize@2.1.0:
+    resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
+
+  micromark-util-symbol@2.0.1:
+    resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+  micromark-util-types@2.0.2:
+    resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+  micromark@4.0.2:
+    resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+
   micromatch@4.0.8:
     resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
     engines: {node: '>=8.6'}
@@ -1540,6 +1718,9 @@
     resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
     engines: {node: '>=6'}
 
+  parse-entities@4.0.2:
+    resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
   parse-node-version@1.0.1:
     resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==}
     engines: {node: '>= 0.10'}
@@ -1593,6 +1774,9 @@
     resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
 
+  property-information@7.1.0:
+    resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
   proxy-from-env@1.1.0:
     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 
@@ -1845,6 +2029,12 @@
   react-is@18.3.1:
     resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
 
+  react-markdown@10.1.0:
+    resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==}
+    peerDependencies:
+      '@types/react': '>=18'
+      react: '>=18'
+
   react-redux@9.2.0:
     resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==}
     peerDependencies:
@@ -1887,6 +2077,12 @@
   redux@5.0.1:
     resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==}
 
+  remark-parse@11.0.0:
+    resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+  remark-rehype@11.1.2:
+    resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
   reselect@5.1.1:
     resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==}
 
@@ -1967,6 +2163,9 @@
     resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
     engines: {node: '>=0.10.0'}
 
+  space-separated-tokens@2.0.2:
+    resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
   stack-utils@2.0.6:
     resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
     engines: {node: '>=10'}
@@ -1980,6 +2179,9 @@
   string-convert@0.2.1:
     resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==}
 
+  stringify-entities@4.0.4:
+    resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
   strip-indent@3.0.0:
     resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
     engines: {node: '>=8'}
@@ -1988,6 +2190,12 @@
     resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
     engines: {node: '>=8'}
 
+  style-to-js@1.1.16:
+    resolution: {integrity: sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==}
+
+  style-to-object@1.0.8:
+    resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==}
+
   stylis@4.3.6:
     resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==}
 
@@ -2046,6 +2254,12 @@
     resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
     engines: {node: '>=18'}
 
+  trim-lines@3.0.1:
+    resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+  trough@2.2.0:
+    resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
   ts-api-utils@2.1.0:
     resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
     engines: {node: '>=18.12'}
@@ -2074,6 +2288,24 @@
   undici-types@6.21.0:
     resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
 
+  unified@11.0.5:
+    resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+  unist-util-is@6.0.0:
+    resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
+
+  unist-util-position@5.0.0:
+    resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+  unist-util-stringify-position@4.0.0:
+    resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+  unist-util-visit-parents@6.0.1:
+    resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
+
+  unist-util-visit@5.0.0:
+    resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+
   update-browserslist-db@1.1.3:
     resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
     hasBin: true
@@ -2088,6 +2320,12 @@
     peerDependencies:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
 
+  vfile-message@4.0.2:
+    resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
+
+  vfile@6.0.3:
+    resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
   vite-node@3.1.4:
     resolution: {integrity: sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA==}
     engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -2221,6 +2459,9 @@
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
 
+  zwitch@2.0.4:
+    resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
 snapshots:
 
   '@adobe/css-tools@4.4.3': {}
@@ -2829,8 +3070,20 @@
     dependencies:
       '@babel/types': 7.27.1
 
+  '@types/debug@4.1.12':
+    dependencies:
+      '@types/ms': 2.1.0
+
+  '@types/estree-jsx@1.0.5':
+    dependencies:
+      '@types/estree': 1.0.7
+
   '@types/estree@1.0.7': {}
 
+  '@types/hast@3.0.4':
+    dependencies:
+      '@types/unist': 3.0.3
+
   '@types/istanbul-lib-coverage@2.0.6': {}
 
   '@types/istanbul-lib-report@3.0.3':
@@ -2848,6 +3101,12 @@
 
   '@types/json-schema@7.0.15': {}
 
+  '@types/mdast@4.0.4':
+    dependencies:
+      '@types/unist': 3.0.3
+
+  '@types/ms@2.1.0': {}
+
   '@types/node@22.15.30':
     dependencies:
       undici-types: 6.21.0
@@ -2862,6 +3121,10 @@
 
   '@types/stack-utils@2.0.3': {}
 
+  '@types/unist@2.0.11': {}
+
+  '@types/unist@3.0.3': {}
+
   '@types/use-sync-external-store@0.0.6': {}
 
   '@types/yargs-parser@21.0.3': {}
@@ -2947,6 +3210,8 @@
       '@typescript-eslint/types': 8.32.1
       eslint-visitor-keys: 4.2.0
 
+  '@ungap/structured-clone@1.3.0': {}
+
   '@vitejs/plugin-react@4.4.1(vite@6.3.5(@types/node@22.15.30)(less@4.3.0))':
     dependencies:
       '@babel/core': 7.27.1
@@ -3099,6 +3364,8 @@
     transitivePeerDependencies:
       - debug
 
+  bail@2.0.2: {}
+
   balanced-match@1.0.2: {}
 
   brace-expansion@1.1.11:
@@ -3132,6 +3399,8 @@
 
   caniuse-lite@1.0.30001718: {}
 
+  ccount@2.0.1: {}
+
   chai@5.2.0:
     dependencies:
       assertion-error: 2.0.1
@@ -3150,6 +3419,14 @@
       ansi-styles: 4.3.0
       supports-color: 7.2.0
 
+  character-entities-html4@2.1.0: {}
+
+  character-entities-legacy@3.0.0: {}
+
+  character-entities@2.0.2: {}
+
+  character-reference-invalid@2.0.1: {}
+
   check-error@2.1.1: {}
 
   ci-info@3.9.0: {}
@@ -3166,6 +3443,8 @@
     dependencies:
       delayed-stream: 1.0.0
 
+  comma-separated-tokens@2.0.3: {}
+
   compute-scroll-into-view@3.1.1: {}
 
   concat-map@0.0.1: {}
@@ -3210,6 +3489,10 @@
 
   decimal.js@10.5.0: {}
 
+  decode-named-character-reference@1.1.0:
+    dependencies:
+      character-entities: 2.0.2
+
   deep-eql@5.0.2: {}
 
   deep-is@0.1.4: {}
@@ -3218,6 +3501,10 @@
 
   dequal@2.0.3: {}
 
+  devlop@1.1.0:
+    dependencies:
+      dequal: 2.0.3
+
   diff-sequences@29.6.3: {}
 
   dom-accessibility-api@0.5.16: {}
@@ -3363,6 +3650,8 @@
 
   estraverse@5.3.0: {}
 
+  estree-util-is-identifier-name@3.0.0: {}
+
   estree-walker@3.0.3:
     dependencies:
       '@types/estree': 1.0.7
@@ -3379,6 +3668,8 @@
       jest-message-util: 29.7.0
       jest-util: 29.7.0
 
+  extend@3.0.2: {}
+
   fast-deep-equal@3.1.3: {}
 
   fast-glob@3.3.3:
@@ -3487,10 +3778,36 @@
     dependencies:
       function-bind: 1.1.2
 
+  hast-util-to-jsx-runtime@2.3.6:
+    dependencies:
+      '@types/estree': 1.0.7
+      '@types/hast': 3.0.4
+      '@types/unist': 3.0.3
+      comma-separated-tokens: 2.0.3
+      devlop: 1.1.0
+      estree-util-is-identifier-name: 3.0.0
+      hast-util-whitespace: 3.0.0
+      mdast-util-mdx-expression: 2.0.1
+      mdast-util-mdx-jsx: 3.2.0
+      mdast-util-mdxjs-esm: 2.0.1
+      property-information: 7.1.0
+      space-separated-tokens: 2.0.2
+      style-to-js: 1.1.16
+      unist-util-position: 5.0.0
+      vfile-message: 4.0.2
+    transitivePeerDependencies:
+      - supports-color
+
+  hast-util-whitespace@3.0.0:
+    dependencies:
+      '@types/hast': 3.0.4
+
   html-encoding-sniffer@4.0.0:
     dependencies:
       whatwg-encoding: 3.1.1
 
+  html-url-attributes@3.0.1: {}
+
   http-proxy-agent@7.0.2:
     dependencies:
       agent-base: 7.1.3
@@ -3527,14 +3844,29 @@
 
   indent-string@4.0.0: {}
 
+  inline-style-parser@0.2.4: {}
+
+  is-alphabetical@2.0.1: {}
+
+  is-alphanumerical@2.0.1:
+    dependencies:
+      is-alphabetical: 2.0.1
+      is-decimal: 2.0.1
+
+  is-decimal@2.0.1: {}
+
   is-extglob@2.1.1: {}
 
   is-glob@4.0.3:
     dependencies:
       is-extglob: 2.1.1
 
+  is-hexadecimal@2.0.1: {}
+
   is-number@7.0.0: {}
 
+  is-plain-obj@4.1.0: {}
+
   is-potential-custom-element-name@1.0.1: {}
 
   is-what@3.14.1: {}
@@ -3656,6 +3988,8 @@
 
   lodash@4.17.21: {}
 
+  longest-streak@3.1.0: {}
+
   loupe@3.1.3: {}
 
   lru-cache@10.4.3: {}
@@ -3678,8 +4012,230 @@
 
   math-intrinsics@1.1.0: {}
 
+  mdast-util-from-markdown@2.0.2:
+    dependencies:
+      '@types/mdast': 4.0.4
+      '@types/unist': 3.0.3
+      decode-named-character-reference: 1.1.0
+      devlop: 1.1.0
+      mdast-util-to-string: 4.0.0
+      micromark: 4.0.2
+      micromark-util-decode-numeric-character-reference: 2.0.2
+      micromark-util-decode-string: 2.0.1
+      micromark-util-normalize-identifier: 2.0.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+      unist-util-stringify-position: 4.0.0
+    transitivePeerDependencies:
+      - supports-color
+
+  mdast-util-mdx-expression@2.0.1:
+    dependencies:
+      '@types/estree-jsx': 1.0.5
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.2
+      mdast-util-to-markdown: 2.1.2
+    transitivePeerDependencies:
+      - supports-color
+
+  mdast-util-mdx-jsx@3.2.0:
+    dependencies:
+      '@types/estree-jsx': 1.0.5
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      '@types/unist': 3.0.3
+      ccount: 2.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.2
+      mdast-util-to-markdown: 2.1.2
+      parse-entities: 4.0.2
+      stringify-entities: 4.0.4
+      unist-util-stringify-position: 4.0.0
+      vfile-message: 4.0.2
+    transitivePeerDependencies:
+      - supports-color
+
+  mdast-util-mdxjs-esm@2.0.1:
+    dependencies:
+      '@types/estree-jsx': 1.0.5
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.2
+      mdast-util-to-markdown: 2.1.2
+    transitivePeerDependencies:
+      - supports-color
+
+  mdast-util-phrasing@4.1.0:
+    dependencies:
+      '@types/mdast': 4.0.4
+      unist-util-is: 6.0.0
+
+  mdast-util-to-hast@13.2.0:
+    dependencies:
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      '@ungap/structured-clone': 1.3.0
+      devlop: 1.1.0
+      micromark-util-sanitize-uri: 2.0.1
+      trim-lines: 3.0.1
+      unist-util-position: 5.0.0
+      unist-util-visit: 5.0.0
+      vfile: 6.0.3
+
+  mdast-util-to-markdown@2.1.2:
+    dependencies:
+      '@types/mdast': 4.0.4
+      '@types/unist': 3.0.3
+      longest-streak: 3.1.0
+      mdast-util-phrasing: 4.1.0
+      mdast-util-to-string: 4.0.0
+      micromark-util-classify-character: 2.0.1
+      micromark-util-decode-string: 2.0.1
+      unist-util-visit: 5.0.0
+      zwitch: 2.0.4
+
+  mdast-util-to-string@4.0.0:
+    dependencies:
+      '@types/mdast': 4.0.4
+
   merge2@1.4.1: {}
 
+  micromark-core-commonmark@2.0.3:
+    dependencies:
+      decode-named-character-reference: 1.1.0
+      devlop: 1.1.0
+      micromark-factory-destination: 2.0.1
+      micromark-factory-label: 2.0.1
+      micromark-factory-space: 2.0.1
+      micromark-factory-title: 2.0.1
+      micromark-factory-whitespace: 2.0.1
+      micromark-util-character: 2.1.1
+      micromark-util-chunked: 2.0.1
+      micromark-util-classify-character: 2.0.1
+      micromark-util-html-tag-name: 2.0.1
+      micromark-util-normalize-identifier: 2.0.1
+      micromark-util-resolve-all: 2.0.1
+      micromark-util-subtokenize: 2.1.0
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-factory-destination@2.0.1:
+    dependencies:
+      micromark-util-character: 2.1.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-factory-label@2.0.1:
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-character: 2.1.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-factory-space@2.0.1:
+    dependencies:
+      micromark-util-character: 2.1.1
+      micromark-util-types: 2.0.2
+
+  micromark-factory-title@2.0.1:
+    dependencies:
+      micromark-factory-space: 2.0.1
+      micromark-util-character: 2.1.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-factory-whitespace@2.0.1:
+    dependencies:
+      micromark-factory-space: 2.0.1
+      micromark-util-character: 2.1.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-util-character@2.1.1:
+    dependencies:
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-util-chunked@2.0.1:
+    dependencies:
+      micromark-util-symbol: 2.0.1
+
+  micromark-util-classify-character@2.0.1:
+    dependencies:
+      micromark-util-character: 2.1.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-util-combine-extensions@2.0.1:
+    dependencies:
+      micromark-util-chunked: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-util-decode-numeric-character-reference@2.0.2:
+    dependencies:
+      micromark-util-symbol: 2.0.1
+
+  micromark-util-decode-string@2.0.1:
+    dependencies:
+      decode-named-character-reference: 1.1.0
+      micromark-util-character: 2.1.1
+      micromark-util-decode-numeric-character-reference: 2.0.2
+      micromark-util-symbol: 2.0.1
+
+  micromark-util-encode@2.0.1: {}
+
+  micromark-util-html-tag-name@2.0.1: {}
+
+  micromark-util-normalize-identifier@2.0.1:
+    dependencies:
+      micromark-util-symbol: 2.0.1
+
+  micromark-util-resolve-all@2.0.1:
+    dependencies:
+      micromark-util-types: 2.0.2
+
+  micromark-util-sanitize-uri@2.0.1:
+    dependencies:
+      micromark-util-character: 2.1.1
+      micromark-util-encode: 2.0.1
+      micromark-util-symbol: 2.0.1
+
+  micromark-util-subtokenize@2.1.0:
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-chunked: 2.0.1
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+
+  micromark-util-symbol@2.0.1: {}
+
+  micromark-util-types@2.0.2: {}
+
+  micromark@4.0.2:
+    dependencies:
+      '@types/debug': 4.1.12
+      debug: 4.4.1
+      decode-named-character-reference: 1.1.0
+      devlop: 1.1.0
+      micromark-core-commonmark: 2.0.3
+      micromark-factory-space: 2.0.1
+      micromark-util-character: 2.1.1
+      micromark-util-chunked: 2.0.1
+      micromark-util-combine-extensions: 2.0.1
+      micromark-util-decode-numeric-character-reference: 2.0.2
+      micromark-util-encode: 2.0.1
+      micromark-util-normalize-identifier: 2.0.1
+      micromark-util-resolve-all: 2.0.1
+      micromark-util-sanitize-uri: 2.0.1
+      micromark-util-subtokenize: 2.1.0
+      micromark-util-symbol: 2.0.1
+      micromark-util-types: 2.0.2
+    transitivePeerDependencies:
+      - supports-color
+
   micromatch@4.0.8:
     dependencies:
       braces: 3.0.3
@@ -3741,6 +4297,16 @@
     dependencies:
       callsites: 3.1.0
 
+  parse-entities@4.0.2:
+    dependencies:
+      '@types/unist': 2.0.11
+      character-entities-legacy: 3.0.0
+      character-reference-invalid: 2.0.1
+      decode-named-character-reference: 1.1.0
+      is-alphanumerical: 2.0.1
+      is-decimal: 2.0.1
+      is-hexadecimal: 2.0.1
+
   parse-node-version@1.0.1: {}
 
   parse5@7.3.0:
@@ -3784,6 +4350,8 @@
       ansi-styles: 5.2.0
       react-is: 18.3.1
 
+  property-information@7.1.0: {}
+
   proxy-from-env@1.1.0: {}
 
   prr@1.0.1:
@@ -4121,6 +4689,24 @@
 
   react-is@18.3.1: {}
 
+  react-markdown@10.1.0(@types/react@19.1.4)(react@19.1.0):
+    dependencies:
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      '@types/react': 19.1.4
+      devlop: 1.1.0
+      hast-util-to-jsx-runtime: 2.3.6
+      html-url-attributes: 3.0.1
+      mdast-util-to-hast: 13.2.0
+      react: 19.1.0
+      remark-parse: 11.0.0
+      remark-rehype: 11.1.2
+      unified: 11.0.5
+      unist-util-visit: 5.0.0
+      vfile: 6.0.3
+    transitivePeerDependencies:
+      - supports-color
+
   react-redux@9.2.0(@types/react@19.1.4)(react@19.1.0)(redux@5.0.1):
     dependencies:
       '@types/use-sync-external-store': 0.0.6
@@ -4153,6 +4739,23 @@
 
   redux@5.0.1: {}
 
+  remark-parse@11.0.0:
+    dependencies:
+      '@types/mdast': 4.0.4
+      mdast-util-from-markdown: 2.0.2
+      micromark-util-types: 2.0.2
+      unified: 11.0.5
+    transitivePeerDependencies:
+      - supports-color
+
+  remark-rehype@11.1.2:
+    dependencies:
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      mdast-util-to-hast: 13.2.0
+      unified: 11.0.5
+      vfile: 6.0.3
+
   reselect@5.1.1: {}
 
   resize-observer-polyfill@1.5.1: {}
@@ -4232,6 +4835,8 @@
   source-map@0.6.1:
     optional: true
 
+  space-separated-tokens@2.0.2: {}
+
   stack-utils@2.0.6:
     dependencies:
       escape-string-regexp: 2.0.0
@@ -4242,12 +4847,25 @@
 
   string-convert@0.2.1: {}
 
+  stringify-entities@4.0.4:
+    dependencies:
+      character-entities-html4: 2.1.0
+      character-entities-legacy: 3.0.0
+
   strip-indent@3.0.0:
     dependencies:
       min-indent: 1.0.1
 
   strip-json-comments@3.1.1: {}
 
+  style-to-js@1.1.16:
+    dependencies:
+      style-to-object: 1.0.8
+
+  style-to-object@1.0.8:
+    dependencies:
+      inline-style-parser: 0.2.4
+
   stylis@4.3.6: {}
 
   supports-color@7.2.0:
@@ -4293,6 +4911,10 @@
     dependencies:
       punycode: 2.3.1
 
+  trim-lines@3.0.1: {}
+
+  trough@2.2.0: {}
+
   ts-api-utils@2.1.0(typescript@5.8.3):
     dependencies:
       typescript: 5.8.3
@@ -4317,6 +4939,39 @@
 
   undici-types@6.21.0: {}
 
+  unified@11.0.5:
+    dependencies:
+      '@types/unist': 3.0.3
+      bail: 2.0.2
+      devlop: 1.1.0
+      extend: 3.0.2
+      is-plain-obj: 4.1.0
+      trough: 2.2.0
+      vfile: 6.0.3
+
+  unist-util-is@6.0.0:
+    dependencies:
+      '@types/unist': 3.0.3
+
+  unist-util-position@5.0.0:
+    dependencies:
+      '@types/unist': 3.0.3
+
+  unist-util-stringify-position@4.0.0:
+    dependencies:
+      '@types/unist': 3.0.3
+
+  unist-util-visit-parents@6.0.1:
+    dependencies:
+      '@types/unist': 3.0.3
+      unist-util-is: 6.0.0
+
+  unist-util-visit@5.0.0:
+    dependencies:
+      '@types/unist': 3.0.3
+      unist-util-is: 6.0.0
+      unist-util-visit-parents: 6.0.1
+
   update-browserslist-db@1.1.3(browserslist@4.24.5):
     dependencies:
       browserslist: 4.24.5
@@ -4331,6 +4986,16 @@
     dependencies:
       react: 19.1.0
 
+  vfile-message@4.0.2:
+    dependencies:
+      '@types/unist': 3.0.3
+      unist-util-stringify-position: 4.0.0
+
+  vfile@6.0.3:
+    dependencies:
+      '@types/unist': 3.0.3
+      vfile-message: 4.0.2
+
   vite-node@3.1.4(@types/node@22.15.30)(less@4.3.0):
     dependencies:
       cac: 6.7.14
@@ -4365,7 +5030,7 @@
       fsevents: 2.3.3
       less: 4.3.0
 
-  vitest@3.1.4(@types/node@22.15.30)(jsdom@26.1.0)(less@4.3.0):
+  vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.30)(jsdom@26.1.0)(less@4.3.0):
     dependencies:
       '@vitest/expect': 3.1.4
       '@vitest/mocker': 3.1.4(vite@6.3.5(@types/node@22.15.30)(less@4.3.0))
@@ -4389,6 +5054,7 @@
       vite-node: 3.1.4(@types/node@22.15.30)(less@4.3.0)
       why-is-node-running: 2.3.0
     optionalDependencies:
+      '@types/debug': 4.1.12
       '@types/node': 22.15.30
       jsdom: 26.1.0
     transitivePeerDependencies:
@@ -4442,3 +5108,5 @@
   yallist@3.1.1: {}
 
   yocto-queue@0.1.0: {}
+
+  zwitch@2.0.4: {}
diff --git a/src/AppLayout.tsx b/src/AppLayout.tsx
index 99765e6..ba15c74 100644
--- a/src/AppLayout.tsx
+++ b/src/AppLayout.tsx
@@ -1,26 +1,43 @@
+// src/AppLayout.tsx
+
+import React, { useEffect, useMemo } from 'react';
 import { Outlet, useLocation, useNavigate } from 'react-router';
-import { Layout, Menu, Dropdown, Button, Flex } from 'antd';
-import { HomeOutlined, AppstoreOutlined, DownOutlined } from '@ant-design/icons';
-import { useEffect, useMemo } from 'react';
+import { Layout, Menu, Dropdown, Button, Flex, Space } from 'antd';
+import {
+    HomeOutlined,
+    AppstoreOutlined,
+    DownOutlined,
+    UserOutlined,
+    SettingOutlined,
+    LogoutOutlined
+} from '@ant-design/icons';
 import logo from "./assets/logo.png";
 import { useAppDispatch, useAppSelector } from './store/hooks';
 import { getUserInfo } from './feature/user/userSlice';
 import { logout } from './feature/auth/authSlice';
-const { Header } = Layout;
 
-const AppLayout = () => {
+const { Header, Content, Footer } = Layout;
+
+const AppLayout: React.FC = () => {
     const location = useLocation();
     const navigate = useNavigate();
-    const userState = useAppSelector(state => state.user);
     const dispatch = useAppDispatch();
 
-    useEffect(() => {
-        dispatch(getUserInfo())
-    }, [dispatch])
+    // Redux状态
+    const { isAuth } = useAppSelector(state => state.auth);
+    const userState = useAppSelector(state => state.user);
 
-    // 判断是否在登录、注册或找回密码页面
+    // 获取用户信息
+    useEffect(() => {
+        if (isAuth) {
+            dispatch(getUserInfo());
+        }
+    }, [dispatch, isAuth]);
+
+    // 判断是否在认证页面
     const isAuthPage = useMemo(() => {
-        return ['/login', '/register', '/forget'].includes(location.pathname);
+        const authPaths = ['/login', '/register', '/forget'];
+        return authPaths.includes(location.pathname);
     }, [location.pathname]);
 
     // 导航项配置
@@ -32,17 +49,24 @@
             path: '/',
         },
         {
-            key: 'tasks',
-            label: '任务清单',
+            key: 'works',
+            label: '作品',
             icon: <AppstoreOutlined />,
-            path: '/tasks',
+            path: '/works',
         },
     ];
 
+    // 获取当前选中的菜单项
+    const selectedKey = useMemo(() => {
+        if (location.pathname === '/') return 'home';
+        if (location.pathname.startsWith('/works')) return 'works';
+        return '';
+    }, [location.pathname]);
+
     // 处理登出逻辑
     const handleLogout = () => {
-        dispatch(logout())
-        navigate('/login');  // 重定向到登录页
+        dispatch(logout());
+        navigate('/login', { replace: true });
     };
 
     // 下拉菜单内容
@@ -50,66 +74,137 @@
         {
             key: 'profile',
             label: '个人中心',
+            icon: <UserOutlined />,
             onClick: () => navigate('/profile'),
         },
         {
+            key: 'settings',
+            label: '设置',
+            icon: <SettingOutlined />,
+            onClick: () => navigate('/settings'),
+        },
+        {
+            type: 'divider' as const,
+        },
+        {
             key: 'logout',
             label: '登出',
+            icon: <LogoutOutlined />,
             onClick: handleLogout,
+            danger: true,
         },
     ];
 
+    // 处理菜单点击
+    const handleMenuClick = (path: string) => {
+        navigate(path);
+    };
+
     return (
         <Layout style={{ minHeight: '100vh', width: '100%' }}>
-            <Header className="header" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
-                {/* logo */}
-                <Flex justify='center' align='center'>
-                    <img src={logo} alt="Logo" height='48px' />
-                    <div style={{ color: 'white', marginLeft: '10px' }}>
+            <Header
+                style={{
+                    display: 'flex',
+                    alignItems: 'center',
+                    justifyContent: 'space-between',
+                    padding: '0 24px',
+                    background: '#001529'
+                }}
+            >
+                {/* Logo区域 */}
+                <Flex
+                    align="center"
+                    style={{ cursor: 'pointer' }}
+                    onClick={() => navigate('/')}
+                >
+                    <img
+                        src={logo}
+                        alt="创驿Logo"
+                        style={{ height: 48 }}
+                    />
+                    <div style={{
+                        color: 'white',
+                        marginLeft: 12,
+                        fontSize: 18,
+                        fontWeight: 'bold'
+                    }}>
                         创驿
                     </div>
                 </Flex>
 
-                <div style={{
-                    height: '30px',
-                    width: '1px',
-                    backgroundColor: 'white',
-                    margin: '0 20px',
-                }}></div>
-
-                {/* 中间导航菜单 */}
-                <Menu
-                    mode="horizontal"
-                    theme="dark"
-                    selectedKeys={[location.pathname === '/' ? 'home' : location.pathname.slice(1)]}
-                    items={menuItems.map(item => ({
-                        ...item,
-                        onClick: () => navigate(item.path),
-                    }))}
-                    style={{ flex: 1 }}
-                />
-
-                {/* 右侧用户名和下拉菜单 */}
+                {/* 分割线 */}
                 {!isAuthPage && (
-                    <div style={{ display: 'flex', alignItems: 'center', color: 'white' }}>
-                        <span>{userState.username}</span>
+                    <div style={{
+                        height: 30,
+                        width: 1,
+                        backgroundColor: 'rgba(255, 255, 255, 0.3)',
+                        margin: '0 20px',
+                    }} />
+                )}
+
+                {/* 导航菜单 */}
+                {!isAuthPage && (
+                    <Menu
+                        mode="horizontal"
+                        theme="dark"
+                        selectedKeys={selectedKey ? [selectedKey] : []}
+                        items={menuItems.map(item => ({
+                            ...item,
+                            onClick: () => handleMenuClick(item.path),
+                        }))}
+                        style={{
+                            flex: 1,
+                            minWidth: 0,
+                            backgroundColor: 'transparent',
+                            borderBottom: 'none'
+                        }}
+                    />
+                )}
+
+                {/* 用户信息区域 */}
+                {!isAuthPage && isAuth && (
+                    <Space size="middle">
+                        <span style={{ color: 'white' }}>
+                            欢迎,{userState.username || '用户'}
+                        </span>
                         <Dropdown
-                            trigger={['click']}
                             menu={{ items: dropdownMenuItems }}
+                            trigger={['click']}
+                            placement="bottomRight"
                         >
-                            <Button type="text" icon={<DownOutlined />} style={{ marginLeft: '10px', color: 'white' }} />
+                            <Button
+                                type="text"
+                                style={{
+                                    color: 'white',
+                                    display: 'flex',
+                                    alignItems: 'center'
+                                }}
+                            >
+                                <DownOutlined />
+                            </Button>
                         </Dropdown>
-                    </div>
+                    </Space>
                 )}
             </Header>
-            <Layout.Content style={{ padding: '24px' }}>
+
+            <Content style={{
+                padding: isAuthPage ? 0 : 24,
+                minHeight: 'calc(100vh - 64px - 70px)' // 减去header和footer高度
+            }}>
                 <Outlet />
-            </Layout.Content>
-            <Layout.Footer style={{ textAlign: 'center' }}>
-                © 2025 创驿 - 愿做你创作路上的同行者
-            </Layout.Footer>
+            </Content>
+
+            {!isAuthPage && (
+                <Footer style={{
+                    textAlign: 'center',
+                    background: '#f0f2f5',
+                    padding: '24px 50px'
+                }}>
+                    © 2025 创驿 - 愿做你创作路上的同行者
+                </Footer>
+            )}
         </Layout>
     );
 };
 
-export default AppLayout;
+export default AppLayout;
\ No newline at end of file
diff --git a/src/api/interceptors.ts b/src/api/interceptors.ts
index bc2e566..3c0863b 100644
--- a/src/api/interceptors.ts
+++ b/src/api/interceptors.ts
@@ -7,7 +7,6 @@
     config.url = requestUrl.replace("/auth/","/");
   } else {
     const token = localStorage.getItem('token');
-    console.log(token);
     config.headers['token'] = `${token}`;
   }
   return config;
diff --git a/src/feature/auth/authSlice.ts b/src/feature/auth/authSlice.ts
index 607a6fd..289ce16 100644
--- a/src/feature/auth/authSlice.ts
+++ b/src/feature/auth/authSlice.ts
@@ -1,5 +1,7 @@
+// src/feature/auth/authSlice.ts
+
 import { createAsyncThunk, createSlice, type PayloadAction } from "@reduxjs/toolkit";
-import type { AuthState } from "../../store/types";
+import type { AuthState } from "./types";
 import type { LoginRequest } from "../../api/Auth/type";
 import AuthAPI from "../../api/Auth/AuthApi";
 
@@ -9,9 +11,9 @@
 const initialState: AuthState = {
   token: storedToken || '',
   loading: false,
-  isAuth: false,
-  error: ''
-}
+  isAuth: !!storedToken, // 如果有token就设为true
+  error: '',
+};
 
 export const loginUser = createAsyncThunk<
   {token: string},
@@ -33,17 +35,47 @@
   }
 );
 
+// 新增:从localStorage恢复登录状态
+export const loginFromLocalStorage = createAsyncThunk<
+  {token: string} | {empty: true},
+  void,
+  { rejectValue: string }
+>(
+  'auth/loginFromLocalStorage',
+  async (_, { rejectWithValue, dispatch }) => {
+    try {
+      const token = localStorage.getItem('token');
+      if (!token) {
+        // 返回空状态而不是错误
+        return { empty: true };
+      }
+      
+      // 直接使用refreshToken来验证token有效性
+      const result = await dispatch(refreshToken(token));
+      if (refreshToken.fulfilled.match(result)) {
+        // refresh成功,返回新的token
+        return { token: result.payload.token };
+      } else {
+        // refresh失败,token无效
+        localStorage.removeItem('token');
+        return rejectWithValue('token已失效,需要重新登录');
+      }
+    } catch {
+      localStorage.removeItem('token');
+      return rejectWithValue('恢复登录状态失败');
+    }
+  }
+);
+
 export const refreshToken = createAsyncThunk<
   {token: string},
   string,
   { rejectValue: string }
 >(
-
   'auth/refresh',
   async (oldToken: string, { rejectWithValue }) => {
     try {
       const response = await AuthAPI.refreshToken(oldToken);
-      console.log(response);
       if(response.data.code == 0)
         return {token: response.data.data};
       else 
@@ -61,42 +93,77 @@
     logout: (state) => {
       state.token = '';
       state.isAuth = false;
-      localStorage.clear()
-    },
-  },extraReducers: (builder) => {
-      // 处理登录的异步操作
-      builder
-        .addCase(loginUser.pending, (state) => {
-          state.loading = true;
-        })
-        .addCase(loginUser.fulfilled, (state, action: PayloadAction<{token: string}>) => {
-          state.loading = false;
-          state.token = action.payload.token;
-          state.isAuth = true;
-
-          localStorage.setItem('token', state.token);
-        })
-        .addCase(loginUser.rejected, (state, action) => {
-          state.loading = false;
-          state.error = action.payload ? action.payload : '' // 错误处理
-        })
-
-        // 处理刷新 token 的异步操作
-        .addCase(refreshToken.pending, (state) => {
-          state.loading = true;
-        })
-        .addCase(refreshToken.fulfilled, (state, action) => {
-          state.loading = false;
-          state.token = action.payload.token; 
-          localStorage.setItem('token', state.token);
-        })
-        .addCase(refreshToken.rejected, (state, action) => {
-          state.loading = false;
-          state.error = action.payload ? action.payload : ''
-        });
+      localStorage.clear();
     },
     
+    // 清除错误信息
+    clearError: (state) => {
+      state.error = '';
+    },
+  },
+  extraReducers: (builder) => {
+    // 处理普通登录的异步操作
+    builder
+      .addCase(loginUser.pending, (state) => {
+        state.loading = true;
+        state.error = '';
+      })
+      .addCase(loginUser.fulfilled, (state, action: PayloadAction<{token: string}>) => {
+        state.loading = false;
+        state.token = action.payload.token;
+        state.isAuth = true;
+        localStorage.setItem('token', state.token);
+      })
+      .addCase(loginUser.rejected, (state, action) => {
+        state.loading = false;
+        state.error = action.payload ? action.payload : '';
+      });
+      
+    // 处理从localStorage恢复登录状态
+    builder
+      .addCase(loginFromLocalStorage.pending, (state) => {
+        state.loading = true;
+        state.error = '';
+      })
+      .addCase(loginFromLocalStorage.fulfilled, (state, action) => {
+        state.loading = false;
+        if ('token' in action.payload) {
+          // 有token的情况
+          state.token = action.payload.token;
+          state.isAuth = true;
+        } else {
+          // 空token的情况
+          state.token = '';
+          state.isAuth = false;
+        }
+      })
+      .addCase(loginFromLocalStorage.rejected, (state, action) => {
+        state.loading = false;
+        state.token = '';
+        state.isAuth = false;
+        state.error = action.payload ? action.payload : '';
+        localStorage.removeItem('token');
+      });
+      
+    // 处理刷新 token 的异步操作
+    builder
+      .addCase(refreshToken.pending, (state) => {
+        state.loading = true;
+        state.error = '';
+      })
+      .addCase(refreshToken.fulfilled, (state, action) => {
+        state.loading = false;
+        state.token = action.payload.token;
+        state.isAuth = true;
+        localStorage.setItem('token', state.token);
+      })
+      .addCase(refreshToken.rejected, (state, action) => {
+        state.loading = false;
+        state.error = action.payload ? action.payload : '';
+        state.isAuth = false;
+      });
+  },
 });
 
-export const { logout } = authSlice.actions;
+export const { logout, clearError } = authSlice.actions;
 export default authSlice.reducer;
\ No newline at end of file
diff --git a/src/feature/auth/types.ts b/src/feature/auth/types.ts
new file mode 100644
index 0000000..6d91e01
--- /dev/null
+++ b/src/feature/auth/types.ts
@@ -0,0 +1,7 @@
+// 定义认证状态
+export interface AuthState {
+    token: string;
+    loading: boolean;
+    isAuth: boolean;
+    error: string
+}
\ No newline at end of file
diff --git a/src/feature/Home.tsx b/src/feature/home/Home.tsx
similarity index 100%
rename from src/feature/Home.tsx
rename to src/feature/home/Home.tsx
diff --git a/src/feature/user/userSlice.ts b/src/feature/user/userSlice.ts
index d6200af..c3f7e44 100644
--- a/src/feature/user/userSlice.ts
+++ b/src/feature/user/userSlice.ts
@@ -32,12 +32,8 @@
     async (_, { rejectWithValue }) => {
         const response = await UserAPi.getMe();
         if (response.data.code == 0) {
-            console.log("xixi")
-            console.log(response)
             return response.data.data;
         } else {
-            console.log("buxixi")
-            console.log(response)
             return rejectWithValue(response.data.message);
         }
     } 
diff --git a/src/feature/work/CreatWorkComponents.tsx b/src/feature/work/CreatWorkComponents.tsx
new file mode 100644
index 0000000..12766ee
--- /dev/null
+++ b/src/feature/work/CreatWorkComponents.tsx
@@ -0,0 +1,545 @@
+import React, { useState, useCallback } from 'react';
+import {
+    Form, Input, Select, Upload, Button, Card, message, Space, Modal,
+    Divider, Row, Col, Typography, Alert, List, Tag,
+    type FormInstance
+} from 'antd';
+import {
+    PlusOutlined, InboxOutlined, DeleteOutlined, EditOutlined,
+    CheckCircleOutlined, SendOutlined, FileTextOutlined
+} from '@ant-design/icons';
+import ReactMarkdown from 'react-markdown';
+import type {
+    UploadFile, UploadProps, UploadChangeParam, RcFile,
+} from 'antd/es/upload';
+import { type StepFormProps, type BasicInfo, ARTWORK_CATEGORIES, type VersionFormData } from './types';
+import { getBase64 } from './utils';
+
+const { TextArea } = Input;
+const { Dragger } = Upload;
+const { Title, Text, Paragraph } = Typography;
+
+// ==================== 描述组件 ====================
+interface DescriptionsProps {
+    bordered?: boolean;
+    column?: number;
+    children: React.ReactNode;
+}
+
+interface DescriptionsItemProps {
+    label: string;
+    children: React.ReactNode;
+}
+
+export const Descriptions: React.FC<DescriptionsProps> & {
+    Item: React.FC<DescriptionsItemProps>;
+} = ({ children }) => {
+    return <div style={{ marginBottom: 16 }}>{children}</div>;
+};
+
+Descriptions.Item = ({ label, children }: DescriptionsItemProps) => {
+    return (
+        <div style={{ marginBottom: 12 }}>
+            <Text strong style={{ marginRight: 16 }}>{label}:</Text>
+            <span>{children}</span>
+        </div>
+    );
+};
+
+// ==================== 步骤1:基础信息 ====================
+export const BasicInfoStep: React.FC<StepFormProps> = ({ data, onUpdate, onNext }) => {
+    const [form]: [FormInstance<BasicInfo>] = Form.useForm<BasicInfo>();
+    const [previewMode, setPreviewMode] = useState<boolean>(false);
+
+    const handleFinish = useCallback((values: BasicInfo) => {
+        onUpdate('basicInfo', values);
+        onNext?.();
+    }, [onUpdate, onNext]);
+
+    const handlePreview = useCallback(() => {
+        form.validateFields().then((values) => {
+            onUpdate('basicInfo', values);
+            setPreviewMode(true);
+        }).catch(() => {
+            message.error('请先填写完整信息');
+        });
+    }, [form, onUpdate]);
+
+    return (
+        <>
+            <Card>
+                <Form form={form} layout="vertical" initialValues={data.basicInfo} onFinish={handleFinish} autoComplete="off">
+                    <Form.Item
+                        label="作品名称"
+                        name="artworkName"
+                        rules={[
+                            { required: true, message: '请输入作品名称' },
+                            { min: 2, message: '作品名称至少2个字符' },
+                            { max: 50, message: '作品名称最多50个字符' },
+                        ]}
+                    >
+                        <Input placeholder="请输入作品名称,例如:未来城市概念设计" size="large" showCount maxLength={50} />
+                    </Form.Item>
+
+                    <Form.Item label="作品分类" name="artworkCategory" rules={[{ required: true, message: '请选择作品分类' }]}>
+                        <Select placeholder="请选择作品分类" size="large" options={ARTWORK_CATEGORIES} />
+                    </Form.Item>
+
+                    <Form.Item
+                        label="作品描述"
+                        name="artworkDescription"
+                        rules={[
+                            { required: true, message: '请输入作品描述' },
+                            { min: 20, message: '作品描述至少20个字符' },
+                            { max: 2000, message: '作品描述最多2000个字符' },
+                        ]}
+                        extra="支持 Markdown 格式,可以使用 # 标题、**粗体**、*斜体* 等格式"
+                    >
+                        <TextArea
+                            placeholder="请详细描述你的作品,包括创作理念、技术特点、使用说明等"
+                            rows={10}
+                            showCount
+                            maxLength={2000}
+                        />
+                    </Form.Item>
+
+                    <Form.Item>
+                        <Space size="middle">
+                            <Button type="primary" htmlType="submit" size="large">下一步</Button>
+                            <Button onClick={handlePreview} size="large">预览描述</Button>
+                        </Space>
+                    </Form.Item>
+                </Form>
+            </Card>
+
+            <Modal title="作品描述预览" open={previewMode} onCancel={() => setPreviewMode(false)} footer={null} width={800}>
+                <div style={{ maxHeight: '60vh', overflow: 'auto' }}>
+                    <ReactMarkdown>{form.getFieldValue('artworkDescription') || ''}</ReactMarkdown>
+                </div>
+            </Modal>
+        </>
+    );
+};
+
+// ==================== 步骤2:封面上传 ====================
+export const CoverUploadStep: React.FC<StepFormProps> = ({ data, onUpdate, onNext, onPrev }) => {
+    const [fileList, setFileList] = useState<UploadFile[]>(data.coverInfo.coverFile ? [data.coverInfo.coverFile] : []);
+    const [previewImage, setPreviewImage] = useState<string>('');
+    const [previewOpen, setPreviewOpen] = useState<boolean>(false);
+
+    const handleChange: UploadProps['onChange'] = useCallback((info: UploadChangeParam<UploadFile>) => {
+        const { fileList: newFileList } = info;
+        setFileList(newFileList);
+        onUpdate('coverInfo', { coverFile: newFileList[0] });
+    }, [onUpdate]);
+
+    const handlePreview = useCallback(async (file: UploadFile): Promise<void> => {
+        if (!file.url && !file.preview) {
+            file.preview = await getBase64(file.originFileObj as RcFile);
+        }
+        setPreviewImage(file.url || (file.preview as string));
+        setPreviewOpen(true);
+    }, []);
+
+    const beforeUpload = useCallback((file: RcFile): boolean => {
+        const isImage = file.type.startsWith('image/');
+        if (!isImage) {
+            message.error('只能上传图片文件!');
+            return false;
+        }
+        const isLt5M = file.size / 1024 / 1024 < 5;
+        if (!isLt5M) {
+            message.error('图片大小不能超过 5MB!');
+            return false;
+        }
+        return false;
+    }, []);
+
+    const handleNext = useCallback((): void => {
+        if (fileList.length === 0) {
+            message.error('请上传作品封面');
+            return;
+        }
+        onNext?.();
+    }, [fileList, onNext]);
+
+    return (
+        <Card>
+            <Alert
+                message="封面图片要求"
+                description={
+                    <ul style={{ marginBottom: 0, paddingLeft: 20 }}>
+                        <li>图片格式:JPG、PNG、GIF</li>
+                        <li>图片大小:不超过 5MB</li>
+                        <li>建议尺寸:宽高比 3:4,最小分辨率 600x800</li>
+                        <li>内容要求:清晰展示作品特色,避免模糊或像素化</li>
+                    </ul>
+                }
+                type="info"
+                showIcon
+                style={{ marginBottom: 24 }}
+            />
+
+            <Upload
+                listType="picture-card"
+                fileList={fileList}
+                onChange={handleChange}
+                onPreview={handlePreview}
+                beforeUpload={beforeUpload}
+                maxCount={1}
+                accept="image/*"
+            >
+                {fileList.length === 0 && (
+                    <div>
+                        <PlusOutlined />
+                        <div style={{ marginTop: 8 }}>上传封面</div>
+                    </div>
+                )}
+            </Upload>
+
+            <Modal open={previewOpen} title="封面预览" footer={null} onCancel={() => setPreviewOpen(false)}>
+                <img alt="封面预览" style={{ width: '100%' }} src={previewImage} />
+            </Modal>
+
+            <Divider />
+            <Space size="middle">
+                <Button onClick={onPrev} size="large">上一步</Button>
+                <Button type="primary" onClick={handleNext} size="large">下一步</Button>
+            </Space>
+        </Card>
+    );
+};
+
+// ==================== 版本管理相关组件 ====================
+const VersionItem: React.FC<{
+    version: VersionFormData;
+    index: number;
+    onEdit: (index: number) => void;
+    onDelete: (index: number) => void;
+}> = ({ version, index, onEdit, onDelete }) => {
+    return (
+        <Row align="middle">
+            <Col span={20}>
+                <Space direction="vertical" style={{ width: '100%' }}>
+                    <Space>
+                        <Tag color="blue">v{version.version}</Tag>
+                        <Text strong>{version.versionDescription}</Text>
+                    </Space>
+                    {version.seedFile && (
+                        <Space>
+                            <FileTextOutlined />
+                            <Text type="secondary">{version.seedFile.name}</Text>
+                        </Space>
+                    )}
+                </Space>
+            </Col>
+            <Col span={4} style={{ textAlign: 'right' }}>
+                <Space>
+                    <Button type="text" icon={<EditOutlined />} onClick={() => onEdit(index)} />
+                    <Button type="text" danger icon={<DeleteOutlined />} onClick={() => onDelete(index)} />
+                </Space>
+            </Col>
+        </Row>
+    );
+};
+
+const VersionEditForm: React.FC<{
+    form: FormInstance<VersionFormData>;
+    version: VersionFormData;
+    onSave: () => void;
+    onCancel: () => void;
+    onFileChange: (file: UploadFile | undefined) => void;
+}> = ({ form, version, onSave, onCancel, onFileChange }) => {
+    const beforeUpload = useCallback((file: RcFile): boolean => {
+        const isLt100M = file.size / 1024 / 1024 < 100;
+        if (!isLt100M) {
+            message.error('种子文件大小不能超过 100MB!');
+            return false;
+        }
+        return false;
+    }, []);
+
+    return (
+        <Form form={form} layout="vertical" initialValues={version}>
+            <Row gutter={16}>
+                <Col span={6}>
+                    <Form.Item label="版本号" name="version" rules={[{ required: true, message: '请输入版本号' }]}>
+                        <Input placeholder="例如:1.0" />
+                    </Form.Item>
+                </Col>
+                <Col span={18}>
+                    <Form.Item
+                        label="版本描述"
+                        name="versionDescription"
+                        rules={[
+                            { required: true, message: '请输入版本描述' },
+                            { min: 10, message: '版本描述至少10个字符' },
+                        ]}
+                    >
+                        <TextArea placeholder="描述此版本的更新内容、新增功能等" rows={3} showCount maxLength={500} />
+                    </Form.Item>
+                </Col>
+            </Row>
+
+            <Form.Item label="种子文件">
+                <Dragger
+                    maxCount={1}
+                    beforeUpload={beforeUpload}
+                    fileList={version.seedFile ? [version.seedFile] : []}
+                    onChange={({ fileList }) => onFileChange(fileList[0])}
+                    onRemove={() => onFileChange(undefined)}
+                >
+                    <p className="ant-upload-drag-icon"><InboxOutlined /></p>
+                    <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
+                    <p className="ant-upload-hint">支持单个文件上传,文件大小不超过 100MB</p>
+                </Dragger>
+            </Form.Item>
+
+            <Space>
+                <Button type="primary" onClick={onSave}>保存</Button>
+                <Button onClick={onCancel}>取消</Button>
+            </Space>
+        </Form>
+    );
+};
+
+// ==================== 步骤3:版本管理 ====================
+export const VersionManagementStep: React.FC<StepFormProps> = ({ data, onUpdate, onNext, onPrev }) => {
+    const [versions, setVersions] = useState<VersionFormData[]>(
+        data.versions.length > 0 ? data.versions : [{ version: '1.0', versionDescription: '', seedFile: undefined }]
+    );
+    const [editingIndex, setEditingIndex] = useState<number | null>(null);
+    const [form]: [FormInstance<VersionFormData>] = Form.useForm<VersionFormData>();
+
+    const handleAddVersion = useCallback(() => {
+        const newVersion: VersionFormData = {
+            version: `${versions.length + 1}.0`,
+            versionDescription: '',
+            seedFile: undefined,
+        };
+        setVersions([...versions, newVersion]);
+        setEditingIndex(versions.length);
+    }, [versions]);
+
+    const handleSaveVersion = useCallback((index: number) => {
+        form.validateFields().then((values) => {
+            const newVersions = [...versions];
+            newVersions[index] = { ...newVersions[index], ...values };
+            setVersions(newVersions);
+            setEditingIndex(null);
+            form.resetFields();
+            message.success('版本信息已保存');
+        }).catch(() => {
+            message.error('请完整填写版本信息');
+        });
+    }, [form, versions]);
+
+    const handleDeleteVersion = useCallback((index: number) => {
+        Modal.confirm({
+            title: '确认删除',
+            content: '确定要删除这个版本吗?',
+            onOk: () => {
+                const newVersions = versions.filter((_, i) => i !== index);
+                setVersions(newVersions);
+                if (editingIndex === index) {
+                    setEditingIndex(null);
+                }
+            },
+        });
+    }, [versions, editingIndex]);
+
+    const handleFileChange = useCallback((index: number, file: UploadFile | undefined) => {
+        const newVersions = [...versions];
+        newVersions[index].seedFile = file;
+        setVersions(newVersions);
+    }, [versions]);
+
+    const handleNext = useCallback(() => {
+        if (versions.length === 0) {
+            message.error('至少需要添加一个版本');
+            return;
+        }
+
+        const incompleteVersion = versions.find((v, index) =>
+            !v.version || !v.versionDescription || !v.seedFile || index === editingIndex
+        );
+
+        if (incompleteVersion) {
+            message.error('请完成所有版本的信息填写');
+            return;
+        }
+
+        onUpdate('versions', versions);
+        onNext?.();
+    }, [versions, editingIndex, onUpdate, onNext]);
+
+    return (
+        <Card>
+            <div style={{ marginBottom: 16 }}>
+                <Title level={4}>版本列表</Title>
+                <Paragraph type="secondary">每个版本需要包含版本号、版本描述和种子文件</Paragraph>
+            </div>
+
+            <List
+                dataSource={versions}
+                renderItem={(version, index) => (
+                    <List.Item
+                        key={index}
+                        style={{
+                            background: editingIndex === index ? '#fafafa' : 'transparent',
+                            padding: 16,
+                            marginBottom: 16,
+                            border: '1px solid #f0f0f0',
+                            borderRadius: 8,
+                        }}
+                    >
+                        {editingIndex === index ? (
+                            <VersionEditForm
+                                form={form}
+                                version={version}
+                                onSave={() => handleSaveVersion(index)}
+                                onCancel={() => setEditingIndex(null)}
+                                onFileChange={(file) => handleFileChange(index, file)}
+                            />
+                        ) : (
+                            <VersionItem
+                                version={version}
+                                index={index}
+                                onEdit={(idx) => {
+                                    setEditingIndex(idx);
+                                    form.setFieldsValue(version);
+                                }}
+                                onDelete={handleDeleteVersion}
+                            />
+                        )}
+                    </List.Item>
+                )}
+            />
+
+            {editingIndex === null && (
+                <Button
+                    type="dashed"
+                    onClick={handleAddVersion}
+                    style={{ width: '100%', marginBottom: 24 }}
+                    icon={<PlusOutlined />}
+                >
+                    添加版本
+                </Button>
+            )}
+
+            <Divider />
+            <Space size="middle">
+                <Button onClick={onPrev} size="large">上一步</Button>
+                <Button type="primary" onClick={handleNext} size="large">下一步</Button>
+            </Space>
+        </Card>
+    );
+};
+
+// ==================== 步骤4:确认发布 ====================
+export const ConfirmPublishStep: React.FC<StepFormProps & { onPublish: () => void }> = ({ data, onPrev, onPublish }) => {
+    const [publishing, setPublishing] = useState<boolean>(false);
+
+    const handlePublish = useCallback(async () => {
+        setPublishing(true);
+        try {
+            await new Promise(resolve => setTimeout(resolve, 2000));
+            message.success('作品发布成功!');
+            onPublish();
+        } catch {
+            message.error('发布失败,请重试');
+        } finally {
+            setPublishing(false);
+        }
+    }, [onPublish]);
+
+    return (
+        <Card>
+            <Title level={3} style={{ marginBottom: 24 }}>
+                <CheckCircleOutlined style={{ color: '#52c41a', marginRight: 8 }} />
+                确认发布信息
+            </Title>
+
+            <div style={{ marginBottom: 32 }}>
+                <Title level={4}>基础信息</Title>
+                <Descriptions bordered column={1}>
+                    <Descriptions.Item label="作品名称">{data.basicInfo.artworkName}</Descriptions.Item>
+                    <Descriptions.Item label="作品分类">
+                        <Tag color="blue">{data.basicInfo.artworkCategory}</Tag>
+                    </Descriptions.Item>
+                    <Descriptions.Item label="作品描述">
+                        <div style={{ maxHeight: 200, overflow: 'auto' }}>
+                            <ReactMarkdown>{data.basicInfo.artworkDescription}</ReactMarkdown>
+                        </div>
+                    </Descriptions.Item>
+                </Descriptions>
+            </div>
+
+            <div style={{ marginBottom: 32 }}>
+                <Title level={4}>作品封面</Title>
+                {data.coverInfo.coverFile && (
+                    <img
+                        src={data.coverInfo.coverFile.thumbUrl || data.coverInfo.coverFile.url}
+                        alt="作品封面"
+                        style={{ maxWidth: 300, maxHeight: 400, objectFit: 'cover' }}
+                    />
+                )}
+            </div>
+
+            <div style={{ marginBottom: 32 }}>
+                <Title level={4}>版本信息</Title>
+                <List
+                    dataSource={data.versions}
+                    renderItem={(version) => (
+                        <List.Item>
+                            <List.Item.Meta
+                                title={
+                                    <Space>
+                                        <Tag color="green">v{version.version}</Tag>
+                                        <Text>{version.versionDescription}</Text>
+                                    </Space>
+                                }
+                                description={
+                                    version.seedFile && (
+                                        <Space>
+                                            <FileTextOutlined />
+                                            <Text type="secondary">{version.seedFile.name}</Text>
+                                        </Space>
+                                    )
+                                }
+                            />
+                        </List.Item>
+                    )}
+                />
+            </div>
+
+            <Alert
+                message="发布须知"
+                description={
+                    <ul style={{ marginBottom: 0, paddingLeft: 20 }}>
+                        <li>发布后的作品将公开展示,所有用户都可以查看和下载</li>
+                        <li>请确保作品内容符合社区规范,不包含违法违规内容</li>
+                        <li>发布后您仍可以编辑作品信息和添加新版本</li>
+                        <li>请尊重他人知识产权,确保作品为原创或已获得授权</li>
+                    </ul>
+                }
+                type="warning"
+                showIcon
+                style={{ marginBottom: 24 }}
+            />
+
+            <Space size="middle">
+                <Button onClick={onPrev} size="large">上一步</Button>
+                <Button
+                    type="primary"
+                    onClick={handlePublish}
+                    loading={publishing}
+                    icon={<SendOutlined />}
+                    size="large"
+                >
+                    确认发布
+                </Button>
+            </Space>
+        </Card>
+    );
+};
\ No newline at end of file
diff --git a/src/feature/work/CreateWork.tsx b/src/feature/work/CreateWork.tsx
new file mode 100644
index 0000000..5e97433
--- /dev/null
+++ b/src/feature/work/CreateWork.tsx
@@ -0,0 +1,53 @@
+import React, { useMemo } from 'react';
+import { Layout, Steps, Card, Typography } from 'antd';
+import { FileTextOutlined, FileImageOutlined, SaveOutlined, SendOutlined } from '@ant-design/icons';
+import { BasicInfoStep, CoverUploadStep, VersionManagementStep, ConfirmPublishStep } from './CreatWorkComponents';
+import { useCreateWorkForm } from './hooks';
+
+
+const { Content } = Layout;
+const { Title, Paragraph } = Typography;
+
+const CreateWork: React.FC = () => {
+    const { currentStep, formData, handleUpdateFormData, handleNext, handlePrev, handlePublish } = useCreateWorkForm();
+
+    const steps = useMemo(() => [
+        { title: '基础信息', description: '填写作品基本信息', icon: <FileTextOutlined /> },
+        { title: '上传封面', description: '上传作品封面图片', icon: <FileImageOutlined /> },
+        { title: '版本管理', description: '添加作品版本和文件', icon: <SaveOutlined /> },
+        { title: '确认发布', description: '检查并发布作品', icon: <SendOutlined /> },
+    ], []);
+
+    const renderStepContent = useMemo(() => {
+        const commonProps = { data: formData, onUpdate: handleUpdateFormData, onNext: handleNext, onPrev: handlePrev };
+
+        switch (currentStep) {
+            case 0: return <BasicInfoStep {...commonProps} />;
+            case 1: return <CoverUploadStep {...commonProps} />;
+            case 2: return <VersionManagementStep {...commonProps} />;
+            case 3: return <ConfirmPublishStep {...commonProps} onPublish={handlePublish} />;
+            default: return null;
+        }
+    }, [currentStep, formData, handleUpdateFormData, handleNext, handlePrev, handlePublish]);
+
+    return (
+        <Layout style={{ minHeight: '100vh', backgroundColor: '#f5f5f5' }}>
+            <Content style={{ padding: '20px' }}>
+                <div style={{ maxWidth: 1000, margin: '0 auto' }}>
+                    <Card style={{ marginBottom: 24 }}>
+                        <Title level={2} style={{ marginBottom: 8 }}>创建新作品</Title>
+                        <Paragraph type="secondary">通过以下步骤发布您的创意作品,与社区分享您的才华</Paragraph>
+                    </Card>
+
+                    <Card style={{ marginBottom: 24 }}>
+                        <Steps current={currentStep} items={steps} />
+                    </Card>
+
+                    {renderStepContent}
+                </div>
+            </Content>
+        </Layout>
+    );
+};
+
+export default CreateWork;
\ No newline at end of file
diff --git a/src/feature/work/EditWork.tsx b/src/feature/work/EditWork.tsx
new file mode 100644
index 0000000..f56d42a
--- /dev/null
+++ b/src/feature/work/EditWork.tsx
@@ -0,0 +1,753 @@
+import React, { useState, useCallback } from 'react';
+import {
+    Modal, Form, Input, Upload, Button, message, Space, Card,
+    Typography, Alert, List, Tag, Popconfirm, Row, Col,
+    type FormInstance
+} from 'antd';
+import {
+    EditOutlined, DeleteOutlined, PlusOutlined, InboxOutlined,
+    SaveOutlined, FileTextOutlined, UserOutlined
+} from '@ant-design/icons';
+import ReactMarkdown from 'react-markdown';
+import type {
+    UploadFile, UploadProps, UploadChangeParam, RcFile,
+} from 'antd/es/upload';
+import type {
+    ArtworkData, VersionFormData, Comment,
+} from './types';
+
+const { TextArea } = Input;
+const { Dragger } = Upload;
+const { Text } = Typography;
+
+// ==================== 工具函数 ====================
+const getBase64 = (file: RcFile): Promise<string> =>
+    new Promise((resolve, reject) => {
+        const reader = new FileReader();
+        reader.readAsDataURL(file);
+        reader.onload = (): void => resolve(reader.result as string);
+        reader.onerror = (error): void => reject(error);
+    });
+
+// ==================== 类型定义 ====================
+interface EditCoverProps {
+    visible: boolean;
+    currentCover: string;
+    onCancel: () => void;
+    onSave: (coverUrl: string) => Promise<void>;
+}
+
+interface EditDescriptionProps {
+    visible: boolean;
+    currentDescription: string;
+    onCancel: () => void;
+    onSave: (description: string) => Promise<void>;
+}
+
+interface EditVersionsProps {
+    visible: boolean;
+    versions: VersionFormData[];
+    onCancel: () => void;
+    onSave: (versions: VersionFormData[]) => Promise<void>;
+}
+
+interface CommentItemProps {
+    comment: Comment;
+    isAuthor: boolean;
+    onDelete: (commentId: string) => Promise<void>;
+    level?: number;
+}
+
+interface EditWorkControlsProps {
+    artwork: ArtworkData;
+    isAuthor: boolean;
+    onUpdate: (updatedArtwork: Partial<ArtworkData>) => Promise<void>;
+    onDeleteComment: (commentId: string) => Promise<void>;
+}
+
+interface VersionItemProps {
+    version: VersionFormData;
+    index: number;
+    onEdit: (index: number) => void;
+    onDelete: (index: number) => void;
+}
+
+interface VersionEditFormProps {
+    form: FormInstance<VersionFormData>;
+    version: VersionFormData;
+    onSave: () => void;
+    onCancel: () => void;
+    onFileChange: (file: UploadFile | undefined) => void;
+}
+
+// ==================== 封面编辑组件 ====================
+export const EditWorkCover: React.FC<EditCoverProps> = ({
+    visible,
+    currentCover,
+    onCancel,
+    onSave
+}) => {
+    const [fileList, setFileList] = useState<UploadFile[]>([]);
+    const [previewImage, setPreviewImage] = useState<string>('');
+    const [previewOpen, setPreviewOpen] = useState<boolean>(false);
+    const [uploading, setUploading] = useState<boolean>(false);
+
+    const handleChange: UploadProps['onChange'] = useCallback((info: UploadChangeParam<UploadFile>): void => {
+        setFileList(info.fileList);
+    }, []);
+
+    const handlePreview = useCallback(async (file: UploadFile): Promise<void> => {
+        if (!file.url && !file.preview) {
+            file.preview = await getBase64(file.originFileObj as RcFile);
+        }
+        setPreviewImage(file.url || (file.preview as string));
+        setPreviewOpen(true);
+    }, []);
+
+    const beforeUpload = useCallback((file: RcFile): boolean => {
+        const isImage = file.type.startsWith('image/');
+        if (!isImage) {
+            message.error('只能上传图片文件!');
+            return false;
+        }
+        const isLt5M = file.size / 1024 / 1024 < 5;
+        if (!isLt5M) {
+            message.error('图片大小不能超过 5MB!');
+            return false;
+        }
+        return false; // 阻止自动上传
+    }, []);
+
+    const handleSave = useCallback(async (): Promise<void> => {
+        if (fileList.length === 0) {
+            message.error('请选择要上传的封面图片');
+            return;
+        }
+
+        setUploading(true);
+        try {
+            // 模拟上传过程
+            const file = fileList[0];
+            const coverUrl = file.preview || URL.createObjectURL(file.originFileObj as RcFile);
+
+            await onSave(coverUrl);
+            message.success('封面更新成功!');
+            onCancel();
+        } catch {
+            message.error('封面更新失败,请重试');
+        } finally {
+            setUploading(false);
+        }
+    }, [fileList, onSave, onCancel]);
+
+    return (
+        <>
+            <Modal
+                title="编辑作品封面"
+                open={visible}
+                onCancel={onCancel}
+                footer={[
+                    <Button key="cancel" onClick={onCancel}>
+                        取消
+                    </Button>,
+                    <Button
+                        key="save"
+                        type="primary"
+                        loading={uploading}
+                        onClick={handleSave}
+                        icon={<SaveOutlined />}
+                    >
+                        保存
+                    </Button>,
+                ]}
+                width={600}
+            >
+                <div style={{ marginBottom: 16 }}>
+                    <Text strong>当前封面:</Text>
+                    <div style={{ marginTop: 8 }}>
+                        <img
+                            src={currentCover}
+                            alt="当前封面"
+                            style={{ maxWidth: '100%', maxHeight: 200, objectFit: 'cover' }}
+                        />
+                    </div>
+                </div>
+
+                <Alert
+                    message="新封面要求"
+                    description="图片格式:JPG、PNG、GIF;大小不超过 5MB;建议尺寸:宽高比 3:4"
+                    type="info"
+                    showIcon
+                    style={{ marginBottom: 16 }}
+                />
+
+                <Upload
+                    listType="picture-card"
+                    fileList={fileList}
+                    onChange={handleChange}
+                    onPreview={handlePreview}
+                    beforeUpload={beforeUpload}
+                    maxCount={1}
+                    accept="image/*"
+                >
+                    {fileList.length === 0 && (
+                        <div>
+                            <PlusOutlined />
+                            <div style={{ marginTop: 8 }}>选择新封面</div>
+                        </div>
+                    )}
+                </Upload>
+            </Modal>
+
+            <Modal
+                open={previewOpen}
+                title="图片预览"
+                footer={null}
+                onCancel={(): void => setPreviewOpen(false)}
+            >
+                <img alt="预览" style={{ width: '100%' }} src={previewImage} />
+            </Modal>
+        </>
+    );
+};
+
+// ==================== 作品描述编辑组件 ====================
+export const EditWorkDescription: React.FC<EditDescriptionProps> = ({
+    visible,
+    currentDescription,
+    onCancel,
+    onSave
+}) => {
+    const [form] = Form.useForm<{ description: string }>();
+    const [previewMode, setPreviewMode] = useState<boolean>(false);
+    const [saving, setSaving] = useState<boolean>(false);
+
+    const handleSave = useCallback(async (): Promise<void> => {
+        try {
+            const values = await form.validateFields();
+            setSaving(true);
+            await onSave(values.description);
+            message.success('作品描述更新成功!');
+            onCancel();
+        } catch (error) {
+            if (error && typeof error === 'object' && 'errorFields' in error) {
+                message.error('请检查输入内容');
+            } else {
+                message.error('更新失败,请重试');
+            }
+        } finally {
+            setSaving(false);
+        }
+    }, [form, onSave, onCancel]);
+
+    const handlePreview = useCallback((): void => {
+        form.validateFields().then(() => {
+            setPreviewMode(true);
+        }).catch(() => {
+            message.error('请先填写完整信息');
+        });
+    }, [form]);
+
+    return (
+        <>
+            <Modal
+                title="编辑作品描述"
+                open={visible}
+                onCancel={onCancel}
+                footer={[
+                    <Button key="preview" onClick={handlePreview}>
+                        预览
+                    </Button>,
+                    <Button key="cancel" onClick={onCancel}>
+                        取消
+                    </Button>,
+                    <Button
+                        key="save"
+                        type="primary"
+                        loading={saving}
+                        onClick={handleSave}
+                        icon={<SaveOutlined />}
+                    >
+                        保存
+                    </Button>,
+                ]}
+                width={800}
+            >
+                <Form
+                    form={form}
+                    layout="vertical"
+                    initialValues={{ description: currentDescription }}
+                >
+                    <Form.Item
+                        label="作品描述"
+                        name="description"
+                        rules={[
+                            { required: true, message: '请输入作品描述' },
+                            { min: 20, message: '作品描述至少20个字符' },
+                            { max: 2000, message: '作品描述最多2000个字符' },
+                        ]}
+                        extra="支持 Markdown 格式,可以使用 # 标题、**粗体**、*斜体* 等格式"
+                    >
+                        <TextArea
+                            placeholder="请详细描述你的作品,包括创作理念、技术特点、使用说明等"
+                            rows={12}
+                            showCount
+                            maxLength={2000}
+                        />
+                    </Form.Item>
+                </Form>
+            </Modal>
+
+            <Modal
+                title="作品描述预览"
+                open={previewMode}
+                onCancel={(): void => setPreviewMode(false)}
+                footer={null}
+                width={800}
+            >
+                <div style={{ maxHeight: '60vh', overflow: 'auto' }}>
+                    <ReactMarkdown>{form.getFieldValue('description') || ''}</ReactMarkdown>
+                </div>
+            </Modal>
+        </>
+    );
+};
+
+// ==================== 版本编辑相关组件 ====================
+const VersionItem: React.FC<VersionItemProps> = ({
+    version,
+    index,
+    onEdit,
+    onDelete
+}) => {
+    return (
+        <Row align="middle" style={{ width: '100%' }}>
+            <Col span={20}>
+                <Space direction="vertical" style={{ width: '100%' }}>
+                    <Space>
+                        <Tag color="blue">v{version.version}</Tag>
+                        <Text strong>{version.versionDescription}</Text>
+                    </Space>
+                    {version.seedFile && (
+                        <Space>
+                            <FileTextOutlined />
+                            <Text type="secondary">{version.seedFile.name}</Text>
+                        </Space>
+                    )}
+                </Space>
+            </Col>
+            <Col span={4} style={{ textAlign: 'right' }}>
+                <Space>
+                    <Button
+                        type="text"
+                        icon={<EditOutlined />}
+                        onClick={(): void => onEdit(index)}
+                    />
+                    <Popconfirm
+                        title="确定要删除这个版本吗?"
+                        onConfirm={(): void => onDelete(index)}
+                        okText="确定"
+                        cancelText="取消"
+                    >
+                        <Button type="text" danger icon={<DeleteOutlined />} />
+                    </Popconfirm>
+                </Space>
+            </Col>
+        </Row>
+    );
+};
+
+const VersionEditForm: React.FC<VersionEditFormProps> = ({
+    form,
+    version,
+    onSave,
+    onCancel,
+    onFileChange
+}) => {
+    const beforeUpload = useCallback((file: RcFile): boolean => {
+        const isLt100M = file.size / 1024 / 1024 < 100;
+        if (!isLt100M) {
+            message.error('种子文件大小不能超过 100MB!');
+            return false;
+        }
+        return false;
+    }, []);
+
+    return (
+        <div style={{ width: '100%' }}>
+            <Form form={form} layout="vertical" initialValues={version}>
+                <Row gutter={16}>
+                    <Col span={6}>
+                        <Form.Item
+                            label="版本号"
+                            name="version"
+                            rules={[{ required: true, message: '请输入版本号' }]}
+                        >
+                            <Input placeholder="例如:1.0" />
+                        </Form.Item>
+                    </Col>
+                    <Col span={18}>
+                        <Form.Item
+                            label="版本描述"
+                            name="versionDescription"
+                            rules={[
+                                { required: true, message: '请输入版本描述' },
+                                { min: 10, message: '版本描述至少10个字符' },
+                            ]}
+                        >
+                            <TextArea
+                                placeholder="描述此版本的更新内容、新增功能等"
+                                rows={3}
+                                showCount
+                                maxLength={500}
+                            />
+                        </Form.Item>
+                    </Col>
+                </Row>
+
+                <Form.Item label="种子文件">
+                    <Dragger
+                        maxCount={1}
+                        beforeUpload={beforeUpload}
+                        fileList={version.seedFile ? [version.seedFile] : []}
+                        onChange={({ fileList }): void => onFileChange(fileList[0])}
+                        onRemove={(): void => onFileChange(undefined)}
+                    >
+                        <p className="ant-upload-drag-icon"><InboxOutlined /></p>
+                        <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
+                        <p className="ant-upload-hint">支持单个文件上传,文件大小不超过 100MB</p>
+                    </Dragger>
+                </Form.Item>
+
+                <Space>
+                    <Button type="primary" onClick={onSave}>
+                        保存
+                    </Button>
+                    <Button onClick={onCancel}>
+                        取消
+                    </Button>
+                </Space>
+            </Form>
+        </div>
+    );
+};
+
+// ==================== 版本管理组件 ====================
+export const EditWorkVersions: React.FC<EditVersionsProps> = ({
+    visible,
+    versions,
+    onCancel,
+    onSave
+}) => {
+    const [localVersions, setLocalVersions] = useState<VersionFormData[]>(versions);
+    const [editingIndex, setEditingIndex] = useState<number | null>(null);
+    const [form] = Form.useForm<VersionFormData>();
+    const [saving, setSaving] = useState<boolean>(false);
+
+    const handleAddVersion = useCallback((): void => {
+        const newVersion: VersionFormData = {
+            version: `${localVersions.length + 1}.0`,
+            versionDescription: '',
+            seedFile: undefined,
+        };
+        setLocalVersions([...localVersions, newVersion]);
+        setEditingIndex(localVersions.length);
+    }, [localVersions]);
+
+    const handleSaveVersion = useCallback((index: number): void => {
+        form.validateFields().then((values) => {
+            const newVersions = [...localVersions];
+            newVersions[index] = { ...newVersions[index], ...values };
+            setLocalVersions(newVersions);
+            setEditingIndex(null);
+            form.resetFields();
+            message.success('版本信息已保存');
+        }).catch(() => {
+            message.error('请完整填写版本信息');
+        });
+    }, [form, localVersions]);
+
+    const handleDeleteVersion = useCallback((index: number): void => {
+        const newVersions = localVersions.filter((_, i) => i !== index);
+        setLocalVersions(newVersions);
+        if (editingIndex === index) {
+            setEditingIndex(null);
+        }
+    }, [localVersions, editingIndex]);
+
+    const handleFileChange = useCallback((index: number, file: UploadFile | undefined): void => {
+        const newVersions = [...localVersions];
+        newVersions[index].seedFile = file;
+        setLocalVersions(newVersions);
+    }, [localVersions]);
+
+    const handleSave = useCallback(async (): Promise<void> => {
+        if (localVersions.length === 0) {
+            message.error('至少需要保留一个版本');
+            return;
+        }
+
+        const incompleteVersion = localVersions.find((v, index) =>
+            !v.version || !v.versionDescription || !v.seedFile || index === editingIndex
+        );
+
+        if (incompleteVersion) {
+            message.error('请完成所有版本的信息填写');
+            return;
+        }
+
+        setSaving(true);
+        try {
+            await onSave(localVersions);
+            message.success('版本信息更新成功!');
+            onCancel();
+        } catch {
+            message.error('更新失败,请重试');
+        } finally {
+            setSaving(false);
+        }
+    }, [localVersions, editingIndex, onSave, onCancel]);
+
+    return (
+        <Modal
+            title="编辑版本信息"
+            open={visible}
+            onCancel={onCancel}
+            footer={[
+                <Button key="cancel" onClick={onCancel}>
+                    取消
+                </Button>,
+                <Button
+                    key="save"
+                    type="primary"
+                    loading={saving}
+                    onClick={handleSave}
+                    icon={<SaveOutlined />}
+                >
+                    保存所有更改
+                </Button>,
+            ]}
+            width={900}
+        >
+            <div style={{ maxHeight: '60vh', overflow: 'auto' }}>
+                <List
+                    dataSource={localVersions}
+                    renderItem={(version, index): React.ReactElement => (
+                        <List.Item
+                            key={index}
+                            style={{
+                                background: editingIndex === index ? '#fafafa' : 'transparent',
+                                padding: 16,
+                                marginBottom: 16,
+                                border: '1px solid #f0f0f0',
+                                borderRadius: 8,
+                            }}
+                        >
+                            {editingIndex === index ? (
+                                <VersionEditForm
+                                    form={form}
+                                    version={version}
+                                    onSave={(): void => handleSaveVersion(index)}
+                                    onCancel={(): void => setEditingIndex(null)}
+                                    onFileChange={(file): void => handleFileChange(index, file)}
+                                />
+                            ) : (
+                                <VersionItem
+                                    version={version}
+                                    index={index}
+                                    onEdit={(idx): void => {
+                                        setEditingIndex(idx);
+                                        form.setFieldsValue(version);
+                                    }}
+                                    onDelete={handleDeleteVersion}
+                                />
+                            )}
+                        </List.Item>
+                    )}
+                />
+
+                {editingIndex === null && (
+                    <Button
+                        type="dashed"
+                        onClick={handleAddVersion}
+                        style={{ width: '100%', marginTop: 16 }}
+                        icon={<PlusOutlined />}
+                    >
+                        添加新版本
+                    </Button>
+                )}
+            </div>
+        </Modal>
+    );
+};
+
+// ==================== 评论管理组件 ====================
+export const EditWorkComment: React.FC<CommentItemProps> = ({
+    comment,
+    isAuthor,
+    onDelete,
+    level = 0
+}) => {
+    const [deleting, setDeleting] = useState<boolean>(false);
+
+    const handleDelete = useCallback(async (): Promise<void> => {
+        if (!comment.id) return;
+
+        setDeleting(true);
+        try {
+            await onDelete(comment.id);
+            message.success('评论删除成功');
+        } catch {
+            message.error('删除失败,请重试');
+        } finally {
+            setDeleting(false);
+        }
+    }, [comment.id, onDelete]);
+
+    return (
+        <div style={{ marginLeft: level * 24 }}>
+            <div
+                style={{
+                    background: '#fafafa',
+                    padding: 12,
+                    borderRadius: 8,
+                    marginBottom: 8,
+                }}
+            >
+                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
+                    <div style={{ flex: 1 }}>
+                        <Space style={{ marginBottom: 8 }}>
+                            <UserOutlined />
+                            <Text strong>{comment.author}</Text>
+                            {comment.createdAt && (
+                                <Text type="secondary" style={{ fontSize: 12 }}>
+                                    {new Date(comment.createdAt).toLocaleString()}
+                                </Text>
+                            )}
+                        </Space>
+                        <div>
+                            <Text>{comment.content}</Text>
+                        </div>
+                    </div>
+
+                    {isAuthor && comment.id && (
+                        <Popconfirm
+                            title="确定要删除这条评论吗?"
+                            onConfirm={handleDelete}
+                            okText="确定"
+                            cancelText="取消"
+                        >
+                            <Button
+                                type="text"
+                                danger
+                                size="small"
+                                icon={<DeleteOutlined />}
+                                loading={deleting}
+                            />
+                        </Popconfirm>
+                    )}
+                </div>
+            </div>
+
+            {/* 递归渲染子评论 */}
+            {comment.child && comment.child.length > 0 && (
+                <div>
+                    {comment.child.map((childComment, index) => (
+                        <EditWorkComment
+                            key={childComment.id || index}
+                            comment={childComment}
+                            isAuthor={isAuthor}
+                            onDelete={onDelete}
+                            level={level + 1}
+                        />
+                    ))}
+                </div>
+            )}
+        </div>
+    );
+};
+
+// ==================== 主编辑控制器组件 ====================
+export const EditWorkControls: React.FC<EditWorkControlsProps> = ({
+    artwork,
+    isAuthor,
+    onUpdate,
+}) => {
+    const [editCoverVisible, setEditCoverVisible] = useState<boolean>(false);
+    const [editDescriptionVisible, setEditDescriptionVisible] = useState<boolean>(false);
+    const [editVersionsVisible, setEditVersionsVisible] = useState<boolean>(false);
+
+    const handleUpdateCover = useCallback(async (coverUrl: string): Promise<void> => {
+        await onUpdate({ artworkCover: coverUrl });
+    }, [onUpdate]);
+
+    const handleUpdateDescription = useCallback(async (description: string): Promise<void> => {
+        await onUpdate({ artworkDescription: description });
+    }, [onUpdate]);
+
+    const handleUpdateVersions = useCallback(async (versions: VersionFormData[]): Promise<void> => {
+        // 转换为展示用的版本格式
+        const versionList = versions.map(v => ({
+            version: v.version,
+            versionDescription: v.versionDescription,
+            seedFile: v.seedFile?.name || '',
+        }));
+        await onUpdate({ versionList });
+    }, [onUpdate]);
+
+    if (!isAuthor) {
+        return null;
+    }
+
+    return (
+        <>
+            <Card title="作者管理" style={{ marginBottom: 24 }}>
+                <Space wrap>
+                    <Button
+                        icon={<EditOutlined />}
+                        onClick={(): void => setEditCoverVisible(true)}
+                    >
+                        编辑封面
+                    </Button>
+                    <Button
+                        icon={<EditOutlined />}
+                        onClick={(): void => setEditDescriptionVisible(true)}
+                    >
+                        编辑描述
+                    </Button>
+                    <Button
+                        icon={<EditOutlined />}
+                        onClick={(): void => setEditVersionsVisible(true)}
+                    >
+                        管理版本
+                    </Button>
+                </Space>
+            </Card>
+
+            <EditWorkCover
+                visible={editCoverVisible}
+                currentCover={artwork.artworkCover}
+                onCancel={(): void => setEditCoverVisible(false)}
+                onSave={handleUpdateCover}
+            />
+
+            <EditWorkDescription
+                visible={editDescriptionVisible}
+                currentDescription={artwork.artworkDescription}
+                onCancel={(): void => setEditDescriptionVisible(false)}
+                onSave={handleUpdateDescription}
+            />
+
+            <EditWorkVersions
+                visible={editVersionsVisible}
+                versions={artwork.versionList.map(v => ({
+                    version: v.version,
+                    versionDescription: v.versionDescription,
+                    seedFile: { name: v.seedFile } as UploadFile,
+                }))}
+                onCancel={(): void => setEditVersionsVisible(false)}
+                onSave={handleUpdateVersions}
+            />
+        </>
+    );
+};
\ No newline at end of file
diff --git a/src/feature/work/Work.tsx b/src/feature/work/Work.tsx
new file mode 100644
index 0000000..56939d1
--- /dev/null
+++ b/src/feature/work/Work.tsx
@@ -0,0 +1,288 @@
+// src/feature/work/Work.tsx
+
+import React, { useEffect, useState, useCallback } from 'react';
+import { Layout, Flex, Spin, Alert, message } from 'antd';
+import { useParams } from 'react-router';
+import { useAppDispatch, useAppSelector } from '../../store/hooks';
+import {
+    fetchArtworkDetail, fetchComments, addComment, selectCurrentArtwork,
+    selectWorkLoading, selectWorkError, selectComments, setCommentsPage, clearCurrentArtwork,
+    updateArtwork, deleteComment
+} from './workSlice';
+import { Sidebar, MainContent } from './WorkComponents';
+import { EditWorkControls } from './EditWork';
+import type { ArtworkData, Comment } from './types';
+
+const { Content } = Layout;
+
+interface UserState {
+    userid?: string | number;
+    username?: string;
+}
+
+interface RootState {
+    user: UserState;
+    work: {
+        currentArtwork: ArtworkData | null;
+        loading: {
+            artwork: boolean;
+            comments: boolean;
+            addComment: boolean;
+            updateArtwork?: boolean;
+            deleteComment?: boolean;
+        };
+        error: {
+            artwork: string | null;
+            comments: string | null;
+            addComment: string | null;
+            updateArtwork?: string | null;
+            deleteComment?: string | null;
+        };
+        comments: {
+            list: Comment[];
+            total: number;
+            current: number;
+            pageSize: number;
+        };
+    };
+}
+
+const Work: React.FC = () => {
+    const dispatch = useAppDispatch();
+    const { work_id } = useParams<{ work_id: string }>();
+
+    // Redux state
+    const currentArtwork = useAppSelector(selectCurrentArtwork);
+    const loading = useAppSelector(selectWorkLoading);
+    const error = useAppSelector(selectWorkError);
+    const comments = useAppSelector(selectComments);
+    const currentUser = useAppSelector((state: RootState) => state.user);
+
+    // Local state for edit functionality
+    const [showEditControls, setShowEditControls] = useState<boolean>(false);
+
+    // 初始化数据
+    useEffect(() => {
+        if (work_id) {
+            dispatch(clearCurrentArtwork());
+            dispatch(fetchArtworkDetail(work_id));
+            dispatch(fetchComments({ workId: work_id, page: 1, pageSize: 5 }));
+        }
+    }, [work_id, dispatch]);
+
+    // 权限判断
+    const isAuthor: boolean = Boolean(
+        currentUser?.userid && currentArtwork?.authorId &&
+        String(currentUser.userid) === String(currentArtwork.authorId)
+    );
+
+    // 显示编辑控件
+    useEffect(() => {
+        setShowEditControls(isAuthor);
+    }, [isAuthor]);
+
+    // 评论分页处理
+    const handleCommentsPageChange = useCallback((page: number, pageSize: number): void => {
+        dispatch(setCommentsPage({ current: page, pageSize }));
+        if (work_id) {
+            dispatch(fetchComments({ workId: work_id, page, pageSize }));
+        }
+    }, [work_id, dispatch]);
+
+    // 添加评论
+    const handleAddComment = useCallback(async (content: string, parentId?: string): Promise<void> => {
+        if (!work_id) return;
+        try {
+            await dispatch(addComment({ workId: work_id, content, parentId })).unwrap();
+            message.success(parentId ? '回复发表成功!' : '评论发表成功!');
+        } catch {
+            message.error('评论发表失败,请重试');
+        }
+    }, [work_id, dispatch]);
+
+    // ==================== EditWork 集成功能 ====================
+
+    // 更新作品信息
+    const handleUpdateArtwork = useCallback(async (updates: Partial<ArtworkData>): Promise<void> => {
+        if (!work_id || !currentArtwork) return;
+
+        try {
+            // 检查 updateArtwork action 是否存在
+            if (updateArtwork) {
+                await dispatch(updateArtwork({
+                    workId: work_id,
+                    updates
+                })).unwrap();
+                message.success('作品信息更新成功!');
+            } else {
+                // 临时处理:直接更新本地状态
+                console.log('updateArtwork action not available, using local update');
+                message.success('作品信息更新成功!(本地更新)');
+            }
+        } catch (error) {
+            console.error('更新作品失败:', error);
+            message.error('更新失败,请重试');
+            throw error;
+        }
+    }, [work_id, currentArtwork, dispatch]);
+
+    // 删除评论
+    const handleDeleteComment = useCallback(async (commentId: string): Promise<void> => {
+        if (!work_id) return;
+
+        try {
+            // 检查 deleteComment action 是否存在
+            if (deleteComment) {
+                await dispatch(deleteComment({
+                    workId: work_id,
+                    commentId
+                })).unwrap();
+                message.success('评论删除成功!');
+
+                // 重新加载评论列表
+                dispatch(fetchComments({
+                    workId: work_id,
+                    page: comments.current,
+                    pageSize: comments.pageSize
+                }));
+            } else {
+                // 临时处理
+                console.log('deleteComment action not available');
+                message.success('评论删除成功!(本地处理)');
+            }
+        } catch (error) {
+            console.error('删除评论失败:', error);
+            message.error('删除评论失败,请重试');
+            throw error;
+        }
+    }, [work_id, dispatch, comments.current, comments.pageSize]);
+
+    // 兼容旧的编辑处理器
+    const handleEditArtwork = useCallback((): void => {
+        if (isAuthor) {
+            setShowEditControls(true);
+            message.info('请使用上方的编辑控件来修改作品信息');
+        } else {
+            message.warning('您没有编辑此作品的权限');
+        }
+    }, [isAuthor]);
+
+    // ==================== 渲染逻辑 ====================
+
+    // 加载状态
+    if (loading.artwork) {
+        return (
+            <Layout style={{ minHeight: '100vh', backgroundColor: '#f5f5f5' }}>
+                <Content style={{ padding: '20px' }}>
+                    <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }}>
+                        <Spin size="large" tip="加载作品详情中..." />
+                    </div>
+                </Content>
+            </Layout>
+        );
+    }
+
+    // 错误状态
+    if (error.artwork) {
+        return (
+            <Layout style={{ minHeight: '100vh', backgroundColor: '#f5f5f5' }}>
+                <Content style={{ padding: '20px' }}>
+                    <Flex justify="center" style={{ width: '100%' }}>
+                        <div style={{ width: '90%', maxWidth: 1200 }}>
+                            <Alert
+                                message="加载失败"
+                                description={error.artwork}
+                                type="error"
+                                showIcon
+                            />
+                        </div>
+                    </Flex>
+                </Content>
+            </Layout>
+        );
+    }
+
+    // 作品不存在
+    if (!currentArtwork) {
+        return (
+            <Layout style={{ minHeight: '100vh', backgroundColor: '#f5f5f5' }}>
+                <Content style={{ padding: '20px' }}>
+                    <Flex justify="center" align="center" style={{ height: '50vh' }}>
+                        <Alert
+                            message="作品不存在"
+                            description="未找到对应的作品信息"
+                            type="warning"
+                            showIcon
+                        />
+                    </Flex>
+                </Content>
+            </Layout>
+        );
+    }
+
+    // 确保数据完整性,添加默认值
+    const safeArtwork = {
+        ...currentArtwork,
+        usersSeedingCurrently: currentArtwork.usersSeedingCurrently || [],
+        usersSeedingHistory: currentArtwork.usersSeedingHistory || [],
+        versionList: currentArtwork.versionList || [],
+        comments: comments.list || []
+    };
+
+    const safeComments = {
+        ...comments,
+        list: comments.list || []
+    };
+
+    // 主要内容渲染
+    return (
+        <Layout style={{ minHeight: '100vh', backgroundColor: '#f5f5f5' }}>
+            <Content style={{ padding: '20px' }}>
+                <Flex justify="center" style={{ width: '100%' }}>
+                    <div style={{ width: '90%', maxWidth: 1200 }}>
+                        {/* EditWork 编辑控件 - 仅作者可见 */}
+                        {showEditControls && (
+                            <div style={{ marginBottom: 20 }}>
+                                <EditWorkControls
+                                    artwork={safeArtwork}
+                                    isAuthor={isAuthor}
+                                    onUpdate={handleUpdateArtwork}
+                                    onDeleteComment={handleDeleteComment}
+                                />
+                            </div>
+                        )}
+
+                        {/* 原有的作品展示布局 */}
+                        <Flex gap={20}>
+                            <Sidebar
+                                coverUrl={safeArtwork.artworkCover}
+                                currentUsers={safeArtwork.usersSeedingCurrently}
+                                historyUsers={safeArtwork.usersSeedingHistory}
+                            />
+                            <MainContent
+                                artworkName={safeArtwork.artworkName || safeArtwork.artworkCategory}
+                                author={safeArtwork.author}
+                                category={safeArtwork.artworkCategory}
+                                description={safeArtwork.artworkDescription}
+                                versions={safeArtwork.versionList}
+                                comments={safeComments.list}
+                                commentsTotal={safeComments.total}
+                                commentsLoading={loading.comments}
+                                commentsError={error.comments}
+                                addCommentLoading={loading.addComment}
+                                onCommentsPageChange={handleCommentsPageChange}
+                                onAddComment={handleAddComment}
+                                currentPage={safeComments.current}
+                                pageSize={safeComments.pageSize}
+                                isAuthor={isAuthor}
+                                onEditArtwork={handleEditArtwork}
+                            />
+                        </Flex>
+                    </div>
+                </Flex>
+            </Content>
+        </Layout>
+    );
+};
+
+export default Work;
\ No newline at end of file
diff --git a/src/feature/work/WorkComponents.tsx b/src/feature/work/WorkComponents.tsx
new file mode 100644
index 0000000..64ef37a
--- /dev/null
+++ b/src/feature/work/WorkComponents.tsx
@@ -0,0 +1,368 @@
+import React, { useState } from 'react';
+import { Card, Typography, Tag, Flex, Table, Collapse, List, Spin, Alert, Button, Input, Form, message } from 'antd';
+import { EditOutlined, SendOutlined } from '@ant-design/icons';
+import ReactMarkdown from 'react-markdown';
+import type { ColumnsType } from 'antd/es/table';
+import type { PaginationConfig } from 'antd/es/pagination';
+import type { FormInstance } from 'antd/es/form';
+import type { Comment, Version, User, HistoryUser } from './types';
+import { parseUploadSize } from './types';
+
+const { Title, Paragraph } = Typography;
+const { Panel } = Collapse;
+const { TextArea } = Input;
+
+// 作品封面组件
+export const ArtworkCover: React.FC<{ coverUrl: string }> = ({ coverUrl }) => (
+    <Card cover={<img alt="作品封面" src={coverUrl} style={{ height: 250, objectFit: 'cover' }} />} />
+);
+
+// 当前做种用户组件
+export const CurrentSeedingUsers: React.FC<{ users: User[] }> = ({ users }) => (
+    <Card>
+        <Title level={4} style={{ marginBottom: 12 }}>当前做种用户</Title>
+        <Flex wrap="wrap" gap={8}>
+            {users.map((user) => (
+                <Tag key={user.userId} color="green">{user.username}</Tag>
+            ))}
+        </Flex>
+    </Card>
+);
+
+// 历史做种用户组件
+export const HistorySeedingUsers: React.FC<{ users: HistoryUser[] }> = ({ users }) => {
+    const sortedUsers = [...users].sort((a, b) => parseUploadSize(b.uploadTotal) - parseUploadSize(a.uploadTotal));
+
+    const columns: ColumnsType<HistoryUser> = [
+        { title: '用户名', dataIndex: 'username', key: 'username' },
+        {
+            title: '上传总量',
+            dataIndex: 'uploadTotal',
+            key: 'uploadTotal',
+            sorter: (a: HistoryUser, b: HistoryUser) => parseUploadSize(a.uploadTotal) - parseUploadSize(b.uploadTotal),
+        },
+    ];
+
+    return (
+        <Card>
+            <Title level={4} style={{ marginBottom: 12 }}>历史做种用户</Title>
+            <Table columns={columns} dataSource={sortedUsers} rowKey="username" pagination={false} size="small" />
+        </Card>
+    );
+};
+
+// 作品描述组件
+export const ArtworkDescription: React.FC<{
+    name: string;
+    author: string;
+    category: string;
+    description: string;
+    isAuthor?: boolean;
+    onEdit?: () => void;
+}> = ({ name, author, category, description, isAuthor = false, onEdit }) => (
+    <Card style={{ marginBottom: 20 }}>
+        <Flex justify="space-between" align="flex-start">
+            <div style={{ flex: 1 }}>
+                <Title level={2} style={{ marginBottom: 8 }}>{name}</Title>
+                <Paragraph style={{ marginBottom: 8, fontSize: 16 }}>
+                    <strong>作者:</strong>{author}
+                </Paragraph>
+                <div style={{ marginBottom: 16 }}>
+                    <Tag color="blue">{category}</Tag>
+                </div>
+                <div style={{ lineHeight: 1.6 }}>
+                    <ReactMarkdown>{description}</ReactMarkdown>
+                </div>
+            </div>
+            {isAuthor && (
+                <Button type="primary" icon={<EditOutlined />} onClick={onEdit} style={{ marginLeft: 16 }}>
+                    编辑作品
+                </Button>
+            )}
+        </Flex>
+    </Card>
+);
+
+// 版本历史组件
+export const VersionHistory: React.FC<{ versions: Version[] }> = ({ versions }) => (
+    <Card title="版本历史" style={{ marginBottom: 20 }}>
+        <Collapse>
+            {versions.map((version, index) => (
+                <Panel
+                    header={`版本 ${version.version}`}
+                    key={`version-${index}`}
+                    extra={<Tag color="blue">v{version.version}</Tag>}
+                >
+                    <div style={{ marginBottom: 16 }}>
+                        <strong>版本描述:</strong>
+                        <div style={{ marginTop: 8, lineHeight: 1.6 }}>
+                            <ReactMarkdown>{version.versionDescription}</ReactMarkdown>
+                        </div>
+                    </div>
+                    <div>
+                        <strong>种子文件:</strong>
+                        <a href={version.seedFile} target="_blank" rel="noopener noreferrer" style={{ marginLeft: 8 }}>
+                            下载链接
+                        </a>
+                    </div>
+                </Panel>
+            ))}
+        </Collapse>
+    </Card>
+);
+
+// 评论项组件(递归)
+export const CommentItem: React.FC<{
+    comment: Comment;
+    level?: number;
+    onReply?: (parentId: string, parentAuthor: string) => void;
+}> = ({ comment, level = 0, onReply }) => (
+    <div style={{ marginLeft: level * 20 }}>
+        <div style={{ marginBottom: 8 }}>
+            <Paragraph style={{ marginBottom: 4 }}>
+                <strong>{comment.author}:</strong>{comment.content}
+            </Paragraph>
+            <div style={{ fontSize: 12, color: '#999', marginBottom: 4 }}>
+                {comment.createdAt && <span style={{ marginRight: 16 }}>{comment.createdAt}</span>}
+                {onReply && (
+                    <Button
+                        type="link"
+                        size="small"
+                        style={{ padding: 0, height: 'auto', fontSize: 12 }}
+                        onClick={() => onReply(comment.id || comment.author, comment.author)}
+                    >
+                        回复
+                    </Button>
+                )}
+            </div>
+        </div>
+        {comment.child && comment.child.length > 0 && (
+            <div style={{
+                borderLeft: level === 0 ? '2px solid #f0f0f0' : 'none',
+                paddingLeft: level === 0 ? 12 : 0
+            }}>
+                {comment.child.map((child, index) => (
+                    <CommentItem
+                        key={child.id || `child-${level}-${index}`}
+                        comment={child}
+                        level={level + 1}
+                        onReply={onReply}
+                    />
+                ))}
+            </div>
+        )}
+    </div>
+);
+
+// 发表评论组件
+export const CommentForm: React.FC<{
+    loading?: boolean;
+    onSubmit: (content: string, parentId?: string) => void;
+    replyTo?: { id: string; author: string } | null;
+    onCancelReply?: () => void;
+}> = ({ loading = false, onSubmit, replyTo, onCancelReply }) => {
+    const [form]: [FormInstance] = Form.useForm();
+    const [content, setContent] = useState('');
+
+    const handleSubmit = (): void => {
+        if (!content.trim()) {
+            message.warning('请输入评论内容');
+            return;
+        }
+        onSubmit(content.trim(), replyTo?.id);
+        setContent('');
+        form.resetFields();
+    };
+
+    const placeholder = replyTo ? `回复 @${replyTo.author}:` : "发表你的看法...";
+
+    return (
+        <Card
+            size="small"
+            style={{ marginBottom: 16 }}
+            title={replyTo ? (
+                <div style={{ fontSize: 14 }}>
+                    <span>回复 @{replyTo.author}</span>
+                    <Button type="link" size="small" onClick={onCancelReply} style={{ padding: '0 0 0 8px', fontSize: 12 }}>
+                        取消
+                    </Button>
+                </div>
+            ) : undefined}
+        >
+            <Form form={form} layout="vertical">
+                <Form.Item>
+                    <TextArea
+                        value={content}
+                        onChange={(e) => setContent(e.target.value)}
+                        placeholder={placeholder}
+                        rows={3}
+                        maxLength={500}
+                        showCount
+                    />
+                </Form.Item>
+                <Form.Item style={{ marginBottom: 0 }}>
+                    <Flex justify="flex-end" gap={8}>
+                        {replyTo && <Button onClick={onCancelReply}>取消</Button>}
+                        <Button
+                            type="primary"
+                            icon={<SendOutlined />}
+                            loading={loading}
+                            onClick={handleSubmit}
+                            disabled={!content.trim()}
+                        >
+                            {replyTo ? '发表回复' : '发表评论'}
+                        </Button>
+                    </Flex>
+                </Form.Item>
+            </Form>
+        </Card>
+    );
+};
+
+// 评论区组件
+export const CommentSection: React.FC<{
+    comments: Comment[];
+    total: number;
+    loading?: boolean;
+    error?: string | null;
+    addCommentLoading?: boolean;
+    onPageChange: (page: number, pageSize: number) => void;
+    onAddComment: (content: string, parentId?: string) => void;
+    currentPage: number;
+    pageSize: number;
+}> = ({ comments, total, loading, error, addCommentLoading, onPageChange, onAddComment, currentPage, pageSize }) => {
+    const [replyTo, setReplyTo] = useState<{ id: string; author: string } | null>(null);
+
+    const handleReply = (parentId: string, parentAuthor: string): void => {
+        setReplyTo({ id: parentId, author: parentAuthor });
+    };
+
+    const handleCancelReply = (): void => {
+        setReplyTo(null);
+    };
+
+    const handleSubmitComment = (content: string, parentId?: string): void => {
+        onAddComment(content, parentId);
+        setReplyTo(null);
+    };
+
+    const paginationConfig: PaginationConfig = {
+        current: currentPage,
+        pageSize,
+        total,
+        showSizeChanger: true,
+        showQuickJumper: true,
+        showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条,共 ${total} 条评论`,
+        pageSizeOptions: ['5', '10', '20'],
+        onChange: onPageChange,
+        onShowSizeChange: onPageChange,
+    };
+
+    return (
+        <Card title={`评论 (${total})`} style={{ marginBottom: 20 }}>
+            <CommentForm
+                loading={addCommentLoading}
+                onSubmit={handleSubmitComment}
+                replyTo={replyTo}
+                onCancelReply={handleCancelReply}
+            />
+
+            {error ? (
+                <Alert message="加载评论失败" description={error} type="error" showIcon />
+            ) : loading ? (
+                <Flex justify="center" align="center" style={{ minHeight: 200 }}>
+                    <Spin size="large" />
+                </Flex>
+            ) : comments.length > 0 ? (
+                <List
+                    dataSource={comments}
+                    pagination={paginationConfig}
+                    renderItem={(comment, index) => (
+                        <List.Item
+                            key={comment.id || `comment-${index}`}
+                            style={{ border: 'none', padding: '16px 0', borderBottom: '1px solid #f0f0f0' }}
+                        >
+                            <CommentItem comment={comment} onReply={handleReply} />
+                        </List.Item>
+                    )}
+                />
+            ) : (
+                <Paragraph style={{ textAlign: 'center', color: '#999', margin: '20px 0' }}>
+                    暂无评论,来发表第一条评论吧!
+                </Paragraph>
+            )}
+        </Card>
+    );
+};
+
+// 侧边栏组合组件
+export const Sidebar: React.FC<{
+    coverUrl: string;
+    currentUsers: User[];
+    historyUsers: HistoryUser[];
+    loading?: boolean;
+    error?: string | null;
+}> = ({ coverUrl, currentUsers, historyUsers, loading, error }) => (
+    <Flex flex={1} vertical gap={20}>
+        <ArtworkCover coverUrl={coverUrl} />
+        {loading ? (
+            <Flex justify="center" align="center" style={{ minHeight: 200 }}>
+                <Spin size="large" />
+            </Flex>
+        ) : error ? (
+            <Alert message="加载用户信息失败" description={error} type="error" showIcon />
+        ) : (
+            <>
+                <CurrentSeedingUsers users={currentUsers} />
+                <HistorySeedingUsers users={historyUsers} />
+            </>
+        )}
+    </Flex>
+);
+
+// 主内容区组合组件
+export const MainContent: React.FC<{
+    artworkName: string;
+    author: string;
+    category: string;
+    description: string;
+    versions: Version[];
+    comments: Comment[];
+    commentsTotal: number;
+    commentsLoading?: boolean;
+    commentsError?: string | null;
+    addCommentLoading?: boolean;
+    onCommentsPageChange: (page: number, pageSize: number) => void;
+    onAddComment: (content: string, parentId?: string) => void;
+    currentPage: number;
+    pageSize: number;
+    isAuthor?: boolean;
+    onEditArtwork?: () => void;
+}> = ({
+    artworkName, author, category, description, versions, comments, commentsTotal,
+    commentsLoading, commentsError, addCommentLoading, onCommentsPageChange, onAddComment,
+    currentPage, pageSize, isAuthor, onEditArtwork
+}) => (
+        <Flex flex={4} vertical>
+            <ArtworkDescription
+                name={artworkName}
+                author={author}
+                category={category}
+                description={description}
+                isAuthor={isAuthor}
+                onEdit={onEditArtwork}
+            />
+            <VersionHistory versions={versions} />
+            <CommentSection
+                comments={comments}
+                total={commentsTotal}
+                loading={commentsLoading}
+                error={commentsError}
+                addCommentLoading={addCommentLoading}
+                onPageChange={onCommentsPageChange}
+                onAddComment={onAddComment}
+                currentPage={currentPage}
+                pageSize={pageSize}
+            />
+        </Flex>
+    );
\ No newline at end of file
diff --git a/src/feature/work/hooks.ts b/src/feature/work/hooks.ts
new file mode 100644
index 0000000..f07189e
--- /dev/null
+++ b/src/feature/work/hooks.ts
@@ -0,0 +1,34 @@
+import { useCallback, useState } from "react";
+import { useNavigate } from "react-router";
+import type { 
+    WorkFormData, 
+    BasicInfo, 
+    CoverInfo, 
+    VersionFormData,
+    ArtworkCategory
+} from './types';
+
+// ==================== Hook ====================
+export const useCreateWorkForm = () => {
+    const navigate = useNavigate();
+    const [currentStep, setCurrentStep] = useState<number>(0);
+    const [formData, setFormData] = useState<WorkFormData>({
+        basicInfo: { 
+            artworkName: '', 
+            artworkCategory: '概念设计' as ArtworkCategory, 
+            artworkDescription: '' 
+        },
+        coverInfo: {},
+        versions: [],
+    });
+
+    const handleUpdateFormData = useCallback((field: keyof WorkFormData, value: BasicInfo | CoverInfo | VersionFormData[]) => {
+        setFormData(prev => ({ ...prev, [field]: value }));
+    }, []);
+
+    const handleNext = useCallback(() => setCurrentStep(prev => Math.min(prev + 1, 3)), []);
+    const handlePrev = useCallback(() => setCurrentStep(prev => Math.max(prev - 1, 0)), []);
+    const handlePublish = useCallback(() => navigate('/work/new-work-id'), [navigate]);
+
+    return { currentStep, formData, handleUpdateFormData, handleNext, handlePrev, handlePublish };
+};
\ No newline at end of file
diff --git a/src/feature/work/mockData.ts b/src/feature/work/mockData.ts
new file mode 100644
index 0000000..8470e61
--- /dev/null
+++ b/src/feature/work/mockData.ts
@@ -0,0 +1,405 @@
+import type { ArtworkData, Comment } from './types';
+
+// 生成随机时间的工具函数
+const generateRandomDate = (daysAgo: number): string => {
+    const date = new Date();
+    date.setDate(date.getDate() - Math.floor(Math.random() * daysAgo));
+    return date.toLocaleString('zh-CN', {
+        year: 'numeric',
+        month: '2-digit',
+        day: '2-digit',
+        hour: '2-digit',
+        minute: '2-digit'
+    });
+};
+
+// 通用评论数据
+const baseComments: Comment[] = [
+    {
+        id: 'comment_1',
+        content: '这个作品真的很棒!设计思路很新颖,学到了很多东西。',
+        author: '设计爱好者小王',
+        authorId: 'user_wang_001',
+        createdAt: generateRandomDate(3),
+        child: [
+            {
+                id: 'comment_1_1',
+                content: '同感!特别是色彩搭配的部分,很有启发性。',
+                author: '视觉设计师李雷',
+                authorId: 'user_lilei_002',
+                createdAt: generateRandomDate(2),
+                child: [],
+            },
+            {
+                id: 'comment_1_2',
+                content: '确实,作者的审美很在线,期待更多作品!',
+                author: '创意总监韩梅梅',
+                authorId: 'user_hanmeimei_003',
+                createdAt: generateRandomDate(2),
+                child: [
+                    {
+                        id: 'comment_1_2_1',
+                        content: '@创意总监韩梅梅 您说得对,这种风格确实很难得',
+                        author: '设计爱好者小王',
+                        authorId: 'user_wang_001',
+                        createdAt: generateRandomDate(1),
+                        child: [],
+                    }
+                ],
+            },
+        ],
+    },
+    {
+        id: 'comment_2',
+        content: '技术实现方面有什么特别的难点吗?想了解一下制作过程。',
+        author: '技术控阿明',
+        authorId: 'user_aming_004',
+        createdAt: generateRandomDate(5),
+        child: [],
+    },
+    {
+        id: 'comment_3',
+        content: '看起来很专业,请问这是用什么软件制作的?',
+        author: '新手小白',
+        authorId: 'user_xiaobai_005',
+        createdAt: generateRandomDate(4),
+        child: [
+            {
+                id: 'comment_3_1',
+                content: '从效果来看应该是用Adobe全家桶,主要是PS和AI',
+                author: '软件专家老刘',
+                authorId: 'user_laoliu_006',
+                createdAt: generateRandomDate(3),
+                child: [],
+            }
+        ],
+    },
+    {
+        id: 'comment_4',
+        content: '色彩运用得很巧妙,给人一种很舒服的视觉感受。',
+        author: '色彩搭配师小张',
+        authorId: 'user_xiaozhang_007',
+        createdAt: generateRandomDate(6),
+        child: [],
+    },
+    {
+        id: 'comment_5',
+        content: '作品质量很高,但是感觉在某些细节上还可以再优化一下。',
+        author: '完美主义者',
+        authorId: 'user_perfect_008',
+        createdAt: generateRandomDate(7),
+        child: [
+            {
+                id: 'comment_5_1',
+                content: '能具体说说哪些地方可以优化吗?我也想学习学习',
+                author: '求知者小陈',
+                authorId: 'user_xiaochen_009',
+                createdAt: generateRandomDate(6),
+                child: [],
+            }
+        ],
+    },
+    {
+        id: 'comment_6',
+        content: '已经下载收藏了,感谢分享!🎉',
+        author: '收藏家大佬',
+        authorId: 'user_collector_010',
+        createdAt: generateRandomDate(8),
+        child: [],
+    },
+    {
+        id: 'comment_7',
+        content: '这个风格很适合我正在做的项目,能不能商用呢?',
+        author: '商务合作方',
+        authorId: 'user_business_011',
+        createdAt: generateRandomDate(9),
+        child: [],
+    },
+    {
+        id: 'comment_8',
+        content: '教程什么时候出?期待大神的分享!',
+        author: '学习狂人',
+        authorId: 'user_learner_012',
+        createdAt: generateRandomDate(10),
+        child: [],
+    }
+];
+
+// 作品数据集合
+export const mockArtworks: Record<string, ArtworkData> = {
+    '12345': {
+        artworkId: '12345',
+        artworkCover: 'https://picsum.photos/300/400?random=1',
+        author: '视觉设计师张三',
+        authorId: 'author_zhangsan_001',
+        artworkName: '未来城市概念设计',
+        artworkCategory: '概念设计',
+        comments: [],
+        artworkDescription: `# 未来城市概念设计
+
+这是一个关于2050年智慧城市的概念设计作品。整个设计融合了**可持续发展**、**人工智能**和**绿色科技**的理念。
+
+## 设计理念
+
+- 🌱 **生态友好**:建筑与自然和谐共生
+- 🤖 **智能化**:AI驱动的城市管理系统
+- 🚗 **零排放**:全面电动化的交通系统
+- 🏗️ **模块化**:可扩展的建筑结构
+
+## 技术特点
+
+采用了最新的**参数化设计**方法,通过算法生成建筑形态,确保每个结构都能最大化利用自然光和风能。
+
+*希望这个设计能为未来城市规划提供一些启发。*`,
+        versionList: [
+            {
+                version: '1.0',
+                seedFile: 'magnet:?xt=urn:btih:future_city_v1_0&dn=未来城市v1.0.zip',
+                versionDescription: `## 初始版本 v1.0
+
+### 包含内容
+- 🎨 **高分辨率效果图** (4K)
+- 📐 **CAD源文件** (.dwg)
+- 🖼️ **PSD分层文件**
+- 📄 **设计说明文档**
+
+### 更新说明
+首次发布,包含完整的设计方案和素材文件。`,
+            },
+            {
+                version: '1.1',
+                seedFile: 'magnet:?xt=urn:btih:future_city_v1_1&dn=未来城市v1.1.zip',
+                versionDescription: `## 更新版本 v1.1
+
+### 新增内容
+- 🌃 **夜景渲染图**
+- 🎬 **动画演示视频** (1080p)
+- 🔧 **Blender源文件**
+
+### 修复内容
+- 修复了部分贴图丢失问题
+- 优化了文件结构
+- 添加了英文版说明文档`,
+            },
+        ],
+        usersSeedingCurrently: [
+            { username: '设计师小李', userId: 'user_xiaoli_101' },
+            { username: '建筑师王工', userId: 'user_wanggong_102' },
+            { username: '学生小赵', userId: 'user_xiaozhao_103' },
+            { username: '创意总监', userId: 'user_director_104' },
+        ],
+        usersSeedingHistory: [
+            {
+                username: '资深下载者', uploadTotal: '156.8GB',
+                userId: ''
+            },
+            {
+                username: '设计素材库', uploadTotal: '89.2GB',
+                userId: ''
+            },
+            {
+                username: '创意工作室', uploadTotal: '67.5GB',
+                userId: ''
+            },
+            {
+                username: '学院资源组', uploadTotal: '45.3GB',
+                userId: ''
+            },
+            {
+                username: '独立设计师', uploadTotal: '23.7GB',
+                userId: ''
+            },
+        ],
+    },
+    
+    '23456': {
+        artworkId: '23456',
+        artworkCover: 'https://picsum.photos/300/400?random=2',
+        author: 'UI设计师李四',
+        authorId: 'author_lisi_002',
+        artworkName: '移动应用界面设计套件',
+        artworkCategory: 'UI/UX设计',
+        comments: [],
+        artworkDescription: `# 移动应用界面设计套件
+
+一套完整的移动端UI设计规范和组件库,包含**100+个精美界面**和**500+个设计组件**。
+
+## 包含内容
+
+### 📱 界面设计
+- 登录注册页面
+- 主页和导航
+- 商品展示页面
+- 个人中心
+- 设置页面
+
+### 🎨 设计系统
+- **颜色规范**:主色调、辅助色、状态色
+- **字体系统**:标题、正文、注释文字
+- **图标库**:线性图标、填充图标
+- **组件库**:按钮、输入框、卡片等`,
+        versionList: [
+            {
+                version: '1.0',
+                seedFile: 'magnet:?xt=urn:btih:ui_kit_v1_0&dn=UI设计套件v1.0.zip',
+                versionDescription: `## 基础版本 v1.0
+
+### 核心功能
+- 📱 **50个界面模板**
+- 🎨 **基础组件库**
+- 📋 **设计规范文档**
+- 🎯 **Sketch源文件**`,
+            },
+        ],
+        usersSeedingCurrently: [
+            { username: 'UI设计新手', userId: 'user_ui_newbie_201' },
+            { username: '产品经理小王', userId: 'user_pm_wang_202' },
+        ],
+        usersSeedingHistory: [
+            {
+                username: 'UI设计公司', uploadTotal: '78.9GB',
+                userId: ''
+            },
+            {
+                username: '设计师联盟', uploadTotal: '45.6GB',
+                userId: ''
+            },
+            {
+                username: '学习小组', uploadTotal: '23.4GB',
+                userId: ''
+            },
+        ],
+    },
+
+    '67890': {
+        artworkId: '67890',
+        artworkCover: 'https://picsum.photos/300/400?random=6',
+        author: '刘松林',
+        authorId: '2', // 用户ID为2
+        artworkName: 'React组件库开发指南',
+        artworkCategory: '前端开发',
+        comments: [],
+        artworkDescription: `# React组件库开发指南
+
+一套完整的**企业级React组件库**开发教程和源码,包含从设计到发布的完整流程。
+
+## 项目特色
+
+### 🚀 技术栈
+- **React 18** + **TypeScript**
+- **Styled-components** 样式解决方案
+- **Storybook** 组件文档
+- **Jest** + **Testing Library** 测试
+
+### 📦 组件覆盖
+- **基础组件**: Button, Input, Select, Modal等
+- **布局组件**: Grid, Layout, Container等  
+- **数据展示**: Table, List, Card, Timeline等`,
+        versionList: [
+            {
+                version: '1.0',
+                seedFile: 'magnet:?xt=urn:btih:react_components_v1_0&dn=React组件库v1.0.zip',
+                versionDescription: `## 基础版本 v1.0
+
+### 核心内容
+- 📚 **完整教程文档** (50+页)
+- 💻 **基础组件源码** (20+个组件)
+- 🧪 **单元测试示例**
+- 📖 **Storybook配置**`,
+            },
+        ],
+        usersSeedingCurrently: [
+            { username: '前端新手小李', userId: 'user_frontend_newbie_601' },
+            { username: 'React爱好者', userId: 'user_react_fan_602' },
+        ],
+        usersSeedingHistory: [
+            {
+                username: '大厂前端团队', uploadTotal: '567.8GB',
+                userId: ''
+            },
+            {
+                username: '开源社区', uploadTotal: '234.5GB',
+                userId: ''
+            },
+            {
+                username: '技术培训机构', uploadTotal: '189.7GB',
+                userId: ''
+            },
+        ],
+    },
+};
+
+// 获取指定作品的评论数据
+export const getCommentsForArtwork = (artworkId: string): Comment[] => {
+    // 为不同作品生成不同的评论
+    const commentVariations: Record<string, Comment[]> = {
+        '12345': baseComments,
+        '23456': baseComments.slice(0, 5).map(comment => ({
+            ...comment,
+            id: `ui_${comment.id}`,
+            content: comment.content.replace('作品', 'UI套件').replace('设计', '界面设计'),
+        })),
+        '67890': [
+            {
+                id: 'dev_comment_1',
+                content: '这个组件库的设计思路很棒!TypeScript类型定义特别完善。',
+                author: '前端架构师张工',
+                authorId: 'user_architect_zhang',
+                createdAt: generateRandomDate(2),
+                child: [
+                    {
+                        id: 'dev_comment_1_1',
+                        content: '同感!特别是组件API的设计,很符合React的设计理念。',
+                        author: 'React核心开发者',
+                        authorId: 'user_react_core',
+                        createdAt: generateRandomDate(1),
+                        child: [],
+                    }
+                ],
+            },
+            {
+                id: 'dev_comment_2',
+                content: '构建配置写得很详细,我们团队已经参考这个搭建了自己的组件库。',
+                author: '技术负责人小刘',
+                authorId: 'user_tech_liu',
+                createdAt: generateRandomDate(3),
+                child: [],
+            },
+        ],
+    };
+    
+    return commentVariations[artworkId] || baseComments;
+};
+
+// 根据作品ID获取作品数据
+export const getArtworkById = (artworkId: string): ArtworkData | null => {
+    const artwork = mockArtworks[artworkId];
+    if (artwork) {
+        return {
+            ...artwork,
+            comments: getCommentsForArtwork(artworkId)
+        };
+    }
+    return null;
+};
+
+// 获取所有作品列表
+export const getAllArtworks = (): ArtworkData[] => {
+    return Object.values(mockArtworks);
+};
+
+// 按分类获取作品
+export const getArtworksByCategory = (category: string): ArtworkData[] => {
+    return Object.values(mockArtworks).filter(artwork => artwork.artworkCategory === category);
+};
+
+// 搜索作品
+export const searchArtworks = (keyword: string): ArtworkData[] => {
+    const lowerKeyword = keyword.toLowerCase();
+    return Object.values(mockArtworks).filter(artwork => 
+        artwork.artworkName.toLowerCase().includes(lowerKeyword) ||
+        artwork.artworkDescription.toLowerCase().includes(lowerKeyword) ||
+        artwork.author.toLowerCase().includes(lowerKeyword) ||
+        artwork.artworkCategory.toLowerCase().includes(lowerKeyword)
+    );
+};
\ No newline at end of file
diff --git a/src/feature/work/types.ts b/src/feature/work/types.ts
new file mode 100644
index 0000000..2d7dbd7
--- /dev/null
+++ b/src/feature/work/types.ts
@@ -0,0 +1,283 @@
+import type { UploadFile } from 'antd/es/upload';
+
+// ==================== 基础类型 ====================
+
+export interface User {
+    userId: string;
+    username: string;
+}
+
+export interface HistoryUser extends User {
+    uploadTotal: string;
+}
+
+// ==================== 评论相关 ====================
+
+export interface Comment {
+    id?: string;
+    content: string;
+    author: string;
+    authorId?: string;
+    createdAt?: string;
+    child: Comment[];
+}
+
+// ==================== 版本管理相关 ====================
+
+// 用于表单创建的版本信息
+export interface VersionFormData {
+    version: string;
+    versionDescription: string;
+    seedFile?: UploadFile; // 表单中的文件对象
+}
+
+// 用于展示的版本信息(后端返回)
+export interface Version {
+    version: string;
+    versionDescription: string;
+    seedFile: string; // 文件URL或路径
+    uploadedAt?: string;
+    fileSize?: number;
+}
+
+// ==================== 作品相关 ====================
+
+// 基础信息(表单用)
+export interface BasicInfo {
+    artworkName: string;
+    artworkCategory: ArtworkCategory;
+    artworkDescription: string;
+}
+
+// 封面信息(表单用)
+export interface CoverInfo {
+    coverFile?: UploadFile;
+}
+
+// 表单数据结构
+export interface WorkFormData {
+    basicInfo: BasicInfo;
+    coverInfo: CoverInfo;
+    versions: VersionFormData[];
+}
+
+// 完整的作品数据(后端返回/展示用)
+export interface ArtworkData {
+    artworkId: string;
+    artworkCover: string;
+    author: string;
+    authorId: string;
+    artworkName: string;
+    artworkCategory: ArtworkCategory;
+    artworkDescription: string;
+    versionList: Version[];
+    comments: Comment[];
+    usersSeedingCurrently: User[];
+    usersSeedingHistory: HistoryUser[];
+    createdAt?: string;
+    updatedAt?: string;
+    downloadCount?: number;
+    likeCount?: number;
+}
+
+// ==================== 表单相关 ====================
+
+export interface StepFormProps {
+    data: WorkFormData;
+    onUpdate: (field: keyof WorkFormData, value: BasicInfo | CoverInfo | VersionFormData[]) => void;
+    onNext?: () => void;
+    onPrev?: () => void;
+}
+
+// ==================== 常量定义 ====================
+
+export const ARTWORK_CATEGORIES = [
+    { label: '概念设计', value: '概念设计' },
+    { label: 'UI/UX设计', value: 'UI/UX设计' },
+    { label: '3D建模', value: '3D建模' },
+    { label: '摄影作品', value: '摄影作品' },
+    { label: '音乐制作', value: '音乐制作' },
+    { label: '前端开发', value: '前端开发' },
+    { label: '插画艺术', value: '插画艺术' },
+    { label: '动画制作', value: '动画制作' },
+    { label: '视频剪辑', value: '视频剪辑' },
+    { label: '其他', value: '其他' },
+];
+
+// 提取分类值的联合类型
+export type ArtworkCategory = '概念设计' | 'UI/UX设计' | '3D建模' | '摄影作品' | '音乐制作' | '前端开发' | '插画艺术' | '动画制作' | '视频剪辑' | '其他';
+
+// 分类选项类型(用于 Select 组件)
+export interface ArtworkCategoryOption {
+    label: string;
+    value: ArtworkCategory;
+}
+
+// ==================== 工具函数 ====================
+
+/**
+ * 解析上传大小字符串为MB数值
+ * @param uploadStr 上传大小字符串,如 "1.5GB", "500MB"
+ * @returns 大小值(以MB为单位)
+ */
+export const parseUploadSize = (uploadStr: string): number => {
+    const match = uploadStr.match(/(\d+(?:\.\d+)?)\s*(GB|MB|KB|TB)?/i);
+    if (!match) return 0;
+    
+    const size = parseFloat(match[1]);
+    const unit = (match[2] || '').toUpperCase();
+    
+    const multipliers: Record<string, number> = {
+        'TB': 1024 * 1024,
+        'GB': 1024,
+        'MB': 1,
+        'KB': 1 / 1024,
+        '': 1
+    };
+    
+    return size * (multipliers[unit] || 1);
+};
+
+/**
+ * 格式化文件大小为可读字符串
+ * @param sizeInMB 文件大小(MB)
+ * @returns 格式化后的字符串
+ */
+export const formatFileSize = (sizeInMB: number): string => {
+    if (sizeInMB >= 1024) {
+        return `${(sizeInMB / 1024).toFixed(1)}GB`;
+    } else if (sizeInMB >= 1) {
+        return `${sizeInMB.toFixed(1)}MB`;
+    } else {
+        return `${(sizeInMB * 1024).toFixed(0)}KB`;
+    }
+};
+
+/**
+ * 格式化日期
+ * @param dateString 日期字符串
+ * @returns 格式化后的日期字符串
+ */
+export const formatDate = (dateString?: string): string => {
+    if (!dateString) return '';
+    
+    const date = new Date(dateString);
+    const now = new Date();
+    const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);
+    
+    if (diffInHours < 1) {
+        return '刚刚';
+    } else if (diffInHours < 24) {
+        return `${Math.floor(diffInHours)}小时前`;
+    } else if (diffInHours < 24 * 7) {
+        return `${Math.floor(diffInHours / 24)}天前`;
+    } else {
+        return date.toLocaleDateString('zh-CN');
+    }
+};
+
+/**
+ * 验证文件大小是否符合要求
+ * @param fileSize 文件大小(字节)
+ * @param maxSizeMB 最大允许大小(MB)
+ * @returns 是否符合要求
+ */
+export const isValidFileSize = (fileSize: number, maxSizeMB: number): boolean => {
+    const fileSizeMB = fileSize / (1024 * 1024);
+    return fileSizeMB <= maxSizeMB;
+};
+
+/**
+ * 验证文件类型是否符合要求
+ * @param fileName 文件名
+ * @param allowedExtensions 允许的扩展名数组
+ * @returns 是否符合要求
+ */
+export const isValidFileType = (fileName: string, allowedExtensions: string[]): boolean => {
+    if (!fileName) return false;
+    const extension = fileName.toLowerCase().split('.').pop();
+    return extension ? allowedExtensions.includes(extension) : false;
+};
+
+/**
+ * 验证图片文件类型
+ * @param fileName 文件名
+ * @returns 是否为有效图片
+ */
+export const isValidImageFile = (fileName: string): boolean => {
+    return isValidFileType(fileName, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']);
+};
+
+/**
+ * 安全地解析JSON字符串
+ * @param jsonString JSON字符串
+ * @returns 解析结果或null
+ */
+export const safeJsonParse = <T = unknown>(jsonString: string): T | null => {
+    try {
+        return JSON.parse(jsonString) as T;
+    } catch {
+        return null;
+    }
+};
+
+// ==================== 类型守卫 ====================
+
+export const isValidArtworkCategory = (category: string): category is ArtworkCategory => {
+    return ARTWORK_CATEGORIES.some(cat => cat.value === category);
+};
+
+export const isComment = (obj: unknown): obj is Comment => {
+    return typeof obj === 'object' && 
+           obj !== null && 
+           'content' in obj && 
+           'author' in obj && 
+           'child' in obj &&
+           typeof (obj as Record<string, unknown>).content === 'string' && 
+           typeof (obj as Record<string, unknown>).author === 'string' && 
+           Array.isArray((obj as Record<string, unknown>).child);
+};
+
+export const isUser = (obj: unknown): obj is User => {
+    return typeof obj === 'object' && 
+           obj !== null && 
+           'userId' in obj && 
+           'username' in obj &&
+           typeof (obj as Record<string, unknown>).userId === 'string' && 
+           typeof (obj as Record<string, unknown>).username === 'string';
+};
+
+export const isHistoryUser = (obj: unknown): obj is HistoryUser => {
+    return isUser(obj) && 
+           'uploadTotal' in obj &&
+           typeof (obj as Record<string, unknown>).uploadTotal === 'string';
+};
+
+export const isVersion = (obj: unknown): obj is Version => {
+    return typeof obj === 'object' && 
+           obj !== null && 
+           'version' in obj && 
+           'versionDescription' in obj && 
+           'seedFile' in obj &&
+           typeof (obj as Record<string, unknown>).version === 'string' && 
+           typeof (obj as Record<string, unknown>).versionDescription === 'string' && 
+           typeof (obj as Record<string, unknown>).seedFile === 'string';
+};
+
+export const isArtworkData = (obj: unknown): obj is ArtworkData => {
+    if (typeof obj !== 'object' || obj === null) return false;
+    
+    const artwork = obj as Record<string, unknown>;
+    
+    return typeof artwork.artworkId === 'string' &&
+           typeof artwork.artworkCover === 'string' &&
+           typeof artwork.author === 'string' &&
+           typeof artwork.authorId === 'string' &&
+           typeof artwork.artworkName === 'string' &&
+           typeof artwork.artworkCategory === 'string' &&
+           typeof artwork.artworkDescription === 'string' &&
+           Array.isArray(artwork.versionList) &&
+           Array.isArray(artwork.comments) &&
+           Array.isArray(artwork.usersSeedingCurrently) &&
+           Array.isArray(artwork.usersSeedingHistory);
+};
\ No newline at end of file
diff --git a/src/feature/work/utils.ts b/src/feature/work/utils.ts
new file mode 100644
index 0000000..a10d95f
--- /dev/null
+++ b/src/feature/work/utils.ts
@@ -0,0 +1,155 @@
+import type { RcFile } from 'antd/es/upload';
+
+// 将文件转换为Base64
+export const getBase64 = (file: RcFile): Promise<string> =>
+    new Promise((resolve, reject) => {
+        const reader = new FileReader();
+        reader.readAsDataURL(file);
+        reader.onload = () => resolve(reader.result as string);
+        reader.onerror = (error) => reject(error);
+    });
+
+// 验证图片文件
+interface ValidationResult {
+    valid: boolean;
+    message?: string;
+}
+
+export const validateImageFile = (file: RcFile): ValidationResult => {
+    const isImage = file.type.startsWith('image/');
+    if (!isImage) {
+        return { valid: false, message: '只能上传图片文件!' };
+    }
+
+    const isLt5M = file.size / 1024 / 1024 < 5;
+    if (!isLt5M) {
+        return { valid: false, message: '图片大小不能超过 5MB!' };
+    }
+
+    return { valid: true };
+};
+
+// 验证种子文件
+export const validateSeedFile = (file: RcFile): ValidationResult => {
+    const isLt100M = file.size / 1024 / 1024 < 100;
+    if (!isLt100M) {
+        return { valid: false, message: '种子文件大小不能超过 100MB!' };
+    }
+
+    return { valid: true };
+};
+
+// 格式化文件大小
+export const formatFileSize = (bytes: number): string => {
+    if (bytes === 0) return '0 Bytes';
+
+    const k = 1024;
+    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+};
+
+// 防抖函数 - 修复版本
+export const debounce = <T extends (...args: unknown[]) => unknown>(
+    func: T,
+    wait: number
+): ((...args: Parameters<T>) => void) => {
+    let timeout: ReturnType<typeof setTimeout>;
+    
+    return (...args: Parameters<T>) => {
+        clearTimeout(timeout);
+        timeout = setTimeout(() => func(...args), wait);
+    };
+};
+
+// 节流函数 - 修复版本
+export const throttle = <T extends (...args: unknown[]) => unknown>(
+    func: T,
+    limit: number
+): ((...args: Parameters<T>) => void) => {
+    let inThrottle: boolean;
+    
+    return (...args: Parameters<T>) => {
+        if (!inThrottle) {
+            func(...args);
+            inThrottle = true;
+            setTimeout(() => inThrottle = false, limit);
+        }
+    };
+};
+// 生成唯一ID
+export const generateId = (): string => {
+    return Date.now().toString(36) + Math.random().toString(36).substr(2);
+};
+
+// 安全的JSON解析
+export const safeJsonParse = <T>(str: string, defaultValue: T): T => {
+    try {
+        return JSON.parse(str) as T;
+    } catch {
+        return defaultValue;
+    }
+};
+
+// 检查是否为空值
+export const isEmpty = (value: unknown): boolean => {
+    if (value === null || value === undefined) return true;
+    if (typeof value === 'string') return value.trim() === '';
+    if (Array.isArray(value)) return value.length === 0;
+    if (typeof value === 'object') return Object.keys(value).length === 0;
+    return false;
+};
+
+// URL参数解析
+export const parseUrlParams = (url: string): Record<string, string> => {
+    const params: Record<string, string> = {};
+    const urlObj = new URL(url);
+    
+    urlObj.searchParams.forEach((value, key) => {
+        params[key] = value;
+    });
+    
+    return params;
+};
+
+// 时间格式化
+export const formatDate = (date: Date | string | number, format: string = 'YYYY-MM-DD HH:mm:ss'): string => {
+    const d = new Date(date);
+    
+    const year = d.getFullYear();
+    const month = String(d.getMonth() + 1).padStart(2, '0');
+    const day = String(d.getDate()).padStart(2, '0');
+    const hours = String(d.getHours()).padStart(2, '0');
+    const minutes = String(d.getMinutes()).padStart(2, '0');
+    const seconds = String(d.getSeconds()).padStart(2, '0');
+    
+    return format
+        .replace('YYYY', year.toString())
+        .replace('MM', month)
+        .replace('DD', day)
+        .replace('HH', hours)
+        .replace('mm', minutes)
+        .replace('ss', seconds);
+};
+
+// 相对时间格式化(例如:2小时前)
+export const formatRelativeTime = (date: Date | string | number): string => {
+    const now = new Date();
+    const target = new Date(date);
+    const diff = now.getTime() - target.getTime();
+    
+    const seconds = Math.floor(diff / 1000);
+    const minutes = Math.floor(seconds / 60);
+    const hours = Math.floor(minutes / 60);
+    const days = Math.floor(hours / 24);
+    const months = Math.floor(days / 30);
+    const years = Math.floor(months / 12);
+    
+    if (years > 0) return `${years}年前`;
+    if (months > 0) return `${months}个月前`;
+    if (days > 0) return `${days}天前`;
+    if (hours > 0) return `${hours}小时前`;
+    if (minutes > 0) return `${minutes}分钟前`;
+    return '刚刚';
+};
\ No newline at end of file
diff --git a/src/feature/work/workSlice.ts b/src/feature/work/workSlice.ts
new file mode 100644
index 0000000..6b2c12c
--- /dev/null
+++ b/src/feature/work/workSlice.ts
@@ -0,0 +1,469 @@
+import { createSlice, createAsyncThunk, type PayloadAction } from '@reduxjs/toolkit';
+import type { ArtworkData, Comment } from './types';
+import type { RootState } from '../../store/store';
+import { getArtworkById, getCommentsForArtwork } from './mockData';
+
+// ==================== 类型定义 ====================
+interface WorkState {
+    currentArtwork: ArtworkData | null;
+    loading: {
+        artwork: boolean;
+        comments: boolean;
+        addComment: boolean;
+        updateArtwork: boolean;
+        deleteComment: boolean;
+    };
+    error: {
+        artwork: string | null;
+        comments: string | null;
+        addComment: string | null;
+        updateArtwork: string | null;
+        deleteComment: string | null;
+    };
+    comments: {
+        list: Comment[];
+        total: number;
+        current: number;
+        pageSize: number;
+    };
+}
+
+interface FetchCommentsParams {
+    workId: string;
+    page: number;
+    pageSize: number;
+}
+
+interface AddCommentParams {
+    workId: string;
+    content: string;
+    parentId?: string;
+}
+
+interface UpdateArtworkParams {
+    workId: string;
+    updates: Partial<ArtworkData>;
+}
+
+interface DeleteCommentParams {
+    workId: string;
+    commentId: string;
+}
+
+interface SetCommentsPageParams {
+    current: number;
+    pageSize: number;
+}
+
+// ==================== 初始状态 ====================
+const initialState: WorkState = {
+    currentArtwork: null,
+    loading: {
+        artwork: false,
+        comments: false,
+        addComment: false,
+        updateArtwork: false,
+        deleteComment: false,
+    },
+    error: {
+        artwork: null,
+        comments: null,
+        addComment: null,
+        updateArtwork: null,
+        deleteComment: null,
+    },
+    comments: {
+        list: [],
+        total: 0,
+        current: 1,
+        pageSize: 5,
+    },
+};
+
+// ==================== Mock 工具函数 ====================
+
+// 模拟网络延迟
+const mockDelay = (ms: number = 800): Promise<void> => 
+    new Promise(resolve => setTimeout(resolve, ms));
+
+// 生成新评论ID
+const generateCommentId = (): string => {
+    return `comment_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
+};
+
+// 生成新评论数据
+const createNewComment = (content: string): Comment => {
+    return {
+        id: generateCommentId(),
+        content,
+        author: '当前用户', // 实际应用中从用户状态获取
+        authorId: 'current_user_id',
+        createdAt: new Date().toLocaleString('zh-CN'),
+        child: [],
+    };
+};
+
+// 递归删除评论
+const removeCommentById = (comments: Comment[], targetId: string): Comment[] => {
+    return comments.filter(comment => {
+        if (comment.id === targetId) {
+            return false;
+        }
+        if (comment.child.length > 0) {
+            comment.child = removeCommentById(comment.child, targetId);
+        }
+        return true;
+    });
+};
+
+// 递归添加回复评论
+const addReplyToComment = (comments: Comment[], parentId: string, newComment: Comment): Comment[] => {
+    return comments.map(comment => {
+        if (comment.id === parentId) {
+            return {
+                ...comment,
+                child: [...comment.child, newComment]
+            };
+        }
+        if (comment.child.length > 0) {
+            return {
+                ...comment,
+                child: addReplyToComment(comment.child, parentId, newComment)
+            };
+        }
+        return comment;
+    });
+};
+
+// 分页处理评论
+const paginateComments = (comments: Comment[], page: number, pageSize: number): Comment[] => {
+    const startIndex = (page - 1) * pageSize;
+    const endIndex = startIndex + pageSize;
+    return comments.slice(startIndex, endIndex);
+};
+
+// ==================== 异步 Actions ====================
+
+// 获取作品详情
+export const fetchArtworkDetail = createAsyncThunk<
+    ArtworkData,
+    string,
+    { rejectValue: string }
+>(
+    'work/fetchArtworkDetail',
+    async (workId: string, { rejectWithValue }) => {
+        try {
+            await mockDelay(600); // 模拟网络延迟
+            
+            const artwork = getArtworkById(workId);
+            
+            if (!artwork) {
+                throw new Error(`作品 ${workId} 不存在`);
+            }
+            
+            return artwork;
+        } catch (error) {
+            const message = error instanceof Error ? error.message : '获取作品详情失败';
+            return rejectWithValue(message);
+        }
+    }
+);
+
+// 获取评论列表
+export const fetchComments = createAsyncThunk<
+    { comments: Comment[]; total: number },
+    FetchCommentsParams,
+    { rejectValue: string }
+>(
+    'work/fetchComments',
+    async ({ workId, page, pageSize }, { rejectWithValue }) => {
+        try {
+            await mockDelay(400); // 模拟网络延迟
+            
+            const allComments = getCommentsForArtwork(workId);
+            const paginatedComments = paginateComments(allComments, page, pageSize);
+            
+            return {
+                comments: paginatedComments,
+                total: allComments.length
+            };
+        } catch (error) {
+            const message = error instanceof Error ? error.message : '获取评论失败';
+            return rejectWithValue(message);
+        }
+    }
+);
+
+// 添加评论
+export const addComment = createAsyncThunk<
+    Comment,
+    AddCommentParams,
+    { rejectValue: string }
+>(
+    'work/addComment',
+    async ({ workId, content }, { rejectWithValue }) => {
+        try {
+            await mockDelay(500); // 模拟网络延迟
+            
+            // 验证作品是否存在
+            const artwork = getArtworkById(workId);
+            if (!artwork) {
+                throw new Error('作品不存在');
+            }
+            
+            // 创建新评论
+            const newComment = createNewComment(content);
+            
+            // 模拟服务器返回完整的评论数据
+            return newComment;
+        } catch (error) {
+            const message = error instanceof Error ? error.message : '添加评论失败';
+            return rejectWithValue(message);
+        }
+    }
+);
+
+// 更新作品信息
+export const updateArtwork = createAsyncThunk<
+    ArtworkData,
+    UpdateArtworkParams,
+    { rejectValue: string }
+>(
+    'work/updateArtwork',
+    async ({ workId, updates }, { rejectWithValue }) => {
+        try {
+            await mockDelay(1000); // 模拟网络延迟
+            
+            const currentArtwork = getArtworkById(workId);
+            if (!currentArtwork) {
+                throw new Error('作品不存在');
+            }
+            
+            // 模拟文件上传处理
+            const processedUpdates = { ...updates };
+            
+            // 如果包含 blob URL,模拟转换为正式URL
+            if (updates.artworkCover && updates.artworkCover.startsWith('blob:')) {
+                // 模拟上传成功,生成新的图片URL
+                processedUpdates.artworkCover = `https://picsum.photos/300/400?random=${Date.now()}`;
+            }
+            
+            // 处理版本文件上传
+            if (updates.versionList) {
+                processedUpdates.versionList = updates.versionList.map(version => ({
+                    ...version,
+                    seedFile: version.seedFile.startsWith?.('blob:') 
+                        ? `magnet:?xt=urn:btih:updated_${Date.now()}&dn=${version.version}.zip`
+                        : version.seedFile
+                }));
+            }
+            
+            // 合并更新后的数据
+            const updatedArtwork: ArtworkData = {
+                ...currentArtwork,
+                ...processedUpdates,
+                updatedAt: new Date().toISOString(),
+            };
+            
+            return updatedArtwork;
+        } catch (error) {
+            const message = error instanceof Error ? error.message : '更新作品失败';
+            return rejectWithValue(message);
+        }
+    }
+);
+
+// 删除评论
+export const deleteComment = createAsyncThunk<
+    string,
+    DeleteCommentParams,
+    { rejectValue: string }
+>(
+    'work/deleteComment',
+    async ({ workId, commentId }, { rejectWithValue }) => {
+        try {
+            await mockDelay(300); // 模拟网络延迟
+            
+            // 验证作品是否存在
+            const artwork = getArtworkById(workId);
+            if (!artwork) {
+                throw new Error('作品不存在');
+            }
+            
+            // 模拟删除成功
+            return commentId;
+        } catch (error) {
+            const message = error instanceof Error ? error.message : '删除评论失败';
+            return rejectWithValue(message);
+        }
+    }
+);
+
+// ==================== Slice 定义 ====================
+const workSlice = createSlice({
+    name: 'work',
+    initialState,
+    reducers: {
+        // 清除当前作品
+        clearCurrentArtwork: (state) => {
+            state.currentArtwork = null;
+            state.comments.list = [];
+            state.comments.total = 0;
+            state.comments.current = 1;
+            // 清除所有错误状态
+            Object.keys(state.error).forEach(key => {
+                state.error[key as keyof typeof state.error] = null;
+            });
+        },
+        
+        // 设置评论分页
+        setCommentsPage: (state, action: PayloadAction<SetCommentsPageParams>) => {
+            state.comments.current = action.payload.current;
+            state.comments.pageSize = action.payload.pageSize;
+        },
+        
+        // 清除特定错误
+        clearError: (state, action: PayloadAction<keyof WorkState['error']>) => {
+            state.error[action.payload] = null;
+        },
+        
+        // 清除所有错误
+        clearAllErrors: (state) => {
+            Object.keys(state.error).forEach(key => {
+                state.error[key as keyof typeof state.error] = null;
+            });
+        },
+    },
+    extraReducers: (builder) => {
+        // 获取作品详情
+        builder
+            .addCase(fetchArtworkDetail.pending, (state) => {
+                state.loading.artwork = true;
+                state.error.artwork = null;
+            })
+            .addCase(fetchArtworkDetail.fulfilled, (state, action) => {
+                state.loading.artwork = false;
+                state.currentArtwork = action.payload;
+                state.error.artwork = null;
+            })
+            .addCase(fetchArtworkDetail.rejected, (state, action) => {
+                state.loading.artwork = false;
+                state.error.artwork = action.payload || '获取作品详情失败';
+            });
+
+        // 获取评论列表
+        builder
+            .addCase(fetchComments.pending, (state) => {
+                state.loading.comments = true;
+                state.error.comments = null;
+            })
+            .addCase(fetchComments.fulfilled, (state, action) => {
+                state.loading.comments = false;
+                state.comments.list = action.payload.comments;
+                state.comments.total = action.payload.total;
+                state.error.comments = null;
+            })
+            .addCase(fetchComments.rejected, (state, action) => {
+                state.loading.comments = false;
+                state.error.comments = action.payload || '获取评论失败';
+            });
+
+        // 添加评论
+        builder
+            .addCase(addComment.pending, (state) => {
+                state.loading.addComment = true;
+                state.error.addComment = null;
+            })
+            .addCase(addComment.fulfilled, (state, action) => {
+                state.loading.addComment = false;
+                
+                const newComment = action.payload;
+                const { parentId } = action.meta.arg;
+                
+                if (parentId) {
+                    // 添加回复评论
+                    state.comments.list = addReplyToComment(state.comments.list, parentId, newComment);
+                } else {
+                    // 添加顶级评论
+                    state.comments.list.unshift(newComment);
+                    state.comments.total += 1;
+                }
+                
+                state.error.addComment = null;
+            })
+            .addCase(addComment.rejected, (state, action) => {
+                state.loading.addComment = false;
+                state.error.addComment = action.payload || '添加评论失败';
+            });
+
+        // 更新作品信息
+        builder
+            .addCase(updateArtwork.pending, (state) => {
+                state.loading.updateArtwork = true;
+                state.error.updateArtwork = null;
+            })
+            .addCase(updateArtwork.fulfilled, (state, action) => {
+                state.loading.updateArtwork = false;
+                state.currentArtwork = action.payload;
+                state.error.updateArtwork = null;
+            })
+            .addCase(updateArtwork.rejected, (state, action) => {
+                state.loading.updateArtwork = false;
+                state.error.updateArtwork = action.payload || '更新作品失败';
+            });
+
+        // 删除评论
+        builder
+            .addCase(deleteComment.pending, (state) => {
+                state.loading.deleteComment = true;
+                state.error.deleteComment = null;
+            })
+            .addCase(deleteComment.fulfilled, (state, action) => {
+                state.loading.deleteComment = false;
+                
+                // 从评论列表中移除已删除的评论
+                state.comments.list = removeCommentById(state.comments.list, action.payload);
+                state.comments.total = Math.max(0, state.comments.total - 1);
+                state.error.deleteComment = null;
+            })
+            .addCase(deleteComment.rejected, (state, action) => {
+                state.loading.deleteComment = false;
+                state.error.deleteComment = action.payload || '删除评论失败';
+            });
+    },
+});
+
+// ==================== Actions 导出 ====================
+export const { 
+    clearCurrentArtwork, 
+    setCommentsPage, 
+    clearError, 
+    clearAllErrors 
+} = workSlice.actions;
+
+// ==================== Selectors 导出 ====================
+export const selectCurrentArtwork = (state: RootState): ArtworkData | null => 
+    state.work.currentArtwork;
+
+export const selectWorkLoading = (state: RootState): WorkState['loading'] => 
+    state.work.loading;
+
+export const selectWorkError = (state: RootState): WorkState['error'] => 
+    state.work.error;
+
+export const selectComments = (state: RootState): WorkState['comments'] => 
+    state.work.comments;
+
+export const selectIsAuthor = (state: RootState): boolean => {
+    const currentUser = state.user;
+    const currentArtwork = state.work.currentArtwork;
+    
+    return Boolean(
+        currentUser?.userid && 
+        currentArtwork?.authorId &&
+        String(currentUser.userid) === String(currentArtwork.authorId)
+    );
+};
+
+// ==================== Reducer 导出 ====================
+export default workSlice.reducer;
\ No newline at end of file
diff --git a/src/routes/ProtectedRoute.tsx b/src/routes/ProtectedRoute.tsx
index 238fdf4..2764f5a 100644
--- a/src/routes/ProtectedRoute.tsx
+++ b/src/routes/ProtectedRoute.tsx
@@ -1,7 +1,10 @@
-import React, { useEffect } from 'react';
-import { useAppSelector, useAppDispatch } from '../store/hooks'; // 导入 hooks
+// src/routes/ProtectedRoute.tsx
+
+import React, { useEffect, useState } from 'react';
+import { useAppSelector, useAppDispatch } from '../store/hooks';
 import { useNavigate } from 'react-router';
-import { refreshToken } from '../feature/auth/authSlice'; // 导入刷新 token 的 thunk
+import { refreshToken } from '../feature/auth/authSlice';
+import { Spin } from 'antd';
 
 interface ProtectedRouteProps {
   children: React.ReactNode;
@@ -11,26 +14,68 @@
   const { isAuth, token } = useAppSelector((state) => state.auth);
   const navigate = useNavigate();
   const dispatch = useAppDispatch();
+  const [isLoading, setIsLoading] = useState(false);
 
   useEffect(() => {
     const tryRefreshToken = async () => {
+      // 如果没有token,直接跳转到登录页
       if (!token) {
-        navigate('/login'); // 如果没有 token,跳转到登录页
+        navigate('/login', { replace: true });
+        return;
       }
+
+      // 如果有token但未认证,尝试刷新token
       if (!isAuth && token) {
+        setIsLoading(true);
         try {
-          await dispatch(refreshToken(token)).unwrap(); // 尝试刷新 token
-        } catch {
-          navigate('/login');
+          await dispatch(refreshToken(token)).unwrap();
+        } catch (error) {
+          console.error('Token refresh failed:', error);
+          navigate('/login', { replace: true });
+        } finally {
+          setIsLoading(false);
         }
       }
     };
 
-    tryRefreshToken(); // 执行 token 刷新
+    tryRefreshToken();
   }, [isAuth, token, dispatch, navigate]);
 
-  // 如果已认证则渲染 children,否则返回 null
-  return isAuth ? <>{children}</> : null;
+  // 显示加载状态
+  if (isLoading) {
+    return (
+      <div style={{
+        display: 'flex',
+        justifyContent: 'center',
+        alignItems: 'center',
+        height: '100vh'
+      }}>
+        <Spin size="large" tip="验证身份中..." />
+      </div>
+    );
+  }
+
+  // 如果没有token,返回null(会触发导航)
+  if (!token) {
+    return null;
+  }
+
+  // 如果已认证,渲染children
+  if (isAuth) {
+    return <>{children}</>;
+  }
+
+  // 如果有token但还在验证中,显示加载状态
+  return (
+    <div style={{
+      display: 'flex',
+      justifyContent: 'center',
+      alignItems: 'center',
+      height: '100vh'
+    }}>
+      <Spin size="large" tip="验证身份中..." />
+    </div>
+  );
 };
 
-export default ProtectedRoute;
+export default ProtectedRoute;
\ No newline at end of file
diff --git a/src/routes/routes.ts b/src/routes/routes.ts
index 585b1f6..3bb3135 100644
--- a/src/routes/routes.ts
+++ b/src/routes/routes.ts
@@ -1,29 +1,45 @@
+// src/routes/routes.ts
+
 import { createBrowserRouter } from "react-router";
-import Home from "../feature/Home";
+import Home from "../feature/home/Home";
 import AuthLayout from "../feature/auth/AuthLayout";
 import Login from "../feature/auth/Login";
 import Register from "../feature/auth/Register";
 import Forget from "../feature/auth/Forget";
 import AppLayout from "../AppLayout";
 import withProtect from "./withProtect";
+import Work from "../feature/work/Work";
+import CreateWork from "../feature/work/CreateWork";
 
+// 创建受保护的组件
+const ProtectedHome = withProtect(Home);
+const ProtectedWork = withProtect(Work);
+const ProtectedCreatWork = withProtect(CreateWork)
 export default createBrowserRouter([
   {
+    path: "/",
     Component: AppLayout,
     children: [
       {
         path: "/",
-        // 使用 ProtectedRoute 来包裹需要保护的页面
-        element: withProtect(Home),
+        Component: ProtectedHome,
       },
       {
         Component: AuthLayout,
         children: [
-          { path: "login", Component: Login },
-          { path: "register", Component: Register },
-          { path: "forget", Component: Forget },
+          { path: "/login", Component: Login },
+          { path: "/register", Component: Register },
+          { path: "/forget", Component: Forget },
         ],
       },
+      {
+        path: "/work/:work_id",
+        Component: ProtectedWork,
+      },
+      {
+        path:"/work/creat",
+        Component: ProtectedCreatWork
+      }
     ],
   },
-]);
+]);
\ No newline at end of file
diff --git a/src/routes/withProtect.ts b/src/routes/withProtect.ts
index bcde943..f8ea125 100644
--- a/src/routes/withProtect.ts
+++ b/src/routes/withProtect.ts
@@ -1,10 +1,14 @@
-import React from 'react';
-import ProtectedRoute from './ProtectedRoute'; 
+// src/routes/withProtect.ts
 
-const withProtect = (Component: React.ComponentType) => {
-  return React.createElement(ProtectedRoute, {
-    children: React.createElement(Component)
-  });
+import React from 'react';
+import ProtectedRoute from './ProtectedRoute';
+
+const withProtect = <P extends object>(Component: React.ComponentType<P>) => {
+  return function ProtectedComponent(props: P) {
+    return React.createElement(ProtectedRoute, {
+      children: React.createElement(Component, props)
+    });
+  };
 };
 
 export default withProtect;
\ No newline at end of file
diff --git a/src/store/store.ts b/src/store/store.ts
index 4921218..cb5b975 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -1,10 +1,13 @@
 import { configureStore } from '@reduxjs/toolkit'
 import authReducer from "../feature/auth/authSlice"
 import userReducer from "../feature/user/userSlice"
+import workReducer from "../feature/work/workSlice"
+
 export const store = configureStore({
   reducer: {
       auth: authReducer,
       user: userReducer,
+      work: workReducer,
   },
   middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(),
 })
diff --git a/src/store/types.ts b/src/store/types.ts
deleted file mode 100644
index 3e2d796..0000000
--- a/src/store/types.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// 定义用户基本信息
-export interface User {
-    id: number;
-    username: string;
-    email: string;
-    role: string;
-    token: string;
-}
-
-// 定义认证状态
-export interface AuthState {
-    token: string;
-    loading: boolean;
-    isAuth: boolean;
-    error: string
-}
\ No newline at end of file