From 69c66046b2642d67298b1f3a9b6b0f6ce266a6d6 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Mon, 27 Apr 2026 14:49:00 +0800 Subject: [PATCH] f --- src/apis/agent.js | 24 +++ src/auto-imports.d.ts | 4 + src/components.d.ts | 1 + src/components/PriceInputPopup.vue | 40 +--- src/pages.json | 18 +- src/pages/agent.vue | 32 +++- src/pages/agentVipApply.vue | 6 - src/pages/login.vue | 2 +- src/pages/me.vue | 31 ++- src/pages/promote.vue | 43 +---- src/pages/promoteDetails.vue | 66 ++++++- src/pages/rewardsDetails.vue | 2 +- src/pages/subordinateDetail.vue | 296 +++++++++++++++++++++++++++++ src/pages/subordinateList.vue | 215 +++++++++++++++++++++ src/uni-pages.d.ts | 2 + src/utils/promotionPricing.js | 46 +++++ src/utils/request.js | 24 ++- src/utils/routerGuard.js | 53 +++--- 18 files changed, 777 insertions(+), 128 deletions(-) create mode 100644 src/pages/subordinateDetail.vue create mode 100644 src/pages/subordinateList.vue create mode 100644 src/utils/promotionPricing.js diff --git a/src/apis/agent.js b/src/apis/agent.js index 9a6d21f..6b5f639 100644 --- a/src/apis/agent.js +++ b/src/apis/agent.js @@ -35,6 +35,30 @@ export const getAgentRewards = (params) => { }) } +/** + * 获取我的下级列表 + * @param {Object} params 查询参数 {page, page_size} + */ +export const getAgentSubordinateList = (params) => { + return request({ + url: '/agent/subordinate/list', + method: 'GET', + params + }) +} + +/** + * 获取下级贡献详情 + * @param {Object} params 查询参数 {subordinate_id, page, page_size} + */ +export const getAgentSubordinateContributionDetail = (params) => { + return request({ + url: '/agent/subordinate/contribution/detail', + method: 'GET', + params + }) +} + /** * 获取代理状态 */ diff --git a/src/auto-imports.d.ts b/src/auto-imports.d.ts index c71474a..0812c8a 100644 --- a/src/auto-imports.d.ts +++ b/src/auto-imports.d.ts @@ -13,6 +13,7 @@ declare global { const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] const buildPromotionH5Url: typeof import('./utils/promotionH5Url.js')['buildPromotionH5Url'] + 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 computed: typeof import('vue')['computed'] @@ -134,6 +135,7 @@ declare global { const resolveComponent: typeof import('vue')['resolveComponent'] const resolveRef: typeof import('@vueuse/core')['resolveRef'] const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] + const safeTruncate: typeof import('./utils/promotionPricing.js')['safeTruncate'] const setMiniPromotionShareFriend: typeof import('./utils/miniPromotionSharePayload.js')['setMiniPromotionShareFriend'] const setupRouterGuard: typeof import('./utils/routerGuard.js')['setupRouterGuard'] const shallowReactive: typeof import('vue')['shallowReactive'] @@ -358,6 +360,7 @@ declare module 'vue' { readonly asyncComputed: UnwrapRef readonly autoResetRef: UnwrapRef readonly buildPromotionH5Url: UnwrapRef + readonly calculatePromotionPricing: UnwrapRef readonly chatCrypto: UnwrapRef readonly chatEncrypt: UnwrapRef readonly computed: UnwrapRef @@ -479,6 +482,7 @@ declare module 'vue' { readonly resolveComponent: UnwrapRef readonly resolveRef: UnwrapRef readonly resolveUnref: UnwrapRef + readonly safeTruncate: UnwrapRef readonly setMiniPromotionShareFriend: UnwrapRef readonly setupRouterGuard: UnwrapRef readonly shallowReactive: UnwrapRef diff --git a/src/components.d.ts b/src/components.d.ts index c8a81f1..e580c1b 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -24,6 +24,7 @@ declare module 'vue' { 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'] WdNavbar: typeof import('wot-design-uni/components/wd-navbar/wd-navbar.vue')['default'] + WdPagination: typeof import('wot-design-uni/components/wd-pagination/wd-pagination.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'] diff --git a/src/components/PriceInputPopup.vue b/src/components/PriceInputPopup.vue index 55b6fa0..116ee4f 100644 --- a/src/components/PriceInputPopup.vue +++ b/src/components/PriceInputPopup.vue @@ -11,8 +11,7 @@
+ :placeholder="priceRangePlaceholder" @blur="onBlurPrice" custom-class="wd-input" />
推广收益为 {{ promotionRevenue }}
@@ -40,6 +39,7 @@ + + + + + + +{ + "layout": "page", + "title": "下级贡献详情", + "agent": true, + "auth": true +} + diff --git a/src/pages/subordinateList.vue b/src/pages/subordinateList.vue new file mode 100644 index 0000000..37bbd27 --- /dev/null +++ b/src/pages/subordinateList.vue @@ -0,0 +1,215 @@ + + + + + + + +{ + "layout": "page", + "title": "我的下级", + "agent": true, + "auth": true +} + diff --git a/src/uni-pages.d.ts b/src/uni-pages.d.ts index 0844c8d..aabab2d 100644 --- a/src/uni-pages.d.ts +++ b/src/uni-pages.d.ts @@ -18,6 +18,8 @@ interface NavigateToOptions { "/pages/promote" | "/pages/promoteDetails" | "/pages/rewardsDetails" | + "/pages/subordinateDetail" | + "/pages/subordinateList" | "/pages/withdrawDetails"; } interface RedirectToOptions extends NavigateToOptions {} diff --git a/src/utils/promotionPricing.js b/src/utils/promotionPricing.js new file mode 100644 index 0000000..523ada8 --- /dev/null +++ b/src/utils/promotionPricing.js @@ -0,0 +1,46 @@ +export function safeTruncate(num, decimals = 2) { + if (Number.isNaN(num) || !Number.isFinite(num)) + return '0.00' + + const factor = 10 ** decimals + const scaled = Math.trunc(num * factor) + return (scaled / factor).toFixed(decimals) +} + +function calculatePlatformOverpricingCost(price, config) { + if (price <= config.p_pricing_standard) + return 0 + return (price - config.p_pricing_standard) * config.p_overpricing_ratio +} + +function calculateSuperiorOverpricingCost(price, config) { + if (config.a_overpricing_ratio <= 0) + return 0 + if (price <= config.a_pricing_standard) + return 0 + if (config.a_pricing_end <= config.a_pricing_standard) + return 0 + + const superiorRangeAmount = Math.min(price, config.a_pricing_end) - config.a_pricing_standard + return Math.max(0, superiorRangeAmount) * config.a_overpricing_ratio +} + +export function calculatePromotionPricing(priceInput, config) { + if (!config) + return { costPrice: '0.00', promotionRevenue: '0.00' } + + const price = Number(priceInput) + if (!Number.isFinite(price)) + return { costPrice: '0.00', promotionRevenue: '0.00' } + + const baseCost = Number(config.cost_price) || 0 + const platformOverpricingCost = calculatePlatformOverpricingCost(price, config) + const superiorOverpricingCost = calculateSuperiorOverpricingCost(price, config) + const totalCost = baseCost + platformOverpricingCost + superiorOverpricingCost + const revenue = price - totalCost + + return { + costPrice: safeTruncate(totalCost), + promotionRevenue: safeTruncate(revenue), + } +} diff --git a/src/utils/request.js b/src/utils/request.js index 12073d1..3d380bb 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -9,6 +9,8 @@ const BASE_URL = getApiPrefix() const BASE_URL = getApiBaseUrl() // #endif const TEMP_USER_INVALID_CODE = 100012 +const USER_DISABLED_CODE = 100011 +const USER_CANCELLED_CODE = 100013 let wxMiniReauthPromise = null const clearAuthData = () => { @@ -19,6 +21,13 @@ const clearAuthData = () => { uni.removeStorageSync('agentInfo') } +const forceLogoutToLogin = () => { + clearAuthData() + uni.reLaunch({ + url: '/pages/login', + }) +} + const silentWxMiniReAuth = () => { if (wxMiniReauthPromise) return wxMiniReauthPromise @@ -90,6 +99,11 @@ function request(options) { success: (res) => { // 响应拦截器逻辑 if (res.statusCode === 200) { + if (res.data?.code === USER_DISABLED_CODE || res.data?.code === USER_CANCELLED_CODE) { + forceLogoutToLogin() + reject(res.data) + return + } if (res.data?.code === TEMP_USER_INVALID_CODE) { if (!options.__retriedAfterReauth) { silentWxMiniReAuth() @@ -111,10 +125,12 @@ function request(options) { resolve(res.data) } else if (res.statusCode === 401) { - uni.removeStorageSync('token') - uni.redirectTo({ - url: '/pages/login', - }) + forceLogoutToLogin() + reject(res.data) + } + else if (res.statusCode === 403) { + forceLogoutToLogin() + reject(res.data) } else { uni.showToast({ title: res.data.msg || '请求失败', icon: 'none' }) diff --git a/src/utils/routerGuard.js b/src/utils/routerGuard.js index d0e10dc..42d2821 100644 --- a/src/utils/routerGuard.js +++ b/src/utils/routerGuard.js @@ -1,55 +1,60 @@ -import pagesJson from '@/pages.json' -const pagesConfig = pagesJson.pages +import pagesJson from "@/pages.json"; +const pagesConfig = pagesJson.pages; // 检查登录状态 function checkIsLoggedIn() { - return !!uni.getStorageSync('token') + return !!uni.getStorageSync("token"); } // 检查是否是代理 function checkIsAgent() { - const agentInfo = uni.getStorageSync('agentInfo') - return agentInfo?.isAgent + const agentInfo = uni.getStorageSync("agentInfo"); + return agentInfo?.isAgent; } function checkBindMobile() { - const userInfo = uni.getStorageSync('userInfo') - return userInfo?.mobile.length > 0 + const userInfo = uni.getStorageSync("userInfo"); + return userInfo?.mobile.length > 0; } // 添加路由拦截器 function setupRouterGuard() { - const methods = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'] + const methods = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]; - methods.forEach(method => { + methods.forEach((method) => { uni.addInterceptor(method, { invoke(e) { - const url = e.url.split('?')[0] - const currentPageConfig = pagesConfig.find(page => '/' +page.path === url) // 根据路径查找 pages.json 中的配置 + const url = e.url.split("?")[0]; + const currentPageConfig = pagesConfig.find( + (page) => "/" + page.path === url, + ); // 根据路径查找 pages.json 中的配置 // 检查是否需要登录 - if (currentPageConfig?.auth && (!checkIsLoggedIn() || !checkBindMobile())) { + if ( + currentPageConfig?.auth && + (!checkIsLoggedIn() || !checkBindMobile()) + ) { // 跳转到登录页 uni.redirectTo({ - url: '/pages/login' - }) + url: "/pages/login", + }); - return false + return false; } // 检查是否需要代理身份 if (currentPageConfig?.agent && !checkIsAgent()) { uni.navigateTo({ - url: '/pages/invitationAgentApply' - }) + url: "/pages/invitationAgentApply", + }); - return false + return false; } - return true + return true; }, fail() { - return false - } - }) - }) + return false; + }, + }); + }); } -export { setupRouterGuard } +export { setupRouterGuard };