forked from gxwebsoft/mp-10550
feat(dealer): 添加分销商收益明细页面并优化订单管理功能
- 新增收益明细页面,支持下拉刷新和上拉加载更多 - 在app.config.ts中注册收益明细页面路由 - 更新API基础URL配置,统一使用mp-api域名 - 优化提交表单逻辑,确保refereeId参数为数字类型 - 修改订单页面,添加resourceId参数以正确过滤分销订单 - 修复订单号显示逻辑,优先使用接口返回的订单号 - 优化订单列表项点击事件,跳转到收益明细页面 - 更新客户名称显示格式,包含昵称和用户ID - 调整订单详情展示布局和信息内容
This commit is contained in:
@@ -3,19 +3,19 @@ export const ENV_CONFIG = {
|
|||||||
// 开发环境
|
// 开发环境
|
||||||
development: {
|
development: {
|
||||||
// API_BASE_URL: 'http://127.0.0.1:9200/api',
|
// API_BASE_URL: 'http://127.0.0.1:9200/api',
|
||||||
API_BASE_URL: 'https://cms-api.websoft.top/api',
|
API_BASE_URL: 'https://mp-api.websoft.top/api',
|
||||||
APP_NAME: '开发环境',
|
APP_NAME: '开发环境',
|
||||||
DEBUG: 'true',
|
DEBUG: 'true',
|
||||||
},
|
},
|
||||||
// 生产环境
|
// 生产环境
|
||||||
production: {
|
production: {
|
||||||
API_BASE_URL: 'https://cms-api.websoft.top/api',
|
API_BASE_URL: 'https://mp-api.websoft.top/api',
|
||||||
APP_NAME: '桂乐淘',
|
APP_NAME: '桂乐淘',
|
||||||
DEBUG: 'false',
|
DEBUG: 'false',
|
||||||
},
|
},
|
||||||
// 测试环境
|
// 测试环境
|
||||||
test: {
|
test: {
|
||||||
API_BASE_URL: 'https://cms-api.s209.websoft.top/api',
|
API_BASE_URL: 'https://mp-api.s209.websoft.top/api',
|
||||||
APP_NAME: '测试环境',
|
APP_NAME: '测试环境',
|
||||||
DEBUG: 'true',
|
DEBUG: 'true',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,5 +31,11 @@ export interface ShopDealerCapital {
|
|||||||
*/
|
*/
|
||||||
export interface ShopDealerCapitalParam extends PageParam {
|
export interface ShopDealerCapitalParam extends PageParam {
|
||||||
id?: number;
|
id?: number;
|
||||||
|
// 仅查询当前分销商的收益/资金明细
|
||||||
|
userId?: number;
|
||||||
|
// 可选:按订单过滤
|
||||||
|
orderId?: number;
|
||||||
|
// 可选:资金流动类型过滤
|
||||||
|
flowType?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ export interface ShopDealerOrder {
|
|||||||
id?: number;
|
id?: number;
|
||||||
// 买家用户ID
|
// 买家用户ID
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
nickname?: string;
|
||||||
|
// 订单编号(部分接口会直接返回订单号字符串)
|
||||||
|
orderNo?: string;
|
||||||
// 订单ID
|
// 订单ID
|
||||||
orderId?: number;
|
orderId?: number;
|
||||||
// 订单总金额(不含运费)
|
// 订单总金额(不含运费)
|
||||||
@@ -47,5 +50,7 @@ export interface ShopDealerOrderParam extends PageParam {
|
|||||||
secondUserId?: number;
|
secondUserId?: number;
|
||||||
thirdUserId?: number;
|
thirdUserId?: number;
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
// 数据权限/资源ID(通常传当前登录用户ID)
|
||||||
|
resourceId?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export default {
|
|||||||
"apply/add",
|
"apply/add",
|
||||||
"withdraw/index",
|
"withdraw/index",
|
||||||
"orders/index",
|
"orders/index",
|
||||||
|
"capital/index",
|
||||||
"team/index",
|
"team/index",
|
||||||
"qrcode/index",
|
"qrcode/index",
|
||||||
"invite-stats/index",
|
"invite-stats/index",
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ const AddUserAddress = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const submitSucceed = async (values: any) => {
|
const submitSucceed = async (values: User) => {
|
||||||
try {
|
try {
|
||||||
// 验证必填字段
|
// 验证必填字段
|
||||||
if (!values.phone && !FormData?.phone) {
|
if (!values.phone && !FormData?.phone) {
|
||||||
@@ -192,7 +192,7 @@ const AddUserAddress = () => {
|
|||||||
userId: user?.userId,
|
userId: user?.userId,
|
||||||
realName: values.realName || FormData?.nickname,
|
realName: values.realName || FormData?.nickname,
|
||||||
mobile: values.phone || FormData?.phone,
|
mobile: values.phone || FormData?.phone,
|
||||||
refereeId: values.refereeId || FormData?.refereeId
|
refereeId: Number(values.refereeId) || Number(FormData?.refereeId)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (roles.length > 0) {
|
if (roles.length > 0) {
|
||||||
|
|||||||
4
src/dealer/capital/index.config.ts
Normal file
4
src/dealer/capital/index.config.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export default definePageConfig({
|
||||||
|
navigationBarTitleText: '收益明细'
|
||||||
|
})
|
||||||
|
|
||||||
2
src/dealer/capital/index.scss
Normal file
2
src/dealer/capital/index.scss
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/* Intentionally empty: styling is done via utility classes. */
|
||||||
|
|
||||||
199
src/dealer/capital/index.tsx
Normal file
199
src/dealer/capital/index.tsx
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import React, {useCallback, useEffect, useState} from 'react'
|
||||||
|
import {View, Text, ScrollView} from '@tarojs/components'
|
||||||
|
import {Empty, Tag, PullToRefresh, Loading} from '@nutui/nutui-react-taro'
|
||||||
|
import Taro from '@tarojs/taro'
|
||||||
|
import {pageShopDealerCapital} from '@/api/shop/shopDealerCapital'
|
||||||
|
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||||
|
import type {ShopDealerCapital} from '@/api/shop/shopDealerCapital/model'
|
||||||
|
|
||||||
|
const PAGE_SIZE = 10
|
||||||
|
|
||||||
|
const DealerCapital: React.FC = () => {
|
||||||
|
const {dealerUser} = useDealerUser()
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [refreshing, setRefreshing] = useState(false)
|
||||||
|
const [loadingMore, setLoadingMore] = useState(false)
|
||||||
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
|
const [hasMore, setHasMore] = useState(true)
|
||||||
|
const [records, setRecords] = useState<ShopDealerCapital[]>([])
|
||||||
|
|
||||||
|
const getFlowTypeText = (flowType?: number) => {
|
||||||
|
switch (flowType) {
|
||||||
|
case 10:
|
||||||
|
return '佣金收入'
|
||||||
|
case 20:
|
||||||
|
return '提现支出'
|
||||||
|
case 30:
|
||||||
|
return '转账支出'
|
||||||
|
case 40:
|
||||||
|
return '转账收入'
|
||||||
|
default:
|
||||||
|
return '资金变动'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFlowTypeTag = (flowType?: number) => {
|
||||||
|
// 收入:success;支出:danger;其它:default
|
||||||
|
if (flowType === 10 || flowType === 40) return 'success'
|
||||||
|
if (flowType === 20 || flowType === 30) return 'danger'
|
||||||
|
return 'default'
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatMoney = (flowType?: number, money?: string) => {
|
||||||
|
const isIncome = flowType === 10 || flowType === 40
|
||||||
|
const isExpense = flowType === 20 || flowType === 30
|
||||||
|
const sign = isIncome ? '+' : isExpense ? '-' : ''
|
||||||
|
return `${sign}${money || '0.00'}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchRecords = useCallback(async (page: number = 1, isRefresh: boolean = false) => {
|
||||||
|
if (!dealerUser?.userId) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isRefresh) {
|
||||||
|
setRefreshing(true)
|
||||||
|
} else if (page === 1) {
|
||||||
|
setLoading(true)
|
||||||
|
} else {
|
||||||
|
setLoadingMore(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await pageShopDealerCapital({
|
||||||
|
page,
|
||||||
|
limit: PAGE_SIZE,
|
||||||
|
// 只显示与当前登录用户相关的收益明细
|
||||||
|
userId: dealerUser.userId
|
||||||
|
})
|
||||||
|
|
||||||
|
const list = result?.list || []
|
||||||
|
if (page === 1) {
|
||||||
|
setRecords(list)
|
||||||
|
} else {
|
||||||
|
setRecords(prev => [...prev, ...list])
|
||||||
|
}
|
||||||
|
|
||||||
|
setHasMore(list.length === PAGE_SIZE)
|
||||||
|
setCurrentPage(page)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取收益明细失败:', error)
|
||||||
|
Taro.showToast({
|
||||||
|
title: '获取收益明细失败',
|
||||||
|
icon: 'error'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
setRefreshing(false)
|
||||||
|
setLoadingMore(false)
|
||||||
|
}
|
||||||
|
}, [dealerUser?.userId])
|
||||||
|
|
||||||
|
const handleRefresh = async () => {
|
||||||
|
await fetchRecords(1, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLoadMore = async () => {
|
||||||
|
if (!loadingMore && hasMore) {
|
||||||
|
await fetchRecords(currentPage + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dealerUser?.userId) {
|
||||||
|
fetchRecords(1)
|
||||||
|
}
|
||||||
|
}, [fetchRecords, dealerUser?.userId])
|
||||||
|
|
||||||
|
if (!dealerUser) {
|
||||||
|
return (
|
||||||
|
<View className="bg-gray-50 min-h-screen flex items-center justify-center">
|
||||||
|
<Loading/>
|
||||||
|
<Text className="text-gray-500 mt-2">加载中...</Text>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className="min-h-screen bg-gray-50">
|
||||||
|
<PullToRefresh
|
||||||
|
onRefresh={handleRefresh}
|
||||||
|
disabled={refreshing}
|
||||||
|
pullingText="下拉刷新"
|
||||||
|
canReleaseText="释放刷新"
|
||||||
|
refreshingText="刷新中..."
|
||||||
|
completeText="刷新完成"
|
||||||
|
>
|
||||||
|
<ScrollView
|
||||||
|
scrollY
|
||||||
|
className="h-screen"
|
||||||
|
onScrollToLower={handleLoadMore}
|
||||||
|
lowerThreshold={50}
|
||||||
|
>
|
||||||
|
<View className="p-4">
|
||||||
|
{loading && records.length === 0 ? (
|
||||||
|
<View className="text-center py-8">
|
||||||
|
<Loading/>
|
||||||
|
<Text className="text-gray-500 mt-2">加载中...</Text>
|
||||||
|
</View>
|
||||||
|
) : records.length > 0 ? (
|
||||||
|
<>
|
||||||
|
{records.map((item) => (
|
||||||
|
<View key={item.id} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
|
||||||
|
<View className="flex justify-between items-start mb-1">
|
||||||
|
<Text className="font-semibold text-gray-800">
|
||||||
|
{item.describe || '收益明细'}
|
||||||
|
</Text>
|
||||||
|
<Tag type={getFlowTypeTag(item.flowType)}>
|
||||||
|
{getFlowTypeText(item.flowType)}
|
||||||
|
</Tag>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className="flex justify-between items-center mb-1">
|
||||||
|
<Text className="text-sm text-gray-400">
|
||||||
|
佣金收入
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
className={`text-sm font-semibold ${
|
||||||
|
item.flowType === 10 || item.flowType === 40 ? 'text-green-600' :
|
||||||
|
item.flowType === 20 || item.flowType === 30 ? 'text-red-500' :
|
||||||
|
'text-gray-700'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{formatMoney(item.flowType, item.money)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View className="flex justify-between items-center">
|
||||||
|
<Text className="text-sm text-gray-400">
|
||||||
|
{/*用户:{item.userId ?? '-'}*/}
|
||||||
|
</Text>
|
||||||
|
<Text className="text-sm text-gray-400">
|
||||||
|
{item.createTime || '-'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{loadingMore && (
|
||||||
|
<View className="text-center py-4">
|
||||||
|
<Loading/>
|
||||||
|
<Text className="text-gray-500 mt-1 text-sm">加载更多...</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
{!hasMore && records.length > 0 && (
|
||||||
|
<View className="text-center py-4">
|
||||||
|
<Text className="text-gray-400 text-sm">没有更多数据了</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Empty description="暂无收益明细"/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</PullToRefresh>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DealerCapital
|
||||||
@@ -24,7 +24,8 @@ const DealerOrders: React.FC = () => {
|
|||||||
|
|
||||||
// 获取订单数据
|
// 获取订单数据
|
||||||
const fetchOrders = useCallback(async (page: number = 1, isRefresh: boolean = false) => {
|
const fetchOrders = useCallback(async (page: number = 1, isRefresh: boolean = false) => {
|
||||||
if (!dealerUser?.userId) return
|
// 需要当前登录用户ID(用于 resourceId 参数)
|
||||||
|
if (!dealerUser || !dealerUser.userId) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isRefresh) {
|
if (isRefresh) {
|
||||||
@@ -37,14 +38,17 @@ const DealerOrders: React.FC = () => {
|
|||||||
|
|
||||||
const result = await pageShopDealerOrder({
|
const result = await pageShopDealerOrder({
|
||||||
page,
|
page,
|
||||||
limit: 10
|
limit: 10,
|
||||||
|
// 后端需要 resourceId=当前登录用户ID 才能正确过滤分销订单
|
||||||
|
resourceId: dealerUser.userId
|
||||||
})
|
})
|
||||||
|
|
||||||
if (result?.list) {
|
if (result?.list) {
|
||||||
const newOrders = result.list.map(order => ({
|
const newOrders = result.list.map(order => ({
|
||||||
...order,
|
...order,
|
||||||
orderNo: `${order.orderId}`,
|
// 优先使用接口返回的订单号;没有则降级展示 orderId
|
||||||
customerName: `用户${order.userId}`,
|
orderNo: order.orderNo ?? (order.orderId != null ? String(order.orderId) : undefined),
|
||||||
|
customerName: `${order.nickname}${order.userId}`,
|
||||||
userCommission: order.firstMoney || '0.00'
|
userCommission: order.firstMoney || '0.00'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -102,32 +106,37 @@ const DealerOrders: React.FC = () => {
|
|||||||
return 'warning'
|
return 'warning'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleGoCapital = () => {
|
||||||
|
Taro.navigateTo({url: '/dealer/capital/index'})
|
||||||
|
}
|
||||||
|
|
||||||
const renderOrderItem = (order: OrderWithDetails) => (
|
const renderOrderItem = (order: OrderWithDetails) => (
|
||||||
<View key={order.id} className="bg-white rounded-lg p-4 mb-3 shadow-sm">
|
<View
|
||||||
|
key={order.id}
|
||||||
|
className="bg-white rounded-lg p-4 mb-3 shadow-sm"
|
||||||
|
onClick={handleGoCapital}
|
||||||
|
>
|
||||||
<View className="flex justify-between items-start mb-1">
|
<View className="flex justify-between items-start mb-1">
|
||||||
<Text className="font-semibold text-gray-800">
|
<Text className="font-semibold text-gray-800">
|
||||||
订单号:{order.orderNo}
|
订单号:{order.orderNo || '-'}
|
||||||
</Text>
|
</Text>
|
||||||
<Tag type={getStatusColor(order.isSettled, order.isInvalid)}>
|
<Tag type={getStatusColor(order.isSettled, order.isInvalid)}>
|
||||||
{getStatusText(order.isSettled, order.isInvalid)}
|
{getStatusText(order.isSettled, order.isInvalid)}
|
||||||
</Tag>
|
</Tag>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View className="flex justify-between items-center mb-1">
|
{/*<View className="flex justify-between items-center mb-1">*/}
|
||||||
<Text className="text-sm text-gray-400">
|
{/* <Text className="text-sm text-gray-400">*/}
|
||||||
订单金额:¥{order.orderPrice || '0.00'}
|
{/* 订单金额:¥{order.orderPrice || '0.00'}*/}
|
||||||
</Text>
|
{/* </Text>*/}
|
||||||
<Text className="text-sm text-orange-500 font-semibold">
|
{/*</View>*/}
|
||||||
我的佣金:¥{order.userCommission}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View className="flex justify-between items-center">
|
<View className="flex justify-between items-center">
|
||||||
<Text className="text-sm text-gray-400">
|
<Text className="text-sm text-gray-400">
|
||||||
客户:{order.customerName}
|
{order.createTime}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-sm text-gray-400">
|
<Text className="text-sm text-gray-400">
|
||||||
{order.createTime}
|
订单金额:¥{order.orderPrice || '0.00'}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user