From dca69d095afedb0eb90abee095e095d74242fc30 Mon Sep 17 00:00:00 2001 From: chuxuehaocai Date: Fri, 29 May 2026 12:51:23 +0800 Subject: [PATCH] feat:improve logic --- lib/config/strings.dart | 1 + lib/main.dart | 11 ++++ lib/pages/home_page.dart | 97 ++++++++++++++++++++++++++--- lib/services/title_api_service.dart | 4 +- 4 files changed, 105 insertions(+), 8 deletions(-) diff --git a/lib/config/strings.dart b/lib/config/strings.dart index 80bad74..c0e5280 100644 --- a/lib/config/strings.dart +++ b/lib/config/strings.dart @@ -19,6 +19,7 @@ class AppStrings { static const qrScanSuccess = '二维码解析成功'; static const qrScanFailed = '未能识别二维码,请手动粘贴内容'; static const qrScanError = '解析失败'; + static const forcePreviewApi = '强制使用 Preview API'; static const loginFailed = '登录失败'; static const requestFailed = '请求失败'; static const settingsTooltip = '设置'; diff --git a/lib/main.dart b/lib/main.dart index 7de2b65..8df26f0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -51,6 +51,7 @@ class _LoginPageState extends State { final _apiService = ApiService(); String _qrCode = ''; bool _loading = false; + bool _forcePreviewApi = false; @override void dispose() { @@ -115,6 +116,7 @@ class _LoginPageState extends State { userId: result.userId, token: result.token, cookies: result.cookies, + forcePreviewApi: _forcePreviewApi, ), ), ); @@ -317,6 +319,15 @@ class _LoginPageState extends State { ), ], ), + const SizedBox(height: 16), + CheckboxListTile( + value: _forcePreviewApi, + onChanged: (v) => setState(() => _forcePreviewApi = v ?? false), + title: const Text(AppStrings.forcePreviewApi), + controlAffinity: ListTileControlAffinity.leading, + contentPadding: EdgeInsets.zero, + dense: true, + ), ], ), ), diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 8bd3ddd..f6d52ab 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -14,12 +14,14 @@ class HomePage extends StatefulWidget { final int userId; final String token; final String? cookies; + final bool forcePreviewApi; const HomePage({ super.key, required this.userId, required this.token, this.cookies, + this.forcePreviewApi = false, }); @override @@ -34,6 +36,7 @@ class _HomePageState extends State { String? _error; bool _loading = true; bool _loggingOut = false; + String? _sessionCookies; static const _tabTitles = [ AppStrings.tabHome, @@ -76,10 +79,12 @@ class _HomePageState extends State { token: widget.token, ); if (!mounted) return; + _sessionCookies = service.cookies; setState(() => _preview = preview); // isLogin == true => 已有人登录, 不再走完整登录, 直接展示 preview 概要 - if (preview.isLogin) { + // forcePreviewApi => 跳过 UserLoginApi, 仅展示 preview + Login 按钮 + if (preview.isLogin || widget.forcePreviewApi) { setState(() => _loading = false); return; } @@ -89,10 +94,55 @@ class _HomePageState extends State { token: widget.token, ); if (!mounted) return; + _sessionCookies = service.cookies; setState(() => _login = login); final userData = await service.getUserDataTyped(widget.userId); if (!mounted) return; + _sessionCookies = service.cookies; + setState(() { + _userData = userData; + _loading = false; + }); + } on TitleApiException catch (e) { + if (!mounted) return; + setState(() { + _error = e.message; + _loading = false; + }); + } catch (e) { + if (!mounted) return; + setState(() { + _error = e.toString(); + _loading = false; + }); + } + } + + Future _performLogin() async { + if (!TitleServerConfigHolder().isConfigured) return; + setState(() { + _loading = true; + _error = null; + }); + + final service = TitleApiService( + TitleServerConfigHolder().config!, + cookies: _sessionCookies ?? widget.cookies, + ); + + try { + final login = await service.userLoginFull( + userId: widget.userId, + token: widget.token, + ); + if (!mounted) return; + _sessionCookies = service.cookies; + setState(() => _login = login); + + final userData = await service.getUserDataTyped(widget.userId); + if (!mounted) return; + _sessionCookies = service.cookies; setState(() { _userData = userData; _loading = false; @@ -118,7 +168,7 @@ class _HomePageState extends State { if (!TitleServerConfigHolder().isConfigured) return; final service = TitleApiService( TitleServerConfigHolder().config!, - cookies: widget.cookies, + cookies: _sessionCookies ?? widget.cookies, ); try { await service.userLogout( @@ -171,7 +221,7 @@ class _HomePageState extends State { _buildBody(theme), TicketPage( userId: widget.userId, - cookies: widget.cookies, + cookies: _sessionCookies ?? widget.cookies, loginDateTime: _login?.loginDateTime, playerRating: _userData?.playerRating ?? _preview?.playerRating ?? 0, onLogoutRequested: _login != null ? _logoutSession : null, @@ -268,8 +318,13 @@ class _HomePageState extends State { return const SizedBox.shrink(); } - if (preview.isLogin && userData == null) { - return _buildPreviewOnly(theme, preview); + if ((preview.isLogin || (widget.forcePreviewApi && _login == null)) && userData == null) { + return _buildPreviewOnly( + theme, + preview, + showLoginButton: widget.forcePreviewApi && _login == null, + onLoginPressed: _performLogin, + ); } if (userData != null) { @@ -279,7 +334,12 @@ class _HomePageState extends State { return const SizedBox.shrink(); } - Widget _buildPreviewOnly(ThemeData theme, UserPreviewDataBean preview) { + Widget _buildPreviewOnly( + ThemeData theme, + UserPreviewDataBean preview, { + bool showLoginButton = false, + VoidCallback? onLoginPressed, + }) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: ConstrainedBox( @@ -295,12 +355,35 @@ class _HomePageState extends State { borderRadius: BorderRadius.circular(10), ), child: Text( - AppStrings.inheritedAccountNotice, + showLoginButton ? 'Preview API 模式,点击下方按钮登录。' : AppStrings.inheritedAccountNotice, style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onTertiaryContainer, ), ), ), + if (showLoginButton) ...[ + const SizedBox(height: 12), + SizedBox( + width: double.infinity, + child: FilledButton.icon( + onPressed: _loading ? null : onLoginPressed, + icon: _loading + ? const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Icon(Icons.login, size: 20), + label: Text(_loading ? AppStrings.loggingIn : AppStrings.login), + style: FilledButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + ), + ), + ], const SizedBox(height: 12), _ProfileFromPreviewCard(theme: theme, preview: preview), const SizedBox(height: 12), diff --git a/lib/services/title_api_service.dart b/lib/services/title_api_service.dart index db744a8..bc0564f 100644 --- a/lib/services/title_api_service.dart +++ b/lib/services/title_api_service.dart @@ -40,7 +40,9 @@ class TitleApiService { final TitleServerConfig _config; String? _cookies; - TitleApiService(this._config, {this._cookies}); + TitleApiService(this._config, {String? cookies}) : _cookies = cookies; + + String? get cookies => _cookies; Uint8List _aesEncrypt(Uint8List plaintext) { final cipher = PaddedBlockCipherImpl(