feat: 同步管理端、用户端与后端业务,并接通线上 Web 接口

补齐平台订阅、外部登录、CRM 同步与用户端页面;Nginx 转发用户端接口,登录页使用 Google 与 Apple 标志。

Co-authored-by: Cursor <cursoragent@cursor.com>
这个提交包含在:
wikiboss
2026-09-23 18:01:47 +08:00
父节点 8ea9c25386
当前提交 62e0ae4435
共有 227 个文件被更改,包括 21855 次插入 和 5264 次删除

查看文件

@@ -112,3 +112,131 @@ test('3. team/brand-kit locale 必须包含 menu.team.brandKit 与中英文案',
assert.equal(defaultI18n['en-US']['menu.team.brandKit'], 'Brand Kit');
assert.equal(defaultI18n['zh-CN']['menu.team.brandKit'], '品牌规范');
});
test('4. 版权页脚:无真实保存字段时不得提交/假装已生效,须禁用或提示暂不可保存', () => {
const content = readPage();
const localeContent = fs.readFileSync(brandKitLocalePath, 'utf-8');
// 当前 brand 保存契约仅有 companyName / logoUrl / primaryColor,无 footer|copyright|legalNotice
const savePayloadMatch = content.match(
/interface BrandSavePayload\s*\{[\s\S]*?\}/
);
const savePayloadBlock = savePayloadMatch?.[0] ?? '';
const hasFooterInSavePayload = /\b(footer|copyright|legalNotice)\b/.test(
savePayloadBlock
);
const hasFooterAssignedToBody =
/body\.(footer|copyright|legalNotice)\s*=/.test(content) ||
/(?:const|let)\s+body\s*[:=][^{]*\{[\s\S]*?\b(footer|copyright|legalNotice)\s*:/.test(
content
);
assert.ok(
localeContent.includes("'teamBrandKit.footer.unavailable'") ||
localeContent.includes("'teamBrandKit.copyright.unavailable'") ||
localeContent.includes("'teamBrandKit.legalNotice.unavailable'"),
'locale 必须包含页脚/版权暂不可保存词条'
);
assert.ok(
localeContent.includes("'teamBrandKit.form.footer'") ||
localeContent.includes("'teamBrandKit.form.copyright'") ||
localeContent.includes("'teamBrandKit.form.legalNotice'"),
'locale 必须包含页脚输入标签文案'
);
assert.ok(
content.includes("t['teamBrandKit.footer.unavailable']") ||
content.includes("t['teamBrandKit.copyright.unavailable']") ||
content.includes("t['teamBrandKit.legalNotice.unavailable']") ||
content.includes('teamBrandKit.footer.unavailable') ||
content.includes('teamBrandKit.copyright.unavailable') ||
content.includes('teamBrandKit.legalNotice.unavailable'),
'页面必须引用页脚暂不可保存文案'
);
// 禁止把写死版权句当成已保存生效内容
assert.ok(
!/©\s*20\d{2}|All rights reserved|版权所有|保留所有权利/i.test(content),
'禁止页面写死版权声明并当成已生效'
);
assert.ok(
!hasFooterInSavePayload && !hasFooterAssignedToBody,
'无后端页脚字段时禁止把 footer/copyright/legalNotice 写入保存 payload'
);
// 空值不得提交假声明(保存体不得硬编码版权句子)
assert.ok(
!/BrandSavePayload[\s\S]{0,400}(©|All rights reserved|版权所有)/i.test(
content
),
'空值不得向保存接口提交假版权声明'
);
const hasFooterSaveField = hasFooterInSavePayload || hasFooterAssignedToBody;
if (!hasFooterSaveField) {
const footerInputShown =
/field=["'](footer|copyright|legalNotice)["']/.test(content) ||
content.includes('teamBrandKit.form.footer') ||
content.includes('teamBrandKit.form.copyright') ||
content.includes('teamBrandKit.form.legalNotice');
assert.ok(footerInputShown, '可展示页脚输入,但不得当作已保存字段');
const footerDisabled =
/disabled[\s\S]{0,160}(footer|copyright|legalNotice)|(footer|copyright|legalNotice)[\s\S]{0,200}disabled/i.test(
content
) ||
content.includes('disabled={!FOOTER_SAVE_SUPPORTED}') ||
content.includes('disabled={true}');
const footerUnavailableHint =
content.includes("t['teamBrandKit.footer.unavailable']") ||
content.includes("t['teamBrandKit.copyright.unavailable']") ||
content.includes("t['teamBrandKit.legalNotice.unavailable']") ||
content.includes('teamBrandKit.footer.unavailable') ||
content.includes('teamBrandKit.copyright.unavailable') ||
content.includes('teamBrandKit.legalNotice.unavailable');
assert.ok(
footerDisabled || footerUnavailableHint,
'无页脚保存字段时必须禁用输入/保存或提示暂不可保存'
);
}
// Message.success 仅允许出现在 code === 1000 成功分支
const successMatches = [
...content.matchAll(/Message\.success\s*\([^)]*\)/g),
];
for (const match of successMatches) {
const idx = match.index ?? 0;
const windowBefore = content.slice(Math.max(0, idx - 280), idx);
assert.ok(
/code\s*===\s*1000/.test(windowBefore),
'保存失败不得 Message.success;成功提示必须在 code === 1000 分支内'
);
}
});
test('5. locale 页脚词条须说明暂不可保存,且中英文齐全', () => {
const localeContent = fs.readFileSync(brandKitLocalePath, 'utf-8');
const unavailableKey =
localeContent.includes("'teamBrandKit.footer.unavailable'")
? 'teamBrandKit.footer.unavailable'
: localeContent.includes("'teamBrandKit.copyright.unavailable'")
? 'teamBrandKit.copyright.unavailable'
: 'teamBrandKit.legalNotice.unavailable';
assert.ok(
localeContent.includes(`'${unavailableKey}'`),
'必须包含暂不可保存词条'
);
assert.ok(
/暂不可保存|暂不可用|not available|cannot be saved|unavailable/i.test(
localeContent
),
'暂不可保存文案须明确不可落库'
);
assert.ok(!/\bany\b/.test(localeContent), 'locale 禁止使用 any');
assert.ok(
!/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u.test(
localeContent
),
'locale 禁止使用 emoji'
);
});