111
This commit is contained in:
241
monisuo-admin/src/pages/monisuo/admins.vue
Normal file
241
monisuo-admin/src/pages/monisuo/admins.vue
Normal file
@@ -0,0 +1,241 @@
|
||||
<script lang="ts" setup>
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
import type { AdminRecord } from '@/services/api/monisuo-admin.api'
|
||||
|
||||
import { BasicPage } from '@/components/global-layout'
|
||||
import { useCreateAdminMutation, useGetAdminListQuery, useToggleAdminStatusMutation } from '@/services/api/monisuo-admin.api'
|
||||
|
||||
const { data, isLoading, refetch } = useGetAdminListQuery()
|
||||
const createMutation = useCreateAdminMutation()
|
||||
const toggleStatusMutation = useToggleAdminStatusMutation()
|
||||
|
||||
const admins = computed(() => data.value?.data || [])
|
||||
|
||||
const showCreateDialog = ref(false)
|
||||
const newAdmin = ref({ username: '', password: '', nickname: '', role: 2 as number })
|
||||
|
||||
function openCreateDialog() {
|
||||
newAdmin.value = { username: '', password: '', nickname: '', role: 2 }
|
||||
showCreateDialog.value = true
|
||||
}
|
||||
|
||||
async function createAdmin() {
|
||||
if (!newAdmin.value.username || !newAdmin.value.password) {
|
||||
toast.error('请输入用户名和密码')
|
||||
return
|
||||
}
|
||||
if (newAdmin.value.password.length < 4) {
|
||||
toast.error('密码至少4位')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await createMutation.mutateAsync(newAdmin.value)
|
||||
toast.success('创建成功')
|
||||
showCreateDialog.value = false
|
||||
refetch()
|
||||
}
|
||||
catch (e: any) {
|
||||
toast.error(e.message || e.response?.data?.msg || '创建失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleStatus(admin: AdminRecord) {
|
||||
if (admin.isSystem === 1) {
|
||||
toast.error('系统预置管理员不可操作')
|
||||
return
|
||||
}
|
||||
const newStatus = admin.status === 1 ? 0 : 1
|
||||
try {
|
||||
await toggleStatusMutation.mutateAsync({ id: admin.id, status: newStatus })
|
||||
toast.success(newStatus === 1 ? '已启用' : '已禁用')
|
||||
refetch()
|
||||
}
|
||||
catch (e: any) {
|
||||
toast.error(e.message || e.response?.data?.msg || '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
function roleText(role: number) {
|
||||
if (role === 1) return '超级管理员'
|
||||
if (role === 2) return '管理员'
|
||||
if (role === 3) return '财务'
|
||||
return '未知'
|
||||
}
|
||||
|
||||
function roleBadge(role: number) {
|
||||
if (role === 1) return 'default'
|
||||
if (role === 3) return 'outline'
|
||||
return 'secondary'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicPage title="管理员管理" description="管理系统管理员和财务账号">
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-end">
|
||||
<UiButton @click="openCreateDialog">
|
||||
<Icon icon="lucide:plus" class="size-4 mr-2" />
|
||||
新增账号
|
||||
</UiButton>
|
||||
</div>
|
||||
|
||||
<!-- PC端表格 -->
|
||||
<UiCard class="hidden md:block overflow-x-auto p-4">
|
||||
<UiTable>
|
||||
<UiTableHeader>
|
||||
<UiTableRow>
|
||||
<UiTableHead class="w-[80px]">
|
||||
ID
|
||||
</UiTableHead>
|
||||
<UiTableHead>用户名</UiTableHead>
|
||||
<UiTableHead>昵称</UiTableHead>
|
||||
<UiTableHead>角色</UiTableHead>
|
||||
<UiTableHead>状态</UiTableHead>
|
||||
<UiTableHead>创建时间</UiTableHead>
|
||||
<UiTableHead class="text-right">
|
||||
操作
|
||||
</UiTableHead>
|
||||
</UiTableRow>
|
||||
</UiTableHeader>
|
||||
<UiTableBody>
|
||||
<UiTableRow v-if="isLoading">
|
||||
<UiTableCell :col-span="7" class="text-center py-8">
|
||||
<UiSpinner class="mx-auto" />
|
||||
</UiTableCell>
|
||||
</UiTableRow>
|
||||
<UiTableRow v-else-if="admins.length === 0">
|
||||
<UiTableCell :col-span="7" class="text-center py-8 text-muted-foreground">
|
||||
暂无数据
|
||||
</UiTableCell>
|
||||
</UiTableRow>
|
||||
<UiTableRow v-for="admin in admins" :key="admin.id">
|
||||
<UiTableCell>{{ admin.id }}</UiTableCell>
|
||||
<UiTableCell class="font-mono font-medium">
|
||||
{{ admin.username }}
|
||||
</UiTableCell>
|
||||
<UiTableCell>{{ admin.nickname }}</UiTableCell>
|
||||
<UiTableCell>
|
||||
<UiBadge :variant="roleBadge(admin.role)">
|
||||
{{ roleText(admin.role) }}
|
||||
</UiBadge>
|
||||
</UiTableCell>
|
||||
<UiTableCell>
|
||||
<UiBadge :variant="admin.status === 1 ? 'default' : 'destructive'">
|
||||
{{ admin.status === 1 ? '正常' : '禁用' }}
|
||||
</UiBadge>
|
||||
</UiTableCell>
|
||||
<UiTableCell>{{ admin.createTime }}</UiTableCell>
|
||||
<UiTableCell class="text-right">
|
||||
<UiButton
|
||||
v-if="admin.isSystem !== 1"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
:disabled="toggleStatusMutation.isPending.value"
|
||||
@click="toggleStatus(admin)"
|
||||
>
|
||||
<Icon
|
||||
:icon="admin.status === 1 ? 'lucide:ban' : 'lucide:check-circle'"
|
||||
class="size-4"
|
||||
:class="admin.status === 1 ? 'text-destructive' : 'text-green-500'"
|
||||
/>
|
||||
</UiButton>
|
||||
</UiTableCell>
|
||||
</UiTableRow>
|
||||
</UiTableBody>
|
||||
</UiTable>
|
||||
</UiCard>
|
||||
|
||||
<!-- 移动端卡片 -->
|
||||
<div class="md:hidden space-y-3">
|
||||
<div v-if="isLoading" class="text-center py-8">
|
||||
<UiSpinner class="mx-auto" />
|
||||
</div>
|
||||
<template v-else-if="admins.length > 0">
|
||||
<UiCard v-for="admin in admins" :key="admin.id" class="p-4">
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<div class="font-mono font-bold">
|
||||
{{ admin.username }}
|
||||
</div>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
{{ admin.nickname }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-1">
|
||||
<UiBadge :variant="roleBadge(admin.role)">
|
||||
{{ roleText(admin.role) }}
|
||||
</UiBadge>
|
||||
<UiBadge :variant="admin.status === 1 ? 'default' : 'destructive'">
|
||||
{{ admin.status === 1 ? '正常' : '禁用' }}
|
||||
</UiBadge>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="admin.isSystem !== 1" class="mt-2 flex justify-end">
|
||||
<UiButton
|
||||
size="sm"
|
||||
variant="outline"
|
||||
:disabled="toggleStatusMutation.isPending.value"
|
||||
@click="toggleStatus(admin)"
|
||||
>
|
||||
{{ admin.status === 1 ? '禁用' : '启用' }}
|
||||
</UiButton>
|
||||
</div>
|
||||
</UiCard>
|
||||
</template>
|
||||
<div v-else class="text-center py-8 text-muted-foreground">
|
||||
暂无数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 新增账号弹窗 -->
|
||||
<UiDialog v-model:open="showCreateDialog">
|
||||
<UiDialogContent class="max-w-md">
|
||||
<UiDialogHeader>
|
||||
<UiDialogTitle>新增账号</UiDialogTitle>
|
||||
</UiDialogHeader>
|
||||
<div class="grid gap-4 py-4">
|
||||
<div class="grid gap-2">
|
||||
<UiLabel>用户名 <span class="text-red-500">*</span></UiLabel>
|
||||
<UiInput v-model="newAdmin.username" placeholder="请输入用户名" />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<UiLabel>密码 <span class="text-red-500">*</span></UiLabel>
|
||||
<UiInput v-model="newAdmin.password" type="password" placeholder="至少4位" />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<UiLabel>昵称</UiLabel>
|
||||
<UiInput v-model="newAdmin.nickname" placeholder="可选" />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<UiLabel>角色 <span class="text-red-500">*</span></UiLabel>
|
||||
<UiSelect v-model="newAdmin.role">
|
||||
<UiSelectTrigger>
|
||||
<UiSelectValue placeholder="请选择角色" />
|
||||
</UiSelectTrigger>
|
||||
<UiSelectContent>
|
||||
<UiSelectItem :value="2">
|
||||
管理员
|
||||
</UiSelectItem>
|
||||
<UiSelectItem :value="3">
|
||||
财务
|
||||
</UiSelectItem>
|
||||
</UiSelectContent>
|
||||
</UiSelect>
|
||||
</div>
|
||||
</div>
|
||||
<UiDialogFooter>
|
||||
<UiButton variant="outline" @click="showCreateDialog = false">
|
||||
取消
|
||||
</UiButton>
|
||||
<UiButton :disabled="createMutation.isPending.value" @click="createAdmin">
|
||||
<UiSpinner v-if="createMutation.isPending.value" class="mr-2" />
|
||||
创建
|
||||
</UiButton>
|
||||
</UiDialogFooter>
|
||||
</UiDialogContent>
|
||||
</UiDialog>
|
||||
</BasicPage>
|
||||
</template>
|
||||
372
monisuo-admin/src/pages/monisuo/finance-orders.vue
Normal file
372
monisuo-admin/src/pages/monisuo/finance-orders.vue
Normal file
@@ -0,0 +1,372 @@
|
||||
<script lang="ts" setup>
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { toast } from 'vue-sonner'
|
||||
|
||||
import type { OrderFund } from '@/services/api/monisuo-admin.api'
|
||||
|
||||
import { BasicPage } from '@/components/global-layout'
|
||||
import { useApproveOrderMutation, useGetPendingOrdersQuery } from '@/services/api/monisuo-admin.api'
|
||||
|
||||
const pageNum = ref(1)
|
||||
const pageSize = ref(10)
|
||||
|
||||
const { data: pendingData, isLoading: pendingLoading, refetch: refetchPending } = useGetPendingOrdersQuery({
|
||||
pageNum: pageNum.value,
|
||||
pageSize: pageSize.value,
|
||||
})
|
||||
|
||||
const approveMutation = useApproveOrderMutation()
|
||||
|
||||
const pendingOrders = computed(() => pendingData.value?.data?.list || [])
|
||||
const pendingTotal = computed(() => pendingData.value?.data?.total || 0)
|
||||
const totalPages = computed(() => Math.ceil(pendingTotal.value / pageSize.value))
|
||||
|
||||
const showApproveDialog = ref(false)
|
||||
const showDetailDialog = ref(false)
|
||||
const currentOrder = ref<OrderFund | null>(null)
|
||||
const approveStatus = ref(2)
|
||||
const rejectReason = ref('')
|
||||
const adminRemark = ref('')
|
||||
|
||||
function viewOrderDetail(order: OrderFund) {
|
||||
currentOrder.value = order
|
||||
showDetailDialog.value = true
|
||||
}
|
||||
|
||||
function openApproveDialog(order: OrderFund, status: number) {
|
||||
currentOrder.value = order
|
||||
approveStatus.value = status
|
||||
rejectReason.value = ''
|
||||
adminRemark.value = ''
|
||||
showApproveDialog.value = true
|
||||
}
|
||||
|
||||
async function handleApprove() {
|
||||
if (!currentOrder.value)
|
||||
return
|
||||
|
||||
const action = approveStatus.value === 2 ? '通过' : '驳回'
|
||||
|
||||
try {
|
||||
await approveMutation.mutateAsync({
|
||||
orderNo: currentOrder.value.orderNo,
|
||||
status: approveStatus.value,
|
||||
rejectReason: rejectReason.value || undefined,
|
||||
adminRemark: adminRemark.value || undefined,
|
||||
})
|
||||
|
||||
toast.success(`订单已${action}`)
|
||||
showApproveDialog.value = false
|
||||
refetchPending()
|
||||
}
|
||||
catch (e: any) {
|
||||
toast.error(e.message || e.response?.data?.msg || `${action}失败`)
|
||||
}
|
||||
}
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
pageNum.value = page
|
||||
refetchPending()
|
||||
}
|
||||
|
||||
function handlePageSizeChange(size: unknown) {
|
||||
if (size === null || size === undefined)
|
||||
return
|
||||
pageSize.value = Number(size)
|
||||
pageNum.value = 1
|
||||
refetchPending()
|
||||
}
|
||||
|
||||
function formatAmount(amount: number): string {
|
||||
return amount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
|
||||
}
|
||||
|
||||
function copyToClipboard(text: string) {
|
||||
navigator.clipboard.writeText(text)
|
||||
toast.success('已复制到剪贴板')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicPage title="财务审批" description="审批提现订单">
|
||||
<div class="space-y-4">
|
||||
<!-- 提现待财务审核列表 -->
|
||||
<UiCard class="hidden md:block overflow-x-auto p-4">
|
||||
<UiTable>
|
||||
<UiTableHeader>
|
||||
<UiTableRow>
|
||||
<UiTableHead>订单号</UiTableHead>
|
||||
<UiTableHead>用户</UiTableHead>
|
||||
<UiTableHead class="text-right">
|
||||
提现金额
|
||||
</UiTableHead>
|
||||
<UiTableHead class="text-right">
|
||||
手续费
|
||||
</UiTableHead>
|
||||
<UiTableHead class="text-right">
|
||||
应收款项
|
||||
</UiTableHead>
|
||||
<UiTableHead>审批人</UiTableHead>
|
||||
<UiTableHead class="hidden xl:table-cell">
|
||||
时间
|
||||
</UiTableHead>
|
||||
<UiTableHead class="text-right">
|
||||
操作
|
||||
</UiTableHead>
|
||||
</UiTableRow>
|
||||
</UiTableHeader>
|
||||
<UiTableBody>
|
||||
<UiTableRow v-if="pendingLoading">
|
||||
<UiTableCell :col-span="8" class="text-center py-8">
|
||||
<UiSpinner class="mx-auto" />
|
||||
</UiTableCell>
|
||||
</UiTableRow>
|
||||
<UiTableRow v-else-if="pendingOrders.length === 0">
|
||||
<UiTableCell :col-span="8" class="text-center py-8 text-muted-foreground">
|
||||
<Icon icon="lucide:inbox" class="size-8 mx-auto mb-2 opacity-50" />
|
||||
<p>暂无待审核订单</p>
|
||||
</UiTableCell>
|
||||
</UiTableRow>
|
||||
<UiTableRow v-for="order in pendingOrders" :key="order.id">
|
||||
<UiTableCell class="font-mono text-xs">
|
||||
{{ order.orderNo }}
|
||||
</UiTableCell>
|
||||
<UiTableCell>{{ order.username }}</UiTableCell>
|
||||
<UiTableCell class="text-right font-mono font-medium">
|
||||
${{ formatAmount(order.amount) }}
|
||||
</UiTableCell>
|
||||
<UiTableCell class="text-right font-mono text-muted-foreground">
|
||||
-${{ formatAmount(order.fee || 0) }}
|
||||
</UiTableCell>
|
||||
<UiTableCell class="text-right font-mono font-bold text-green-600">
|
||||
${{ formatAmount(order.receivableAmount || 0) }}
|
||||
</UiTableCell>
|
||||
<UiTableCell class="text-sm">
|
||||
{{ order.approveAdminName || '-' }}
|
||||
</UiTableCell>
|
||||
<UiTableCell class="hidden xl:table-cell text-muted-foreground text-sm">
|
||||
{{ order.createTime }}
|
||||
</UiTableCell>
|
||||
<UiTableCell class="text-right">
|
||||
<div class="flex justify-end gap-1">
|
||||
<UiButton size="sm" variant="ghost" @click="viewOrderDetail(order)">
|
||||
<Icon icon="lucide:eye" class="size-4" />
|
||||
</UiButton>
|
||||
<UiButton
|
||||
size="sm"
|
||||
:disabled="approveMutation.isPending.value"
|
||||
@click="openApproveDialog(order, 2)"
|
||||
>
|
||||
通过
|
||||
</UiButton>
|
||||
<UiButton
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
:disabled="approveMutation.isPending.value"
|
||||
@click="openApproveDialog(order, 3)"
|
||||
>
|
||||
驳回
|
||||
</UiButton>
|
||||
</div>
|
||||
</UiTableCell>
|
||||
</UiTableRow>
|
||||
</UiTableBody>
|
||||
</UiTable>
|
||||
</UiCard>
|
||||
|
||||
<!-- 移动端卡片 -->
|
||||
<div class="md:hidden space-y-3">
|
||||
<div v-if="pendingLoading" class="text-center py-8">
|
||||
<UiSpinner class="mx-auto" />
|
||||
</div>
|
||||
<template v-else-if="pendingOrders.length > 0">
|
||||
<UiCard v-for="order in pendingOrders" :key="order.id" class="p-4">
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="space-y-1">
|
||||
<div class="font-mono text-xs text-muted-foreground">
|
||||
{{ order.orderNo }}
|
||||
</div>
|
||||
<div class="font-medium">
|
||||
{{ order.username }}
|
||||
</div>
|
||||
</div>
|
||||
<UiBadge variant="secondary">
|
||||
待财务审核
|
||||
</UiBadge>
|
||||
</div>
|
||||
<div class="mt-3 pt-3 border-t">
|
||||
<div class="text-xl font-mono font-bold text-red-600 dark:text-red-400">
|
||||
-${{ formatAmount(order.amount) }}
|
||||
</div>
|
||||
<div class="text-sm text-muted-foreground mt-1">
|
||||
手续费: -${{ formatAmount(order.fee || 0) }} | 实际到账: ${{ formatAmount(order.receivableAmount || 0) }}
|
||||
</div>
|
||||
<div class="text-sm text-muted-foreground mt-1">
|
||||
审批人: {{ order.approveAdminName || '-' }}
|
||||
</div>
|
||||
<div v-if="order.walletAddress" class="mt-2 text-sm">
|
||||
<span class="text-muted-foreground">提现地址:</span>
|
||||
<div class="font-mono text-xs break-all mt-1 flex items-center gap-1">
|
||||
{{ order.walletAddress }}
|
||||
<Icon icon="lucide:copy" class="size-3 cursor-pointer" @click="copyToClipboard(order.walletAddress!)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-muted-foreground mt-1">
|
||||
{{ order.createTime }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 flex gap-2">
|
||||
<UiButton size="sm" class="flex-1" @click="openApproveDialog(order, 2)">
|
||||
通过
|
||||
</UiButton>
|
||||
<UiButton size="sm" variant="destructive" class="flex-1" @click="openApproveDialog(order, 3)">
|
||||
驳回
|
||||
</UiButton>
|
||||
</div>
|
||||
</UiCard>
|
||||
</template>
|
||||
<div v-else class="text-center py-8 text-muted-foreground">
|
||||
<Icon icon="lucide:inbox" class="size-8 mx-auto mb-2 opacity-50" />
|
||||
<p>暂无待审核订单</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div v-if="pendingTotal > 0" class="flex items-center justify-between gap-4 px-2">
|
||||
<div class="text-sm text-muted-foreground">
|
||||
共 {{ pendingTotal }} 条待审核
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<UiButton
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-8 w-8"
|
||||
:disabled="pageNum <= 1"
|
||||
@click="handlePageChange(pageNum - 1)"
|
||||
>
|
||||
<Icon icon="lucide:chevron-left" class="size-4" />
|
||||
</UiButton>
|
||||
<span class="text-sm min-w-[80px] text-center">
|
||||
{{ pageNum }} / {{ totalPages }}
|
||||
</span>
|
||||
<UiButton
|
||||
variant="outline"
|
||||
size="icon"
|
||||
class="h-8 w-8"
|
||||
:disabled="pageNum >= totalPages"
|
||||
@click="handlePageChange(pageNum + 1)"
|
||||
>
|
||||
<Icon icon="lucide:chevron-right" class="size-4" />
|
||||
</UiButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 订单详情弹窗 -->
|
||||
<UiDialog v-model:open="showDetailDialog">
|
||||
<UiDialogContent class="max-w-md max-h-[90vh] overflow-y-auto">
|
||||
<UiDialogHeader>
|
||||
<UiDialogTitle>提现订单详情</UiDialogTitle>
|
||||
</UiDialogHeader>
|
||||
<div v-if="currentOrder" class="space-y-4">
|
||||
<div class="grid grid-cols-3 gap-2 text-sm">
|
||||
<div class="text-muted-foreground">订单号</div>
|
||||
<div class="col-span-2 font-mono">{{ currentOrder.orderNo }}</div>
|
||||
|
||||
<div class="text-muted-foreground">用户</div>
|
||||
<div class="col-span-2 font-medium">{{ currentOrder.username }}</div>
|
||||
|
||||
<div class="text-muted-foreground">提现金额</div>
|
||||
<div class="col-span-2 font-mono font-bold text-lg">${{ formatAmount(currentOrder.amount) }}</div>
|
||||
|
||||
<div class="text-muted-foreground">手续费(10%)</div>
|
||||
<div class="col-span-2 font-mono">-${{ formatAmount(currentOrder.fee || 0) }}</div>
|
||||
|
||||
<div class="text-muted-foreground">应收款项</div>
|
||||
<div class="col-span-2 font-mono font-bold text-green-600">${{ formatAmount(currentOrder.receivableAmount || 0) }}</div>
|
||||
|
||||
<div class="text-muted-foreground">提现地址</div>
|
||||
<div class="col-span-2">
|
||||
<div v-if="currentOrder.walletAddress" class="flex items-start gap-1">
|
||||
<span class="font-mono text-xs break-all">{{ currentOrder.walletAddress }}</span>
|
||||
<Icon icon="lucide:copy" class="size-4 cursor-pointer flex-shrink-0" @click="copyToClipboard(currentOrder.walletAddress!)" />
|
||||
</div>
|
||||
<span v-else class="text-muted-foreground">-</span>
|
||||
</div>
|
||||
|
||||
<div v-if="currentOrder.approveAdminName" class="text-muted-foreground">审批人</div>
|
||||
<div v-if="currentOrder.approveAdminName" class="col-span-2">
|
||||
{{ currentOrder.approveAdminName }}
|
||||
</div>
|
||||
|
||||
<div class="text-muted-foreground">创建时间</div>
|
||||
<div class="col-span-2">{{ currentOrder.createTime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<UiDialogFooter>
|
||||
<template v-if="currentOrder">
|
||||
<UiButton variant="outline" @click="showDetailDialog = false">
|
||||
关闭
|
||||
</UiButton>
|
||||
<UiButton @click="openApproveDialog(currentOrder, 2); showDetailDialog = false">
|
||||
通过
|
||||
</UiButton>
|
||||
<UiButton variant="destructive" @click="openApproveDialog(currentOrder, 3); showDetailDialog = false">
|
||||
驳回
|
||||
</UiButton>
|
||||
</template>
|
||||
</UiDialogFooter>
|
||||
</UiDialogContent>
|
||||
</UiDialog>
|
||||
|
||||
<!-- 审批弹窗 -->
|
||||
<UiDialog v-model:open="showApproveDialog">
|
||||
<UiDialogContent class="max-w-md max-h-[90vh] overflow-y-auto">
|
||||
<UiDialogHeader>
|
||||
<UiDialogTitle>{{ approveStatus === 2 ? '通过提现' : '驳回提现' }}</UiDialogTitle>
|
||||
</UiDialogHeader>
|
||||
<div v-if="currentOrder" class="grid gap-4 py-4">
|
||||
<div class="p-3 rounded-lg bg-muted/50 text-sm space-y-2">
|
||||
<div>
|
||||
<div class="text-muted-foreground">订单号</div>
|
||||
<div class="font-mono">{{ currentOrder.orderNo }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-muted-foreground">用户</div>
|
||||
<div class="font-medium">{{ currentOrder.username }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-muted-foreground">提现金额</div>
|
||||
<div class="font-mono font-bold text-lg">${{ formatAmount(currentOrder.amount) }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-muted-foreground">应收款项</div>
|
||||
<div class="font-mono text-green-600">${{ formatAmount(currentOrder.receivableAmount || 0) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="approveStatus === 3" class="grid gap-2">
|
||||
<UiLabel>驳回原因 <span class="text-red-500">*</span></UiLabel>
|
||||
<UiInput v-model="rejectReason" placeholder="请输入驳回原因" />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<UiLabel>备注</UiLabel>
|
||||
<UiInput v-model="adminRemark" placeholder="可选" />
|
||||
</div>
|
||||
</div>
|
||||
<UiDialogFooter>
|
||||
<UiButton variant="outline" @click="showApproveDialog = false">
|
||||
取消
|
||||
</UiButton>
|
||||
<UiButton
|
||||
:variant="approveStatus === 3 ? 'destructive' : 'default'"
|
||||
:disabled="approveMutation.isPending.value || (approveStatus === 3 && !rejectReason.trim())"
|
||||
@click="handleApprove"
|
||||
>
|
||||
<UiSpinner v-if="approveMutation.isPending.value" class="mr-2" />
|
||||
确认
|
||||
</UiButton>
|
||||
</UiDialogFooter>
|
||||
</UiDialogContent>
|
||||
</UiDialog>
|
||||
</BasicPage>
|
||||
</template>
|
||||
Reference in New Issue
Block a user