Files
bdrp-app/src/pages/agent-promote-details.vue
2026-04-27 14:48:54 +08:00

268 lines
7.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
definePage({ layout: 'default', auth: true })
import { onReachBottom } from '@dcloudio/uni-app'
// 颜色配置(根据产品名称映射)
const typeColors = {
小微企业: { bg: 'bg-blue-100', text: 'text-blue-800', dot: 'bg-blue-500' },
入职风险: { bg: 'bg-green-100', text: 'text-green-800', dot: 'bg-green-500' },
家政风险: { bg: 'bg-purple-100', text: 'text-purple-800', dot: 'bg-purple-500' },
婚恋风险: { bg: 'bg-pink-100', text: 'text-pink-800', dot: 'bg-pink-500' },
贷前风险: { bg: 'bg-orange-100', text: 'text-orange-800', dot: 'bg-orange-500' },
租赁风险: { bg: 'bg-indigo-100', text: 'text-indigo-800', dot: 'bg-indigo-500' },
个人风险: { bg: 'bg-red-100', text: 'text-red-800', dot: 'bg-red-500' },
个人大数据: { bg: 'bg-red-100', text: 'text-red-800', dot: 'bg-red-500' },
// 默认类型
default: { bg: 'bg-gray-100', text: 'text-gray-800', dot: 'bg-gray-500' },
}
// 新增点 4: 定义脱敏函数
function desen(value, type) {
// 如果值是空,直接返回空字符串,让外层的 || '-' 生效
if (!value) {
return ''
}
// 根据类型进行不同的替换
switch (type) {
case 'mobile': // 手机号保留前3位和后4位中间4位替换为 ****
return value.replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
case 'id_card':// 身份证保留前6位和后1位中间替换为 ********
if (value.length <= 7)
return value
return `${value.slice(0, 6)}********${value.slice(-1)}`
default:
return value // 其他类型不处理
}
}
const page = ref(1)
const pageSize = ref(10)
const data = ref({
total: 0,
list: [],
})
const loading = ref(false)
const hasMore = ref(true)
const loadMoreState = ref('loading')
// 获取颜色样式
function getReportTypeStyle(name) {
const color = typeColors[name] || typeColors.default
return `${color.bg} ${color.text}`
}
// 获取小圆点颜色
function getDotColor(name) {
return (typeColors[name] || typeColors.default).dot
}
// 获取金额颜色
function getAmountColor(item) {
// 状态为已退款,显示红色
if (item.status === 2) {
return 'text-red-500'
}
// 如果有部分退款,显示橙色
if (item.refunded_amount > 0) {
return 'text-orange-500'
}
// 正常情况显示绿色
return 'text-green-500'
}
// 获取金额前缀(+ 或 -
function getAmountPrefix(item) {
if (item.status === 2) {
return '-'
}
return '+'
}
// 获取状态文本
function getStatusText(item) {
if (item.status === 2) {
return '已退款'
}
if (item.status === 1) {
// 冻结中
if (item.refunded_amount > 0) {
return '冻结中(部分退款)'
}
return '冻结中'
}
if (item.status === 0) {
// 已结算
if (item.refunded_amount > 0) {
return '已结算(部分退款)'
}
return '已结算'
}
return '未知状态'
}
// 获取状态样式
function getStatusStyle(item) {
if (item.status === 2) {
return 'bg-red-100 text-red-800'
}
if (item.status === 1) {
// 冻结中
if (item.refunded_amount > 0) {
return 'bg-orange-100 text-orange-800'
}
return 'bg-yellow-100 text-yellow-800'
}
if (item.status === 0) {
// 已结算
if (item.refunded_amount > 0) {
return 'bg-blue-100 text-blue-800'
}
return 'bg-green-100 text-green-800'
}
return 'bg-gray-100 text-gray-800'
}
// 获取数据
function mergeUniqueById(oldList, newList) {
const map = new Map()
const resolveKey = (item, index) => String(item?.id ?? item?.order_id ?? `${item?.create_time || ''}_${item?.status || ''}_${index}`)
oldList.forEach((item, index) => {
map.set(resolveKey(item, index), item)
})
newList.forEach((item, index) => {
map.set(resolveKey(item, oldList.length + index), item)
})
return Array.from(map.values())
}
async function getData(reset = false) {
try {
if (loading.value)
return
if (!reset && !hasMore.value)
return
loading.value = true
if (reset) {
page.value = 1
hasMore.value = true
loadMoreState.value = 'loading'
data.value = { total: 0, list: [] }
}
const { data: res, error } = await useApiFetch(
`/agent/commission?page=${page.value}&page_size=${pageSize.value}`,
{ silent: true },
).get().json()
if (res.value?.code === 200 && !error.value) {
const incoming = res.value.data.list || []
data.value.total = res.value.data.total || 0
data.value.list = reset ? incoming : mergeUniqueById(data.value.list, incoming)
const isLastPage = incoming.length < pageSize.value || data.value.list.length >= data.value.total
hasMore.value = !isLastPage
loadMoreState.value = isLastPage ? 'finished' : 'loading'
if (!isLastPage)
page.value += 1
}
else {
loadMoreState.value = 'error'
}
}
finally {
loading.value = false
}
}
// 初始化加载
onMounted(() => {
getData(true)
})
onReachBottom(() => {
getData()
})
</script>
<template>
<view class="min-h-screen bg-gray-50">
<view class="detail-scroll">
<view v-for="(item, index) in data.list" :key="index" class="mx-4 my-2 rounded-lg bg-white p-4 shadow-sm">
<view class="mb-2 flex items-center justify-between">
<!-- 修改点 1: 使用 desen 函数处理 mobile -->
<text class="text-sm text-gray-500">
{{ desen(item.query_params?.mobile, 'mobile') || '-' }}
</text>
<text
class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium"
:class="getReportTypeStyle(item.product_name)"
>
<text class="mr-1 h-2 w-2 rounded-full" :class="getDotColor(item.product_name)" />
{{ item.product_name }}
</text>
</view>
<view class="mb-2 flex items-center justify-between">
<text class="text-gray-700 font-medium">
直接收益
</text>
<view class="flex flex-col items-end">
<!-- 主金额显示净佣金 -->
<text :class="getAmountColor(item)" class="text-lg font-bold">
{{ getAmountPrefix(item) }}{{ (item.net_amount || 0).toFixed(2) }}
</text>
<!-- 如果有部分退款显示原始金额和已退金额 -->
<text v-if="item.refunded_amount > 0 && item.net_amount > 0" class="mt-1 text-xs text-gray-400">
原始 {{ item.amount.toFixed(2) }}已退 {{ item.refunded_amount.toFixed(2) }}
</text>
</view>
</view>
<view class="flex items-center justify-between">
<text class="text-sm text-gray-500">
{{ desen(item.query_params?.name) || '-' }}
</text>
<!-- 状态标签 -->
<text
class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium"
:class="getStatusStyle(item)"
>
{{ getStatusText(item) }}
</text>
</view>
<view class="mb-2 flex items-center justify-between">
<text class="text-sm text-gray-500">
{{ item.create_time || '-' }}
</text>
</view>
<view class="mt-2 flex items-center">
<text class="text-sm text-gray-500">
订单号
</text>
<text class="text-sm text-gray-700 font-mono">
{{ item.order_id || '-' }}
</text>
</view>
</view>
<view v-if="loading" class="py-4 text-center text-sm text-gray-400">
加载中...
</view>
<view v-else-if="!data.list.length" class="py-4 text-center text-sm text-gray-400">
暂无记录
</view>
</view>
<wd-loadmore :state="loadMoreState" @reload="getData" />
</view>
</template>
<style scoped>
/* 列表项入场动画 */
.list-enter-active {
transition: all 0.3s ease;
}
.list-enter-from {
opacity: 0;
transform: translateY(20px);
}
.detail-scroll {
min-height: calc(100vh - 110px);
}
</style>