refactor(client): 删除死代码 PlansScreen + NavView.plans + choosePlan l10n(Renew→Purchase 直达后无调用者)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-12 18:53:10 +08:00
parent d0bd24bc4b
commit 2416c943cb
12 changed files with 3 additions and 82 deletions
-1
View File
@@ -473,7 +473,6 @@ abstract class AppText {
String get updateCheckFailed; // 检查失败(网络异常)
// ── 套餐选择 ──
String get choosePlan;
String get freePlan;
String get proPlan;
String get teamPlan;
-2
View File
@@ -250,8 +250,6 @@ class StringsEn extends AppText {
@override
String get updateCheckFailed => 'Update check failed, try again later';
@override
String get choosePlan => 'Choose plan';
@override
String get freePlan => 'Free';
@override
-2
View File
@@ -250,8 +250,6 @@ class StringsEs extends AppText {
@override
String get updateCheckFailed => 'Falló la búsqueda de actualizaciones, inténtalo más tarde';
@override
String get choosePlan => 'Elegir plan';
@override
String get freePlan => 'Gratis';
@override
-2
View File
@@ -250,8 +250,6 @@ class StringsJa extends AppText {
@override
String get updateCheckFailed => 'アップデートの確認に失敗しました。後でもう一度お試しください';
@override
String get choosePlan => 'プランを選択';
@override
String get freePlan => '無料';
@override
-2
View File
@@ -250,8 +250,6 @@ class StringsKo extends AppText {
@override
String get updateCheckFailed => '업데이트 확인에 실패했습니다. 잠시 후 다시 시도하세요';
@override
String get choosePlan => '요금제 선택';
@override
String get freePlan => '무료';
@override
-2
View File
@@ -250,8 +250,6 @@ class StringsRu extends AppText {
@override
String get updateCheckFailed => 'Не удалось проверить обновления, попробуйте позже';
@override
String get choosePlan => 'Выбор тарифа';
@override
String get freePlan => 'Бесплатный';
@override
-2
View File
@@ -249,8 +249,6 @@ class StringsZh extends AppText {
@override
String get updateCheckFailed => '检查更新失败,请稍后重试';
@override
String get choosePlan => '选择套餐';
@override
String get freePlan => '免费版';
@override
-4
View File
@@ -49,7 +49,6 @@ class DesktopShell extends ConsumerWidget {
NavView.account: t.tabMe,
NavView.contact: t.contactTitle,
NavView.settings: t.settingsTitle,
NavView.plans: t.choosePlan,
NavView.redeem: t.redeemTitle,
NavView.devices: t.myDevices,
NavView.purchase: t.purchaseTitle,
@@ -76,9 +75,6 @@ class DesktopShell extends ConsumerWidget {
case NavView.settings:
return const SettingsPage();
// 账户下钻子页(内容区,顶栏带返回)
case NavView.plans:
// 只有 pro 走 pay v2 购买通道;team 等仍走既有兑换/联系人工流程。
return PlansScreen(t: t, embedded: true, onChoose: (code) => go(code == 'pro' ? NavView.purchase : NavView.redeem));
case NavView.redeem:
return RedeemScreen(t: t, embedded: true);
case NavView.devices:
+3 -3
View File
@@ -3,11 +3,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
/// 一级视图 + 账户子页。
/// desktop 侧栏暴露 6 个一级项(connect..settings);mobile/tablet 取前 4 项,
/// contact/settings 在 mobile 走账户子页。plans/redeem 是 account 的下钻页。
enum NavView { connect, servers, stats, account, contact, settings, plans, redeem, devices, purchase, payment, orders, invite, notifications }
/// contact/settings 在 mobile 走账户子页。redeem 是 account 的下钻页。
enum NavView { connect, servers, stats, account, contact, settings, redeem, devices, purchase, payment, orders, invite, notifications }
/// 账户下钻子页(desktop 在内容区切换、顶栏带返回;mobile/tablet 走全屏 push)。
const Set<NavView> kAccountSubViews = {NavView.plans, NavView.redeem, NavView.devices, NavView.purchase, NavView.payment, NavView.orders, NavView.invite};
const Set<NavView> kAccountSubViews = {NavView.redeem, NavView.devices, NavView.purchase, NavView.payment, NavView.orders, NavView.invite};
/// 当前视图。
final navViewProvider = StateProvider<NavView>((ref) => NavView.connect);
-61
View File
@@ -20,7 +20,6 @@ import '../services/auth_api.dart';
import '../state/account_providers.dart';
import 'pangolin_button.dart';
import 'pangolin_icons.dart';
import 'plan_card.dart';
/// 通用:带返回箭头的子页骨架。embedded=true 时只返回内容(desktop 内容区下钻,
/// 返回/标题由外层 shell 顶栏提供),否则整页 Scaffoldmobile/tablet 全屏 push)。
@@ -67,66 +66,6 @@ class SettingsScreen extends StatelessWidget {
}
}
/// ── 套餐选择 ── (价格/额度来自 GET /v1/plans;当前档由 me.plan 判定;
/// 功能清单仍取 l10n,后端无此字段)
class PlansScreen extends ConsumerWidget {
const PlansScreen({super.key, required this.t, this.onChoose, this.onBack, this.embedded = false});
final AppText t;
final ValueChanged<String>? onChoose;
final VoidCallback? onBack;
final bool embedded;
List<String> _feats(String code) => switch (code) {
'free' => t.featsFree,
'pro' => t.featsPro,
'team' => t.featsTeam,
_ => const [],
};
// 套餐名是 UI 文案(后端 plans 表无名称列),按 code 取 l10n。
String _name(String code) => switch (code) {
'free' => t.freePlan,
'pro' => t.proPlan,
'team' => t.teamPlan,
_ => code,
};
@override
Widget build(BuildContext context, WidgetRef ref) {
final c = context.pangolin;
final plansAsync = ref.watch(plansProvider);
final myPlan = ref.watch(meProvider).valueOrNull?.plan ?? 'free';
Widget body() => plansAsync.when(
loading: () => const Center(child: Padding(padding: EdgeInsets.all(40), child: CircularProgressIndicator())),
error: (_, __) => Center(
child: Padding(padding: const EdgeInsets.all(40), child: Text(t.lang.loadFailedRetry, style: PangolinText.body.copyWith(color: c.fg3)))),
data: (plans) => ListView(
padding: const EdgeInsets.fromLTRB(20, 14, 20, 24),
children: [
for (final p in plans)
Padding(
padding: EdgeInsets.only(bottom: 14, top: p.code == 'pro' ? 12 : 0),
child: PlanCard(
name: _name(p.code),
price: p.priceLabel(),
period: t.perMonth,
features: _feats(p.code),
ctaLabel: p.code == myPlan ? t.current : (p.code == 'team' ? t.choose : t.upgrade),
featured: p.code == 'pro',
isCurrent: p.code == myPlan,
popularLabel: p.code == 'pro' ? t.mostPopular : null,
onPressed: () => onChoose?.call(p.code),
),
),
],
),
);
return _SubScaffold(title: t.choosePlan, onBack: onBack, embedded: embedded, child: body());
}
}
/// ── 设备管理 ── (真实 GET /v1/me/devices;移除 = DELETE。本机高亮待 P6 设备 id)
class DevicesScreen extends ConsumerWidget {
const DevicesScreen({super.key, required this.t, this.onBack, this.embedded = false});
@@ -70,7 +70,6 @@ void main() {
testWidgets('desktop 联系页', (t) => _shoot(t, NavView.contact, 'desktop_contact'));
testWidgets('desktop 设置页', (t) => _shoot(t, NavView.settings, 'desktop_settings'));
// 账户下钻子页(内容区 + 顶栏返回)
testWidgets('desktop 套餐选择', (t) => _shoot(t, NavView.plans, 'desktop_plans'));
testWidgets('desktop 兑换购买', (t) => _shoot(t, NavView.redeem, 'desktop_redeem'));
testWidgets('desktop 设备管理', (t) => _shoot(t, NavView.devices, 'desktop_devices'));
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB