HotKeywords.jsx 12.1 KB
import React from 'react'
import { Table, Divider, Modal, Button, Input, Cascader, Upload, Icon, message } from 'antd'

import HotApi from '../../services/seo/hot-keywords'

const { TextArea } = Input;

const titleObj = {
    id: '序号',
    keyword: '关键词',
    msortName: '大品类',
    sortName: '小品类',
    yoho_goods_num: '商品数',
    is_push: '是否推送',
    add_time: '添加时间'
};

const columns = [];

Object.keys(titleObj).forEach(key => {
    columns.push({
        title: titleObj[key],
        dataIndex: key,
        key: key,
    });
});

let globalSort = [];

function ActionButton(props) {
    function editClick() {
        props.keyword.callbackFn('edit', props.keyword);
    }
    function deleteClick() {
        props.keyword.callbackFn('delete', props.keyword);
    }
    return (
        <span>
            <a href="javascript:;" onClick={editClick}>编辑</a>
            <Divider type="vertical" />
            <a href="javascript:;" onClick={deleteClick}>删除</a>
        </span>
    );
}

class OptionModal extends React.Component {
    constructor(props) {
        super(props);

        this.props = props;
        this.state = {
            sorts: globalSort || []
        };

        this.renderData = Object.assign({}, props.record || {});

        this.hotApi = new HotApi();

        this.loadHotList = props.loadHotList;
        this.hideOptionModal = props.hideOptionModal;
        this.handleKeywordChange = this.handleKeywordChange.bind(this);
        this.handleDescChange = this.handleDescChange.bind(this);
        this.handleSortChange = this.handleSortChange.bind(this);
        this.handleImageChange = this.handleImageChange.bind(this);
        this.loadSortData = this.loadSortData.bind(this);


        switch (this.renderData.type) {
            case 'edit':
                this.modalTitle = '编辑关键词';
                this.handleOk = this.handleSave.bind(this);
                break;
            case 'delete':
                this.modalTitle = '删除关键词';
                this.handleOk = this.handleDelete.bind(this);
                break;
            default:
                this.modalTitle = '新建关键词';
                this.handleOk = this.handleSave.bind(this);
                break;
        }

        if (!globalSort.length) {
            this.loadSortDataAsync().then(result => {
                this.setState({sorts: result});
                globalSort = result;
            });
        }
    }
    handleDelete() {
        return this.hotApi.delHotKeywords([this.renderData.id]).then(result => {
            if (result.code === 200) {
                this.loadHotList && this.loadHotList();
                this.hideOptionModal && this.hideOptionModal();
            } else {
                message.error(result.message);
            }
        });
    }
    handleSave() {
        return this.hotApi.saveHotKeywords(this.renderData).then(result => {
            if (result.code === 200) {
                this.loadHotList && this.loadHotList();
                this.hideOptionModal && this.hideOptionModal();
            } else {
                message.error(result.message);
            }
        });
    }
    handleKeywordChange(e) {
        this.renderData.keyword = e.target.value;
    }
    handleDescChange(e) {
        this.renderData.describe = e.target.value;
    }
    handleSortChange(select) {
        this.renderData.msort = select[0];
        this.renderData.misort = select[1];
        this.renderData.sort_id = select[2];
    }
    handleImageChange(info) {
        const status = info.file.status;

        if (status === 'uploading') {
            this.setState({ loading: true });
            return;
        } else if (status === 'done') {
            const result = info.file.response;
            let state = { loading: false };

            if (result.code === 200) {
                this.renderData.goods_img = result.data.images[0];
            }

            this.setState(state);
        }
    }
    beforeUpload(file) {
        const isImage = file.type.indexOf('image') > -1;
        const isLt2M = file.size / 1024 / 1024 < 2;

        if (!isImage) {
            message.error('请上传图片!');
        } else if (!isLt2M) {
            message.error('图片大小需小于 2MB!');
        }

        return isImage && isLt2M;
    }
    loadSortData(selectedOptions) {
        const targetOption = selectedOptions[selectedOptions.length - 1];

        targetOption.loading = true;

        this.loadSortDataAsync(targetOption.value).then(result => {
            targetOption.loading = false;
            targetOption.children = result;
            globalSort = this.state.sorts;
            this.setState({sorts: this.state.sorts});
        });
    }
    loadSortDataAsync(id) {
        return this.hotApi.getSubSorts(id || 0).then(result => {
            result.map(val => {
                if (id) {
                    val.value = val.sort_id;
                    val.label = val.sort_name;
                    val.isLeaf = false;
                    val.children = (val.sub || []).map(sval => {
                        sval.value = sval.sort_id;
                        sval.label = sval.sort_name;
                        sval.isLeaf = true;

                        return sval;
                    })
                } else {
                    val.value = val.id;
                    val.label = val.sortName;
                    val.isLeaf = false;
                }

                return val;
            });

            return result;
        });
    }
    uploadButton(loading) {
        return (
            <div>
                <Icon type={loading ? 'loading' : 'plus'} />
                <div className="ant-upload-text">Upload</div>
            </div>);
    }
    render() {
        const record = this.renderData;

        let title = '';

        if (record.sort_id || record.msort || record.misort) {
            let arr = [];

            record.msortName && arr.push(record.msortName);
            record.misortName && arr.push(record.misortName);
            record.sortName && arr.push(record.sortName);
            record.sortShowName = arr.join('/');
        }

        if (record && record.type === 'delete') {
            return (
                <Modal title={this.modalTitle} visible={true} onOk={this.handleOk} onCancel={this.hideOptionModal}>
                    <p>确认删除该关键词?</p>
                </Modal>
            )
        } else {
            const imageUrl = '';

            return (
                <Modal title={this.modalTitle} visible={true} onOk={this.handleOk} onCancel={this.hideOptionModal}>
                    <div style={{ paddingBottom: 10 }}>
                        <span>关键词:</span>
                        <Input onChange={this.handleKeywordChange} defaultValue={record.keyword} readOnly={record.id > 0}/>
                    </div>
                    <div style={{ paddingBottom: 10 }}>
                        <span>描述:</span>
                        <TextArea rows={4} onChange={this.handleDescChange} defaultValue={record.describe}/>
                    </div>
                    <div style={{ paddingBottom: 10 }}>
                        <span>封面图:</span>
                        <Upload
                            name="avatar"
                            listType="picture-card"
                            className="avatar-uploader"
                            showUploadList={false}
                            action="/upload/image"
                            name="file"
                            beforeUpload={this.beforeUpload}
                            onChange={this.handleImageChange}>
                            {record.goods_img ? <img src={record.goods_img}  style={{maxWidth: 200}} /> : this.uploadButton(this.state.loading)}
                        </Upload>
                    </div>
                    <div style={{ paddingBottom: 10 }}>
                        <span>品类:</span>
                        {record.sortShowName ? <Input defaultValue={record.sortShowName} readOnly={record.id > 0}/> : <Cascader
                            options={this.state.sorts}
                            loadData={this.loadSortData}
                            onChange={this.handleSortChange}
                            style={{ width: '100%' }}
                            placeholder="" />}

                    </div>
                </Modal>
            )
        }
    }
}

columns.push({
    title: '操作',
    key: 'action',
    render(keyword) {
        return <ActionButton keyword={keyword}/>
    }
});

class HotKeywords extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            showModal: false,
            dataSource: [],
            columns: columns,
            selectedRowKeys: [],
            pagination: {
                current: 1,
                total: 1,
                pageSize: 10
            }
        };

        this.hotApi = new HotApi();

        this.loadHotList = this.loadHotList.bind(this);
        this.handleTableChange = this.handleTableChange.bind(this);
        this.deleteTableRow = this.deleteTableRow.bind(this);
        this.hideOptionModal = this.hideOptionModal.bind(this);
        this.addTableRow = this.addTableRow.bind(this);

        this.loadHotList();
    }
    loadHotList(params = {}) {
        const { current, pageSize } = this.state.pagination;

        params.page = params.page || current || 1;
        params.limit = params.limit || pageSize || 10;

        this.hotApi.getHotList(params).then(result => {
            if (result.code === 200 && result.data) {
                const pagination = this.state.pagination;
                const { keywords, total } = result.data;

                pagination.total = total;

                this.setState({
                    dataSource: keywords,
                    pagination: pagination
                });
            }
        });
    }
    onSelectChange(selectedRowKeys) {
        this.setState({selectedRowKeys});
    }
    handleTableChange(pagination)  {
        this.setState({pagination});
        this.loadHotList({page: pagination.current});
    }
    deleteTableRow() {
        this.deleteKeywordsAsync(this.state.selectedRowKeys);
    }
    addTableRow() {
        this.showOptionModal('add');
    }
    sendToBaidu() {

    }
    deleteKeywordsAsync(ids) {
        this.hotApi.delHotKeywords(ids).then(result => {
            result.code === 200 && this.loadHotList();
        });
    }
    showOptionModal(type, record) {
        // const modelRecord = {...record};
        const modelRecord = record || {};

        modelRecord.type = type;
        this.modelRecord = modelRecord;
        this.setState({showModal: true});
    }
    hideOptionModal() {
        this.modelRecord = null;
        this.setState({showModal: false});
    }
    optionModal(showModal) {
        if (showModal) {
            return <OptionModal hideOptionModal={this.hideOptionModal} record={this.modelRecord} loadHotList={this.loadHotList}/>
        } else {
            return <div></div>;
        }
    }
    render() {
        const { showModal, dataSource, columns, selectedRowKeys, pagination, loading } = this.state;
        const hasSelected = selectedRowKeys.length > 0;

        const rowSelection = {
            selectedRowKeys,
            onChange: this.onSelectChange.bind(this)
        };
        const rowKey = record => {
            record.callbackFn = this.showOptionModal.bind(this);

            return record.id;
        }

        return (
            <div>
                <div style={{ paddingBottom: 10 }}>
                    <Button type="primary" onClick={this.deleteTableRow} disabled={!hasSelected} loading={loading}>删除</Button>
                    <Button type="primary" style={{ marginLeft: 10 }} onClick={this.addTableRow}>添加</Button>
                    {this.optionModal(showModal)}
                </div>

                <Table rowSelection={rowSelection} dataSource={dataSource} columns={columns}
                    rowKey={rowKey} pagination={pagination} onChange={this.handleTableChange}/>
            </div>
        );
    }
}

export default HotKeywords