fix: v0.19.3 admin settings GET 补返回 1080P 两个单价字段
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 11m45s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 11m45s
v0.19.0 做 1080P 时 QuotaConfig 加了 base_token_price_1080p 和
base_token_price_1080p_video 字段, serializer (PUT) 和计费逻辑
(_get_token_price) 都处理了, 但 _settings_dict (GET) 漏了两行,
导致管理后台设置页两个 1080P 单价输入框显示空白。
实际影响
- DB 值对 (51 / 31), 计费走 _get_token_price 直接读 DB, 计费一直正确
- 前端 SettingsPage fetchSettings 用 setSettings(data) 覆盖,
GET 返回缺字段 -> state 变 undefined -> 输入框显示空
- 管理员点保存: undefined 被 JSON.stringify 省略 -> PUT body 不含
这两字段 -> serializer validated_data 里没有 -> DB 未改
- 所以目前"巧合安全", 但风险: 管理员在空输入框填数字后清空,
Number("") = 0 会覆盖 DB, 把单价刷成 0
修复
- backend/apps/generation/views.py _settings_dict() 加两行返回
base_token_price_1080p / base_token_price_1080p_video
- 前端 GET 后 state 直接拿到 51 / 31, 输入框自动显示, 不依赖"巧合"
回归测试 (backend/tests/test_1080p_api.py)
- 新增 TestAdminSettingsResponse.test_get_returns_all_token_price_fields
断言 GET /admin/settings 返回 6 个 token_price 字段全齐
- 失败消息明示: "缺字段会导致前端输入框显示空" 以防以后再漏
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
13440f2709
commit
ecdb9cb471
@ -1907,6 +1907,8 @@ def _settings_dict(config):
|
|||||||
'base_token_price_video': float(config.base_token_price_video),
|
'base_token_price_video': float(config.base_token_price_video),
|
||||||
'base_token_price_fast': float(config.base_token_price_fast),
|
'base_token_price_fast': float(config.base_token_price_fast),
|
||||||
'base_token_price_fast_video': float(config.base_token_price_fast_video),
|
'base_token_price_fast_video': float(config.base_token_price_fast_video),
|
||||||
|
'base_token_price_1080p': float(config.base_token_price_1080p),
|
||||||
|
'base_token_price_1080p_video': float(config.base_token_price_1080p_video),
|
||||||
'announcement': config.announcement,
|
'announcement': config.announcement,
|
||||||
'announcement_enabled': config.announcement_enabled,
|
'announcement_enabled': config.announcement_enabled,
|
||||||
'max_desktop_sessions': config.max_desktop_sessions,
|
'max_desktop_sessions': config.max_desktop_sessions,
|
||||||
|
|||||||
@ -127,5 +127,38 @@ class TestVideoGenerateResolution(TestCase):
|
|||||||
self.assertNotEqual(body.get('error'), 'invalid_resolution')
|
self.assertNotEqual(body.get('error'), 'invalid_resolution')
|
||||||
|
|
||||||
|
|
||||||
|
class TestAdminSettingsResponse(TestCase):
|
||||||
|
"""GET /api/v1/admin/settings 必须返回所有 token_price 字段,
|
||||||
|
以防 v0.19.0 那种"字段在 serializer 里加了、但 _settings_dict 漏了"的回归。"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
QuotaConfig.objects.get_or_create(pk=1)
|
||||||
|
self.admin = User.objects.create_user(
|
||||||
|
username='test_admin_settings',
|
||||||
|
email='test_admin_settings@example.com',
|
||||||
|
password='testpass123',
|
||||||
|
is_staff=True,
|
||||||
|
is_superuser=True,
|
||||||
|
)
|
||||||
|
self.client = APIClient()
|
||||||
|
self.client.force_authenticate(user=self.admin)
|
||||||
|
|
||||||
|
def test_get_returns_all_token_price_fields(self):
|
||||||
|
"""GET 返回 4 档单价(全部分辨率 + 是否含视频),缺一不可 — 缺字段会导致前端输入框显示空。"""
|
||||||
|
resp = self.client.get('/api/v1/admin/settings')
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
body = resp.json()
|
||||||
|
for field in (
|
||||||
|
'base_token_price',
|
||||||
|
'base_token_price_video',
|
||||||
|
'base_token_price_fast',
|
||||||
|
'base_token_price_fast_video',
|
||||||
|
'base_token_price_1080p',
|
||||||
|
'base_token_price_1080p_video',
|
||||||
|
):
|
||||||
|
self.assertIn(field, body, f'GET /admin/settings response missing {field!r} — 前端这个输入框会显示空')
|
||||||
|
self.assertIsInstance(body[field], (int, float), f'{field} 应该是数字类型')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(verbosity=2)
|
unittest.main(verbosity=2)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user