fix(environment): 迁移不可变规则落地——034 违规补齐改为新迁移 037,修复 browser_env.image_version 残留导致的创建环境 500
douyin-release-gate / verify (push) Failing after 3m10s

- 迁移 037(幂等):补删 browser_env.image_version、audit_event 镜像列、browser_image 表
- 恢复 034 为引入时原版(撤销 6cd4cdc 的原地修改)
- 新增 migrations immutable 单测:迁移文件引入后不得改内容,要改就新增版本号
- web: 指纹种子字段中文化 + 指纹参数 400 错误映射为具体中文提示
This commit is contained in:
2026-09-28 10:32:37 +08:00
parent 85ffe6906f
commit 5e391b70e9
6 changed files with 172 additions and 13 deletions
+30 -6
View File
@@ -28,7 +28,7 @@ function fingerprintPayload(form: any) {
return payload;
}
// 已用 seed 之外的最小可用 seed(对齐归档版 nextFingerprintSeed)。
// 已用指纹种子之外的最小可用种子(对齐归档版 nextFingerprintSeed)。
function nextFingerprintSeed(runtimes: any[]): string {
const used = new Set(runtimes.map((runtime) => Number(runtime.fingerprint?.seed)).filter((seed) => Number.isInteger(seed) && seed > 0));
let seed = 1000;
@@ -36,6 +36,24 @@ function nextFingerprintSeed(runtimes: any[]): string {
return String(seed);
}
// 后端把 fingerprint 校验错误映射成具体中文字段提示(internal/environment/fingerprint.go Validate)。
function fingerprintErrorMessage(errorText: string): string {
const fieldTexts: Array<[RegExp, string]> = [
[/seed must be 1\.\.2147483647/, '指纹种子取值为 1 到 2147483647 的整数'],
[/platform must be/, '操作系统仅支持 windows、linux、macos'],
[/brand must be/, '浏览器品牌仅支持 Chrome、Edge、Opera、Vivaldi'],
[/platform_version/, '系统版本格式不正确,如 11.0.0'],
[/brand_version/, '品牌版本格式不正确,如 132.0.6834.159'],
[/hardware_concurrency/, 'CPU 核心数取值为 0 到 128'],
[/lang must be/, '语言格式不正确,如 zh-CN'],
[/accept_lang/, '接受语言格式不正确,如 zh-CN,en-US'],
[/timezone/, '时区格式不正确,如 Asia/Shanghai'],
[/proxy_server/, '代理地址格式不正确'],
[/disable_spoofing/, '禁用指纹伪装只能是 font、audio、canvas、clientrects、gpu 的子集'],
];
return fieldTexts.find(([pattern]) => pattern.test(errorText))?.[1] || `指纹参数校验未通过:${errorText}`;
}
export default function Page() {
const [form] = Form.useForm();
const [runtimes, setRuntimes] = useState<any[]>([]);
@@ -91,8 +109,14 @@ export default function Page() {
messageApi.success('运行环境已创建。');
history.push('/browsers');
} catch (reason: any) {
const status = reason.status ?? reason.body?.status;
const errorText = reason.body?.error || reason.message || '';
messageApi.error(
reason.status === 503 ? `环境不可用(503):${reason.message}` : conflictMessage(reason, '账号或运行环境已有活动绑定;表单内容已保留。'),
status === 503
? `环境不可用(503):${errorText}`
: status === 400 && /must be|seed|platform|brand|lang|timezone|concurrency|spoofing/i.test(errorText)
? fingerprintErrorMessage(errorText)
: conflictMessage(reason, '账号或运行环境已有活动绑定;表单内容已保留。'),
);
} finally {
setSubmitBusy(false);
@@ -134,13 +158,13 @@ export default function Page() {
<Col xs={24} md={12} xl={8}>
<Form.Item
name="seed"
label="Fingerprint Seed"
label="指纹种子"
required
rules={[
{ required: true, message: '请输入 seed' },
{ type: 'integer', min: 1, max: 2147483647, message: 'Fingerprint Seed 取值为 1 到 2147483647 的整数' },
{ required: true, message: '请输入指纹种子' },
{ type: 'integer', min: 1, max: 2147483647, message: '指纹种子取值为 1 到 2147483647 的整数' },
]}
extra="1..2147483647 的整数,派生指纹参数"
extra="1..2147483647 的整数,不同种子派生不同浏览器指纹"
>
<InputNumber min={1} max={2147483647} style={{ width: 180 }} />
</Form.Item>