实现租客成长等级并优化展示
This commit is contained in:
@@ -13,6 +13,9 @@ export interface AdminUserItem {
|
||||
deposit_free_quota_cent: number
|
||||
deposit_free_used_cent: number
|
||||
deposit_free_remaining_cent: number
|
||||
renter_growth_points: number
|
||||
renter_growth_level: string
|
||||
renter_growth_level_name: string
|
||||
available_balance_cent: number
|
||||
frozen_balance_cent: number
|
||||
status: UserStatus
|
||||
|
||||
@@ -266,7 +266,17 @@ const ownerLossPriceCent = computed(() => {
|
||||
const hasOwnerRentBreakdown = computed(() => ownerCoinBasePriceCent.value !== null)
|
||||
const fundSplitRows = computed(() => {
|
||||
if (!order.value) return []
|
||||
const rows: FundSplitRow[] = [{ label: '租客租金', amountCent: order.value.rent_amount_cent }]
|
||||
const rows: FundSplitRow[] = []
|
||||
if (Number(order.value.rent_discount_amount_cent || 0) > 0) {
|
||||
rows.push(
|
||||
{ label: '原始租金', amountCent: order.value.rent_original_amount_cent },
|
||||
{
|
||||
label: `${order.value.renter_growth_level_name || '成长等级'}优惠`,
|
||||
amountCent: -Number(order.value.rent_discount_amount_cent || 0),
|
||||
}
|
||||
)
|
||||
}
|
||||
rows.push({ label: '租客租金', amountCent: order.value.rent_amount_cent })
|
||||
if (hasOwnerRentBreakdown.value) {
|
||||
rows.push(
|
||||
{ label: '号主纯币价格', amountCent: ownerCoinBasePriceCent.value },
|
||||
@@ -843,7 +853,12 @@ function paymentPaidAt(record: AdminPayment) {
|
||||
<el-button v-if="canResetHandoff" type="success" @click="openAction('reset')">
|
||||
{{ resetActionLabel }}
|
||||
</el-button>
|
||||
<el-button v-if="canPlatformHandoff" type="primary" plain @click="openPlatformHandoff">
|
||||
<el-button
|
||||
v-if="canPlatformHandoff"
|
||||
class="platform-handoff-button"
|
||||
type="primary"
|
||||
@click="openPlatformHandoff"
|
||||
>
|
||||
{{ platformHandoffAction?.label || '客服代交接' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@@ -1551,6 +1566,27 @@ function paymentPaidAt(record: AdminPayment) {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.platform-handoff-button {
|
||||
min-width: 96px;
|
||||
border-color: #2563eb;
|
||||
background: #2563eb;
|
||||
color: #ffffff;
|
||||
font-weight: 700;
|
||||
box-shadow: 0 6px 14px rgba(37, 99, 235, 0.18);
|
||||
}
|
||||
|
||||
.platform-handoff-button:hover,
|
||||
.platform-handoff-button:focus {
|
||||
border-color: #1d4ed8;
|
||||
background: #1d4ed8;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.platform-handoff-button:active {
|
||||
border-color: #1e40af;
|
||||
background: #1e40af;
|
||||
}
|
||||
|
||||
.order-detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.1fr) minmax(360px, 0.9fr);
|
||||
|
||||
@@ -312,6 +312,14 @@ function moneyCent(value: number | string | undefined) {
|
||||
<el-table-column label="实名状态" width="100">
|
||||
<template #default="{ row }">{{ realnameStatusLabel(row.realname_status) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="成长等级" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="success" effect="light">{{ row.renter_growth_level_name || '普通' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="成长积分" width="100" align="right">
|
||||
<template #default="{ row }">{{ Number(row.renter_growth_points || 0) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="可用余额" width="108" align="right">
|
||||
<template #default="{ row }">
|
||||
<span class="balance-available">¥{{ moneyCent(row.available_balance_cent) }}</span>
|
||||
|
||||
@@ -10,6 +10,8 @@ export interface AuthUser {
|
||||
realname_status: RealnameStatusValue
|
||||
risk_status: RiskStatus
|
||||
credit_score: number
|
||||
renter_growth_points?: number
|
||||
renter_growth_level?: string
|
||||
status: UserStatus
|
||||
}
|
||||
|
||||
|
||||
@@ -104,11 +104,16 @@ const settingsGroups = [
|
||||
},
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
if (!isLoggedIn.value) {
|
||||
router.replace({ path: '/m/login', query: { redirect: route.fullPath } })
|
||||
} else {
|
||||
loadBalance()
|
||||
try {
|
||||
await session.loadMe()
|
||||
} catch {
|
||||
// 保留本地会话展示,避免个人中心因网络短暂异常整页不可用。
|
||||
}
|
||||
void loadBalance()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -348,6 +353,17 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="growth-card">
|
||||
<div>
|
||||
<span>租客成长等级</span>
|
||||
<strong>{{ session.renterGrowthLevelName }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>当前积分</span>
|
||||
<strong>{{ session.renterGrowthPoints }}</strong>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 余额卡片 - 银行卡质感暗色卡片 -->
|
||||
<div class="balance-card">
|
||||
<div class="balance-row">
|
||||
@@ -780,6 +796,39 @@ function resolveAvatarURL(url: string | undefined | null) {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.growth-card {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
margin: 12px 16px 0;
|
||||
}
|
||||
|
||||
.growth-card > div {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
padding: 14px;
|
||||
border: 1px solid rgba(243, 244, 246, 0.9);
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 4px 16px rgba(0, 0, 0, 0.02),
|
||||
0 1px 4px rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.growth-card span {
|
||||
color: #9ca3af;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.growth-card strong {
|
||||
color: #7c3aed;
|
||||
font-size: 20px;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
/* ========== Balance Card ========== */
|
||||
.balance-card {
|
||||
margin: 12px 16px 14px;
|
||||
|
||||
@@ -50,8 +50,10 @@ const realnameTone = computed(() => {
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
if (!session.phone) {
|
||||
try {
|
||||
await session.loadMe()
|
||||
} catch {
|
||||
// 保留本地会话展示,避免资料页因网络短暂异常整页不可用。
|
||||
}
|
||||
resetForm()
|
||||
})
|
||||
@@ -258,6 +260,14 @@ async function savePassword() {
|
||||
<dt>实名状态</dt>
|
||||
<dd :class="`is-${realnameTone}`">{{ realnameStatusLabel(session.realnameStatus) }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>租客等级</dt>
|
||||
<dd class="growth-level">{{ session.renterGrowthLevelName }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>成长积分</dt>
|
||||
<dd>{{ session.renterGrowthPoints }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<button class="realname-shortcut" type="button" @click="router.push('/realname')">
|
||||
<span>查看实名认证</span>
|
||||
@@ -604,6 +614,10 @@ async function savePassword() {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.account-card dd.growth-level {
|
||||
color: #7c3aed;
|
||||
}
|
||||
|
||||
.realname-shortcut {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -27,6 +27,13 @@ export interface Order {
|
||||
deposit_original_amount_cent: number
|
||||
deposit_waived_amount_cent: number
|
||||
platform_fee_cent?: number
|
||||
rent_original_amount_cent?: number
|
||||
rent_discount_amount_cent?: number
|
||||
renter_growth_level?: string
|
||||
renter_growth_level_name?: string
|
||||
renter_discount_bps?: number
|
||||
growth_points_awarded?: number
|
||||
growth_points_awarded_at?: string
|
||||
account_snapshot?: Record<string, unknown>
|
||||
listing_snapshot?: string
|
||||
checkout_info?: string
|
||||
|
||||
@@ -188,6 +188,14 @@ async function copyListingCode() {
|
||||
<div class="meta-item">
|
||||
<span class="meta-label">{{ orderAmountLabel }}</span>
|
||||
<strong class="meta-value accent">¥{{ money(orderRentDisplayAmount) }}</strong>
|
||||
<span
|
||||
v-if="isRenter && Number(order.rent_discount_amount_cent || 0) > 0"
|
||||
class="meta-note"
|
||||
>
|
||||
{{ order.renter_growth_level_name || '成长等级' }}优惠 ¥{{
|
||||
money(amountYuan(order.rent_discount_amount_cent))
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="isOwner && ownerIncomeDisplayAmount !== null" class="meta-item">
|
||||
<span class="meta-label">{{ ownerIncomeLabel }}</span>
|
||||
|
||||
@@ -388,6 +388,14 @@ watch([() => route.query.focus, order, loading], () => {
|
||||
<div class="metric-card highlight">
|
||||
<span class="metric-label">{{ orderAmountLabel }}</span>
|
||||
<strong class="metric-value amount">¥{{ money(orderRentDisplayAmount) }}</strong>
|
||||
<span
|
||||
v-if="isRenter && Number(order.rent_discount_amount_cent || 0) > 0"
|
||||
class="metric-note"
|
||||
>
|
||||
{{ order.renter_growth_level_name || '成长等级' }}优惠 ¥{{
|
||||
money(amountYuan(order.rent_discount_amount_cent))
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="isOwner && ownerIncomeDisplayAmount !== null" class="metric-card income">
|
||||
<span class="metric-label">{{ ownerIncomeLabel }}</span>
|
||||
|
||||
Reference in New Issue
Block a user