$ErrorActionPreference = 'Stop' $root = Split-Path -Parent $PSScriptRoot $contracts = [ordered]@{ 'pages/notification/n02-message-detail.vue' = @('noticeDetail', 'markAsRead', 'openNoticeTarget', 'notice-state--expired', 'notice-state--ready') 'pages/profile/m02-edit-profile.vue' = @('profileForm', 'chooseAvatar', 'validateProfile', 'saveProfile', 'profile-state--saving') 'pages/profile/m03-security-settings.vue' = @('securityItems', 'openSecurityItem', 'device-state--safe', 'checkSecurity', '/pages/profile/m04-change-password', '/pages/profile/m05-change-phone') 'pages/profile/m04-change-password.vue' = @('passwordForm', 'validatePassword', 'togglePassword', 'savePassword', 'password-state--saving') 'pages/profile/m05-change-phone.vue' = @('phoneForm', 'sendCode', 'codeCountdown', 'savePhone', 'phone-state--saving') 'pages/profile/m06-help-center.vue' = @('helpCategories', 'filteredQuestions', 'toggleQuestion', 'contactSupport', '/pages/profile/m07-feedback') 'pages/profile/m07-feedback.vue' = @('feedbackForm', 'feedbackTypes', 'validateFeedback', 'submitFeedback', 'feedback-state--submitting') 'pages/profile/m08-promotion.vue' = @('inviteCode', 'copyInviteCode', 'generatePoster', 'share-state--ready', 'posterVisible') 'pages/profile/m09-vip-orders.vue' = @('serviceBenefits', 'orders', 'order-state--empty', 'openServiceNotice', 'order-state--ready') 'pages/profile/m10-about-settings.vue' = @('agreementItems', 'openAgreement', 'confirmLogout', 'appVersion', 'logoutVisible') } foreach ($entry in $contracts.GetEnumerator()) { $source = Get-Content -LiteralPath (Join-Path $root $entry.Key) -Raw -Encoding UTF8 if ($source -match ')|import\s+ModulePage\s+from') { throw "$($entry.Key) must not consume ModulePage" } foreach ($forbidden in @('@/utils/api.js', 'uni.showToast', 'uni.showModal', 'uni.showLoading', 'uni.showActionSheet')) { if ($source.Contains($forbidden)) { throw "$($entry.Key) contains forbidden token: $forbidden" } } foreach ($required in @('ModulePageBackground', 'PageHeader', 'AppButton') + $entry.Value) { if (-not $source.Contains($required)) { throw "$($entry.Key) missing business token: $required" } } if ($source -notmatch 'min-height:\s*100vh') { throw "$($entry.Key) must use natural page height" } } Write-Output 'NM-PAGE-BUSINESS-CONTRACT PASS'