import { h, Component, render } from '@/components/preact' import { isFunction, isArray, safety, deepMerge, mergeArr, IEVersion } from '@/components/common/util' /** * 普通的多选渲染 */ class General extends Component{ constructor(options){ super(options); this.setState({ filterValue: '', remote: true, loading: false, pageIndex: 1, pageSize: 10, }); this.searchCid = 0; this.inputOver = true; this.__value = ''; } optionClick(item, selected, disabled, e){ this.props.ck(item, selected, disabled); //阻止父组件上的事件冒泡 this.blockClick(e); } groupClick(item, e){ const { click, children, disabled } = this.props.prop; let m = item[click], arr = item[children].filter(opt => !opt[disabled]); if(m === 'SELECT'){ this.props.onReset(arr, 'append'); }else if(m === 'CLEAR'){ this.props.onReset(arr, 'delete'); }else if(m === 'AUTO'){ this.props.onReset(arr, 'auto'); }else if(isFunction(m)){ m(item); } //阻止父组件上的事件冒泡 this.blockClick(e); } blockClick(e){ e.stopPropagation(); } pagePrevClick(e){ let index = this.state.pageIndex; if(index <= 1){ return ; } this.changePageIndex(index - 1); } pageNextClick(e, size){ let index = this.state.pageIndex; if(index >= size){ return ; } this.changePageIndex(index + 1); } changePageIndex(index){ this.setState({ pageIndex: index }) } searchInput(e){ let v = e.target.value; if(v === this.__value){ return ; } clearTimeout(this.searchCid); if(this.inputOver){ //保证输入框内的值是实时的 this.__value = v; //让搜索变成异步的 this.searchCid = setTimeout(() => { this.callback = true; this.setState({ filterValue: this.__value, remote: true }) }, this.props.delay); } } focus(){ this.searchInputRef && this.searchInputRef.focus(); } blur(){ this.searchInputRef && this.searchInputRef.blur(); } handleComposition(e){ let type = e.type; if(type === 'compositionstart'){ this.inputOver = false; clearTimeout(this.searchCid); }else if(type === 'compositionend'){ this.inputOver = true; this.searchInput(e); } } componentWillReceiveProps(props){ if(this.props.show != props.show){ if(!props.show){ //清空输入框的值 this.setState({ filterValue: '' }); this.__value = ''; this.searchInputRef && (this.searchInputRef.value = ''); }else{ //聚焦输入框 setTimeout(() => this.focus(), 0); } } } componentDidUpdate(){ if(this.callback){ this.callback = false; let done = this.props.filterDone; if(isFunction(done)){ done(this.state.filterValue, this.tempData || []); } } } render(config) { let { data, prop, template, theme, radio, sels, empty, filterable, filterMethod, remoteSearch, remoteMethod, delay, searchTips } = config const { name, value, disabled, children, optgroup } = prop; let arr = deepMerge([], data); //是否开启了搜索 if(filterable){ if(remoteSearch){//是否进行远程搜索 if(this.state.remote){ this.callback = false; this.setState({ loading: true, remote: false }); //让输入框失去焦点 this.blur(); remoteMethod(this.state.filterValue, result => { //回调后可以重新聚焦 this.focus(); this.callback = true; this.setState({ loading: false }); this.props.onReset(result, 'data'); }, this.props.show); } }else{ const filterData = (item, index) => { const isGroup = item[optgroup]; if(isGroup){ delete item.__del; return true; } return filterMethod(this.state.filterValue, item, index, prop); } arr = arr.filter(filterData); for(let i = 0; i < arr.length - 1; i++){ let a = arr[i]; let b = arr[i + 1]; if(a[optgroup] && b[optgroup]){ arr[i].__del = true; } } if(arr.length && arr[arr.length - 1][optgroup]){ arr[arr.length - 1].__del = true; } arr = arr.filter(item => !item.__del); } } const search = ( ); //如果是分组模式, 要分页先去除分组, 然后在计算分页, 最后再加上分组 let groups = [], groupInfo = {}; groups = arr.filter(item => item[optgroup]).forEach(g => { g[children].forEach(item => groupInfo[item[value]] = g); }); arr = arr.filter(item => !item[optgroup]); let paging = ''; if(config.paging){ //计算当前分页的总页码 const size = Math.floor((arr.length - 1) / config.pageSize) + 1; //如果当前页码大于总页码, 重置一下 if(this.state.pageIndex > size){ this.changePageIndex(size); } //如有总页码>1, 但是因为搜索造成的页码=0的情况 if(size > 0 && this.state.pageIndex <= 0){ this.changePageIndex(1); } //实现简单的物理分页 let start = (this.state.pageIndex - 1) * config.pageSize; let end = start + config.pageSize; arr = arr.slice(start, end); const disabledStyle = {cursor: 'no-drop', color: '#d2d2d2'}; let prevStyle = {}, nextStyle = {}; this.state.pageIndex <= 1 && (prevStyle = disabledStyle); this.state.pageIndex == size && (nextStyle = disabledStyle); // const defaultCurrClass = { // position: 'relative', // borderRadius: '1px', // } // { // ''.padEnd(size, ' ').split('').map((s, i) => ( // { i + 1 } // )) // } paging = (
上一页 { this.state.pageIndex } / { size } this.pageNextClick.bind(this, e, size)() }>下一页
) }else{ //检查是否设置了显示数量上限 if(config.showCount > 0){ arr = arr.slice(0, config.showCount); } } let newArr = [], group; arr.forEach(item => { let g = groupInfo[item[value]]; if(g != group){ group = g; newArr.push(group); } newArr.push(item); }); arr = newArr; let safetyArr = deepMerge([], arr); this.tempData = safetyArr; //工具条操作 const toolbar = (
{ config.toolbar.list.map(tool => { const toolClass = 'toolbar-tag'; let info; if(tool === 'ALL'){ info = { icon: 'xm-iconfont xm-icon-quanxuan', name: '全选', method: (pageData) => { const { optgroup, disabled } = prop; const list = pageData.filter(item => !item[optgroup]).filter(item => !item[disabled]) this.props.onReset(mergeArr(list, sels, prop), 'sels'); } }; }else if(tool === 'CLEAR'){ info = { icon: 'xm-iconfont xm-icon-qingkong', name: '清空', method: (pageData) => { this.props.onReset(sels.filter(item => item[prop.disabled]), 'sels'); } }; }else { info = tool } const hoverChange = e => { if(e.type === 'mouseenter') e.target.style.color = theme.color; if(e.type === 'mouseleave') e.target.style.color = ''; } return (
{ isFunction(info.method) && info.method(safetyArr) } } onMouseEnter={ hoverChange } onMouseLeave={ hoverChange }> { config.toolbar.showIcon && } { info.name }
) }).filter(a => a) }
) const showIcon = config.model.icon != 'hidden'; const renderItem = item => { const selected = !!sels.find(sel => sel[value] == item[value]) const iconStyle = selected ? { color: theme.color, border: 'none' } : { borderColor: theme.color, }; const itemStyle = {} if(!showIcon && selected){ itemStyle.backgroundColor = theme.color; item[disabled] && (itemStyle.backgroundColor = '#C2C2C2'); } const className = ['xm-option', (item[disabled] ? ' disabled' : ''), (selected ? ' selected' : ''), (showIcon ? 'show-icon' : 'hide-icon') ].join(' '); const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : 'xm-icon-duox'].join(' '); return (
{ showIcon && }
) } const renderGroup = item => { const isGroup = item[optgroup]; if(isGroup){//分组模式 return (
{ item[name] }
) } return renderItem(item); } arr = arr.map(renderGroup); if(!arr.length){ arr.push(
{ empty }
) } return (
{ config.toolbar.show && toolbar } { filterable && search }
{ arr }
{ config.paging && paging }
{ this.state.loading &&
}
) } } export default General;