fix: align photo unit prices and update purchase labels

This commit is contained in:
2026-09-15 11:23:48 +08:00
parent b1cdc1fe06
commit 5f8586666c
2 changed files with 25 additions and 15 deletions
@@ -289,7 +289,7 @@ class RecentPhotosFlowTest {
compose.onNodeWithText("全选").performClick() compose.onNodeWithText("全选").performClick()
compose.waitUntil(10_000) { resultVm.totalPrice.value == "4.00" } compose.waitUntil(10_000) { resultVm.totalPrice.value == "4.00" }
assertEquals(2, resultVm.selectedPhotos.value.size) assertEquals(2, resultVm.selectedPhotos.value.size)
compose.onNodeWithText("支付打印版\n4元").assertIsEnabled() compose.onNodeWithText("购买打印照片\n4元").assertIsEnabled()
screenshot("recent-photos-results") screenshot("recent-photos-results")
compose.onAllNodesWithText("点击预览")[0].performClick() compose.onAllNodesWithText("点击预览")[0].performClick()
compose.onNodeWithContentDescription("关闭").assertIsDisplayed().performClick() compose.onNodeWithContentDescription("关闭").assertIsDisplayed().performClick()
@@ -342,7 +342,7 @@ class RecentPhotosFlowTest {
compose.onNodeWithText("打印版 2元/张").assertIsDisplayed() compose.onNodeWithText("打印版 2元/张").assertIsDisplayed()
compose.onNodeWithText("电子版 1元/张").assertIsDisplayed() compose.onNodeWithText("电子版 1元/张").assertIsDisplayed()
screenshot("purchase-two-modes") screenshot("purchase-two-modes")
compose.onNodeWithText("支付电子版\n1元").performClick() compose.onNodeWithText("购买电子照片\n1元").performClick()
compose.waitUntil(10_000) { requests.any { it.url.encodedPath.endsWith("pay-success-message") } } compose.waitUntil(10_000) { requests.any { it.url.encodedPath.endsWith("pay-success-message") } }
compose.onNodeWithText("微信支付").assertIsDisplayed() compose.onNodeWithText("微信支付").assertIsDisplayed()
compose.onNodeWithText("订单金额 1元").assertDoesNotExist() compose.onNodeWithText("订单金额 1元").assertDoesNotExist()
@@ -374,7 +374,7 @@ class RecentPhotosFlowTest {
compose.runOnIdle { resultVm.retryQuote() } compose.runOnIdle { resultVm.retryQuote() }
compose.waitUntil(10_000) { !resultVm.quoteLoading.value } compose.waitUntil(10_000) { !resultVm.quoteLoading.value }
compose.onNodeWithText("电子版暂不可购买").assertIsNotEnabled() compose.onNodeWithText("电子版暂不可购买").assertIsNotEnabled()
compose.onNodeWithText("支付打印版\n2元").assertIsEnabled() compose.onNodeWithText("购买打印照片\n2元").assertIsEnabled()
} }
private fun pushCompletion(number: String = "MOCK-RECENT-1", mode: String = "electronic") { private fun pushCompletion(number: String = "MOCK-RECENT-1", mode: String = "electronic") {
@@ -389,7 +389,7 @@ class RecentPhotosFlowTest {
val routes = CopyOnWriteArrayList<String>() val routes = CopyOnWriteArrayList<String>()
val collector = kotlinx.coroutines.CoroutineScope(kotlinx.coroutines.Dispatchers.Main).launchCollect(nav) { routes.add(it) } val collector = kotlinx.coroutines.CoroutineScope(kotlinx.coroutines.Dispatchers.Main).launchCollect(nav) { routes.add(it) }
try { try {
compose.onNodeWithText("支付电子版\n1元").performClick() compose.onNodeWithText("购买电子照片\n1元").performClick()
compose.waitUntil(10_000) { requests.any { it.url.encodedPath.endsWith("pay-success-message") } } compose.waitUntil(10_000) { requests.any { it.url.encodedPath.endsWith("pay-success-message") } }
compose.waitForIdle() compose.waitForIdle()
assertTrue(routes.isEmpty()) assertTrue(routes.isEmpty())
@@ -410,26 +410,26 @@ class RecentPhotosFlowTest {
showElectronicSelection("1.00") showElectronicSelection("1.00")
queryFails = true queryFails = true
val quotesBefore = requests.count { it.url.encodedPath.endsWith("verify-result") } val quotesBefore = requests.count { it.url.encodedPath.endsWith("verify-result") }
compose.onNodeWithText("支付电子版\n1元").performClick() compose.onNodeWithText("购买电子照片\n1元").performClick()
compose.waitUntil(10_000) { requests.count { it.url.encodedPath.endsWith("verify-result") } > quotesBefore && !resultVm.quoteLoading.value } compose.waitUntil(10_000) { requests.count { it.url.encodedPath.endsWith("verify-result") } > quotesBefore && !resultVm.quoteLoading.value }
assertNull(resultVm.payQrCodeUrl.value) assertNull(resultVm.payQrCodeUrl.value)
compose.onNodeWithText("微信支付").assertDoesNotExist() compose.onNodeWithText("微信支付").assertDoesNotExist()
compose.onNodeWithText("支付电子版\n1元").assertIsEnabled() compose.onNodeWithText("购买电子照片\n1元").assertIsEnabled()
} }
@Test fun rejectedLinkRestoresButtonsAndQuoteBusinessErrorsRemainVisible() { @Test fun rejectedLinkRestoresButtonsAndQuoteBusinessErrorsRemainVisible() {
showElectronicSelection("1.00") showElectronicSelection("1.00")
payFails = true payFails = true
val quotesBefore = requests.count { it.url.encodedPath.endsWith("verify-result") } val quotesBefore = requests.count { it.url.encodedPath.endsWith("verify-result") }
compose.onNodeWithText("支付电子版\n1元").performClick() compose.onNodeWithText("购买电子照片\n1元").performClick()
compose.waitUntil(10_000) { requests.count { it.url.encodedPath.endsWith("verify-result") } > quotesBefore && !resultVm.quoteLoading.value && !resultVm.creatingOrder.value } compose.waitUntil(10_000) { requests.count { it.url.encodedPath.endsWith("verify-result") } > quotesBefore && !resultVm.quoteLoading.value && !resultVm.creatingOrder.value }
assertNull(resultVm.payQrCodeUrl.value) assertNull(resultVm.payQrCodeUrl.value)
compose.onNodeWithText("支付电子版\n1元").assertIsEnabled() compose.onNodeWithText("购买电子照片\n1元").assertIsEnabled()
quoteFails = true quoteFails = true
compose.runOnIdle { resultVm.retryQuote() } compose.runOnIdle { resultVm.retryQuote() }
compose.waitUntil(10_000) { resultVm.quoteError.value != null } compose.waitUntil(10_000) { resultVm.quoteError.value != null }
compose.onNodeWithText("项目已下线,请重新选择").assertIsDisplayed() compose.onNodeWithText("项目已下线,请重新选择").assertIsDisplayed()
compose.onNodeWithText("支付打印版\n--元").assertIsNotEnabled() compose.onNodeWithText("购买打印照片\n--元").assertIsNotEnabled()
} }
@Test fun selectionChangesDiscardTheOldQrAndOrder() { @Test fun selectionChangesDiscardTheOldQrAndOrder() {
@@ -484,7 +484,7 @@ class RecentPhotosFlowTest {
compose.setContent { FaceRecognitionResultScreen(source = AppRoutes.RECENT_RESULT_SOURCE, viewModel = resultVm) } compose.setContent { FaceRecognitionResultScreen(source = AppRoutes.RECENT_RESULT_SOURCE, viewModel = resultVm) }
compose.waitUntil(10_000) { resultVm.recentPhotosState.value == RecentPhotosState.ERROR } compose.waitUntil(10_000) { resultVm.recentPhotosState.value == RecentPhotosState.ERROR }
compose.onNodeWithText("照片加载失败,请重试").assertIsDisplayed() compose.onNodeWithText("照片加载失败,请重试").assertIsDisplayed()
compose.onNodeWithText("支付打印版\n--元").assertIsNotEnabled() compose.onNodeWithText("购买打印照片\n--元").assertIsNotEnabled()
recentCode = 200 recentCode = 200
compose.onNodeWithText("重试").performClick() compose.onNodeWithText("重试").performClick()
compose.waitUntil(10_000) { resultVm.recentPhotosState.value == RecentPhotosState.EMPTY } compose.waitUntil(10_000) { resultVm.recentPhotosState.value == RecentPhotosState.EMPTY }
@@ -149,16 +149,26 @@ fun FaceRecognitionResultScreen(
colors = CardDefaults.cardColors(containerColor = Color(0xFFF4F4F4)) colors = CardDefaults.cardColors(containerColor = Color(0xFFF4F4F4))
) { ) {
Column(Modifier.fillMaxWidth().padding(24.dp)) { Column(Modifier.fillMaxWidth().padding(24.dp)) {
Text("已选择 ${selectedCount} 张", fontSize = 24.sp, fontWeight = FontWeight.Bold) Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Text("已选择 ${selectedCount} 张", fontSize = 24.sp, fontWeight = FontWeight.Bold)
Spacer(Modifier.weight(1f))
Row(
horizontalArrangement = Arrangement.spacedBy(20.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text("打印版 ${formatPriceDisplay(pricePerPhoto)}元/张", fontSize = 21.sp)
Text("电子版 ${formatPriceDisplay(electronicPrice)}元/张", fontSize = 21.sp)
}
}
Spacer(Modifier.height(16.dp)) Spacer(Modifier.height(16.dp))
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) { Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) {
PurchaseMode.entries.forEach { mode -> PurchaseMode.entries.forEach { mode ->
val isPrint = mode == PurchaseMode.PRINT val isPrint = mode == PurchaseMode.PRINT
val unit = if (isPrint) pricePerPhoto else electronicPrice
val total = if (isPrint) totalPrice else electronicTotal val total = if (isPrint) totalPrice else electronicTotal
Column(Modifier.weight(1f)) { Column(Modifier.weight(1f)) {
Text("${mode.label} ${formatPriceDisplay(unit)}元/张", fontSize = 21.sp)
Spacer(Modifier.height(12.dp))
Button( Button(
onClick = { viewModel.getPayUrl(mode) { showPayDialog = true } }, onClick = { viewModel.getPayUrl(mode) { showPayDialog = true } },
enabled = selectedCount > 0 && total != "--" && !creatingOrder && !quoteLoading, enabled = selectedCount > 0 && total != "--" && !creatingOrder && !quoteLoading,
@@ -171,7 +181,7 @@ fun FaceRecognitionResultScreen(
) { ) {
Text( Text(
text = if (!isPrint && total == "--" && !quoteLoading) text = if (!isPrint && total == "--" && !quoteLoading)
"电子版暂不可购买" else "支付${mode.label}\n${formatPriceDisplay(total)}元", "电子版暂不可购买" else "${if (isPrint) "购买打印照片" else "购买电子照片"}\n${formatPriceDisplay(total)}元",
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
fontSize = 24.sp, fontSize = 24.sp,
lineHeight = 32.sp, lineHeight = 32.sp,