/** * 角色身份自定义名称全链路规范与对齐测试 * 覆盖范围:配置层、服务层、模型层、后台管理、数据大屏、UniApp 移动端 */ const fs = require('fs'); const path = require('path'); let passCount = 0; let failCount = 0; function assert(condition, message) { if (condition) { console.log(` \x1b[32m[PASS]\x1b[0m ${message}`); passCount++; } else { console.error(` \x1b[31m[FAIL]\x1b[0m ${message}`); failCount++; } } console.log('========================================================'); console.log(' 角色身份自定义名称全栈链路验证测试'); console.log('========================================================\n'); // 1. PartnerConfig.php 验证 const partnerConfigPath = path.resolve(__dirname, '../addons/shopro/service/partner/PartnerConfig.php'); assert(fs.existsSync(partnerConfigPath), 'PartnerConfig.php 文件存在'); if (fs.existsSync(partnerConfigPath)) { const content = fs.readFileSync(partnerConfigPath, 'utf-8'); assert(content.includes('public static function roleNames'), 'PartnerConfig 包含 roleNames() 方法'); assert(content.includes('partner_role_name_taster'), 'roleNames() 包含品酒师别名读取'); assert(content.includes('partner_role_name_maker'), 'roleNames() 包含创客别名读取'); assert(content.includes('partner_role_name_venue'), 'roleNames() 包含酒道馆别名读取'); assert(content.includes('partner_role_name_county'), 'roleNames() 包含区县别名读取'); assert(content.includes('partner_role_name_partner'), 'roleNames() 包含合伙股东别名读取'); assert(content.includes("$maker . '进阶奖'"), 'rewardTypeMap() 动态拼接创客进阶奖'); assert(content.includes("$venue . '运营奖'"), 'rewardTypeMap() 动态拼接酒道馆运营奖'); assert(content.includes("$county . '统筹奖'"), 'rewardTypeMap() 动态拼接区县统筹奖'); } // 2. IdentityService.php 验证 const identityServicePath = path.resolve(__dirname, '../addons/shopro/service/partner/IdentityService.php'); assert(fs.existsSync(identityServicePath), 'IdentityService.php 文件存在'); if (fs.existsSync(identityServicePath)) { const content = fs.readFileSync(identityServicePath, 'utf-8'); assert(content.includes('PartnerConfig::roleNames()'), 'IdentityService 调用 PartnerConfig::roleNames()'); assert(content.includes("'custom_role_names' => $roleNames"), 'IdentityService::build 返回 custom_role_names'); assert(content.includes("'maker_level_name' =>"), 'IdentityService::build 返回动态 maker_level_name'); assert(content.includes("'role_names' => $roleNames"), 'IdentityService::attachProfile 附加 role_names'); } // 3. Agent.php 模型验证 const agentModelPath = path.resolve(__dirname, '../application/admin/model/shopro/commission/Agent.php'); assert(fs.existsSync(agentModelPath), 'Agent.php 模型文件存在'); if (fs.existsSync(agentModelPath)) { const content = fs.readFileSync(agentModelPath, 'utf-8'); assert(content.includes("'role_names'"), 'Agent 模型 $append 包含 role_names'); assert(content.includes("'custom_role_names'"), 'Agent 模型 $append 包含 custom_role_names'); assert(content.includes('getRoleNamesAttr'), 'Agent 模型包含 getRoleNamesAttr 获取器'); } // 4. Config.php 控制器与 config/index.html 验证 const configCtrlPath = path.resolve(__dirname, '../application/admin/controller/shopro/Config.php'); const configViewPath = path.resolve(__dirname, '../application/admin/view/shopro/config/index.html'); assert(fs.existsSync(configCtrlPath), 'Config.php 控制器存在'); assert(fs.existsSync(configViewPath), 'config/index.html 视图存在'); if (fs.existsSync(configCtrlPath)) { const content = fs.readFileSync(configCtrlPath, 'utf-8'); assert(content.includes("'partner_role_name_taster'"), 'Config.php 包含品酒师配置字段保存'); assert(content.includes("'partner_role_name_maker'"), 'Config.php 包含创客配置字段保存'); assert(content.includes("'partner_role_name_venue'"), 'Config.php 包含酒道馆配置字段保存'); assert(content.includes("'partner_role_name_county'"), 'Config.php 包含区县配置字段保存'); } if (fs.existsSync(configViewPath)) { const content = fs.readFileSync(configViewPath, 'utf-8'); assert(content.includes('角色身份自定义名称'), 'config/index.html 包含角色身份自定义名称配置模块'); assert(content.includes('form.model.partner_role_name_taster'), '包含品酒师输入框绑定'); assert(content.includes('form.model.partner_role_name_maker'), '包含创客输入框绑定'); assert(content.includes('form.model.partner_role_name_venue'), '包含酒道馆输入框绑定'); assert(content.includes('form.model.partner_role_name_county'), '包含区县代理输入框绑定'); } // 5. 后台分销商管理与详情页验证 const agentCtrlPath = path.resolve(__dirname, '../application/admin/controller/shopro/commission/Agent.php'); const agentDetailViewPath = path.resolve(__dirname, '../application/admin/view/shopro/commission/agent/detail.html'); const agentIndexViewPath = path.resolve(__dirname, '../application/admin/view/shopro/commission/agent/index.html'); const agentJsPath = path.resolve(__dirname, '../public/assets/js/backend/shopro/commission/agent.js'); assert(fs.existsSync(agentCtrlPath), 'commission/Agent.php 控制器存在'); assert(fs.existsSync(agentDetailViewPath), 'agent/detail.html 存在'); assert(fs.existsSync(agentIndexViewPath), 'agent/index.html 存在'); assert(fs.existsSync(agentJsPath), 'agent.js 存在'); if (fs.existsSync(agentCtrlPath)) { const content = fs.readFileSync(agentCtrlPath, 'utf-8'); assert(content.includes('custom_role_names = \\addons\\shopro\\service\\partner\\PartnerConfig::roleNames()'), 'Agent.php detail() 接口返回 custom_role_names'); } if (fs.existsSync(agentDetailViewPath)) { const content = fs.readFileSync(agentDetailViewPath, 'utf-8'); assert(content.includes('state.data.custom_role_names?.venue'), 'detail.html 动态绑定酒道馆 label'); assert(content.includes('state.data.custom_role_names?.county'), 'detail.html 动态绑定区县代理 label'); } if (fs.existsSync(agentIndexViewPath)) { const content = fs.readFileSync(agentIndexViewPath, 'utf-8'); assert(content.includes('scope.row.role_names?.venue'), 'index.html 动态显示酒道馆 tag'); assert(content.includes('scope.row.role_names?.county'), 'index.html 动态显示区县 tag'); } if (fs.existsSync(agentJsPath)) { const content = fs.readFileSync(agentJsPath, 'utf-8'); assert(content.includes('function identityLabel('), 'agent.js 弹窗使用 dynamic identityLabel'); assert(content.includes('state.filter.tools.identity.options.data = ['), 'agent.js 列表搜索工具栏同步自定义名称'); } // 6. 数据大屏验证 const dashboardCtrlPath = path.resolve(__dirname, '../application/admin/controller/shopro/Dashboard.php'); const dashboardViewPath = path.resolve(__dirname, '../application/admin/view/shopro/dashboard/index.html'); assert(fs.existsSync(dashboardCtrlPath), 'Dashboard.php 存在'); assert(fs.existsSync(dashboardViewPath), 'dashboard/index.html 存在'); if (fs.existsSync(dashboardCtrlPath)) { const content = fs.readFileSync(dashboardCtrlPath, 'utf-8'); assert(content.includes('$roleNames = PartnerConfig::roleNames()'), 'Dashboard.php 读取角色别名配置'); assert(content.includes("'custom_role_names' => $roleNames"), 'Dashboard.php 返回 custom_role_names'); } if (fs.existsSync(dashboardViewPath)) { const content = fs.readFileSync(dashboardViewPath, 'utf-8'); assert(content.includes('state.partner.role_names?.taster'), '大屏品酒师卡片使用动态名称'); assert(content.includes('state.partner.role_names?.maker'), '大屏创客卡片使用动态名称'); assert(content.includes('state.partner.role_names?.venue'), '大屏酒道馆卡片使用动态名称'); assert(content.includes('state.partner.role_names?.county'), '大屏区县卡片使用动态名称'); } // 7. UniApp 移动端验证 const userCardVuePath = path.resolve(__dirname, '../uniapp/sheep/components/s-user-card/s-user-card.vue'); const commInfoVuePath = path.resolve(__dirname, '../uniapp/pages/commission/components/commission-info.vue'); const teamVuePath = path.resolve(__dirname, '../uniapp/pages/commission/team.vue'); const rewardsVuePath = path.resolve(__dirname, '../uniapp/pages/commission/rewards.vue'); assert(fs.existsSync(userCardVuePath), 's-user-card.vue 存在'); assert(fs.existsSync(commInfoVuePath), 'commission-info.vue 存在'); assert(fs.existsSync(teamVuePath), 'team.vue 存在'); assert(fs.existsSync(rewardsVuePath), 'rewards.vue 存在'); if (fs.existsSync(userCardVuePath)) { const content = fs.readFileSync(userCardVuePath, 'utf-8'); assert(content.includes("roleNames.taster || '品酒师'"), 's-user-card.vue 动态显示品酒师徽章'); assert(content.includes("roleNames.venue || '酒道馆'"), 's-user-card.vue 动态显示酒道馆徽章'); assert(content.includes("roleNames.county || '区县'"), 's-user-card.vue 动态显示区县徽章'); } if (fs.existsSync(commInfoVuePath)) { const content = fs.readFileSync(commInfoVuePath, 'utf-8'); assert(content.includes("roleNames.venue || '酒道馆'"), 'commission-info.vue 动态显示酒道馆 mini-tag'); assert(content.includes("roleNames.county || '区县'"), 'commission-info.vue 动态显示区县 mini-tag'); assert(content.includes('levelTitle'), 'commission-info.vue 等级标题动态映射'); } if (fs.existsSync(teamVuePath)) { const content = fs.readFileSync(teamVuePath, 'utf-8'); assert(content.includes("roleNames.venue || '酒道馆'"), 'team.vue 列表项动态显示酒道馆'); assert(content.includes("roleNames.county || '区县代理'"), 'team.vue 列表项动态显示区县代理'); assert(content.includes('filterPills = computed('), 'team.vue 筛选胶囊采用计算属性'); } if (fs.existsSync(rewardsVuePath)) { const content = fs.readFileSync(rewardsVuePath, 'utf-8'); assert(content.includes('tabMaps = computed('), 'rewards.vue Tab列表采用计算属性'); assert(content.includes("roleNames.value.maker || '创客'"), 'rewards.vue 收益Tab动态绑定创客'); assert(content.includes("roleNames.value.venue || '酒道馆'"), 'rewards.vue 收益Tab动态绑定酒道馆'); assert(content.includes("roleNames.value.county || '区县'"), 'rewards.vue 收益Tab动态绑定区县'); } console.log('\n--------------------------------------------------------'); console.log(`测试执行结果: 通过 ${passCount} 项, 失败 ${failCount} 项`); console.log('========================================================\n'); if (failCount > 0) { process.exit(1); } else { process.exit(0); }