feat(quality-owner): 增加优质号主、极品专区与无忧租号保险
- 支持保证金余额支付、在线支付开通及后台手动设置审计 - 新增极品专区发布权限、赔付方案与保险结算费率快照 - 优化首页、商品卡和个人中心的优质号主身份展示
This commit is contained in:
@@ -18,6 +18,18 @@ import { uploadFile } from '@/shared/api/files'
|
||||
import { formatCent } from '@/shared/utils/money'
|
||||
import { setPassword } from '@/features/auth/api/auth'
|
||||
import { fetchUserInvitationSummary } from '@/features/invitation/api/invitation'
|
||||
import {
|
||||
activateQualityOwner,
|
||||
fetchQualityOwnerStatus,
|
||||
queryQualityOwnerPayment,
|
||||
startQualityOwnerPayment,
|
||||
type QualityOwnerStatus,
|
||||
} from '@/features/quality-owner/api/qualityOwner'
|
||||
import type { PaymentPayWay } from '@/features/orders/api/orders'
|
||||
import { useMobilePayWaySelect } from '@/features/orders/composables/useMobilePayWaySelect'
|
||||
import { useMobilePaymentCashier } from '@/features/orders/composables/useMobilePaymentCashier'
|
||||
import MobilePayWaySelectPopup from '@/features/orders/components/MobilePayWaySelectPopup.vue'
|
||||
import MobilePaymentCashierPopup from '@/features/orders/components/MobilePaymentCashierPopup.vue'
|
||||
|
||||
import { useDistributionSiteStore } from '@/stores/distributionSite'
|
||||
|
||||
@@ -33,6 +45,22 @@ const { unreadCount: notificationUnreadCount, unreadLabel: notificationUnreadLab
|
||||
|
||||
/** 数据项 */
|
||||
const availableBalanceCent = ref(0)
|
||||
const qualityOwnerStatus = ref<QualityOwnerStatus | null>(null)
|
||||
const qualityOwnerLoading = ref(false)
|
||||
const qualityOwnerOnlineLoading = ref(false)
|
||||
const qualityOwnerPayWaySelect = useMobilePayWaySelect()
|
||||
const qualityOwnerCashier = useMobilePaymentCashier({
|
||||
queryPayment: () => queryQualityOwnerPayment(),
|
||||
paidMessage: '保证金支付成功,优质号主已开通',
|
||||
})
|
||||
const {
|
||||
paymentPopupVisible: qualityOwnerPaymentPopupVisible,
|
||||
activePayment: activeQualityOwnerPayment,
|
||||
payURL: qualityOwnerPaymentPayURL,
|
||||
paymentQRCodeURL: qualityOwnerPaymentQRCodeURL,
|
||||
qrGenerating: qualityOwnerPaymentQRGenerating,
|
||||
checkingPayment: qualityOwnerPaymentChecking,
|
||||
} = qualityOwnerCashier
|
||||
const showSettings = ref(false)
|
||||
const showProfileEditor = ref(false)
|
||||
const savingProfile = ref(false)
|
||||
@@ -121,10 +149,72 @@ onMounted(async () => {
|
||||
// 保留本地会话展示,避免个人中心因网络短暂异常整页不可用。
|
||||
}
|
||||
void loadBalance()
|
||||
void loadQualityOwnerStatus()
|
||||
void loadInviteRate()
|
||||
}
|
||||
})
|
||||
|
||||
async function loadQualityOwnerStatus() {
|
||||
try {
|
||||
qualityOwnerStatus.value = await fetchQualityOwnerStatus()
|
||||
} catch {
|
||||
qualityOwnerStatus.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function handleActivateQualityOwner() {
|
||||
const status = qualityOwnerStatus.value
|
||||
if (!status || status.active) return
|
||||
try {
|
||||
await showDialog({
|
||||
title: '开通优质号主',
|
||||
message: `确认从可用余额中扣除 ¥${formatCent(
|
||||
status.required_deposit_cent
|
||||
)} 作为保证金?取消资格时会退回余额。`,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '确认缴纳',
|
||||
cancelButtonText: '取消',
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
qualityOwnerLoading.value = true
|
||||
try {
|
||||
qualityOwnerStatus.value = await activateQualityOwner()
|
||||
await session.loadMe()
|
||||
await loadBalance()
|
||||
showToast({ message: '优质号主已开通', icon: 'passed' })
|
||||
} catch (error) {
|
||||
showToast({ message: readError(error, '开通失败,请确认余额充足'), icon: 'cross' })
|
||||
} finally {
|
||||
qualityOwnerLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleOnlineQualityOwnerPayment() {
|
||||
const payWay = await qualityOwnerPayWaySelect.select()
|
||||
if (!payWay) return
|
||||
qualityOwnerOnlineLoading.value = true
|
||||
try {
|
||||
const payment = await startQualityOwnerPayment(payWay as PaymentPayWay)
|
||||
if (payment.paid) {
|
||||
await handleQualityOwnerPaid()
|
||||
return
|
||||
}
|
||||
await qualityOwnerCashier.openMobilePaymentCashier(payment, handleQualityOwnerPaid)
|
||||
} catch (error) {
|
||||
showToast({ message: readError(error, '发起在线支付失败'), icon: 'cross' })
|
||||
} finally {
|
||||
qualityOwnerOnlineLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleQualityOwnerPaid() {
|
||||
qualityOwnerStatus.value = await fetchQualityOwnerStatus()
|
||||
await session.loadMe()
|
||||
await loadBalance()
|
||||
}
|
||||
|
||||
async function loadBalance() {
|
||||
try {
|
||||
const wallet = await fetchWalletBalance()
|
||||
@@ -366,6 +456,9 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
>
|
||||
未实名
|
||||
</van-tag>
|
||||
<van-tag v-if="qualityOwnerStatus?.active" round class="owner-quality-tag">
|
||||
<van-icon name="award-o" /> 优质号主
|
||||
</van-tag>
|
||||
</div>
|
||||
<p class="user-meta">ID: {{ displayId }} · {{ maskedPhone }}</p>
|
||||
</div>
|
||||
@@ -393,6 +486,65 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="quality-owner-card" :class="{ 'is-active': qualityOwnerStatus?.active }">
|
||||
<div class="quality-owner-heading">
|
||||
<div>
|
||||
<span>优质号主</span>
|
||||
<strong>{{ qualityOwnerStatus?.active ? '已开通' : '解锁极品专区发布权限' }}</strong>
|
||||
</div>
|
||||
<van-tag :type="qualityOwnerStatus?.active ? 'success' : 'default'" round>
|
||||
{{ qualityOwnerStatus?.active ? '优质号主' : '未开通' }}
|
||||
</van-tag>
|
||||
</div>
|
||||
<div class="quality-owner-info">
|
||||
<div>
|
||||
<span>保证金</span>
|
||||
<strong>¥{{ formatCent(qualityOwnerStatus?.required_deposit_cent || 20000) }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>极品专区保险费率</span>
|
||||
<strong
|
||||
>{{
|
||||
((qualityOwnerStatus?.premium_insurance_fee_bps || 400) / 100).toFixed(1)
|
||||
}}%</strong
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!qualityOwnerStatus?.active" class="quality-owner-actions">
|
||||
<van-button
|
||||
block
|
||||
round
|
||||
type="primary"
|
||||
color="#7c3aed"
|
||||
:loading="qualityOwnerLoading"
|
||||
:disabled="
|
||||
(qualityOwnerStatus?.available_balance_cent || 0) <
|
||||
(qualityOwnerStatus?.required_deposit_cent || 20000)
|
||||
"
|
||||
@click="handleActivateQualityOwner"
|
||||
>
|
||||
余额支付开通
|
||||
</van-button>
|
||||
<van-button
|
||||
block
|
||||
round
|
||||
plain
|
||||
type="primary"
|
||||
:loading="qualityOwnerOnlineLoading"
|
||||
@click="handleOnlineQualityOwnerPayment"
|
||||
>
|
||||
微信 / 支付宝支付开通
|
||||
</van-button>
|
||||
</div>
|
||||
<p v-else>
|
||||
{{
|
||||
qualityOwnerStatus?.deposit_source === 'manual'
|
||||
? '已由后台开通优质号主。'
|
||||
: '保证金已冻结,取消优质号主资格时退回可用余额。'
|
||||
}}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- 余额卡片 - 银行卡质感暗色卡片 -->
|
||||
<div class="balance-card">
|
||||
<div class="balance-row">
|
||||
@@ -496,6 +648,22 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<MobilePayWaySelectPopup
|
||||
v-model:show="qualityOwnerPayWaySelect.visible.value"
|
||||
@choose="qualityOwnerPayWaySelect.choose"
|
||||
@closed="qualityOwnerPayWaySelect.handleClosed"
|
||||
/>
|
||||
|
||||
<MobilePaymentCashierPopup
|
||||
v-model:show="qualityOwnerPaymentPopupVisible"
|
||||
:payment="activeQualityOwnerPayment"
|
||||
:pay-url="qualityOwnerPaymentPayURL"
|
||||
:qr-code-url="qualityOwnerPaymentQRCodeURL"
|
||||
:qr-generating="qualityOwnerPaymentQRGenerating"
|
||||
:checking="qualityOwnerPaymentChecking"
|
||||
@refresh="qualityOwnerCashier.refreshPaymentStatus(false)"
|
||||
/>
|
||||
|
||||
<!-- 账单明细 Popup -->
|
||||
<van-popup
|
||||
v-model:show="showLedgers"
|
||||
|
||||
Reference in New Issue
Block a user