This commit is contained in:
maplemei 2021-05-28 18:30:08 +08:00
parent e928c6a038
commit f8fa44c94c
14 changed files with 171 additions and 45 deletions

View File

@ -1,5 +1,22 @@
## 更新日志
### 1.2.3
*2021-05-28*
#### 新增
- 新增`submitConversion`配置方法, 用于拓展表单提交数据, 默认是value数组
#### Bug fixes
- 修复级联模式下第一组数据过多时不显示滚动条
- 修复级联模式下隐藏图标背景色透明的bug
- 修复级联模式下如果子节点是空数组也显示右箭头的bug
- 修复级联/树模式下,如果子节点是空数组,然后操作选中状态异常
- 修复工具条点击清空, `on`监听到的`isAdd`为`true`的bug [#I3T2KE](https://gitee.com/maplemei/xm-select/issues/I3T2KE)
- 修复setValue时对多选上限的判断异常 [#I3SABO](https://gitee.com/maplemei/xm-select/issues/I3SABO)
### 1.2.2

View File

@ -30,7 +30,7 @@
- xm-select技术群②: `938624691` (500人)
- xm-select技术群③: `1145047250` (500人)
[issues 需求记录](https://gitee.com/maplemei/xm-select/issues/I1NSO7)
[issues 需求记录](https://gitee.com/maplemei/xm-select/issues)
[更新日志](CHANGELOG.md)

2
dist/static/2.js vendored

File diff suppressed because one or more lines are too long

2
dist/static/3.js vendored

File diff suppressed because one or more lines are too long

8
dist/static/docs.js vendored

File diff suppressed because one or more lines are too long

2
dist/xm-select.js vendored

File diff suppressed because one or more lines are too long

View File

@ -4,10 +4,7 @@
<div class="container">
<h1>
<router-link :to="`/`">
<!-- logo -->
<slot>
<!-- <img src="../assets/images/element-logo.svg" alt="element-logo" class="nav-logo"> -->
<!-- <img src="../assets/images/element-logo-small.svg" alt="element-logo" class="nav-logo-small"> -->
xm-select
</slot>
</router-link>
@ -19,7 +16,7 @@
<router-link active-class="active" :to="`/`">使用手册</router-link>
</li>
<li class="nav-item">
<a href='https://gitee.com/maplemei/xm-select/issues/I1NSO7' target="_blank" style="opacity: 1;">提新需求</a>
<a href='https://gitee.com/maplemei/xm-select/issues' target="_blank" style="opacity: 1;">提新需求</a>
</li>
<li class="nav-item">

View File

@ -7,18 +7,53 @@
<script>
xmSelect.render({
el: '#demo1',
model: {
label: {
type: 'search'
},
autoRow: true,
cascader: {
show: true,
indent: 200,
},
radio: true,
filterable: true,
data: [
{name: '张三', value: 1, selected: true},
{name: '李四', value: 2},
{name: '王五', value: 3},
]
height: '200px',
max: 1,
maxMethod(a, item){
console.log(item)
},
submitConversion(sels, prop){
return sels.map(item => item[prop.name]).join(',')
},
data(){
return [
{name: '销售员', value: -1, disabled: false, children: [
{name: '张三1', value: 1, selected: true, children: []},
{name: '王五1', value: 13, disabled: true},
{name: '王五1', value: 131, disabled: true},
{name: '王五1', value: 132, disabled: true},
{name: '王五1', value: 133, disabled: true},
{name: '王五1', value: 134, disabled: true},
{name: '王五1', value: 135, disabled: true},
{name: '王五1', value: 136, disabled: true},
{name: '王五1', value: 137, disabled: true},
{name: '王五1', value: 138, disabled: true},
]},
{name: '奖品', value: -2, children: [
{name: '奖品3', value: -3, children: [
]},
{name: '苹果2', value: 4, disabled: true},
{name: '香蕉2', value: 5},
{name: '葡萄2', value: 6},
]},
{name: '李四1', value: 2},
{name: '王五1', value: 3, disabled: true},
{name: '王五1', value: 31, disabled: true},
{name: '王五1', value: 32, disabled: true},
{name: '王五1', value: 33, disabled: true},
{name: '王五1', value: 34, disabled: true},
{name: '王五1', value: 35, disabled: true},
{name: '王五1', value: 36, disabled: true},
{name: '王五1', value: 37, disabled: true},
{name: '王五1', value: 38, disabled: true},
]
}
})

View File

@ -52,6 +52,7 @@
| create | 创建条目 | function(val, data), val: 搜索的数据, data: 当前下拉数据 | - | null |
| tree | 树形结构, 具体看下表 | object | - | - |
| cascader | 级联结构, 具体看下表 | object | - | - |
| submitConversion | 配置表单提交数据 | function(sels, prop), sels: 已选中数据, prop: 自定义的prop | - | - |
### prop
@ -211,7 +212,7 @@ list: [ "ALL", "CLEAR",
| render | 渲染多选 | (options: 配置项) | 实例对象 |
| get | 获取页面中已经渲染的多选 | (filter: 过滤`el`, single: 是否返回单实例) | 符合条件的实例数组 |
| batch | 批量操作已渲染的多选 | (filter: 过滤`el`, method: 方法, ...方法参数) | 符合条件的实例数组 |
| arrr2tree | 把列表数据转化为树状结构 | (arr: 数据, pid: 父节点ID的key, id: 对应key, children: 对应key, topParentId: 顶级节点的ID) | 符合条件的数组 |
| arr2tree | 把列表数据转化为树状结构 | (arr: 数据, pid: 父节点ID的key, id: 对应key, children: 对应key, topParentId: 顶级节点的ID) | 符合条件的数组 |
```
//render 使用方式

View File

@ -120,7 +120,7 @@ class Framework extends Component{
return cgList;
}
value(sels, show, listenOn, jsChangeData){
value(sels, show, listenOn, jsChangeData, isAdd = true){
if(show !== false && show !== true){
show = this.state.show;
}
@ -129,7 +129,7 @@ class Framework extends Component{
let changeData = this.exchangeValue(sels);
//检测是否超选了
if(this.checkMax(changeData, changeData)){
if(this.checkMax(changeData, changeData, true)){
return ;
}
@ -138,7 +138,7 @@ class Framework extends Component{
this.clearAndReset(data, changeData, false);
changeData = this.init({ data, prop }, true);
}
this.resetSelectValue(changeData, jsChangeData ? jsChangeData : changeData, true, listenOn);
this.resetSelectValue(changeData, jsChangeData ? jsChangeData : changeData, isAdd, listenOn);
this.setState({ show })
}
@ -147,7 +147,7 @@ class Framework extends Component{
data.forEach(item => {
item[selected] = changeData.findIndex(c => c[value] === item[value]) != -1 || parentCK;
let child = item[children];
if(child && isArray(child)){
if(child && isArray(child) && child.length > 0){
this.clearAndReset(child, changeData, item[selected])
let len = child.length;
let slen = child.filter(i => i[selected] === true || i.__node.selected === true).length;
@ -250,11 +250,12 @@ class Framework extends Component{
}
}
checkMax(item, sels){
checkMax(item, sels, contains){
const { max, maxMethod, theme } = this.props
//查看是否设置了多选上限
let maxCount = toNum(max);
if(maxCount > 0 && sels.length >= maxCount){
let flag = (contains ? sels.length : (isArray(item) ? item.length : 1) + sels.length) > maxCount;
if(maxCount > 0 && flag){
this.updateBorderColor(theme.maxColor);
//查看是否需要回调
maxMethod && isFunction(maxMethod) && maxMethod(sels, item);
@ -265,14 +266,14 @@ class Framework extends Component{
//选项, 选中状态, 禁用状态, 是否强制删除:在label上点击删除
itemClick(item, itemSelected, itemDisabled, mandatoryDelete){
const { theme, prop, radio, repeat, clickClose, max, maxMethod, tree, data } = this.props
const { theme, prop, radio, repeat, clickClose, max, maxMethod, tree, cascader, data } = this.props
let sels = [ ...this.state.sels ]
const { value, selected, disabled, children, optgroup } = prop
//如果是禁用状态, 不能进行操作
if(itemDisabled) return;
if(item[optgroup] && tree.strict){
if(item[optgroup] && (tree.strict || cascader.strict)){
let child = item[children], change = [], isAdd = true, handlerType;
if(item.__node.selected){
handlerType = 'del';
@ -293,7 +294,7 @@ class Framework extends Component{
this.treeHandler(sels, item, change, handlerType);
}
if(this.checkMax(change, change)){
if(this.checkMax(change, sels)){//TODO 这里还是有问题, 如果是取消的
return ;
}
sels = [ ...this.state.sels ], change = [];
@ -401,7 +402,7 @@ class Framework extends Component{
}else
//树状结构数据更新
if(type === 'treeData'){
this.value(data, null, true)
this.value(data, null, true, false, false)
}else
//树状结构数据更新
if(type === 'close'){
@ -436,7 +437,7 @@ class Framework extends Component{
sels.splice(index, 1);
}
});
this.value(sels, this.props.show, true, changeData)
this.value(sels, this.props.show, true, changeData, false)
}
auto(arr){
@ -478,7 +479,7 @@ class Framework extends Component{
}
render(config, state) {
const { theme, prop, radio, repeat, clickClose, on, max, maxMethod, content, disabled, tree } = config;
const { theme, prop, radio, repeat, clickClose, on, max, maxMethod, content, disabled, tree, submitConversion } = config;
const borderStyle = { borderColor: theme.color };
let { data, dataObj, flatData, sels, show, tmpColor, bodyClass } = state;
@ -519,7 +520,7 @@ class Framework extends Component{
lay-verType={ config.layVerType }
lay-reqText={ config.layReqText }
name={ config.name }
value={ sels.map(item => item[prop.value]).join(',') }
value={ submitConversion(sels, prop) }
></input>
<i class={ show ? 'xm-icon xm-icon-expand' : 'xm-icon' } />
{ sels.length === 0 && <div class="xm-tips">{ config.tips }</div> }

View File

@ -36,6 +36,65 @@ class Label extends Component{
let input = this.base.querySelector('.label-search-input');
input && input.blur();
}
labelDrag(item, e){
let type = e.type;
let node = e.target;
while(true){
if(!node || node.tagName === 'I'){
return ;
}
if(node.tagName === 'DIV' && node.style.position !== 'fixed'){
break;
}
node = node.parentNode;
}
console.log(e)
if(type === 'mousedown'){
let dragNode = node.cloneNode(true);
let { pageX, pageY, offsetX, offsetY } = e;//鼠标当前位置
console.log(pageX, pageY, offsetX, offsetY)
dragNode.style.position = 'fixed';
dragNode.style.left = (pageX - offsetX) + 'px';
dragNode.style.top = (pageY - offsetY) + 'px';
node.appendChild(dragNode);
console.log(dragNode)
dragNode.onmousemove = (ev) => {
dragNode.style.left = (ev.pageX - offsetX) + 'px';
dragNode.style.top = (ev.pageY - offsetY) + 'px';
}
dragNode.mouseup = () => {
dragNode.parentNode.removeChild(dragNode);
dragNode.onmousemove = null;
dragNode.mouseup = null;
dragNode.mouseleave = null;
}
dragNode.mouseleave = () => {
console.log('mouseleave')
}
}else if(type === 'mouseup'){
let childs = node.childNodes;
for(let i = 0; i < childs.length; i++) {
let f = childs[i];
if(f.tagName === 'DIV'){
node.removeChild(f);
f.onmousemove = null;
break;
}
}
}
e.stopPropagation();
}
componentDidMount(){
if (this.labelRef.addEventListener) {
@ -81,9 +140,13 @@ class Label extends Component{
html = arr.splice(0, count).map(sel => {
const styleProps = { width: conf.showIcon ? 'calc(100% - 20px)' : '100%', }
const className = ['xm-label-block', sel[disabled] ? 'disabled':''].join(' ');
const className = ['xm-label-block', sel[disabled] ? 'disabled':''].join(' ');
// onMouseDown = { this.labelDrag.bind(this, sel) }
// onMouseUp = { this.labelDrag.bind(this, sel) }
return (
<div class={className} style={ style }>
<div class={className} style={ style }
>
{ conf.template && isFunction(conf.template) ? (
<span style={ styleProps } dangerouslySetInnerHTML={{ __html: conf.template(sel, arr) }}></span>
) : (

View File

@ -18,7 +18,7 @@ class Cascader extends Component{
optionClick(item, selected, disabled, type, index, e){
if(type === 'line'){
if(disabled){
if(!item.optgroup && disabled){
return ;
}
//加载中的不需要进行处理
@ -57,7 +57,7 @@ class Cascader extends Component{
render(config, state) {
const { prop, empty, sels, theme, radio, template, data, cascader } = config;
let { name, value, disabled, children } = prop;
let { name, value, disabled, children, optgroup } = prop;
const showIcon = config.model.icon != 'hidden';
const renderItem = (item, indent, index, checked) => {
@ -108,6 +108,12 @@ class Cascader extends Component{
itemStyle.backgroundColor = theme.hover
}
//隐藏图标的处理
if(!showIcon && selected){
itemStyle.backgroundColor = theme.color;
dis && (itemStyle.backgroundColor = '#C2C2C2');
}
const contentStyle = {}, checkedStyle = {};
if(checked){
contentStyle.color = theme.color
@ -133,7 +139,7 @@ class Cascader extends Component{
} onMouseEnter={ hoverChange } onMouseLeave={ hoverChange }>
{ 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> }
{ item[optgroup] && <div class={ checkedClass } style={ checkedStyle }></div> }
</div>
)
}
@ -146,7 +152,7 @@ class Cascader extends Component{
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 class="xm-cascader-scroll scroll-body">{ child.map(c => renderGroup(c, indent, index + 1)) }</div>
</div>
)
return renderItem(item, indent, index, checked)
@ -161,7 +167,7 @@ class Cascader extends Component{
}
return (
<div onClick={ this.blockClick } class="xm-body-cascader" style={{ width: cascader.indent + 'px', maxHeight: config.height }}>
<div onClick={ this.blockClick } class="xm-body-cascader scroll-body" style={{ width: cascader.indent + 'px', maxHeight: config.height }}>
{ arr }
</div>
)

View File

@ -184,6 +184,9 @@ export default function (lan = 'zn') {
//监听选中事件
on({ arr, item, selected }){
}
},
submitConversion(sels, prop){
return sels.map(item => item[prop.value]).join(',')
}
}
}

View File

@ -488,6 +488,9 @@ xm-select{
.disabled .xm-right-arrow{
color: #C2C2C2 !important;
}
.hide-icon.disabled .xm-right-arrow{
color: #999 !important;
}
}
}