diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d3cdc40..8bb4ea21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,104 @@
***
+## [v6.10.3] - 2026-06-02
+
+### 🌐 多语言翻译字段补全
+
+**问题:** 新增 `roleNative`(原生栈)和7个分发渠道翻译字段后,10个非中英语言文件缺少这些字段导致编译 Error。
+
+**修复方案:**
+- ✅ 10个语言文件(es, fr, it, pt, ru, ar, hi, bn, ko, ja, zh_tw, de)补全8个 TAbout 字段
+- ✅ `roleNative` — 各语言原生栈翻译
+- ✅ `distributionChannel` — 分发渠道标题
+- ✅ `distAndroid/distIOS/distMacOS/distHarmony/distWeb/distWindows` — 各平台分发说明
+- ✅ fr.dart 双引号 lint 修复
+
+**涉及文件:**
+- `lib/l10n/languages/es.dart` — 西班牙语
+- `lib/l10n/languages/fr.dart` — 法语
+- `lib/l10n/languages/it.dart` — 意大利语
+- `lib/l10n/languages/pt.dart` — 葡萄牙语
+- `lib/l10n/languages/ru.dart` — 俄语
+- `lib/l10n/languages/ar.dart` — 阿拉伯语
+- `lib/l10n/languages/hi.dart` — 印地语
+- `lib/l10n/languages/bn.dart` — 孟加拉语
+- `lib/l10n/languages/ko.dart` — 韩语
+- `lib/l10n/languages/ja.dart` — 日语
+- `lib/l10n/languages/zh_tw.dart` — 繁体中文
+- `lib/l10n/languages/de.dart` — 德语
+
+***
+
+## [v6.10.2] - 2026-06-02
+
+### 🔐 二维码扫码登录自动跳转
+
+**问题:** Device A 扫描 Device B(登录页)的二维码后,Device A 显示"扫码成功"但 Device B 无响应,不会自动登录。
+
+**根因:** 生成二维码后缺少轮询/WebSocket 监听机制,无法感知扫码确认状态变化。
+
+**修复方案:**
+- ✅ `qrcode_login_provider.dart` — 新增 `waiting`/`scanned`/`logging` 步骤,生成二维码后自动启动 HTTP 轮询(3秒间隔) + WebSocket 双通道监听
+- ✅ 收到 `confirmed` + `token` 后自动调用 `AuthService.tokenLogin(token)` 完成登录
+- ✅ `qrcode_ws_service.dart` — 处理 confirmed 状态携带 token 的推送,终态自动取消订阅
+- ✅ `qrcode_login_page.dart` — 新增状态指示器(等待扫码/已扫码/正在登录),登录成功后自动跳转首页
+- ✅ 切换 Tab / 退出页面时自动停止轮询,防止资源泄漏
+
+**涉及文件:**
+- `features/auth/providers/qrcode_login_provider.dart` — 核心轮询+自动登录逻辑
+- `features/auth/services/qrcode_ws_service.dart` — WS终态自动取消订阅
+- `features/auth/presentation/qrcode_login_page.dart` — UI状态指示+自动跳转
+
+***
+
+## [v6.10.1] - 2026-06-02
+
+### 🐛 修复 iOS 离线模式 Syncfusion Chart 崩溃
+
+**问题:** 点击"离线模式"或导航到含图表页面时,Syncfusion Chart 在 build/layout 阶段调用 `markNeedsLayout`,导致 "build during layout" 错误,App 卡死/闪退。
+
+**根因:** Syncfusion Flutter Charts 已知 Bug — `ChartSeriesRenderer.markNeedsLayout` 在 widget 树构建期间被调用,违反 Flutter 渲染协议。
+
+**修复方案:**
+- ✅ 增强 `DeferredBuilder` — 添加 `RepaintBoundary` 隔离重绘 + 可选 `placeholder` 参数
+- ✅ 全项目 **21个文件、约35处** Syncfusion 图表全部用 `DeferredBuilder` 包裹,延迟到 `postFrameCallback` 渲染
+- ✅ 所有图表系列补齐 `animationDuration: 0`,防止动画触发 `markNeedsLayout`
+
+**涉及文件:**
+- `shared/widgets/containers/deferred_builder.dart` — 增加 RepaintBoundary + placeholder
+- `features/mine/user_center/` — learning_charts, learning_center_page, coin_log_page, learning_progress_page
+- `features/tool_center/statistics/` — learning_stats_tab, coin_stats_tab, favorite_stats_tab, statistics_page
+- `features/reading_report/` — trend_chart
+- `features/file_transfer/` — transfer_speed_chart, transfer_stats_page
+- `features/mine/achievement/` — achievement_page
+- `features/check/` — check_page
+- `features/discover/` — readlater_stats_page
+- `features/home/` — history_page, favorite_page
+- `features/tool_center/leisure/` — leisure_settings_sections
+- `features/mine/settings/` — data_management_page, translate_plugin_page, permission_management_page
+
+***
+
## [v6.10.0] - 2026-06-02
-### 🏗️ 架构优化 + 灵动岛增强 + Lint规则 + 应用图标
+### 🏗️ 架构优化 + 灵动岛增强 + Lint规则 + 应用图标 + 引导页协议多语言
+
+**0. 协议页软件著作权证书图片 📜:**
+- 🔄 协议内容"2.1 平台版权"→"2.1 软件著作权"(中文+英文同步修改)
+- ✅ 新增 `WatermarkedCopyrightImage` 组件 — 展示软件著作权证书图片
+- ✅ 对角线"闲言"水印覆盖(CustomPaint + 旋转文字)
+- ✅ 点击图片弹出全屏查看(InteractiveViewer 支持缩放)
+- ✅ 通用协议页 + 引导页协议页 均支持图片展示
+- ✅ 图片右上角全屏提示标签
+
+**1. 引导页协议多语言修复 🌐:**
+- 🐛 修复引导页协议内容始终显示中文的问题
+- ✅ `AgreementData.getContent/getUpdateDate` 传入当前语言ID
+- ✅ `agreementType.title` → `agreementType.titleFor(languageId)` 显示本地化标题
+- ✅ `_parseChapters` 章节解析兼容英文罗马数字编号(I. II. III. / Zero.)
+- ✅ 新增 `_localeToLanguageId` 方法将 Flutter Locale 映射为协议语言ID
+- ✅ 支持14种语言的协议内容、标题、更新日期自动切换
**1. MacosPlatformService 统一 🏗️:**
- 🔄 分散在多文件的 MethodChannel 统一为 `MacosPlatformService`
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 41d081b6..ce5be335 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -104,24 +104,5 @@
group.apps.xy.xianyan.share
- UIApplicationShortcutItems
-
-
- UIApplicationShortcutItemType
- action_theme
- UIApplicationShortcutItemTitle
- 主题个性化
- UIApplicationShortcutItemIconName
- palette
-
-
- UIApplicationShortcutItemType
- action_general_settings
- UIApplicationShortcutItemTitle
- 通用设置
- UIApplicationShortcutItemIconName
- settings
-
-
diff --git a/lib/app/app.dart b/lib/app/app.dart
index 152eb68d..6e9cb334 100644
--- a/lib/app/app.dart
+++ b/lib/app/app.dart
@@ -24,6 +24,7 @@ import 'package:flutter_quill/flutter_quill.dart'
import 'package:flutter/services.dart';
import '../core/services/device/quick_actions_service.dart';
+import '../core/services/device/macos_platform_service.dart';
import '../core/services/data/home_widget_service.dart';
import '../core/services/ui/status_bar_service.dart';
import '../core/router/app_router.dart' show appRouter, rootNavigatorKey;
@@ -222,6 +223,18 @@ class _XianyanAppState extends ConsumerState
}
}
+ @override
+ void didChangePlatformBrightness() {
+ super.didChangePlatformBrightness();
+ final settings = ref.read(themeSettingsProvider);
+ if (settings.themeMode == AppThemeMode.system) {
+ final isDark =
+ WidgetsBinding.instance.platformDispatcher.platformBrightness ==
+ Brightness.dark;
+ MacosPlatformService.syncTheme(isDark);
+ }
+ }
+
@override
void didChangeLocales(List? locales) {
super.didChangeLocales(locales);
@@ -316,6 +329,15 @@ class _XianyanAppState extends ConsumerState
final themeMode = _resolveThemeMode(settings.themeMode);
+ final effectiveIsDark = switch (themeMode) {
+ ThemeMode.dark => true,
+ ThemeMode.light => false,
+ ThemeMode.system =>
+ WidgetsBinding.instance.platformDispatcher.platformBrightness ==
+ Brightness.dark,
+ };
+ MacosPlatformService.syncTheme(effectiveIsDark);
+
return Directionality(
textDirection: textDirection,
child: _LocaleTransitionWrapper(
diff --git a/lib/features/agreements/data/agreement_data.dart b/lib/features/agreements/data/agreement_data.dart
index ae1554d4..5cdf1369 100644
--- a/lib/features/agreements/data/agreement_data.dart
+++ b/lib/features/agreements/data/agreement_data.dart
@@ -872,7 +872,7 @@ class AgreementData {
二、内容版权归属
-2.1 平台版权
+2.1 软件著作权
• **闲言APP**的软件著作权归**弥勒市朋普镇微风暴网络科技工作室**所有
• 软件著作权登记号:【2020SR0421982】
• 应用的界面设计、图标、代码等受【著作权法】保护
@@ -1996,7 +1996,7 @@ I. Disclaimers
II. Content Copyright
-2.1 Platform Copyright
+2.1 Software Copyright
• The software copyright of **Xianyan APP** belongs to **Mile City Pengpu Town Weifengbao Network Technology Studio**
• Software Copyright Registration Number: 2020SR0421982
• The interface design, icons, code, etc. of the app are protected by copyright law
diff --git a/lib/features/agreements/presentation/agreement_page.dart b/lib/features/agreements/presentation/agreement_page.dart
index d1348f60..99487939 100644
--- a/lib/features/agreements/presentation/agreement_page.dart
+++ b/lib/features/agreements/presentation/agreement_page.dart
@@ -16,6 +16,7 @@ import '../../../core/theme/app_typography.dart';
import '../../../core/theme/app_radius.dart';
import '../../../l10n/app_locale.dart';
import '../../../shared/widgets/containers/glass_container.dart';
+import '../../../shared/widgets/media/watermarked_copyright_image.dart';
import '../data/agreement_types.dart';
import '../data/agreement_data.dart';
import '../../../shared/widgets/adaptive/adaptive_back_button.dart';
@@ -199,6 +200,10 @@ class _AgreementSection extends StatelessWidget {
final AppThemeExtension ext;
final _Section section;
+ bool get _isCopyrightSection =>
+ section.title.contains('软件著作权') ||
+ section.title.contains('Software Copyright');
+
@override
Widget build(BuildContext context) {
return Padding(
@@ -217,6 +222,10 @@ class _AgreementSection extends StatelessWidget {
const SizedBox(height: AppSpacing.sm),
],
if (section.body.isNotEmpty) _RichBody(ext: ext, text: section.body),
+ if (_isCopyrightSection) ...[
+ const SizedBox(height: AppSpacing.sm),
+ const WatermarkedCopyrightImage(),
+ ],
],
),
);
diff --git a/lib/features/auth/presentation/login_page.dart b/lib/features/auth/presentation/login_page.dart
index 2b5b17d0..ad7af208 100644
--- a/lib/features/auth/presentation/login_page.dart
+++ b/lib/features/auth/presentation/login_page.dart
@@ -489,7 +489,7 @@ class _LoginPageState extends ConsumerState
ext,
icon: CupertinoIcons.person_2,
label: auth.legacyUser,
- accentColor: Theme.of(context).colorScheme.secondary,
+ accentColor: ext.accentLight,
onTap: () => _switchLoginMode(_LoginMode.legacy),
),
const SizedBox(width: AppSpacing.lg),
@@ -678,7 +678,9 @@ class _LoginPageState extends ConsumerState
child: GestureDetector(
onTap: () => _showAgreement(true),
child: Text(
- '《${auth.userAgreement}》',
+ auth.userAgreement.startsWith('《')
+ ? auth.userAgreement
+ : '《${auth.userAgreement}》',
style: AppTypography.footnote.copyWith(
color: ext.accent,
fontWeight: FontWeight.w600,
@@ -696,7 +698,9 @@ class _LoginPageState extends ConsumerState
child: GestureDetector(
onTap: () => _showAgreement(false),
child: Text(
- '《${auth.privacyPolicy}》',
+ auth.privacyPolicy.startsWith('《')
+ ? auth.privacyPolicy
+ : '《${auth.privacyPolicy}》',
style: AppTypography.footnote.copyWith(
color: ext.accent,
fontWeight: FontWeight.w600,
diff --git a/lib/features/auth/presentation/qrcode_login_page.dart b/lib/features/auth/presentation/qrcode_login_page.dart
index 033b0bba..ded5c05e 100644
--- a/lib/features/auth/presentation/qrcode_login_page.dart
+++ b/lib/features/auth/presentation/qrcode_login_page.dart
@@ -1,9 +1,9 @@
/// ============================================================
/// 闲言APP — 二维码登录页面
/// 创建时间: 2026-05-10
-/// 更新时间: 2026-05-10
+/// 更新时间: 2026-06-02
/// 作用: 扫码登录(扫描Web端二维码确认登录)+ 生成二维码(Web端扫码登录)
-/// 上次更新: 初始创建
+/// 上次更新: 生成二维码后自动轮询监听,confirmed后自动tokenLogin跳转首页
/// ============================================================
import 'dart:async';
@@ -15,11 +15,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:qr_flutter/qr_flutter.dart';
+import '../../../core/router/app_routes.dart';
+import '../../../core/router/app_nav_extension.dart';
import '../../../core/theme/app_radius.dart';
import '../../../core/theme/app_spacing.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/theme/app_typography.dart';
import '../../../core/utils/logger.dart';
+import '../providers/auth_provider.dart';
import '../providers/qrcode_login_provider.dart';
import '../../../shared/widgets/adaptive/adaptive_back_button.dart';
import '../../../shared/widgets/feedback/app_toast.dart';
@@ -45,6 +48,7 @@ class _QrcodeLoginPageState extends ConsumerState {
bool _hasScanned = false;
StreamSubscription