From f208bbdb9aa3a360115c56644d85882493bce6f9 Mon Sep 17 00:00:00 2001 From: wong <106998207@qq.com> Date: Sat, 20 Dec 2025 16:45:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B8=A0=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../distribution-management/detail/api.ts | 289 ++++++++++-------- .../distribution-management/detail/data.ts | 27 ++ .../distribution-management/detail/index.tsx | 41 ++- .../distribution-management/index.tsx | 2 +- .../distribution/ChannelUserController.php | 25 +- 5 files changed, 230 insertions(+), 154 deletions(-) diff --git a/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/api.ts b/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/api.ts index 4b3bf8b2..114c7efa 100644 --- a/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/api.ts +++ b/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/api.ts @@ -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 => { - 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 => { - 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 => { + return request("/v1/frontend/distribution/user/home", { channelCode }, "GET") as Promise; +}; + +// 将接口返回的 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, }; }; diff --git a/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/data.ts b/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/data.ts index 28658ce5..31cd9a6b 100644 --- a/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/data.ts +++ b/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/data.ts @@ -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; // 今日获客数 + }; } diff --git a/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/index.tsx b/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/index.tsx index 033648a1..1df858fc 100644 --- a/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/distribution-management/detail/index.tsx @@ -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, diff --git a/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx b/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx index b1658bef..2c91b2e7 100644 --- a/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/distribution-management/index.tsx @@ -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" }} > diff --git a/Server/application/cunkebao/controller/distribution/ChannelUserController.php b/Server/application/cunkebao/controller/distribution/ChannelUserController.php index 5ee436cf..ee6dc67f 100644 --- a/Server/application/cunkebao/controller/distribution/ChannelUserController.php +++ b/Server/application/cunkebao/controller/distribution/ChannelUserController.php @@ -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. 客户和好友统计