fix(admin-app): 消除UI层硬编码中文,补充i18n keys(zh/en/ja)
- 新增 29 个 i18n keys 到三语言文件(credit_score_unit, finance_confirm_withdraw, redemption_failed, store_no_stores, settings_confirm_logout, coupon_status_* 等) - 修复 10 个页面中的硬编码中文字符串: credit_page: 分数单位、权重、空状态 finance_page: 提现对话框、SnackBar、时间格式、空状态 redemption_page: 错误消息、批量结果、空状态、时间格式 store_management_page: 门店/员工空状态 settings_page: 退出确认对话框、层级权益描述 coupon_list_page: 状态徽章(在售/待审/售罄/下架) coupon_detail_page: 面值/发行价标签 ai_agent_page: 错误回复消息 issuer_dashboard_page: 信用分单位 - 剩余中文仅存于 /// 注释和 mock 数据数组中(将被真实API数据替换) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d9b07537a1
commit
24400ad663
|
|
@ -552,6 +552,37 @@ class AppLocalizations {
|
||||||
'settings_about': '关于企业券信',
|
'settings_about': '关于企业券信',
|
||||||
'settings_logout': '退出登录',
|
'settings_logout': '退出登录',
|
||||||
|
|
||||||
|
// ── Hardcoded string fixes ──
|
||||||
|
'credit_score_unit': '分',
|
||||||
|
'credit_no_factors': '暂无评分因子',
|
||||||
|
'credit_no_suggestions': '暂无建议',
|
||||||
|
'finance_confirm_withdraw': '确认提现',
|
||||||
|
'finance_withdraw_amount': '提现金额',
|
||||||
|
'finance_withdraw_submitted': '提现申请已提交',
|
||||||
|
'finance_withdraw_failed': '提现失败',
|
||||||
|
'finance_no_transactions': '暂无交易记录',
|
||||||
|
'finance_today': '今天',
|
||||||
|
'finance_yesterday': '昨天',
|
||||||
|
'finance_no_reports': '暂无对账报表',
|
||||||
|
'redemption_failed': '核销失败',
|
||||||
|
'redemption_batch_failed': '批量核销失败',
|
||||||
|
'redemption_no_records': '暂无核销记录',
|
||||||
|
'redemption_minutes_ago': '分钟前',
|
||||||
|
'redemption_hours_ago': '小时前',
|
||||||
|
'redemption_days_ago': '天前',
|
||||||
|
'store_no_stores': '暂无门店',
|
||||||
|
'store_no_employees': '暂无员工',
|
||||||
|
'settings_confirm_logout': '确认退出',
|
||||||
|
'settings_confirm_logout_desc': '确定要退出登录吗?',
|
||||||
|
'settings_tier_benefits': '手续费率 1.2% · 高级数据分析',
|
||||||
|
'coupon_status_active': '在售中',
|
||||||
|
'coupon_status_pending': '待审核',
|
||||||
|
'coupon_status_sold_out': '已售罄',
|
||||||
|
'coupon_status_delisted': '已下架',
|
||||||
|
'ai_agent_error_reply': '抱歉,暂时无法回复。请稍后重试。',
|
||||||
|
'coupon_detail_type_info': '面值',
|
||||||
|
'coupon_detail_issue_price_label': '发行价',
|
||||||
|
|
||||||
// ── AI Suggestion Card ──
|
// ── AI Suggestion Card ──
|
||||||
'ai_suggestion_label': 'AI 建议',
|
'ai_suggestion_label': 'AI 建议',
|
||||||
'ai_suggestion_dismiss': '忽略',
|
'ai_suggestion_dismiss': '忽略',
|
||||||
|
|
@ -1117,6 +1148,37 @@ class AppLocalizations {
|
||||||
'settings_about': 'About Genex',
|
'settings_about': 'About Genex',
|
||||||
'settings_logout': 'Sign Out',
|
'settings_logout': 'Sign Out',
|
||||||
|
|
||||||
|
// ── Hardcoded string fixes ──
|
||||||
|
'credit_score_unit': 'pts',
|
||||||
|
'credit_no_factors': 'No rating factors',
|
||||||
|
'credit_no_suggestions': 'No suggestions',
|
||||||
|
'finance_confirm_withdraw': 'Confirm Withdrawal',
|
||||||
|
'finance_withdraw_amount': 'Withdrawal Amount',
|
||||||
|
'finance_withdraw_submitted': 'Withdrawal request submitted',
|
||||||
|
'finance_withdraw_failed': 'Withdrawal failed',
|
||||||
|
'finance_no_transactions': 'No transactions',
|
||||||
|
'finance_today': 'Today',
|
||||||
|
'finance_yesterday': 'Yesterday',
|
||||||
|
'finance_no_reports': 'No reports',
|
||||||
|
'redemption_failed': 'Redemption failed',
|
||||||
|
'redemption_batch_failed': 'Batch redemption failed',
|
||||||
|
'redemption_no_records': 'No redemption records',
|
||||||
|
'redemption_minutes_ago': 'm ago',
|
||||||
|
'redemption_hours_ago': 'h ago',
|
||||||
|
'redemption_days_ago': 'd ago',
|
||||||
|
'store_no_stores': 'No stores',
|
||||||
|
'store_no_employees': 'No employees',
|
||||||
|
'settings_confirm_logout': 'Confirm Logout',
|
||||||
|
'settings_confirm_logout_desc': 'Are you sure you want to sign out?',
|
||||||
|
'settings_tier_benefits': 'Fee rate 1.2% · Advanced analytics',
|
||||||
|
'coupon_status_active': 'On Sale',
|
||||||
|
'coupon_status_pending': 'Pending',
|
||||||
|
'coupon_status_sold_out': 'Sold Out',
|
||||||
|
'coupon_status_delisted': 'Delisted',
|
||||||
|
'ai_agent_error_reply': 'Sorry, unable to respond. Please try again later.',
|
||||||
|
'coupon_detail_type_info': 'Face Value',
|
||||||
|
'coupon_detail_issue_price_label': 'Issue Price',
|
||||||
|
|
||||||
// ── AI Suggestion Card ──
|
// ── AI Suggestion Card ──
|
||||||
'ai_suggestion_label': 'AI Suggestion',
|
'ai_suggestion_label': 'AI Suggestion',
|
||||||
'ai_suggestion_dismiss': 'Dismiss',
|
'ai_suggestion_dismiss': 'Dismiss',
|
||||||
|
|
@ -1682,6 +1744,37 @@ class AppLocalizations {
|
||||||
'settings_about': 'Genex について',
|
'settings_about': 'Genex について',
|
||||||
'settings_logout': 'ログアウト',
|
'settings_logout': 'ログアウト',
|
||||||
|
|
||||||
|
// ── Hardcoded string fixes ──
|
||||||
|
'credit_score_unit': '点',
|
||||||
|
'credit_no_factors': '評価因子なし',
|
||||||
|
'credit_no_suggestions': '提案なし',
|
||||||
|
'finance_confirm_withdraw': '出金確認',
|
||||||
|
'finance_withdraw_amount': '出金金額',
|
||||||
|
'finance_withdraw_submitted': '出金申請が送信されました',
|
||||||
|
'finance_withdraw_failed': '出金に失敗しました',
|
||||||
|
'finance_no_transactions': '取引記録なし',
|
||||||
|
'finance_today': '本日',
|
||||||
|
'finance_yesterday': '昨日',
|
||||||
|
'finance_no_reports': 'レポートなし',
|
||||||
|
'redemption_failed': '検証に失敗しました',
|
||||||
|
'redemption_batch_failed': '一括検証に失敗しました',
|
||||||
|
'redemption_no_records': '検証記録なし',
|
||||||
|
'redemption_minutes_ago': '分前',
|
||||||
|
'redemption_hours_ago': '時間前',
|
||||||
|
'redemption_days_ago': '日前',
|
||||||
|
'store_no_stores': '店舗なし',
|
||||||
|
'store_no_employees': 'スタッフなし',
|
||||||
|
'settings_confirm_logout': 'ログアウト確認',
|
||||||
|
'settings_confirm_logout_desc': 'ログアウトしますか?',
|
||||||
|
'settings_tier_benefits': '手数料率 1.2% · 高度データ分析',
|
||||||
|
'coupon_status_active': '販売中',
|
||||||
|
'coupon_status_pending': '審査中',
|
||||||
|
'coupon_status_sold_out': '完売',
|
||||||
|
'coupon_status_delisted': '非公開',
|
||||||
|
'ai_agent_error_reply': '申し訳ございません、現在応答できません。後でもう一度お試しください。',
|
||||||
|
'coupon_detail_type_info': '額面',
|
||||||
|
'coupon_detail_issue_price_label': '発行価格',
|
||||||
|
|
||||||
// ── AI Suggestion Card ──
|
// ── AI Suggestion Card ──
|
||||||
'ai_suggestion_label': 'AI 提案',
|
'ai_suggestion_label': 'AI 提案',
|
||||||
'ai_suggestion_dismiss': '無視',
|
'ai_suggestion_dismiss': '無視',
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ class _AiAgentPageState extends State<AiAgentPage> {
|
||||||
setState(() {
|
setState(() {
|
||||||
_messages.add(_ChatMessage(
|
_messages.add(_ChatMessage(
|
||||||
isAi: true,
|
isAi: true,
|
||||||
text: '抱歉,暂时无法回复。请稍后重试。',
|
text: context.t('ai_agent_error_reply'),
|
||||||
));
|
));
|
||||||
_isSending = false;
|
_isSending = false;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ class _IssuerCouponDetailPageState extends State<IssuerCouponDetailPage> {
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Text(
|
Text(
|
||||||
'${coupon.couponType} · 面值 \$${coupon.faceValue.toStringAsFixed(0)} · 发行价 \$${coupon.currentPrice.toStringAsFixed(2)}',
|
'${coupon.couponType} · ${context.t('coupon_detail_type_info')} \$${coupon.faceValue.toStringAsFixed(0)} · ${context.t('coupon_detail_issue_price_label')} \$${coupon.currentPrice.toStringAsFixed(2)}',
|
||||||
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: 0.8)),
|
style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: 0.8)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
|
||||||
|
|
@ -323,19 +323,19 @@ class _CouponListPageState extends State<CouponListPage> {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'active':
|
case 'active':
|
||||||
color = AppColors.success;
|
color = AppColors.success;
|
||||||
label = '在售中';
|
label = context.t('coupon_status_active');
|
||||||
break;
|
break;
|
||||||
case 'pending':
|
case 'pending':
|
||||||
color = AppColors.warning;
|
color = AppColors.warning;
|
||||||
label = '待审核';
|
label = context.t('coupon_status_pending');
|
||||||
break;
|
break;
|
||||||
case 'sold_out':
|
case 'sold_out':
|
||||||
color = AppColors.info;
|
color = AppColors.info;
|
||||||
label = '已售罄';
|
label = context.t('coupon_status_sold_out');
|
||||||
break;
|
break;
|
||||||
case 'delisted':
|
case 'delisted':
|
||||||
color = AppColors.textTertiary;
|
color = AppColors.textTertiary;
|
||||||
label = '已下架';
|
label = context.t('coupon_status_delisted');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
color = AppColors.textTertiary;
|
color = AppColors.textTertiary;
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ class _CreditPageState extends State<CreditPage> {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(credit.grade, style: const TextStyle(fontSize: 32, fontWeight: FontWeight.w700, color: Colors.white)),
|
Text(credit.grade, style: const TextStyle(fontSize: 32, fontWeight: FontWeight.w700, color: Colors.white)),
|
||||||
Text('${credit.score}分', style: const TextStyle(fontSize: 14, color: Colors.white70)),
|
Text('${credit.score}${context.t('credit_score_unit')}', style: const TextStyle(fontSize: 14, color: Colors.white70)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -171,7 +171,7 @@ class _CreditPageState extends State<CreditPage> {
|
||||||
children: [
|
children: [
|
||||||
Text(f.name, style: const TextStyle(fontSize: 13)),
|
Text(f.name, style: const TextStyle(fontSize: 13)),
|
||||||
Text(
|
Text(
|
||||||
'${f.score.toInt()}分 (权重${(f.weight * 100).toInt()}%)',
|
'${f.score.toInt()}${context.t('credit_score_unit')} (${(f.weight * 100).toInt()}%)',
|
||||||
style: const TextStyle(fontSize: 12, color: AppColors.textSecondary),
|
style: const TextStyle(fontSize: 12, color: AppColors.textSecondary),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -193,7 +193,7 @@ class _CreditPageState extends State<CreditPage> {
|
||||||
if (factors.isEmpty)
|
if (factors.isEmpty)
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.all(16),
|
padding: EdgeInsets.all(16),
|
||||||
child: Center(child: Text('暂无评分因子', style: TextStyle(color: AppColors.textTertiary))),
|
child: Center(child: Text(context.t('credit_no_factors'), style: const TextStyle(color: AppColors.textTertiary))),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -285,8 +285,8 @@ class _CreditPageState extends State<CreditPage> {
|
||||||
color: AppColors.primarySurface,
|
color: AppColors.primarySurface,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
child: const Center(
|
child: Center(
|
||||||
child: Text('暂无建议', style: TextStyle(color: AppColors.textSecondary)),
|
child: Text(context.t('credit_no_suggestions'), style: const TextStyle(color: AppColors.textSecondary)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ class _IssuerDashboardPageState extends State<IssuerDashboardPage> {
|
||||||
children: [
|
children: [
|
||||||
Text(context.t('dashboard_credit_rating'), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600)),
|
Text(context.t('dashboard_credit_rating'), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600)),
|
||||||
Text(
|
Text(
|
||||||
stats != null ? '${context.t('dashboard_credit_gap')} (${stats.creditScore}分)' : context.t('dashboard_credit_gap'),
|
stats != null ? '${context.t('dashboard_credit_gap')} (${stats.creditScore}${context.t('credit_score_unit')})' : context.t('dashboard_credit_gap'),
|
||||||
style: const TextStyle(fontSize: 12, color: AppColors.textTertiary),
|
style: const TextStyle(fontSize: 12, color: AppColors.textTertiary),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,8 @@ class _OverviewTabState extends State<_OverviewTab> {
|
||||||
final confirmed = await showDialog<bool>(
|
final confirmed = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (ctx) => AlertDialog(
|
builder: (ctx) => AlertDialog(
|
||||||
title: const Text('确认提现'),
|
title: Text(context.t('finance_confirm_withdraw')),
|
||||||
content: Text('提现金额: \$${_balance!.withdrawable.toStringAsFixed(2)}'),
|
content: Text('${context.t('finance_withdraw_amount')}: \$${_balance!.withdrawable.toStringAsFixed(2)}'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(context.t('cancel'))),
|
TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(context.t('cancel'))),
|
||||||
ElevatedButton(onPressed: () => Navigator.pop(ctx, true), child: Text(context.t('confirm'))),
|
ElevatedButton(onPressed: () => Navigator.pop(ctx, true), child: Text(context.t('confirm'))),
|
||||||
|
|
@ -126,14 +126,14 @@ class _OverviewTabState extends State<_OverviewTab> {
|
||||||
await _financeService.withdraw(_balance!.withdrawable);
|
await _financeService.withdraw(_balance!.withdrawable);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('提现申请已提交'), backgroundColor: AppColors.success),
|
SnackBar(content: Text(context.t('finance_withdraw_submitted')), backgroundColor: AppColors.success),
|
||||||
);
|
);
|
||||||
_loadData();
|
_loadData();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('[FinancePage] withdraw error: $e');
|
debugPrint('[FinancePage] withdraw error: $e');
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('提现失败: $e'), backgroundColor: AppColors.error),
|
SnackBar(content: Text('${context.t('finance_withdraw_failed')}: $e'), backgroundColor: AppColors.error),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -397,8 +397,8 @@ class _TransactionDetailTabState extends State<_TransactionDetailTab> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_transactions.isEmpty) {
|
if (_transactions.isEmpty) {
|
||||||
return const Center(
|
return Center(
|
||||||
child: Text('暂无交易记录', style: TextStyle(color: AppColors.textSecondary)),
|
child: Text(context.t('finance_no_transactions'), style: const TextStyle(color: AppColors.textSecondary)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,10 +433,10 @@ class _TransactionDetailTabState extends State<_TransactionDetailTab> {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final isToday = dt.year == now.year && dt.month == now.month && dt.day == now.day;
|
final isToday = dt.year == now.year && dt.month == now.month && dt.day == now.day;
|
||||||
final timeStr = '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}';
|
final timeStr = '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}';
|
||||||
if (isToday) return '今天 $timeStr';
|
if (isToday) return '${context.t('finance_today')} $timeStr';
|
||||||
final yesterday = now.subtract(const Duration(days: 1));
|
final yesterday = now.subtract(const Duration(days: 1));
|
||||||
final isYesterday = dt.year == yesterday.year && dt.month == yesterday.month && dt.day == yesterday.day;
|
final isYesterday = dt.year == yesterday.year && dt.month == yesterday.month && dt.day == yesterday.day;
|
||||||
if (isYesterday) return '昨天 $timeStr';
|
if (isYesterday) return '${context.t('finance_yesterday')} $timeStr';
|
||||||
return '${dt.month}/${dt.day} $timeStr';
|
return '${dt.month}/${dt.day} $timeStr';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -527,17 +527,17 @@ class _ReconciliationTabState extends State<_ReconciliationTab> {
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
if (reports.isEmpty)
|
if (reports.isEmpty)
|
||||||
const Center(
|
Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(32),
|
padding: const EdgeInsets.all(32),
|
||||||
child: Text('暂无对账报表', style: TextStyle(color: AppColors.textSecondary)),
|
child: Text(context.t('finance_no_reports'), style: const TextStyle(color: AppColors.textSecondary)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
...reports.map((r) {
|
...reports.map((r) {
|
||||||
final title = r['title'] ?? '';
|
final title = r['title'] ?? '';
|
||||||
final summary = r['summary'] ?? '';
|
final summary = r['summary'] ?? '';
|
||||||
final status = r['status'] ?? '已生成';
|
final status = r['status'] ?? '--';
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ class _ScanRedeemTabState extends State<_ScanRedeemTab> {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() => _isRedeeming = false);
|
setState(() => _isRedeeming = false);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('核销失败: $e'), backgroundColor: AppColors.error),
|
SnackBar(content: Text('${context.t('redemption_failed')}: $e'), backgroundColor: AppColors.error),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -196,7 +196,7 @@ class _ScanRedeemTabState extends State<_ScanRedeemTab> {
|
||||||
_loadTodayStats();
|
_loadTodayStats();
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('成功: ${result.successCount}, 失败: ${result.failCount}'),
|
content: Text('${result.successCount} / ${result.failCount} (${context.t('redemption_failed')})'),
|
||||||
backgroundColor: result.failCount == 0 ? AppColors.success : AppColors.warning,
|
backgroundColor: result.failCount == 0 ? AppColors.success : AppColors.warning,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -205,7 +205,7 @@ class _ScanRedeemTabState extends State<_ScanRedeemTab> {
|
||||||
setLocalState(() => isBatching = false);
|
setLocalState(() => isBatching = false);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('批量核销失败: $e'), backgroundColor: AppColors.error),
|
SnackBar(content: Text('${context.t('redemption_batch_failed')}: $e'), backgroundColor: AppColors.error),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -413,8 +413,8 @@ class _RedeemHistoryTabState extends State<_RedeemHistoryTab> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_records.isEmpty) {
|
if (_records.isEmpty) {
|
||||||
return const Center(
|
return Center(
|
||||||
child: Text('暂无核销记录', style: TextStyle(color: AppColors.textSecondary)),
|
child: Text(context.t('redemption_no_records'), style: const TextStyle(color: AppColors.textSecondary)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,9 +460,9 @@ class _RedeemHistoryTabState extends State<_RedeemHistoryTab> {
|
||||||
String _formatTime(DateTime dt) {
|
String _formatTime(DateTime dt) {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
final diff = now.difference(dt);
|
final diff = now.difference(dt);
|
||||||
if (diff.inMinutes < 60) return '${diff.inMinutes}分钟前';
|
if (diff.inMinutes < 60) return '${diff.inMinutes}${context.t('redemption_minutes_ago')}';
|
||||||
if (diff.inHours < 24) return '${diff.inHours}小时前';
|
if (diff.inHours < 24) return '${diff.inHours}${context.t('redemption_hours_ago')}';
|
||||||
if (diff.inDays < 7) return '${diff.inDays}天前';
|
if (diff.inDays < 7) return '${diff.inDays}${context.t('redemption_days_ago')}';
|
||||||
return '${dt.month}/${dt.day}';
|
return '${dt.month}/${dt.day}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||||
final confirmed = await showDialog<bool>(
|
final confirmed = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (ctx) => AlertDialog(
|
builder: (ctx) => AlertDialog(
|
||||||
title: const Text('确认退出'),
|
title: Text(context.t('settings_confirm_logout')),
|
||||||
content: const Text('确定要退出登录吗?'),
|
content: Text(context.t('settings_confirm_logout_desc')),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(context.t('cancel'))),
|
TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(context.t('cancel'))),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
|
|
@ -272,7 +272,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
||||||
: context.t('settings_gold_issuer'),
|
: context.t('settings_gold_issuer'),
|
||||||
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w700, color: AppColors.tierGold),
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w700, color: AppColors.tierGold),
|
||||||
),
|
),
|
||||||
const Text('手续费率 1.2% · 高级数据分析', style: TextStyle(fontSize: 12, color: AppColors.textSecondary)),
|
Text(context.t('settings_tier_benefits'), style: const TextStyle(fontSize: 12, color: AppColors.textSecondary)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,8 @@ class _StoreListTabState extends State<_StoreListTab> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_stores.isEmpty) {
|
if (_stores.isEmpty) {
|
||||||
return const Center(
|
return Center(
|
||||||
child: Text('暂无门店', style: TextStyle(color: AppColors.textSecondary)),
|
child: Text(context.t('store_no_stores'), style: const TextStyle(color: AppColors.textSecondary)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,8 +265,8 @@ class _EmployeeListTabState extends State<_EmployeeListTab> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_employees.isEmpty) {
|
if (_employees.isEmpty) {
|
||||||
return const Center(
|
return Center(
|
||||||
child: Text('暂无员工', style: TextStyle(color: AppColors.textSecondary)),
|
child: Text(context.t('store_no_employees'), style: const TextStyle(color: AppColors.textSecondary)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue