From 89207dcf811dd9167c6794bfa4b18e3b5df318bb Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Fri, 17 Jul 2026 15:58:25 +0800 Subject: [PATCH] f --- pages.config.ts | 4 +- src/auto-imports.d.ts | 23 ++-- src/components.d.ts | 16 +++ src/composables/useAppReviewPresentation.ts | 94 +++++++++++++ src/composables/useNavigationAuthGuard.ts | 14 ++ src/layouts/home.vue | 2 +- src/pages/agent-rewards-details.vue | 9 +- src/pages/agent-vip-config.vue | 5 + src/pages/agent.vue | 5 +- src/pages/help-detail.vue | 7 +- src/pages/help-guide.vue | 6 + src/pages/help.vue | 138 +++++--------------- src/pages/index.vue | 48 +++---- src/pages/me.vue | 10 +- src/pages/subordinate-detail.vue | 5 + src/pages/subordinate-list.vue | 5 + 16 files changed, 227 insertions(+), 164 deletions(-) create mode 100644 src/composables/useAppReviewPresentation.ts diff --git a/pages.config.ts b/pages.config.ts index d952ec2..27bcd3e 100644 --- a/pages.config.ts +++ b/pages.config.ts @@ -6,7 +6,7 @@ export default defineUniPages({ { path: 'pages/privacy-consent', style: { navigationStyle: 'custom', navigationBarTitleText: '隐私政策授权' } }, { path: 'pages/launch', style: { navigationStyle: 'custom', navigationBarTitleText: '' } }, { path: 'pages/index', style: { navigationBarTitleText: '首页' } }, - { path: 'pages/agent', style: { navigationBarTitleText: '代理中心' } }, + { path: 'pages/agent', style: { navigationBarTitleText: '推广收益' } }, { path: 'pages/agent-manage-agreement', style: { navigationBarTitleText: '代理管理协议', navigationStyle: 'default' } }, { path: 'pages/agent-promote-details', auth: true, style: { navigationBarTitleText: '收益明细' } }, { path: 'pages/agent-rewards-details', auth: true, style: { navigationBarTitleText: '奖励明细' } }, @@ -17,7 +17,7 @@ export default defineUniPages({ { path: 'pages/help', style: { navigationBarTitleText: '帮助中心' } }, { path: 'pages/help-detail', style: { navigationBarTitleText: '帮助详情' } }, { path: 'pages/help-guide', style: { navigationBarTitleText: '引导指南' } }, - { path: 'pages/invitation', auth: true, style: { navigationBarTitleText: '邀请下级' } }, + { path: 'pages/invitation', auth: true, style: { navigationBarTitleText: '邀请好友' } }, { path: 'pages/invitation-agent-apply', auth: true, style: { navigationBarTitleText: '代理申请' } }, { path: 'pages/login', style: { navigationBarTitleText: '登录' } }, { path: 'pages/me', style: { navigationBarTitleText: '我的' } }, diff --git a/src/auto-imports.d.ts b/src/auto-imports.d.ts index 0cd723e..89f9e5d 100644 --- a/src/auto-imports.d.ts +++ b/src/auto-imports.d.ts @@ -7,7 +7,6 @@ export {} declare global { const EffectScope: typeof import('vue')['EffectScope'] - const ZoomAdapter: typeof import('./utils/zoomAdapter.js')['ZoomAdapter'] const aesDecrypt: typeof import('./utils/crypto.js')['aesDecrypt'] const aesEncrypt: typeof import('./utils/crypto.js')['aesEncrypt'] const appendAppAuthQueryParams: typeof import('./composables/useReportWebview')['appendAppAuthQueryParams'] @@ -15,8 +14,6 @@ declare global { const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] const buildAgentVipApplyH5Url: typeof import('./composables/useAgentVipH5')['buildAgentVipApplyH5Url'] const calculatePromotionPricing: typeof import('./utils/promotionPricing.js')['calculatePromotionPricing'] - const chatCrypto: typeof import('./utils/chatCrypto.js')['default'] - const chatEncrypt: typeof import('./utils/chatEncrypt.js')['default'] const clearAuthStorage: typeof import('./utils/storage')['clearAuthStorage'] const clearToken: typeof import('./utils/storage')['clearToken'] const computed: typeof import('vue')['computed'] @@ -44,6 +41,7 @@ declare global { const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] const effectScope: typeof import('vue')['effectScope'] const ensureCurrentPageAccess: typeof import('./composables/useNavigationAuthGuard')['ensureCurrentPageAccess'] + const ensureCurrentPageAppReviewAllowed: typeof import('./composables/useAppReviewPresentation')['ensureCurrentPageAppReviewAllowed'] const ensurePageAccessByUrl: typeof import('./composables/useNavigationAuthGuard')['ensurePageAccessByUrl'] const ensurePrivacyConsentIfNeeded: typeof import('./composables/usePrivacyConsent')['ensurePrivacyConsentIfNeeded'] const extendRef: typeof import('@vueuse/core')['extendRef'] @@ -128,6 +126,7 @@ declare global { const openAgentVipApplyInExternalBrowser: typeof import('./composables/useAgentVipH5')['openAgentVipApplyInExternalBrowser'] const openCustomerService: typeof import('./composables/useCustomerService')['openCustomerService'] const openExternalUrl: typeof import('./composables/openExternalUrl')['openExternalUrl'] + const parseQueryFromUrl: typeof import('./composables/useAppReviewPresentation')['parseQueryFromUrl'] const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] const provide: typeof import('vue')['provide'] const provideLocal: typeof import('@vueuse/core')['provideLocal'] @@ -139,6 +138,7 @@ declare global { const reactivePick: typeof import('@vueuse/core')['reactivePick'] const readLocalFileAsBase64: typeof import('./utils/appLocalFile')['readLocalFileAsBase64'] const readonly: typeof import('vue')['readonly'] + const redirectIfAppReviewRouteBlocked: typeof import('./composables/useAppReviewPresentation')['redirectIfAppReviewRouteBlocked'] const ref: typeof import('vue')['ref'] const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] const refDebounced: typeof import('@vueuse/core')['refDebounced'] @@ -161,6 +161,8 @@ declare global { const shallowReactive: typeof import('vue')['shallowReactive'] const shallowReadonly: typeof import('vue')['shallowReadonly'] const shallowRef: typeof import('vue')['shallowRef'] + const shouldBlockAppReviewRoute: typeof import('./composables/useAppReviewPresentation')['shouldBlockAppReviewRoute'] + const shouldHideDownlineMlmUi: typeof import('./composables/useAppReviewPresentation')['shouldHideDownlineMlmUi'] const shouldSilencePrivacyBlockedRequest: typeof import('./composables/usePrivacyConsent')['shouldSilencePrivacyBlockedRequest'] const syncRef: typeof import('@vueuse/core')['syncRef'] const syncRefs: typeof import('@vueuse/core')['syncRefs'] @@ -202,7 +204,6 @@ declare global { const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] const useAttrs: typeof import('vue')['useAttrs'] - const useAuthGuard: typeof import('./composables/useAuthGuard')['useAuthGuard'] const useAuthStore: typeof import('./stores/auth')['useAuthStore'] const useBase64: typeof import('@vueuse/core')['useBase64'] const useBattery: typeof import('@vueuse/core')['useBattery'] @@ -216,7 +217,6 @@ declare global { const useCloned: typeof import('@vueuse/core')['useCloned'] const useColorMode: typeof import('@vueuse/core')['useColorMode'] const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] - const useCount: typeof import('./composables/useCount')['useCount'] const useCountdown: typeof import('@vueuse/core')['useCountdown'] const useCounter: typeof import('@vueuse/core')['useCounter'] const useCssModule: typeof import('vue')['useCssModule'] @@ -243,7 +243,6 @@ declare global { const useElementHover: typeof import('@vueuse/core')['useElementHover'] const useElementSize: typeof import('@vueuse/core')['useElementSize'] const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] - const useEnv: typeof import('./composables/useEnv.js')['useEnv'] const useEventBus: typeof import('@vueuse/core')['useEventBus'] const useEventListener: typeof import('@vueuse/core')['useEventListener'] const useEventSource: typeof import('@vueuse/core')['useEventSource'] @@ -260,7 +259,6 @@ declare global { const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] const useGlobalNotification: typeof import('./composables/useGlobalNotification.js')['useGlobalNotification'] const useHotUpdate: typeof import('./composables/useHotUpdate')['useHotUpdate'] - const useHttp: typeof import('./composables/useHttp.js')['useHttp'] const useId: typeof import('vue')['useId'] const useIdle: typeof import('@vueuse/core')['useIdle'] const useImage: typeof import('@vueuse/core')['useImage'] @@ -304,12 +302,10 @@ declare global { const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] const usePreferredReducedTransparency: typeof import('@vueuse/core')['usePreferredReducedTransparency'] const usePrevious: typeof import('@vueuse/core')['usePrevious'] - const useQuery: typeof import('./composables/useQuery')['useQuery'] const useRafFn: typeof import('@vueuse/core')['useRafFn'] const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] const useReportWebview: typeof import('./composables/useReportWebview')['useReportWebview'] const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] - const useRiskNotifier: typeof import('./composables/useRiskNotifier.js')['useRiskNotifier'] const useRoute: typeof import('./composables/uni-router')['useRoute'] const useRouter: typeof import('./composables/uni-router')['useRouter'] const useSEO: typeof import('./composables/useSEO.js')['useSEO'] @@ -360,14 +356,11 @@ declare global { const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] - const useWebView: typeof import('./composables/useWebView.js')['useWebView'] const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] - const useWeixinShare: typeof import('./composables/useWeixinShare.js')['useWeixinShare'] const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] - const useZoomAdapter: typeof import('./composables/useZoomAdapter.js')['useZoomAdapter'] const watch: typeof import('vue')['watch'] const watchArray: typeof import('@vueuse/core')['watchArray'] const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] @@ -385,7 +378,6 @@ declare global { const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] const whenever: typeof import('@vueuse/core')['whenever'] const writePngBase64ToLocal: typeof import('./utils/appLocalFile')['writePngBase64ToLocal'] - const zoomAdapter: typeof import('./utils/zoomAdapter.js')['default'] } // for type re-export declare global { @@ -446,6 +438,7 @@ declare module 'vue' { readonly eagerComputed: UnwrapRef readonly effectScope: UnwrapRef readonly ensureCurrentPageAccess: UnwrapRef + readonly ensureCurrentPageAppReviewAllowed: UnwrapRef readonly ensurePageAccessByUrl: UnwrapRef readonly ensurePrivacyConsentIfNeeded: UnwrapRef readonly extendRef: UnwrapRef @@ -530,6 +523,7 @@ declare module 'vue' { readonly openAgentVipApplyInExternalBrowser: UnwrapRef readonly openCustomerService: UnwrapRef readonly openExternalUrl: UnwrapRef + readonly parseQueryFromUrl: UnwrapRef readonly pausableWatch: UnwrapRef readonly provide: UnwrapRef readonly provideLocal: UnwrapRef @@ -541,6 +535,7 @@ declare module 'vue' { readonly reactivePick: UnwrapRef readonly readLocalFileAsBase64: UnwrapRef readonly readonly: UnwrapRef + readonly redirectIfAppReviewRouteBlocked: UnwrapRef readonly ref: UnwrapRef readonly refAutoReset: UnwrapRef readonly refDebounced: UnwrapRef @@ -563,6 +558,8 @@ declare module 'vue' { readonly shallowReactive: UnwrapRef readonly shallowReadonly: UnwrapRef readonly shallowRef: UnwrapRef + readonly shouldBlockAppReviewRoute: UnwrapRef + readonly shouldHideDownlineMlmUi: UnwrapRef readonly shouldSilencePrivacyBlockedRequest: UnwrapRef readonly syncRef: UnwrapRef readonly syncRefs: UnwrapRef diff --git a/src/components.d.ts b/src/components.d.ts index 0ec5470..75ed9d2 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -19,5 +19,21 @@ declare module 'vue' { RealNameAuthDialog: typeof import('./components/RealNameAuthDialog.vue')['default'] SectionTitle: typeof import('./components/SectionTitle.vue')['default'] VipBanner: typeof import('./components/VipBanner.vue')['default'] + WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default'] + WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default'] + WdCellGroup: typeof import('wot-design-uni/components/wd-cell-group/wd-cell-group.vue')['default'] + WdCheckbox: typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue')['default'] + WdColPicker: typeof import('wot-design-uni/components/wd-col-picker/wd-col-picker.vue')['default'] + WdDivider: typeof import('wot-design-uni/components/wd-divider/wd-divider.vue')['default'] + WdForm: typeof import('wot-design-uni/components/wd-form/wd-form.vue')['default'] + WdFormItem: typeof import('wot-design-uni/components/wd-form-item/wd-form-item.vue')['default'] + WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default'] + WdInput: typeof import('wot-design-uni/components/wd-input/wd-input.vue')['default'] + WdLoadmore: typeof import('wot-design-uni/components/wd-loadmore/wd-loadmore.vue')['default'] + WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default'] + WdPicker: typeof import('wot-design-uni/components/wd-picker/wd-picker.vue')['default'] + WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default'] + WdTabbar: typeof import('wot-design-uni/components/wd-tabbar/wd-tabbar.vue')['default'] + WdTabbarItem: typeof import('wot-design-uni/components/wd-tabbar-item/wd-tabbar-item.vue')['default'] } } diff --git a/src/composables/useAppReviewPresentation.ts b/src/composables/useAppReviewPresentation.ts new file mode 100644 index 0000000..032a311 --- /dev/null +++ b/src/composables/useAppReviewPresentation.ts @@ -0,0 +1,94 @@ +/** + * App Store 展示策略:保留「邀请好友」,不在 App 内呈现「下级 / 团队 / 层级返利」相关能力。 + * 后端逻辑不变,仅影响 bdrp-app 前端入口与文案。 + */ + +const BLOCKED_PAGE_ROUTES = new Set([ + 'pages/subordinate-list', + 'pages/subordinate-detail', + 'pages/agent-rewards-details', + 'pages/agent-vip-config', + 'pages/agent-vip', +]) + +const BLOCKED_HELP_DETAIL_IDS = new Set([ + 'invite_earnings', + 'vip_guide', + 'direct_earnings', +]) + +const BLOCKED_HELP_GUIDE_IDS = new Set([ + // 邀请好友引导保留展示 +]) + +let cachedHideDownline: boolean | null = null + +/** 是否在 App 内隐藏下级/团队返利相关 UI(当前 App 以 iOS 上架为主) */ +export function shouldHideDownlineMlmUi(): boolean { + if (cachedHideDownline !== null) + return cachedHideDownline + try { + const sys = uni.getSystemInfoSync() + cachedHideDownline = sys.uniPlatform === 'app' || sys.platform === 'ios' + } + catch { + cachedHideDownline = true + } + return cachedHideDownline +} + +export function shouldBlockAppReviewRoute(route: string, query: Record = {}): boolean { + if (!shouldHideDownlineMlmUi()) + return false + const normalized = route.replace(/^\//, '').split('?')[0] + if (BLOCKED_PAGE_ROUTES.has(normalized)) + return true + const helpId = String(query.id || query.ID || '').trim() + if (normalized === 'pages/help-detail' && BLOCKED_HELP_DETAIL_IDS.has(helpId)) + return true + if (normalized === 'pages/help-guide' && BLOCKED_HELP_GUIDE_IDS.has(helpId)) + return true + return false +} + +export function parseQueryFromUrl(url = ''): Record { + const qIndex = url.indexOf('?') + if (qIndex === -1) + return {} + const query: Record = {} + const search = url.slice(qIndex + 1) + for (const part of search.split('&')) { + if (!part) + continue + const eq = part.indexOf('=') + const key = eq === -1 ? part : part.slice(0, eq) + const value = eq === -1 ? '' : part.slice(eq + 1) + if (key) + query[decodeURIComponent(key)] = decodeURIComponent(value) + } + return query +} + +const HOME_URL = '/pages/index' + +export function redirectIfAppReviewRouteBlocked(route: string, query: Record = {}) { + if (!shouldBlockAppReviewRoute(route, query)) + return false + uni.redirectTo({ url: HOME_URL }) + return true +} + +/** 当前页若为审核屏蔽页则跳回首页 */ +export function ensureCurrentPageAppReviewAllowed(): boolean { + const stack = getCurrentPages() + const page = stack[stack.length - 1] as { route?: string, options?: Record } + if (!page?.route) + return true + const route = page.route.replace(/^\//, '') + const query = page.options || {} + if (shouldBlockAppReviewRoute(route, query)) { + uni.redirectTo({ url: HOME_URL }) + return false + } + return true +} diff --git a/src/composables/useNavigationAuthGuard.ts b/src/composables/useNavigationAuthGuard.ts index abfeabe..f2f862b 100644 --- a/src/composables/useNavigationAuthGuard.ts +++ b/src/composables/useNavigationAuthGuard.ts @@ -1,4 +1,5 @@ import { pages } from 'virtual:uni-pages' +import { parseQueryFromUrl, shouldBlockAppReviewRoute } from '@/composables/useAppReviewPresentation' import { useAgentStore } from '@/stores/agentStore' import { getAgentInfo, getToken } from '@/utils/storage' @@ -85,11 +86,24 @@ function goAgentApply(mode: GuardMode) { uni.navigateTo({ url: AGENT_APPLY_URL }) } +function blockAppReviewRoute(mode: GuardMode) { + if (mode === 'redirect') + uni.redirectTo({ url: HOME_URL }) + else + uni.redirectTo({ url: HOME_URL }) +} + export function ensurePageAccessByUrl(url = '', mode: GuardMode = 'navigate') { const route = parseRouteFromUrl(url) if (!route || route === LOGIN_ROUTE) return false + const query = parseQueryFromUrl(url) + if (shouldBlockAppReviewRoute(route, query)) { + blockAppReviewRoute(mode) + return true + } + const permission = getPermission(route) if (!permission.requiresAuth) return false diff --git a/src/layouts/home.vue b/src/layouts/home.vue index a5713ca..cb8d343 100644 --- a/src/layouts/home.vue +++ b/src/layouts/home.vue @@ -20,7 +20,7 @@ const tabbar = ref('index') const safeAreaTop = ref(0) const menu = reactive([ { title: '首页', icon: 'home', name: 'index' }, - { title: '资产', icon: 'cart', name: 'agent' }, + { title: '收益', icon: 'cart', name: 'agent' }, { title: '我的', icon: 'user', name: 'me' }, ]) diff --git a/src/pages/agent-rewards-details.vue b/src/pages/agent-rewards-details.vue index f497691..9da642a 100644 --- a/src/pages/agent-rewards-details.vue +++ b/src/pages/agent-rewards-details.vue @@ -1,6 +1,13 @@ - - - - diff --git a/src/pages/index.vue b/src/pages/index.vue index ae5ccbb..fdc647f 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -4,7 +4,6 @@ import bannerImg2 from '/static/images/index/banner_2.png' import bannerImg3 from '/static/images/index/banner_3.png' import honestyBanner from '/static/images/index/banner_B.png' import indexPromoteIcon from '/static/images/index/tgbg.png' -import indexInvitationIcon from '/static/images/index/yqhy.png' import { ensurePrivacyConsentIfNeeded } from '@/composables/usePrivacyConsent' definePage({ layout: 'home' }) @@ -15,10 +14,6 @@ onShow(() => { const banners = [bannerImg, bannerImg2, bannerImg3] -function toInvitation() { - uni.navigateTo({ url: '/pages/invitation' }) -} - function toPromote() { uni.navigateTo({ url: '/pages/promote' }) } @@ -44,46 +39,30 @@ function toPromote() { - 即刻赚佣金 + 推广服务 - + 直推报告 - - 选择所需报告类型,灵活定价,一键分享客户,客户下单即结算,佣金实时到账 + + 选择所需报告类型,灵活定价,一键分享客户,客户下单即结算,收益实时到账 立即推广 - - - - - - - 邀请下级代理 - - - 邀请好友成为代理,好友推广获客,客户支付即返佣,团队收益轻松到手 - - - 立即邀请 - + + - - + @@ -103,10 +82,13 @@ function toPromote() { 0 1.5px 4px 0 rgba(60, 120, 255, 0.08); } -.card-gradient-2 { - background: linear-gradient(135deg, #e6f7fa 0%, #fafdff 100%); - box-shadow: - 0 6px 24px 0 rgba(0, 200, 180, 0.1), - 0 1.5px 4px 0 rgba(0, 200, 180, 0.08); +.card-icon-wrap { + max-width: 88px; +} + +.card-icon { + width: 100%; + max-width: 80px; + max-height: 80px; } diff --git a/src/pages/me.vue b/src/pages/me.vue index d04af07..eff9210 100644 --- a/src/pages/me.vue +++ b/src/pages/me.vue @@ -3,6 +3,7 @@ import { storeToRefs } from 'pinia' import { computed, onBeforeMount, ref, watch } from 'vue' import { openCustomerService } from '@/composables/useCustomerService' import { openAgentVipApplyInExternalBrowser } from '@/composables/useAgentVipH5' +import { shouldHideDownlineMlmUi } from '@/composables/useAppReviewPresentation' import { useAgentStore } from '@/stores/agentStore' import { useDialogStore } from '@/stores/dialogStore' import { useUserStore } from '@/stores/userStore' @@ -16,6 +17,7 @@ const dialogStore = useDialogStore() const { isAgent, level, ExpiryTime } = storeToRefs(agentStore) const { userAvatar, isLoggedIn, mobile } = storeToRefs(userStore) const isWeChat = ref(false) +const hideDownlineMlmUi = shouldHideDownlineMlmUi() const normalizedLevel = computed(() => { const raw = String(level.value || '').trim() @@ -242,11 +244,11 @@ onBeforeMount(() => { - + -