fix(充值商品): 移除已退役的 bonus_points / duration_days 入参
- 后台 upsert 请求 DTO 与 SpacetimeDB procedure 入参移除 bonus_points、duration_days(评审第 19 条) - 充点商品固定「¥1 = 10 泥点、无首充赠送」,module 落库统一写 0,保留退役列兼容存量 schema - 删除 InvalidRechargeProductFields 校验与错误文案;api-server / spacetime-client 同步收敛 - admin-web 表单移除「首充赠送」输入与状态,列表改为只展示基础泥点 - scripts/admin-web-fake-api.mjs 假数据同步 bonusPoints: 0
This commit is contained in:
@@ -680,8 +680,6 @@ export interface AdminUpsertProfileRechargeProductRequest {
|
||||
priceCents: number;
|
||||
kind: ProfileRechargeProductKind;
|
||||
pointsAmount: number;
|
||||
bonusPoints: number;
|
||||
durationDays: number;
|
||||
badgeLabel?: string | null;
|
||||
description?: string | null;
|
||||
enabled: boolean;
|
||||
|
||||
@@ -19,11 +19,7 @@ import {
|
||||
} from '../api/adminApiClient';
|
||||
import type { ProfileRechargeProductConfigAdminResponse } from '../api/adminApiTypes';
|
||||
import { useAdminWriteConfirm } from '../components/useAdminWriteConfirm';
|
||||
import {
|
||||
handlePageError,
|
||||
parseNonNegativeIntegerOrZero,
|
||||
parsePositiveIntegerOrZero,
|
||||
} from './pageUtils';
|
||||
import { handlePageError, parsePositiveIntegerOrZero } from './pageUtils';
|
||||
|
||||
interface AdminRechargeProductPageProps {
|
||||
token: string;
|
||||
@@ -38,7 +34,6 @@ const DEFAULT_RECHARGE_PRODUCT_FORM = {
|
||||
title: '60泥点',
|
||||
priceCents: '600',
|
||||
pointsAmount: '60',
|
||||
bonusPoints: '0',
|
||||
badgeLabel: '',
|
||||
description: '60泥点',
|
||||
enabled: true,
|
||||
@@ -49,7 +44,7 @@ const DEFAULT_RECHARGE_PRODUCT_FORM = {
|
||||
* 泥点充值商品。
|
||||
*
|
||||
* 会员档位已迁到独立的「会员档位」页(`profile_membership_plan`),本页只维护充点商品。
|
||||
* 新方案固定「¥1 = 10 泥点、无任何首充赠送」,首充赠送字段保留能力但默认 0。
|
||||
* 新方案固定「¥1 = 10 泥点、无首充赠送」,因此表单不再提供首充赠送 / 天数等已退役字段。
|
||||
*/
|
||||
export function AdminRechargeProductPage({
|
||||
token,
|
||||
@@ -70,9 +65,6 @@ export function AdminRechargeProductPage({
|
||||
const [pointsAmount, setPointsAmount] = useState(
|
||||
DEFAULT_RECHARGE_PRODUCT_FORM.pointsAmount,
|
||||
);
|
||||
const [bonusPoints, setBonusPoints] = useState(
|
||||
DEFAULT_RECHARGE_PRODUCT_FORM.bonusPoints,
|
||||
);
|
||||
const [badgeLabel, setBadgeLabel] = useState(
|
||||
DEFAULT_RECHARGE_PRODUCT_FORM.badgeLabel,
|
||||
);
|
||||
@@ -141,8 +133,6 @@ export function AdminRechargeProductPage({
|
||||
priceCents: parsePositiveIntegerOrZero(priceCents),
|
||||
kind: 'points',
|
||||
pointsAmount: parsePositiveIntegerOrZero(pointsAmount),
|
||||
bonusPoints: parseNonNegativeIntegerOrZero(bonusPoints),
|
||||
durationDays: 0,
|
||||
badgeLabel: badgeLabel.trim(),
|
||||
description: description.trim(),
|
||||
enabled,
|
||||
@@ -172,7 +162,6 @@ export function AdminRechargeProductPage({
|
||||
setTitle(entry.title);
|
||||
setPriceCents(String(entry.priceCents));
|
||||
setPointsAmount(String(entry.pointsAmount));
|
||||
setBonusPoints(String(entry.bonusPoints));
|
||||
setBadgeLabel(entry.badgeLabel);
|
||||
setDescription(entry.description);
|
||||
setEnabled(entry.enabled);
|
||||
@@ -184,7 +173,6 @@ export function AdminRechargeProductPage({
|
||||
setTitle(DEFAULT_RECHARGE_PRODUCT_FORM.title);
|
||||
setPriceCents(DEFAULT_RECHARGE_PRODUCT_FORM.priceCents);
|
||||
setPointsAmount(DEFAULT_RECHARGE_PRODUCT_FORM.pointsAmount);
|
||||
setBonusPoints(DEFAULT_RECHARGE_PRODUCT_FORM.bonusPoints);
|
||||
setBadgeLabel(DEFAULT_RECHARGE_PRODUCT_FORM.badgeLabel);
|
||||
setDescription(DEFAULT_RECHARGE_PRODUCT_FORM.description);
|
||||
setEnabled(DEFAULT_RECHARGE_PRODUCT_FORM.enabled);
|
||||
@@ -248,26 +236,15 @@ export function AdminRechargeProductPage({
|
||||
</AdminField>
|
||||
</AdminFormRow>
|
||||
|
||||
<AdminFormRow>
|
||||
<AdminField label="基础泥点">
|
||||
<input
|
||||
min={1}
|
||||
step={1}
|
||||
type="number"
|
||||
value={pointsAmount}
|
||||
onChange={(event) => setPointsAmount(event.target.value)}
|
||||
/>
|
||||
</AdminField>
|
||||
<AdminField label="首充赠送">
|
||||
<input
|
||||
min={0}
|
||||
step={1}
|
||||
type="number"
|
||||
value={bonusPoints}
|
||||
onChange={(event) => setBonusPoints(event.target.value)}
|
||||
/>
|
||||
</AdminField>
|
||||
</AdminFormRow>
|
||||
<AdminField label="基础泥点">
|
||||
<input
|
||||
min={1}
|
||||
step={1}
|
||||
type="number"
|
||||
value={pointsAmount}
|
||||
onChange={(event) => setPointsAmount(event.target.value)}
|
||||
/>
|
||||
</AdminField>
|
||||
|
||||
<AdminFormRow>
|
||||
<AdminField label="角标">
|
||||
@@ -397,7 +374,7 @@ function sortProducts(entries: ProfileRechargeProductConfigAdminResponse[]) {
|
||||
function formatProductContent(
|
||||
entry: ProfileRechargeProductConfigAdminResponse,
|
||||
) {
|
||||
return `${entry.pointsAmount} + ${entry.bonusPoints} 泥点`;
|
||||
return `${entry.pointsAmount} 泥点`;
|
||||
}
|
||||
|
||||
function formatPrice(priceCents: number) {
|
||||
|
||||
@@ -800,21 +800,16 @@ function route(pathname, method, url, requestBody = '') {
|
||||
};
|
||||
}
|
||||
if (pathname === '/admin/api/profile/recharge-products') {
|
||||
const product = (
|
||||
productId,
|
||||
title,
|
||||
priceCents,
|
||||
pointsAmount,
|
||||
bonusPoints,
|
||||
) => ({
|
||||
const product = (productId, title, priceCents, pointsAmount) => ({
|
||||
productId,
|
||||
title,
|
||||
priceCents,
|
||||
kind: 'points',
|
||||
pointsAmount,
|
||||
bonusPoints,
|
||||
// 已退役列:真实后端固定写 0,假数据也保持一致。
|
||||
bonusPoints: 0,
|
||||
durationDays: 0,
|
||||
badgeLabel: bonusPoints ? `赠送 ${bonusPoints}` : '',
|
||||
badgeLabel: '',
|
||||
description: `${pointsAmount} 泥点`,
|
||||
tier: 'none',
|
||||
membershipPeriodPoints: 0,
|
||||
@@ -830,8 +825,8 @@ function route(pathname, method, url, requestBody = '') {
|
||||
});
|
||||
return {
|
||||
entries: [
|
||||
product('prod_points_600', '600 泥点', 3_000, 600, 0),
|
||||
product('prod_points_1200', '1200 泥点 + 赠送 100', 6_000, 1_200, 100),
|
||||
product('prod_points_600', '600 泥点', 3_000, 600),
|
||||
product('prod_points_1200', '1200 泥点', 6_000, 1_200),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1131,8 +1131,6 @@ pub async fn admin_upsert_profile_recharge_product(
|
||||
payload.price_cents,
|
||||
kind,
|
||||
payload.points_amount,
|
||||
payload.bonus_points,
|
||||
payload.duration_days,
|
||||
payload.badge_label.unwrap_or_default(),
|
||||
payload.description.unwrap_or_default(),
|
||||
payload.enabled,
|
||||
|
||||
@@ -393,8 +393,6 @@ pub fn build_runtime_profile_recharge_product_admin_upsert_input(
|
||||
price_cents: u64,
|
||||
kind: RuntimeProfileRechargeProductKind,
|
||||
points_amount: u64,
|
||||
bonus_points: u64,
|
||||
duration_days: u32,
|
||||
badge_label: String,
|
||||
description: String,
|
||||
enabled: bool,
|
||||
@@ -414,9 +412,6 @@ pub fn build_runtime_profile_recharge_product_admin_upsert_input(
|
||||
if points_amount == 0 {
|
||||
return Err(RuntimeProfileFieldError::InvalidRechargeProductPoints);
|
||||
}
|
||||
if duration_days != 0 || bonus_points != 0 {
|
||||
return Err(RuntimeProfileFieldError::InvalidRechargeProductFields);
|
||||
}
|
||||
}
|
||||
// 中文注释:会员商品已迁移到 profile_membership_plan 目录,这里只保留泥点商品。
|
||||
RuntimeProfileRechargeProductKind::Membership => {
|
||||
@@ -431,8 +426,6 @@ pub fn build_runtime_profile_recharge_product_admin_upsert_input(
|
||||
price_cents,
|
||||
kind,
|
||||
points_amount,
|
||||
bonus_points,
|
||||
duration_days,
|
||||
badge_label: normalize_optional_string(Some(badge_label)).unwrap_or_default(),
|
||||
description: normalize_optional_string(Some(description)).unwrap_or_default(),
|
||||
enabled,
|
||||
|
||||
@@ -2082,8 +2082,6 @@ pub struct RuntimeProfileRechargeProductAdminUpsertInput {
|
||||
pub price_cents: u64,
|
||||
pub kind: RuntimeProfileRechargeProductKind,
|
||||
pub points_amount: u64,
|
||||
pub bonus_points: u64,
|
||||
pub duration_days: u32,
|
||||
pub badge_label: String,
|
||||
pub description: String,
|
||||
pub enabled: bool,
|
||||
|
||||
@@ -89,7 +89,6 @@ pub enum RuntimeProfileFieldError {
|
||||
InvalidRechargeProductPrice,
|
||||
InvalidRechargeProductPoints,
|
||||
InvalidRechargeProductKind,
|
||||
InvalidRechargeProductFields,
|
||||
InvalidMembershipPlan,
|
||||
InvalidMembershipPlanOrder,
|
||||
MissingPaymentChannel,
|
||||
@@ -185,9 +184,6 @@ impl std::fmt::Display for RuntimeProfileFieldError {
|
||||
Self::InvalidRechargeProductKind => {
|
||||
f.write_str("充值商品类型无效:会员商品已迁移到会员档位目录")
|
||||
}
|
||||
Self::InvalidRechargeProductFields => {
|
||||
f.write_str("泥点商品不支持 duration_days 与 bonus_points 字段")
|
||||
}
|
||||
Self::InvalidMembershipPlan => {
|
||||
f.write_str("会员档位配置无效:月价、年价、每期泥点与并发上限必须有效")
|
||||
}
|
||||
|
||||
@@ -820,8 +820,6 @@ pub struct AdminUpsertProfileRechargeProductRequest {
|
||||
pub price_cents: u64,
|
||||
pub kind: String,
|
||||
pub points_amount: u64,
|
||||
pub bonus_points: u64,
|
||||
pub duration_days: u32,
|
||||
#[serde(default)]
|
||||
pub badge_label: Option<String>,
|
||||
#[serde(default)]
|
||||
|
||||
@@ -580,8 +580,6 @@ impl From<module_runtime::RuntimeProfileRechargeProductAdminUpsertInput>
|
||||
price_cents: input.price_cents,
|
||||
kind: map_runtime_profile_recharge_product_kind(input.kind),
|
||||
points_amount: input.points_amount,
|
||||
bonus_points: input.bonus_points,
|
||||
duration_days: input.duration_days,
|
||||
badge_label: input.badge_label,
|
||||
description: input.description,
|
||||
enabled: input.enabled,
|
||||
|
||||
@@ -1699,8 +1699,6 @@ impl SpacetimeClient {
|
||||
price_cents: u64,
|
||||
kind: module_runtime::RuntimeProfileRechargeProductKind,
|
||||
points_amount: u64,
|
||||
bonus_points: u64,
|
||||
duration_days: u32,
|
||||
badge_label: String,
|
||||
description: String,
|
||||
enabled: bool,
|
||||
@@ -1714,8 +1712,6 @@ impl SpacetimeClient {
|
||||
price_cents,
|
||||
kind,
|
||||
points_amount,
|
||||
bonus_points,
|
||||
duration_days,
|
||||
badge_label,
|
||||
description,
|
||||
enabled,
|
||||
|
||||
-2
@@ -15,8 +15,6 @@ pub struct RuntimeProfileRechargeProductAdminUpsertInput {
|
||||
pub price_cents: u64,
|
||||
pub kind: RuntimeProfileRechargeProductKind,
|
||||
pub points_amount: u64,
|
||||
pub bonus_points: u64,
|
||||
pub duration_days: u32,
|
||||
pub badge_label: String,
|
||||
pub description: String,
|
||||
pub enabled: bool,
|
||||
|
||||
@@ -8500,8 +8500,6 @@ fn upsert_profile_recharge_product_config_record(
|
||||
input.price_cents,
|
||||
input.kind,
|
||||
input.points_amount,
|
||||
input.bonus_points,
|
||||
input.duration_days,
|
||||
input.badge_label,
|
||||
input.description,
|
||||
input.enabled,
|
||||
@@ -8533,8 +8531,9 @@ fn upsert_profile_recharge_product_config_record(
|
||||
price_cents: validated_input.price_cents,
|
||||
kind: validated_input.kind,
|
||||
points_amount: validated_input.points_amount,
|
||||
bonus_points: validated_input.bonus_points,
|
||||
duration_days: validated_input.duration_days,
|
||||
// 已退役列:充点商品固定「¥1 = 10 泥点、无首充赠送」,不再从后台入参接收。
|
||||
bonus_points: 0,
|
||||
duration_days: 0,
|
||||
badge_label: validated_input.badge_label,
|
||||
description: validated_input.description,
|
||||
// 已退役列:不参与运行态,写固定默认值即可。
|
||||
|
||||
Reference in New Issue
Block a user