UNPKG

zent

Version:

一套前端设计语言和基于React的实现

337 lines (313 loc) 9.74 kB
import React, { Component, PureComponent } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import Input from 'input'; import Select from 'select'; import Pop from 'pop'; import find from 'lodash/find'; import fullfillImage from 'zan-utils/fullfillImage'; import Upload from 'upload'; class SKUContainer extends (PureComponent || Component) { constructor(props) { super(props); this.state = { skuOptions: [], newLeafText: '', leafValue: [], id: 0 }; } componentWillMount() { let { sku } = this.props; let { optionValue } = this.context; sku[optionValue] && this.fetchLeafById(sku[optionValue]); } componentWillReceiveProps(nextProps) { let { optionValue } = this.context; if (this.state.id === nextProps.sku[optionValue]) return; this.fetchLeafById(nextProps.sku[optionValue]); } fetchLeafById(id) { if (!id) return; this.context.onFetchSKU(id).then(skuOptions => { this.setState({ id, skuOptions }); }); } resetLeaf = () => { this.setState({ leafValue: [] }); }; selectSKU = () => { let { sku, hasSKUImage } = this.props; let { leafValue } = this.state; let { optionValue } = this.context; const skuLeaf = this.skuLeaf.state.selectedItems.map((item, key) => { item[optionValue] = item.value || leafValue[key]; item.is_show = hasSKUImage; delete item.cid; return item; }); let skuLeafIds = sku.leaf.map(item => item[optionValue]); skuLeaf.forEach(item => { if (skuLeafIds.indexOf(item[optionValue]) < 0) { sku.leaf.push(item); } }); this.resetLeaf(); this.props.onSKULeafChange(sku.leaf); }; removeSKULeaf(idx) { let { sku } = this.props; sku.leaf.splice(idx, 1); this.props.onSKULeafChange(sku.leaf); } createSKULeaf = (evt, leaf) => { let { sku } = this.props; let { leafValue, skuOptions } = this.state; let { onCreateSKU, optionValue, optionText } = this.context; if (leaf[optionValue] || typeof leaf[optionText] !== 'string') { if (leafValue.indexOf(leaf[optionValue]) < 0) { leafValue.push(leaf[optionValue]); } return false; } if (!leaf[optionText]) { return; } onCreateSKU({ text: leaf[optionText], id: sku[optionValue] }).then(data => { let newSKULeaf = {}; leafValue.push(data); newSKULeaf[optionText] = leaf[optionText]; newSKULeaf[optionValue] = data; skuOptions.push(newSKULeaf); this.setState({ newLeafText: '', leafValue: [].concat(leafValue), skuOptions: [].concat(skuOptions) }); }); }; updateLeafValue = sku => { let { optionValue } = this.context; let { leafValue } = this.state; leafValue = leafValue.filter(item => item !== sku[optionValue]); this.setState({ leafValue: [].concat(leafValue) }); }; asyncFilterSKULeaf = keyword => { let { optionText, maxLeafTextLength } = this.context; let { skuOptions } = this.state; if (maxLeafTextLength && maxLeafTextLength > 0) { keyword = keyword.substring(0, maxLeafTextLength); } if (skuOptions.some(item => item[optionText] === keyword)) return; this.setState({ newLeafText: keyword }); }; filterSKU = (item, keyword) => { let { maxLeafTextLength } = this.context; if (maxLeafTextLength && maxLeafTextLength > 0) { keyword = keyword.substring(0, maxLeafTextLength); } return item.text.indexOf(keyword) > -1; }; handleReset = () => { this.setState({ newLeafText: '' }); }; handleRenameSKULeaf(index) { let { sku, onSKULeafChange } = this.props; let { optionValue, optionText, onCreateSKU } = this.context; let { skuOptions } = this.state; let findKey = {}; findKey[optionText] = this.renameText; let skuItem = find(skuOptions, findKey); if (skuItem) { sku.leaf[index] = skuItem; onSKULeafChange(sku.leaf); return; } onCreateSKU({ text: this.renameText, id: sku[optionValue] }).then(data => { let newSKULeaf = {}; newSKULeaf[optionText] = this.renameText; newSKULeaf[optionValue] = data; skuOptions.push(newSKULeaf); this.setState({ skuOptions: [].concat(skuOptions) }); sku.leaf[index] = newSKULeaf; onSKULeafChange(sku.leaf); }); } renderSKUPopContent() { let { optionValue, optionText } = this.context; let { leafValue, skuOptions, newLeafText } = this.state; if (newLeafText) { skuOptions = [].concat(skuOptions); if (skuOptions.length > 0 && skuOptions[0][optionValue] === 0) { skuOptions[0][optionText] = newLeafText; } else { let newLeaf = {}; newLeaf[optionValue] = 0; newLeaf[optionText] = newLeafText; skuOptions.unshift(newLeaf); } } return ( <Select ref={skuLeaf => (this.skuLeaf = skuLeaf)} data={skuOptions} optionValue={optionValue} tags open filter={this.filterSKU} value={leafValue} onAsyncFilter={this.asyncFilterSKULeaf} onChange={this.createSKULeaf} onDelete={this.updateLeafValue} onOpen={this.handleReset} /> ); } removeImg(id) { const { sku } = this.props; let { optionValue } = this.context; sku.leaf.forEach(item => { if (item[optionValue] === id) { item.img_url = ''; } }); this.props.onSKULeafChange(sku.leaf); } uploadSuccess(id, imageUrl) { const { sku } = this.props; let { optionValue } = this.context; sku.leaf.forEach(item => { if (item[optionValue] === id) { item.img_url = fullfillImage(imageUrl[0].src, '!100x100.jpg'); } }); this.props.onSKULeafChange(sku.leaf); } render() { let { optionValue, optionText, prefix } = this.context; let { sku, hasSKUImage } = this.props; return ( <div className="group-container"> <div className="sku-list"> {sku.leaf.map((item, index) => { return ( <Pop key={index} trigger="click" position="bottom-center" content={ <Input defaultValue={item[optionText]} onChange={evt => (this.renameText = evt.target.value)} /> } wrapperClassName={cx(`${this.context.prefix}-item`, { active: hasSKUImage })} onConfirm={this.handleRenameSKULeaf.bind(this, index)} > <div> <span>{item[optionText]}</span> <span className="item-remove" onClick={this.removeSKULeaf.bind(this, index)} > x </span> {hasSKUImage ? ( <div className="upload-img-wrap"> <div className="arrow" /> {item.img_url ? ( <div className="upload-img"> <span className="item-remove small" title="删除" onClick={this.removeImg.bind( this, item[optionValue] )} > × </span> <img src={item.img_url} role="presentation" alt="" data-src={item.img_url} /> <Upload triggerClassName="img-edit" materials maxAmount="1" onUpload={this.uploadSuccess.bind( this, item[optionValue] )} > <span>替换</span> </Upload> </div> ) : ( <Upload materials maxAmount="1" onUpload={this.uploadSuccess.bind( this, item[optionValue] )} > <i>+</i> </Upload> )} </div> ) : ( '' )} </div> </Pop> ); })} {sku[optionValue] > 0 ? ( <Pop trigger="click" position="bottom-center" className={`${prefix}-pop`} wrapperClassName={`${prefix}-pop`} content={this.renderSKUPopContent()} onConfirm={this.selectSKU} onClose={this.resetLeaf} > <span className="sku-add">+添加</span> </Pop> ) : ( '' )} </div> </div> ); } } SKUContainer.contextTypes = { prefix: PropTypes.string, maxLeafTextLength: PropTypes.number, optionValue: PropTypes.string, optionText: PropTypes.string, onFetchSKU: PropTypes.func, onCreateSKU: PropTypes.func }; export default SKUContainer;