docs: 完善 fluwx 5.x 迁移与 AdminLayout 跳转备注
- main.dart: 说明 fluwx 5.x 实例共享机制与迁移前后对比 - welcome_page.dart: 说明 addSubscriber/NormalAuth/WeChatAuthResponse 用法, 以及 fluwx 3.x → 5.x API 对照 - AdminLayout.tsx: 说明 useEffect 跳转的原因(React #310 错误根因) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2e66db08ef
commit
a27baa1181
|
|
@ -100,7 +100,14 @@ export const AdminLayout: React.FC<{ children: React.ReactNode }> = ({ children
|
|||
const { isAuthenticated, isLoading, user, logout } = useAuth();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
// 未登录 → /login(必须在 useEffect 中跳转,不能在 render 期间调用 router)
|
||||
// 未登录 → 跳转 /login
|
||||
//
|
||||
// ⚠️ 必须在 useEffect 中执行,不能直接在 render 函数体内调用 router.replace()。
|
||||
// 原因:render 期间调用 router 会触发父组件的状态更新(React #310 错误):
|
||||
// "Cannot update a component while rendering a different component"
|
||||
//
|
||||
// useEffect 在 commit 阶段(DOM 更新后)执行,此时可以安全地触发导航。
|
||||
// 依赖数组包含 router 是为了满足 exhaustive-deps lint 规则,router 引用稳定不会重复触发。
|
||||
useEffect(() => {
|
||||
if (!isLoading && !isAuthenticated) {
|
||||
router.replace('/login');
|
||||
|
|
|
|||
|
|
@ -50,13 +50,19 @@ class _WelcomePageState extends State<WelcomePage> {
|
|||
// 'profile': 获取用户显示名和头像 URL
|
||||
final _googleSignIn = GoogleSignIn(scopes: ['email', 'profile']);
|
||||
|
||||
// fluwx 5.x 使用实例方式调用,registerApi 在 main.dart 中已完成
|
||||
// fluwx 5.x API 迁移说明:
|
||||
// 旧版 (3.x): 顶层 Stream `weChatResponseEventHandler.distinct().listen(...)`
|
||||
// 新版 (5.x): 实例方法 `Fluwx().addSubscriber((response) {...})`
|
||||
//
|
||||
// Fluwx() 底层 MethodChannel 为单例,新建实例不会重复注册 SDK,
|
||||
// registerApi 已在 main.dart 的 app 启动时完成,此处直接使用。
|
||||
final _fluwx = Fluwx();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 监听微信授权回调(用户授权后,微信 App 返回 code)
|
||||
// 订阅微信平台所有回调事件(授权/支付/分享等均通过同一 subscriber 派发)
|
||||
// 通过 `is WeChatAuthResponse` 类型守卫过滤出登录授权响应
|
||||
_fluwx.addSubscriber((response) {
|
||||
if (response is WeChatAuthResponse && mounted) {
|
||||
_handleWechatAuthResp(response);
|
||||
|
|
@ -77,10 +83,20 @@ class _WelcomePageState extends State<WelcomePage> {
|
|||
return;
|
||||
}
|
||||
setState(() => _wechatLoading = true);
|
||||
// NormalAuth: 标准微信 OAuth 授权(弹出微信 App 授权页)
|
||||
// scope: 'snsapi_userinfo' — 获取用户基本信息(需用户手动同意)
|
||||
// 'snsapi_base' — 静默授权(只获取 openid,无需同意页)
|
||||
// state: 任意字符串,原样返回,用于防 CSRF;后端可校验一致性
|
||||
// 旧版: sendWeChatAuth(scope: ..., state: ...)
|
||||
// 新版: authBy(which: NormalAuth(scope: ..., state: ...))
|
||||
await _fluwx.authBy(which: NormalAuth(scope: 'snsapi_userinfo', state: 'genex_login'));
|
||||
// 授权结果通过 addSubscriber 异步回调
|
||||
// 授权结果异步通过 addSubscriber 回调,不在此处等待
|
||||
}
|
||||
|
||||
// WeChatAuthResponse 字段说明:
|
||||
// errCode: 0 = 成功, -4 = 用户拒绝, -2 = 用户取消
|
||||
// code: 一次性授权码(5 分钟有效),发送后端换取 access_token + unionid
|
||||
// 旧版响应类: WXAuthResp,新版: WeChatAuthResponse
|
||||
Future<void> _handleWechatAuthResp(WeChatAuthResponse resp) async {
|
||||
setState(() => _wechatLoading = false);
|
||||
if ((resp.errCode ?? -1) != 0 || resp.code == null) return;
|
||||
|
|
|
|||
|
|
@ -43,17 +43,23 @@ import 'features/profile/presentation/pages/share_page.dart';
|
|||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// ── 微信 SDK 初始化 ────────────────────────────────────────────────────
|
||||
// ── 微信 SDK 初始化 (fluwx 5.x) ──────────────────────────────────────
|
||||
// WECHAT_APP_ID 在构建时通过 --dart-define 注入,例如:
|
||||
// flutter build apk --dart-define=WECHAT_APP_ID=wx0000000000000000
|
||||
// flutter build ipa --dart-define=WECHAT_APP_ID=wx0000000000000000
|
||||
//
|
||||
// 未传入 WECHAT_APP_ID 时(本地开发 / CI 未配置),跳过初始化,
|
||||
// WelcomePage 中点击微信按钮会提示「请先安装微信 App」(isWeChatInstalled=false)。
|
||||
// WelcomePage 中点击微信按钮会提示「微信未安装」(isWeChatInstalled=false)。
|
||||
//
|
||||
// universalLink: iOS Universal Links 地址,需在微信开放平台填写并配置
|
||||
// apple-app-site-association 文件(路径: https://www.gogenex.com/wechat/apple-app-site-association)
|
||||
// 详见: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Universal_Links/Universal_Links.html
|
||||
//
|
||||
// fluwx 5.x 迁移说明:
|
||||
// 旧版 (3.x): 顶层函数 registerWxApi(appId: ..., universalLink: ...)
|
||||
// 新版 (5.x): 实例方法 Fluwx().registerApi(appId: ..., universalLink: ...)
|
||||
// 注册只需执行一次(app 启动时),Fluwx 底层 MethodChannel 为单例,
|
||||
// 后续在 WelcomePage 中新建 Fluwx() 实例可共享同一注册状态。
|
||||
const wechatAppId = String.fromEnvironment('WECHAT_APP_ID', defaultValue: '');
|
||||
if (wechatAppId.isNotEmpty) {
|
||||
await Fluwx().registerApi(appId: wechatAppId, universalLink: 'https://www.gogenex.com/wechat/');
|
||||
|
|
|
|||
Loading…
Reference in New Issue