refactor: 代码架构重构 - 提取组件、统一状态管理和数据访问层
- 新增布局组件(SidebarBrand、SidebarUser、SidebarNavItem) - 新增通用UI组件(EmptyState、StatusBadge、TagInput、SearchBar) - 新增全局状态管理(UserContext) - 新增自定义Hooks(usePageState、useNavigation) - 新增统一数据访问层(src/services/api.js) - 新增常量配置(constants/pages.js、constants/storageKeys.js) - 样式文件模块化,拆分页面特定样式 - 更新README文档,添加组件和使用说明 - 同步OpenSpec规范到主specs目录
This commit is contained in:
50
src/hooks/useNavigation.js
Normal file
50
src/hooks/useNavigation.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
/**
|
||||
* 导航逻辑 Hook
|
||||
* 统一处理页面导航和附加数据状态管理
|
||||
*
|
||||
* @param {Function} setPageCallback - 设置当前页面的回调函数
|
||||
* @returns {Object} 导航操作函数
|
||||
*/
|
||||
function useNavigation(setPageCallback) {
|
||||
const [extraData, setExtraData] = useState({});
|
||||
|
||||
/**
|
||||
* 导航到指定页面
|
||||
* @param {string} pageId - 目标页面 ID
|
||||
* @param {Object} data - 附加数据(如 skillId、taskId 等)
|
||||
*/
|
||||
const navigateToPage = useCallback((pageId, data = {}) => {
|
||||
setPageCallback(pageId);
|
||||
|
||||
// 如果有附加数据,更新 extraData
|
||||
if (Object.keys(data).length > 0) {
|
||||
setExtraData(data);
|
||||
}
|
||||
}, [setPageCallback]);
|
||||
|
||||
/**
|
||||
* 设置附加数据
|
||||
* @param {Object} data - 附加数据对象
|
||||
*/
|
||||
const setExtraDataValue = useCallback((data) => {
|
||||
setExtraData(prev => ({ ...prev, ...data }));
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* 清除附加数据
|
||||
*/
|
||||
const clearExtraData = useCallback(() => {
|
||||
setExtraData({});
|
||||
}, []);
|
||||
|
||||
return {
|
||||
extraData,
|
||||
navigateToPage,
|
||||
setExtraData: setExtraDataValue,
|
||||
clearExtraData,
|
||||
};
|
||||
}
|
||||
|
||||
export default useNavigation;
|
||||
58
src/hooks/usePageState.js
Normal file
58
src/hooks/usePageState.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
/**
|
||||
* 页面状态持久化 Hook
|
||||
* 封装页面状态管理、localStorage 同步和主页跳转重置逻辑
|
||||
*
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {string} options.storageKey - localStorage 存储键名
|
||||
* @param {string} options.defaultPage - 默认页面 ID
|
||||
* @param {Object} options.pageTitles - 页面标题映射对象
|
||||
* @param {Function} options.getPageTitle - 自定义获取页面标题函数(可选)
|
||||
* @returns {Object} 状态和操作函数
|
||||
*/
|
||||
function usePageState({
|
||||
storageKey,
|
||||
defaultPage,
|
||||
pageTitles,
|
||||
getPageTitle: customGetPageTitle,
|
||||
}) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// 从 localStorage 恢复或使用默认值
|
||||
const [currentPage, setCurrentPage] = useState(() => {
|
||||
const saved = localStorage.getItem(`${storageKey}_currentPage`);
|
||||
return saved || defaultPage;
|
||||
});
|
||||
|
||||
// 处理主页跳转重置
|
||||
useEffect(() => {
|
||||
if (location.state?.fromHome) {
|
||||
setCurrentPage(defaultPage);
|
||||
navigate('.', { replace: true, state: {} });
|
||||
}
|
||||
}, [location.state, navigate, defaultPage]);
|
||||
|
||||
// 同步到 localStorage
|
||||
useEffect(() => {
|
||||
localStorage.setItem(`${storageKey}_currentPage`, currentPage);
|
||||
}, [storageKey, currentPage]);
|
||||
|
||||
// 获取页面标题
|
||||
const getPageTitle = (pageId = currentPage) => {
|
||||
if (customGetPageTitle) {
|
||||
return customGetPageTitle(pageId, currentPage);
|
||||
}
|
||||
return pageTitles[pageId] || '';
|
||||
};
|
||||
|
||||
return {
|
||||
currentPage,
|
||||
setCurrentPage,
|
||||
getPageTitle,
|
||||
};
|
||||
}
|
||||
|
||||
export default usePageState;
|
||||
Reference in New Issue
Block a user