diff --git a/client/lib/screens/about/about_screen.dart b/client/lib/screens/about/about_screen.dart index 8058460..62cc95b 100644 --- a/client/lib/screens/about/about_screen.dart +++ b/client/lib/screens/about/about_screen.dart @@ -6,7 +6,6 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:intl/intl.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -16,11 +15,9 @@ import '../../core/responsive/responsive.dart'; import '../../core/theme/app_dims.g.dart'; import '../../core/theme/context_tokens.dart'; import '../../core/update/app_updater.dart'; -import '../../core/utils/clock.dart'; import '../../core/utils/dialog_util.dart'; import '../../providers/changelog_provider.dart'; import '../../providers/feedback_provider.dart'; -import '../../providers/license_provider.dart'; import '../../providers/update_provider.dart'; import '../../core/theme/app_fonts.dart'; import '../../widgets/brand_mark.dart'; @@ -55,7 +52,6 @@ class _AboutScreenState extends ConsumerState { children: [ _heroCard(t), _productCard(t), - _licenseCard(t), _changelogCard(t), // 页脚 Padding( @@ -372,72 +368,8 @@ class _AboutScreenState extends ConsumerState { } } - // ── 卡3:授权信息(3 cell)───────────────────────────────── - Widget _licenseCard(dynamic t) { - final lic = ref.watch(licenseProvider).valueOrNull; - final expires = lic?.expiresAt != null - ? DateFormat('yyyy-MM-dd').format(lic!.expiresAt!) - : '—'; - // 状态/剩余天数走可注入时钟(golden 确定化) - final active = lic?.isActive == true && - (lic?.expiresAt == null || lic!.expiresAt!.isAfter(appNow())); - final days = lic?.expiresAt != null - ? lic!.expiresAt!.difference(appNow()).inDays.clamp(0, 99999) - : null; - final mobile = context.isMobile; - final cells = [ - _licCell(t, '授权状态', active ? '已授权' : '未授权', - color: active ? t.success : t.warn), - _licCell(t, '到期日', expires), - _licCell(t, '剩余天数', days != null ? '$days 天' : '—'), - ]; - return _card( - t, - Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - _cardH(t, LucideIcons.shieldCheck, '授权信息'), - if (mobile) - Column(children: [ - for (final c in cells) - Padding(padding: const EdgeInsets.only(bottom: 10), child: c), - ]) - else - Row(children: [ - for (var i = 0; i < cells.length; i++) ...[ - if (i > 0) const SizedBox(width: 14), - Expanded(child: cells[i]), - ], - ]), - ]), - ); - } - - /// 原型 .lic-cell:lk 11 muted + lv 17/700/mono。 - Widget _licCell(dynamic t, String label, String value, {Color? color}) => - Container( - padding: const EdgeInsets.fromLTRB(16, 14, 16, 14), - decoration: BoxDecoration( - color: t.bg, - border: Border.all(color: t.borderSubtle), - borderRadius: BorderRadius.circular(AppDims.rMd), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label, - style: TextStyle(fontSize: AppDims.fsXs, color: t.muted)), - const SizedBox(height: 6), - Text(value, - style: TextStyle( - fontSize: AppDims.fsH2, - fontWeight: FontWeight.w700, - fontFamily: AppFonts.mono, - fontFamilyFallback: AppFonts.monoFallback, - color: color ?? t.heading)), - ], - ), - ); - - // ── 卡4:更新日志(timeline,默认 2 条 + 展开)─────────────── + // ── 卡3:更新日志(timeline,默认 2 条 + 展开)─────────────── + // (原授权信息卡已迁至 设置 → 授权管理) Widget _changelogCard(dynamic t) { final appVersion = ref.watch(appVersionProvider).valueOrNull ?? ''; final entries = ref.watch(changelogProvider).valueOrNull ?? const []; diff --git a/client/lib/screens/settings/settings_screen.dart b/client/lib/screens/settings/settings_screen.dart index 243e8fd..6742112 100644 --- a/client/lib/screens/settings/settings_screen.dart +++ b/client/lib/screens/settings/settings_screen.dart @@ -691,42 +691,38 @@ class _LicensePanelState extends ConsumerState<_LicensePanel> { final expires = lic?.expiresAt != null ? DateFormat('yyyy-MM-dd').format(lic!.expiresAt!) : '—'; - // 剩余天数走可注入时钟(golden 确定化),不用 model 内的 DateTime.now() + // 状态/剩余天数走可注入时钟(golden 确定化),不用 model 内的 DateTime.now() + final active = lic?.isActive == true && + (lic?.expiresAt == null || lic!.expiresAt!.isAfter(appNow())); final days = lic?.expiresAt != null ? lic!.expiresAt!.difference(appNow()).inDays.clamp(0, 99999) : null; + final licCells = [ + _licCell(t, '授权状态', active ? '已授权' : '未授权', + color: active ? t.success : t.warn), + _licCell(t, '到期日', expires), + _licCell(t, '剩余天数', days != null ? '$days 天' : '—'), + ]; return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - // ── 卡1:授权到期时间(原型 .lic 统计条:bg 底 / border / r-md)── + // ── 卡1:授权信息(3 cell,自「关于我们」迁入)── _SettingsCard( - title: '授权到期时间', - desc: '当前门店的授权有效期,续期时长在现有到期时间上叠加', - child: Container( - padding: const EdgeInsets.fromLTRB(20, 18, 20, 18), - decoration: BoxDecoration( - color: t.bg, - border: Border.all(color: t.border), - borderRadius: BorderRadius.circular(AppDims.rMd), - ), - child: Row(children: [ - _stat(t, '授权到期日', expires), - const SizedBox(width: 24), - _stat(t, '剩余天数', days != null ? '剩余 $days 天' : '—', warn: true), - const Spacer(), - Container( - width: 46, - height: 46, - decoration: BoxDecoration( - color: t.okSoft, - borderRadius: BorderRadius.circular(AppDims.rMd), - ), - child: - Icon(LucideIcons.shieldCheck, size: 22, color: t.success), - ), - ]), - ), + title: '授权信息', + desc: '当前门店的授权状态与有效期,续期时长在现有到期时间上叠加', + child: context.isMobile + ? Column(children: [ + for (final c in licCells) + Padding( + padding: const EdgeInsets.only(bottom: 10), child: c), + ]) + : Row(children: [ + for (var i = 0; i < licCells.length; i++) ...[ + if (i > 0) const SizedBox(width: 14), + Expanded(child: licCells[i]), + ], + ]), ), const SizedBox(height: 16), // ── 卡2:在线购买 / 续费(后端 purchase 接口 admin only, @@ -811,20 +807,30 @@ class _LicensePanelState extends ConsumerState<_LicensePanel> { ); } - Widget _stat(dynamic t, String label, String value, {bool warn = false}) => - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label, style: TextStyle(fontSize: AppDims.fsSm, color: t.muted)), - const SizedBox(height: 4), - Text(value, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.w700, - fontFamily: AppFonts.mono, - fontFamilyFallback: AppFonts.monoFallback, - color: warn ? t.warn : t.heading)), - ], + /// 原型 .lic-cell(与「关于我们」同款):lk 11 muted + lv 17/700/mono。 + Widget _licCell(dynamic t, String label, String value, {Color? color}) => + Container( + padding: const EdgeInsets.fromLTRB(16, 14, 16, 14), + decoration: BoxDecoration( + color: t.bg, + border: Border.all(color: t.borderSubtle), + borderRadius: BorderRadius.circular(AppDims.rMd), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, + style: TextStyle(fontSize: AppDims.fsXs, color: t.muted)), + const SizedBox(height: 6), + Text(value, + style: TextStyle( + fontSize: AppDims.fsH2, + fontWeight: FontWeight.w700, + fontFamily: AppFonts.mono, + fontFamilyFallback: AppFonts.monoFallback, + color: color ?? t.heading)), + ], + ), ); } diff --git a/client/test/golden/goldens/about_a.png b/client/test/golden/goldens/about_a.png index 16cd7e5..424e887 100644 Binary files a/client/test/golden/goldens/about_a.png and b/client/test/golden/goldens/about_a.png differ diff --git a/client/test/golden/goldens/about_b.png b/client/test/golden/goldens/about_b.png index 113ee3a..cb82bb0 100644 Binary files a/client/test/golden/goldens/about_b.png and b/client/test/golden/goldens/about_b.png differ diff --git a/client/test/golden/goldens/about_c.png b/client/test/golden/goldens/about_c.png index c933d9b..8cd018f 100644 Binary files a/client/test/golden/goldens/about_c.png and b/client/test/golden/goldens/about_c.png differ diff --git a/client/test/golden/goldens/about_mobile_a.png b/client/test/golden/goldens/about_mobile_a.png index 8fdb1ee..024127b 100644 Binary files a/client/test/golden/goldens/about_mobile_a.png and b/client/test/golden/goldens/about_mobile_a.png differ diff --git a/client/test/golden/goldens/about_mobile_b.png b/client/test/golden/goldens/about_mobile_b.png index fe817c6..a450132 100644 Binary files a/client/test/golden/goldens/about_mobile_b.png and b/client/test/golden/goldens/about_mobile_b.png differ diff --git a/client/test/golden/goldens/about_mobile_c.png b/client/test/golden/goldens/about_mobile_c.png index a2becf3..a329bb3 100644 Binary files a/client/test/golden/goldens/about_mobile_c.png and b/client/test/golden/goldens/about_mobile_c.png differ