This commit is contained in:
maplemei
2020-02-10 14:39:38 +08:00
parent 588abc3d5d
commit 27f86e678c
16 changed files with 253 additions and 90 deletions

View File

@@ -6,7 +6,7 @@ import Label from '../label';
import General from '../plugin/general';
import Custom from '../plugin/custom';
import Tree from '../plugin/tree';
// import Cascader from '../plugin/cascader';
import Cascader from '../plugin/cascader';
/**
* 框架渲染类, 渲染基础的外边框 + 属性变化监听
@@ -384,8 +384,7 @@ class Framework extends Component{
const bodyProps = { ...config, data, dataObj, flatData, sels, ck: this.itemClick.bind(this), show, onReset: this.onReset.bind(this) }
//渲染组件
// let Body = content ? <Custom { ...bodyProps } /> : tree.show ? <Tree { ...bodyProps } /> : config.cascader.show ? <Cascader { ...bodyProps } /> : <General { ...bodyProps } />;
let Body = content ? <Custom { ...bodyProps } /> : tree.show ? <Tree { ...bodyProps } /> : <General { ...bodyProps } />;
let Body = content ? <Custom { ...bodyProps } /> : tree.show ? <Tree { ...bodyProps } /> : config.cascader.show ? <Cascader { ...bodyProps } /> : <General { ...bodyProps } />;
return (
<xm-select { ...xmSelectProps } >

View File

@@ -16,17 +16,30 @@ class Cascader extends Component{
e.stopPropagation();
}
optionClick(item, selected, disabled, index, e){
console.log(item, index);
this.props.ck(item, selected, disabled);
let expand = this.state.expand.slice(0, index + 1);
expand[index] = item[this.props.prop.value];
this.setState({ expand });
optionClick(item, selected, disabled, type, index, e){
if(type === 'line'){
if(disabled){
return ;
}
//加载中的不需要进行处理
if(item.__node.loading === true){
return;
}
const { cascader, prop, sels } = this.props;
//不是父节点的不需要处理
if(!cascader.lazy && !item[prop.optgroup]){
this.props.ck(item, selected, disabled);
return
}
let expand = this.state.expand.slice(0, index + 1);
expand[index] = item[this.props.prop.value];
this.setState({ expand });
}else if(type === 'checkbox'){
this.props.ck(item, selected, disabled);
}
//阻止父组件上的事件冒泡
this.blockClick(e);
}
@@ -47,7 +60,7 @@ class Cascader extends Component{
let { name, value, disabled, children } = prop;
const showIcon = config.model.icon != 'hidden';
const renderItem = (item, indent, index) => {
const renderItem = (item, indent, index, checked) => {
//是否被选中
let selected = !!sels.find(sel => sel[value] == item[value]);
//是否禁用
@@ -55,8 +68,11 @@ class Cascader extends Component{
// 是否半选
let half = item.__node.half === true;
selected = selected || half || item.__node.selected
dis = dis || item.__node.disabled;
//是否遵义严格父子结构
if(cascader.strict){
selected = selected || half || item.__node.selected
dis = dis || item.__node.disabled;
}
const iconStyle = selected ? {
color: theme.color,
@@ -67,8 +83,19 @@ class Cascader extends Component{
const itemStyle = { backgroundColor: 'transparent' }
const className = ['xm-option', (dis ? ' disabled' : ''), (selected ? ' selected' : ''), (showIcon ? 'show-icon' : 'hide-icon') ].join(' ');
const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : half ? 'xm-icon-banxuan' : 'xm-icon-duox'].join(' ');
const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : cascader.strict && half ? 'xm-icon-banxuan' : 'xm-icon-duox'].join(' ');
if(item[value] === this.state.val){
itemStyle.backgroundColor = theme.hover
}
const contentStyle = {}, checkedStyle = {};
if(checked){
contentStyle.color = theme.color
contentStyle.fontWeight = 700
checkedStyle.color = theme.color
}
let checkedClass = 'xm-right-arrow';
//处理鼠标选择的背景色
const hoverChange = e => {
@@ -83,31 +110,30 @@ class Cascader extends Component{
return (
<div class={ className } style={ itemStyle } value={ item[value] } onClick={
this.optionClick.bind(this, item, selected, dis, index)
this.optionClick.bind(this, item, selected, dis, 'line', index)
} onMouseEnter={ hoverChange } onMouseLeave={ hoverChange }>
{ showIcon && <i class={ iconClass } style={ iconStyle } ></i> }
<div class='xm-option-content' dangerouslySetInnerHTML={{ __html: template({ data, item, arr: sels, name: item[name], value: item[value] }) }}></div>
{ showIcon && <i class={ iconClass } style={ iconStyle } onClick={ this.optionClick.bind(this, item, selected, dis, 'checkbox', index) }></i> }
<div class='xm-option-content' style={ contentStyle } dangerouslySetInnerHTML={{ __html: template({ data, item, arr: sels, name: item[name], value: item[value] }) }}></div>
{ item[children] && <div class={ checkedClass } style={ checkedStyle }></div> }
</div>
)
}
let boxArr = [];
const renderGroup = (item, indent, index) => {
const child = item[children];
indent = indent + cascader.indent + 6
indent = cascader.indent + 10
return (
<div class="xm-cascader">
{ renderItem(item, indent, index) }
{ child && this.state.expand[index] === item[value] &&
<div class="xm-cascader-box" index={ index % 4 } style={{ left: indent + 'px' }}>{ child.map(c => renderGroup(c, indent, index + 1)) }</div>
}
const checked = child && this.state.expand[index] === item[value];
checked && boxArr.push(
<div class="xm-cascader-box" index={ index % 4 } style={{ left: indent + 'px', width: cascader.indent + 'px'}}>
<div class="xm-cascader-scroll">{ child.map(c => renderGroup(c, indent, index + 1)) }</div>
</div>
)
return renderItem(item, indent, index, checked)
}
let arr = data.map(item => renderGroup(item, 0, 0)).filter(a => a);
let arr = data.map(item => renderGroup(item, 2, 0)).concat(boxArr).filter(a => a);
// let safetyArr = deepMerge([], arr);
// let safetySels = deepMerge([], sels);
@@ -116,7 +142,7 @@ class Cascader extends Component{
}
return (
<div onClick={ this.blockClick } class="xm-body-cascader">
<div onClick={ this.blockClick } class="xm-body-cascader" style={{ width: cascader.indent + 'px', height: config.height }}>
{ arr }
</div>
)

View File

@@ -194,7 +194,7 @@ class General extends Component{
}
//组件将要接收新属性
componentWillReceiveProps(props){
componentWillReceiveProps(props){
if(this.props.show != props.show){
if(!props.show){
//清空输入框的值

View File

@@ -237,7 +237,7 @@ class Tree extends Component{
}
const className = ['xm-option', (dis ? ' disabled' : ''), (selected ? ' selected' : ''), (showIcon ? 'show-icon' : 'hide-icon') ].join(' ');
const iconClass = ['xm-option-icon xm-iconfont', radio ? 'xm-icon-danx' : tree.strict && half ? 'xm-icon-banxuan' : 'xm-icon-duox'].join(' ');
const treeIconClass = ['xm-tree-icon', expand ? 'expand':'', item[children] && (item[children].length > 0 || (tree.lazy && item.__node.loading !== false)) ? 'visible':'hidden'].join(' ');
const treeIconClass = ['xm-tree-icon', expand ? 'expand':'', item[children] && (item[children].length > 0 || (tree.lazy && item.__node.loading !== false)) ? 'xm-visible':'xm-hidden'].join(' ');
const iconArray = [];
if(tree.showFolderIcon){
@@ -284,7 +284,7 @@ class Tree extends Component{
child.length === 0 && (expand = false)
return (
<div class="xm-tree">
{ tree.showFolderIcon && tree.showLine && expand && child.length > 1 && <i class='left-line left-line-group' style={ {left: indent + 3 + 'px'} }></i> }
{ tree.showFolderIcon && tree.showLine && expand && child.length > 0 && <i class='left-line left-line-group' style={ {left: indent + 3 + 'px'} }></i> }
{ renderItem(item, indent, child.length === 0 && (!tree.lazy || tree.lazy && item.__node.loading === false) ? 0 : expand) }
{ expand && <div class="xm-tree-box">{ child.map(c => renderGroup(c, indent)) }</div> }
</div>
@@ -311,7 +311,7 @@ class Tree extends Component{
//工具条操作
function flat(list, array){
array.forEach(item => item[optgroup] ? flat(list, item[children]) : list.push(item))
array.forEach(item => item[optgroup] ? (!tree.strict && list.push(item), flat(list, item[children])) : list.push(item))
}
const toolbar = (
<div class='xm-toolbar'>

View File

@@ -107,7 +107,9 @@ export default function (lan = 'zn') {
//是否展示级联
show: false,
//间距
indent: 200,
indent: 100,
//是否严格遵守父子模式
strict: true,
},
//自定义属性名称
prop: {

View File

@@ -401,7 +401,7 @@ xm-select{
margin-left: -2px;
transform: rotate(90deg);
}
&.visible{
&.xm-visible{
visibility: visible;
}
}
@@ -429,36 +429,57 @@ xm-select{
.xm-cascader{
// position: relative;
&-box{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 5px 0;
border: @border;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, .12);
margin: -1px;
&::before{
content: ' ';
position: absolute;
width: 0;
height: 0;
border: 6px solid transparent;
border-right-color: @defaultBorderColor;
top: 10px;
left: -12px;
}
&::after{
content: ' ';
position: absolute;
width: 0;
height: 0;
border: 6px solid transparent;
border-right-color: #fff;
top: 10px;
left: -11px;
}
}
&-scroll{
height: 100%;
overflow-x: hidden;
overflow-y: auto;
padding: 5px 0;
}
&-box[index="0"]{
background-color: #F5F5F5;
}
&-box[index="1"]{
background-color: #FAFAFA;
}
&-box[index="2"]{
background-color: #FFFFFF;
}
&-box[index="3"]{
background-color: #EFEFEF;
}
}
&.cascader{
background-color: #EFEFEF;
width: unset;
min-width: unset;
.xm-option-content{
padding-left: 8px;
}
.disabled .xm-right-arrow{
color: #C2C2C2 !important;
}
}
}
.xm-input{
@@ -533,6 +554,19 @@ xm-select{
cursor: initial;
}
.xm-right-arrow{
position: absolute;
color: #666;
right: 5px;
top: -1px;
font-weight: 700;
transform: scale(0.6, 1);
&::after{
content: '>';
}
}
}
//不同尺寸下的数据调整
@@ -573,7 +607,7 @@ xm-select{
.left-line-group{
height: calc(100% - @size);
}
.xm-tree-icon.hidden+.top-line{
.xm-tree-icon.xm-hidden+.top-line{
top: @size / 2 - 1px;
}
}