Add Bank Card for Withdrawal
Some checks failed
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
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
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
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled

This commit is contained in:
Mrx
2026-02-06 15:20:45 +08:00
parent b98b39bee5
commit c8527d582f
4 changed files with 811 additions and 382 deletions

View File

@@ -4,19 +4,19 @@ export namespace AgentApi {
export interface AgentListItem { export interface AgentListItem {
id: number; id: number;
user_id: number; user_id: number;
agent_code: number;
level: number; // 1=普通2=黄金3=钻石
level_name: string; level_name: string;
region: string; region: string;
mobile: string; mobile: string;
wechat_id?: string; membership_expiry_time: string;
team_leader_id?: number;
balance: number; balance: number;
total_earnings: number; total_earnings: number;
frozen_balance: number; frozen_balance: number;
withdrawn_amount: number; withdrawn_amount: number;
is_real_name: boolean;
create_time: string; create_time: string;
is_real_name_verified: boolean;
real_name: string;
id_card: string;
real_name_status: 'approved' | 'pending' | 'rejected';
} }
export interface AgentList { export interface AgentList {
@@ -29,8 +29,7 @@ export namespace AgentApi {
pageSize: number; pageSize: number;
mobile?: string; mobile?: string;
region?: string; region?: string;
level?: number; parent_agent_id?: number;
team_leader_id?: number;
id?: number; id?: number;
create_time_start?: string; create_time_start?: string;
create_time_end?: string; create_time_end?: string;
@@ -40,10 +39,8 @@ export namespace AgentApi {
export interface AgentLinkListItem { export interface AgentLinkListItem {
agent_id: number; agent_id: number;
product_id: number;
product_name: string; product_name: string;
set_price: number; price: number;
actual_base_price: number;
link_identifier: string; link_identifier: string;
create_time: string; create_time: string;
} }
@@ -57,7 +54,6 @@ export namespace AgentApi {
page: number; page: number;
pageSize: number; pageSize: number;
agent_id?: number; agent_id?: number;
product_id?: number;
product_name?: string; product_name?: string;
link_identifier?: string; link_identifier?: string;
} }
@@ -86,41 +82,43 @@ export namespace AgentApi {
status?: number; status?: number;
} }
// 代理返佣相关接口 // 代理奖励相关接口
export interface AgentRebateListItem { export interface AgentRewardListItem {
id: number; id: number;
agent_id: number; agent_id: number;
source_agent_id: number; relation_agent_id: number;
order_id: number;
rebate_type: number; // 1=直接上级返佣2=钻石上级返佣3=黄金上级返佣
amount: number; amount: number;
type: string;
create_time: string; create_time: string;
} }
export interface AgentRebateList { export interface AgentRewardList {
total: number; total: number;
items: AgentRebateListItem[]; items: AgentRewardListItem[];
} }
export interface GetAgentRebateListParams { export interface GetAgentRewardListParams {
page: number; page: number;
pageSize: number; pageSize: number;
agent_id?: number; agent_id?: number;
source_agent_id?: number; relation_agent_id?: number;
rebate_type?: number; type?: string;
} }
// 代理提现相关接口 // 代理提现相关接口
export interface AgentWithdrawalListItem { export interface AgentWithdrawalListItem {
id: number; id: string;
agent_id: number; agent_id: string;
withdraw_no: string; withdraw_no: string;
amount: number; amount: number;
tax_amount: number; tax_amount: number;
actual_amount: number; actual_amount: number;
status: number; // 1=待审核2=审核通过3=审核拒绝4=提现中5=提现成功6=提现失败 status: number;
withdrawal_type: number;
payee_account: string; payee_account: string;
payee_name: string; payee_name: string;
bank_card_no?: string;
bank_name?: string;
remark: string; remark: string;
create_time: string; create_time: string;
} }
@@ -133,27 +131,78 @@ export namespace AgentApi {
export interface GetAgentWithdrawalListParams { export interface GetAgentWithdrawalListParams {
page: number; page: number;
pageSize: number; pageSize: number;
agent_id?: number; agent_id?: number | string;
status?: number; status?: number;
withdraw_no?: string; withdraw_no?: string;
withdrawal_type?: number;
} }
export interface AuditWithdrawalParams { export interface AuditWithdrawalParams {
withdrawal_id: number; withdrawal_id: string;
status: number; // 2=通过3=拒绝 status: number; // 2=通过3=拒绝
remark: string; remark?: string;
}
// 代理上级抽佣相关接口
export interface AgentCommissionDeductionListItem {
id: number;
agent_id: number;
deducted_agent_id: number;
amount: number;
product_name: string;
type: 'cost' | 'pricing';
status: number;
create_time: string;
}
export interface AgentCommissionDeductionList {
total: number;
items: AgentCommissionDeductionListItem[];
}
export interface GetAgentCommissionDeductionListParams {
page: number;
pageSize: number;
agent_id?: number;
product_name?: string;
type?: 'cost' | 'pricing';
status?: number;
}
// 平台抽佣列表项
export interface AgentPlatformDeductionListItem {
id: number;
agent_id: number;
amount: number;
type: 'cost' | 'pricing';
status: number;
create_time: string;
}
// 平台抽佣列表响应
export interface AgentPlatformDeductionList {
total: number;
items: AgentPlatformDeductionListItem[];
}
// 获取平台抽佣列表参数
export interface GetAgentPlatformDeductionListParams {
page: number;
pageSize: number;
agent_id?: number;
type?: 'cost' | 'pricing';
status?: number;
} }
// 代理产品配置列表项 // 代理产品配置列表项
export interface AgentProductionConfigItem { export interface AgentProductionConfigItem {
id: number; id: number;
product_id: number;
product_name: string; product_name: string;
base_price: number; cost_price: number;
price_range_min: number; price_range_min: number;
price_range_max: number; price_range_max: number;
price_threshold: number; pricing_standard: number;
price_fee_rate: number; overpricing_ratio: number;
create_time: string; create_time: string;
} }
@@ -168,17 +217,17 @@ export namespace AgentApi {
page: number; page: number;
pageSize: number; pageSize: number;
product_name?: string; product_name?: string;
product_id?: number;
id?: number; id?: number;
} }
// 更新代理产品配置参数 // 更新代理产品配置参数
export interface UpdateAgentProductionConfigParams { export interface UpdateAgentProductionConfigParams {
id: number; id: number;
base_price: number; cost_price: number;
price_range_min: number;
price_range_max: number; price_range_max: number;
price_threshold?: number; pricing_standard: number;
price_fee_rate?: number; overpricing_ratio: number;
} }
// 更新代理产品配置响应 // 更新代理产品配置响应
@@ -186,94 +235,122 @@ export namespace AgentApi {
success: boolean; success: boolean;
} }
// 代理升级记录相关接口 export interface MembershipRechargeOrderListItem {
export interface AgentUpgradeListItem {
id: number; id: number;
user_id: number;
agent_id: number; agent_id: number;
from_level: number; level_name: string;
to_level: number; amount: number;
upgrade_type: number; // 1=自主付费2=钻石升级下级 payment_method: 'alipay' | 'appleiap' | 'other' | 'wechat';
upgrade_fee: number; order_no: string;
rebate_amount: number; platform_order_id: string;
status: number; // 1=待处理2=已完成3=已失败 status: 'cancelled' | 'failed' | 'pending' | 'success';
create_time: string; create_time: string;
} }
export interface AgentUpgradeList { export interface GetMembershipRechargeOrderListParams {
total: number;
items: AgentUpgradeListItem[];
}
export interface GetAgentUpgradeListParams {
page: number; page: number;
pageSize: number; pageSize: number;
user_id?: number;
agent_id?: number; agent_id?: number;
upgrade_type?: number; level_name?: string;
status?: number; status?: string;
} }
// 代理订单相关接口 export interface MembershipRechargeOrderList {
export interface AgentOrderListItem { total: number;
items: MembershipRechargeOrderListItem[];
}
// 代理会员配置相关接口
export interface AgentMembershipConfigListItem {
id: number; id: number;
agent_id: number; level_name: string;
order_id: number; price: number;
product_id: number; report_commission: number;
product_name: string; lower_activity_reward: null | number;
order_amount: number; new_activity_reward: null | number;
set_price: number; lower_standard_count: null | number;
actual_base_price: number; new_lower_standard_count: null | number;
price_cost: number; lower_withdraw_reward_ratio: null | number;
agent_profit: number; lower_convert_vip_reward: null | number;
process_status: number; // 0=待处理1=处理成功2=处理失败 lower_convert_svip_reward: null | number;
exemption_amount: number;
price_increase_max: null | number;
price_ratio: null | number;
price_increase_amount: null | number;
create_time: string; create_time: string;
} }
export interface AgentOrderList { export interface GetAgentMembershipConfigListParams {
page: number;
pageSize: number;
level_name?: string;
}
// 代理会员配置编辑请求参数
export interface UpdateAgentMembershipConfigParams {
id: number; // 主键
level_name: string; // 会员级别名称
price: number; // 会员年费
report_commission: number; // 直推报告收益
lower_activity_reward?: null | number; // 下级活跃奖励金额
new_activity_reward?: null | number; // 新增活跃奖励金额
lower_standard_count?: null | number; // 活跃下级达标个数
new_lower_standard_count?: null | number; // 新增活跃下级达标个数
lower_withdraw_reward_ratio?: null | number; // 下级提现奖励比例
lower_convert_vip_reward?: null | number; // 下级转化VIP奖励
lower_convert_svip_reward?: null | number; // 下级转化SVIP奖励
exemption_amount?: null | number; // 免责金额
price_increase_max?: null | number; // 提价最高金额
price_ratio?: null | number; // 提价区间收取比例
price_increase_amount?: null | number; // 在原本成本上加价的金额
}
// 后台列表通用分页响应
export interface AdminListResp<T> {
total: number; total: number;
items: AgentOrderListItem[]; items: T[];
} }
export interface GetAgentOrderListParams { export interface GetAgentOrderListParams {
page: number; page: number;
pageSize: number; pageSize: number;
agent_id?: number; agent_id?: number | string;
order_id?: number; [key: string]: any;
process_status?: number;
} }
// 邀请码管理相关接口 export interface GetAgentRealNameListParams {
export interface InviteCodeListItem { page: number;
id: number; pageSize: number;
code: string; agent_id?: number | string;
agent_id: number; // 0表示平台发放 [key: string]: any;
agent_mobile: string;
target_level: number;
status: number; // 0=未使用1=已使用2=已失效
used_user_id?: number;
used_agent_id?: number;
used_time?: string;
expire_time?: string;
remark?: string;
create_time: string;
} }
export interface InviteCodeList { export interface GetAgentRebateListParams {
total: number; page: number;
items: InviteCodeListItem[]; pageSize: number;
agent_id?: number | string;
[key: string]: any;
}
export interface GetAgentUpgradeListParams {
page: number;
pageSize: number;
agent_id?: number | string;
[key: string]: any;
} }
export interface GetInviteCodeListParams { export interface GetInviteCodeListParams {
page: number; page: number;
pageSize: number; pageSize: number;
code?: string;
agent_id?: number;
target_level?: number; target_level?: number;
status?: number; [key: string]: any;
} }
export interface GenerateDiamondInviteCodeParams { export interface GenerateDiamondInviteCodeParams {
count: number; count: number;
expire_days?: number; // 可选0表示不过期 expire_days?: number;
remark?: string; remark?: string;
} }
@@ -281,33 +358,26 @@ export namespace AgentApi {
codes: string[]; codes: string[];
} }
// 系统配置相关接口(价格配置已移除,改为产品配置表管理) export interface UpgradeAgentParams {
agent_id: string;
to_level: number;
}
// 代理系统配置(后台)
export interface AgentConfig { export interface AgentConfig {
level_bonus: { level_bonus: { normal: number; gold: number; diamond: number };
diamond: number;
gold: number;
normal: number;
};
upgrade_fee: { upgrade_fee: {
normal_to_gold: number; normal_to_gold: number;
normal_to_diamond: number; normal_to_diamond: number;
gold_to_diamond: number; gold_to_diamond?: number;
}; };
upgrade_rebate: { upgrade_rebate: {
normal_to_gold_rebate: number; normal_to_gold_rebate: number;
to_diamond_rebate: number; to_diamond_rebate: number;
}; };
direct_parent_rebate: { direct_parent_rebate: { diamond: number; gold: number; normal: number };
diamond: number; // 直接上级是钻石的返佣金额6元 max_gold_rebate_amount: number;
gold: number; // 直接上级是黄金的返佣金额3元 commission_freeze: { ratio: number; threshold: number; days: number };
normal: number; // 直接上级是普通的返佣金额2元
};
max_gold_rebate_amount: number; // 黄金代理最大返佣金额3元
commission_freeze: {
ratio: number; // 佣金冻结比例例如0.1表示10%
threshold: number; // 佣金冻结阈值(订单单价达到此金额才触发冻结,单位:元)
days: number; // 佣金冻结解冻天数单位例如30表示30天后解冻
};
tax_rate: number; tax_rate: number;
tax_exemption_amount: number; tax_exemption_amount: number;
gold_max_uplift_amount: number; gold_max_uplift_amount: number;
@@ -315,85 +385,17 @@ export namespace AgentApi {
} }
export interface UpdateAgentConfigParams { export interface UpdateAgentConfigParams {
level_bonus?: { level_bonus?: AgentConfig['level_bonus'];
diamond?: number; upgrade_fee?: AgentConfig['upgrade_fee'];
gold?: number; upgrade_rebate?: AgentConfig['upgrade_rebate'];
normal?: number; direct_parent_rebate?: AgentConfig['direct_parent_rebate'];
}; max_gold_rebate_amount?: number;
upgrade_fee?: { commission_freeze?: AgentConfig['commission_freeze'];
normal_to_gold?: number;
normal_to_diamond?: number;
gold_to_diamond?: number;
};
upgrade_rebate?: {
normal_to_gold_rebate?: number;
to_diamond_rebate?: number;
};
direct_parent_rebate?: {
diamond?: number; // 直接上级是钻石的返佣金额6元
gold?: number; // 直接上级是黄金的返佣金额3元
normal?: number; // 直接上级是普通的返佣金额2元
};
max_gold_rebate_amount?: number; // 黄金代理最大返佣金额3元
commission_freeze?: {
ratio?: number; // 佣金冻结比例例如0.1表示10%
threshold?: number; // 佣金冻结阈值(订单单价达到此金额才触发冻结,单位:元)
days?: number; // 佣金冻结解冻天数单位例如30表示30天后解冻
};
tax_rate?: number; tax_rate?: number;
tax_exemption_amount?: number; tax_exemption_amount?: number;
gold_max_uplift_amount?: number; gold_max_uplift_amount?: number;
diamond_max_uplift_amount?: number; diamond_max_uplift_amount?: number;
} }
// 实名认证相关接口
export interface AgentRealNameListItem {
id: number;
agent_id: number;
name: string;
id_card: string; // 加密,需要脱敏显示
mobile: string; // 加密
status: number; // 1=未验证2=已通过
verify_time?: string;
create_time: string;
}
export interface AgentRealNameList {
total: number;
items: AgentRealNameListItem[];
}
export interface GetAgentRealNameListParams {
page: number;
pageSize: number;
agent_id?: number;
status?: number;
}
// 代理奖励相关接口
export interface AgentRewardListItem {
id: number;
agent_id: number;
type: string; // 奖励类型register=注册奖励first_order=首单奖励level_up=升级奖励
amount: number;
order_id?: number;
status: string; // pending=待发放paid=已发放failed=发放失败
create_time: string;
pay_time?: string;
}
export interface AgentRewardList {
total: number;
items: AgentRewardListItem[];
}
export interface GetAgentRewardListParams {
page: number;
pageSize: number;
agent_id?: number;
type?: string;
status?: string;
}
} }
/** /**
@@ -429,6 +431,18 @@ async function getAgentCommissionList(
); );
} }
/**
* 获取代理奖励列表
*/
async function getAgentRewardList(params: AgentApi.GetAgentRewardListParams) {
return requestClient.get<AgentApi.AgentRewardList>(
'/agent/agent-reward/list',
{
params,
},
);
}
/** /**
* 获取代理提现列表 * 获取代理提现列表
*/ */
@@ -443,6 +457,44 @@ async function getAgentWithdrawalList(
); );
} }
/**
* 审核代理提现
*/
async function auditWithdrawal(params: AgentApi.AuditWithdrawalParams) {
return requestClient.post<{ success: boolean }>(
'/agent/withdrawal/audit',
params,
);
}
/**
* 获取代理上级抽佣列表
*/
async function getAgentCommissionDeductionList(
params: AgentApi.GetAgentCommissionDeductionListParams,
) {
return requestClient.get<AgentApi.AgentCommissionDeductionList>(
'/agent/agent-commission-deduction/list',
{
params,
},
);
}
/**
* 获取平台抽佣列表
*/
async function getAgentPlatformDeductionList(
params: AgentApi.GetAgentPlatformDeductionListParams,
) {
return requestClient.get<AgentApi.AgentPlatformDeductionList>(
'/agent/agent-platform-deduction/list',
{
params,
},
);
}
/** /**
* 获取代理产品配置列表 * 获取代理产品配置列表
*/ */
@@ -470,40 +522,13 @@ async function updateAgentProductionConfig(
} }
/** /**
* 获取代理返佣记录列表 * 获取会员充值订单列表
*/ */
async function getAgentRebateList(params: AgentApi.GetAgentRebateListParams) { async function getMembershipRechargeOrderList(
return requestClient.get<AgentApi.AgentRebateList>('/agent/rebate/list', { params: AgentApi.GetMembershipRechargeOrderListParams,
params,
});
}
/**
* 获取代理升级记录列表
*/
async function getAgentUpgradeList(
params: AgentApi.GetAgentUpgradeListParams,
) { ) {
return requestClient.get<AgentApi.AgentUpgradeList>('/agent/upgrade/list', { return requestClient.get<AgentApi.MembershipRechargeOrderList>(
params, '/agent/agent-membership-recharge-order/list',
});
}
/**
* 获取代理订单列表
*/
async function getAgentOrderList(params: AgentApi.GetAgentOrderListParams) {
return requestClient.get<AgentApi.AgentOrderList>('/agent/order/list', {
params,
});
}
/**
* 获取邀请码列表
*/
async function getInviteCodeList(params: AgentApi.GetInviteCodeListParams) {
return requestClient.get<AgentApi.InviteCodeList>(
'/agent/invite_code/list',
{ {
params, params,
}, },
@@ -511,7 +536,48 @@ async function getInviteCodeList(params: AgentApi.GetInviteCodeListParams) {
} }
/** /**
* 生成钻石邀请码 * 获取代理会员配置列表
*/
async function getAgentMembershipConfigList(
params: AgentApi.GetAgentMembershipConfigListParams,
) {
return requestClient.get<{
items: AgentApi.AgentMembershipConfigListItem[];
total: number;
}>('/agent/agent-membership-config/list', { params });
}
/**
* 更新代理会员配置
*/
async function updateAgentMembershipConfig(
params: AgentApi.UpdateAgentMembershipConfigParams,
) {
return requestClient.post<{ success: boolean }>(
'/agent/agent-membership-config/update',
params,
);
}
/**
* 获取代理系统配置(后台)
*/
async function getAgentConfig() {
return requestClient.get<AgentApi.AgentConfig>('/agent/config');
}
/**
* 更新代理系统配置(后台)
*/
async function updateAgentConfig(params: AgentApi.UpdateAgentConfigParams) {
return requestClient.post<{ success: boolean }>(
'/agent/config/update',
params,
);
}
/**
* 生成钻石邀请码(后台)
*/ */
async function generateDiamondInviteCode( async function generateDiamondInviteCode(
params: AgentApi.GenerateDiamondInviteCodeParams, params: AgentApi.GenerateDiamondInviteCodeParams,
@@ -523,83 +589,90 @@ async function generateDiamondInviteCode(
} }
/** /**
* 获取系统配置 * 获取邀请码列表(后台)
*/ */
async function getAgentConfig() { async function getInviteCodeList(params: AgentApi.GetInviteCodeListParams) {
return requestClient.get<AgentApi.AgentConfig>('/agent/config'); return requestClient.get<AgentApi.AdminListResp<Record<string, any>>>(
} '/agent/invite_code/list',
{ params },
/**
* 更新系统配置
*/
async function updateAgentConfig(params: AgentApi.UpdateAgentConfigParams) {
return requestClient.post<{ success: boolean }>(
'/agent/config/update',
params,
); );
} }
/** /**
* 获取实名认证列表 * 获取代理订单列表(后台)
*/
async function getAgentOrderList(params: AgentApi.GetAgentOrderListParams) {
return requestClient.get<AgentApi.AdminListResp<Record<string, any>>>(
'/agent/order/list',
{ params },
);
}
/**
* 获取代理实名认证列表(后台)
*/ */
async function getAgentRealNameList( async function getAgentRealNameList(
params: AgentApi.GetAgentRealNameListParams, params: AgentApi.GetAgentRealNameListParams,
) { ) {
return requestClient.get<AgentApi.AgentRealNameList>( return requestClient.get<AgentApi.AdminListResp<Record<string, any>>>(
'/agent/real_name/list', '/agent/real_name/list',
{ { params },
params,
},
); );
} }
/** /**
* 审核提现 * 获取代理返佣列表(后台)
*/ */
async function auditWithdrawal(params: AgentApi.AuditWithdrawalParams) { async function getAgentRebateList(params: AgentApi.GetAgentRebateListParams) {
return requestClient.post<{ success: boolean }>( return requestClient.get<AgentApi.AdminListResp<Record<string, any>>>(
'/agent/withdrawal/audit', '/agent/rebate/list',
params, { params },
); );
} }
/** /**
* 平台升级代理等级(免费升级,遵守代理系统逻辑 * 获取代理升级记录列表(后台
*/ */
async function upgradeAgent(params: { async function getAgentUpgradeList(
agent_id: string; params: AgentApi.GetAgentUpgradeListParams,
to_level: number; // 2=黄金3=钻石
}) {
return requestClient.post<{ success: boolean }>('/agent/upgrade', params);
}
/**
* 获取代理奖励列表
*/
async function getAgentRewardList(
params: AgentApi.GetAgentRewardListParams,
) { ) {
return requestClient.get<AgentApi.AgentRewardList>('/agent/reward/list', { return requestClient.get<AgentApi.AdminListResp<Record<string, any>>>(
'/agent/upgrade/list',
{ params },
);
}
/**
* 平台升级代理等级(后台)
*/
async function upgradeAgent(params: AgentApi.UpgradeAgentParams) {
return requestClient.post<{ success: boolean }>(
'/agent/upgrade/agent',
params, params,
}); );
} }
export { export {
auditWithdrawal, auditWithdrawal,
generateDiamondInviteCode, getAgentCommissionDeductionList,
getAgentCommissionList, getAgentCommissionList,
getAgentConfig, getAgentConfig,
getAgentLinkList, getAgentLinkList,
getAgentList, getAgentList,
getAgentMembershipConfigList,
getAgentOrderList, getAgentOrderList,
getAgentPlatformDeductionList,
getAgentProductionConfigList, getAgentProductionConfigList,
getAgentRebateList,
getAgentRealNameList, getAgentRealNameList,
getAgentRebateList,
getAgentRewardList, getAgentRewardList,
getAgentUpgradeList, getAgentUpgradeList,
getAgentWithdrawalList, getAgentWithdrawalList,
getInviteCodeList, getInviteCodeList,
getMembershipRechargeOrderList,
generateDiamondInviteCode,
updateAgentConfig, updateAgentConfig,
updateAgentMembershipConfig,
updateAgentProductionConfig, updateAgentProductionConfig,
upgradeAgent, upgradeAgent,
}; };

View File

@@ -1,24 +1,23 @@
import type { OnActionClickFn } from '#/adapter/vxe-table';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { AgentApi } from '#/api/agent';
export function useWithdrawalColumns(): VxeTableGridOptions['columns'] { export function useWithdrawalColumns(
onActionClick?: OnActionClickFn<AgentApi.AgentWithdrawalListItem>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
title: 'ID', title: '提现单号',
field: 'id', field: 'withdraw_no',
width: 80, width: 180,
}, },
{ {
title: '代理ID', title: '代理ID',
field: 'agent_id', field: 'agent_id',
width: 100, width: 100,
}, },
{
title: '提现单号',
field: 'withdraw_no',
width: 180,
},
{ {
title: '提现金额', title: '提现金额',
field: 'amount', field: 'amount',
@@ -26,27 +25,49 @@ export function useWithdrawalColumns(): VxeTableGridOptions['columns'] {
formatter: ({ cellValue }) => `¥${cellValue.toFixed(2)}`, formatter: ({ cellValue }) => `¥${cellValue.toFixed(2)}`,
}, },
{ {
title: '税费金额', title: '实际到账',
field: 'tax_amount',
width: 120,
formatter: ({ cellValue }) => `¥${cellValue.toFixed(2)}`,
},
{
title: '实际到账金额',
field: 'actual_amount', field: 'actual_amount',
width: 120, width: 120,
formatter: ({ cellValue }) => `¥${cellValue.toFixed(2)}`, formatter: ({ cellValue }) => `¥${cellValue?.toFixed(2) || '0.00'}`,
}, },
{ {
title: '收款账号', title: '税费',
field: 'tax_amount',
width: 100,
formatter: ({ cellValue }) => `¥${cellValue?.toFixed(2) || '0.00'}`,
},
{
title: '提现方式',
field: 'withdrawal_type',
width: 120,
formatter: ({ cellValue }: { cellValue: number }) => {
const methodMap: Record<number, string> = {
1: '支付宝',
2: '银行卡',
};
return methodMap[cellValue] || '未知';
},
},
{
title: '收款账户',
field: 'payee_account', field: 'payee_account',
width: 180, width: 180,
}, },
{ {
title: '收款人姓名', title: '收款人',
field: 'payee_name', field: 'payee_name',
width: 120, width: 120,
}, },
{
title: '银行卡号',
field: 'bank_card_no',
width: 180,
},
{
title: '开户行',
field: 'bank_name',
width: 180,
},
{ {
title: '状态', title: '状态',
field: 'status', field: 'status',
@@ -55,11 +76,9 @@ export function useWithdrawalColumns(): VxeTableGridOptions['columns'] {
name: 'CellTag', name: 'CellTag',
options: [ options: [
{ value: 1, color: 'warning', label: '待审核' }, { value: 1, color: 'warning', label: '待审核' },
{ value: 2, color: 'success', label: '审核通过' }, { value: 2, color: 'processing', label: '通过' },
{ value: 3, color: 'error', label: '审核拒绝' }, { value: 3, color: 'error', label: '拒绝' },
{ value: 4, color: 'processing', label: '提现中' }, { value: 5, color: 'success', label: '已打款' },
{ value: 5, color: 'success', label: '提现成功' },
{ value: 6, color: 'error', label: '提现失败' },
], ],
}, },
}, },
@@ -69,18 +88,33 @@ export function useWithdrawalColumns(): VxeTableGridOptions['columns'] {
width: 200, width: 200,
}, },
{ {
title: '创建时间', title: '申请时间',
field: 'create_time', field: 'create_time',
width: 160, width: 180,
sortable: true,
}, },
{ {
align: 'center', align: 'center',
slots: { default: 'operation' }, cellRender: {
attrs: {
nameField: 'withdraw_no',
nameTitle: '提现单号',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'audit',
text: '审核',
disabled: (row: AgentApi.AgentWithdrawalListItem) => {
return row.status !== 1; // 只有待审核状态(status=1)才能审核
},
},
],
},
field: 'operation', field: 'operation',
fixed: 'right', fixed: 'right',
title: '操作', title: '操作',
width: 120, width: 100,
}, },
]; ];
} }
@@ -88,26 +122,48 @@ export function useWithdrawalColumns(): VxeTableGridOptions['columns'] {
export function useWithdrawalFormSchema(): VbenFormSchema[] { export function useWithdrawalFormSchema(): VbenFormSchema[] {
return [ return [
{ {
component: 'Input',
fieldName: 'withdraw_no', fieldName: 'withdraw_no',
label: '提现单号', label: '提现单号',
component: 'Input',
componentProps: {
placeholder: '请输入提现单号',
allowClear: true,
},
}, },
{ {
fieldName: 'agent_id',
label: '代理ID',
component: 'Input',
componentProps: {
placeholder: '请输入代理ID',
allowClear: true,
},
},
{
fieldName: 'withdrawal_type',
label: '提现方式',
component: 'Select', component: 'Select',
componentProps: {
options: [
{ label: '支付宝', value: 1 },
{ label: '银行卡', value: 2 },
],
allowClear: true,
},
},
{
fieldName: 'status', fieldName: 'status',
label: '状态', label: '状态',
component: 'Select',
componentProps: { componentProps: {
allowClear: true,
options: [ options: [
{ label: '待审核', value: 1 }, { label: '待审核', value: 1 },
{ label: '审核通过', value: 2 }, { label: '通过', value: 2 },
{ label: '审核拒绝', value: 3 }, { label: '拒绝', value: 3 },
{ label: '提现中', value: 4 }, { label: '已打款', value: 5 },
{ label: '提现成功', value: 5 },
{ label: '提现失败', value: 6 },
], ],
allowClear: true,
}, },
}, },
]; ];
} }

View File

@@ -1,15 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { AgentApi } from '#/api/agent'; import { computed } from 'vue';
import { computed, ref } from 'vue'; import { Page, useVbenModal } from '@vben/common-ui';
import { Page } from '@vben/common-ui';
import { Button, Input, Modal, Space, message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { auditWithdrawal, getAgentWithdrawalList } from '#/api/agent'; import { getAgentWithdrawalList } from '#/api/agent';
import type { AgentApi } from '#/api/agent';
import AuditModal from './modules/audit-modal.vue';
import { useWithdrawalColumns, useWithdrawalFormSchema } from './data'; import { useWithdrawalColumns, useWithdrawalFormSchema } from './data';
interface Props { interface Props {
@@ -28,9 +26,32 @@ const queryParams = computed(() => ({
...(props.agentId ? { agent_id: props.agentId } : {}), ...(props.agentId ? { agent_id: props.agentId } : {}),
})); }));
const auditRemark = ref(''); // 审核弹窗
const auditModalVisible = ref(false); const [AuditModalComponent, auditModalApi] = useVbenModal({
const currentWithdrawal = ref<AgentApi.AgentWithdrawalListItem | null>(null); connectedComponent: AuditModal,
destroyOnClose: true,
});
const handleActionClick = ({
code,
row,
}: {
code: string;
row: AgentApi.AgentWithdrawalListItem;
}) => {
if (code === 'audit') {
auditModalApi
.setData({
withdrawal: row,
onSuccess: () => {
auditModalApi.close();
// 刷新列表
gridApi.query();
},
})
.open();
}
};
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
@@ -38,7 +59,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
submitOnChange: true, submitOnChange: true,
}, },
gridOptions: { gridOptions: {
columns: useWithdrawalColumns(), columns: useWithdrawalColumns(handleActionClick),
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ query: async ({
@@ -63,90 +84,11 @@ const [Grid, gridApi] = useVbenVxeGrid({
}, },
}, },
}); });
// 审核提现
function handleAudit(row: AgentApi.AgentWithdrawalListItem) {
currentWithdrawal.value = row;
auditRemark.value = '';
auditModalVisible.value = true;
}
// 确认审核
async function confirmAudit(status: number) {
if (!currentWithdrawal.value) return;
try {
await auditWithdrawal({
withdrawal_id: currentWithdrawal.value.id,
status,
remark: auditRemark.value || '',
});
message.success('审核成功');
auditModalVisible.value = false;
gridApi.query();
} catch (error) {
console.error('审核失败:', error);
}
}
// 取消审核
function cancelAudit() {
auditModalVisible.value = false;
auditRemark.value = '';
currentWithdrawal.value = null;
}
</script> </script>
<template> <template>
<Page :auto-content-height="!agentId"> <Page :auto-content-height="!agentId">
<Grid :table-title="agentId ? '提现记录列表' : '所有提现记录'"> <Grid :table-title="agentId ? '提现记录列表' : '所有提现记录'" />
<template #operation="{ row }"> <AuditModalComponent />
<Space>
<Button v-if="row.status === 1" type="link" size="small" @click="handleAudit(row)">
审核
</Button>
</Space>
</template>
</Grid>
<Modal v-model:open="auditModalVisible" title="审核提现" :width="600" @cancel="cancelAudit">
<div v-if="currentWithdrawal" class="audit-info">
<p><strong>提现单号</strong>{{ currentWithdrawal.withdraw_no }}</p>
<p>
<strong>提现金额</strong>¥{{ currentWithdrawal.amount.toFixed(2) }}
</p>
<p><strong>收款账号</strong>{{ currentWithdrawal.payee_account }}</p>
<p><strong>收款人姓名</strong>{{ currentWithdrawal.payee_name }}</p>
</div>
<div class="audit-remark">
<p><strong>审核备注</strong></p>
<Input.TextArea v-model:value="auditRemark" :rows="4" placeholder="请输入审核备注" />
</div>
<template #footer>
<Button @click="cancelAudit">取消</Button>
<Button type="primary" danger @click="confirmAudit(3)">
拒绝
</Button>
<Button type="primary" @click="confirmAudit(2)">通过</Button>
</template>
</Modal>
</Page> </Page>
</template> </template>
<style lang="less" scoped>
.audit-info {
margin-bottom: 16px;
p {
margin-bottom: 8px;
}
}
.audit-remark {
margin-top: 16px;
p {
margin-bottom: 8px;
}
}
</style>

View File

@@ -0,0 +1,358 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { auditWithdrawal } from '#/api/agent';
import type { AgentApi } from '#/api/agent';
interface ModalData {
withdrawal: AgentApi.AgentWithdrawalListItem;
onSuccess?: () => void;
}
const [Modal, modalApi] = useVbenModal({
onConfirm: () => handleSubmit(),
});
const modalData = computed(() => modalApi.getData<ModalData>());
const withdrawal = computed(() => modalData.value?.withdrawal);
const [Form, formApi] = useVbenForm({
schema: [
{
fieldName: 'status',
label: '审核结果',
component: 'RadioGroup',
componentProps: {
options: [
{ label: '通过', value: 2 },
{ label: '拒绝', value: 3 },
],
},
rules: 'selectRequired',
},
{
fieldName: 'remark',
label: '备注',
component: 'Textarea',
componentProps: {
placeholder: '请输入备注信息(可选)',
rows: 4,
maxlength: 500,
showCount: true,
},
},
],
showDefaultActions: false,
});
const handleSubmit = async () => {
if (!withdrawal.value) {
return;
}
// 验证表单
const { valid } = await formApi.validate();
if (!valid) {
message.error('请完善审核信息');
return;
}
// 获取表单值
const values = await formApi.getValues();
if (!values) {
return;
}
// 确保 status 字段存在且有效2=通过3=拒绝)
if (values.status === undefined || values.status === null) {
message.error('请选择审核结果');
return;
}
if (values.status !== 2 && values.status !== 3) {
message.error('审核结果无效,请选择"通过"或"拒绝"');
return;
}
modalApi.lock(true);
try {
await auditWithdrawal({
withdrawal_id: withdrawal.value.id,
status: values.status,
remark: values.remark || '',
});
message.success('审核成功');
modalData.value?.onSuccess?.();
modalApi.close();
} catch (error: any) {
message.error(error?.message || '审核失败');
} finally {
modalApi.lock(false);
}
};
</script>
<template>
<Modal class="w-[700px]">
<div class="audit-modal">
<!-- 提现信息卡片 -->
<div v-if="withdrawal" class="withdrawal-info">
<div class="info-header">
<h3 class="info-title">
<span class="title-icon">💰</span>
提现信息
</h3>
</div>
<div class="info-content">
<div class="info-row">
<div class="info-item">
<span class="label">提现单号</span>
<span class="value highlight">{{ withdrawal.withdraw_no }}</span>
</div>
<div class="info-item">
<span class="label">代理ID</span>
<span class="value">{{ withdrawal.agent_id }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="label">提现金额</span>
<span class="value amount">¥{{ withdrawal.amount.toFixed(2) }}</span>
</div>
<div class="info-item">
<span class="label">实际到账</span>
<span class="value amount-success">¥{{ withdrawal.actual_amount?.toFixed(2) || '0.00' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="label">税费</span>
<span class="value tax">¥{{ withdrawal.tax_amount?.toFixed(2) || '0.00' }}</span>
</div>
<div class="info-item">
<span class="label">提现方式</span>
<span class="value">
<span :class="['method-tag', withdrawal.withdrawal_type === 1 ? 'alipay' : 'bank']">
{{ withdrawal.withdrawal_type === 1 ? '支付宝' : '银行卡' }}
</span>
</span>
</div>
</div>
<div class="info-row">
<div class="info-item full-width">
<span class="label">收款账户</span>
<span class="value">{{ withdrawal.payee_account }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="label">收款人</span>
<span class="value">{{ withdrawal.payee_name }}</span>
</div>
<div v-if="withdrawal.bank_card_no" class="info-item">
<span class="label">银行卡号</span>
<span class="value">{{ withdrawal.bank_card_no }}</span>
</div>
</div>
<div v-if="withdrawal.bank_name" class="info-row">
<div class="info-item full-width">
<span class="label">开户行</span>
<span class="value">{{ withdrawal.bank_name }}</span>
</div>
</div>
</div>
</div>
<!-- 审核表单 -->
<div class="audit-form">
<Form />
</div>
</div>
</Modal>
</template>
<style lang="less" scoped>
.audit-modal {
padding: 0;
.withdrawal-info {
margin-bottom: 24px;
background: linear-gradient(135deg, #f5f7fa 0%, #ffffff 100%);
border-radius: 8px;
border: 1px solid #e8eaed;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
.info-header {
padding: 16px 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
.info-title {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #ffffff;
display: flex;
align-items: center;
gap: 8px;
.title-icon {
font-size: 20px;
}
}
}
.info-content {
padding: 20px;
}
.info-row {
display: flex;
gap: 24px;
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
}
.info-item {
flex: 1;
display: flex;
flex-direction: column;
gap: 6px;
&.full-width {
flex: 1 1 100%;
}
.label {
font-size: 13px;
color: #8c8c8c;
font-weight: 500;
letter-spacing: 0.3px;
}
.value {
font-size: 15px;
color: #262626;
font-weight: 500;
word-break: break-all;
&.highlight {
color: #1890ff;
font-weight: 600;
font-family: 'Monaco', 'Menlo', monospace;
}
&.amount {
color: #fa8c16;
font-size: 18px;
font-weight: 700;
}
&.amount-success {
color: #52c41a;
font-size: 18px;
font-weight: 700;
}
&.tax {
color: #ff4d4f;
font-weight: 600;
}
.method-tag {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 13px;
font-weight: 500;
&.alipay {
background: linear-gradient(135deg, #1677ff 0%, #0958d9 100%);
color: #ffffff;
}
&.bank {
background: linear-gradient(135deg, #52c41a 0%, #389e0d 100%);
color: #ffffff;
}
}
}
}
}
.audit-form {
padding: 0 4px;
:deep(.vben-form) {
.ant-form-item-label {
label {
font-weight: 500;
color: #262626;
}
}
.ant-radio-group {
.ant-radio-button-wrapper {
padding: 8px 24px;
height: auto;
font-weight: 500;
transition: all 0.3s;
&:first-child {
border-radius: 6px 0 0 6px;
}
&:last-child {
border-radius: 0 6px 6px 0;
}
&.ant-radio-button-wrapper-checked {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-color: #667eea;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
}
}
}
.ant-input {
border-radius: 6px;
transition: all 0.3s;
&:focus,
&:hover {
border-color: #667eea;
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
}
}
textarea.ant-input {
resize: vertical;
min-height: 100px;
border-radius: 6px;
padding: 12px;
font-size: 14px;
line-height: 1.6;
transition: all 0.3s;
&:focus {
border-color: #667eea;
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
}
}
}
}
}
</style>