Commit 7405d5ee authored by XieZhiXiong's avatar XieZhiXiong

developing

parents 2fafc798 9d81f411
......@@ -29,6 +29,7 @@
"dependencies": {
"@ant-design/icons": "^4.2.1",
"@ant-design/pro-layout": "^5.0.16",
"@antv/data-set": "^0.11.5",
"@formily/antd": "^1.2.11",
"@formily/antd-components": "^1.2.11",
"@umijs/hooks": "^1.9.3",
......@@ -42,6 +43,7 @@
"lingxi-editor-core": "^1.0.6",
"lingxi-web": "^1.0.6",
"lint-staged": "^10.0.7",
"lodash": "^4.17.20",
"mobx": "^5.15.4",
"mobx-react": "^6.2.2",
"moment": "^2.27.0",
......
.miniChart {
position: relative;
width: 100%;
.chartContent {
position: absolute;
bottom: -28px;
width: 100%;
> div {
margin: 0 -5px;
overflow: hidden;
}
}
.chartLoading {
position: absolute;
top: 16px;
left: 50%;
margin-left: -7px;
}
}
import React from 'react';
import { Axis, Chart, Geom, Tooltip } from 'bizcharts';
import { IAxis } from 'bizcharts/lib/components/Axis';
import autoHeight from '../autoHeight';
import styles from './index.less';
import { ShapeString, ShapeAttrCallback, IChartProps } from 'bizcharts/lib/interface';
export interface MiniAreaProps {
color?: string;
height?: number;
borderColor?: string;
line?: boolean;
animate?: boolean;
xAxis?: IAxis;
autoFit?: boolean;
scale?: {
x?: {
tickCount?: number;
alias?: string;
};
y?: {
tickCount?: number;
alias?: string;
};
};
yAxis?: Partial<IAxis>;
borderWidth?: number;
data: {
x: number | string;
y: number;
}[];
padding?: number | number[] | 'auto';
borderShape?: ShapeString | ShapeString | [ShapeString, ShapeString[] | ShapeAttrCallback];
}
const MiniArea: React.FC<MiniAreaProps> = (props) => {
const {
height = 1,
data = [],
autoFit = true,
color = 'rgba(24, 144, 255, 0.2)',
borderColor = '#1089ff',
scale = { x: {}, y: {} },
borderWidth = 2,
line,
xAxis,
yAxis,
animate = true,
padding,
borderShape = 'line',
} = props;
const newPadding = padding || [36, 5, 30, 5];
const scaleProps = {
x: {
type: 'cat',
range: [0, 1],
...scale.x,
},
y: {
min: 0,
...scale.y,
},
};
const tooltip: [string, (...args: any[]) => { name?: string; value: string }] = [
'x*y',
(x: string, y: string) => ({
name: x,
value: y,
}),
];
const chartHeight = height + 54;
return (
<div className={styles.miniChart} style={{ height }}>
<div className={styles.chartContent}>
{height > 0 && (
<Chart
animate={animate}
scale={scaleProps}
height={chartHeight}
autoFit={autoFit}
data={data}
padding={newPadding}
>
<Axis
key="axis-x"
name="x"
label={null}
line={null}
tickLine={null}
grid={null}
{...xAxis}
/>
<Axis
key="axis-y"
name="y"
label={null}
line={null}
tickLine={null}
grid={null}
{...yAxis}
/>
<Tooltip showTitle={false} />
<Geom
type="area"
position="x*y"
color={color}
tooltip={tooltip}
// shape="smooth"
style={{
fillOpacity: 0.3,
}}
/>
{line ? (
<Geom
type="line"
position="x*y"
shape={borderShape}
color={borderColor}
size={borderWidth}
tooltip={false}
/>
) : (
<span style={{ display: 'none' }} />
)}
</Chart>
)}
</div>
</div>
);
};
export default autoHeight()(MiniArea);
@import '~antd/es/style/themes/default.less';
.pie {
position: relative;
.chart {
position: relative;
}
&.hasLegend .chart {
width: ~'calc(100% - 240px)';
}
.legend {
position: absolute;
top: 50%;
right: 0;
min-width: 200px;
margin: 0 20px;
padding: 0;
list-style: none;
transform: translateY(-50%);
li {
height: 22px;
margin-bottom: 16px;
line-height: 22px;
cursor: pointer;
&:last-child {
margin-bottom: 0;
}
}
}
.dot {
position: relative;
top: -1px;
display: inline-block;
width: 8px;
height: 8px;
margin-right: 8px;
border-radius: 8px;
}
.line {
display: inline-block;
width: 1px;
height: 16px;
margin-right: 8px;
background-color: @border-color-split;
}
.legendTitle {
color: @text-color;
}
.percent {
color: @text-color-secondary;
}
.value {
position: absolute;
right: 0;
}
.title {
margin-bottom: 8px;
}
.total {
position: absolute;
top: 50%;
left: 50%;
max-height: 62px;
text-align: center;
transform: translate(-50%, -50%);
& > h4 {
height: 22px;
margin-bottom: 8px;
color: @text-color-secondary;
font-weight: normal;
font-size: 14px;
line-height: 22px;
}
& > p {
display: block;
height: 32px;
color: @heading-color;
font-size: 1.2em;
line-height: 32px;
white-space: nowrap;
}
}
}
.legendBlock {
&.hasLegend .chart {
width: 100%;
margin: 0 0 32px 0;
}
.legend {
position: relative;
transform: none;
}
}
import { Chart, Coord, Geom, Tooltip } from 'bizcharts';
import React, { Component } from 'react';
import DataSet from '@antv/data-set';
import G2 from '@antv/g2/lib/chart/chart';
import Debounce from 'lodash.debounce';
import { Divider } from 'antd';
import classNames from 'classnames';
import autoHeight from '../autoHeight';
import styles from './index.less';
export interface PieProps {
animate?: boolean;
color?: string;
colors?: string[];
selected?: boolean;
height?: number;
margin?: [number, number, number, number];
hasLegend?: boolean;
padding?: [number, number, number, number];
percent?: number;
data?: {
x: string | string;
y: number;
}[];
inner?: number;
lineWidth?: number;
autoFit?: boolean;
style?: React.CSSProperties;
className?: string;
total?: React.ReactNode | number | (() => React.ReactNode | number);
title?: React.ReactNode;
tooltip?: boolean;
valueFormat?: (value: string) => string | React.ReactNode;
subTitle?: React.ReactNode;
}
interface PieState {
legendData: { checked: boolean; x: string; color: string; percent: number; y: string }[];
legendBlock: boolean;
}
class Pie extends Component<PieProps, PieState> {
state: PieState = {
legendData: [],
legendBlock: false,
};
requestRef: number | undefined = undefined;
root: HTMLDivElement | undefined = undefined;
chart: G2 | undefined = undefined;
// for window resize auto responsive legend
resize = Debounce(() => {
const { hasLegend } = this.props;
const { legendBlock } = this.state;
if (!hasLegend || !this.root) {
window.removeEventListener('resize', this.resize);
return;
}
if (
this.root &&
this.root.parentNode &&
(this.root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
this.setState({
legendBlock: true,
});
}
} else if (legendBlock) {
this.setState({
legendBlock: false,
});
}
}, 400);
componentDidMount() {
window.addEventListener(
'resize',
() => {
this.requestRef = requestAnimationFrame(() => this.resize());
},
{ passive: true },
);
}
componentDidUpdate(preProps: PieProps) {
const { data } = this.props;
if (data !== preProps.data) {
// because of charts data create when rendered
// so there is a trick for get rendered time
// this.getLegendData();
}
}
componentWillUnmount() {
if (this.requestRef) {
window.cancelAnimationFrame(this.requestRef);
}
window.removeEventListener('resize', this.resize);
if (this.resize) {
(this.resize as any).cancel();
}
}
getG2Instance = (chart: G2) => {
this.chart = chart;
requestAnimationFrame(() => {
this.getLegendData();
this.resize();
});
};
// for custom lengend view
getLegendData = () => {
if (!this.chart) return;
const geom = this.chart.geometries[0]; // 获取所有的图形
if (!geom) return;
const items = (geom as any).dataArray || []; // 获取图形对应的
const legendData = items.map((item: { color: any; _origin: any }[]) => {
/* eslint no-underscore-dangle:0 */
const origin = item[0]._origin;
origin.color = item[0].color;
origin.checked = true;
return origin;
});
console.log('legendData', legendData)
this.setState({
legendData,
});
};
handleRoot = (n: HTMLDivElement) => {
this.root = n;
};
handleLegendClick = (item: any, i: string | number) => {
const newItem = item;
newItem.checked = !newItem.checked;
const { legendData } = this.state;
legendData[i] = newItem;
const filteredLegendData = legendData.filter((l) => l.checked).map((l) => l.x);
if (this.chart) {
this.chart.filter('x', (val) => filteredLegendData.indexOf(`${val}`) > -1);
}
this.setState({
legendData,
});
};
render() {
const {
valueFormat,
subTitle,
total,
hasLegend = false,
className,
style,
height = 0,
autoFit = true,
percent,
color,
inner = 0.75,
animate = true,
colors,
lineWidth = 1,
} = this.props;
const { legendData, legendBlock } = this.state;
const pieClassName = classNames(styles.pie, className, {
[styles.hasLegend]: !!hasLegend,
[styles.legendBlock]: legendBlock,
});
const {
data: propsData,
selected: propsSelected = true,
tooltip: propsTooltip = true,
} = this.props;
let data = propsData || [];
let selected = propsSelected;
let tooltip = propsTooltip;
const defaultColors = colors;
data = data || [];
selected = selected || true;
tooltip = tooltip || true;
let formatColor;
const scale = {
x: {
type: 'cat',
range: [0, 1],
},
y: {
min: 0,
},
};
if (percent || percent === 0) {
selected = false;
tooltip = false;
formatColor = (value: string) => {
if (value === '占比') {
return color || 'rgba(24, 144, 255, 0.85)';
}
return '#F0F2F5';
};
data = [
{
x: '占比',
y: parseFloat(`${percent}`),
},
{
x: '反比',
y: 100 - parseFloat(`${percent}`),
},
];
}
const tooltipFormat: [string, (...args: any[]) => { name?: string; value: string }] = [
'x*percent',
(x: string, p: number) => ({
name: x,
value: `${(p * 100).toFixed(2)}%`,
}),
];
const padding = [12, 0, 12, 0] as [number, number, number, number];
const { DataView } = DataSet;
const dv = new DataView();
dv.source(data).transform({
type: 'percent',
field: 'y',
dimension: 'x',
as: 'percent',
});
return (
<div ref={this.handleRoot} className={pieClassName} style={style}>
<div className={styles.chart}>
<Chart
scale={scale}
height={height}
autoFit={autoFit}
data={dv}
padding={padding}
animate={animate}
onGetG2Instance={this.getG2Instance}
>
{!!tooltip && <Tooltip showTitle={false} />}
<Coord type="theta" innerRadius={inner} />
<Geom
style={{ lineWidth, stroke: '#fff' }}
tooltip={tooltip ? tooltipFormat : undefined}
type="interval"
position="percent"
color={['x', percent || percent === 0 ? formatColor : defaultColors] as any}
selected={selected}
/>
</Chart>
{(subTitle || total) && (
<div className={styles.total}>
{subTitle && <h4 className="pie-sub-title">{subTitle}</h4>}
{/* eslint-disable-next-line */}
{total && (
<div className="pie-stat">{typeof total === 'function' ? total() : total}</div>
)}
</div>
)}
</div>
{hasLegend && (
<ul className={styles.legend}>
{legendData.map((item, i) => (
<li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
<span
className={styles.dot}
style={{
backgroundColor: !item.checked ? '#aaa' : item.color,
}}
/>
<span className={styles.legendTitle}>{item.x}</span>
<Divider type="vertical" />
<span className={styles.percent}>
{`${(Number.isNaN(item.percent) ? 0 : item.percent * 100).toFixed(2)}%`}
</span>
<span className={styles.value}>{valueFormat ? valueFormat(item.y) : item.y}</span>
</li>
))}
</ul>
)}
</div>
);
}
}
export default autoHeight()(Pie);
import React from 'react';
export type IReactComponent<P = any> =
| React.StatelessComponent<P>
| React.ComponentClass<P>
| React.ClassicComponentClass<P>;
function computeHeight(node: HTMLDivElement) {
const { style } = node;
style.height = '100%';
const totalHeight = parseInt(`${getComputedStyle(node).height}`, 10);
const padding =
parseInt(`${getComputedStyle(node).paddingTop}`, 10) +
parseInt(`${getComputedStyle(node).paddingBottom}`, 10);
return totalHeight - padding;
}
function getAutoHeight(n: HTMLDivElement | undefined) {
if (!n) {
return 0;
}
const node = n;
let height = computeHeight(node);
const parentNode = node.parentNode as HTMLDivElement;
if (parentNode) {
height = computeHeight(parentNode);
}
return height;
}
interface AutoHeightProps {
height?: number;
}
function autoHeight() {
return <P extends AutoHeightProps>(
WrappedComponent: React.ComponentClass<P> | React.FC<P>,
): React.ComponentClass<P> => {
class AutoHeightComponent extends React.Component<P & AutoHeightProps> {
state = {
computedHeight: 0,
};
root: HTMLDivElement | undefined = undefined;
componentDidMount() {
const { height } = this.props;
if (!height) {
let h = getAutoHeight(this.root);
this.setState({ computedHeight: h });
if (h < 1) {
h = getAutoHeight(this.root);
this.setState({ computedHeight: h });
}
}
}
handleRoot = (node: HTMLDivElement) => {
this.root = node;
};
render() {
const { height } = this.props;
const { computedHeight } = this.state;
const h = height || computedHeight;
return (
<div ref={this.handleRoot}>
{h > 0 && <WrappedComponent {...this.props} height={h} />}
</div>
);
}
}
return AutoHeightComponent;
};
}
export default autoHeight;
import MiniArea from './MiniArea';
import Pie from './Pie';
const Charts = {
MiniArea,
Pie,
};
export {
Charts as default,
MiniArea,
Pie,
};
.mellow {
:global {
.ant-card {
border-radius: 8px;
&-head {
border-bottom: none;
&-title {
line-height: 24px;
padding-bottom: 0;
font-size: 16px;
font-weight: 500;
color: rgba(23, 43, 77, 1);
}
}
&-body {
padding: 14px 24px 24px;
}
}
}
}
\ No newline at end of file
/*
* @Author: XieZhiXiong
* @Date: 2020-08-26 17:32:45
* @LastEditors: XieZhiXiong
* @LastEditTime: 2020-08-26 17:33:28
* @Description: 基于 antd Card 封装的适合项目 UI 的 Card,使用方式跟 antd Card 一样,这里只是修改了样式
*/
import React from 'react';
import { Card } from 'antd';
import { CardProps } from 'antd/lib/card';
import styles from './index.less';
const MellowCard: React.FC<CardProps> = props => {
const { children, ...rest } = props;
return (
<div className={styles.mellow}>
<Card {...rest}>
{children}
</Card>
</div>
)
};
export default MellowCard;
\ No newline at end of file
......@@ -21,8 +21,9 @@ import CircleBox from './components/CircleBox';
import Phone from './components/Phone';
import CustomRadio from './components/CustomRadio';
import SearchSelect from './components/SearchSelect';
import './index.less'
import { Checkbox, Input } from '@formily/antd-components';
import './index.less';
import cx from 'classnames'
export interface NiceFormProps extends IAntdSchemaFormProps {}
......@@ -35,6 +36,13 @@ const RowLayout = styled(props => <Row justify='end' {...props}/>)`
}
`
const renderCol = (schema, isLast) => {
const { flexcol = {} } = schema['x-component-props']
return <Col style={isLast ? {} : {marginRight: 24}} {...flexcol} key={schema.path}>
<SchemaField schema={schema.toJSON()} path={schema.path}/>
</Col>
}
// 自定义flex布局容器
registerVirtualBox('flex-box', props => {
const childProperties = props.schema.getOrderProperties()
......
......@@ -17,8 +17,19 @@ export interface UserRegister {
useType: UseType;
}
export interface ShopInfo {
id: number;
name: string;
type: number;
environment: number;
logoUrl: string;
describe: string;
state: number;
url: string;
}
export interface Web {
shopInfo: any[];
shopInfo: ShopInfo[];
}
export interface PayConfig {
......
.equityInfo {
.container {
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 24px;
height: 192px;
background: #ffffff;
border-radius: 8px;
&-title {
margin-bottom: 24px;
line-height: 24px;
font-size: 16px;
font-weight: 500;
color: rgba(23, 43, 77, 1);
}
&-content {
}
}
.tofo {
display: flex;
padding: 0;
margin: 0;
&-item {
flex: 1;
list-style: none;
&-logo {
width: 40px;
height: 40px;
margin: 0 auto 4px;
text-align: center;
> img {
width: 100%;
height: 100%;
}
}
&-title {
margin-bottom: 9px;
line-height: 22px;
font-size: 14px;
font-weight: 400;
color: rgba(23, 43, 77, 1);
text-align: center;
:global {
.anticon {
margin-left: 4px;
}
}
}
&-extra {
text-align: center;
}
&-tag {
line-height: 22px;
padding: 0 6px;
font-size: 14px;
font-weight: 400;
text-align: center;
border-radius: 4px;
&-price {
color: rgba(101, 84, 192, 1);
background: rgba(234, 230, 255, 1);
}
&-recurrence {
color: rgba(230, 63, 59, 1);
background: rgba(255, 235, 230, 1);
}
&-integral {
color: rgba(255, 153, 31, 1);
background: rgba(255, 250, 230, 1);
}
}
}
}
.exhibition {
display: flex;
align-items: center;
&-left {
flex: 1;
}
&-right {
flex-shrink: 0;
}
&-title {
line-height: 20px;
margin-bottom: 24px;
font-size: 14px;
font-weight: 400;
color: rgba(107, 119, 140, 1);
}
&-amount {
font-size: 24px;
font-weight: 500;
color: rgba(23, 43, 77, 1);
line-height: 24px;
> span {
margin-left: 8px;
line-height: 12px;
font-size: 12px;
font-weight: 400;
color: rgba(107, 119, 140, 1);
}
}
&-logo {
width: 72px;
height: 72px;
> img {
width: 100%;
height: 100%;
}
}
}
}
\ No newline at end of file
import React, { useState } from 'react';
import {
Row,
Col,
Tabs,
} from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import PolymericTable from '@/components/PolymericTable';
import { EditableColumns } from '@/components/PolymericTable/interface';
import MellowCard from '@/components/MellowCard';
import equity1 from '@/assets/imgs/equity-1.png';
import equity2 from '@/assets/imgs/equity-2.png';
import equity3 from '@/assets/imgs/equity-3.png';
import equity4 from '@/assets/imgs/equity-4.png';
import equity5 from '@/assets/imgs/equity-5.png';
import styles from './index.less';
const { TabPane } = Tabs;
interface PageProps {
detailData: any;
}
const EquityInfo: React.FC<{}> = props => {
const columns: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
},
{
title: '会员权益名称',
dataIndex: 'project',
align: 'center',
},
{
title: '获取数量',
dataIndex: 'score',
align: 'center',
},
{
title: '获取时间',
dataIndex: 'created',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
align: 'center',
ellipsis: true,
},
];
const columns2: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
},
{
title: '会员权益名称',
dataIndex: 'project',
align: 'center',
},
{
title: '会员权益使用名称',
dataIndex: 'name',
align: 'center',
},
{
title: '使用数量',
dataIndex: 'count',
align: 'center',
},
{
title: '使用时间',
dataIndex: 'created',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
align: 'center',
ellipsis: true,
},
];
const handleTabChange = key => {
console.log('key', key)
};
return (
<div className={styles.equityInfo}>
<Row gutter={[0, 24]}>
<Col span={24}>
<Row gutter={24}>
<Col span={8}>
<div className={styles.container}>
<div className={styles['container-title']}>
当前权益
</div>
<div className={styles['container-content']}>
<ul className={styles.tofo}>
<li className={styles['tofo-item']}>
<div className={styles['tofo-item-logo']}>
<img src={equity1} />
</div>
<div className={styles['tofo-item-title']}>
价格权益
<QuestionCircleOutlined />
</div>
<div className={styles['tofo-item-extra']}>
<span className={classNames(styles['tofo-item-tag'], styles['tofo-item-tag-price'])}>95% 折扣</span>
</div>
</li>
<li className={styles['tofo-item']}>
<div className={styles['tofo-item-logo']}>
<img src={equity2} />
</div>
<div className={styles['tofo-item-title']}>
返现权益
<QuestionCircleOutlined />
</div>
<div className={styles['tofo-item-extra']}>
<span className={classNames(styles['tofo-item-tag'], styles['tofo-item-tag-recurrence'])}>0.1% 返现</span>
</div>
</li>
<li className={styles['tofo-item']}>
<div className={styles['tofo-item-logo']}>
<img src={equity3} />
</div>
<div className={styles['tofo-item-title']}>
积分权益
<QuestionCircleOutlined />
</div>
<div className={styles['tofo-item-extra']}>
<span className={classNames(styles['tofo-item-tag'], styles['tofo-item-tag-integral'])}>1% 积分</span>
</div>
</li>
</ul>
</div>
</div>
</Col>
<Col span={8}>
<div className={styles.container}>
<div className={styles['container-content']}>
<div className={styles.exhibition}>
<div className={styles['exhibition-left']}>
<div className={styles['exhibition-title']}>
累计返现金额
</div>
<div className={styles['exhibition-amount']}>
50000.00
<span>CNY</span>
</div>
</div>
<div className={styles['exhibition-right']}>
<div className={styles['exhibition-logo']}>
<img src={equity4} />
</div>
</div>
</div>
</div>
</div>
</Col>
<Col span={8}>
<div className={styles.container}>
<div className={styles['container-content']}>
<div className={styles.exhibition}>
<div className={styles['exhibition-left']}>
<div className={styles['exhibition-title']}>
可用积分
</div>
<div className={styles['exhibition-amount']}>
2000/200000
</div>
</div>
<div className={styles['exhibition-right']}>
<div className={styles['exhibition-logo']}>
<img src={equity5} />
</div>
</div>
</div>
</div>
</div>
</Col>
</Row>
</Col>
<Col span={24}>
<MellowCard
title="活跃分获取记录"
>
<Tabs onChange={handleTabChange}>
<TabPane tab="权益获取记录" key="1">
<PolymericTable
dataSource={[]}
columns={columns}
loading={false}
pagination={null}
/>
</TabPane>
<TabPane tab="权益使用记录" key="2">
<PolymericTable
dataSource={[]}
columns={columns2}
loading={false}
pagination={null}
/>
</TabPane>
</Tabs>
</MellowCard>
</Col>
</Row>
</div>
);
};
export default EquityInfo;
@card-prefix: card;
.levelInfo {
.infoWrap {
display: flex;
&-left {
margin-right: 40px;
flex-shrink: 0;
}
&-right {
flex: 1;
}
}
.card {
width: 338px;
height: 190px;
padding: 32px 24px 16px 24px;
background: linear-gradient(135deg, rgba(255, 235, 225, 1) 0%, rgba(251, 196, 167, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
border-radius: 8px;
position: relative;
z-index: 0;
&-name {
margin-bottom: 48px;
line-height: 33px;
font-size: 24px;
font-weight: 500;
color: rgba(164, 114, 104, 1);
}
&-progress {
padding: 0 72px 0 0;
:global {
.ant-progress-bg {
background: rgba(164, 114, 104, 1) !important;
}
.ant-progress-inner {
background-color: rgb(233, 191, 169, 1) !important;
}
}
}
&-txt {
display: flex;
justify-content: space-between;
}
&-experience {
font-size: 12px;
font-weight: 400;
color: rgba(164, 114, 104, 1);
line-height: 20px;
}
&-higher {
font-size: 12px;
font-weight: 400;
color: rgba(186, 140, 115, 1);
line-height: 20px;
}
&-level2 {
background: linear-gradient(135deg, rgba(233, 244, 255, 1) 0%, rgba(164, 185, 223, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
.@{card-prefix} {
&-name {
color: rgba(91, 111, 146, 1);
}
&-progress {
:global {
.ant-progress-bg {
background: rgba(87, 108, 143, 1) !important;
}
.ant-progress-inner {
background-color: rgba(171, 192, 220, 1) !important;
}
}
}
&-experience {
color: rgba(91, 111, 146, 1);
}
&-higher {
color: rgba(133, 150, 179, 1);
}
}
}
&-level3 {
background: linear-gradient(135deg, rgba(255, 245, 222, 1) 0%, rgba(212, 191, 146, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
.@{card-prefix} {
&-name {
color: rgba(141, 107, 56, 1);
}
&-progress {
:global {
.ant-progress-bg {
background: rgba(141, 107, 56, 1) !important;
}
.ant-progress-inner {
background-color: rgba(214, 195, 157, 1) !important;
}
}
}
&-experience {
color: rgba(141, 107, 56, 1);
}
&-higher {
color: rgba(174, 154, 113, 1);
}
}
}
&-level4 {
background: linear-gradient(135deg, rgba(232, 239, 255, 1) 0%, rgba(157, 162, 194, 1) 100%);
box-shadow: 0 1px 2px 0 rgba(23, 43, 77, 0.12);
.@{card-prefix} {
&-name {
color: rgba(89, 91, 113, 1);
}
&-progress {
:global {
.ant-progress-bg {
background: rgba(89, 91, 113, 1) !important;
}
.ant-progress-inner {
background-color: rgba(167, 170, 198, 1) !important;
}
}
}
&-experience {
color: rgba(89, 91, 113, 1);
}
&-higher {
color: rgba(134, 136, 166, 1);
}
}
}
&::after {
content: '';
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 100px;
z-index: -1;
width: 100px;
transform: skewX(24deg);
background: linear-gradient(rgba(255, 255, 255, .2), rgba(255, 255, 255, 0));
}
}
}
\ No newline at end of file
import React, { useState } from 'react';
import {
Row,
Col,
Progress,
Card,
} from 'antd';
import classNames from 'classnames';
import { MiniArea } from '@/components/Charts';
import PolymericTable from '@/components/PolymericTable';
import { EditableColumns } from '@/components/PolymericTable/interface';
import MellowCard from '@/components/MellowCard';
import styles from './index.less';
interface PageProps {
detailData: any;
}
function fixedZero(val: number) {
return val * 1 < 10 ? `0${val}` : val;
}
function getActiveData() {
const activeData = [];
for (let i = 0; i < 12; i += 1) {
activeData.push({
x: `${i}月`,
y: Math.floor(Math.random() * 200) + i * 50,
});
}
return activeData;
}
const LevelInfo: React.FC<{}> = props => {
const [chartData , setChartData] = useState(getActiveData());
const columns: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
},
{
title: '获取项目',
dataIndex: 'project',
align: 'center',
},
{
title: '获取分值',
dataIndex: 'score',
align: 'center',
},
{
title: '获取时间',
dataIndex: 'created',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
align: 'center',
ellipsis: true,
},
];
return (
<div className={styles.levelInfo}>
<Row gutter={[0, 24]}>
<Col span={24}>
<MellowCard
title="会员等级"
headStyle={{
borderBottom: 'none',
}}
>
<div className={styles.infoWrap}>
<div className={styles['infoWrap-left']}>
<div className={classNames(styles.card, styles['card-level1'])}>
<div className={styles['card-name']}>青铜会员</div>
<div className={styles['card-progress']}>
<Progress
strokeWidth={4}
strokeLinecap="square"
showInfo={false}
percent={75}
/>
</div>
<div className={styles['card-txt']}>
<div className={styles['card-experience']}>
5000/15000
</div>
<div className={styles['card-higher']}>
白银会员
</div>
</div>
<div className={styles['card-higher']}>
当前活跃分
</div>
</div>
</div>
<div className={styles['infoWrap-right']}>
<MiniArea
animate={false}
line
borderWidth={2}
height={180}
padding={[10, 20, 50, 60]}
scale={{
x: {
alias: '2021年', // 别名
},
y: {
tickCount: 5,
alias: '活跃分', // 别名
},
}}
xAxis={{
tickLine: undefined,
label: undefined,
title: {
style: {
fontSize: 12,
fill: '#97A0AF',
fontWeight: 400,
rotate: 90,
},
},
}}
yAxis={{
tickLine: undefined,
label: {
offset: 10,
},
title: {
style: {
fontSize: 12,
fill: '#97A0AF',
fontWeight: 400,
rotate: 90,
},
},
grid: {
line: {
type: 'line',
style: {
stroke: "#d9d9d9",
lineWidth: 1,
lineDash: [2, 2]
}
}
},
}}
color="l(90) 0:#AAC5FC 1:#FFFFFF"
data={chartData}
/>
</div>
</div>
</MellowCard>
</Col>
<Col span={24}>
<MellowCard
title="活跃分获取记录"
headStyle={{
borderBottom: 'none',
}}
>
<PolymericTable
dataSource={[]}
columns={columns}
loading={false}
pagination={null}
/>
</MellowCard>
</Col>
</Row>
</div>
);
};
export default LevelInfo;
.sincerityInfo {
}
\ No newline at end of file
import React, { useState } from 'react';
import {
Row,
Col,
Tabs,
} from 'antd';
import { QuestionCircleOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import PolymericTable from '@/components/PolymericTable';
import { EditableColumns } from '@/components/PolymericTable/interface';
import { Pie } from '@/components/Charts';
import MellowCard from '@/components/MellowCard';
import styles from './index.less';
const { TabPane } = Tabs;
interface PageProps {
detailData: any;
}
const salesPieData = [
{
"x": "家用电器",
"y": 4544
},
{
"x": "食用酒水",
"y": 3321
},
{
"x": "个护健康",
"y": 3113
},
{
"x": "服饰箱包",
"y": 2341
},
{
"x": "母婴产品",
"y": 1231
},
{
"x": "其他",
"y": 1231
}
];
const SincerityInfo: React.FC<{}> = props => {
const columns: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
},
{
title: '会员权益名称',
dataIndex: 'project',
align: 'center',
},
{
title: '获取数量',
dataIndex: 'score',
align: 'center',
},
{
title: '获取时间',
dataIndex: 'created',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
align: 'center',
ellipsis: true,
},
];
const columns2: EditableColumns[] = [
{
title: 'ID',
dataIndex: 'id',
align: 'center',
},
{
title: '会员权益名称',
dataIndex: 'project',
align: 'center',
},
{
title: '会员权益使用名称',
dataIndex: 'name',
align: 'center',
},
{
title: '使用数量',
dataIndex: 'count',
align: 'center',
},
{
title: '使用时间',
dataIndex: 'created',
align: 'center',
},
{
title: '备注',
dataIndex: 'node',
align: 'center',
ellipsis: true,
},
];
const handleTabChange = key => {
console.log('key', key)
};
return (
<div className={styles.sincerityInfo}>
<Row gutter={[0, 24]}>
<Col span={24}>
<Row gutter={24}>
<Col span={8}>
<MellowCard
title="信用积分"
>
<Pie
hasLegend={false}
subTitle="看我"
total="123.4"
data={salesPieData}
valueFormat={(value) => `${value} + !`}
height={248}
lineWidth={4}
/>
</MellowCard>
</Col>
<Col span={16}>
</Col>
</Row>
</Col>
<Col span={24}>
<MellowCard
title="活跃分获取记录"
>
<Tabs onChange={handleTabChange}>
<TabPane tab="权益获取记录" key="1">
<PolymericTable
dataSource={[]}
columns={columns}
loading={false}
pagination={null}
/>
</TabPane>
<TabPane tab="权益使用记录" key="2">
<PolymericTable
dataSource={[]}
columns={columns2}
loading={false}
pagination={null}
/>
</TabPane>
</Tabs>
</MellowCard>
</Col>
</Row>
</div>
);
};
export default SincerityInfo;
import React, { useState, useEffect, useRef, ReactNode } from 'react';
import React, { useState, useEffect, useRef, ReactNode, Suspense } from 'react';
import { history } from 'umi';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { PageHeader, Tag, Badge, Tabs, Steps, Descriptions } from 'antd';
......@@ -13,6 +13,10 @@ import LevelDetail from './levelDetail';
import EquitiesDetail from './equitiesDetail';
import IntegrityDetail from './integrityDetail';
const LevelInfo = React.lazy(() => import('./LevelInfo'));
const EquityInfo = React.lazy(() => import('./EquityInfo'));
const SincerityInfo = React.lazy(() => import('./SincerityInfo'));
const { TabPane } = Tabs;
const { Step } = Steps;
......@@ -110,11 +114,18 @@ const MemberDetail: React.FC<{}> = () => {
) : actived === '2' ? (
<AuthDetail detailData={detailData} />
) : actived === '3' ? (
<LevelDetail detailData={detailData} />
// <LevelDetail detailData={detailData} />
<Suspense fallback={null}>
<LevelInfo />
</Suspense>
) : actived === '4' ? (
<EquitiesDetail detailData={detailData} />
<Suspense fallback={null}>
<EquityInfo />
</Suspense>
) : (
<IntegrityDetail detailData={detailData} />
<Suspense fallback={null}>
<SincerityInfo />
</Suspense>
)}
</PageHeaderWrapper>
);
......
......@@ -377,27 +377,8 @@ export const getQueryStringParams = (url?: string) => {
return queryString.parse(searchParam)
}
/**
* 节流函数
* @param {func} func 需要执行的函数
* @param {number} delay 间隔
*/
export function debounce(func: (any?) => void, delay: number) {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
}
}
export default {
isArray,
isObject,
omit,
debounce,
}
\ No newline at end of file
......@@ -70,7 +70,7 @@ const baseRequest = extend({
// 请求拦截器
baseRequest.interceptors.request.use((url: string, options: RequestOptionsInit): { url: string, options: RequestOptionsInit } => {
// 判断是否有权限
const { userId, memberId, token } = getAuth()
const { userId, memberId, token } = getAuth() || {};
const headers = {
...options.headers,
userId,
......
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