From 311f2516096935673f6f884ceb2c56a5966eea58 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 14 Sep 2026 06:19:11 +0800 Subject: [PATCH] test: lock miniapp reference page scope --- miniapp/app.json | 6 +- miniapp/app.wxss | 14 ++++ miniapp/pages/activity/activity.wxml | 2 +- miniapp/pages/anti-fraud/anti-fraud.wxml | 2 +- miniapp/pages/content/content.wxml | 2 +- .../counseling-intro/counseling-intro.wxml | 2 +- miniapp/pages/discover/discover.wxml | 4 +- miniapp/pages/index/index.ts | 73 ++++++++++++++----- miniapp/pages/index/index.wxml | 2 +- miniapp/pages/matchmaker/matchmaker.wxml | 2 +- miniapp/pages/messages/messages.wxml | 2 +- miniapp/pages/mine/mine.wxml | 4 +- .../premarital-intro/premarital-intro.wxml | 2 +- .../service-station/service-station.wxml | 2 +- ui-tests/miniapp-reference-contracts.mjs | 70 ++++++++++++++++++ 15 files changed, 155 insertions(+), 34 deletions(-) create mode 100644 ui-tests/miniapp-reference-contracts.mjs diff --git a/miniapp/app.json b/miniapp/app.json index 7177e72..d722741 100644 --- a/miniapp/app.json +++ b/miniapp/app.json @@ -69,9 +69,9 @@ ], "window": { "navigationBarTitleText": "丹阳公益婚恋", - "navigationBarBackgroundColor": "#E96B6B", + "navigationBarBackgroundColor": "#171D72", "navigationBarTextStyle": "white", - "backgroundColor": "#FAFAF8", + "backgroundColor": "#F4F5FA", "backgroundTextStyle": "dark", "enablePullDownRefresh": false }, @@ -113,4 +113,4 @@ } ] } -} \ No newline at end of file +} diff --git a/miniapp/app.wxss b/miniapp/app.wxss index 6c7ed75..392d56b 100644 --- a/miniapp/app.wxss +++ b/miniapp/app.wxss @@ -13,6 +13,20 @@ page { --color-primary-light: #FFF3F2; --color-primary-lighter: #FFF8F7; + /* ============ 小程序参考图品牌主题 ============ */ + --mini-night-start: #172A72; + --mini-night-end: #25104F; + --mini-night-soft: #3445A1; + --mini-accent-pink: #FF4F91; + --mini-accent-coral: #FF6A78; + --mini-card-bg: rgba(255, 255, 255, 0.98); + --mini-text: #1F2744; + --mini-muted: #7D839B; + --mini-card-radius: 24rpx; + --mini-text-on-night: #FFFFFF; + --mini-text-on-night-muted: rgba(255, 255, 255, 0.72); + --mini-shadow: 0 16rpx 40rpx rgba(28, 30, 88, 0.14); + /* ============ 功能色(规范 §4) ============ */ --color-success: #2E9B68; --color-success-light: #ECF8F2; diff --git a/miniapp/pages/activity/activity.wxml b/miniapp/pages/activity/activity.wxml index 7264dd1..72832eb 100644 --- a/miniapp/pages/activity/activity.wxml +++ b/miniapp/pages/activity/activity.wxml @@ -1,5 +1,5 @@ - + 婚恋反诈中心真诚交往,也要守住安全边界平台不会以任何理由要求转账、投资或提供银行卡密码。常见风险信号!{{item}}遇到异常请停止转账并保存相关记录遇到可疑情况怎么办1停止资金操作不要继续转账、充值或提供验证码2保存相关证据保留聊天、付款与账号信息3及时举报或报警紧急情况请直接拨打 110举报可疑行为 \ No newline at end of file +婚恋反诈中心真诚交往,也要守住安全边界平台不会以任何理由要求转账、投资或提供银行卡密码。常见风险信号!{{item}}遇到异常请停止转账并保存相关记录遇到可疑情况怎么办1停止资金操作不要继续转账、充值或提供验证码2保存相关证据保留聊天、付款与账号信息3及时举报或报警紧急情况请直接拨打 110举报可疑行为 \ No newline at end of file diff --git a/miniapp/pages/content/content.wxml b/miniapp/pages/content/content.wxml index a0f1271..ec8f7c0 100644 --- a/miniapp/pages/content/content.wxml +++ b/miniapp/pages/content/content.wxml @@ -1 +1 @@ -婚恋课堂认真学习,更好地相遇提供真实、克制、可实践的关系成长与安全知识。{{item}}{{item.category}}{{item.title}} \ No newline at end of file +婚恋课堂认真学习,更好地相遇提供真实、克制、可实践的关系成长与安全知识。{{item}}{{item.category}}{{item.title}} \ No newline at end of file diff --git a/miniapp/pages/counseling-intro/counseling-intro.wxml b/miniapp/pages/counseling-intro/counseling-intro.wxml index 792fc7b..b83d73b 100644 --- a/miniapp/pages/counseling-intro/counseling-intro.wxml +++ b/miniapp/pages/counseling-intro/counseling-intro.wxml @@ -1 +1 @@ -U55 公益婚恋咨询当关系让你困扰,可以认真谈一谈由婚恋咨询人员提供关系与情绪支持;咨询服务与公益红娘服务彼此独立。我们可以提供的帮助选择最接近当前需要的方向{{index+1}}{{item.name}}{{item.description}}›咨询内容会按敏感信息保护。公益红娘不能查看咨询正文,咨询人员也只能处理明确分配给自己的服务。 \ No newline at end of file +U55 公益婚恋咨询当关系让你困扰,可以认真谈一谈由婚恋咨询人员提供关系与情绪支持;咨询服务与公益红娘服务彼此独立。我们可以提供的帮助选择最接近当前需要的方向{{index+1}}{{item.name}}{{item.description}}›咨询内容会按敏感信息保护。公益红娘不能查看咨询正文,咨询人员也只能处理明确分配给自己的服务。 \ No newline at end of file diff --git a/miniapp/pages/discover/discover.wxml b/miniapp/pages/discover/discover.wxml index a585964..1fc1030 100644 --- a/miniapp/pages/discover/discover.wxml +++ b/miniapp/pages/discover/discover.wxml @@ -1,9 +1,9 @@ - + - 🔍 + 搜索 ({ ...entry, ...ENTRY_VISUALS[entry.code] })) + Page({ data: { unreadCount: 0, + loading: true, + loadError: false, userState: null, isOnboarding: false, isVerified: false, @@ -18,7 +42,7 @@ Page({ statusChecks: [], banners: [], currentBannerIndex: 0, - quickEntries: [], + quickEntries: QUICK_ENTRIES, recommendations: [], recState: 'idle', actionLoadingUserId: '', @@ -42,7 +66,7 @@ Page({ }, onShow() { - if (authStore.state.isLoggedIn) { + if (authStore.state.isLoggedIn && !this.data.loading) { this.loadHomeData() } }, @@ -56,6 +80,7 @@ Page({ async checkAuthAndLoad() { if (!authStore.state.isLoggedIn) { this.setData({ + loading: false, isOnboarding: true, onboardingMessage: '登录后即可开始寻找合适的人', onboardingActions: [{ text: '去登录', event: 'login', variant: 'primary' }], @@ -66,12 +91,13 @@ Page({ }, async loadHomeData() { + this.setData({ loading: true, loadError: false }) try { const res = await api.get('/home') this.processHomeData(res) } catch (err) { console.error('首页数据加载失败', err) - this.setData({ recState: 'error' }) + this.setData({ loading: false, loadError: true, recState: 'error' }) } }, @@ -83,33 +109,40 @@ Page({ const profileStatus = userState?.profileStatus || '' const eligStatus = userState?.localEligibilityStatus || 'not_declared' - const isOnboarding = !userState || profileStatus !== 'approved' + const isOnboarding = !userState || !userState.verified || (profileStatus !== 'approved' && profileStatus !== 'completed') const isPaused = relStatus === 'paused' const isSuccessful = relStatus === 'matched_successfully' const isVerified = eligStatus === 'verified' const checks = [ { label: '已实名', done: userState?.verified || false }, - { label: '本地资格', done: eligStatus === 'verified' || eligStatus === 'pending_review' }, + { label: '本地资格', done: eligStatus === 'verified' }, { label: '资料已审核', done: profileStatus === 'approved' || profileStatus === 'completed' }, ] this.setData({ + loading: false, loadError: false, userState, isOnboarding, isVerified, isPaused, isSuccessful, onboardingMessage: this.buildOnboardingMessage(userState, profileStatus, eligStatus), onboardingActions: this.buildOnboardingActions(userState, profileStatus, eligStatus), statusChecks: checks, - banners, quickEntries, + banners: banners || [], + quickEntries: quickEntries?.length + ? quickEntries.map((entry) => ({ ...entry, ...ENTRY_VISUALS[entry.code] })) + : QUICK_ENTRIES, recommendations: recommendations || [], recState: (recommendations && recommendations.length > 0) ? 'loaded' : 'empty', - serviceRecommendations, activities, serviceLocation, + serviceRecommendations: serviceRecommendations || [], activities: activities || [], serviceLocation, + articles: data.articles || [], safetyNotice: safetyNotice || this.data.safetyNotice, }) }, buildOnboardingMessage(state, profileStatus, eligStatus) { if (!state) return '登录后即可开始寻找合适的人' + if (!state.verified) return '完成实名认证后,即可继续完善资料并使用公益婚恋服务' + if (profileStatus === 'pending_review') return '资料正在人工审核,请耐心等待审核结果' if (eligStatus === 'not_declared') return '完成本地资格声明后即可开始寻找合适的人' if (eligStatus === 'needs_evidence') return '补充本地资格佐证后即可开始寻找合适的人' if (profileStatus !== 'approved' && profileStatus !== 'completed') return '资料审核通过后即可开始寻找合适的人' @@ -143,20 +176,21 @@ Page({ wx.navigateTo({ url: `/pages/activity-detail/activity-detail?id=${targetValue}` }) } else if (targetType === 'matchmaker') { wx.navigateTo({ url: '/pages/matchmaker/matchmaker' }) - } else if (targetType === 'service_location' && targetValue) { - wx.navigateTo({ url: `/pages/local-eligibility/local-eligibility?from=service_station&id=${targetValue}` }) + } else { + const routes = { matchmaker: '/pages/matchmaker/matchmaker', counseling: '/pages/counseling-intro/counseling-intro', premarital: '/pages/premarital-intro/premarital-intro', service_location: '/pages/service-station/service-station', article: '/pages/content-detail/content-detail', internal_page: targetValue } + const url = routes[targetType] + if (url && /^\/pages\//.test(url)) wx.navigateTo({ url }) } }, onEntryTap(e) { const { code, enabled, targetPage } = e.currentTarget.dataset.entry if (!enabled) { - wx.showToast({ title: '完成资料后可使用此功能', icon: 'none' }) + wx.showToast({ title: e.currentTarget.dataset.entry.disabledReason || '暂不可使用此功能', icon: 'none' }) return } - if (targetPage.startsWith('pages/')) { - wx.navigateTo({ url: targetPage }) - } + if (targetPage === '/pages/discover/discover' || targetPage === '/pages/activity/activity') wx.switchTab({ url: targetPage }) + else if (targetPage?.startsWith('/pages/')) wx.navigateTo({ url: targetPage }) }, onViewDetail(e) { @@ -203,7 +237,7 @@ Page({ }, onResume() { - wx.showToast({ title: '功能开发中', icon: 'none' }) + wx.navigateTo({ url: '/pages/relationship-status/relationship-status' }) }, onSeeMore() { wx.switchTab({ url: '/pages/discover/discover' }) }, @@ -213,7 +247,7 @@ Page({ if (id) wx.navigateTo({ url: `/pages/activity-detail/activity-detail?id=${id}` }) }, onStationTap() { - wx.navigateTo({ url: '/pages/local-eligibility/local-eligibility?from=service_station' }) + wx.navigateTo({ url: '/pages/service-station/service-station' }) }, onServiceTap(e) { const type = e.currentTarget.dataset.type @@ -221,14 +255,17 @@ Page({ case 'matchmaker': wx.navigateTo({ url: '/pages/matchmaker/matchmaker' }) break case 'counseling': + wx.navigateTo({ url: '/pages/counseling-intro/counseling-intro' }) + break case 'premarital': - wx.navigateTo({ url: `/pages/local-eligibility/local-eligibility?from=${type}` }) + wx.navigateTo({ url: '/pages/premarital-intro/premarital-intro' }) break } }, onSafetyTap() { - wx.navigateTo({ url: '/pages/local-eligibility/local-eligibility?from=anti_fraud' }) + wx.navigateTo({ url: '/pages/anti-fraud/anti-fraud' }) }, + onArticleTap(e) { wx.navigateTo({ url: `/pages/content-detail/content-detail?id=${e.currentTarget.dataset.id}` }) }, onMessages() { wx.switchTab({ url: '/pages/messages/messages' }) }, formatDate(timestamp) { diff --git a/miniapp/pages/index/index.wxml b/miniapp/pages/index/index.wxml index b34f8fb..4077676 100644 --- a/miniapp/pages/index/index.wxml +++ b/miniapp/pages/index/index.wxml @@ -1,4 +1,4 @@ - + 善缘丹阳真实相识 · 公益牵线 diff --git a/miniapp/pages/matchmaker/matchmaker.wxml b/miniapp/pages/matchmaker/matchmaker.wxml index 5174b60..4039bb0 100644 --- a/miniapp/pages/matchmaker/matchmaker.wxml +++ b/miniapp/pages/matchmaker/matchmaker.wxml @@ -1,5 +1,5 @@ - + - + + @@ -19,4 +19,4 @@ 退出登录 - \ No newline at end of file + diff --git a/miniapp/pages/premarital-intro/premarital-intro.wxml b/miniapp/pages/premarital-intro/premarital-intro.wxml index f05975e..3a82936 100644 --- a/miniapp/pages/premarital-intro/premarital-intro.wxml +++ b/miniapp/pages/premarital-intro/premarital-intro.wxml @@ -1 +1 @@ -U58 婚前辅导在进入婚姻前,把重要的事认真谈清楚帮助双方讨论共同生活、家庭责任与沟通方式,可邀请伴侣共同参与。辅导内容沟沟通与期望表达需求、倾听差异,形成可以共同遵守的约定家家庭与责任讨论家庭角色、财务安排与双方家庭关系伴共同生活对生活方式、未来计划和冲突处理建立共识双方共同参与效果更好,但必须基于自愿,不会因为一方申请而自动通知或要求另一方参加。申请婚前辅导 \ No newline at end of file +U58 婚前辅导在进入婚姻前,把重要的事认真谈清楚帮助双方讨论共同生活、家庭责任与沟通方式,可邀请伴侣共同参与。辅导内容沟沟通与期望表达需求、倾听差异,形成可以共同遵守的约定家家庭与责任讨论家庭角色、财务安排与双方家庭关系伴共同生活对生活方式、未来计划和冲突处理建立共识双方共同参与效果更好,但必须基于自愿,不会因为一方申请而自动通知或要求另一方参加。申请婚前辅导 \ No newline at end of file diff --git a/miniapp/pages/service-station/service-station.wxml b/miniapp/pages/service-station/service-station.wxml index 62f6d8e..e86d789 100644 --- a/miniapp/pages/service-station/service-station.wxml +++ b/miniapp/pages/service-station/service-station.wxml @@ -1 +1 @@ -固定公益服务阵地善缘丹阳公益服务站提供面对面的婚恋服务咨询,让线上服务在丹阳有真实落点。服务站信息址丹阳市城区公益服务中心丹阳市云阳街道(具体地址以预约确认为准)时周二至周日 09:00–17:30节假日开放时间以平台通知为准可预约服务{{index+1}}{{item}}›服务站人员仅处理现场预约与指定服务,不会浏览无关用户资料。预约到站服务 \ No newline at end of file +固定公益服务阵地善缘丹阳公益服务站提供面对面的婚恋服务咨询,让线上服务在丹阳有真实落点。服务站信息址丹阳市城区公益服务中心丹阳市云阳街道(具体地址以预约确认为准)时周二至周日 09:00–17:30节假日开放时间以平台通知为准可预约服务{{index+1}}{{item}}›服务站人员仅处理现场预约与指定服务,不会浏览无关用户资料。预约到站服务 \ No newline at end of file diff --git a/ui-tests/miniapp-reference-contracts.mjs b/ui-tests/miniapp-reference-contracts.mjs new file mode 100644 index 0000000..1e9b6c6 --- /dev/null +++ b/ui-tests/miniapp-reference-contracts.mjs @@ -0,0 +1,70 @@ +import assert from 'node:assert/strict' +import { existsSync, readFileSync } from 'node:fs' +import { resolve } from 'node:path' + +const root = resolve(import.meta.dirname, '..') +const read = (path) => readFileSync(resolve(root, path), 'utf8') +const app = JSON.parse(read('miniapp/app.json')) +const corePages = [ + 'index', + 'discover', + 'messages', + 'activity', + 'mine', + 'matchmaker', + 'counseling-intro', + 'premarital-intro', + 'content', + 'anti-fraud', + 'service-station', +] +const quickEntryCodes = [ + 'find_object', + 'matchmaker', + 'activities', + 'counseling', + 'classroom', + 'premarital', + 'anti_fraud', + 'service_station', +] + +assert.deepEqual( + app.tabBar.list.map((item) => item.text), + ['首页', '找对象', '消息', '活动', '我的'], + '五个 Tab 的顺序发生偏移', +) + +for (const page of corePages) { + const base = `miniapp/pages/${page}/${page}` + for (const extension of ['.json', '.wxml', '.wxss']) { + assert.ok(existsSync(resolve(root, base + extension)), `${page}${extension} 不存在`) + } + const template = read(base + '.wxml') + assert.match(template, /reference-page/, `${page} 未接入参考图页面骨架`) + assert.doesNotMatch(template, /[\u{1F300}-\u{1FAFF}]/u, `${page} 含 Emoji`) +} + +const homeLogic = read('miniapp/pages/index/index.ts') +let previousIndex = -1 +for (const code of quickEntryCodes) { + const index = homeLogic.indexOf(code) + assert.ok(index >= 0, `首页缺少入口 ${code}`) + assert.ok(index > previousIndex, `首页入口 ${code} 顺序错误`) + previousIndex = index +} + +const theme = read('miniapp/app.wxss') +for (const token of [ + '--mini-night-start', + '--mini-night-end', + '--mini-accent-pink', + '--mini-accent-coral', + '--mini-card-bg', + '--mini-card-radius', + '--mini-shadow', +]) { + assert.ok(theme.includes(token), `缺少全局 Token ${token}`) +} + +console.log('Miniapp reference contracts passed')