Commit 7f4473c5c59e9c7054109a272e0834e03094b789

Authored by 常守达
1 parent ffa69d85

feat(ui): 鸿蒙下单掉用

... ... @@ -33,6 +33,8 @@ class SubmitFeedbackController extends GetxController {
});
}
static const maxVideoSizeBytes = 200 * 1024 * 1024;
Future<void> pickImages() async {
final remainingCount = maxImageCount - selectedImages.length;
if (remainingCount <= 0) {
... ... @@ -53,7 +55,22 @@ class SubmitFeedbackController extends GetxController {
if (images.isEmpty) return;
selectedImages.addAll(images.take(remainingCount));
final validImages = <XFile>[];
var hasOversizedFile = false;
for (final file in images) {
final size = await file.length();
if (size > maxVideoSizeBytes) {
hasOversizedFile = true;
continue;
}
validImages.add(file);
}
if (hasOversizedFile) {
AppToast.show('单个文件大小不能超过 200MB');
}
selectedImages.addAll(validImages);
}
void removeImage(XFile image) {
... ...
... ... @@ -9,6 +9,7 @@ import 'package:doublefeel_flutter/app/modules/home/widgets/today/no_health_data
import 'package:doublefeel_flutter/app/modules/login/views/email_login_contact_us_bottom_sheet.dart';
import 'package:doublefeel_flutter/app/modules/report_common/models/report_period.dart';
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/core/config/app_environment_config.dart';
import 'package:doublefeel_flutter/core/constants/intent_keys.dart';
import 'package:doublefeel_flutter/core/logging/app_logger.dart';
... ... @@ -737,9 +738,11 @@ class TodayController extends GetxController with WidgetsBindingObserver {
final result = await _payApi.getProductList();
if (result is! AppSuccess<PayProductListResponse>) return;
final products = (result.data.productList ?? const <PayProduct>[])
.where((product) => _nonEmpty(product.appleId) != null)
.toList();
final products = isIOS()
? (result.data.productList ?? const <PayProduct>[])
.where((product) => _nonEmpty(product.appleId) != null)
.toList()
: (result.data.productList ?? const <PayProduct>[]);
yearlyProduct.value =
products.firstWhereOrNull((p) => p.content?.isDiscountOffer == 1);
// AppLogger.e(yearlyProduct);
... ... @@ -774,26 +777,42 @@ class TodayController extends GetxController with WidgetsBindingObserver {
}
String originDisplayPrice() {
final appleInfo = yearlyProductAppleInfo.value;
if (appleInfo == null) return '';
final actual =
appleInfo.price > 0 ? appleInfo.price : appleInfo.originPrice;
final inflated = actual / 100.0 * 1.2;
// 保留两位小数,单位与 currencyCode 一致
return '${appleInfo.currencyCode}${inflated.toStringAsFixed(2)}';
if (isIOS()) {
final appleInfo = yearlyProductAppleInfo.value;
if (appleInfo == null) return '';
final actual =
appleInfo.price > 0 ? appleInfo.price : appleInfo.originPrice;
final inflated = actual / 100.0 * 1.2;
// 保留两位小数,单位与 currencyCode 一致
return '${appleInfo.currencyCode}${inflated.toStringAsFixed(2)}';
} else if (isOhos()) {
final actual = yearlyProduct.value?.price ?? 0;
final inflated = actual / 100.0 * 1.2;
// 保留两位小数,单位与 currencyCode 一致
return ${inflated.toStringAsFixed(2)}';
} else {
return '';
}
}
String displayPrice() {
final appleInfo = yearlyProductAppleInfo.value;
if (appleInfo == null) return '';
final price = appleInfo.price;
if (price > 0) {
final priceDescription = appleInfo.priceDescription.trim();
if (priceDescription.isNotEmpty) {
return priceDescription;
if (isIOS()) {
final appleInfo = yearlyProductAppleInfo.value;
if (appleInfo == null) return '';
final price = appleInfo.price;
if (price > 0) {
final priceDescription = appleInfo.priceDescription.trim();
if (priceDescription.isNotEmpty) {
return priceDescription;
}
}
return appleInfo.originPriceDescription;
} else if (isOhos()) {
final actual = (yearlyProduct.value?.price ?? 0) / 100.0;
return ${actual.toStringAsFixed(2)}';
} else {
return '';
}
return appleInfo.originPriceDescription;
}
@override
... ...
... ... @@ -9,6 +9,7 @@ import 'package:doublefeel_flutter/app/modules/watch_theme/models/watch_theme_mo
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/app/utils/assets_helper.dart';
import 'package:doublefeel_flutter/app/utils/dialog_utils.dart';
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/core/config/app_environment_config.dart';
import 'package:doublefeel_flutter/core/services/thinking_data_service.dart';
import 'package:doublefeel_flutter/core/theme/app_theme.dart';
... ... @@ -57,12 +58,14 @@ class MyTab extends GetView<MyController> {
? _ProCard(vipInfo: vipInfo)
: _UnlockPremiumCard(controller),
const SizedBox(height: 12),
_WatchThemeCard(
themes: controller.watchThemeItems,
isLoading: controller.isLoadingWatchThemes.value,
onTap: () => controller.goWatchThemePage(),
),
const SizedBox(height: 12),
if (isIOS()) ...[
_WatchThemeCard(
themes: controller.watchThemeItems,
isLoading: controller.isLoadingWatchThemes.value,
onTap: () => controller.goWatchThemePage(),
),
const SizedBox(height: 12)
],
_SettingsRow(
title: context.l10n.accountInformation,
onTap: () => Get.to(
... ...
... ... @@ -10,7 +10,8 @@ import 'today_faq_bottom_sheet.dart';
void showHrvPrincipleExplanationBottomSheet(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final statusBarHeight = MediaQuery.of(context).padding.top;
final maxChildSize = (screenHeight - statusBarHeight) / screenHeight;
final maxChildSize =
isOhos() ? 0.8 : (screenHeight - statusBarHeight) / screenHeight;
Get.bottomSheet(
DraggableScrollableSheet(
maxChildSize: maxChildSize,
... ...
import 'package:doublefeel_flutter/app/modules/home/controllers/today_controller.dart';
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/core/theme/app_theme.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:flutter/material.dart';
... ... @@ -95,9 +96,11 @@ class PremiumCard extends StatelessWidget {
],
),
const Spacer(),
Obx(() => controller.yearlyProductAppleInfo.value !=
null &&
controller.yearlyProduct.value != null
Obx(() => (isIOS()
? controller.yearlyProductAppleInfo.value !=
null &&
controller.yearlyProduct.value != null
: controller.yearlyProduct.value != null)
? Row(
children: [
Text(
... ... @@ -110,7 +113,8 @@ class PremiumCard extends StatelessWidget {
),
const SizedBox(width: 6),
Text(
controller.displayPrice(),
l10n.originalPrice(
controller.displayPrice()),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
... ...
import 'dart:async';
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/app/utils/assets_helper.dart';
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/core/services/thinking_data_service.dart';
import 'package:doublefeel_flutter/core/theme/app_theme.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
... ... @@ -287,7 +288,7 @@ class TodayAdCarousel extends StatelessWidget {
),
);
}
if (showHrv) {
if (isIOS() && showHrv) {
activeBanners.add(
TodayHrvAdBanner(
controller: controller,
... ...
... ... @@ -30,25 +30,25 @@ class MembershipDetailController extends GetxController {
final isUnlocking = false.obs;
Future<void> unlock() async {
isUnlocking.value = true;
try {
final orderResult = await _payApi.createOrderByApple(123);
if (orderResult is! AppSuccess<ApplePayOrderResponse>) return;
final orderUuid = orderResult.data.orderInfo?.orderUuid?.trim();
if (orderUuid == null || orderUuid.isEmpty) {
AppToast.show(l10n.purchaseOrderInfoUnavailable);
return;
}
final paymentResult = await _performApplePayment(
productId: 'appleProductId',
orderUuid: orderUuid,
);
await _handleApplePaymentResult(paymentResult);
} finally {
isUnlocking.value = false;
}
// isUnlocking.value = true;
// try {
// final orderResult = await _payApi.createOrderByApple(123);
// if (orderResult is! AppSuccess<ApplePayOrderResponse>) return;
// final orderUuid = orderResult.data.orderInfo?.orderUuid?.trim();
// if (orderUuid == null || orderUuid.isEmpty) {
// AppToast.show(l10n.purchaseOrderInfoUnavailable);
// return;
// }
// final paymentResult = await _performApplePayment(
// productId: 'appleProductId',
// orderUuid: orderUuid,
// );
// await _handleApplePaymentResult(paymentResult);
// } finally {
// isUnlocking.value = false;
// }
}
Future<void> _handleApplePaymentResult(
... ...
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/core/network/api/pay_api.dart';
import 'package:doublefeel_flutter/core/network/api/vip_api.dart';
import 'package:doublefeel_flutter/core/result/app_result.dart';
... ... @@ -22,41 +23,84 @@ class MembershipOfferController extends GetxController {
final UserPreferencesStorage _userPreferences =
Get.find<UserPreferencesStorage>();
final AppPlatformHostApi _platformHostApi = AppPlatformHostApi();
final AlipayHostApi _alipayHostApi = AlipayHostApi();
final isUnlocking = false.obs;
Future<void> unlock() async {
if (isUnlocking.value) return;
final productId = yearlyProduct.value?.id;
final appleProductId = yearlyProduct.value?.appleId;
if (productId == null || appleProductId == null || appleProductId.isEmpty) {
AppToast.show(l10n.purchaseProductInfoUnavailable);
return;
}
isUnlocking.value = true;
try {
final orderResult = await _payApi.createOrderByApple(productId);
if (orderResult is! AppSuccess<ApplePayOrderResponse>) {
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
if (isOhos()) {
if (productId == null) {
AppToast.show(l10n.purchaseProductInfoUnavailable);
return;
}
isUnlocking.value = true;
final orderResult = await _payApi.createCustomOrder(
productId: productId,
paymentChannel: PaymentChannel.alipay.value,
productChannel: ProductChannel.huawei.value,
);
if (orderResult is! AppSuccess<ApplePayOrderResponse>) {
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
}
return;
}
return;
}
final orderUuid = orderResult.data.orderInfo?.orderUuid?.trim();
if (orderUuid == null || orderUuid.isEmpty) {
AppToast.show(l10n.purchaseOrderInfoUnavailable);
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
final prepayData = orderResult.data.prepayData?.trim();
if (prepayData == null || prepayData.isEmpty) {
AppToast.show(l10n.purchaseOrderInfoUnavailable);
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
}
return;
}
return;
}
final paymentResult = await _performApplePayment(
productId: appleProductId,
orderUuid: orderUuid,
);
await _handleApplePaymentResult(paymentResult);
//todo 鸿蒙Alipay prepayData
final result = await _alipayHostApi.launchAliPay(prepayData);
if (result == AliPayResultCode.success) {
_trackSuccessPayOrder();
await _completeSuccessfulPurchase();
} else if (result == AliPayResultCode.error) {
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
}
}
} else if (isIOS()) {
final appleProductId = yearlyProduct.value?.appleId;
if (productId == null ||
appleProductId == null ||
appleProductId.isEmpty) {
AppToast.show(l10n.purchaseProductInfoUnavailable);
return;
}
isUnlocking.value = true;
final orderResult = await _payApi.createOrderByApple(productId);
if (orderResult is! AppSuccess<ApplePayOrderResponse>) {
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
}
return;
}
final orderUuid = orderResult.data.orderInfo?.orderUuid?.trim();
if (orderUuid == null || orderUuid.isEmpty) {
AppToast.show(l10n.purchaseOrderInfoUnavailable);
if (isFromOnboard) {
Get.offAllNamed(AppRoutes.home, arguments: {'isFromOnboard': true});
}
return;
}
final paymentResult = await _performApplePayment(
productId: appleProductId,
orderUuid: orderUuid,
);
await _handleApplePaymentResult(paymentResult);
}
} finally {
isUnlocking.value = false;
}
... ... @@ -87,13 +131,16 @@ class MembershipOfferController extends GetxController {
}
trackMap['product_type'] = yearlyProduct.value?.appleId;
trackMap['price'] = yearlyProduct.value?.price;
final appleInfo = yearlyProductAppleInfo.value;
trackMap['currency_code'] = appleInfo?.currencyCode ?? '';
var actualPrice = appleInfo?.price ?? 0;
trackMap['actual_price'] =
actualPrice > 0 ? actualPrice : (appleInfo?.originPrice ?? 0);
if (isOhos()) {
trackMap['currency_code'] = 'CN';
trackMap['actual_price'] = yearlyProduct.value?.price;
} else if (isIOS()) {
final appleInfo = yearlyProductAppleInfo.value;
trackMap['currency_code'] = appleInfo?.currencyCode ?? '';
var actualPrice = appleInfo?.price ?? 0;
trackMap['actual_price'] =
actualPrice > 0 ? actualPrice : (appleInfo?.originPrice ?? 0);
}
ta.track(
'success_doublefeel_pay_order',
... ... @@ -192,19 +239,24 @@ class MembershipOfferController extends GetxController {
final result = await _payApi.getProductList();
if (result is! AppSuccess<PayProductListResponse>) return;
final products = (result.data.productList ?? const <PayProduct>[])
.where((product) => _nonEmpty(product.appleId) != null)
.toList();
yearlyProduct.value =
products.firstWhereOrNull((p) => p.content?.isDiscountOffer == 1);
if (yearlyProduct.value != null) {
final appleProductId = _nonEmpty(yearlyProduct.value!.appleId);
if (appleProductId == null) return;
yearlyProductAppleInfo.value = await _requestAppleProductInfo(
productId: appleProductId,
baseUnit: yearlyProduct.value!.content?.baseUnit() ?? 1);
if (isIOS()) {
final products = (result.data.productList ?? const <PayProduct>[])
.where((product) => _nonEmpty(product.appleId) != null)
.toList();
yearlyProduct.value =
products.firstWhereOrNull((p) => p.content?.isDiscountOffer == 1);
if (yearlyProduct.value != null) {
final appleProductId = _nonEmpty(yearlyProduct.value!.appleId);
if (appleProductId == null) return;
yearlyProductAppleInfo.value = await _requestAppleProductInfo(
productId: appleProductId,
baseUnit: yearlyProduct.value!.content?.baseUnit() ?? 1);
}
} else if (isOhos()) {
final products = (result.data.productList ?? const <PayProduct>[]);
yearlyProduct.value =
products.firstWhereOrNull((p) => p.content?.isDiscountOffer == 1);
}
}
... ...
import 'package:doublefeel_flutter/app/modules/membership_offer/controllers/membership_offer_controller.dart';
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/core/theme/app_theme.dart';
import 'package:doublefeel_flutter/data/models/pay/pay_models.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
... ... @@ -78,51 +79,97 @@ class MembershipOfferView extends GetView<MembershipOfferController> {
'assets/images/user_onboarding/ic_membership_box.png'),
const SizedBox(height: 4),
Obx(() {
final yearInfo =
controller.yearlyProductAppleInfo.value;
final yearProduct = controller.yearlyProduct.value;
return yearInfo == null || yearProduct == null
? const SizedBox(
child: CircularProgressIndicator())
: Column(
children: [
Text(
context.l10n.originalPricePerYear(
_originDisplayPrice(yearInfo)),
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 16,
decoration:
TextDecoration.lineThrough,
decorationColor: Color(0xFF78787D),
letterSpacing: 0,
if (isOhos()) {
return (yearProduct == null)
? const SizedBox(
child: CircularProgressIndicator())
: Column(
children: [
Text(
context.l10n.originalPricePerYear(
_originDisplayPriceOhos(
yearProduct)),
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 16,
decoration:
TextDecoration.lineThrough,
decorationColor: Color(0xFF78787D),
letterSpacing: 0,
),
),
const SizedBox(height: 6),
Text(
_displayPriceOhos(yearProduct),
textAlign: TextAlign.center,
style: TextStyle(
color: context.colors.primary,
fontSize: 28,
fontWeight: FontWeight.w600,
letterSpacing: 0,
),
),
const SizedBox(height: 6),
Text(
_planSubtitleOhos(yearProduct),
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 12,
letterSpacing: 0,
),
),
),
const SizedBox(height: 6),
Text(
_displayPrice(yearInfo),
textAlign: TextAlign.center,
style: TextStyle(
color: context.colors.primary,
fontSize: 28,
fontWeight: FontWeight.w600,
letterSpacing: 0,
],
);
} else if (isIOS()) {
final yearInfo =
controller.yearlyProductAppleInfo.value;
return (yearInfo == null || yearProduct == null)
? const SizedBox(
child: CircularProgressIndicator())
: Column(
children: [
Text(
context.l10n.originalPricePerYear(
_originDisplayPrice(yearInfo)),
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 16,
decoration:
TextDecoration.lineThrough,
decorationColor: Color(0xFF78787D),
letterSpacing: 0,
),
),
),
const SizedBox(height: 6),
Text(
_planSubtitle(yearProduct, yearInfo),
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 12,
letterSpacing: 0,
const SizedBox(height: 6),
Text(
_displayPrice(yearInfo),
textAlign: TextAlign.center,
style: TextStyle(
color: context.colors.primary,
fontSize: 28,
fontWeight: FontWeight.w600,
letterSpacing: 0,
),
),
),
],
);
const SizedBox(height: 6),
Text(
_planSubtitle(yearProduct, yearInfo),
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 12,
letterSpacing: 0,
),
),
],
);
} else {
return SizedBox();
}
}),
],
),
... ... @@ -186,6 +233,22 @@ class MembershipOfferView extends GetView<MembershipOfferController> {
return appleInfo.originPriceDescription;
}
String _originDisplayPriceOhos(PayProduct product) {
final inflated = (product.price ?? 0) / 100.0 * 1.2;
return ${inflated.toStringAsFixed(2)}';
}
String _displayPriceOhos(PayProduct product) {
final actual = (product.price ?? 0) / 100.0;
return ${actual.toStringAsFixed(2)}';
}
String _planSubtitleOhos(PayProduct product) {
final monthly = (product.price ?? 0) / 100.0 / 12;
return l10n.purchaseMonthlyUnitPrice(monthly.toStringAsFixed(2));
}
String? _nonEmpty(String? value) {
final trimmed = value?.trim();
if (trimmed == null || trimmed.isEmpty) return null;
... ...
import 'package:doublefeel_flutter/app/utils/platform_compact.dart';
import 'package:doublefeel_flutter/data/models/pay/apple_pay_order_response.dart';
import '../../result/app_result.dart';
... ... @@ -17,8 +18,12 @@ class PayApi {
final response = await _dioClient.dio.get(
ApiPaths.paymentProducts,
queryParameters: {
'product_type': productType ?? 1,
'product_channel': 2,
'product_type': productType ?? ProductType.vip.value,
'product_channel': isOhos()
? ProductChannel.huawei.value
: (isIOS()
? ProductChannel.apple.value
: ProductChannel.self.value),
},
);
return PayProductListResponse.fromJson(
... ... @@ -35,8 +40,8 @@ class PayApi {
ApiPaths.paymentOrder,
data: CreatePayOrderRequest(
productId: productId,
productChannel: 2,
paymentChannel: 3,
productChannel: ProductChannel.apple.value,
paymentChannel: PaymentChannel.apple.value,
).toJson(),
);
return ApplePayOrderResponse.fromJson(
... ... @@ -66,6 +71,28 @@ class PayApi {
);
}
Future<AppResult<ApplePayOrderResponse>> createCustomOrder({
required int productId,
required int paymentChannel,
required int productChannel,
}) {
return safeCall(
call: () async {
final response = await _dioClient.dio.post(
ApiPaths.paymentOrder,
data: CreatePayOrderRequest(
productId: productId,
paymentChannel: paymentChannel,
productChannel: productChannel,
).toJson(),
);
return ApplePayOrderResponse.fromJson(
response.data as Map<String, dynamic>,
);
},
);
}
Future<AppResult<SubscriptionProductListResponse>> getSubscriptionList() {
return safeCall(
call: () async {
... ... @@ -89,3 +116,44 @@ class PayApi {
);
}
}
enum ProductType {
/// 会员 (1)
vip(1),
/// 订阅会员 (10)
subscriptionVip(10);
const ProductType(this.value);
final int value;
}
/// 商品渠道
enum ProductChannel {
/// 自营 (1)
self(1),
/// 苹果 (2)
apple(2),
/// 华为 (3)
huawei(3);
const ProductChannel(this.value);
final int value;
}
/// 支付渠道
enum PaymentChannel {
/// 微信 (1)
wechat(1),
/// 支付宝 (2)
alipay(2),
/// 苹果 (3)
apple(3);
const PaymentChannel(this.value);
final int value;
}
... ...
class ApplePayOrderResponse {
const ApplePayOrderResponse({this.orderInfo});
const ApplePayOrderResponse({this.orderInfo, this.prepayData});
final ApplePayOrderInfo? orderInfo;
final String? prepayData;
factory ApplePayOrderResponse.fromJson(Map<String, dynamic> json) {
return ApplePayOrderResponse(
prepayData: json['prepay_data'] as String?,
orderInfo: json['order_info'] == null
? null
: ApplePayOrderInfo.fromJson(
... ... @@ -15,6 +17,7 @@ class ApplePayOrderResponse {
Map<String, dynamic> toJson() {
final val = <String, dynamic>{};
if (prepayData != null) val['prepay_data'] = prepayData;
if (orderInfo != null) val['order_info'] = orderInfo!.toJson();
return val;
}
... ...
... ... @@ -1188,7 +1188,7 @@
"annualMemberDiscounts": "年度会员优惠",
"specialOffers": "优惠",
"currentPrice": "现价",
"originalPrice": "原价{price}",
"originalPrice": "原价{price}/年",
"@originalPrice": {
"description": "原价标签",
"placeholders": {
... ...
... ... @@ -667,7 +667,7 @@
"annualMemberDiscounts": "年度会员优惠",
"specialOffers": "优惠",
"currentPrice": "现价",
"originalPrice": "原价{price}",
"originalPrice": "原价{price}/年",
"freeRedemptionOffer": "免费兑换优惠",
"cellPhoneNumber": "手机号",
"todayOnWeeklyCalendar": "今",
... ...
... ... @@ -667,7 +667,7 @@
"annualMemberDiscounts": "年度會員優惠",
"specialOffers": "優惠",
"currentPrice": "現價",
"originalPrice": "原價{price}",
"originalPrice": "原價{price}/年",
"freeRedemptionOffer": "免費兌換優惠",
"cellPhoneNumber": "手機號",
"todayOnWeeklyCalendar": "今",
... ...
... ... @@ -4132,7 +4132,7 @@ abstract class AppLocalizations {
/// 原价标签
///
/// In zh, this message translates to:
/// **'原价{price}'**
/// **'原价{price}/年'**
String originalPrice(String price);
/// No description provided for @freeRedemptionOffer.
... ...
... ... @@ -2205,7 +2205,7 @@ class AppLocalizationsZh extends AppLocalizations {
@override
String originalPrice(String price) {
return '原价$price';
return '原价$price/年';
}
@override
... ... @@ -5007,7 +5007,7 @@ class AppLocalizationsZhHans extends AppLocalizationsZh {
@override
String originalPrice(String price) {
return '原价$price';
return '原价$price/年';
}
@override
... ... @@ -7809,7 +7809,7 @@ class AppLocalizationsZhHant extends AppLocalizationsZh {
@override
String originalPrice(String price) {
return '原價$price';
return '原價$price/年';
}
@override
... ...