Răsfoiți Sursa

✨ feat(goods): 新增商品分类级联选择组件

- 创建GoodsCategoryCascadeSelector组件,实现三级分类的级联选择功能
- 优化分类选择逻辑,当一级分类变化时自动重置二级和三级分类,二级分类变化时自动重置三级分类
- 在商品创建和编辑页面中使用新的级联选择组件替换原有分类选择代码
- 为分类选择器添加必填标识和状态筛选参数(state=1)

🐛 fix(category): 修复分类选择器状态筛选问题

- 在GoodsCategorySelector中添加state=1筛选条件,确保只显示启用状态的分类

♻️ refactor(goods): 重构商品页面分类选择逻辑

- 将商品创建和编辑页面中的分类选择代码重构为使用GoodsCategoryCascadeSelector组件
- 移除重复的分类选择表单字段代码,提高代码复用性和可维护性
yourname 4 luni în urmă
părinte
comite
d8e1da6358

+ 113 - 0
src/client/admin-shadcn/components/GoodsCategoryCascadeSelector.tsx

@@ -0,0 +1,113 @@
+import React from 'react';
+import { useFormContext } from 'react-hook-form';
+import {
+  FormField,
+  FormItem,
+  FormLabel,
+  FormControl,
+  FormMessage,
+} from '@/client/components/ui/form';
+import GoodsCategorySelector from './GoodsCategorySelector';
+
+interface GoodsCategoryCascadeSelectorProps {
+  formNamePrefix?: string;
+  required?: boolean;
+}
+
+const GoodsCategoryCascadeSelector: React.FC<GoodsCategoryCascadeSelectorProps> = ({
+  formNamePrefix = '',
+  required = false,
+}) => {
+  const form = useFormContext();
+
+  // 监听一级分类变化,重置二级和三级分类
+  const handleCategoryId1Change = (value: number) => {
+    form.setValue(`${formNamePrefix}categoryId1`, value);
+    form.setValue(`${formNamePrefix}categoryId2`, 0);
+    form.setValue(`${formNamePrefix}categoryId3`, 0);
+  };
+
+  // 监听二级分类变化,重置三级分类
+  const handleCategoryId2Change = (value: number) => {
+    form.setValue(`${formNamePrefix}categoryId2`, value);
+    form.setValue(`${formNamePrefix}categoryId3`, 0);
+  };
+
+  // 监听三级分类变化
+  const handleCategoryId3Change = (value: number) => {
+    form.setValue(`${formNamePrefix}categoryId3`, value);
+  };
+
+  return (
+    <div className="grid grid-cols-3 gap-4">
+      <FormField
+        control={form.control}
+        name={`${formNamePrefix}categoryId1`}
+        render={({ field }) => (
+          <FormItem>
+            <FormLabel>
+              一级分类
+              {required && <span className="text-red-500"> *</span>}
+            </FormLabel>
+            <FormControl>
+              <GoodsCategorySelector
+                value={field.value || undefined}
+                onChange={handleCategoryId1Change}
+                level={1}
+              />
+            </FormControl>
+            <FormMessage />
+          </FormItem>
+        )}
+      />
+
+      <FormField
+        control={form.control}
+        name={`${formNamePrefix}categoryId2`}
+        render={({ field }) => (
+          <FormItem>
+            <FormLabel>
+              二级分类
+              {required && <span className="text-red-500"> *</span>}
+            </FormLabel>
+            <FormControl>
+              <GoodsCategorySelector
+                value={field.value || undefined}
+                onChange={handleCategoryId2Change}
+                level={2}
+                parentId={form.watch(`${formNamePrefix}categoryId1`)}
+                disabled={!form.watch(`${formNamePrefix}categoryId1`)}
+              />
+            </FormControl>
+            <FormMessage />
+          </FormItem>
+        )}
+      />
+
+      <FormField
+        control={form.control}
+        name={`${formNamePrefix}categoryId3`}
+        render={({ field }) => (
+          <FormItem>
+            <FormLabel>
+              三级分类
+              {required && <span className="text-red-500"> *</span>}
+            </FormLabel>
+            <FormControl>
+              <GoodsCategorySelector
+                value={field.value || undefined}
+                onChange={handleCategoryId3Change}
+                level={3}
+                parentId={form.watch(`${formNamePrefix}categoryId2`)}
+                disabled={!form.watch(`${formNamePrefix}categoryId2`)}
+              />
+            </FormControl>
+            <FormMessage />
+          </FormItem>
+        )}
+      />
+    </div>
+  );
+};
+
+export default GoodsCategoryCascadeSelector;

+ 1 - 0
src/client/admin-shadcn/components/GoodsCategorySelector.tsx

@@ -36,6 +36,7 @@ const GoodsCategorySelector: React.FC<GoodsCategorySelectorProps> = ({
           filters: JSON.stringify({
           filters: JSON.stringify({
             level,
             level,
             parentId: parentId || undefined,
             parentId: parentId || undefined,
+            state: 1
           })
           })
         }
         }
       });
       });

+ 4 - 57
src/client/admin-shadcn/pages/Goods.tsx

@@ -23,6 +23,7 @@ import { CreateGoodsDto, UpdateGoodsDto } from '@/server/modules/goods/goods.sch
 import { DataTablePagination } from '@/client/admin-shadcn/components/DataTablePagination';
 import { DataTablePagination } from '@/client/admin-shadcn/components/DataTablePagination';
 import ImageSelector from '@/client/admin-shadcn/components/ImageSelector';
 import ImageSelector from '@/client/admin-shadcn/components/ImageSelector';
 import GoodsCategorySelector from '@/client/admin-shadcn/components/GoodsCategorySelector';
 import GoodsCategorySelector from '@/client/admin-shadcn/components/GoodsCategorySelector';
+import GoodsCategoryCascadeSelector from '@/client/admin-shadcn/components/GoodsCategoryCascadeSelector';
 import SupplierSelector from '@/client/admin-shadcn/components/SupplierSelector';
 import SupplierSelector from '@/client/admin-shadcn/components/SupplierSelector';
 import { Search, Plus, Edit, Trash2, Package } from 'lucide-react';
 import { Search, Plus, Edit, Trash2, Package } from 'lucide-react';
 
 
@@ -381,63 +382,7 @@ export const GoodsPage = () => {
                   />
                   />
                 </div>
                 </div>
 
 
-                <div className="grid grid-cols-3 gap-4">
-                  <FormField
-                    control={createForm.control}
-                    name="categoryId1"
-                    render={({ field }) => (
-                      <FormItem>
-                        <FormLabel>一级分类</FormLabel>
-                        <FormControl>
-                          <GoodsCategorySelector
-                            value={field.value || undefined}
-                            onChange={field.onChange}
-                            level={1}
-                          />
-                        </FormControl>
-                        <FormMessage />
-                      </FormItem>
-                    )}
-                  />
-
-                  <FormField
-                    control={createForm.control}
-                    name="categoryId2"
-                    render={({ field }) => (
-                      <FormItem>
-                        <FormLabel>二级分类</FormLabel>
-                        <FormControl>
-                          <GoodsCategorySelector
-                            value={field.value || undefined}
-                            onChange={field.onChange}
-                            level={2}
-                            parentId={createForm.watch('categoryId1')}
-                          />
-                        </FormControl>
-                        <FormMessage />
-                      </FormItem>
-                    )}
-                  />
-
-                  <FormField
-                    control={createForm.control}
-                    name="categoryId3"
-                    render={({ field }) => (
-                      <FormItem>
-                        <FormLabel>三级分类</FormLabel>
-                        <FormControl>
-                          <GoodsCategorySelector
-                            value={field.value || undefined}
-                            onChange={field.onChange}
-                            level={3}
-                            parentId={createForm.watch('categoryId2')}
-                          />
-                        </FormControl>
-                        <FormMessage />
-                      </FormItem>
-                    )}
-                  />
-                </div>
+                <GoodsCategoryCascadeSelector required={true} />
 
 
                 <div className="grid grid-cols-2 gap-4">
                 <div className="grid grid-cols-2 gap-4">
                   <FormField
                   <FormField
@@ -599,6 +544,8 @@ export const GoodsPage = () => {
                   />
                   />
                 </div>
                 </div>
 
 
+                <GoodsCategoryCascadeSelector />
+
                 <div className="grid grid-cols-2 gap-4">
                 <div className="grid grid-cols-2 gap-4">
                   <FormField
                   <FormField
                     control={updateForm.control}
                     control={updateForm.control}