-
分类字典页面 - 路径: /config/system/category
+
+
+
+
分类字典
+
树形结构管理系统常用分类数据
+
+
+
+ {/* 搜索和筛选 */}
+
dispatch({ type: 'SET_SEARCH_KEYWORD', payload: value })}
+ onTypeFilterChange={(value) => dispatch({ type: 'SET_TYPE_FILTER', payload: value })}
+ />
+
+ {/* 分类树 */}
+ dispatch({ type: 'TOGGLE_EXPAND', payload: id })}
+ onAdd={handleAdd}
+ onEdit={handleEdit}
+ onDelete={handleDelete}
+ />
+
+ {/* 编辑对话框 */}
+ dispatch({
+ type: 'SET_DIALOG_STATE',
+ payload: { open, editing: undefined, parent: undefined },
+ })}
+ onFormDataChange={(data) => dispatch({ type: 'SET_FORM_DATA', payload: data })}
+ onSave={handleSave}
+ />
+
+ {/* 使用说明 */}
+
);
}
\ No newline at end of file
diff --git a/crop-x/src/app/(app)/central-config/system/category/reducer.ts b/crop-x/src/app/(app)/central-config/system/category/reducer.ts
new file mode 100644
index 0000000..8c7b4f7
--- /dev/null
+++ b/crop-x/src/app/(app)/central-config/system/category/reducer.ts
@@ -0,0 +1,94 @@
+import { CategoryDictionary, CategoryAction, CategoryState, CategoryFormData } from './types';
+
+const initialFormData: CategoryFormData = {
+ code: '',
+ name: '',
+ type: 'industry',
+ description: '',
+ sortOrder: 0,
+ isActive: true,
+};
+
+export const initialState: CategoryState = {
+ categories: [],
+ searchKeyword: '',
+ typeFilter: 'all',
+ expandedIds: new Set(),
+ dialogState: {
+ open: false,
+ editing: undefined,
+ parent: undefined,
+ },
+ formData: initialFormData,
+};
+
+export function categoryReducer(state: CategoryState, action: CategoryAction): CategoryState {
+ switch (action.type) {
+ case 'SET_CATEGORIES':
+ return { ...state, categories: action.payload };
+
+ case 'ADD_CATEGORY':
+ return { ...state, categories: [...state.categories, action.payload] };
+
+ case 'UPDATE_CATEGORY':
+ return {
+ ...state,
+ categories: state.categories.map(cat =>
+ cat.id === action.payload.id
+ ? { ...cat, ...action.payload.updates, updatedAt: new Date().toISOString() }
+ : cat
+ ),
+ };
+
+ case 'DELETE_CATEGORY':
+ return {
+ ...state,
+ categories: state.categories.filter(cat => cat.id !== action.payload),
+ };
+
+ case 'SET_SEARCH_KEYWORD':
+ return { ...state, searchKeyword: action.payload };
+
+ case 'SET_TYPE_FILTER':
+ return { ...state, typeFilter: action.payload };
+
+ case 'TOGGLE_EXPAND':
+ const newExpanded = new Set(state.expandedIds);
+ if (newExpanded.has(action.payload)) {
+ newExpanded.delete(action.payload);
+ } else {
+ newExpanded.add(action.payload);
+ }
+ return { ...state, expandedIds: newExpanded };
+
+ case 'SET_DIALOG_STATE':
+ return {
+ ...state,
+ dialogState: action.payload,
+ formData: action.payload.editing
+ ? {
+ code: action.payload.editing.code,
+ name: action.payload.editing.name,
+ type: action.payload.editing.type,
+ description: action.payload.editing.description || '',
+ sortOrder: action.payload.editing.sortOrder,
+ isActive: action.payload.editing.isActive,
+ }
+ : action.payload.parent
+ ? {
+ ...initialFormData,
+ type: action.payload.parent.type,
+ }
+ : initialFormData,
+ };
+
+ case 'SET_FORM_DATA':
+ return {
+ ...state,
+ formData: { ...state.formData, ...action.payload },
+ };
+
+ default:
+ return state;
+ }
+}
\ No newline at end of file
diff --git a/crop-x/src/app/(app)/central-config/system/category/types.ts b/crop-x/src/app/(app)/central-config/system/category/types.ts
new file mode 100644
index 0000000..046220b
--- /dev/null
+++ b/crop-x/src/app/(app)/central-config/system/category/types.ts
@@ -0,0 +1,53 @@
+// 分类字典类型定义
+export interface CategoryDictionary {
+ id: string;
+ code: string;
+ name: string;
+ type: string; // 分类类型:industry, equipment, crop等
+ parentId?: string;
+ level: number;
+ sortOrder: number;
+ description?: string;
+ isActive: boolean;
+ children?: CategoryDictionary[];
+ createdAt: string;
+ updatedAt: string;
+}
+
+export type CategoryType = 'industry' | 'equipment' | 'crop' | 'operation' | 'other';
+
+// 分类表单数据
+export interface CategoryFormData {
+ code: string;
+ name: string;
+ type: string;
+ description: string;
+ sortOrder: number;
+ isActive: boolean;
+}
+
+// 分类操作类型
+export type CategoryAction =
+ | { type: 'SET_CATEGORIES'; payload: CategoryDictionary[] }
+ | { type: 'ADD_CATEGORY'; payload: CategoryDictionary }
+ | { type: 'UPDATE_CATEGORY'; payload: { id: string; updates: Partial
} }
+ | { type: 'DELETE_CATEGORY'; payload: string }
+ | { type: 'SET_SEARCH_KEYWORD'; payload: string }
+ | { type: 'SET_TYPE_FILTER'; payload: string }
+ | { type: 'TOGGLE_EXPAND'; payload: string }
+ | { type: 'SET_DIALOG_STATE'; payload: { open: boolean; editing?: CategoryDictionary; parent?: CategoryDictionary | null } }
+ | { type: 'SET_FORM_DATA'; payload: Partial };
+
+// 分类状态
+export interface CategoryState {
+ categories: CategoryDictionary[];
+ searchKeyword: string;
+ typeFilter: string;
+ expandedIds: Set;
+ dialogState: {
+ open: boolean;
+ editing?: CategoryDictionary;
+ parent?: CategoryDictionary | null;
+ };
+ formData: CategoryFormData;
+}
\ No newline at end of file
diff --git a/crop-x/src/app/(app)/central-config/user/role/components/RoleFormDialog.tsx b/crop-x/src/app/(app)/central-config/user/role/components/RoleFormDialog.tsx
index 61a0ad7..2d8f589 100644
--- a/crop-x/src/app/(app)/central-config/user/role/components/RoleFormDialog.tsx
+++ b/crop-x/src/app/(app)/central-config/user/role/components/RoleFormDialog.tsx
@@ -90,7 +90,7 @@ export function RoleFormDialog({
菜单与操作权限
选择菜单后可配置该菜单下的操作权限