This commit is contained in:
@@ -4,55 +4,40 @@ import { getFundSummary, getCommissionRecords, getCommissionStats } from '@/api/
|
|||||||
import type { FundSummary, CommissionRecord, CommissionStats } from '@/api/commission'
|
import type { FundSummary, CommissionRecord, CommissionStats } from '@/api/commission'
|
||||||
import SimplePicker from '@/components/SimplePicker.vue'
|
import SimplePicker from '@/components/SimplePicker.vue'
|
||||||
|
|
||||||
// 佣金概览
|
|
||||||
const commissionSummary = ref<FundSummary | null>(null)
|
const commissionSummary = ref<FundSummary | null>(null)
|
||||||
|
|
||||||
// 店铺ID (从登录信息获取)
|
|
||||||
const shopId = ref<number>(0)
|
const shopId = ref<number>(0)
|
||||||
|
|
||||||
// 从本地存储获取用户信息
|
|
||||||
function getUserInfo() {
|
|
||||||
const userInfo = uni.getStorageSync('user_info')
|
|
||||||
return userInfo || null
|
|
||||||
}
|
|
||||||
|
|
||||||
// 佣金明细列表
|
|
||||||
const commissionRecords = ref<CommissionRecord[]>([])
|
const commissionRecords = ref<CommissionRecord[]>([])
|
||||||
|
|
||||||
// 佣金统计
|
|
||||||
const commissionStats = ref<CommissionStats | null>(null)
|
const commissionStats = ref<CommissionStats | null>(null)
|
||||||
|
|
||||||
// 加载状态
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const loadingRecords = ref(false)
|
const loadingRecords = ref(false)
|
||||||
|
|
||||||
// 分页参数
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
const pageSize = 20
|
const pageSize = 20
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
|
||||||
// 搜索关键词
|
|
||||||
const searchKeyword = ref('')
|
const searchKeyword = ref('')
|
||||||
|
|
||||||
// 佣金来源筛选
|
|
||||||
const sourceFilter = ref<string | undefined>(undefined)
|
const sourceFilter = ref<string | undefined>(undefined)
|
||||||
const showSourcePicker = ref(false)
|
const showSourcePicker = ref(false)
|
||||||
|
const showSearchTypePicker = ref(false)
|
||||||
|
|
||||||
// 佣金来源选项
|
|
||||||
const sourceOptions = [
|
const sourceOptions = [
|
||||||
{ label: '全部来源', value: undefined },
|
{ label: '全部来源', value: undefined },
|
||||||
{ label: '成本价差', value: 'cost_diff' },
|
{ label: '成本价差', value: 'cost_diff' },
|
||||||
{ label: '一次性佣金', value: 'one_time' },
|
{ label: '一次性佣金', value: 'one_time' },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 获取当前选中的来源名称
|
const searchType = ref<'iccid' | 'virtual_no' | 'order_no'>('iccid')
|
||||||
|
|
||||||
|
const searchTypeOptions = [
|
||||||
|
{ label: 'ICCID', value: 'iccid' },
|
||||||
|
{ label: '虚拟号', value: 'virtual_no' },
|
||||||
|
{ label: '订单号', value: 'order_no' }
|
||||||
|
]
|
||||||
|
|
||||||
const selectedSourceName = computed(() => {
|
const selectedSourceName = computed(() => {
|
||||||
if (sourceFilter.value === undefined) return '佣金来源'
|
if (sourceFilter.value === undefined) return '来源'
|
||||||
const option = sourceOptions.find(o => o.value === sourceFilter.value)
|
const option = sourceOptions.find(o => o.value === sourceFilter.value)
|
||||||
return option?.label || '佣金来源'
|
return option?.label || '来源'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 格式化金额(分转元,带千分号)
|
|
||||||
function formatAmount(amount: number) {
|
function formatAmount(amount: number) {
|
||||||
const yuan = (amount / 100).toFixed(2)
|
const yuan = (amount / 100).toFixed(2)
|
||||||
const parts = yuan.split('.')
|
const parts = yuan.split('.')
|
||||||
@@ -60,7 +45,6 @@ function formatAmount(amount: number) {
|
|||||||
return `¥${parts.join('.')}`
|
return `¥${parts.join('.')}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取佣金来源文本
|
|
||||||
function getSourceText(source: string) {
|
function getSourceText(source: string) {
|
||||||
const map: Record<string, string> = {
|
const map: Record<string, string> = {
|
||||||
cost_diff: '成本价差',
|
cost_diff: '成本价差',
|
||||||
@@ -70,316 +54,257 @@ function getSourceText(source: string) {
|
|||||||
return map[source] || source
|
return map[source] || source
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取佣金状态文本
|
|
||||||
function getStatusText(status: number) {
|
function getStatusText(status: number) {
|
||||||
const map: Record<number, string> = {
|
return status === 1 ? '已入账' : '已失效'
|
||||||
1: '已入账',
|
|
||||||
2: '已失效',
|
|
||||||
}
|
|
||||||
return map[status] || '未知'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取佣金状态颜色
|
|
||||||
function getStatusColor(status: number) {
|
|
||||||
const map: Record<number, { bg: string, text: string }> = {
|
|
||||||
1: { bg: '#e8f5e9', text: '#2e7d32' }, // 已入账
|
|
||||||
2: { bg: '#f5f5f5', text: '#999' }, // 已失效
|
|
||||||
}
|
|
||||||
return map[status] || { bg: '#f5f5f5', text: '#999' }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 格式化时间
|
|
||||||
function formatTime(time: string) {
|
function formatTime(time: string) {
|
||||||
if (!time) return '-'
|
if (!time) return '-'
|
||||||
const date = new Date(time)
|
const date = new Date(time)
|
||||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
return `${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
|
||||||
const day = String(date.getDate()).padStart(2, '0')
|
|
||||||
const hour = String(date.getHours()).padStart(2, '0')
|
|
||||||
const minute = String(date.getMinutes()).padStart(2, '0')
|
|
||||||
return `${month}-${day} ${hour}:${minute}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面加载
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 从登录信息获取 shop_id
|
const userInfo = uni.getStorageSync('user_info')
|
||||||
const userInfo = getUserInfo()
|
|
||||||
if (userInfo?.shop_id) {
|
if (userInfo?.shop_id) {
|
||||||
shopId.value = userInfo.shop_id
|
shopId.value = userInfo.shop_id
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCommissionSummary()
|
loadCommissionSummary()
|
||||||
loadCommissionStats()
|
loadCommissionStats()
|
||||||
loadCommissionRecords()
|
loadCommissionRecords()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 加载佣金概览
|
|
||||||
async function loadCommissionSummary() {
|
async function loadCommissionSummary() {
|
||||||
try {
|
try {
|
||||||
const summary = await getFundSummary()
|
commissionSummary.value = await getFundSummary()
|
||||||
commissionSummary.value = summary
|
} catch (error) {
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error('加载佣金概览失败:', error)
|
console.error('加载佣金概览失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载佣金统计
|
|
||||||
async function loadCommissionStats() {
|
async function loadCommissionStats() {
|
||||||
if (!shopId.value) return
|
if (!shopId.value) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stats = await getCommissionStats(shopId.value)
|
commissionStats.value = await getCommissionStats(shopId.value)
|
||||||
commissionStats.value = stats
|
} catch (error) {
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error('加载佣金统计失败:', error)
|
console.error('加载佣金统计失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载佣金明细
|
async function loadCommissionRecords(isRefresh = false) {
|
||||||
async function loadCommissionRecords() {
|
|
||||||
if (!shopId.value) return
|
if (!shopId.value) return
|
||||||
|
if (isRefresh) {
|
||||||
|
page.value = 1
|
||||||
|
commissionRecords.value = []
|
||||||
|
}
|
||||||
loadingRecords.value = true
|
loadingRecords.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const params: any = {
|
const params: any = { page: page.value, page_size: pageSize }
|
||||||
page: page.value,
|
|
||||||
page_size: pageSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 佣金来源筛选
|
|
||||||
if (sourceFilter.value) {
|
if (sourceFilter.value) {
|
||||||
params.commission_source = sourceFilter.value
|
params.commission_source = sourceFilter.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索关键词(支持 ICCID、虚拟号、订单号)
|
|
||||||
if (searchKeyword.value) {
|
if (searchKeyword.value) {
|
||||||
const keyword = searchKeyword.value.trim()
|
const keyword = searchKeyword.value.trim()
|
||||||
// 根据关键词类型判断搜索字段
|
if (searchType.value === 'iccid') params.iccid = keyword
|
||||||
if (/^\d{19,20}$/.test(keyword)) {
|
else if (searchType.value === 'virtual_no') params.virtual_no = keyword
|
||||||
// ICCID 通常是19-20位数字
|
else params.order_no = keyword
|
||||||
params.iccid = keyword
|
|
||||||
}
|
|
||||||
else if (/^\d{15}$/.test(keyword)) {
|
|
||||||
// 虚拟号通常是15位数字
|
|
||||||
params.virtual_no = keyword
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// 订单号
|
|
||||||
params.order_no = keyword
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await getCommissionRecords(shopId.value, params)
|
const response = await getCommissionRecords(shopId.value, params)
|
||||||
|
|
||||||
if (page.value === 1) {
|
if (page.value === 1) {
|
||||||
commissionRecords.value = response.items || []
|
commissionRecords.value = response.items || []
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
commissionRecords.value.push(...(response.items || []))
|
commissionRecords.value.push(...(response.items || []))
|
||||||
}
|
}
|
||||||
|
|
||||||
total.value = response.total || 0
|
total.value = response.total || 0
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
|
||||||
console.error('加载佣金明细失败:', error)
|
console.error('加载佣金明细失败:', error)
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
loadingRecords.value = false
|
loadingRecords.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索
|
|
||||||
function handleSearch() {
|
function handleSearch() {
|
||||||
page.value = 1
|
loadCommissionRecords(true)
|
||||||
commissionRecords.value = []
|
|
||||||
loadCommissionRecords()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空搜索
|
|
||||||
function clearSearch() {
|
|
||||||
searchKeyword.value = ''
|
|
||||||
page.value = 1
|
|
||||||
commissionRecords.value = []
|
|
||||||
loadCommissionRecords()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 来源筛选变化
|
|
||||||
function onSourceConfirm(option: { label: string, value: any }) {
|
function onSourceConfirm(option: { label: string, value: any }) {
|
||||||
sourceFilter.value = option.value
|
sourceFilter.value = option.value
|
||||||
page.value = 1
|
loadCommissionRecords(true)
|
||||||
commissionRecords.value = []
|
}
|
||||||
loadCommissionRecords()
|
|
||||||
|
function onSearchTypeConfirm(option: { label: string, value: any }) {
|
||||||
|
searchType.value = option.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载更多
|
|
||||||
function loadMore() {
|
function loadMore() {
|
||||||
if (commissionRecords.value.length >= total.value) {
|
if (commissionRecords.value.length < total.value) {
|
||||||
return
|
page.value++
|
||||||
|
loadCommissionRecords()
|
||||||
}
|
}
|
||||||
page.value++
|
|
||||||
loadCommissionRecords()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新
|
function onScroll(e: any) {
|
||||||
function refreshList() {
|
const { scrollTop, scrollHeight, clientHeight } = e.target
|
||||||
page.value = 1
|
if (scrollHeight - scrollTop - clientHeight < 100) {
|
||||||
commissionRecords.value = []
|
loadMore()
|
||||||
loadCommissionSummary()
|
}
|
||||||
loadCommissionStats()
|
|
||||||
loadCommissionRecords()
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="bg-[var(--bg-page)] min-h-screen pb-safe">
|
<view class="bg-page min-h-screen">
|
||||||
<view v-if="loading" class="pt-20 center">
|
<!-- 顶部搜索区域 -->
|
||||||
<text class="text-14px text-[var(--text-secondary)]">加载中...</text>
|
<view class="bg-white px-4 pt-4 pb-3">
|
||||||
</view>
|
<!-- 搜索框 -->
|
||||||
|
<view class="relative flex items-center">
|
||||||
<view v-else>
|
<input
|
||||||
<view class="bg-brand px-4 py-3 mx-4 mt-4 rounded-12px">
|
v-model="searchKeyword"
|
||||||
<text class="text-11px text-white/60">可提现佣金</text>
|
class="flex-1 h-10 bg-[#f1f5f9] rounded-full pl-4 pr-12 text-sm text-[#1e293b] placeholder-[#94a3b8]"
|
||||||
<text class="text-24px font-700 text-white block mt-1">
|
:placeholder="searchType === 'iccid' ? '搜索ICCID' : searchType === 'virtual_no' ? '搜索虚拟号' : '搜索订单号'"
|
||||||
{{ commissionSummary ? formatAmount(commissionSummary.available_commission) : '--' }}
|
@confirm="handleSearch"
|
||||||
</text>
|
/>
|
||||||
|
<view class="absolute right-1 flex items-center">
|
||||||
|
<view v-if="searchKeyword" class="w-8 h-8 flex items-center justify-center text-[#94a3b8]"
|
||||||
|
@click="searchKeyword = ''">
|
||||||
|
<i class="i-mdi-close-circle text-lg" />
|
||||||
|
</view>
|
||||||
|
<view class="w-8 h-8 flex items-center justify-center text-brand" @click="handleSearch">
|
||||||
|
<i class="i-mdi-magnify text-xl" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="bg-[var(--bg-container)] rounded-12px p-4 mx-4 mt-3">
|
<!-- 筛选器 -->
|
||||||
<view class="grid grid-cols-3 gap-4">
|
<view class="flex items-center gap-2 mt-3">
|
||||||
<view class="text-center">
|
<view class="flex items-center gap-1 px-3 py-1.5 bg-[#f8fafc] rounded-full" @click="showSearchTypePicker = true">
|
||||||
<text class="text-11px text-[var(--text-tertiary)] block">累计佣金</text>
|
<text class="text-12px text-[#64748b]">{{ searchType === 'iccid' ? 'ICCID' : searchType === 'virtual_no' ? '虚拟号' : '订单号' }}</text>
|
||||||
<text class="text-16px font-700 text-[var(--text-primary)] mt-1">
|
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||||
|
</view>
|
||||||
|
<view class="flex items-center gap-1 px-3 py-1.5 bg-[#f8fafc] rounded-full" @click="showSourcePicker = true">
|
||||||
|
<text class="text-12px" :class="sourceFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">{{ selectedSourceName }}</text>
|
||||||
|
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||||
|
</view>
|
||||||
|
<view v-if="sourceFilter !== undefined" class="flex items-center gap-1 px-2 py-1.5 rounded-full bg-[#ff4d4f]/10 text-[#ff4d4f]"
|
||||||
|
@click="sourceFilter = undefined; loadCommissionRecords(true)">
|
||||||
|
<i class="i-mdi-close text-12px" />
|
||||||
|
<text class="text-12px font-medium">清除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<view class="px-4 pb-4">
|
||||||
|
<!-- 概览卡片 -->
|
||||||
|
<view class="bg-white rounded-16px p-5 mt-4 shadow-[0_2px_12px_rgba(0,0,0,0.08)]">
|
||||||
|
<view class="flex items-center justify-between">
|
||||||
|
<view>
|
||||||
|
<text class="text-12px text-[#999]">可提现佣金</text>
|
||||||
|
<text class="text-32px font-700 text-[#212121] block mt-1">
|
||||||
|
{{ commissionSummary ? formatAmount(commissionSummary.available_commission) : '--' }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<image src="@/static/icons/佣金中心.png" class="w-12 h-12 rounded-12px" mode="aspectFit" />
|
||||||
|
</view>
|
||||||
|
<view class="flex gap-3 mt-4 pt-4 border-t border-[#f5f5f5]">
|
||||||
|
<view class="flex-1 text-center">
|
||||||
|
<text class="text-11px text-[#999]">累计佣金</text>
|
||||||
|
<text class="text-14px font-600 text-[#212121] block mt-1">
|
||||||
{{ commissionSummary ? formatAmount(commissionSummary.total_commission) : '--' }}
|
{{ commissionSummary ? formatAmount(commissionSummary.total_commission) : '--' }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-center">
|
<view class="flex-1 text-center border-l border-[#f5f5f5]">
|
||||||
<text class="text-11px text-[var(--text-tertiary)] block">冻结</text>
|
<text class="text-11px text-[#999]">已提现</text>
|
||||||
<text class="text-16px font-700 text-[var(--text-tertiary)] mt-1">
|
<text class="text-14px font-600 text-[#52c41a] block mt-1">
|
||||||
{{ commissionSummary ? formatAmount(commissionSummary.frozen_commission) : '--' }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
<view class="text-center">
|
|
||||||
<text class="text-11px text-[var(--text-tertiary)] block">已提现</text>
|
|
||||||
<text class="text-16px font-700 text-[#52c41a] mt-1">
|
|
||||||
{{ commissionSummary ? formatAmount(commissionSummary.withdrawn_commission) : '--' }}
|
{{ commissionSummary ? formatAmount(commissionSummary.withdrawn_commission) : '--' }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<view class="flex-1 text-center border-l border-[#f5f5f5]">
|
||||||
</view>
|
<text class="text-11px text-[#999]">冻结</text>
|
||||||
|
<text class="text-14px font-600 text-[#ff4d4f] block mt-1">
|
||||||
<view class="px-4 mt-4">
|
{{ commissionSummary ? formatAmount(commissionSummary.frozen_commission) : '--' }}
|
||||||
<text class="text-14px font-600 text-[var(--text-primary)] block mb-2">佣金统计</text>
|
|
||||||
<view class="bg-[var(--bg-container)] rounded-12px p-4">
|
|
||||||
<view class="flex items-center justify-between">
|
|
||||||
<text class="text-13px text-[var(--text-secondary)]">成本价差</text>
|
|
||||||
<view class="flex items-center gap-2">
|
|
||||||
<text class="text-14px font-600 text-[var(--text-primary)]">
|
|
||||||
{{ commissionStats ? formatAmount(commissionStats.cost_diff_amount) : '--' }}
|
|
||||||
</text>
|
|
||||||
<text class="text-11px text-[var(--text-tertiary)]">
|
|
||||||
{{ commissionStats ? (commissionStats.cost_diff_percent / 10).toFixed(1) + '%' : '--' }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-between mt-3">
|
|
||||||
<text class="text-13px text-[var(--text-secondary)]">一次性佣金</text>
|
|
||||||
<view class="flex items-center gap-2">
|
|
||||||
<text class="text-14px font-600 text-[var(--text-primary)]">
|
|
||||||
{{ commissionStats ? formatAmount(commissionStats.one_time_amount) : '--' }}
|
|
||||||
</text>
|
|
||||||
<text class="text-11px text-[var(--text-tertiary)]">
|
|
||||||
{{ commissionStats ? (commissionStats.one_time_percent / 10).toFixed(1) + '%' : '--' }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center justify-between mt-3 pt-3 border-t border-[var(--border-secondary)]">
|
|
||||||
<text class="text-13px font-600 text-[var(--text-primary)]">总计</text>
|
|
||||||
<text class="text-16px font-700 text-brand">
|
|
||||||
{{ commissionStats ? formatAmount(commissionStats.total_amount) : '--' }}
|
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="px-4 mt-4">
|
<!-- 佣金统计 -->
|
||||||
<text class="text-14px font-600 text-[var(--text-primary)] block mb-2">佣金明细</text>
|
<view class="bg-white rounded-16px p-4 mt-3 shadow-[0_2px_8px_rgba(0,0,0,0.04)]">
|
||||||
|
<text class="text-14px font-600 text-[#212121]">佣金统计</text>
|
||||||
<view class="flex items-center gap-2 mb-3">
|
<view class="mt-3 space-y-3">
|
||||||
<input
|
<view class="flex items-center justify-between">
|
||||||
v-model="searchKeyword"
|
<view class="flex items-center gap-2">
|
||||||
class="flex-1 h-40px bg-[var(--bg-container)] rounded-8px px-3 text-14px text-[var(--text-primary)]"
|
<view class="w-2 h-2 rounded-full bg-[#2196f3]" />
|
||||||
placeholder="搜索 ICCID / 虚拟号 / 订单号"
|
<text class="text-13px text-[#666]">成本价差</text>
|
||||||
placeholder-class="text-[var(--text-quaternary)]"
|
</view>
|
||||||
@confirm="handleSearch"
|
<view class="flex items-center gap-2">
|
||||||
>
|
<span class="text-11px text-[#999]">{{ commissionStats ? (commissionStats.cost_diff_percent / 10).toFixed(1) + '%' : '--' }}</span>
|
||||||
<view
|
<text class="text-14px font-600 text-[#212121]">{{ commissionStats ? formatAmount(commissionStats.cost_diff_amount) : '--' }}</text>
|
||||||
class="px-4 h-40px bg-brand text-white text-14px rounded-8px flex items-center justify-center"
|
</view>
|
||||||
@click="handleSearch"
|
</view>
|
||||||
>
|
<view class="flex items-center justify-between">
|
||||||
搜索
|
<view class="flex items-center gap-2">
|
||||||
</view>
|
<view class="w-2 h-2 rounded-full bg-[#ff9800]" />
|
||||||
</view>
|
<text class="text-13px text-[#666]">一次性佣金</text>
|
||||||
|
</view>
|
||||||
<view class="flex items-center gap-2 mb-3">
|
<view class="flex items-center gap-2">
|
||||||
<view class="flex-1 bg-[var(--bg-container)] rounded-8px px-3 h-40px flex items-center" @click="showSourcePicker = true">
|
<span class="text-11px text-[#999]">{{ commissionStats ? (commissionStats.one_time_percent / 10).toFixed(1) + '%' : '--' }}</span>
|
||||||
<text class="flex-1 text-14px text-[var(--text-primary)]">{{ selectedSourceName }}</text>
|
<text class="text-14px font-600 text-[#212121]">{{ commissionStats ? formatAmount(commissionStats.one_time_amount) : '--' }}</text>
|
||||||
<text class="text-12px text-[var(--text-tertiary)]">▼</text>
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex items-center justify-between pt-3 border-t border-[#f0f0f0]">
|
||||||
|
<text class="text-13px font-600 text-[#212121]">总计</text>
|
||||||
|
<text class="text-16px font-700 text-brand">{{ commissionStats ? formatAmount(commissionStats.total_amount) : '--' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 佣金明细 -->
|
||||||
|
<view class="mt-4">
|
||||||
<view class="flex items-center justify-between mb-3">
|
<view class="flex items-center justify-between mb-3">
|
||||||
<text class="text-12px text-[var(--text-secondary)]">共 {{ total }} 条记录</text>
|
<text class="text-14px font-600 text-[#212121]">佣金明细</text>
|
||||||
|
<text class="text-12px text-[#999]">共 {{ total }} 条</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="loadingRecords && page === 1" class="pt-10 center">
|
<view v-if="loadingRecords && page === 1" class="pt-20 flex justify-center">
|
||||||
<text class="text-14px text-[var(--text-secondary)]">加载中...</text>
|
<text class="text-14px text-[#64748b]">加载中...</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-else-if="commissionRecords.length > 0" class="space-y-2">
|
<view v-else-if="commissionRecords.length > 0" class="space-y-2">
|
||||||
<view
|
<view
|
||||||
v-for="record in commissionRecords"
|
v-for="record in commissionRecords"
|
||||||
:key="record.id"
|
:key="record.id"
|
||||||
class="bg-[var(--bg-container)] rounded-12px p-4"
|
class="bg-white rounded-12px p-4"
|
||||||
>
|
>
|
||||||
<view class="flex items-center justify-between">
|
<view class="flex items-center justify-between mb-2">
|
||||||
<view class="flex items-center gap-2">
|
<view class="flex items-center gap-2">
|
||||||
<text class="text-14px font-600 text-[var(--text-primary)]">
|
<text class="text-14px font-500 text-[#212121]">{{ getSourceText(record.commission_source) }}</text>
|
||||||
{{ getSourceText(record.commission_source) }}
|
<view :class="record.status === 1 ? 'bg-[#e8f5e9] text-[#2e7d32]' : 'bg-[#f5f5f5] text-[#999]'"
|
||||||
</text>
|
class="px-2 py-0.5 rounded text-11px">
|
||||||
<view
|
|
||||||
:style="{
|
|
||||||
backgroundColor: getStatusColor(record.status).bg,
|
|
||||||
color: getStatusColor(record.status).text,
|
|
||||||
}"
|
|
||||||
class="px-2 py-0.5 rounded text-11px font-600"
|
|
||||||
>
|
|
||||||
{{ getStatusText(record.status) }}
|
{{ getStatusText(record.status) }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="text-18px font-700 text-brand">
|
<text class="text-16px font-600 text-[#52c41a]">+{{ formatAmount(record.amount) }}</text>
|
||||||
+{{ formatAmount(record.amount) }}
|
|
||||||
</text>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="flex items-center justify-between mt-2">
|
<view class="flex items-center justify-between text-12px text-[#999]">
|
||||||
<text class="text-12px text-[var(--text-tertiary)]">{{ formatTime(record.created_at) }}</text>
|
<text>{{ formatTime(record.created_at) }}</text>
|
||||||
<text v-if="record.order_id" class="text-11px text-[var(--text-tertiary)]">订单ID: {{ record.order_id }}</text>
|
<text v-if="record.order_id">订单 {{ record.order_id }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="commissionRecords.length < total" class="py-3 center">
|
<view v-if="commissionRecords.length < total" class="py-4 text-center">
|
||||||
<text v-if="loadingRecords" class="text-12px text-[var(--text-secondary)]">加载中...</text>
|
<text v-if="loadingRecords" class="text-12px text-[#64748b]">加载中...</text>
|
||||||
<text v-else class="text-12px text-brand" @click="loadMore">加载更多</text>
|
<text v-else class="text-12px text-brand" @click="loadMore">加载更多</text>
|
||||||
</view>
|
</view>
|
||||||
|
<view v-else class="py-4 text-center">
|
||||||
|
<text class="text-12px text-[#cbd5e1]">没有更多了</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-else class="pt-10 center">
|
<view v-else class="pt-16 flex flex-col items-center">
|
||||||
<text class="text-14px text-[var(--text-secondary)]">暂无佣金记录</text>
|
<i class="i-mdi-file-document-outline text-5xl text-[#e0e0e0] mb-3" />
|
||||||
|
<text class="text-14px text-[#999]">{{ searchKeyword ? '未找到相关结果' : '暂无佣金记录' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="h-16" />
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<SimplePicker
|
<SimplePicker
|
||||||
@@ -388,30 +313,21 @@ function refreshList() {
|
|||||||
title="选择佣金来源"
|
title="选择佣金来源"
|
||||||
@confirm="onSourceConfirm"
|
@confirm="onSourceConfirm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<SimplePicker
|
||||||
|
v-model:show="showSearchTypePicker"
|
||||||
|
:options="searchTypeOptions"
|
||||||
|
title="选择搜索类型"
|
||||||
|
@confirm="onSearchTypeConfirm"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.center {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.space-y-2 > view:not(:last-child) {
|
.space-y-2 > view:not(:last-child) {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
.space-y-3 > view:not(:last-child) {
|
||||||
@keyframes spin {
|
margin-bottom: 12px;
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
.animate-spin {
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -6,46 +6,22 @@ import { createWithdrawal, getWithdrawalRecords } from '@/api/withdrawal'
|
|||||||
import type { WithdrawalRecord } from '@/api/withdrawal'
|
import type { WithdrawalRecord } from '@/api/withdrawal'
|
||||||
import SimplePicker from '@/components/SimplePicker.vue'
|
import SimplePicker from '@/components/SimplePicker.vue'
|
||||||
|
|
||||||
// 佣金概览
|
|
||||||
const commissionSummary = ref<FundSummary | null>(null)
|
const commissionSummary = ref<FundSummary | null>(null)
|
||||||
|
|
||||||
// 店铺ID (从登录信息获取)
|
|
||||||
const shopId = ref<number>(0)
|
const shopId = ref<number>(0)
|
||||||
|
|
||||||
// 从本地存储获取用户信息
|
|
||||||
function getUserInfo() {
|
|
||||||
const userInfo = uni.getStorageSync('user_info')
|
|
||||||
return userInfo || null
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提现金额(元)
|
|
||||||
const withdrawAmount = ref('')
|
const withdrawAmount = ref('')
|
||||||
|
|
||||||
// 账户信息
|
|
||||||
const accountName = ref('')
|
const accountName = ref('')
|
||||||
const accountNumber = ref('')
|
const accountNumber = ref('')
|
||||||
|
|
||||||
// 提现记录
|
|
||||||
const withdrawRecords = ref<WithdrawalRecord[]>([])
|
const withdrawRecords = ref<WithdrawalRecord[]>([])
|
||||||
|
|
||||||
// 当前Tab
|
|
||||||
const activeTab = ref<'apply' | 'records'>('apply')
|
const activeTab = ref<'apply' | 'records'>('apply')
|
||||||
|
|
||||||
// 加载状态
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const submitting = ref(false)
|
const submitting = ref(false)
|
||||||
const loadingRecords = ref(false)
|
const loadingRecords = ref(false)
|
||||||
|
|
||||||
// 分页参数
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
const pageSize = 20
|
const pageSize = 20
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
|
||||||
// 状态筛选
|
|
||||||
const statusFilter = ref<number | undefined>(undefined)
|
const statusFilter = ref<number | undefined>(undefined)
|
||||||
const showStatusPicker = ref(false)
|
const showStatusPicker = ref(false)
|
||||||
|
|
||||||
// 状态选项
|
|
||||||
const statusOptions = [
|
const statusOptions = [
|
||||||
{ label: '全部状态', value: undefined },
|
{ label: '全部状态', value: undefined },
|
||||||
{ label: '审核中', value: 1 },
|
{ label: '审核中', value: 1 },
|
||||||
@@ -54,53 +30,22 @@ const statusOptions = [
|
|||||||
{ label: '已到账', value: 4 },
|
{ label: '已到账', value: 4 },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 获取当前选中的状态名称
|
|
||||||
const selectedStatusName = computed(() => {
|
const selectedStatusName = computed(() => {
|
||||||
if (statusFilter.value === undefined) return '全部状态'
|
if (statusFilter.value === undefined) return '状态'
|
||||||
const option = statusOptions.find(o => o.value === statusFilter.value)
|
const option = statusOptions.find(o => o.value === statusFilter.value)
|
||||||
return option?.label || '全部状态'
|
return option?.label || '状态'
|
||||||
})
|
})
|
||||||
|
|
||||||
// Tab选项
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ key: 'apply', label: '申请提现' },
|
{ key: 'apply', label: '申请提现' },
|
||||||
{ key: 'records', label: '提现记录' },
|
{ key: 'records', label: '提现记录' },
|
||||||
]
|
]
|
||||||
|
|
||||||
// 可提现金额(分转元)
|
|
||||||
const availableAmount = computed(() => {
|
const availableAmount = computed(() => {
|
||||||
if (!commissionSummary.value) return 0
|
if (!commissionSummary.value) return 0
|
||||||
return commissionSummary.value.available_commission / 100
|
return commissionSummary.value.available_commission / 100
|
||||||
})
|
})
|
||||||
|
|
||||||
// 格式化可提现金额显示(带千分号)
|
|
||||||
const formattedAvailableAmount = computed(() => {
|
|
||||||
const amount = availableAmount.value.toFixed(2)
|
|
||||||
const parts = amount.split('.')
|
|
||||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
||||||
return parts.join('.')
|
|
||||||
})
|
|
||||||
|
|
||||||
// 实际到账金额 (无手续费,带千分号)
|
|
||||||
const actualAmount = computed(() => {
|
|
||||||
const amount = parseFloat(withdrawAmount.value) || 0
|
|
||||||
const fixed = amount.toFixed(2)
|
|
||||||
const parts = fixed.split('.')
|
|
||||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
||||||
return parts.join('.')
|
|
||||||
})
|
|
||||||
|
|
||||||
// 格式化输入金额显示 (带千分号)
|
|
||||||
const formattedWithdrawAmount = computed(() => {
|
|
||||||
if (!withdrawAmount.value) return '0.00'
|
|
||||||
const amount = parseFloat(withdrawAmount.value) || 0
|
|
||||||
const fixed = amount.toFixed(2)
|
|
||||||
const parts = fixed.split('.')
|
|
||||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
||||||
return parts.join('.')
|
|
||||||
})
|
|
||||||
|
|
||||||
// 格式化金额(分转元,带千分号)
|
|
||||||
function formatAmount(amount: number) {
|
function formatAmount(amount: number) {
|
||||||
const yuan = (amount / 100).toFixed(2)
|
const yuan = (amount / 100).toFixed(2)
|
||||||
const parts = yuan.split('.')
|
const parts = yuan.split('.')
|
||||||
@@ -108,226 +53,161 @@ function formatAmount(amount: number) {
|
|||||||
return `¥${parts.join('.')}`
|
return `¥${parts.join('.')}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取提现状态文本
|
|
||||||
function getStatusText(status: number, statusName?: string) {
|
function getStatusText(status: number, statusName?: string) {
|
||||||
if (statusName) return statusName
|
return statusName || (status === 1 ? '审核中' : status === 2 ? '已通过' : status === 3 ? '已拒绝' : status === 4 ? '已到账' : '未知')
|
||||||
const map: Record<number, string> = {
|
|
||||||
1: '审核中',
|
|
||||||
2: '已通过',
|
|
||||||
3: '已拒绝',
|
|
||||||
4: '已到账',
|
|
||||||
}
|
|
||||||
return map[status] || '未知'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取提现状态颜色
|
|
||||||
function getStatusColor(status: number) {
|
function getStatusColor(status: number) {
|
||||||
const map: Record<number, { bg: string, text: string }> = {
|
const map: Record<number, { bg: string, text: string }> = {
|
||||||
1: { bg: '#fff3e0', text: '#e65100' }, // 审核中
|
1: { bg: '#fff3e0', text: '#e65100' },
|
||||||
2: { bg: '#e8f5e9', text: '#2e7d32' }, // 已通过
|
2: { bg: '#e8f5e9', text: '#2e7d32' },
|
||||||
3: { bg: '#ffebee', text: '#c62828' }, // 已拒绝
|
3: { bg: '#ffebee', text: '#c62828' },
|
||||||
4: { bg: '#e3f2fd', text: '#1565c0' }, // 已到账
|
4: { bg: '#e3f2fd', text: '#1565c0' },
|
||||||
}
|
}
|
||||||
return map[status] || { bg: '#f5f5f5', text: '#999' }
|
return map[status] || { bg: '#f5f5f5', text: '#999' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化时间
|
|
||||||
function formatTime(time: string) {
|
function formatTime(time: string) {
|
||||||
if (!time) return '-'
|
if (!time) return '-'
|
||||||
const date = new Date(time)
|
const date = new Date(time)
|
||||||
const year = date.getFullYear()
|
return `${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
|
||||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
||||||
const day = String(date.getDate()).padStart(2, '0')
|
|
||||||
const hour = String(date.getHours()).padStart(2, '0')
|
|
||||||
const minute = String(date.getMinutes()).padStart(2, '0')
|
|
||||||
return `${year}-${month}-${day} ${hour}:${minute}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面加载
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 从登录信息获取 shop_id
|
const userInfo = uni.getStorageSync('user_info')
|
||||||
const userInfo = getUserInfo()
|
|
||||||
if (userInfo?.shop_id) {
|
if (userInfo?.shop_id) {
|
||||||
shopId.value = userInfo.shop_id
|
shopId.value = userInfo.shop_id
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCommissionSummary()
|
loadCommissionSummary()
|
||||||
loadWithdrawRecords()
|
loadWithdrawRecords()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 加载佣金概览
|
|
||||||
async function loadCommissionSummary() {
|
async function loadCommissionSummary() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const summary = await getFundSummary()
|
commissionSummary.value = await getFundSummary()
|
||||||
commissionSummary.value = summary
|
|
||||||
withdrawAmount.value = availableAmount.value.toFixed(2)
|
withdrawAmount.value = availableAmount.value.toFixed(2)
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
|
||||||
console.error('加载佣金概览失败:', error)
|
console.error('加载佣金概览失败:', error)
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载提现记录
|
async function loadWithdrawRecords(isRefresh = false) {
|
||||||
async function loadWithdrawRecords() {
|
|
||||||
if (!shopId.value) return
|
if (!shopId.value) return
|
||||||
|
if (isRefresh) {
|
||||||
|
page.value = 1
|
||||||
|
withdrawRecords.value = []
|
||||||
|
}
|
||||||
loadingRecords.value = true
|
loadingRecords.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const params: any = {
|
const params: any = { page: page.value, page_size: pageSize }
|
||||||
page: page.value,
|
|
||||||
page_size: pageSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 状态筛选
|
|
||||||
if (statusFilter.value !== undefined) {
|
if (statusFilter.value !== undefined) {
|
||||||
params.status = statusFilter.value
|
params.status = statusFilter.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await getWithdrawalRecords(shopId.value, params)
|
const response = await getWithdrawalRecords(shopId.value, params)
|
||||||
|
|
||||||
if (page.value === 1) {
|
if (page.value === 1) {
|
||||||
withdrawRecords.value = response.items || []
|
withdrawRecords.value = response.items || []
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
withdrawRecords.value.push(...(response.items || []))
|
withdrawRecords.value.push(...(response.items || []))
|
||||||
}
|
}
|
||||||
|
|
||||||
total.value = response.total || 0
|
total.value = response.total || 0
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
|
||||||
console.error('加载提现记录失败:', error)
|
console.error('加载提现记录失败:', error)
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
loadingRecords.value = false
|
loadingRecords.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 快捷金额按钮
|
|
||||||
function setQuickAmount(amount: number) {
|
function setQuickAmount(amount: number) {
|
||||||
withdrawAmount.value = amount.toString()
|
withdrawAmount.value = amount.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 全部提现
|
|
||||||
function setAllAmount() {
|
function setAllAmount() {
|
||||||
withdrawAmount.value = availableAmount.value.toFixed(2)
|
withdrawAmount.value = availableAmount.value.toFixed(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交提现申请
|
|
||||||
async function handleSubmit() {
|
async function handleSubmit() {
|
||||||
// 校验
|
|
||||||
const amount = parseFloat(withdrawAmount.value)
|
const amount = parseFloat(withdrawAmount.value)
|
||||||
if (!amount || amount <= 0) {
|
if (!amount || amount <= 0) {
|
||||||
uni.$u.toast('请输入提现金额')
|
uni.$u.toast('请输入提现金额')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount > availableAmount.value) {
|
if (amount > availableAmount.value) {
|
||||||
uni.$u.toast('提现金额超过可用余额')
|
uni.$u.toast('提现金额超过可用余额')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = accountName.value.trim()
|
const name = accountName.value.trim()
|
||||||
if (!name) {
|
if (!name) {
|
||||||
uni.$u.toast('请输入收款人姓名')
|
uni.$u.toast('请输入收款人姓名')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!/^[\u4e00-\u9fa5]{2,20}$|^[a-zA-Z]{2,20}$/.test(name)) {
|
|
||||||
uni.$u.toast('姓名格式错误')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const account = accountNumber.value.trim()
|
const account = accountNumber.value.trim()
|
||||||
if (!account) {
|
if (!account) {
|
||||||
uni.$u.toast('请输入支付宝账号')
|
uni.$u.toast('请输入支付宝账号')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const phoneRegex = /^1[3-9]\d{9}$/
|
|
||||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
|
||||||
if (!phoneRegex.test(account) && !emailRegex.test(account)) {
|
|
||||||
uni.$u.toast('支付宝账号格式错误')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await createWithdrawal(shopId.value, {
|
await createWithdrawal(shopId.value, {
|
||||||
account_name: name,
|
account_name: name,
|
||||||
account_number: account,
|
account_number: account,
|
||||||
amount: Math.round(amount * 100),
|
amount: Math.round(amount * 100),
|
||||||
withdrawal_method: 'alipay',
|
withdrawal_method: 'alipay',
|
||||||
})
|
})
|
||||||
|
|
||||||
uni.$u.toast('提现申请已提交')
|
uni.$u.toast('提现申请已提交')
|
||||||
|
|
||||||
withdrawAmount.value = ''
|
withdrawAmount.value = ''
|
||||||
accountName.value = ''
|
accountName.value = ''
|
||||||
accountNumber.value = ''
|
accountNumber.value = ''
|
||||||
|
|
||||||
await loadCommissionSummary()
|
await loadCommissionSummary()
|
||||||
page.value = 1
|
page.value = 1
|
||||||
await loadWithdrawRecords()
|
await loadWithdrawRecords()
|
||||||
|
|
||||||
activeTab.value = 'records'
|
activeTab.value = 'records'
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
|
||||||
console.error('提现申请失败:', error)
|
console.error('提现申请失败:', error)
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
submitting.value = false
|
submitting.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换Tab
|
|
||||||
function handleTabChange(tab: 'apply' | 'records') {
|
function handleTabChange(tab: 'apply' | 'records') {
|
||||||
activeTab.value = tab
|
activeTab.value = tab
|
||||||
if (tab === 'records') {
|
if (tab === 'records') {
|
||||||
page.value = 1
|
loadWithdrawRecords(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStatusConfirm(option: { label: string, value: any }) {
|
||||||
|
statusFilter.value = option.value
|
||||||
|
loadWithdrawRecords(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMore() {
|
||||||
|
if (withdrawRecords.value.length < total.value) {
|
||||||
|
page.value++
|
||||||
loadWithdrawRecords()
|
loadWithdrawRecords()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 状态筛选变化
|
function onScroll(e: any) {
|
||||||
function onStatusConfirm(option: { label: string, value: any }) {
|
const { scrollTop, scrollHeight, clientHeight } = e.target
|
||||||
statusFilter.value = option.value
|
if (scrollHeight - scrollTop - clientHeight < 100) {
|
||||||
page.value = 1
|
loadMore()
|
||||||
withdrawRecords.value = []
|
|
||||||
loadWithdrawRecords()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载更多
|
|
||||||
function loadMore() {
|
|
||||||
if (withdrawRecords.value.length >= total.value) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
page.value++
|
|
||||||
loadWithdrawRecords()
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="bg-[var(--bg-page)] min-h-screen pb-safe">
|
<view class="bg-page min-h-screen">
|
||||||
<view class="bg-brand rounded-12px px-4 py-3 mx-4">
|
<!-- 顶部搜索区域 -->
|
||||||
<text class="text-11px text-white/60">可提现金额</text>
|
<view class="bg-white px-4 pt-4 pb-3">
|
||||||
<text class="text-24px font-700 text-white block mt-1">¥{{ formattedAvailableAmount }}</text>
|
<view class="flex rounded-full bg-[#f1f5f9] p-1">
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="px-4 mt-4">
|
|
||||||
<view class="flex rounded-full bg-[var(--bg-container)] p-1">
|
|
||||||
<view
|
<view
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
:key="tab.key"
|
:key="tab.key"
|
||||||
:class="[
|
class="flex-1 text-center py-2 rounded-full text-14px font-medium transition-all"
|
||||||
'flex-1 text-center py-2 rounded-full text-14px transition-all',
|
:class="activeTab === tab.key ? 'bg-white text-[#212121] shadow-sm' : 'text-[#999]'"
|
||||||
activeTab === tab.key
|
|
||||||
? 'bg-brand text-white font-600'
|
|
||||||
: 'text-[var(--text-secondary)]',
|
|
||||||
]"
|
|
||||||
@click="handleTabChange(tab.key)"
|
@click="handleTabChange(tab.key)"
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
@@ -335,136 +215,145 @@ function loadMore() {
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="activeTab === 'apply'" class="px-4 mt-4">
|
<!-- 内容区域 -->
|
||||||
<view class="bg-[var(--bg-container)] rounded-12px p-4">
|
<view class="px-4 pb-4">
|
||||||
<text class="text-12px text-[var(--text-tertiary)]">提现金额</text>
|
<!-- 申请提现 -->
|
||||||
<view class="flex items-center mt-1">
|
<view v-if="activeTab === 'apply'">
|
||||||
<text class="text-24px text-[var(--text-secondary)] mr-1">¥</text>
|
<!-- 可提现金额卡片 -->
|
||||||
<input
|
<view class="bg-white rounded-16px p-5 mt-4 shadow-[0_2px_12px_rgba(0,0,0,0.08)]">
|
||||||
v-model="withdrawAmount"
|
|
||||||
type="digit"
|
|
||||||
class="flex-1 text-24px text-[var(--text-primary)]"
|
|
||||||
placeholder="0.00"
|
|
||||||
placeholder-class="text-[var(--text-quaternary)]"
|
|
||||||
>
|
|
||||||
</view>
|
|
||||||
<view class="flex items-center gap-2 mt-3">
|
|
||||||
<view
|
|
||||||
v-for="amount in [100, 500, 1000]"
|
|
||||||
:key="amount"
|
|
||||||
:class="[
|
|
||||||
'px-4 py-1.5 text-13px rounded-full transition-all',
|
|
||||||
withdrawAmount == amount.toString()
|
|
||||||
? 'bg-brand text-white font-600'
|
|
||||||
: 'bg-[var(--bg-muted)] text-[var(--text-secondary)]',
|
|
||||||
]"
|
|
||||||
@click="setQuickAmount(amount)"
|
|
||||||
>
|
|
||||||
{{ amount }}
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
:class="[
|
|
||||||
'px-4 py-1.5 text-13px rounded-full transition-all font-500',
|
|
||||||
withdrawAmount == availableAmount.toFixed(2)
|
|
||||||
? 'bg-brand text-white'
|
|
||||||
: 'bg-[var(--bg-muted)] text-[var(--text-secondary)]',
|
|
||||||
]"
|
|
||||||
@click="setAllAmount"
|
|
||||||
>
|
|
||||||
全部
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="bg-[var(--bg-container)] rounded-12px p-4 mt-3">
|
|
||||||
<text class="text-12px text-[var(--text-tertiary)]">收款人姓名</text>
|
|
||||||
<input
|
|
||||||
v-model="accountName"
|
|
||||||
class="w-full text-16px text-[var(--text-primary)] mt-1"
|
|
||||||
placeholder="请输入姓名"
|
|
||||||
placeholder-class="text-[var(--text-quaternary)]"
|
|
||||||
>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="bg-[var(--bg-container)] rounded-12px p-4 mt-3">
|
|
||||||
<text class="text-12px text-[var(--text-tertiary)]">支付宝账号</text>
|
|
||||||
<input
|
|
||||||
v-model="accountNumber"
|
|
||||||
class="w-full text-16px text-[var(--text-primary)] mt-1"
|
|
||||||
placeholder="请输入账号"
|
|
||||||
placeholder-class="text-[var(--text-quaternary)]"
|
|
||||||
>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="bg-[var(--bg-container)] rounded-12px p-4 mt-3">
|
|
||||||
<view class="flex items-center justify-between">
|
|
||||||
<text class="text-14px text-[var(--text-secondary)]">提现金额</text>
|
|
||||||
<text class="text-20px font-600 text-brand">¥{{ formattedWithdrawAmount }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view
|
|
||||||
:class="[
|
|
||||||
'w-full py-4 rounded-12px text-center text-16px font-600 mt-4',
|
|
||||||
submitting ? 'bg-[var(--bg-muted)] text-[var(--text-quaternary)]' : 'bg-brand text-white',
|
|
||||||
]"
|
|
||||||
@click="handleSubmit"
|
|
||||||
>
|
|
||||||
{{ submitting ? '提交中...' : '确认提现' }}
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-else class="px-4 mt-4">
|
|
||||||
<view class="flex items-center gap-2 mb-3">
|
|
||||||
<view class="flex-1 bg-[var(--bg-container)] rounded-12px px-4 py-3" @click="showStatusPicker = true">
|
|
||||||
<text class="text-14px text-[var(--text-primary)]">{{ selectedStatusName }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-if="loadingRecords && page === 1" class="pt-10 center">
|
|
||||||
<text class="text-14px text-[var(--text-secondary)]">加载中...</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view v-else-if="withdrawRecords.length > 0" class="space-y-3">
|
|
||||||
<view
|
|
||||||
v-for="record in withdrawRecords"
|
|
||||||
:key="record.id"
|
|
||||||
class="bg-[var(--bg-container)] rounded-12px p-4"
|
|
||||||
>
|
|
||||||
<view class="flex items-center justify-between">
|
<view class="flex items-center justify-between">
|
||||||
<text class="text-13px text-[var(--text-tertiary)]">{{ formatTime(record.created_at) }}</text>
|
<view>
|
||||||
|
<text class="text-12px text-[#999]">可提现金额</text>
|
||||||
|
<text class="text-32px font-700 text-[#212121] block mt-1">
|
||||||
|
¥{{ availableAmount.toFixed(2) }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<image src="@/static/icons/提现管理.png" class="w-12 h-12 rounded-12px" mode="aspectFit" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 提现金额输入 -->
|
||||||
|
<view class="bg-white rounded-16px p-4 mt-3">
|
||||||
|
<text class="text-12px text-[#999]">提现金额</text>
|
||||||
|
<view class="flex items-center mt-2">
|
||||||
|
<text class="text-24px text-[#212121] mr-2">¥</text>
|
||||||
|
<input
|
||||||
|
v-model="withdrawAmount"
|
||||||
|
type="digit"
|
||||||
|
class="flex-1 text-24px text-[#212121]"
|
||||||
|
placeholder="0.00"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="flex gap-2 mt-3">
|
||||||
<view
|
<view
|
||||||
:style="{
|
v-for="amount in [100, 500, 1000]"
|
||||||
backgroundColor: getStatusColor(record.status).bg,
|
:key="amount"
|
||||||
color: getStatusColor(record.status).text,
|
class="px-4 py-2 rounded-full text-13px"
|
||||||
}"
|
:class="withdrawAmount == amount.toString() ? 'bg-brand text-white' : 'bg-[#f1f5f9] text-[#666]'"
|
||||||
class="px-3 py-1 rounded-full text-12px font-600"
|
@click="setQuickAmount(amount)"
|
||||||
>
|
>
|
||||||
{{ getStatusText(record.status, record.status_name) }}
|
¥{{ amount }}
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="px-4 py-2 rounded-full text-13px"
|
||||||
|
:class="withdrawAmount == availableAmount.toFixed(2) ? 'bg-brand text-white' : 'bg-[#f1f5f9] text-[#666]'"
|
||||||
|
@click="setAllAmount"
|
||||||
|
>
|
||||||
|
全部
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex items-center justify-between mt-3">
|
|
||||||
<text class="text-14px text-[var(--text-secondary)]">{{ record.account_name }}</text>
|
|
||||||
<text class="text-20px font-700 text-brand">-{{ formatAmount(record.amount) }}</text>
|
|
||||||
</view>
|
|
||||||
<view v-if="record.status === 3 && record.reject_reason" class="mt-2 pt-2 border-t border-[var(--border-secondary)]">
|
|
||||||
<text class="text-12px text-[var(--color-error)]">{{ record.reject_reason }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="withdrawRecords.length < total" class="py-4 center">
|
<!-- 收款信息 -->
|
||||||
<text v-if="loadingRecords" class="text-14px text-[var(--text-secondary)]">加载中...</text>
|
<view class="bg-white rounded-16px p-4 mt-3">
|
||||||
<text v-else class="text-14px text-[var(--brand-primary)]" @click="loadMore">加载更多</text>
|
<text class="text-12px text-[#999]">收款人姓名</text>
|
||||||
|
<input
|
||||||
|
v-model="accountName"
|
||||||
|
class="w-full text-16px text-[#212121] mt-2"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="bg-white rounded-16px p-4 mt-3">
|
||||||
|
<text class="text-12px text-[#999]">支付宝账号</text>
|
||||||
|
<input
|
||||||
|
v-model="accountNumber"
|
||||||
|
class="w-full text-16px text-[#212121] mt-2"
|
||||||
|
placeholder="请输入账号"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 提交按钮 -->
|
||||||
|
<view
|
||||||
|
class="bg-brand rounded-full py-4 text-center text-16px font-600 text-white mt-6"
|
||||||
|
:class="{ 'opacity-50': submitting }"
|
||||||
|
@click="handleSubmit"
|
||||||
|
>
|
||||||
|
{{ submitting ? '提交中...' : '确认提现' }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-else class="pt-16 center">
|
<!-- 提现记录 -->
|
||||||
<text class="text-14px text-[var(--text-secondary)]">暂无记录</text>
|
<view v-else>
|
||||||
|
<view class="flex items-center gap-2 mt-4 mb-3">
|
||||||
|
<view class="flex items-center gap-1 px-3 py-1.5 bg-[#f8fafc] rounded-full" @click="showStatusPicker = true">
|
||||||
|
<text class="text-12px text-[#64748b]">{{ selectedStatusName }}</text>
|
||||||
|
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="statusFilter !== undefined"
|
||||||
|
class="flex items-center gap-1 px-2 py-1.5 rounded-full bg-[#ff4d4f]/10 text-[#ff4d4f]"
|
||||||
|
@click="statusFilter = undefined; loadWithdrawRecords(true)"
|
||||||
|
>
|
||||||
|
<i class="i-mdi-close text-12px" />
|
||||||
|
<text class="text-12px font-medium">清除</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="loadingRecords && page === 1" class="pt-20 flex justify-center">
|
||||||
|
<text class="text-14px text-[#64748b]">加载中...</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else-if="withdrawRecords.length > 0" class="space-y-3">
|
||||||
|
<view
|
||||||
|
v-for="record in withdrawRecords"
|
||||||
|
:key="record.id"
|
||||||
|
class="bg-white rounded-12px p-4"
|
||||||
|
>
|
||||||
|
<view class="flex items-center justify-between mb-2">
|
||||||
|
<text class="text-12px text-[#999]">{{ formatTime(record.created_at) }}</text>
|
||||||
|
<view
|
||||||
|
:style="{ backgroundColor: getStatusColor(record.status).bg, color: getStatusColor(record.status).text }"
|
||||||
|
class="px-2 py-0.5 rounded text-11px font-500"
|
||||||
|
>
|
||||||
|
{{ getStatusText(record.status, record.status_name) }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex items-center justify-between">
|
||||||
|
<text class="text-14px text-[#666]">{{ record.account_name }}</text>
|
||||||
|
<text class="text-18px font-600 text-[#ff4d4f]">-{{ formatAmount(record.amount) }}</text>
|
||||||
|
</view>
|
||||||
|
<view v-if="record.status === 3 && record.reject_reason" class="mt-2 pt-2 border-t border-[#f0f0f0]">
|
||||||
|
<text class="text-12px text-[#ff4d4f]">拒绝原因: {{ record.reject_reason }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="withdrawRecords.length < total" class="py-4 text-center">
|
||||||
|
<text v-if="loadingRecords" class="text-12px text-[#64748b]">加载中...</text>
|
||||||
|
<text v-else class="text-12px text-brand" @click="loadMore">加载更多</text>
|
||||||
|
</view>
|
||||||
|
<view v-else class="py-4 text-center">
|
||||||
|
<text class="text-12px text-[#cbd5e1]">没有更多了</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else class="pt-16 flex flex-col items-center">
|
||||||
|
<i class="i-mdi-file-document-outline text-5xl text-[#e0e0e0] mb-3" />
|
||||||
|
<text class="text-14px text-[#999]">暂无提现记录</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="h-16" />
|
|
||||||
|
|
||||||
<SimplePicker
|
<SimplePicker
|
||||||
v-model:show="showStatusPicker"
|
v-model:show="showStatusPicker"
|
||||||
:options="statusOptions"
|
:options="statusOptions"
|
||||||
@@ -475,26 +364,7 @@ function loadMore() {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.center {
|
.space-y-3 > view:not(:last-child) {
|
||||||
display: flex;
|
margin-bottom: 12px;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
.space-y-2 > view:not(:last-child) {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-spin {
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user