重构(后台金额): 抽出统一的元金额格式化
- shared AdminFormat 新增 formatAdminCurrencyCents(分 → ¥x.xx)并从 components 导出 - AdminUserDetailDialog / AdminMembershipPlanPage / AdminRechargeOrderPage / AdminRechargeProductPage 删除各自重复的 formatMoney/formatPrice - 补充 formatAdminCurrencyCents 单测,避免后台各页面金额格式漂移
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
AdminStatusPill,
|
||||
AdminTag,
|
||||
AdminTagList,
|
||||
formatAdminCurrencyCents,
|
||||
} from '@genarrative/shared/components';
|
||||
import { RefreshCcw, ShieldAlert, UserRound, X } from 'lucide-react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
@@ -382,12 +383,14 @@ export function AdminUserDetailDialog({
|
||||
<td>{order.productTitle || order.productId}</td>
|
||||
<td>
|
||||
{order.paidAmountCents > 0
|
||||
? formatMoney(order.paidAmountCents)
|
||||
? formatAdminCurrencyCents(order.paidAmountCents)
|
||||
: '未支付'}
|
||||
</td>
|
||||
<td>{order.pointsDelta} 泥点</td>
|
||||
<td>
|
||||
{formatMoney(order.cumulativeSuccessRefundCents)}
|
||||
{formatAdminCurrencyCents(
|
||||
order.cumulativeSuccessRefundCents,
|
||||
)}
|
||||
<small>欠账 {order.unrecoveredPoints} 泥点</small>
|
||||
</td>
|
||||
<td>{formatOrderStatus(order.status)}</td>
|
||||
@@ -442,7 +445,7 @@ function UserIdentityHeader({ detail }: { detail: AdminUserDetailResponse }) {
|
||||
value: (
|
||||
<>
|
||||
{typeof detail.cumulativeRechargedCents === 'number'
|
||||
? formatMoney(detail.cumulativeRechargedCents)
|
||||
? formatAdminCurrencyCents(detail.cumulativeRechargedCents)
|
||||
: '未知'}
|
||||
</>
|
||||
),
|
||||
@@ -580,10 +583,6 @@ function MembershipSection({
|
||||
);
|
||||
}
|
||||
|
||||
function formatMoney(cents: number) {
|
||||
return `¥${(cents / 100).toFixed(2)}`;
|
||||
}
|
||||
|
||||
function formatMicros(value: number) {
|
||||
if (!Number.isFinite(value) || value <= 0) {
|
||||
return '-';
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
AdminPage,
|
||||
AdminPageHeading,
|
||||
AdminPanel,
|
||||
formatAdminCurrencyCents,
|
||||
} from '@genarrative/shared/components';
|
||||
import { RefreshCcw, Save } from 'lucide-react';
|
||||
import { FormEvent, useEffect, useState } from 'react';
|
||||
@@ -410,8 +411,8 @@ export function AdminMembershipPlanPage({
|
||||
</small>
|
||||
</td>
|
||||
<td>
|
||||
{formatPrice(entry.monthPriceCents)} /{' '}
|
||||
{formatPrice(entry.yearPriceCents)}
|
||||
{formatAdminCurrencyCents(entry.monthPriceCents)} /{' '}
|
||||
{formatAdminCurrencyCents(entry.yearPriceCents)}
|
||||
</td>
|
||||
<td>{entry.periodPoints}</td>
|
||||
<td>{formatPlanLimits(entry)}</td>
|
||||
@@ -460,7 +461,3 @@ function formatPlanLimits(entry: ProfileMembershipPlanAdminResponse) {
|
||||
: `${entry.concurrentJobLimit} 个`;
|
||||
return `${modelLabel} · 并发 ${concurrency}`;
|
||||
}
|
||||
|
||||
function formatPrice(priceCents: number) {
|
||||
return `¥${(priceCents / 100).toFixed(2)}`;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
AdminPanelHeading,
|
||||
AdminTag,
|
||||
AdminTagList,
|
||||
formatAdminCurrencyCents,
|
||||
} from '@genarrative/shared/components';
|
||||
import {
|
||||
AlertTriangle,
|
||||
@@ -312,7 +313,7 @@ export function AdminRechargeOrderPage({
|
||||
setRefundRequestId(requestId);
|
||||
const confirmed = await confirmWrite({
|
||||
action: '发起微信退款并追回泥点',
|
||||
target: `${refundOrder.orderId} / ${formatMoney(amountCents)}`,
|
||||
target: `${refundOrder.orderId} / ${formatAdminCurrencyCents(amountCents)}`,
|
||||
});
|
||||
if (!confirmed || submitLockRef.current) {
|
||||
return;
|
||||
@@ -721,15 +722,19 @@ export function AdminRechargeOrderPage({
|
||||
<div className="admin-refund-summary-grid">
|
||||
<Metric
|
||||
label="订单实付"
|
||||
value={formatMoney(refundOrder.paidAmountCents)}
|
||||
value={formatAdminCurrencyCents(refundOrder.paidAmountCents)}
|
||||
/>
|
||||
<Metric
|
||||
label="累计已退"
|
||||
value={formatMoney(refundOrder.cumulativeSuccessRefundCents)}
|
||||
value={formatAdminCurrencyCents(
|
||||
refundOrder.cumulativeSuccessRefundCents,
|
||||
)}
|
||||
/>
|
||||
<Metric
|
||||
label="剩余可退"
|
||||
value={formatMoney(refundOrder.remainingRefundableCents)}
|
||||
value={formatAdminCurrencyCents(
|
||||
refundOrder.remainingRefundableCents,
|
||||
)}
|
||||
/>
|
||||
<Metric
|
||||
label="永久泥点"
|
||||
@@ -859,7 +864,13 @@ export function AdminRechargeOrderPage({
|
||||
},
|
||||
{
|
||||
label: <>预检后剩余可退</>,
|
||||
value: <>{formatMoney(preview.remainingRefundableCents)}</>,
|
||||
value: (
|
||||
<>
|
||||
{formatAdminCurrencyCents(
|
||||
preview.remainingRefundableCents,
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -984,16 +995,32 @@ export function AdminRechargeOrderPage({
|
||||
},
|
||||
{
|
||||
label: <>本地订单总额</>,
|
||||
value: <>{formatMoney(manualReviewTarget.order.amountCents)}</>,
|
||||
value: (
|
||||
<>
|
||||
{formatAdminCurrencyCents(
|
||||
manualReviewTarget.order.amountCents,
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: <>退款订单总额</>,
|
||||
value: <>{formatMoney(manualReviewTarget.refund.totalCents)}</>,
|
||||
value: (
|
||||
<>
|
||||
{formatAdminCurrencyCents(
|
||||
manualReviewTarget.refund.totalCents,
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: <>本次退款金额</>,
|
||||
value: (
|
||||
<>{formatMoney(manualReviewTarget.refund.refundCents)}</>
|
||||
<>
|
||||
{formatAdminCurrencyCents(
|
||||
manualReviewTarget.refund.refundCents,
|
||||
)}
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
@@ -1107,7 +1134,7 @@ function RechargeOrderRow({
|
||||
<td>
|
||||
<strong>{formatOrderPaidAmount(order)}</strong>
|
||||
{order.paidAmountCents > 0 ? null : (
|
||||
<small>订单 {formatMoney(order.amountCents)}</small>
|
||||
<small>订单 {formatAdminCurrencyCents(order.amountCents)}</small>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
@@ -1117,7 +1144,9 @@ function RechargeOrderRow({
|
||||
) : null}
|
||||
</td>
|
||||
<td>
|
||||
<span>累计 {formatMoney(order.cumulativeSuccessRefundCents)}</span>
|
||||
<span>
|
||||
累计 {formatAdminCurrencyCents(order.cumulativeSuccessRefundCents)}
|
||||
</span>
|
||||
<small>
|
||||
应追回 {order.targetRecoveryPoints} / 已追回 {order.recoveredPoints}
|
||||
</small>
|
||||
@@ -1313,14 +1342,10 @@ function formatMembershipChangeSummary(
|
||||
return `${action} ${planPath}${cycle}`;
|
||||
}
|
||||
|
||||
function formatMoney(cents: number) {
|
||||
return `¥${(cents / 100).toFixed(2)}`;
|
||||
}
|
||||
|
||||
/** 实付只属于真正支付过的订单:未支付 / 已关闭 / 已过期订单显示“未支付”。 */
|
||||
function formatOrderPaidAmount(order: AdminRechargeOrderEntryPayload) {
|
||||
return order.paidAmountCents > 0
|
||||
? formatMoney(order.paidAmountCents)
|
||||
? formatAdminCurrencyCents(order.paidAmountCents)
|
||||
: '未支付';
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
AdminPage,
|
||||
AdminPageHeading,
|
||||
AdminPanel,
|
||||
formatAdminCurrencyCents,
|
||||
formatAdminDateTime,
|
||||
} from '@genarrative/shared/components';
|
||||
import { RefreshCcw, Save } from 'lucide-react';
|
||||
@@ -333,7 +334,7 @@ export function AdminRechargeProductPage({
|
||||
</AdminButton>
|
||||
<small>{entry.productId}</small>
|
||||
</td>
|
||||
<td>{formatPrice(entry.priceCents)}</td>
|
||||
<td>{formatAdminCurrencyCents(entry.priceCents)}</td>
|
||||
<td>{formatProductContent(entry)}</td>
|
||||
<td>{entry.enabled ? '启用' : '停用'}</td>
|
||||
</tr>
|
||||
@@ -384,10 +385,6 @@ function formatProductContent(
|
||||
return `${entry.pointsAmount} 泥点`;
|
||||
}
|
||||
|
||||
function formatPrice(priceCents: number) {
|
||||
return `¥${(priceCents / 100).toFixed(2)}`;
|
||||
}
|
||||
|
||||
function parseInteger(value: string) {
|
||||
const parsed = Number.parseInt(value, 10);
|
||||
if (!Number.isFinite(parsed)) {
|
||||
|
||||
Reference in New Issue
Block a user