fix and add
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
This commit is contained in:
@@ -78,6 +78,7 @@ export namespace AgentApi {
|
|||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
agent_id?: number;
|
agent_id?: number;
|
||||||
|
order_id?: number;
|
||||||
product_name?: string;
|
product_name?: string;
|
||||||
status?: number;
|
status?: number;
|
||||||
}
|
}
|
||||||
@@ -333,6 +334,13 @@ export interface GetAgentLinkProductStatisticsParams {}
|
|||||||
price_ratio?: null | number; // 提价区间收取比例
|
price_ratio?: null | number; // 提价区间收取比例
|
||||||
price_increase_amount?: null | number; // 在原本成本上加价的金额
|
price_increase_amount?: null | number; // 在原本成本上加价的金额
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 代理钱包信息
|
||||||
|
export interface AgentWalletInfo {
|
||||||
|
balance: number; // 可用余额
|
||||||
|
frozen_balance: number; // 冻结余额
|
||||||
|
total_earnings: number; // 总收益
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -571,6 +579,15 @@ async function getAgentLinkProductStatistics() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取代理钱包信息
|
||||||
|
*/
|
||||||
|
async function getAgentWallet(agentId: number) {
|
||||||
|
return requestClient.get<AgentApi.AgentWalletInfo>(
|
||||||
|
`/agent/wallet/${agentId}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
batchUnfreezeAgentCommission,
|
batchUnfreezeAgentCommission,
|
||||||
getAgentCommissionDeductionList,
|
getAgentCommissionDeductionList,
|
||||||
@@ -584,6 +601,7 @@ export {
|
|||||||
getAgentProductionConfigList,
|
getAgentProductionConfigList,
|
||||||
getAgentRewardList,
|
getAgentRewardList,
|
||||||
getAgentStatistics,
|
getAgentStatistics,
|
||||||
|
getAgentWallet,
|
||||||
getAgentWithdrawalList,
|
getAgentWithdrawalList,
|
||||||
getMembershipRechargeOrderList,
|
getMembershipRechargeOrderList,
|
||||||
getWithdrawalStatistics,
|
getWithdrawalStatistics,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export function useCommissionColumns(
|
|||||||
const statusMap: Record<number, string> = {
|
const statusMap: Record<number, string> = {
|
||||||
0: '已结算',
|
0: '已结算',
|
||||||
1: '冻结中',
|
1: '冻结中',
|
||||||
2: '已取消',
|
2: '已退款',
|
||||||
};
|
};
|
||||||
return statusMap[cellValue] || '未知';
|
return statusMap[cellValue] || '未知';
|
||||||
},
|
},
|
||||||
@@ -83,21 +83,7 @@ export function useCommissionColumns(
|
|||||||
row?.status !== 1 ? '!text-gray-400 !cursor-not-allowed' : '',
|
row?.status !== 1 ? '!text-gray-400 !cursor-not-allowed' : '',
|
||||||
tooltip: (row: AgentApi.AgentCommissionListItem) => {
|
tooltip: (row: AgentApi.AgentCommissionListItem) => {
|
||||||
if (row?.status === 0) return '已结算的佣金无需解冻';
|
if (row?.status === 0) return '已结算的佣金无需解冻';
|
||||||
if (row?.status === 2) return '已取消的佣金无法操作';
|
if (row?.status === 2) return '已退款的佣金无法操作';
|
||||||
return '';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'cancel',
|
|
||||||
text: '取消',
|
|
||||||
type: 'primary',
|
|
||||||
disabled: (row: AgentApi.AgentCommissionListItem) =>
|
|
||||||
row?.status !== 1,
|
|
||||||
class: (row: AgentApi.AgentCommissionListItem) =>
|
|
||||||
row?.status !== 1 ? '!text-gray-400 !cursor-not-allowed' : '',
|
|
||||||
tooltip: (row: AgentApi.AgentCommissionListItem) => {
|
|
||||||
if (row?.status === 0) return '只能取消冻结中的佣金';
|
|
||||||
if (row?.status === 2) return '已取消的佣金无法再次取消';
|
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -114,10 +100,22 @@ export function useCommissionColumns(
|
|||||||
// 佣金记录搜索表单配置
|
// 佣金记录搜索表单配置
|
||||||
export function useCommissionFormSchema(): VbenFormSchema[] {
|
export function useCommissionFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
component: 'InputNumber',
|
||||||
|
fieldName: 'order_id',
|
||||||
|
label: '订单ID',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入订单ID',
|
||||||
|
style: { width: '100%' },
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
fieldName: 'product_name',
|
fieldName: 'product_name',
|
||||||
label: '产品名称',
|
label: '产品名称',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入产品名称(支持模糊搜索)',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
@@ -125,10 +123,11 @@ export function useCommissionFormSchema(): VbenFormSchema[] {
|
|||||||
label: '状态',
|
label: '状态',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
|
placeholder: '请选择状态',
|
||||||
options: [
|
options: [
|
||||||
{ label: '已结算', value: 0 },
|
{ label: '已结算', value: 0 },
|
||||||
{ label: '冻结中', value: 1 },
|
{ label: '冻结中', value: 1 },
|
||||||
{ label: '已取消', value: 2 },
|
{ label: '已退款', value: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue';
|
import { computed, h, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { Button, message, Modal } from 'ant-design-vue';
|
import { Button, message, Modal, Select } from 'ant-design-vue';
|
||||||
|
|
||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import {
|
import {
|
||||||
batchUnfreezeAgentCommission,
|
batchUnfreezeAgentCommission,
|
||||||
getAgentCommissionList,
|
getAgentCommissionList,
|
||||||
|
getAgentList,
|
||||||
|
getAgentWallet,
|
||||||
updateAgentCommissionStatus,
|
updateAgentCommissionStatus,
|
||||||
} from '#/api/agent';
|
} from '#/api/agent';
|
||||||
|
import type { AgentApi } from '#/api';
|
||||||
|
|
||||||
import { useCommissionColumns, useCommissionFormSchema } from './data';
|
import { useCommissionColumns, useCommissionFormSchema } from './data';
|
||||||
|
|
||||||
@@ -17,18 +20,77 @@ interface Props {
|
|||||||
agentId?: number;
|
agentId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QueryParams {
|
|
||||||
currentPage: number;
|
|
||||||
pageSize: number;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
// 用于一键解冻筛选的代理商ID
|
||||||
|
const unfreezeAgentId = ref<number | undefined>();
|
||||||
|
|
||||||
|
// 代理商列表(完整列表)
|
||||||
|
const allAgentList = ref<AgentApi.AgentListItem[]>([]);
|
||||||
|
|
||||||
|
// 显示在下拉框中的代理商列表(可能是过滤后的)
|
||||||
|
const agentList = ref<AgentApi.AgentListItem[]>([]);
|
||||||
|
|
||||||
const queryParams = computed(() => ({
|
const queryParams = computed(() => ({
|
||||||
...(props.agentId ? { agent_id: props.agentId } : {}),
|
...(props.agentId ? { agent_id: props.agentId } : {}),
|
||||||
|
...(unfreezeAgentId.value ? { agent_id: unfreezeAgentId.value } : {}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// 加载代理商列表
|
||||||
|
async function loadAgentList() {
|
||||||
|
try {
|
||||||
|
const result = await getAgentList({ page: 1, pageSize: 10000 });
|
||||||
|
allAgentList.value = result.items || [];
|
||||||
|
agentList.value = result.items || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载代理商列表失败:', error);
|
||||||
|
message.error('加载代理商列表失败,请刷新页面重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索时动态过滤代理商(支持ID和手机号)
|
||||||
|
function onAgentSearch(value: string) {
|
||||||
|
if (!value || value.trim() === '') {
|
||||||
|
// 如果输入为空,显示所有代理商
|
||||||
|
agentList.value = allAgentList.value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchValue = value.trim();
|
||||||
|
|
||||||
|
// 从完整列表中过滤匹配的代理商
|
||||||
|
const filtered = allAgentList.value.filter(agent => {
|
||||||
|
// 匹配代理ID
|
||||||
|
if (agent.id.toString().includes(searchValue)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 匹配手机号
|
||||||
|
if (agent.mobile && agent.mobile.includes(searchValue)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 匹配姓名(如果存在)
|
||||||
|
if (agent.real_name && agent.real_name.includes(searchValue)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
agentList.value = filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取未找到时的提示文案
|
||||||
|
function getNotFoundContent() {
|
||||||
|
if (unfreezeAgentId.value) {
|
||||||
|
return '点击确认使用此ID';
|
||||||
|
}
|
||||||
|
return '暂无代理商';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面加载时获取代理商列表
|
||||||
|
onMounted(() => {
|
||||||
|
loadAgentList();
|
||||||
|
});
|
||||||
|
|
||||||
// 操作处理函数
|
// 操作处理函数
|
||||||
function onActionClick({ code, row }: { code: string; row: any }) {
|
function onActionClick({ code, row }: { code: string; row: any }) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
@@ -38,70 +100,88 @@ function onActionClick({ code, row }: { code: string; row: any }) {
|
|||||||
case 'unfreeze':
|
case 'unfreeze':
|
||||||
onUnfreeze(row);
|
onUnfreeze(row);
|
||||||
break;
|
break;
|
||||||
case 'cancel':
|
|
||||||
onCancel(row);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 冻结佣金
|
// 冻结佣金
|
||||||
async function onFreeze(row: any) {
|
async function onFreeze(row: any) {
|
||||||
Modal.confirm({
|
try {
|
||||||
title: '确认冻结',
|
// 先获取代理商钱包信息,检查余额是否充足
|
||||||
content: `确定要冻结佣金金额 ¥${row.amount.toFixed(2)} 吗?冻结后将暂时无法提现。`,
|
const hideChecking = message.loading({
|
||||||
okText: '确认冻结',
|
content: '正在检查余额...',
|
||||||
cancelText: '取消',
|
duration: 0,
|
||||||
onOk: async () => {
|
key: 'check_balance',
|
||||||
try {
|
});
|
||||||
await updateAgentCommissionStatus(row.id, 1);
|
|
||||||
message.success('佣金已冻结');
|
const wallet = await getAgentWallet(row.agent_id);
|
||||||
onRefresh();
|
hideChecking();
|
||||||
} catch (error: any) {
|
|
||||||
const errorMsg = error?.response?.data?.msg || error?.message || '操作失败,请重试';
|
// 检查余额是否充足
|
||||||
message.error(errorMsg);
|
if (wallet.balance < row.amount) {
|
||||||
}
|
Modal.warning({
|
||||||
|
title: '余额不足',
|
||||||
|
content: `该代理商当前可用余额为 ¥${wallet.balance.toFixed(2)},不足以冻结佣金 ¥${row.amount.toFixed(2)}。\n缺少金额:¥${(row.amount - wallet.balance).toFixed(2)}`,
|
||||||
|
okText: '我知道了',
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// 余额充足,继续冻结操作
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认冻结',
|
||||||
|
content: `确定要冻结佣金金额 ¥${row.amount.toFixed(2)} 吗?\n当前可用余额:¥${wallet.balance.toFixed(2)},冻结后可用余额:¥${(wallet.balance - row.amount).toFixed(2)}`,
|
||||||
|
okText: '确认冻结',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: async () => {
|
||||||
|
try {
|
||||||
|
await updateAgentCommissionStatus(row.id, 1);
|
||||||
|
message.success('佣金已冻结');
|
||||||
|
onRefresh();
|
||||||
|
} catch (error: any) {
|
||||||
|
const errorMsg = error?.response?.data?.msg || error?.message || '操作失败,请重试';
|
||||||
|
message.error(errorMsg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
const errorMsg = error?.response?.data?.msg || error?.message || '获取钱包信息失败,请重试';
|
||||||
|
message.error(errorMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解冻佣金到用户余额
|
// 解冻佣金到用户余额
|
||||||
async function onUnfreeze(row: any) {
|
async function onUnfreeze(row: any) {
|
||||||
Modal.confirm({
|
try {
|
||||||
title: '确认解冻',
|
// 获取代理商钱包信息用于显示
|
||||||
content: `确定要解冻佣金金额 ¥${row.amount.toFixed(2)} 吗?解冻后将转入用户钱包余额。`,
|
const hideChecking = message.loading({
|
||||||
okText: '确认解冻',
|
content: '正在获取钱包信息...',
|
||||||
cancelText: '取消',
|
duration: 0,
|
||||||
onOk: async () => {
|
key: 'get_wallet',
|
||||||
try {
|
});
|
||||||
await updateAgentCommissionStatus(row.id, 0);
|
|
||||||
message.success('佣金已解冻并转入用户钱包余额');
|
|
||||||
onRefresh();
|
|
||||||
} catch (error: any) {
|
|
||||||
const errorMsg = error?.response?.data?.msg || error?.message || '操作失败,请重试';
|
|
||||||
message.error(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取消佣金
|
const wallet = await getAgentWallet(row.agent_id);
|
||||||
async function onCancel(row: any) {
|
hideChecking();
|
||||||
Modal.confirm({
|
|
||||||
title: '确认取消',
|
Modal.confirm({
|
||||||
content: `确定要取消佣金金额 ¥${row.amount.toFixed(2)} 吗?取消后将无法恢复。`,
|
title: '确认解冻',
|
||||||
okText: '确认取消',
|
content: `确定要解冻佣金金额 ¥${row.amount.toFixed(2)} 吗?\n解冻后将转入用户钱包余额。\n当前可用余额:¥${wallet.balance.toFixed(2)},解冻后可用余额:¥${(wallet.balance + row.amount).toFixed(2)}`,
|
||||||
cancelText: '返回',
|
okText: '确认解冻',
|
||||||
onOk: async () => {
|
cancelText: '取消',
|
||||||
try {
|
onOk: async () => {
|
||||||
await updateAgentCommissionStatus(row.id, 2);
|
try {
|
||||||
message.success('佣金已取消');
|
await updateAgentCommissionStatus(row.id, 0);
|
||||||
onRefresh();
|
message.success('佣金已解冻并转入用户钱包余额');
|
||||||
} catch (error: any) {
|
onRefresh();
|
||||||
const errorMsg = error?.response?.data?.msg || error?.message || '操作失败,请重试';
|
} catch (error: any) {
|
||||||
message.error(errorMsg);
|
const errorMsg = error?.response?.data?.msg || error?.message || '操作失败,请重试';
|
||||||
}
|
message.error(errorMsg);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
const errorMsg = error?.response?.data?.msg || error?.message || '获取钱包信息失败,请重试';
|
||||||
|
message.error(errorMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新列表
|
// 刷新列表
|
||||||
@@ -109,29 +189,141 @@ function onRefresh() {
|
|||||||
gridApi.query();
|
gridApi.query();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 选中代理商后刷新表格
|
||||||
|
function onAgentSelect(value: any) {
|
||||||
|
console.log('选中代理商:', value);
|
||||||
|
// 如果是清空选择,value 为 undefined
|
||||||
|
// 如果有值,转换为数字
|
||||||
|
unfreezeAgentId.value = value ? parseInt(String(value), 10) : undefined;
|
||||||
|
// 延迟一点让 computed 更新后再刷新
|
||||||
|
setTimeout(() => {
|
||||||
|
onRefresh();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
// 批量解冻佣金
|
// 批量解冻佣金
|
||||||
async function onBatchUnfreeze() {
|
async function onBatchUnfreeze() {
|
||||||
const content = props.agentId
|
const targetAgentId = unfreezeAgentId.value || props.agentId;
|
||||||
? '确定要一键解冻当前代理商所有冻结中的佣金吗?解冻后将全部转入用户钱包余额。'
|
|
||||||
: '确定要一键解冻所有冻结中的佣金吗?解冻后将全部转入用户钱包余额。';
|
|
||||||
|
|
||||||
Modal.confirm({
|
const hideChecking = message.loading({
|
||||||
title: '批量解冻确认',
|
content: '正在检查数据,请稍候...',
|
||||||
content,
|
duration: 0,
|
||||||
okText: '确认解冻',
|
key: 'check_frozen_data',
|
||||||
cancelText: '取消',
|
|
||||||
onOk: async () => {
|
|
||||||
try {
|
|
||||||
const result = await batchUnfreezeAgentCommission(props.agentId);
|
|
||||||
message.success(
|
|
||||||
`批量解冻成功!共解冻 ${result.count} 条记录,总金额 ¥${result.amount.toFixed(2)}`,
|
|
||||||
);
|
|
||||||
onRefresh();
|
|
||||||
} catch (error) {
|
|
||||||
message.error('批量解冻失败,请重试');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 查询所有冻结中的佣金记录
|
||||||
|
const frozenCommissions = await getAgentCommissionList({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10000,
|
||||||
|
status: 1,
|
||||||
|
...(targetAgentId ? { agent_id: targetAgentId } : {}),
|
||||||
|
});
|
||||||
|
|
||||||
|
hideChecking();
|
||||||
|
|
||||||
|
// 如果没有冻结的佣金,直接返回
|
||||||
|
if (!frozenCommissions.items || frozenCommissions.items.length === 0) {
|
||||||
|
message.info({
|
||||||
|
content: '没有需要解冻的冻结佣金',
|
||||||
|
key: 'check_frozen_data',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 统计每个代理商的佣金冻结金额
|
||||||
|
const commissionFrozenMap = new Map<number, number>();
|
||||||
|
frozenCommissions.items.forEach((item: any) => {
|
||||||
|
const currentAmount = commissionFrozenMap.get(item.agent_id) || 0;
|
||||||
|
commissionFrozenMap.set(item.agent_id, currentAmount + item.amount);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. 检查每个代理商的钱包冻结余额是否足够
|
||||||
|
let insufficientAgents: string[] = [];
|
||||||
|
let totalFrozenAmount = 0;
|
||||||
|
|
||||||
|
for (const [agentId, commissionAmount] of commissionFrozenMap) {
|
||||||
|
totalFrozenAmount += commissionAmount;
|
||||||
|
|
||||||
|
// 获取该代理商的钱包信息
|
||||||
|
const wallet = await getAgentWallet(agentId);
|
||||||
|
|
||||||
|
if (wallet.frozen_balance < commissionAmount) {
|
||||||
|
// 找到该代理商的信息
|
||||||
|
const agent = allAgentList.value.find(a => a.id === agentId);
|
||||||
|
const agentInfo = agent ? `${agent.real_name || agent.mobile} (ID: ${agentId})` : `ID: ${agentId}`;
|
||||||
|
insufficientAgents.push(
|
||||||
|
`${agentInfo}:钱包冻结余额 ¥${wallet.frozen_balance.toFixed(2)},需要解冻 ¥${commissionAmount.toFixed(2)},缺少 ¥${(commissionAmount - wallet.frozen_balance).toFixed(2)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有余额不足的代理商,显示错误信息
|
||||||
|
if (insufficientAgents.length > 0) {
|
||||||
|
Modal.error({
|
||||||
|
title: '冻结余额不足,无法解冻',
|
||||||
|
width: 600,
|
||||||
|
content: h('div', [
|
||||||
|
h('p', '以下代理商的钱包冻结余额不足以解冻其冻结的佣金:'),
|
||||||
|
h('ul', { style: { 'max-height': '300px', 'overflow-y': 'auto', 'padding-left': '20px' } },
|
||||||
|
insufficientAgents.map(msg => h('li', { style: { marginBottom: '8px' } }, msg))
|
||||||
|
),
|
||||||
|
h('p', { style: { marginTop: '16px', color: '#999' } }, '请先核实钱包冻结余额数据,或联系技术支持。'),
|
||||||
|
]),
|
||||||
|
okText: '我知道了',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 余额检查通过,确认解冻
|
||||||
|
const content = targetAgentId
|
||||||
|
? `确定要一键解冻代理商 ID: ${targetAgentId} 所有冻结中的佣金吗?\n\n共 ${frozenCommissions.items.length} 条记录,总金额 ¥${totalFrozenAmount.toFixed(2)}。\n解冻后将全部转入用户钱包余额。`
|
||||||
|
: `确定要一键解冻所有冻结中的佣金吗?\n\n共 ${frozenCommissions.items.length} 条记录,总金额 ¥${totalFrozenAmount.toFixed(2)}。\n解冻后将全部转入用户钱包余额。`;
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: '批量解冻确认',
|
||||||
|
content,
|
||||||
|
okText: '确认解冻',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: async () => {
|
||||||
|
const hideLoading = message.loading({
|
||||||
|
content: '正在批量解冻佣金,请稍候...',
|
||||||
|
duration: 0,
|
||||||
|
key: 'batch_unfreeze',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const result = await batchUnfreezeAgentCommission(targetAgentId);
|
||||||
|
message.success({
|
||||||
|
content: `批量解冻成功!共解冻 ${result.count} 条记录,总金额 ¥${result.amount.toFixed(2)}`,
|
||||||
|
key: 'batch_unfreeze',
|
||||||
|
});
|
||||||
|
onRefresh();
|
||||||
|
} catch (error: any) {
|
||||||
|
hideLoading();
|
||||||
|
const errorMsg = error?.response?.data?.msg || error?.message || '批量解冻失败,请重试';
|
||||||
|
// 如果是版本冲突错误,给出更友好的提示
|
||||||
|
if (errorMsg.includes('update db no rows change') || errorMsg.includes('版本冲突') || errorMsg.includes('状态已被其他操作修改')) {
|
||||||
|
message.error({
|
||||||
|
content: '批量解冻失败:部分佣金或钱包数据已被其他操作修改,请稍后重试。如果问题持续,请联系管理员。',
|
||||||
|
key: 'batch_unfreeze',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message.error({
|
||||||
|
content: `批量解冻失败:${errorMsg}`,
|
||||||
|
key: 'batch_unfreeze',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (error: any) {
|
||||||
|
hideChecking();
|
||||||
|
const errorMsg = error?.response?.data?.msg || error?.message || '数据检查失败,请重试';
|
||||||
|
message.error({
|
||||||
|
content: `检查失败:${errorMsg}`,
|
||||||
|
key: 'check_frozen_data',
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
@@ -155,16 +347,15 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
},
|
},
|
||||||
proxyConfig: {
|
proxyConfig: {
|
||||||
ajax: {
|
ajax: {
|
||||||
query: async ({
|
query: async ({ page, form, sort }: any, formValues: Record<string, any>) => {
|
||||||
page,
|
console.log('=== 佣金列表查询参数 ===');
|
||||||
form,
|
console.log('第一个参数 (params):', { page, form, sort });
|
||||||
}: {
|
console.log('第二个参数 (formValues):', formValues);
|
||||||
form: Record<string, any>;
|
console.log(' queryParams.value:', queryParams.value);
|
||||||
page: QueryParams;
|
|
||||||
}) => {
|
|
||||||
return await getAgentCommissionList({
|
return await getAgentCommissionList({
|
||||||
...queryParams.value,
|
...queryParams.value,
|
||||||
...form,
|
...formValues,
|
||||||
page: page.currentPage,
|
page: page.currentPage,
|
||||||
pageSize: page.pageSize,
|
pageSize: page.pageSize,
|
||||||
});
|
});
|
||||||
@@ -174,6 +365,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
result: 'items',
|
result: 'items',
|
||||||
total: 'total',
|
total: 'total',
|
||||||
},
|
},
|
||||||
|
autoLoad: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -183,10 +375,35 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
<Page :auto-content-height="!agentId">
|
<Page :auto-content-height="!agentId">
|
||||||
<Grid :table-title="agentId ? '佣金记录列表' : '所有佣金记录'">
|
<Grid :table-title="agentId ? '佣金记录列表' : '所有佣金记录'">
|
||||||
<template #toolbar-tools>
|
<template #toolbar-tools>
|
||||||
<Button type="primary" @click="onBatchUnfreeze">
|
<div class="flex items-center gap-2">
|
||||||
<span class="mr-1">⚡</span>
|
<span class="text-sm text-gray-600">选择代理商:</span>
|
||||||
一键解冻
|
<Select
|
||||||
</Button>
|
v-model:value="unfreezeAgentId"
|
||||||
|
placeholder="全部代理商 / 输入代理ID或手机号"
|
||||||
|
:allow-clear="true"
|
||||||
|
:loading="agentList.length === 0"
|
||||||
|
style="width: 260px"
|
||||||
|
show-search
|
||||||
|
:filter-option="false"
|
||||||
|
:show-arrow="true"
|
||||||
|
:not-found-content="getNotFoundContent()"
|
||||||
|
@search="onAgentSearch"
|
||||||
|
@change="onAgentSelect"
|
||||||
|
>
|
||||||
|
<Select.Option
|
||||||
|
v-for="agent in agentList"
|
||||||
|
:key="agent.id"
|
||||||
|
:value="agent.id"
|
||||||
|
:label="`${agent.real_name || agent.mobile} (ID: ${agent.id})`"
|
||||||
|
>
|
||||||
|
{{ agent.real_name || agent.mobile }} (ID: {{ agent.id }})
|
||||||
|
</Select.Option>
|
||||||
|
</Select>
|
||||||
|
<Button type="primary" @click="onBatchUnfreeze">
|
||||||
|
<span class="mr-1">⚡</span>
|
||||||
|
一键解冻
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
Reference in New Issue
Block a user