feat(distribution): 添加分销员状态检查与加载指示

- 在多个分销相关页面中引入分销员状态检查,确保用户在访问前具备有效分销资格。
- 增加加载指示器以改善用户体验,提示用户正在加载数据。
- 更新相关逻辑以处理分销员资格的不同状态,确保用户在不符合条件时获得适当反馈。
This commit is contained in:
田香琪
2026-09-09 13:21:53 +08:00
parent 4fdd266dec
commit c12c76f6f5
21 changed files with 419 additions and 83 deletions

View File

@@ -1,5 +1,9 @@
<template>
<view class="page" :style="themeStyle">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else>
<view class="filter-bar">
<scroll-view scroll-x class="filter-scroll" :show-scrollbar="false">
<view class="filter-tabs">
@@ -126,6 +130,7 @@
<view class="guide-btn" @click="showGuide = false">知道了</view>
</view>
</u-popup>
</template>
</view>
</template>
@@ -135,6 +140,7 @@ import { onShow, onLoad } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getDistributionPerformance } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -146,6 +152,7 @@ const rangeTabs = [
{ label: '近七日', value: 'LAST_7_DAYS' },
]
const pageReady = ref(false)
const activeRange = ref('ALL')
const loading = ref(false)
const customVisible = ref(false)
@@ -176,7 +183,13 @@ onLoad((options: Record<string, string>) => {
})
onShow(() => {
loadPerformance()
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
loadPerformance()
})
})
function formatMoney(val: number | string) {

View File

@@ -7,7 +7,7 @@
</view>
<!-- 账户列表 -->
<view v-else-if="accounts.length" class="account-list">
<view v-else-if="pageReady && accounts.length" class="account-list">
<view
class="account-item"
v-for="item in accounts"
@@ -39,12 +39,12 @@
</view>
<!-- 空状态 -->
<view v-else class="empty-wrap">
<view v-else-if="pageReady" class="empty-wrap">
<text class="empty-text">暂无银行卡请添加</text>
</view>
<!-- 添加账户按钮 -->
<view class="add-btn-wrap">
<view v-if="pageReady" class="add-btn-wrap">
<view class="add-btn" @click="openAddPopup">+ 添加账户</view>
</view>
</view>
@@ -102,6 +102,7 @@ import { onLoad, onShow } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getBankCards, addBankCard, deleteBankCard, setDefaultBankCard } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -113,7 +114,8 @@ const isSelectMode = ref(false)
const accounts = ref<any[]>([])
const selectedId = ref('')
const loading = ref(false)
const pageReady = ref(false)
const loading = ref(true)
const addPopupVisible = ref(false)
const saveLoading = ref(false)
const form = ref({ holderName: '', bankName: '', cardNo: '' })
@@ -127,7 +129,14 @@ onLoad((options: any) => {
})
onShow(() => {
loadAccounts()
loading.value = true
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
loadAccounts()
})
})
function loadAccounts() {

View File

@@ -33,6 +33,7 @@ import { onLoad, onReachBottom } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { cashLog } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -40,13 +41,18 @@ const themeStyle = computed(() => getThemeStyle(store.state.theme))
const cashList = ref<any[]>([])
const cashPage = ref(1)
const cashTotal = ref(0)
const cashLoading = ref(false)
const cashLoading = ref(true)
const cashLoadingMore = ref(false)
const cashFinished = ref(false)
const PAGE_SIZE = 15
onLoad(() => {
loadCashHistory(true)
assertActiveDistributor().then((d) => {
if (!d) {
return
}
loadCashHistory(true)
})
})
onReachBottom(() => {

View File

@@ -19,7 +19,10 @@
</view>
</view>
<template v-if="detailId">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else-if="detailId">
<view v-if="detailLoading" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
@@ -62,7 +65,7 @@
</view>
</template>
<template v-else>
<template v-else-if="pageReady">
<view class="main-tabs">
<view
v-for="item in mainTabs"
@@ -184,6 +187,7 @@ import {
updateDistributionCustomerStarred,
} from '@/api/distribution'
import { parseGoodsImageUrl } from '@/utils/filters.js'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -207,6 +211,7 @@ const rangeTabs = [
const activeFilter = ref('ALL')
const activeRange = ref('ALL')
const keyword = ref('')
const pageReady = ref(false)
const loading = ref(false)
const loadingMore = ref(false)
const finished = ref(false)
@@ -245,9 +250,15 @@ onShow(() => {
if (current?.options) {
applyRouteOptions(current.options)
}
if (!detailId.value) {
resetAndLoad()
}
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
if (!detailId.value) {
resetAndLoad()
}
})
})
onReachBottom(() => {

View File

@@ -119,7 +119,8 @@ import { onShow } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import config from '@/config/config'
import { distribution, getDistributionGrades } from '@/api/distribution'
import { getDistributionGrades } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
import { getUserInfo } from '@/api/members'
const store = useStore()
@@ -166,18 +167,21 @@ function refreshUserInfo() {
function loadPageData() {
loading.value = true
Promise.all([fetchGrades(), fetchDistribution()]).finally(() => {
loading.value = false
})
}
function fetchDistribution() {
return distribution().then((res) => {
if (!res.data?.result) {
return
}
distributionData.value = res.data.result
})
let allowed = false
assertActiveDistributor()
.then((result) => {
if (!result) {
return
}
allowed = true
distributionData.value = result
return fetchGrades()
})
.finally(() => {
if (allowed) {
loading.value = false
}
})
}
function fetchGrades() {

View File

@@ -58,6 +58,7 @@ import { onLoad, onReachBottom } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { cashLog, getDistributionOrders } from '@/api/distribution'
import { unitPrice } from '@/utils/filters.js'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
@@ -79,7 +80,12 @@ onLoad((option) => {
uni.setNavigationBarTitle({
title: type === 0 ? '分销业绩' : '提现记录',
})
type === 0 ? fetchAchievementList() : fetchWithdrawLog()
assertActiveDistributor().then((d) => {
if (!d) {
return
}
type === 0 ? fetchAchievementList() : fetchWithdrawLog()
})
})
onReachBottom(() => {

View File

@@ -10,6 +10,8 @@
<view class="nav-placeholder"></view>
</view>
<view v-if="checking" class="center-pending">加载中...</view>
<template v-else-if="centerReady">
<!-- 顶部用户信息 -->
<view class="header">
<view class="user-row" @click="goGrade">
@@ -199,6 +201,7 @@
</view>
</view>
</view>
</template>
</view>
</template>
@@ -209,7 +212,6 @@ import { useStore } from '@/store'
import config from '@/config/config'
import { getThemeStyle } from '@/utils/theme'
import {
distribution,
getDistributionFeaturedGoods,
getDistributionGrades,
getDistributionCustomers,
@@ -218,6 +220,7 @@ import {
getDistributionPerformance,
} from '@/api/distribution'
import { getUserInfo } from '@/api/members'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -226,6 +229,8 @@ const statusBarHeight = ref(20)
const expanded = ref(false)
const distributionData = ref<Record<string, any>>({})
const checking = ref(true)
const centerReady = ref(false)
const gradeList = ref<any[]>([])
const featuredGoods = ref<any[]>([])
const todayOrderCount = ref(0)
@@ -288,25 +293,38 @@ function refreshUserInfo() {
}
function loadPageData() {
Promise.all([
fetchDistribution(),
fetchGrades(),
fetchTodayOrders(),
fetchTodayEarnings(),
fetchTodayCustomers(),
fetchTodayInvites(),
fetchFeaturedGoods(),
])
checking.value = true
centerReady.value = false
distributionData.value = {}
fetchDistribution()
.then((active) => {
if (!active) {
return
}
centerReady.value = true
Promise.all([
fetchGrades(),
fetchTodayOrders(),
fetchTodayEarnings(),
fetchTodayCustomers(),
fetchTodayInvites(),
fetchFeaturedGoods(),
])
})
.finally(() => {
if (centerReady.value) {
checking.value = false
}
})
}
function fetchDistribution() {
return distribution().then((res) => {
if (!res.data?.result) {
uni.showToast({ title: '您还不是分销员', icon: 'none' })
setTimeout(() => goBack(), 1500)
return
return assertActiveDistributor().then((result) => {
if (!result) {
return false
}
distributionData.value = res.data.result
distributionData.value = result
return true
})
}
@@ -497,6 +515,13 @@ function goOrder() {
width: 72rpx;
}
.center-pending {
padding: 120rpx 0;
color: #999;
font-size: 28rpx;
text-align: center;
}
.header {
background: linear-gradient(180deg, #1f2228 0%, #2a2e36 100%);
padding: 24rpx 32rpx 40rpx;

View File

@@ -1,5 +1,9 @@
<template>
<view class="page" :style="themeStyle">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else>
<view class="hero">
<view class="hero-title">邀好友 赚奖励</view>
</view>
@@ -54,6 +58,7 @@
<view class="view-all" @click="goInviteList">查看我的邀请</view>
</view>
</template>
</view>
</template>
@@ -65,6 +70,7 @@ import config from '@/config/config'
import { getThemeStyle } from '@/utils/theme'
import { getDistributionInvitees } from '@/api/distribution'
import { parseGoodsImageUrl } from '@/utils/filters.js'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -91,12 +97,19 @@ const flowSteps = [
},
]
const pageReady = ref(false)
const loading = ref(false)
const inviteTotal = ref(0)
const inviteList = ref<any[]>([])
onShow(() => {
loadPreview()
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
loadPreview()
})
})
function loadPreview() {

View File

@@ -1,5 +1,9 @@
<template>
<view class="page" :style="themeStyle">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else>
<view class="filter-bar">
<scroll-view scroll-x class="filter-scroll" :show-scrollbar="false">
<view class="filter-tabs">
@@ -80,6 +84,7 @@
</view>
</view>
</u-popup>
</template>
</view>
</template>
@@ -91,6 +96,7 @@ import config from '@/config/config'
import { getThemeStyle } from '@/utils/theme'
import { getDistributionInvitees } from '@/api/distribution'
import { parseGoodsImageUrl } from '@/utils/filters.js'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -104,6 +110,7 @@ const rangeTabs = [
]
const activeRange = ref('ALL')
const pageReady = ref(false)
const loading = ref(false)
const loadingMore = ref(false)
const finished = ref(false)
@@ -138,7 +145,13 @@ onShow(() => {
if (current?.options) {
applyRouteOptions(current.options)
}
resetAndLoad()
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
resetAndLoad()
})
})
onReachBottom(() => {

View File

@@ -58,6 +58,7 @@ import { onLoad, onReady, onShareAppMessage } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getInviteCard } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
import { getMpCode } from '@/api/goods'
import { parseGoodsImageUrl } from '@/utils/filters.js'
import {
@@ -282,6 +283,11 @@ async function loadInviteCardSetting() {
qrError.value = ''
composeError.value = ''
const distributor = await assertActiveDistributor()
if (!distributor) {
return
}
try {
const res = await getInviteCard()
if (!res.data?.success || !res.data?.result) {

View File

@@ -1,6 +1,13 @@
<template>
<view class="wrapper" :style="themeStyle">
<view v-if="loading" class="loading">加载中...</view>
<view v-else-if="isRetreated" class="page-body">
<view class="section result-section">
<view class="result-icon retreated">!</view>
<view class="result-title">分销资格已清退</view>
<view class="result-desc">{{ DISTRIBUTION_RETREAT_MESSAGE }}</view>
</view>
</view>
<view v-else-if="!plan">
<view class="empty">暂未开放线上招募</view>
</view>
@@ -171,6 +178,7 @@ import config from '@/config/config'
import { parseGoodsImageUrl, tipsToLogin } from '@/utils/filters.js'
import { resolveRecruitDistributionIdFromScene } from '@/utils/distributionBind.js'
import { getRecruitPage, getRecruitProgress, getRecruitInviter, submitRecruitApplication } from '@/api/distribution'
import { DISTRIBUTION_RETREAT_MESSAGE, DISTRIBUTION_STATUS } from '@/utils/distributionStatus'
const defaultAvatar = config.defaultUserPhoto
@@ -198,7 +206,12 @@ const fields = computed(() => pageInfo.value.fields || [])
const recruitGoods = computed(() => plan.value?.recruitGoods || [])
const agreementContent = computed(() => plan.value?.agreementContent || '')
const distributionStatus = computed(() => pageInfo.value.distributionStatus || '')
const currentApplication = computed(() => pageInfo.value.currentApplication || null)
const isRetreated = computed(() => distributionStatus.value === DISTRIBUTION_STATUS.RETREAT)
const showPoster = computed(() => {
if (isRetreated.value) return false
const p = plan.value
if (!p) return false
if (p.posterEnabled === false) return false
@@ -211,45 +224,50 @@ const posterRuleText = computed(() => plan.value?.posterRuleText || '')
const posterContact = computed(() => plan.value?.posterContact || '')
const hasJoinCondition = computed(() => {
if (isRetreated.value) return false
const p = plan.value
if (!p || p.joinConditionType !== 'CONDITIONAL') return false
return !!(p.requireSelfPurchaseAmount || p.requireConsumeCount || p.requirePurchaseGoods)
})
const conditionsMet = computed(() => {
if (isRetreated.value) return false
if (!hasJoinCondition.value) return true
return !!progress.value?.satisfied
})
const distributionStatus = computed(() => pageInfo.value.distributionStatus || '')
const currentApplication = computed(() => pageInfo.value.currentApplication || null)
const isApplyApproved = computed(() => {
if (distributionStatus.value === 'PASS') return true
if (isRetreated.value) return false
if (distributionStatus.value === DISTRIBUTION_STATUS.PASS) return true
if (submitApplicationStatus.value === 'APPROVED') return true
if (applySubmitted.value && submitAuditMode.value === 'AUTO_PASS') return true
return currentApplication.value?.applicationStatus === 'APPROVED'
return false
})
const isApplyPending = computed(() => {
if (isRetreated.value) return false
if (isApplyApproved.value) return false
if (distributionStatus.value === 'APPLY') return true
if (distributionStatus.value === DISTRIBUTION_STATUS.APPLY) return true
if (submitApplicationStatus.value === 'PENDING') return true
if (applySubmitted.value && submitAuditMode.value === 'MANUAL') return true
return currentApplication.value?.applicationStatus === 'PENDING'
})
const showApplyResult = computed(() => isApplyApproved.value || isApplyPending.value)
const showApplyResult = computed(() => {
if (isRetreated.value) return false
return isApplyApproved.value || isApplyPending.value
})
const isManualApply = computed(() => {
return (plan.value?.applyMode || 'MANUAL') === 'MANUAL'
})
const showLoginFooter = computed(() => {
return !!plan.value && !isUserLoggedIn.value && !loading.value
return !isRetreated.value && !!plan.value && !isUserLoggedIn.value && !loading.value
})
const showInviterHeader = computed(() => {
if (isRetreated.value) return false
if (!recruitToken.value) return false
const info = inviterInfo.value
return !!(info?.memberName || info?.memberAvatar)
@@ -259,15 +277,15 @@ const inviterName = computed(() => inviterInfo.value?.memberName || '分销员')
const inviterAvatar = computed(() => parseGoodsImageUrl(inviterInfo.value?.memberAvatar) || defaultAvatar)
const showManualApply = computed(() => {
return isUserLoggedIn.value && !showApplyResult.value && conditionsMet.value && isManualApply.value
return !isRetreated.value && isUserLoggedIn.value && !showApplyResult.value && conditionsMet.value && isManualApply.value
})
const showAutoApplyTip = computed(() => {
return isUserLoggedIn.value && !showApplyResult.value && conditionsMet.value && plan.value?.applyMode === 'AUTO'
return !isRetreated.value && isUserLoggedIn.value && !showApplyResult.value && conditionsMet.value && plan.value?.applyMode === 'AUTO'
})
const showApplyForm = computed(() => {
return !!plan.value?.requireApplyInfo && fields.value.length > 0
return !isRetreated.value && !!plan.value?.requireApplyInfo && fields.value.length > 0
})
const canApply = computed(() => {
@@ -445,7 +463,7 @@ function handleApplySuccess(application: any) {
submitAuditMode.value = auditMode
submitApplicationStatus.value = status
if (auditMode === 'AUTO_PASS' || status === 'APPROVED') {
pageInfo.value.distributionStatus = 'PASS'
pageInfo.value.distributionStatus = DISTRIBUTION_STATUS.PASS
if (pageInfo.value.currentApplication) {
pageInfo.value.currentApplication.applicationStatus = 'APPROVED'
}
@@ -458,6 +476,10 @@ function submit() {
if (!tipsToLogin('normal')) {
return
}
if (isRetreated.value) {
uni.showToast({ title: DISTRIBUTION_RETREAT_MESSAGE, icon: 'none' })
return
}
if (!showManualApply.value) {
return
}
@@ -738,6 +760,11 @@ function submit() {
color: #fa8c16;
}
.result-icon.retreated {
background: #fff2f0;
color: #ff4d4f;
}
.result-title {
font-size: 36rpx;
font-weight: 600;

View File

@@ -1,5 +1,9 @@
<template>
<view class="page">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else>
<view class="search-bar">
<view class="search-inner">
<u-icon name="search" color="#bbb" size="18" />
@@ -81,6 +85,7 @@
<text>{{ finished ? '没有更多了' : (loadingMore ? '加载中...' : '上拉加载更多') }}</text>
</view>
</scroll-view>
</template>
</view>
</template>
@@ -88,6 +93,7 @@
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { distributionGoods, getDistributionGoodsSetting } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const DEFAULT_SORT_MAP: Record<string, { field: string; order: string }> = {
HIGHEST_COMMISSION: { field: 'COMMISSION', order: 'DESC' },
@@ -103,6 +109,7 @@ const sortTabs = [
{ field: 'PRICE', label: '价格' },
]
const pageReady = ref(false)
const routeQuery = ref<Record<string, string>>({})
const keyword = ref('')
const sortField = ref('COMMISSION')
@@ -128,6 +135,11 @@ onLoad((options) => {
})
async function initPage() {
const distributor = await assertActiveDistributor()
if (!distributor) {
return
}
pageReady.value = true
await loadGoodsSetting()
resetAndFetch()
}

View File

@@ -9,7 +9,7 @@
<view class="nav-placeholder"></view>
</view>
<view class="hero">
<view v-if="!loading && detail.orderItemSn" class="hero">
<view class="hero-status">{{ detail.settlementStatusText || '待结算' }}</view>
<view class="hero-sub">分销订单详情</view>
</view>
@@ -109,11 +109,12 @@ import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getDistributionOrderDetail } from '@/api/distribution'
import { parseGoodsImageUrl, formatGoodsSpecs } from '@/utils/filters.js'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
const statusBarHeight = ref(20)
const loading = ref(false)
const loading = ref(true)
const detail = ref<Record<string, any>>({})
const orderItemSn = ref('')
const orderType = ref('PROMOTION')
@@ -122,7 +123,12 @@ onLoad((options) => {
statusBarHeight.value = uni.getWindowInfo?.()?.statusBarHeight || 20
orderItemSn.value = options?.orderItemSn || ''
orderType.value = options?.orderType || 'PROMOTION'
loadDetail()
assertActiveDistributor().then((d) => {
if (!d) {
return
}
loadDetail()
})
})
const totalGoodsNum = computed(() => Number(detail.value.totalGoodsNum || detail.value.num || 0))

View File

@@ -1,5 +1,9 @@
<template>
<view class="page" :style="themeStyle">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else>
<view class="search-bar">
<view class="search-inner">
<u-icon name="search" color="#bbb" size="18" />
@@ -132,6 +136,7 @@
</view>
</view>
</u-popup>
</template>
</view>
</template>
@@ -142,6 +147,7 @@ import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getDistributionOrders } from '@/api/distribution'
import { parseGoodsImageUrl, formatGoodsSpecs } from '@/utils/filters.js'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -161,6 +167,7 @@ const rangeTabs = [
const activeTab = ref('PROMOTION')
const activeRange = ref('ALL')
const keyword = ref('')
const pageReady = ref(false)
const loading = ref(false)
const loadingMore = ref(false)
const finished = ref(false)
@@ -202,7 +209,13 @@ onShow(() => {
if (current?.options) {
applyRouteOptions(current.options)
}
resetAndLoad()
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
resetAndLoad()
})
})
onReachBottom(() => {

View File

@@ -50,6 +50,7 @@ import { onLoad, onReady, onShareAppMessage } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getPromotionPoster } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
import { getMpCode } from '@/api/goods'
import { parseGoodsImageUrl } from '@/utils/filters.js'
import {
@@ -269,6 +270,11 @@ async function loadPosterSetting() {
qrError.value = ''
composeError.value = ''
const distributor = await assertActiveDistributor()
if (!distributor) {
return
}
try {
const res = await getPromotionPoster()
if (!res.data?.success || !res.data?.result) {

View File

@@ -1,6 +1,10 @@
<template>
<view class="page">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<distribution-goods-share
v-else
:sku-id="query.skuId"
:goods-id="query.goodsId"
:distribution-id="query.distributionId"
@@ -12,11 +16,19 @@
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import DistributionGoodsShare from '@/components/distribution-goods-share/index.vue'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const query = ref<Record<string, string>>({})
const pageReady = ref(false)
onLoad((options) => {
query.value = (options || {}) as Record<string, string>
assertActiveDistributor().then((d) => {
if (!d) {
return
}
pageReady.value = true
})
})
</script>
@@ -25,4 +37,14 @@ onLoad((options) => {
min-height: 100vh;
background: #fff;
}
.state-wrap {
padding: 120rpx 0;
text-align: center;
}
.state-text {
color: #999;
font-size: 26rpx;
}
</style>

View File

@@ -32,6 +32,7 @@ import { onLoad, onReachBottom } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { getWalletLog } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
@@ -39,13 +40,18 @@ const themeStyle = computed(() => getThemeStyle(store.state.theme))
const walletList = ref<any[]>([])
const walletPage = ref(1)
const walletTotal = ref(0)
const walletLoading = ref(false)
const walletLoading = ref(true)
const walletLoadingMore = ref(false)
const walletFinished = ref(false)
const PAGE_SIZE = 15
onLoad(() => {
loadWalletLog(true)
assertActiveDistributor().then((d) => {
if (!d) {
return
}
loadWalletLog(true)
})
})
onReachBottom(() => {

View File

@@ -1,6 +1,9 @@
<template>
<view class="page" :style="themeStyle">
<view class="content">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<view v-else class="content">
<!-- 到账账户 -->
<view class="section-card">
<view class="account-row" @click="openAccountDrawer">
@@ -139,11 +142,13 @@ import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useStore } from '@/store'
import { getThemeStyle } from '@/utils/theme'
import { distribution, cash, getBankCards, addBankCard } from '@/api/distribution'
import { cash, getBankCards, addBankCard } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
const store = useStore()
const themeStyle = computed(() => getThemeStyle(store.state.theme))
const pageReady = ref(false)
const canRebate = ref(0)
const amount = ref('')
const submitLoading = ref(false)
@@ -161,14 +166,17 @@ const saveLoading = ref(false)
const form = ref({ holderName: '', bankName: '', cardNo: '' })
function loadInfo() {
distribution().then((res: any) => {
const d = res?.data?.result || {}
return assertActiveDistributor().then((d) => {
if (!d) {
return null
}
canRebate.value = Number(d.canRebate || 0)
if (!inited.value) {
const prefill = Math.min(canRebate.value, 9999)
amount.value = prefill > 0 ? prefill.toFixed(2) : ''
inited.value = true
}
return d
})
}
@@ -188,8 +196,13 @@ function loadCards() {
}
onLoad(() => {
loadInfo()
loadCards()
loadInfo().then((d) => {
if (!d) {
return
}
pageReady.value = true
loadCards()
})
})
function openAccountDrawer() {
@@ -304,6 +317,16 @@ function maskCard(cardNo: string) {
.content { padding: 24rpx; }
.state-wrap {
padding: 120rpx 0;
text-align: center;
}
.state-text {
color: #999;
font-size: 26rpx;
}
.section-card {
background: #fff;
border-radius: 20rpx;

View File

@@ -1,5 +1,9 @@
<template>
<view class="wrapper" :style="themeStyle">
<view v-if="!pageReady" class="state-wrap">
<text class="state-text">加载中...</text>
</view>
<template v-else>
<view class="feedBack-box">
<view class="box-title">提现金额</view>
<view class="amount-row">
@@ -23,13 +27,15 @@
</view>
<view class="submit" @click="submitWithdraw">提现</view>
</template>
</view>
</template>
<script setup lang="ts">
import { ref, computed, getCurrentInstance, onMounted } from 'vue'
import { useStore } from '@/store'
import { distribution, cash } from '@/api/distribution'
import { cash } from '@/api/distribution'
import { assertActiveDistributor } from '@/utils/distributionStatus'
import { unitPrice } from '@/utils/filters.js'
import { getThemeStyle } from '@/utils/theme'
@@ -38,23 +44,20 @@ const { proxy } = getCurrentInstance()!
const themeStyle = computed(() => getThemeStyle(store.state.theme))
const price = ref('')
const pageReady = ref(false)
const distributionData = ref<Record<string, any>>({})
onMounted(() => {
fetchDistributionInfo()
})
function hideLoadingIfNeeded() {
if (store.state.isShowToast) uni.hideLoading()
}
function fetchDistributionInfo() {
uni.showLoading({ title: '加载中' })
distribution().then((res) => {
if (res.data.result) {
distributionData.value = res.data.result
assertActiveDistributor().then((result) => {
if (!result) {
return
}
hideLoadingIfNeeded()
distributionData.value = result
pageReady.value = true
})
}
@@ -98,6 +101,16 @@ page {
background: #f8f8f8;
}
.state-wrap {
padding: 120rpx 0;
text-align: center;
}
.state-text {
color: #999;
font-size: 26rpx;
}
.feedBack-box {
background: #fff;
border-radius: 20rpx;

View File

@@ -136,6 +136,7 @@ import { distribution as fetchDistribution } from '@/api/distribution'
import configs from '@/config/config'
import storage from '@/utils/storage'
import { tipsToLogin, setClipboard } from '@/utils/filters.js'
import { DISTRIBUTION_RETREAT_MESSAGE, DISTRIBUTION_STATUS } from '@/utils/distributionStatus'
const sharingShow = ref(false)
const sharingLink = ref('')
@@ -194,18 +195,19 @@ function distribution() {
if (!tipsToLogin('normal')) {
return
}
// 入口按 distributionStatus 路由:有对象 ≠ 有效分销员。清退停住,不进 join / home。
fetchDistribution().then((res) => {
if (res.data.result) {
const type = res.data.result.distributionStatus
if (type == 'PASS') {
if (type == DISTRIBUTION_STATUS.PASS) {
uni.navigateTo({
url: '/pages/mine/distribution/home',
})
} else if (type == 'REFUSE') {
} else if (type == DISTRIBUTION_STATUS.REFUSE) {
goRecruitJoin()
} else if (type == 'RETREAT') {
} else if (type == DISTRIBUTION_STATUS.RETREAT) {
uni.showToast({
title: '您的分销资格已被清退。请联系管理员!',
title: DISTRIBUTION_RETREAT_MESSAGE,
duration: 2000,
icon: 'none',
})