This commit is contained in:
eleanor.mao 2025-05-29 01:04:31 +08:00
parent fa30ec2988
commit ed99c7b1ae
6 changed files with 93 additions and 55 deletions

View File

@ -3,12 +3,12 @@ import classNames from 'classnames';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import ListPlaceholder from '@/components/list-placeholder'; import ListPlaceholder from '@/components/list-placeholder';
import { ProfitStatusDescriptions } from '@/constants/partner';
import { GetProfitRequest, PartnerProfitItem, ProfitType } from '@/types/partner'; import { GetProfitRequest, PartnerProfitItem, ProfitType } from '@/types/partner';
import { logWithPrefix } from '@/utils/common'; import { logWithPrefix } from '@/utils/common';
import { formatMoney, formatTimestamp, getProfitList as requestData } from '@/utils/partner'; import { formatMoney, formatTimestamp, getProfitList as requestData } from '@/utils/partner';
import './index.less'; import './index.less';
import { PROFIT_STATUS_MAP, PROFIT_TYPE_MAP } from '@/constants/partner';
export interface IPartnerProfitListProps extends GetProfitRequest { export interface IPartnerProfitListProps extends GetProfitRequest {
visible?: boolean; visible?: boolean;
@ -22,7 +22,7 @@ const PREFIX = 'partner-profit';
const log = logWithPrefix(PREFIX); const log = logWithPrefix(PREFIX);
function ProfitList(props: IPartnerProfitListProps) { function ProfitList(props: IPartnerProfitListProps) {
const { className, listHeight, refreshDisabled, visible = true, profitType, onListEmpty } = props; const { className, listHeight, refreshDisabled, visible = true, type, onListEmpty } = props;
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
const [loadingMore, setLoadingMore] = useState(false); const [loadingMore, setLoadingMore] = useState(false);
const [loadMoreError, setLoadMoreError] = useState(false); const [loadMoreError, setLoadMoreError] = useState(false);
@ -34,7 +34,7 @@ function ProfitList(props: IPartnerProfitListProps) {
try { try {
setRefreshing(true); setRefreshing(true);
setLoadMoreError(false); setLoadMoreError(false);
const list = await requestData({ profitType }); const list = await requestData({ type });
setDataList(list); setDataList(list);
!list.length && onListEmptyRef.current?.(); !list.length && onListEmptyRef.current?.();
log('pull refresh success'); log('pull refresh success');
@ -65,7 +65,7 @@ function ProfitList(props: IPartnerProfitListProps) {
setDataList([]); setDataList([]);
setLoadingMore(true); setLoadingMore(true);
setLoadMoreError(false); setLoadMoreError(false);
const list = await requestData({ profitType }); const list = await requestData({ type });
setDataList(list); setDataList(list);
!list.length && onListEmptyRef.current?.(); !list.length && onListEmptyRef.current?.();
} catch (e) { } catch (e) {
@ -77,7 +77,7 @@ function ProfitList(props: IPartnerProfitListProps) {
} }
}; };
refresh(); refresh();
}, [visible, profitType]); }, [visible, type]);
return ( return (
<div className={`${PREFIX}__tab-content`}> <div className={`${PREFIX}__tab-content`}>
@ -95,18 +95,21 @@ function ProfitList(props: IPartnerProfitListProps) {
fixedHeight={typeof listHeight !== 'undefined'} fixedHeight={typeof listHeight !== 'undefined'}
style={listHeight ? { height: `${listHeight}px` } : undefined} style={listHeight ? { height: `${listHeight}px` } : undefined}
> >
{dataList.map(item => ( {dataList.map(item => {
<div className={`${PREFIX}__row`} key={item.id}> const isChat = type === ProfitType.CHAT_SHARE || item.earnType.toString().toLowerCase().indexOf('chat');
<div className={`${PREFIX}__row-content`}> return (
<div className={`${PREFIX}__item time`}>{formatTimestamp(item.created)}</div> <div className={`${PREFIX}__row`} key={item.id}>
<div className={`${PREFIX}__item project`}>{PROFIT_TYPE_MAP[profitType]}</div> <div className={`${PREFIX}__row-content`}>
<div className={`${PREFIX}__item status`}> <div className={`${PREFIX}__item time`}>{formatTimestamp(item.created)}</div>
{profitType === ProfitType.Anchor ? '已结算' : PROFIT_STATUS_MAP[item.status]} <div className={`${PREFIX}__item project`}>{isChat ? '主播被开聊' : '会员支付'}</div>
<div className={`${PREFIX}__item status`}>
{isChat ? '已结算' : ProfitStatusDescriptions[item.status]}
</div>
<div className={`${PREFIX}__item income`}>+{formatMoney(item.amount)}</div>
</div> </div>
<div className={`${PREFIX}__item income`}>+{formatMoney(item.profit)}</div>
</div> </div>
</div> );
))} })}
<ListPlaceholder hasMore={false} loadingMore={loadingMore} loadMoreError={loadMoreError} /> <ListPlaceholder hasMore={false} loadingMore={loadingMore} loadMoreError={loadMoreError} />
</List> </List>
</PullRefresh> </PullRefresh>

View File

@ -30,15 +30,15 @@ export default function PartnerProfit() {
<Tabs className={`${PREFIX}__tabs`}> <Tabs className={`${PREFIX}__tabs`}>
<Tabs.TabPane title="推荐主播收益"> <Tabs.TabPane title="推荐主播收益">
<TableTitle /> <TableTitle />
<ProfitList profitType={ProfitType.Anchor} /> <ProfitList type={ProfitType.CHAT_SHARE} />
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane title="推荐会员权益"> <Tabs.TabPane title="推荐会员权益">
<TableTitle /> <TableTitle />
<ProfitList profitType={ProfitType.Member} /> <ProfitList type={ProfitType.PAYMENT_SHARE} />
</Tabs.TabPane> </Tabs.TabPane>
<Tabs.TabPane title="推荐合伙人收益"> <Tabs.TabPane title="推荐合伙人收益">
<TableTitle /> <TableTitle />
<ProfitList profitType={ProfitType.Partner} /> <ProfitList type={ProfitType.INDIRECT_MEMBER_REFERRAL} />
</Tabs.TabPane> </Tabs.TabPane>
</Tabs> </Tabs>
</div> </div>

View File

@ -1,21 +1,54 @@
export enum ProfitType {
Anchor = '1',
Member = '2',
Partner = '3',
}
export enum ProfitStatus { export enum ProfitStatus {
AVAILABLE = '1', /**
WITHDRAWING = '2', * / ()
WITHDRAW = '3', */
PENDING_CALCULATION = 0,
/**
* / (T+7 )
*
*/
DIRECT_SETTLEMENT_PENDING = 1,
/**
* /
*/
DIRECT_SETTLEMENT_PROCESSING = 2,
/**
* ()
*/
INDIRECT_SETTLED_TO_BALANCE = 3,
/**
* (退)
*/
CANCELLED = 4,
/**
*
*/
FAILED = 5,
/**
*
*/
OTHER = 6,
/**
*
*/
FINISHED = 7,
} }
export const PROFIT_TYPE_MAP = { // 如果需要为每个枚举值添加描述,可以使用一个单独的映射对象
[ProfitType.Anchor]: '主播被开聊', export const ProfitStatusDescriptions: { [key in ProfitStatus]: string } = {
[ProfitType.Member]: '会员支付', [ProfitStatus.PENDING_CALCULATION]: '',
[ProfitType.Partner]: '合伙人收益分成', [ProfitStatus.DIRECT_SETTLEMENT_PENDING]: '待分账',
}; [ProfitStatus.DIRECT_SETTLEMENT_PROCESSING]: '',
export const PROFIT_STATUS_MAP = { [ProfitStatus.INDIRECT_SETTLED_TO_BALANCE]: '',
[ProfitStatus.AVAILABLE]: '可提现', [ProfitStatus.CANCELLED]: '',
[ProfitStatus.WITHDRAWING]: '提现中', [ProfitStatus.FAILED]: '',
[ProfitStatus.WITHDRAW]: '已提现', [ProfitStatus.OTHER]: '',
[ProfitStatus.FINISHED]: '已分账',
}; };

View File

@ -1,4 +1,4 @@
// export const DOMAIN = 'http://192.168.60.120:8082'; // export const DOMAIN = 'http://192.168.60.148:8082';
export const DOMAIN = 'https://neighbourhood.cn'; export const DOMAIN = 'https://neighbourhood.cn';
export const BASE_URL = `${DOMAIN}/api`; export const BASE_URL = `${DOMAIN}/api`;
@ -80,6 +80,6 @@ export enum API {
GET_INVITE_CODE = '/user/getUserInviteCode', GET_INVITE_CODE = '/user/getUserInviteCode',
GET_INVITE_LIST = '/user/inviteUsers', GET_INVITE_LIST = '/user/inviteUsers',
BECOME_PARTNER = '/user/becomePartner', BECOME_PARTNER = '/user/becomePartner',
GET_PROFIT_LIST = '/profit/profits', GET_PROFIT_LIST = '/user/profit/list',
GET_PROFIT_STAT = '/user/profits', GET_PROFIT_STAT = '/user/profits',
} }

View File

@ -36,9 +36,9 @@ export interface InviteUserInfo {
roleType: string; // 角色类型,可选 roleType: string; // 角色类型,可选
} }
export enum ProfitType { export enum ProfitType {
Anchor = '1', PAYMENT_SHARE = 'PAYMENT_SHARE',
Member = '2', CHAT_SHARE = 'CHAT_SHARE',
Partner = '3', INDIRECT_MEMBER_REFERRAL = 'INDIRECT_MEMBER_REFERRAL',
} }
export enum ProfitStatus { export enum ProfitStatus {
AVAILABLE = '1', AVAILABLE = '1',
@ -46,18 +46,21 @@ export enum ProfitStatus {
WITHDRAW = '3', WITHDRAW = '3',
} }
export interface GetProfitRequest { export interface GetProfitRequest {
profitType: ProfitType; type: ProfitType;
} }
export interface PartnerProfitItem { export interface PartnerProfitItem {
id: number; // 唯一标识 id: number; // 唯一标识
userId: string; // 用户ID partnerId: string;
profit: number; // 利润 sourceUserId: string;
profitType: ProfitType; // 利润类型 originatingUserId: string; // 用户ID
relatedEntityId: string;
relatedEntityType: string;
amount: number; // 利润
earnType: ProfitType; // 利润类型
status: ProfitStatus; // 状态 status: ProfitStatus; // 状态
relatedId: string; // 相关ID
remark: string; // 备注 remark: string; // 备注
created: string; // 创建时间 created: string; // 创建时间
updated: string; // 更新时间 updated: string; // 更新时间
profitTypeEnum: string; // 利润类型枚举 expectedSettlementDate: string;
statusEnum: string; // 状态枚举 actualSettlementDate: string;
} }

View File

@ -61,8 +61,11 @@ export const getInviteCode = async () => {
return inviteCode; return inviteCode;
}; };
export const getProfitList = async (data: GetProfitRequest) => { export const getProfitList = async (data: GetProfitRequest) => {
// const result = await http.post<PartnerProfitItem[]>(API.GET_PROFIT_LIST, { data }); const result = await http.post<PartnerProfitItem[]>(API.GET_PROFIT_LIST, {
// return Array.isArray(result) ? result : []; data,
contentType: 'application/x-www-form-urlencoded',
});
return Array.isArray(result) ? result : [];
return []; return [];
}; };
export const formatMoney = (cents: number) => { export const formatMoney = (cents: number) => {
@ -73,11 +76,8 @@ export const formatMoney = (cents: number) => {
return yuan.toFixed(2); return yuan.toFixed(2);
}; };
export function formatTimestamp(timestamp: string): string { export function formatTimestamp(timestamp: string): string {
// 将字符串时间戳转换为数字类型
const time = Number(timestamp);
// 创建 Date 对象 // 创建 Date 对象
const date = new Date(time); const date = new Date(timestamp);
// 获取年、月、日、时、分、秒 // 获取年、月、日、时、分、秒
const YYYY = date.getFullYear(); const YYYY = date.getFullYear();
@ -85,10 +85,9 @@ export function formatTimestamp(timestamp: string): string {
const DD = String(date.getDate()).padStart(2, '0'); const DD = String(date.getDate()).padStart(2, '0');
const HH = String(date.getHours()).padStart(2, '0'); const HH = String(date.getHours()).padStart(2, '0');
const mm = String(date.getMinutes()).padStart(2, '0'); const mm = String(date.getMinutes()).padStart(2, '0');
const ss = String(date.getSeconds()).padStart(2, '0');
// 拼接成所需的格式 // 拼接成所需的格式
return `${YYYY}.${MM}.${DD} ${HH}:${mm}:${ss}`; return `${YYYY}.${MM}.${DD} ${HH}:${mm}`;
} }
export function formatUserId(input: string): string { export function formatUserId(input: string): string {