Files
new-api/web/src/components/auth/OAuth2Callback.js
t0ng7u 6799daacd1 🚀 feat(web/channels): Deep modular refactor of Channels table
1. Split monolithic `ChannelsTable` (2200+ LOC) into focused components
   • `channels/index.jsx` – composition entry
   • `ChannelsTable.jsx` – pure `<Table>` rendering
   • `ChannelsActions.jsx` – bulk & settings toolbar
   • `ChannelsFilters.jsx` – search / create / column-settings form
   • `ChannelsTabs.jsx` – type tabs
   • `ChannelsColumnDefs.js` – column definitions & render helpers
   • `modals/` – BatchTag, ColumnSelector, ModelTest modals

2. Extract domain hook
   • Moved `useChannelsData.js` → `src/hooks/channels/useChannelsData.js`
     – centralises state, API calls, pagination, filters, batch ops
     – now exports `setActivePage`, fixing tab / status switch errors

3. Update wiring
   • All sub-components consume data via `useChannelsData` props
   • Adjusted import paths after hook relocation

4. Clean legacy file
   • Legacy `components/table/ChannelsTable.js` now re-exports new module

5. Bug fixes
   • Tab switching, status filter & tag aggregation restored
   • Column selector & batch actions operate via unified hook

This commit completes the first phase of modularising the Channels feature, laying groundwork for consistent, maintainable table architecture across the app.
2025-07-18 21:05:36 +08:00

71 lines
2.0 KiB
JavaScript

import React, { useContext, useEffect } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { API, showError, showSuccess, updateAPI, setUserData } from '../../helpers';
import { UserContext } from '../../context/User';
import Loading from '../common/ui/Loading';
const OAuth2Callback = (props) => {
const { t } = useTranslation();
const [searchParams] = useSearchParams();
const [, userDispatch] = useContext(UserContext);
const navigate = useNavigate();
// 最大重试次数
const MAX_RETRIES = 3;
const sendCode = async (code, state, retry = 0) => {
try {
const { data: resData } = await API.get(
`/api/oauth/${props.type}?code=${code}&state=${state}`,
);
const { success, message, data } = resData;
if (!success) {
throw new Error(message || 'OAuth2 callback error');
}
if (message === 'bind') {
showSuccess(t('绑定成功!'));
navigate('/console/personal');
} else {
userDispatch({ type: 'login', payload: data });
localStorage.setItem('user', JSON.stringify(data));
setUserData(data);
updateAPI();
showSuccess(t('登录成功!'));
navigate('/console/token');
}
} catch (error) {
if (retry < MAX_RETRIES) {
// 递增的退避等待
await new Promise((resolve) => setTimeout(resolve, (retry + 1) * 2000));
return sendCode(code, state, retry + 1);
}
// 重试次数耗尽,提示错误并返回设置页面
showError(error.message || t('授权失败'));
navigate('/console/personal');
}
};
useEffect(() => {
const code = searchParams.get('code');
const state = searchParams.get('state');
// 参数缺失直接返回
if (!code) {
showError(t('未获取到授权码'));
navigate('/console/personal');
return;
}
sendCode(code, state);
}, []);
return <Loading />;
};
export default OAuth2Callback;