每日免费发放额为 0 时前端隐藏该池
- 后端:module-runtime 的 daily_free_points_per_day 校验由「必须大于 0」放宽为只校验上界,错误变体改名 DailyFreePointsPerDayOverflow - 前端共享层:mudPoints 新增 shouldShowProfileDailyFreePool,判定 remaining > 0 || reset > 0,判定收口一处 - 钱包入口:PlatformMudPointWalletEntry 在每日免费发放额为 0 且无存量时隐藏该行 - 充值弹层:PlatformProfileRechargeModal 池概览按可见池渲染(三列变两列),扣点顺序提示与泥点确认页文案随可见性切换 - Admin Web:账号配置页每日免费泥点允许填 0(校验、min 与文案同步) - 测试:删除「每日免费必然存在」断言,新增隐藏 / 有存量仍显示 / 发放额为正三类用例,并修正钱包入口测试在 HEAD 上失效的选择器 - 文档:更新会员与泥点前端改造设计文档 §14 与 shared-memory 决策记录
This commit is contained in:
@@ -94,7 +94,7 @@ test('账号配置页一次保存初始和每日免费泥点', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('账号配置页拒绝非正整数每日免费额度', async () => {
|
||||
test('账号配置页拒绝负数或非整数每日免费额度', async () => {
|
||||
render(
|
||||
<AdminProfileWalletConfigPage
|
||||
token="admin-token"
|
||||
@@ -109,5 +109,38 @@ test('账号配置页拒绝非正整数每日免费额度', async () => {
|
||||
(screen.getByRole('button', { name: '保存' }) as HTMLButtonElement)
|
||||
.disabled,
|
||||
).toBe(true);
|
||||
fireEvent.change(input, { target: { value: '-1' } });
|
||||
expect(
|
||||
(screen.getByRole('button', { name: '保存' }) as HTMLButtonElement)
|
||||
.disabled,
|
||||
).toBe(true);
|
||||
expect(upsertProfileWalletConfig).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('账号配置页允许把每日免费泥点配置为 0', async () => {
|
||||
const user = userEvent.setup();
|
||||
vi.mocked(upsertProfileWalletConfig).mockResolvedValue({
|
||||
...configResponse,
|
||||
dailyFreePointsPerDay: 0,
|
||||
});
|
||||
render(
|
||||
<AdminProfileWalletConfigPage
|
||||
token="admin-token"
|
||||
result={configResponse}
|
||||
onUnauthorized={vi.fn()}
|
||||
onResultChange={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
fireEvent.change(await screen.findByLabelText('每日免费泥点数'), {
|
||||
target: { value: '0' },
|
||||
});
|
||||
await user.click(screen.getByRole('button', { name: '保存' }));
|
||||
expect(screen.getByText('初始 100 泥点,每日免费 0 泥点')).toBeTruthy();
|
||||
await user.click(screen.getByRole('button', { name: '确认' }));
|
||||
await waitFor(() =>
|
||||
expect(upsertProfileWalletConfig).toHaveBeenCalledWith('admin-token', {
|
||||
initialMudPoints: 100,
|
||||
dailyFreePointsPerDay: 0,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -66,11 +66,11 @@ export function AdminProfileWalletConfigPage({
|
||||
if (isSaving) {
|
||||
return;
|
||||
}
|
||||
const normalizedDailyFreePointsPerDay = parsePositiveInteger(
|
||||
const normalizedDailyFreePointsPerDay = parseNonNegativeInteger(
|
||||
dailyFreePointsPerDay,
|
||||
);
|
||||
if (!normalizedDailyFreePointsPerDay) {
|
||||
setErrorMessage('每日免费泥点数必须是大于 0 的整数');
|
||||
if (normalizedDailyFreePointsPerDay === null) {
|
||||
setErrorMessage('每日免费泥点数必须是不小于 0 的整数');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ export function AdminProfileWalletConfigPage({
|
||||
|
||||
<AdminField label="每日免费泥点数">
|
||||
<input
|
||||
min={1}
|
||||
min={0}
|
||||
step={1}
|
||||
type="number"
|
||||
value={dailyFreePointsPerDay}
|
||||
@@ -154,7 +154,7 @@ export function AdminProfileWalletConfigPage({
|
||||
disabled={
|
||||
isSaving ||
|
||||
!parsePositiveInteger(initialMudPoints) ||
|
||||
!parsePositiveInteger(dailyFreePointsPerDay)
|
||||
parseNonNegativeInteger(dailyFreePointsPerDay) === null
|
||||
}
|
||||
type="submit"
|
||||
>
|
||||
@@ -205,3 +205,11 @@ function parsePositiveInteger(value: string) {
|
||||
const parsed = Number(value);
|
||||
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : 0;
|
||||
}
|
||||
|
||||
function parseNonNegativeInteger(value: string): number | null {
|
||||
if (value.trim() === '') {
|
||||
return null;
|
||||
}
|
||||
const parsed = Number(value);
|
||||
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user