优化渠道
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// 渠道详情 API(模拟数据)
|
||||
// 渠道详情 API
|
||||
|
||||
import request from "@/api/request";
|
||||
import type {
|
||||
ChannelDetail,
|
||||
ChannelStatistics,
|
||||
@@ -7,186 +8,204 @@ import type {
|
||||
RevenueType,
|
||||
WithdrawalDetailRecord,
|
||||
WithdrawalDetailStatus,
|
||||
ChannelHomeData,
|
||||
} from "./data";
|
||||
|
||||
// 模拟延迟
|
||||
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
// 获取渠道详情
|
||||
// 获取渠道详情(使用真实接口)
|
||||
export const fetchChannelDetail = async (
|
||||
id: string,
|
||||
channelCode: string,
|
||||
): Promise<ChannelDetail> => {
|
||||
await delay(500);
|
||||
const data = await request(
|
||||
"/v1/frontend/distribution/user/home",
|
||||
{ channelCode },
|
||||
"GET",
|
||||
) as ChannelHomeData;
|
||||
|
||||
// 将接口返回的 channelInfo 转换为 ChannelDetail 格式
|
||||
return {
|
||||
id: "CH1765355105571YX9UWX",
|
||||
name: "张大大",
|
||||
code: "CH1765355105571YX9UWX",
|
||||
phone: undefined,
|
||||
wechatId: undefined,
|
||||
createType: "manual",
|
||||
remark: undefined,
|
||||
createTime: "2025-12-10 16:25",
|
||||
id: data.channelInfo.channelCode, // 使用 channelCode 作为 id
|
||||
name: data.channelInfo.channelName,
|
||||
code: data.channelInfo.channelCode,
|
||||
phone: data.channelInfo.phone,
|
||||
wechatId: data.channelInfo.wechatId,
|
||||
createType: data.channelInfo.createType,
|
||||
remark: data.channelInfo.remark,
|
||||
createTime: data.channelInfo.createTime,
|
||||
};
|
||||
};
|
||||
|
||||
// 获取渠道统计数据
|
||||
// 获取渠道统计数据(使用真实接口)
|
||||
export const fetchChannelStatistics = async (
|
||||
id: string,
|
||||
channelCode: string,
|
||||
): Promise<ChannelStatistics> => {
|
||||
await delay(500);
|
||||
const data = await request(
|
||||
"/v1/frontend/distribution/user/home",
|
||||
{ channelCode },
|
||||
"GET",
|
||||
) as ChannelHomeData;
|
||||
|
||||
// 将接口返回的数据转换为 ChannelStatistics 格式
|
||||
return {
|
||||
totalFriends: 0,
|
||||
todayFriends: 0,
|
||||
totalCustomers: 0,
|
||||
todayCustomers: 0,
|
||||
totalRevenue: 8.0,
|
||||
pendingWithdrawal: 8.0,
|
||||
pendingReview: 0.0,
|
||||
withdrawn: 0.0,
|
||||
totalFriends: data.customerStats.totalFriends,
|
||||
todayFriends: data.customerStats.todayFriends,
|
||||
totalCustomers: data.customerStats.totalCustomers,
|
||||
todayCustomers: data.customerStats.todayCustomers,
|
||||
totalRevenue: data.financialStats.totalRevenue,
|
||||
pendingWithdrawal: data.financialStats.withdrawableAmount,
|
||||
pendingReview: data.financialStats.pendingReview,
|
||||
withdrawn: data.financialStats.withdrawn,
|
||||
};
|
||||
};
|
||||
|
||||
// 获取收益明细列表
|
||||
// 获取渠道首页数据(完整数据)
|
||||
export const fetchChannelHomeData = async (
|
||||
channelCode: string,
|
||||
): Promise<ChannelHomeData> => {
|
||||
return request("/v1/frontend/distribution/user/home", { channelCode }, "GET") as Promise<ChannelHomeData>;
|
||||
};
|
||||
|
||||
// 将接口返回的 type 映射到前端的 RevenueType
|
||||
const mapApiTypeToRevenueType = (apiType: string): "addFriend" | "customer" | "other" => {
|
||||
if (apiType === "customer_acquisition") {
|
||||
return "customer";
|
||||
}
|
||||
if (apiType === "add_friend" || apiType === "addFriend") {
|
||||
return "addFriend";
|
||||
}
|
||||
return "other";
|
||||
};
|
||||
|
||||
// 将前端的 RevenueType 映射到接口的 filterType
|
||||
const mapRevenueTypeToFilterType = (type?: RevenueType): string => {
|
||||
if (!type || type === "all") {
|
||||
return "";
|
||||
}
|
||||
if (type === "customer") {
|
||||
return "customer_acquisition";
|
||||
}
|
||||
if (type === "addFriend") {
|
||||
return "add_friend";
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
// 获取收益明细列表(使用真实接口)
|
||||
export const fetchRevenueList = async (params: {
|
||||
channelId: string;
|
||||
channelCode: string;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
type?: RevenueType;
|
||||
date?: string;
|
||||
}): Promise<{ list: RevenueRecord[]; total: number; page: number }> => {
|
||||
await delay(500);
|
||||
|
||||
// 模拟数据
|
||||
const mockRecords: RevenueRecord[] = [
|
||||
const response = await request(
|
||||
"/v1/frontend/distribution/user/revenue-records",
|
||||
{
|
||||
id: "REV001",
|
||||
title: "加好友任务-春季活动",
|
||||
type: "addFriend",
|
||||
typeLabel: "加好友",
|
||||
amount: 5.0,
|
||||
date: "2025-12-09 16:54",
|
||||
channelCode: params.channelCode,
|
||||
page: params.page || 1,
|
||||
limit: params.limit || 10,
|
||||
filterType: mapRevenueTypeToFilterType(params.type),
|
||||
date: params.date || "",
|
||||
},
|
||||
];
|
||||
"GET",
|
||||
) as {
|
||||
list: Array<{
|
||||
id: string;
|
||||
sourceType: string;
|
||||
type: string;
|
||||
typeLabel: string;
|
||||
amount: number;
|
||||
remark?: string;
|
||||
createTime: string;
|
||||
}>;
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
};
|
||||
|
||||
// 筛选过滤
|
||||
let filteredList = mockRecords;
|
||||
if (params.type && params.type !== "all") {
|
||||
filteredList = filteredList.filter(item => item.type === params.type);
|
||||
}
|
||||
if (params.date) {
|
||||
filteredList = filteredList.filter(item => item.date.startsWith(params.date!));
|
||||
}
|
||||
|
||||
const page = params.page || 1;
|
||||
const limit = params.limit || 10;
|
||||
const start = (page - 1) * limit;
|
||||
const end = start + limit;
|
||||
const paginatedList = filteredList.slice(start, end);
|
||||
// 将接口返回的数据转换为 RevenueRecord 格式
|
||||
const list: RevenueRecord[] = response.list.map(item => ({
|
||||
id: item.id,
|
||||
title: item.sourceType || item.typeLabel, // 使用 sourceType 作为 title,如果没有则使用 typeLabel
|
||||
type: mapApiTypeToRevenueType(item.type),
|
||||
typeLabel: item.typeLabel,
|
||||
amount: item.amount, // 金额是分
|
||||
date: item.createTime,
|
||||
remark: item.remark,
|
||||
}));
|
||||
|
||||
return {
|
||||
list: paginatedList,
|
||||
total: filteredList.length,
|
||||
page,
|
||||
list,
|
||||
total: response.total,
|
||||
page: response.page,
|
||||
};
|
||||
};
|
||||
|
||||
// 获取提现明细列表
|
||||
// 获取提现明细列表(使用真实接口)
|
||||
export const fetchWithdrawalDetailList = async (params: {
|
||||
channelId: string;
|
||||
channelCode: string;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
status?: WithdrawalDetailStatus;
|
||||
payType?: "all" | "wechat" | "alipay" | "bankcard";
|
||||
date?: string;
|
||||
}): Promise<{
|
||||
list: WithdrawalDetailRecord[];
|
||||
total: number;
|
||||
page: number;
|
||||
}> => {
|
||||
await delay(500);
|
||||
const requestParams: any = {
|
||||
channelCode: params.channelCode,
|
||||
page: params.page || 1,
|
||||
limit: params.limit || 10,
|
||||
status: params.status || "all",
|
||||
payType: params.payType || "all",
|
||||
};
|
||||
|
||||
// 模拟数据
|
||||
const mockRecords: WithdrawalDetailRecord[] = [
|
||||
{
|
||||
id: "WD001",
|
||||
amount: 100.0,
|
||||
status: "pending",
|
||||
applyDate: "2025-12-10 14:30",
|
||||
},
|
||||
{
|
||||
id: "WD002",
|
||||
amount: 50.0,
|
||||
status: "approved",
|
||||
applyDate: "2025-12-09 10:20",
|
||||
reviewDate: "2025-12-09 15:30",
|
||||
},
|
||||
{
|
||||
id: "WD003",
|
||||
amount: 200.0,
|
||||
status: "paid",
|
||||
applyDate: "2025-12-08 09:15",
|
||||
reviewDate: "2025-12-08 14:20",
|
||||
paidDate: "2025-12-08 16:45",
|
||||
},
|
||||
{
|
||||
id: "WD004",
|
||||
amount: 80.0,
|
||||
status: "rejected",
|
||||
applyDate: "2025-12-07 11:00",
|
||||
reviewDate: "2025-12-07 16:00",
|
||||
remark: "提现金额超出限制",
|
||||
},
|
||||
{
|
||||
id: "WD005",
|
||||
amount: 150.0,
|
||||
status: "approved",
|
||||
applyDate: "2025-12-06 13:25",
|
||||
reviewDate: "2025-12-06 18:10",
|
||||
},
|
||||
{
|
||||
id: "WD006",
|
||||
amount: 120.0,
|
||||
status: "paid",
|
||||
applyDate: "2025-12-05 08:30",
|
||||
reviewDate: "2025-12-05 12:15",
|
||||
paidDate: "2025-12-05 14:20",
|
||||
},
|
||||
{
|
||||
id: "WD007",
|
||||
amount: 60.0,
|
||||
status: "pending",
|
||||
applyDate: "2025-12-04 15:40",
|
||||
},
|
||||
{
|
||||
id: "WD008",
|
||||
amount: 90.0,
|
||||
status: "paid",
|
||||
applyDate: "2025-12-03 10:10",
|
||||
reviewDate: "2025-12-03 14:30",
|
||||
paidDate: "2025-12-03 16:00",
|
||||
remark: "已到账",
|
||||
},
|
||||
];
|
||||
|
||||
// 筛选过滤
|
||||
let filteredList = mockRecords;
|
||||
if (params.status && params.status !== "all") {
|
||||
filteredList = filteredList.filter(item => item.status === params.status);
|
||||
}
|
||||
// 如果有日期参数,添加到请求参数中
|
||||
if (params.date) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.applyDate.startsWith(params.date!),
|
||||
);
|
||||
requestParams.date = params.date;
|
||||
}
|
||||
|
||||
const page = params.page || 1;
|
||||
const limit = params.limit || 10;
|
||||
const start = (page - 1) * limit;
|
||||
const end = start + limit;
|
||||
const paginatedList = filteredList.slice(start, end);
|
||||
const response = await request(
|
||||
"/v1/frontend/distribution/user/withdrawal-records",
|
||||
requestParams,
|
||||
"GET",
|
||||
) as {
|
||||
list: Array<{
|
||||
id: string;
|
||||
amount: number;
|
||||
status: "pending" | "approved" | "rejected" | "paid";
|
||||
statusLabel: string;
|
||||
payType: string;
|
||||
payTypeLabel: string;
|
||||
applyTime: string;
|
||||
reviewTime: string | null;
|
||||
reviewer: string | null;
|
||||
remark: string | null;
|
||||
}>;
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
};
|
||||
|
||||
// 将接口返回的数据转换为 WithdrawalDetailRecord 格式
|
||||
const list: WithdrawalDetailRecord[] = response.list.map(item => ({
|
||||
id: item.id,
|
||||
amount: item.amount, // 金额是分
|
||||
status: item.status,
|
||||
applyDate: item.applyTime,
|
||||
reviewDate: item.reviewTime || undefined,
|
||||
paidDate: undefined, // 接口没有单独的 paidDate 字段
|
||||
remark: item.remark || undefined,
|
||||
reviewer: item.reviewer || undefined,
|
||||
}));
|
||||
|
||||
return {
|
||||
list: paginatedList,
|
||||
total: filteredList.length,
|
||||
page,
|
||||
list,
|
||||
total: response.total,
|
||||
page: response.page,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ export interface RevenueRecord {
|
||||
typeLabel: string;
|
||||
amount: number;
|
||||
date: string;
|
||||
remark?: string; // 备注
|
||||
}
|
||||
|
||||
// 提现明细状态
|
||||
@@ -49,4 +50,30 @@ export interface WithdrawalDetailRecord {
|
||||
reviewDate?: string;
|
||||
paidDate?: string;
|
||||
remark?: string;
|
||||
reviewer?: string; // 审核人
|
||||
}
|
||||
|
||||
// 渠道前端首页数据
|
||||
export interface ChannelHomeData {
|
||||
channelInfo: {
|
||||
channelName: string;
|
||||
channelCode: string;
|
||||
phone?: string;
|
||||
wechatId?: string;
|
||||
remark?: string;
|
||||
createTime: string;
|
||||
createType: "manual" | "auto";
|
||||
};
|
||||
financialStats: {
|
||||
withdrawableAmount: number; // 可提现金额
|
||||
totalRevenue: number; // 总收益
|
||||
pendingReview: number; // 待审核
|
||||
withdrawn: number; // 已提现
|
||||
};
|
||||
customerStats: {
|
||||
totalFriends: number; // 总加好友数
|
||||
todayFriends: number; // 今日加好友数
|
||||
totalCustomers: number; // 总获客数
|
||||
todayCustomers: number; // 今日获客数
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
import {
|
||||
fetchChannelDetail,
|
||||
fetchChannelStatistics,
|
||||
fetchChannelHomeData,
|
||||
fetchRevenueList,
|
||||
fetchWithdrawalDetailList,
|
||||
} from "./api";
|
||||
@@ -92,7 +93,7 @@ const ChannelDetailPage: React.FC = () => {
|
||||
revenueDate,
|
||||
revenuePage,
|
||||
withdrawalDetailStatus,
|
||||
withdrawalDetailDate,
|
||||
withdrawalDetailDate, // 恢复日期筛选依赖
|
||||
withdrawalDetailPage,
|
||||
]);
|
||||
|
||||
@@ -100,12 +101,33 @@ const ChannelDetailPage: React.FC = () => {
|
||||
if (!id) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const [detail, stats] = await Promise.all([
|
||||
fetchChannelDetail(id),
|
||||
fetchChannelStatistics(id),
|
||||
]);
|
||||
setChannelDetail(detail);
|
||||
setStatistics(stats);
|
||||
// 路由参数 id 实际上就是 channelCode(对应列表的 code)
|
||||
// 使用同一个接口同时获取详情和统计数据,只调用一次接口
|
||||
const homeData = await fetchChannelHomeData(id);
|
||||
|
||||
// 设置渠道详情
|
||||
setChannelDetail({
|
||||
id: homeData.channelInfo.channelCode,
|
||||
name: homeData.channelInfo.channelName,
|
||||
code: homeData.channelInfo.channelCode,
|
||||
phone: homeData.channelInfo.phone,
|
||||
wechatId: homeData.channelInfo.wechatId,
|
||||
createType: homeData.channelInfo.createType,
|
||||
remark: homeData.channelInfo.remark,
|
||||
createTime: homeData.channelInfo.createTime,
|
||||
});
|
||||
|
||||
// 设置统计数据
|
||||
setStatistics({
|
||||
totalFriends: homeData.customerStats.totalFriends,
|
||||
todayFriends: homeData.customerStats.todayFriends,
|
||||
totalCustomers: homeData.customerStats.totalCustomers,
|
||||
todayCustomers: homeData.customerStats.todayCustomers,
|
||||
totalRevenue: homeData.financialStats.totalRevenue,
|
||||
pendingWithdrawal: homeData.financialStats.withdrawableAmount,
|
||||
pendingReview: homeData.financialStats.pendingReview,
|
||||
withdrawn: homeData.financialStats.withdrawn,
|
||||
});
|
||||
} catch (e) {
|
||||
// 处理错误
|
||||
} finally {
|
||||
@@ -118,7 +140,7 @@ const ChannelDetailPage: React.FC = () => {
|
||||
setRevenueLoading(true);
|
||||
try {
|
||||
const res = await fetchRevenueList({
|
||||
channelId: id,
|
||||
channelCode: id, // 使用 channelCode,路由参数 id 就是 channelCode
|
||||
page: revenuePage,
|
||||
limit: 10,
|
||||
type: revenueType,
|
||||
@@ -142,10 +164,11 @@ const ChannelDetailPage: React.FC = () => {
|
||||
setWithdrawalDetailLoading(true);
|
||||
try {
|
||||
const res = await fetchWithdrawalDetailList({
|
||||
channelId: id,
|
||||
channelCode: id, // 使用 channelCode,路由参数 id 就是 channelCode
|
||||
page: withdrawalDetailPage,
|
||||
limit: 10,
|
||||
status: withdrawalDetailStatus,
|
||||
payType: "all", // 暂时默认 all,如果后续需要添加 payType 筛选,可以添加状态
|
||||
date: withdrawalDetailDate
|
||||
? `${withdrawalDetailDate.getFullYear()}-${String(
|
||||
withdrawalDetailDate.getMonth() + 1,
|
||||
|
||||
@@ -659,7 +659,7 @@ const DistributionManagement: React.FC = () => {
|
||||
key={channel.id}
|
||||
className={styles.channelCard}
|
||||
onClick={() =>
|
||||
navigate(`/workspace/distribution-management/${channel.id}`)
|
||||
navigate(`/workspace/distribution-management/${channel.code}`)
|
||||
}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
|
||||
@@ -62,7 +62,7 @@ class ChannelUserController extends Controller
|
||||
// 获取参数
|
||||
$phone = $this->request->param('phone', '');
|
||||
$password = $this->request->param('password', '');
|
||||
|
||||
$companyId = $this->request->param('companyId', 0);
|
||||
// 参数验证
|
||||
if (empty($phone)) {
|
||||
return $this->setCorsHeaders(json([
|
||||
@@ -86,10 +86,12 @@ class ChannelUserController extends Controller
|
||||
$channel = Db::name('distribution_channel')
|
||||
->where([
|
||||
['phone', '=', $phone],
|
||||
['companyId', '=', $companyId],
|
||||
['deleteTime', '=', 0]
|
||||
])
|
||||
->find();
|
||||
|
||||
|
||||
if (!$channel) {
|
||||
return $this->setCorsHeaders(json([
|
||||
'code' => 404,
|
||||
@@ -224,11 +226,16 @@ class ChannelUserController extends Controller
|
||||
$channelInfo = [
|
||||
'channelName' => $channel['name'] ?? '',
|
||||
'channelCode' => $channel['code'] ?? '',
|
||||
'phone' => $channel['phone'] ?? '',
|
||||
'wechatId' => $channel['wechatId'] ?? '',
|
||||
'remark' => $channel['remark'] ?? '',
|
||||
'createTime' => !empty($channel['createTime']) ? date('Y-m-d H:i:s', $channel['createTime']) : '',
|
||||
'createType' => $channel['createType'] ?? '',
|
||||
];
|
||||
|
||||
// 2. 财务统计
|
||||
// 当前可提现金额
|
||||
$withdrawableAmount = intval($channel['withdrawableAmount'] ?? 0);
|
||||
$withdrawableAmount = $channel['withdrawableAmount'] ?? 0;
|
||||
|
||||
// 已提现金额(已打款的提现申请)
|
||||
$withdrawnAmount = Db::name('distribution_withdrawal')
|
||||
@@ -238,7 +245,7 @@ class ChannelUserController extends Controller
|
||||
['status', '=', DistributionWithdrawal::STATUS_PAID]
|
||||
])
|
||||
->sum('amount');
|
||||
$withdrawnAmount = intval($withdrawnAmount ?? 0);
|
||||
$withdrawnAmount = $withdrawnAmount ?? 0;
|
||||
|
||||
// 待审核金额(待审核的提现申请)
|
||||
$pendingReviewAmount = Db::name('distribution_withdrawal')
|
||||
@@ -248,7 +255,7 @@ class ChannelUserController extends Controller
|
||||
['status', '=', DistributionWithdrawal::STATUS_PENDING]
|
||||
])
|
||||
->sum('amount');
|
||||
$pendingReviewAmount = intval($pendingReviewAmount ?? 0);
|
||||
$pendingReviewAmount = $pendingReviewAmount ?? 0;
|
||||
|
||||
// 总收益(所有收益记录的总和)
|
||||
$totalRevenue = Db::name('distribution_revenue_record')
|
||||
@@ -257,13 +264,13 @@ class ChannelUserController extends Controller
|
||||
['channelId', '=', $channelId]
|
||||
])
|
||||
->sum('amount');
|
||||
$totalRevenue = intval($totalRevenue ?? 0);
|
||||
$totalRevenue = $totalRevenue ?? 0;
|
||||
|
||||
$financialStats = [
|
||||
'withdrawableAmount' => round($withdrawableAmount / 100, 2), // 当前可提现金额(元)
|
||||
'totalRevenue' => round($totalRevenue / 100, 2), // 总收益(元)
|
||||
'pendingReview' => round($pendingReviewAmount / 100, 2), // 待审核(元)
|
||||
'withdrawn' => round($withdrawnAmount / 100, 2), // 已提现(元)
|
||||
'withdrawableAmount' => $withdrawableAmount, // 当前可提现金额
|
||||
'totalRevenue' => $totalRevenue, // 总收益
|
||||
'pendingReview' => $pendingReviewAmount, // 待审核
|
||||
'withdrawn' => $withdrawnAmount, // 已提现
|
||||
];
|
||||
|
||||
// 3. 客户和好友统计
|
||||
|
||||
Reference in New Issue
Block a user