import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; const MP_ROOT = path.resolve('m:/2026项目/CRMmp/mpuniapp'); const profileUtsPath = path.join(MP_ROOT, 'pages/owner/profile/useProfile.uts'); const profileUvuePath = path.join(MP_ROOT, 'pages/owner/profile/index.uvue'); test('1. useProfile.uts 必须包含名片工作室所有核心文案键', () => { assert.ok(fs.existsSync(profileUtsPath), '必须存在 useProfile.uts'); const content = fs.readFileSync(profileUtsPath, 'utf-8'); assert.ok(content.includes('cardStudioSection'), '必须包含 cardStudioSection'); assert.ok(content.includes('myCards'), '必须包含 myCards'); assert.ok(content.includes('cardEdit'), '必须包含 cardEdit'); assert.ok(content.includes('productCases'), '必须包含 productCases'); assert.ok(content.includes('articleDynamics'), '必须包含 articleDynamics'); assert.ok(content.includes('sharePoster'), '必须包含 sharePoster'); assert.ok(content.includes('exchangeHall'), '必须包含 exchangeHall'); assert.ok(content.includes('editProfile'), '必须包含 editProfile'); }); test('2. profile/index.uvue 零 Emoji 违规审查', () => { const emojiRegex = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u; const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.equal(emojiRegex.test(content), false, 'profile/index.uvue 严禁含有 Emoji'); }); test('3. profile/index.uvue 必须完整挂载数字名片工作室 6 大业务入口', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('/pages/owner/card/index'), '必须包含我的名片列表入口'); assert.ok(content.includes('/pages/owner/card/edit'), '必须包含名片极速维护入口'); assert.ok(content.includes('/pages/owner/card/cases'), '必须包含产品相册与案例入口'); assert.ok(content.includes('/pages/owner/card/articles'), '必须包含文章与商务动态入口'); assert.ok(content.includes('/pages/owner/card/qrcode'), '必须包含分享海报入口'); assert.ok(content.includes('/pages/owner/hall/index'), '必须包含名片互换大厅入口'); }); test('4. openPage 跳转逻辑必须支持 TabBar 页面使用 uni.switchTab 防止死链', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('uni.switchTab'), 'TabBar 页面必须调用 uni.switchTab 跳转'); assert.ok(content.includes('uni.navigateTo'), '常规页面调用 uni.navigateTo 跳转'); assert.ok(content.includes('/pages/owner/card/index'), 'TabBar 判断列表必须包含 /pages/owner/card/index'); }); test('5. 个人资料顶部身份区域与配额进度条具备点击交互响应', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('onEditProfileClick'), '顶部身份卡片必须具备 onEditProfileClick'); assert.ok(content.includes('onQuotaClick'), '配额进度条必须具备 onQuotaClick 交互反馈'); }); test('6. profile/index.uvue 必须集成 Executive 商业资产罗盘指标看板', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('metricsCards'), '指标看板必须包含活跃名片统计'); assert.ok(content.includes('metricsVisitors'), '指标看板必须包含雷达访客统计'); assert.ok(content.includes('metricsLeads'), '指标看板必须包含沉淀线索统计'); assert.ok(content.includes('/pages/owner/radar'), '雷达指标必须支持跳转到雷达页'); assert.ok(content.includes('/pages/owner/leads'), '线索指标必须支持跳转到线索页'); }); test('7. profile/index.uvue 触控热区保证与底部安全区适配', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('env(safe-area-inset-bottom'), '必须适配视口底部安全区'); assert.ok(content.includes('min-height: 44px') || content.includes('min-height: 46px') || content.includes('min-height: 48px'), '核心按钮与触控区必须保证 >= 44px'); }); test('8. profile/index.uvue 必须符合 Bento Grid、漫反射软阴影与极光流光视觉 Token', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('bento-card'), '必须应用 bento-card 便当盒结构'); assert.ok(content.includes('box-shadow'), '必须包含漫反射软阴影设计'); assert.ok(content.includes('linear-gradient'), '必须包含品牌微渐变或极光流光微效果'); }); test('9. 业务入口必须为条状入口 (Grouped Inset Cell Rows),杜绝玩具方块网格', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.ok(content.includes('bento-list-group'), '必须使用 bento-list-group 分组条状容器'); assert.ok(content.includes('bento-row-item'), '必须使用 bento-row-item 条状列表项'); assert.equal(content.includes('workspace-grid'), false, '必须彻底移除 workspace-grid 玩具方块网格'); assert.equal(content.includes('grid-item-head'), false, '必须彻底移除 grid-item-head 网格头部'); }); test('10. 头像交互必须优雅沉浸,杜绝破坏高管形象的右上角突兀红色大叉', () => { const content = fs.readFileSync(profileUvuePath, 'utf-8'); assert.equal(content.includes('avatar-remove-badge'), false, '严禁在头像角部悬挂突兀红色大叉删除标'); assert.ok(content.includes('onAvatarClick'), '头像必须支持点击交互呼出操作面板'); });