import { existsSync, readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { dirname, resolve } from 'node:path' const root = resolve(dirname(fileURLToPath(import.meta.url)), '..') const srcRoot = resolve(root, 'src') const failures = [] const read = (relativePath) => readFileSync(resolve(srcRoot, relativePath), 'utf8') const expectFile = (relativePath) => { const path = resolve(srcRoot, relativePath) if (!existsSync(path)) { failures.push(`${relativePath} is missing`) return '' } return readFileSync(path, 'utf8') } const expectIncludes = (content, expected, label) => { if (!content.includes(expected)) failures.push(`${label} is missing: ${expected}`) } const expectExcludes = (content, unexpected, label) => { if (content.includes(unexpected)) failures.push(`${label} should not contain: ${unexpected}`) } const agreements = expectFile('components/AgreementLinks.vue') expectIncludes(agreements, '用户协议', 'AgreementLinks user agreement link') expectIncludes(agreements, '隐私政策', 'AgreementLinks privacy policy link') expectIncludes(agreements, 'u-popup', 'AgreementLinks popup') expectIncludes(agreements, '场馆小程序用户服务协议', 'AgreementLinks user agreement content') expectIncludes(agreements, '场馆小程序隐私政策', 'AgreementLinks privacy policy content') expectIncludes(agreements, 'defineExpose', 'AgreementLinks exposed popup methods') const unauthPanel = expectFile('components/UnauthLoginPanel.vue') expectIncludes(unauthPanel, '/static/brand/logo.png', 'UnauthLoginPanel brand logo') expectIncludes(unauthPanel, '大兴区冰上运动中心', 'UnauthLoginPanel app name') expectIncludes(unauthPanel, 'brand-section', 'UnauthLoginPanel brand section') expectIncludes(unauthPanel, 'login-card', 'UnauthLoginPanel login card') expectIncludes(unauthPanel, 'justify-content: center;', 'UnauthLoginPanel centered layout') expectIncludes(unauthPanel, 'calc(100vh - 176rpx - env(safe-area-inset-bottom))', 'UnauthLoginPanel available viewport height') expectIncludes(unauthPanel, 'align-self: center;', 'UnauthLoginPanel centered agreement rows') expectIncludes(unauthPanel, 'hasAcceptedUserAgreement = ref(false)', 'UnauthLoginPanel user agreement manual state') expectIncludes(unauthPanel, 'hasAcceptedPrivacyPolicy = ref(false)', 'UnauthLoginPanel privacy policy manual state') expectIncludes(unauthPanel, 'canLogin', 'UnauthLoginPanel login gate') expectIncludes(unauthPanel, 'acceptance-user', 'UnauthLoginPanel user agreement checkbox') expectIncludes(unauthPanel, 'acceptance-privacy', 'UnauthLoginPanel privacy policy checkbox') expectIncludes(unauthPanel, "emit('login')", 'UnauthLoginPanel login emit') expectIncludes(unauthPanel, '请先勾选用户协议和隐私政策', 'UnauthLoginPanel unchecked feedback') expectIncludes(unauthPanel, 'AgreementLinks', 'UnauthLoginPanel shared agreement popup') expectExcludes(unauthPanel, '预约课程、查看', 'UnauthLoginPanel extra marketing copy') expectExcludes(unauthPanel, '冰上课程', 'UnauthLoginPanel extra feature chip') expectExcludes(unauthPanel, '预约行程', 'UnauthLoginPanel extra feature chip') expectExcludes(unauthPanel, '会员权益', 'UnauthLoginPanel extra feature chip') expectExcludes(unauthPanel, '登录仅用于', 'UnauthLoginPanel extra safe tip') expectExcludes(unauthPanel, 'brand-logo-shell', 'UnauthLoginPanel logo shell decoration') expectExcludes(unauthPanel, 'radial-gradient', 'UnauthLoginPanel background decoration') expectExcludes(unauthPanel, 'linear-gradient(180deg, #EEF8FF', 'UnauthLoginPanel blue block background') expectExcludes(unauthPanel, 'background: #FFFFFF;', 'UnauthLoginPanel nested white card background') expectExcludes(unauthPanel, 'space-between', 'UnauthLoginPanel scattered vertical layout') expectExcludes(unauthPanel, 'width: 100%;\n max-width: 420rpx;', 'UnauthLoginPanel left-aligned agreement rows') const loginPages = [ ['pages/ice/bookings/index.vue', 'v-else-if="sessionStatus === SESSION_STATUS.GUEST"', '@login="onWechatLogin"'], ['pages/ice/bookings/detail.vue', 'v-else-if="sessionStatus === SESSION_STATUS.GUEST"', '@login="onWechatLogin"'], ['pages/ice/profile/index.vue', 'v-else-if="sessionStatus === SESSION_STATUS.GUEST"', '@login="onWechatLogin"'], ['pages/ice/profile/detail.vue', 'v-else-if="sessionStatus === SESSION_STATUS.GUEST"', '@login="onWechatLogin"'], ['pages/ice/profile/cards.vue', 'v-else-if="sessionStatus === SESSION_STATUS.GUEST"', '@login="onWechatLogin"'], ['pages/ice/profile/card-history.vue', 'v-else-if="sessionStatus === SESSION_STATUS.GUEST"', '@login="onWechatLogin"'], ['pages/comprehensive/bookings/index.vue', 'v-if="!session.isLoggedIn"', '@login="login"'], ['pages/comprehensive/profile/index.vue', 'v-if="!session.isLoggedIn"', '@login="login"'] ] for (const [page, condition, handler] of loginPages) { const content = read(page) expectIncludes(content, '