From 661d0d2589eb8278144dd44d9450b63e46bcec86 Mon Sep 17 00:00:00 2001 From: xcbyy <2578898740@qq.com> Date: Tue, 13 Oct 2026 10:06:15 +0800 Subject: [PATCH] feat(withdraw): convert withdraw records modal into dedicated independent page --- pwuniapp/common/icons.js | 34 + pwuniapp/pages.json | 20 + pwuniapp/pages/user/index.vue | 180 +--- pwuniapp/pages/user/settings.vue | 770 +++++++++++++++++ pwuniapp/pages/user/withdraw-records.vue | 1009 ++++++++++++++++++++++ pwuniapp/pages/user/withdraw.vue | 51 +- server/tests/client-features.spec.ts | 31 +- server/tests/content-security.spec.ts | 41 +- 8 files changed, 1907 insertions(+), 229 deletions(-) create mode 100644 pwuniapp/pages/user/settings.vue create mode 100644 pwuniapp/pages/user/withdraw-records.vue diff --git a/pwuniapp/common/icons.js b/pwuniapp/common/icons.js index 58d082e..69e879c 100644 --- a/pwuniapp/common/icons.js +++ b/pwuniapp/common/icons.js @@ -296,6 +296,40 @@ export const ICONS = { `), + lock: svgToUri(` + + + + + `), + + trash: svgToUri(` + + + + + + + `), + + fileText: svgToUri(` + + + + + + + + `), + + logOut: svgToUri(` + + + + + + `), + share: svgToUri(` diff --git a/pwuniapp/pages.json b/pwuniapp/pages.json index 2d1d4e7..8630f65 100644 --- a/pwuniapp/pages.json +++ b/pwuniapp/pages.json @@ -132,6 +132,26 @@ "backgroundColor": "#0A0F1D" } }, + { + "path": "pages/user/withdraw-records", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "提现审批明细", + "navigationBarBackgroundColor": "#0A0F1D", + "navigationBarTextStyle": "white", + "backgroundColor": "#0A0F1D" + } + }, + { + "path": "pages/user/settings", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "系统与隐私设置", + "navigationBarBackgroundColor": "#0A0F1D", + "navigationBarTextStyle": "white", + "backgroundColor": "#0A0F1D" + } + }, { "path": "pages/activity/create", "style": { diff --git a/pwuniapp/pages/user/index.vue b/pwuniapp/pages/user/index.vue index 76d8b60..78f2e3a 100644 --- a/pwuniapp/pages/user/index.vue +++ b/pwuniapp/pages/user/index.vue @@ -320,65 +320,6 @@ - - - - - 系统与隐私设置 - - - - - - - - 隐私安全保护 - - - 隐藏手机号与联系方式 - 开启后个人名片及组局联络中间4位自动脱敏 - - - - - - - 通知与订阅 - - - 订单与组局动态提醒 - 接收陪玩接单、服务验收与退款仲裁即时通知 - - - - - - - 本地数据与存储 - - - 清除本地缓存数据 - 当前缓存占用:{{ cacheSizeText }} - - - - - - - 关于系统与合规 - - 软件版本 - v2.6.0 正式版 - - - 服务协议与用户隐私政策 - - - - - - - @@ -602,7 +543,6 @@ const favoriteList = ref([]); const loadingFavorites = ref(false); // 系统与隐私设置 -const showSettingsModal = ref(false); const privacyHidePhone = ref(uni.getStorageSync('privacy_hide_phone') === '1'); const noticeSubscribe = ref(uni.getStorageSync('notice_subscribe') !== '0'); const cacheSizeText = ref('1.25 MB'); @@ -824,6 +764,7 @@ onShow(() => { uni.hideTabBar({ animation: false, fail: () => {} }); loadUserProfile(); loadPlatformConfigs(); + privacyHidePhone.value = uni.getStorageSync('privacy_hide_phone') === '1'; if (isLoggedIn.value) { loadFavorites(); } @@ -1190,23 +1131,11 @@ const updateCacheSize = () => { } }; +// 2. 系统与隐私设置(跳转独立设置页面) const openSettingsModal = () => { - updateCacheSize(); - showSettingsModal.value = true; -}; - -const onToggleHidePhone = (e) => { - const val = e.detail.value; - privacyHidePhone.value = val; - uni.setStorageSync('privacy_hide_phone', val ? '1' : '0'); - uni.showToast({ title: val ? '已开启手机号隐藏' : '已关闭手机号隐藏', icon: 'none' }); -}; - -const onToggleNotice = (e) => { - const val = e.detail.value; - noticeSubscribe.value = val; - uni.setStorageSync('notice_subscribe', val ? '1' : '0'); - uni.showToast({ title: val ? '已开启服务提醒' : '已关闭服务提醒', icon: 'none' }); + uni.navigateTo({ + url: '/pages/user/settings' + }); }; const clearLocalCache = () => { @@ -2610,94 +2539,6 @@ const navTo = (url) => { font-weight: 600; } -// 2. 系统设置弹窗样式 -.settings-modal-box { - max-width: 660rpx; - - .settings-modal-body { - padding: 10rpx 0 24rpx; - - .settings-group { - margin-bottom: 28rpx; - - .settings-group-title { - font-size: 22rpx; - color: #94A3B8; - font-weight: 600; - margin-bottom: 14rpx; - display: block; - } - - .settings-row { - display: flex; - justify-content: space-between; - align-items: center; - background: #0F172A; - border: 1px solid rgba(255, 255, 255, 0.06); - border-radius: 16rpx; - padding: 20rpx; - margin-bottom: 12rpx; - - .settings-label-wrap { - flex: 1; - - .settings-label { - font-size: 26rpx; - color: #F8FAFC; - font-weight: 500; - display: block; - margin-bottom: 4rpx; - } - - .settings-desc { - font-size: 20rpx; - color: #64748B; - display: block; - } - } - - .btn-clear-cache { - font-size: 22rpx; - color: #EF4444; - background: rgba(239, 68, 68, 0.12); - border: 1px solid rgba(239, 68, 68, 0.3); - border-radius: 12rpx; - height: 56rpx; - line-height: 54rpx; - padding: 0 20rpx; - margin: 0; - } - } - - .settings-info-row { - display: flex; - justify-content: space-between; - align-items: center; - background: #0F172A; - border: 1px solid rgba(255, 255, 255, 0.06); - border-radius: 16rpx; - padding: 20rpx; - margin-bottom: 12rpx; - - .info-k { - font-size: 26rpx; - color: #F8FAFC; - } - - .info-v { - font-size: 22rpx; - color: #94A3B8; - } - - .info-arrow { - width: 28rpx; - height: 28rpx; - } - } - } - } -} - // 3. 分销管理弹窗样式 .dist-modal-box { max-width: 680rpx; @@ -3165,17 +3006,6 @@ const navTo = (url) => { } } - .settings-modal-box { - .settings-modal-body .settings-group { - .settings-row, .settings-info-row { - background: #FAFAF9; - border-color: #E7E5E4; - .settings-label-wrap .settings-label, .info-k { - color: #1C1917; - } - } - } - } .dist-modal-box { .dist-summary-banner { diff --git a/pwuniapp/pages/user/settings.vue b/pwuniapp/pages/user/settings.vue new file mode 100644 index 0000000..b41cec2 --- /dev/null +++ b/pwuniapp/pages/user/settings.vue @@ -0,0 +1,770 @@ + + + + + diff --git a/pwuniapp/pages/user/withdraw-records.vue b/pwuniapp/pages/user/withdraw-records.vue new file mode 100644 index 0000000..37b149f --- /dev/null +++ b/pwuniapp/pages/user/withdraw-records.vue @@ -0,0 +1,1009 @@ + + + + + diff --git a/pwuniapp/pages/user/withdraw.vue b/pwuniapp/pages/user/withdraw.vue index 9ba03f4..00cfca2 100644 --- a/pwuniapp/pages/user/withdraw.vue +++ b/pwuniapp/pages/user/withdraw.vue @@ -166,49 +166,6 @@ {{ isSubmitting ? '正在提交申请...' : '确认申请提现' }} - - - - - - 提现审批记录 ({{ withdrawalsList.length }}) - - - - - - - - - {{ rec.withdrawNo }} - - {{ rec.status }} - - - - ¥{{ rec.amount }} - {{ rec.channel }} - - - {{ rec.applyTime }} - 驳回理由:{{ rec.reason }} - - - - - - 暂无提现申请记录 - - - @@ -347,7 +304,9 @@ const loadPageData = async () => { }; const openRecordsDrawer = () => { - showRecordsDrawer.value = true; + uni.navigateTo({ + url: '/pages/user/withdraw-records' + }); }; const handleSubmitWithdraw = async () => { @@ -399,7 +358,9 @@ const handleSubmitWithdraw = async () => { success: (mRes) => { loadPageData(); if (mRes.confirm) { - showRecordsDrawer.value = true; + uni.navigateTo({ + url: '/pages/user/withdraw-records' + }); } } }); diff --git a/server/tests/client-features.spec.ts b/server/tests/client-features.spec.ts index 117cf9a..5f1510f 100644 --- a/server/tests/client-features.spec.ts +++ b/server/tests/client-features.spec.ts @@ -172,16 +172,31 @@ describe('ClientFeatures (TDD 测试套件: 用户端功能闭环)', () => { }); describe('6. 系统与隐私设置闭环验证', () => { - it('个人中心页面必须包含手机号脱敏计算、服务通知与清理缓存能力', () => { + it('个人中心与独立设置页面必须实现手机号脱敏计算、服务通知、清理缓存与版本合规', () => { + // 个人中心验证:包含脱敏计算与跳转独立设置页 const userVuePath = path.join(uniPagesDir, 'user', 'index.vue'); - const content = fs.readFileSync(userVuePath, 'utf-8'); + const userContent = fs.readFileSync(userVuePath, 'utf-8'); - expect(content).toContain('openSettingsModal'); - expect(content).toContain('privacyHidePhone'); - expect(content).toContain('displayPhone'); - expect(content).toContain('clearLocalCache'); - expect(content).toContain('cacheSizeText'); - expect(content).toContain('v2.6.0 正式版'); + expect(userContent).toContain('openSettingsModal'); + expect(userContent).toContain('privacyHidePhone'); + expect(userContent).toContain('displayPhone'); + expect(userContent).toContain('clearLocalCache'); + expect(userContent).toContain('cacheSizeText'); + expect(userContent).toContain('/pages/user/settings'); + + // 独立系统与隐私设置页面规格验证 + const settingsVuePath = path.join(uniPagesDir, 'user', 'settings.vue'); + expect(fs.existsSync(settingsVuePath)).toBe(true); + const settingsContent = fs.readFileSync(settingsVuePath, 'utf-8'); + + expect(settingsContent).toContain('privacyHidePhone'); + expect(settingsContent).toContain('onToggleHidePhone'); + expect(settingsContent).toContain('noticeSubscribe'); + expect(settingsContent).toContain('onToggleNotice'); + expect(settingsContent).toContain('clearLocalCache'); + expect(settingsContent).toContain('cacheSizeText'); + expect(settingsContent).toContain('v2.6.0 正式版'); + expect(settingsContent).toContain('goToProtocol'); }); }); diff --git a/server/tests/content-security.spec.ts b/server/tests/content-security.spec.ts index 0aa2284..2fcfed4 100644 --- a/server/tests/content-security.spec.ts +++ b/server/tests/content-security.spec.ts @@ -130,7 +130,7 @@ describe('ContentSecurityService & Compliance Architecture (TDD 微信内容安 const raw = fs.readFileSync(pagesJsonPath, 'utf-8'); const config = JSON.parse(raw); expect(Array.isArray(config.pages)).toBe(true); - expect(config.pages.length).toBe(18); + expect(config.pages.length).toBe(20); for (const pageItem of config.pages) { const vueFilePath = path.join(rootDir, 'pwuniapp', `${pageItem.path}.vue`); @@ -719,6 +719,45 @@ describe('ContentSecurityService & Compliance Architecture (TDD 微信内容安 } }); }); + + describe('16. 独立专属提现审批明细与记录页面验证 (pages/user/withdraw-records.vue)', () => { + it('pages.json 必须成功注册 pages/user/withdraw-records 且物理文件必须存在', () => { + const recordsPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'withdraw-records.vue'); + expect(fs.existsSync(recordsPath)).toBe(true); + const pagesJsonPath = path.join(rootDir, 'pwuniapp', 'pages.json'); + const pagesJson = fs.readFileSync(pagesJsonPath, 'utf-8'); + expect(pagesJson).toContain('pages/user/withdraw-records'); + expect(pagesJson).toContain('提现审批明细'); + }); + + it('独立提现记录页面必须支持状态选项卡筛选、总览统计与数据拉取', () => { + const recordsPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'withdraw-records.vue'); + const content = fs.readFileSync(recordsPath, 'utf-8'); + expect(content).toContain('tabList'); + expect(content).toContain('filteredRecords'); + expect(content).toContain('getUserWithdrawals'); + expect(content).toContain('goToWithdraw'); + }); + + it('提现页面必须实现对提现记录独立页面的原生导航跳转', () => { + const wdPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'withdraw.vue'); + const content = fs.readFileSync(wdPath, 'utf-8'); + expect(content).toContain('/pages/user/withdraw-records'); + }); + + it('提现记录页面代码严禁包含任何系统 Emoji 与 showModal 4 字门禁违规', () => { + const recordsPath = path.join(rootDir, 'pwuniapp', 'pages', 'user', 'withdraw-records.vue'); + const content = fs.readFileSync(recordsPath, 'utf-8'); + const emojiRegex = /(?:\p{Extended_Pictographic}|\p{Emoji_Presentation}|[\u2600-\u27BF])/u; + expect(emojiRegex.test(content)).toBe(false); + + const modalMatches = content.matchAll(/(?:confirmText|cancelText):\s*['"]([^'"]+)['"]/g); + for (const match of modalMatches) { + const btnText = match[1]; + expect(btnText.length).toBeLessThanOrEqual(4); + } + }); + }); });