top300-stock.js 9.76 KB
import React from 'react';
import { DatePicker, Button, Tooltip, Spin } from 'antd';
import locale from 'antd/es/date-picker/locale/zh_CN';
import axios from '../../libs/axios';
import moment from 'moment';
import 'moment/locale/zh-cn';

import './top300-stock.css'

moment.locale('zh-cn');

class Stock extends React.Component {
    constructor() {
        super();

        this.state = {
            today: moment().endOf('day'),
            onDay: '',
            stats: {},
            data: [],
            loading: false
        };

        this.columns = [
            {
                title: 'id',
                class: 'align-center',
                render(record, index) {
                    return index + 1;
                }
            },
            {
                title: '毒id',
                key: 'du_id',
            },
            {
                title: '品牌',
                key: 'brand',
            },
            {
                title: '货号',
                key: 'model',
            },
            {
                title: '商品名称',
                render(record) {
                    return <Tooltip className="td-col-name" placement="topLeft" title={record.name} >{record.name}</Tooltip>;
                }
            },
            {
                title: '商品id',
                render(record) {
                    return record.product_id > 0 ? record.product_id : '';
                }
            },
            {
                title: '尺码',
                key: 'size',
            },
            {
                title: '销量',
                render(record) {
                    return record.sold_num > -1 ? record.sold_num : '-';
                }
            },
            {
                title: '价格',
                sub: [
                    {
                        title: '毒',
                        key: 'du_price',
                        class: 'align-right',
                    },
                    {
                        title: 'UFO',
                        key: 'ufo_price',
                        class: 'align-right',
                    },
                ]
            },
            {
                title: '现货库存',
                sub: [
                    {
                        title: 'time1',
                        key: 'time1',
                        class: 'align-right',
                    },
                    {
                        title: 'time2',
                        key: 'time2',
                        class: 'align-right',
                    },
                    {
                        title: 'time3',
                        key: 'time3',
                        class: 'align-right',
                    },
                    {
                        title: 'time4',
                        key: 'time4',
                        class: 'align-right',
                    },
                ]
            },
            {
                title: '一周支付数',
                sub: [
                    {
                        title: '现货',
                        key: 'week_spot_count',
                        class: 'align-right',
                    },
                    {
                        title: '总计',
                        key: 'week_count',
                        class: 'align-right',
                    }
                ]
            }
        ];

        let { headers, headRow } = this.formatHeader(this.columns);

        this.headers = headers;
        this.headRow = headRow;
    }
    formatHeader(columns, data = {}, deep = 0) {
        data.headers = data.headers || [];
        data.headRow = data.headRow || [];

        let { headers, headRow } = data;

        if (!headers[deep]) {
            headers[deep] = [];
        }

        columns.map(val => {
            let col = {
                title: val.title,
                key: val.key || ''
            }

            if (val.sub && val.sub.length) {
                col.colspan = val.sub.length;
                this.formatHeader(val.sub, data, deep + 1);
            } else {
                col.rowspan = '{rowspan}';
                headRow.push(val);
            }

            headers[deep].push(col);
        });

        return {
            headers,
            headRow
        };
    }
    componentDidMount() {
        this.getStockData(this.state.today)
    }
    getStockData(day) {
        this.setState({
            loading: true,
            onDay: day.format('YYYY-MM-DD')
        });

        axios.get(`/api/stats/top300/stock?day=${day.format('YYYY-MM-DD')}`).then(res => {
            if (res.code !== 200) {
                return;
            }

            let { list, stats } = res.data || {};
            let timeTitle;

            try {
                timeTitle = JSON.parse(list[0].timeTitle)
            } catch (e) {
                console.log(e)
            }

            if (timeTitle) {
                this.headers.map(row => {
                    row.map(col => {
                        if (timeTitle[col.key]) {
                            col.title = timeTitle[col.key];
                        }
                    });
                });
            }

            setTimeout(() => {
                this.setState({
                    loading: false,
                    data: list,
                    stats
                });
            }, list.length ? 300 : 1000);
        });
    }
    dataOnChange(time) {
        this.getStockData(time);
    }
    toPercent(numerator, denominator) {
        if (!denominator) {
            numerator = 0;
        }

        return `${numerator ? (numerator / denominator * 100).toFixed(2) : 0 }%`;
    }
    renderThead(headers) {
        return (
            <thead>
                {headers.map((row, ri) => {
                    let rs = headers.length - ri;

                    return <tr key={'head-' + ri}>
                        {row.map((col, ci) => {
                            let crs = col.rowspan ? rs : 1;
                            let ccs = col.colspan || 1;

                            return <th key={ci} rowSpan={crs} colSpan={ccs} >{col.title}</th>;
                        })}
                    </tr>;
                })}
            </thead>
        );
    }
    renderTbody(head, data) {
        return (
            <tbody>
                {data.length ? data.map((row, ri) => {
                    let rowClass = row.class || {};

                    return <tr key={'body-' + ri}>
                        {head.map((col, ci) => {
                            let className = col.class || '';
                            let colInfo = col.key ? row[col.key] : col.render(row, ri);

                            className += `${className ? ' ' : ''}${rowClass[col.key] || ''}`

                            return <td key={ci} className={className} >{colInfo}</td>;
                        })}
                    </tr>;
                }) : <tr><td className="empty-tbody" colSpan={head.length}>暂无数据</td></tr>}
                <tr className="table-loading-tr">
                    <td colSpan={head.length}>
                        <Spin className="table-loading" spinning={this.state.loading} tip="加载中..."></Spin>
                    </td>
                </tr>
            </tbody>
        );
    }
    render() {
        const disabledDate = value => {
            const { today } = this.state;
            if (!value || !today) {
                return false;
            }
            return value.valueOf() > today.valueOf();
        };

        const { gray, yellow, total } = this.state.stats || {};
        const white = (total - yellow - gray) || 0;

        return (
            <div>
                <div>
                    <DatePicker onChange={this.dataOnChange.bind(this)} disabledDate={disabledDate} locale={locale} defaultValue={this.state.today} />
                    <a href={`/api/stats/top300/stock/export?day=${this.state.onDay || this.state.today}`} target="_blank" style={{ float: 'right' }}>
                        <Button type="primary" shape="round" icon="download">导出</Button>
                    </a>
                </div>

                <div className="top300-table-block">
                    <div className="top300-stats">
                        <p>总计:{total || 0}</p>
                        <p>
                            颜色:白色 <em className="color-block color-white"></em>
                            <span className="stats-col-block">值:>0 </span>
                            <span className="stats-col-block">数量:{white || 0}</span>
                            占比:{this.toPercent(white, total)}
                        </p>
                        <p>
                            颜色:灰色 <em className="color-block color-gray"></em>
                            <span className="stats-col-block">值:0 </span>
                            <span className="stats-col-block">数量:{gray || 0}</span>
                            占比:{this.toPercent(gray, total)}
                        </p>
                        <p>
                            颜色:黄色 <em className="color-block color-yellow"></em>
                            <span className="stats-col-block">值:缺失 </span>
                            <span className="stats-col-block">数量:{yellow || 0}</span>
                            占比:{this.toPercent(yellow, total)}
                        </p>
                    </div>
                    <div className="scroll-block">
                        <table className="top300-table">
                            {this.renderThead(this.headers)}
                            {this.renderTbody(this.headRow, this.state.data)}
                        </table>
                    </div>
                </div>
            </div>
        )
    }
}

export default Stock;