Commit 0e13e571 authored by GuanHua's avatar GuanHua
parents 8eba425b eae42aa1
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import {
Row,
Col,
......@@ -18,19 +18,60 @@ import styles from './index.less';
const { TabPane } = Tabs;
interface EquityInfoProps {
const PAGE_SIZE = 8;
export interface ReceivedData {
id?: number;
createTime?: string;
ruleName?: string;
score?: number;
remark?: string;
};
export interface UsageData {
id?: number;
createTime?: string;
rightTypeName?: string;
spendTypeName?: string;
point?: number;
remark?: string;
};
export interface FetchParams {
current: number;
pageSize: number;
};
export interface EquityInfoProps {
equityInfo?: {
sumReturnMoney?: number,
sumUsedPoint?: number,
sumPoint?: number,
sumReturnMoney?: number, // 累计返现金额
sumUsedPoint?: number, // 已用积分
sumPoint?: number, // 累计积分
};
fetchReceivedList?: (params: FetchParams) => Promise<{ data: ReceivedData[] , totalCount: number }>;
fetchUsageList?: (params: FetchParams) => Promise<{ data: UsageData[] , totalCount: number }>;
}
const EquityInfo: React.FC<EquityInfoProps> = ({
equityInfo = {},
fetchReceivedList,
fetchUsageList,
}) => {
const columns: EditableColumns[] = [
const [receivedPage, setReceivedPage] = useState(1);
const [receivedSize, setReceivedSize] = useState(PAGE_SIZE);
const [receivedTotal, setReceivedTotal] = useState(0);
const [receivedList, setReceivedList] = useState([]);
const [receivedListLoading, setReceivedListLoading] = useState(false);
const [usagePage, setUsagePage] = useState(1);
const [usageSize, setUsageSize] = useState(PAGE_SIZE);
const [usageTotal, setUsageTotal] = useState(0);
const [usageList, setUsageList] = useState([]);
const [usageListLoading, setUsageListLoading] = useState(false);
const receivedColumns: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
......@@ -38,28 +79,28 @@ const EquityInfo: React.FC<EquityInfoProps> = ({
},
{
title: '会员权益名称',
dataIndex: 'project',
dataIndex: 'rightTypeName ',
align: 'center',
},
{
title: '获取数量',
dataIndex: 'score',
dataIndex: 'point',
align: 'center',
},
{
title: '获取时间',
dataIndex: 'created',
dataIndex: 'createTime',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
dataIndex: 'remark',
align: 'center',
ellipsis: true,
},
];
const columns2: EditableColumns[] = [
const usageColumns: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
......@@ -67,34 +108,99 @@ const EquityInfo: React.FC<EquityInfoProps> = ({
},
{
title: '会员权益名称',
dataIndex: 'project',
dataIndex: 'rightTypeName',
align: 'center',
},
{
title: '会员权益使用名称',
dataIndex: 'name',
dataIndex: 'spendTypeName',
align: 'center',
},
{
title: '使用数量',
dataIndex: 'count',
dataIndex: 'point',
align: 'center',
},
{
title: '使用时间',
dataIndex: 'created',
dataIndex: 'createTime',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
dataIndex: 'remark',
align: 'center',
ellipsis: true,
},
];
const getReceivedList = () => {
if (fetchReceivedList) {
if (receivedListLoading) {
return;
}
setReceivedListLoading(true);
fetchReceivedList({
current: receivedPage,
pageSize: receivedSize,
}).then(res => {
const { data = [], totalCount = 0 } = (res || {});
setReceivedList(data);
setReceivedTotal(totalCount);
}).finally(() => {
setReceivedListLoading(false);
});
}
};
const getUsageList = () => {
if (fetchUsageList) {
if (usageListLoading) {
return;
}
setUsageListLoading(true);
fetchUsageList({
current: usagePage,
pageSize: usageSize,
}).then(res => {
const { data = [], totalCount = 0 } = (res || {});
setUsageList(data);
setUsageTotal(totalCount);
}).finally(() => {
setUsageListLoading(false);
});
}
};
useEffect(() => {
getReceivedList();
}, []);
const handleTabChange = key => {
console.log('key', key)
switch (key) {
case '1':
getReceivedList();
break;
case '2':
getUsageList();
break;
default:
break;
}
};
const handleReceivedPaginationChange = (page: number, size: number) => {
setReceivedPage(page);
setReceivedSize(size);
getReceivedList();
};
const handleUsagePaginationChange = (page: number, size: number) => {
setUsagePage(page);
setUsageSize(size);
getReceivedList();
};
return (
......@@ -209,18 +315,26 @@ const EquityInfo: React.FC<EquityInfoProps> = ({
<Tabs onChange={handleTabChange}>
<TabPane tab="权益获取记录" key="1">
<PolymericTable
dataSource={[]}
columns={columns}
loading={false}
pagination={null}
dataSource={receivedList}
columns={receivedColumns}
loading={receivedListLoading}
pagination={{
pageSize: receivedSize,
total: receivedTotal,
}}
onPaginationChange={handleReceivedPaginationChange}
/>
</TabPane>
<TabPane tab="权益使用记录" key="2">
<PolymericTable
dataSource={[]}
columns={columns2}
loading={false}
pagination={null}
dataSource={usageList}
columns={usageColumns}
loading={usageListLoading}
pagination={{
pageSize: usageSize,
total: usageTotal,
}}
onPaginationChange={handleUsagePaginationChange}
/>
</TabPane>
</Tabs>
......
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import {
Row,
Col,
Tabs,
Card,
Tooltip,
Radio,
Radio,
Spin,
} from 'antd';
import {
QuestionCircleOutlined,
......@@ -13,7 +14,6 @@ import {
MehFilled,
FrownFilled,
} from '@ant-design/icons';
import classNames from 'classnames';
import PolymericTable from '@/components/PolymericTable';
import { EditableColumns } from '@/components/PolymericTable/interface';
import { Pie } from '@/components/Charts';
......@@ -21,18 +21,6 @@ import MellowCard from '@/components/MellowCard';
import equity5 from '@/assets/imgs/equity-5.png';
import styles from './index.less';
import {
Chart,
registerShape,
Geom,
Axis,
Tooltip as ChartTooltip,
Interval,
Interaction,
Coordinate,
} from 'bizcharts';
import DataSet from '@antv/data-set';
const { TabPane } = Tabs;
interface ContentBoxProps {
......@@ -131,9 +119,51 @@ const evaluateData = [
},
];
const SincerityInfo: React.FC<{}> = props => {
export interface BasicInfo {
pieData: {
x: string,
y: number,
}[],
items: {
id: number,
creditTypeName: string,
remark: string,
creditPoint: number,
}[],
loading?: boolean,
};
export interface EstimateSumItems {
id?: number,
title?: JSX.Element,
star?: number,
last7days?: number,
last30days?: number,
last180days?: number,
before180days?: number,
sum?: number,
};
export interface EstimateSum {
dataSource: EstimateSumItems[],
loading?: boolean,
};
interface SincerityInfoProps {
basicInfo?: BasicInfo;
estimateSum?: EstimateSum;
};
const SincerityInfo: React.FC<SincerityInfoProps> = ({
basicInfo = {},
estimateSum = {},
}) => {
const creditData = basicInfo.pieData || [];
const integralItems = basicInfo.items || [];
const [recordType, setRecordType] = useState('business');
const [evaluate, setEvaluate] = useState([]);
const [evaluatePie, setEvaluatePie] = useState([]);
const recordColumns: EditableColumns[] =
recordType === 'business' ?
......@@ -224,22 +254,22 @@ const SincerityInfo: React.FC<{}> = props => {
},
{
title: '最近7天',
dataIndex: 'day7',
dataIndex: 'last7days',
align: 'center',
},
{
title: '最近30天',
dataIndex: 'day30',
dataIndex: 'last30days',
align: 'center',
},
{
title: '最近180天',
dataIndex: 'day180',
dataIndex: 'last180days',
align: 'center',
},
{
title: '180天前',
dataIndex: 'day180+',
dataIndex: 'before180days',
align: 'center',
},
];
......@@ -278,144 +308,183 @@ const SincerityInfo: React.FC<{}> = props => {
},
];
const evaluate = [
{
id: 1,
title: (<Mood type="smile" />),
day7: 10,
day30: 10,
day180: 10,
'day180+': 10,
},
{
id: 2,
title: (<Mood type="notBad" />),
day7: 10,
day30: 10,
day180: 10,
'day180+': 10,
},
{
id: 3,
title: (<Mood type="sad" />),
day7: 10,
day30: 10,
day180: 10,
'day180+': 10,
},
];
const summaryEvaluate = (items: EstimateSumItems[]): EstimateSumItems[] => {
// 顺序写死的 1:表示好评,2:表示中评,3:表示差评
// 根据 1、2星级为差评,3星级为中评,4、5星级为好评往里边塞数据
const source = items || [];
const ret = [
{
id: 1,
title: (<Mood type="smile" />),
},
{
id: 2,
title: (<Mood type="notBad" />),
},
{
id: 3,
title: (<Mood type="sad" />),
},
];
const handleTabChange = key => {
setRecordType(key);
for (let i = 0; i < source.length; i++) {
const item = source[i];
const { star, ...rest } = item;
let target = null;
switch (item.star) {
case 1:
case 2: {
target = ret[0];
break;
}
case 3: {
target = ret[1];
break;
}
case 4:
case 5: {
target = ret[2];
break;
}
default:
break;
}
if (!target) {
continue;
}
// 大于 2 表示已经添加过一次数据,之后就累加上去,否则直接赋值
if (Object.keys(target).length <= 2) {
target = Object.assign(target, rest);
} else {
for (const key in target) {
if (!Object.prototype.hasOwnProperty.call(target, key)) {
continue;
}
// 排除 id、title 固定的 key
if (key !== 'id' && key !== 'title') {
target[key] += item[key];
}
}
}
}
return ret;
};
const getSummaryEvaluatePie = (data: EstimateSumItems[]) => {
const source = data || [];
const count = source.reduce((pre, now) => now.sum + pre, 0);
const ret = [
{
x: `好评 ${((source[0].sum || 0) / count * 100).toFixed(2)}%`,
y: source[0].sum || 0,
},
{
x: `中评 ${((source[1].sum || 0) / count * 100).toFixed(2)}%`,
y: source[1].sum || 0,
},
{
x: `差评 ${((source[2].sum || 0) / count * 100).toFixed(2)}%`,
y: source[2].sum || 0,
},
];
return ret;
};
useEffect(() => {
const evaluate = summaryEvaluate(estimateSum.dataSource);
const evaluatePie = getSummaryEvaluatePie(evaluate);
setEvaluate(evaluate);
setEvaluatePie(evaluatePie);
}, [estimateSum.dataSource]);
const { DataView } = DataSet;
const dv = new DataView();
dv.source(creditData).transform({
type: 'percent',
field: 'y',
dimension: 'x',
as: 'percent',
});
const handleTabChange = key => {
setRecordType(key);
};
return (
<div className={styles.sincerityInfo}>
<Row gutter={[0, 24]}>
<Col span={24}>
<Row gutter={24}>
<Col span={8}>
<MellowCard
title="信用积分"
>
<Pie
hasLegend
subTitle="信用积分"
total="123.4"
data={creditData}
height={178}
/>
</MellowCard>
</Col>
<Col span={16}>
<div className={styles.tofo}>
<MellowCard>
<Card.Grid className={styles['tofo-item']}>
<ContentBox
title="交易评价积分"
desc="交易完成后评价为5分时增加信用积分"
content="+1000"
extra={
<img className={styles['tofo-item-logo']} src={equity5} />
}
/>
</Card.Grid>
<Card.Grid className={styles['tofo-item']}>
<ContentBox
title="售后评价积分"
desc="交易完成后评价为5分时增加信用积分"
content="+1000"
extra={
<img className={styles['tofo-item-logo']} src={equity5} />
}
/>
</Card.Grid>
<Card.Grid className={styles['tofo-item']}>
<ContentBox
title="投诉扣分"
desc="交易完成后评价为5分时增加信用积分"
content="+1000"
extra={
<img className={styles['tofo-item-logo']} src={equity5} />
}
/>
</Card.Grid>
<Card.Grid className={styles['tofo-item']}>
<ContentBox
title="入驻年数积分"
desc="交易完成后评价为5分时增加信用积分"
content="+1000"
extra={
<img className={styles['tofo-item-logo']} src={equity5} />
}
/>
</Card.Grid>
</MellowCard>
</div>
</Col>
</Row>
</Col>
<Col span={24}>
<MellowCard
title="评价统计"
>
<Spin spinning={Boolean(basicInfo.loading)}>
<Row gutter={24}>
<Col span={8}>
<Pie
hasLegend
subTitle="累计评价"
total="1234"
data={evaluateData}
height={178}
colProps={{
span: 8,
}}
/>
<MellowCard
title="信用积分"
>
<Pie
hasLegend
subTitle="信用积分"
total={() => creditData.reduce((pre, now) => now.y + pre, 0)}
data={creditData}
height={178}
/>
</MellowCard>
</Col>
<Col span={16}>
<PolymericTable
dataSource={evaluate}
columns={evaluateColumns}
loading={false}
pagination={null}
rowClassName={() => styles['record-row']}
/>
</Col>
{basicInfo.loading === false && (
<Col span={16}>
<div className={styles.tofo}>
<MellowCard>
{integralItems.map(item => (
<Card.Grid key={item.id} className={styles['tofo-item']}>
<ContentBox
title={item.creditTypeName}
desc={item.remark}
content={item.creditPoint}
extra={
<img className={styles['tofo-item-logo']} src={equity5} />
}
/>
</Card.Grid>
))}
</MellowCard>
</div>
</Col>
)}
</Row>
</MellowCard>
</Spin>
</Col>
<Col span={24}>
<Spin spinning={Boolean(estimateSum.loading)}>
<MellowCard
title="评价统计"
>
<Row gutter={24}>
<Col span={8}>
<Pie
hasLegend
subTitle="累计评价"
total={() => evaluatePie.reduce((pre, now) => now.y + pre, 0)}
data={evaluatePie}
height={178}
colProps={{
span: 8,
}}
/>
</Col>
<Col span={16}>
<PolymericTable
dataSource={evaluate}
columns={evaluateColumns}
loading={false}
pagination={null}
rowClassName={() => styles['record-row']}
/>
</Col>
</Row>
</MellowCard>
</Spin>
</Col>
<Col span={24}>
......
......@@ -4,6 +4,7 @@ import { Badge, Button, Card, Spin, message } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { SaveOutlined } from '@ant-design/icons';
import { createFormActions, FormEffectHooks, FormPath } from '@formily/antd';
import { Select, Input } from '@formily/antd-components'
import { merge } from 'rxjs';
import { usePageStatus } from '@/hooks/usePageStatus';
import ReutrnEle from '@/components/ReturnEle';
......@@ -19,7 +20,6 @@ const formActions = createFormActions();
const {
onFieldValueChange$,
onFieldInputChange$,
onFormInit$,
} = FormEffectHooks;
const addMember: React.FC<any> = props => {
......@@ -338,13 +338,6 @@ const addMember: React.FC<any> = props => {
getPageitemsBasic,
);
onFormInit$().subscribe(() => {
actions.setFieldState('roleId', state => {
state.loading = true;
})
})
useAsyncLinkageEffect();
}}
schema={initDetailSchema(memberItems)}
......
......@@ -230,6 +230,9 @@ export const initDetailSchema = (props: any) => {
'x-component-props': {
placeholder: '请选择',
},
'x-props': {
hasFeedback: true,
},
},
levelId: {
type: 'string',
......@@ -239,6 +242,9 @@ export const initDetailSchema = (props: any) => {
'x-component-props': {
placeholder: '请选择',
},
'x-props': {
hasFeedback: true,
},
},
MEGA_LAYOUT1_1: {
type: 'object',
......@@ -259,11 +265,17 @@ export const initDetailSchema = (props: any) => {
},
phone: {
type: 'string',
required: true,
'x-component-props': {
placeholder: '请输入你的手机号码',
maxLength: 11,
},
required: true,
'x-rules': [
{
pattern: PATTERN_MAPS.phone,
message: '请输入正确格式的手机号',
},
],
},
},
},
......
import React from 'react';
import Info from '../../components/EquityInfo';
import React, { useEffect, useState } from 'react';
import { Spin } from 'antd';
import { usePageStatus } from '@/hooks/usePageStatus';
import { PublicApi } from '@/services/api';
import { GetMemberAbilityMaintenanceDetailRightBasicResponse } from '@/services/MemberApi';
import Info, { ReceivedData, UsageData } from '../../components/EquityInfo';
const EquityInfo: React.FC<{}> = () => {
const { id, validateId } = usePageStatus();
const [equityInfo, setEquityInfo] = useState<GetMemberAbilityMaintenanceDetailRightBasicResponse>(null);
const [infoLoading, setInfoLoading] = useState(false);
const getEquityInfo = () => {
setInfoLoading(true);
PublicApi.getMemberAbilityMaintenanceDetailRightBasic({
memberId: id,
validateId,
}).then(res => {
if (res.code !== 1000) {
return;
}
setEquityInfo(res.data);
}).finally(() => {
setInfoLoading(false);
});
};
useEffect(() => {
getEquityInfo();
}, []);
const getReceivedList = params => {
return new Promise<{ data: ReceivedData[] , totalCount: number }>((resolve, reject) => {
PublicApi.getMemberAbilityMaintenanceDetailRightHistoryPage({
memberId: id,
validateId,
...params,
}).then(res => {
const { data = [], totalCount = 0 } = res.data;
resolve({ data, totalCount });
}).catch(err => {
reject(err);
});
})
};
const getUsageList = params => {
return new Promise<{ data: UsageData[] , totalCount: number }>((resolve, reject) => {
PublicApi.getMemberAbilityMaintenanceDetailRightSpendHistoryPage({
memberId: id,
validateId,
...params,
}).then(res => {
const { data = [], totalCount = 0 } = res.data;
resolve({ data, totalCount });
}).catch(err => {
reject(err);
});
})
};
return (
<div>
<Info />
</div>
<Spin spinning={infoLoading}>
<Info
equityInfo={{
sumReturnMoney: equityInfo?.sumReturnMoney,
sumUsedPoint: equityInfo?.sumUsedPoint,
sumPoint: equityInfo?.sumPoint,
}}
fetchReceivedList={getReceivedList}
fetchUsageList={getUsageList}
/>
</Spin>
);
};
......
......@@ -38,13 +38,13 @@ const MemberQueryDetailed: React.FC<QueryProps> = props => {
const { MemberStore, children } = props;
const { id, validateId } = usePageStatus();
const [basicInfo, setBasicInfo] = useState<GetMemberAbilityMaintenanceDetailBasicResponse>(null);
const [infoLoading, setInfoLoaading] = useState(false);
const [infoLoading, setInfoLoading] = useState(false);
const getBasicInfo = () => {
if (!id || !validateId) {
return;
}
setInfoLoaading(true);
setInfoLoading(true);
PublicApi.getMemberAbilityMaintenanceDetailBasic({
memberId: id,
validateId,
......@@ -55,7 +55,7 @@ const MemberQueryDetailed: React.FC<QueryProps> = props => {
setBasicInfo(res.data);
MemberStore.setmemberMaintainInfo(res.data);
}).finally(() => {
setInfoLoaading(false);
setInfoLoading(false);
});
};
......
......@@ -9,13 +9,13 @@ import { reject } from 'lodash';
const LevelInfo: React.FC<{}> = () => {
const { id, validateId } = usePageStatus();
const [levelInfo, setLevelInfo] = useState<GetMemberAbilityMaintenanceDetailLevelBasicResponse>(null);
const [infoLoading, setInfoLoaading] = useState(false);
const [infoLoading, setInfoLoading] = useState(false);
const getMemberLevelInfo = () => {
if (!id && !validateId) {
return;
}
setInfoLoaading(true);
setInfoLoading(true);
PublicApi.getMemberAbilityMaintenanceDetailLevelBasic({
memberId: id,
validateId,
......@@ -26,7 +26,7 @@ const LevelInfo: React.FC<{}> = () => {
setLevelInfo(res.data);
}).finally(() => {
setInfoLoaading(false);
setInfoLoading(false);
});
};
......
import React from 'react';
import Info from '../../components/SincerityInfo';
import React, { useEffect, useState } from 'react';
import { usePageStatus } from '@/hooks/usePageStatus';
import { PublicApi } from '@/services/api';
import Info, { BasicInfo, EstimateSum } from '../../components/SincerityInfo';
const SincerityInfo: React.FC<{}> = () => {
const { id, validateId } = usePageStatus();
const [basicInfo, setBasicInfo] = useState<BasicInfo>(null);
const [infoLoading, setInfoLoading] = useState(false);
const [estimateSum, setEstimateSum] = useState<EstimateSum>(null);
const [estimateSumLoading, setEstimateSumLoading] = useState(false);
const getBasicInfo = () => {
setInfoLoading(true);
PublicApi.getMemberAbilityMaintenanceDetailCreditBasic({
memberId: id,
validateId,
}).then(res => {
if (res.code !== 1000) {
return;
}
const {
tradeCommentPoint,
afterSaleCommentPoint,
complainPoint,
registerYearsPoint,
configs,
} = (res.data || {});
const pieData = [
{
x: '交易评价积分',
y: tradeCommentPoint || 0,
},
{
x: '售后评价积分',
y: afterSaleCommentPoint || 0,
},
{
x: '投诉扣分',
y: complainPoint || 0,
},
{
x: '入驻年数积分',
y: registerYearsPoint || 0,
},
];
setBasicInfo({
pieData,
items: configs,
});
}).finally(() => {
setInfoLoading(false);
});
};
const getEstimateSum = () => {
setEstimateSumLoading(true);
PublicApi.getMemberAbilityMaintenanceDetailCreditTradeSummary({
memberId: id,
validateId,
}).then(res => {
if (res.code !== 1000) {
return;
}
const { rows = [] } = (res.data || {});
const mock = [
{
before180days: 1,
last7days: 1,
last30days: 1,
last180days: 1,
star: 1,
sum: 1,
},
{
before180days: 2,
last7days: 2,
last30days: 2,
last180days: 2,
star: 2,
sum: 2,
},
{
before180days: 3,
last7days: 3,
last30days: 3,
last180days: 3,
star: 3,
sum: 3,
},
{
before180days: 4,
last7days: 4,
last30days: 4,
last180days: 4,
star: 4,
sum: 4,
},
{
before180days: 5,
last7days: 5,
last30days: 5,
last180days: 5,
star: 5,
sum: 5,
},
];
setEstimateSum({
dataSource: mock,
});
}).finally(() => {
setEstimateSumLoading(false);
});
};
useEffect(() => {
getBasicInfo();
getEstimateSum();
}, []);
return (
<div>
<Info />
<Info
basicInfo={{
...basicInfo,
loading: infoLoading,
}}
estimateSum={{
...estimateSum,
loading: estimateSumLoading,
}}
/>
</div>
);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment